summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/copyin.c445
-rw-r--r--src/copyout.c654
-rw-r--r--src/copypass.c149
-rw-r--r--src/cpio.h11
-rw-r--r--src/cpiohdr.h84
-rw-r--r--src/defer.c11
-rw-r--r--src/defer.h15
-rw-r--r--src/dstring.c16
-rw-r--r--src/dstring.h7
-rw-r--r--src/extern.h155
-rw-r--r--src/filemode.c7
-rw-r--r--src/filetypes.h7
-rw-r--r--src/global.c14
-rw-r--r--src/idcache.c7
-rw-r--r--src/main.c301
-rw-r--r--src/makepath.c72
-rw-r--r--src/tar.c63
-rw-r--r--src/tar.h8
-rw-r--r--src/tarhdr.h7
-rw-r--r--src/userspec.c20
-rw-r--r--src/util.c439
21 files changed, 1332 insertions, 1160 deletions
diff --git a/src/copyin.c b/src/copyin.c
index a1063a35c407..819e2f4ebc58 100644
--- a/src/copyin.c
+++ b/src/copyin.c
@@ -1,5 +1,6 @@
/* copyin.c - extract or list a cpio archive
- Copyright (C) 1990,1991,1992,2001,2002,2003,2004 Free Software Foundation, Inc.
+ Copyright (C) 1990,1991,1992,2001,2002,2003,2004,
+ 2005, 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
@@ -11,9 +12,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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>
@@ -27,14 +29,14 @@
#include "defer.h"
#include <rmt.h>
#ifndef FNM_PATHNAME
-#include <fnmatch.h>
+# include <fnmatch.h>
#endif
#ifndef HAVE_LCHOWN
-#define lchown chown
+# define lchown(f,u,g) 0
#endif
-static void copyin_regular_file(struct new_cpio_header* file_hdr,
+static void copyin_regular_file(struct cpio_file_stat* file_hdr,
int in_file_des);
void
@@ -47,7 +49,7 @@ warn_junk_bytes (long bytes_skipped)
static int
-query_rename(struct new_cpio_header* file_hdr, FILE *tty_in, FILE *tty_out,
+query_rename(struct cpio_file_stat* file_hdr, FILE *tty_in, FILE *tty_out,
FILE *rename_in)
{
char *str_res; /* Result for string function. */
@@ -125,7 +127,7 @@ tape_skip_padding (int in_file_des, int offset)
static void
-list_file(struct new_cpio_header* file_hdr, int in_file_des)
+list_file(struct cpio_file_stat* file_hdr, int in_file_des)
{
if (verbose_flag)
{
@@ -176,15 +178,15 @@ list_file(struct new_cpio_header* file_hdr, int in_file_des)
#endif
if (crc != file_hdr->c_chksum)
{
- error (0, 0, _("%s: checksum error (0x%x, should be 0x%x)"),
+ error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
file_hdr->c_name, crc, file_hdr->c_chksum);
}
}
}
static int
-try_existing_file(struct new_cpio_header* file_hdr, int in_file_des,
- int *existing_dir)
+try_existing_file (struct cpio_file_stat* file_hdr, int in_file_des,
+ int *existing_dir)
{
struct stat file_stat;
@@ -238,7 +240,7 @@ struct deferment *deferments = NULL;
go on one list, although we could optimize this if necessary. */
static void
-defer_copyin (struct new_cpio_header *file_hdr)
+defer_copyin (struct cpio_file_stat *file_hdr)
{
struct deferment *d;
d = create_deferment (file_hdr);
@@ -252,7 +254,7 @@ defer_copyin (struct new_cpio_header *file_hdr)
list and create any which are links to this file. */
static void
-create_defered_links (struct new_cpio_header *file_hdr)
+create_defered_links (struct cpio_file_stat *file_hdr)
{
struct deferment *d;
struct deferment *d_prev;
@@ -299,7 +301,7 @@ create_defered_links (struct new_cpio_header *file_hdr)
then create the other deferred links. */
static int
-create_defered_links_to_skipped (struct new_cpio_header *file_hdr,
+create_defered_links_to_skipped (struct cpio_file_stat *file_hdr,
int in_file_des)
{
struct deferment *d;
@@ -307,7 +309,6 @@ create_defered_links_to_skipped (struct new_cpio_header *file_hdr,
int ino;
int maj;
int min;
- int link_res;
if (file_hdr->c_filesize == 0)
{
/* The file doesn't have any data attached to it so we don't have
@@ -355,10 +356,7 @@ create_final_defers ()
struct deferment *d;
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 (&times, sizeof (struct utimbuf));
-
+
for (d = deferments; d != NULL; d = d->next)
{
/* Debian hack: A line, which could cause an endless loop, was
@@ -385,34 +383,20 @@ create_final_defers ()
}
if (out_file_des < 0)
{
- error (0, errno, "%s", d->header.c_name);
+ open_error (d->header.c_name);
continue;
}
+ set_perms (out_file_des, &d->header);
+
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, &times) < 0)
- error (0, errno, "%s", d->header.c_name);
- }
+ close_error (d->header.c_name);
+
}
}
static void
-copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
+copyin_regular_file (struct cpio_file_stat* file_hdr, int in_file_des)
{
int out_file_des; /* Output file descriptor. */
@@ -460,7 +444,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
{
tape_toss_input (in_file_des, file_hdr->c_filesize);
tape_skip_padding (in_file_des, file_hdr->c_filesize);
- return;
+ return;
}
}
else if (file_hdr->c_nlink > 1
@@ -509,7 +493,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
if (out_file_des < 0)
{
- error (0, errno, "%s", file_hdr->c_name);
+ open_error (file_hdr->c_name);
tape_toss_input (in_file_des, file_hdr->c_filesize);
tape_skip_padding (in_file_des, file_hdr->c_filesize);
return;
@@ -541,7 +525,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
if (archive_format == arf_crcascii)
{
if (crc != file_hdr->c_chksum)
- error (0, 0, _("%s: checksum error (0x%x, should be 0x%x)"),
+ error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
file_hdr->c_name, crc, file_hdr->c_chksum);
}
tape_skip_padding (in_file_des, file_hdr->c_filesize);
@@ -557,39 +541,19 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
write (out_file_des, "", 1);
delayed_seek_count = 0;
}
+
+ set_perms (out_file_des, file_hdr);
+
if (close (out_file_des) < 0)
- error (0, errno, "%s", file_hdr->c_name);
+ close_error (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)"),
+ error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
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)
- {
- struct utimbuf times; /* For setting file times. */
- /* Initialize this in case it has members we don't know to set. */
- bzero (&times, sizeof (struct utimbuf));
-
- times.actime = times.modtime = file_hdr->c_mtime;
- if (utime (file_hdr->c_name, &times) < 0)
- error (0, errno, "%s", file_hdr->c_name);
- }
-
tape_skip_padding (in_file_des, file_hdr->c_filesize);
if (file_hdr->c_nlink > 1
&& (archive_format == arf_newascii || archive_format == arf_crcascii) )
@@ -603,7 +567,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
}
static void
-copyin_directory(struct new_cpio_header* file_hdr, int existing_dir)
+copyin_directory (struct cpio_file_stat *file_hdr, int existing_dir)
{
int res; /* Result of various function calls. */
#ifdef HPUX_CDF
@@ -663,43 +627,29 @@ copyin_directory(struct new_cpio_header* file_hdr, int existing_dir)
because the directory exists. If that's the case,
don't complain about it. */
struct stat file_stat;
- if ( (errno != EEXIST) ||
- (lstat (file_hdr->c_name, &file_stat) != 0) ||
- !(S_ISDIR (file_stat.st_mode) ) )
+ if (errno != EEXIST)
{
- error (0, errno, "%s", file_hdr->c_name);
+ mkdir_error (file_hdr->c_name);
+ return;
+ }
+ if (lstat (file_hdr->c_name, &file_stat))
+ {
+ stat_error (file_hdr->c_name);
+ return;
+ }
+ if (!(S_ISDIR (file_stat.st_mode)))
+ {
+ error (0, 0, _("%s is not a directory"),
+ quotearg_colon (file_hdr->c_name));
return;
}
}
- 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)
- {
- struct utimbuf times; /* For setting file times. */
- /* Initialize this in case it has members we don't know to set. */
- bzero (&times, sizeof (struct utimbuf));
- times.actime = times.modtime = file_hdr->c_mtime;
- if (utime (file_hdr->c_name, &times) < 0)
- error (0, errno, "%s", file_hdr->c_name);
- }
+ set_perms (-1, file_hdr);
}
static void
-copyin_device(struct new_cpio_header* file_hdr)
+copyin_device (struct cpio_file_stat* file_hdr)
{
int res; /* Result of various function calls. */
@@ -752,32 +702,27 @@ copyin_device(struct new_cpio_header* file_hdr)
}
if (res < 0)
{
- error (0, errno, "%s", file_hdr->c_name);
+ mknod_error (file_hdr->c_name);
return;
}
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);
+ {
+ uid_t uid = set_owner_flag ? set_owner : file_hdr->c_uid;
+ gid_t gid = set_group_flag ? set_group : file_hdr->c_gid;
+ if ((chown (file_hdr->c_name, uid, gid) < 0)
+ && errno != EPERM)
+ chown_error_details (file_hdr->c_name, uid, gid);
+ }
/* 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);
+ chmod_error_details (file_hdr->c_name, file_hdr->c_mode);
if (retain_time_flag)
- {
- struct utimbuf times; /* For setting file times. */
- /* Initialize this in case it has members we don't know to set. */
- bzero (&times, sizeof (struct utimbuf));
-
- times.actime = times.modtime = file_hdr->c_mtime;
- if (utime (file_hdr->c_name, &times) < 0)
- error (0, errno, "%s", file_hdr->c_name);
- }
+ set_file_times (-1, file_hdr->c_name, file_hdr->c_mtime,
+ file_hdr->c_mtime);
}
static void
-copyin_link(struct new_cpio_header *file_hdr, int in_file_des)
+copyin_link(struct cpio_file_stat *file_hdr, int in_file_des)
{
char *link_name = NULL; /* Name of hard and symbolic links. */
int res; /* Result of various function calls. */
@@ -807,23 +752,24 @@ copyin_link(struct new_cpio_header *file_hdr, int in_file_des)
}
if (res < 0)
{
- error (0, errno, "%s", file_hdr->c_name);
+ error (0, errno, _("%s: Cannot symlink to %s"),
+ quotearg_colon (link_name), quote_n (1, file_hdr->c_name));
free (link_name);
return;
}
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);
- }
+ {
+ uid_t uid = set_owner_flag ? set_owner : file_hdr->c_uid;
+ gid_t gid = set_group_flag ? set_group : file_hdr->c_gid;
+ if ((lchown (file_hdr->c_name, uid, gid) < 0)
+ && errno != EPERM)
+ chown_error_details (file_hdr->c_name, uid, gid);
+ }
free (link_name);
}
static void
-copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
+copyin_file (struct cpio_file_stat* file_hdr, int in_file_des)
{
int existing_dir;
@@ -835,11 +781,11 @@ copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
switch (file_hdr->c_mode & CP_IFMT)
{
case CP_IFREG:
- copyin_regular_file(file_hdr, in_file_des);
+ copyin_regular_file (file_hdr, in_file_des);
break;
case CP_IFDIR:
- copyin_directory(file_hdr, existing_dir);
+ copyin_directory (file_hdr, existing_dir);
break;
case CP_IFCHR:
@@ -850,12 +796,12 @@ copyin_file (struct new_cpio_header* file_hdr, int in_file_des)
#ifdef CP_IFIFO
case CP_IFIFO:
#endif
- copyin_device(file_hdr);
+ copyin_device (file_hdr);
break;
#ifdef CP_IFLNK
case CP_IFLNK:
- copyin_link(file_hdr, in_file_des);
+ copyin_link (file_hdr, in_file_des);
break;
#endif
@@ -876,7 +822,7 @@ static time_t current_time;
this file is a symbolic link to. */
void
-long_format (struct new_cpio_header *file_hdr, char *link_name)
+long_format (struct cpio_file_stat *file_hdr, char *link_name)
{
char mbuf[11];
char tbuf[40];
@@ -897,7 +843,7 @@ long_format (struct new_cpio_header *file_hdr, char *link_name)
}
tbuf[16] = '\0';
- printf ("%s %3u ", mbuf, file_hdr->c_nlink);
+ printf ("%s %3lu ", mbuf, file_hdr->c_nlink);
if (numeric_uid)
printf ("%-8u %-8u ", (unsigned int) file_hdr->c_uid,
@@ -908,10 +854,10 @@ long_format (struct new_cpio_header *file_hdr, char *link_name)
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,
+ printf ("%3lu, %3lu ", file_hdr->c_rdev_maj,
file_hdr->c_rdev_min);
else
- printf ("%8lu ", file_hdr->c_filesize);
+ printf ("%8"PRIuMAX" ", (uintmax_t) file_hdr->c_filesize);
printf ("%s ", tbuf + 4);
@@ -997,7 +943,7 @@ read_pattern_file ()
pattern_fp = fopen (pattern_file_name, "r");
if (pattern_fp == NULL)
- error (1, errno, "%s", pattern_file_name);
+ open_error (pattern_file_name);
while (ds_fgetstr (pattern_fp, &pattern_name, '\n') != NULL)
{
if (new_num_patterns >= max_new_patterns)
@@ -1011,7 +957,7 @@ read_pattern_file ()
++new_num_patterns;
}
if (ferror (pattern_fp) || fclose (pattern_fp) == EOF)
- error (1, errno, "%s", pattern_file_name);
+ close_error (pattern_file_name);
for (i = 0; i < num_patterns; ++i)
new_save_patterns[i] = save_patterns[i];
@@ -1020,6 +966,52 @@ read_pattern_file ()
num_patterns = new_num_patterns;
}
+
+uintmax_t
+from_ascii (char const *where, size_t digs, unsigned logbase)
+{
+ uintmax_t value = 0;
+ char const *buf = where;
+ char const *end = buf + digs;
+ int overflow = 0;
+ static char codetab[] = "0123456789ABCDEF";
+
+ for (; *buf == ' '; buf++)
+ {
+ if (buf == end)
+ return 0;
+ }
+
+ if (buf == end || *buf == 0)
+ return 0;
+ while (1)
+ {
+ unsigned d;
+
+ char *p = strchr (codetab, toupper (*buf));
+ if (!p)
+ {
+ error (0, 0, _("Malformed number %.*s"), digs, where);
+ break;
+ }
+
+ d = p - codetab;
+ if ((d >> logbase) > 1)
+ {
+ error (0, 0, _("Malformed number %.*s"), digs, where);
+ break;
+ }
+ value += d;
+ if (++buf == end || *buf == 0)
+ break;
+ overflow |= value ^ (value << logbase >> logbase);
+ value <<= logbase;
+ }
+ if (overflow)
+ error (0, 0, _("Archive value %.*s is out of range"),
+ digs, where);
+ return value;
+}
@@ -1030,8 +1022,13 @@ read_pattern_file ()
descriptor IN_DES into FILE_HDR. */
void
-read_in_header (struct new_cpio_header *file_hdr, int in_des)
+read_in_header (struct cpio_file_stat *file_hdr, int in_des)
{
+ union {
+ char str[6];
+ unsigned short num;
+ struct old_cpio_header old_header;
+ } magic;
long bytes_skipped = 0; /* Bytes of junk found before magic number. */
/* Search for a valid magic number. */
@@ -1090,52 +1087,53 @@ read_in_header (struct new_cpio_header *file_hdr, int in_des)
file_hdr->c_tar_linkname = NULL;
- tape_buffered_read ((char *) file_hdr, in_des, 6L);
+ tape_buffered_read (magic.str, 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))
+ && !strncmp (magic.str, "070701", 6))
{
if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped);
+ file_hdr->c_magic = 070701;
read_in_new_ascii (file_hdr, in_des);
break;
}
if (archive_format == arf_crcascii
- && !strncmp ((char *) file_hdr, "070702", 6))
+ && !strncmp (magic.str, "070702", 6))
{
if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped);
-
+ file_hdr->c_magic = 070702;
read_in_new_ascii (file_hdr, in_des);
break;
}
if ( (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
- && !strncmp ((char *) file_hdr, "070707", 6))
+ && !strncmp (magic.str, "070707", 6))
{
if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped);
-
+ file_hdr->c_magic = 070707;
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)))
+ && (magic.num == 070707
+ || magic.num == swab_short ((unsigned short) 070707)))
{
/* Having to skip 1 byte because of word alignment is normal. */
if (bytes_skipped > 0)
warn_junk_bytes (bytes_skipped);
-
- read_in_binary (file_hdr, in_des);
+ file_hdr->c_magic = 070707;
+ read_in_binary (file_hdr, &magic.old_header, in_des);
break;
}
bytes_skipped++;
- bcopy ((char *) file_hdr + 1, (char *) file_hdr, 5);
- tape_buffered_read ((char *) file_hdr + 5, in_des, 1L);
+ memmove (magic.str, magic.str + 1, 5);
+ tape_buffered_read (magic.str, in_des, 1L);
}
}
@@ -1144,25 +1142,30 @@ read_in_header (struct new_cpio_header *file_hdr, int in_des)
already filled in. */
void
-read_in_old_ascii (struct new_cpio_header *file_hdr, int in_des)
+read_in_old_ascii (struct cpio_file_stat *file_hdr, int in_des)
{
- char ascii_header[78];
+ struct old_ascii_header ascii_header;
unsigned long dev;
- unsigned long rdev;
-
- tape_buffered_read (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);
+
+ tape_buffered_read (ascii_header.c_dev, in_des,
+ sizeof ascii_header - sizeof ascii_header.c_magic);
+ dev = FROM_OCTAL (ascii_header.c_dev);
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);
+ file_hdr->c_ino = FROM_OCTAL (ascii_header.c_ino);
+ file_hdr->c_mode = FROM_OCTAL (ascii_header.c_mode);
+ file_hdr->c_uid = FROM_OCTAL (ascii_header.c_uid);
+ file_hdr->c_gid = FROM_OCTAL (ascii_header.c_gid);
+ file_hdr->c_nlink = FROM_OCTAL (ascii_header.c_nlink);
+ dev = FROM_OCTAL (ascii_header.c_rdev);
+ file_hdr->c_rdev_maj = major (dev);
+ file_hdr->c_rdev_min = minor (dev);
+
+ file_hdr->c_mtime = FROM_OCTAL (ascii_header.c_mtime);
+ file_hdr->c_namesize = FROM_OCTAL (ascii_header.c_namesize);
+ file_hdr->c_filesize = FROM_OCTAL (ascii_header.c_filesize);
+
/* Read file name from input. */
if (file_hdr->c_name != NULL)
free (file_hdr->c_name);
@@ -1204,19 +1207,27 @@ read_in_old_ascii (struct new_cpio_header *file_hdr, int in_des)
already filled in. */
void
-read_in_new_ascii (struct new_cpio_header *file_hdr, int in_des)
+read_in_new_ascii (struct cpio_file_stat *file_hdr, int in_des)
{
- char ascii_header[112];
-
- tape_buffered_read (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);
+ struct new_ascii_header ascii_header;
+
+ tape_buffered_read (ascii_header.c_ino, in_des,
+ sizeof ascii_header - sizeof ascii_header.c_magic);
+
+ file_hdr->c_ino = FROM_HEX (ascii_header.c_ino);
+ file_hdr->c_mode = FROM_HEX (ascii_header.c_mode);
+ file_hdr->c_uid = FROM_HEX (ascii_header.c_uid);
+ file_hdr->c_gid = FROM_HEX (ascii_header.c_gid);
+ file_hdr->c_nlink = FROM_HEX (ascii_header.c_nlink);
+ file_hdr->c_mtime = FROM_HEX (ascii_header.c_mtime);
+ file_hdr->c_filesize = FROM_HEX (ascii_header.c_filesize);
+ file_hdr->c_dev_maj = FROM_HEX (ascii_header.c_dev_maj);
+ file_hdr->c_dev_min = FROM_HEX (ascii_header.c_dev_min);
+ file_hdr->c_rdev_maj = FROM_HEX (ascii_header.c_rdev_maj);
+ file_hdr->c_rdev_min = FROM_HEX (ascii_header.c_rdev_min);
+ file_hdr->c_namesize = FROM_HEX (ascii_header.c_namesize);
+ file_hdr->c_chksum = FROM_HEX (ascii_header.c_chksum);
+
/* Read file name from input. */
if (file_hdr->c_name != NULL)
free (file_hdr->c_name);
@@ -1234,15 +1245,14 @@ read_in_new_ascii (struct new_cpio_header *file_hdr, int in_des)
number, device, and inode number), which are already filled in. */
void
-read_in_binary (struct new_cpio_header *file_hdr, int in_des)
+read_in_binary (struct cpio_file_stat *file_hdr,
+ struct old_cpio_header *short_hdr,
+ int in_des)
{
- struct old_cpio_header short_hdr;
+ file_hdr->c_magic = short_hdr->c_magic;
- /* 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;
- tape_buffered_read (((char *) &short_hdr) + 6, in_des, 20L);
+ tape_buffered_read (((char *) short_hdr) + 6, in_des,
+ sizeof *short_hdr - 6 /* = 20 */);
/* If the magic number is byte swapped, fix the header. */
if (file_hdr->c_magic == swab_short ((unsigned short) 070707))
@@ -1259,21 +1269,21 @@ read_in_binary (struct new_cpio_header *file_hdr, int in_des)
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];
+ 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)
@@ -1342,15 +1352,18 @@ void
process_copy_in ()
{
char done = false; /* True if trailer reached. */
- FILE *tty_in; /* Interactive file for rename option. */
- FILE *tty_out; /* Interactive file for rename option. */
- FILE *rename_in; /* Batch file for rename option. */
+ FILE *tty_in = NULL; /* Interactive file for rename option. */
+ FILE *tty_out = NULL; /* Interactive file for rename option. */
+ FILE *rename_in = NULL; /* Batch file for rename option. */
struct stat file_stat; /* Output file stat record. */
- struct new_cpio_header file_hdr; /* Output header information. */
+ struct cpio_file_stat file_hdr; /* Output header information. */
int in_file_des; /* Input file descriptor. */
char skip_file; /* Flag for use with patterns. */
int i; /* Loop index variable. */
+ umask (0); /* Reset umask to preserve modes of
+ created files */
+
/* Initialize the copy in. */
if (pattern_file_name)
{
@@ -1418,7 +1431,7 @@ process_copy_in ()
#ifdef DEBUG_CPIO
if (debug_flag)
{
- struct new_cpio_header *h;
+ struct cpio_file_stat *h;
h = &file_hdr;
fprintf (stderr,
"magic = 0%o, ino = %d, mode = 0%o, uid = %d, gid = %d\n",
@@ -1437,37 +1450,15 @@ process_copy_in ()
}
#endif
/* Is this the header for the TRAILER file? */
- if (strcmp ("TRAILER!!!", file_hdr.c_name) == 0)
+ if (strcmp (CPIO_TRAILER_NAME, file_hdr.c_name) == 0)
{
done = true;
break;
}
- /* Do we have to ignore absolute paths, and if so, does the filename
- have an absolute path? */
- if (no_abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0] == '/')
- {
- char *p;
-
- p = file_hdr.c_name;
- while (*p == '/')
- ++p;
- if (*p == '\0')
- {
- strcpy (file_hdr.c_name, ".");
- }
- else
- {
- /* Debian hack: file_hrd.c_name is sometimes set to
- point to static memory by code in tar.c. This
- causes a segfault. Therefore, memmove is used
- instead of freeing and reallocating. (Reported by
- Horst Knobloch.) This bug has been reported to
- "bug-gnu-utils@prep.ai.mit.edu". (99/1/6) -BEM */
- (void)memmove (file_hdr.c_name, p, (size_t)(strlen (p) + 1));
- }
- }
-
+ cpio_safer_name_suffix (file_hdr.c_name, false, !no_abs_paths_flag,
+ false);
+
/* Does the file name match one of the given patterns? */
if (num_patterns <= 0)
skip_file = false;
@@ -1530,7 +1521,7 @@ process_copy_in ()
tape_skip_padding (in_file_des, file_hdr.c_filesize);
if (crc != file_hdr.c_chksum)
{
- error (0, 0, _("%s: checksum error (0x%x, should be 0x%x)"),
+ error (0, 0, _("%s: checksum error (0x%lx, should be 0x%lx)"),
file_hdr.c_name, crc, file_hdr.c_chksum);
}
/* Debian hack: -v and -V now work with --only-verify-crc.
diff --git a/src/copyout.c b/src/copyout.c
index 23da993de584..0ab294ec64b0 100644
--- a/src/copyout.c
+++ b/src/copyout.c
@@ -1,5 +1,6 @@
/* copyout.c - create a cpio archive
- Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004 Free Software Foundation, Inc.
+ 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
@@ -11,9 +12,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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>
@@ -26,14 +28,15 @@
#include "extern.h"
#include "defer.h"
#include <rmt.h>
+#include <paxlib.h>
/* Read FILE_SIZE bytes of FILE_NAME from IN_FILE_DES and
compute and return a checksum for them. */
-static unsigned long
+static unsigned int
read_for_checksum (int in_file_des, int file_size, char *file_name)
{
- unsigned long crc;
+ unsigned int crc;
char buf[BUFSIZ];
int bytes_left;
int bytes_read;
@@ -65,13 +68,8 @@ read_for_checksum (int in_file_des, int file_size, char *file_name)
static void
tape_clear_rest_of_block (int out_file_des)
{
- while (output_size < io_block_size)
- {
- if ((io_block_size - output_size) > 512)
- tape_buffered_write (zeros_512, out_file_des, 512);
- else
- tape_buffered_write (zeros_512, out_file_des, io_block_size - output_size);
- }
+ 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)
@@ -80,7 +78,7 @@ tape_clear_rest_of_block (int out_file_des)
static void
tape_pad_output (int out_file_des, int offset)
{
- int pad;
+ size_t pad;
if (archive_format == arf_newascii || archive_format == arf_crcascii)
pad = (4 - (offset % 4)) % 4;
@@ -92,7 +90,7 @@ tape_pad_output (int out_file_des, int offset)
pad = 0;
if (pad != 0)
- tape_buffered_write (zeros_512, out_file_des, pad);
+ write_nuls_to_file (pad, out_file_des, tape_buffered_write);
}
@@ -109,7 +107,7 @@ struct deferment *deferouts = NULL;
already been defered. */
static int
-count_defered_links_to_dev_ino (struct new_cpio_header *file_hdr)
+count_defered_links_to_dev_ino (struct cpio_file_stat *file_hdr)
{
struct deferment *d;
int ino;
@@ -133,7 +131,7 @@ count_defered_links_to_dev_ino (struct new_cpio_header *file_hdr)
we already seen and defered all of the other links? */
static int
-last_link (struct new_cpio_header *file_hdr)
+last_link (struct cpio_file_stat *file_hdr)
{
int other_files_sofar;
@@ -150,7 +148,7 @@ last_link (struct new_cpio_header *file_hdr)
list. */
static void
-add_link_defer (struct new_cpio_header *file_hdr)
+add_link_defer (struct cpio_file_stat *file_hdr)
{
struct deferment *d;
d = create_deferment (file_hdr);
@@ -159,13 +157,13 @@ add_link_defer (struct new_cpio_header *file_hdr)
}
/* We are about to put a file into a newc or crc archive that is
- multiply linked. We have already seen and defered all of the
+ 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 new_cpio_header *file_hdr, int out_des)
+writeout_other_defers (struct cpio_file_stat *file_hdr, int out_des)
{
struct deferment *d;
struct deferment *d_prev;
@@ -207,13 +205,10 @@ writeout_other_defers (struct new_cpio_header *file_hdr, int out_des)
for writeout_final_defers() to call. */
static void
-writeout_defered_file (struct new_cpio_header *header, int out_file_des)
+writeout_defered_file (struct cpio_file_stat *header, int out_file_des)
{
int in_file_des;
- struct new_cpio_header file_hdr;
- struct utimbuf times; /* For setting file times. */
- /* Initialize this in case it has members we don't know to set. */
- bzero (&times, sizeof (struct utimbuf));
+ struct cpio_file_stat file_hdr;
file_hdr = *header;
@@ -222,7 +217,7 @@ writeout_defered_file (struct new_cpio_header *header, int out_file_des)
O_RDONLY | O_BINARY, 0);
if (in_file_des < 0)
{
- error (0, errno, "%s", header->c_name);
+ open_error (header->c_name);
return;
}
@@ -231,8 +226,10 @@ writeout_defered_file (struct new_cpio_header *header, int out_file_des)
file_hdr.c_filesize,
header->c_name);
- write_out_header (&file_hdr, out_file_des);
- copy_files_disk_to_tape (in_file_des, out_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)
@@ -241,21 +238,11 @@ writeout_defered_file (struct new_cpio_header *header, int out_file_des)
tape_pad_output (out_file_des, file_hdr.c_filesize);
- if (close (in_file_des) < 0)
- error (0, errno, "%s", header->c_name);
if (reset_time_flag)
- {
- times.actime = file_hdr.c_mtime;
- times.modtime = file_hdr.c_mtime;
- /* Debian hack: Silently ignore EROFS because reading the file
- won't have upset its timestamp if it's on a read-only
- filesystem. This has been submitted as a suggestion to
- "bug-gnu-utils@prep.ai.mit.edu". -BEM */
- if (utime (file_hdr.c_name, &times) < 0
- && errno != EROFS)
- error (0, errno, "%s", file_hdr.c_name);
- }
- return;
+ 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
@@ -279,7 +266,7 @@ writeout_final_defers (int out_des)
}
else
{
- struct new_cpio_header file_hdr;
+ struct cpio_file_stat file_hdr;
file_hdr = d->header;
file_hdr.c_filesize = 0;
write_out_header (&file_hdr, out_des);
@@ -288,156 +275,319 @@ writeout_final_defers (int out_des)
}
}
-
-/* Write out header FILE_HDR, including the file name, to file
- descriptor OUT_DES. */
+/* 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
-write_out_header (struct new_cpio_header *file_hdr, int out_des)
+to_ascii_or_warn (char *where, uintmax_t n, size_t digits,
+ unsigned logbase,
+ const char *filename, const char *fieldname)
{
- if (archive_format == arf_newascii || archive_format == arf_crcascii)
+ 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))
{
- char ascii_header[112];
- char *magic_string;
-
- if (archive_format == arf_crcascii)
- magic_string = "070702";
- else
- magic_string = "070701";
- sprintf (ascii_header,
- "%6s%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx",
- magic_string,
- 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);
- tape_buffered_write (ascii_header, out_des, 110L);
-
- /* 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 + 110);
+ field_width_error (filename, fieldname);
+ return 1;
}
- else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
- {
- char ascii_header[78];
- dev_t dev;
- dev_t rdev;
+ return 0;
+}
- if (archive_format == arf_oldascii)
- {
- dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
- rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
- }
- else
- {
- /* 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:
+
+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:
+ case CP_IFSOCK:
#endif
#ifdef CP_IFIFO
- case CP_IFIFO:
+ case CP_IFIFO:
#endif
- file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
- file_hdr->c_rdev_min);
- rdev = 1;
- break;
- default:
- dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
- rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
- break;
- }
- }
-
- if ((warn_option & CPIO_WARN_TRUNCATE) && (file_hdr->c_ino >> 16) != 0)
- error (0, 0, _("%s: truncating inode number"), file_hdr->c_name);
-
- /* Debian hack: The type of dev_t has changed in glibc. Fixed output
- to ensure that a long int is passed to sprintf. This has been
- reported to "bug-gnu-utils@prep.ai.mit.edu". (1998/5/26) -BEM */
- sprintf (ascii_header,
- "%06ho%06lo%06lo%06lo%06lo%06lo%06lo%06lo%011lo%06lo%011lo",
- file_hdr->c_magic & 0xFFFF, (long) dev & 0xFFFF,
- file_hdr->c_ino & 0xFFFF, file_hdr->c_mode & 0xFFFF,
- file_hdr->c_uid & 0xFFFF, file_hdr->c_gid & 0xFFFF,
- file_hdr->c_nlink & 0xFFFF, (long) rdev & 0xFFFF,
- file_hdr->c_mtime, file_hdr->c_namesize & 0xFFFF,
- file_hdr->c_filesize);
- tape_buffered_write (ascii_header, out_des, 76L);
-
- /* Write file name to output. */
- tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
+ 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;
}
- else if (archive_format == arf_tar || archive_format == arf_ustar)
+}
+
+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)
{
- write_out_tar_header (file_hdr, out_des);
+ field_width_error (file_hdr->c_name, _("name size"));
+ return 1;
}
- else
+
+ 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)
{
- struct old_cpio_header short_hdr;
+ field_width_error (file_hdr->c_name, _("file size"));
+ return 1;
+ }
+
+ /* Output the file header. */
+ tape_buffered_write ((char *) &short_hdr, out_des, 26);
- short_hdr.c_magic = 070707;
- short_hdr.c_dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
+ /* Write file name to output. */
+ tape_buffered_write (file_hdr->c_name, out_des, file_hdr->c_namesize);
- if ((warn_option & CPIO_WARN_TRUNCATE) && (file_hdr->c_ino >> 16) != 0)
- error (0, 0, _("%s: truncating inode number"), file_hdr->c_name);
+ tape_pad_output (out_des, file_hdr->c_namesize + 26);
+ return 0;
+}
- short_hdr.c_ino = file_hdr->c_ino & 0xFFFF;
- short_hdr.c_mode = file_hdr->c_mode & 0xFFFF;
- short_hdr.c_uid = file_hdr->c_uid & 0xFFFF;
- short_hdr.c_gid = file_hdr->c_gid & 0xFFFF;
- short_hdr.c_nlink = file_hdr->c_nlink & 0xFFFF;
- if (archive_format != arf_hpbinary)
- short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
- else
+
+/* 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))
{
- switch (file_hdr->c_mode & CP_IFMT)
- {
- /* 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. */
- 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);
- short_hdr.c_rdev = makedev (0, 1);
- break;
- default:
- short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj,
- file_hdr->c_rdev_min);
- break;
- }
+ error (0, 0, _("%s: file name too long"), file_hdr->c_name);
+ return 1;
}
- short_hdr.c_mtimes[0] = file_hdr->c_mtime >> 16;
- short_hdr.c_mtimes[1] = file_hdr->c_mtime & 0xFFFF;
+ write_out_tar_header (file_hdr, out_des); /* FIXME: No error checking */
+ return 0;
- short_hdr.c_namesize = file_hdr->c_namesize & 0xFFFF;
+ case arf_binary:
+ return write_out_binary_header (makedev (file_hdr->c_rdev_maj,
+ file_hdr->c_rdev_min),
+ file_hdr, out_des);
- short_hdr.c_filesizes[0] = file_hdr->c_filesize >> 16;
- short_hdr.c_filesizes[1] = file_hdr->c_filesize & 0xFFFF;
+ 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);
- /* Output the file header. */
- tape_buffered_write ((char *) &short_hdr, out_des, 26L);
-
- /* 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 + 26);
+ 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. */
@@ -447,17 +597,14 @@ process_copy_out ()
{
int res; /* Result of functions. */
dynamic_string input_name; /* Name of file read from stdin. */
- struct utimbuf times; /* For resetting file times after copy. */
struct stat file_stat; /* Stat record for file. */
- struct new_cpio_header file_hdr; /* Output header information. */
+ struct cpio_file_stat file_hdr; /* Output header information. */
int in_file_des; /* Source file descriptor. */
int out_file_des; /* Output file descriptor. */
- char *p;
+ char *orig_file_name = NULL;
/* Initialize the copy out. */
ds_init (&input_name, 128);
- /* Initialize this in case it has members we don't know to set. */
- bzero (&times, sizeof (struct utimbuf));
file_hdr.c_magic = 070707;
/* Check whether the output file might be a tape. */
@@ -497,55 +644,11 @@ process_copy_out ()
/* Process next file. */
if ((*xstat) (input_name.ds_string, &file_stat) < 0)
- error (0, errno, "%s", input_name.ds_string);
+ stat_error (input_name.ds_string);
else
{
/* Set values in output header. */
- file_hdr.c_dev_maj = major (file_stat.st_dev);
- file_hdr.c_dev_min = minor (file_stat.st_dev);
- file_hdr.c_ino = file_stat.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. */
- file_hdr.c_mode = (file_stat.st_mode & 07777);
- if (S_ISREG (file_stat.st_mode))
- file_hdr.c_mode |= CP_IFREG;
- else if (S_ISDIR (file_stat.st_mode))
- file_hdr.c_mode |= CP_IFDIR;
-#ifdef S_ISBLK
- else if (S_ISBLK (file_stat.st_mode))
- file_hdr.c_mode |= CP_IFBLK;
-#endif
-#ifdef S_ISCHR
- else if (S_ISCHR (file_stat.st_mode))
- file_hdr.c_mode |= CP_IFCHR;
-#endif
-#ifdef S_ISFIFO
- else if (S_ISFIFO (file_stat.st_mode))
- file_hdr.c_mode |= CP_IFIFO;
-#endif
-#ifdef S_ISLNK
- else if (S_ISLNK (file_stat.st_mode))
- file_hdr.c_mode |= CP_IFLNK;
-#endif
-#ifdef S_ISSOCK
- else if (S_ISSOCK (file_stat.st_mode))
- file_hdr.c_mode |= CP_IFSOCK;
-#endif
-#ifdef S_ISNWK
- else if (S_ISNWK (file_stat.st_mode))
- file_hdr.c_mode |= CP_IFNWK;
-#endif
- file_hdr.c_uid = file_stat.st_uid;
- file_hdr.c_gid = file_stat.st_gid;
- file_hdr.c_nlink = file_stat.st_nlink;
- file_hdr.c_rdev_maj = major (file_stat.st_rdev);
- file_hdr.c_rdev_min = minor (file_stat.st_rdev);
- file_hdr.c_mtime = file_stat.st_mtime;
- file_hdr.c_filesize = file_stat.st_size;
- file_hdr.c_chksum = 0;
- file_hdr.c_tar_linkname = NULL;
+ stat_to_cpio (&file_hdr, &file_stat);
if (archive_format == arf_tar || archive_format == arf_ustar)
{
@@ -562,17 +665,12 @@ process_copy_out ()
}
}
- /* Strip leading `./' from the filename. */
- p = input_name.ds_string;
- while (*p == '.' && *(p + 1) == '/')
- {
- ++p;
- while (*p == '/')
- ++p;
- }
+ assign_string (&orig_file_name, input_name.ds_string);
+ cpio_safer_name_suffix (input_name.ds_string, false,
+ !no_abs_paths_flag, true);
#ifndef HPUX_CDF
- file_hdr.c_name = p;
- file_hdr.c_namesize = strlen (p) + 1;
+ 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) )
{
@@ -581,7 +679,7 @@ process_copy_out ()
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 (p);
+ file_hdr.c_name = add_cdf_double_slashes (input_name.ds_string);
file_hdr.c_namesize = strlen (file_hdr.c_name) + 1;
}
else
@@ -589,18 +687,11 @@ process_copy_out ()
/* 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 = p;
- file_hdr.c_namesize = strlen (p) + 1;
+ file_hdr.c_name = input_name.ds_string;
+ file_hdr.c_namesize = strlen (input_name.ds_string) + 1;
}
#endif
- if ((archive_format == arf_tar || archive_format == arf_ustar)
- && is_tar_filename_too_long (file_hdr.c_name))
- {
- error (0, 0, _("%s: file name too long"),
- file_hdr.c_name);
- continue;
- }
-
+
/* Copy the named file to the output. */
switch (file_hdr.c_mode & CP_IFMT)
{
@@ -613,7 +704,8 @@ process_copy_out ()
file_hdr.c_dev_min)))
{
file_hdr.c_tar_linkname = otherfile;
- write_out_header (&file_hdr, out_file_des);
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
break;
}
}
@@ -630,50 +722,45 @@ process_copy_out ()
break;
}
}
- in_file_des = open (input_name.ds_string,
+ in_file_des = open (orig_file_name,
O_RDONLY | O_BINARY, 0);
if (in_file_des < 0)
{
- error (0, errno, "%s", input_name.ds_string);
+ 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,
- input_name.ds_string);
-
- write_out_header (&file_hdr, out_file_des);
- copy_files_disk_to_tape (in_file_des, out_file_des, file_hdr.c_filesize, input_name.ds_string);
- warn_if_file_changed(input_name.ds_string, 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, file_hdr.c_name, file_hdr.c_dev_maj,
+ 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 (close (in_file_des) < 0)
- error (0, errno, "%s", input_name.ds_string);
if (reset_time_flag)
- {
- times.actime = file_stat.st_atime;
- times.modtime = file_stat.st_mtime;
- /* Debian hack: Silently ignore EROFS because
- reading the file won't have upset its timestamp
- if it's on a read-only filesystem. This has been
- submitted as a suggestion to
- "bug-gnu-utils@prep.ai.mit.edu". -BEM */
- if (utime (file_hdr.c_name, &times) < 0
- && errno != EROFS)
- error (0, errno, "%s", file_hdr.c_name);
- }
+ 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;
- write_out_header (&file_hdr, out_file_des);
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
break;
case CP_IFCHR:
@@ -687,7 +774,7 @@ process_copy_out ()
if (archive_format == arf_tar)
{
error (0, 0, _("%s not dumped: not a regular file"),
- file_hdr.c_name);
+ orig_file_name);
continue;
}
else if (archive_format == arf_ustar)
@@ -702,14 +789,16 @@ process_copy_out ()
file_hdr.c_mode = (file_stat.st_mode & 07777);
file_hdr.c_mode |= CP_IFREG;
file_hdr.c_tar_linkname = otherfile;
- write_out_header (&file_hdr, out_file_des);
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
break;
}
- add_inode (file_hdr.c_ino, file_hdr.c_name,
+ add_inode (file_hdr.c_ino, orig_file_name,
file_hdr.c_dev_maj, file_hdr.c_dev_min);
}
file_hdr.c_filesize = 0;
- write_out_header (&file_hdr, out_file_des);
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
break;
#ifdef CP_IFLNK
@@ -718,14 +807,18 @@ process_copy_out ()
char *link_name = (char *) xmalloc (file_stat.st_size + 1);
int link_size;
- link_size = readlink (input_name.ds_string, link_name,
+ link_size = readlink (orig_file_name, link_name,
file_stat.st_size);
if (link_size < 0)
{
- error (0, errno, "%s", input_name.ds_string);
+ readlink_warn (orig_file_name);
free (link_name);
continue;
}
+ link_name[link_size] = 0;
+ cpio_safer_name_suffix (link_name, false,
+ !no_abs_paths_flag, true);
+ link_size = strlen (link_name);
file_hdr.c_filesize = link_size;
if (archive_format == arf_tar || archive_format == arf_ustar)
{
@@ -738,12 +831,14 @@ process_copy_out ()
{
link_name[link_size] = '\0';
file_hdr.c_tar_linkname = link_name;
- write_out_header (&file_hdr, out_file_des);
+ if (write_out_header (&file_hdr, out_file_des))
+ continue;
}
}
else
{
- write_out_header (&file_hdr, out_file_des);
+ 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);
}
@@ -753,16 +848,18 @@ process_copy_out ()
#endif
default:
- error (0, 0, _("%s: unknown file type"), input_name.ds_string);
+ error (0, 0, _("%s: unknown file type"), orig_file_name);
}
-
+
if (verbose_flag)
- fprintf (stderr, "%s\n", input_name.ds_string);
+ 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;
@@ -779,14 +876,11 @@ process_copy_out ()
file_hdr.c_filesize = 0;
file_hdr.c_namesize = 11;
- file_hdr.c_name = "TRAILER!!!";
+ 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
- {
- tape_buffered_write (zeros_512, out_file_des, 512);
- tape_buffered_write (zeros_512, out_file_des, 512);
- }
+ write_nuls_to_file (1024, out_file_des, tape_buffered_write);
/* Fill up the output block. */
tape_clear_rest_of_block (out_file_des);
diff --git a/src/copypass.c b/src/copypass.c
index db6f327159d8..78576c6231cd 100644
--- a/src/copypass.c
+++ b/src/copypass.c
@@ -1,5 +1,6 @@
/* copypass.c - cpio copy pass sub-function.
- Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004 Free Software Foundation, Inc.
+ 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
@@ -11,9 +12,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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>
@@ -24,11 +26,23 @@
#include "cpiohdr.h"
#include "dstring.h"
#include "extern.h"
+#include "paxlib.h"
#ifndef HAVE_LCHOWN
-#define lchown chown
+# define lchown chown
#endif
+
+/* A wrapper around set_perms using another set of arguments */
+static void
+set_copypass_perms (int fd, const char *name, struct stat *st)
+{
+ struct cpio_file_stat header;
+ header.c_name = name;
+ stat_to_cpio (&header, st);
+ set_perms (fd, &header);
+}
+
/* Copy files listed on the standard input into directory `directory_name'.
If `link_flag', link instead of copying. */
@@ -40,7 +54,6 @@ process_copy_pass ()
int dirname_len; /* Length of `directory_name'. */
int res; /* Result of functions. */
char *slash; /* For moving past slashes in input name. */
- struct utimbuf times; /* For resetting file times after copy. */
struct stat in_file_stat; /* Stat record for input file. */
struct stat out_file_stat; /* Stat record for output file. */
int in_file_des; /* Input file descriptor. */
@@ -51,6 +64,9 @@ process_copy_pass ()
int cdf_char;
#endif
+ umask (0); /* Reset umask to preserve modes of
+ created files */
+
/* Initialize the copy pass. */
dirname_len = strlen (directory_name);
ds_init (&input_name, 128);
@@ -58,8 +74,6 @@ process_copy_pass ()
strcpy (output_name.ds_string, directory_name);
output_name.ds_string[dirname_len] = '/';
output_is_seekable = true;
- /* Initialize this in case it has members we don't know to set. */
- bzero (&times, sizeof (struct utimbuf));
/* Copy files with names read from stdin. */
while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
@@ -82,7 +96,7 @@ process_copy_pass ()
if ((*xstat) (input_name.ds_string, &in_file_stat) < 0)
{
- error (0, errno, "%s", input_name.ds_string);
+ stat_error (input_name.ds_string);
continue;
}
@@ -150,7 +164,7 @@ process_copy_pass ()
O_RDONLY | O_BINARY, 0);
if (in_file_des < 0)
{
- error (0, errno, "%s", input_name.ds_string);
+ open_error (input_name.ds_string);
continue;
}
out_file_des = open (output_name.ds_string,
@@ -163,7 +177,7 @@ process_copy_pass ()
}
if (out_file_des < 0)
{
- error (0, errno, "%s", output_name.ds_string);
+ open_error (output_name.ds_string);
close (in_file_des);
continue;
}
@@ -179,43 +193,28 @@ process_copy_pass ()
write (out_file_des, "", 1);
delayed_seek_count = 0;
}
+
+ set_copypass_perms (out_file_des,
+ output_name.ds_string, &in_file_stat);
+
+ if (reset_time_flag)
+ {
+ set_file_times (in_file_des,
+ input_name.ds_string,
+ in_file_stat.st_atime,
+ in_file_stat.st_mtime);
+ set_file_times (out_file_des,
+ output_name.ds_string,
+ in_file_stat.st_atime,
+ in_file_stat.st_mtime);
+ }
+
if (close (in_file_des) < 0)
- error (0, errno, "%s", input_name.ds_string);
+ close_error (input_name.ds_string);
+
if (close (out_file_des) < 0)
- error (0, errno, "%s", output_name.ds_string);
-
- /* Set the attributes of the new file. */
- if (!no_chown_flag)
- if ((chown (output_name.ds_string,
- set_owner_flag ? set_owner : in_file_stat.st_uid,
- set_group_flag ? set_group : in_file_stat.st_gid) < 0)
- && errno != EPERM)
- error (0, errno, "%s", output_name.ds_string);
- /* chown may have turned off some permissions we wanted. */
- if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
- error (0, errno, "%s", output_name.ds_string);
- if (reset_time_flag)
- {
- times.actime = in_file_stat.st_atime;
- times.modtime = in_file_stat.st_mtime;
- /* Debian hack: Silently ignore EROFS because
- reading the file won't have upset its timestamp
- if it's on a read-only filesystem. This has been
- submitted as a suggestion to
- "bug-gnu-utils@prep.ai.mit.edu". -BEM */
- if (utime (input_name.ds_string, &times) < 0
- && errno != EROFS)
- error (0, errno, "%s", input_name.ds_string);
- if (utime (output_name.ds_string, &times) < 0
- && errno != EROFS)
- error (0, errno, "%s", output_name.ds_string);
- }
- if (retain_time_flag)
- {
- times.actime = times.modtime = in_file_stat.st_mtime;
- if (utime (output_name.ds_string, &times) < 0)
- error (0, errno, "%s", output_name.ds_string);
- }
+ close_error (output_name.ds_string);
+
warn_if_file_changed(input_name.ds_string, in_file_stat.st_size,
in_file_stat.st_mtime);
}
@@ -261,31 +260,11 @@ process_copy_pass ()
(lstat (output_name.ds_string, &out_file_stat) != 0) ||
!(S_ISDIR (out_file_stat.st_mode) ) )
{
- error (0, errno, "%s", output_name.ds_string);
+ stat_error (output_name.ds_string);
continue;
}
}
- if (!no_chown_flag)
- if ((chown (output_name.ds_string,
- set_owner_flag ? set_owner : in_file_stat.st_uid,
- set_group_flag ? set_group : in_file_stat.st_gid) < 0)
- && errno != EPERM)
- error (0, errno, "%s", output_name.ds_string);
- /* chown may have turned off some permissions we wanted. */
- if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
- error (0, errno, "%s", output_name.ds_string);
-#ifdef HPUX_CDF
- if (cdf_flag)
- /* Once we "hide" the directory with the chmod(),
- we have to refer to it using name+ isntead of name. */
- output_name.ds_string [cdf_char] = '+';
-#endif
- if (retain_time_flag)
- {
- times.actime = times.modtime = in_file_stat.st_mtime;
- if (utime (output_name.ds_string, &times) < 0)
- error (0, errno, "%s", output_name.ds_string);
- }
+ set_copypass_perms (-1, output_name.ds_string, &in_file_stat);
}
else if (S_ISCHR (in_file_stat.st_mode) ||
S_ISBLK (in_file_stat.st_mode) ||
@@ -321,24 +300,10 @@ process_copy_pass ()
}
if (res < 0)
{
- error (0, errno, "%s", output_name.ds_string);
+ mknod_error (output_name.ds_string);
continue;
}
- if (!no_chown_flag)
- if ((chown (output_name.ds_string,
- set_owner_flag ? set_owner : in_file_stat.st_uid,
- set_group_flag ? set_group : in_file_stat.st_gid) < 0)
- && errno != EPERM)
- error (0, errno, "%s", output_name.ds_string);
- /* chown may have turned off some permissions we wanted. */
- if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
- error (0, errno, "%s", output_name.ds_string);
- if (retain_time_flag)
- {
- times.actime = times.modtime = in_file_stat.st_mtime;
- if (utime (output_name.ds_string, &times) < 0)
- error (0, errno, "%s", output_name.ds_string);
- }
+ set_copypass_perms (-1, output_name.ds_string, &in_file_stat);
}
}
@@ -353,7 +318,7 @@ process_copy_pass ()
in_file_stat.st_size);
if (link_size < 0)
{
- error (0, errno, "%s", input_name.ds_string);
+ readlink_error (input_name.ds_string);
free (link_name);
continue;
}
@@ -369,18 +334,20 @@ process_copy_pass ()
}
if (res < 0)
{
- error (0, errno, "%s", output_name.ds_string);
+ symlink_error (output_name.ds_string, link_name);
free (link_name);
continue;
}
/* Set the attributes of the new link. */
if (!no_chown_flag)
- if ((lchown (output_name.ds_string,
- set_owner_flag ? set_owner : in_file_stat.st_uid,
- set_group_flag ? set_group : in_file_stat.st_gid) < 0)
- && errno != EPERM)
- error (0, errno, "%s", output_name.ds_string);
+ {
+ uid_t uid = set_owner_flag ? set_owner : in_file_stat.st_uid;
+ gid_t gid = set_group_flag ? set_group : in_file_stat.st_gid;
+ if ((lchown (output_name.ds_string, uid, gid) < 0)
+ && errno != EPERM)
+ chown_error_details (output_name.ds_string, uid, gid);
+ }
free (link_name);
}
#endif
diff --git a/src/cpio.h b/src/cpio.h
index 3861ab0d668f..34d1cf10e408 100644
--- a/src/cpio.h
+++ b/src/cpio.h
@@ -1,5 +1,5 @@
/* Extended cpio format from POSIX.1.
- Copyright (C) 1992 Free Software Foundation, Inc.
+ Copyright (C) 1992, 2005 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
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
#ifndef _CPIO_H
@@ -25,6 +26,8 @@
and variable length file data.
A header for a filename "TRAILER!!!" indicates the end of the archive. */
+#define CPIO_TRAILER_NAME "TRAILER!!!"
+
/* All the fields in the header are ISO 646 (approximately ASCII) strings
of octal numbers, left padded, not NUL terminated.
diff --git a/src/cpiohdr.h b/src/cpiohdr.h
index c3943b464e16..503563f84406 100644
--- a/src/cpiohdr.h
+++ b/src/cpiohdr.h
@@ -1,5 +1,5 @@
/* Extended cpio header from POSIX.1.
- Copyright (C) 1992 Free Software Foundation, Inc.
+ Copyright (C) 1992, 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
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
#ifndef _CPIOHDR_H
@@ -34,9 +35,21 @@ struct old_cpio_header
unsigned short c_mtimes[2];
unsigned short c_namesize;
unsigned short c_filesizes[2];
- unsigned long c_mtime; /* Long-aligned copy of `c_mtimes'. */
- unsigned long c_filesize; /* Long-aligned copy of `c_filesizes'. */
- char *c_name;
+};
+
+struct old_ascii_header
+{
+ char c_magic[6];
+ char c_dev[6];
+ char c_ino[6];
+ char c_mode[6];
+ char c_uid[6];
+ char c_gid[6];
+ char c_nlink[6];
+ char c_rdev[6];
+ char c_mtime[11];
+ char c_namesize[6];
+ char c_filesize[11];
};
/* "New" portable format and CRC format:
@@ -47,44 +60,47 @@ struct old_cpio_header
A header for a filename "TRAILER!!!" indicates the end of the archive. */
/* All the fields in the header are ISO 646 (approximately ASCII) strings
- of hexadecimal numbers, left padded, not NUL terminated.
+ of hexadecimal numbers, left padded, not NUL terminated: */
- Field Name Length in Bytes Notes
- c_magic 6 "070701" for "new" portable format
- "070702" for CRC format
- c_ino 8
- c_mode 8
- c_uid 8
- c_gid 8
- c_nlink 8
- c_mtime 8
- c_filesize 8 must be 0 for FIFOs and directories
- c_maj 8
- c_min 8
- c_rmaj 8 only valid for chr and blk special files
- c_rmin 8 only valid for chr and blk special files
- c_namesize 8 count includes terminating NUL in pathname
- c_chksum 8 0 for "new" portable format; for CRC format
- the sum of all the bytes in the file */
+struct new_ascii_header
+{
+ char c_magic[6]; /* "070701" for "new" portable format
+ "070702" for CRC format */
+ char c_ino[8];
+ char c_mode[8];
+ char c_uid[8];
+ char c_gid[8];
+ char c_nlink[8];
+ char c_mtime[8];
+ char c_filesize[8]; /* must be 0 for FIFOs and directories */
+ char c_dev_maj[8];
+ char c_dev_min[8];
+ char c_rdev_maj[8]; /* only valid for chr and blk special files */
+ char c_rdev_min[8]; /* only valid for chr and blk special files */
+ char c_namesize[8]; /* count includes terminating NUL in pathname */
+ char c_chksum[8]; /* 0 for "new" portable format; for CRC format
+ the sum of all the bytes in the file */
+};
-struct new_cpio_header
+struct cpio_file_stat /* Internal representation of a CPIO header */
{
unsigned short c_magic;
- unsigned long c_ino;
- unsigned long c_mode;
- unsigned long c_uid;
- unsigned long c_gid;
- unsigned long c_nlink;
- unsigned long c_mtime;
- unsigned long c_filesize;
+ ino_t c_ino;
+ mode_t c_mode;
+ uid_t c_uid;
+ gid_t c_gid;
+ size_t c_nlink;
+ time_t c_mtime;
+ off_t c_filesize;
long c_dev_maj;
long c_dev_min;
long c_rdev_maj;
long c_rdev_min;
- unsigned long c_namesize;
+ size_t c_namesize;
unsigned long c_chksum;
char *c_name;
char *c_tar_linkname;
};
+
#endif /* cpiohdr.h */
diff --git a/src/defer.c b/src/defer.c
index cb6fb40c1135..83e15dd7c3d2 100644
--- a/src/defer.c
+++ b/src/defer.c
@@ -1,5 +1,5 @@
/* defer.c - handle "defered" links in newc and crc archives
- Copyright (C) 1993,2003,2004 Free Software Foundation, Inc.
+ Copyright (C) 1993, 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
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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>
@@ -24,7 +25,7 @@
#include "defer.h"
struct deferment *
-create_deferment (struct new_cpio_header *file_hdr)
+create_deferment (struct cpio_file_stat *file_hdr)
{
struct deferment *d;
d = (struct deferment *) xmalloc (sizeof (struct deferment) );
diff --git a/src/defer.h b/src/defer.h
index 657257f353df..00aafecc01b6 100644
--- a/src/defer.h
+++ b/src/defer.h
@@ -1,5 +1,5 @@
/* defer.h
- Copyright (C) 1993, 2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1993, 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
@@ -11,15 +11,16 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
struct deferment
{
struct deferment *next;
- struct new_cpio_header header;
+ struct cpio_file_stat header;
};
-struct deferment *create_deferment P_((struct new_cpio_header *file_hdr));
-void free_deferment P_((struct deferment *d));
+struct deferment *create_deferment (struct cpio_file_stat *file_hdr);
+void free_deferment (struct deferment *d);
diff --git a/src/dstring.c b/src/dstring.c
index e3cdae764a91..aefeab88ce87 100644
--- a/src/dstring.c
+++ b/src/dstring.c
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
#if defined(HAVE_CONFIG_H)
# include <config.h>
@@ -27,13 +28,8 @@
#endif
#include "dstring.h"
-#if __STDC__
-# define P_(s) s
-#else
-# define P_(s) ()
-#endif
-char *xmalloc P_((unsigned n));
-char *xrealloc P_((char *p, unsigned n));
+char *xmalloc (unsigned n);
+char *xrealloc (char *p, unsigned n);
/* Initialiaze dynamic string STRING with space for SIZE characters. */
diff --git a/src/dstring.h b/src/dstring.h
index 1615518c4420..3628b99b3f66 100644
--- a/src/dstring.h
+++ b/src/dstring.h
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
#ifndef NULL
#define NULL 0
diff --git a/src/extern.h b/src/extern.h
index e6e3d6e28e94..2bed3ce8f0be 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -1,5 +1,5 @@
/* extern.h - External declarations for cpio. Requires system.h.
- Copyright (C) 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 2001, 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
@@ -11,15 +11,21 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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 "paxlib.h"
+#include "quotearg.h"
+#include "quote.h"
enum archive_format
{
arf_unknown, arf_binary, arf_oldascii, arf_newascii, arf_crcascii,
arf_tar, arf_ustar, arf_hpoldascii, arf_hpbinary
};
+
extern enum archive_format archive_format;
extern int reset_time_flag;
extern int io_block_size;
@@ -66,7 +72,7 @@ extern char *new_media_message_after_number;
extern int archive_des;
extern char *archive_name;
extern char *rsh_command_option;
-extern unsigned long crc;
+extern unsigned int crc;
extern int delayed_seek_count;
#ifdef DEBUG_CPIO
extern int debug_flag;
@@ -81,7 +87,6 @@ extern long long input_bytes, output_bytes;
#else
extern long input_bytes, output_bytes;
#endif
-extern char zeros_512[];
extern char *directory_name;
extern char **save_patterns;
extern int num_patterns;
@@ -94,38 +99,35 @@ extern char *program_name;
extern int (*xstat) ();
extern void (*copy_function) ();
-#if defined PROTOTYPES || (defined __STDC__ && __STDC__)
-# define P_(s) s
-#else
-# define P_(s) ()
-#endif
/* copyin.c */
-void warn_junk_bytes P_((long bytes_skipped));
-void read_in_header P_((struct new_cpio_header *file_hdr, int in_des));
-void read_in_old_ascii P_((struct new_cpio_header *file_hdr, int in_des));
-void read_in_new_ascii P_((struct new_cpio_header *file_hdr, int in_des));
-void read_in_binary P_((struct new_cpio_header *file_hdr, int in_des));
-void swab_array P_((char *arg, int count));
-void process_copy_in P_((void));
-void long_format P_((struct new_cpio_header *file_hdr, char *link_name));
-void print_name_with_quoting P_((char *p));
+void warn_junk_bytes (long bytes_skipped);
+/* FIXME: make read_* static in copyin.c */
+void read_in_header (struct cpio_file_stat *file_hdr, int in_des);
+void read_in_old_ascii (struct cpio_file_stat *file_hdr, int in_des);
+void read_in_new_ascii (struct cpio_file_stat *file_hdr, int in_des);
+void read_in_binary (struct cpio_file_stat *file_hdr,
+ struct old_cpio_header *short_hdr, int in_des);
+void swab_array (char *arg, int count);
+void process_copy_in (void);
+void long_format (struct cpio_file_stat *file_hdr, char *link_name);
+void print_name_with_quoting (char *p);
/* copyout.c */
-void write_out_header P_((struct new_cpio_header *file_hdr, int out_des));
-void process_copy_out P_((void));
+int write_out_header (struct cpio_file_stat *file_hdr, int out_des);
+void process_copy_out (void);
/* copypass.c */
-void process_copy_pass P_((void));
-int link_to_maj_min_ino P_((char *file_name, int st_dev_maj,
- int st_dev_min, int st_ino));
-int link_to_name P_((char *link_name, char *link_target));
+void process_copy_pass (void);
+int link_to_maj_min_ino (char *file_name, int st_dev_maj,
+ int st_dev_min, int st_ino);
+int link_to_name (char *link_name, char *link_target);
/* dirname.c */
-char *dirname P_((char *path));
+char *dirname (char *path);
/* filemode.c */
-void mode_string P_((unsigned int mode, char *str));
+void mode_string (unsigned int mode, char *str);
/* idcache.c */
#ifndef __MSDOS__
@@ -136,61 +138,63 @@ gid_t *getgidbyname ();
#endif
/* main.c */
-void process_args P_((int argc, char *argv[]));
-void initialize_buffers P_((void));
+void process_args (int argc, char *argv[]);
+void initialize_buffers (void);
/* makepath.c */
-int make_path P_((char *argpath, int mode, int parent_mode,
- uid_t owner, gid_t group, char *verbose_fmt_string));
+int make_path (char *argpath, int mode, int parent_mode,
+ uid_t owner, gid_t group, char *verbose_fmt_string);
/* tar.c */
-void write_out_tar_header P_((struct new_cpio_header *file_hdr, int out_des));
-int null_block P_((long *block, int size));
-void read_in_tar_header P_((struct new_cpio_header *file_hdr, int in_des));
-int otoa P_((char *s, unsigned long *n));
-int is_tar_header P_((char *buf));
-int is_tar_filename_too_long P_((char *name));
+void write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des);
+int null_block (long *block, int size);
+void read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des);
+int otoa (char *s, unsigned long *n);
+int is_tar_header (char *buf);
+int is_tar_filename_too_long (char *name);
/* userspec.c */
#ifndef __MSDOS__
-char *parse_user_spec P_((char *name, uid_t *uid, gid_t *gid,
- char **username, char **groupname));
+char *parse_user_spec (char *name, uid_t *uid, gid_t *gid,
+ char **username, char **groupname);
#endif
/* util.c */
-void tape_empty_output_buffer P_((int out_des));
-void disk_empty_output_buffer P_((int out_des));
-void swahw_array P_((char *ptr, int count));
-void tape_buffered_write P_((char *in_buf, int out_des, long num_bytes));
-void tape_buffered_read P_((char *in_buf, int in_des, long num_bytes));
-int tape_buffered_peek P_((char *peek_buf, int in_des, int num_bytes));
-void tape_toss_input P_((int in_des, long num_bytes));
-void copy_files_tape_to_disk P_((int in_des, int out_des, long num_bytes));
-void copy_files_disk_to_tape P_((int in_des, int out_des, long num_bytes, char *filename));
-void copy_files_disk_to_disk P_((int in_des, int out_des, long num_bytes, char *filename));
-void warn_if_file_changed P_((char *file_name, unsigned long old_file_size,
- unsigned long old_file_mtime));
-void create_all_directories P_((char *name));
-void prepare_append P_((int out_file_des));
-char *find_inode_file P_((unsigned long node_num,
- unsigned long major_num, unsigned long minor_num));
-void add_inode P_((unsigned long node_num, char *file_name,
- unsigned long major_num, unsigned long minor_num));
-int open_archive P_((char *file));
-void tape_offline P_((int tape_des));
-void get_next_reel P_((int tape_des));
-void set_new_media_message P_((char *message));
+void tape_empty_output_buffer (int out_des);
+void disk_empty_output_buffer (int out_des);
+void swahw_array (char *ptr, int count);
+void tape_buffered_write (char *in_buf, int out_des, off_t num_bytes);
+void tape_buffered_read (char *in_buf, int in_des, off_t num_bytes);
+int tape_buffered_peek (char *peek_buf, int in_des, int num_bytes);
+void tape_toss_input (int in_des, off_t num_bytes);
+void copy_files_tape_to_disk (int in_des, int out_des, off_t num_bytes);
+void copy_files_disk_to_tape (int in_des, int out_des, off_t num_bytes, char *filename);
+void copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes, char *filename);
+void warn_if_file_changed (char *file_name, unsigned long old_file_size,
+ off_t old_file_mtime);
+void create_all_directories (char *name);
+void prepare_append (int out_file_des);
+char *find_inode_file (unsigned long node_num,
+ unsigned long major_num, unsigned long minor_num);
+void add_inode (unsigned long node_num, char *file_name,
+ unsigned long major_num, unsigned long minor_num);
+int open_archive (char *file);
+void tape_offline (int tape_des);
+void get_next_reel (int tape_des);
+void set_new_media_message (char *message);
#if defined(__MSDOS__) && !defined(__GNUC__)
-int chown P_((char *path, int owner, int group));
+int chown (char *path, int owner, int group);
#endif
#ifdef __TURBOC__
-int utime P_((char *filename, struct utimbuf *utb));
+int utime (char *filename, struct utimbuf *utb);
#endif
#ifdef HPUX_CDF
-char *add_cdf_double_slashes P_((char *filename));
+char *add_cdf_double_slashes (char *filename);
#endif
-
-#define DISK_IO_BLOCK_SIZE (512)
+void write_nuls_to_file (off_t num_bytes, int out_des,
+ void (*writer) (char *in_buf,
+ int out_des, off_t num_bytes));
+#define DISK_IO_BLOCK_SIZE 512
/* FIXME: Move to system.h? */
#ifndef SYMLINK_USES_UMASK
@@ -198,3 +202,20 @@ char *add_cdf_double_slashes P_((char *filename));
#else
# define UMASKED_SYMLINK(name1,name2,mode) umasked_symlink(name1,name2,mode)
#endif /* SYMLINK_USES_UMASK */
+
+void set_perms (int fd, struct cpio_file_stat *header);
+void set_file_times (int fd, const char *name, unsigned long atime,
+ unsigned long mtime);
+void stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st);
+void cpio_safer_name_suffix (char *name, bool link_target,
+ bool absolute_names, bool strip_leading_dots);
+
+/* FIXME: These two defines should be defined in paxutils */
+#define LG_8 3
+#define LG_16 4
+
+uintmax_t from_ascii (char const *where, size_t digs, unsigned logbase);
+
+#define FROM_OCTAL(f) from_ascii (f, sizeof f, LG_8)
+#define FROM_HEX(f) from_ascii (f, sizeof f, LG_16)
+
diff --git a/src/filemode.c b/src/filemode.c
index ff4d379c7a4f..98f281370dd8 100644
--- a/src/filemode.c
+++ b/src/filemode.c
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
#ifdef HAVE_CONFIG_H
#include <config.h>
diff --git a/src/filetypes.h b/src/filetypes.h
index 9f785a182662..de6d77f6284a 100644
--- a/src/filetypes.h
+++ b/src/filetypes.h
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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 sys/types.h and sys/stat.h before this file. */
diff --git a/src/global.c b/src/global.c
index 97b6bea1495d..3341e8ab1d6f 100644
--- a/src/global.c
+++ b/src/global.c
@@ -1,5 +1,5 @@
/* global.c - global variables and initial values for cpio.
- Copyright (C) 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 2001, 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
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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>
@@ -139,7 +140,7 @@ char *archive_name = NULL;
char *rsh_command_option = NULL;
/* CRC checksum. */
-unsigned long crc;
+unsigned int crc;
/* Input and output buffers. */
char *input_buffer, *output_buffer;
@@ -165,9 +166,6 @@ long long input_bytes, output_bytes;
long input_bytes, output_bytes;
#endif
-/* 512 bytes of 0; used for various padding operations. */
-char zeros_512[512];
-
/* Saving of argument values for later reference. */
char *directory_name = NULL;
char **save_patterns;
diff --git a/src/idcache.c b/src/idcache.c
index d3bf482472f2..17fcc04e238c 100644
--- a/src/idcache.c
+++ b/src/idcache.c
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
#ifdef HAVE_CONFIG_H
#include <config.h>
diff --git a/src/main.c b/src/main.c
index cd96e584d99f..7581b8ffd17e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,6 @@
/* main.c - main program and argument processing for cpio.
- Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004, 2005, 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
@@ -11,9 +12,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
/* Written by Phil Nelson <phil@cs.wwu.edu>,
David MacKenzie <djm@gnu.ai.mit.edu>,
@@ -21,6 +23,7 @@
and Sergey Poznyakoff <gray@mirddin.farlep.net> */
#include <system.h>
+#include <paxlib.h>
#include <stdio.h>
#include <getopt.h>
@@ -29,7 +32,7 @@
#include <sys/stat.h>
#ifdef HAVE_LOCALE_H
-# include <locale.h>
+# include <locale.h>
#endif
#include "filetypes.h"
@@ -37,10 +40,11 @@
#include "dstring.h"
#include "extern.h"
#include <rmt.h>
-#include <localedir.h>
+#include <rmt-command.h>
enum cpio_options {
- NO_ABSOLUTE_FILENAMES_OPTION=256,
+ NO_ABSOLUTE_FILENAMES_OPTION=256,
+ ABSOLUTE_FILENAMES_OPTION,
NO_PRESERVE_OWNER_OPTION,
ONLY_VERIFY_CRC_OPTION,
RENAME_BATCH_FILE_OPTION,
@@ -50,8 +54,9 @@ enum cpio_options {
FORCE_LOCAL_OPTION,
DEBUG_OPTION,
BLOCK_SIZE_OPTION,
- TO_STDOUT_OPTION,
-
+ TO_STDOUT_OPTION,
+
+ HANG_OPTION,
USAGE_OPTION,
LICENSE_OPTION,
VERSION_OPTION
@@ -71,129 +76,156 @@ Examples:\n\
/* Print usage error message and exit with error. */
-#define USAGE_ERROR(args) do { error args; exit(2); } while (0)
#define CHECK_USAGE(cond, opt, mode_opt) \
- if (cond) USAGE_ERROR((0, 0, _("%s is meaningless with %s"), opt, mode_opt));
+ if (cond) \
+ ERROR((PAXEXIT_FAILURE, 0, _("%s is meaningless with %s"), opt, mode_opt));
static struct argp_option options[] = {
+ /* ********** */
+#define GRID 10
{NULL, 0, NULL, 0,
- N_("Main operation mode:"), 10},
+ N_("Main operation mode:"), GRID },
{"create", 'o', 0, 0,
- N_("Create the archive (run in copy-out mode)"), 10},
+ N_("Create the archive (run in copy-out mode)"), GRID },
{"extract", 'i', 0, 0,
- N_("Extract files from an archive (run in copy-in mode)")},
+ N_("Extract files from an archive (run in copy-in mode)"), GRID },
{"pass-through", 'p', 0, 0,
- N_("Run in copy-pass mode"), 10},
+ N_("Run in copy-pass mode"), GRID },
{"list", 't', 0, 0,
- N_("Print a table of contents of the input"), 10},
-
+ N_("Print a table of contents of the input"), GRID },
+#undef GRID
+
+ /* ********** */
+#define GRID 100
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid in any mode:"), 100},
+ N_("Operation modifiers valid in any mode:"), GRID },
{"file", 'F', N_("[[USER@]HOST:]FILE-NAME"), 0,
- N_("Use this FILE-NAME instead of standard input or output. Optional USER and HOST specify the user and host names in case of a remote archive"), 110},
+ N_("Use this FILE-NAME instead of standard input or output. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
{"force-local", FORCE_LOCAL_OPTION, 0, 0,
- N_("Archive file is local, even if its name contains colons"), 110},
+ N_("Archive file is local, even if its name contains colons"), GRID+1 },
{"format", 'H', N_("FORMAT"), 0,
- N_("Use given archive FORMAT"), 110},
+ N_("Use given archive FORMAT"), GRID+1 },
{NULL, 'B', NULL, 0,
- N_("Set the I/O block size to 5120 bytes"), 110},
+ N_("Set the I/O block size to 5120 bytes"), GRID+1 },
{"block-size", BLOCK_SIZE_OPTION, N_("BLOCK-SIZE"), 0,
- N_("Set the I/O block size to BLOCK-SIZE * 512 bytes"), 110},
+ N_("Set the I/O block size to BLOCK-SIZE * 512 bytes"), GRID+1 },
{NULL, 'c', NULL, 0,
- N_("Use the old portable (ASCII) archive format"), 0},
+ N_("Use the old portable (ASCII) archive format"), GRID+1 },
{"dot", 'V', NULL, 0,
- N_("Print a \".\" for each file processed"), 110},
+ N_("Print a \".\" for each file processed"), GRID+1 },
{"io-size", 'C', N_("NUMBER"), 0,
- N_("Set the I/O block size to the given NUMBER of bytes"), 110},
+ N_("Set the I/O block size to the given NUMBER of bytes"), GRID+1 },
{"message", 'M', N_("STRING"), 0,
N_("Print STRING when the end of a volume of the backup media is reached"),
- 110},
+ GRID+1 },
{"nonmatching", 'f', 0, 0,
- N_("Only copy files that do not match any of the given patterns"), 110},
+ N_("Only copy files that do not match any of the given patterns"), GRID+1 },
{"numeric-uid-gid", 'n', 0, 0,
N_("In the verbose table of contents listing, show numeric UID and GID"),
- 110},
+ GRID+1 },
{"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
- N_("Use remote COMMAND instead of rsh"), 110},
+ N_("Use remote COMMAND instead of rsh"), GRID+1 },
{"quiet", QUIET_OPTION, NULL, 0,
- N_("Do not print the number of blocks copied"), 110},
+ N_("Do not print the number of blocks copied"), GRID+1 },
{"verbose", 'v', NULL, 0,
- N_("Verbosely list the files processed"), 110},
+ N_("Verbosely list the files processed"), GRID+1 },
#ifdef DEBUG_CPIO
{"debug", DEBUG_OPTION, NULL, 0,
- N_("Enable debugging info"), 110},
+ N_("Enable debugging info"), GRID+1 },
#endif
{"warning", 'W', N_("FLAG"), 0,
- N_("Control warning display. Currently FLAG is one of 'none', 'truncate', 'all'. Multiple options accumulate."), 110 },
-
+ N_("Control warning display. Currently FLAG is one of 'none', 'truncate', 'all'. Multiple options accumulate."), GRID+1 },
+#undef GRID
+
/* ********** */
+#define GRID 200
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid only in copy-in mode:"), 200},
+ N_("Operation modifiers valid only in copy-in mode:"), GRID },
{"pattern-file", 'E', N_("FILE"), 0,
- N_("In copy-in mode, read additional patterns specifying filenames to extract or list from FILE"), 210},
- {"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
- N_("Create all files relative to the current directory"), 210},
+ N_("Read additional patterns specifying filenames to extract or list from FILE"), 210},
{"only-verify-crc", ONLY_VERIFY_CRC_OPTION, 0, 0,
- N_("When reading a CRC format archive in copy-in mode, only verify the CRC's of each file in the archive, don't actually extract the files"), 210},
+ N_("When reading a CRC format archive, only verify the CRC's of each file in the archive, don't actually extract the files"), 210},
{"rename", 'r', 0, 0,
- N_("Interactively rename files"), 210},
+ N_("Interactively rename files"), GRID+1 },
{"rename-batch-file", RENAME_BATCH_FILE_OPTION, N_("FILE"), OPTION_HIDDEN,
- "", 210},
+ "", GRID+1 },
{"swap", 'b', NULL, 0,
- N_("Swap both halfwords of words and bytes of halfwords in the data. Equivalent to -sS"), 210},
+ N_("Swap both halfwords of words and bytes of halfwords in the data. Equivalent to -sS"), GRID+1 },
{"swap-bytes", 's', NULL, 0,
- N_("Swap the bytes of each halfword in the files"), 210},
+ N_("Swap the bytes of each halfword in the files"), GRID+1 },
{"swap-halfwords", 'S', NULL, 0,
N_("Swap the halfwords of each word (4 bytes) in the files"),
- 210},
+ GRID+1 },
{"to-stdout", TO_STDOUT_OPTION, NULL, 0,
- N_("Extract files to standard output"), 210},
+ N_("Extract files to standard output"), GRID+1 },
+#undef GRID
/* ********** */
+#define GRID 300
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid only in copy-out mode:"), 300},
+ N_("Operation modifiers valid only in copy-out mode:"), GRID },
{"append", 'A', 0, 0,
- N_("Append to an existing archive."), 310 },
+ N_("Append to an existing archive."), GRID+1 },
{NULL, 'O', N_("[[USER@]HOST:]FILE-NAME"), 0,
- N_("Archive filename to use instead of standard output. Optional USER and HOST specify the user and host names in case of a remote archive"), 310},
+ N_("Archive filename to use instead of standard output. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
+#undef GRID
/* ********** */
+#define GRID 400
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid only in copy-pass mode:"), 400},
+ N_("Operation modifiers valid only in copy-pass mode:"), GRID},
{"link", 'l', 0, 0,
- N_("Link files instead of copying them, when possible"), 410},
+ N_("Link files instead of copying them, when possible"), GRID+1 },
+#undef GRID
+
/* ********** */
+#define GRID 500
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid for copy-out and copy-pass modes:"), 500},
+ N_("Operation modifiers valid in copy-in and copy-out modes:"), GRID },
+ {"absolute-filenames", ABSOLUTE_FILENAMES_OPTION, 0, 0,
+ N_("Do not strip file system prefix components from the file names"),
+ GRID+1 },
+ {"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
+ N_("Create all files relative to the current directory"), GRID+1 },
+#undef GRID
+ /* ********** */
+#define GRID 600
+ {NULL, 0, NULL, 0,
+ N_("Operation modifiers valid in copy-out and copy-pass modes:"), GRID },
{"null", '0', 0, 0,
- N_("A list of filenames is terminated by a null character instead of a newline"), 510 },
+ N_("A list of filenames is terminated by a null character instead of a newline"), GRID+1 },
{NULL, 'I', N_("[[USER@]HOST:]FILE-NAME"), 0,
- N_("Archive filename to use instead of standard input. Optional USER and HOST specify the user and host names in case of a remote archive"), 510},
+ N_("Archive filename to use instead of standard input. Optional USER and HOST specify the user and host names in case of a remote archive"), GRID+1 },
{"dereference", 'L', 0, 0,
- N_("Dereference symbolic links (copy the files that they point to instead of copying the links)."), 510},
+ N_("Dereference symbolic links (copy the files that they point to instead of copying the links)."), GRID+1 },
{"owner", 'R', N_("[USER][:.][GROUP]"), 0,
- N_("Set the ownership of all files created to the specified USER and/or GROUP"), 510},
- {"sparse", SPARSE_OPTION, NULL, 0,
- N_("Write files with large blocks of zeros as sparse files"), 510},
+ N_("Set the ownership of all files created to the specified USER and/or GROUP"), GRID+1 },
{"reset-access-time", 'a', NULL, 0,
- N_("Reset the access times of files after reading them"), 510},
+ N_("Reset the access times of files after reading them"), GRID+1 },
+#undef GRID
/* ********** */
+#define GRID 700
{NULL, 0, NULL, 0,
- N_("Operation modifiers valid for copy-in and copy-pass modes:"), 600},
+ N_("Operation modifiers valid in copy-in and copy-pass modes:"), GRID },
{"preserve-modification-time", 'm', 0, 0,
- N_("Retain previous file modification times when creating files"), 610},
+ N_("Retain previous file modification times when creating files"), GRID+1 },
{"make-directories", 'd', 0, 0,
- N_("Create leading directories where needed"), 610},
+ N_("Create leading directories where needed"), GRID+1 },
{"no-preserve-owner", NO_PRESERVE_OWNER_OPTION, 0, 0,
- N_("Do not change the ownership of the files"), 610},
+ N_("Do not change the ownership of the files"), GRID+1 },
{"unconditional", 'u', NULL, 0,
- N_("Replace all files unconditionally"), 610},
-
+ N_("Replace all files unconditionally"), GRID+1 },
+ {"sparse", SPARSE_OPTION, NULL, 0,
+ N_("Write files with large blocks of zeros as sparse files"), GRID+1 },
+#undef GRID
+
+ /* ********** */
+#define GRID 800
{NULL, 0, NULL, 0,
- N_("Informative options:"), 700 },
+ N_("Informative options:"), GRID },
{"help", '?', 0, 0, N_("Give this help list"), -1},
{"usage", USAGE_OPTION, 0, 0, N_("Give a short usage message"), -1},
@@ -201,7 +233,9 @@ static struct argp_option options[] = {
{"version", VERSION_OPTION, 0, 0, N_("Print program version"), -1},
/* FIXME -V (--dot) conflicts with the default short option for
--version */
-
+ {"HANG", HANG_OPTION, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
+ N_("hang for SECS seconds (default 3600)"), 0},
+#undef GRID
{0, 0, 0, 0}
};
@@ -224,8 +258,8 @@ license ()
" GNU General Public License for more details.\n"
"\n"
" You should have received a copy of the GNU General Public License\n"
- " along with GNU cpio; if not, write to the Free Software\n"
- " Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\n"));
+ " along with GNU cpio; if not, write to the Free Software Foundation,\n"
+ " Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n\n"));
exit (0);
}
@@ -269,6 +303,7 @@ warn_control (char *arg)
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
+ static volatile int _argp_hang;
switch (key)
{
case '0': /* Read null-terminated filenames. */
@@ -301,7 +336,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
case 'c': /* Use the old portable ASCII format. */
if (archive_format != arf_unknown)
- USAGE_ERROR ((0, 0, _("Archive format multiply defined")));
+ error (0, EXIT_FAILURE, _("Archive format multiply defined"));
#ifdef SVR4_COMPAT
archive_format = arf_newascii; /* -H newc. */
#else
@@ -333,7 +368,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
case 'H': /* Header format name. */
if (archive_format != arf_unknown)
- USAGE_ERROR ((0, 0, _("Archive format multiply defined")));
+ error (PAXEXIT_FAILURE, 0, _("Archive format multiply defined"));
if (!strcasecmp (arg, "crc"))
archive_format = arf_crcascii;
else if (!strcasecmp (arg, "newc"))
@@ -358,7 +393,7 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case 'i': /* Copy-in mode. */
if (copy_function != 0)
- USAGE_ERROR ((0, 0, _("Mode already defined")));
+ error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
copy_function = process_copy_in;
break;
@@ -394,17 +429,21 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case NO_ABSOLUTE_FILENAMES_OPTION: /* --no-absolute-filenames */
no_abs_paths_flag = true;
break;
-
+
+ case ABSOLUTE_FILENAMES_OPTION: /* --absolute-filenames */
+ no_abs_paths_flag = false;
+ break;
+
case NO_PRESERVE_OWNER_OPTION: /* --no-preserve-owner */
if (set_owner_flag || set_group_flag)
- USAGE_ERROR ((0, 0,
- _("--no-preserve-owner cannot be used with --owner")));
+ error (PAXEXIT_FAILURE, 0,
+ _("--no-preserve-owner cannot be used with --owner"));
no_chown_flag = true;
break;
case 'o': /* Copy-out mode. */
if (copy_function != 0)
- USAGE_ERROR ((0, 0, _("Mode already defined")));
+ error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
copy_function = process_copy_out;
break;
@@ -418,7 +457,7 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case 'p': /* Copy-pass mode. */
if (copy_function != 0)
- USAGE_ERROR ((0, 0, _("Mode already defined")));
+ error (PAXEXIT_FAILURE, 0, _("Mode already defined"));
copy_function = process_copy_pass;
break;
@@ -440,25 +479,26 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case 'R': /* Set the owner. */
if (no_chown_flag)
- USAGE_ERROR ((0, 0,
- _("--owner cannot be used with --no-preserve-owner")));
- {
- char *e, *u, *g;
-
- e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
- if (e)
- error (2, 0, "%s: %s", arg, e);
- if (u)
- {
- free (u);
- set_owner_flag = true;
- }
- if (g)
- {
- free (g);
- set_group_flag = true;
- }
- }
+ error (PAXEXIT_FAILURE, 0,
+ _("--owner cannot be used with --no-preserve-owner"));
+ else
+ {
+ char *e, *u, *g;
+
+ e = parse_user_spec (arg, &set_owner, &set_group, &u, &g);
+ if (e)
+ error (PAXEXIT_FAILURE, 0, "%s: %s", arg, e);
+ if (u)
+ {
+ free (u);
+ set_owner_flag = true;
+ }
+ if (g)
+ {
+ free (g);
+ set_group_flag = true;
+ }
+ }
break;
case 's': /* Swap bytes. */
@@ -507,6 +547,12 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
case TO_STDOUT_OPTION:
to_stdout_option = true;
break;
+
+ case HANG_OPTION:
+ _argp_hang = atoi (arg ? arg : "3600");
+ while (_argp_hang-- > 0)
+ sleep (1);
+ break;
case '?':
argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
@@ -552,9 +598,9 @@ process_args (int argc, char *argv[])
int index;
if (argc < 2)
- USAGE_ERROR ((0, 0,
- _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
- program_name, program_name));
+ error (PAXEXIT_FAILURE, 0,
+ _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
+ program_name, program_name);
xstat = lstat;
@@ -568,9 +614,9 @@ process_args (int argc, char *argv[])
if (table_flag)
copy_function = process_copy_in;
else
- USAGE_ERROR ((0, 0,
- _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
- program_name, program_name));
+ error (PAXEXIT_FAILURE, 0,
+ _("You must specify one of -oipt options.\nTry `%s --help' or `%s --usage' for more information.\n"),
+ program_name, program_name);
}
/* Work around for pcc bug. */
@@ -584,7 +630,6 @@ process_args (int argc, char *argv[])
CHECK_USAGE(reset_time_flag, "--reset", "--extract");
CHECK_USAGE(xstat != lstat, "--dereference", "--extract");
CHECK_USAGE(append_flag, "--append", "--extract");
- CHECK_USAGE(sparse_flag, "--sparse", "--extract");
CHECK_USAGE(output_archive_name, "-O", "--extract");
if (to_stdout_option)
{
@@ -597,7 +642,8 @@ process_args (int argc, char *argv[])
}
if (archive_name && input_archive_name)
- USAGE_ERROR((0, 0, _("Both -I and -F are used in copy-in mode")));
+ error (PAXEXIT_FAILURE, 0,
+ _("Both -I and -F are used in copy-in mode"));
if (archive_format == arf_crcascii)
crc_i_flag = true;
@@ -609,7 +655,7 @@ process_args (int argc, char *argv[])
else if (copy_function == copy_out)
{
if (index != argc)
- USAGE_ERROR ((0, 0, _("Too many arguments")));
+ error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
archive_des = 1;
CHECK_USAGE(create_dir_flag, "--make-directories", "--create");
@@ -617,24 +663,24 @@ process_args (int argc, char *argv[])
CHECK_USAGE(table_flag, "--list", "--create");
CHECK_USAGE(unconditional_flag, "--unconditional", "--create");
CHECK_USAGE(link_flag, "--link", "--create");
+ CHECK_USAGE(sparse_flag, "--sparse", "--create");
CHECK_USAGE(retain_time_flag, "--preserve-modification-time",
"--create");
CHECK_USAGE(no_chown_flag, "--no-preserve-owner", "--create");
- CHECK_USAGE(set_owner_flag||set_group_flag, "--owner", "--create");
CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--create");
CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
"--create");
CHECK_USAGE(to_stdout_option, "--to-stdout", "--create");
if (append_flag && !(archive_name || output_archive_name))
- USAGE_ERROR ((0, 0,
- _("--append is used but no archive file name is given (use -F or -O options")));
+ error (PAXEXIT_FAILURE, 0,
+ _("--append is used but no archive file name is given (use -F or -O options)"));
CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--create");
- CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames", "--create");
CHECK_USAGE(input_archive_name, "-I", "--create");
if (archive_name && output_archive_name)
- USAGE_ERROR ((0, 0, _("Both -O and -F are used in copy-out mode")));
+ error (PAXEXIT_FAILURE, 0,
+ _("Both -O and -F are used in copy-out mode"));
if (archive_format == arf_unknown)
archive_format = arf_binary;
@@ -644,12 +690,14 @@ process_args (int argc, char *argv[])
else
{
/* Copy pass. */
- if (index != argc - 1)
- USAGE_ERROR ((0, 0, _("Too many arguments")));
+ if (index < argc - 1)
+ error (PAXEXIT_FAILURE, 0, _("Too many arguments"));
+ else if (index > argc - 1)
+ error (PAXEXIT_FAILURE, 0, _("Not enough arguments"));
if (archive_format != arf_unknown)
- USAGE_ERROR((0, 0,
- _("Archive format is not specified in copy-pass mode (use --format option)")));
+ error (PAXEXIT_FAILURE, 0,
+ _("Archive format is not specified in copy-pass mode (use --format option)"));
CHECK_USAGE(swap_bytes_flag, "--swap-bytes (--swap)", "--pass-through");
CHECK_USAGE(swap_halfwords_flag, "--swap-halfwords (--swap)",
@@ -660,6 +708,8 @@ process_args (int argc, char *argv[])
CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--pass-through");
CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames",
"--pass-through");
+ CHECK_USAGE(no_abs_paths_flag, "--absolute-pathnames",
+ "--pass-through");
CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through");
directory_name = argv[index];
@@ -668,11 +718,12 @@ process_args (int argc, char *argv[])
if (archive_name)
{
if (copy_function != copy_in && copy_function != copy_out)
- USAGE_ERROR ((0, 0,
- _("-F can be used only with --create or --extract")));
+ error (PAXEXIT_FAILURE, 0,
+ _("-F can be used only with --create or --extract"));
archive_des = open_archive (archive_name);
if (archive_des < 0)
- error (1, errno, "%s", archive_name);
+ error (PAXEXIT_FAILURE, errno, _("Cannot open %s"),
+ quotearg_colon (archive_name));
}
/* Prevent SysV non-root users from giving away files inadvertantly.
@@ -725,33 +776,19 @@ initialize_buffers ()
out_buff = output_buffer;
output_size = 0;
output_bytes = 0;
-
- /* Clear the block of zeros. */
- bzero (zeros_512, 512);
}
int
main (int argc, char *argv[])
{
-#ifdef HAVE_LOCALE_H
setlocale (LC_ALL, "");
-#endif
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
program_name = argv[0];
- umask (0);
-
-#ifdef __TURBOC__
- _fmode = O_BINARY; /* Put stdin and stdout in binary mode. */
-#endif
-#ifdef __EMX__ /* gcc on OS/2. */
- _response (&argc, &argv);
- _wildcard (&argc, &argv);
-#endif
process_args (argc, argv);
-
+
initialize_buffers ();
(*copy_function) ();
diff --git a/src/makepath.c b/src/makepath.c
index 9587ba8dc629..ff4c25f72c8d 100644
--- a/src/makepath.c
+++ b/src/makepath.c
@@ -1,5 +1,5 @@
/* makepath.c -- Ensure that a directory path exists.
- Copyright (C) 1990 Free Software Foundation, Inc.
+ Copyright (C) 1990, 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
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu> and
Jim Meyering <meyering@cs.utexas.edu>. */
@@ -23,46 +24,11 @@
come together again in the future. */
#include <system.h>
-
-#ifdef __GNUC__
-#define alloca __builtin_alloca
-#else
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#else
-#ifdef _AIX
- #pragma alloca
-#else
-char *alloca ();
-#endif
-#endif
-#endif
+#include <paxlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if !defined(S_ISDIR) && defined(S_IFDIR)
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#endif
-
-#include <errno.h>
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#else
-extern int errno;
-#endif
-
-#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
-#include <string.h>
-#ifndef index
-#define index strchr
-#endif
-#else
-#include <strings.h>
-#endif
/* Ensure that the directory ARGPATH exists.
Remove any trailing slashes from ARGPATH before calling this function.
@@ -126,7 +92,7 @@ make_path (char *argpath,
slash = dirpath;
while (*slash == '/')
slash++;
- while ((slash = index (slash, '/')))
+ while ((slash = strchr (slash, '/')))
{
#ifdef HPUX_CDF
int iscdf;
@@ -164,7 +130,7 @@ make_path (char *argpath,
#endif
)
{
- error (0, errno, "%s", dirpath);
+ chown_error_details (dirpath, owner, group);
retval = 1;
}
if (re_protect)
@@ -231,23 +197,23 @@ make_path (char *argpath,
#endif
)
{
- error (0, errno, "%s", dirpath);
+ chown_error_details (dirpath, owner, group);
retval = 1;
}
}
- /* chown may have turned off some permission bits we wanted. */
- if ((mode & 07000) != 0 && chmod (dirpath, mode))
- {
- error (0, errno, "%s", dirpath);
- retval = 1;
- }
+ /* chown may have turned off some permission bits we wanted. */
+ if ((mode & 07000) != 0 && chmod (dirpath, mode))
+ {
+ chmod_error_details (dirpath, mode);
+ retval = 1;
+ }
/* If the mode for leading directories didn't include owner "wx"
privileges, we have to reset their protections to the correct
value. */
for (p = leading_dirs; p != NULL; p = p->next)
{
- *(p->dirname_end) = '\0';
+ *p->dirname_end = '\0';
#if 0
/* cpio always calls make_path with parent mode 0700, so
we don't have to do this. If we ever do have to do this,
@@ -255,7 +221,7 @@ make_path (char *argpath,
bit so we don't break HP CDF's. */
if (chmod (dirpath, parent_mode))
{
- error (0, errno, "%s", dirpath);
+ chmod_error_details (dirpath, parent_mode);
retval = 1;
}
#endif
@@ -286,12 +252,12 @@ make_path (char *argpath,
#endif
)
{
- error (0, errno, "%s", dirpath);
+ chown_error_details (dirpath, owner, group);
retval = 1;
}
if (chmod (dirpath, mode))
{
- error (0, errno, "%s", dirpath);
+ chmod_error_details (dirpath, mode);
retval = 1;
}
}
diff --git a/src/tar.c b/src/tar.c
index 939d83a225aa..2a470c49516e 100644
--- a/src/tar.c
+++ b/src/tar.c
@@ -1,5 +1,5 @@
/* tar.c - read in write tar headers for cpio
- Copyright (C) 1992, 2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 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
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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>
@@ -112,10 +113,10 @@ to_oct (register long value, register int digits, register char *where)
/* Compute and return a checksum for TAR_HDR,
counting the checksum bytes as if they were spaces. */
-unsigned long
+unsigned int
tar_checksum (struct tar_header *tar_hdr)
{
- unsigned long sum = 0;
+ unsigned int sum = 0;
char *p = (char *) tar_hdr;
char *q = p + TARRECORDSIZE;
int i;
@@ -136,13 +137,13 @@ tar_checksum (struct tar_header *tar_hdr)
descriptor OUT_DES. */
void
-write_out_tar_header (struct new_cpio_header *file_hdr, int out_des)
+write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des)
{
int name_len;
union tar_record tar_rec;
struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
- bzero ((char *) &tar_rec, TARRECORDSIZE);
+ memset (&tar_rec, 0, sizeof tar_rec);
/* process_copy_out must ensure that file_hdr->c_name is short enough,
or we will lose here. */
@@ -254,7 +255,7 @@ null_block (long *block, int size)
into FILE_HDR. */
void
-read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
+read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des)
{
long bytes_skipped = 0;
int warned = false;
@@ -280,7 +281,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
if (null_block ((long *) &tar_rec, TARRECORDSIZE))
#endif
{
- file_hdr->c_name = "TRAILER!!!";
+ file_hdr->c_name = CPIO_TRAILER_NAME;
return;
}
#if 0
@@ -290,7 +291,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
while (1)
{
- otoa (tar_hdr->chksum, &file_hdr->c_chksum);
+ file_hdr->c_chksum = FROM_OCTAL (tar_hdr->chksum);
if (file_hdr->c_chksum != tar_checksum (tar_hdr))
{
@@ -307,8 +308,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
error (0, 0, _("invalid header: checksum error"));
warned = true;
}
- bcopy (((char *) &tar_rec) + 1, (char *) &tar_rec,
- TARRECORDSIZE - 1);
+ memmove (&tar_rec, ((char *) &tar_rec) + 1, TARRECORDSIZE - 1);
tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
++bytes_skipped;
continue;
@@ -319,7 +319,7 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
else
file_hdr->c_name = stash_tar_filename (tar_hdr->prefix, tar_hdr->name);
file_hdr->c_nlink = 1;
- otoa (tar_hdr->mode, &file_hdr->c_mode);
+ file_hdr->c_mode = FROM_OCTAL (tar_hdr->mode);
file_hdr->c_mode = file_hdr->c_mode & 07777;
/* Debian hack: This version of cpio uses the -n flag also to extract
tar archives using the numeric UID/GID instead of the user/group
@@ -328,17 +328,17 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
&& (uidp = getuidbyname (tar_hdr->uname)))
file_hdr->c_uid = *uidp;
else
- otoa (tar_hdr->uid, &file_hdr->c_uid);
+ file_hdr->c_uid = FROM_OCTAL (tar_hdr->uid);
if (archive_format == arf_ustar && !numeric_uid
&& (gidp = getgidbyname (tar_hdr->gname)))
file_hdr->c_gid = *gidp;
else
- otoa (tar_hdr->gid, &file_hdr->c_gid);
- otoa (tar_hdr->size, &file_hdr->c_filesize);
- otoa (tar_hdr->mtime, &file_hdr->c_mtime);
- otoa (tar_hdr->devmajor, (unsigned long *) &file_hdr->c_rdev_maj);
- otoa (tar_hdr->devminor, (unsigned long *) &file_hdr->c_rdev_min);
+ file_hdr->c_gid = FROM_OCTAL (tar_hdr->gid);
+ file_hdr->c_filesize = FROM_OCTAL (tar_hdr->size);
+ file_hdr->c_mtime = FROM_OCTAL (tar_hdr->mtime);
+ file_hdr->c_rdev_maj = FROM_OCTAL (tar_hdr->devmajor);
+ file_hdr->c_rdev_min = FROM_OCTAL (tar_hdr->devminor);
file_hdr->c_tar_linkname = NULL;
switch (tar_hdr->typeflag)
@@ -409,26 +409,6 @@ read_in_tar_header (struct new_cpio_header *file_hdr, int in_des)
warn_junk_bytes (bytes_skipped);
}
-/* Convert the string of octal digits S into a number and store
- it in *N. Return nonzero if the whole string was converted,
- zero if there was something after the number.
- Skip leading and trailing spaces. */
-
-int
-otoa (char *s, unsigned long *n)
-{
- unsigned long val = 0;
-
- while (*s == ' ')
- ++s;
- while (*s >= '0' && *s <= '7')
- val = 8 * val + *s++ - '0';
- while (*s == ' ')
- ++s;
- *n = val;
- return *s == '\0';
-}
-
/* Return
2 if BUF is a valid POSIX tar header (the checksum is correct
and it has the "ustar" magic string),
@@ -441,7 +421,7 @@ is_tar_header (char *buf)
struct tar_header *tar_hdr = (struct tar_header *) buf;
unsigned long chksum;
- otoa (tar_hdr->chksum, &chksum);
+ chksum = FROM_OCTAL (tar_hdr->chksum);
if (chksum != tar_checksum (tar_hdr))
return 0;
@@ -473,7 +453,6 @@ is_tar_filename_too_long (char *name)
{
int whole_name_len;
int prefix_name_len;
- char *p;
whole_name_len = strlen (name);
if (whole_name_len <= TARNAMESIZE)
diff --git a/src/tar.h b/src/tar.h
index 79f289eea15e..7b27e86a56fc 100644
--- a/src/tar.h
+++ b/src/tar.h
@@ -14,10 +14,10 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+You should have received a copy of the GNU Library General
+Public License along with this library; see the file COPYING.LIB.
+If not, write to the Free Software Foundation, Inc., 51 Franklin
+Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#ifndef _TAR_H
diff --git a/src/tarhdr.h b/src/tarhdr.h
index 8b1211dffae0..b901739c19cc 100644
--- a/src/tarhdr.h
+++ b/src/tarhdr.h
@@ -11,9 +11,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
#ifndef _TARHDR_H
diff --git a/src/userspec.c b/src/userspec.c
index c426acd81bda..d9be4f43570d 100644
--- a/src/userspec.c
+++ b/src/userspec.c
@@ -1,5 +1,6 @@
/* userspec.c -- Parse a user and group string.
- Copyright (C) 1989, 1990, 1991, 1992, 2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1992, 2001,
+ 2004, 2005 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
@@ -11,9 +12,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
@@ -72,7 +74,7 @@ extern struct group *getgrgid (gid_t gid);
otherwise return 0. */
static int
-isnumber (const char *str)
+isnumber_p (const char *str)
{
for (; *str; str++)
if (!isdigit (*str))
@@ -111,9 +113,9 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
V_STRDUP (spec, spec_arg);
/* Find the separator if there is one. */
- separator = index (spec, ':');
+ separator = strchr (spec, ':');
if (separator == NULL)
- separator = index (spec, '.');
+ separator = strchr (spec, '.');
/* Replace separator with a NUL. */
if (separator != NULL)
@@ -136,7 +138,7 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
if (pwd == NULL)
{
- if (!isnumber (u))
+ if (!isnumber_p (u))
error_msg = _("invalid user");
else
{
@@ -182,7 +184,7 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
grp = getgrnam (g);
if (grp == NULL)
{
- if (!isnumber (g))
+ if (!isnumber_p (g))
error_msg = _("invalid group");
else
*gid = atoi (g);
diff --git a/src/util.c b/src/util.c
index 4b64648ee2b1..5bcc40aa2495 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,5 +1,6 @@
/* util.c - Several utility routines for cpio.
- Copyright (C) 1990, 1991, 1992, 2001, 2004 Free Software Foundation, Inc.
+ 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
@@ -11,9 +12,10 @@
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.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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>
@@ -23,15 +25,21 @@
#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>
+# ifdef HAVE_SYS_IO_TRIOCTL_H
+# include <sys/io/trioctl.h>
+# endif
+# include <sys/mtio.h>
#endif
#if !HAVE_DECL_ERRNO
@@ -90,6 +98,8 @@ tape_empty_output_buffer (int out_des)
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,
@@ -207,7 +217,7 @@ tape_fill_input_buffer (int in_des, int num_bytes)
Exit with an error if end of file is reached. */
static int
-disk_fill_input_buffer (int in_des, int num_bytes)
+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;
@@ -227,10 +237,10 @@ disk_fill_input_buffer (int in_des, int num_bytes)
When `out_buff' fills up, flush it to file descriptor OUT_DES. */
void
-tape_buffered_write (char *in_buf, int out_des, long num_bytes)
+tape_buffered_write (char *in_buf, int out_des, off_t num_bytes)
{
- register long bytes_left = num_bytes; /* Bytes needing to be copied. */
- register long space_left; /* Room left in output buffer. */
+ off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
+ off_t space_left; /* Room left in output buffer. */
while (bytes_left > 0)
{
@@ -241,7 +251,7 @@ tape_buffered_write (char *in_buf, int out_des, long num_bytes)
{
if (bytes_left < space_left)
space_left = bytes_left;
- bcopy (in_buf, out_buff, (unsigned) space_left);
+ memcpy (out_buff, in_buf, (unsigned) space_left);
out_buff += space_left;
output_size += space_left;
in_buf += space_left;
@@ -254,10 +264,10 @@ tape_buffered_write (char *in_buf, int out_des, long num_bytes)
When `out_buff' fills up, flush it to file descriptor OUT_DES. */
void
-disk_buffered_write (char *in_buf, int out_des, long num_bytes)
+disk_buffered_write (char *in_buf, int out_des, off_t num_bytes)
{
- register long bytes_left = num_bytes; /* Bytes needing to be copied. */
- register long space_left; /* Room left in output buffer. */
+ off_t bytes_left = num_bytes; /* Bytes needing to be copied. */
+ off_t space_left; /* Room left in output buffer. */
while (bytes_left > 0)
{
@@ -268,7 +278,7 @@ disk_buffered_write (char *in_buf, int out_des, long num_bytes)
{
if (bytes_left < space_left)
space_left = bytes_left;
- bcopy (in_buf, out_buff, (unsigned) space_left);
+ memcpy (out_buff, in_buf, (unsigned) space_left);
out_buff += space_left;
output_size += space_left;
in_buf += space_left;
@@ -282,10 +292,10 @@ disk_buffered_write (char *in_buf, int out_des, long num_bytes)
When `in_buff' is exhausted, refill it from file descriptor IN_DES. */
void
-tape_buffered_read (char *in_buf, int in_des, long num_bytes)
+tape_buffered_read (char *in_buf, int in_des, off_t num_bytes)
{
- register long bytes_left = num_bytes; /* Bytes needing to be copied. */
- register long space_left; /* Bytes to copy from input buffer. */
+ 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)
{
@@ -295,7 +305,7 @@ tape_buffered_read (char *in_buf, int in_des, long num_bytes)
space_left = bytes_left;
else
space_left = input_size;
- bcopy (in_buff, in_buf, (unsigned) space_left);
+ memcpy (in_buf, in_buff, (unsigned) space_left);
in_buff += space_left;
in_buf += space_left;
input_size -= space_left;
@@ -345,7 +355,7 @@ tape_buffered_peek (char *peek_buf, int in_des, int num_bytes)
first block to make room. */
int half;
half = input_buffer_size / 2;
- bcopy (input_buffer + half, input_buffer, half);
+ memmove (input_buffer, input_buffer + half, half);
in_buff = in_buff - half;
append_buf = append_buf - half;
}
@@ -369,17 +379,17 @@ tape_buffered_peek (char *peek_buf, int in_des, int num_bytes)
got_bytes = num_bytes;
else
got_bytes = input_size;
- bcopy (in_buff, peek_buf, (unsigned) got_bytes);
+ 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, long num_bytes)
+tape_toss_input (int in_des, off_t num_bytes)
{
- register long bytes_left = num_bytes; /* Bytes needing to be copied. */
- register long space_left; /* Bytes to copy from input buffer. */
+ 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)
{
@@ -403,18 +413,19 @@ tape_toss_input (int in_des, long num_bytes)
}
}
-static void
-write_nuls_to_file (long num_bytes, int out_des,
- void (*writer) (char *in_buf, int out_des, long num_bytes))
+void
+write_nuls_to_file (off_t num_bytes, int out_des,
+ void (*writer) (char *in_buf, int out_des, off_t num_bytes))
{
- long blocks;
- long extra_bytes;
- long i;
-
- blocks = num_bytes / 512;
- extra_bytes = num_bytes % 512;
+ 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, 512);
+ writer (zeros_512, out_des, sizeof zeros_512);
if (extra_bytes)
writer (zeros_512, out_des, extra_bytes);
}
@@ -428,7 +439,7 @@ write_nuls_to_file (long num_bytes, int out_des,
NUM_BYTES is the number of bytes to copy. */
void
-copy_files_tape_to_disk (int in_des, int out_des, long num_bytes)
+copy_files_tape_to_disk (int in_des, int out_des, off_t num_bytes)
{
long size;
long k;
@@ -458,13 +469,13 @@ copy_files_tape_to_disk (int in_des, int out_des, long num_bytes)
NUM_BYTES is the number of bytes to copy. */
void
-copy_files_disk_to_tape (int in_des, int out_des, long num_bytes,
+copy_files_disk_to_tape (int in_des, int out_des, off_t num_bytes,
char *filename)
{
long size;
long k;
int rc;
- long original_num_bytes;
+ off_t original_num_bytes;
original_num_bytes = num_bytes;
@@ -472,14 +483,20 @@ copy_files_disk_to_tape (int in_des, int out_des, long num_bytes,
{
if (input_size == 0)
if (rc = disk_fill_input_buffer (in_des,
- num_bytes < DISK_IO_BLOCK_SIZE ?
- num_bytes : DISK_IO_BLOCK_SIZE))
+ num_bytes < DISK_IO_BLOCK_SIZE ?
+ num_bytes : DISK_IO_BLOCK_SIZE))
{
if (rc > 0)
- error (0, 0, _("File %s shrunk by %ld bytes, padding with zeros"),
- filename, num_bytes);
+ {
+ 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 %ld in file %s, padding with zeros"),
+ 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;
@@ -505,12 +522,12 @@ copy_files_disk_to_tape (int in_des, int out_des, long num_bytes,
NUM_BYTES is the number of bytes to copy. */
void
-copy_files_disk_to_disk (int in_des, int out_des, long num_bytes,
+copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes,
char *filename)
{
long size;
long k;
- long original_num_bytes;
+ off_t original_num_bytes;
int rc;
original_num_bytes = num_bytes;
@@ -520,10 +537,16 @@ copy_files_disk_to_disk (int in_des, int out_des, long num_bytes,
if (rc = disk_fill_input_buffer (in_des, num_bytes))
{
if (rc > 0)
- error (0, 0, _("File %s shrunk by %ld bytes, padding with zeros"),
- filename, num_bytes);
+ {
+ 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 %ld in file %s, padding with zeros"),
+ 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;
@@ -545,20 +568,23 @@ copy_files_disk_to_disk (int in_des, int out_des, long num_bytes,
void
warn_if_file_changed (char *file_name, unsigned long old_file_size,
- unsigned long old_file_mtime)
+ off_t old_file_mtime)
{
struct stat new_file_stat;
if ((*xstat) (file_name, &new_file_stat) < 0)
{
- error (0, errno, "%s", file_name);
+ 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, _("File %s grew, %ld new bytes not copied"),
- file_name, (long)(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);
@@ -658,82 +684,40 @@ struct inode_val
};
/* Inode hash table. Allocated by first call to add_inode. */
-static struct inode_val **hash_table = NULL;
-
-/* Size of current hash table. Initial size is 47. (47 = 2*22 + 3) */
-static int hash_size = 22;
+static Hash_table *hash_table = NULL;
-/* Number of elements in current hash table. */
-static int hash_num;
+static size_t
+inode_val_hasher (const void *val, size_t n_buckets)
+{
+ const struct inode_val *ival = val;
+ return ival->inode % n_buckets;
+}
-/* Find the file name associated with NODE_NUM. If there is no file
- associated with NODE_NUM, return NULL. */
+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)
{
- int start; /* Initial hash location. */
- int temp; /* Rehash search variable. */
-
- if (hash_table != NULL)
- {
- /* Hash function is node number modulo the table size. */
- start = node_num % hash_size;
-
- /* Initial look into the table. */
- if (hash_table[start] == NULL)
- return NULL;
- if (hash_table[start]->inode == node_num
- && hash_table[start]->major_num == major_num
- && hash_table[start]->minor_num == minor_num)
- return hash_table[start]->file_name;
-
- /* The home position is full with a different inode record.
- Do a linear search terminated by a NULL pointer. */
- for (temp = (start + 1) % hash_size;
- hash_table[temp] != NULL && temp != start;
- temp = (temp + 1) % hash_size)
- {
- if (hash_table[temp]->inode == node_num
- && hash_table[start]->major_num == major_num
- && hash_table[start]->minor_num == minor_num)
- return hash_table[temp]->file_name;
- }
- }
- return NULL;
-}
-
-/* Do the hash insert. Used in normal inserts and resizing the hash
- table. It is guaranteed that there is room to insert the item.
- NEW_VALUE is the pointer to the previously allocated inode, file
- name association record. */
-
-static void
-hash_insert (struct inode_val *new_value)
-{
- int start; /* Home position for the value. */
- int temp; /* Used for rehashing. */
-
- /* Hash function is node number modulo the table size. */
- start = new_value->inode % hash_size;
-
- /* Do the initial look into the table. */
- if (hash_table[start] == NULL)
- {
- hash_table[start] = new_value;
- return;
- }
-
- /* If we get to here, the home position is full with a different inode
- record. Do a linear search for the first NULL pointer and insert
- the new item there. */
- temp = (start + 1) % hash_size;
- while (hash_table[temp] != NULL)
- temp = (temp + 1) % hash_size;
-
- /* Insert at the NULL. */
- hash_table[temp] = new_value;
+ 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.) */
@@ -743,7 +727,8 @@ 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;
@@ -751,39 +736,12 @@ add_inode (unsigned long node_num, char *file_name, unsigned long major_num,
temp->minor_num = minor_num;
temp->file_name = xstrdup (file_name);
- /* Do we have to increase the size of (or initially allocate)
- the hash table? */
- if (hash_num == hash_size || hash_table == NULL)
- {
- struct inode_val **old_table; /* Pointer to old table. */
- int i; /* Index for re-insert loop. */
-
- /* Save old table. */
- old_table = hash_table;
- if (old_table == NULL)
- hash_num = 0;
-
- /* Calculate new size of table and allocate it.
- Sequence of table sizes is 47, 97, 197, 397, 797, 1597, 3197, 6397 ...
- where 3197 and most of the sizes after 6397 are not prime. The other
- numbers listed are prime. */
- hash_size = 2 * hash_size + 3;
- hash_table = (struct inode_val **)
- xmalloc (hash_size * sizeof (struct inode_val *));
- bzero (hash_table, hash_size * sizeof (struct inode_val *));
-
- /* Insert the values from the old table into the new table. */
- for (i = 0; i < hash_num; i++)
- hash_insert (old_table[i]);
-
- if (old_table != NULL)
- free (old_table);
- }
-
- /* Insert the new record and increment the count of elements in the
- hash table. */
- hash_insert (temp);
- hash_num++;
+ 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 */
}
@@ -800,14 +758,14 @@ open_archive (char *file)
copy_in = process_copy_in;
if (copy_function == copy_in)
- fd = rmtopen (file, O_RDONLY | O_BINARY, 0666, rsh_command_option);
+ 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, 0666,
+ fd = rmtopen (file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, MODE_RW,
rsh_command_option);
else
- fd = rmtopen (file, O_RDWR | O_BINARY, 0666, rsh_command_option);
+ fd = rmtopen (file, O_RDWR | O_BINARY, MODE_RW, rsh_command_option);
}
return fd;
@@ -887,7 +845,7 @@ get_next_reel (int tape_des)
tape_des = open_archive (archive_name);
if (tape_des == -1)
- error (1, errno, "%s", archive_name);
+ open_error (archive_name);
}
else
{
@@ -907,7 +865,7 @@ get_next_reel (int tape_des)
tape_des = open_archive (next_archive_name);
if (tape_des == -1)
- error (0, errno, "%s", next_archive_name);
+ open_error (next_archive_name);
}
while (tape_des < 0);
}
@@ -1003,9 +961,10 @@ umasked_symlink (char *name1, char *name2, int mode)
/* 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 (which it will reuse for
- later calls so our caller doesn't have to worry about freeing
- the string) instead of the original input string. */
+ 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)
@@ -1055,7 +1014,7 @@ add_cdf_double_slashes (char *input_name)
*p = '\0';
if ((*xstat) (input_name, &dir_stat) < 0)
{
- error (0, errno, "%s", input_name);
+ stat_error (input_name);
return input_name;
}
@@ -1081,7 +1040,7 @@ add_cdf_double_slashes (char *input_name)
*p = '\0';
if ((*xstat) (input_name, &dir_stat) < 0)
{
- error (0, errno, "%s", input_name);
+ stat_error (input_name);
return input_name;
}
*p = '/';
@@ -1109,7 +1068,7 @@ islastparentcdf (char *path)
int slash_count;
int length; /* Length of result, not including NUL. */
- slash = rindex (path, '/');
+ slash = strrchr (path, '/');
if (slash == 0)
return 0;
else
@@ -1131,9 +1090,6 @@ islastparentcdf (char *path)
#define DISKBLOCKSIZE (512)
-enum sparse_write_states { begin, in_zeros, not_in_zeros };
-
-
static int
buf_all_zeros (char *buf, int bufsize)
{
@@ -1151,7 +1107,7 @@ 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. */
-int
+static int
sparse_write (int fildes, char *buf, unsigned int nbyte)
{
int complete_block_count;
@@ -1162,7 +1118,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
int lseek_rc;
int write_rc;
int i;
- enum sparse_write_states state;
+ enum { begin, in_zeros, not_in_zeros } state;
complete_block_count = nbyte / DISKBLOCKSIZE;
leftover_bytes_count = nbyte % DISKBLOCKSIZE;
@@ -1192,6 +1148,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
}
buf += DISKBLOCKSIZE;
break;
+
case in_zeros :
if (buf_all_zeros (buf, DISKBLOCKSIZE))
{
@@ -1206,6 +1163,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
}
buf += DISKBLOCKSIZE;
break;
+
case not_in_zeros :
if (buf_all_zeros (buf, DISKBLOCKSIZE))
{
@@ -1228,6 +1186,7 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
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;
@@ -1245,3 +1204,139 @@ sparse_write (int fildes, char *buf, unsigned int nbyte)
}
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));
+}
+