home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / ohlutil / cp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-24  |  22.9 KB  |  970 lines

  1. /*  cp.c  -- file copying (main routines)
  2.     Copyright (C) 1989, 1990 Free Software Foundation.
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 1, or (at your option)
  7.     any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.     Written by Torbjorn Granlund, and David MacKenzie. */
  19.  
  20. /*
  21.  * MS-DOS port (c) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet
  22.  *
  23.  * To this port, the same copying conditions apply as to the
  24.  * original release.
  25.  *
  26.  * IMPORTANT:
  27.  * This file is not identical to the original GNU release!
  28.  * You should have received this code as patch to the official
  29.  * GNU release.
  30.  *
  31.  * MORE IMPORTANT:
  32.  * This port comes with ABSOLUTELY NO WARRANTY.
  33.  *
  34.  * $Header: e:/gnu/fileutil/RCS/cp.c'v 1.3.0.2 90/06/29 00:46:37 tho Stable $
  35.  */
  36.  
  37. /* Yet to be done:
  38.  
  39.  * Symlink translation. */
  40.  
  41. #include <stdio.h>
  42. #include "cp.h"
  43. #include "getopt.h"
  44. #include "backupfile.h"
  45.  
  46. #ifdef MSDOS
  47. extern enum backup_type get_version (char *version);
  48. extern char *savedir (char *dir, unsigned name_size);
  49. #endif /* MSDOS */
  50.  
  51. #ifndef _POSIX_SOURCE
  52. /* This definition assumes that MODE has the S_IFIFO bit set. */
  53. #define mkfifo(path, mode) (mknod ((path), (mode), 0))
  54.  
  55. int geteuid ();
  56. #endif
  57.  
  58. enum backup_type get_version ();
  59.  
  60. #define INITIAL_HASH_MODULE 100
  61.  
  62. #define INITIAL_ENTRY_TAB_SIZE 70
  63.  
  64. /* A pointer to either lstat or stat, depending on
  65.    whether dereferencing of symlinks is done.  */
  66. #ifdef MSDOS
  67. int (*xstat) (char *, struct stat *);
  68. #else
  69. int (*xstat) ();
  70. #endif /* MSDOS */
  71.  
  72. /* The invocation name of this program.  */
  73. char *program_name;
  74.  
  75. /* If nonzero, dereference symbolic links (copy the files they point to). */
  76. int flag_dereference = 1;
  77.  
  78. /* If nonzero, override protection for target files if possible. */
  79. int flag_force = 0;
  80.  
  81. /* If nonzero, always query before removing existing targets. */
  82. int flag_interactive = 0;
  83.  
  84. /* If nonzero, give the copies the original files' permissions. */
  85. int flag_preserve = 0;
  86.  
  87. /* If nonzero, copy directories recursively and copy special files
  88.    as themselves rather than copying their contents. */
  89. int flag_recursive = 0;
  90.  
  91. /* If nonzero, when copying recursively, skip any subdirectories that are
  92.    on different filesystems from the one we started on. */
  93. int flag_one_file_system = 0;
  94.  
  95. /* If nonzero, display the names of the files before copying them. */
  96. int flag_verbose = 0;
  97.  
  98. /* The error code to return to the system. */
  99. int exit_status = 0;
  100.  
  101. /* If nonzero, effective uid is 0. */
  102. int root;
  103.  
  104. /* The bits to preserve in created files' modes. */
  105. int umask_kill;
  106.  
  107. /* If nonzero, skip unwritable files if not interactive. */
  108. int stdin_not_tty;
  109.  
  110. struct option long_opts[] =
  111. {
  112.   {"backup", 0, NULL, 'b'},
  113.   {"force", 0, &flag_force, 1},
  114.   {"interactive", 0, &flag_interactive, 1},
  115.   {"no-dereference", 0, &flag_dereference, 0},
  116.   {"one-file-system", 0, &flag_one_file_system, 1},
  117.   {"preserve", 0, &flag_preserve, 1},
  118.   {"recursive", 0, &flag_recursive, 1},
  119.   {"suffix", 1, NULL, 'S'},
  120.   {"verbose", 0, &flag_verbose, 1},
  121.   {"version-control", 1, NULL, 'V'},
  122.   {NULL, 0, NULL, 0}
  123. };
  124.  
  125. void
  126. main (argc, argv)
  127.      int argc;
  128.      char *argv[];
  129. {
  130.   int c;
  131.   int ind;
  132.   int make_backups = 0;
  133.   char *version;
  134.  
  135.   program_name = argv[0];
  136. #ifdef MSDOS
  137.   strlwr (program_name);
  138. #endif /* not MSDOS */
  139.  
  140.   version = getenv ("SIMPLE_BACKUP_SUFFIX");
  141.   if (version)
  142.     simple_backup_suffix = version;
  143.   version = getenv ("VERSION_CONTROL");
  144.  
  145.   /* Find out the current file creation mask, to knock the right bits
  146.      when using chmod.  The creation mask is set to to be liberal, so
  147.      that created directories can be written, even if it would not
  148.      have been allowed with the mask this process was started with.  */
  149.  
  150. #ifdef MSDOS            /* not 100%ly correct ... */
  151.   umask_kill = 07777 ^ umask (0);
  152. #else /* not MSDOS */
  153.   umask_kill = 0777777 ^ umask (0);
  154. #endif /* not MSDOS */
  155.  
  156.  
  157.   while ((c = getopt_long (argc, argv, "bdfioprvRS:V:", long_opts, &ind))
  158.      != EOF)
  159.     {
  160.       if (c == 0 && long_opts[ind].flag == NULL)
  161.     c = long_opts[ind].val;
  162.       switch (c)
  163.     {
  164.     case 0:
  165.       break;
  166.  
  167.     case 'b':
  168.       make_backups = 1;
  169.       break;
  170.  
  171.     case 'd':
  172.       flag_dereference = 0;
  173.       break;
  174.  
  175.     case 'f':
  176.       flag_force = 1;
  177.       break;
  178.  
  179.     case 'i':
  180.       flag_interactive = 1;
  181.       break;
  182.  
  183.     case 'o':
  184.       flag_one_file_system = 1;
  185.       break;
  186.  
  187.     case 'p':
  188.       flag_preserve = 1;
  189.       break;
  190.  
  191.     case 'r':
  192.     case 'R':
  193.       flag_recursive = 1;
  194.       break;
  195.  
  196.     case 'v':
  197.       flag_verbose = 1;
  198.       break;
  199.  
  200.     case 'S':
  201.       simple_backup_suffix = optarg;
  202.       break;
  203.  
  204.     case 'V':
  205.       version = optarg;
  206.       break;
  207.  
  208.     default:
  209.       usage ((char *) 0);
  210.     }
  211.     }
  212.  
  213.   if (make_backups)
  214.     backup_type = get_version (version);
  215.  
  216.   if (flag_interactive)
  217.     flag_force = 0;
  218.  
  219.   if (flag_preserve == 1)
  220. #ifdef MSDOS            /* not 100%ly correct ... */
  221.     umask_kill = 07777;
  222. #else /* not MSDOS */
  223.     umask_kill = 0777777;
  224. #endif /* not MSDOS */
  225.  
  226.   /* The key difference between -d (+no-dereference) and not is the version
  227.      of `stat' to call.  */
  228.  
  229.   if (flag_dereference)
  230.     xstat = stat;
  231.   else
  232.     xstat = lstat;
  233.  
  234.   stdin_not_tty = !isatty (0);
  235.   root = (geteuid () == 0);
  236.  
  237.   /* Allocate space for remembering copied and created files.  */
  238.  
  239.   hash_init (INITIAL_HASH_MODULE, INITIAL_ENTRY_TAB_SIZE);
  240.  
  241.   exit_status |= do_copy (argc, argv);
  242.  
  243.   exit (exit_status);
  244. }
  245.  
  246. /* Scan the arguments, and copy each by calling `copy'.
  247.    Return 0 if successful, 1 if any errors occur. */
  248.  
  249. int
  250. do_copy (argc, argv)
  251.      int argc;
  252.      char *argv[];
  253. {
  254.   char *target;
  255.   struct stat sb;
  256.   int new_dst = 0;
  257.   int ret = 0;
  258.  
  259.   if (optind >= argc)
  260.     usage ("missing file arguments");
  261.   if (optind >= argc - 1)
  262.     usage ("missing file argument");
  263.  
  264.   target = argv[argc - 1];
  265. #ifdef MSDOS
  266.   strlwr (target);
  267. #endif /* MSDOS */
  268.  
  269.   strip_trailing_slashes (target);
  270.  
  271.   if (lstat (target, &sb))
  272.     {
  273.       if (errno != ENOENT)
  274.     {
  275.       error (0, errno, "%s", target);
  276.       return 1;
  277.     }
  278.       else
  279.     new_dst = 1;
  280.     }
  281.   else
  282.     {
  283.       struct stat sbx;
  284.  
  285.       /* If `target' is not a symlink to a nonexistent file, use
  286.      the results of stat instead of lstat, so we can copy files
  287.      into symlinks to directories. */
  288.       if (stat (target, &sbx) == 0)
  289.     sb = sbx;
  290.     }
  291.  
  292.   if (!new_dst && (sb.st_mode & S_IFMT) == S_IFDIR)
  293.     {
  294.       /* cp e_file_1...e_file_n e_dir
  295.      copy the files `e_file_1' through `e_file_n'
  296.      to the existing directory `e_dir'. */
  297.  
  298.       for (;;)
  299.     {
  300.       char *arg;
  301.       char *ap;
  302.       char *dst_path;
  303.  
  304.       arg = argv[optind];
  305.  
  306.       strip_trailing_slashes (arg);
  307.  
  308.       /* Append the last component of `arg' to `target'.  */
  309.  
  310.       ap = rindex (arg, '/');
  311.       if (ap == 0)
  312.         ap = arg;
  313.       else
  314.         ap++;
  315.       dst_path = xmalloc (strlen (target) + strlen (ap) + 2);
  316.       str_cpy (str_cpy (str_cpy (dst_path, target), "/"), ap);
  317.  
  318.       ret |= copy (arg, dst_path, new_dst, 0, (struct dir_list *) 0);
  319.       forget_all ();
  320.  
  321.       ++optind;
  322.       if (optind == argc - 1)
  323.         break;
  324.     }
  325.       return ret;
  326.     }
  327.   else if (argc - optind == 2)
  328.     return copy (argv[optind], target, new_dst, 0, (struct dir_list *) 0);
  329.   else
  330.     usage ("when copying multiple files, last argument must be a directory");
  331. }
  332.  
  333. /* Copy the file `src_path' to the file `dst_path'.  The files may be of
  334.    any type.  If the file `dst_path' cannot exist because its parent
  335.    directory was just created, `new_dst' should be non-zero.  If
  336.    `dst_path' might already exist, `new_dst' should be zero.
  337.    `device' is the device number of the parent directory, or 0 if
  338.    this file has no known parent.  `ancestors' points to a linked, null
  339.    terminated list of parent directories of `src_path'.
  340.    Return 0 if successful, 1 if an error occurs. */
  341.  
  342. int
  343. copy (src_path, dst_path, new_dst, device, ancestors)
  344.      char *src_path;
  345.      char *dst_path;
  346.      int new_dst;
  347.      dev_t device;
  348.      struct dir_list *ancestors;
  349. {
  350.   struct stat src_sb;
  351.   struct stat dst_sb;
  352.   int mode;
  353.   int type;
  354.   char *earlier_file;
  355.   int may_overwrite;
  356.   char *dst_backup = NULL;
  357.  
  358. #ifdef MSDOS
  359.   strlwr(src_path);
  360.   strlwr(dst_path);
  361. #endif /* MSDOS */
  362.  
  363.   if ((*xstat) (src_path, &src_sb))
  364.     {
  365.       error (0, errno, "%s", src_path);
  366.       return 1;
  367.     }
  368.  
  369.   /* Are we crossing a file system boundary?  */
  370.   if (flag_one_file_system && device != 0 && device != src_sb.st_dev)
  371.     return 0;
  372.  
  373.   /* We wouldn't insert a node unless nlink > 1, except that we need to
  374.      find created files so as to not copy infinitely if a directory is
  375.      copied into itself.  */
  376.  
  377.   earlier_file = remember_copied (dst_path, src_sb.st_ino, src_sb.st_dev);
  378.  
  379.   /* Have we encountered a file just created?  */
  380.  
  381.   if (earlier_file == &new_file)
  382.     return 0;
  383.  
  384.   if (flag_verbose)
  385.     printf ("  %s -> %s\n", src_path, dst_path);
  386.  
  387.   /* Did we copy this inode somewhere else (in this command line argument)
  388.      and therefore this is a second hard link to the inode?  */
  389.  
  390.   if (!flag_dereference && src_sb.st_nlink > 1 && earlier_file)
  391.     {
  392.       if (!new_dst)
  393.     {
  394.       if (backup_type != none)
  395.         {
  396.           dst_backup = find_backup_file_name (dst_path);
  397.           if (dst_backup == NULL)
  398.         error (1, 0, "virtual memory exhausted");
  399.           if (rename (dst_path, dst_backup))
  400.         {
  401.           if (errno != ENOENT)
  402.             {
  403.               error (0, errno, "cannot backup `%s'", dst_path);
  404.               free (dst_backup);
  405.               return 1;
  406.             }
  407.           else
  408.             {
  409.               free (dst_backup);
  410.               dst_backup = NULL;
  411.             }
  412.         }
  413.         }
  414.       else if (unlink (dst_path) && errno != ENOENT)
  415.         {
  416.           error (0, errno, "cannot remove old link `%s'", dst_path);
  417.           return 1;
  418.         }
  419.     }
  420.       if (link (earlier_file, dst_path))
  421.     {
  422.       error (0, errno, "cannot create link `%s'", dst_path);
  423.       goto un_backup;
  424.     }
  425.       if (dst_backup)
  426.     free (dst_backup);
  427.       return 0;
  428.     }
  429.  
  430.   mode = src_sb.st_mode;
  431.   type = src_sb.st_mode & S_IFMT;
  432.  
  433.   if (type == S_IFDIR && !flag_recursive)
  434.     {
  435.       error (0, 0, "%s: omitting directory", src_path);
  436.       return 1;
  437.     }
  438.  
  439.   if (!new_dst)
  440.     {
  441.       if ((*xstat) (dst_path, &dst_sb))
  442.     {
  443.       if (errno != ENOENT)
  444.         {
  445.           error (0, errno, "%s", dst_path);
  446.           return 1;
  447.         }
  448.       else
  449.         new_dst = 1;
  450.     }
  451.       else
  452.     {
  453.       /* The file exists already.  */
  454. #ifndef MSDOS
  455.       if (src_sb.st_ino == dst_sb.st_ino && src_sb.st_dev == dst_sb.st_dev)
  456.         {
  457.           error (0, 0, "`%s' and `%s' are the same file (omitted)",
  458.              src_path, dst_path);
  459.           return 1;
  460.         }
  461. #endif /* not MSDOS */
  462.  
  463.       if ((dst_sb.st_mode & S_IFMT) == S_IFDIR && type != S_IFDIR)
  464.         {
  465.           error (0, 0, "%s: cannot overwrite directory with non-directory",
  466.              dst_path);
  467.           return 1;
  468.         }
  469.  
  470.       /* Treat the file as nonwritable if it lacks write permission bits,
  471.          even if we are root.  */
  472. #ifdef S_IFLNK
  473.       if (type == S_IFLNK)
  474.         may_overwrite = 1;
  475.       else
  476. #endif
  477.         may_overwrite =
  478.           eaccess_stat (&dst_sb,
  479. #ifdef MSDOS
  480.                 W_OK) == 0
  481. #else /* not MSDOS */
  482.                 type == S_IFDIR ? (W_OK | X_OK) : W_OK) == 0
  483. #endif /* not MSDOS */
  484.                   && (dst_sb.st_mode & 0222)
  485.                 && (type != S_IFDIR
  486.                     || (dst_sb.st_mode & 0111));
  487.  
  488.       if (flag_interactive)
  489.         {
  490.           fprintf (stderr, "%s: replace `%s'? ", program_name, dst_path);
  491.           if (!yesno ())
  492.         return 0;
  493.         }
  494.       else if (!flag_force && !may_overwrite)
  495.         {
  496.           if (stdin_not_tty)
  497.         {
  498.           error (0, 0, "%s: no write permission", dst_path);
  499.           return 1;
  500.         }
  501.           fprintf (stderr, "%s: override mode %04o for `%s'? ",
  502.                program_name, dst_sb.st_mode & 0777, dst_path);
  503.           if (!yesno ())
  504.         return 0;
  505.         }
  506.  
  507.       if (backup_type != none)
  508.         {
  509.           dst_backup = find_backup_file_name (dst_path);
  510.           if (dst_backup == NULL)
  511.         error (1, 0, "virtual memory exhausted");
  512.           if (rename (dst_path, dst_backup))
  513.         {
  514.           if (errno != ENOENT)
  515.             {
  516.               error (0, errno, "cannot backup `%s'", dst_path);
  517.               free (dst_backup);
  518.               return 1;
  519.             }
  520.           else
  521.             {
  522.               free (dst_backup);
  523.               dst_backup = NULL;
  524.             }
  525.         }
  526.           new_dst = 1;
  527.         }
  528.       else if (!may_overwrite)
  529.         {
  530.           if (type == S_IFDIR)
  531.         {
  532.           /* Temporarily change mode to allow overwriting. */
  533.           if (chmod (dst_path, dst_sb.st_mode | S_IEXEC | S_IWRITE))
  534.             {
  535.               error (0, errno, "%s", dst_path);
  536.               return 1;
  537.             }
  538.         }
  539.           else
  540.         {
  541.           if (unlink (dst_path) && errno != ENOENT)
  542.             {
  543.               error (0, errno, "cannot remove old link to `%s'",
  544.                  dst_path);
  545.               return 1;
  546.             }
  547.           new_dst = 1;
  548.         }
  549.         }
  550.     }
  551.     }
  552.  
  553.   if (!flag_recursive)
  554.     {
  555.       if (copy_reg (src_path, dst_path))
  556.     goto un_backup;
  557.     }
  558.   else
  559.     switch (type)
  560.       {
  561. #ifdef S_IFIFO
  562.       case S_IFIFO:
  563.     /* If a fifo already exists, we cannot do a better one.  */
  564.     if (new_dst)
  565.       {
  566.         if (mkfifo (dst_path, mode & umask_kill))
  567.           {
  568.         error (0, errno, "cannot make fifo `%s'", dst_path);
  569.         goto un_backup;
  570.           }
  571.       }
  572.     break;
  573. #endif
  574.  
  575. #ifndef MSDOS
  576.       case S_IFBLK:
  577.       case S_IFCHR:
  578. #ifdef S_IFSOCK
  579.       case S_IFSOCK:
  580. #endif
  581.     if (!root)
  582.       {
  583.         error (0, 0, "%s: omitting special file", src_path);
  584.         goto un_backup;
  585.       }
  586.     if (!new_dst && unlink (dst_path) && errno != ENOENT)
  587.       {
  588.         error (0, errno, "cannot remove old link to `%s'", dst_path);
  589.         return 1;
  590.       }
  591.     
  592.     if (mknod (dst_path, mode & umask_kill, src_sb.st_rdev))
  593.       {
  594.         error (0, errno, "cannot create special file `%s'", dst_path);
  595.         goto un_backup;
  596.       }
  597.     break;
  598. #endif /* !MSDOS */
  599.  
  600.       case S_IFDIR:
  601.     {
  602.       struct dir_list *dir;
  603.  
  604.       /* If this directory has been copied before during the
  605.          recursion, there's a symbolic link to an ancestor
  606.          directory of the symbolic link.  It's impossible to
  607.          continue to copy this, unless we've got an infinite disk.  */
  608.  
  609.       if (is_ancestor (&src_sb, ancestors))
  610.         {
  611.           error (0, 0, "%s: omitting cyclic symbolic link", src_path);
  612.           goto un_backup;
  613.         }
  614.  
  615.       /* Insert the current directory in the list of parents.  */
  616.  
  617.       dir = (struct dir_list *) alloca (sizeof (struct dir_list));
  618. #ifdef MSDOS            /* always short of stack space ... */
  619.       if (!dir)
  620.         error (1, 0, "%s: stack overflow", src_path);
  621. #endif /* MSDOS */
  622.       dir->parent = ancestors;
  623.       dir->ino = src_sb.st_ino;
  624.       dir->dev = src_sb.st_dev;
  625.  
  626.       /* Create the directory.  If a directory already exists, we
  627.          cannot create a better one.  */
  628.  
  629.       if (new_dst)
  630.         {
  631.           /* Create the new directory writable and searchable, so
  632.          we can create new entries in it.  */
  633.  
  634. #ifdef MSDOS
  635.           if (mkdir (dst_path))
  636. #else /* not MSDOS */
  637.           if (mkdir (dst_path, 0700))
  638. #endif /* not MSDOS */
  639.         {
  640.           error (0, errno, "cannot create directory `%s'", dst_path);
  641.           goto un_backup;
  642.         }
  643.  
  644.           /* Insert the created directory's inode and device
  645.          numbers into the search structure, so that we can
  646.          avoid copying it again.  */
  647.           
  648.           if (remember_created (dst_path))
  649.         goto un_backup;
  650.         }
  651.  
  652.       /* Now, copy the contents of the directory.  */
  653.  
  654.       if (copy_dir (src_path, dst_path, new_dst, &src_sb, dir))
  655.         goto err_return;
  656.     }
  657.     break;
  658.  
  659.       case S_IFREG:
  660.     if (copy_reg (src_path, dst_path))
  661.       goto un_backup;
  662.     break;
  663.  
  664. #ifdef S_IFLNK
  665.       case S_IFLNK:
  666.     {
  667.       char *link_val = (char *) alloca (src_sb.st_size + 1);
  668.  
  669.       if (readlink (src_path, link_val, src_sb.st_size) < 0)
  670.         {
  671.           error (0, errno, "cannot read symbolic link `%s'", src_path);
  672.           goto un_backup;
  673.         }
  674.       link_val[src_sb.st_size] = '\0';
  675.  
  676.       if (!new_dst && unlink (dst_path) && errno != ENOENT)
  677.         {
  678.           error (0, errno, "cannot remove old link to `%s'", dst_path);
  679.           return 1;
  680.         }
  681.  
  682.       if (symlink (link_val, dst_path))
  683.         {
  684.           error (0, errno, "cannot create symbolic link `%s'", dst_path);
  685.           goto un_backup;
  686.         }
  687.     }
  688.     return 0;
  689. #endif
  690.  
  691.       default:
  692.     error (0, 0, "%s: unknown file type (omitted)", src_path);
  693.     goto un_backup;
  694.       }
  695.  
  696.   if ((flag_preserve || new_dst) && (type == S_IFREG || type == S_IFDIR))
  697.     {
  698.       if (chmod (dst_path, mode & umask_kill))
  699.     {
  700.       error (0, errno, "%s", dst_path);
  701.       goto err_return;
  702.     }
  703.     }
  704.   else if (type == S_IFDIR && !new_dst && !may_overwrite)
  705.     {
  706.       /* Reset the temporarily changed mode.  */
  707.       if (chmod (dst_path, dst_sb.st_mode))
  708.     {
  709.       error (0, errno, "%s", dst_path);
  710.       goto err_return;
  711.     }
  712.     }
  713.  
  714.   /* Adjust the times (and if possible, ownership) for the copy. */
  715.  
  716.   if (flag_preserve)
  717.     {
  718.       struct utimbuf tv;
  719.  
  720.       tv.actime = src_sb.st_atime;
  721.       tv.modtime = src_sb.st_mtime;
  722.  
  723.       if (utime (dst_path, &tv))
  724.     {
  725.       error (0, errno, "%s", dst_path);
  726.       goto err_return;
  727.     }
  728.  
  729. #ifndef MSDOS
  730.       if (chown (dst_path, src_sb.st_uid, src_sb.st_gid) && errno != EPERM)
  731.     {
  732.       error (0, errno, "%s", dst_path);
  733.       goto err_return;
  734.     }
  735. #endif /* not MSDOS */
  736.     }
  737.  
  738.   if (dst_backup)
  739.     free (dst_backup);
  740.   return 0;
  741.  
  742.  err_return:
  743.   if (dst_backup)
  744.     free (dst_backup);
  745.   return 1;
  746.  
  747.  un_backup:
  748.   if (dst_backup)
  749.     {
  750.       if (rename (dst_backup, dst_path))
  751.     error (0, errno, "cannot un-backup `%s'", dst_path);
  752.       free (dst_backup);
  753.     }
  754.   return 1;
  755. }
  756.  
  757. /* Read the contents of the directory `src_path_in', and recursively
  758.    copy the contents to `dst_path_in'.  `new_dst' is non-zero if
  759.    `dst_path_in' is a directory that was created previously in the
  760.    recursion.  Return 0 if successful, -1 if an error occurs. */
  761.  
  762. int
  763. copy_dir (src_path_in, dst_path_in, new_dst, src_sb, ancestors)
  764.      char *src_path_in;
  765.      char *dst_path_in;
  766.      int new_dst;
  767.      struct stat *src_sb;
  768.      struct dir_list *ancestors;
  769. {
  770.   char *name_space;
  771.   char *namep;
  772.   char *src_path;
  773.   char *dst_path;
  774.   int ret = 0;
  775.  
  776.   errno = 0;
  777.   name_space = savedir (src_path_in, src_sb->st_size);
  778.   if (name_space == 0)
  779.     {
  780.       if (errno)
  781.     {
  782.       error (0, errno, "%s", src_path_in);
  783.       return -1;
  784.     }
  785.       else
  786.     error (1, 0, "virtual memory exhausted");
  787.     }
  788.  
  789.   namep = name_space;
  790.   while (*namep != '\0')
  791.     {
  792.       int fn_length = strlen (namep) + 1;
  793.  
  794.       dst_path = xmalloc (strlen (dst_path_in) + fn_length + 1);
  795.       src_path = xmalloc (strlen (src_path_in) + fn_length + 1);
  796.  
  797.       str_cpy (str_cpy (str_cpy (src_path, src_path_in), "/"), namep);
  798.       str_cpy (str_cpy (str_cpy (dst_path, dst_path_in), "/"), namep);
  799.  
  800.       ret |= copy (src_path, dst_path, new_dst, src_sb->st_dev, ancestors);
  801.  
  802.       /* Free the memory for `src_path'.  The memory for `dst_path'
  803.      cannot be deallocated, since it is used to create multiple
  804.      hard links.  (Of course it is possible to optimize memory
  805.      allocation, as most files have only one link.)  */
  806.  
  807.       free (src_path);
  808.  
  809.       namep += fn_length;
  810.     }
  811.   free (name_space);
  812.   return -ret;
  813. }
  814.  
  815. /* Copy a regular file from `src_path' to `dst_path'.  Large blocks of zeroes,
  816.    as well as holes in the source file, are made into holes in the
  817.    target file.  (Holes are read as zero by the `read' system call.)
  818.    Return 0 if successful, -1 if an error occurred. */
  819.  
  820. int
  821. copy_reg (src_path, dst_path)
  822.      char *src_path;
  823.      char *dst_path;
  824. {
  825.   char *buf;
  826.   int buf_size;
  827.   int target_desc;
  828.   int source_desc;
  829.   int n_read;
  830.   int n_written;
  831.   struct stat sb;
  832.   int return_val = 0;
  833.   long n_read_total = 0;
  834.   char *cp;
  835.   int *ip;
  836.   int last_write_made_hole = 0;
  837.  
  838. #ifdef MSDOS
  839.   source_desc = open (src_path, O_BINARY | O_RDONLY);
  840. #else
  841.   source_desc = open (src_path, O_RDONLY);
  842. #endif /* MSDOS */
  843.   if (source_desc < 0)
  844.     {
  845.       error (0, errno, "%s", src_path);
  846.       return -1;
  847.     }
  848.  
  849.   /* Create the new regular file with small permissions initially,
  850.      not to create a security hole.  */
  851.  
  852. #ifdef MSDOS
  853.   target_desc = open (dst_path, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, 0600);
  854. #else
  855.   target_desc = open (dst_path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
  856. #endif /* MSDOS */
  857.   if (target_desc < 0)
  858.     {
  859.       error (0, errno, "cannot create regular file `%s'", dst_path);
  860.       return_val = -1;
  861.       goto ret2;
  862.     }
  863.  
  864.   /* Find out the appropriate buffer length.  */
  865.  
  866.   if (fstat (target_desc, &sb))
  867.     {
  868.       error (0, errno, "%s", dst_path);
  869.       return_val = -1;
  870.       goto ret;
  871.     }
  872.  
  873.   buf_size = ST_BLKSIZE (sb);
  874.  
  875.   /* Make a buffer with space for a sentinel at the end.  */
  876.  
  877.   buf = (char *) alloca (buf_size + sizeof (int));
  878. #ifdef MSDOS
  879.   if (!buf)
  880.     error (2, 0, "%s: stack overflow", src_path);
  881. #endif /* MSDOS */
  882.  
  883.   for (;;)
  884.     {
  885.       n_read = read (source_desc, buf, buf_size);
  886.       if (n_read < 0)
  887.     {
  888.       error (0, errno, "%s", src_path);
  889.       return_val = -1;
  890.       goto ret;
  891.     }
  892.       if (n_read == 0)
  893.     break;
  894.  
  895. #ifdef MSDOS
  896.       n_read_total += (long) n_read;
  897. #else /* not MSDOS */
  898.       n_read_total += n_read;
  899. #endif /* not MSDOS */
  900.  
  901.       buf[n_read] = 1;        /* Sentinel to stop loop.  */
  902.  
  903.       /* Find first non-zero *word*, or the word with the sentinel.  */
  904.  
  905.       ip = (int *) buf;
  906.       while (*ip++ == 0)
  907.     ;
  908.  
  909.       /* Find the first non-zero *byte*, or the sentinel.  */
  910.  
  911.       cp = (char *) (ip - 1);
  912.       while (*cp++ == 0)
  913.     ;
  914.  
  915.       /* If we found the sentinel, the whole input block was zero,
  916.      and we can make a hole.  */
  917.  
  918.       if (cp > buf + n_read)
  919.     {
  920.       /* Make a hole.  */
  921.       if (lseek (target_desc, (off_t) n_read, L_INCR) < 0L)
  922.         {
  923.           error (0, errno, "%s", dst_path);
  924.           return_val = -1;
  925.           goto ret;
  926.         }
  927.       last_write_made_hole = 1;
  928.     }
  929.       else
  930.     {
  931.       n_written = write (target_desc, buf, n_read);
  932.       if (n_written < n_read)
  933.         {
  934.           error (0, errno, "%s", dst_path);
  935.           return_val = -1;
  936.           goto ret;
  937.         }
  938.       last_write_made_hole = 0;
  939.     }
  940.     }
  941.  
  942.   /* If the file ends with a `hole', something needs to be written at
  943.      the end.  Otherwise the kernel would truncate the file at the end
  944.      of the last write operation.  */
  945.  
  946.   if (last_write_made_hole)
  947.     {
  948. #ifndef FTRUNCATE_MISSING
  949.       /* Write a null character and truncate it again.  */
  950.       if (write (target_desc, "", 1) != 1
  951.       || ftruncate (target_desc, n_read_total) < 0)
  952. #else
  953.       /* Seek backwards one character and write a null.  */
  954.       if (lseek (target_desc, (off_t) -1, L_INCR) < 0L
  955.       || write (target_desc, "", 1) != 1)
  956. #endif
  957.     {
  958.       error (0, errno, "%s", dst_path);
  959.       return_val = -1;
  960.     }
  961.     }
  962.  
  963. ret:
  964.   close (target_desc);
  965. ret2:
  966.   close (source_desc);
  967.  
  968.   return return_val;
  969. }
  970.