diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2002-10-18 15:38:12 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2002-10-18 15:38:12 +0000 |
commit | aae52303c155286dabf18478a477e71a186e469a (patch) | |
tree | 10d3e9259d2d359e79faceb0a0019162b3200029 | |
parent | e180c2a576a4dafce86b9a35fe9fe97c41536a5e (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.c | 7 | ||||
-rw-r--r-- | bin/pax/ar_subs.c | 22 | ||||
-rw-r--r-- | bin/pax/buf_subs.c | 8 | ||||
-rw-r--r-- | bin/pax/extern.h | 4 | ||||
-rw-r--r-- | bin/pax/file_subs.c | 32 | ||||
-rw-r--r-- | bin/pax/options.c | 18 | ||||
-rw-r--r-- | bin/pax/pax.1 | 10 | ||||
-rw-r--r-- | bin/pax/pax.h | 4 | ||||
-rw-r--r-- | bin/pax/tar.c | 52 | ||||
-rw-r--r-- | bin/pax/tar.h | 8 |
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 */ |