summaryrefslogtreecommitdiff
path: root/archivers
diff options
context:
space:
mode:
authorminskim <minskim>2005-12-01 03:00:01 +0000
committerminskim <minskim>2005-12-01 03:00:01 +0000
commit7d372d18b5679482e09b8c41c75e343eadd943f4 (patch)
tree69dde1e99ccb4689c49aeb9e139310ed0897b827 /archivers
parentff50788b1b1daf30af75b9001316149aff877f93 (diff)
downloadpkgsrc-7d372d18b5679482e09b8c41c75e343eadd943f4.tar.gz
Update pax to 20051108. The previous version failed to handle the -X
option, which is used in print/teTeX3-texmf. The only difference from the pax in src is that tar does not support the --chroot option if fchroot(2) is not available. Major changes and bug fixes since 20040802: PR/18759: FUKAUMI Naoki: pax/tar dot-dot handling broken PR/18840: Frederick Bruckman: Fix for PR/18663 incomplete pax symlink handling This patch makes ``--insecure'' do something. Now if ``--insecure'' is not set (the default) we do a realpath(3) in all the pathnames that we are trying to create and if either realpath fails, or the path is outside our working directory, we print a warning and die. This maybe too strict and might fail on valid archives that create symlinks and directories in the wrong order. PR/31923: Sergey Svishchev: pax-as-tar ignores -k, overwrites existing files Fix from Onno van der Linden PR/30132: Juan RP: tar --chroot refuses to extract files. fchroot() changes the effective path, so we need to call updatepath(). Apply user supplied patterns first before applying actions for -A. This way pax behavior WRT to patterns lines up with the example in the documentation and how other implementations do it as well since -A is a non-standard option/behavior. Fixes items noted in PR#23776 Add an option --chroot to tar. Causes it to chroot(".") before doing an extract. With -h this will cause existing absolute symlinks to be treated as relative to the current directory. Helps sysinst handle existing symlinks in the target system. Remove 'L' from the usage (got spilt into 'h' and 'H' many moons ago) Add 'S' to usage, and put into correct place in options list. PR/27213: Greg A. Woods: pax doesn't honour SIGPIPE when listing But always exit, not just on SIGPIPE. Properly handle "cpio" archives where the last hardlink includes the data of a file. This fixes PR bin/26514. PR/20228: Simon Burge: pax has problems reading a particular cpio archive The problem here is that the archive is too short (< 512 bytes). The buffer routines, try to read at least 512 bytes, even when we try to determine what format file we have, which is wrong. Don't leave arcn->org_name pointing to ftent->fts_path, if we being cpio then ftent is freed just below. Take a copy of the name and point org_name at the copy. Should fix PR/30627 (the fix in the PR will break pax and tar!) PR/30167: J.T. Conklin: NetBSD tar does not support GNU tar --no-recursion flag Fix from PR#29290. Properly terminate the cpio_longopts struct so an unknown option doesn't run off the end and core dump Fix broken cpio(1) option handling: - "cpio -i -t" should list the contents of a file, not extract it. - Don't extract a file when only option "-d" is given. Patch supplied by Paul Ripke in PR bin/26513. PR/27212: Greg A. Woods: Accept "-C <dirname>" inside filelists in addition to "-C\n<dirname>". But we are not making it the default output option as the patch suggests. PR/19490: Julio Merino: Teach tar about --sparse, -S option. Do it for cpio too. PR/27208: Greg A. Woods: pax must call options() before using syswarn() or tty_warn() PR/20071: Perry Metzger: --extract handling is broken. This patch fixes Perry's example.
Diffstat (limited to 'archivers')
-rw-r--r--archivers/pax/Makefile4
-rw-r--r--archivers/pax/files/Makefile.in6
-rw-r--r--archivers/pax/files/ar_io.c53
-rw-r--r--archivers/pax/files/ar_subs.c217
-rw-r--r--archivers/pax/files/buf_subs.c11
-rw-r--r--archivers/pax/files/config.h.in3
-rwxr-xr-xarchivers/pax/files/configure3
-rw-r--r--archivers/pax/files/configure.ac2
-rw-r--r--archivers/pax/files/cpio.19
-rw-r--r--archivers/pax/files/cpio.c7
-rw-r--r--archivers/pax/files/extern.h18
-rw-r--r--archivers/pax/files/file_subs.c97
-rw-r--r--archivers/pax/files/ftree.c7
-rw-r--r--archivers/pax/files/getoldopt.c5
-rw-r--r--archivers/pax/files/options.c122
-rw-r--r--archivers/pax/files/pat_rep.c79
-rw-r--r--archivers/pax/files/pax.192
-rw-r--r--archivers/pax/files/pax.c26
-rw-r--r--archivers/pax/files/pax.h3
-rw-r--r--archivers/pax/files/tables.c8
-rw-r--r--archivers/pax/files/tables.h4
-rw-r--r--archivers/pax/files/tar.127
-rw-r--r--archivers/pax/files/tar.c93
-rw-r--r--archivers/pax/files/tty_subs.c8
24 files changed, 607 insertions, 297 deletions
diff --git a/archivers/pax/Makefile b/archivers/pax/Makefile
index 7dba5640afe..091057d7f5a 100644
--- a/archivers/pax/Makefile
+++ b/archivers/pax/Makefile
@@ -1,7 +1,7 @@
-# $NetBSD: Makefile,v 1.20 2005/05/31 21:39:29 rillig Exp $
+# $NetBSD: Makefile,v 1.21 2005/12/01 03:00:01 minskim Exp $
#
-DISTNAME= pax-20040802
+DISTNAME= pax-20051108
CATEGORIES= archivers pkgtools
MASTER_SITES= # empty
DISTFILES= # empty
diff --git a/archivers/pax/files/Makefile.in b/archivers/pax/files/Makefile.in
index 886dce3c518..4b26ee7cf9f 100644
--- a/archivers/pax/files/Makefile.in
+++ b/archivers/pax/files/Makefile.in
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.in,v 1.8 2004/08/21 06:33:39 jlam Exp $
+# $NetBSD: Makefile.in,v 1.9 2005/12/01 03:00:01 minskim Exp $
srcdir= @srcdir@
@@ -22,10 +22,10 @@ INSTALL= @INSTALL@
PROG= pax
-OBJS= ar_io.o ar_subs.o buf_subs.o cpio.o file_subs.o ftree.o \
+OBJS= ar_io.o ar_subs.o buf_subs.o file_subs.o ftree.o \
gen_subs.o getoldopt.o options.o pat_rep.o pax.o sel_subs.o tables.o \
tar.o tty_subs.o \
- getid.o spec.o misc.o stat_flags.o pack_dev.o
+ getid.o spec.o misc.o stat_flags.o pack_dev.o cpio.o
all: $(PROG)
diff --git a/archivers/pax/files/ar_io.c b/archivers/pax/files/ar_io.c
index c1f7d3ed359..a2cec3c61b4 100644
--- a/archivers/pax/files/ar_io.c
+++ b/archivers/pax/files/ar_io.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ar_io.c,v 1.8 2004/08/21 03:28:56 jlam Exp $ */
+/* $NetBSD: ar_io.c,v 1.9 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -48,13 +48,16 @@
#if 0
static char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 4/18/94";
#else
-__RCSID("$NetBSD: ar_io.c,v 1.8 2004/08/21 03:28:56 jlam Exp $");
+__RCSID("$NetBSD: ar_io.c,v 1.9 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
@@ -71,9 +74,6 @@ __RCSID("$NetBSD: ar_io.c,v 1.8 2004/08/21 03:28:56 jlam Exp $");
#if HAVE_SYS_MTIO_H
#include <sys/mtio.h>
#endif
-#if HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
@@ -238,10 +238,8 @@ ar_open(const char *name)
return(-1);
if (chdname != NULL)
- if (chdir(chdname) != 0) {
- syswarn(1, errno, "Failed chdir to %s", chdname);
+ if (dochdir(chdname) == -1)
return(-1);
- }
/*
* set up is based on device type
*/
@@ -261,13 +259,14 @@ ar_open(const char *name)
return(-1);
}
- if (S_ISCHR(arsb.st_mode))
+ if (S_ISCHR(arsb.st_mode)) {
#ifdef SUPPORT_TAPE
artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE;
#else
- artyp = ISCHR;
+ tty_warn(1, "System does not have tape support");
+ artyp = ISREG;
#endif /* SUPPORT_TAPE */
- else if (S_ISBLK(arsb.st_mode))
+ } else if (S_ISBLK(arsb.st_mode))
artyp = ISBLK;
else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE))
artyp = ISPIPE;
@@ -1025,8 +1024,8 @@ ar_rdsync(void)
#ifdef SUPPORT_RMT
case ISRMT:
#endif /* SUPPORT_RMT */
-#ifdef SUPPORT_TAPE
case ISTAPE:
+#ifdef SUPPORT_TAPE
/*
* if the last i/o was a successful data transfer, we assume
* the fault is just a bad record on the tape that we are now
@@ -1054,8 +1053,10 @@ ar_rdsync(void)
}
#endif /* SUPPORT_RMT */
lstrval = 1;
- break;
+#else
+ tty_warn(1, "System does not have tape support");
#endif /* SUPPORT_TAPE */
+ break;
case ISREG:
case ISCHR:
case ISBLK:
@@ -1172,9 +1173,9 @@ ar_rev(off_t sksz)
{
off_t cpos;
#ifdef SUPPORT_TAPE
+ int phyblk;
struct mtop mb;
#endif /* SUPPORT_TAPE */
- int phyblk;
/*
* make sure we do not have try to reverse on a flawed archive
@@ -1238,11 +1239,11 @@ ar_rev(off_t sksz)
return(-1);
}
break;
-#ifdef SUPPORT_TAPE
case ISTAPE:
#ifdef SUPPORT_RMT
case ISRMT:
#endif /* SUPPORT_RMT */
+#ifdef SUPPORT_TAPE
/*
* Calculate and move the proper number of PHYSICAL tape
* blocks. If the sksz is not an even multiple of the physical
@@ -1295,8 +1296,10 @@ ar_rev(off_t sksz)
lstrval = -1;
return(-1);
}
- break;
+#else
+ tty_warn(1, "System does not have tape support");
#endif /* SUPPORT_TAPE */
+ break;
}
lstrval = 1;
return(0);
@@ -1781,16 +1784,12 @@ ar_summary(int n)
*/
int
-ar_dochdir(char *name)
+ar_dochdir(const char *name)
{
- /* First fchdir() back... */
- if (fchdir(cwdfd) < 0) {
- syswarn(1, errno, "Can't fchdir to starting directory");
- return(-1);
- }
- if (chdir(name) < 0) {
- syswarn(1, errno, "Can't chdir to %s", name);
- return(-1);
- }
- return (0);
+ /* First fdochdir() back... */
+ if (fdochdir(cwdfd) == -1)
+ return -1;
+ if (dochdir(name) == -1)
+ return -1;
+ return 0;
}
diff --git a/archivers/pax/files/ar_subs.c b/archivers/pax/files/ar_subs.c
index e068eeff4b5..9168c977445 100644
--- a/archivers/pax/files/ar_subs.c
+++ b/archivers/pax/files/ar_subs.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ar_subs.c,v 1.7 2004/08/21 03:28:56 jlam Exp $ */
+/* $NetBSD: ar_subs.c,v 1.8 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -48,7 +48,7 @@
#if 0
static char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94";
#else
-__RCSID("$NetBSD: ar_subs.c,v 1.7 2004/08/21 03:28:56 jlam Exp $");
+__RCSID("$NetBSD: ar_subs.c,v 1.8 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
@@ -94,9 +94,15 @@ __RCSID("$NetBSD: ar_subs.c,v 1.7 2004/08/21 03:28:56 jlam Exp $");
#include "pax.h"
#include "extern.h"
+static int path_check(ARCHD *, int);
static void wr_archive(ARCHD *, int is_app);
static int get_arc(void);
static int next_head(ARCHD *);
+#if !HAVE_NBTOOL_CONFIG_H
+#ifdef HAVE_FCHROOT
+static int fdochroot(int);
+#endif /* HAVE_FCHROOT */
+#endif
extern sigset_t s_mask;
/*
@@ -108,6 +114,110 @@ static char hdbuf[BLKMULT]; /* space for archive header on read */
u_long flcnt; /* number of files processed */
ARCHD archd;
+static char cwdpath[MAXPATHLEN]; /* current working directory path */
+static size_t cwdpathlen; /* current working directory path len */
+
+int
+updatepath(void)
+{
+ if (getcwd(cwdpath, sizeof(cwdpath)) == NULL) {
+ syswarn(1, errno, "Cannot get working directory");
+ return -1;
+ }
+ cwdpathlen = strlen(cwdpath);
+ return 0;
+}
+
+int
+fdochdir(int fcwd)
+{
+ if (fchdir(fcwd) == -1) {
+ syswarn(1, errno, "Cannot chdir to `.'");
+ return -1;
+ }
+ return updatepath();
+}
+
+int
+dochdir(const char *name)
+{
+ if (chdir(name) == -1)
+ syswarn(1, errno, "Cannot chdir to `%s'", name);
+ return updatepath();
+}
+
+#if !HAVE_NBTOOL_CONFIG_H
+#ifdef HAVE_FCHROOT
+static int
+fdochroot(int fcwd)
+{
+ if (fchroot(fcwd) != 0) {
+ syswarn(1, errno, "Can't fchroot to \".\"");
+ return -1;
+ }
+ return updatepath();
+}
+#endif /* HAVE_FCHROOT */
+#endif
+
+/*
+ * mkdir(), but if we failed, check if someone else made it for us
+ * already and don't error out.
+ */
+int
+domkdir(const char *fname, mode_t mode)
+{
+ int error;
+ struct stat sb;
+
+ if ((error = mkdir(fname, mode)) != -1)
+ return error;
+
+ switch (errno) {
+ case EISDIR:
+ return 0;
+ case EEXIST:
+ error = errno;
+ if (stat(fname, &sb) != -1 && S_ISDIR(sb.st_mode))
+ return 0;
+ errno = error;
+ /*FALLTHROUGH*/
+ default:
+ return -1;
+ }
+}
+
+static int
+path_check(ARCHD *arcn, int level)
+{
+ char buf[MAXPATHLEN];
+ char *p;
+
+ if ((p = strrchr(arcn->name, '/')) == NULL)
+ return 0;
+ *p = '\0';
+
+ if (realpath(arcn->name, buf) == NULL) {
+ int error;
+ error = path_check(arcn, level + 1);
+ *p = '/';
+ if (error == 0)
+ return 0;
+ if (level == 0)
+ syswarn(1, 0, "Cannot resolve `%s'", arcn->name);
+ return -1;
+ }
+ if (strncmp(buf, cwdpath, cwdpathlen) != 0) {
+ *p = '/';
+ syswarn(1, 0, "Attempt to write file `%s' that resolves into "
+ "`%s/%s' outside current working directory `%s' ignored",
+ arcn->name, buf, p + 1, cwdpath);
+ return -1;
+ }
+ *p = '/';
+ return 0;
+}
+
/*
* list()
* list the contents of an archive which match user supplied pattern(s)
@@ -144,15 +254,11 @@ list(void)
* we need to read, to get the real filename
*/
off_t cnt;
- if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF
- ? -1 : -2, &cnt))
+ if (!(*frmt->rd_data)(arcn, -arcn->type, &cnt))
(void)rd_skip(cnt + arcn->pad);
continue;
}
- if (arcn->name[0] == '/' && !check_Aflag()) {
- memmove(arcn->name, arcn->name + 1, strlen(arcn->name));
- }
/*
* check for pattern, and user specified options match.
* When all patterns are matched we are done.
@@ -173,8 +279,22 @@ list(void)
*/
if ((res = mod_name(arcn)) < 0)
break;
- if (res == 0)
+ if (res == 0) {
+ if (arcn->name[0] == '/' && !check_Aflag()) {
+ memmove(arcn->name, arcn->name + 1,
+ strlen(arcn->name));
+ }
ls_list(arcn, now, stdout);
+ }
+ /*
+ * if there's an error writing to stdout then we must
+ * stop now -- we're probably writing to a pipe that
+ * has been closed by the reader.
+ */
+ if (ferror(stdout)) {
+ syswarn(1, errno, "Listing incomplete.");
+ break;
+ }
}
/*
* skip to next archive format header using values calculated
@@ -221,6 +341,12 @@ extract(void)
return;
now = time((time_t *)NULL);
+#if !HAVE_NBTOOL_CONFIG_H
+#ifdef HAVE_FCHROOT
+ if (do_chroot)
+ (void)fdochroot(cwdfd);
+#endif /* HAVE_FCHROOT */
+#endif
/*
* When we are doing interactive rename, we store the mapping of names
@@ -234,19 +360,17 @@ extract(void)
* says it is done
*/
while (next_head(arcn) == 0) {
+ int write_to_hard_link = 0;
+
if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
/*
* we need to read, to get the real filename
*/
- if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF
- ? -1 : -2, &cnt))
+ if (!(*frmt->rd_data)(arcn, -arcn->type, &cnt))
(void)rd_skip(cnt + arcn->pad);
continue;
}
- if (arcn->name[0] == '/' && !check_Aflag()) {
- memmove(arcn->name, arcn->name + 1, strlen(arcn->name));
- }
/*
* check for pattern, and user specified options match. When
* all the patterns are matched we are done
@@ -264,6 +388,11 @@ extract(void)
continue;
}
+ if (kflag && (lstat(arcn->name, &sb) == 0)) {
+ (void)rd_skip(arcn->skip + arcn->pad);
+ continue;
+ }
+
/*
* with -u or -D only extract when the archive member is newer
* than the file with the same name in the file system (no
@@ -306,6 +435,9 @@ extract(void)
continue;
}
+ if (arcn->name[0] == '/' && !check_Aflag()) {
+ memmove(arcn->name, arcn->name + 1, strlen(arcn->name));
+ }
/*
* Non standard -Y and -Z flag. When the existing file is
* same age or newer skip; ignore this for GNU long links.
@@ -342,32 +474,40 @@ extract(void)
*/
if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL) &&
!to_stdout)
- if (chdir(arcn->pat->chdname) != 0)
- syswarn(1, errno, "Cannot chdir to %s",
- arcn->pat->chdname);
+ dochdir(arcn->pat->chdname);
+
+ if (secure && path_check(arcn, 0) != 0) {
+ (void)rd_skip(arcn->skip + arcn->pad);
+ continue;
+ }
+
+
/*
* all ok, extract this member based on type
*/
- if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) {
+ if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) {
/*
* process archive members that are not regular files.
* throw out padding and any data that might follow the
* header (as determined by the format).
*/
- if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
- res = lnk_creat(arcn);
+ if ((arcn->type == PAX_HLK) ||
+ (arcn->type == PAX_HRG))
+ res = lnk_creat(arcn, &write_to_hard_link);
else
res = node_creat(arcn);
- (void)rd_skip(arcn->skip + arcn->pad);
- if (res < 0)
- purg_lnk(arcn);
+ if (!write_to_hard_link) {
+ (void)rd_skip(arcn->skip + arcn->pad);
+ if (res < 0)
+ purg_lnk(arcn);
- if (vflag && vfpart) {
- (void)putc('\n', listf);
- vfpart = 0;
+ if (vflag && vfpart) {
+ (void)putc('\n', listf);
+ vfpart = 0;
+ }
+ continue;
}
- continue;
}
if (to_stdout)
fd = STDOUT_FILENO;
@@ -377,7 +517,7 @@ extract(void)
* it, skip over the data and purge the name from hard
* link table.
*/
- if ((fd = file_creat(arcn)) < 0) {
+ if ((fd = file_creat(arcn, write_to_hard_link)) < 0) {
(void)fflush(listf);
(void)rd_skip(arcn->skip + arcn->pad);
purg_lnk(arcn);
@@ -402,9 +542,7 @@ extract(void)
* if required, chdir around.
*/
if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
- if (fchdir(cwdfd) != 0)
- syswarn(1, errno,
- "Can't fchdir to starting directory");
+ fdochdir(cwdfd);
}
/*
@@ -509,9 +647,6 @@ wr_archive(ARCHD *arcn, int is_app)
}
}
- if (arcn->name[0] == '/' && !check_Aflag()) {
- memmove(arcn->name, arcn->name + 1, strlen(arcn->name));
- }
/*
* Now modify the name as requested by the user
*/
@@ -525,6 +660,10 @@ wr_archive(ARCHD *arcn, int is_app)
break;
}
+ if (arcn->name[0] == '/' && !check_Aflag()) {
+ memmove(arcn->name, arcn->name + 1, strlen(arcn->name));
+ }
+
if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) {
/*
* unable to obtain the crc we need, close the file,
@@ -965,10 +1104,14 @@ copy(void)
/*
* create a link or special file
*/
- if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
- res = lnk_creat(arcn);
- else
+ if ((arcn->type == PAX_HLK) ||
+ (arcn->type == PAX_HRG)) {
+ int payload;
+
+ res = lnk_creat(arcn, &payload);
+ } else {
res = node_creat(arcn);
+ }
if (res < 0)
purg_lnk(arcn);
if (vflag && vfpart) {
@@ -988,7 +1131,7 @@ copy(void)
purg_lnk(arcn);
continue;
}
- if ((fddest = file_creat(arcn)) < 0) {
+ if ((fddest = file_creat(arcn, 0)) < 0) {
rdfile_close(arcn, &fdsrc);
purg_lnk(arcn);
continue;
diff --git a/archivers/pax/files/buf_subs.c b/archivers/pax/files/buf_subs.c
index 39be14e91c7..5816491d974 100644
--- a/archivers/pax/files/buf_subs.c
+++ b/archivers/pax/files/buf_subs.c
@@ -1,4 +1,4 @@
-/* $NetBSD: buf_subs.c,v 1.5 2004/08/21 03:28:56 jlam Exp $ */
+/* $NetBSD: buf_subs.c,v 1.6 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -48,7 +48,7 @@
#if 0
static char sccsid[] = "@(#)buf_subs.c 8.2 (Berkeley) 4/18/94";
#else
-__RCSID("$NetBSD: buf_subs.c,v 1.5 2004/08/21 03:28:56 jlam Exp $");
+__RCSID("$NetBSD: buf_subs.c,v 1.6 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
@@ -771,7 +771,7 @@ rd_wrfile(ARCHD *arcn, int ofd, off_t *left)
* written. just closing with the file offset moved forward may not put
* a hole at the end of the file.
*/
- if (ofd != -1 && isem && (arcn->sb.st_size > 0L))
+ if (ofd >= 0 && isem && (arcn->sb.st_size > 0L))
file_flush(ofd, fnm, isem);
/*
@@ -911,10 +911,13 @@ buf_fill(void)
/*
* errors require resync, EOF goes to next archive
+ * but in case we have not determined yet the format,
+ * this means that we have a very short file, so we
+ * are done again.
*/
if (cnt < 0)
break;
- if (ar_next() < 0) {
+ if (frmt == NULL || ar_next() < 0) {
fini = 1;
return(0);
}
diff --git a/archivers/pax/files/config.h.in b/archivers/pax/files/config.h.in
index 973056817bc..9f7df695669 100644
--- a/archivers/pax/files/config.h.in
+++ b/archivers/pax/files/config.h.in
@@ -17,6 +17,9 @@
/* Define to 1 if you have the <err.h> header file. */
#undef HAVE_ERR_H
+/* Define to 1 if you have the `fchroot' function. */
+#undef HAVE_FCHROOT
+
/* Define to 1 if you have the <fnctl.h> header file. */
#undef HAVE_FNCTL_H
diff --git a/archivers/pax/files/configure b/archivers/pax/files/configure
index ef66033ab27..b259b0b6536 100755
--- a/archivers/pax/files/configure
+++ b/archivers/pax/files/configure
@@ -3516,7 +3516,8 @@ fi
# Checks for library functions.
-for ac_func in lutimes
+
+for ac_func in fchroot lutimes
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5
diff --git a/archivers/pax/files/configure.ac b/archivers/pax/files/configure.ac
index 5a4fa132b3b..ef2349665c0 100644
--- a/archivers/pax/files/configure.ac
+++ b/archivers/pax/files/configure.ac
@@ -30,7 +30,7 @@ AH_BOTTOM([/* Define to 1 if the user- and root-changeable masks were detected *
])
# Checks for library functions.
-AC_CHECK_FUNCS([lutimes])
+AC_CHECK_FUNCS([fchroot lutimes])
AC_CHECK_FUNCS([getrlimit setrlimit])
AC_CONFIG_FILES([Makefile])
diff --git a/archivers/pax/files/cpio.1 b/archivers/pax/files/cpio.1
index c17e6a5df6c..7d94de6a918 100644
--- a/archivers/pax/files/cpio.1
+++ b/archivers/pax/files/cpio.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: cpio.1,v 1.2 2004/06/20 10:11:02 grant Exp $
+.\" $NetBSD: cpio.1,v 1.3 2005/12/01 03:00:01 minskim Exp $
.\"
.\" Copyright (c) 1997 SigmaSoft, Th. Lockert
.\" All rights reserved.
@@ -11,11 +11,6 @@
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by SigmaSoft, Th. Lockert.
-.\" 4. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -256,7 +251,7 @@ files that contain
can be processed.
.El
.El
-.Sh ERRORS
+.Sh EXIT STATUS
.Nm
will exit with one of the following values:
.Bl -tag -width 2n
diff --git a/archivers/pax/files/cpio.c b/archivers/pax/files/cpio.c
index 014f74d48da..53c546739fa 100644
--- a/archivers/pax/files/cpio.c
+++ b/archivers/pax/files/cpio.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cpio.c,v 1.4 2004/08/21 03:28:56 jlam Exp $ */
+/* $NetBSD: cpio.c,v 1.5 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -48,7 +48,7 @@
#if 0
static char sccsid[] = "@(#)cpio.c 8.1 (Berkeley) 5/31/93";
#else
-__RCSID("$NetBSD: cpio.c,v 1.4 2004/08/21 03:28:56 jlam Exp $");
+__RCSID("$NetBSD: cpio.c,v 1.5 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
@@ -490,8 +490,7 @@ cpio_wr(ARCHD *arcn)
* if this file has data, we are done. The caller will write the file
* data, if we are link tell caller we are done, go to next file
*/
- if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
- (arcn->type == PAX_HRG))
+ if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
return(0);
if (arcn->type != PAX_SLK)
return(1);
diff --git a/archivers/pax/files/extern.h b/archivers/pax/files/extern.h
index 66fb75a8742..c6f44633fb8 100644
--- a/archivers/pax/files/extern.h
+++ b/archivers/pax/files/extern.h
@@ -1,4 +1,4 @@
-/* $NetBSD: extern.h,v 1.5 2004/06/20 10:11:02 grant Exp $ */
+/* $NetBSD: extern.h,v 1.6 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -83,13 +83,17 @@ int ar_fow(off_t, off_t *);
int ar_rev(off_t );
int ar_next(void);
void ar_summary(int);
-int ar_dochdir(char *);
+int ar_dochdir(const char *);
/*
* ar_subs.c
*/
extern u_long flcnt;
extern ARCHD archd;
+int updatepath(void);
+int dochdir(const char *);
+int fdochdir(int);
+int domkdir(const char *, mode_t);
void list(void);
void extract(void);
void append(void);
@@ -151,10 +155,11 @@ int bcpio_wr(ARCHD *);
* file_subs.c
*/
extern char *gnu_name_string, *gnu_link_string;
+extern size_t gnu_name_length, gnu_link_length;
extern char *xtmp_name;
-int file_creat(ARCHD *);
+int file_creat(ARCHD *, int);
void file_close(ARCHD *, int);
-int lnk_creat(ARCHD *);
+int lnk_creat(ARCHD *, int *);
int cross_lnk(ARCHD *);
int chk_same(ARCHD *);
int node_creat(ARCHD *);
@@ -210,6 +215,11 @@ int opt_add(const char *);
int bad_opt(void);
int mkpath(char *);
char *chdname;
+#if !HAVE_NBTOOL_CONFIG_H
+#ifdef HAVE_FCHROOT
+int do_chroot;
+#endif /* HAVE_FCHROOT */
+#endif
/*
* pat_rep.c
diff --git a/archivers/pax/files/file_subs.c b/archivers/pax/files/file_subs.c
index 545b182b880..55495e8f94d 100644
--- a/archivers/pax/files/file_subs.c
+++ b/archivers/pax/files/file_subs.c
@@ -1,4 +1,4 @@
-/* $NetBSD: file_subs.c,v 1.10 2004/08/21 04:20:50 jlam Exp $ */
+/* $NetBSD: file_subs.c,v 1.11 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -48,7 +48,7 @@
#if 0
static char sccsid[] = "@(#)file_subs.c 8.1 (Berkeley) 5/31/93";
#else
-__RCSID("$NetBSD: file_subs.c,v 1.10 2004/08/21 04:20:50 jlam Exp $");
+__RCSID("$NetBSD: file_subs.c,v 1.11 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
@@ -122,7 +122,7 @@ static int warn_broken;
*/
int
-file_creat(ARCHD *arcn)
+file_creat(ARCHD *arcn, int write_to_hardlink)
{
int fd = -1;
int oerrno;
@@ -142,6 +142,19 @@ file_creat(ARCHD *arcn)
}
return -1;
}
+
+ /*
+ * In "cpio" archives it's usually the last record of a set of
+ * hardlinks which includes the contents of the file. We cannot
+ * use a tempory file in that case because we couldn't link it
+ * with the existing other hardlinks after restoring the contents
+ * to it. And it's also useless to create the hardlink under a
+ * temporary name because the other hardlinks would have partial
+ * contents while restoring.
+ */
+ if (write_to_hardlink)
+ return (open(arcn->name, O_TRUNC | O_EXCL | O_RDWR, 0));
+
/*
* Create a temporary file name so that the file doesn't have partial
* contents while restoring.
@@ -151,7 +164,7 @@ file_creat(ARCHD *arcn)
syswarn(1, errno, "Cannot malloc %d bytes", arcn->nlen + 8);
return(-1);
}
- if (xtmp_name)
+ if (xtmp_name != NULL)
abort();
xtmp_name = arcn->tmp_name;
@@ -191,13 +204,17 @@ file_creat(ARCHD *arcn)
void
file_close(ARCHD *arcn, int fd)
{
- int res = 0;
+ char *tmp_name;
+ int res;
if (fd < 0)
return;
+
+ tmp_name = (arcn->tmp_name != NULL) ? arcn->tmp_name : arcn->name;
+
if (close(fd) < 0)
syswarn(0, errno, "Cannot close file descriptor on %s",
- arcn->tmp_name);
+ tmp_name);
/*
* set owner/groups first as this may strip off mode bits we want
@@ -205,7 +222,9 @@ file_close(ARCHD *arcn, int fd)
* modification times.
*/
if (pids)
- res = set_ids(arcn->tmp_name, arcn->sb.st_uid, arcn->sb.st_gid);
+ res = set_ids(tmp_name, arcn->sb.st_uid, arcn->sb.st_gid);
+ else
+ res = 0;
/*
* IMPORTANT SECURITY NOTE:
@@ -215,19 +234,24 @@ file_close(ARCHD *arcn, int fd)
if (!pmode || res)
arcn->sb.st_mode &= ~SETBITS(0);
if (pmode)
- set_pmode(arcn->tmp_name, arcn->sb.st_mode);
+ set_pmode(tmp_name, arcn->sb.st_mode);
else
- set_pmode(arcn->tmp_name, arcn->sb.st_mode & FILEBITS(0));
+ set_pmode(tmp_name, arcn->sb.st_mode & FILEBITS(0));
if (patime || pmtime)
- set_ftime(arcn->tmp_name, arcn->sb.st_mtime, arcn->sb.st_atime, 0);
+ set_ftime(tmp_name, arcn->sb.st_mtime, arcn->sb.st_atime, 0);
+
+ /* Did we write directly to the target file? */
+ if (arcn->tmp_name == NULL)
+ return;
+
/*
* Finally, now the temp file is fully instantiated rename it to
* the desired file name.
*/
- if (rename(arcn->tmp_name, arcn->name) < 0) {
+ if (rename(tmp_name, arcn->name) < 0) {
syswarn(0, errno, "Cannot rename %s to %s",
- arcn->tmp_name, arcn->name);
- (void)unlink(arcn->tmp_name);
+ tmp_name, arcn->name);
+ (void)unlink(tmp_name);
}
#if HAVE_FILE_FLAGS
@@ -249,12 +273,21 @@ file_close(ARCHD *arcn, int fd)
*/
int
-lnk_creat(ARCHD *arcn)
+lnk_creat(ARCHD *arcn, int *payload)
{
struct stat sb;
/*
- * we may be running as root, so we have to be sure that link target
+ * Check if this hardlink carries the "payload". In "cpio" archives
+ * it's usually the last record of a set of hardlinks which includes
+ * the contents of the file.
+ *
+ */
+ *payload = S_ISREG(arcn->sb.st_mode) &&
+ (arcn->sb.st_size > 0) && (arcn->sb.st_size <= arcn->skip);
+
+ /*
+ * We may be running as root, so we have to be sure that link target
* is not a directory, so we lstat and check
*/
if (lstat(arcn->ln_name, &sb) < 0) {
@@ -461,8 +494,7 @@ node_creat(ARCHD *arcn)
nm = target;
}
}
- res = mkdir(nm, file_mode);
-
+ res = domkdir(nm, file_mode);
badlink:
if (ign)
res = 0;
@@ -717,7 +749,7 @@ chk_path(char *name, uid_t st_uid, gid_t st_gid)
* the path fails at this point, see if we can create the
* needed directory and continue on
*/
- if (mkdir(name, S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
+ if (domkdir(name, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
*spt = '/';
retval = -1;
break;
@@ -747,7 +779,14 @@ chk_path(char *name, uid_t st_uid, gid_t st_gid)
*(spt++) = '/';
continue;
}
- return(retval);
+ /*
+ * We perform one final check here, because if someone else
+ * created the directory in parallel with us, we might return
+ * the wrong error code, even if the directory exists now.
+ */
+ if (retval == -1 && stat(name, &sb) == 0 && S_ISDIR(sb.st_mode))
+ retval = 0;
+ return retval;
}
/*
@@ -914,6 +953,7 @@ file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz,
int wcnt;
char *st = str;
char **strp;
+ size_t *lenp;
/*
* while we have data to process
@@ -973,26 +1013,29 @@ file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz,
* have non-zero data in this file system block, have to write
*/
switch (fd) {
- case -1:
+ case -PAX_GLF:
strp = &gnu_name_string;
+ lenp = &gnu_name_length;
break;
- case -2:
+ case -PAX_GLL:
strp = &gnu_link_string;
+ lenp = &gnu_link_length;
break;
default:
strp = NULL;
+ lenp = NULL;
break;
}
if (strp) {
- if (*strp)
- err(1, "WARNING! Major Internal Error! GNU hack Failing!");
- *strp = malloc(wcnt + 1);
- if (*strp == NULL) {
+ char *nstr = *strp ? realloc(*strp, *lenp + wcnt + 1) :
+ malloc(wcnt + 1);
+ if (nstr == NULL) {
tty_warn(1, "Out of memory");
return(-1);
}
- strlcpy(*strp, st, wcnt);
- break;
+ (void)strlcpy(&nstr[*lenp], st, wcnt + 1);
+ *strp = nstr;
+ *lenp += wcnt;
} else if (xwrite(fd, st, wcnt) != wcnt) {
syswarn(1, errno, "Failed write to file %s", name);
return(-1);
diff --git a/archivers/pax/files/ftree.c b/archivers/pax/files/ftree.c
index 4a0177144f6..e402382d615 100644
--- a/archivers/pax/files/ftree.c
+++ b/archivers/pax/files/ftree.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ftree.c,v 1.8 2004/08/21 04:20:50 jlam Exp $ */
+/* $NetBSD: ftree.c,v 1.9 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -84,7 +84,7 @@
#if 0
static char sccsid[] = "@(#)ftree.c 8.2 (Berkeley) 4/18/94";
#else
-__RCSID("$NetBSD: ftree.c,v 1.8 2004/08/21 04:20:50 jlam Exp $");
+__RCSID("$NetBSD: ftree.c,v 1.9 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
@@ -774,7 +774,8 @@ next_file(ARCHD *arcn)
* copy file name, set file name length
*/
arcn->nlen = strlcpy(arcn->name, ftent->fts_path, sizeof(arcn->name));
- arcn->org_name = ftent->fts_path;
+ arcn->org_name = arcn->fts_name;
+ strlcpy(arcn->fts_name, ftent->fts_path, sizeof arcn->fts_name);
if (strcmp(NM_CPIO, argv0) == 0) {
/*
* cpio does *not* descend directories listed in the
diff --git a/archivers/pax/files/getoldopt.c b/archivers/pax/files/getoldopt.c
index 0468ae919db..e79da32b4af 100644
--- a/archivers/pax/files/getoldopt.c
+++ b/archivers/pax/files/getoldopt.c
@@ -1,4 +1,4 @@
-/* $NetBSD: getoldopt.c,v 1.5 2004/08/21 03:28:56 jlam Exp $ */
+/* $NetBSD: getoldopt.c,v 1.6 2005/12/01 03:00:01 minskim Exp $ */
/*
* Plug-compatible replacement for getopt() for parsing tar-like
@@ -21,7 +21,7 @@
#include <sys/cdefs.h>
#endif
#if !defined(lint)
-__RCSID("$NetBSD: getoldopt.c,v 1.5 2004/08/21 03:28:56 jlam Exp $");
+__RCSID("$NetBSD: getoldopt.c,v 1.6 2005/12/01 03:00:01 minskim Exp $");
#endif /* not lint */
#if HAVE_NBTOOL_CONFIG_H
@@ -69,6 +69,7 @@ getoldopt(int argc, char **argv, const char *optstring,
optind = 2;
}
+ c = '\0';
if (!use_getopt) {
c = *key++;
if (c == '\0') {
diff --git a/archivers/pax/files/options.c b/archivers/pax/files/options.c
index 6f63150eaeb..f3293bb0d5b 100644
--- a/archivers/pax/files/options.c
+++ b/archivers/pax/files/options.c
@@ -1,4 +1,4 @@
-/* $NetBSD: options.c,v 1.7 2004/08/21 03:28:56 jlam Exp $ */
+/* $NetBSD: options.c,v 1.8 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -48,7 +48,7 @@
#if 0
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94";
#else
-__RCSID("$NetBSD: options.c,v 1.7 2004/08/21 03:28:56 jlam Exp $");
+__RCSID("$NetBSD: options.c,v 1.8 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
@@ -125,8 +125,10 @@ static void pax_options(int, char **);
static void pax_usage(void);
static void tar_options(int, char **);
static void tar_usage(void);
+#ifndef NO_CPIO
static void cpio_options(int, char **);
static void cpio_usage(void);
+#endif
/* errors from getline */
#define GETLINE_FILE_CORRUPT 1
@@ -156,6 +158,12 @@ static int getline_error;
#define OPT_FORCE_LOCAL 13
#define OPT_INSECURE 14
#define OPT_STRICT 15
+#define OPT_SPARSE 16
+#if !HAVE_NBTOOL_CONFIG_H
+#ifdef HAVE_FCHROOT
+#define OPT_CHROOT 17
+#endif /* HAVE_FCHROOT */
+#endif
/*
* Format specific routine table - MUST BE IN SORTED ORDER BY NAME
@@ -163,10 +171,11 @@ static int getline_error;
*
* name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
* read, end_read, st_write, write, end_write, trail,
- * rd_data, wr_data, options
+ * subtrail, rd_data, wr_data, options
*/
FSUB fsub[] = {
+#ifndef NO_CPIO
/* 0: OLD BINARY CPIO */
{ "bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, NULL,
@@ -186,7 +195,7 @@ FSUB fsub[] = {
{ "sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, NULL,
cpio_subtrail, rd_wrfile, wr_rdfile, bad_opt },
-
+#endif
/* 4: OLD TAR */
{ "tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
@@ -197,12 +206,17 @@ FSUB fsub[] = {
ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
NULL, rd_wrfile, wr_rdfile, bad_opt }
};
+#ifndef NO_CPIO
#define F_BCPIO 0 /* old binary cpio format */
#define F_CPIO 1 /* old octal character cpio format */
#define F_SV4CPIO 2 /* SVR4 hex cpio format */
#define F_SV4CRC 3 /* SVR4 hex with crc cpio format */
#define F_TAR 4 /* old V7 UNIX tar format */
#define F_USTAR 5 /* ustar format */
+#else
+#define F_TAR 0 /* old V7 UNIX tar format */
+#define F_USTAR 1 /* ustar format */
+#endif
#define DEFLT F_USTAR /* default write format from list above */
/*
@@ -210,7 +224,11 @@ FSUB fsub[] = {
* of archive we are dealing with. This helps to properly id archive formats
* some formats may be subsets of others....
*/
-int ford[] = {F_USTAR, F_TAR, F_SV4CRC, F_SV4CPIO, F_CPIO, F_BCPIO, -1};
+int ford[] = {F_USTAR, F_TAR,
+#ifndef NO_CPIO
+ F_SV4CRC, F_SV4CPIO, F_CPIO, F_BCPIO,
+#endif
+ -1};
/*
* filename record separator
@@ -235,11 +253,15 @@ options(int argc, char **argv)
else
argv0 = argv[0];
- if (strcmp(NM_TAR, argv0) == 0)
+ if (strstr(argv0, NM_TAR)) {
+ argv0 = NM_TAR;
tar_options(argc, argv);
- else if (strcmp(NM_CPIO, argv0) == 0)
+#ifndef NO_CPIO
+ } else if (strstr(argv0, NM_CPIO)) {
+ argv0 = NM_CPIO;
cpio_options(argc, argv);
- else {
+#endif
+ } else {
argv0 = NM_PAX;
pax_options(argc, argv);
}
@@ -250,6 +272,7 @@ struct option pax_longopts[] = {
OPT_INSECURE },
{ "force-local", no_argument, 0,
OPT_FORCE_LOCAL },
+ { 0, 0, 0 },
};
/*
@@ -704,7 +727,7 @@ pax_options(int argc, char **argv)
--argc;
dirptr = argv[argc];
if (mkpath(dirptr) < 0)
- pax_usage();
+ exit(1);
/* FALLTHROUGH */
case ARCHIVE:
case APPND:
@@ -757,6 +780,7 @@ struct option tar_longopts[] = {
{ "directory", required_argument, 0, 'C' },
{ "to-stdout", no_argument, 0, 'O' },
{ "absolute-paths", no_argument, 0, 'P' },
+ { "sparse", no_argument, 0, 'S' },
{ "files-from", required_argument, 0, 'T' },
{ "exclude-from", required_argument, 0, 'X' },
{ "compress", no_argument, 0, 'Z' },
@@ -775,6 +799,14 @@ struct option tar_longopts[] = {
OPT_INSECURE },
{ "exclude", required_argument, 0,
OPT_EXCLUDE },
+ { "no-recursion", no_argument, 0,
+ OPT_NORECURSE },
+#if !HAVE_NBTOOL_CONFIG_H
+#ifdef HAVE_FCHROOT
+ { "chroot", no_argument, 0,
+ OPT_CHROOT },
+#endif /* HAVE_FCHROOT */
+#endif
#if 0 /* Not implemented */
{ "catenate", no_argument, 0, 'A' }, /* F */
{ "concatenate", no_argument, 0, 'A' }, /* F */
@@ -801,7 +833,6 @@ struct option tar_longopts[] = {
OPT_REMOVE_FILES },
{ "same-order", no_argument, 0, 's' },
{ "preserve-order", no_argument, 0, 's' },
- { "sparse", no_argument, 0, 'S' },
{ "null", no_argument, 0,
OPT_NULL },
{ "totals", no_argument, 0,
@@ -813,8 +844,6 @@ struct option tar_longopts[] = {
{ "verify", no_argument, 0, 'W' },
{ "block-compress", no_argument, 0,
OPT_BLOCK_COMPRESS },
- { "norecurse", no_argument, 0,
- OPT_NORECURSE },
#endif
{ 0, 0, 0, 0 },
};
@@ -843,7 +872,7 @@ tar_options(int argc, char **argv)
* process option flags
*/
while ((c = getoldopt(argc, argv,
- "+b:cef:hjklmopqrs:tuvwxzBC:HI:OPT:X:Z014578",
+ "+b:cef:hjklmopqrs:tuvwxzBC:HI:OPST:X:Z014578",
tar_longopts, NULL))
!= -1) {
switch(c) {
@@ -1038,6 +1067,9 @@ tar_options(int argc, char **argv)
rmleadslash = 0;
Aflag = 1;
break;
+ case 'S':
+ /* do nothing; we already generate sparse files */
+ break;
case 'X':
/*
* GNU tar compat: exclude the files listed in optarg
@@ -1094,6 +1126,16 @@ tar_options(int argc, char **argv)
if (tar_gnutar_minus_minus_exclude(optarg) != 0)
tar_usage();
break;
+ case OPT_NORECURSE:
+ dflag = 1;
+ break;
+#if !HAVE_NBTOOL_CONFIG_H
+#ifdef HAVE_FCHROOT
+ case OPT_CHROOT:
+ do_chroot = 1;
+ break;
+#endif /* HAVE_FCHROOT */
+#endif
default:
tar_usage();
break;
@@ -1161,8 +1203,10 @@ tar_options(int argc, char **argv)
break;
file = *argv++;
dir = chdname;
- } else
+ } else {
file = NULL;
+ dir = NULL;
+ }
if (file != NULL) {
FILE *fp;
char *str;
@@ -1183,6 +1227,10 @@ tar_options(int argc, char **argv)
dirisnext = 1;
continue;
}
+ if (strncmp(str, "-C ", 3) == 0) {
+ dir = str + 3;
+ continue;
+ }
if (pat_add(str, dir) < 0)
tar_usage();
sawpat = 1;
@@ -1240,8 +1288,10 @@ tar_options(int argc, char **argv)
break;
file = *argv++;
dir = NULL;
- } else
+ } else {
file = NULL;
+ dir = NULL;
+ }
if (file != NULL) {
FILE *fp;
char *str;
@@ -1270,6 +1320,11 @@ tar_options(int argc, char **argv)
dirisnext = 1;
continue;
}
+ if (strncmp(str, "-C ", 3) == 0) {
+ if (ftree_add(str + 3, 1) < 0)
+ tar_usage();
+ continue;
+ }
if (ftree_add(str, 0) < 0)
tar_usage();
}
@@ -1308,7 +1363,6 @@ int
mkpath(path)
char *path;
{
- struct stat sb;
char *slash;
int done = 0;
@@ -1321,24 +1375,22 @@ mkpath(path)
done = (*slash == '\0');
*slash = '\0';
- if (stat(path, &sb)) {
- if (errno != ENOENT || mkdir(path, 0777)) {
- tty_warn(1, "%s", path);
- return (-1);
- }
- } else if (!S_ISDIR(sb.st_mode)) {
- syswarn(1, ENOTDIR, "%s", path);
- return (-1);
- }
+ if (domkdir(path, 0777) == -1)
+ goto out;
if (!done)
*slash = '/';
}
- return (0);
+ return 0;
+out:
+ /* Can't create or or not a directory */
+ syswarn(1, errno, "Cannot create directory `%s'", path);
+ return -1;
}
+#ifndef NO_CPIO
struct option cpio_longopts[] = {
{ "reset-access-time", no_argument, 0, 'a' },
{ "make-directories", no_argument, 0, 'd' },
@@ -1362,6 +1414,8 @@ struct option cpio_longopts[] = {
{ "swap-halfwords", no_argument, 0, 'S' },
{ "insecure", no_argument, 0,
OPT_INSECURE },
+ { "sparse", no_argument, 0,
+ OPT_SPARSE },
#ifdef notyet
/* Not implemented */
@@ -1382,11 +1436,10 @@ struct option cpio_longopts[] = {
OPT_ONLY_VERIFY_CRC },
{ "rsh-command", required_argument, 0,
OPT_RSH_COMMAND },
- { "sparce", no_argument, 0,
- OPT_SPARSE },
{ "version", no_argument, 0,
OPT_VERSION },
#endif
+ { 0, 0, 0, 0 },
};
/*
@@ -1446,7 +1499,6 @@ cpio_options(int argc, char **argv)
* pax does this by default ..
*/
nodirs = 0;
- flg |= RF;
break;
case 'f':
/*
@@ -1515,6 +1567,7 @@ cpio_options(int argc, char **argv)
*/
act = LIST;
listf = stdout;
+ flg &= ~RF;
break;
case 'u':
/*
@@ -1651,6 +1704,10 @@ cpio_options(int argc, char **argv)
case OPT_INSECURE:
secure = 0;
break;
+
+ case OPT_SPARSE:
+ /* do nothing; we already generate sparse files */
+ break;
default:
cpio_usage();
break;
@@ -1733,6 +1790,7 @@ cpio_options(int argc, char **argv)
break;
}
}
+#endif
/*
* printflg()
@@ -1804,8 +1862,10 @@ bad_opt(void)
(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
if (strcmp(NM_TAR, argv0) == 0)
tar_usage();
+#ifndef NO_CPIO
else if (strcmp(NM_CPIO, argv0) == 0)
cpio_usage();
+#endif
else
pax_usage();
return(0);
@@ -2020,7 +2080,7 @@ pax_usage(void)
void
tar_usage(void)
{
- (void)fputs("usage: tar [-]{crtux}[-befhjlmopqvwzHLOPXZ014578] [archive] "
+ (void)fputs("usage: tar [-]{crtux}[-befhjlmopqvwzHOPSXZ014578] [archive] "
"[blocksize]\n"
" [-C directory] [-T file] [-s replstr] "
"[file ...]\n", stderr);
@@ -2028,6 +2088,7 @@ tar_usage(void)
/* NOTREACHED */
}
+#ifndef NO_CPIO
/*
* cpio_usage()
* print the usage summary to the user
@@ -2049,3 +2110,4 @@ cpio_usage(void)
exit(1);
/* NOTREACHED */
}
+#endif
diff --git a/archivers/pax/files/pat_rep.c b/archivers/pax/files/pat_rep.c
index 2c208fcb458..5e0c3529e71 100644
--- a/archivers/pax/files/pat_rep.c
+++ b/archivers/pax/files/pat_rep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pat_rep.c,v 1.4 2004/08/21 03:28:56 jlam Exp $ */
+/* $NetBSD: pat_rep.c,v 1.5 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -48,7 +48,7 @@
#if 0
static char sccsid[] = "@(#)pat_rep.c 8.2 (Berkeley) 4/18/94";
#else
-__RCSID("$NetBSD: pat_rep.c,v 1.4 2004/08/21 03:28:56 jlam Exp $");
+__RCSID("$NetBSD: pat_rep.c,v 1.5 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
@@ -139,7 +139,9 @@ rep_add(char *str)
char *pt1;
char *pt2;
REPLACE *rep;
-#ifndef NET2_REGEX
+#ifdef NET2_REGEX
+ static const char rebuf[] = "Error";
+#else
int res;
char rebuf[BUFSIZ];
#endif
@@ -164,7 +166,7 @@ rep_add(char *str)
if (*pt1 == *str)
break;
}
- if (pt1 == NULL) {
+ if (*pt1 == 0) {
tty_warn(1, "Invalid replacement string %s", str);
return(-1);
}
@@ -184,9 +186,9 @@ rep_add(char *str)
#else
if ((res = regcomp(&(rep->rcmp), str+1, 0)) != 0) {
regerror(res, &(rep->rcmp), rebuf, sizeof(rebuf));
+#endif
tty_warn(1, "%s while compiling regular expression %s", rebuf,
str);
-#endif
(void)free((char *)rep);
return(-1);
}
@@ -205,7 +207,7 @@ rep_add(char *str)
if (*pt2 == *str)
break;
}
- if (pt2 == NULL) {
+ if (*pt2 == 0) {
#ifdef NET2_REGEX
(void)free((char *)rep->rcmp);
#else
@@ -679,38 +681,6 @@ mod_name(ARCHD *arcn)
{
int res = 0;
- /*
- * Strip off leading '/' if appropriate.
- * Currently, this option is only set for the tar format.
- */
- if (rmleadslash && arcn->name[0] == '/') {
- if (arcn->name[1] == '\0') {
- arcn->name[0] = '.';
- } else {
- (void)memmove(arcn->name, &arcn->name[1],
- strlen(arcn->name));
- arcn->nlen--;
- }
- if (rmleadslash < 2) {
- rmleadslash = 2;
- tty_warn(0, "Removing leading / from absolute path names in the archive");
- }
- }
- if (rmleadslash && arcn->ln_name[0] == '/' &&
- (arcn->type == PAX_HLK || arcn->type == PAX_HRG)) {
- if (arcn->ln_name[1] == '\0') {
- arcn->ln_name[0] = '.';
- } else {
- (void)memmove(arcn->ln_name, &arcn->ln_name[1],
- strlen(arcn->ln_name));
- arcn->ln_nlen--;
- }
- if (rmleadslash < 2) {
- rmleadslash = 2;
- tty_warn(0, "Removing leading / from absolute path names in the archive");
- }
- }
-
if (secure) {
if (checkdotdot(arcn->name)) {
tty_warn(0, "Ignoring file containing `..' (%s)",
@@ -771,6 +741,39 @@ mod_name(ARCHD *arcn)
(arcn->type == PAX_HRG))
sub_name(arcn->ln_name, &(arcn->ln_nlen), sizeof(arcn->ln_name));
}
+
+ /*
+ * Strip off leading '/' if appropriate.
+ * Currently, this option is only set for the tar format.
+ */
+ if (rmleadslash && arcn->name[0] == '/') {
+ if (arcn->name[1] == '\0') {
+ arcn->name[0] = '.';
+ } else {
+ (void)memmove(arcn->name, &arcn->name[1],
+ strlen(arcn->name));
+ arcn->nlen--;
+ }
+ if (rmleadslash < 2) {
+ rmleadslash = 2;
+ tty_warn(0, "Removing leading / from absolute path names in the archive");
+ }
+ }
+ if (rmleadslash && arcn->ln_name[0] == '/' &&
+ (arcn->type == PAX_HLK || arcn->type == PAX_HRG)) {
+ if (arcn->ln_name[1] == '\0') {
+ arcn->ln_name[0] = '.';
+ } else {
+ (void)memmove(arcn->ln_name, &arcn->ln_name[1],
+ strlen(arcn->ln_name));
+ arcn->ln_nlen--;
+ }
+ if (rmleadslash < 2) {
+ rmleadslash = 2;
+ tty_warn(0, "Removing leading / from absolute path names in the archive");
+ }
+ }
+
return(res);
}
diff --git a/archivers/pax/files/pax.1 b/archivers/pax/files/pax.1
index 77a9a77ac4a..72955952e24 100644
--- a/archivers/pax/files/pax.1
+++ b/archivers/pax/files/pax.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: pax.1,v 1.4 2004/06/20 10:11:02 grant Exp $
+.\" $NetBSD: pax.1,v 1.5 2005/12/01 03:00:01 minskim Exp $
.\"
.\" Copyright (c) 1992 Keith Muller.
.\" Copyright (c) 1992, 1993
@@ -1174,6 +1174,51 @@ options are specified along with the
.Fl n
option, a file is not considered selected unless it is newer
than the file to which it is compared.
+.Sh EXIT STATUS
+.Nm
+will exit with one of the following values:
+.Bl -tag -width 2n
+.It 0
+All files were processed successfully.
+.It 1
+An error occurred.
+.El
+.Pp
+Whenever
+.Nm
+cannot create a file or a link when reading an archive or cannot
+find a file when writing an archive, or cannot preserve the user ID,
+group ID, or file mode when the
+.Fl p
+option is specified, a diagnostic message is written to
+.Dv standard error
+and a non-zero exit status will be returned, but processing will continue.
+In the case where pax cannot create a link to a file,
+.Nm
+will not create a second copy of the file.
+.Pp
+If the extraction of a file from an archive is prematurely terminated by
+a signal or error,
+.Nm
+may have only partially extracted a file the user wanted.
+Additionally, the file modes of extracted files and directories
+may have incorrect file bits, and the modification and access times may be
+wrong.
+.Pp
+If the creation of an archive is prematurely terminated by a signal or error,
+.Nm
+may have only partially created the archive which may violate the specific
+archive format specification.
+.Pp
+If while doing a
+.Em copy ,
+.Nm
+detects a file is about to overwrite itself, the file is not copied,
+a diagnostic message is written to
+.Dv standard error
+and when
+.Nm
+completes it will exit with a non-zero exit status.
.Sh EXAMPLES
The command:
.Dl pax -w -f /dev/rst0 \&.
@@ -1236,51 +1281,6 @@ will update (and list) only those files in the destination directory
which are older (less recent inode change or file modification times) than
files with the same name found in the source file tree
.Pa home .
-.Sh ERRORS
-.Nm
-will exit with one of the following values:
-.Bl -tag -width 2n
-.It 0
-All files were processed successfully.
-.It 1
-An error occurred.
-.El
-.Pp
-Whenever
-.Nm
-cannot create a file or a link when reading an archive or cannot
-find a file when writing an archive, or cannot preserve the user ID,
-group ID, or file mode when the
-.Fl p
-option is specified, a diagnostic message is written to
-.Dv standard error
-and a non-zero exit status will be returned, but processing will continue.
-In the case where pax cannot create a link to a file,
-.Nm
-will not create a second copy of the file.
-.Pp
-If the extraction of a file from an archive is prematurely terminated by
-a signal or error,
-.Nm
-may have only partially extracted a file the user wanted.
-Additionally, the file modes of extracted files and directories
-may have incorrect file bits, and the modification and access times may be
-wrong.
-.Pp
-If the creation of an archive is prematurely terminated by a signal or error,
-.Nm
-may have only partially created the archive which may violate the specific
-archive format specification.
-.Pp
-If while doing a
-.Em copy ,
-.Nm
-detects a file is about to overwrite itself, the file is not copied,
-a diagnostic message is written to
-.Dv standard error
-and when
-.Nm
-completes it will exit with a non-zero exit status.
.Sh SEE ALSO
.Xr cpio 1 ,
.Xr tar 1 ,
diff --git a/archivers/pax/files/pax.c b/archivers/pax/files/pax.c
index 01da438a287..b62439abd71 100644
--- a/archivers/pax/files/pax.c
+++ b/archivers/pax/files/pax.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pax.c,v 1.7 2004/08/21 03:28:56 jlam Exp $ */
+/* $NetBSD: pax.c,v 1.8 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -50,7 +50,7 @@ __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
#if 0
static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 4/18/94";
#else
-__RCSID("$NetBSD: pax.c,v 1.7 2004/08/21 03:28:56 jlam Exp $");
+__RCSID("$NetBSD: pax.c,v 1.8 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
@@ -107,7 +107,7 @@ static int gen_init(void);
int act = ERROR; /* read/write/append/copy */
FSUB *frmt = NULL; /* archive format type */
int cflag; /* match all EXCEPT pattern/file */
-int cwdfd; /* starting cwd */
+int cwdfd = -1; /* starting cwd */
int dflag; /* directory member match only */
int iflag; /* interactive file/archive rename */
int jflag; /* pass through bzip2 */
@@ -280,6 +280,17 @@ main(int argc, char **argv)
listf = stderr;
/*
+ * parse options, determine operational mode
+ */
+ options(argc, argv);
+
+ /*
+ * general init
+ */
+ if ((gen_init() < 0) || (tty_init() < 0))
+ return(exit_val);
+
+ /*
* Keep a reference to cwd, so we can always come back home.
*/
cwdfd = open(".", O_RDONLY);
@@ -287,6 +298,8 @@ main(int argc, char **argv)
syswarn(0, errno, "Can't open current working directory.");
return(exit_val);
}
+ if (updatepath() == -1)
+ return(exit_val);
/*
* Where should we put temporary files?
@@ -306,13 +319,6 @@ main(int argc, char **argv)
tempbase = tempfile + tdlen;
*tempbase++ = '/';
- /*
- * parse options, determine operational mode, general init
- */
- options(argc, argv);
- if ((gen_init() < 0) || (tty_init() < 0))
- return(exit_val);
-
(void)time(&starttime);
#ifdef SIGINFO
(void)signal(SIGINFO, ar_summary);
diff --git a/archivers/pax/files/pax.h b/archivers/pax/files/pax.h
index ce3b02333da..1c9ee13eddf 100644
--- a/archivers/pax/files/pax.h
+++ b/archivers/pax/files/pax.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pax.h,v 1.8 2004/08/21 03:28:56 jlam Exp $ */
+/* $NetBSD: pax.h,v 1.9 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -116,6 +116,7 @@ typedef struct {
int ln_nlen; /* link name length */
char ln_name[PAXPATHLEN+1]; /* name to link to (if any) */
char *org_name; /* orig name in file system */
+ char fts_name[PAXPATHLEN+1]; /* name from fts (for *org_name) */
char *tmp_name; /* tmp name used to restore */
PATTERN *pat; /* ptr to pattern match (if any) */
struct stat sb; /* stat buffer see stat(2) */
diff --git a/archivers/pax/files/tables.c b/archivers/pax/files/tables.c
index 0545671e184..8b675ca2b00 100644
--- a/archivers/pax/files/tables.c
+++ b/archivers/pax/files/tables.c
@@ -1,4 +1,4 @@
-/* $NetBSD: tables.c,v 1.5 2004/08/21 04:20:50 jlam Exp $ */
+/* $NetBSD: tables.c,v 1.6 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -48,7 +48,7 @@
#if 0
static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 5/31/93";
#else
-__RCSID("$NetBSD: tables.c,v 1.5 2004/08/21 04:20:50 jlam Exp $");
+__RCSID("$NetBSD: tables.c,v 1.6 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
@@ -97,13 +97,13 @@ __RCSID("$NetBSD: tables.c,v 1.5 2004/08/21 04:20:50 jlam Exp $");
* keeps. Tables are dynamically created only when they are needed. The
* goal was speed and the ability to work with HUGE archives. The databases
* were kept simple, but do have complex rules for when the contents change.
- * As of this writing, the posix library functions were more complex than
+ * As of this writing, the POSIX library functions were more complex than
* needed for this application (pax databases have very short lifetimes and
* do not survive after pax is finished). Pax is required to handle very
* large archives. These database routines carefully combine memory usage and
* temporary file storage in ways which will not significantly impact runtime
* performance while allowing the largest possible archives to be handled.
- * Trying to force the fit to the posix database routines was not considered
+ * Trying to force the fit to the POSIX database routines was not considered
* time well spent.
*/
diff --git a/archivers/pax/files/tables.h b/archivers/pax/files/tables.h
index 7c493f77ba0..4a7211fe54d 100644
--- a/archivers/pax/files/tables.h
+++ b/archivers/pax/files/tables.h
@@ -1,4 +1,4 @@
-/* $NetBSD: tables.h,v 1.3 2003/12/20 04:45:04 grant Exp $ */
+/* $NetBSD: tables.h,v 1.4 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -77,7 +77,7 @@ typedef struct hrdlnk {
typedef struct ftm {
int namelen; /* file name length */
time_t mtime; /* files last modification time */
- off_t seek; /* loacation in scratch file */
+ off_t seek; /* location in scratch file */
struct ftm *fow;
} FTM;
diff --git a/archivers/pax/files/tar.1 b/archivers/pax/files/tar.1
index 618874f35d0..f6fd920b10c 100644
--- a/archivers/pax/files/tar.1
+++ b/archivers/pax/files/tar.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: tar.1,v 1.4 2004/06/20 10:11:02 grant Exp $
+.\" $NetBSD: tar.1,v 1.5 2005/12/01 03:00:01 minskim Exp $
.\"
.\" Copyright (c) 1996 SigmaSoft, Th. Lockert
.\" All rights reserved.
@@ -11,11 +11,6 @@
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by SigmaSoft, Th. Lockert.
-.\" 4. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -30,7 +25,7 @@
.\"
.\" OpenBSD: tar.1,v 1.28 2000/11/09 23:58:56 aaron Exp
.\"
-.Dd May 4, 2004
+.Dd May 7, 2005
.Dt TAR 1
.Os
.Sh NAME
@@ -39,7 +34,7 @@
.Sh SYNOPSIS
.Nm tar
.Sm off
-.Oo \&- Oc {crtux} Op Fl befhjklmopqvwzHLOPXZ014578
+.Oo \&- Oc {crtux} Op Fl befhjklmopqvwzHOPSXZ014578
.Sm on
.Op Ar archive
.Op Ar blocksize
@@ -150,6 +145,10 @@ No more than one archive member is matched for each
.Ar pattern .
When members of type directory are matched, the file hierarchy rooted at that
directory is also matched.
+.It Fl S , -sparse
+This flag has no effect as
+.Nm
+always generates sparse files.
.It Fl s Ar replstr
Modify the file or archive member names specified by the
.Ar pattern
@@ -236,6 +235,14 @@ Compress archive using compress.
Do not enable GNU tar extensions such as long filenames and long link names.
.It Fl -atime-preserve
Preserve file access times.
+.It Fl -chroot
+.Fn chroot
+to the current directory before extracting files.
+Use with
+.Fl x
+and
+.Fl h
+to make absolute symlinks relative to the current directory.
.It Fl -unlink
Ignored, only accepted for compatibility with other
.Nm
@@ -257,6 +264,10 @@ as a path component.
With this option, files that contain
.Sq ..
can be processed.
+.It Fl -no-recursion
+Cause files of type directory being copied or archived, or archive members of
+type directory being extracted, to match only the directory file or archive
+member and not the file hierarchy rooted at the directory.
.El
.Pp
The options
diff --git a/archivers/pax/files/tar.c b/archivers/pax/files/tar.c
index 14cbd7562d5..b02ee64421e 100644
--- a/archivers/pax/files/tar.c
+++ b/archivers/pax/files/tar.c
@@ -1,4 +1,4 @@
-/* $NetBSD: tar.c,v 1.9 2004/08/21 03:28:56 jlam Exp $ */
+/* $NetBSD: tar.c,v 1.10 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -48,7 +48,7 @@
#if 0
static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94";
#else
-__RCSID("$NetBSD: tar.c,v 1.9 2004/08/21 03:28:56 jlam Exp $");
+__RCSID("$NetBSD: tar.c,v 1.10 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
@@ -98,7 +98,7 @@ __RCSID("$NetBSD: tar.c,v 1.9 2004/08/21 03:28:56 jlam Exp $");
* Routines for reading, writing and header identify of various versions of tar
*/
-static int expandname(char *, size_t, char **, const char *, size_t);
+static int expandname(char *, size_t, char **, size_t *, const char *, size_t);
static void longlink(ARCHD *, int);
static u_long tar_chksm(char *, int);
static char *name_split(char *, int);
@@ -123,6 +123,8 @@ static char *gnu_hack_string; /* ././@LongLink hackery */
static int gnu_hack_len; /* len of gnu_hack_string */
char *gnu_name_string; /* ././@LongLink hackery name */
char *gnu_link_string; /* ././@LongLink hackery link */
+size_t gnu_name_length; /* ././@LongLink hackery name */
+size_t gnu_link_length; /* ././@LongLink hackery link */
static int gnu_short_trailer; /* gnu short trailer */
static const char LONG_LINK[] = "././@LongLink";
@@ -401,6 +403,7 @@ tar_id(char *blk, int size)
{
HD_TAR *hd;
HD_USTAR *uhd;
+ static int is_ustar = -1;
if (size < BLKMULT)
return(-1);
@@ -416,8 +419,16 @@ tar_id(char *blk, int size)
*/
if (hd->name[0] == '\0')
return(-1);
- if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0)
- return(-1);
+ if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0) {
+ if (is_ustar == -1) {
+ is_ustar = 1;
+ return(-1);
+ } else
+ tty_warn(0,
+ "Busted tar archive: has both ustar and old tar "
+ "records");
+ } else
+ is_ustar = 0;
return check_sum(hd->chksum, sizeof(hd->chksum), blk, BLKMULT, 1);
}
@@ -489,9 +500,11 @@ tar_rd(ARCHD *arcn, char *buf)
hd = (HD_TAR *)buf;
if (hd->linkflag != LONGLINKTYPE && hd->linkflag != LONGNAMETYPE) {
arcn->nlen = expandname(arcn->name, sizeof(arcn->name),
- &gnu_name_string, hd->name, sizeof(hd->name));
+ &gnu_name_string, &gnu_name_length, hd->name,
+ sizeof(hd->name));
arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
- &gnu_link_string, hd->linkname, sizeof(hd->linkname));
+ &gnu_link_string, &gnu_link_length, hd->linkname,
+ sizeof(hd->linkname));
}
arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
0xfff);
@@ -856,10 +869,11 @@ ustar_rd(ARCHD *arcn, char *buf)
if (hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) {
arcn->nlen = expandname(dest, sizeof(arcn->name) - cnt,
- &gnu_name_string, hd->name, sizeof(hd->name)) + cnt;
+ &gnu_name_string, &gnu_name_length, hd->name,
+ sizeof(hd->name)) + cnt;
arcn->ln_nlen = expandname(arcn->ln_name,
- sizeof(arcn->ln_name), &gnu_link_string, hd->linkname,
- sizeof(hd->linkname));
+ sizeof(arcn->ln_name), &gnu_link_string, &gnu_link_length,
+ hd->linkname, sizeof(hd->linkname));
}
/*
@@ -979,13 +993,14 @@ ustar_rd(ARCHD *arcn, char *buf)
}
static int
-expandname(char *buf, size_t len, char **gnu_name, const char *name,
- size_t nlen)
+expandname(char *buf, size_t len, char **gnu_name, size_t *gnu_length,
+ const char *name, size_t nlen)
{
if (*gnu_name) {
len = strlcpy(buf, *gnu_name, len);
free(*gnu_name);
*gnu_name = NULL;
+ *gnu_length = 0;
} else {
if (len > ++nlen)
len = nlen;
@@ -1035,6 +1050,17 @@ longlink(ARCHD *arcn, int type)
* data to write after the header, -1 if archive write failed
*/
+static int
+size_err(const char *what, ARCHD *arcn)
+{
+ /*
+ * header field is out of range
+ */
+ tty_warn(1, "Ustar %s header field is too small for %s",
+ what, arcn->org_name);
+ return 1;
+}
+
int
ustar_wr(ARCHD *arcn)
{
@@ -1121,7 +1147,7 @@ ustar_wr(ARCHD *arcn)
case PAX_DIR:
hd->typeflag = DIRTYPE;
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
- goto out;
+ return size_err("DIRTYPE", arcn);
break;
case PAX_CHR:
case PAX_BLK:
@@ -1134,12 +1160,12 @@ ustar_wr(ARCHD *arcn)
ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
sizeof(hd->devminor), 3) ||
ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
- goto out;
+ return size_err("DEVTYPE", arcn);
break;
case PAX_FIF:
hd->typeflag = FIFOTYPE;
if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
- goto out;
+ return size_err("FIFOTYPE", arcn);
break;
case PAX_GLL:
case PAX_SLK:
@@ -1154,7 +1180,7 @@ ustar_wr(ARCHD *arcn)
strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
if (ul_oct((u_long)gnu_hack_len, hd->size,
sizeof(hd->size), 3))
- goto out;
+ return size_err("LINKTYPE", arcn);
break;
case PAX_GLF:
case PAX_REG:
@@ -1198,11 +1224,14 @@ ustar_wr(ARCHD *arcn)
* set the remaining fields. Some versions want all 16 bits of mode
* we better humor them (they really do not meet spec though)....
*/
- if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) ||
- ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) ||
- ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) ||
- ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
- goto out;
+ if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3))
+ return size_err("MODE", arcn);
+ if (ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3))
+ return size_err("UID", arcn);
+ if (ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3))
+ return size_err("GID", arcn);
+ if (ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
+ return size_err("MTIME", arcn);
user = user_from_uid(arcn->sb.st_uid, 1);
group = group_from_gid(arcn->sb.st_gid, 1);
strncpy(hd->uname, user ? user : "", sizeof(hd->uname));
@@ -1215,7 +1244,7 @@ ustar_wr(ARCHD *arcn)
*/
if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum,
sizeof(hd->chksum), 3))
- goto out;
+ return size_err("CHKSUM", arcn);
if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
return(-1);
if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
@@ -1233,13 +1262,6 @@ ustar_wr(ARCHD *arcn)
if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
return(0);
return(1);
-
- out:
- /*
- * header field is out of range
- */
- tty_warn(1, "Ustar header field is too small for %s", arcn->org_name);
- return(1);
}
/*
@@ -1265,7 +1287,15 @@ name_split(char *name, int len)
*/
if (len < TNMSZ)
return(name);
- if (len > (TPFSZ + TNMSZ))
+ /*
+ * GNU tar does not honor the prefix+name mode if the magic
+ * is not "ustar\0". So in GNU tar compatibility mode, we don't
+ * split the filename into prefix+name because we are setting
+ * the magic to "ustar " as GNU tar does. This of course will
+ * end up creating a LongLink record in cases where it does not
+ * really need do, but we are behaving like GNU tar after all.
+ */
+ if (is_gnutar || len > (TPFSZ + TNMSZ))
return(NULL);
/*
@@ -1318,11 +1348,10 @@ tar_gnutar_exclude_one(const char *line, size_t len)
char sbuf[MAXPATHLEN * 2 + 1];
/* + / + // + .*""/\/ + \/.* */
char rabuf[MAXPATHLEN * 2 + 1 + 1 + 2 + 4 + 4];
- int i, j;
+ int i, j = 0;
if (line[len - 1] == '\n')
len--;
- strncpy(sbuf, ".*" "\\/", j = 4);
for (i = 0; i < len; i++) {
/*
* convert glob to regexp, escaping everything
diff --git a/archivers/pax/files/tty_subs.c b/archivers/pax/files/tty_subs.c
index ee34a76696a..d33dccba7ba 100644
--- a/archivers/pax/files/tty_subs.c
+++ b/archivers/pax/files/tty_subs.c
@@ -1,4 +1,4 @@
-/* $NetBSD: tty_subs.c,v 1.4 2004/08/21 03:28:56 jlam Exp $ */
+/* $NetBSD: tty_subs.c,v 1.5 2005/12/01 03:00:01 minskim Exp $ */
/*-
* Copyright (c) 1992 Keith Muller.
@@ -48,7 +48,7 @@
#if 0
static char sccsid[] = "@(#)tty_subs.c 8.2 (Berkeley) 4/18/94";
#else
-__RCSID("$NetBSD: tty_subs.c,v 1.4 2004/08/21 03:28:56 jlam Exp $");
+__RCSID("$NetBSD: tty_subs.c,v 1.5 2005/12/01 03:00:01 minskim Exp $");
#endif
#endif /* not lint */
@@ -101,8 +101,8 @@ static FILE *ttyinf = NULL; /* input pointing at control tty */
/*
* tty_init()
- * try to open the controlling termina (if any) for this process. if the
- * open fails, future ops that require user input will get an EOF
+ * Try to open the controlling terminal (if any) for this process. If the
+ * open fails, future ops that require user input will get an EOF.
*/
int