home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / cpio-2.3-src.lha / GNU / src / amiga / cpio-2.3 / copypass.c < prev    next >
C/C++ Source or Header  |  1993-05-04  |  14KB  |  450 lines

  1. /* copypass.c - cpio copy pass sub-function.
  2.    Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  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 2, 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. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include "filetypes.h"
  22. #include "system.h"
  23. #include "cpiohdr.h"
  24. #include "dstring.h"
  25. #include "extern.h"
  26.  
  27. #ifndef HAVE_LCHOWN
  28. #define lchown chown
  29. #endif
  30.  
  31. /* Copy files listed on the standard input into directory `directory_name'.
  32.    If `link_flag', link instead of copying.  */
  33.  
  34. void
  35. process_copy_pass ()
  36. {
  37.   dynamic_string input_name;    /* Name of file from stdin.  */
  38.   dynamic_string output_name;    /* Name of new file.  */
  39.   int dirname_len;        /* Length of `directory_name'.  */
  40.   int res;            /* Result of functions.  */
  41.   char *slash;            /* For moving past slashes in input name.  */
  42.   struct utimbuf times;        /* For resetting file times after copy.  */
  43.   struct stat in_file_stat;    /* Stat record for input file.  */
  44.   struct stat out_file_stat;    /* Stat record for output file.  */
  45.   int in_file_des;        /* Input file descriptor.  */
  46.   int out_file_des;        /* Output file descriptor.  */
  47.   int existing_dir;        /* True if file is a dir & already exists.  */
  48. #ifdef HPUX_CDF
  49.   int cdf_flag;
  50.   int cdf_char;
  51. #endif
  52.  
  53.   /* Initialize the copy pass.  */
  54.   dirname_len = strlen (directory_name);
  55.   ds_init (&input_name, 128);
  56.   ds_init (&output_name, dirname_len + 2);
  57.   strcpy (output_name.ds_string, directory_name);
  58.   output_name.ds_string[dirname_len] = '/';
  59.   output_is_seekable = TRUE;
  60.   /* Initialize this in case it has members we don't know to set.  */
  61.   bzero (×, sizeof (struct utimbuf));
  62.  
  63.   /* Copy files with names read from stdin.  */
  64.   while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
  65.     {
  66.       int link_res = -1;
  67.  
  68.       /* Check for blank line and ignore it if found.  */
  69.       if (input_name.ds_string[0] == '\0')
  70.     {
  71.       error (0, 0, "blank line ignored");
  72.       continue;
  73.     }
  74.  
  75.       /* Check for current directory and ignore it if found.  */
  76.       if (input_name.ds_string[0] == '.'
  77.       && (input_name.ds_string[1] == '\0'
  78.           || (input_name.ds_string[1] == '/'
  79.           && input_name.ds_string[2] == '\0')))
  80.     continue;
  81.  
  82.       if ((*xstat) (input_name.ds_string, &in_file_stat) < 0)
  83.     {
  84.       error (0, errno, "%s", input_name.ds_string);
  85.       continue;
  86.     }
  87.  
  88.       /* Make the name of the new file.  */
  89.       for (slash = input_name.ds_string; *slash == '/'; ++slash)
  90.     ;
  91. #ifdef HPUX_CDF
  92.       /* For CDF's we add a 2nd `/' after all "hidden" directories.
  93.      This kind of a kludge, but it's what we do when creating
  94.      archives, and it's easier to do this than to separately
  95.      keep track of which directories in a path are "hidden".  */
  96.       slash = add_cdf_double_slashes (slash);
  97. #endif
  98.       ds_resize (&output_name, dirname_len + strlen (slash) + 2);
  99.       strcpy (output_name.ds_string + dirname_len + 1, slash);
  100.  
  101.       existing_dir = FALSE;
  102.       if (lstat (output_name.ds_string, &out_file_stat) == 0)
  103.     {
  104.       if (S_ISDIR (out_file_stat.st_mode)
  105.           && S_ISDIR (in_file_stat.st_mode))
  106.         {
  107.           /* If there is already a directory there that
  108.          we are trying to create, don't complain about it.  */
  109.           existing_dir = TRUE;
  110.         }
  111.       else if (!unconditional_flag
  112.            && in_file_stat.st_mtime <= out_file_stat.st_mtime)
  113.         {
  114.           error (0, 0, "%s not created: newer or same age version exists",
  115.              output_name.ds_string);
  116.           continue;        /* Go to the next file.  */
  117.         }
  118.       else if (S_ISDIR (out_file_stat.st_mode)
  119.             ? rmdir (output_name.ds_string)
  120.             : unlink (output_name.ds_string))
  121.         {
  122.           error (0, errno, "cannot remove current %s",
  123.              output_name.ds_string);
  124.           continue;        /* Go to the next file.  */
  125.         }
  126.     }
  127.  
  128.       /* Do the real copy or link.  */
  129.       if (S_ISREG (in_file_stat.st_mode))
  130.     {
  131. #ifndef __MSDOS__
  132.       /* Can the current file be linked to a another file?
  133.          Set link_name to the original file name.  */
  134.       if (link_flag)
  135.         /* User said to link it if possible.  Try and link to
  136.            the original copy.  If that fails we'll still try
  137.            and link to a copy we've already made.  */
  138.         link_res = link_to_name (output_name.ds_string, 
  139.                      input_name.ds_string);
  140.       if ( (link_res < 0) && (in_file_stat.st_nlink > 1) )
  141.         link_res = link_to_maj_min_ino (output_name.ds_string, 
  142.                 major (in_file_stat.st_dev), 
  143.                 minor (in_file_stat.st_dev), 
  144.                 in_file_stat.st_ino);
  145. #endif
  146.  
  147.       /* If the file was not linked, copy contents of file.  */
  148.       if (link_res < 0)
  149.         {
  150.           in_file_des = open (input_name.ds_string,
  151.                   O_RDONLY | O_BINARY, 0);
  152.           if (in_file_des < 0)
  153.         {
  154.           error (0, errno, "%s", input_name.ds_string);
  155.           continue;
  156.         }
  157.           out_file_des = open (output_name.ds_string,
  158.                    O_CREAT | O_WRONLY | O_BINARY, 0600);
  159.           if (out_file_des < 0 && create_dir_flag)
  160.         {
  161.           create_all_directories (output_name.ds_string);
  162.           out_file_des = open (output_name.ds_string,
  163.                        O_CREAT | O_WRONLY | O_BINARY, 0600);
  164.         }
  165.           if (out_file_des < 0)
  166.         {
  167.           error (0, errno, "%s", output_name.ds_string);
  168.           close (in_file_des);
  169.           continue;
  170.         }
  171.  
  172.           copy_files (in_file_des, out_file_des, in_file_stat.st_size);
  173.           empty_output_buffer (out_file_des);
  174.           if (close (in_file_des) < 0)
  175.         error (0, errno, "%s", input_name.ds_string);
  176.           if (close (out_file_des) < 0)
  177.         error (0, errno, "%s", output_name.ds_string);
  178.  
  179.           /* Set the attributes of the new file.  */
  180.           if (!no_chown_flag)
  181.         if ((chown (output_name.ds_string,
  182.                 set_owner_flag ? set_owner : in_file_stat.st_uid,
  183.               set_group_flag ? set_group : in_file_stat.st_gid) < 0)
  184.             && errno != EPERM)
  185.           error (0, errno, "%s", output_name.ds_string);
  186.           /* chown may have turned off some permissions we wanted. */
  187.           if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
  188.         error (0, errno, "%s", output_name.ds_string);
  189.           if (reset_time_flag)
  190.         {
  191.           times.actime = in_file_stat.st_atime;
  192.           times.modtime = in_file_stat.st_mtime;
  193.           if (utime (input_name.ds_string, ×) < 0)
  194.             error (0, errno, "%s", input_name.ds_string);
  195.           if (utime (output_name.ds_string, ×) < 0)
  196.             error (0, errno, "%s", output_name.ds_string);
  197.         }
  198.           if (retain_time_flag)
  199.         {
  200.           times.actime = times.modtime = in_file_stat.st_mtime;
  201.           if (utime (output_name.ds_string, ×) < 0)
  202.             error (0, errno, "%s", output_name.ds_string);
  203.         }
  204.         }
  205.     }
  206.       else if (S_ISDIR (in_file_stat.st_mode))
  207.     {
  208. #ifdef HPUX_CDF
  209.       cdf_flag = 0;
  210. #endif
  211.       if (!existing_dir)
  212.         {
  213. #ifdef HPUX_CDF
  214.           /* If the directory name ends in a + and is SUID,
  215.          then it is a CDF.  Strip the trailing + from the name
  216.          before creating it.  */
  217.           cdf_char = strlen (output_name.ds_string) - 1;
  218.           if ( (cdf_char > 0) &&
  219.            (in_file_stat.st_mode & 04000) &&
  220.            (output_name.ds_string [cdf_char] == '+') )
  221.         {
  222.           output_name.ds_string [cdf_char] = '\0';
  223.           cdf_flag = 1;
  224.         }
  225. #endif
  226.           res = mkdir (output_name.ds_string, in_file_stat.st_mode);
  227.  
  228.         }
  229.       else
  230.         res = 0;
  231.       if (res < 0 && create_dir_flag)
  232.         {
  233.           create_all_directories (output_name.ds_string);
  234.           res = mkdir (output_name.ds_string, in_file_stat.st_mode);
  235.         }
  236.       if (res < 0)
  237.         {
  238.           error (0, errno, "%s", output_name.ds_string);
  239.           continue;
  240.         }
  241.       if (!no_chown_flag)
  242.         if ((chown (output_name.ds_string,
  243.             set_owner_flag ? set_owner : in_file_stat.st_uid,
  244.               set_group_flag ? set_group : in_file_stat.st_gid) < 0)
  245.         && errno != EPERM)
  246.           error (0, errno, "%s", output_name.ds_string);
  247.       /* chown m