summaryrefslogtreecommitdiffstats
path: root/contrib/cpio/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cpio/src/util.c')
-rw-r--r--contrib/cpio/src/util.c1344
1 files changed, 0 insertions, 1344 deletions
diff --git a/contrib/cpio/src/util.c b/contrib/cpio/src/util.c
deleted file mode 100644
index 8773f75..0000000
--- a/contrib/cpio/src/util.c
+++ /dev/null
@@ -1,1344 +0,0 @@
-/* $FreeBSD$ */
-
-/* util.c - Several utility routines for cpio.
- Copyright (C) 1990, 1991, 1992, 2001, 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 "cpiohdr.h"
-#include "dstring.h"
-#include "extern.h"
-#include <paxlib.h>
-#include "filetypes.h"
-#include <safe-read.h>
-#include <full-write.h>
-#include <rmt.h>
-#include <hash.h>
-#include <utimens.h>
-
-#include <sys/ioctl.h>
-
-#ifdef HAVE_SYS_MTIO_H
-# ifdef HAVE_SYS_IO_TRIOCTL_H
-# include <sys/io/trioctl.h>
-# endif
-# include <sys/mtio.h>
-#endif
-
-#if !HAVE_DECL_ERRNO
-extern int errno;
-#endif
-
-/* Write `output_size' bytes of `output_buffer' to file
- descriptor OUT_DES and reset `output_size' and `out_buff'. */
-
-void
-tape_empty_output_buffer (int out_des)
-{
- int bytes_written;
-
-#ifdef BROKEN_LONG_TAPE_DRIVER
- static long output_bytes_before_lseek = 0;
-
- /* Some tape drivers seem to have a signed internal seek pointer and
- they lose if it overflows and becomes negative (e.g. when writing
- tapes > 2Gb). Doing an lseek (des, 0, SEEK_SET) seems to reset the
- seek pointer and prevent it from overflowing. */
- if (output_is_special
- && ( (output_bytes_before_lseek += output_size) >= 1073741824L) )
- {
- lseek(out_des, 0L, SEEK_SET);
- output_bytes_before_lseek = 0;
- }
-#endif
-
- bytes_written = rmtwrite (out_des, output_buffer, output_size);
- if (bytes_written != output_size)
- {
- int rest_bytes_written;
- int rest_output_size;
-
- if (output_is_special
- && (bytes_written >= 0
- || (bytes_written < 0
- && (errno == ENOSPC || errno == EIO || errno == ENXIO))))
- {
- get_next_reel (out_des);
- if (bytes_written > 0)
- rest_output_size = output_size - bytes_written;
- else
- rest_output_size = output_size;
- rest_bytes_written = rmtwrite (out_des, output_buffer,
- rest_output_size);
- if (rest_bytes_written != rest_output_size)
- error (1, errno, _("write error"));
- }
- else
- error (1, errno, _("write error"));
- }
- output_bytes += output_size;
- out_buff = output_buffer;
- output_size = 0;
-}
-
-static int sparse_write (int fildes, char *buf, unsigned int nbyte);
-
-/* Write `output_size' bytes of `output_buffer' to file
- descriptor OUT_DES and reset `output_size' and `out_buff'.
- If `swapping_halfwords' or `swapping_bytes' is set,
- do the appropriate swapping first. Our callers have
- to make sure to only set these flags if `output_size'
- is appropriate (a multiple of 4 for `swapping_halfwords',
- 2 for `swapping_bytes'). The fact that DISK_IO_BLOCK_SIZE
- must always be a multiple of 4 helps us (and our callers)
- insure this. */
-
-void
-disk_empty_output_buffer (int out_des)
-{
- int bytes_written;
-
- if (swapping_halfwords || swapping_bytes)
- {
- if (swapping_halfwords)
- {
- int complete_words;
- complete_words = output_size / 4;
- swahw_array (output_buffer, complete_words);
- if (swapping_bytes)
- swab_array (output_buffer, 2 * complete_words);
- }
- else
- {
- int complete_halfwords;
- complete_halfwords = output_size /2;
- swab_array (output_buffer, complete_halfwords);
- }
- }
-
- if (sparse_flag)
- bytes_written = sparse_write (out_des, output_buffer, output_size);
- else
- bytes_written = write (out_des, output_buffer, output_size);
-
- if (bytes_written != output_size)
- {
- error (1, errno, _("write error"));
- }
- output_bytes += output_size;
- out_buff = output_buffer;
- output_size = 0;
-}
-
-/* Exchange the halfwords of each element of the array of COUNT longs
- starting at PTR. PTR does not have to be aligned at a word
- boundary. */
-
-void
-swahw_array (char *ptr, int count)
-{
- char tmp;
-
- for (; count > 0; --count)
- {
- tmp = *ptr;
- *ptr = *(ptr + 2);
- *(ptr + 2) = tmp;
- ++ptr;
- tmp = *ptr;
- *ptr = *(ptr + 2);
- *(ptr + 2) = tmp;
- ptr += 3;
- }
-}
-
-/* Read at most NUM_BYTES or `io_block_size' bytes, whichever is smaller,
- into the start of `input_buffer' from file descriptor IN_DES.
- Set `input_size' to the number of bytes read and reset `in_buff'.
- Exit with an error if end of file is reached. */
-
-#ifdef BROKEN_LONG_TAPE_DRIVER
-static long input_bytes_before_lseek = 0;
-#endif
-
-static void
-tape_fill_input_buffer (int in_des, int num_bytes)
-{
-#ifdef BROKEN_LONG_TAPE_DRIVER
- /* Some tape drivers seem to have a signed internal seek pointer and
- they lose if it overflows and becomes negative (e.g. when writing
- tapes > 4Gb). Doing an lseek (des, 0, SEEK_SET) seems to reset the
- seek pointer and prevent it from overflowing. */
- if (input_is_special
- && ( (input_bytes_before_lseek += num_bytes) >= 1073741824L) )
- {
- lseek(in_des, 0L, SEEK_SET);
- input_bytes_before_lseek = 0;
- }
-#endif
- in_buff = input_buffer;
- num_bytes = (num_bytes < io_block_size) ? num_bytes : io_block_size;
- input_size = rmtread (in_des, input_buffer, num_bytes);
- if (input_size == 0 && input_is_special)
- {
- get_next_reel (in_des);
- input_size = rmtread (in_des, input_buffer, num_bytes);
- }
- if (input_size < 0)
- error (1, errno, _("read error"));
- if (input_size == 0)
- {
- error (0, 0, _("premature end of file"));
- exit (1);
- }
- input_bytes += input_size;
-}
-
-/* Read at most NUM_BYTES or `DISK_IO_BLOCK_SIZE' bytes, whichever is smaller,
- into the start of `input_buffer' from file descriptor IN_DES.
- Set `input_size' to the number of bytes read and reset `in_buff'.
- Exit with an error if end of file is reached. */
-
-static int
-disk_fill_input_buffer (int in_des, off_t num_bytes)
-{
- in_buff = input_buffer;
- num_bytes = (num_bytes < DISK_IO_BLOCK_SIZE) ? num_bytes : DISK_IO_BLOCK_SIZE;
- input_size = read (in_des, input_buffer, num_bytes);
- if (input_size < 0)
- {
- input_size = 0;
- return (-1);
- }
- else if (input_size == 0)
- return (1);
- input_bytes += input_size;
- return (0);
-}
-
-/* Copy NUM_BYTES of buffer IN_BUF to `out_buff', which may be partly full.
- When `out_buff' fills up, flush it to file descriptor OUT_DES. */
-
-void
-tape_buffered_write (char *in_buf, int out_des, off_t num_bytes)
-{
- off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
- off_t space_left; /* Room left in output buffer. */
-
- while (bytes_left > 0)
- {
- space_left = io_block_size - output_size;
- if (space_left == 0)
- tape_empty_output_buffer (out_des);
- else
- {
- if (bytes_left < space_left)
- space_left = bytes_left;
- memcpy (out_buff, in_buf, (unsigned) space_left);
- out_buff += space_left;
- output_size += space_left;
- in_buf += space_left;
- bytes_left -= space_left;
- }
- }
-}
-
-/* Copy NUM_BYTES of buffer IN_BUF to `out_buff', which may be partly full.
- When `out_buff' fills up, flush it to file descriptor OUT_DES. */
-
-void
-disk_buffered_write (char *in_buf, int out_des, off_t num_bytes)
-{
- off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
- off_t space_left; /* Room left in output buffer. */
-
- while (bytes_left > 0)
- {
- space_left = DISK_IO_BLOCK_SIZE - output_size;
- if (space_left == 0)
- disk_empty_output_buffer (out_des);
- else
- {
- if (bytes_left < space_left)
- space_left = bytes_left;
- memcpy (out_buff, in_buf, (unsigned) space_left);
- out_buff += space_left;
- output_size += space_left;
- in_buf += space_left;
- bytes_left -= space_left;
- }
- }
-}
-
-/* Copy NUM_BYTES of buffer `in_buff' into IN_BUF.
- `in_buff' may be partly full.
- When `in_buff' is exhausted, refill it from file descriptor IN_DES. */
-
-void
-tape_buffered_read (char *in_buf, int in_des, off_t num_bytes)
-{
- off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
- off_t space_left; /* Bytes to copy from input buffer. */
-
- while (bytes_left > 0)
- {
- if (input_size == 0)
- tape_fill_input_buffer (in_des, io_block_size);
- if (bytes_left < input_size)
- space_left = bytes_left;
- else
- space_left = input_size;
- memcpy (in_buf, in_buff, (unsigned) space_left);
- in_buff += space_left;
- in_buf += space_left;
- input_size -= space_left;
- bytes_left -= space_left;
- }
-}
-
-/* Copy the the next NUM_BYTES bytes of `input_buffer' into PEEK_BUF.
- If NUM_BYTES bytes are not available, read the next `io_block_size' bytes
- into the end of `input_buffer' and update `input_size'.
-
- Return the number of bytes copied into PEEK_BUF.
- If the number of bytes returned is less than NUM_BYTES,
- then EOF has been reached. */
-
-int
-tape_buffered_peek (char *peek_buf, int in_des, int num_bytes)
-{
- long tmp_input_size;
- long got_bytes;
- char *append_buf;
-
-#ifdef BROKEN_LONG_TAPE_DRIVER
- /* Some tape drivers seem to have a signed internal seek pointer and
- they lose if it overflows and becomes negative (e.g. when writing
- tapes > 4Gb). Doing an lseek (des, 0, SEEK_SET) seems to reset the
- seek pointer and prevent it from overflowing. */
- if (input_is_special
- && ( (input_bytes_before_lseek += num_bytes) >= 1073741824L) )
- {
- lseek(in_des, 0L, SEEK_SET);
- input_bytes_before_lseek = 0;
- }
-#endif
-
- while (input_size < num_bytes)
- {
- append_buf = in_buff + input_size;
- if ( (append_buf - input_buffer) >= input_buffer_size)
- {
- /* We can keep up to 2 "blocks" (either the physical block size
- or 512 bytes(the size of a tar record), which ever is
- larger) in the input buffer when we are peeking. We
- assume that our caller will never be interested in peeking
- ahead at more than 512 bytes, so we know that by the time
- we need a 3rd "block" in the buffer we can throw away the
- first block to make room. */
- int half;
- half = input_buffer_size / 2;
- memmove (input_buffer, input_buffer + half, half);
- in_buff = in_buff - half;
- append_buf = append_buf - half;
- }
- tmp_input_size = rmtread (in_des, append_buf, io_block_size);
- if (tmp_input_size == 0)
- {
- if (input_is_special)
- {
- get_next_reel (in_des);
- tmp_input_size = rmtread (in_des, append_buf, io_block_size);
- }
- else
- break;
- }
- if (tmp_input_size < 0)
- error (1, errno, _("read error"));
- input_bytes += tmp_input_size;
- input_size += tmp_input_size;
- }
- if (num_bytes <= input_size)
- got_bytes = num_bytes;
- else
- got_bytes = input_size;
- memcpy (peek_buf, in_buff, (unsigned) got_bytes);
- return got_bytes;
-}
-
-/* Skip the next NUM_BYTES bytes of file descriptor IN_DES. */
-
-void
-tape_toss_input (int in_des, off_t num_bytes)
-{
- off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
- off_t space_left; /* Bytes to copy from input buffer. */
-
- while (bytes_left > 0)
- {
- if (input_size == 0)
- tape_fill_input_buffer (in_des, io_block_size);
- if (bytes_left < input_size)
- space_left = bytes_left;
- else
- space_left = input_size;
-
- if (crc_i_flag && only_verify_crc_flag)
- {
- int k;
- for (k = 0; k < space_left; ++k)
- crc += in_buff[k] & 0xff;
- }
-
- in_buff += space_left;
- input_size -= space_left;
- bytes_left -= space_left;
- }
-}
-
-void
-write_nuls_to_file (off_t num_bytes, int out_des,
- void (*writer) (char *in_buf, int out_des, off_t num_bytes))
-{
- off_t blocks;
- off_t extra_bytes;
- off_t i;
- static char zeros_512[512];
-
- blocks = num_bytes / sizeof zeros_512;
- extra_bytes = num_bytes % sizeof zeros_512;
- for (i = 0; i < blocks; ++i)
- writer (zeros_512, out_des, sizeof zeros_512);
- if (extra_bytes)
- writer (zeros_512, out_des, extra_bytes);
-}
-
-/* Copy a file using the input and output buffers, which may start out
- partly full. After the copy, the files are not closed nor the last
- block flushed to output, and the input buffer may still be partly
- full. If `crc_i_flag' is set, add each byte to `crc'.
- IN_DES is the file descriptor for input;
- OUT_DES is the file descriptor for output;
- NUM_BYTES is the number of bytes to copy. */
-
-void
-copy_files_tape_to_disk (int in_des, int out_des, off_t num_bytes)
-{
- long size;
- long k;
-
- while (num_bytes > 0)
- {
- if (input_size == 0)
- tape_fill_input_buffer (in_des, io_block_size);
- size = (input_size < num_bytes) ? input_size : num_bytes;
- if (crc_i_flag)
- {
- for (k = 0; k < size; ++k)
- crc += in_buff[k] & 0xff;
- }
- disk_buffered_write (in_buff, out_des, size);
- num_bytes -= size;
- input_size -= size;
- in_buff += size;
- }
-}
-/* Copy a file using the input and output buffers, which may start out
- partly full. After the copy, the files are not closed nor the last
- block flushed to output, and the input buffer may still be partly
- full. If `crc_i_flag' is set, add each byte to `crc'.
- IN_DES is the file descriptor for input;
- OUT_DES is the file descriptor for output;
- NUM_BYTES is the number of bytes to copy. */
-
-void
-copy_files_disk_to_tape (int in_des, int out_des, off_t num_bytes,
- char *filename)
-{
- long size;
- long k;
- int rc;
- off_t original_num_bytes;
-
- original_num_bytes = num_bytes;
-
- while (num_bytes > 0)
- {
- if (input_size == 0)
- if (rc = disk_fill_input_buffer (in_des,
- num_bytes < DISK_IO_BLOCK_SIZE ?
- num_bytes : DISK_IO_BLOCK_SIZE))
- {
- if (rc > 0)
- {
- char buf[UINTMAX_STRSIZE_BOUND];
- error (0, 0,
- ngettext ("File %s shrunk by %s byte, padding with zeros",
- "File %s shrunk by %s bytes, padding with zeros",
- num_bytes),
- filename, STRINGIFY_BIGINT (num_bytes, buf));
- }
- else
- error (0, 0, _("Read error at byte %lld in file %s, padding with zeros"),
- original_num_bytes - num_bytes, filename);
- write_nuls_to_file (num_bytes, out_des, tape_buffered_write);
- break;
- }
- size = (input_size < num_bytes) ? input_size : num_bytes;
- if (crc_i_flag)
- {
- for (k = 0; k < size; ++k)
- crc += in_buff[k] & 0xff;
- }
- tape_buffered_write (in_buff, out_des, size);
- num_bytes -= size;
- input_size -= size;
- in_buff += size;
- }
-}
-/* Copy a file using the input and output buffers, which may start out
- partly full. After the copy, the files are not closed nor the last
- block flushed to output, and the input buffer may still be partly
- full. If `crc_i_flag' is set, add each byte to `crc'.
- IN_DES is the file descriptor for input;
- OUT_DES is the file descriptor for output;
- NUM_BYTES is the number of bytes to copy. */
-
-void
-copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes,
- char *filename)
-{
- long size;
- long k;
- off_t original_num_bytes;
- int rc;
-
- original_num_bytes = num_bytes;
- while (num_bytes > 0)
- {
- if (input_size == 0)
- if (rc = disk_fill_input_buffer (in_des, num_bytes))
- {
- if (rc > 0)
- {
- char buf[UINTMAX_STRSIZE_BOUND];
- error (0, 0,
- ngettext ("File %s shrunk by %s byte, padding with zeros",
- "File %s shrunk by %s bytes, padding with zeros",
- num_bytes),
- filename, STRINGIFY_BIGINT (num_bytes, buf));
- }
- else
- error (0, 0, _("Read error at byte %lld in file %s, padding with zeros"),
- original_num_bytes - num_bytes, filename);
- write_nuls_to_file (num_bytes, out_des, disk_buffered_write);
- break;
- }
- size = (input_size < num_bytes) ? input_size : num_bytes;
- if (crc_i_flag)
- {
- for (k = 0; k < size; ++k)
- crc += in_buff[k] & 0xff;
- }
- disk_buffered_write (in_buff, out_des, size);
- num_bytes -= size;
- input_size -= size;
- in_buff += size;
- }
-}
-
-/* Warn if file changed while it was being copied. */
-
-void
-warn_if_file_changed (char *file_name, unsigned long old_file_size,
- off_t old_file_mtime)
-{
- struct stat new_file_stat;
- if ((*xstat) (file_name, &new_file_stat) < 0)
- {
- stat_error (file_name);
- return;
- }
-
- /* Only check growth, shrinkage detected in copy_files_disk_to_{disk,tape}()
- */
- if (new_file_stat.st_size > old_file_size)
- error (0, 0,
- ngettext ("File %s grew, %"PRIuMAX" new byte not copied",
- "File %s grew, %"PRIuMAX" new bytes not copied",
- (long)(new_file_stat.st_size - old_file_size)),
- file_name, (uintmax_t) (new_file_stat.st_size - old_file_size));
-
- else if (new_file_stat.st_mtime != old_file_mtime)
- error (0, 0, _("File %s was modified while being copied"), file_name);
-}
-
-/* Create all directories up to but not including the last part of NAME.
- Do not destroy any nondirectories while creating directories. */
-
-void
-create_all_directories (char *name)
-{
- char *dir;
- int mode;
-#ifdef HPUX_CDF
- int cdf;
-#endif
-
- dir = dir_name (name);
- mode = 0700;
-#ifdef HPUX_CDF
- cdf = islastparentcdf (name);
- if (cdf)
- {
- dir [strlen (dir) - 1] = '\0'; /* remove final + */
- mode = 04700;
- }
-
-#endif
-
- if (dir == NULL)
- error (2, 0, _("virtual memory exhausted"));
-
- if (dir[0] != '.' || dir[1] != '\0')
- make_path (dir, mode, 0700, -1, -1, (char *) NULL);
-
- free (dir);
-}
-
-/* Prepare to append to an archive. We have been in
- process_copy_in, keeping track of the position where
- the last header started in `last_header_start'. Now we
- have the starting position of the last header (the TRAILER!!!
- header, or blank record for tar archives) and we want to start
- writing (appending) over the last header. The last header may
- be in the middle of a block, so to keep the buffering in sync
- we lseek back to the start of the block, read everything up
- to but not including the last header, lseek back to the start
- of the block, and then do a copy_buf_out of what we read.
- Actually, we probably don't have to worry so much about keeping the
- buffering perfect since you can only append to archives that
- are disk files. */
-
-void
-prepare_append (int out_file_des)
-{
- int start_of_header;
- int start_of_block;
- int useful_bytes_in_block;
- char *tmp_buf;
-
- start_of_header = last_header_start;
- /* Figure out how many bytes we will rewrite, and where they start. */
- useful_bytes_in_block = start_of_header % io_block_size;
- start_of_block = start_of_header - useful_bytes_in_block;
-
- if (lseek (out_file_des, start_of_block, SEEK_SET) < 0)
- error (1, errno, _("cannot seek on output"));
- if (useful_bytes_in_block > 0)
- {
- tmp_buf = (char *) xmalloc (useful_bytes_in_block);
- read (out_file_des, tmp_buf, useful_bytes_in_block);
- if (lseek (out_file_des, start_of_block, SEEK_SET) < 0)
- error (1, errno, _("cannot seek on output"));
- /* fix juo -- is this copy_tape_buf_out? or copy_disk? */
- tape_buffered_write (tmp_buf, out_file_des, useful_bytes_in_block);
- free (tmp_buf);
- }
-
- /* We are done reading the archive, so clear these since they
- will now be used for reading in files that we are appending
- to the archive. */
- input_size = 0;
- input_bytes = 0;
- in_buff = input_buffer;
-}
-
-/* Support for remembering inodes with multiple links. Used in the
- "copy in" and "copy pass" modes for making links instead of copying
- the file. */
-
-struct inode_val
-{
- unsigned long inode;
- unsigned long major_num;
- unsigned long minor_num;
- char *file_name;
-};
-
-/* Inode hash table. Allocated by first call to add_inode. */
-static Hash_table *hash_table = NULL;
-
-static size_t
-inode_val_hasher (const void *val, size_t n_buckets)
-{
- const struct inode_val *ival = val;
- return ival->inode % n_buckets;
-}
-
-static bool
-inode_val_compare (const void *val1, const void *val2)
-{
- const struct inode_val *ival1 = val1;
- const struct inode_val *ival2 = val2;
- return ival1->inode == ival2->inode
- && ival1->major_num == ival2->major_num
- && ival1->minor_num == ival2->minor_num;
-}
-
-char *
-find_inode_file (unsigned long node_num, unsigned long major_num,
- unsigned long minor_num)
-{
- struct inode_val sample;
- struct inode_val *ival;
-
- if (!hash_table)
- return NULL;
-
- sample.inode = node_num;
- sample.major_num = major_num;
- sample.minor_num = minor_num;
- ival = hash_lookup (hash_table, &sample);
- return ival ? ival->file_name : NULL;
-}
-
-/* Associate FILE_NAME with the inode NODE_NUM. (Insert into hash table.) */
-
-void
-add_inode (unsigned long node_num, char *file_name, unsigned long major_num,
- unsigned long minor_num)
-{
- struct inode_val *temp;
- struct inode_val *e;
-
- /* Create new inode record. */
- temp = (struct inode_val *) xmalloc (sizeof (struct inode_val));
- temp->inode = node_num;
- temp->major_num = major_num;
- temp->minor_num = minor_num;
- temp->file_name = xstrdup (file_name);
-
- if (!((hash_table
- || (hash_table = hash_initialize (0, 0, inode_val_hasher,
- inode_val_compare, 0)))
- && (e = hash_insert (hash_table, temp))))
- xalloc_die ();
- /* FIXME: e is not used */
-}
-
-
-/* Open FILE in the mode specified by the command line options
- and return an open file descriptor for it,
- or -1 if it can't be opened. */
-
-int
-open_archive (char *file)
-{
- int fd;
- void (*copy_in) (); /* Workaround for pcc bug. */
-
- copy_in = process_copy_in;
-
- if (copy_function == copy_in)
- fd = rmtopen (file, O_RDONLY | O_BINARY, MODE_RW, rsh_command_option);
- else
- {
- if (!append_flag)
- fd = rmtopen (file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, MODE_RW,
- rsh_command_option);
- else
- fd = rmtopen (file, O_RDWR | O_BINARY, MODE_RW, rsh_command_option);
- }
-
- return fd;
-}
-
-/* Attempt to rewind the tape drive on file descriptor TAPE_DES
- and take it offline. */
-
-void
-tape_offline (int tape_des)
-{
-#if defined(MTIOCTOP) && defined(MTOFFL)
- struct mtop control;
-
- control.mt_op = MTOFFL;
- control.mt_count = 1;
- rmtioctl (tape_des, MTIOCTOP, (char*) &control); /* Don't care if it fails. */
-#endif
-}
-
-/* The file on file descriptor TAPE_DES is assumed to be magnetic tape
- (or floppy disk or other device) and the end of the medium
- has been reached. Ask the user for to mount a new "tape" to continue
- the processing. If the user specified the device name on the
- command line (with the -I, -O, -F or --file options), then we can
- automatically re-open the same device to use the next medium. If the
- user did not specify the device name, then we have to ask them which
- device to use. */
-
-void
-get_next_reel (int tape_des)
-{
- static int reel_number = 1;
- FILE *tty_in; /* File for interacting with user. */
- FILE *tty_out; /* File for interacting with user. */
- int old_tape_des;
- char *next_archive_name;
- dynamic_string new_name;
- char *str_res;
-
- ds_init (&new_name, 128);
-
- /* Open files for interactive communication. */
- tty_in = fopen (TTY_NAME, "r");
- if (tty_in == NULL)
- error (2, errno, TTY_NAME);
- tty_out = fopen (TTY_NAME, "w");
- if (tty_out == NULL)
- error (2, errno, TTY_NAME);
-
- old_tape_des = tape_des;
- tape_offline (tape_des);
- rmtclose (tape_des);
-
- /* Give message and wait for carrage return. User should hit carrage return
- only after loading the next tape. */
- ++reel_number;
- if (new_media_message)
- fprintf (tty_out, "%s", new_media_message);
- else if (new_media_message_with_number)
- fprintf (tty_out, "%s%d%s", new_media_message_with_number, reel_number,
- new_media_message_after_number);
- else if (archive_name)
- fprintf (tty_out, _("Found end of volume. Load next volume and press RETURN. "));
- else
- fprintf (tty_out, _("Found end of volume. To continue, type device/file name when ready.\n"));
-
- fflush (tty_out);
-
- if (archive_name)
- {
- int c;
-
- do
- c = getc (tty_in);
- while (c != EOF && c != '\n');
-
- tape_des = open_archive (archive_name);
- if (tape_des == -1)
- open_error (archive_name);
- }
- else
- {
- do
- {
- if (tape_des < 0)
- {
- fprintf (tty_out,
- _("To continue, type device/file name when ready.\n"));
- fflush (tty_out);
- }
-
- str_res = ds_fgets (tty_in, &new_name);
- if (str_res == NULL || str_res[0] == '\0')
- exit (1);
- next_archive_name = str_res;
-
- tape_des = open_archive (next_archive_name);
- if (tape_des == -1)
- open_error (next_archive_name);
- }
- while (tape_des < 0);
- }
-
- /* We have to make sure that `tape_des' has not changed its value even
- though we closed it and reopened it, since there are local
- copies of it in other routines. This works fine on Unix (even with
- rmtread and rmtwrite) since open will always return the lowest
- available file descriptor and we haven't closed any files (e.g.,
- stdin, stdout or stderr) that were opened before we originally opened
- the archive. */
-
- if (tape_des != old_tape_des)
- error (1, 0, _("internal error: tape descriptor changed from %d to %d"),
- old_tape_des, tape_des);
-
- free (new_name.ds_string);
- fclose (tty_in);
- fclose (tty_out);
-}
-
-/* If MESSAGE does not contain the string "%d", make `new_media_message'
- a copy of MESSAGE. If MESSAGES does contain the string "%d", make
- `new_media_message_with_number' a copy of MESSAGE up to, but
- not including, the string "%d", and make `new_media_message_after_number'
- a copy of MESSAGE after the string "%d". */
-
-void
-set_new_media_message (char *message)
-{
- char *p;
- int prev_was_percent;
-
- p = message;
- prev_was_percent = 0;
- while (*p != '\0')
- {
- if (*p == 'd' && prev_was_percent)
- break;
- prev_was_percent = (*p == '%');
- ++p;
- }
- if (*p == '\0')
- {
- new_media_message = xstrdup (message);
- }
- else
- {
- int length = p - message - 1;
-
- new_media_message_with_number = xmalloc (length + 1);
- strncpy (new_media_message_with_number, message, length);
- new_media_message_with_number[length] = '\0';
- length = strlen (p + 1);
- new_media_message_after_number = xmalloc (length + 1);
- strcpy (new_media_message_after_number, p + 1);
- }
-}
-
-#ifdef SYMLINK_USES_UMASK
-/* Most machines always create symlinks with rwxrwxrwx protection,
- but some (HP/UX 8.07; maybe DEC's OSF on MIPS, too?) use the
- umask when creating symlinks, so if your umask is 022 you end
- up with rwxr-xr-x symlinks (although HP/UX seems to completely
- ignore the protection). There doesn't seem to be any way to
- manipulate the modes once the symlinks are created (e.g.
- a hypothetical "lchmod"), so to create them with the right
- modes we have to set the umask first. */
-
-int
-umasked_symlink (char *name1, char *name2, int mode)
-{
- int old_umask;
- int rc;
- mode = ~(mode & 0777) & 0777;
- old_umask = umask (mode);
- rc = symlink (name1, name2);
- umask (old_umask);
- return rc;
-}
-#endif /* SYMLINK_USES_UMASK */
-
-#ifdef HPUX_CDF
-/* When we create a cpio archive we mark CDF's by putting an extra `/'
- after their component name so we can distinguish the CDF's when we
- extract the archive (in case the "hidden" directory's files appear
- in the archive before the directory itself). E.g., in the path
- "a/b+/c", if b+ is a CDF, we will write this path as "a/b+//c" in
- the archive so when we extract the archive we will know that b+
- is actually a CDF, and not an ordinary directory whose name happens
- to end in `+'. We also do the same thing internally in copypass.c. */
-
-
-/* Take an input pathname and check it for CDF's. Insert an extra
- `/' in the pathname after each "hidden" directory. If we add
- any `/'s, return a malloced string instead of the original input
- string.
- FIXME: This creates a memory leak.
-*/
-
-char *
-add_cdf_double_slashes (char *input_name)
-{
- static char *ret_name = NULL; /* re-usuable return buffer (malloc'ed) */
- static int ret_size = -1; /* size of return buffer. */
- char *p;
- char *q;
- int n;
- struct stat dir_stat;
-
- /* Search for a `/' preceeded by a `+'. */
-
- for (p = input_name; *p != '\0'; ++p)
- {
- if ( (*p == '+') && (*(p + 1) == '/') )
- break;
- }
-
- /* If we didn't find a `/' preceeded by a `+' then there are
- no CDF's in this pathname. Return the original pathname. */
-
- if (*p == '\0')
- return input_name;
-
- /* There was a `/' preceeded by a `+' in the pathname. If it is a CDF
- then we will need to copy the input pathname to our return
- buffer so we can insert the extra `/'s. Since we can't tell
- yet whether or not it is a CDF we will just always copy the
- string to the return buffer. First we have to make sure the
- buffer is large enough to hold the string and any number of
- extra `/'s we might add. */
-
- n = 2 * (strlen (input_name) + 1);
- if (n >= ret_size)
- {
- if (ret_size < 0)
- ret_name = (char *) malloc (n);
- else
- ret_name = (char *)realloc (ret_name, n);
- ret_size = n;
- }
-
- /* Clear the `/' after this component, so we can stat the pathname
- up to and including this component. */
- ++p;
- *p = '\0';
- if ((*xstat) (input_name, &dir_stat) < 0)
- {
- stat_error (input_name);
- return input_name;
- }
-
- /* Now put back the `/' after this component and copy the pathname up to
- and including this component and its trailing `/' to the return
- buffer. */
- *p++ = '/';
- strncpy (ret_name, input_name, p - input_name);
- q = ret_name + (p - input_name);
-
- /* If it was a CDF, add another `/'. */
- if (S_ISDIR (dir_stat.st_mode) && (dir_stat.st_mode & 04000) )
- *q++ = '/';
-
- /* Go through the rest of the input pathname, copying it to the
- return buffer, and adding an extra `/' after each CDF. */
- while (*p != '\0')
- {
- if ( (*p == '+') && (*(p + 1) == '/') )
- {
- *q++ = *p++;
-
- *p = '\0';
- if ((*xstat) (input_name, &dir_stat) < 0)
- {
- stat_error (input_name);
- return input_name;
- }
- *p = '/';
-
- if (S_ISDIR (dir_stat.st_mode) && (dir_stat.st_mode & 04000) )
- *q++ = '/';
- }
- *q++ = *p++;
- }
- *q = '\0';
-
- return ret_name;
-}
-
-/* Is the last parent directory (e.g., c in a/b/c/d) a CDF? If the
- directory name ends in `+' and is followed by 2 `/'s instead of 1
- then it is. This is only the case for cpio archives, but we don't
- have to worry about tar because tar always has the directory before
- its files (or else we lose). */
-int
-islastparentcdf (char *path)
-{
- char *newpath;
- char *slash;
- int slash_count;
- int length; /* Length of result, not including NUL. */
-
- slash = strrchr (path, '/');
- if (slash == 0)
- return 0;
- else
- {
- slash_count = 0;
- while (slash > path && *slash == '/')
- {
- ++slash_count;
- --slash;
- }
-
-
- if ( (*slash == '+') && (slash_count >= 2) )
- return 1;
- }
- return 0;
-}
-#endif
-
-#define DISKBLOCKSIZE (512)
-
-static int
-buf_all_zeros (char *buf, int bufsize)
-{
- int i;
- for (i = 0; i < bufsize; ++i)
- {
- if (*buf++ != '\0')
- return 0;
- }
- return 1;
-}
-
-int delayed_seek_count = 0;
-
-/* Write NBYTE bytes from BUF to remote tape connection FILDES.
- Return the number of bytes written on success, -1 on error. */
-
-static int
-sparse_write (int fildes, char *buf, unsigned int nbyte)
-{
- int complete_block_count;
- int leftover_bytes_count;
- int seek_count;
- int write_count;
- char *cur_write_start;
- int lseek_rc;
- int write_rc;
- int i;
- enum { begin, in_zeros, not_in_zeros } state;
-
- complete_block_count = nbyte / DISKBLOCKSIZE;
- leftover_bytes_count = nbyte % DISKBLOCKSIZE;
-
- if (delayed_seek_count != 0)
- state = in_zeros;
- else
- state = begin;
-
- seek_count = delayed_seek_count;
-
- for (i = 0; i < complete_block_count; ++i)
- {
- switch (state)
- {
- case begin :
- if (buf_all_zeros (buf, DISKBLOCKSIZE))
- {
- seek_count = DISKBLOCKSIZE;
- state = in_zeros;
- }
- else
- {
- cur_write_start = buf;
- write_count = DISKBLOCKSIZE;
- state = not_in_zeros;
- }
- buf += DISKBLOCKSIZE;
- break;
-
- case in_zeros :
- if (buf_all_zeros (buf, DISKBLOCKSIZE))
- {
- seek_count += DISKBLOCKSIZE;
- }
- else
- {
- lseek (fildes, seek_count, SEEK_CUR);
- cur_write_start = buf;
- write_count = DISKBLOCKSIZE;
- state = not_in_zeros;
- }
- buf += DISKBLOCKSIZE;
- break;
-
- case not_in_zeros :
- if (buf_all_zeros (buf, DISKBLOCKSIZE))
- {
- write_rc = write (fildes, cur_write_start, write_count);
- seek_count = DISKBLOCKSIZE;
- state = in_zeros;
- }
- else
- {
- write_count += DISKBLOCKSIZE;
- }
- buf += DISKBLOCKSIZE;
- break;
- }
- }
-
- switch (state)
- {
- case begin :
- case in_zeros :
- delayed_seek_count = seek_count;
- break;
-
- case not_in_zeros :
- write_rc = write (fildes, cur_write_start, write_count);
- delayed_seek_count = 0;
- break;
- }
-
- if (leftover_bytes_count != 0)
- {
- if (delayed_seek_count != 0)
- {
- lseek_rc = lseek (fildes, delayed_seek_count, SEEK_CUR);
- delayed_seek_count = 0;
- }
- write_rc = write (fildes, buf, leftover_bytes_count);
- }
- return nbyte;
-}
-
-#define CPIO_UID(uid) (set_owner_flag ? set_owner : (uid))
-#define CPIO_GID(gid) (set_group_flag ? set_group : (gid))
-
-void
-stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st)
-{
- hdr->c_dev_maj = major (st->st_dev);
- hdr->c_dev_min = minor (st->st_dev);
- hdr->c_ino = st->st_ino;
- /* For POSIX systems that don't define the S_IF macros,
- we can't assume that S_ISfoo means the standard Unix
- S_IFfoo bit(s) are set. So do it manually, with a
- different name. Bleah. */
- hdr->c_mode = (st->st_mode & 07777);
- if (S_ISREG (st->st_mode))
- hdr->c_mode |= CP_IFREG;
- else if (S_ISDIR (st->st_mode))
- hdr->c_mode |= CP_IFDIR;
-#ifdef S_ISBLK
- else if (S_ISBLK (st->st_mode))
- hdr->c_mode |= CP_IFBLK;
-#endif
-#ifdef S_ISCHR
- else if (S_ISCHR (st->st_mode))
- hdr->c_mode |= CP_IFCHR;
-#endif
-#ifdef S_ISFIFO
- else if (S_ISFIFO (st->st_mode))
- hdr->c_mode |= CP_IFIFO;
-#endif
-#ifdef S_ISLNK
- else if (S_ISLNK (st->st_mode))
- hdr->c_mode |= CP_IFLNK;
-#endif
-#ifdef S_ISSOCK
- else if (S_ISSOCK (st->st_mode))
- hdr->c_mode |= CP_IFSOCK;
-#endif
-#ifdef S_ISNWK
- else if (S_ISNWK (st->st_mode))
- hdr->c_mode |= CP_IFNWK;
-#endif
- hdr->c_uid = CPIO_UID (st->st_uid);
- hdr->c_gid = CPIO_GID (st->st_gid);
- hdr->c_nlink = st->st_nlink;
- hdr->c_rdev_maj = major (st->st_rdev);
- hdr->c_rdev_min = minor (st->st_rdev);
- hdr->c_mtime = st->st_mtime;
- hdr->c_filesize = st->st_size;
- hdr->c_chksum = 0;
- hdr->c_tar_linkname = NULL;
-}
-
-#ifndef HAVE_FCHOWN
-# define fchown(fd, uid, gid) (-1)
-#endif
-
-int
-fchown_or_chown (int fd, const char *name, uid_t uid, uid_t gid)
-{
- if (HAVE_FCHOWN && fd != -1)
- return fchown (fd, uid, gid);
- else
- return chown (name, uid, gid);
-}
-
-int
-fchmod_or_chmod (int fd, const char *name, mode_t mode)
-{
- if (HAVE_FCHMOD && fd != -1)
- return fchmod (fd, mode);
- else
- return chmod(name, mode);
-}
-
-void
-set_perms (int fd, struct cpio_file_stat *header)
-{
- if (!no_chown_flag)
- {
- uid_t uid = CPIO_UID (header->c_uid);
- gid_t gid = CPIO_GID (header->c_gid);
- if ((fchown_or_chown (fd, header->c_name, uid, gid) < 0)
- && errno != EPERM)
- chown_error_details (header->c_name, uid, gid);
- }
- /* chown may have turned off some permissions we wanted. */
- if (fchmod_or_chmod (fd, header->c_name, header->c_mode) < 0)
- chmod_error_details (header->c_name, header->c_mode);
-#ifdef HPUX_CDF
- if ((header->c_mode & CP_IFMT) && 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)
- set_file_times (fd, header->c_name, header->c_mtime, header->c_mtime);
-}
-
-void
-set_file_times (int fd,
- const char *name, unsigned long atime, unsigned long mtime)
-{
- struct timespec ts[2];
-
- memset (&ts, 0, sizeof ts);
-
- ts[0].tv_sec = atime;
- ts[1].tv_sec = mtime;
-
- /* Silently ignore EROFS because reading the file won't have upset its
- timestamp if it's on a read-only filesystem. */
- if (gl_futimens (fd, name, ts) < 0 && errno != EROFS)
- utime_error (name);
-}
-
-/* Do we have to ignore absolute paths, and if so, does the filename
- have an absolute path? */
-void
-cpio_safer_name_suffix (char *name, bool link_target, bool absolute_names,
- bool strip_leading_dots)
-{
- char *p = safer_name_suffix (name, link_target, absolute_names);
- if (strip_leading_dots && strcmp (p, "./"))
- /* strip leading `./' from the filename. */
- while (*p == '.' && *(p + 1) == '/')
- {
- ++p;
- while (*p == '/')
- ++p;
- }
- if (p != name)
- memmove (name, p, (size_t)(strlen (p) + 1));
-}
-
OpenPOWER on IntegriCloud