home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / c / cpio11as.zip / COPYPASS.C < prev    next >
C/C++ Source or Header  |  1992-02-22  |  10KB  |  346 lines

  1. /* copypass.c - cpio copy pass sub-function.
  2.    Copyright (C) 1988, 1989, 1990 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 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. /* MS-DOS port (c) 1990 by Thorsten Ohl, ohl@gnu.ai.mit.edu
  19.    This port is also distributed under the terms of the
  20.    GNU General Public License as published by the
  21.    Free Software Foundation.
  22.  
  23.    Please note that this file is not identical to the
  24.    original GNU release, you should have received this
  25.    code as patch to the official release.
  26.  
  27.    $Header: e:/gnu/cpio/RCS/copypass.c 1.1.0.2 90/09/23 23:11:03 tho Exp $
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #ifndef S_IFLNK
  34. #define lstat stat
  35. #endif
  36. #include <errno.h>
  37. #ifndef MSDOS            /* sigh, it's `volatile' !!! */
  38. extern int errno;
  39. #endif
  40. #include <fcntl.h>
  41. #ifndef MSDOS
  42. #include <sys/file.h>
  43. #endif
  44. #ifdef USG
  45. #include <time.h>
  46. #include <string.h>
  47. #else
  48. #include <sys/time.h>
  49. #include <strings.h>
  50. #endif
  51. #include "cpio.h"
  52. #include "dstring.h"
  53. #include "extern.h"
  54.  
  55. #ifdef MSDOS
  56. extern int mkdir (char *, int);    /* we're cheating! */
  57. #endif
  58.  
  59. /* Copy files listed on the standard input into directory `directory_name'.
  60.    If `link_flag', link instead of copying. */
  61.  
  62. void
  63. process_copy_pass ()
  64. {
  65.   dynamic_string input_name;    /* Name of file from stdin. */
  66.   dynamic_string output_name;    /* Name of new file. */
  67.   int dirname_len;        /* Length of `directory_name'. */
  68.   int res;            /* Result of functions. */
  69.   char *slash;            /* For moving past slashes in input name. */
  70.   long times[2];        /* For resetting file times after copy.  */
  71.   struct stat in_file_stat;    /* Stat record for input file. */
  72.   struct stat out_file_stat;    /* Stat record for output file. */
  73.   int in_file_des;        /* Input file descriptor. */
  74.   int out_file_des;        /* Output file descriptor. */
  75.  
  76.   /* Initialize the copy out. */
  77.   dirname_len = strlen (directory_name);
  78.   ds_init (&input_name, 128);
  79.   ds_init (&output_name, dirname_len + 2);
  80.   strcpy (output_name.ds_string, directory_name);
  81.   output_name.ds_string[dirname_len] = '/';
  82.   output_is_seekable = TRUE;
  83.  
  84.   /* Copy files with names read from stdin. */
  85.   while (ds_fgets (stdin, &input_name) != NULL)
  86.     {
  87.       char *link_name = NULL;
  88.  
  89.       /* Check for blank line and ignore it if found. */
  90.       if (input_name.ds_string[0] == '\0')
  91.     {
  92.       error (0, 0, "blank line ignored");
  93.       continue;
  94.     }
  95.  
  96.       if ((*xstat) (input_name.ds_string, &in_file_stat) < 0)
  97.     {
  98.       error (0, errno, "%s", input_name.ds_string);
  99.       continue;
  100.     }
  101.  
  102.       /* Make the name of the new file. */
  103.       for (slash = input_name.ds_string; *slash == '/'; ++slash)
  104.     ;
  105.       ds_resize (&output_name, dirname_len + strlen (slash) + 2);
  106.       strcpy (output_name.ds_string + dirname_len + 1, slash);
  107.  
  108.       if (lstat (output_name.ds_string, &out_file_stat) == 0)
  109.     {
  110.       if (!unconditional_flag
  111.           && in_file_stat.st_mtime < out_file_stat.st_mtime)
  112.         {
  113.           error (0, 0, "%s not created: newer version exists",
  114.              output_name.ds_string);
  115.           continue;        /* Go to the next file. */
  116.         }
  117.       else if ((out_file_stat.st_mode & S_IFMT) == S_IFDIR)
  118.         {
  119.           error (0, 0, "cannot remove current %s: Is a directory",
  120.              output_name.ds_string);
  121.           continue;        /* Go to the next file. */
  122.         }
  123.       else if (unlink (output_name.ds_string))
  124.         {
  125.           error (0, errno, "cannot remove current %s",
  126.              output_name.ds_string);
  127.           continue;        /* Go to the next file. */
  128.         }          
  129.     }
  130.  
  131.       /* Do the real copy or link.  */
  132.       switch (in_file_stat.st_mode & S_IFMT)
  133.     {
  134.     case S_IFREG:
  135.       /* Can the current file be linked to a another file?
  136.          Set link_name to the original file name.  */
  137. #ifdef MSDOS
  138.           link_name = NULL;
  139. #else /* not MSDOS */
  140.       if (link_flag)
  141.         {
  142.           /* User said to link it if possible. */
  143.           link_name = input_name.ds_string;
  144.         }
  145.       else if (in_file_stat.st_nlink > 1)
  146.         {
  147.           /* Is the file a link to a previously copied file?  */
  148.           link_name = find_inode_file (in_file_stat.st_ino);
  149.           if (link_name == NULL)
  150.         add_inode (in_file_stat.st_ino, output_name.ds_string);
  151.         }
  152.  
  153.       /* If there is a link name, do the link.  */
  154.       if (link_name != NULL)
  155.         {
  156.           res = link (link_name, output_name.ds_string);
  157.           if (res < 0 && create_dir_flag)
  158.         {
  159.           create_all_directories (output_name.ds_string);
  160.           res = link (link_name, output_name.ds_string);
  161.         }
  162.           if (res == 0)
  163.         {
  164.           if (verbose_flag)
  165.             error (0, 0, "%s linked to %s",
  166.                link_name, output_name.ds_string);
  167.         }
  168.           else if (link_flag)
  169.         {
  170.           error (0, errno, "cannot link %s to %s",
  171.              link_name, output_name.ds_string);
  172.         }
  173.           else
  174.         {
  175.           /* For some reason we can not link a previously linked file.
  176.              Do a complete copy. */
  177.           link_name = NULL;
  178.         }
  179.         }
  180. #endif /* not MSDOS */
  181.  
  182.       /* If the file was not linked, copy contents of file. */
  183.       if (link_name == NULL)
  184.         {
  185. #ifdef MSDOS
  186.           in_file_des = open (input_name.ds_string,
  187.                   O_RDONLY | O_BINARY, 0);
  188. #else
  189.           in_file_des = open (input_name.ds_string, O_RDONLY, 0);
  190. #endif
  191.           if (in_file_des < 0)
  192.         {
  193.           error (0, errno, "%s", input_name.ds_string);
  194.           continue;
  195.         }
  196. #ifdef MSDOS
  197.           out_file_des = open (output_name.ds_string,
  198.                    O_CREAT | O_WRONLY | O_BINARY, 0600);
  199. #else
  200.           out_file_des = open (output_name.ds_string,
  201.                    O_CREAT | O_WRONLY, 0600);
  202. #endif
  203.           if (out_file_des < 0 && create_dir_flag)
  204.         {
  205.           create_all_directories (output_name.ds_string);
  206. #ifdef MSDOS
  207.           out_file_des = open (output_name.ds_string,
  208.                        O_CREAT | O_WRONLY | O_BINARY, 0600);
  209. #else
  210.           out_file_des = open (output_name.ds_string,
  211.                        O_CREAT | O_WRONLY, 0600);
  212. #endif
  213.         }
  214.           if (out_file_des < 0)
  215.         {
  216.           error (0, errno, "%s", output_name.ds_string);
  217.           close (in_file_des);
  218.           continue;
  219.         }
  220.  
  221.           copy_files (in_file_des, out_file_des, in_file_stat.st_size);
  222.           empty_output_buffer (out_file_des);
  223.           finish_output_file (output_name.ds_string, out_file_des);
  224.           close (in_file_des);
  225.           close (out_file_des);
  226.  
  227.           /* Set the attributes of the new file.  */
  228.           if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
  229.         error (0, errno, "%s", output_name.ds_string);
  230. #ifndef MSDOS
  231.           if (chown (output_name.ds_string, in_file_stat.st_uid,
  232.              in_file_stat.st_gid) < 0
  233.           && errno != EPERM)
  234.         error (0, errno, "%s", output_name.ds_string);
  235. #endif /* not MSDOS */
  236.           if (reset_time_flag)
  237.         {
  238.           times[0] = in_file_stat.st_atime;
  239.           times[1] = in_file_stat.st_mtime;
  240.           if (utime (input_name.ds_string, times) < 0)
  241.             error (0, errno, "%s", input_name.ds_string);
  242.           if (utime (output_name.ds_string, times) < 0)
  243.             error (0, errno, "%s", output_name.ds_string);
  244.         }
  245.         }
  246.       break;
  247.  
  248.     case S_IFDIR:
  249.       res = mkdir (output_name.ds_string, in_file_stat.st_mode);
  250.       if (res < 0 && create_dir_flag)
  251.         {
  252.           create_all_directories (output_name.ds_string);
  253.           res = mkdir (output_name.ds_string, in_file_stat.st_mode);
  254.         }
  255.       if (res < 0)
  256.         {
  257.           error (0, errno, "%s", output_name.ds_string);
  258.           continue;
  259.         }
  260. #ifndef MSDOS
  261.       if (chown (output_name.ds_string, in_file_stat.st_uid,
  262.              in_file_stat.st_gid) < 0
  263.           && errno != EPERM)
  264.         error (0, errno, "%s", output_name.ds_string);
  265. #endif /* not MSDOS */
  266.       break;
  267.  
  268.     case S_IFCHR:
  269. #ifdef S_IFBLK
  270.     case S_IFBLK:
  271. #endif
  272. #ifdef S_IFIFO
  273.     case S_IFIFO:
  274. #endif
  275. #ifdef S_IFSOCK
  276.     case S_IFSOCK:
  277. #endif
  278. #ifndef MSDOS
  279.        res = mknod (output_name.ds_string, in_file_stat.st_mode,
  280.                in_file_stat.st_rdev);
  281.       if (res < 0 && create_dir_flag)
  282.         {
  283.           create_all_directories (output_name.ds_string);
  284.           res = mknod (output_name.ds_string, in_file_stat.st_mode,
  285.                in_file_stat.st_rdev);
  286.         }
  287.       if (res < 0)
  288.         {
  289.           error (0, errno, "%s", output_name.ds_string);
  290.           continue;
  291.         }
  292.       if (chown (output_name.ds_string, in_file_stat.st_uid,
  293.              in_file_stat.st_gid) < 0
  294.           && errno != EPERM)
  295.         error (0, errno, "%s", output_name.ds_string);
  296. #endif /* not MSDOS */
  297.       break;
  298.  
  299. #ifdef S_IFLNK
  300.     case S_IFLNK:
  301.       link_name = (char *) xmalloc (in_file_stat.st_size + 1);
  302.  
  303.       if (readlink (input_name.ds_string, link_name,
  304.             in_file_stat.st_size) < 0)
  305.         {
  306.           error (0, errno, "%s", input_name.ds_string);
  307.           free (link_name);
  308.           continue;
  309.         }
  310.       link_name[in_file_stat.st_size] = '\0';
  311.  
  312.       res = symlink (link_name, output_name.ds_string);
  313.       if (res < 0 && create_dir_flag)
  314.         {
  315.           create_all_directories (output_name.ds_string);
  316.           res = symlink (link_name, output_name.ds_string);
  317.         }
  318.       if (res < 0)
  319.         {
  320.           error (0, errno, "%s", output_name.ds_string);
  321.           free (link_name);
  322.           continue;
  323.         }
  324.       free (link_name);
  325.       break;
  326. #endif
  327.  
  328.     default:
  329.       error (0, 0, "%s: unknown file type", input_name.ds_string);
  330.     }
  331.  
  332.       if (verbose_flag)
  333.     fprintf (stderr, "%s\n", output_name.ds_string);
  334.     }
  335.  
  336. #ifdef MSDOS
  337.   res = (int) (output_bytes / io_block_size);
  338. #else
  339.   res = output_bytes / io_block_size;
  340. #endif
  341.   if (res == 1)
  342.     fprintf (stderr, "1 block\n");
  343.   else
  344.     fprintf (stderr, "%d blocks\n", res);
  345. }
  346.