|
|
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.