From 58e9e7462b72a04612e67f659053afd54a7e4e41 Mon Sep 17 00:00:00 2001 From: Marcelo Alencar Date: Tue, 30 Mar 2021 19:56:10 -0300 Subject: [PATCH] bin/pax: Synchronize on NetBSD-current (30/03/2021 16:09 UTC) --- bin/pax/Makefile | 8 +++-- bin/pax/ar_io.c | 36 +++++++++++----------- bin/pax/buf_subs.c | 6 ++-- bin/pax/cpio.1 | 10 +++--- bin/pax/dumptar.c | 19 +++++++++--- bin/pax/extern.h | 5 ++- bin/pax/file_subs.c | 8 ++--- bin/pax/gen_subs.c | 34 +++++++++++++++++---- bin/pax/options.c | 74 +++++++++++++++++++++++++++++++++++++++++++-- bin/pax/pat_rep.c | 15 ++++----- bin/pax/pax.1 | 49 +++++++++++++++++++++++------- bin/pax/pax.c | 26 ++++++++-------- bin/pax/tar.1 | 28 ++++++++++++----- bin/pax/tar.c | 30 ++++++++++++------ 14 files changed, 250 insertions(+), 98 deletions(-) diff --git a/bin/pax/Makefile b/bin/pax/Makefile index 9b2f6a6db..98945e296 100644 --- a/bin/pax/Makefile +++ b/bin/pax/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.39 2010/04/23 19:41:02 joerg Exp $ +# $NetBSD: Makefile,v 1.41 2019/10/13 07:28:04 mrg Exp $ # @(#)Makefile 8.1 (Berkeley) 5/31/93 .include @@ -23,7 +23,7 @@ LDADD+= -lutil .endif .endif -MAN= pax.1 tar.1 cpio.1 +MAN= pax.1 .if defined(HOSTPROG) CPPFLAGS+= -DHOSTPROG @@ -35,12 +35,14 @@ CPPFLAGS+= -DHAVE_SYS_MTIO_H .if ${MKBSDTAR} == "no" LINKS+= ${BINDIR}/pax ${BINDIR}/tar SYMLINKS+=${BINDIR}/tar /usr/bin/tar +MAN+=tar.1 .if defined(__MINIX) SYMLINKS+=${BINDIR}/tar /usr/bin/bsdtar .endif LINKS+= ${BINDIR}/pax ${BINDIR}/cpio SYMLINKS+=${BINDIR}/cpio /usr/bin/cpio +MAN+=cpio.1 .endif .endif # } ! HOSTPROG @@ -57,4 +59,6 @@ CPPFLAGS+= -DHOSTPROG MLINKS+= pax.1 bsdtar.1 .endif # defined(__MINIX) +COPTS.tar.c+= ${GCC_NO_STRINGOP_TRUNCATION} + .include diff --git a/bin/pax/ar_io.c b/bin/pax/ar_io.c index f5ad892be..a7c5cb855 100644 --- a/bin/pax/ar_io.c +++ b/bin/pax/ar_io.c @@ -1,4 +1,4 @@ -/* $NetBSD: ar_io.c,v 1.56 2015/03/09 23:38:08 sevan Exp $ */ +/* $NetBSD: ar_io.c,v 1.59 2019/02/04 04:36:41 mrg Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -42,27 +42,27 @@ #if 0 static char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 4/18/94"; #else -__RCSID("$NetBSD: ar_io.c,v 1.56 2015/03/09 23:38:08 sevan Exp $"); +__RCSID("$NetBSD: ar_io.c,v 1.59 2019/02/04 04:36:41 mrg Exp $"); #endif #endif /* not lint */ -#include #include -#include -#include #include #ifdef HAVE_SYS_MTIO_H #include #endif +#include +#include #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include #include +#include +#include +#include #ifdef SUPPORT_RMT #define __RMTLIB_PRIVATE #include @@ -1631,8 +1631,7 @@ void ar_summary(int n) { time_t secs; - int len; - char buf[BUFSIZ]; + char buf[4096]; char tbuf[MAXPATHLEN/4]; /* XXX silly size! */ char s1buf[MAXPATHLEN/8]; /* XXX very silly size! */ char s2buf[MAXPATHLEN/8]; /* XXX very silly size! */ @@ -1657,33 +1656,32 @@ ar_summary(int n) * could have written anything yet. */ if (frmt == NULL && act != COPY) { - len = snprintf(buf, sizeof(buf), + snprintf(buf, sizeof(buf), "unknown format, %s skipped in %s\n", sizefmt(s1buf, sizeof(s1buf), rdcnt), timefmt(tbuf, sizeof(tbuf), rdcnt, secs, "bytes")); if (n == 0) (void)fprintf(outf, "%s: %s", argv0, buf); else - (void)write(STDERR_FILENO, buf, len); + (void)write(STDERR_FILENO, buf, strlen(buf)); return; } if (n != 0 && *archd.name) { - len = snprintf(buf, sizeof(buf), "Working on `%s' (%s)\n", + snprintf(buf, sizeof(buf), "Working on `%s' (%s)\n", archd.name, sizefmt(s1buf, sizeof(s1buf), archd.sb.st_size)); - (void)write(STDERR_FILENO, buf, len); - len = 0; + (void)write(STDERR_FILENO, buf, strlen(buf)); } if (act == COPY) { - len = snprintf(buf, sizeof(buf), + snprintf(buf, sizeof(buf), "%lu files in %s\n", (unsigned long)flcnt, timefmt(tbuf, sizeof(tbuf), flcnt, secs, "files")); } else { - len = snprintf(buf, sizeof(buf), + snprintf(buf, sizeof(buf), "%s vol %d, %lu files, %s read, %s written in %s\n", frmt->name, arvol-1, (unsigned long)flcnt, sizefmt(s1buf, sizeof(s1buf), rdcnt), diff --git a/bin/pax/buf_subs.c b/bin/pax/buf_subs.c index d4c27514d..e4b97afb2 100644 --- a/bin/pax/buf_subs.c +++ b/bin/pax/buf_subs.c @@ -1,4 +1,4 @@ -/* $NetBSD: buf_subs.c,v 1.28 2007/04/29 20:23:34 msaitoh Exp $ */ +/* $NetBSD: buf_subs.c,v 1.29 2018/03/19 03:11:39 msaitoh Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)buf_subs.c 8.2 (Berkeley) 4/18/94"; #else -__RCSID("$NetBSD: buf_subs.c,v 1.28 2007/04/29 20:23:34 msaitoh Exp $"); +__RCSID("$NetBSD: buf_subs.c,v 1.29 2018/03/19 03:11:39 msaitoh Exp $"); #endif #endif /* not lint */ @@ -493,7 +493,7 @@ wr_rdbuf(char *out, int outcnt) int cnt; /* - * while there is data to copy copy into the write buffer. when the + * while there is data to copy into the write buffer. when the * write buffer fills, flush it to the archive and continue */ while (outcnt > 0) { diff --git a/bin/pax/cpio.1 b/bin/pax/cpio.1 index 6ecff6466..45f58541c 100644 --- a/bin/pax/cpio.1 +++ b/bin/pax/cpio.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: cpio.1,v 1.14 2015/12/19 18:48:33 wiz Exp $ +.\" $NetBSD: cpio.1,v 1.15 2017/07/03 21:33:23 wiz Exp $ .\" .\" Copyright (c) 1997 SigmaSoft, Th. Lockert .\" All rights reserved. @@ -39,8 +39,8 @@ .Op Fl F Ar archive .Op Fl H Ar format .Op Fl O Ar archive -.Ar "\*[Lt] name-list" -.Op Ar "\*[Gt] archive" +.Ar "< name-list" +.Op Ar "> archive" .Nm cpio .Fl i .Op Fl 6BbcdfmrSstuvZz @@ -50,12 +50,12 @@ .Op Fl H Ar format .Op Fl I Ar archive .Op Ar "pattern ..." -.Op Ar "\*[Lt] archive" +.Op Ar "< archive" .Nm cpio .Fl p .Op Fl adLlmuv .Ar destination-directory -.Ar "\*[Lt] name-list" +.Ar "< name-list" .Sh DESCRIPTION The .Nm diff --git a/bin/pax/dumptar.c b/bin/pax/dumptar.c index 0af32fbba..553870202 100644 --- a/bin/pax/dumptar.c +++ b/bin/pax/dumptar.c @@ -1,4 +1,4 @@ -/* $NetBSD: dumptar.c,v 1.2 2008/04/28 20:22:51 martin Exp $ */ +/* $NetBSD: dumptar.c,v 1.3 2016/05/30 17:34:35 dholland Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. @@ -30,8 +30,12 @@ */ #include -#include +#include +#include +#include #include +#include +#include #include #include @@ -39,20 +43,25 @@ #define ussum(a) 1 +/* + * Ensure null termination. + */ static char * buf(const char *p, size_t s) { static char buf[1024]; - (void)snprintf(buf, sizeof(buf), "%s", p); + + assert(s < sizeof(buf)); + memcpy(buf, p, s); buf[s] = '\0'; return buf; } -int +static int intarg(const char *p, size_t s) { char *ep, *b = buf(p, s); - int r = (int)strtol(p, &ep, 8); + int r = (int)strtol(b, &ep, 8); return r; } diff --git a/bin/pax/extern.h b/bin/pax/extern.h index 298600c2d..254177c50 100644 --- a/bin/pax/extern.h +++ b/bin/pax/extern.h @@ -1,4 +1,4 @@ -/* $NetBSD: extern.h,v 1.59 2012/08/09 08:09:21 christos Exp $ */ +/* $NetBSD: extern.h,v 1.60 2020/04/03 16:13:32 joerg Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -204,9 +204,8 @@ void options(int, char **); OPLIST * opt_next(void); int bad_opt(void); int mkpath(char *); -char *chdname; #if !HAVE_NBTOOL_CONFIG_H -int do_chroot; +extern int do_chroot; #endif /* diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c index 840bf4980..176a95295 100644 --- a/bin/pax/file_subs.c +++ b/bin/pax/file_subs.c @@ -1,4 +1,4 @@ -/* $NetBSD: file_subs.c,v 1.63 2013/07/29 17:46:36 christos Exp $ */ +/* $NetBSD: file_subs.c,v 1.64 2019/03/20 03:13:39 gutteridge Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)file_subs.c 8.1 (Berkeley) 5/31/93"; #else -__RCSID("$NetBSD: file_subs.c,v 1.63 2013/07/29 17:46:36 christos Exp $"); +__RCSID("$NetBSD: file_subs.c,v 1.64 2019/03/20 03:13:39 gutteridge Exp $"); #endif #endif /* not lint */ @@ -913,7 +913,7 @@ set_chflags(char *fnm, u_int32_t flags) * actual storage is quite small (the files are sparse). The problem is * the holes read as all zeros so are probably stored on the archive that * way (there is no way to determine if the file block is really a hole, - * we only know that a file block of all zero's can be a hole). + * we only know that a file block of all zeros can be a hole). * At this writing, no major archive format knows how to archive files * with holes. However, on extraction (or during copy, -rw) we have to * deal with these files. Without detecting the holes, the files can @@ -986,7 +986,7 @@ file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz, if (*isempt) { /* * have not written to this block yet, so we keep - * looking for zero's + * looking for zeros */ pt = st; end = st + wcnt; diff --git a/bin/pax/gen_subs.c b/bin/pax/gen_subs.c index 1ffa95a36..9228c695f 100644 --- a/bin/pax/gen_subs.c +++ b/bin/pax/gen_subs.c @@ -1,4 +1,4 @@ -/* $NetBSD: gen_subs.c,v 1.36 2012/08/09 08:09:21 christos Exp $ */ +/* $NetBSD: gen_subs.c,v 1.37 2018/11/30 00:53:11 christos Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)gen_subs.c 8.1 (Berkeley) 5/31/93"; #else -__RCSID("$NetBSD: gen_subs.c,v 1.36 2012/08/09 08:09:21 christos Exp $"); +__RCSID("$NetBSD: gen_subs.c,v 1.37 2018/11/30 00:53:11 christos Exp $"); #endif #endif /* not lint */ @@ -306,12 +306,10 @@ u32_asc(uintmax_t val, char *str, int len, int base) /* * asc_umax() - * convert hex/octal character string into a uintmax. We do - * not have to to check for overflow! (the headers in all supported - * formats are not large enough to create an overflow). + * convert hex/octal/base-256 value into a uintmax. * NOTE: strings passed to us are NOT TERMINATED. * Return: - * uintmax_t value + * uintmax_t value; UINTMAX_MAX for overflow/negative */ uintmax_t @@ -322,6 +320,30 @@ asc_umax(char *str, int len, int base) stop = str + len; + /* + * if the highest bit of first byte is set, it's base-256 encoded + * (base-256 is basically (n-1)-bit big endian signed + */ + if (str < stop && (*str & 0x80)) { + /* + * uintmax_t can't be negative, so fail on negative numbers + */ + if (*str & 0x40) + return UINTMAX_MAX; + + tval = *str++ & 0x3f; + while (str < stop) { + /* + * check for overflow + */ + if (tval > (UINTMAX_MAX/256)) + return UINTMAX_MAX; + tval = (tval << 8) | ((*str++) & 0xFF); + } + + return tval; + } + /* * skip over leading blanks and zeros */ diff --git a/bin/pax/options.c b/bin/pax/options.c index 1af5fe4b7..8d5bcfcb1 100644 --- a/bin/pax/options.c +++ b/bin/pax/options.c @@ -1,4 +1,4 @@ -/* $NetBSD: options.c,v 1.116 2015/04/11 15:41:33 christos Exp $ */ +/* $NetBSD: options.c,v 1.119 2020/04/03 16:13:32 joerg Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 4/18/94"; #else -__RCSID("$NetBSD: options.c,v 1.116 2015/04/11 15:41:33 christos Exp $"); +__RCSID("$NetBSD: options.c,v 1.119 2020/04/03 16:13:32 joerg Exp $"); #endif #endif /* not lint */ @@ -64,6 +64,7 @@ __RCSID("$NetBSD: options.c,v 1.116 2015/04/11 15:41:33 christos Exp $"); #include #include #include +#include #include "pax.h" #include "options.h" #include "cpio.h" @@ -73,9 +74,15 @@ __RCSID("$NetBSD: options.c,v 1.116 2015/04/11 15:41:33 christos Exp $"); #include "mtree.h" #endif /* SMALL */ +char *chdname; +#if !HAVE_NBTOOL_CONFIG_H +int do_chroot; +#endif + /* * Routines which handle command line options */ +struct stat tst; /* Timestamp to set if non-0 */ static int nopids; /* tar mode: suppress "pids" for -p option */ static char flgch[] = FLGCH; /* list of all possible flags (pax) */ @@ -88,6 +95,9 @@ static void printflg(unsigned int); static int c_frmt(const void *, const void *); static off_t str_offt(char *); static char *get_line(FILE *fp); +#ifndef SMALL +static int set_tstamp(const char *, struct stat *); +#endif static void pax_options(int, char **); __dead static void pax_usage(void); static void tar_options(int, char **); @@ -129,8 +139,9 @@ static int get_line_error; #define OPT_SPARSE 16 #define OPT_XZ 17 #define OPT_GNU 18 +#define OPT_TIMESTAMP 19 #if !HAVE_NBTOOL_CONFIG_H -#define OPT_CHROOT 19 +#define OPT_CHROOT 20 #endif /* @@ -251,6 +262,8 @@ struct option pax_longopts[] = { OPT_XZ }, { "gnu", no_argument, 0, OPT_GNU }, + { "timestamp", required_argument, 0, + OPT_TIMESTAMP }, { 0, 0, 0, 0 }, }; @@ -661,6 +674,14 @@ pax_options(int argc, char **argv) case OPT_GNU: is_gnutar = 1; break; +#ifndef SMALL + case OPT_TIMESTAMP: + if (set_tstamp(optarg, &tst) == -1) { + tty_warn(1, "Invalid timestamp `%s'", optarg); + tar_usage(); + } + break; +#endif case '?': default: pax_usage(); @@ -803,6 +824,8 @@ struct option tar_longopts[] = { { "chroot", no_argument, 0, OPT_CHROOT }, #endif + { "timestamp", required_argument, 0, + OPT_TIMESTAMP }, #if 0 /* Not implemented */ { "catenate", no_argument, 0, 'A' }, /* F */ { "concatenate", no_argument, 0, 'A' }, /* F */ @@ -1143,6 +1166,14 @@ tar_options(int argc, char **argv) case OPT_CHROOT: do_chroot = 1; break; +#endif +#ifndef SMALL + case OPT_TIMESTAMP: + if (set_tstamp(optarg, &tst) == -1) { + tty_warn(1, "Invalid timestamp `%s'", optarg); + tar_usage(); + } + break; #endif default: tar_usage(); @@ -2083,6 +2114,43 @@ get_line(FILE *f) return temp; } +#ifndef SMALL +/* + * set_tstamp() + * Use a specific timestamp for all individual files created in the + * archive + */ +static int +set_tstamp(const char *b, struct stat *st) +{ + time_t when; + char *eb; + long long l; + + if (stat(b, st) != -1) + return 0; + +#ifndef HAVE_NBTOOL_CONFIG_H + errno = 0; + if ((when = parsedate(b, NULL, NULL)) == -1 && errno != 0) +#endif + { + errno = 0; + l = strtoll(b, &eb, 0); + if (b == eb || *eb || errno) + return -1; + when = (time_t)l; + } + + st->st_ino = 1; +#if HAVE_STRUCT_STAT_BIRTHTIME + st->st_birthtime = +#endif + st->st_mtime = st->st_ctime = st->st_atime = when; + return 0; +} +#endif + /* * no_op() * for those option functions where the archive format has nothing to do. diff --git a/bin/pax/pat_rep.c b/bin/pax/pat_rep.c index fd402e292..05f4874e4 100644 --- a/bin/pax/pat_rep.c +++ b/bin/pax/pat_rep.c @@ -1,4 +1,4 @@ -/* $NetBSD: pat_rep.c,v 1.29 2009/04/07 19:52:35 perry Exp $ */ +/* $NetBSD: pat_rep.c,v 1.31 2019/03/20 02:50:50 gutteridge Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)pat_rep.c 8.2 (Berkeley) 4/18/94"; #else -__RCSID("$NetBSD: pat_rep.c,v 1.29 2009/04/07 19:52:35 perry Exp $"); +__RCSID("$NetBSD: pat_rep.c,v 1.31 2019/03/20 02:50:50 gutteridge Exp $"); #endif #endif /* not lint */ @@ -85,12 +85,13 @@ static int resub(regex_t *, regmatch_t *, char *, char *, char *, char *); * parses the -s replacement string; compiles the regular expression * and stores the compiled value and its replacement string together in * replacement string list. Input to this function is of the form: - * /old/new/pg + * /old/new/gps * The first char in the string specifies the delimiter used by this * replacement string. "Old" is a regular expression in "ed" format which * is compiled by regcomp() and is applied to filenames. "new" is the - * substitution string; p and g are options flags for printing and global - * replacement (over the single filename) + * substitution string; g, p, and s are options flags for global + * replacement (over the single filename), printing, and preventing + * substitutions on symbolic link destinations. * Return: * 0 if a proper replacement string and regular expression was added to * the list of replacement patterns; -1 otherwise. @@ -895,7 +896,7 @@ fix_path( char *or_name, int *or_len, char *dir_name, int dir_len) * namelen the size of the name buffer. * nlen is the length of this name (and is modified to hold the length of * the final string). - * prnt is a flag that says whether to print the final result. + * flags contains various options to control behavior. * Return: * 0 if substitution was successful, 1 if we are to skip the file (the name * ended up empty) @@ -924,7 +925,7 @@ rep_name(char *name, size_t namelen, int *nlen, int flags) * (the user already saw that substitution go by) */ pt = rephead; - (void)strcpy(buf1, name); + (void)strlcpy(buf1, name, sizeof(buf1)); inpt = buf1; outpt = nname; endpt = outpt + PAXPATHLEN; diff --git a/bin/pax/pax.1 b/bin/pax/pax.1 index 41f388444..41b9009d9 100644 --- a/bin/pax/pax.1 +++ b/bin/pax/pax.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: pax.1,v 1.63 2013/11/14 07:45:05 wiz Exp $ +.\" $NetBSD: pax.1,v 1.71 2019/03/19 00:36:14 gutteridge Exp $ .\" .\" Copyright (c) 1992 Keith Muller. .\" Copyright (c) 1992, 1993 @@ -33,7 +33,7 @@ .\" .\" @(#)pax.1 8.4 (Berkeley) 4/18/94 .\" -.Dd November 13, 2013 +.Dd March 19, 2019 .Dt PAX 1 .Os .Sh NAME @@ -572,20 +572,21 @@ using the syntax of the .Xr ed 1 utility regular expressions. The format of these regular expressions are: -.Dl /old/new/[gp] +.Dl /old/new/[gps] As in .Xr ed 1 , .Cm old is a basic regular expression and .Cm new -can contain an ampersand (\*[Am]), \en (where n is a digit) back-references, +can contain an ampersand (&), \en (where n is a digit) back-references, or subexpression matching. The .Cm old string may also contain .Aq Dv newline characters. -Any non-null character can be used as a delimiter (/ is shown here). +Any non-null character except a backslash (\\) can be used as a delimiter +(/ is shown here). Multiple .Fl s expressions can be specified. @@ -604,9 +605,14 @@ The optional trailing will cause the final result of a successful substitution to be written to .Dv standard error in the following format: -.Dl Ao "original pathname" Ac \*[Gt]\*[Gt] Ao "new pathname" Ac +.Dl Ao "original pathname" Ac >> Ao "new pathname" Ac File or archive member names that substitute to the empty string are not selected and will be skipped. +The substitutions are applied by default to the destination hard and symbolic +links. +The optional trailing +.Cm s +prevents the substitutions from being performed on symbolic link destinations. .It Fl t Reset the access times of any file or directory read or accessed by .Nm @@ -742,6 +748,19 @@ Typical archive format restrictions include (but are not limited to): file pathname length, file size, link pathname length and the type of the file. .It Fl Fl gnu Recognize GNU tar extensions. +.It Fl Fl timestamp Ar timestamp +Store all modification times in the archive with the +.Ar timestamp +given instead of the actual modification time of the individual archive member +so that repeatable builds are possible. +The +.Ar timestamp +can be a +.Pa pathname , +where the timestamps are derived from that file, a parseable date for +.Xr parsedate 3 +(this option is not yet available in the tools build), or an integer value +interpreted as the number of seconds from the Epoch. .It Fl Fl xz Use .Xr xz 1 @@ -958,11 +977,11 @@ Time comparisons using both file times is useful when is used to create a time based incremental archive (only files that were changed during a specified time range will be archived). .Pp -A time range is made up of six different fields and each field must contain two -digits. +A time range is made up of seven different fields and each field must contain +two digits. The format is: .Dl [[[[[cc]yy]mm]dd]hh]mm[\&.ss] -Where +where .Cm cc is the first two digits of the year (the century), .Cm yy @@ -1277,7 +1296,15 @@ and operations are extensions to the .Tn POSIX standard. +.Sh HISTORY +A +.Nm +utility appeared in +.Bx 4.4 . .Sh AUTHORS -Keith Muller at the University of California, San Diego. -Luke Mewburn implemented +.An -nosplit +.An Keith Muller +at the University of California, San Diego. +.An Luke Mewburn +implemented .Fl M . diff --git a/bin/pax/pax.c b/bin/pax/pax.c index 253d5fc94..5aefef05b 100644 --- a/bin/pax/pax.c +++ b/bin/pax/pax.c @@ -1,4 +1,4 @@ -/* $NetBSD: pax.c,v 1.47 2011/08/29 14:47:48 joerg Exp $ */ +/* $NetBSD: pax.c,v 1.49 2019/04/24 17:27:08 cheusov Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -44,23 +44,23 @@ __COPYRIGHT("@(#) Copyright (c) 1992, 1993\ #if 0 static char sccsid[] = "@(#)pax.c 8.2 (Berkeley) 4/18/94"; #else -__RCSID("$NetBSD: pax.c,v 1.47 2011/08/29 14:47:48 joerg Exp $"); +__RCSID("$NetBSD: pax.c,v 1.49 2019/04/24 17:27:08 cheusov Exp $"); #endif #endif /* not lint */ -#include #include +#include #include #include -#include -#include +#include #include +#include #include -#include +#include #include #include -#include -#include +#include +#include #include #include "pax.h" #include "extern.h" @@ -453,28 +453,28 @@ gen_init(void) if ((sigaction(SIGHUP, &n_hand, &o_hand) < 0) && (o_hand.sa_handler == SIG_IGN) && - (sigaction(SIGHUP, &o_hand, &o_hand) < 0)) + (sigaction(SIGHUP, &o_hand, NULL) < 0)) goto out; if ((sigaction(SIGTERM, &n_hand, &o_hand) < 0) && (o_hand.sa_handler == SIG_IGN) && - (sigaction(SIGTERM, &o_hand, &o_hand) < 0)) + (sigaction(SIGTERM, &o_hand, NULL) < 0)) goto out; if ((sigaction(SIGINT, &n_hand, &o_hand) < 0) && (o_hand.sa_handler == SIG_IGN) && - (sigaction(SIGINT, &o_hand, &o_hand) < 0)) + (sigaction(SIGINT, &o_hand, NULL) < 0)) goto out; if ((sigaction(SIGQUIT, &n_hand, &o_hand) < 0) && (o_hand.sa_handler == SIG_IGN) && - (sigaction(SIGQUIT, &o_hand, &o_hand) < 0)) + (sigaction(SIGQUIT, &o_hand, NULL) < 0)) goto out; #ifdef SIGXCPU if ((sigaction(SIGXCPU, &n_hand, &o_hand) < 0) && (o_hand.sa_handler == SIG_IGN) && - (sigaction(SIGXCPU, &o_hand, &o_hand) < 0)) + (sigaction(SIGXCPU, &o_hand, NULL) < 0)) goto out; #endif n_hand.sa_handler = SIG_IGN; diff --git a/bin/pax/tar.1 b/bin/pax/tar.1 index 97ac36f43..de735e9a9 100644 --- a/bin/pax/tar.1 +++ b/bin/pax/tar.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: tar.1,v 1.35 2015/04/11 16:22:07 wiz Exp $ +.\" $NetBSD: tar.1,v 1.39 2019/03/19 10:14:46 wiz Exp $ .\" .\" Copyright (c) 1996 SigmaSoft, Th. Lockert .\" All rights reserved. @@ -25,7 +25,7 @@ .\" .\" OpenBSD: tar.1,v 1.28 2000/11/09 23:58:56 aaron Exp .\" -.Dd April 11, 2015 +.Dd March 19, 2019 .Dt TAR 1 .Os .Sh NAME @@ -107,10 +107,10 @@ then the archive will be processed using .It Fl h , Fl Fl dereference Follow symbolic links as if they were normal files or directories. -.It Fl J, Fl Fl xz +.It Fl J , Fl Fl xz Compress/decompress archive using .Xr xz 1 . -.It Fl j, Fl Fl bzip2, Fl Fl bunzip2 +.It Fl j , Fl Fl bzip2 , Fl Fl bunzip2 Use .Xr bzip2 1 for compression of the archive. @@ -170,14 +170,15 @@ As in .Cm old is a basic regular expression and .Cm new -can contain an ampersand (\*[Am]), \en (where n is a digit) back-references, +can contain an ampersand (&), \en (where n is a digit) back-references, or subexpression matching. The .Cm old string may also contain .Aq Dv newline characters. -Any non-null character can be used as a delimiter (/ is shown here). +Any non-null character except a backslash (\\) can be used as a delimiter +(/ is shown here). Multiple .Fl s expressions can be specified. @@ -196,7 +197,7 @@ The optional trailing will cause the final result of a successful substitution to be written to .Dv standard error in the following format: -.Dl \*[Lt]original pathname\*[Gt] \*[Gt]\*[Gt] \*[Lt]new pathname\*[Gt] +.Dl Ao "original pathname" Ac >> Ao "new pathname" Ac File or archive member names that substitute to the empty string are not selected and will be skipped. The substitutions are applied by default to the destination hard and symbolic @@ -297,6 +298,19 @@ can be processed. 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. +.It Fl Fl timestamp Ar timestamp +Store all modification times in the archive with the +.Ar timestamp +given instead of the actual modification time of the individual archive member +so that repeatable builds are possible. +The +.Ar timestamp +can be a +.Pa pathname , +where the timestamps are derived from that file, a parseable date for +.Xr parsedate 3 +(this option is not yet available in the tools build), or an integer value +interpreted as the number of seconds from the Epoch. .El .Pp The options diff --git a/bin/pax/tar.c b/bin/pax/tar.c index f4d57d41f..513846f4e 100644 --- a/bin/pax/tar.c +++ b/bin/pax/tar.c @@ -1,4 +1,4 @@ -/* $NetBSD: tar.c,v 1.72 2015/06/16 22:31:08 christos Exp $ */ +/* $NetBSD: tar.c,v 1.75 2019/03/20 03:13:39 gutteridge Exp $ */ /*- * Copyright (c) 1992 Keith Muller. @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94"; #else -__RCSID("$NetBSD: tar.c,v 1.72 2015/06/16 22:31:08 christos Exp $"); +__RCSID("$NetBSD: tar.c,v 1.75 2019/03/20 03:13:39 gutteridge Exp $"); #endif #endif /* not lint */ @@ -64,6 +64,8 @@ __RCSID("$NetBSD: tar.c,v 1.72 2015/06/16 22:31:08 christos Exp $"); #include "extern.h" #include "tar.h" +extern struct stat tst; + /* * Routines for reading, writing and header identify of various versions of tar */ @@ -349,7 +351,7 @@ tar_chksm(char *blk, int len) * checksum field as the sum of 8 blanks (which is pre-computed as * BLNKSUM). * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding - * starts, no point in summing zero's) + * starts, no point in summing zeros) */ pt += CHK_LEN; stop = blk + len; @@ -366,7 +368,7 @@ tar_chksm(char *blk, int len) * tar_id() * determine if a block given to us is a valid tar header (and not a USTAR * header). We have to be on the lookout for those pesky blocks of all - * zero's. + * zeros. * Return: * 0 if a tar header, -1 otherwise */ @@ -384,7 +386,7 @@ tar_id(char *blk, int size) uhd = (HD_USTAR *)blk; /* - * check for block of zero's first, a simple and fast test, then make + * check for block of zeros first, a simple and fast test, then make * sure this is not a ustar header by looking for the ustar magic * cookie. We should use TMAGLEN, but some USTAR archive programs are * wrong and create archives missing the \0. Last we check the @@ -484,6 +486,8 @@ tar_rd(ARCHD *arcn, char *buf) arcn->sb.st_uid = (uid_t)asc_u32(hd->uid, sizeof(hd->uid), OCT); arcn->sb.st_gid = (gid_t)asc_u32(hd->gid, sizeof(hd->gid), OCT); arcn->sb.st_size = (off_t)ASC_OFFT(hd->size, sizeof(hd->size), OCT); + if (arcn->sb.st_size == -1) + return -1; arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->mtime, sizeof(hd->mtime), OCT); arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; @@ -587,6 +591,7 @@ tar_wr(ARCHD *arcn) { HD_TAR *hd; int len; + uintmax_t mtime; char hdblk[sizeof(HD_TAR)]; /* @@ -695,10 +700,11 @@ tar_wr(ARCHD *arcn) /* * copy those fields that are independent of the type */ + mtime = tst.st_ino ? tst.st_mtime : arcn->sb.st_mtime; if (u32_oct((uintmax_t)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) || u32_oct((uintmax_t)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) || u32_oct((uintmax_t)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) || - u32_oct((uintmax_t)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1)) + u32_oct(mtime, hd->mtime, sizeof(hd->mtime), 1)) goto out; /* @@ -763,7 +769,7 @@ ustar_stwr(void) /* * ustar_id() * determine if a block given to us is a valid ustar header. We have to - * be on the lookout for those pesky blocks of all zero's + * be on the lookout for those pesky blocks of all zeros * Return: * 0 if a ustar header, -1 otherwise */ @@ -778,7 +784,7 @@ ustar_id(char *blk, int size) hd = (HD_USTAR *)blk; /* - * check for block of zero's first, a simple and fast test then check + * check for block of zeros first, a simple and fast test then check * ustar magic cookie. We should use TMAGLEN, but some USTAR archive * programs are fouled up and create archives missing the \0. Last we * check the checksum. If ok we have to assume it is a valid header. @@ -856,6 +862,8 @@ ustar_rd(ARCHD *arcn, char *buf) arcn->sb.st_mode = (mode_t)(asc_u32(hd->mode, sizeof(hd->mode), OCT) & 0xfff); arcn->sb.st_size = (off_t)ASC_OFFT(hd->size, sizeof(hd->size), OCT); + if (arcn->sb.st_size == -1) + return -1; arcn->sb.st_mtime = (time_t)(int32_t)asc_u32(hd->mtime, sizeof(hd->mtime), OCT); arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; @@ -1046,6 +1054,7 @@ ustar_wr(ARCHD *arcn) { HD_USTAR *hd; char *pt; + uintmax_t mtime; char hdblk[sizeof(HD_USTAR)]; const char *user, *group; @@ -1210,7 +1219,8 @@ ustar_wr(ARCHD *arcn) return size_err("UID", arcn); if (u32_oct((uintmax_t)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3)) return size_err("GID", arcn); - if (u32_oct((uintmax_t)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3)) + mtime = tst.st_ino ? tst.st_mtime : arcn->sb.st_mtime; + if (u32_oct(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); @@ -1369,7 +1379,7 @@ tar_gnutar_exclude_one(const char *line, size_t len) } /* - * deal with GNU tar -X/--exclude-from & --exclude switchs. basically, + * deal with GNU tar -X/--exclude-from & --exclude switches. basically, * we go through each line of the file, building a string from the "glob" * lines in the file into RE lines, of the form `/^RE$//', which we pass * to rep_add(), which will add a empty replacement (exclusion), for the