diff options
Diffstat (limited to 'gnu/usr.bin/cpio/copyin.c')
-rw-r--r-- | gnu/usr.bin/cpio/copyin.c | 1310 |
1 files changed, 0 insertions, 1310 deletions
diff --git a/gnu/usr.bin/cpio/copyin.c b/gnu/usr.bin/cpio/copyin.c deleted file mode 100644 index 332eb12..0000000 --- a/gnu/usr.bin/cpio/copyin.c +++ /dev/null @@ -1,1310 +0,0 @@ -/* 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 <sys/types.h> -#include <sys/stat.h> -#ifdef __FreeBSD__ -#include <ctype.h> -#endif -#include "filetypes.h" -#include "system.h" -#include "cpiohdr.h" -#include "dstring.h" -#include "extern.h" -#include "defer.h" -#include "rmt.h" -#ifndef FNM_PATHNAME -#include <fnmatch.h> -#endif - -#ifndef HAVE_LCHOWN -#define lchown chown -#endif - -static void read_pattern_file (); -static void skip_padding (); -static void defer_copyin (); -static void create_defered_links (); -static void create_final_defers (); -static int check_for_deferments (); - -/* 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 || archive_format == arf_hpoldascii) - && !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 || archive_format == arf_hpbinary) - && (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, - "%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6lo%11lo", - &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); -#ifndef __MSDOS__ - /* HP/UX cpio creates archives that look just like ordinary archives, - but for devices it sets major = 0, minor = 1, and puts the - actual major/minor number in the filesize field. See if this - is an HP/UX cpio archive, and if so fix it. We have to do this - here because process_copy_in() assumes filesize is always 0 - for devices. */ - switch (file_hdr->c_mode & CP_IFMT) - { - case CP_IFCHR: - case CP_IFBLK: -#ifdef CP_IFSOCK - case CP_IFSOCK: -#endif -#ifdef CP_IFIFO - case CP_IFIFO: -#endif - if (file_hdr->c_filesize != 0 - && file_hdr->c_rdev_maj == 0 - && file_hdr->c_rdev_min == 1) - { - file_hdr->c_rdev_maj = major (file_hdr->c_filesize); - file_hdr->c_rdev_min = minor (file_hdr->c_filesize); - file_hdr->c_filesize = 0; - } - break; - default: - break; - } -#endif /* __MSDOS__ */ -} - -/* 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, - "%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx", - &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, device, and inode 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 the data into the short header, then later transfer - it into the argument long header. */ - short_hdr.c_dev = ((struct old_cpio_header *) file_hdr)->c_dev; - short_hdr.c_ino = ((struct old_cpio_header *) file_hdr)->c_ino; - 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); - -#ifndef __MSDOS__ - /* HP/UX cpio creates archives that look just like ordinary archives, - but for devices it sets major = 0, minor = 1, and puts the - actual major/minor number in the filesize field. See if this - is an HP/UX cpio archive, and if so fix it. We have to do this - here because process_copy_in() assumes filesize is always 0 - for devices. */ - switch (file_hdr->c_mode & CP_IFMT) - { - case CP_IFCHR: - case CP_IFBLK: -#ifdef CP_IFSOCK - case CP_IFSOCK: -#endif -#ifdef CP_IFIFO - case CP_IFIFO: -#endif - if (file_hdr->c_filesize != 0 - && file_hdr->c_rdev_maj == 0 - && file_hdr->c_rdev_min == 1) - { - file_hdr->c_rdev_maj = major (file_hdr->c_filesize); - file_hdr->c_rdev_min = minor (file_hdr->c_filesize); - file_hdr->c_filesize = 0; - } - break; - default: - break; - } -#endif /* __MSDOS__ */ -} - -/* 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. */ - char deferred; /* Deferred file creation, don't print name. */ - 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. */ -#ifdef HPUX_CDF - int cdf_flag; /* True if file is a CDF. */ - int cdf_char; /* Index of `+' char indicating a CDF. */ -#endif - - /* 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); - -#ifdef DEBUG_CPIO - if (debug_flag) - { - struct new_cpio_header *h; - h = &file_hdr; - fprintf (stderr, - "magic = 0%o, ino = %d, mode = 0%o, uid = %d, gid = %d\n", - h->c_magic, h->c_ino, h->c_mode, h->c_uid, h->c_gid); - fprintf (stderr, - "nlink = %d, mtime = %d, filesize = %d, dev_maj = 0x%x\n", - h->c_nlink, h->c_mtime, h->c_filesize, h->c_dev_maj); - fprintf (stderr, - "dev_min = 0x%x, rdev_maj = 0x%x, rdev_min = 0x%x, namesize = %d\n", - h->c_dev_min, h->c_rdev_maj, h->c_rdev_min, h->c_namesize); - fprintf (stderr, - "chksum = %d, name = \"%s\", tar_linkname = \"%s\"\n", - h->c_chksum, h->c_name, - h->c_tar_linkname ? h->c_tar_linkname : "(null)" ); - - } -#endif - /* Is this the header for the TRAILER file? */ - if (strcmp ("TRAILER!!!", file_hdr.c_name) == 0) - { - done = TRUE; - break; - } - - deferred = FALSE; - /* 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) { - skip_file = check_for_deferments(&file_hdr); - if (!skip_file) - deferred = TRUE; /* don't print this name */ - } - } - - 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 (S_ISDIR (file_stat.st_mode) - ? rmdir (file_hdr.c_name) - : 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_newascii - || archive_format == arf_crcascii) ) - { - int link_res; - if (file_hdr.c_filesize == 0) - { - /* The newc and crc formats store multiply linked copies - of the same file in the archive only once. The - actual data is attached to the last link in the - archive, and the other links all have a filesize - of 0. Since this file has multiple links and a - filesize of 0, its data is probably attatched to - another file in the archive. Save the link, and - process it later when we get the actual data. We - can't just create it with length 0 and add the - data later, in case the file is readonly. We still - lose if its parent directory is readonly (and we aren't - running as root), but there's nothing we can do about - that. */ - defer_copyin (&file_hdr); - toss_input (in_file_des, file_hdr.c_filesize); - skip_padding (in_file_des, file_hdr.c_filesize); - break; - } - /* If the file has data (filesize != 0), then presumably - any other links have already been defer_copyin'ed(), - but GNU cpio version 2.0-2.2 didn't do that, so we - still have to check for links here (and also in case - the archive was created and later appeneded to). */ - link_res = link_to_maj_min_ino (file_hdr.c_name, - file_hdr.c_dev_maj, file_hdr.c_dev_maj, - file_hdr.c_ino); - if (link_res == 0) - { - toss_input (in_file_des, file_hdr.c_filesize); - skip_padding (in_file_des, file_hdr.c_filesize); - break; - } - } - else if (file_hdr.c_nlink > 1 && archive_format != arf_tar - && archive_format != arf_ustar) - { - int link_res; - link_res = link_to_maj_min_ino (file_hdr.c_name, - file_hdr.c_dev_maj, file_hdr.c_dev_maj, - file_hdr.c_ino); - if (link_res == 0) - { - toss_input (in_file_des, file_hdr.c_filesize); - skip_padding (in_file_des, file_hdr.c_filesize); - break; - } - } - else if ((archive_format == arf_tar || archive_format == arf_ustar) - && file_hdr.c_tar_linkname && - file_hdr.c_tar_linkname[0] != '\0') - { - int link_res; - link_res = link_to_name (file_hdr.c_name, - file_hdr.c_tar_linkname); - if (link_res < 0) - { - error (0, errno, "cannot link %s to %s", - file_hdr.c_tar_linkname, file_hdr.c_name); - } - break; - } -#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); - if (file_hdr.c_nlink > 1 && (archive_format == arf_newascii - || archive_format == arf_crcascii) ) - { - /* (see comment above for how the newc and crc formats - store multiple links). Now that we have the data - for this file, create any other links to it which - we defered. */ - create_defered_links (&file_hdr); - } - } - 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; - -#ifdef HPUX_CDF - cdf_flag = 0; -#endif - if (!existing_dir) - - { -#ifdef HPUX_CDF - /* If the directory name ends in a + and is SUID, - then it is a CDF. Strip the trailing + from - the name before creating it. */ - cdf_char = strlen (file_hdr.c_name) - 1; - if ( (cdf_char > 0) && - (file_hdr.c_mode & 04000) && - (file_hdr.c_name [cdf_char] == '+') ) - { - file_hdr.c_name [cdf_char] = '\0'; - cdf_flag = 1; - } -#endif - 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); -#ifdef HPUX_CDF - if (cdf_flag) - /* Once we "hide" the directory with the chmod(), - we have to refer to it using name+ instead of name. */ - file_hdr.c_name [cdf_char] = '+'; -#endif - 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 - if (file_hdr.c_nlink > 1 && archive_format != arf_tar - && archive_format != arf_ustar) - { - int link_res; - link_res = link_to_maj_min_ino (file_hdr.c_name, - file_hdr.c_dev_maj, file_hdr.c_dev_maj, - file_hdr.c_ino); - if (link_res == 0) - break; - } - else if (archive_format == arf_ustar && - file_hdr.c_tar_linkname && - file_hdr.c_tar_linkname [0] != '\0') - { - int link_res; - link_res = link_to_name (file_hdr.c_name, - file_hdr.c_tar_linkname); - if (link_res < 0) - { - error (0, errno, "cannot link %s to %s", - file_hdr.c_tar_linkname, file_hdr.c_name); - /* Something must be wrong, because we couldn't - find the file to link to. But can we assume - that the device maj/min numbers are correct - and fall through to the mknod? It's probably - safer to just break, rather than possibly - creating a bogus device file. */ - } - break; - } - - 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); - 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; -#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 = UMASKED_SYMLINK (link_name, file_hdr.c_name, - file_hdr.c_mode); - if (res < 0 && create_dir_flag) - { - create_all_directories (file_hdr.c_name); - res = UMASKED_SYMLINK (link_name, file_hdr.c_name, - file_hdr.c_mode); - } - 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 && !deferred) - fprintf (stderr, "%s\n", file_hdr.c_name); - if (dot_flag && !deferred) - fputc ('.', stderr); - } - } - - if (dot_flag) - fputc ('\n', stderr); - - if (append_flag) - return; - - if (archive_format == arf_newascii || archive_format == arf_crcascii) - create_final_defers (); - 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; - strftime(tbuf, sizeof(tbuf), "%c", localtime(&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: -#ifdef __FreeBSD__ - if (isprint(c)) -#else - if (c > 040 && -#ifdef __MSDOS__ - c < 0377 && c != 0177 -#else - c < 0177 -#endif - ) -#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 || archive_format == arf_hpbinary) - 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); -} - - -/* The newc and crc formats store multiply linked copies of the same file - in the archive only once. The actual data is attached to the last link - in the archive, and the other links all have a filesize of 0. When a - file in the archive has multiple links and a filesize of 0, its data is - probably "attatched" to another file in the archive, so we can't create - it right away. We have to "defer" creating it until we have created - the file that has the data "attatched" to it. We keep a list of the - "defered" links on deferments. */ - -struct deferment *deferments = NULL; - -/* Add a file header to the deferments list. For now they all just - go on one list, although we could optimize this if necessary. */ - -static void -defer_copyin (file_hdr) - struct new_cpio_header *file_hdr; -{ - struct deferment *d; - d = create_deferment (file_hdr); - d->next = deferments; - deferments = d; - return; -} - -/* We just created a file that (probably) has some other links to it - which have been defered. Go through all of the links on the deferments - list and create any which are links to this file. */ - -static void -create_defered_links (file_hdr) - struct new_cpio_header *file_hdr; -{ - struct deferment *d; - struct deferment *d_prev; - int ino; - int maj; - int min; - int link_res; - ino = file_hdr->c_ino; - maj = file_hdr->c_dev_maj; - min = file_hdr->c_dev_min; - d = deferments; - d_prev = NULL; - while (d != NULL) - { - if ( (d->header.c_ino == ino) && (d->header.c_dev_maj == maj) - && (d->header.c_dev_min == min) ) - { - struct deferment *d_free; - link_res = link_to_name (d->header.c_name, file_hdr->c_name); - if (link_res < 0) - { - error (0, errno, "cannot link %s to %s", - d->header.c_name, file_hdr->c_name); - } - if (d_prev != NULL) - d_prev->next = d->next; - else - deferments = d->next; - d_free = d; - d = d->next; - free_deferment (d_free); - } - else - { - d_prev = d; - d = d->next; - } - } -} - -/* If we had a multiply linked file that really was empty then we would - have defered all of its links, since we never found any with data - "attached", and they will still be on the deferment list even when - we are done reading the whole archive. Write out all of these - empty links that are still on the deferments list. */ - -static void -create_final_defers () -{ - struct deferment *d; - struct deferment *d_prev; - struct new_cpio_header *h; - int link_res; - int out_file_des; - struct utimbuf times; /* For setting file times. */ - /* Initialize this in case it has members we don't know to set. */ - bzero (×, sizeof (struct utimbuf)); - - for (d = deferments; d != NULL; d = d->next) - { - link_res = link_to_maj_min_ino (d->header.c_name, - d->header.c_dev_maj, d->header.c_dev_maj, - d->header.c_ino); - if (link_res == 0) - { - continue; - } - out_file_des = open (d->header.c_name, - O_CREAT | O_WRONLY | O_BINARY, 0600); - if (out_file_des < 0 && create_dir_flag) - { - create_all_directories (d->header.c_name); - out_file_des = open (d->header.c_name, - O_CREAT | O_WRONLY | O_BINARY, - 0600); - } - if (out_file_des < 0) - { - error (0, errno, "%s", d->header.c_name); - continue; - } - - if (close (out_file_des) < 0) - error (0, errno, "%s", d->header.c_name); - - /* File is now copied; set attributes. */ - if (!no_chown_flag) - if ((chown (d->header.c_name, - set_owner_flag ? set_owner : d->header.c_uid, - set_group_flag ? set_group : d->header.c_gid) < 0) - && errno != EPERM) - error (0, errno, "%s", d->header.c_name); - /* chown may have turned off some permissions we wanted. */ - if (chmod (d->header.c_name, (int) d->header.c_mode) < 0) - error (0, errno, "%s", d->header.c_name); - if (retain_time_flag) - { - times.actime = times.modtime = d->header.c_mtime; - if (utime (d->header.c_name, ×) < 0) - error (0, errno, "%s", d->header.c_name); - } - } -} - -static int -check_for_deferments(struct new_cpio_header *file_hdr) -{ - struct deferment *d; - struct deferment *prev = NULL; - - for (d = deferments; d != NULL; d = d->next) { - if (file_hdr->c_ino == d->header.c_ino && - file_hdr->c_dev_maj == d->header.c_dev_maj && - file_hdr->c_dev_min == d->header.c_dev_min) { - free(file_hdr->c_name); - if (prev != NULL) - prev->next = d->next; - else - deferments = d->next; - file_hdr->c_name = strdup(d->header.c_name); - free_deferment(d); - return FALSE; - } - prev = d; - } - return TRUE; -} |