home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
arc
/
Archiver
/
cpio
/
src
/
copyin.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-19
|
26KB
|
945 lines
/* copyin.c - extract or list a cpio archive
Copyright (C) 1990, 1991, 1992 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 2, 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. */
#include <stdio.h>
#include <fnmatch.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "filetypes.h"
#include "system.h"
#include "cpiohdr.h"
#include "dstring.h"
#include "extern.h"
#include "rmt.h"
#ifndef HAVE_LCHOWN
#define lchown chown
#endif
static void read_pattern_file ();
static void skip_padding ();
/* Return 16-bit integer I with the bytes swapped. */
#define swab_short(i) ((((i) << 8) & 0xff00) | (((i) >> 8) & 0x00ff))
/* Read the header, including the name of the file, from file
descriptor IN_DES into FILE_HDR. */
void
read_in_header (file_hdr, in_des)
struct new_cpio_header *file_hdr;
int in_des;
{
long bytes_skipped = 0; /* Bytes of junk found before magic number. */
/* Search for a valid magic number. */
if (archive_format == arf_unknown)
{
char tmpbuf[512];
int check_tar;
int peeked_bytes;
while (archive_format == arf_unknown)
{
peeked_bytes = peek_in_buf (tmpbuf, in_des, 512);
if (peeked_bytes < 6)
error (1, 0, "premature end of archive");
if (!strncmp (tmpbuf, "070701", 6))
archive_format = arf_newascii;
else if (!strncmp (tmpbuf, "070707", 6))
archive_format = arf_oldascii;
else if (!strncmp (tmpbuf, "070702", 6))
{
archive_format = arf_crcascii;
crc_i_flag = TRUE;
}
else if ((*((unsigned short *) tmpbuf) == 070707) ||
(*((unsigned short *) tmpbuf) == swab_short ((unsigned short) 070707)))
archive_format = arf_binary;
else if (peeked_bytes >= 512
&& (check_tar = is_tar_header (tmpbuf)))
{
if (check_tar == 2)
archive_format = arf_ustar;
else
archive_format = arf_tar;
}
else
{
copy_in_buf ((char *) tmpbuf, in_des, 1L);
++bytes_skipped;
}
}
}
if (archive_format == arf_tar || archive_format == arf_ustar)
{
if (append_flag)
last_header_start = input_bytes - io_block_size +
(in_buff - input_buffer);
if (bytes_skipped > 0)
error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
read_in_tar_header (file_hdr, in_des);
return;
}
file_hdr->c_tar_linkname = NULL;
copy_in_buf ((char *) file_hdr, in_des, 6L);
while (1)
{
if (append_flag)
last_header_start = input_bytes - io_block_size
+ (in_buff - input_buffer) - 6;
if (archive_format == arf_newascii
&& !strncmp ((char *) file_hdr, "070701", 6))
{
if (bytes_skipped > 0)
error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
read_in_new_ascii (file_hdr, in_des);
break;
}
if (archive_format == arf_crcascii
&& !strncmp ((char *) file_hdr, "070702", 6))
{
if (bytes_skipped > 0)
error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
read_in_new_ascii (file_hdr, in_des);
break;
}
if (archive_format == arf_oldascii
&& !strncmp ((char *) file_hdr, "070707", 6))
{
if (bytes_skipped > 0)
error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
read_in_old_ascii (file_hdr, in_des);
break;
}
if (archive_format == arf_binary
&& (file_hdr->c_magic == 070707
|| file_hdr->c_magic == swab_short ((unsigned short) 070707)))
{
/* Having to skip 1 byte because of word alignment is normal. */
if (bytes_skipped > 0)
error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
read_in_binary (file_hdr, in_des);
break;
}
bytes_skipped++;
bcopy ((char *) file_hdr + 1, (char *) file_hdr, 5);
copy_in_buf ((char *) file_hdr + 5, in_des, 1L);
}
}
/* Fill in FILE_HDR by reading an old-format ASCII format cpio header from
file descriptor IN_DES, except for the magic number, which is
already filled in. */
void
read_in_old_ascii (file_hdr, in_des)
struct new_cpio_header *file_hdr;
int in_des;
{
char ascii_header[78];
unsigned long dev;
unsigned long rdev;
copy_in_buf (ascii_header, in_des, 70L);
ascii_header[70] = '\0';
sscanf (ascii_header,
"%6o%6o%6o%6o%6o%6o%6o%11o%6o%11o",
&dev, &file_hdr->c_ino,
&file_hdr->c_mode, &file_hdr->c_uid, &file_hdr->c_gid,
&file_hdr->c_nlink, &rdev, &file_hdr->c_mtime,
&file_hdr->c_namesize, &file_hdr->c_filesize);
file_hdr->c_dev_maj = major (dev);
file_hdr->c_dev_min = minor (dev);
file_hdr->c_rdev_maj = major (rdev);
file_hdr->c_rdev_min = minor (rdev);
/* Read file name from input. */
if (file_hdr->c_name != NULL)
free (file_hdr->c_name);
file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize + 1);
copy_in_buf (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
}
/* Fill in FILE_HDR by reading a new-format ASCII format cpio header from
file descriptor IN_DES, except for the magic number, which is
already filled in. */
void
read_in_new_ascii (file_hdr, in_des)
struct new_cpio_header *file_hdr;
int in_des;
{
char ascii_header[112];
copy_in_buf (ascii_header, in_des, 104L);
ascii_header[104] = '\0';
sscanf (ascii_header,
"%8x%8x%8x%8x%8x%8x%8x%8x%8x%8x%8x%8x%8x",
&file_hdr->c_ino, &file_hdr->c_mode, &file_hdr->c_uid,
&file_hdr->c_gid, &file_hdr->c_nlink, &file_hdr->c_mtime,
&file_hdr->c_filesize, &file_hdr->c_dev_maj, &file_hdr->c_dev_min,
&file_hdr->c_rdev_maj, &file_hdr->c_rdev_min, &file_hdr->c_namesize,
&file_hdr->c_chksum);
/* Read file name from input. */
if (file_hdr->c_name != NULL)
free (file_hdr->c_name);
file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize);
copy_in_buf (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
/* In SVR4 ASCII format, the amount of space allocated for the header
is rounded up to the next long-word, so we might need to drop
1-3 bytes. */
skip_padding (in_des, file_hdr->c_namesize + 110);
}
/* Fill in FILE_HDR by reading a binary format cpio header from
file descriptor IN_DES, except for the first 6 bytes (the magic
number), which are already filled in. */
void
read_in_binary (file_hdr, in_des)
struct new_cpio_header *file_hdr;
int in_des;
{
struct old_cpio_header short_hdr;
copy_in_buf (((char *) &short_hdr) + 6, in_des, 20L);
/* If the magic number is byte swapped, fix the header. */
if (file_hdr->c_magic == swab_short ((unsigned short) 070707))
{
static int warned = 0;
/* Alert the user that they might have to do byte swapping on
the file contents. */
if (warned == 0)
{
error (0, 0, "warning: archive header has reverse byte-order");
warned = 1;
}
swab_array ((char *) &short_hdr, 13);
}
file_hdr->c_dev_maj = major (short_hdr.c_dev);
file_hdr->c_dev_min = minor (short_hdr.c_dev);
file_hdr->c_ino = short_hdr.c_ino;
file_hdr->c_mode = short_hdr.c_mode;
file_hdr->c_uid = short_hdr.c_uid;
file_hdr->c_gid = short_hdr.c_gid;
file_hdr->c_nlink = short_hdr.c_nlink;
file_hdr->c_rdev_maj = major (short_hdr.c_rdev);
file_hdr->c_rdev_min = minor (short_hdr.c_rdev);
file_hdr->c_mtime = (unsigned long) short_hdr.c_mtimes[0] << 16
| short_hdr.c_mtimes[1];
file_hdr->c_namesize = short_hdr.c_namesize;
file_hdr->c_filesize = (unsigned long) short_hdr.c_filesizes[0] << 16
| short_hdr.c_filesizes[1];
/* Read file name from input. */
if (file_hdr->c_name != NULL)
free (file_hdr->c_name);
file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize);
copy_in_buf (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
/* In binary mode, the amount of space allocated in the header for
the filename is `c_namesize' rounded up to the next short-word,
so we might need to drop a byte. */
if (file_hdr->c_namesize % 2)
toss_input (in_des, 1L);
}
/* Exchange the bytes of each element of the array of COUNT shorts
starting at PTR. */
void
swab_array (ptr, count)
char *ptr;
int count;
{
char tmp;
while (count-- > 0)
{
tmp = *ptr;
*ptr = *(ptr + 1);
++ptr;
*ptr = tmp;
++ptr;
}
}
/* Current time for verbose table. */
static time_t current_time;
/* Read the collection from standard input and create files
in the file system. */
void
process_copy_in ()
{
char done = FALSE; /* True if trailer reached. */
int res; /* Result of various function calls. */
dynamic_string new_name; /* New file name for rename option. */
FILE *tty_in; /* Interactive file for rename option. */
FILE *tty_out; /* Interactive file for rename option. */
char *str_res; /* Result for string function. */
struct utimbuf times; /* For setting file times. */
struct stat file_stat; /* Output file stat record. */
struct new_cpio_header file_hdr; /* Output header information. */
int out_file_des; /* Output file descriptor. */
int in_file_des; /* Input file descriptor. */
char skip_file; /* Flag for use with patterns. */
int existing_dir; /* True if file is a dir & already exists. */
int i; /* Loop index variable. */
char *link_name = NULL; /* Name of hard and symbolic links. */
/* Initialize the copy in. */
if (pattern_file_name)
read_pattern_file ();
file_hdr.c_name = NULL;
ds_init (&new_name, 128);
/* Initialize this in case it has members we don't know to set. */
bzero (×, sizeof (struct utimbuf));
/* Open interactive file pair for rename operation. */
if (rename_flag)
{
tty_in = fopen (CONSOLE, "r");
if (tty_in == NULL)
error (2, errno, CONSOLE);
tty_out = fopen (CONSOLE, "w");
if (tty_out == NULL)
error (2, errno, CONSOLE);
}
/* Get date and time if needed for processing the table option. */
if (table_flag && verbose_flag)
time (¤t_time);
#ifdef __MSDOS__
setmode (archive_des, O_BINARY);
#endif
/* Check whether the input file might be a tape. */
in_file_des = archive_des;
if (_isrmt (in_file_des))
{
input_is_special = 1;
input_is_seekable = 0;
}
else
{
if (fstat (in_file_des, &file_stat))
error (1, errno, "standard input is closed");
input_is_special =
#ifdef S_ISBLK
S_ISBLK (file_stat.st_mode) ||
#endif
S_ISCHR (file_stat.st_mode);
input_is_seekable = S_ISREG (file_stat.st_mode);
}
output_is_seekable = TRUE;
/* While there is more input in the collection, process the input. */
while (!done)
{
link_name = NULL;
swapping_halfwords = swapping_bytes = FALSE;
/* Start processing the next file by reading the header. */
read_in_header (&file_hdr, in_file_des);
/* Is this the header for the TRAILER file? */
if (strcmp ("TRAILER!!!", file_hdr.c_name) == 0)
{
done = TRUE;
break;
}
/* Does the file name match one of the given patterns? */
if (num_patterns <= 0)
skip_file = FALSE;
else
{
skip_file = copy_matching_files;
for (i = 0; i < num_patterns
&& skip_file == copy_matching_files; i++)
{
if (fnmatch (save_patterns[i], file_hdr.c_name, 0) == 0)
skip_file = !copy_matching_files;
}
}
if (skip_file)
{
toss_input (in_file_des, file_hdr.c_filesize);
skip_padding (in_file_des, file_hdr.c_filesize);
}
else if (table_flag)
{
if (verbose_flag)
{
#ifdef CP_IFLNK
if ((file_hdr.c_mode & CP_IFMT) == CP_IFLNK)
{
if (archive_format != arf_tar && archive_format != arf_ustar)
{
link_name = (char *) xmalloc ((unsigned int) file_hdr.c_filesize + 1);
link_name[file_hdr.c_filesize] = '\0';
copy_in_buf (link_name, in_file_des, file_hdr.c_filesize);
long_format (&file_hdr, link_name);
free (link_name);
skip_padding (in_file_des, file_hdr.c_filesize);
continue;
}
else
{
long_format (&file_hdr, file_hdr.c_tar_linkname);
continue;
}
}
else
#endif
long_format (&file_hdr, (char *) 0);
}
else
printf ("%s\n", file_hdr.c_name);
toss_input (in_file_des, file_hdr.c_filesize);
skip_padding (in_file_des, file_hdr.c_filesize);
}
else if (append_flag)
{
toss_input (in_file_des, file_hdr.c_filesize);
skip_padding (in_file_des, file_hdr.c_filesize);
}
else
{
/* Copy the input file into the directory structure. */
/* Do we need to rename the file? */
if (rename_flag)
{
fprintf (tty_out, "rename %s -> ", file_hdr.c_name);
fflush (tty_out);
str_res = ds_fgets (tty_in, &new_name);
if (str_res == NULL || str_res[0] == 0)
{
toss_input (in_file_des, file_hdr.c_filesize);
skip_padding (in_file_des, file_hdr.c_filesize);
continue;
}
else
file_hdr.c_name = xstrdup (new_name.ds_string);
}
/* See if the file already exists. */
existing_dir = FALSE;
if (lstat (file_hdr.c_name, &file_stat) == 0)
{
if (S_ISDIR (file_stat.st_mode)
&& ((file_hdr.c_mode & CP_IFMT) == CP_IFDIR))
{
/* If there is already a directory there that
we are trying to create, don't complain about
it. */
existing_dir = TRUE;
}
else if (!unconditional_flag
&& file_hdr.c_mtime <= file_stat.st_mtime)
{
error (0, 0, "%s not created: newer or same age version exists",
file_hdr.c_name);
toss_input (in_file_des, file_hdr.c_filesize);
skip_padding (in_file_des, file_hdr.c_filesize);
continue; /* Go to the next file. */
}
else if (unlink (file_hdr.c_name))
{
error (0, errno, "cannot remove current %s",
file_hdr.c_name);
toss_input (in_file_des, file_hdr.c_filesize);
skip_padding (in_file_des, file_hdr.c_filesize);
continue; /* Go to the next file. */
}
}
/* Do the real copy or link. */
switch (file_hdr.c_mode & CP_IFMT)
{
case CP_IFREG:
#ifndef __MSDOS__
/* Can the current file be linked to a previously copied file? */
if (file_hdr.c_nlink > 1 && archive_format != arf_tar
&& archive_format != arf_ustar)
{
link_name = find_inode_file (file_hdr.c_ino,
file_hdr.c_dev_maj, file_hdr.c_dev_min);
if (link_name == NULL)
add_inode (file_hdr.c_ino, file_hdr.c_name,
file_hdr.c_dev_maj, file_hdr.c_dev_min);
else
{
res = link (link_name, file_hdr.c_name);
if (res < 0 && create_dir_flag)
{
create_all_directories (file_hdr.c_name);
res = link (link_name, file_hdr.c_name);
}
if (res == 0)
{
if (verbose_flag)
error (0, 0, "%s linked to %s",
link_name, file_hdr.c_name);
toss_input (in_file_des, file_hdr.c_filesize);
skip_padding (in_file_des, file_hdr.c_filesize);
}
else
link_name = NULL;
}
}
else if ((archive_format == arf_tar || archive_format == arf_ustar)
&& file_hdr.c_tar_linkname)
{
link_name = file_hdr.c_tar_linkname;
res = link (link_name, file_hdr.c_name);
if (res < 0 && create_dir_flag)
{
create_all_directories (file_hdr.c_name);
res = link (link_name, file_hdr.c_name);
}
if (res == 0)
{
if (verbose_flag)
error (0, 0, "%s linked to %s",
link_name, file_hdr.c_name);
}
else
{
error (0, errno, "cannot link %s to %s",
file_hdr.c_tar_linkname, file_hdr.c_name);
}
}
#endif
/* If not linked, copy the contents of the file. */
if (link_name == NULL)
{
out_file_des = open (file_hdr.c_name,
O_CREAT | O_WRONLY | O_BINARY, 0600);
if (out_file_des < 0 && create_dir_flag)
{
create_all_directories (file_hdr.c_name);
out_file_des = open (file_hdr.c_name,
O_CREAT | O_WRONLY | O_BINARY,
0600);
}
if (out_file_des < 0)
{
error (0, errno, "%s", file_hdr.c_name);
toss_input (in_file_des, file_hdr.c_filesize);
skip_padding (in_file_des, file_hdr.c_filesize);
continue;
}
crc = 0;
if (swap_halfwords_flag)
{
if ((file_hdr.c_filesize % 4) == 0)
swapping_halfwords = TRUE;
else
error (0, 0, "cannot swap halfwords of %s: odd number of halfwords",
file_hdr.c_name);
}
if (swap_bytes_flag)
{
if ((file_hdr.c_filesize % 2) == 0)
swapping_bytes = TRUE;
else
error (0, 0, "cannot swap bytes of %s: odd number of bytes",
file_hdr.c_name);
}
copy_files (in_file_des, out_file_des, file_hdr.c_filesize);
empty_output_buffer (out_file_des);
if (close (out_file_des) < 0)
error (0, errno, "%s", file_hdr.c_name);
if (archive_format == arf_crcascii)
{
if (crc != file_hdr.c_chksum)
error (0, 0, "%s: checksum error (0x%x, should be 0x%x)",
file_hdr.c_name, crc, file_hdr.c_chksum);
}
/* File is now copied; set attributes. */
if (!no_chown_flag)
if ((chown (file_hdr.c_name,
set_owner_flag ? set_owner : file_hdr.c_uid,
set_group_flag ? set_group : file_hdr.c_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", file_hdr.c_name);
/* chown may have turned off some permissions we wanted. */
if (chmod (file_hdr.c_name, (int) file_hdr.c_mode) < 0)
error (0, errno, "%s", file_hdr.c_name);
if (retain_time_flag)
{
times.actime = times.modtime = file_hdr.c_mtime;
if (utime (file_hdr.c_name, ×) < 0)
error (0, errno, "%s", file_hdr.c_name);
}
skip_padding (in_file_des, file_hdr.c_filesize);
}
break;
case CP_IFDIR:
/* Strip any trailing `/'s off the filename; tar puts
them on. We might as well do it here in case anybody
else does too, since they cause strange things to happen. */
strip_trailing_slashes (file_hdr.c_name);
/* Ignore the current directory. It must already exist,
and we don't want to change its permission, ownership
or time. */
if (file_hdr.c_name[0] == '.' && file_hdr.c_name[1] == '\0')
break;
if (!existing_dir)
res = mkdir (file_hdr.c_name, file_hdr.c_mode);
else
res = 0;
if (res < 0 && create_dir_flag)
{
create_all_directories (file_hdr.c_name);
res = mkdir (file_hdr.c_name, file_hdr.c_mode);
}
if (res < 0)
{
error (0, errno, "%s", file_hdr.c_name);
continue;
}
if (!no_chown_flag)
if ((chown (file_hdr.c_name,
set_owner_flag ? set_owner : file_hdr.c_uid,
set_group_flag ? set_group : file_hdr.c_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", file_hdr.c_name);
/* chown may have turned off some permissions we wanted. */
if (chmod (file_hdr.c_name, (int) file_hdr.c_mode) < 0)
error (0, errno, "%s", file_hdr.c_name);
if (retain_time_flag)
{
times.actime = times.modtime = file_hdr.c_mtime;
if (utime (file_hdr.c_name, ×) < 0)
error (0, errno, "%s", file_hdr.c_name);
}
break;
#ifndef __MSDOS__
case CP_IFCHR:
case CP_IFBLK:
#ifdef CP_IFSOCK
case CP_IFSOCK:
#endif
#ifdef CP_IFIFO
case CP_IFIFO:
#endif
res = mknod (file_hdr.c_name, file_hdr.c_mode,
makedev (file_hdr.c_rdev_maj, file_hdr.c_rdev_min));
if (res < 0 && create_dir_flag)
{
create_all_directories (file_hdr.c_name);
res = mknod (file_hdr.c_name, file_hdr.c_mode,
makedev (file_hdr.c_rdev_maj, file_hdr.c_rdev_min));
}
if (res < 0)
{
error (0, errno, "%s", file_hdr.c_name);
continue;
}
if (!no_chown_flag)
if ((chown (file_hdr.c_name,
set_owner_flag ? set_owner : file_hdr.c_uid,
set_group_flag ? set_group : file_hdr.c_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", file_hdr.c_name);
/* chown may have turned off some permissions we wanted. */
if (chmod (file_hdr.c_name, file_hdr.c_mode) < 0)
error (0, errno, "%s", file_hdr.c_name);
break;
#endif
#ifdef CP_IFLNK
case CP_IFLNK:
{
if (archive_format != arf_tar && archive_format != arf_ustar)
{
link_name = (char *) xmalloc ((unsigned int) file_hdr.c_filesize + 1);
link_name[file_hdr.c_filesize] = '\0';
copy_in_buf (link_name, in_file_des, file_hdr.c_filesize);
skip_padding (in_file_des, file_hdr.c_filesize);
}
else
{
link_name = xstrdup (file_hdr.c_tar_linkname);
}
res = symlink (link_name, file_hdr.c_name);
if (res < 0 && create_dir_flag)
{
create_all_directories (file_hdr.c_name);
res = symlink (link_name, file_hdr.c_name);
}
if (res < 0)
{
error (0, errno, "%s", file_hdr.c_name);
free (link_name);
link_name = NULL;
continue;
}
if (!no_chown_flag)
if ((lchown (file_hdr.c_name,
set_owner_flag ? set_owner : file_hdr.c_uid,
set_group_flag ? set_group : file_hdr.c_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", file_hdr.c_name);
free (link_name);
link_name = NULL;
}
break;
#endif
default:
error (0, 0, "%s: unknown file type", file_hdr.c_name);
toss_input (in_file_des, file_hdr.c_filesize);
skip_padding (in_file_des, file_hdr.c_filesize);
}
if (verbose_flag)
fprintf (stderr, "%s\n", file_hdr.c_name);
if (dot_flag)
fputc ('.', stderr);
}
}
if (dot_flag)
fputc ('\n', stderr);
if (append_flag)
return;
res = (input_bytes + io_block_size - 1) / io_block_size;
if (res == 1)
fprintf (stderr, "1 block\n");
else
fprintf (stderr, "%d blocks\n", res);
}
/* Print the file described by FILE_HDR in long format.
If LINK_NAME is nonzero, it is the name of the file that
this file is a symbolic link to. */
void
long_format (file_hdr, link_name)
struct new_cpio_header *file_hdr;
char *link_name;
{
char mbuf[11];
char tbuf[40];
time_t when;
mode_string (file_hdr->c_mode, mbuf);
mbuf[10] = '\0';
/* Get time values ready to print. */
when = file_hdr->c_mtime;
strcpy (tbuf, ctime (&when));
if (current_time - when > 6L * 30L * 24L * 60L * 60L
|| current_time - when < 0L)
{
/* The file is older than 6 months, or in the future.
Show the year instead of the time of day. */
strcpy (tbuf + 11, tbuf + 19);
}
tbuf[16] = '\0';
printf ("%s %3u ", mbuf, file_hdr->c_nlink);
#ifndef __MSDOS__
if (numeric_uid)
#endif
printf ("%-8u %-8u ", (unsigned int) file_hdr->c_uid,
(unsigned int) file_hdr->c_gid);
#ifndef __MSDOS__
else
printf ("%-8.8s %-8.8s ", getuser (file_hdr->c_uid),
getgroup (file_hdr->c_gid));
if ((file_hdr->c_mode & CP_IFMT) == CP_IFCHR
|| (file_hdr->c_mode & CP_IFMT) == CP_IFBLK)
printf ("%3u, %3u ", file_hdr->c_rdev_maj,
file_hdr->c_rdev_min);
else
#endif
printf ("%8lu ", file_hdr->c_filesize);
printf ("%s ", tbuf + 4);
print_name_with_quoting (file_hdr->c_name);
if (link_name)
{
printf (" -> ");
print_name_with_quoting (link_name);
}
putc ('\n', stdout);
}
void
print_name_with_quoting (p)
register char *p;
{
register unsigned char c;
while (c = *p++)
{
switch (c)
{
#ifndef __MSDOS__
case '\\':
printf ("\\\\");
break;
#endif
case '\n':
printf ("\\n");
break;
case '\b':
printf ("\\b");
break;
case '\r':
printf ("\\r");
break;
case '\t':
printf ("\\t");
break;
case '\f':
printf ("\\f");
break;
case ' ':
printf ("\\ ");
break;
case '"':
printf ("\\\"");
break;
default:
if (c > 040 &&
#ifdef __MSDOS__
c < 0377 && c != 0177
#else
c < 0177
#endif
)
putchar (c);
else
printf ("\\%03o", (unsigned int) c);
}
}
}
/* Read a pattern file (for the -E option). Put a list of
`num_patterns' elements in `save_patterns'. Any patterns that were
already in `save_patterns' (from the command line) are preserved. */
static void
read_pattern_file ()
{
int max_new_patterns;
char **new_save_patterns;
int new_num_patterns;
int i;
dynamic_string pattern_name;
FILE *pattern_fp;
if (num_patterns < 0)
num_patterns = 0;
max_new_patterns = 1 + num_patterns;
new_save_patterns = (char **) xmalloc (max_new_patterns * sizeof (char *));
new_num_patterns = num_patterns;
ds_init (&pattern_name, 128);
pattern_fp = fopen (pattern_file_name, "r");
if (pattern_fp == NULL)
error (1, errno, "%s", pattern_file_name);
while (ds_fgetstr (pattern_fp, &pattern_name, '\n') != NULL)
{
if (new_num_patterns >= max_new_patterns)
{
max_new_patterns += 1;
new_save_patterns = (char **)
xrealloc ((char *) new_save_patterns,
max_new_patterns * sizeof (char *));
}
new_save_patterns[new_num_patterns] = xstrdup (pattern_name.ds_string);
++new_num_patterns;
}
if (ferror (pattern_fp) || fclose (pattern_fp) == EOF)
error (1, errno, "%s", pattern_file_name);
for (i = 0; i < num_patterns; ++i)
new_save_patterns[i] = save_patterns[i];
save_patterns = new_save_patterns;
num_patterns = new_num_patterns;
}
/* Skip the padding on IN_FILE_DES after a header or file,
up to the next header.
The number of bytes skipped is based on OFFSET -- the current offset
from the last start of a header (or file) -- and the current
header type. */
static void
skip_padding (in_file_des, offset)
int in_file_des;
int offset;
{
int pad;
if (archive_format == arf_crcascii || archive_format == arf_newascii)
pad = (4 - (offset % 4)) % 4;
else if (archive_format == arf_binary)
pad = (2 - (offset % 2)) % 2;
else if (archive_format == arf_tar || archive_format == arf_ustar)
pad = (512 - (offset % 512)) % 512;
else
pad = 0;
if (pad != 0)
toss_input (in_file_des, pad);
}