aboutsummaryrefslogtreecommitdiff
path: root/contrib/cpio/src/copyout.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cpio/src/copyout.c')
-rw-r--r--contrib/cpio/src/copyout.c1010
1 files changed, 0 insertions, 1010 deletions
diff --git a/contrib/cpio/src/copyout.c b/contrib/cpio/src/copyout.c
deleted file mode 100644
index 5e429faa9da8..000000000000
--- a/contrib/cpio/src/copyout.c
+++ /dev/null
@@ -1,1010 +0,0 @@
-/* $FreeBSD$ */
-
-/* copyout.c - create a cpio archive
- Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004,
- 2006 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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301 USA. */
-
-#include <system.h>
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "filetypes.h"
-#include "cpiohdr.h"
-#include "dstring.h"
-#include "extern.h"
-#include "defer.h"
-#include <rmt.h>
-#include <paxlib.h>
-
-static int check_rdev ();
-
-/* Read FILE_SIZE bytes of FILE_NAME from IN_FILE_DES and
- compute and return a checksum for them. */
-
-static unsigned int
-read_for_checksum (int in_file_des, int file_size, char *file_name)
-{
- unsigned int crc;
- char buf[BUFSIZ];
- int bytes_left;
- int bytes_read;
- int i;
-
- crc = 0;
-
- for (bytes_left = file_size; bytes_left > 0; bytes_left -= bytes_read)
- {
- bytes_read = read (in_file_des, buf, BUFSIZ);
- if (bytes_read < 0)
- error (1, errno, _("cannot read checksum for %s"), file_name);
- if (bytes_read == 0)
- break;
- if (bytes_left < bytes_read)
- bytes_read = bytes_left;
- for (i = 0; i < bytes_read; ++i)
- crc += buf[i] & 0xff;
- }
- if (lseek (in_file_des, 0L, SEEK_SET))
- error (1, errno, _("cannot read checksum for %s"), file_name);
-
- return crc;
-}
-
-/* Write out NULs to fill out the rest of the current block on
- OUT_FILE_DES. */
-
-static void
-tape_clear_rest_of_block (int out_file_des)
-{
- write_nuls_to_file (io_block_size - output_size, out_file_des,
- tape_buffered_write);
-}
-
-/* Write NULs on OUT_FILE_DES to move from OFFSET (the current location)
- to the end of the header. */
-
-static void
-tape_pad_output (int out_file_des, int offset)
-{
- size_t pad;
-
- if (archive_format == arf_newascii || archive_format == arf_crcascii)
- pad = (4 - (offset % 4)) % 4;
- else if (archive_format == arf_tar || archive_format == arf_ustar)
- pad = (512 - (offset % 512)) % 512;
- else if (archive_format != arf_oldascii && archive_format != arf_hpoldascii)
- pad = (2 - (offset % 2)) % 2;
- else
- pad = 0;
-
- if (pad != 0)
- write_nuls_to_file (pad, out_file_des, tape_buffered_write);
-}
-
-
-/* When creating newc and crc archives if a file has multiple (hard)
- links, we don't put any of them into the archive until we have seen
- all of them (or until we get to the end of the list of files that
- are going into the archive and know that we have seen all of the links
- to the file that we will see). We keep these "defered" files on
- this list. */
-
-struct deferment *deferouts = NULL;
-
-/* Count the number of other (hard) links to this file that have
- already been defered. */
-
-static int
-count_defered_links_to_dev_ino (struct cpio_file_stat *file_hdr)
-{
- struct deferment *d;
- int ino;
- int maj;
- int min;
- int count;
- ino = file_hdr->c_ino;
- maj = file_hdr->c_dev_maj;
- min = file_hdr->c_dev_min;
- count = 0;
- for (d = deferouts; d != NULL; d = d->next)
- {
- if ( (d->header.c_ino == ino) && (d->header.c_dev_maj == maj)
- && (d->header.c_dev_min == min) )
- ++count;
- }
- return count;
-}
-
-/* Is this file_hdr the last (hard) link to a file? I.e., have
- we already seen and defered all of the other links? */
-
-static int
-last_link (struct cpio_file_stat *file_hdr)
-{
- int other_files_sofar;
-
- other_files_sofar = count_defered_links_to_dev_ino (file_hdr);
- if (file_hdr->c_nlink == (other_files_sofar + 1) )
- {
- return 1;
- }
- return 0;
-}
-
-
-/* Add the file header for a link that is being defered to the deferouts
- list. */
-
-static void
-add_link_defer (struct cpio_file_stat *file_hdr)
-{
- struct deferment *d;
- d = create_deferment (file_hdr);
- d->next = deferouts;
- deferouts = d;
-}
-
-/* We are about to put a file into a newc or crc archive that is
- multiply linked. We have already seen and deferred all of the
- other links to the file but haven't written them into the archive.
- Write the other links into the archive, and remove them from the
- deferouts list. */
-
-static void
-writeout_other_defers (struct cpio_file_stat *file_hdr, int out_des)
-{
- struct deferment *d;
- struct deferment *d_prev;
- int ino;
- int maj;
- int min;
- ino = file_hdr->c_ino;
- maj = file_hdr->c_dev_maj;
- min = file_hdr->c_dev_min;
- d_prev = NULL;
- d = deferouts;
- 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;
- d->header.c_filesize = 0;
- write_out_header (&d->header, out_des);
- if (d_prev != NULL)
- d_prev->next = d->next;
- else
- deferouts = d->next;
- d_free = d;
- d = d->next;
- free_deferment (d_free);
- }
- else
- {
- d_prev = d;
- d = d->next;
- }
- }
- return;
-}
-
-/* Write a file into the archive. This code is the same as
- the code in process_copy_out(), but we need it here too
- for writeout_final_defers() to call. */
-
-static void
-writeout_defered_file (struct cpio_file_stat *header, int out_file_des)
-{
- int in_file_des;
- struct cpio_file_stat file_hdr;
-
- file_hdr = *header;
-
-
- in_file_des = open (header->c_name,
- O_RDONLY | O_BINARY, 0);
- if (in_file_des < 0)
- {
- open_error (header->c_name);
- return;
- }
-
- if (archive_format == arf_crcascii)
- file_hdr.c_chksum = read_for_checksum (in_file_des,
- file_hdr.c_filesize,
- header->c_name);
-
- if (write_out_header (&file_hdr, out_file_des))
- return;
- copy_files_disk_to_tape (in_file_des, out_file_des, file_hdr.c_filesize,
- header->c_name);
- warn_if_file_changed(header->c_name, file_hdr.c_filesize, file_hdr.c_mtime);
-
- if (archive_format == arf_tar || archive_format == arf_ustar)
- add_inode (file_hdr.c_ino, file_hdr.c_name, file_hdr.c_dev_maj,
- file_hdr.c_dev_min);
-
- tape_pad_output (out_file_des, file_hdr.c_filesize);
-
- if (reset_time_flag)
- set_file_times (in_file_des, file_hdr.c_name, file_hdr.c_mtime,
- file_hdr.c_mtime);
- if (close (in_file_des) < 0)
- close_error (header->c_name);
-}
-
-/* When writing newc and crc format archives we defer multiply linked
- files until we have seen all of the links to the file. If a file
- has links to it that aren't going into the archive, then we will
- never see the "last" link to the file, so at the end we just write
- all of the leftover defered files into the archive. */
-
-static void
-writeout_final_defers (int out_des)
-{
- struct deferment *d;
- int other_count;
- while (deferouts != NULL)
- {
- d = deferouts;
- other_count = count_defered_links_to_dev_ino (&d->header);
- if (other_count == 1)
- {
- writeout_defered_file (&d->header, out_des);
- }
- else
- {
- struct cpio_file_stat file_hdr;
- file_hdr = d->header;
- file_hdr.c_filesize = 0;
- write_out_header (&file_hdr, out_des);
- }
- deferouts = deferouts->next;
- }
-}
-
-/* FIXME: to_ascii could be used instead of to_oct() and to_octal() from tar,
- so it should be moved to paxutils too.
- Allowed values for logbase are: 1 (binary), 2, 3 (octal), 4 (hex) */
-int
-to_ascii (char *where, uintmax_t v, size_t digits, unsigned logbase)
-{
- static char codetab[] = "0123456789ABCDEF";
- int i = digits;
-
- do
- {
- where[--i] = codetab[(v & ((1 << logbase) - 1))];
- v >>= logbase;
- }
- while (i);
-
- return v != 0;
-}
-
-static void
-field_width_error (const char *filename, const char *fieldname)
-{
- error (0, 0, _("%s: field width not sufficient for storing %s"),
- filename, fieldname);
-}
-
-static void
-field_width_warning (const char *filename, const char *fieldname)
-{
- if (warn_option & CPIO_WARN_TRUNCATE)
- error (0, 0, _("%s: truncating %s"), filename, fieldname);
-}
-
-void
-to_ascii_or_warn (char *where, uintmax_t n, size_t digits,
- unsigned logbase,
- const char *filename, const char *fieldname)
-{
- if (to_ascii (where, n, digits, logbase))
- field_width_warning (filename, fieldname);
-}
-
-int
-to_ascii_or_error (char *where, uintmax_t n, size_t digits,
- unsigned logbase,
- const char *filename, const char *fieldname)
-{
- if (to_ascii (where, n, digits, logbase))
- {
- field_width_error (filename, fieldname);
- return 1;
- }
- return 0;
-}
-
-
-int
-write_out_new_ascii_header (const char *magic_string,
- struct cpio_file_stat *file_hdr, int out_des)
-{
- char ascii_header[110];
- char *p;
-
- p = stpcpy (ascii_header, magic_string);
- to_ascii_or_warn (p, file_hdr->c_ino, 8, LG_16,
- file_hdr->c_name, _("inode number"));
- p += 8;
- to_ascii_or_warn (p, file_hdr->c_mode, 8, LG_16, file_hdr->c_name,
- _("file mode"));
- p += 8;
- to_ascii_or_warn (p, file_hdr->c_uid, 8, LG_16, file_hdr->c_name,
- _("uid"));
- p += 8;
- to_ascii_or_warn (p, file_hdr->c_gid, 8, LG_16, file_hdr->c_name,
- _("gid"));
- p += 8;
- to_ascii_or_warn (p, file_hdr->c_nlink, 8, LG_16, file_hdr->c_name,
- _("number of links"));
- p += 8;
- to_ascii_or_warn (p, file_hdr->c_mtime, 8, LG_16, file_hdr->c_name,
- _("modification time"));
- p += 8;
- if (to_ascii_or_error (p, file_hdr->c_filesize, 8, LG_16, file_hdr->c_name,
- _("file size")))
- return 1;
- p += 8;
- if (to_ascii_or_error (p, file_hdr->c_dev_maj, 8, LG_16, file_hdr->c_name,
- _("device major number")))
- return 1;
- p += 8;
- if (to_ascii_or_error (p, file_hdr->c_dev_min, 8, LG_16, file_hdr->c_name,
- _("device minor number")))
- return 1;
- p += 8;
- if (to_ascii_or_error (p, file_hdr->c_rdev_maj, 8, LG_16, file_hdr->c_name,
- _("rdev major")))
- return 1;
- p += 8;
- if (to_ascii_or_error (p, file_hdr->c_rdev_min, 8, LG_16, file_hdr->c_name,
- _("rdev minor")))
- return 1;
- p += 8;
- if (to_ascii_or_error (p, file_hdr->c_namesize, 8, LG_16, file_hdr->c_name,
- _("name size")))
- return 1;
- p += 8;
- to_ascii (p, file_hdr->c_chksum & 0xffffffff, 8, LG_16);
-
- tape_buffered_write (ascii_header, out_des, sizeof ascii_header);
-
- /* Write file name to output. */
- tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
- tape_pad_output (out_des, file_hdr->c_namesize + sizeof ascii_header);
- return 0;
-}
-
-int
-write_out_old_ascii_header (dev_t dev, dev_t rdev,
- struct cpio_file_stat *file_hdr, int out_des)
-{
- char ascii_header[76];
- char *p = ascii_header;
-
- to_ascii (p, file_hdr->c_magic, 6, LG_8);
- p += 6;
- to_ascii_or_warn (p, dev, 6, LG_8, file_hdr->c_name, _("device number"));
- p += 6;
- to_ascii_or_warn (p, file_hdr->c_ino, 6, LG_8, file_hdr->c_name,
- _("inode number"));
- p += 6;
- to_ascii_or_warn (p, file_hdr->c_mode, 6, LG_8, file_hdr->c_name,
- _("file mode"));
- p += 6;
- to_ascii_or_warn (p, file_hdr->c_uid, 6, LG_8, file_hdr->c_name, _("uid"));
- p += 6;
- to_ascii_or_warn (p, file_hdr->c_gid, 6, LG_8, file_hdr->c_name, _("gid"));
- p += 6;
- to_ascii_or_warn (p, file_hdr->c_nlink, 6, LG_8, file_hdr->c_name,
- _("number of links"));
- p += 6;
- to_ascii_or_warn (p, rdev, 6, LG_8, file_hdr->c_name, _("rdev"));
- p += 6;
- to_ascii_or_warn (p, file_hdr->c_mtime, 11, LG_8, file_hdr->c_name,
- _("modification time"));
- p += 11;
- if (to_ascii_or_error (p, file_hdr->c_namesize, 6, LG_8, file_hdr->c_name,
- _("name size")))
- return 1;
- p += 6;
- if (to_ascii_or_error (p, file_hdr->c_filesize, 11, LG_8, file_hdr->c_name,
- _("file size")))
- return 1;
-
- tape_buffered_write (ascii_header, out_des, sizeof ascii_header);
-
- /* Write file name to output. */
- tape_buffered_write (file_hdr->c_name, out_des, file_hdr->c_namesize);
- return 0;
-}
-
-void
-hp_compute_dev (struct cpio_file_stat *file_hdr, dev_t *pdev, dev_t *prdev)
-{
- /* 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. */
- 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
- file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
- file_hdr->c_rdev_min);
- *pdev = *prdev = makedev (0, 1);
- break;
-
- default:
- *pdev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
- *prdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
- break;
- }
-}
-
-int
-write_out_binary_header (dev_t rdev,
- struct cpio_file_stat *file_hdr, int out_des)
-{
- struct old_cpio_header short_hdr;
-
- short_hdr.c_magic = 070707;
- short_hdr.c_dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
-
- if ((warn_option & CPIO_WARN_TRUNCATE) && (file_hdr->c_ino >> 16) != 0)
- error (0, 0, _("%s: truncating inode number"), file_hdr->c_name);
-
- short_hdr.c_ino = file_hdr->c_ino & 0xFFFF;
- if (short_hdr.c_ino != file_hdr->c_ino)
- field_width_warning (file_hdr->c_name, _("inode number"));
-
- short_hdr.c_mode = file_hdr->c_mode & 0xFFFF;
- if (short_hdr.c_mode != file_hdr->c_mode)
- field_width_warning (file_hdr->c_name, _("file mode"));
-
- short_hdr.c_uid = file_hdr->c_uid & 0xFFFF;
- if (short_hdr.c_uid != file_hdr->c_uid)
- field_width_warning (file_hdr->c_name, _("uid"));
-
- short_hdr.c_gid = file_hdr->c_gid & 0xFFFF;
- if (short_hdr.c_gid != file_hdr->c_gid)
- field_width_warning (file_hdr->c_name, _("gid"));
-
- short_hdr.c_nlink = file_hdr->c_nlink & 0xFFFF;
- if (short_hdr.c_nlink != file_hdr->c_nlink)
- field_width_warning (file_hdr->c_name, _("number of links"));
-
- short_hdr.c_rdev = rdev;
- short_hdr.c_mtimes[0] = file_hdr->c_mtime >> 16;
- short_hdr.c_mtimes[1] = file_hdr->c_mtime & 0xFFFF;
-
- short_hdr.c_namesize = file_hdr->c_namesize & 0xFFFF;
- if (short_hdr.c_namesize != file_hdr->c_namesize)
- {
- field_width_error (file_hdr->c_name, _("name size"));
- return 1;
- }
-
- short_hdr.c_filesizes[0] = file_hdr->c_filesize >> 16;
- short_hdr.c_filesizes[1] = file_hdr->c_filesize & 0xFFFF;
-
- if (((off_t)short_hdr.c_filesizes[0] << 16) + short_hdr.c_filesizes[1]
- != file_hdr->c_filesize)
- {
- field_width_error (file_hdr->c_name, _("file size"));
- return 1;
- }
-
- /* Output the file header. */
- tape_buffered_write ((char *) &short_hdr, out_des, 26);
-
- /* Write file name to output. */
- tape_buffered_write (file_hdr->c_name, out_des, file_hdr->c_namesize);
-
- tape_pad_output (out_des, file_hdr->c_namesize + 26);
- return 0;
-}
-
-
-/* Write out header FILE_HDR, including the file name, to file
- descriptor OUT_DES. */
-
-int
-write_out_header (struct cpio_file_stat *file_hdr, int out_des)
-{
- dev_t dev;
- dev_t rdev;
-
- switch (archive_format)
- {
- case arf_newascii:
- return write_out_new_ascii_header ("070701", file_hdr, out_des);
-
- case arf_crcascii:
- return write_out_new_ascii_header ("070702", file_hdr, out_des);
-
- case arf_oldascii:
- return write_out_old_ascii_header (makedev (file_hdr->c_dev_maj,
- file_hdr->c_dev_min),
- makedev (file_hdr->c_rdev_maj,
- file_hdr->c_rdev_min),
- file_hdr, out_des);
-
- case arf_hpoldascii:
- hp_compute_dev (file_hdr, &dev, &rdev);
- return write_out_old_ascii_header (dev, rdev, file_hdr, out_des);
-
- case arf_tar:
- case arf_ustar:
- if (is_tar_filename_too_long (file_hdr->c_name))
- {
- error (0, 0, _("%s: file name too long"), file_hdr->c_name);
- return 1;
- }
- write_out_tar_header (file_hdr, out_des); /* FIXME: No error checking */
- return 0;
-
- case arf_binary:
- return write_out_binary_header (makedev (file_hdr->c_rdev_maj,
- file_hdr->c_rdev_min),
- file_hdr, out_des);
-
- case arf_hpbinary:
- hp_compute_dev (file_hdr, &dev, &rdev);
- /* FIXME: dev ignored. Should it be? */
- return write_out_binary_header (rdev, file_hdr, out_des);
-
- default:
- abort ();
- }
-}
-
-static void
-assign_string (char **pvar, char *value)
-{
- char *p = xrealloc (*pvar, strlen (value) + 1);
- strcpy (p, value);
- *pvar = p;
-}
-
-/* Read a list of file names from the standard input
- and write a cpio collection on the standard output.
- The format of the header depends on the compatibility (-c) flag. */
-
-void
-process_copy_out ()
-{
- int res; /* Result of functions. */
- dynamic_string input_name; /* Name of file read from stdin. */
- struct stat file_stat; /* Stat record for file. */
- struct cpio_file_stat file_hdr; /* Output header information. */
- int in_file_des; /* Source file descriptor. */
- int out_file_des; /* Output file descriptor. */
- char *orig_file_name = NULL;
-
- /* Initialize the copy out. */
- ds_init (&input_name, 128);
- file_hdr.c_magic = 070707;
-
- /* Check whether the output file might be a tape. */
- out_file_des = archive_des;
- if (_isrmt (out_file_des))
- {
- output_is_special = 1;
- output_is_seekable = 0;
- }
- else
- {
- if (fstat (out_file_des, &file_stat))
- error (1, errno, _("standard output is closed"));
- output_is_special =
-#ifdef S_ISBLK
- S_ISBLK (file_stat.st_mode) ||
-#endif
- S_ISCHR (file_stat.st_mode);
- output_is_seekable = S_ISREG (file_stat.st_mode);
- }
-
- if (append_flag)
- {
- process_copy_in ();
- prepare_append (out_file_des);
- }
-
- /* Copy files with names read from stdin. */
- while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
- {
- /* Check for blank line. */
- if (input_name.ds_string[0] == 0)
- {
- error (0, 0, _("blank line ignored"));
- continue;
- }
-
- /* Process next file. */
- if ((*xstat) (input_name.ds_string, &file_stat) < 0)
- stat_error (input_name.ds_string);
- else
- {
- /* Set values in output header. */
- stat_to_cpio (&file_hdr, &file_stat);
-
- if (archive_format == arf_tar || archive_format == arf_ustar)
- {
- if (file_hdr.c_mode & CP_IFDIR)
- {
- int len = strlen (input_name.ds_string);
- /* Make sure the name ends with a slash */
- if (input_name.ds_string[len-1] != '/')
- {
- ds_resize (&input_name, len + 2);
- input_name.ds_string[len] = '/';
- input_name.ds_string[len+1] = 0;
- }
- }
- }
-
- switch (check_rdev (&file_hdr))
- {
- case 1:
- error (0, 0, "%s not dumped: major number would be truncated",
- file_hdr.c_name);
- continue;
- case 2:
- error (0, 0, "%s not dumped: minor number would be truncated",
- file_hdr.c_name);
- continue;
- case 4:
- error (0, 0, "%s not dumped: device number would be truncated",
- file_hdr.c_name);
- continue;
- }
-
- assign_string (&orig_file_name, input_name.ds_string);
- cpio_safer_name_suffix (input_name.ds_string, false,
- abs_paths_flag, true);
-#ifndef HPUX_CDF
- file_hdr.c_name = input_name.ds_string;
- file_hdr.c_namesize = strlen (input_name.ds_string) + 1;
-#else
- if ( (archive_format != arf_tar) && (archive_format != arf_ustar) )
- {
- /* We mark CDF's in cpio files by adding a 2nd `/' after the
- "hidden" directory name. We need to do this so we can
- properly recreate the directory as hidden (in case the
- files of a directory go into the archive before the
- directory itself (e.g from "find ... -depth ... | cpio")). */
- file_hdr.c_name = add_cdf_double_slashes (input_name.ds_string);
- file_hdr.c_namesize = strlen (file_hdr.c_name) + 1;
- }
- else
- {
- /* We don't mark CDF's in tar files. We assume the "hidden"
- directory will always go into the archive before any of
- its files. */
- file_hdr.c_name = input_name.ds_string;
- file_hdr.c_namesize = strlen (input_name.ds_string) + 1;
- }
-#endif
-
- /* Copy the named file to the output. */
- switch (file_hdr.c_mode & CP_IFMT)
- {
- case CP_IFREG:
- if (archive_format == arf_tar || archive_format == arf_ustar)
- {
- char *otherfile;
- if ((otherfile = find_inode_file (file_hdr.c_ino,
- file_hdr.c_dev_maj,
- file_hdr.c_dev_min)))
- {
- file_hdr.c_tar_linkname = otherfile;
- if (write_out_header (&file_hdr, out_file_des))
- continue;
- break;
- }
- }
- if ( (archive_format == arf_newascii || archive_format == arf_crcascii)
- && (file_hdr.c_nlink > 1) )
- {
- if (last_link (&file_hdr) )
- {
- writeout_other_defers (&file_hdr, out_file_des);
- }
- else
- {
- add_link_defer (&file_hdr);
- break;
- }
- }
- in_file_des = open (orig_file_name,
- O_RDONLY | O_BINARY, 0);
- if (in_file_des < 0)
- {
- open_error (orig_file_name);
- continue;
- }
-
- if (archive_format == arf_crcascii)
- file_hdr.c_chksum = read_for_checksum (in_file_des,
- file_hdr.c_filesize,
- orig_file_name);
-
- if (write_out_header (&file_hdr, out_file_des))
- continue;
- copy_files_disk_to_tape (in_file_des,
- out_file_des, file_hdr.c_filesize,
- orig_file_name);
- warn_if_file_changed(orig_file_name, file_hdr.c_filesize,
- file_hdr.c_mtime);
-
- if (archive_format == arf_tar || archive_format == arf_ustar)
- add_inode (file_hdr.c_ino, orig_file_name, file_hdr.c_dev_maj,
- file_hdr.c_dev_min);
-
- tape_pad_output (out_file_des, file_hdr.c_filesize);
-
- if (reset_time_flag)
- set_file_times (in_file_des,
- orig_file_name,
- file_stat.st_atime, file_stat.st_mtime);
- if (close (in_file_des) < 0)
- close_error (orig_file_name);
- break;
-
- case CP_IFDIR:
- file_hdr.c_filesize = 0;
- if (write_out_header (&file_hdr, out_file_des))
- continue;
- break;
-
- case CP_IFCHR:
- case CP_IFBLK:
-#ifdef CP_IFSOCK
- case CP_IFSOCK:
-#endif
-#ifdef CP_IFIFO
- case CP_IFIFO:
-#endif
- if (archive_format == arf_tar)
- {
- error (0, 0, _("%s not dumped: not a regular file"),
- orig_file_name);
- continue;
- }
- else if (archive_format == arf_ustar)
- {
- char *otherfile;
- if ((otherfile = find_inode_file (file_hdr.c_ino,
- file_hdr.c_dev_maj,
- file_hdr.c_dev_min)))
- {
- /* This file is linked to another file already in the
- archive, so write it out as a hard link. */
- file_hdr.c_mode = (file_stat.st_mode & 07777);
- file_hdr.c_mode |= CP_IFREG;
- file_hdr.c_tar_linkname = otherfile;
- if (write_out_header (&file_hdr, out_file_des))
- continue;
- break;
- }
- add_inode (file_hdr.c_ino, orig_file_name,
- file_hdr.c_dev_maj, file_hdr.c_dev_min);
- }
- file_hdr.c_filesize = 0;
- if (write_out_header (&file_hdr, out_file_des))
- continue;
- break;
-
-#ifdef CP_IFLNK
- case CP_IFLNK:
- {
- char *link_name = (char *) xmalloc (file_stat.st_size + 1);
- int link_size;
-
- link_size = readlink (orig_file_name, link_name,
- file_stat.st_size);
- if (link_size < 0)
- {
- readlink_warn (orig_file_name);
- free (link_name);
- continue;
- }
- link_name[link_size] = 0;
- cpio_safer_name_suffix (link_name, false,
- abs_paths_flag, true);
- link_size = strlen (link_name);
- file_hdr.c_filesize = link_size;
- if (archive_format == arf_tar || archive_format == arf_ustar)
- {
- if (link_size + 1 > 100)
- {
- error (0, 0, _("%s: symbolic link too long"),
- file_hdr.c_name);
- }
- else
- {
- link_name[link_size] = '\0';
- file_hdr.c_tar_linkname = link_name;
- if (write_out_header (&file_hdr, out_file_des))
- continue;
- }
- }
- else
- {
- if (write_out_header (&file_hdr, out_file_des))
- continue;
- tape_buffered_write (link_name, out_file_des, link_size);
- tape_pad_output (out_file_des, link_size);
- }
- free (link_name);
- }
- break;
-#endif
-
- default:
- error (0, 0, _("%s: unknown file type"), orig_file_name);
- }
-
- if (verbose_flag)
- fprintf (stderr, "%s\n", orig_file_name);
- if (dot_flag)
- fputc ('.', stderr);
- }
- }
-
- free (orig_file_name);
-
- writeout_final_defers(out_file_des);
- /* The collection is complete; append the trailer. */
- file_hdr.c_ino = 0;
- file_hdr.c_mode = 0;
- file_hdr.c_uid = 0;
- file_hdr.c_gid = 0;
- file_hdr.c_nlink = 1; /* Must be 1 for crc format. */
- file_hdr.c_dev_maj = 0;
- file_hdr.c_dev_min = 0;
- file_hdr.c_rdev_maj = 0;
- file_hdr.c_rdev_min = 0;
- file_hdr.c_mtime = 0;
- file_hdr.c_chksum = 0;
-
- file_hdr.c_filesize = 0;
- file_hdr.c_namesize = 11;
- file_hdr.c_name = CPIO_TRAILER_NAME;
- if (archive_format != arf_tar && archive_format != arf_ustar)
- write_out_header (&file_hdr, out_file_des);
- else
- write_nuls_to_file (1024, out_file_des, tape_buffered_write);
-
- /* Fill up the output block. */
- tape_clear_rest_of_block (out_file_des);
- tape_empty_output_buffer (out_file_des);
- if (dot_flag)
- fputc ('\n', stderr);
- if (!quiet_flag)
- {
- res = (output_bytes + io_block_size - 1) / io_block_size;
- fprintf (stderr, ngettext ("%d block\n", "%d blocks\n", res), res);
- }
-}
-
-static int
-check_rdev (file_hdr)
- struct cpio_file_stat *file_hdr;
-{
- if (archive_format == arf_newascii || archive_format == arf_crcascii)
- {
- if ((file_hdr->c_rdev_maj & 0xFFFFFFFF) != file_hdr->c_rdev_maj)
- return 1;
- if ((file_hdr->c_rdev_min & 0xFFFFFFFF) != file_hdr->c_rdev_min)
- return 2;
- }
- else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
- {
-#ifndef __MSDOS__
- dev_t rdev;
-
- rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
- if (archive_format == arf_oldascii)
- {
- if ((rdev & 0xFFFF) != rdev)
- return 4;
- }
- else
- {
- 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
- /* We could handle one more bit if longs are >= 33 bits. */
- if ((rdev & 037777777777) != rdev)
- return 4;
- break;
- default:
- if ((rdev & 0xFFFF) != rdev)
- return 4;
- break;
- }
- }
-#endif
- }
- else if (archive_format == arf_tar || archive_format == arf_ustar)
- {
- /* The major and minor formats are limited to 7 octal digits in ustar
- format, and to_oct () adds a gratuitous trailing blank to further
- limit the format to 6 octal digits. */
- if ((file_hdr->c_rdev_maj & 0777777) != file_hdr->c_rdev_maj)
- return 1;
- if ((file_hdr->c_rdev_min & 0777777) != file_hdr->c_rdev_min)
- return 2;
- }
- else
- {
-#ifndef __MSDOS__
- dev_t rdev;
-
- rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
- if (archive_format != arf_hpbinary)
- {
- if ((rdev & 0xFFFF) != rdev)
- return 4;
- }
- else
- {
- 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 ((rdev & 0xFFFFFFFF) != rdev)
- return 4;
- file_hdr->c_filesize = rdev;
- rdev = makedev (0, 1);
- break;
- default:
- if ((rdev & 0xFFFF) != rdev)
- return 4;
- break;
- }
- }
-#endif
- }
- return 0;
-}