home *** CD-ROM | disk | FTP | other *** search
- /* copypass.c - cpio copy pass sub-function.
- Copyright (C) 1988, 1989, 1990 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* MS-DOS port (c) 1990 by Thorsten Ohl, ohl@gnu.ai.mit.edu
- This port is also distributed under the terms of the
- GNU General Public License as published by the
- Free Software Foundation.
-
- Please note that this file is not identical to the
- original GNU release, you should have received this
- code as patch to the official release.
-
- $Header: e:/gnu/cpio/RCS/copypass.c 1.1.0.2 90/09/23 23:11:03 tho Exp $
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #ifndef S_IFLNK
- #define lstat stat
- #endif
- #include <errno.h>
- #ifndef MSDOS /* sigh, it's `volatile' !!! */
- extern int errno;
- #endif
- #include <fcntl.h>
- #ifndef MSDOS
- #include <sys/file.h>
- #endif
- #ifdef USG
- #include <time.h>
- #include <string.h>
- #else
- #include <sys/time.h>
- #include <strings.h>
- #endif
- #include "cpio.h"
- #include "dstring.h"
- #include "extern.h"
-
- #ifdef MSDOS
- extern int mkdir (char *, int); /* we're cheating! */
- #endif
-
- /* Copy files listed on the standard input into directory `directory_name'.
- If `link_flag', link instead of copying. */
-
- void
- process_copy_pass ()
- {
- dynamic_string input_name; /* Name of file from stdin. */
- dynamic_string output_name; /* Name of new file. */
- int dirname_len; /* Length of `directory_name'. */
- int res; /* Result of functions. */
- char *slash; /* For moving past slashes in input name. */
- long times[2]; /* For resetting file times after copy. */
- struct stat in_file_stat; /* Stat record for input file. */
- struct stat out_file_stat; /* Stat record for output file. */
- int in_file_des; /* Input file descriptor. */
- int out_file_des; /* Output file descriptor. */
-
- /* Initialize the copy out. */
- dirname_len = strlen (directory_name);
- ds_init (&input_name, 128);
- ds_init (&output_name, dirname_len + 2);
- strcpy (output_name.ds_string, directory_name);
- output_name.ds_string[dirname_len] = '/';
- output_is_seekable = TRUE;
-
- /* Copy files with names read from stdin. */
- while (ds_fgets (stdin, &input_name) != NULL)
- {
- char *link_name = NULL;
-
- /* Check for blank line and ignore it if found. */
- if (input_name.ds_string[0] == '\0')
- {
- error (0, 0, "blank line ignored");
- continue;
- }
-
- if ((*xstat) (input_name.ds_string, &in_file_stat) < 0)
- {
- error (0, errno, "%s", input_name.ds_string);
- continue;
- }
-
- /* Make the name of the new file. */
- for (slash = input_name.ds_string; *slash == '/'; ++slash)
- ;
- ds_resize (&output_name, dirname_len + strlen (slash) + 2);
- strcpy (output_name.ds_string + dirname_len + 1, slash);
-
- if (lstat (output_name.ds_string, &out_file_stat) == 0)
- {
- if (!unconditional_flag
- && in_file_stat.st_mtime < out_file_stat.st_mtime)
- {
- error (0, 0, "%s not created: newer version exists",
- output_name.ds_string);
- continue; /* Go to the next file. */
- }
- else if ((out_file_stat.st_mode & S_IFMT) == S_IFDIR)
- {
- error (0, 0, "cannot remove current %s: Is a directory",
- output_name.ds_string);
- continue; /* Go to the next file. */
- }
- else if (unlink (output_name.ds_string))
- {
- error (0, errno, "cannot remove current %s",
- output_name.ds_string);
- continue; /* Go to the next file. */
- }
- }
-
- /* Do the real copy or link. */
- switch (in_file_stat.st_mode & S_IFMT)
- {
- case S_IFREG:
- /* Can the current file be linked to a another file?
- Set link_name to the original file name. */
- #ifdef MSDOS
- link_name = NULL;
- #else /* not MSDOS */
- if (link_flag)
- {
- /* User said to link it if possible. */
- link_name = input_name.ds_string;
- }
- else if (in_file_stat.st_nlink > 1)
- {
- /* Is the file a link to a previously copied file? */
- link_name = find_inode_file (in_file_stat.st_ino);
- if (link_name == NULL)
- add_inode (in_file_stat.st_ino, output_name.ds_string);
- }
-
- /* If there is a link name, do the link. */
- if (link_name != NULL)
- {
- res = link (link_name, output_name.ds_string);
- if (res < 0 && create_dir_flag)
- {
- create_all_directories (output_name.ds_string);
- res = link (link_name, output_name.ds_string);
- }
- if (res == 0)
- {
- if (verbose_flag)
- error (0, 0, "%s linked to %s",
- link_name, output_name.ds_string);
- }
- else if (link_flag)
- {
- error (0, errno, "cannot link %s to %s",
- link_name, output_name.ds_string);
- }
- else
- {
- /* For some reason we can not link a previously linked file.
- Do a complete copy. */
- link_name = NULL;
- }
- }
- #endif /* not MSDOS */
-
- /* If the file was not linked, copy contents of file. */
- if (link_name == NULL)
- {
- #ifdef MSDOS
- in_file_des = open (input_name.ds_string,
- O_RDONLY | O_BINARY, 0);
- #else
- in_file_des = open (input_name.ds_string, O_RDONLY, 0);
- #endif
- if (in_file_des < 0)
- {
- error (0, errno, "%s", input_name.ds_string);
- continue;
- }
- #ifdef MSDOS
- out_file_des = open (output_name.ds_string,
- O_CREAT | O_WRONLY | O_BINARY, 0600);
- #else
- out_file_des = open (output_name.ds_string,
- O_CREAT | O_WRONLY, 0600);
- #endif
- if (out_file_des < 0 && create_dir_flag)
- {
- create_all_directories (output_name.ds_string);
- #ifdef MSDOS
- out_file_des = open (output_name.ds_string,
- O_CREAT | O_WRONLY | O_BINARY, 0600);
- #else
- out_file_des = open (output_name.ds_string,
- O_CREAT | O_WRONLY, 0600);
- #endif
- }
- if (out_file_des < 0)
- {
- error (0, errno, "%s", output_name.ds_string);
- close (in_file_des);
- continue;
- }
-
- copy_files (in_file_des, out_file_des, in_file_stat.st_size);
- empty_output_buffer (out_file_des);
- finish_output_file (output_name.ds_string, out_file_des);
- close (in_file_des);
- close (out_file_des);
-
- /* Set the attributes of the new file. */
- if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
- error (0, errno, "%s", output_name.ds_string);
- #ifndef MSDOS
- if (chown (output_name.ds_string, in_file_stat.st_uid,
- in_file_stat.st_gid) < 0
- && errno != EPERM)
- error (0, errno, "%s", output_name.ds_string);
- #endif /* not MSDOS */
- if (reset_time_flag)
- {
- times[0] = in_file_stat.st_atime;
- times[1] = in_file_stat.st_mtime;
- if (utime (input_name.ds_string, times) < 0)
- error (0, errno, "%s", input_name.ds_string);
- if (utime (output_name.ds_string, times) < 0)
- error (0, errno, "%s", output_name.ds_string);
- }
- }
- break;
-
- case S_IFDIR:
- res = mkdir (output_name.ds_string, in_file_stat.st_mode);
- if (res < 0 && create_dir_flag)
- {
- create_all_directories (output_name.ds_string);
- res = mkdir (output_name.ds_string, in_file_stat.st_mode);
- }
- if (res < 0)
- {
- error (0, errno, "%s", output_name.ds_string);
- continue;
- }
- #ifndef MSDOS
- if (chown (output_name.ds_string, in_file_stat.st_uid,
- in_file_stat.st_gid) < 0
- && errno != EPERM)
- error (0, errno, "%s", output_name.ds_string);
- #endif /* not MSDOS */
- break;
-
- case S_IFCHR:
- #ifdef S_IFBLK
- case S_IFBLK:
- #endif
- #ifdef S_IFIFO
- case S_IFIFO:
- #endif
- #ifdef S_IFSOCK
- case S_IFSOCK:
- #endif
- #ifndef MSDOS
- res = mknod (output_name.ds_string, in_file_stat.st_mode,
- in_file_stat.st_rdev);
- if (res < 0 && create_dir_flag)
- {
- create_all_directories (output_name.ds_string);
- res = mknod (output_name.ds_string, in_file_stat.st_mode,
- in_file_stat.st_rdev);
- }
- if (res < 0)
- {
- error (0, errno, "%s", output_name.ds_string);
- continue;
- }
- if (chown (output_name.ds_string, in_file_stat.st_uid,
- in_file_stat.st_gid) < 0
- && errno != EPERM)
- error (0, errno, "%s", output_name.ds_string);
- #endif /* not MSDOS */
- break;
-
- #ifdef S_IFLNK
- case S_IFLNK:
- link_name = (char *) xmalloc (in_file_stat.st_size + 1);
-
- if (readlink (input_name.ds_string, link_name,
- in_file_stat.st_size) < 0)
- {
- error (0, errno, "%s", input_name.ds_string);
- free (link_name);
- continue;
- }
- link_name[in_file_stat.st_size] = '\0';
-
- res = symlink (link_name, output_name.ds_string);
- if (res < 0 && create_dir_flag)
- {
- create_all_directories (output_name.ds_string);
- res = symlink (link_name, output_name.ds_string);
- }
- if (res < 0)
- {
- error (0, errno, "%s", output_name.ds_string);
- free (link_name);
- continue;
- }
- free (link_name);
- break;
- #endif
-
- default:
- error (0, 0, "%s: unknown file type", input_name.ds_string);
- }
-
- if (verbose_flag)
- fprintf (stderr, "%s\n", output_name.ds_string);
- }
-
- #ifdef MSDOS
- res = (int) (output_bytes / io_block_size);
- #else
- res = output_bytes / io_block_size;
- #endif
- if (res == 1)
- fprintf (stderr, "1 block\n");
- else
- fprintf (stderr, "%d blocks\n", res);
- }
-