|
|
1.1 root 1: /* move.c
2: Move a file.
3:
4: Copyright (C) 1991, 1992 Ian Lance Taylor
5:
6: This file is part of the Taylor UUCP package.
7:
8: This program is free software; you can redistribute it and/or
9: modify it under the terms of the GNU General Public License as
10: published by the Free Software Foundation; either version 2 of the
11: License, or (at your option) any later version.
12:
13: This program is distributed in the hope that it will be useful, but
14: WITHOUT ANY WARRANTY; without even the implied warranty of
15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16: General Public License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with this program; if not, write to the Free Software
20: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21:
22: The author of the program may be contacted at [email protected] or
23: c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
24: */
25:
26: #include "uucp.h"
27:
28: #include "uudefs.h"
29: #include "sysdep.h"
30: #include "system.h"
31:
32: #include <errno.h>
33:
34: #if HAVE_FCNTL_H
35: #include <fcntl.h>
36: #else
37: #if HAVE_SYS_FILE_H
38: #include <sys/file.h>
39: #endif
40: #endif
41:
42: /* Move (rename) a file from one name to another. This routine will
43: optionally create necessary directories, and fpublic indicates
44: whether the new directories should be publically accessible or not.
45: If fcheck is true, it will try to determine whether the named user
46: has write access to the new file. */
47:
48: boolean
49: fsysdep_move_file (zorig, zto, fmkdirs, fpublic, fcheck, zuser)
50: const char *zorig;
51: const char *zto;
52: boolean fmkdirs;
53: boolean fpublic;
54: boolean fcheck;
55: const char *zuser;
56: {
57: struct stat s;
58: int o;
59:
60: DEBUG_MESSAGE2 (DEBUG_SPOOLDIR,
61: "fsysdep_move_file: Moving %s to %s", zorig, zto);
62:
63: /* Optionally make sure that zuser has write access on the
64: directory. */
65: if (fcheck)
66: {
67: char *zcopy;
68: char *zslash;
69:
70: zcopy = zbufcpy (zto);
71: zslash = strrchr (zcopy, '/');
72: if (zslash == zcopy)
73: zslash[1] = '\0';
74: else
75: *zslash = '\0';
76:
77: if (stat (zcopy, &s) != 0)
78: {
79: ulog (LOG_ERROR, "stat (%s): %s", zcopy, strerror (errno));
80: (void) remove (zorig);
81: ubuffree (zcopy);
82: return FALSE;
83: }
84: if (! fsuser_access (&s, W_OK, zuser))
85: {
86: ulog (LOG_ERROR, "%s: %s", zcopy, strerror (EACCES));
87: (void) remove (zorig);
88: ubuffree (zcopy);
89: return FALSE;
90: }
91: ubuffree (zcopy);
92:
93: /* A malicious user now has a few milliseconds to change a
94: symbolic link to a directory uucp has write permission on but
95: the user does not (the obvious choice being /usr/lib/uucp).
96: The only certain method I can come up with to close this race
97: is to fork an suid process which takes on the users identity
98: and does the actual copy. This is sufficiently high overhead
99: that I'm not going to do it. */
100: }
101:
102: /* We try to use rename to move the file. */
103:
104: if (rename (zorig, zto) == 0)
105: return TRUE;
106:
107: if (fmkdirs && errno == ENOENT)
108: {
109: if (! fsysdep_make_dirs (zto, fpublic))
110: {
111: (void) remove (zorig);
112: return FALSE;
113: }
114: if (rename (zorig, zto) == 0)
115: return TRUE;
116: }
117:
118: #if HAVE_RENAME
119: /* On some systems the system call rename seems to fail for
120: arbitrary reasons. To get around this, we always try to copy the
121: file by hand if the rename failed. */
122: errno = EXDEV;
123: #endif
124:
125: /* If we can't link across devices, we must copy the file by hand. */
126: if (errno != EXDEV)
127: {
128: ulog (LOG_ERROR, "rename (%s, %s): %s", zorig, zto,
129: strerror (errno));
130: (void) remove (zorig);
131: return FALSE;
132: }
133:
134: /* Copy the file. */
135: if (stat ((char *) zorig, &s) < 0)
136: {
137: ulog (LOG_ERROR, "stat (%s): %s", zorig, strerror (errno));
138: (void) remove (zorig);
139: return FALSE;
140: }
141:
142: /* Make sure the file gets the right mode by creating it before we
143: call fcopy_file. */
144: (void) remove (zto);
145: o = creat ((char *) zto, s.st_mode);
146: if (o < 0)
147: {
148: if (fmkdirs && errno == ENOENT)
149: {
150: if (! fsysdep_make_dirs (zto, fpublic))
151: {
152: (void) remove (zorig);
153: return FALSE;
154: }
155: o = creat ((char *) zto, s.st_mode);
156: }
157: if (o < 0)
158: {
159: ulog (LOG_ERROR, "creat (%s): %s", zto, strerror (errno));
160: (void) remove (zorig);
161: return FALSE;
162: }
163: }
164: (void) close (o);
165:
166: if (! fcopy_file (zorig, zto, fpublic, fmkdirs))
167: {
168: (void) remove (zorig);
169: return FALSE;
170: }
171:
172: if (remove (zorig) != 0)
173: ulog (LOG_ERROR, "remove (%s): %s", zorig, strerror (errno));
174:
175: return TRUE;
176: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.