summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2002-10-18 15:38:12 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2002-10-18 15:38:12 +0000
commitaae52303c155286dabf18478a477e71a186e469a (patch)
tree10d3e9259d2d359e79faceb0a0019162b3200029
parente180c2a576a4dafce86b9a35fe9fe97c41536a5e (diff)
Pull in some changes from NetBSD
o When extracting GNU tar archives, honor @LongLink long links/files o Add an option to prevent pax from prompting for the next volume upon premature end of archive.
-rw-r--r--bin/pax/ar_io.c7
-rw-r--r--bin/pax/ar_subs.c22
-rw-r--r--bin/pax/buf_subs.c8
-rw-r--r--bin/pax/extern.h4
-rw-r--r--bin/pax/file_subs.c32
-rw-r--r--bin/pax/options.c18
-rw-r--r--bin/pax/pax.110
-rw-r--r--bin/pax/pax.h4
-rw-r--r--bin/pax/tar.c52
-rw-r--r--bin/pax/tar.h8
10 files changed, 133 insertions, 32 deletions
diff --git a/bin/pax/ar_io.c b/bin/pax/ar_io.c
index d334c6b619c..380378a1971 100644
--- a/bin/pax/ar_io.c
+++ b/bin/pax/ar_io.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar_io.c,v 1.29 2002/10/16 19:20:02 millert Exp $ */
+/* $OpenBSD: ar_io.c,v 1.30 2002/10/18 15:38:11 millert Exp $ */
/* $NetBSD: ar_io.c,v 1.5 1996/03/26 23:54:13 mrg Exp $ */
/*-
@@ -42,7 +42,7 @@
#if 0
static const char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 4/18/94";
#else
-static const char rcsid[] = "$OpenBSD: ar_io.c,v 1.29 2002/10/16 19:20:02 millert Exp $";
+static const char rcsid[] = "$OpenBSD: ar_io.c,v 1.30 2002/10/18 15:38:11 millert Exp $";
#endif
#endif /* not lint */
@@ -89,6 +89,7 @@ static int can_unlnk = 0; /* do we unlink null archives? */
const char *arcname; /* printable name of archive */
const char *gzip_program; /* name of gzip program */
static pid_t zpid = -1; /* pid of child process */
+int force_one_volume; /* 1 if we ignore volume changes */
static int get_phys(void);
extern sigset_t s_mask;
@@ -1122,7 +1123,7 @@ ar_next(void)
if (sigprocmask(SIG_SETMASK, &o_mask, NULL) < 0)
syswarn(0, errno, "Unable to restore signal mask");
- if (done || !wr_trail || strcmp(NM_TAR, argv0) == 0)
+ if (done || !wr_trail || force_one_volume || strcmp(NM_TAR, argv0) == 0)
return(-1);
tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0);
diff --git a/bin/pax/ar_subs.c b/bin/pax/ar_subs.c
index 0e5159c6e5b..a17366f5f8d 100644
--- a/bin/pax/ar_subs.c
+++ b/bin/pax/ar_subs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar_subs.c,v 1.21 2002/10/16 19:20:02 millert Exp $ */
+/* $OpenBSD: ar_subs.c,v 1.22 2002/10/18 15:38:11 millert Exp $ */
/* $NetBSD: ar_subs.c,v 1.5 1995/03/21 09:07:06 cgd Exp $ */
/*-
@@ -42,7 +42,7 @@
#if 0
static const char sccsid[] = "@(#)ar_subs.c 8.2 (Berkeley) 4/18/94";
#else
-static const char rcsid[] = "$OpenBSD: ar_subs.c,v 1.21 2002/10/16 19:20:02 millert Exp $";
+static const char rcsid[] = "$OpenBSD: ar_subs.c,v 1.22 2002/10/18 15:38:11 millert Exp $";
#endif
#endif /* not lint */
@@ -108,6 +108,16 @@ list(void)
* step through the archive until the format says it is done
*/
while (next_head(arcn) == 0) {
+ if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+ /*
+ * we need to read, to get the real filename
+ */
+ off_t cnt;
+ if (!(*frmt->rd_data)(arcn, -1, &cnt));
+ (void)rd_skip(cnt + arcn->pad);
+ continue;
+ }
+
/*
* check for pattern, and user specified options match.
* When all patterns are matched we are done.
@@ -191,6 +201,14 @@ extract(void)
* says it is done
*/
while (next_head(arcn) == 0) {
+ if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+ /*
+ * we need to read, to get the real filename
+ */
+ if (!(*frmt->rd_data)(arcn, -1, &cnt));
+ (void)rd_skip(cnt + arcn->pad);
+ continue;
+ }
/*
* check for pattern, and user specified options match. When
diff --git a/bin/pax/buf_subs.c b/bin/pax/buf_subs.c
index 46487e205c8..f89bdcee2c8 100644
--- a/bin/pax/buf_subs.c
+++ b/bin/pax/buf_subs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: buf_subs.c,v 1.14 2002/10/16 19:20:02 millert Exp $ */
+/* $OpenBSD: buf_subs.c,v 1.15 2002/10/18 15:38:11 millert Exp $ */
/* $NetBSD: buf_subs.c,v 1.5 1995/03/21 09:07:08 cgd Exp $ */
/*-
@@ -42,7 +42,7 @@
#if 0
static const char sccsid[] = "@(#)buf_subs.c 8.2 (Berkeley) 4/18/94";
#else
-static const char rcsid[] = "$OpenBSD: buf_subs.c,v 1.14 2002/10/16 19:20:02 millert Exp $";
+static const char rcsid[] = "$OpenBSD: buf_subs.c,v 1.15 2002/10/18 15:38:11 millert Exp $";
#endif
#endif /* not lint */
@@ -687,7 +687,9 @@ rd_wrfile(ARCHD *arcn, int ofd, off_t *left)
* pass the blocksize of the file being written to the write routine,
* if the size is zero, use the default MINFBSZ
*/
- if (fstat(ofd, &sb) == 0) {
+ if (ofd == -1)
+ sz = PAXPATHLEN + 1; /* GNU tar long link/file */
+ else if (fstat(ofd, &sb) == 0) {
if (sb.st_blksize > 0)
sz = (int)sb.st_blksize;
} else
diff --git a/bin/pax/extern.h b/bin/pax/extern.h
index d65e55a62d3..cc677925812 100644
--- a/bin/pax/extern.h
+++ b/bin/pax/extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: extern.h,v 1.23 2002/10/16 19:20:02 millert Exp $ */
+/* $OpenBSD: extern.h,v 1.24 2002/10/18 15:38:11 millert Exp $ */
/* $NetBSD: extern.h,v 1.5 1996/03/26 23:54:16 mrg Exp $ */
/*-
@@ -51,6 +51,7 @@
*/
extern const char *arcname;
extern const char *gzip_program;
+extern int force_one_volume;
int ar_open(const char *);
void ar_close(void);
void ar_drain(void);
@@ -279,6 +280,7 @@ u_int st_hash(char *, int, int);
/*
* tar.c
*/
+extern char *gnu_hack_string;
int tar_endwr(void);
off_t tar_endrd(void);
int tar_trail(char *, int, int *);
diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c
index 6167e4b2efc..7286def7ccd 100644
--- a/bin/pax/file_subs.c
+++ b/bin/pax/file_subs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file_subs.c,v 1.20 2002/10/16 19:20:02 millert Exp $ */
+/* $OpenBSD: file_subs.c,v 1.21 2002/10/18 15:38:11 millert Exp $ */
/* $NetBSD: file_subs.c,v 1.4 1995/03/21 09:07:18 cgd Exp $ */
/*-
@@ -42,21 +42,21 @@
#if 0
static const char sccsid[] = "@(#)file_subs.c 8.1 (Berkeley) 5/31/93";
#else
-static const char rcsid[] = "$OpenBSD: file_subs.c,v 1.20 2002/10/16 19:20:02 millert Exp $";
+static const char rcsid[] = "$OpenBSD: file_subs.c,v 1.21 2002/10/18 15:38:11 millert Exp $";
#endif
#endif /* not lint */
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/time.h>
#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/param.h>
+#include <sys/uio.h>
+#include <err.h>
+#include <errno.h>
#include <fcntl.h>
-#include <string.h>
#include <stdio.h>
-#include <errno.h>
-#include <sys/uio.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include "pax.h"
#include "options.h"
#include "extern.h"
@@ -858,7 +858,8 @@ file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz,
/*
* skip, buf is empty so far
*/
- if (lseek(fd, (off_t)wcnt, SEEK_CUR) < 0) {
+ if (fd > -1 &&
+ lseek(fd, (off_t)wcnt, SEEK_CUR) < 0) {
syswarn(1,errno,"File seek on %s",
name);
return(-1);
@@ -875,7 +876,18 @@ 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
*/
- if (write(fd, st, wcnt) != wcnt) {
+ if (fd == -1) {
+ /* GNU hack */
+ if (gnu_hack_string)
+ err(1, "WARNING! Major Internal Error! GNU hack Failing!");
+ gnu_hack_string = malloc(wcnt + 1);
+ if (gnu_hack_string == NULL) {
+ paxwarn(1, "Out of memory");
+ return(-1);
+ }
+ memcpy(gnu_hack_string, st, wcnt);
+ gnu_hack_string[wcnt] = '\0';
+ } else if (write(fd, st, wcnt) != wcnt) {
syswarn(1, errno, "Failed write to file %s", name);
return(-1);
}
diff --git a/bin/pax/options.c b/bin/pax/options.c
index 30fe4bbfecb..7e4f0a7f82e 100644
--- a/bin/pax/options.c
+++ b/bin/pax/options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: options.c,v 1.54 2002/10/16 19:20:02 millert Exp $ */
+/* $OpenBSD: options.c,v 1.55 2002/10/18 15:38:11 millert Exp $ */
/* $NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg Exp $ */
/*-
@@ -42,7 +42,7 @@
#if 0
static const char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94";
#else
-static const char rcsid[] = "$OpenBSD: options.c,v 1.54 2002/10/16 19:20:02 millert Exp $";
+static const char rcsid[] = "$OpenBSD: options.c,v 1.55 2002/10/18 15:38:11 millert Exp $";
#endif
#endif /* not lint */
@@ -451,6 +451,12 @@ pax_options(int argc, char **argv)
Lflag = 1;
flg |= CLF;
break;
+ case 'O':
+ /*
+ * Force one volume. Non standard option.
+ */
+ force_one_volume = 1;
+ break;
case 'P':
/*
* do NOT follow symlinks (default)
@@ -1521,25 +1527,25 @@ no_op(void)
void
pax_usage(void)
{
- (void)fputs("usage: pax [-cdnvz] [-E limit] [-f archive] ", stderr);
+ (void)fputs("usage: pax [-cdnvzO] [-E limit] [-f archive] ", stderr);
(void)fputs("[-s replstr] ... [-U user] ...", stderr);
(void)fputs("\n [-G group] ... ", stderr);
(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
(void)fputs("[pattern ...]\n", stderr);
- (void)fputs(" pax -r [-cdiknuvzDYZ] [-E limit] ", stderr);
+ (void)fputs(" pax -r [-cdiknuvzDOYZ] [-E limit] ", stderr);
(void)fputs("[-f archive] [-o options] ... \n", stderr);
(void)fputs(" [-p string] ... [-s replstr] ... ", stderr);
(void)fputs("[-U user] ... [-G group] ...\n ", stderr);
(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
(void)fputs(" [pattern ...]\n", stderr);
- (void)fputs(" pax -w [-dituvzHLPX] [-b blocksize] ", stderr);
+ (void)fputs(" pax -w [-dituvzHLOPX] [-b blocksize] ", stderr);
(void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr);
(void)fputs(" [-B bytes] [-s replstr] ... ", stderr);
(void)fputs("[-o options] ... [-U user] ...", stderr);
(void)fputs("\n [-G group] ... ", stderr);
(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
(void)fputs("[file ...]\n", stderr);
- (void)fputs(" pax -r -w [-diklntuvDHLPXYZ] ", stderr);
+ (void)fputs(" pax -r -w [-diklntuvDHLOPXYZ] ", stderr);
(void)fputs("[-p string] ... [-s replstr] ...", stderr);
(void)fputs("\n [-U user] ... [-G group] ... ", stderr);
(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
diff --git a/bin/pax/pax.1 b/bin/pax/pax.1
index ccebc4fc996..8790f2c412b 100644
--- a/bin/pax/pax.1
+++ b/bin/pax/pax.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pax.1,v 1.33 2002/10/16 15:56:42 millert Exp $
+.\" $OpenBSD: pax.1,v 1.34 2002/10/18 15:38:11 millert Exp $
.\" $NetBSD: pax.1,v 1.3 1995/03/21 09:07:37 cgd Exp $
.\"
.\" Copyright (c) 1992 Keith Muller.
@@ -833,6 +833,13 @@ Follow only command-line symbolic links while performing a physical file
system traversal.
.It Fl L
Follow all symbolic links to perform a logical file system traversal.
+.It Fl O
+Force the archive to be one volume.
+If a volume ends prematurely,
+.Nm
+will not prompt for a new volume.
+This option can be useful for
+automated tasks where error recovery cannot be performed by a human.
.It Fl P
Do not follow symbolic links, perform a physical file system traversal.
This is the default mode.
@@ -1166,6 +1173,7 @@ The options
.Fl G ,
.Fl H ,
.Fl L ,
+.Fl O ,
.Fl P ,
.Fl T ,
.Fl U ,
diff --git a/bin/pax/pax.h b/bin/pax/pax.h
index 61dea00a78e..9516c5d13f3 100644
--- a/bin/pax/pax.h
+++ b/bin/pax/pax.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pax.h,v 1.12 2002/10/16 18:40:30 millert Exp $ */
+/* $OpenBSD: pax.h,v 1.13 2002/10/18 15:38:11 millert Exp $ */
/* $NetBSD: pax.h,v 1.3 1995/03/21 09:07:41 cgd Exp $ */
/*-
@@ -212,6 +212,8 @@ typedef struct {
#define PAX_HLK 8 /* hard link */
#define PAX_HRG 9 /* hard link to a regular file */
#define PAX_CTG 10 /* high performance file */
+#define PAX_GLL 11 /* GNU long symlink */
+#define PAX_GLF 12 /* GNU long file */
} ARCHD;
/*
diff --git a/bin/pax/tar.c b/bin/pax/tar.c
index 49f69308ef0..550bb08df5c 100644
--- a/bin/pax/tar.c
+++ b/bin/pax/tar.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tar.c,v 1.28 2002/10/16 19:20:02 millert Exp $ */
+/* $OpenBSD: tar.c,v 1.29 2002/10/18 15:38:11 millert Exp $ */
/* $NetBSD: tar.c,v 1.5 1995/03/21 09:07:49 cgd Exp $ */
/*-
@@ -42,7 +42,7 @@
#if 0
static const char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94";
#else
-static const char rcsid[] = "$OpenBSD: tar.c,v 1.28 2002/10/16 19:20:02 millert Exp $";
+static const char rcsid[] = "$OpenBSD: tar.c,v 1.29 2002/10/18 15:38:11 millert Exp $";
#endif
#endif /* not lint */
@@ -74,6 +74,7 @@ static int uqd_oct(u_quad_t, char *, int, int);
*/
static int tar_nodir; /* do not write dirs under old tar */
+char *gnu_hack_string; /* GNU ././@LongLink hackery */
/*
* tar_endwr()
@@ -329,6 +330,7 @@ tar_id(char *blk, int size)
return(-1);
if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
return(-1);
+ force_one_volume = 1;
return(0);
}
@@ -395,7 +397,14 @@ tar_rd(ARCHD *arcn, char *buf)
* copy out the name and values in the stat buffer
*/
hd = (HD_TAR *)buf;
- arcn->nlen = strlcpy(arcn->name, hd->name, sizeof(arcn->name));
+ if (gnu_hack_string) {
+ arcn->nlen = strlcpy(arcn->name, gnu_hack_string,
+ sizeof(arcn->name));
+ free(gnu_hack_string);
+ gnu_hack_string = NULL;
+ } else {
+ arcn->nlen = strlcpy(arcn->name, hd->name, sizeof(arcn->name));
+ }
arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
0xfff);
arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
@@ -442,6 +451,21 @@ tar_rd(ARCHD *arcn, char *buf)
*/
arcn->sb.st_mode |= S_IFREG;
break;
+ case LONGLINKTYPE:
+ arcn->type = PAX_GLL;
+ /* FALLTHROUGH */
+ case LONGNAMETYPE:
+ /*
+ * GNU long link/file; we tag these here and let the
+ * pax internals deal with it -- too ugly otherwise.
+ */
+ if (hd->linkflag != LONGLINKTYPE)
+ arcn->type = PAX_GLF;
+ arcn->pad = TAR_PAD(arcn->sb.st_size);
+ arcn->skip = arcn->sb.st_size;
+ arcn->ln_name[0] = '\0';
+ arcn->ln_nlen = 0;
+ break;
case DIRTYPE:
/*
* It is a directory, set the mode for -v printing
@@ -754,7 +778,14 @@ ustar_rd(ARCHD *arcn, char *buf)
*dest++ = '/';
cnt++;
}
- arcn->nlen = cnt + strlcpy(dest, hd->name, sizeof(arcn->name) - cnt);
+ if (gnu_hack_string) {
+ arcn->nlen = strlcpy(dest, gnu_hack_string,
+ sizeof(arcn->name) - cnt);
+ free(gnu_hack_string);
+ gnu_hack_string = NULL;
+ } else {
+ arcn->nlen = strlcpy(dest, hd->name, sizeof(arcn->name) - cnt);
+ }
/*
* follow the spec to the letter. we should only have mode bits, strip
@@ -848,6 +879,19 @@ ustar_rd(ARCHD *arcn, char *buf)
arcn->ln_nlen = strlcpy(arcn->ln_name, hd->linkname,
sizeof(arcn->ln_name));
break;
+ case LONGLINKTYPE:
+ case LONGNAMETYPE:
+ /*
+ * GNU long link/file; we tag these here and let the
+ * pax internals deal with it -- too ugly otherwise.
+ */
+ arcn->type =
+ hd->typeflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
+ arcn->pad = TAR_PAD(arcn->sb.st_size);
+ arcn->skip = arcn->sb.st_size;
+ arcn->ln_name[0] = '\0';
+ arcn->ln_nlen = 0;
+ break;
case CONTTYPE:
case AREGTYPE:
case REGTYPE:
diff --git a/bin/pax/tar.h b/bin/pax/tar.h
index 79a8ce49d89..45952b8af56 100644
--- a/bin/pax/tar.h
+++ b/bin/pax/tar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tar.h,v 1.5 1997/04/16 03:50:25 millert Exp $ */
+/* $OpenBSD: tar.h,v 1.6 2002/10/18 15:38:11 millert Exp $ */
/* $NetBSD: tar.h,v 1.3 1995/03/21 09:07:51 cgd Exp $ */
/*-
@@ -66,6 +66,12 @@
#define CONTTYPE '7' /* high perf file */
/*
+ * GNU tar compatibility;
+ */
+#define LONGLINKTYPE 'K' /* Long Symlink */
+#define LONGNAMETYPE 'L' /* Long File */
+
+/*
* Mode field encoding of the different file types - values in octal
*/
#define TSUID 04000 /* Set UID on execution */