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 >
Wrap
C/C++ Source or Header
|
1992-02-22
|
10KB
|
346 lines
/* 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);
}