home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / uucp-1.04 / unix / move.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-13  |  4.4 KB  |  177 lines

  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 ian@airs.com 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. }
  177.