]> git.gag.com Git - debian/pax/commitdiff
freshen to upstream CVS head origin/upstream upstream/20080811
authorBdale Garbee <bdale@gag.com>
Mon, 11 Aug 2008 15:43:21 +0000 (12:43 -0300)
committerBdale Garbee <bdale@gag.com>
Mon, 11 Aug 2008 15:43:21 +0000 (12:43 -0300)
30 files changed:
Makefile
ar_io.c
ar_subs.c
buf_subs.c
cache.c
cache.h
cpio.1
cpio.c
cpio.h
extern.h
file_subs.c
ftree.c
ftree.h
gen_subs.c
getoldopt.c
options.c
options.h
pat_rep.c
pat_rep.h
pax.1
pax.c
pax.h
sel_subs.c
sel_subs.h
tables.c
tables.h
tar.1
tar.c
tar.h
tty_subs.c

index e8affe51ff5ac132dd030a9fb2a7c03c272efac7..9ea2e86dcc6a2dac9ba3ef4308f269a6e9c09e91 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,28 +1,15 @@
-#      $OpenBSD: Makefile,v 1.9 1997/09/21 11:35:28 deraadt Exp $
+#      $OpenBSD: Makefile,v 1.10 2001/05/26 00:32:20 millert Exp $
 
 # To install on versions prior to BSD 4.4 the following may have to be
 # defined with CFLAGS +=
 #
-# -DNET2_STAT  Use NET2 or older stat structure. The version of the
-#              stat structure is easily determined by looking at the
-#              basic type of an off_t (often defined in the file:
-#              /usr/include/sys/types.h). If off_t is a long (and is
-#              NOT A quad) then you must define NET2_STAT.
+# -DLONG_OFF_T Define this if the base type of an off_t is a long (and is
+#              NOT a quad).  (This is often defined in the file
+#              /usr/include/sys/types.h).
 #              This define is important, as if you do have a quad_t
-#              off_t and define NET2_STAT, pax will compile but will
+#              off_t and define LONG_OFF_T, pax will compile but will
 #              NOT RUN PROPERLY.
 #
-# -DNET2_FTS   Use the older NET2 fts. To identify the version,
-#              examine the file: /usr/include/fts.h. If FTS_COMFOLLOW
-#              is not defined then you must define NET2_FTS.
-#              Pax may not compile if this not (un)defined properly.
-#
-# -DNET2_REGEX Use the older regexp.h not regex.h. The regex version
-#              is determined by looking at the value returned by
-#              regexec() (man 3 regexec). If regexec return a 1 for
-#              success (and NOT a 0 for success) you have the older
-#              regex routines and must define NET2_REGEX.
-#              Pax may not compile if this not (un)defined properly.
 
 PROG=   pax
 SRCS=  ar_io.c ar_subs.c buf_subs.c cache.c cpio.c file_subs.c ftree.c\
diff --git a/ar_io.c b/ar_io.c
index 6afe997e246abc1442eeb8958447ed86f51eede5..2a833bb2f65d333c5b285d553cc8d7de916d01ab 100644 (file)
--- a/ar_io.c
+++ b/ar_io.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ar_io.c,v 1.18 1998/09/20 02:22:21 millert Exp $      */
+/*     $OpenBSD: ar_io.c,v 1.38 2008/06/11 00:49:08 pvalchev Exp $     */
 /*     $NetBSD: ar_io.c,v 1.5 1996/03/26 23:54:13 mrg Exp $    */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)ar_io.c    8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)ar_io.c      8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: ar_io.c,v 1.18 1998/09/20 02:22:21 millert Exp $";
+static const char rcsid[] = "$OpenBSD: ar_io.c,v 1.38 2008/06/11 00:49:08 pvalchev Exp $";
 #endif
 #endif /* not lint */
 
@@ -52,6 +48,7 @@ static char rcsid[] = "$OpenBSD: ar_io.c,v 1.18 1998/09/20 02:22:21 millert Exp
 #include <sys/ioctl.h>
 #include <sys/mtio.h>
 #include <sys/param.h>
+#include <sys/wait.h>
 #include <signal.h>
 #include <string.h>
 #include <fcntl.h>
@@ -72,8 +69,8 @@ static char rcsid[] = "$OpenBSD: ar_io.c,v 1.18 1998/09/20 02:22:21 millert Exp
 #define EXT_MODE       O_RDONLY        /* open mode for list/extract */
 #define AR_MODE                (O_WRONLY | O_CREAT | O_TRUNC)  /* mode for archive */
 #define APP_MODE       O_RDWR          /* mode for append */
-#define STDO           "<STDOUT>"      /* psuedo name for stdout */
-#define STDN           "<STDIN>"       /* psuedo name for stdin */
+#define STDO           "<STDOUT>"      /* pseudo name for stdout */
+#define STDN           "<STDIN>"       /* pseudo name for stdin */
 static int arfd = -1;                  /* archive file descriptor */
 static int artyp = ISREG;              /* archive type: file/FIFO/tape */
 static int arvol = 1;                  /* archive volume number */
@@ -85,12 +82,14 @@ static struct stat arsb;            /* stat of archive device at open */
 static int invld_rec;                  /* tape has out of spec record size */
 static int wr_trail = 1;               /* trailer was rewritten in append */
 static int can_unlnk = 0;              /* do we unlink null archives?  */
-char *arcname;                         /* printable name of archive */
-char *gzip_program;                    /* name of gzip program */
+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 __P((void));
+static int get_phys(void);
 extern sigset_t s_mask;
-static void ar_start_gzip __P((int));
+static void ar_start_gzip(int, const char *, int);
 
 /*
  * ar_open()
@@ -101,14 +100,8 @@ static void ar_start_gzip __P((int));
  *     -1 on failure, 0 otherwise
  */
 
-#ifdef __STDC__
 int
-ar_open(char *name)
-#else
-int
-ar_open(name)
-       char *name;
-#endif
+ar_open(const char *name)
 {
        struct mtget mb;
 
@@ -129,29 +122,27 @@ ar_open(name)
                        arfd = STDIN_FILENO;
                        arcname = STDN;
                } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0)
-                       syswarn(0, errno, "Failed open to read on %s", name);
-               if (zflag)
-                       ar_start_gzip(arfd);
+                       syswarn(1, errno, "Failed open to read on %s", name);
+               if (arfd != -1 && gzip_program != NULL)
+                       ar_start_gzip(arfd, gzip_program, 0);
                break;
        case ARCHIVE:
                if (name == NULL) {
                        arfd = STDOUT_FILENO;
                        arcname = STDO;
                } else if ((arfd = open(name, AR_MODE, DMOD)) < 0)
-                       syswarn(0, errno, "Failed open to write on %s", name);
+                       syswarn(1, errno, "Failed open to write on %s", name);
                else
                        can_unlnk = 1;
-               if (zflag)
-                       ar_start_gzip(arfd);
+               if (arfd != -1 && gzip_program != NULL)
+                       ar_start_gzip(arfd, gzip_program, 1);
                break;
        case APPND:
-               if (zflag)
-                       err(1, "can not gzip while appending");
                if (name == NULL) {
                        arfd = STDOUT_FILENO;
                        arcname = STDO;
                } else if ((arfd = open(name, APP_MODE, DMOD)) < 0)
-                       syswarn(0, errno, "Failed open to read/write on %s",
+                       syswarn(1, errno, "Failed open to read/write on %s",
                                name);
                break;
        case COPY:
@@ -166,13 +157,15 @@ ar_open(name)
                return(-1);
 
        if (chdname != NULL)
-               if (chdir(chdname) != 0)
+               if (chdir(chdname) != 0) {
                        syswarn(1, errno, "Failed chdir to %s", chdname);
+                       return(-1);
+               }
        /*
         * set up is based on device type
         */
        if (fstat(arfd, &arsb) < 0) {
-               syswarn(0, errno, "Failed stat on %s", arcname);
+               syswarn(1, errno, "Failed stat on %s", arcname);
                (void)close(arfd);
                arfd = -1;
                can_unlnk = 0;
@@ -214,11 +207,11 @@ ar_open(name)
        /*
         * set default blksz on read. APPNDs writes rdblksz on the last volume
         * On all new archive volumes, we shift to wrblksz (if the user
-        * specified one, otherwize we will continue to use rdblksz). We
-        * must to set blocksize based on what kind of device the archive is
+        * specified one, otherwise we will continue to use rdblksz). We
+        * must set blocksize based on what kind of device the archive is
         * stored.
         */
-       switch(artyp) {
+       switch (artyp) {
        case ISTAPE:
                /*
                 * Tape drives come in at least two flavors. Those that support
@@ -281,7 +274,7 @@ ar_open(name)
                        if ((arsb.st_size % rdblksz) == 0)
                                break;
                /*
-                * When we cannont find a match, we may have a flawed archive.
+                * When we cannot find a match, we may have a flawed archive.
                 */
                if (rdblksz <= 0)
                        rdblksz = FILEBLK;
@@ -295,7 +288,7 @@ ar_open(name)
                break;
        default:
                /*
-                * should never happen, worse case, slow... 
+                * should never happen, worst case, slow...
                 */
                blksz = rdblksz = BLKMULT;
                break;
@@ -308,14 +301,10 @@ ar_open(name)
  * ar_close()
  *     closes archive device, increments volume number, and prints i/o summary
  */
-#ifdef __STDC__
 void
 ar_close(void)
-#else
-void
-ar_close()
-#endif
 {
+       int status;
 
        if (arfd < 0) {
                did_io = io_ok = flcnt = 0;
@@ -347,8 +336,19 @@ ar_close()
                can_unlnk = 0;
        }
 
+       /*
+        * for a quick extract/list, pax frequently exits before the child
+        * process is done
+        */
+       if ((act == LIST || act == EXTRACT) && nflag && zpid > 0)
+               kill(zpid, SIGINT);
+
        (void)close(arfd);
 
+       /* Do not exit before child to ensure data integrity */
+       if (zpid > 0)
+               waitpid(zpid, &status, 0);
+
        if (vflag && (artyp == ISTAPE)) {
                (void)fputs("done.\n", listf);
                vfpart = 0;
@@ -388,7 +388,7 @@ ar_close()
         * could have written anything yet.
         */
        if (frmt == NULL) {
-#      ifdef NET2_STAT
+#      ifdef LONG_OFF_T
                (void)fprintf(listf, "%s: unknown format, %lu bytes skipped.\n",
 #      else
                (void)fprintf(listf, "%s: unknown format, %qu bytes skipped.\n",
@@ -403,7 +403,7 @@ ar_close()
                (void)fprintf(listf, "%qu blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120);
        else if (strcmp(NM_TAR, argv0) != 0)
                (void)fprintf(listf,
-#      ifdef NET2_STAT
+#      ifdef LONG_OFF_T
                    "%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n",
 #      else
                    "%s: %s vol %d, %lu files, %qu bytes read, %qu bytes written.\n",
@@ -420,15 +420,10 @@ ar_close()
  *     other side of the pipe from getting a SIGPIPE (pax will stop
  *     reading an archive once a format dependent trailer is detected).
  */
-#ifdef __STDC__
 void
 ar_drain(void)
-#else
-void
-ar_drain()
-#endif
 {
-       register int res;
+       int res;
        char drbuf[MAXBLK];
 
        /*
@@ -457,13 +452,8 @@ ar_drain()
  *     0 if all ready to write, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ar_set_wr(void)
-#else
-int
-ar_set_wr()
-#endif
 {
        off_t cpos;
 
@@ -473,7 +463,7 @@ ar_set_wr()
         */
        wr_trail = 0;
 
-       /* 
+       /*
         * Add any device dependent code as required here
         */
        if (artyp != ISREG)
@@ -494,19 +484,14 @@ ar_set_wr()
 /*
  * ar_app_ok()
  *     check if the last volume in the archive allows appends. We cannot check
- *     this until we are ready to write since there is no spec that says all 
+ *     this until we are ready to write since there is no spec that says all
  *     volumes in a single archive have to be of the same type...
  * Return:
  *     0 if we can append, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
 ar_app_ok(void)
-#else
-int
-ar_app_ok()
-#endif
 {
        if (artyp == ISPIPE) {
                paxwarn(1, "Cannot append to an archive obtained from a pipe.");
@@ -529,17 +514,10 @@ ar_app_ok()
  *     Number of bytes in buffer. 0 for end of file, -1 for a read error.
  */
 
-#ifdef __STDC__
 int
-ar_read(register char *buf, register int cnt)
-#else
-int
-ar_read(buf, cnt)
-       register char *buf;
-       register int cnt;
-#endif
+ar_read(char *buf, int cnt)
 {
-       register int res = 0;
+       int res = 0;
 
        /*
         * if last i/o was in error, no more reads until reset or new volume
@@ -563,10 +541,10 @@ ar_read(buf, cnt)
                        io_ok = 1;
                        if (res != rdblksz) {
                                /*
-                                * Record size changed. If this is happens on
+                                * Record size changed. If this happens on
                                 * any record after the first, we probably have
                                 * a tape drive which has a fixed record size
-                                * we are getting multiple records in a single
+                                * (we are getting multiple records in a single
                                 * read). Watch out for record blocking that
                                 * violates pax spec (must be a multiple of
                                 * BLKMULT).
@@ -616,20 +594,13 @@ ar_read(buf, cnt)
  * Return:
  *     Number of bytes written. 0 indicates end of volume reached and with no
  *     flaws (as best that can be detected). A -1 indicates an unrecoverable
- *     error in the archive occured.
+ *     error in the archive occurred.
  */
 
-#ifdef __STDC__
 int
-ar_write(register char *buf, register int bsz)
-#else
-int
-ar_write(buf, bsz)
-       register char *buf;
-       register int bsz;
-#endif
+ar_write(char *buf, int bsz)
 {
-       register int res;
+       int res;
        off_t cpos;
 
        /*
@@ -657,10 +628,10 @@ ar_write(buf, bsz)
        case ISREG:
                if ((res > 0) && (res % BLKMULT)) {
                        /*
-                        * try to fix up partial writes which are not BLKMULT
+                        * try to fix up partial writes which are not BLKMULT
                         * in size by forcing the runt record to next archive
                         * volume
-                        */
+                        */
                        if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
                                break;
                        cpos -= (off_t)res;
@@ -705,7 +676,7 @@ ar_write(buf, bsz)
        /*
         * Better tell the user the bad news...
         * if this is a block aligned archive format, we may have a bad archive
-        * if the format wants the header to start at a BLKMULT boundry. While
+        * if the format wants the header to start at a BLKMULT boundary.. While
         * we can deal with the mis-aligned data, it violates spec and other
         * archive readers will likely fail. if the format is not block
         * aligned, the user may be lucky (and the archive is ok).
@@ -744,13 +715,8 @@ ar_write(buf, bsz)
  *     0 when ok to try i/o again, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
 ar_rdsync(void)
-#else
-int
-ar_rdsync()
-#endif
 {
        long fsbz;
        off_t cpos;
@@ -758,7 +724,7 @@ ar_rdsync()
        struct mtop mb;
 
        /*
-        * Fail resync attempts at user request (done) or this is going to be
+        * Fail resync attempts at user request (done) or if this is going to be
         * an update/append to a existing archive. if last i/o hit media end,
         * we need to go to the next volume not try a resync
         */
@@ -772,13 +738,13 @@ ar_rdsync()
        if (io_ok)
                did_io = 1;
 
-       switch(artyp) {
+       switch (artyp) {
        case ISTAPE:
                /*
                 * 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
                 * past. If we did not get any data since the last resync try
-                * to move the tape foward one PHYSICAL record past any
+                * to move the tape forward one PHYSICAL record past any
                 * damaged tape section. Some tape drives are stubborn and need
                 * to be pushed.
                 */
@@ -827,7 +793,7 @@ ar_rdsync()
 
 /*
  * ar_fow()
- *     Move the I/O position within the archive foward the specified number of
+ *     Move the I/O position within the archive forward the specified number of
  *     bytes as supported by the device. If we cannot move the requested
  *     number of bytes, return the actual number of bytes moved in skipped.
  * Return:
@@ -835,15 +801,8 @@ ar_rdsync()
  *     partial move (the amount moved is in skipped)
  */
 
-#ifdef __STDC__
 int
 ar_fow(off_t sksz, off_t *skipped)
-#else
-int
-ar_fow(sksz, skipped)
-       off_t sksz;
-       off_t *skipped;
-#endif
 {
        off_t cpos;
        off_t mpos;
@@ -853,7 +812,7 @@ ar_fow(sksz, skipped)
                return(0);
 
        /*
-        * we cannot move foward at EOF or error
+        * we cannot move forward at EOF or error
         */
        if (lstrval <= 0)
                return(lstrval);
@@ -862,7 +821,7 @@ ar_fow(sksz, skipped)
         * Safer to read forward on devices where it is hard to find the end of
         * the media without reading to it. With tapes we cannot be sure of the
         * number of physical blocks to skip (we do not know physical block
-        * size at this point), so we must only read foward on tapes!
+        * size at this point), so we must only read forward on tapes!
         */
        if (artyp != ISREG)
                return(0);
@@ -871,12 +830,12 @@ ar_fow(sksz, skipped)
         * figure out where we are in the archive
         */
        if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) {
-               /* 
-                * we can be asked to move farther than there are bytes in this
+               /*
+                * we can be asked to move farther than there are bytes in this
                 * volume, if so, just go to file end and let normal buf_fill()
                 * deal with the end of file (it will go to next volume by
                 * itself)
-                */
+                */
                if ((mpos = cpos + sksz) > arsb.st_size) {
                        *skipped = arsb.st_size - cpos;
                        mpos = arsb.st_size;
@@ -885,7 +844,7 @@ ar_fow(sksz, skipped)
                if (lseek(arfd, mpos, SEEK_SET) >= 0)
                        return(0);
        }
-       syswarn(1, errno, "Foward positioning operation on archive failed");
+       syswarn(1, errno, "Forward positioning operation on archive failed");
        lstrval = -1;
        return(-1);
 }
@@ -901,18 +860,12 @@ ar_fow(sksz, skipped)
  *     0 if moved the requested distance, -1 on complete failure
  */
 
-#ifdef __STDC__
 int
 ar_rev(off_t sksz)
-#else
-int
-ar_rev(sksz)
-       off_t sksz;
-#endif
 {
        off_t cpos;
        struct mtop mb;
-       register int phyblk;
+       int phyblk;
 
        /*
         * make sure we do not have try to reverse on a flawed archive
@@ -920,7 +873,7 @@ ar_rev(sksz)
        if (lstrval < 0)
                return(lstrval);
 
-       switch(artyp) {
+       switch (artyp) {
        case ISPIPE:
                if (sksz <= 0)
                        break;
@@ -953,8 +906,8 @@ ar_rev(sksz)
 
                /*
                 * we may try to go backwards past the start when the archive
-                * is only a single record. If this hapens and we are on a
-                * multi volume archive, we need to go to the end of the
+                * is only a single record. If this happens and we are on a
+                * multi-volume archive, we need to go to the end of the
                 * previous volume and continue our movement backwards from
                 * there.
                 */
@@ -977,12 +930,12 @@ ar_rev(sksz)
                break;
        case ISTAPE:
                /*
-                * Calculate and move the proper number of PHYSICAL tape
+                * Calculate and move the proper number of PHYSICAL tape
                 * blocks. If the sksz is not an even multiple of the physical
                 * tape size, we cannot do the move (this should never happen).
-                * (We also cannot handler trailers spread over two vols).
+                * (We also cannot handle trailers spread over two vols.)
                 * get_phys() also makes sure we are in front of the filemark.
-                */
+                */
                if ((phyblk = get_phys()) <= 0) {
                        lstrval = -1;
                        return(-1);
@@ -1031,7 +984,7 @@ ar_rev(sksz)
 /*
  * get_phys()
  *     Determine the physical block size on a tape drive. We need the physical
- *     block size so we know how many bytes we skip over when we move with 
+ *     block size so we know how many bytes we skip over when we move with
  *     mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when
  *     return.
  *     This is one really SLOW routine...
@@ -1039,17 +992,12 @@ ar_rev(sksz)
  *     physical block size if ok (ok > 0), -1 otherwise
  */
 
-#ifdef __STDC__
 static int
 get_phys(void)
-#else
-static int
-get_phys()
-#endif
 {
-       register int padsz = 0;
-       register int res;
-       register int phyblk;
+       int padsz = 0;
+       int res;
+       int phyblk;
        struct mtop mb;
        char scbuf[MAXBLK];
 
@@ -1097,7 +1045,7 @@ get_phys()
        }
 
        /*
-        * read foward to the file mark, then back up in front of the filemark
+        * read forward to the file mark, then back up in front of the filemark
         * (this is a bit paranoid, but should be safe to do).
         */
        while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)
@@ -1157,13 +1105,8 @@ get_phys()
  *     0 when ready to continue, -1 when all done
  */
 
-#ifdef __STDC__
 int
 ar_next(void)
-#else
-int
-ar_next()
-#endif
 {
        char buf[PAXPATHLEN+2];
        static int freeit = 0;
@@ -1180,7 +1123,7 @@ ar_next()
        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);
@@ -1206,7 +1149,7 @@ ar_next()
                else
                        tty_prnt("\n");
 
-               for(;;) {
+               for (;;) {
                        tty_prnt("Type \"y\" to continue, \".\" to quit %s,",
                                argv0);
                        tty_prnt(" or \"s\" to switch to new device.\nIf you");
@@ -1285,7 +1228,7 @@ ar_next()
                 */
                if (ar_open(buf) >= 0) {
                        if (freeit) {
-                               (void)free(arcname);
+                               (void)free((char *)arcname);
                                freeit = 0;
                        }
                        if ((arcname = strdup(buf)) == NULL) {
@@ -1309,58 +1252,39 @@ ar_next()
  * to keep the fd the same in the calling function (parent).
  */
 void
-#ifdef __STDC__
-ar_start_gzip(int fd)
-#else
-ar_start_gzip(fd)
-       int fd;
-#endif
+ar_start_gzip(int fd, const char *gzip_program, int wr)
 {
-       pid_t pid;
        int fds[2];
-       char *gzip_flags;
+       const char *gzip_flags;
 
        if (pipe(fds) < 0)
                err(1, "could not pipe");
-       pid = fork();
-       if (pid < 0)
+       zpid = fork();
+       if (zpid < 0)
                err(1, "could not fork");
 
        /* parent */
-       if (pid) {
-               switch (act) {
-               case ARCHIVE:
+       if (zpid) {
+               if (wr)
                        dup2(fds[1], fd);
-                       break;
-               case LIST:
-               case EXTRACT:
+               else
                        dup2(fds[0], fd);
-                       break;
-               default:
-                       errx(1, "ar_start_gzip:  impossible");
-               }
                close(fds[0]);
                close(fds[1]);
        } else {
-               switch (act) {
-               case ARCHIVE:
+               if (wr) {
                        dup2(fds[0], STDIN_FILENO);
                        dup2(fd, STDOUT_FILENO);
                        gzip_flags = "-c";
-                       break;
-               case LIST:
-               case EXTRACT:
+               } else {
                        dup2(fds[1], STDOUT_FILENO);
                        dup2(fd, STDIN_FILENO);
                        gzip_flags = "-dc";
-                       break;
-               default:
-                       errx(1, "ar_start_gzip:  impossible");
                }
                close(fds[0]);
                close(fds[1]);
-               if (execlp(gzip_program, gzip_program, gzip_flags, NULL) < 0)
-                       err(1, "could not exec");
+               if (execlp(gzip_program, gzip_program, gzip_flags, (char *)NULL) < 0)
+                       err(1, "could not exec %s", gzip_program);
                /* NOTREACHED */
        }
 }
index 46868823185ad94e1a91eb6fffbc1a5f21f94577..73aefdabb489f2ab41851a548784608da5688f1a 100644 (file)
--- a/ar_subs.c
+++ b/ar_subs.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ar_subs.c,v 1.14 1998/09/20 02:22:21 millert Exp $    */
+/*     $OpenBSD: ar_subs.c,v 1.32 2008/05/06 06:54:28 henning Exp $    */
 /*     $NetBSD: ar_subs.c,v 1.5 1995/03/21 09:07:06 cgd Exp $  */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)ar_subs.c  8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)ar_subs.c    8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: ar_subs.c,v 1.14 1998/09/20 02:22:21 millert Exp $";
+static const char rcsid[] = "$OpenBSD: ar_subs.c,v 1.32 2008/05/06 06:54:28 henning Exp $";
 #endif
 #endif /* not lint */
 
@@ -60,9 +56,9 @@ static char rcsid[] = "$OpenBSD: ar_subs.c,v 1.14 1998/09/20 02:22:21 millert Ex
 #include "pax.h"
 #include "extern.h"
 
-static void wr_archive __P((register ARCHD *, int is_app));
-static int get_arc __P((void));
-static int next_head __P((register ARCHD *));
+static void wr_archive(ARCHD *, int is_app);
+static int get_arc(void);
+static int next_head(ARCHD *);
 extern sigset_t s_mask;
 
 /*
@@ -79,16 +75,11 @@ u_long flcnt;                               /* number of files processed */
  *     (no pattern matches all).
  */
 
-#ifdef __STDC__
 void
 list(void)
-#else
-void
-list()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
+       ARCHD *arcn;
+       int res;
        ARCHD archd;
        time_t now;
 
@@ -113,6 +104,17 @@ list()
         * 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, arcn->type == PAX_GLF
+                           ? -1 : -2, &cnt))
+                               (void)rd_skip(cnt + arcn->pad);
+                       continue;
+               }
+
                /*
                 * check for pattern, and user specified options match.
                 * When all patterns are matched we are done.
@@ -161,16 +163,11 @@ list()
  *     pattern(s) (no patterns extracts all members)
  */
 
-#ifdef __STDC__
 void
 extract(void)
-#else
-void
-extract()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
+       ARCHD *arcn;
+       int res;
        off_t cnt;
        ARCHD archd;
        struct stat sb;
@@ -201,6 +198,15 @@ extract()
         * 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, arcn->type == PAX_GLF
+                           ? -1 : -2, &cnt))
+                               (void)rd_skip(cnt + arcn->pad);
+                       continue;
+               }
 
                /*
                 * check for pattern, and user specified options match. When
@@ -220,7 +226,7 @@ extract()
 
                /*
                 * with -u or -D only extract when the archive member is newer
-                * than the file with the same name in the file system (nos
+                * than the file with the same name in the file system (no
                 * test of being the same type is required).
                 * NOTE: this test is done BEFORE name modifications as
                 * specified by pax. this operation can be confusing to the
@@ -261,7 +267,7 @@ extract()
                }
 
                /*
-                * Non standard -Y and -Z flag. When the exisiting file is
+                * Non standard -Y and -Z flag. When the existing file is
                 * same age or newer skip
                 */
                if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
@@ -286,7 +292,7 @@ extract()
                        if (vflag > 1)
                                ls_list(arcn, now, listf);
                        else {
-                               (void)fputs(arcn->name, listf);
+                               (void)safe_print(arcn->name, listf);
                                vfpart = 1;
                        }
                }
@@ -321,7 +327,7 @@ extract()
                                (void)putc('\n', listf);
                                vfpart = 0;
                        }
-                       continue;
+                       goto popd;
                }
                /*
                 * we have a file with data here. If we can not create it, skip
@@ -330,7 +336,7 @@ extract()
                if ((fd = file_creat(arcn)) < 0) {
                        (void)rd_skip(arcn->skip + arcn->pad);
                        purg_lnk(arcn);
-                       continue;
+                       goto popd;
                }
                /*
                 * extract the file from the archive and skip over padding and
@@ -345,6 +351,7 @@ extract()
                if (!res)
                        (void)rd_skip(cnt + arcn->pad);
 
+popd:
                /*
                 * if required, chdir around.
                 */
@@ -372,21 +379,14 @@ extract()
  *     previously written archive.
  */
 
-#ifdef __STDC__
 static void
-wr_archive(register ARCHD *arcn, int is_app)
-#else
-static void
-wr_archive(arcn, is_app)
-       register ARCHD *arcn;
-       int is_app;
-#endif
+wr_archive(ARCHD *arcn, int is_app)
 {
-       register int res;
-       register int hlk;
-       register int wr_one;
+       int res;
+       int hlk;
+       int wr_one;
        off_t cnt;
-       int (*wrf)();
+       int (*wrf)(ARCHD *);
        int fd = -1;
        time_t now;
 
@@ -397,11 +397,22 @@ wr_archive(arcn, is_app)
        if (((hlk = frmt->hlk) == 1) && (lnk_start() < 0))
                return;
 
+       /*
+        * if this is not append, and there are no files, we do not write a 
+        * trailer
+        */
+       wr_one = is_app;
+
        /*
         * start up the file traversal code and format specific write
         */
-       if ((ftree_start() < 0) || ((*frmt->st_wr)() < 0))
+       if (ftree_start() < 0) {
+               if (is_app)
+                       goto trailer;
                return;
+       } else if (((*frmt->st_wr)() < 0))
+               return;
+
        wrf = frmt->wr;
 
        /*
@@ -411,11 +422,6 @@ wr_archive(arcn, is_app)
        if (iflag && (name_start() < 0))
                return;
 
-       /*
-        * if this not append, and there are no files, we do no write a trailer
-        */
-       wr_one = is_app;
-
        now = time(NULL);
 
        /*
@@ -435,8 +441,10 @@ wr_archive(arcn, is_app)
                         */
                        if ((res = chk_ftime(arcn)) < 0)
                                break;
-                       if (res > 0)
+                       if (res > 0) {
+                               ftree_skipped_newer(arcn);
                                continue;
+                       }
                }
 
                /*
@@ -479,7 +487,7 @@ wr_archive(arcn, is_app)
                if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) {
                        /*
                         * unable to obtain the crc we need, close the file,
-                        * purge link table entry 
+                        * purge link table entry
                         */
                        rdfile_close(arcn, &fd);
                        purg_lnk(arcn);
@@ -490,7 +498,7 @@ wr_archive(arcn, is_app)
                        if (vflag > 1)
                                ls_list(arcn, now, listf);
                        else {
-                               (void)fputs(arcn->name, listf);
+                               (void)safe_print(arcn->name, listf);
                                vfpart = 1;
                        }
                }
@@ -506,7 +514,7 @@ wr_archive(arcn, is_app)
                }
                wr_one = 1;
                if (res > 0) {
-                       /* 
+                       /*
                         * format write says no file data needs to be stored
                         * so we are done messing with this file
                         */
@@ -543,8 +551,9 @@ wr_archive(arcn, is_app)
                        break;
        }
 
+trailer:
        /*
-        * tell format to write trailer; pad to block boundry; reset directory
+        * tell format to write trailer; pad to block boundary; reset directory
         * mode/access times, and check if all patterns supplied by the user
         * were matched. block off signals to avoid chance for multiple entry
         * into the cleanup code
@@ -569,7 +578,7 @@ wr_archive(arcn, is_app)
  *     is called to add the new members.
  *     PAX IMPLEMENTATION DETAIL NOTE:
  *     -u is implemented by adding the new members to the end of the archive.
- *     Care is taken so that these do not end up as links to the older 
+ *     Care is taken so that these do not end up as links to the older
  *     version of the same file already stored in the archive. It is expected
  *     when extraction occurs these newer versions will over-write the older
  *     ones stored "earlier" in the archive (this may be a bad assumption as
@@ -582,16 +591,11 @@ wr_archive(arcn, is_app)
  *     over write existing files that it creates.
  */
 
-#ifdef __STDC__
 void
 append(void)
-#else
-void
-append()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
+       ARCHD *arcn;
+       int res;
        ARCHD archd;
        FSUB *orgfrmt;
        int udev;
@@ -602,7 +606,7 @@ append()
 
        /*
         * Do not allow an append operation if the actual archive is of a
-        * different format than the user specified foramt.
+        * different format than the user specified format.
         */
        if (get_arc() < 0)
                return;
@@ -698,7 +702,7 @@ append()
        lnk_end();
 
        /*
-        * try to postion for write, if this fails quit. if any error occurs,
+        * try to position for write, if this fails quit. if any error occurs,
         * we will refuse to write
         */
        if (appnd_start(tlen) < 0)
@@ -711,7 +715,7 @@ append()
                (void)fputs("done.\n", listf);
                vfpart = 0;
        }
-       
+
        /*
         * go to the writing phase to add the new members
         */
@@ -723,13 +727,8 @@ append()
  *     write a new archive
  */
 
-#ifdef __STDC__
 void
 archive(void)
-#else
-void
-archive()
-#endif
 {
        ARCHD archd;
 
@@ -754,20 +753,15 @@ archive()
  *     (except the files are forced to be under the destination directory).
  */
 
-#ifdef __STDC__
 void
 copy(void)
-#else
-void
-copy()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
-       register int fddest;
-       register char *dest_pt;
-       register int dlen;
-       register int drem;
+       ARCHD *arcn;
+       int res;
+       int fddest;
+       char *dest_pt;
+       int dlen;
+       int drem;
        int fdsrc = -1;
        struct stat sb;
        ARCHD archd;
@@ -778,13 +772,18 @@ copy()
         * set up the destination dir path and make sure it is a directory. We
         * make sure we have a trailing / on the destination
         */
-       dlen = l_strncpy(dirbuf, dirptr, sizeof(dirbuf) - 1);
+       dlen = strlcpy(dirbuf, dirptr, sizeof(dirbuf));
+       if (dlen >= sizeof(dirbuf) ||
+           (dlen == sizeof(dirbuf) - 1 && dirbuf[dlen - 1] != '/')) {
+               paxwarn(1, "directory name is too long %s", dirptr);
+               return;
+       }
        dest_pt = dirbuf + dlen;
        if (*(dest_pt-1) != '/') {
                *dest_pt++ = '/';
+               *dest_pt = '\0';
                ++dlen;
        }
-       *dest_pt = '\0';
        drem = PAXPATHLEN - dlen;
 
        if (stat(dirptr, &sb) < 0) {
@@ -799,7 +798,7 @@ copy()
 
        /*
         * start up the hard link table; file traversal routines and the
-        * modification time and access mode database 
+        * modification time and access mode database
         */
        if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0))
                return;
@@ -842,17 +841,12 @@ copy()
                        /*
                         * create the destination name
                         */
-                       if (*(arcn->name) == '/')
-                               res = 1;
-                       else
-                               res = 0;
-                       if ((arcn->nlen - res) > drem) {
+                       if (strlcpy(dest_pt, arcn->name + (*arcn->name == '/'),
+                           drem + 1) > drem) {
                                paxwarn(1, "Destination pathname too long %s",
                                        arcn->name);
                                continue;
                        }
-                       (void)strncpy(dest_pt, arcn->name + res, drem);
-                       dirbuf[PAXPATHLEN] = '\0';
 
                        /*
                         * if existing file is same age or newer skip
@@ -860,10 +854,11 @@ copy()
                        res = lstat(dirbuf, &sb);
                        *dest_pt = '\0';
 
-                       if (res == 0) {
+                       if (res == 0) {
+                               ftree_skipped_newer(arcn);
                                if (uflag && Dflag) {
                                        if ((arcn->sb.st_mtime<=sb.st_mtime) &&
-                                           (arcn->sb.st_ctime<=sb.st_ctime))
+                                           (arcn->sb.st_ctime<=sb.st_ctime))
                                                continue;
                                } else if (Dflag) {
                                        if (arcn->sb.st_ctime <= sb.st_ctime)
@@ -890,7 +885,7 @@ copy()
                }
 
                /*
-                * Non standard -Y and -Z flag. When the exisiting file is
+                * Non standard -Y and -Z flag. When the existing file is
                 * same age or newer skip
                 */
                if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
@@ -906,7 +901,7 @@ copy()
                }
 
                if (vflag) {
-                       (void)fputs(arcn->name, listf);
+                       (void)safe_print(arcn->name, listf);
                        vfpart = 1;
                }
                ++flcnt;
@@ -1006,21 +1001,15 @@ copy()
  *     the specs for rd_wrbuf() for more details)
  */
 
-#ifdef __STDC__
-static int
-next_head(register ARCHD *arcn)
-#else
 static int
-next_head(arcn)
-       register ARCHD *arcn;
-#endif
+next_head(ARCHD *arcn)
 {
-       register int ret;
-       register char *hdend;
-       register int res;
-       register int shftsz;
-       register int hsz;
-       register int in_resync = 0;     /* set when we are in resync mode */
+       int ret;
+       char *hdend;
+       int res;
+       int shftsz;
+       int hsz;
+       int in_resync = 0;              /* set when we are in resync mode */
        int cnt = 0;                    /* counter for trailer function */
        int first = 1;                  /* on 1st read, EOF isn't premature. */
 
@@ -1031,7 +1020,7 @@ next_head(arcn)
        res = hsz = frmt->hsz;
        hdend = hdbuf;
        shftsz = hsz - 1;
-       for(;;) {
+       for (;;) {
                /*
                 * keep looping until we get a contiguous FULL buffer
                 * (frmt->hsz is the proper size)
@@ -1095,7 +1084,7 @@ next_head(arcn)
                        /*
                         * this format has trailers outside of valid headers
                         */
-                       if ((ret = (*frmt->trail)(hdbuf,in_resync,&cnt)) == 0){
+                       if ((ret = (*frmt->trail)(arcn,hdbuf,in_resync,&cnt)) == 0){
                                /*
                                 * valid trailer found, drain input as required
                                 */
@@ -1142,7 +1131,7 @@ next_head(arcn)
         * the header. NOTE: the parameters are different than trailer routines
         * which encode trailers outside of the header!
         */
-       if (frmt->inhead && ((*frmt->trail)(arcn) == 0)) {
+       if (frmt->inhead && ((*frmt->trail)(arcn,NULL,0,NULL) == 0)) {
                /*
                 * valid trailer found, drain input as required
                 */
@@ -1164,18 +1153,13 @@ next_head(arcn)
  *     0 if archive found -1 otherwise
  */
 
-#ifdef __STDC__
 static int
 get_arc(void)
-#else
-static int
-get_arc()
-#endif
 {
-       register int i;
-       register int hdsz = 0;
-       register int res;
-       register int minhd = BLKMULT;
+       int i;
+       int hdsz = 0;
+       int res;
+       int minhd = BLKMULT;
        char *hdend;
        int notice = 0;
 
@@ -1192,7 +1176,7 @@ get_arc()
        res = BLKMULT;
        hdsz = 0;
        hdend = hdbuf;
-       for(;;) {
+       for (;;) {
                for (;;) {
                        /*
                         * fill the buffer with at least the smallest header
@@ -1238,7 +1222,7 @@ get_arc()
                        if ((*fsub[ford[i]].id)(hdbuf, hdsz) < 0)
                                continue;
                        frmt = &(fsub[ford[i]]);
-                       /* 
+                       /*
                         * yuck, to avoid slow special case code in the extract
                         * routines, just push this header back as if it was
                         * not seen. We have left extra space at start of the
index ad5f78eb7b53a11c07923854c91acc347bebbaa7..aff311aa6f28d5bf52d911ffdff57c70944b8ff5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: buf_subs.c,v 1.7 1997/09/01 18:29:46 deraadt Exp $    */
+/*     $OpenBSD: buf_subs.c,v 1.21 2005/11/09 19:59:06 otto Exp $      */
 /*     $NetBSD: buf_subs.c,v 1.5 1995/03/21 09:07:08 cgd Exp $ */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)buf_subs.c 8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)buf_subs.c   8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: buf_subs.c,v 1.7 1997/09/01 18:29:46 deraadt Exp $";
+static const char rcsid[] = "$OpenBSD: buf_subs.c,v 1.21 2005/11/09 19:59:06 otto Exp $";
 #endif
 #endif /* not lint */
 
@@ -89,13 +85,8 @@ off_t rdcnt;                         /* # of bytes read on current vol */
  *     0 if ok, -1 if the user specified write block size violates pax spec
  */
 
-#ifdef __STDC__
 int
 wr_start(void)
-#else
-int
-wr_start()
-#endif
 {
        buf = &(bufmem[BLKMULT]);
        /*
@@ -124,7 +115,7 @@ wr_start()
        }
 
        /*
-        * we only allow wrblksz to be used with all archive operations 
+        * we only allow wrblksz to be used with all archive operations
         */
        blksz = rdblksz = wrblksz;
        if ((ar_open(arcname) < 0) && (ar_next() < 0))
@@ -142,13 +133,8 @@ wr_start()
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 rd_start(void)
-#else
-int
-rd_start()
-#endif
 {
        /*
         * leave space for the header pushback (see get_arc()). If we are
@@ -164,7 +150,7 @@ rd_start()
                }
                if (wrblksz % BLKMULT) {
                        paxwarn(1, "Write block size %d is not a %d byte multiple",
-                       wrblksz, BLKMULT);
+                       wrblksz, BLKMULT);
                        return(-1);
                }
        }
@@ -185,13 +171,8 @@ rd_start()
  *     set up buffer system for copying within the file system
  */
 
-#ifdef __STDC__
 void
 cp_start(void)
-#else
-void
-cp_start()
-#endif
 {
        buf = &(bufmem[BLKMULT]);
        rdblksz = blksz = MAXBLK;
@@ -206,13 +187,13 @@ cp_start()
  *     the start of the header of the first file added to the archive. The
  *     format specific end read function tells us how many bytes to move
  *     backwards in the archive to be positioned BEFORE the trailer. Two
- *     different postions have to be adjusted, the O.S. file offset (e.g. the
+ *     different position have to be adjusted, the O.S. file offset (e.g. the
  *     position of the tape head) and the write point within the data we have
  *     stored in the read (soon to become write) buffer. We may have to move
  *     back several records (the number depends on the size of the archive
  *     record and the size of the format trailer) to read up the record where
  *     the first byte of the trailer is recorded. Trailers may span (and
- *     overlap) record boundries.
+ *     overlap) record boundaries.
  *     We first calculate which record has the first byte of the trailer. We
  *     move the OS file offset back to the start of this record and read it
  *     up. We set the buffer write pointer to be at this byte (the byte where
@@ -220,25 +201,19 @@ cp_start()
  *     start of this record so a flush of this buffer will replace the record
  *     in the archive.
  *     A major problem is rewriting this last record. For archives stored
- *     on disk files, this is trival. However, many devices are really picky
+ *     on disk files, this is trivial. However, many devices are really picky
  *     about the conditions under which they will allow a write to occur.
- *     Often devices restrict the conditions where writes can be made writes,
- *     so it may not be feasable to append archives stored on all types of
- *     devices. 
+ *     Often devices restrict the conditions where writes can be made,
+ *     so it may not be feasible to append archives stored on all types of
+ *     devices.
  * Return:
  *     0 for success, -1 for failure
  */
 
-#ifdef __STDC__
 int
 appnd_start(off_t skcnt)
-#else
-int
-appnd_start(skcnt)
-       off_t skcnt;
-#endif
 {
-       register int res;
+       int res;
        off_t cnt;
 
        if (exit_val != 0) {
@@ -322,7 +297,7 @@ appnd_start(skcnt)
        paxwarn(1, "Unable to rewrite archive trailer, cannot append.");
        return(-1);
 }
-       
+
 /*
  * rd_sync()
  *     A read error occurred on this archive volume. Resync the buffer and
@@ -334,16 +309,11 @@ appnd_start(skcnt)
  *     0 on success, and -1 on failure
  */
 
-#ifdef __STDC__
 int
 rd_sync(void)
-#else
-int
-rd_sync()
-#endif
 {
-       register int errcnt = 0;
-       register int res;
+       int errcnt = 0;
+       int res;
 
        /*
         * if the user says bail out on first fault, we are out of here...
@@ -400,22 +370,15 @@ rd_sync()
  * pback()
  *     push the data used during the archive id phase back into the I/O
  *     buffer. This is required as we cannot be sure that the header does NOT
- *     overlap a block boundry (as in the case we are trying to recover a
+ *     overlap a block boundary (as in the case we are trying to recover a
  *     flawed archived). This was not designed to be used for any other
  *     purpose. (What software engineering, HA!)
  *     WARNING: do not even THINK of pback greater than BLKMULT, unless the
  *     pback space is increased.
  */
 
-#ifdef __STDC__
 void
 pback(char *pt, int cnt)
-#else
-void
-pback(pt, cnt)
-       char *pt;
-       int cnt;
-#endif
 {
        bufpt -= cnt;
        memcpy(bufpt, pt, cnt);
@@ -424,27 +387,21 @@ pback(pt, cnt)
 
 /*
  * rd_skip()
- *     skip foward in the archive during a archive read. Used to get quickly
+ *     skip forward in the archive during a archive read. Used to get quickly
  *     past file data and padding for files the user did NOT select.
  * Return:
  *     0 if ok, -1 failure, and 1 when EOF on the archive volume was detected.
  */
 
-#ifdef __STDC__
 int
 rd_skip(off_t skcnt)
-#else
-int
-rd_skip(skcnt)
-       off_t skcnt;
-#endif
 {
        off_t res;
        off_t cnt;
        off_t skipped = 0;
 
        /*
-        * consume what data we have in the buffer. If we have to move foward
+        * consume what data we have in the buffer. If we have to move forward
         * whole records, we call the low level skip function to see if we can
         * move within the archive without doing the expensive reads on data we
         * do not want.
@@ -497,21 +454,16 @@ rd_skip(skcnt)
        return(0);
 }
 
-/* 
+/*
  * wr_fin()
  *     flush out any data (and pad if required) the last block. We always pad
  *     with zero (even though we do not have to). Padding with 0 makes it a
- *     lot easier to recover if the archive is damaged. zero paddding SHOULD
+ *     lot easier to recover if the archive is damaged. zero padding SHOULD
  *     BE a requirement....
  */
 
-#ifdef __STDC__
 void
 wr_fin(void)
-#else
-void
-wr_fin()
-#endif
 {
        if (bufpt > buf) {
                memset(bufpt, 0, bufend - bufpt);
@@ -526,22 +478,15 @@ wr_fin()
  *     by format specific write routines to pass a file header). On failure we
  *     punt. We do not allow the user to continue to write flawed archives.
  *     We assume these headers are not very large (the memory copy we use is
- *     a bit expensive). 
+ *     a bit expensive).
  * Return:
  *     0 if buffer was filled ok, -1 o.w. (buffer flush failure)
  */
 
-#ifdef __STDC__
 int
-wr_rdbuf(register char *out, register int outcnt)
-#else
-int
-wr_rdbuf(out, outcnt)
-       register char *out;
-       register int outcnt;
-#endif
+wr_rdbuf(char *out, int outcnt)
 {
-       register int cnt;
+       int cnt;
 
        /*
         * while there is data to copy copy into the write buffer. when the
@@ -574,19 +519,12 @@ wr_rdbuf(out, outcnt)
  *     -1 is a read error
  */
 
-#ifdef __STDC__
 int
-rd_wrbuf(register char *in, register int cpcnt)
-#else
-int
-rd_wrbuf(in, cpcnt)
-       register char *in;
-       register int cpcnt;
-#endif
+rd_wrbuf(char *in, int cpcnt)
 {
-       register int res;
-       register int cnt;
-       register int incnt = cpcnt;
+       int res;
+       int cnt;
+       int incnt = cpcnt;
 
        /*
         * loop until we fill the buffer with the requested number of bytes
@@ -597,7 +535,7 @@ rd_wrbuf(in, cpcnt)
                        /*
                         * read error, return what we got (or the error if
                         * no data was copied). The caller must know that an
-                        * error occured and has the best knowledge what to
+                        * error occurred and has the best knowledge what to
                         * do with it
                         */
                        if ((res = cpcnt - incnt) > 0)
@@ -620,7 +558,7 @@ rd_wrbuf(in, cpcnt)
 
 /*
  * wr_skip()
- *     skip foward during a write. In other words add padding to the file.
+ *     skip forward during a write. In other words add padding to the file.
  *     we add zero filled padding as it makes flawed archives much easier to
  *     recover from. the caller tells us how many bytes of padding to add
  *     This routine was not designed to add HUGE amount of padding, just small
@@ -629,16 +567,10 @@ rd_wrbuf(in, cpcnt)
  *     0 if ok, -1 if there was a buf_flush failure
  */
 
-#ifdef __STDC__
 int
 wr_skip(off_t skcnt)
-#else
-int
-wr_skip(skcnt)
-       off_t skcnt;
-#endif
 {
-       register int cnt;
+       int cnt;
 
        /*
         * loop while there is more padding to add
@@ -673,20 +605,12 @@ wr_skip(skcnt)
  *     0, but "left" is set to be greater than zero.
  */
 
-#ifdef __STDC__
 int
 wr_rdfile(ARCHD *arcn, int ifd, off_t *left)
-#else
-int
-wr_rdfile(arcn, ifd, left)
-       ARCHD *arcn;
-       int ifd;
-       off_t *left;
-#endif
 {
-       register int cnt;
-       register int res = 0;
-       register off_t size = arcn->sb.st_size;
+       int cnt;
+       int res = 0;
+       off_t size = arcn->sb.st_size;
        struct stat sb;
 
        /*
@@ -742,32 +666,26 @@ wr_rdfile(arcn, ifd, left)
  *     we return a 0 but "left" is set to be the amount unwritten
  */
 
-#ifdef __STDC__
 int
 rd_wrfile(ARCHD *arcn, int ofd, off_t *left)
-#else
-int
-rd_wrfile(arcn, ofd, left)
-       ARCHD *arcn;
-       int ofd;
-       off_t *left;
-#endif
 {
-       register int cnt = 0;
-       register off_t size = arcn->sb.st_size;
-       register int res = 0;
-       register char *fnm = arcn->name;
+       int cnt = 0;
+       off_t size = arcn->sb.st_size;
+       int res = 0;
+       char *fnm = arcn->name;
        int isem = 1;
        int rem;
        int sz = MINFBSZ;
-       struct stat sb;
-       u_long crc = 0L;
+       struct stat sb;
+       u_int32_t crc = 0;
 
        /*
         * 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 < 0)
+               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
@@ -810,7 +728,7 @@ rd_wrfile(arcn, ofd, left)
        /*
         * if the last block has a file hole (all zero), we must make sure this
         * gets updated in the file. We force the last block of zeros to be
-        * written. just closing with the file offset moved foward may not put
+        * written. just closing with the file offset moved forward may not put
         * a hole at the end of the file.
         */
        if (isem && (arcn->sb.st_size > 0L))
@@ -838,22 +756,14 @@ rd_wrfile(arcn, ofd, left)
  *     destination file so we can properly copy files with holes.
  */
 
-#ifdef __STDC__
 void
 cp_file(ARCHD *arcn, int fd1, int fd2)
-#else
-void
-cp_file(arcn, fd1, fd2)
-       ARCHD *arcn;
-       int fd1;
-       int fd2;
-#endif
 {
-       register int cnt;
-       register off_t cpcnt = 0L;
-       register int res = 0;
-       register char *fnm = arcn->name;
-       register int no_hole = 0;
+       int cnt;
+       off_t cpcnt = 0L;
+       int res = 0;
+       char *fnm = arcn->name;
+       int no_hole = 0;
        int isem = 1;
        int rem;
        int sz = MINFBSZ;
@@ -880,7 +790,7 @@ cp_file(arcn, fd1, fd2)
        /*
         * read the source file and copy to destination file until EOF
         */
-       for(;;) {
+       for (;;) {
                if ((cnt = read(fd1, buf, blksz)) <= 0)
                        break;
                if (no_hole)
@@ -910,7 +820,7 @@ cp_file(arcn, fd1, fd2)
        /*
         * if the last block has a file hole (all zero), we must make sure this
         * gets updated in the file. We force the last block of zeros to be
-        * written. just closing with the file offset moved foward may not put
+        * written. just closing with the file offset moved forward may not put
         * a hole at the end of the file.
         */
        if (!no_hole && isem && (arcn->sb.st_size > 0L))
@@ -927,21 +837,16 @@ cp_file(arcn, fd1, fd2)
  *     0 when finished (user specified termination in ar_next()).
  */
 
-#ifdef __STDC__
 int
 buf_fill(void)
-#else
-int
-buf_fill()
-#endif
 {
-       register int cnt;
+       int cnt;
        static int fini = 0;
 
        if (fini)
                return(0);
 
-       for(;;) {
+       for (;;) {
                /*
                 * try to fill the buffer. on error the next archive volume is
                 * opened and we try again.
@@ -977,22 +882,16 @@ buf_fill()
  *     0 if all is ok, -1 when a write error occurs.
  */
 
-#ifdef __STDC__
 int
-buf_flush(register int bufcnt)
-#else
-int
-buf_flush(bufcnt)
-       register int bufcnt;
-#endif
+buf_flush(int bufcnt)
 {
-       register int cnt;
-       register int push = 0;
-       register int totcnt = 0;
+       int cnt;
+       int push = 0;
+       int totcnt = 0;
 
        /*
         * if we have reached the user specified byte count for each archive
-        * volume, prompt for the next volume. (The non-standrad -R flag).
+        * volume, prompt for the next volume. (The non-standard -R flag).
         * NOTE: If the wrlimit is smaller than wrcnt, we will always write
         * at least one record. We always round limit UP to next blocksize.
         */
diff --git a/cache.c b/cache.c
index 60301d88d2d35004486052b8ef468b0bcfdc7db1..44eda1f518a7c826521d208a4d313f9a1cbb20ac 100644 (file)
--- a/cache.c
+++ b/cache.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cache.c,v 1.6 1997/07/25 18:58:27 mickey Exp $        */
+/*     $OpenBSD: cache.c,v 1.17 2004/03/16 03:28:34 tedu Exp $ */
 /*     $NetBSD: cache.c,v 1.4 1995/03/21 09:07:10 cgd Exp $    */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)cache.c    8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)cache.c      8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] = "$OpenBSD: cache.c,v 1.6 1997/07/25 18:58:27 mickey Exp $";
+static const char rcsid[] = "$OpenBSD: cache.c,v 1.17 2004/03/16 03:28:34 tedu Exp $";
 #endif
 #endif /* not lint */
 
@@ -76,18 +72,13 @@ static GIDC **grptb = NULL; /* group name to gid cache */
 
 /*
  * uidtb_start
- *     creates an an empty uidtb
+ *     creates an empty uidtb
  * Return:
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 uidtb_start(void)
-#else
-int
-uidtb_start()
-#endif
 {
        static int fail = 0;
 
@@ -105,18 +96,13 @@ uidtb_start()
 
 /*
  * gidtb_start
- *     creates an an empty gidtb
+ *     creates an empty gidtb
  * Return:
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 gidtb_start(void)
-#else
-int
-gidtb_start()
-#endif
 {
        static int fail = 0;
 
@@ -134,18 +120,13 @@ gidtb_start()
 
 /*
  * usrtb_start
- *     creates an an empty usrtb
+ *     creates an empty usrtb
  * Return:
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 usrtb_start(void)
-#else
-int
-usrtb_start()
-#endif
 {
        static int fail = 0;
 
@@ -163,18 +144,13 @@ usrtb_start()
 
 /*
  * grptb_start
- *     creates an an empty grptb
+ *     creates an empty grptb
  * Return:
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 grptb_start(void)
-#else
-int
-grptb_start()
-#endif
 {
        static int fail = 0;
 
@@ -198,18 +174,11 @@ grptb_start()
  *     Pointer to stored name (or a empty string)
  */
 
-#ifdef __STDC__
 char *
 name_uid(uid_t uid, int frc)
-#else
-char *
-name_uid(uid, frc)
-       uid_t uid;
-       int frc;
-#endif
 {
-       register struct passwd *pw;
-       register UIDC *ptr;
+       struct passwd *pw;
+       UIDC *ptr;
 
        if ((uidtb == NULL) && (uidtb_start() < 0))
                return("");
@@ -235,23 +204,19 @@ name_uid(uid, frc)
                ++pwopn;
        }
        if (ptr == NULL)
-               ptr = (UIDC *)malloc(sizeof(UIDC));
+               ptr = uidtb[uid % UID_SZ] = malloc(sizeof(UIDC));
 
        if ((pw = getpwuid(uid)) == NULL) {
                /*
                 * no match for this uid in the local password file
-                * a string that is the uid in numberic format
+                * a string that is the uid in numeric format
                 */
                if (ptr == NULL)
                        return("");
                ptr->uid = uid;
                ptr->valid = INVALID;
-#              ifdef NET2_STAT
-               (void)snprintf(ptr->name, sizeof(ptr->name), "%u", uid);
-#              else
                (void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
                               (unsigned long)uid);
-#              endif
                if (frc == 0)
                        return("");
        } else {
@@ -261,8 +226,7 @@ name_uid(uid, frc)
                if (ptr == NULL)
                        return(pw->pw_name);
                ptr->uid = uid;
-               (void)strncpy(ptr->name, pw->pw_name, UNMLEN-1);
-               ptr->name[UNMLEN-1] = '\0';
+               (void)strlcpy(ptr->name, pw->pw_name, sizeof(ptr->name));
                ptr->valid = VALID;
        }
        return(ptr->name);
@@ -276,18 +240,11 @@ name_uid(uid, frc)
  *     Pointer to stored name (or a empty string)
  */
 
-#ifdef __STDC__
 char *
 name_gid(gid_t gid, int frc)
-#else
-char *
-name_gid(gid, frc)
-       gid_t gid;
-       int frc;
-#endif
 {
-       register struct group *gr;
-       register GIDC *ptr;
+       struct group *gr;
+       GIDC *ptr;
 
        if ((gidtb == NULL) && (gidtb_start() < 0))
                return("");
@@ -313,7 +270,7 @@ name_gid(gid, frc)
                ++gropn;
        }
        if (ptr == NULL)
-               ptr = (GIDC *)malloc(sizeof(GIDC));
+               ptr = gidtb[gid % GID_SZ] = malloc(sizeof(GIDC));
 
        if ((gr = getgrgid(gid)) == NULL) {
                /*
@@ -324,12 +281,8 @@ name_gid(gid, frc)
                        return("");
                ptr->gid = gid;
                ptr->valid = INVALID;
-#              ifdef NET2_STAT
-               (void)snprintf(ptr->name, sizeof(ptr->name), "%u", gid);
-#              else
                (void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
                               (unsigned long)gid);
-#              endif
                if (frc == 0)
                        return("");
        } else {
@@ -339,8 +292,7 @@ name_gid(gid, frc)
                if (ptr == NULL)
                        return(gr->gr_name);
                ptr->gid = gid;
-               (void)strncpy(ptr->name, gr->gr_name, GNMLEN-1);
-               ptr->name[GNMLEN-1] = '\0';
+               (void)strlcpy(ptr->name, gr->gr_name, sizeof(ptr->name));
                ptr->valid = VALID;
        }
        return(ptr->name);
@@ -353,19 +305,12 @@ name_gid(gid, frc)
  *     the uid (if any) for a user name, or a -1 if no match can be found
  */
 
-#ifdef __STDC__
 int
 uid_name(char *name, uid_t *uid)
-#else
-int
-uid_name(name, uid)
-       char *name;
-       uid_t *uid;
-#endif
 {
-       register struct passwd *pw;
-       register UIDC *ptr;
-       register int namelen;
+       struct passwd *pw;
+       UIDC *ptr;
+       int namelen;
 
        /*
         * return -1 for mangled names
@@ -393,7 +338,8 @@ uid_name(name, uid)
        }
 
        if (ptr == NULL)
-               ptr = (UIDC *)malloc(sizeof(UIDC));
+               ptr = usrtb[st_hash(name, namelen, UNM_SZ)] =
+                 (UIDC *)malloc(sizeof(UIDC));
 
        /*
         * no match, look it up, if no match store it as an invalid entry,
@@ -405,8 +351,7 @@ uid_name(name, uid)
                *uid = pw->pw_uid;
                return(0);
        }
-       (void)strncpy(ptr->name, name, UNMLEN-1);
-       ptr->name[UNMLEN-1] = '\0';
+       (void)strlcpy(ptr->name, name, sizeof(ptr->name));
        if ((pw = getpwnam(name)) == NULL) {
                ptr->valid = INVALID;
                return(-1);
@@ -423,19 +368,12 @@ uid_name(name, uid)
  *     the gid (if any) for a group name, or a -1 if no match can be found
  */
 
-#ifdef __STDC__
 int
 gid_name(char *name, gid_t *gid)
-#else
-int
-gid_name(name, gid)
-       char *name;
-       gid_t *gid;
-#endif
 {
-       register struct group *gr;
-       register GIDC *ptr;
-       register int namelen;
+       struct group *gr;
+       GIDC *ptr;
+       int namelen;
 
        /*
         * return -1 for mangled names
@@ -462,7 +400,8 @@ gid_name(name, gid)
                ++gropn;
        }
        if (ptr == NULL)
-               ptr = (GIDC *)malloc(sizeof(GIDC));
+               ptr = grptb[st_hash(name, namelen, GID_SZ)] =
+                 (GIDC *)malloc(sizeof(GIDC));
 
        /*
         * no match, look it up, if no match store it as an invalid entry,
@@ -475,8 +414,7 @@ gid_name(name, gid)
                return(0);
        }
 
-       (void)strncpy(ptr->name, name, GNMLEN-1);
-       ptr->name[GNMLEN-1] = '\0';
+       (void)strlcpy(ptr->name, name, sizeof(ptr->name));
        if ((gr = getgrnam(name)) == NULL) {
                ptr->valid = INVALID;
                return(-1);
diff --git a/cache.h b/cache.h
index 01283ef9e5978f206a9481cbab6339f88de8062d..5c7b9b8b5f3c0698a0e8350ee67b95e9e8a71d1a 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cache.h,v 1.2 1996/06/23 14:20:31 deraadt Exp $       */
+/*     $OpenBSD: cache.h,v 1.4 2003/10/20 06:22:27 jmc Exp $   */
 /*     $NetBSD: cache.h,v 1.3 1995/03/21 09:07:12 cgd Exp $    */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -45,7 +41,7 @@
  * caches. Traditional passwd/group cache routines perform quite poorly with
  * archives. The chances of hitting a valid lookup with an archive is quite a
  * bit worse than with files already resident on the file system. These misses
- * create a MAJOR performance cost. To adress this problem, these routines
+ * create a MAJOR performance cost. To address this problem, these routines
  * cache both hits and misses.
  *
  * NOTE:  name lengths must be as large as those stored in ANY PROTOCOL and
diff --git a/cpio.1 b/cpio.1
index bbc4ab9f1c281777c3bc5da64eb1438dcab0990e..6ee5fadb5ada1205b5a5497d2cf6cd50a1ffe92b 100644 (file)
--- a/cpio.1
+++ b/cpio.1
@@ -1,3 +1,4 @@
+.\"    $OpenBSD: cpio.1,v 1.28 2008/06/11 07:42:50 jmc Exp $
 .\"
 .\" Copyright (c) 1997 SigmaSoft, Th. Lockert
 .\" All rights reserved.
 .\" 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
@@ -27,9 +23,9 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\"    $OpenBSD: cpio.1,v 1.5 1998/09/14 22:13:52 aaron Exp $
+.\"    $OpenBSD: cpio.1,v 1.28 2008/06/11 07:42:50 jmc Exp $
 .\"
-.Dd February 16, 1997
+.Dd $Mdocdate: June 11 2008 $
 .Dt CPIO 1
 .Os
 .Sh NAME
 .Sh SYNOPSIS
 .Nm cpio
 .Fl o
-.Op Fl aABcLvzZ
+.Op Fl AaBcjLvZz
 .Op Fl C Ar bytes
 .Op Fl F Ar archive
 .Op Fl H Ar format
 .Op Fl O Ar archive
-.Ar "< name-list"
-.Op Ar "> archive"
+.Ar \*(Lt name-list
+.Op Ar \*(Gt archive
 .Nm cpio
 .Fl i
-.Op Fl bBcdfmrsStuvzZ6
+.Op Fl 6BbcdfjmrSstuvZz
 .Op Fl C Ar bytes
 .Op Fl E Ar file
 .Op Fl F Ar archive
 .Op Fl H Ar format
 .Op Fl I Ar archive
-.Op Ar "pattern ..."
-.Op Ar "< archive"
+.Op Ar pattern ...
+.Op Ar \*(Lt archive
 .Nm cpio
 .Fl p
-.Op Fl adlLmuv
+.Op Fl adLlmuv
 .Ar destination-directory
-.Ar "< name-list"
+.Ar \*(Lt name-list
 .Sh DESCRIPTION
 The
 .Nm
@@ -67,112 +63,138 @@ command copies files to and from a
 .Nm
 archive.
 .Pp
-The following options are supported:
-.Bl -tag -width Fl
+The options are as follows:
+.Bl -tag -width Ds
 .It Fl o
-Create an archive.  Reads the list of files to store in the
+Create an archive.
+Reads the list of files to store in the
 archive from standard input, and writes the archive on standard
 output.
-.Bl -tag -width Fl
+.Bl -tag -width Ds
+.It Fl A
+Append to the specified archive.
 .It Fl a
 Reset the access times on files that have been copied to the
 archive.
-.It Fl A
-Append to the specified archive.
 .It Fl B
 Set block size of output to 5120 bytes.
+.It Fl C Ar bytes
+Set the block size of output to
+.Ar bytes .
 .It Fl c
 Use ASCII format for
 .Nm
 header for portability.
-.It Fl C Ar bytes
-Set the block size of output to
-.Ar bytes .
 .It Fl F Ar archive
-.It Fl O Ar archive
-Use the specified file name as the archive to write to.
+Use the specified file as the input for the archive.
 .It Fl H Ar format
-Write the archive in the specified format.  Recognized
-formats are:
-.Bl -tag -width Ds
+Write the archive in the specified format.
+Recognized formats are:
+.Pp
+.Bl -tag -width sv4cpio -compact
 .It Ar bcpio
-Old binary cpio format.
+Old binary
+.Nm
+format.
 .It Ar cpio
-Old octal character cpio format.
+Old octal character
+.Nm
+format.
 .It Ar sv4cpio
-SVR4 hex cpio format.
+SVR4 hex
+.Nm
+format.
 .It Ar tar
 Old tar format.
 .It Ar ustar
 POSIX ustar format.
 .El
+.It Fl j
+Compress archive using the bzip2 format.
+The bzip2 utility must be installed separately.
 .It Fl L
 Follow symbolic links.
+.It Fl O Ar archive
+Use the specified file name as the archive to write to.
 .It Fl v
-Be verbose about operations.  List filenames as they are
-written to the archive.
-.It Fl z
-Compress archive using
-.Xr gzip 1
-format.
+Be verbose about operations.
+List filenames as they are written to the archive.
 .It Fl Z
 Compress archive using
 .Xr compress 1
 format.
+.It Fl z
+Compress archive using
+.Xr gzip 1
+format.
 .El
 .It Fl i
-Restore files from an archive.  Reads the archive file from
+Restore files from an archive.
+Reads the archive file from
 standard input and extracts files matching the
 .Ar patterns
 that were specified on the command line.
-.Bl -tag -width Fl
+.Bl -tag -width Ds
+.It Fl 6
+Process old-style
+.Nm
+format archives.
+.It Fl B
+Set the block size of the archive being read to 5120 bytes.
 .It Fl b
 Do byte and word swapping after reading in data from the
 archive, for restoring archives created on systems with
 a different byte order.
-.It Fl B
-Set the block size of the archive being read to 5120 bytes.
-.It Fl c
-Expect the archive headers to be in ASCII format.
 .It Fl C Ar bytes
 Read archive written with a block size of
 .Ar bytes .
+.It Fl c
+Expect the archive headers to be in ASCII format.
 .It Fl d
 Create any intermediate directories as needed during
 restore.
 .It Fl E Ar file
 Read list of file name patterns to extract or list from
 .Ar file .
+.It Fl F Ar archive , Fl I Ar archive
+Use the specified file as the input for the archive.
 .It Fl f
 Restore all files except those matching the
 .Ar patterns
 given on the command line.
-.It Fl F Ar archive
-.It Fl I Ar archive
-Use the specified file as the input for the archive.
 .It Fl H Ar format
-Read an archive of the specified format.  Recognized
-formats are:
-.Bl -tag -width Ds
+Read an archive of the specified format.
+Recognized formats are:
+.Pp
+.Bl -tag -width sv4cpio -compact
 .It Ar bcpio
-Old binary cpio format.
+Old binary
+.Nm
+format.
 .It Ar cpio
-Old octal character cpio format.
+Old octal character
+.Nm
+format.
 .It Ar sv4cpio
-SVR4 hex cpio format.
+SVR4 hex
+.Nm
+format.
 .It Ar tar
 Old tar format.
 .It Ar ustar
 POSIX ustar format.
 .El
+.It Fl j
+Uncompress archive using the bzip2 format.
+The bzip2 utility must be installed separately.
 .It Fl m
 Restore modification times on files.
 .It Fl r
 Rename restored files interactively.
-.It Fl s
-Swap bytes after reading data from the archive.
 .It Fl S
 Swap words after reading data from the archive.
+.It Fl s
+Swap bytes after reading data from the archive.
 .It Fl t
 Only list the contents of the archive, no files or
 directories will be created.
@@ -180,18 +202,16 @@ directories will be created.
 Overwrite files even when the file in the archive is
 older than the one that will be overwritten.
 .It Fl v
-Be verbose about operations.  List filenames as they are
-copied in from the archive.
-.It Fl z
-Uncompress archive using
-.Xr gzip 1
-format.
+Be verbose about operations.
+List filenames as they are copied in from the archive.
 .It Fl Z
 Uncompress archive using
 .Xr compress 1
 format.
-.It Fl 6
-Process old-style \*Qcpio\*U format archives.
+.It Fl z
+Uncompress archive using
+.Xr gzip 1
+format.
 .El
 .It Fl p
 Copy files from one location to another in a single pass.
@@ -199,27 +219,32 @@ The list of files to copy are read from standard input and
 written out to a directory relative to the specified
 .Ar directory
 argument.
-.Bl -tag -width Fl
+.Bl -tag -width Ds
 .It Fl a
 Reset the access times on files that have been copied.
 .It Fl d
 Create any intermediate directories as needed to write
 the files at the new location.
+.It Fl L
+Follow symbolic links.
 .It Fl l
 When possible, link files rather than creating an
 extra copy.
-.It Fl L
-Follow symbolic links.
 .It Fl m
 Restore modification times on files.
 .It Fl u
 Overwrite files even when the original file being copied is
 older than the one that will be overwritten.
 .It Fl v
-Be verbose about operations.  List filenames as they are
-copied.
+Be verbose about operations.
+List filenames as they are copied.
 .El
 .El
+.Sh ENVIRONMENT
+.Bl -tag -width Fl
+.It Ev TMPDIR
+Path in which to store temporary files.
+.El
 .Sh ERRORS
 .Nm
 will exit with one of the following values:
@@ -234,11 +259,12 @@ Whenever
 .Nm
 cannot create a file or a link when extracting an archive or cannot
 find a file while writing an archive, or cannot preserve the user
-ID, group ID, file mode or access and modification times when the
+ID, group ID, file mode, or access and modification times when the
 .Fl p
 option is specified, a diagnostic message is written to standard
 error and a non-zero exit value will be returned, but processing
-will continue.  In the case where
+will continue.
+In the case where
 .Nm
 cannot create a link to a file,
 .Nm
@@ -255,16 +281,29 @@ be wrong.
 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
+may have only partially created the archive, which may violate the
 specific archive format specification.
 .Sh SEE ALSO
 .Xr pax 1 ,
 .Xr tar 1
+.Sh AUTHORS
+Keith Muller at the University of California, San Diego.
+.Sh CAVEATS
+Different file formats have different maximum file sizes.
+It is recommended that a format such as cpio or ustar
+be used for larger files.
+.Pp
+.Bl -column "File format" "Maximum file size" -offset indent -compact
+.It Sy "File format" Ta Sy "Maximum file size"
+.It bcpio Ta 4 Gigabytes
+.It sv4cpio Ta 4 Gigabytes
+.It cpio Ta 8 Gigabytes
+.It tar Ta 8 Gigabytes
+.It ustar Ta 8 Gigabytes
+.El
 .Sh BUGS
-The 
+The
 .Fl s
 and
 .Fl S
 options are currently not implemented.
-.Sh AUTHOR
-Keith Muller at the University of California, San Diego.
diff --git a/cpio.c b/cpio.c
index 47bf5caa932e2640b1525bb9816a116c957bf071..4a9796028b8cdf1a2bdb27f6fd5f04ab3c766cc5 100644 (file)
--- a/cpio.c
+++ b/cpio.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpio.c,v 1.5 1997/07/25 18:58:28 mickey Exp $ */
+/*     $OpenBSD: cpio.c,v 1.18 2008/01/01 16:22:44 tobias Exp $        */
 /*     $NetBSD: cpio.c,v 1.5 1995/03/21 09:07:13 cgd Exp $     */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)cpio.c     8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)cpio.c       8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] = "$OpenBSD: cpio.c,v 1.5 1997/07/25 18:58:28 mickey Exp $";
+static const char rcsid[] = "$OpenBSD: cpio.c,v 1.18 2008/01/01 16:22:44 tobias Exp $";
 #endif
 #endif /* not lint */
 
@@ -58,9 +54,9 @@ static char rcsid[] = "$OpenBSD: cpio.c,v 1.5 1997/07/25 18:58:28 mickey Exp $";
 #include "cpio.h"
 #include "extern.h"
 
-static int rd_nm __P((register ARCHD *, int));
-static int rd_ln_nm __P((register ARCHD *));
-static int com_rd __P((register ARCHD *));
+static int rd_nm(ARCHD *, int);
+static int rd_ln_nm(ARCHD *);
+static int com_rd(ARCHD *);
 
 /*
  * Routines which support the different cpio versions
@@ -79,13 +75,8 @@ static int swp_head;         /* binary cpio header byte swap */
  *      0 if ok -1 otherwise (the return values of lnk_start())
  */
 
-#ifdef __STDC__
 int
 cpio_strd(void)
-#else
-int
-cpio_strd()
-#endif
 {
        return(lnk_start());
 }
@@ -97,17 +88,11 @@ cpio_strd()
  *     mode; looking for a valid header), and cnt (which starts at zero)
  *     which is used to count the number of empty blocks we have seen so far.
  * Return:
- *     0 if a valid trailer, -1 if not a valid trailer, 
+ *     0 if a valid trailer, -1 if not a valid trailer,
  */
 
-#ifdef __STDC__
-int
-cpio_trail(register ARCHD *arcn)
-#else
 int
-cpio_trail(arcn)
-       register ARCHD *arcn;
-#endif
+cpio_trail(ARCHD *arcn, char *notused, int notused2, int *notused3)
 {
        /*
         * look for trailer id in file we are about to process
@@ -124,19 +109,13 @@ cpio_trail(arcn)
  *     0
  */
 
-#ifdef __STDC__
-static int
-com_rd(register ARCHD *arcn)
-#else
 static int
-com_rd(arcn)
-       register ARCHD *arcn;
-#endif
+com_rd(ARCHD *arcn)
 {
        arcn->skip = 0;
        arcn->pat = NULL;
        arcn->org_name = arcn->name;
-       switch(arcn->sb.st_mode & C_IFMT) {
+       switch (arcn->sb.st_mode & C_IFMT) {
        case C_ISFIFO:
                arcn->type = PAX_FIF;
                break;
@@ -173,19 +152,14 @@ com_rd(arcn)
 }
 
 /*
- * cpio_end_wr()
+ * cpio_endwr()
  *     write the special file with the name trailer in the proper format
  * Return:
  *     result of the write of the trailer from the cpio specific write func
  */
 
-#ifdef __STDC__
 int
 cpio_endwr(void)
-#else
-int
-cpio_endwr()
-#endif
 {
        ARCHD last;
 
@@ -196,7 +170,7 @@ cpio_endwr()
        last.nlen = sizeof(TRAILER) - 1;
        last.type = PAX_REG;
        last.sb.st_nlink = 1;
-       (void)strcpy(last.name, TRAILER);
+       (void)strlcpy(last.name, TRAILER, sizeof(last.name));
        return((*frmt->wr)(&last));
 }
 
@@ -207,15 +181,8 @@ cpio_endwr()
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 static int
-rd_nm(register ARCHD *arcn, int nsz)
-#else
-static int
-rd_nm(arcn, nsz)
-       register ARCHD *arcn;
-       int nsz;
-#endif
+rd_nm(ARCHD *arcn, int nsz)
 {
        /*
         * do not even try bogus values
@@ -244,21 +211,15 @@ rd_nm(arcn, nsz)
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
-static int
-rd_ln_nm(register ARCHD *arcn)
-#else
 static int
-rd_ln_nm(arcn)
-       register ARCHD *arcn;
-#endif
+rd_ln_nm(ARCHD *arcn)
 {
        /*
         * check the length specified for bogus values
         */
        if ((arcn->sb.st_size == 0) ||
            (arcn->sb.st_size >= sizeof(arcn->ln_name))) {
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                paxwarn(1, "Cpio link name length is invalid: %lu",
                    arcn->sb.st_size);
 #              else
@@ -301,15 +262,8 @@ rd_ln_nm(arcn)
  *      0 if a valid header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 cpio_id(char *blk, int size)
-#else
-int
-cpio_id(blk, size)
-       char *blk;
-       int size;
-#endif
 {
        if ((size < sizeof(HD_CPIO)) ||
            (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
@@ -325,18 +279,11 @@ cpio_id(blk, size)
  *     0 if a valid header, -1 otherwise.
  */
 
-#ifdef __STDC__
-int
-cpio_rd(register ARCHD *arcn, register char *buf)
-#else
 int
-cpio_rd(arcn, buf)
-       register ARCHD *arcn;
-       register char *buf;
-#endif
+cpio_rd(ARCHD *arcn, char *buf)
 {
-       register int nsz;
-       register HD_CPIO *hd;
+       int nsz;
+       HD_CPIO *hd;
 
        /*
         * check that this is a valid header, if not return -1
@@ -361,7 +308,7 @@ cpio_rd(arcn, buf)
        arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
            OCT);
        arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
-#      ifdef NET2_STAT
+#      ifdef LONG_OFF_T
        arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize),
            OCT);
 #      else
@@ -381,8 +328,8 @@ cpio_rd(arcn, buf)
 
        if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
                /*
-                * no link name to read for this file
-                */
+                * no link name to read for this file
+                */
                arcn->ln_nlen = 0;
                arcn->ln_name[0] = '\0';
                return(com_rd(arcn));
@@ -408,13 +355,8 @@ cpio_rd(arcn, buf)
  *      size of trailer header in this format
  */
 
-#ifdef __STDC__
 off_t
 cpio_endrd(void)
-#else
-off_t
-cpio_endrd()
-#endif
 {
        return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
 }
@@ -426,13 +368,8 @@ cpio_endrd()
  *     0 if ok, -1 otherwise (what dev_start() returns)
  */
 
-#ifdef __STDC__
 int
 cpio_stwr(void)
-#else
-int
-cpio_stwr()
-#endif
 {
        return(dev_start());
 }
@@ -446,17 +383,11 @@ cpio_stwr()
  *     data to write after the header, -1 if archive write failed
  */
 
-#ifdef __STDC__
 int
-cpio_wr(register ARCHD *arcn)
-#else
-int
-cpio_wr(arcn)
-       register ARCHD *arcn;
-#endif
+cpio_wr(ARCHD *arcn)
 {
-       register HD_CPIO *hd;
-       register int nsz;
+       HD_CPIO *hd;
+       int nsz;
        char hdblk[sizeof(HD_CPIO)];
 
        /*
@@ -471,14 +402,14 @@ cpio_wr(arcn)
        if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
                arcn->sb.st_rdev = 0;
 
-       switch(arcn->type) {
+       switch (arcn->type) {
        case PAX_CTG:
        case PAX_REG:
        case PAX_HRG:
                /*
                 * set data size for file data
                 */
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
                    sizeof(hd->c_filesize), OCT)) {
 #              else
@@ -576,21 +507,14 @@ cpio_wr(arcn)
 /*
  * vcpio_id()
  *      determine if a block given to us is a valid system VR4 cpio header
- *     WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header 
+ *     WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
  *     uses HEX
  * Return:
  *      0 if a valid header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 vcpio_id(char *blk, int size)
-#else
-int
-vcpio_id(blk, size)
-       char *blk;
-       int size;
-#endif
 {
        if ((size < sizeof(HD_VCPIO)) ||
            (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
@@ -606,15 +530,8 @@ vcpio_id(blk, size)
  *      0 if a valid header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 crc_id(char *blk, int size)
-#else
-int
-crc_id(blk, size)
-       char *blk;
-       int size;
-#endif
 {
        if ((size < sizeof(HD_VCPIO)) ||
            (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
@@ -629,13 +546,8 @@ crc_id(blk, size)
  *      0 if ok -1 otherwise (the return values of lnk_start())
  */
 
-#ifdef __STDC__
 int
 crc_strd(void)
-#else
-int
-crc_strd()
-#endif
 {
        docrc = 1;
        return(lnk_start());
@@ -649,20 +561,13 @@ crc_strd()
  *     0 if a valid header, -1 otherwise.
  */
 
-#ifdef __STDC__
-int
-vcpio_rd(register ARCHD *arcn, register char *buf)
-#else
 int
-vcpio_rd(arcn, buf)
-       register ARCHD *arcn;
-       register char *buf;
-#endif
+vcpio_rd(ARCHD *arcn, char *buf)
 {
-       register HD_VCPIO *hd;
+       HD_VCPIO *hd;
        dev_t devminor;
        dev_t devmajor;
-       register int nsz;
+       int nsz;
 
        /*
         * during the id phase it was determined if we were using CRC, use the
@@ -688,7 +593,7 @@ vcpio_rd(arcn, buf)
        arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
        arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
        arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
-#      ifdef NET2_STAT
+#      ifdef LONG_OFF_T
        arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
            sizeof(hd->c_filesize), HEX);
 #      else
@@ -716,7 +621,7 @@ vcpio_rd(arcn, buf)
                return(-1);
 
        /*
-        * skip padding. header + filename is aligned to 4 byte boundries
+        * skip padding. header + filename is aligned to 4 byte boundaries
         */
        if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
                return(-1);
@@ -755,13 +660,8 @@ vcpio_rd(arcn, buf)
  *      size of trailer header in this format
  */
 
-#ifdef __STDC__
 off_t
 vcpio_endrd(void)
-#else
-off_t
-vcpio_endrd()
-#endif
 {
        return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
                (VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
@@ -774,13 +674,8 @@ vcpio_endrd()
  *     0 if ok, -1 otherwise (what dev_start() returns)
  */
 
-#ifdef __STDC__
 int
 crc_stwr(void)
-#else
-int
-crc_stwr()
-#endif
 {
        docrc = 1;
        return(dev_start());
@@ -795,16 +690,10 @@ crc_stwr()
  *     NO data to write after the header, -1 if archive write failed
  */
 
-#ifdef __STDC__
-int
-vcpio_wr(register ARCHD *arcn)
-#else
 int
-vcpio_wr(arcn)
-       register ARCHD *arcn;
-#endif
+vcpio_wr(ARCHD *arcn)
 {
-       register HD_VCPIO *hd;
+       HD_VCPIO *hd;
        unsigned int nsz;
        char hdblk[sizeof(HD_VCPIO)];
 
@@ -825,18 +714,18 @@ vcpio_wr(arcn)
         */
        if (docrc) {
                if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
-                       OCT) ||
+                       OCT) ||
                    ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
-                       HEX))
+                       HEX))
                        goto out;
        } else {
                if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
-                       OCT) ||
+                       OCT) ||
                    ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
                        goto out;
        }
 
-       switch(arcn->type) {
+       switch (arcn->type) {
        case PAX_CTG:
        case PAX_REG:
        case PAX_HRG:
@@ -845,7 +734,7 @@ vcpio_wr(arcn)
                 * much to pad.
                 */
                arcn->pad = VCPIO_PAD(arcn->sb.st_size);
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
                    sizeof(hd->c_filesize), HEX)) {
 #              else
@@ -888,11 +777,11 @@ vcpio_wr(arcn)
            ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
                HEX) ||
            ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
-               HEX) ||
+               HEX) ||
            ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
-               HEX) ||
+               HEX) ||
            ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
-               HEX) ||
+               HEX) ||
            ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
                HEX) ||
            ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
@@ -958,15 +847,8 @@ vcpio_wr(arcn)
  *      0 if a valid header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 bcpio_id(char *blk, int size)
-#else
-int
-bcpio_id(blk, size)
-       char *blk;
-       int size;
-#endif
 {
        if (size < sizeof(HD_BCPIO))
                return(-1);
@@ -993,18 +875,11 @@ bcpio_id(blk, size)
  *     0 if a valid header, -1 otherwise.
  */
 
-#ifdef __STDC__
-int
-bcpio_rd(register ARCHD *arcn, register char *buf)
-#else
 int
-bcpio_rd(arcn, buf)
-       register ARCHD *arcn;
-       register char *buf;
-#endif
+bcpio_rd(ARCHD *arcn, char *buf)
 {
-       register HD_BCPIO *hd;
-       register int nsz;
+       HD_BCPIO *hd;
+       int nsz;
 
        /*
         * check the header
@@ -1016,7 +891,7 @@ bcpio_rd(arcn, buf)
        hd = (HD_BCPIO *)buf;
        if (swp_head) {
                /*
-                * header has swapped bytes on 16 bit boundries
+                * header has swapped bytes on 16 bit boundaries
                 */
                arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
                arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
@@ -1061,7 +936,7 @@ bcpio_rd(arcn, buf)
                return(-1);
 
        /*
-        * header + file name are aligned to 2 byte boundries, skip if needed
+        * header + file name are aligned to 2 byte boundaries, skip if needed
         */
        if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
                return(-1);
@@ -1097,13 +972,8 @@ bcpio_rd(arcn, buf)
  *      size of trailer header in this format
  */
 
-#ifdef __STDC__
 off_t
 bcpio_endrd(void)
-#else
-off_t
-bcpio_endrd()
-#endif
 {
        return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
                (BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
@@ -1113,24 +983,18 @@ bcpio_endrd()
  * bcpio_wr()
  *     copy the data in the ARCHD to buffer in old binary cpio format
  *     There is a real chance of field overflow with this critter. So we
- *     always check the conversion is ok. nobody in his their right mind
- *     should write an achive in this format...
+ *     always check the conversion is ok. nobody in their right mind
+ *     should write an archive in this format...
  * Return
  *      0 if file has data to be written after the header, 1 if file has NO
  *     data to write after the header, -1 if archive write failed
  */
 
-#ifdef __STDC__
 int
-bcpio_wr(register ARCHD *arcn)
-#else
-int
-bcpio_wr(arcn)
-       register ARCHD *arcn;
-#endif
+bcpio_wr(ARCHD *arcn)
 {
-       register HD_BCPIO *hd;
-       register int nsz;
+       HD_BCPIO *hd;
+       int nsz;
        char hdblk[sizeof(HD_BCPIO)];
        off_t t_offt;
        int t_int;
@@ -1147,7 +1011,7 @@ bcpio_wr(arcn)
                arcn->sb.st_rdev = 0;
        hd = (HD_BCPIO *)hdblk;
 
-       switch(arcn->type) {
+       switch (arcn->type) {
        case PAX_CTG:
        case PAX_REG:
        case PAX_HRG:
diff --git a/cpio.h b/cpio.h
index 811f8f3778a46bd8d23fdc939e3269f4327fbbcf..dfbd03f21e3ec7809d0f55e58589775eb01073ce 100644 (file)
--- a/cpio.h
+++ b/cpio.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpio.h,v 1.2 1996/06/23 14:20:32 deraadt Exp $        */
+/*     $OpenBSD: cpio.h,v 1.4 2003/06/02 23:32:08 millert Exp $        */
 /*     $NetBSD: cpio.h,v 1.3 1995/03/21 09:07:15 cgd Exp $     */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -73,7 +69,7 @@ typedef struct {
        char    c_mtime[11];            /* modification time */
        char    c_namesize[6];          /* length of pathname */
        char    c_filesize[11];         /* length of file in bytes */
-} HD_CPIO; 
+} HD_CPIO;
 
 #define        MAGIC           070707          /* transportable archive id */
 
@@ -84,7 +80,7 @@ typedef struct {
 #endif /* _PAX_ */
 
 /*
- * Binary cpio header structure 
+ * Binary cpio header structure
  *
  * CAUTION! CAUTION! CAUTION!
  * Each field really represents a 16 bit short (NOT ASCII). Described as
@@ -104,7 +100,7 @@ typedef struct {
        u_char  h_namesize[2];
        u_char  h_filesize_1[2];
        u_char  h_filesize_2[2];
-} HD_BCPIO; 
+} HD_BCPIO;
 
 #ifdef _PAX_
 /*
@@ -142,7 +138,7 @@ typedef struct {
        char    c_rmin[8];              /* special file minor # */
        char    c_namesize[8];          /* length of pathname */
        char    c_chksum[8];            /* 0 OR CRC of bytes of FILE data */
-} HD_VCPIO; 
+} HD_VCPIO;
 
 #define        VMAGIC          070701          /* sVr4 new portable archive id */
 #define        VCMAGIC         070702          /* sVr4 new portable archive id CRC */
index df441731d4880bb4640e05dfda8f845722ddd610..acdfafca2d2ca7c93eb8396d0799fcf6051d25d0 100644 (file)
--- a/extern.h
+++ b/extern.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: extern.h,v 1.15 1998/09/20 02:22:21 millert Exp $     */
+/*     $OpenBSD: extern.h,v 1.33 2008/05/06 06:54:28 henning Exp $     */
 /*     $NetBSD: extern.h,v 1.5 1996/03/26 23:54:16 mrg Exp $   */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
 /*
  * ar_io.c
  */
-extern char *arcname;
-extern char *gzip_program;
-int ar_open __P((char *));
-void ar_close __P((void));
-void ar_drain __P((void));
-int ar_set_wr __P((void));
-int ar_app_ok __P((void));
-int ar_read __P((register char *, register int));
-int ar_write __P((register char *, register int));
-int ar_rdsync __P((void));
-int ar_fow __P((off_t, off_t *));
-int ar_rev __P((off_t ));
-int ar_next __P((void));
+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);
+int ar_set_wr(void);
+int ar_app_ok(void);
+int ar_read(char *, int);
+int ar_write(char *, int);
+int ar_rdsync(void);
+int ar_fow(off_t, off_t *);
+int ar_rev(off_t );
+int ar_next(void);
 
 /*
  * ar_subs.c
  */
 extern u_long flcnt;
-void list __P((void));
-void extract __P((void));
-void append __P((void));
-void archive __P((void));
-void copy __P((void));
+void list(void);
+void extract(void);
+void append(void);
+void archive(void);
+void copy(void);
 
 /*
  * buf_subs.c
@@ -83,126 +80,132 @@ extern int rdblksz;
 extern off_t wrlimit;
 extern off_t rdcnt;
 extern off_t wrcnt;
-int wr_start __P((void));
-int rd_start __P((void));
-void cp_start __P((void));
-int appnd_start __P((off_t));
-int rd_sync __P((void));
-void pback __P((char *, int));
-int rd_skip __P((off_t));
-void wr_fin __P((void));
-int wr_rdbuf __P((register char *, register int));
-int rd_wrbuf __P((register char *, register int));
-int wr_skip __P((off_t));
-int wr_rdfile __P((ARCHD *, int, off_t *));
-int rd_wrfile __P((ARCHD *, int, off_t *));
-void cp_file __P((ARCHD *, int, int));
-int buf_fill __P((void));
-int buf_flush __P((register int));
+int wr_start(void);
+int rd_start(void);
+void cp_start(void);
+int appnd_start(off_t);
+int rd_sync(void);
+void pback(char *, int);
+int rd_skip(off_t);
+void wr_fin(void);
+int wr_rdbuf(char *, int);
+int rd_wrbuf(char *, int);
+int wr_skip(off_t);
+int wr_rdfile(ARCHD *, int, off_t *);
+int rd_wrfile(ARCHD *, int, off_t *);
+void cp_file(ARCHD *, int, int);
+int buf_fill(void);
+int buf_flush(int);
 
 /*
  * cache.c
  */
-int uidtb_start __P((void));
-int gidtb_start __P((void));
-int usrtb_start __P((void));
-int grptb_start __P((void));
-char * name_uid __P((uid_t, int));
-char * name_gid __P((gid_t, int));
-int uid_name __P((char *, uid_t *));
-int gid_name __P((char *, gid_t *));
+int uidtb_start(void);
+int gidtb_start(void);
+int usrtb_start(void);
+int grptb_start(void);
+char * name_uid(uid_t, int);
+char * name_gid(gid_t, int);
+int uid_name(char *, uid_t *);
+int gid_name(char *, gid_t *);
 
 /*
  * cpio.c
  */
-int cpio_strd __P((void));
-int cpio_trail __P((register ARCHD *));
-int cpio_endwr __P((void));
-int cpio_id __P((char *, int));
-int cpio_rd __P((register ARCHD *, register char *));
-off_t cpio_endrd __P((void));
-int cpio_stwr __P((void));
-int cpio_wr __P((register ARCHD *));
-int vcpio_id __P((char *, int));
-int crc_id __P((char *, int));
-int crc_strd __P((void));
-int vcpio_rd __P((register ARCHD *, register char *));
-off_t vcpio_endrd __P((void));
-int crc_stwr __P((void));
-int vcpio_wr __P((register ARCHD *));
-int bcpio_id __P((char *, int));
-int bcpio_rd __P((register ARCHD *, register char *));
-off_t bcpio_endrd __P((void));
-int bcpio_wr __P((register ARCHD *));
+int cpio_strd(void);
+int cpio_trail(ARCHD *, char *, int, int *);
+int cpio_endwr(void);
+int cpio_id(char *, int);
+int cpio_rd(ARCHD *, char *);
+off_t cpio_endrd(void);
+int cpio_stwr(void);
+int cpio_wr(ARCHD *);
+int vcpio_id(char *, int);
+int crc_id(char *, int);
+int crc_strd(void);
+int vcpio_rd(ARCHD *, char *);
+off_t vcpio_endrd(void);
+int crc_stwr(void);
+int vcpio_wr(ARCHD *);
+int bcpio_id(char *, int);
+int bcpio_rd(ARCHD *, char *);
+off_t bcpio_endrd(void);
+int bcpio_wr(ARCHD *);
 
 /*
  * file_subs.c
  */
-int file_creat __P((register ARCHD *));
-void file_close __P((register ARCHD *, int));
-int lnk_creat __P((register ARCHD *));
-int cross_lnk __P((register ARCHD *));
-int chk_same __P((register ARCHD *));
-int node_creat __P((register ARCHD *));
-int unlnk_exist __P((register char *, register int));
-int chk_path __P((register char *, uid_t, gid_t));
-void set_ftime __P((char *fnm, time_t mtime, time_t atime, int frc));
-int set_ids __P((char *, uid_t, gid_t));
-int set_lids __P((char *, uid_t, gid_t));
-void set_pmode __P((char *, mode_t));
-int file_write __P((int, char *, register int, int *, int *, int, char *));
-void file_flush __P((int, char *, int));
-void rdfile_close __P((register ARCHD *, register int *));
-int set_crc __P((register ARCHD *, register int));
+extern char *gnu_name_string, *gnu_link_string;
+int file_creat(ARCHD *);
+void file_close(ARCHD *, int);
+int lnk_creat(ARCHD *);
+int cross_lnk(ARCHD *);
+int chk_same(ARCHD *);
+int node_creat(ARCHD *);
+int unlnk_exist(char *, int);
+int chk_path(char *, uid_t, gid_t);
+void set_ftime(char *fnm, time_t mtime, time_t atime, int frc);
+void fset_ftime(char *fnm, int, time_t mtime, time_t atime, int frc);
+int set_ids(char *, uid_t, gid_t);
+int fset_ids(char *, int, uid_t, gid_t);
+int set_lids(char *, uid_t, gid_t);
+void set_pmode(char *, mode_t);
+void fset_pmode(char *, int, mode_t);
+int file_write(int, char *, int, int *, int *, int, char *);
+void file_flush(int, char *, int);
+void rdfile_close(ARCHD *, int *);
+int set_crc(ARCHD *, int);
 
 /*
  * ftree.c
  */
-int ftree_start __P((void));
-int ftree_add __P((register char *, int));
-void ftree_sel __P((register ARCHD *));
-void ftree_chk __P((void));
-int next_file __P((register ARCHD *));
+int ftree_start(void);
+int ftree_add(char *, int);
+void ftree_sel(ARCHD *);
+void ftree_skipped_newer(ARCHD *);
+void ftree_chk(void);
+int next_file(ARCHD *);
 
 /*
  * gen_subs.c
  */
-void ls_list __P((register ARCHD *, time_t, FILE *));
-void ls_tty __P((register ARCHD *));
-int l_strncpy __P((register char *, register char *, int));
-u_long asc_ul __P((register char *, int, register int));
-int ul_asc __P((u_long, register char *, register int, register int));
-#ifndef NET2_STAT
-u_quad_t asc_uqd __P((register char *, int, register int));
-int uqd_asc __P((u_quad_t, register char *, register int, register int));
+void ls_list(ARCHD *, time_t, FILE *);
+void ls_tty(ARCHD *);
+void safe_print(const char *, FILE *);
+u_long asc_ul(char *, int, int);
+int ul_asc(u_long, char *, int, int);
+#ifndef LONG_OFF_T
+u_quad_t asc_uqd(char *, int, int);
+int uqd_asc(u_quad_t, char *, int, int);
 #endif
+size_t fieldcpy(char *, size_t, const char *, size_t);
 
-/* 
+/*
  * getoldopt.c
  */
-int getoldopt __P((int, char **, char *));
+int getoldopt(int, char **, const char *);
 
 /*
  * options.c
  */
 extern FSUB fsub[];
 extern int ford[];
-void options __P((register int, register char **));
-OPLIST * opt_next __P((void));
-int opt_add __P((register char *));
-int bad_opt __P((void));
+void options(int, char **);
+OPLIST * opt_next(void);
+int opt_add(const char *);
+int bad_opt(void);
 char *chdname;
 
 /*
  * pat_rep.c
  */
-int rep_add __P((register char *));
-int pat_add __P((char *, char *));
-void pat_chk __P((void));
-int pat_sel __P((register ARCHD *));
-int pat_match __P((register ARCHD *));
-int mod_name __P((register ARCHD *));
-int set_dest __P((register ARCHD *, char *, int));
+int rep_add(char *);
+int pat_add(char *, char *);
+void pat_chk(void);
+int pat_sel(ARCHD *);
+int pat_match(ARCHD *);
+int mod_name(ARCHD *);
+int set_dest(ARCHD *, char *, int);
 
 /*
  * pax.c
@@ -219,13 +222,13 @@ extern int nflag;
 extern int tflag;
 extern int uflag;
 extern int vflag;
-extern int zflag;
 extern int Dflag;
 extern int Hflag;
 extern int Lflag;
 extern int Xflag;
 extern int Yflag;
 extern int Zflag;
+extern int zeroflag;
 extern int vfpart;
 extern int patime;
 extern int pmtime;
@@ -239,63 +242,67 @@ extern char *dirptr;
 extern char *ltmfrmt;
 extern char *argv0;
 extern FILE *listf;
+extern char *tempfile;
+extern char *tempbase;
+extern int havechd;
 
-int main __P((int, char **));
-void sig_cleanup __P((int));
+int main(int, char **);
+void sig_cleanup(int);
 
 /*
  * sel_subs.c
  */
-int sel_chk __P((register ARCHD *));
-int grp_add __P((register char *));
-int usr_add __P((register char *));
-int trng_add __P((register char *));
+int sel_chk(ARCHD *);
+int grp_add(char *);
+int usr_add(char *);
+int trng_add(char *);
 
 /*
  * tables.c
  */
-int lnk_start __P((void));
-int chk_lnk __P((register ARCHD *));
-void purg_lnk __P((register ARCHD *));
-void lnk_end __P((void));
-int ftime_start __P((void));
-int chk_ftime __P((register ARCHD *));
-int name_start __P((void));
-int add_name __P((register char *, int, char *));
-void sub_name __P((register char *, int *, size_t));
-int dev_start __P((void));
-int add_dev __P((register ARCHD *));
-int map_dev __P((register ARCHD *, u_long, u_long));
-int atdir_start __P((void));
-void atdir_end __P((void));
-void add_atdir __P((char *, dev_t, ino_t, time_t, time_t));
-int get_atdir __P((dev_t, ino_t, time_t *, time_t *));
-int dir_start __P((void));
-void add_dir __P((char *, int, struct stat *, int));
-void proc_dir __P((void));
-u_int st_hash __P((char *, int, int));
+int lnk_start(void);
+int chk_lnk(ARCHD *);
+void purg_lnk(ARCHD *);
+void lnk_end(void);
+int ftime_start(void);
+int chk_ftime(ARCHD *);
+int name_start(void);
+int add_name(char *, int, char *);
+void sub_name(char *, int *, size_t);
+int dev_start(void);
+int add_dev(ARCHD *);
+int map_dev(ARCHD *, u_long, u_long);
+int atdir_start(void);
+void atdir_end(void);
+void add_atdir(char *, dev_t, ino_t, time_t, time_t);
+int get_atdir(dev_t, ino_t, time_t *, time_t *);
+int dir_start(void);
+void add_dir(char *, struct stat *, int);
+void proc_dir(void);
+u_int st_hash(char *, int, int);
 
 /*
  * tar.c
  */
-int tar_endwr __P((void));
-off_t tar_endrd __P((void));
-int tar_trail __P((register char *, register int, register int *));
-int tar_id __P((register char *, int));
-int tar_opt __P((void));
-int tar_rd __P((register ARCHD *, register char *));
-int tar_wr __P((register ARCHD *));
-int ustar_strd __P((void));
-int ustar_stwr __P((void));
-int ustar_id __P((char *, int));
-int ustar_rd __P((register ARCHD *, register char *));
-int ustar_wr __P((register ARCHD *));
+extern char *gnu_hack_string;
+int tar_endwr(void);
+off_t tar_endrd(void);
+int tar_trail(ARCHD *, char *, int, int *);
+int tar_id(char *, int);
+int tar_opt(void);
+int tar_rd(ARCHD *, char *);
+int tar_wr(ARCHD *);
+int ustar_strd(void);
+int ustar_stwr(void);
+int ustar_id(char *, int);
+int ustar_rd(ARCHD *, char *);
+int ustar_wr(ARCHD *);
 
 /*
  * tty_subs.c
  */
-int tty_init __P((void));
-void tty_prnt __P((char *, ...));
-int tty_read __P((char *, int));
-void paxwarn __P((int, char *, ...));
-void syswarn __P((int, int, char *, ...));
+int tty_init(void);
+void tty_prnt(const char *, ...);
+int tty_read(char *, int);
+void paxwarn(int, const char *, ...);
+void syswarn(int, int, const char *, ...);
index 2241c3885f157b11c5b566d92368059ae2323170..73db1af11295febfc8a5c5d6e3123d19bae71325 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: file_subs.c,v 1.13 1997/09/01 18:29:48 deraadt Exp $  */
+/*     $OpenBSD: file_subs.c,v 1.30 2005/11/09 19:59:06 otto Exp $     */
 /*     $NetBSD: file_subs.c,v 1.4 1995/03/21 09:07:18 cgd Exp $        */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)file_subs.c        8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)file_subs.c  8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] = "$OpenBSD: file_subs.c,v 1.13 1997/09/01 18:29:48 deraadt Exp $";
+static const char rcsid[] = "$OpenBSD: file_subs.c,v 1.30 2005/11/09 19:59:06 otto 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"
 
 static int
-mk_link __P((register char *,register struct stat *,register char *, int));
+mk_link(char *, struct stat *, char *, int);
 
 /*
  * routines that deal with file operations such as: creating, removing;
@@ -80,26 +76,20 @@ mk_link __P((register char *,register struct stat *,register char *, int));
  *     file descriptor or -1 for failure
  */
 
-#ifdef __STDC__
-int
-file_creat(register ARCHD *arcn)
-#else
 int
-file_creat(arcn)
-       register ARCHD *arcn;
-#endif
+file_creat(ARCHD *arcn)
 {
        int fd = -1;
        mode_t file_mode;
        int oerrno;
 
        /*
-        * assume file doesn't exist, so just try to create it, most times this
+        * Assume file doesn't exist, so just try to create it, most times this
         * works. We have to take special handling when the file does exist. To
         * detect this, we use O_EXCL. For example when trying to create a
         * file and a character device or fifo exists with the same name, we
-        * can accidently open the device by mistake (or block waiting to open)
-        * If we find that the open has failed, then figure spend the effore to
+        * can accidently open the device by mistake (or block waiting to open).
+        * If we find that the open has failed, then spend the effort to
         * figure out why. This strategy was found to have better average
         * performance in common use than checking the file (and the path)
         * first with lstat.
@@ -143,31 +133,22 @@ file_creat(arcn)
  *     0 for success, -1 for failure
  */
 
-#ifdef __STDC__
 void
-file_close(register ARCHD *arcn, int fd)
-#else
-void
-file_close(arcn, fd)
-       register ARCHD *arcn;
-       int fd;
-#endif
+file_close(ARCHD *arcn, int fd)
 {
        int res = 0;
 
        if (fd < 0)
                return;
-       if (close(fd) < 0)
-               syswarn(0, errno, "Unable to close file descriptor on %s",
-                   arcn->name);
 
        /*
         * set owner/groups first as this may strip off mode bits we want
         * then set file permission modes. Then set file access and
-        * modification times. 
+        * modification times.
         */
        if (pids)
-               res = set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid);
+               res = fset_ids(arcn->name, fd, arcn->sb.st_uid,
+                   arcn->sb.st_gid);
 
        /*
         * IMPORTANT SECURITY NOTE:
@@ -177,27 +158,25 @@ file_close(arcn, fd)
        if (!pmode || res)
                arcn->sb.st_mode &= ~(SETBITS);
        if (pmode)
-               set_pmode(arcn->name, arcn->sb.st_mode);
+               fset_pmode(arcn->name, fd, arcn->sb.st_mode);
        if (patime || pmtime)
-               set_ftime(arcn->name, arcn->sb.st_mtime, arcn->sb.st_atime, 0);
+               fset_ftime(arcn->name, fd, arcn->sb.st_mtime,
+                   arcn->sb.st_atime, 0);
+       if (close(fd) < 0)
+               syswarn(0, errno, "Unable to close file descriptor on %s",
+                   arcn->name);
 }
 
 /*
  * lnk_creat()
  *     Create a hard link to arcn->ln_name from arcn->name. arcn->ln_name
- *     must exist; 
+ *     must exist;
  * Return:
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
-lnk_creat(register ARCHD *arcn)
-#else
-int
-lnk_creat(arcn)
-       register ARCHD *arcn;
-#endif
+lnk_creat(ARCHD *arcn)
 {
        struct stat sb;
 
@@ -230,19 +209,13 @@ lnk_creat(arcn)
  *     0 if cross_lnk() ok, -1 for fatal flaw (like linking to self).
  */
 
-#ifdef __STDC__
 int
-cross_lnk(register ARCHD *arcn)
-#else
-int
-cross_lnk(arcn)
-       register ARCHD *arcn;
-#endif
+cross_lnk(ARCHD *arcn)
 {
        /*
-        * try to make a link to orginal file (-l flag in copy mode). make sure
-        * we do not try to link to directories in case we are running as root
-        * (and it might succeed).
+        * try to make a link to original file (-l flag in copy mode). make
+        * sure we do not try to link to directories in case we are running as
+        * root (and it might succeed).
         */
        if (arcn->type == PAX_DIR)
                return(1);
@@ -260,18 +233,12 @@ cross_lnk(arcn)
  *     0 skip it file exists (-k) or may be the same as source file
  */
 
-#ifdef __STDC__
-int
-chk_same(register ARCHD *arcn)
-#else
 int
-chk_same(arcn)
-       register ARCHD *arcn;
-#endif
+chk_same(ARCHD *arcn)
 {
        struct stat sb;
 
-       /* 
+       /*
         * if file does not exist, return. if file exists and -k, skip it
         * quietly
         */
@@ -303,18 +270,8 @@ chk_same(arcn)
  *     allowed option). -1 an error occurred.
  */
 
-#ifdef __STDC__
-static int
-mk_link(register char *to, register struct stat *to_sb, register char *from,
-       int ign)
-#else
 static int
-mk_link(to, to_sb, from, ign)
-       register char *to;
-       register struct stat *to_sb;
-       register char *from;
-       int ign;
-#endif
+mk_link(char *to, struct stat *to_sb, char *from, int ign)
 {
        struct stat sb;
        int oerrno;
@@ -332,7 +289,7 @@ mk_link(to, to_sb, from, ign)
                 */
                if ((to_sb->st_dev==sb.st_dev)&&(to_sb->st_ino == sb.st_ino)) {
                        paxwarn(1, "Unable to link file %s to itself", to);
-                       return(-1);;
+                       return(-1);
                }
 
                /*
@@ -385,21 +342,18 @@ mk_link(to, to_sb, from, ign)
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
-node_creat(register ARCHD *arcn)
-#else
-int
-node_creat(arcn)
-       register ARCHD *arcn;
-#endif
+node_creat(ARCHD *arcn)
 {
-       register int res;
-       register int ign = 0;
-       register int oerrno;
-       register int pass = 0;
+       int res;
+       int ign = 0;
+       int oerrno;
+       int pass = 0;
        mode_t file_mode;
        struct stat sb;
+       char target[MAXPATHLEN];
+       char *nm = arcn->name;
+       int len;
 
        /*
         * create node based on type, if that fails try to unlink the node and
@@ -410,22 +364,45 @@ node_creat(arcn)
        file_mode = arcn->sb.st_mode & FILEBITS;
 
        for (;;) {
-               switch(arcn->type) {
+               switch (arcn->type) {
                case PAX_DIR:
-                       res = mkdir(arcn->name, file_mode);
+                       /*
+                        * If -h (or -L) was given in tar-mode, follow the
+                        * potential symlink chain before trying to create the
+                        * directory.
+                        */
+                       if (strcmp(NM_TAR, argv0) == 0 && Lflag) {
+                               while (lstat(nm, &sb) == 0 &&
+                                   S_ISLNK(sb.st_mode)) {
+                                       len = readlink(nm, target,
+                                           sizeof target - 1);
+                                       if (len == -1) {
+                                               syswarn(0, errno,
+                                                  "cannot follow symlink %s in chain for %s",
+                                                   nm, arcn->name);
+                                               res = -1;
+                                               goto badlink;
+                                       }
+                                       target[len] = '\0';
+                                       nm = target;
+                               }
+                       }
+                       res = mkdir(nm, file_mode);
+
+badlink:
                        if (ign)
                                res = 0;
                        break;
                case PAX_CHR:
                        file_mode |= S_IFCHR;
-                       res = mknod(arcn->name, file_mode, arcn->sb.st_rdev);
+                       res = mknod(nm, file_mode, arcn->sb.st_rdev);
                        break;
                case PAX_BLK:
                        file_mode |= S_IFBLK;
-                       res = mknod(arcn->name, file_mode, arcn->sb.st_rdev);
+                       res = mknod(nm, file_mode, arcn->sb.st_rdev);
                        break;
                case PAX_FIF:
-                       res = mkfifo(arcn->name, file_mode);
+                       res = mkfifo(nm, file_mode);
                        break;
                case PAX_SCK:
                        /*
@@ -433,10 +410,10 @@ node_creat(arcn)
                         */
                        paxwarn(0,
                            "%s skipped. Sockets cannot be copied or extracted",
-                           arcn->name);
+                           nm);
                        return(-1);
                case PAX_SLK:
-                       res = symlink(arcn->ln_name, arcn->name);
+                       res = symlink(arcn->ln_name, nm);
                        break;
                case PAX_CTG:
                case PAX_HLK:
@@ -447,7 +424,7 @@ node_creat(arcn)
                         * we should never get here
                         */
                        paxwarn(0, "%s has an unknown file type, skipping",
-                               arcn->name);
+                               nm);
                        return(-1);
                }
 
@@ -463,14 +440,14 @@ node_creat(arcn)
                 * we failed to make the node
                 */
                oerrno = errno;
-               if ((ign = unlnk_exist(arcn->name, arcn->type)) < 0)
+               if ((ign = unlnk_exist(nm, arcn->type)) < 0)
                        return(-1);
 
                if (++pass <= 1)
                        continue;
 
-               if (nodirs || chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
-                       syswarn(1, oerrno, "Could not create: %s", arcn->name);
+               if (nodirs || chk_path(nm,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
+                       syswarn(1, oerrno, "Could not create: %s", nm);
                        return(-1);
                }
        }
@@ -480,8 +457,8 @@ node_creat(arcn)
         */
        if (pids)
                res = ((arcn->type == PAX_SLK) ?
-                   set_lids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid) :
-                   set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid));
+                   set_lids(nm, arcn->sb.st_uid, arcn->sb.st_gid) :
+                   set_ids(nm, arcn->sb.st_uid, arcn->sb.st_gid));
        else
                res = 0;
 
@@ -499,7 +476,7 @@ node_creat(arcn)
        if (!pmode || res)
                arcn->sb.st_mode &= ~(SETBITS);
        if (pmode)
-               set_pmode(arcn->name, arcn->sb.st_mode);
+               set_pmode(nm, arcn->sb.st_mode);
 
        if (arcn->type == PAX_DIR && strcmp(NM_CPIO, argv0) != 0) {
                /*
@@ -511,11 +488,11 @@ node_creat(arcn)
                 * and modes will be fixed after the entire archive is read and
                 * before pax exits.
                 */
-               if (access(arcn->name, R_OK | W_OK | X_OK) < 0) {
-                       if (lstat(arcn->name, &sb) < 0) {
+               if (access(nm, R_OK | W_OK | X_OK) < 0) {
+                       if (lstat(nm, &sb) < 0) {
                                syswarn(0, errno,"Could not access %s (stat)",
                                    arcn->name);
-                               set_pmode(arcn->name,file_mode | S_IRWXU);
+                               set_pmode(nm,file_mode | S_IRWXU);
                        } else {
                                /*
                                 * We have to add rights to the dir, so we make
@@ -523,7 +500,7 @@ node_creat(arcn)
                                 * restored AS CREATED and not as stored if
                                 * pmode is not set.
                                 */
-                               set_pmode(arcn->name,
+                               set_pmode(nm,
                                    ((sb.st_mode & FILEBITS) | S_IRWXU));
                                if (!pmode)
                                        arcn->sb.st_mode = sb.st_mode;
@@ -533,13 +510,13 @@ node_creat(arcn)
                         * we have to force the mode to what was set here,
                         * since we changed it from the default as created.
                         */
-                       add_dir(arcn->name, arcn->nlen, &(arcn->sb), 1);
+                       add_dir(nm, &(arcn->sb), 1);
                } else if (pmode || patime || pmtime)
-                       add_dir(arcn->name, arcn->nlen, &(arcn->sb), 0);
+                       add_dir(nm, &(arcn->sb), 0);
        }
 
        if (patime || pmtime)
-               set_ftime(arcn->name, arcn->sb.st_mtime, arcn->sb.st_atime, 0);
+               set_ftime(nm, arcn->sb.st_mtime, arcn->sb.st_atime, 0);
        return(0);
 }
 
@@ -555,15 +532,8 @@ node_creat(arcn)
  *     1 we found a directory and we were going to create a directory.
  */
 
-#ifdef __STDC__
-int
-unlnk_exist(register char *name, register int type)
-#else
 int
-unlnk_exist(name, type)
-       register char *name;
-       register int type;
-#endif
+unlnk_exist(char *name, int type)
 {
        struct stat sb;
 
@@ -613,18 +583,10 @@ unlnk_exist(name, type)
  *     0 otherwise
  */
 
-#ifdef __STDC__
-int
-chk_path( register char *name, uid_t st_uid, gid_t st_gid)
-#else
 int
-chk_path(name, st_uid, st_gid)
-       register char *name;
-       uid_t st_uid;
-       gid_t st_gid;
-#endif
+chk_path(char *name, uid_t st_uid, gid_t st_gid)
 {
-       register char *spt = name;
+       char *spt = name;
        struct stat sb;
        int retval = -1;
 
@@ -634,9 +596,9 @@ chk_path(name, st_uid, st_gid)
        if (*spt == '/')
                ++spt;
 
-       for(;;) {
+       for (;;) {
                /*
-                * work foward from the first / and check each part of the path
+                * work forward from the first / and check each part of the path
                 */
                spt = strchr(spt, '/');
                if (spt == NULL)
@@ -677,7 +639,7 @@ chk_path(name, st_uid, st_gid)
                        (void)set_ids(name, st_uid, st_gid);
 
                /*
-                * make sure the user doen't have some strange umask that
+                * make sure the user doesn't have some strange umask that
                 * causes this newly created directory to be unusable. We fix
                 * the modes and restore them back to the creation default at
                 * the end of pax
@@ -685,7 +647,7 @@ chk_path(name, st_uid, st_gid)
                if ((access(name, R_OK | W_OK | X_OK) < 0) &&
                    (lstat(name, &sb) == 0)) {
                        set_pmode(name, ((sb.st_mode & FILEBITS) | S_IRWXU));
-                       add_dir(name, spt - name, &sb, 1);
+                       add_dir(name, &sb, 1);
                }
                *(spt++) = '/';
                continue;
@@ -695,8 +657,8 @@ chk_path(name, st_uid, st_gid)
 
 /*
  * set_ftime()
- *     Set the access time and modification time for a named file. If frc is
- *     non-zero we force these times to be set even if the user did not
+ *     Set the access time and modification time for a named file. If frc
+ *     is non-zero we force these times to be set even if the user did not
  *     request access and/or modification time preservation (this is also
  *     used by -t to reset access times).
  *     When ign is zero, only those times the user has asked for are set, the
@@ -705,17 +667,8 @@ chk_path(name, st_uid, st_gid)
  *     not set request.
  */
 
-#ifdef __STDC__
 void
 set_ftime(char *fnm, time_t mtime, time_t atime, int frc)
-#else
-void
-set_ftime(fnm, mtime, atime, frc)
-       char *fnm;
-       time_t mtime;
-       time_t atime;
-       int frc;
-#endif
 {
        static struct timeval tv[2] = {{0L, 0L}, {0L, 0L}};
        struct stat sb;
@@ -745,6 +698,36 @@ set_ftime(fnm, mtime, atime, frc)
        return;
 }
 
+void
+fset_ftime(char *fnm, int fd, time_t mtime, time_t atime, int frc)
+{
+       static struct timeval tv[2] = {{0L, 0L}, {0L, 0L}};
+       struct stat sb;
+
+       tv[0].tv_sec = (long)atime;
+       tv[1].tv_sec = (long)mtime;
+       if (!frc && (!patime || !pmtime)) {
+               /*
+                * if we are not forcing, only set those times the user wants
+                * set. We get the current values of the times if we need them.
+                */
+               if (fstat(fd, &sb) == 0) {
+                       if (!patime)
+                               tv[0].tv_sec = (long)sb.st_atime;
+                       if (!pmtime)
+                               tv[1].tv_sec = (long)sb.st_mtime;
+               } else
+                       syswarn(0,errno,"Unable to obtain file stats %s", fnm);
+       }
+       /*
+        * set the times
+        */
+       if (futimes(fd, tv) < 0)
+               syswarn(1, errno, "Access/modification time set failed on: %s",
+                   fnm);
+       return;
+}
+
 /*
  * set_ids()
  *     set the uid and gid of a file system node
@@ -752,16 +735,8 @@ set_ftime(fnm, mtime, atime, frc)
  *     0 when set, -1 on failure
  */
 
-#ifdef __STDC__
 int
 set_ids(char *fnm, uid_t uid, gid_t gid)
-#else
-int
-set_ids(fnm, uid, gid)
-       char *fnm;
-       uid_t uid;
-       gid_t gid;
-#endif
 {
        if (chown(fnm, uid, gid) < 0) {
                /*
@@ -777,6 +752,23 @@ set_ids(fnm, uid, gid)
        return(0);
 }
 
+int
+fset_ids(char *fnm, int fd, uid_t uid, gid_t gid)
+{
+       if (fchown(fd, uid, gid) < 0) {
+               /*
+                * ignore EPERM unless in verbose mode or being run by root.
+                * if running as pax, POSIX requires a warning.
+                */
+               if (strcmp(NM_PAX, argv0) == 0 || errno != EPERM || vflag ||
+                   geteuid() == 0)
+                       syswarn(1, errno, "Unable to set file uid/gid of %s",
+                           fnm);
+               return(-1);
+       }
+       return(0);
+}
+
 /*
  * set_lids()
  *     set the uid and gid of a file system node
@@ -784,16 +776,8 @@ set_ids(fnm, uid, gid)
  *     0 when set, -1 on failure
  */
 
-#ifdef __STDC__
 int
 set_lids(char *fnm, uid_t uid, gid_t gid)
-#else
-int
-set_lids(fnm, uid, gid)
-       char *fnm;
-       uid_t uid;
-       gid_t gid;
-#endif
 {
        if (lchown(fnm, uid, gid) < 0) {
                /*
@@ -814,15 +798,8 @@ set_lids(fnm, uid, gid)
  *     Set file access mode
  */
 
-#ifdef __STDC__
 void
 set_pmode(char *fnm, mode_t mode)
-#else
-void
-set_pmode(fnm, mode)
-       char *fnm;
-       mode_t mode;
-#endif
 {
        mode &= ABITS;
        if (chmod(fnm, mode) < 0)
@@ -830,6 +807,15 @@ set_pmode(fnm, mode)
        return;
 }
 
+void
+fset_pmode(char *fnm, int fd, mode_t mode)
+{
+       mode &= ABITS;
+       if (fchmod(fd, mode) < 0)
+               syswarn(1, errno, "Could not set permissions on %s", fnm);
+       return;
+}
+
 /*
  * file_write()
  *     Write/copy a file (during copy or archive extract). This routine knows
@@ -849,11 +835,11 @@ set_pmode(fnm, mode)
  *     uses lseek whenever it detects the input data is all 0 within that
  *     file block. In more detail, the strategy is as follows:
  *     While the input is all zero keep doing an lseek. Keep track of when we
- *     pass over file block boundries. Only write when we hit a non zero
+ *     pass over file block boundaries. Only write when we hit a non zero
  *     input. once we have written a file block, we continue to write it to
  *     the end (we stop looking at the input). When we reach the start of the
  *     next file block, start checking for zero blocks again. Working on file
- *     block boundries significantly reduces the overhead when copying files
+ *     block boundaries significantly reduces the overhead when copying files
  *     that are NOT very sparse. This overhead (when compared to a write) is
  *     almost below the measurement resolution on many systems. Without it,
  *     files with holes cannot be safely copied. It does has a side effect as
@@ -878,26 +864,15 @@ set_pmode(fnm, mode)
  *     number of bytes written, -1 on write (or lseek) error.
  */
 
-#ifdef __STDC__
 int
-file_write(int fd, char *str, register int cnt, int *rem, int *isempt, int sz,
+file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz,
        char *name)
-#else
-int
-file_write(fd, str, cnt, rem, isempt, sz, name)
-       int fd;
-       char *str;
-       register int cnt;
-       int *rem;
-       int *isempt;
-       int sz;
-       char *name;
-#endif
 {
-       register char *pt;
-       register char *end;
-       register int wcnt;
-       register char *st = str;
+       char *pt;
+       char *end;
+       int wcnt;
+       char *st = str;
+       char **strp;
 
        /*
         * while we have data to process
@@ -938,7 +913,8 @@ file_write(fd, str, cnt, rem, isempt, sz, name)
                                /*
                                 * 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);
@@ -955,7 +931,29 @@ file_write(fd, str, cnt, rem, isempt, sz, name)
                /*
                 * have non-zero data in this file system block, have to write
                 */
-               if (write(fd, st, wcnt) != wcnt) {
+               switch (fd) {
+               case -1:
+                       strp = &gnu_name_string;
+                       break;
+               case -2:
+                       strp = &gnu_link_string;
+                       break;
+               default:
+                       strp = NULL;
+                       break;
+               }
+               if (strp) {
+                       if (*strp)
+                               err(1, "WARNING! Major Internal Error! GNU hack Failing!");
+                       *strp = malloc(wcnt + 1);
+                       if (*strp == NULL) {
+                               paxwarn(1, "Out of memory");
+                               return(-1);
+                       }
+                       memcpy(*strp, st, wcnt);
+                       (*strp)[wcnt] = '\0';
+                       break;
+               } else if (write(fd, st, wcnt) != wcnt) {
                        syswarn(1, errno, "Failed write to file %s", name);
                        return(-1);
                }
@@ -971,16 +969,8 @@ file_write(fd, str, cnt, rem, isempt, sz, name)
  *     write the last BYTE with a zero (back up one byte and write a zero).
  */
 
-#ifdef __STDC__
 void
 file_flush(int fd, char *fname, int isempt)
-#else
-void
-file_flush(fd, fname, isempt)
-       int fd;
-       char *fname;
-       int isempt;
-#endif
 {
        static char blnk[] = "\0";
 
@@ -1010,15 +1000,8 @@ file_flush(fd, fname, isempt)
  *     reset access time (tflag) do so (the times are stored in arcn).
  */
 
-#ifdef __STDC__
-void
-rdfile_close(register ARCHD *arcn, register int *fd)
-#else
 void
-rdfile_close(arcn, fd)
-       register ARCHD *arcn;
-       register int *fd;
-#endif
+rdfile_close(ARCHD *arcn, int *fd)
 {
        /*
         * make sure the file is open
@@ -1047,21 +1030,14 @@ rdfile_close(arcn, fd)
  *     0 if was able to calculate the crc, -1 otherwise
  */
 
-#ifdef __STDC__
 int
-set_crc(register ARCHD *arcn, register int fd)
-#else
-int
-set_crc(arcn, fd)
-       register ARCHD *arcn;
-       register int fd;
-#endif
+set_crc(ARCHD *arcn, int fd)
 {
-       register int i;
-       register int res;
+       int i;
+       int res;
        off_t cpcnt = 0L;
        u_long size;
-       unsigned long crc = 0L;
+       u_int32_t crc = 0;
        char tbuf[FILEBLK];
        struct stat sb;
 
@@ -1080,7 +1056,7 @@ set_crc(arcn, fd)
         * read all the bytes we think that there are in the file. If the user
         * is trying to archive an active file, forget this file.
         */
-       for(;;) {
+       for (;;) {
                if ((res = read(fd, tbuf, size)) <= 0)
                        break;
                cpcnt += res;
@@ -1090,7 +1066,7 @@ set_crc(arcn, fd)
 
        /*
         * safety check. we want to avoid archiving files that are active as
-        * they can create inconsistant archive copies.
+        * they can create inconsistent archive copies.
         */
        if (cpcnt != arcn->sb.st_size)
                paxwarn(1, "File changed size %s", arcn->org_name);
diff --git a/ftree.c b/ftree.c
index f95dd8d03b8b58f681ed8532231563c953f6f815..1ca2a7a1d6315cb07e6ea4043ddb3b83b9d0c271 100644 (file)
--- a/ftree.c
+++ b/ftree.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ftree.c,v 1.9 1998/06/09 07:28:41 deraadt Exp $       */
+/*     $OpenBSD: ftree.c,v 1.28 2008/05/06 06:54:28 henning Exp $      */
 /*     $NetBSD: ftree.c,v 1.4 1995/03/21 09:07:21 cgd Exp $    */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)ftree.c    8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)ftree.c      8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: ftree.c,v 1.9 1998/06/09 07:28:41 deraadt Exp $";
+static const char rcsid[] = "$OpenBSD: ftree.c,v 1.28 2008/05/06 06:54:28 henning Exp $";
 #endif
 #endif /* not lint */
 
@@ -74,7 +70,7 @@ static char rcsid[] = "$OpenBSD: ftree.c,v 1.9 1998/06/09 07:28:41 deraadt Exp $
  * pax, they are read from stdin
  */
 
-static FTS *ftsp = NULL;               /* curent FTS handle */
+static FTS *ftsp = NULL;               /* current FTS handle */
 static int ftsopts;                    /* options to be used on fts_open */
 static char *farray[2];                        /* array for passing each arg to fts */
 static FTREE *fthead = NULL;           /* head of linked list of file args */
@@ -83,7 +79,8 @@ static FTREE *ftcur = NULL;           /* current file arg being processed */
 static FTSENT *ftent = NULL;           /* current file tree entry */
 static int ftree_skip;                 /* when set skip to next file arg */
 
-static int ftree_arg __P((void));
+static int ftree_arg(void);
+static char *getpathname(char *, int);
 
 /*
  * ftree_start()
@@ -95,13 +92,8 @@ static int ftree_arg __P((void));
  *     0 if there is at least one valid file arg to process, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ftree_start(void)
-#else
-int
-ftree_start()
-#endif
 {
        /*
         * set up the operation mode of fts, open the first file arg. We must
@@ -126,11 +118,7 @@ ftree_start()
        else
                ftsopts |= FTS_PHYSICAL;
        if (Hflag)
-#      ifdef NET2_FTS
-               paxwarn(0, "The -H flag is not supported on this version");
-#      else
                ftsopts |= FTS_COMFOLLOW;
-#      endif
        if (Xflag)
                ftsopts |= FTS_XDEV;
 
@@ -154,24 +142,17 @@ ftree_start()
  *     0 if added to the linked list, -1 if failed
  */
 
-#ifdef __STDC__
-int
-ftree_add(register char *str, int chflg)
-#else
 int
-ftree_add(str, chflg)
-       register char *str;
-       int chflg;
-#endif
+ftree_add(char *str, int chflg)
 {
-       register FTREE *ft;
-       register int len;
+       FTREE *ft;
+       int len;
 
        /*
         * simple check for bad args
         */
        if ((str == NULL) || (*str == '\0')) {
-               paxwarn(0, "Invalid file name arguement");
+               paxwarn(0, "Invalid file name argument");
                return(-1);
        }
 
@@ -189,6 +170,7 @@ ftree_add(str, chflg)
                str[len] = '\0';
        ft->fname = str;
        ft->refcnt = 0;
+       ft->newercnt = 0;
        ft->chflg = chflg;
        ft->fow = NULL;
        if (fthead == NULL) {
@@ -206,14 +188,8 @@ ftree_add(str, chflg)
  *     -n and -d processing.
  */
 
-#ifdef __STDC__
-void
-ftree_sel(register ARCHD *arcn)
-#else
 void
-ftree_sel(arcn)
-       register ARCHD *arcn;
-#endif
+ftree_sel(ARCHD *arcn)
 {
        /*
         * set reference bit for this pattern. This linked list is only used
@@ -239,22 +215,30 @@ ftree_sel(arcn)
                (void)fts_set(ftsp, ftent, FTS_SKIP);
 }
 
+/*
+ * ftree_skipped_newer()
+ *     file has been skipped because a newer file exists and -u/-D given
+ */
+
+void
+ftree_skipped_newer(ARCHD *arcn)
+{
+       /* skipped due to -u/-D, mark accordingly */
+       if (ftcur != NULL)
+               ftcur->newercnt = 1;
+}
+
 /*
  * ftree_chk()
  *     called at end on pax execution. Prints all those file args that did not
  *     have a selected member (reference count still 0)
  */
 
-#ifdef __STDC__
 void
 ftree_chk(void)
-#else
-void
-ftree_chk()
-#endif
 {
-       register FTREE *ft;
-       register int wban = 0;
+       FTREE *ft;
+       int wban = 0;
 
        /*
         * make sure all dir access times were reset.
@@ -267,7 +251,7 @@ ftree_chk()
         * that never had a match
         */
        for (ft = fthead; ft != NULL; ft = ft->fow) {
-               if ((ft->refcnt > 0) || ft->chflg)
+               if ((ft->refcnt > 0) || ft->newercnt > 0 || ft->chflg)
                        continue;
                if (wban == 0) {
                        paxwarn(1,"WARNING! These file names were not selected:");
@@ -287,15 +271,9 @@ ftree_chk()
  *     stdin).
  */
 
-#ifdef __STDC__
 static int
 ftree_arg(void)
-#else
-static int
-ftree_arg()
-#endif
 {
-       register char *pt;
 
        /*
         * close off the current file tree
@@ -309,19 +287,17 @@ ftree_arg()
         * keep looping until we get a valid file tree to process. Stop when we
         * reach the end of the list (or get an eof on stdin)
         */
-       for(;;) {
+       for (;;) {
                if (fthead == NULL) {
                        /*
                         * the user didn't supply any args, get the file trees
-                        * to process from stdin; 
+                        * to process from stdin;
                         */
-                       if (fgets(farray[0], PAXPATHLEN+1, stdin) == NULL)
+                       if (getpathname(farray[0], PAXPATHLEN+1) == NULL)
                                return(-1);
-                       if ((pt = strchr(farray[0], '\n')) != NULL)
-                               *pt = '\0';
                } else {
                        /*
-                        * the user supplied the file args as arguements to pax
+                        * the user supplied the file args as arguments to pax
                         */
                        if (ftcur == NULL)
                                ftcur = fthead;
@@ -348,7 +324,7 @@ ftree_arg()
                 * watch it, fts wants the file arg stored in a array of char
                 * ptrs, with the last one a null. we use a two element array
                 * and set farray[0] to point at the buffer with the file name
-                * in it. We cannnot pass all the file args to fts at one shot
+                * in it. We cannot pass all the file args to fts at one shot
                 * as we need to keep a handle on which file arg generates what
                 * files (the -n and -d flags need this). If the open is
                 * successful, return a 0.
@@ -366,23 +342,17 @@ ftree_arg()
  *     0 when contents of arcn have been set with the next file, -1 when done.
  */
 
-#ifdef __STDC__
-int
-next_file(register ARCHD *arcn)
-#else
 int
-next_file(arcn)
-       register ARCHD *arcn;
-#endif
+next_file(ARCHD *arcn)
 {
-       register int cnt;
+       int cnt;
        time_t atime;
        time_t mtime;
 
        /*
         * ftree_sel() might have set the ftree_skip flag if the user has the
         * -n option and a file was selected from this file arg tree. (-n says
-        * only one member is matched for each pattern) ftree_skip being 1 
+        * only one member is matched for each pattern) ftree_skip being 1
         * forces us to go to the next arg now.
         */
        if (ftree_skip) {
@@ -397,8 +367,10 @@ next_file(arcn)
        /*
         * loop until we get a valid file to process
         */
-       for(;;) {
+       for (;;) {
                if ((ftent = fts_read(ftsp)) == NULL) {
+                       if (errno)
+                               syswarn(1, errno, "next_file");
                        /*
                         * out of files in this tree, go to next arg, if none
                         * we are done
@@ -411,7 +383,7 @@ next_file(arcn)
                /*
                 * handle each type of fts_read() flag
                 */
-               switch(ftent->fts_info) {
+               switch (ftent->fts_info) {
                case FTS_D:
                case FTS_DEFAULT:
                case FTS_F:
@@ -430,13 +402,8 @@ next_file(arcn)
                         * remember to force the time (this is -t on a read
                         * directory, not a created directory).
                         */
-#                      ifdef NET2_FTS
-                       if (!tflag || (get_atdir(ftent->fts_statb.st_dev,
-                           ftent->fts_statb.st_ino, &mtime, &atime) < 0))
-#                      else
                        if (!tflag || (get_atdir(ftent->fts_statp->st_dev,
                            ftent->fts_statp->st_ino, &mtime, &atime) < 0))
-#                      endif
                                continue;
                        set_ftime(ftent->fts_path, mtime, atime, 1);
                        continue;
@@ -447,28 +414,16 @@ next_file(arcn)
                        paxwarn(1,"File system cycle found at %s",ftent->fts_path);
                        continue;
                case FTS_DNR:
-#                      ifdef NET2_FTS
-                       syswarn(1, errno,
-#                      else
                        syswarn(1, ftent->fts_errno,
-#                      endif
                            "Unable to read directory %s", ftent->fts_path);
                        continue;
                case FTS_ERR:
-#                      ifdef NET2_FTS
-                       syswarn(1, errno,
-#                      else
                        syswarn(1, ftent->fts_errno,
-#                      endif
                            "File system traversal error");
                        continue;
                case FTS_NS:
                case FTS_NSOK:
-#                      ifdef NET2_FTS
-                       syswarn(1, errno,
-#                      else
                        syswarn(1, ftent->fts_errno,
-#                      endif
                            "Unable to access %s", ftent->fts_path);
                        continue;
                }
@@ -481,11 +436,7 @@ next_file(arcn)
                arcn->pad = 0;
                arcn->ln_nlen = 0;
                arcn->ln_name[0] = '\0';
-#              ifdef NET2_FTS
-               arcn->sb = ftent->fts_statb;
-#              else
-               arcn->sb = *(ftent->fts_statp);
-#              endif
+               memcpy(&arcn->sb, ftent->fts_statp, sizeof(arcn->sb));
 
                /*
                 * file type based set up and copy into the arcn struct
@@ -497,7 +448,7 @@ next_file(arcn)
                 * end in case we cut short a file tree traversal). However
                 * there is no way to reset access times on symlinks.
                 */
-               switch(S_IFMT & arcn->sb.st_mode) {
+               switch (S_IFMT & arcn->sb.st_mode) {
                case S_IFDIR:
                        arcn->type = PAX_DIR;
                        if (!tflag)
@@ -558,8 +509,57 @@ next_file(arcn)
        /*
         * copy file name, set file name length
         */
-       arcn->nlen = l_strncpy(arcn->name, ftent->fts_path, sizeof(arcn->name) - 1);
-       arcn->name[arcn->nlen] = '\0';
+       arcn->nlen = strlcpy(arcn->name, ftent->fts_path, sizeof(arcn->name));
+       if (arcn->nlen >= sizeof(arcn->name))
+               arcn->nlen = sizeof(arcn->name) - 1; /* XXX truncate? */
        arcn->org_name = ftent->fts_path;
        return(0);
 }
+
+/*
+ * getpathname()
+ *     Reads a pathname from stdin, handling NUL- or newline-termination.
+ * Return:
+ *     NULL at end of file, otherwise the NUL-terminated buffer.
+ */
+
+static char *
+getpathname(char *buf, int buflen)
+{
+       char *bp, *ep;
+       int ch, term;
+
+       if (zeroflag) {
+               /*
+                * Read a NUL-terminated pathname, being especially
+                * paranoid about proper termination and pathname length.
+                */
+               for (bp = buf, ep = buf + buflen; bp < ep; bp++) {
+                       if ((ch = getchar()) == EOF) {
+                               if (bp != buf)
+                                       paxwarn(1, "Ignoring unterminated "
+                                           "pathname at EOF");
+                               return(NULL);
+                       }
+                       if ((*bp = ch) == '\0')
+                               return(buf);
+               }
+               /* Too long - skip this path */
+               *--bp = '\0';
+               term = '\0';
+       } else {
+               if (fgets(buf, buflen, stdin) == NULL)
+                       return(NULL);
+               if ((bp = strchr(buf, '\n')) != NULL || feof(stdin)) {
+                       if (bp != NULL)
+                               *bp = '\0';
+                       return(buf);
+               }
+               /* Too long - skip this path */
+               term = '\n';
+       }
+       while ((ch = getchar()) != term && ch != EOF)
+               ;
+       paxwarn(1, "Ignoring too-long pathname: %s", buf);
+       return(NULL);
+}
diff --git a/ftree.h b/ftree.h
index 5ac8ff9b9b44aef31a37a681383e2a21ec4d03ee..9b4cffcc78f83aacf5d9a947d6cb96656f25eb98 100644 (file)
--- a/ftree.h
+++ b/ftree.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ftree.h,v 1.3 1996/10/27 06:45:11 downsj Exp $        */
+/*     $OpenBSD: ftree.h,v 1.5 2008/05/06 06:54:28 henning Exp $       */
 /*     $NetBSD: ftree.h,v 1.3 1995/03/21 09:07:23 cgd Exp $    */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -49,6 +45,7 @@
 typedef struct ftree {
        char            *fname;         /* file tree name */
        int             refcnt;         /* has tree had a selected file? */
+       int             newercnt;       /* skipped due to -u/-D */
        int             chflg;          /* change directory flag */
        struct ftree    *fow;           /* pointer to next entry on list */
 } FTREE;
index 6ff16f0a6eb7ded7a0ed827cdf321098644d6388..7e66f62cd0ac7e6d22175ad420c75126d97de1e6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: gen_subs.c,v 1.8 1997/09/01 18:29:51 deraadt Exp $    */
+/*     $OpenBSD: gen_subs.c,v 1.19 2007/04/04 21:55:10 millert Exp $   */
 /*     $NetBSD: gen_subs.c,v 1.5 1995/03/21 09:07:26 cgd Exp $ */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)gen_subs.c 8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)gen_subs.c   8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] = "$OpenBSD: gen_subs.c,v 1.8 1997/09/01 18:29:51 deraadt Exp $";
+static const char rcsid[] = "$OpenBSD: gen_subs.c,v 1.19 2007/04/04 21:55:10 millert Exp $";
 #endif
 #endif /* not lint */
 
@@ -56,6 +52,7 @@ static char rcsid[] = "$OpenBSD: gen_subs.c,v 1.8 1997/09/01 18:29:51 deraadt Ex
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <vis.h>
 #include "pax.h"
 #include "extern.h"
 
@@ -71,37 +68,33 @@ static char rcsid[] = "$OpenBSD: gen_subs.c,v 1.8 1997/09/01 18:29:51 deraadt Ex
 #define SIXMONTHS       ((DAYSPERNYEAR / 2) * SECSPERDAY)
 #define CURFRMT                "%b %e %H:%M"
 #define OLDFRMT                "%b %e  %Y"
-#ifndef UT_NAMESIZE
-#define UT_NAMESIZE    8
-#endif
-#define UT_GRPSIZE     6
+#define NAME_WIDTH     8
 
 /*
  * ls_list()
  *     list the members of an archive in ls format
  */
 
-#ifdef __STDC__
-void
-ls_list(register ARCHD *arcn, time_t now, FILE *fp)
-#else
 void
-ls_list(arcn, now, fp)
-       register ARCHD *arcn;
-       time_t now;
-       FILE *fp;
-#endif
+ls_list(ARCHD *arcn, time_t now, FILE *fp)
 {
-       register struct stat *sbp;
+       struct stat *sbp;
        char f_mode[MODELEN];
        char f_date[DATELEN];
-       char *timefrmt;
+       const char *timefrmt;
+       int term;
+
+       term = zeroflag ? '\0' : '\n';  /* path termination character */
 
        /*
         * if not verbose, just print the file name
         */
        if (!vflag) {
-               (void)fprintf(fp, "%s\n", arcn->name);
+               if (zeroflag)
+                       (void)fputs(arcn->name, fp);
+               else
+                       safe_print(arcn->name, fp);
+               (void)putc(term, fp);
                (void)fflush(fp);
                return;
        }
@@ -129,22 +122,22 @@ ls_list(arcn, now, fp)
         */
        if (strftime(f_date,DATELEN,timefrmt,localtime(&(sbp->st_mtime))) == 0)
                f_date[0] = '\0';
-       (void)fprintf(fp, "%s%2u %-*s %-*s ", f_mode, sbp->st_nlink,
-               UT_NAMESIZE, name_uid(sbp->st_uid, 1), UT_GRPSIZE,
-               name_gid(sbp->st_gid, 1));
+       (void)fprintf(fp, "%s%2u %-*.*s %-*.*s ", f_mode, sbp->st_nlink,
+               NAME_WIDTH, UT_NAMESIZE, name_uid(sbp->st_uid, 1),
+               NAME_WIDTH, UT_NAMESIZE, name_gid(sbp->st_gid, 1));
 
        /*
         * print device id's for devices, or sizes for other nodes
         */
        if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK))
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                (void)fprintf(fp, "%4u,%4u ", MAJOR(sbp->st_rdev),
 #              else
                (void)fprintf(fp, "%4lu,%4lu ", (unsigned long)MAJOR(sbp->st_rdev),
 #              endif
                    (unsigned long)MINOR(sbp->st_rdev));
        else {
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                (void)fprintf(fp, "%9lu ", sbp->st_size);
 #              else
                (void)fprintf(fp, "%9qu ", sbp->st_size);
@@ -154,34 +147,32 @@ ls_list(arcn, now, fp)
        /*
         * print name and link info for hard and soft links
         */
-       (void)fprintf(fp, "%s %s", f_date, arcn->name);
-       if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
-               (void)fprintf(fp, " == %s\n", arcn->ln_name);
-       else if (arcn->type == PAX_SLK)
-               (void)fprintf(fp, " => %s\n", arcn->ln_name);
-       else
-               (void)putc('\n', fp);
+       (void)fputs(f_date, fp);
+       (void)putc(' ', fp);
+       safe_print(arcn->name, fp);
+       if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
+               fputs(" == ", fp);
+               safe_print(arcn->ln_name, fp);
+       } else if (arcn->type == PAX_SLK) {
+               fputs(" -> ", fp);
+               safe_print(arcn->ln_name, fp);
+       }
+       (void)putc(term, fp);
        (void)fflush(fp);
        return;
 }
 
 /*
  * tty_ls()
- *     print a short summary of file to tty.
+ *     print a short summary of file to tty.
  */
 
-#ifdef __STDC__
-void
-ls_tty(register ARCHD *arcn)
-#else
 void
-ls_tty(arcn)
-       register ARCHD *arcn;
-#endif
+ls_tty(ARCHD *arcn)
 {
        char f_date[DATELEN];
        char f_mode[MODELEN];
-       char *timefrmt;
+       const char *timefrmt;
 
        if (ltmfrmt == NULL) {
                /*
@@ -205,37 +196,23 @@ ls_tty(arcn)
        return;
 }
 
-/*
- * l_strncpy()
- *     copy src to dest up to len chars (stopping at first '\0').
- *     when src is shorter than len, pads to len with '\0'. 
- * Return:
- *     number of chars copied. (Note this is a real performance win over
- *     doing a strncpy(), a strlen(), and then a possible memset())
- */
-
-#ifdef __STDC__
-int
-l_strncpy(register char *dest, register char *src, int len)
-#else
-int
-l_strncpy(dest, src, len)
-       register char *dest;
-       register char *src;
-       int len;
-#endif
+void
+safe_print(const char *str, FILE *fp)
 {
-       register char *stop;
-       register char *start;
-
-       stop = dest + len;
-       start = dest;
-       while ((dest < stop) && (*src != '\0'))
-               *dest++ = *src++;
-       len = dest - start;
-       while (dest < stop)
-               *dest++ = '\0';
-       return(len);
+       char visbuf[5];
+       const char *cp;
+
+       /*
+        * if printing to a tty, use vis(3) to print special characters.
+        */
+       if (isatty(fileno(fp))) {
+               for (cp = str; *cp; cp++) {
+                       (void)vis(visbuf, cp[0], VIS_CSTYLE, cp[1]);
+                       (void)fputs(visbuf, fp);
+               }
+       } else {
+               (void)fputs(str, fp);
+       }
 }
 
 /*
@@ -248,18 +225,10 @@ l_strncpy(dest, src, len)
  *     unsigned long value
  */
 
-#ifdef __STDC__
 u_long
-asc_ul(register char *str, int len, register int base)
-#else
-u_long
-asc_ul(str, len, base)
-       register char *str;
-       int len;
-       register int base;
-#endif
+asc_ul(char *str, int len, int base)
 {
-       register char *stop;
+       char *stop;
        u_long tval = 0;
 
        stop = str + len;
@@ -286,7 +255,7 @@ asc_ul(str, len, base)
                                break;
                }
        } else {
-               while ((str < stop) && (*str >= '0') && (*str <= '7'))
+               while ((str < stop) && (*str >= '0') && (*str <= '7'))
                        tval = (tval << 3) + (*str++ - '0');
        }
        return(tval);
@@ -299,19 +268,10 @@ asc_ul(str, len, base)
  *     NOTE: the string created is NOT TERMINATED.
  */
 
-#ifdef __STDC__
 int
-ul_asc(u_long val, register char *str, register int len, register int base)
-#else
-int
-ul_asc(val, str, len, base)
-       u_long val;
-       register char *str;
-       register int len;
-       register int base;
-#endif
+ul_asc(u_long val, char *str, int len, int base)
 {
-       register char *pt;
+       char *pt;
        u_long digit;
 
        /*
@@ -351,7 +311,7 @@ ul_asc(val, str, len, base)
        return(0);
 }
 
-#ifndef NET2_STAT
+#ifndef LONG_OFF_T
 /*
  * asc_uqd()
  *     convert hex/octal character string into a u_quad_t. We do not have to
@@ -362,18 +322,10 @@ ul_asc(val, str, len, base)
  *     u_quad_t value
  */
 
-#ifdef __STDC__
-u_quad_t
-asc_uqd(register char *str, int len, register int base)
-#else
 u_quad_t
-asc_uqd(str, len, base)
-       register char *str;
-       int len;
-       register int base;
-#endif
+asc_uqd(char *str, int len, int base)
 {
-       register char *stop;
+       char *stop;
        u_quad_t tval = 0;
 
        stop = str + len;
@@ -400,7 +352,7 @@ asc_uqd(str, len, base)
                                break;
                }
        } else {
-               while ((str < stop) && (*str >= '0') && (*str <= '7'))
+               while ((str < stop) && (*str >= '0') && (*str <= '7'))
                        tval = (tval << 3) + (*str++ - '0');
        }
        return(tval);
@@ -413,19 +365,10 @@ asc_uqd(str, len, base)
  *     NOTE: the string created is NOT TERMINATED.
  */
 
-#ifdef __STDC__
-int
-uqd_asc(u_quad_t val, register char *str, register int len, register int base)
-#else
 int
-uqd_asc(val, str, len, base)
-       u_quad_t val;
-       register char *str;
-       register int len;
-       register int base;
-#endif
+uqd_asc(u_quad_t val, char *str, int len, int base)
 {
-       register char *pt;
+       char *pt;
        u_quad_t digit;
 
        /*
@@ -465,3 +408,25 @@ uqd_asc(val, str, len, base)
        return(0);
 }
 #endif
+
+/*
+ * Copy at max min(bufz, fieldsz) chars from field to buf, stopping
+ * at the first NUL char. NUL terminate buf if there is room left.
+ */
+size_t
+fieldcpy(char *buf, size_t bufsz, const char *field, size_t fieldsz)
+{
+       char *p = buf;
+       const char *q = field;
+       size_t i = 0;
+
+       if (fieldsz > bufsz)
+               fieldsz = bufsz;
+       while (i < fieldsz && *q != '\0') {
+               *p++ = *q++;
+               i++;
+       }
+       if (i < bufsz)
+               *p = '\0';
+       return(i);
+}
index 7da7f85e1aabe12ef9ddc15e98093b9aebdca56c..45fdbf29fbc92546da64c0b37543fa581e5e80ef 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: getoldopt.c,v 1.3 1997/09/01 18:29:52 deraadt Exp $   */
+/*     $OpenBSD: getoldopt.c,v 1.8 2003/07/02 21:19:33 deraadt Exp $   */
 /*     $NetBSD: getoldopt.c,v 1.3 1995/03/21 09:07:28 cgd Exp $        */
 
 /*
@@ -7,25 +7,24 @@
  * otherwise, it uses the old rules used by tar, dump, and ps.
  *
  * Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu) and placed
- * in the Pubic Domain for your edification and enjoyment.
+ * in the Public Domain for your edification and enjoyment.
  */
 
 #ifndef lint
-static char rcsid[] = "$OpenBSD: getoldopt.c,v 1.3 1997/09/01 18:29:52 deraadt Exp $";
+static const char rcsid[] = "$OpenBSD: getoldopt.c,v 1.8 2003/07/02 21:19:33 deraadt Exp $";
 #endif /* not lint */
 
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include "pax.h"
+#include "extern.h"
 
 int
-getoldopt(argc, argv, optstring)
-       int     argc;
-       char    **argv;
-       char    *optstring;
+getoldopt(int argc, char **argv, const char *optstring)
 {
-       extern char     *optarg;        /* Points to next arg */
-       extern int      optind;         /* Global argv index */
        static char     *key;           /* Points to next keyletter */
        static char     use_getopt;     /* !=0 if argv[1][0] was '-' */
        char            c;
@@ -34,7 +33,8 @@ getoldopt(argc, argv, optstring)
        optarg = NULL;
 
        if (key == NULL) {              /* First time */
-               if (argc < 2) return EOF;
+               if (argc < 2)
+                       return (-1);
                key = argv[1];
                if (*key == '-')
                        use_getopt++;
@@ -43,18 +43,18 @@ getoldopt(argc, argv, optstring)
        }
 
        if (use_getopt)
-               return getopt(argc, argv, optstring);
+               return (getopt(argc, argv, optstring));
 
        c = *key++;
        if (c == '\0') {
                key--;
-               return EOF;
+               return (-1);
        }
        place = strchr(optstring, c);
 
        if (place == NULL || c == ':') {
                fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
-               return('?');
+               return ('?');
        }
 
        place++;
@@ -65,9 +65,9 @@ getoldopt(argc, argv, optstring)
                } else {
                        fprintf(stderr, "%s: %c argument missing\n",
                                argv[0], c);
-                       return('?');
+                       return ('?');
                }
        }
 
-       return(c);
+       return (c);
 }
index 4aea6004423b0375fbcbb5898d2b52759cce786e..fa198891e54540d81c5c95c0c22f59a88be1972b 100644 (file)
--- a/options.c
+++ b/options.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: options.c,v 1.34 1998/09/20 02:22:22 millert Exp $    */
+/*     $OpenBSD: options.c,v 1.70 2008/06/11 00:49:08 pvalchev Exp $   */
 /*     $NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg Exp $  */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)options.c  8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)options.c    8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: options.c,v 1.34 1998/09/20 02:22:22 millert Exp $";
+static const char rcsid[] = "$OpenBSD: options.c,v 1.70 2008/06/11 00:49:08 pvalchev Exp $";
 #endif
 #endif /* not lint */
 
@@ -72,19 +68,27 @@ static char flgch[] = FLGCH;        /* list of all possible flags */
 static OPLIST *ophead = NULL;  /* head for format specific options -x */
 static OPLIST *optail = NULL;  /* option tail */
 
-static int no_op __P((void));
-static void printflg __P((unsigned int));
-static int c_frmt __P((const void *, const void *));
-static off_t str_offt __P((char *));
-static void pax_options __P((register int, register char **));
-static void pax_usage __P((void));
-static void tar_options __P((register int, register char **));
-static void tar_usage __P((void));
-static void cpio_options __P((register int, register char **));
-static void cpio_usage __P((void));
+static int no_op(void);
+static void printflg(unsigned int);
+static int c_frmt(const void *, const void *);
+static off_t str_offt(char *);
+static char *getline(FILE *fp);
+static void pax_options(int, char **);
+static void pax_usage(void);
+static void tar_options(int, char **);
+static void tar_usage(void);
+static void cpio_options(int, char **);
+static void cpio_usage(void);
+
+/* errors from getline */
+#define GETLINE_FILE_CORRUPT 1
+#define GETLINE_OUT_OF_MEM 2
+static int getline_error;
+
 
 #define GZIP_CMD       "gzip"          /* command to run as gzip */
 #define COMPRESS_CMD   "compress"      /* command to run as compress */
+#define BZIP2_CMD      "bzip2"         /* command to run as bzip2 */
 
 /*
  *     Format specific routine table - MUST BE IN SORTED ORDER BY NAME
@@ -135,26 +139,24 @@ FSUB fsub[] = {
 
 /*
  * ford is the archive search order used by get_arc() to determine what kind
- * of archive we are dealing with. This helps to properly id  archive formats
+ * of archive we are dealing with. This helps to properly id archive formats
  * some formats may be subsets of others....
  */
 int ford[] = {5, 4, 3, 2, 1, 0, -1 };
 
+/*
+ * Do we have -C anywhere?
+ */
+int havechd = 0;
+
 /*
  * options()
  *     figure out if we are pax, tar or cpio. Call the appropriate options
  *     parser
  */
 
-#ifdef __STDC__
-void
-options(register int argc, register char **argv)
-#else
 void
-options(argc, argv)
-       register int argc;
-       register char **argv;
-#endif
+options(int argc, char **argv)
 {
 
        /*
@@ -165,15 +167,18 @@ options(argc, argv)
        else
                argv0 = argv[0];
 
-       if (strcmp(NM_TAR, argv0) == 0)
-               return(tar_options(argc, argv));
-       else if (strcmp(NM_CPIO, argv0) == 0)
-               return(cpio_options(argc, argv));
+       if (strcmp(NM_TAR, argv0) == 0) {
+               tar_options(argc, argv);
+               return;
+       } else if (strcmp(NM_CPIO, argv0) == 0) {
+               cpio_options(argc, argv);
+               return;
+       }
        /*
         * assume pax as the default
         */
        argv0 = NM_PAX;
-       return(pax_options(argc, argv));
+       pax_options(argc, argv);
 }
 
 /*
@@ -182,30 +187,21 @@ options(argc, argv)
  *     the user specified a legal set of flags. If not, complain and exit
  */
 
-#ifdef __STDC__
-static void
-pax_options(register int argc, register char **argv)
-#else
 static void
-pax_options(argc, argv)
-       register int argc;
-       register char **argv;
-#endif
+pax_options(int argc, char **argv)
 {
-       register int c;
-       register int i;
+       int c;
+       int i;
        unsigned int flg = 0;
        unsigned int bflg = 0;
-       register char *pt;
+       char *pt;
        FSUB tmp;
-       extern char *optarg;
-       extern int optind;
 
        /*
         * process option flags
         */
-       while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:zB:DE:G:HLPT:U:XYZ"))
-           != EOF) {
+       while ((c=getopt(argc,argv,"ab:cdf:ijklno:p:rs:tuvwx:zB:DE:G:HLOPT:U:XYZ0"))
+           != -1) {
                switch (c) {
                case 'a':
                        /*
@@ -251,6 +247,12 @@ pax_options(argc, argv)
                        iflag = 1;
                        flg |= IF;
                        break;
+               case 'j':
+                       /*
+                        * use bzip2.  Non standard option.
+                        */
+                       gzip_program = BZIP2_CMD;
+                       break;
                case 'k':
                        /*
                         * do not clobber files that exist
@@ -285,7 +287,7 @@ pax_options(argc, argv)
                         * specify file characteristic options
                         */
                        for (pt = optarg; *pt != '\0'; ++pt) {
-                               switch(*pt) {
+                               switch (*pt) {
                                case 'a':
                                        /*
                                         * do not preserve access time
@@ -316,7 +318,7 @@ pax_options(argc, argv)
                                        break;
                                case 'p':
                                        /*
-                                        * preserver file mode bits
+                                        * preserve file mode bits
                                         */
                                        pmode = 1;
                                        break;
@@ -392,7 +394,6 @@ pax_options(argc, argv)
                        /*
                         * use gzip.  Non standard option.
                         */
-                       zflag = 1;
                        gzip_program = GZIP_CMD;
                        break;
                case 'B':
@@ -458,6 +459,12 @@ pax_options(argc, 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)
@@ -510,6 +517,14 @@ pax_options(argc, argv)
                        Zflag = 1;
                        flg |= CZF;
                        break;
+               case '0':
+                       /*
+                        * Use \0 as pathname terminator.
+                        * (For use with the -print0 option of find(1).)
+                        */
+                       zeroflag = 1;
+                       flg |= C0F;
+                       break;
                default:
                        pax_usage();
                        break;
@@ -590,19 +605,19 @@ pax_options(argc, argv)
  *     the user specified a legal set of flags. If not, complain and exit
  */
 
-#ifdef __STDC__
-static void
-tar_options(register int argc, register char **argv)
-#else
 static void
-tar_options(argc, argv)
-       register int argc;
-       register char **argv;
-#endif
+tar_options(int argc, char **argv)
 {
-       register int c;
+       int c;
        int fstdin = 0;
        int Oflag = 0;
+       int nincfiles = 0;
+       int incfiles_max = 0;
+       struct incfile {
+               char *file;
+               char *dir;
+       };
+       struct incfile *incfiles = NULL;
 
        /*
         * Set default values.
@@ -613,9 +628,8 @@ tar_options(argc, argv)
         * process option flags
         */
        while ((c = getoldopt(argc, argv,
-           "b:cef:hmopruts:vwxzBC:HLOPXZ014578"))
-           != EOF) {
-               switch(c) {
+           "b:cef:hjmopqruts:vwxzBC:HI:LOPXZ014578")) != -1) {
+               switch (c) {
                case 'b':
                        /*
                         * specify blocksize in 512-byte blocks
@@ -659,18 +673,24 @@ tar_options(argc, argv)
                         */
                        Lflag = 1;
                        break;
+               case 'j':
+                       /*
+                        * use bzip2.  Non standard option.
+                        */
+                       gzip_program = BZIP2_CMD;
+                       break;
                case 'm':
                        /*
                         * do not preserve modification time
                         */
                        pmtime = 0;
                        break;
-               case 'o':
-                       if (opt_add("write_opt=nodir") < 0)
-                               tar_usage();
                case 'O':
                        Oflag = 1;
                        break;
+               case 'o':
+                       Oflag = 2;
+                       break;
                case 'p':
                        /*
                         * preserve uid/gid and file mode, regardless of umask
@@ -678,6 +698,12 @@ tar_options(argc, argv)
                        pmode = 1;
                        pids = 1;
                        break;
+               case 'q':
+                       /*
+                        * select first match for a pattern only
+                        */
+                       nflag = 1;
+                       break;
                case 'r':
                case 'u':
                        /*
@@ -724,7 +750,6 @@ tar_options(argc, argv)
                        /*
                         * use gzip.  Non standard option.
                         */
-                       zflag = 1;
                        gzip_program = GZIP_CMD;
                        break;
                case 'B':
@@ -733,6 +758,7 @@ tar_options(argc, argv)
                         */
                        break;
                case 'C':
+                       havechd++;
                        chdname = optarg;
                        break;
                case 'H':
@@ -741,6 +767,20 @@ tar_options(argc, argv)
                         */
                        Hflag = 1;
                        break;
+               case 'I':
+                       if (++nincfiles > incfiles_max) {
+                               incfiles_max = nincfiles + 3;
+                               incfiles = realloc(incfiles,
+                                   sizeof(*incfiles) * incfiles_max);
+                               if (incfiles == NULL) {
+                                       paxwarn(0, "Unable to allocate space "
+                                           "for option list");
+                                       exit(1);
+                               }
+                       }
+                       incfiles[nincfiles - 1].file = optarg;
+                       incfiles[nincfiles - 1].dir = chdname;
+                       break;
                case 'L':
                        /*
                         * follow symlinks
@@ -763,7 +803,6 @@ tar_options(argc, argv)
                        /*
                         * use compress.
                         */
-                       zflag = 1;
                        gzip_program = COMPRESS_CMD;
                        break;
                case '0':
@@ -798,21 +837,10 @@ tar_options(argc, argv)
        else
                listf = stdout;
 
-       /* Traditional tar behaviour (pax wants to read filelist from stdin) */
-       if ((act == ARCHIVE || act == APPND) && argc == 0)
+       /* Traditional tar behaviour (pax wants to read file list from stdin) */
+       if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
                exit(0);
 
-       /*
-        * if we are writing (ARCHIVE) specify tar, otherwise run like pax
-        * (unless -o specified)
-        */
-       if (act == ARCHIVE || act == APPND)
-               frmt = &(fsub[Oflag ? F_OTAR : F_TAR]);
-       else if (Oflag) {
-               paxwarn(1, "The -O/-o options are only valid when writing an archive");
-               tar_usage();            /* only valid when writing */
-       }
-
        /*
         * process the args as they are interpreted by the operation mode
         */
@@ -822,22 +850,62 @@ tar_options(argc, argv)
        default:
                {
                        int sawpat = 0;
+                       char *file, *dir;
 
-                       while (*argv != NULL) {
-                               if (strcmp(*argv, "-C") == 0) {
-                                       if(*++argv == NULL)
+                       while (nincfiles || *argv != NULL) {
+                               /*
+                                * If we queued up any include files,
+                                * pull them in now.  Otherwise, check
+                                * for -I and -C positional flags.
+                                * Anything else must be a file to
+                                * extract.
+                                */
+                               if (nincfiles) {
+                                       file = incfiles->file;
+                                       dir = incfiles->dir;
+                                       incfiles++;
+                                       nincfiles--;
+                               } else if (strcmp(*argv, "-I") == 0) {
+                                       if (*++argv == NULL)
+                                               break;
+                                       file = *argv++;
+                                       dir = chdname;
+                               } else
+                                       file = NULL;
+                               if (file != NULL) {
+                                       FILE *fp;
+                                       char *str;
+
+                                       if (strcmp(file, "-") == 0)
+                                               fp = stdin;
+                                       else if ((fp = fopen(file, "r")) == NULL) {
+                                               paxwarn(1, "Unable to open file '%s' for read", file);
+                                               tar_usage();
+                                       }
+                                       while ((str = getline(fp)) != NULL) {
+                                               if (pat_add(str, dir) < 0)
+                                                       tar_usage();
+                                               sawpat = 1;
+                                       }
+                                       if (strcmp(file, "-") != 0)
+                                               fclose(fp);
+                                       if (getline_error) {
+                                               paxwarn(1, "Problem with file '%s'", file);
+                                               tar_usage();
+                                       }
+                               } else if (strcmp(*argv, "-C") == 0) {
+                                       if (*++argv == NULL)
                                                break;
                                        chdname = *argv++;
-
-                                       continue;
-                               }
-                               if (pat_add(*argv++, chdname) < 0)
+                                       havechd++;
+                               } else if (pat_add(*argv++, chdname) < 0)
                                        tar_usage();
-                               sawpat++;
+                               else
+                                       sawpat = 1;
                        }
                        /*
                         * if patterns were added, we are doing chdir()
-                        * on a file-by-file basis, else, just one 
+                        * on a file-by-file basis, else, just one
                         * global chdir (if any) after opening input.
                         */
                        if (sawpat > 0)
@@ -846,21 +914,72 @@ tar_options(argc, argv)
                break;
        case ARCHIVE:
        case APPND:
+               frmt = &(fsub[Oflag ? F_OTAR : F_TAR]);
+
+               if (Oflag == 2 && opt_add("write_opt=nodir") < 0)
+                       tar_usage();
+
                if (chdname != NULL) {  /* initial chdir() */
                        if (ftree_add(chdname, 1) < 0)
                                tar_usage();
                }
 
-               while (*argv != NULL) {
-                       if (!strcmp(*argv, "-C")) {
+               while (nincfiles || *argv != NULL) {
+                       char *file, *dir;
+
+                       /*
+                        * If we queued up any include files, pull them in
+                        * now.  Otherwise, check for -I and -C positional
+                        * flags.  Anything else must be a file to include
+                        * in the archive.
+                        */
+                       if (nincfiles) {
+                               file = incfiles->file;
+                               dir = incfiles->dir;
+                               incfiles++;
+                               nincfiles--;
+                       } else if (strcmp(*argv, "-I") == 0) {
                                if (*++argv == NULL)
                                        break;
-                               if (ftree_add(*argv++, 1) < 0)
+                               file = *argv++;
+                               dir = NULL;
+                       } else
+                               file = NULL;
+                       if (file != NULL) {
+                               FILE *fp;
+                               char *str;
+
+                               /* Set directory if needed */
+                               if (dir) {
+                                       if (ftree_add(dir, 1) < 0)
+                                               tar_usage();
+                               }
+
+                               if (strcmp(file, "-") == 0)
+                                       fp = stdin;
+                               else if ((fp = fopen(file, "r")) == NULL) {
+                                       paxwarn(1, "Unable to open file '%s' for read", file);
                                        tar_usage();
-                       } else {
-                               if (ftree_add(*argv++, 0) < 0)
+                               }
+                               while ((str = getline(fp)) != NULL) {
+                                       if (ftree_add(str, 0) < 0)
+                                               tar_usage();
+                               }
+                               if (strcmp(file, "-") != 0)
+                                       fclose(fp);
+                               if (getline_error) {
+                                       paxwarn(1, "Problem with file '%s'",
+                                           file);
                                        tar_usage();
-                       }
+                               }
+                       } else if (strcmp(*argv, "-C") == 0) {
+                               if (*++argv == NULL)
+                                       break;
+                               if (ftree_add(*argv++, 1) < 0)
+                                       tar_usage();
+                               havechd++;
+                       } else if (ftree_add(*argv++, 0) < 0)
+                               tar_usage();
                }
                /*
                 * no read errors allowed on updates/append operation!
@@ -875,12 +994,14 @@ tar_options(argc, argv)
        }
 }
 
+int mkpath(char *);
+
 int
 mkpath(path)
        char *path;
 {
        struct stat sb;
-       register char *slash;
+       char *slash;
        int done = 0;
 
        slash = path;
@@ -914,18 +1035,10 @@ mkpath(path)
  *     the user specified a legal set of flags. If not, complain and exit
  */
 
-#ifdef __STDC__
-static void
-cpio_options(register int argc, register char **argv)
-#else
 static void
-cpio_options(argc, argv)
-       register int argc;
-       register char **argv;
-#endif
+cpio_options(int argc, char **argv)
 {
-       register int c, i;
-       size_t len;
+       int c, i;
        char *str;
        FSUB tmp;
        FILE *fp;
@@ -938,7 +1051,7 @@ cpio_options(argc, argv)
        dflag = 1;
        act = -1;
        nodirs = 1;
-       while ((c=getopt(argc,argv,"abcdfiklmoprstuvzABC:E:F:H:I:LO:SZ6")) != EOF)
+       while ((c=getopt(argc,argv,"abcdfijklmoprstuvzABC:E:F:H:I:LO:SZ6")) != -1)
                switch (c) {
                        case 'a':
                                /*
@@ -975,6 +1088,12 @@ cpio_options(argc, argv)
                                 */
                                act = EXTRACT;
                                break;
+                       case 'j':
+                               /*
+                                * use bzip2.  Non standard option.
+                                */
+                               gzip_program = BZIP2_CMD;
+                               break;
                        case 'k':
                                break;
                        case 'l':
@@ -1036,7 +1155,6 @@ cpio_options(argc, argv)
                                /*
                                 * use gzip.  Non standard option.
                                 */
-                               zflag = 1;
                                gzip_program = GZIP_CMD;
                                break;
                        case 'A':
@@ -1065,11 +1183,14 @@ cpio_options(argc, argv)
                                        paxwarn(1, "Unable to open file '%s' for read", optarg);
                                        cpio_usage();
                                }
-                               while ((str = fgetln(fp, &len)) != NULL) {
-                                       str[len - 1] = '\0';
+                               while ((str = getline(fp)) != NULL) {
                                        pat_add(str, NULL);
                                }
                                fclose(fp);
+                               if (getline_error) {
+                                       paxwarn(1, "Problem with file '%s'", optarg);
+                                       cpio_usage();
+                               }
                                break;
                        case 'F':
                        case 'I':
@@ -1116,7 +1237,6 @@ cpio_options(argc, argv)
                                /*
                                 * use compress.  Non standard option.
                                 */
-                               zflag = 1;
                                gzip_program = COMPRESS_CMD;
                                break;
                        case '6':
@@ -1162,9 +1282,12 @@ cpio_options(argc, argv)
                         * no read errors allowed on updates/append operation!
                         */
                        maxflt = 0;
-                       while ((str = fgetln(stdin, &len)) != NULL) {
-                               str[len - 1] = '\0';
-                               ftree_add(strdup(str), NULL);
+                       while ((str = getline(stdin)) != NULL) {
+                               ftree_add(str, 0);
+                       }
+                       if (getline_error) {
+                               paxwarn(1, "Problem while reading stdin");
+                               cpio_usage();
                        }
                        break;
                default:
@@ -1178,14 +1301,8 @@ cpio_options(argc, argv)
  *     print out those invalid flag sets found to the user
  */
 
-#ifdef __STDC__
 static void
 printflg(unsigned int flg)
-#else
-static void
-printflg(flg)
-       unsigned int flg;
-#endif
 {
        int nxt;
        int pos = 0;
@@ -1205,15 +1322,8 @@ printflg(flg)
  *     by the user
  */
 
-#ifdef __STDC__
 static int
 c_frmt(const void *a, const void *b)
-#else
-static int
-c_frmt(a, b)
-       void *a;
-       void *b;
-#endif
 {
        return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
 }
@@ -1226,13 +1336,8 @@ c_frmt(a, b)
  *     pointer to next OPLIST entry or NULL (end of list).
  */
 
-#ifdef __STDC__
 OPLIST *
 opt_next(void)
-#else
-OPLIST *
-opt_next()
-#endif
 {
        OPLIST *opt;
 
@@ -1247,15 +1352,10 @@ opt_next()
  *     when the format does not support options.
  */
 
-#ifdef __STDC__
 int
 bad_opt(void)
-#else
-int
-bad_opt()
-#endif
 {
-       register OPLIST *opt;
+       OPLIST *opt;
 
        if (ophead == NULL)
                return(0);
@@ -1273,34 +1373,29 @@ bad_opt()
  * opt_add()
  *     breaks the value supplied to -o into a option name and value. options
  *     are given to -o in the form -o name-value,name=value
- *     mulltiple -o may be specified.
+ *     multiple -o may be specified.
  * Return:
  *     0 if format in name=value format, -1 if -o is passed junk
  */
 
-#ifdef __STDC__
-int
-opt_add(register char *str)
-#else
 int
-opt_add(str)
-       register char *str;
-#endif
+opt_add(const char *str)
 {
-       register OPLIST *opt;
-       register char *frpt;
-       register char *pt;
-       register char *endpt;
+       OPLIST *opt;
+       char *frpt;
+       char *pt;
+       char *endpt;
+       char *dstr;
 
        if ((str == NULL) || (*str == '\0')) {
                paxwarn(0, "Invalid option name");
                return(-1);
        }
-       if ((str = strdup(str)) == NULL) {
+       if ((dstr = strdup(str)) == NULL) {
                paxwarn(0, "Unable to allocate space for option list");
                return(-1);
        }
-       frpt = endpt = str;
+       frpt = endpt = dstr;
 
        /*
         * break into name and values pieces and stuff each one into a
@@ -1312,12 +1407,12 @@ opt_add(str)
                        *endpt = '\0';
                if ((pt = strchr(frpt, '=')) == NULL) {
                        paxwarn(0, "Invalid options format");
-                       free(str);
+                       free(dstr);
                        return(-1);
                }
                if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
                        paxwarn(0, "Unable to allocate space for option list");
-                       free(str);
+                       free(dstr);
                        return(-1);
                }
                *pt++ = '\0';
@@ -1347,25 +1442,19 @@ opt_add(str)
  *     4) A positive decimal number followed by a m (mult by 512).
  *     5) A positive decimal number followed by a w (mult by sizeof int)
  *     6) Two or more positive decimal numbers (with/without k,b or w).
- *        seperated by x (also * for backwards compatibility), specifying
+ *        separated by x (also * for backwards compatibility), specifying
  *        the product of the indicated values.
  * Return:
  *     0 for an error, a positive value o.w.
  */
 
-#ifdef __STDC__
 static off_t
 str_offt(char *val)
-#else
-static off_t
-str_offt(val)
-       char *val;
-#endif
 {
        char *expr;
        off_t num, t;
 
-#      ifdef NET2_STAT
+#      ifdef LONG_OFF_T
        num = strtol(val, &expr, 0);
        if ((num == LONG_MAX) || (num <= 0) || (expr == val))
 #      else
@@ -1374,7 +1463,7 @@ str_offt(val)
 #      endif
                return(0);
 
-       switch(*expr) {
+       switch (*expr) {
        case 'b':
                t = num;
                num *= 512;
@@ -1405,7 +1494,7 @@ str_offt(val)
                break;
        }
 
-       switch(*expr) {
+       switch (*expr) {
                case '\0':
                        break;
                case '*':
@@ -1421,6 +1510,29 @@ str_offt(val)
        return(num);
 }
 
+char *
+getline(FILE *f)
+{
+       char *name, *temp;
+       size_t len;
+
+       name = fgetln(f, &len);
+       if (!name) {
+               getline_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
+               return(0);
+       }
+       if (name[len-1] != '\n')
+               len++;
+       temp = malloc(len);
+       if (!temp) {
+               getline_error = GETLINE_OUT_OF_MEM;
+               return(0);
+       }
+       memcpy(temp, name, len-1);
+       temp[len-1] = 0;
+       return(temp);
+}
+                       
 /*
  * no_op()
  *     for those option functions where the archive format has nothing to do.
@@ -1428,13 +1540,8 @@ str_offt(val)
  *     0
  */
 
-#ifdef __STDC__
 static int
 no_op(void)
-#else
-static int
-no_op()
-#endif
 {
        return(0);
 }
@@ -1444,37 +1551,20 @@ no_op()
  *     print the usage summary to the user
  */
 
-#ifdef __STDC__
 void
 pax_usage(void)
-#else
-void
-pax_usage()
-#endif
 {
-       (void)fputs("usage: pax [-cdnv] [-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 [-cdiknuvDYZ] [-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 [-dituvHLPX] [-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("[-p string] ... [-s replstr] ...", stderr);
-       (void)fputs("\n           [-U user] ... [-G group] ... ", stderr);
-       (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
-       (void)fputs("\n           [file ...] directory\n", stderr);
+       (void)fputs(
+           "usage: pax [-0cdjnOvz] [-E limit] [-f archive] [-G group] [-s replstr]\n"
+           "           [-T range] [-U user] [pattern ...]\n"
+           "       pax -r [-0cDdijknOuvYZz] [-E limit] [-f archive] [-G group] [-o options]\n"
+           "           [-p string] [-s replstr] [-T range] [-U user] [pattern ...]\n"
+           "       pax -w [-0adHijLOPtuvXz] [-B bytes] [-b blocksize] [-f archive]\n"
+           "           [-G group] [-o options] [-s replstr] [-T range] [-U user]\n"
+           "           [-x format] [file ...]\n"
+           "       pax -rw [-0DdHikLlnOPtuvXYZ] [-G group] [-p string] [-s replstr]\n"
+           "           [-T range] [-U user] [file ...] directory\n",
+           stderr);
        exit(1);
 }
 
@@ -1483,17 +1573,15 @@ pax_usage()
  *     print the usage summary to the user
  */
 
-#ifdef __STDC__
 void
 tar_usage(void)
-#else
-void
-tar_usage()
-#endif
 {
-       (void)fputs("usage: tar -{txru}[cevfbmopswzBHLPXZ014578] [tapefile] ",
-                stderr);
-       (void)fputs("[blocksize] [replstr] [-C directory] file1 file2...\n",
+       (void)fputs(
+           "usage: tar {crtux}[014578befHhjLmOoPpqsvwXZz]\n"
+           "           [blocking-factor | archive | replstr] [-C directory] [-I file]\n"
+           "           [file ...]\n"
+           "       tar {-crtux} [-014578eHhjLmOoPpqvwXZz] [-b blocking-factor]\n"
+           "           [-C directory] [-f archive] [-I file] [-s replstr] [file ...]\n",
            stderr);
        exit(1);
 }
@@ -1503,18 +1591,15 @@ tar_usage()
  *     print the usage summary to the user
  */
 
-#ifdef __STDC__
 void
 cpio_usage(void)
-#else
-void
-cpio_usage()
-#endif
 {
-       (void)fputs("usage: cpio -o [-aABcLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr);
-       (void)fputs("               [-F archive] < name-list [> archive]\n", stderr);
-       (void)fputs("       cpio -i [-bBcdfmnrsStuvVzZ6] [-C bytes] [-E file] [-H format]\n", stderr);
-       (void)fputs("               [-I archive] [-F archive] [pattern...] [< archive]\n", stderr);
-       (void)fputs("       cpio -p [-adlLmuvV] destination-directory < name-list\n", stderr);
+       (void)fputs(
+           "usage: cpio -o [-AaBcjLvZz] [-C bytes] [-F archive] [-H format]\n"
+           "            [-O archive] < name-list [> archive]\n"
+           "       cpio -i [-6BbcdfjmrSstuvZz] [-C bytes] [-E file] [-F archive] [-H format]\n"
+           "            [-I archive] [pattern ...] [< archive]\n"
+           "       cpio -p [-adLlmuv] destination-directory < name-list\n",
+           stderr);
        exit(1);
 }
index d45f54afb871530152534bd02727874e741ec980..30d0e89de8659db10e0c38d1ff1e1ac82b275fc7 100644 (file)
--- a/options.h
+++ b/options.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: options.h,v 1.2 1996/06/23 14:20:37 deraadt Exp $     */
+/*     $OpenBSD: options.h,v 1.4 2003/06/13 17:51:14 millert Exp $     */
 /*     $NetBSD: options.h,v 1.3 1995/03/21 09:07:32 cgd Exp $  */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
 #define        CXF     0x08000000
 #define        CYF     0x10000000      /* nonstandard extension */
 #define        CZF     0x20000000      /* nonstandard extension */
+#define        C0F     0x40000000      /* nonstandard extension */
 
 /*
  * ascii string indexed by bit position above (alter the above and you must
  * alter this string) used to tell the user what flags caused us to complain
  */
-#define FLGCH  "abcdfiklnoprstuvwxBDEGHLPTUXYZ"
+#define FLGCH  "abcdfiklnoprstuvwxBDEGHLPTUXYZ0"
 
 /*
  * legal pax operation bit patterns
index a93809f743692c9e4b1a2a9cdc60184caba81b17..ff79582ce24a34d81f14c1082263478e24c1ee0b 100644 (file)
--- a/pat_rep.c
+++ b/pat_rep.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pat_rep.c,v 1.11 1997/09/01 18:29:56 deraadt Exp $    */
+/*     $OpenBSD: pat_rep.c,v 1.30 2005/08/05 08:30:10 djm Exp $        */
 /*     $NetBSD: pat_rep.c,v 1.4 1995/03/21 09:07:33 cgd Exp $  */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)pat_rep.c  8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)pat_rep.c    8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: pat_rep.c,v 1.11 1997/09/01 18:29:56 deraadt Exp $";
+static const char rcsid[] = "$OpenBSD: pat_rep.c,v 1.30 2005/08/05 08:30:10 djm Exp $";
 #endif
 #endif /* not lint */
 
@@ -55,11 +51,7 @@ static char rcsid[] = "$OpenBSD: pat_rep.c,v 1.11 1997/09/01 18:29:56 deraadt Ex
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
-#ifdef NET2_REGEX
-#include <regexp.h>
-#else
 #include <regex.h>
-#endif
 #include "pax.h"
 #include "pat_rep.h"
 #include "extern.h"
@@ -77,23 +69,19 @@ static PATTERN *pattail = NULL;             /* file pattern match list tail */
 static REPLACE *rephead = NULL;                /* replacement string list head */
 static REPLACE *reptail = NULL;                /* replacement string list tail */
 
-static int rep_name __P((char *, int *, int));
-static int tty_rename __P((register ARCHD *));
-static int fix_path __P((char *, int *, char *, int));
-static int fn_match __P((register char *, register char *, char **));
-static char * range_match __P((register char *, register int));
-#ifdef NET2_REGEX
-static int resub __P((regexp *, char *, char *, register char *));
-#else
-static int resub __P((regex_t *, regmatch_t *, char *, char *, char *));
-#endif
+static int rep_name(char *, size_t, int *, int);
+static int tty_rename(ARCHD *);
+static int fix_path(char *, int *, char *, int);
+static int fn_match(char *, char *, char **);
+static char * range_match(char *, int);
+static int resub(regex_t *, regmatch_t *, char *, char *, char *, char *);
 
 /*
  * rep_add()
  *     parses the -s replacement string; compiles the regular expression
  *     and stores the compiled value and it's replacement string together in
  *     replacement string list. Input to this function is of the form:
- *             /old/new/pg 
+ *             /old/new/pg
  *     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
@@ -104,22 +92,14 @@ static int resub __P((regex_t *, regmatch_t *, char *, char *, char *));
  *     the list of replacement patterns; -1 otherwise.
  */
 
-#ifdef __STDC__
 int
-rep_add(register char *str)
-#else
-int
-rep_add(str)
-       register char *str;
-#endif
+rep_add(char *str)
 {
-       register char *pt1;
-       register char *pt2;
-       register REPLACE *rep;
-#      ifndef NET2_REGEX
-       register int res;
+       char *pt1;
+       char *pt2;
+       REPLACE *rep;
+       int res;
        char rebuf[BUFSIZ];
-#      endif
 
        /*
         * throw out the bad parameters
@@ -133,7 +113,15 @@ rep_add(str)
         * first character in the string specifies what the delimiter is for
         * this expression
         */
-       if ((pt1 = strchr(str+1, *str)) == NULL) {
+       for (pt1 = str+1; *pt1; pt1++) {
+               if (*pt1 == '\\') {
+                       pt1++;
+                       continue;
+               }
+               if (*pt1 == *str)
+                       break;
+       }
+       if (*pt1 == '\0') {
                paxwarn(1, "Invalid replacement string %s", str);
                return(-1);
        }
@@ -148,13 +136,9 @@ rep_add(str)
        }
 
        *pt1 = '\0';
-#      ifdef NET2_REGEX
-       if ((rep->rcmp = regcomp(str+1)) == NULL) {
-#      else
        if ((res = regcomp(&(rep->rcmp), str+1, 0)) != 0) {
                regerror(res, &(rep->rcmp), rebuf, sizeof(rebuf));
                paxwarn(1, "%s while compiling regular expression %s", rebuf, str);
-#      endif
                (void)free((char *)rep);
                return(-1);
        }
@@ -165,12 +149,16 @@ rep_add(str)
         * we then point the node at the new substitution string
         */
        *pt1++ = *str;
-       if ((pt2 = strchr(pt1, *str)) == NULL) {
-#              ifdef NET2_REGEX
-               (void)free((char *)rep->rcmp);
-#              else
+       for (pt2 = pt1; *pt2; pt2++) {
+               if (*pt2 == '\\') {
+                       pt2++;
+                       continue;
+               }
+               if (*pt2 == *str)
+                       break;
+       }
+       if (*pt2 == '\0') {
                regfree(&(rep->rcmp));
-#              endif
                (void)free((char *)rep);
                paxwarn(1, "Invalid replacement string %s", str);
                return(-1);
@@ -185,7 +173,7 @@ rep_add(str)
         * set the options if any
         */
        while (*pt2 != '\0') {
-               switch(*pt2) {
+               switch (*pt2) {
                case 'g':
                case 'G':
                        rep->flgs  |= GLOB;
@@ -195,11 +183,7 @@ rep_add(str)
                        rep->flgs  |= PRNT;
                        break;
                default:
-#                      ifdef NET2_REGEX
-                       (void)free((char *)rep->rcmp);
-#                      else
                        regfree(&(rep->rcmp));
-#                      endif
                        (void)free((char *)rep);
                        *pt1 = *str;
                        paxwarn(1, "Invalid replacement string option %s", str);
@@ -232,17 +216,10 @@ rep_add(str)
  *     0 if the pattern was added to the list, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 pat_add(char *str, char *chdname)
-#else
-int
-pat_add(str, chdname)
-       char *str;
-       char *chdname;
-#endif
 {
-       register PATTERN *pt;
+       PATTERN *pt;
 
        /*
         * throw out the junk
@@ -284,16 +261,11 @@ pat_add(str, chdname)
  *     a selected archive member.
  */
 
-#ifdef __STDC__
 void
 pat_chk(void)
-#else
-void
-pat_chk()
-#endif
 {
-       register PATTERN *pt;
-       register int wban = 0;
+       PATTERN *pt;
+       int wban = 0;
 
        /*
         * walk down the list checking the flags to make sure MTCH was set,
@@ -318,26 +290,20 @@ pat_chk()
  *
  *     NOTE: When the -c option is used, we are called when there was no match
  *     by pat_match() (that means we did match before the inverted sense of
- *     the logic). Now this seems really strange at first, but with -c  we
- *     need to keep track of those patterns that cause a archive member to NOT
+ *     the logic). Now this seems really strange at first, but with -c we
+ *     need to keep track of those patterns that cause an archive member to NOT
  *     be selected (it found an archive member with a specified pattern)
  * Return:
  *     0 if the pattern pointed at by arcn->pat was tagged as creating a
  *     match, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
-pat_sel(register ARCHD *arcn)
-#else
-int
-pat_sel(arcn)
-       register ARCHD *arcn;
-#endif
+pat_sel(ARCHD *arcn)
 {
-       register PATTERN *pt;
-       register PATTERN **ppt;
-       register int len;
+       PATTERN *pt;
+       PATTERN **ppt;
+       int len;
 
        /*
         * if no patterns just return
@@ -356,7 +322,7 @@ pat_sel(arcn)
 
        /*
         * we reach this point only when we allow a single selected match per
-        * pattern, if the pattern matches a directory and we do not have -d 
+        * pattern, if the pattern matches a directory and we do not have -d
         * (dflag) we are done with this pattern. We may also be handed a file
         * in the subtree of a directory. in that case when we are operating
         * with -d, this pattern was already selected and we are done
@@ -415,7 +381,7 @@ pat_sel(arcn)
         * we are then done with this pattern, so we delete it from the list
         * because it can never be used for another match.
         * Seems kind of strange to do for a -c, but the pax spec is really
-        * vague on the interaction of -c -n and -d. We assume that when -c
+        * vague on the interaction of -c, -n and -d. We assume that when -c
         * and the pattern rejects a member (i.e. it matched it) it is done.
         * In effect we place the order of the flags as having -c last.
         */
@@ -430,7 +396,7 @@ pat_sel(arcn)
                /*
                 * should never happen....
                 */
-               paxwarn(1, "Pattern list inconsistant");
+               paxwarn(1, "Pattern list inconsistent");
                return(-1);
        }
        *ppt = pt->fow;
@@ -446,21 +412,15 @@ pat_sel(arcn)
  *     this archive member is "selected" we process and mark the pattern as
  *     one which matched a selected archive member (see pat_sel())
  * Return:
- *     0 if this archive member should be processed, 1 if it should be 
+ *     0 if this archive member should be processed, 1 if it should be
  *     skipped and -1 if we are done with all patterns (and pax should quit
  *     looking for more members)
  */
 
-#ifdef __STDC__
-int
-pat_match(register ARCHD *arcn)
-#else
 int
-pat_match(arcn)
-       register ARCHD *arcn;
-#endif
+pat_match(ARCHD *arcn)
 {
-       register PATTERN *pt;
+       PATTERN *pt;
 
        arcn->pat = NULL;
 
@@ -523,24 +483,16 @@ pat_match(arcn)
 /*
  * fn_match()
  * Return:
- *     0 if this archive member should be processed, 1 if it should be 
+ *     0 if this archive member should be processed, 1 if it should be
  *     skipped and -1 if we are done with all patterns (and pax should quit
  *     looking for more members)
  *     Note: *pend may be changed to show where the prefix ends.
  */
 
-#ifdef __STDC__
-static int
-fn_match(register char *pattern, register char *string, char **pend)
-#else
 static int
-fn_match(pattern, string, pend)
-       register char *pattern;
-       register char *string;
-       char **pend;
-#endif
+fn_match(char *pattern, char *string, char **pend)
 {
-       register char c;
+       char c;
        char test;
 
        *pend = NULL;
@@ -572,7 +524,7 @@ fn_match(pattern, string, pend)
                case '*':
                        c = *pattern;
                        /*
-                        * Collapse multiple *'s. 
+                        * Collapse multiple *'s.
                         */
                        while (c == '*')
                                c = *++pattern;
@@ -610,18 +562,11 @@ fn_match(pattern, string, pend)
        /* NOTREACHED */
 }
 
-#ifdef __STDC__
-static char *
-range_match(register char *pattern, register int test)
-#else
 static char *
-range_match(pattern, test)
-       register char *pattern;
-       register int test;
-#endif
+range_match(char *pattern, int test)
 {
-       register char c;
-       register char c2;
+       char c;
+       char c2;
        int negate;
        int ok = 0;
 
@@ -657,25 +602,19 @@ range_match(pattern, test)
  *     if we spot any file links to the old file name in the future, we will
  *     know exactly how to fix the file link.
  * Return:
- *     0 continue to  process file, 1 skip this file, -1 pax is finished 
+ *     0 continue to  process file, 1 skip this file, -1 pax is finished
  */
 
-#ifdef __STDC__
-int
-mod_name(register ARCHD *arcn)
-#else
 int
-mod_name(arcn)
-       register ARCHD *arcn;
-#endif
+mod_name(ARCHD *arcn)
 {
-       register int res = 0;
+       int res = 0;
 
        /*
         * Strip off leading '/' if appropriate.
         * Currently, this option is only set for the tar format.
         */
-       if (rmleadslash && arcn->name[0] == '/') {
+       while (rmleadslash && arcn->name[0] == '/') {
                if (arcn->name[1] == '\0') {
                        arcn->name[0] = '.';
                } else {
@@ -688,7 +627,7 @@ mod_name(arcn)
                        paxwarn(0, "Removing leading / from absolute path names in the archive");
                }
        }
-       if (rmleadslash && arcn->ln_name[0] == '/' &&
+       while (rmleadslash && arcn->ln_name[0] == '/' &&
            (arcn->type == PAX_HLK || arcn->type == PAX_HRG)) {
                if (arcn->ln_name[1] == '\0') {
                        arcn->ln_name[0] = '.';
@@ -727,12 +666,12 @@ mod_name(arcn)
                 * we have replacement strings, modify the name and the link
                 * name if any.
                 */
-               if ((res = rep_name(arcn->name, &(arcn->nlen), 1)) != 0)
+               if ((res = rep_name(arcn->name, sizeof(arcn->name), &(arcn->nlen), 1)) != 0)
                        return(res);
 
                if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
                    (arcn->type == PAX_HRG)) &&
-                   ((res = rep_name(arcn->ln_name, &(arcn->ln_nlen), 0)) != 0))
+                   ((res = rep_name(arcn->ln_name, sizeof(arcn->ln_name), &(arcn->ln_nlen), 0)) != 0))
                        return(res);
        }
 
@@ -759,14 +698,8 @@ mod_name(arcn)
  *     0 process this file, 1 skip this file, -1 we need to exit pax
  */
 
-#ifdef __STDC__
-static int
-tty_rename(register ARCHD *arcn)
-#else
 static int
-tty_rename(arcn)
-       register ARCHD *arcn;
-#endif
+tty_rename(ARCHD *arcn)
 {
        char tmpname[PAXPATHLEN+2];
        int res;
@@ -816,8 +749,9 @@ tty_rename(arcn)
         */
        tty_prnt("Processing continues, name changed to: %s\n", tmpname);
        res = add_name(arcn->name, arcn->nlen, tmpname);
-       arcn->nlen = l_strncpy(arcn->name, tmpname, sizeof(arcn->name) - 1);
-       arcn->name[arcn->nlen] = '\0';
+       arcn->nlen = strlcpy(arcn->name, tmpname, sizeof(arcn->name));
+       if (arcn->nlen >= sizeof(arcn->name))
+               arcn->nlen = sizeof(arcn->name) - 1; /* XXX truncate? */
        if (res < 0)
                return(-1);
        return(0);
@@ -831,16 +765,8 @@ tty_rename(arcn)
  *     0 if ok, -1 if failure (name too long)
  */
 
-#ifdef __STDC__
-int
-set_dest(register ARCHD *arcn, char *dest_dir, int dir_len)
-#else
 int
-set_dest(arcn, dest_dir, dir_len)
-       register ARCHD *arcn;
-       char *dest_dir;
-       int dir_len;
-#endif
+set_dest(ARCHD *arcn, char *dest_dir, int dir_len)
 {
        if (fix_path(arcn->name, &(arcn->nlen), dest_dir, dir_len) < 0)
                return(-1);
@@ -866,21 +792,12 @@ set_dest(arcn, dest_dir, dir_len)
  *     0 if ok, -1 if the final name is too long
  */
 
-#ifdef __STDC__
-static int
-fix_path( char *or_name, int *or_len, char *dir_name, int dir_len)
-#else
 static int
-fix_path(or_name, or_len, dir_name, dir_len)
-       char *or_name;
-       int *or_len;
-       char *dir_name;
-       int dir_len;
-#endif
+fix_path(char *or_name, int *or_len, char *dir_name, int dir_len)
 {
-       register char *src;
-       register char *dest;
-       register char *start;
+       char *src;
+       char *dest;
+       char *start;
        int len;
 
        /*
@@ -903,7 +820,7 @@ fix_path(or_name, or_len, dir_name, dir_len)
        *or_len = len;
 
        /*
-        * enough space, shift 
+        * enough space, shift
         */
        while (src >= start)
                *dest-- = *src--;
@@ -930,6 +847,7 @@ fix_path(or_name, or_len, dir_name, dir_len)
  *     --Parameters--
  *     name is the file name we are going to apply the regular expressions to
  *     (and may be modified)
+ *     nsize is 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.
@@ -938,27 +856,17 @@ fix_path(or_name, or_len, dir_name, dir_len)
  *     ended up empty)
  */
 
-#ifdef __STDC__
 static int
-rep_name(char *name, int *nlen, int prnt)
-#else
-static int
-rep_name(name, nlen, prnt)
-       char *name;
-       int *nlen;
-       int prnt;
-#endif
+rep_name(char *name, size_t nsize, int *nlen, int prnt)
 {
-       register REPLACE *pt;
-       register char *inpt;
-       register char *outpt;
-       register char *endpt;
-       register char *rpt;
-       register int found = 0;
-       register int res;
-#      ifndef NET2_REGEX
+       REPLACE *pt;
+       char *inpt;
+       char *outpt;
+       char *endpt;
+       char *rpt;
+       int found = 0;
+       int res;
        regmatch_t pm[MAXSUBEXP];
-#      endif
        char nname[PAXPATHLEN+1];       /* final result of all replacements */
        char buf1[PAXPATHLEN+1];        /* where we work on the name */
 
@@ -971,7 +879,7 @@ rep_name(name, nlen, prnt)
         * (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;
@@ -981,15 +889,12 @@ rep_name(name, nlen, prnt)
         */
        while (pt != NULL) {
                do {
+                       char *oinpt = inpt;
                        /*
                         * check for a successful substitution, if not go to
                         * the next pattern, or cleanup if we were global
                         */
-#                      ifdef NET2_REGEX
-                       if (regexec(pt->rcmp, inpt) == 0)
-#                      else
                        if (regexec(&(pt->rcmp), inpt, MAXSUBEXP, pm, 0) != 0)
-#                      endif
                                break;
 
                        /*
@@ -1000,11 +905,7 @@ rep_name(name, nlen, prnt)
                         * do not create a string too long).
                         */
                        found = 1;
-#                      ifdef NET2_REGEX
-                       rpt = pt->rcmp->startp[0];
-#                      else
                        rpt = inpt + pm[0].rm_so;
-#                      endif
 
                        while ((inpt < rpt) && (outpt < endpt))
                                *outpt++ = *inpt++;
@@ -1017,12 +918,8 @@ rep_name(name, nlen, prnt)
                         * replacement string and place it the prefix in the
                         * final output. If we have problems, skip it.
                         */
-#                      ifdef NET2_REGEX
-                       if ((res = resub(pt->rcmp,pt->nstr,outpt,endpt)) < 0) {
-#                      else
-                       if ((res = resub(&(pt->rcmp),pm,pt->nstr,outpt,endpt))
+                       if ((res = resub(&(pt->rcmp),pm,pt->nstr,oinpt,outpt,endpt))
                            < 0) {
-#                      endif
                                if (prnt)
                                        paxwarn(1, "Replacement name error %s",
                                            name);
@@ -1040,11 +937,7 @@ rep_name(name, nlen, prnt)
                         * the final result. Make sure we do not overrun the
                         * output buffer
                         */
-#                      ifdef NET2_REGEX
-                       inpt = pt->rcmp->endp[0];
-#                      else
                        inpt += pm[0].rm_eo - pm[0].rm_so;
-#                      endif
 
                        if ((outpt == endpt) || (*inpt == '\0'))
                                break;
@@ -1097,98 +990,28 @@ rep_name(name, nlen, prnt)
                 */
                if (*nname == '\0')
                        return(1);
-               *nlen = l_strncpy(name, nname, PAXPATHLEN + 1);
-               name[PAXPATHLEN] = '\0';
+               *nlen = strlcpy(name, nname, nsize);
        }
        return(0);
 }
 
-#ifdef NET2_REGEX
-/*
- * resub()
- *     apply the replacement to the matched expression. expand out the old
- *     style ed(1) subexpression expansion.
- * Return:
- *     -1 if error, or the number of characters added to the destination.
- */
-
-#ifdef __STDC__
-static int
-resub(regexp *prog, char *src, char *dest, register char *destend)
-#else
-static int
-resub(prog, src, dest, destend)
-       regexp *prog;
-       char *src;
-       char *dest;
-       register char *destend;
-#endif
-{
-       register char *spt;
-       register char *dpt;
-       register char c;
-       register int no;
-       register int len;
-
-       spt = src;
-       dpt = dest;
-       while ((dpt < destend) && ((c = *spt++) != '\0')) {
-               if (c == '&')
-                       no = 0;
-               else if ((c == '\\') && (*spt >= '0') && (*spt <= '9'))
-                       no = *spt++ - '0';
-               else {
-                       if ((c == '\\') && ((*spt == '\\') || (*spt == '&')))
-                               c = *spt++;
-                       *dpt++ = c;
-                       continue;
-               }
-               if ((prog->startp[no] == NULL) || (prog->endp[no] == NULL) ||
-                   ((len = prog->endp[no] - prog->startp[no]) <= 0))
-                       continue;
-
-               /*
-                * copy the subexpression to the destination.
-                * fail if we run out of space or the match string is damaged
-                */
-               if (len > (destend - dpt))
-                       len = destend - dpt;
-               if (l_strncpy(dpt, prog->startp[no], len) != len)
-                       return(-1);
-               dpt += len;
-       }
-       return(dpt - dest);
-}
-
-#else
-
 /*
  * resub()
  *     apply the replacement to the matched expression. expand out the old
- *     style ed(1) subexpression expansion.
+ *     style ed(1) subexpression expansion.
  * Return:
  *     -1 if error, or the number of characters added to the destination.
  */
 
-#ifdef __STDC__
-static int
-resub(regex_t *rp, register regmatch_t *pm, char *src, char *dest,
-       register char *destend)
-#else
 static int
-resub(rp, pm, src, dest, destend)
-       regex_t *rp;
-       register regmatch_t *pm;
-       char *src;
-       char *dest;
-       register char *destend;
-#endif
+resub(regex_t *rp, regmatch_t *pm, char *src, char *inpt, char *dest,
+       char *destend)
 {
-       register char *spt;
-       register char *dpt;
-       register char c;
-       register regmatch_t *pmpt;
-       register int len;
+       char *spt;
+       char *dpt;
+       char c;
+       regmatch_t *pmpt;
+       int len;
        int subexcnt;
 
        spt =  src;
@@ -1209,12 +1032,12 @@ resub(rp, pm, src, dest, destend)
                                return(-1);
                        pmpt = pm + len;
                } else {
-                       /*
+                       /*
                         * Ordinary character, just copy it
                         */
-                       if ((c == '\\') && ((*spt == '\\') || (*spt == '&')))
-                               c = *spt++;
-                       *dpt++ = c;
+                       if ((c == '\\') && (*spt != '\0'))
+                               c = *spt++;
+                       *dpt++ = c;
                        continue;
                }
 
@@ -1230,11 +1053,9 @@ resub(rp, pm, src, dest, destend)
                 * fail if we run out of space or the match string is damaged
                 */
                if (len > (destend - dpt))
-                       len = destend - dpt;
-               if (l_strncpy(dpt, src + pmpt->rm_so, len) != len)
-                       return(-1);
+                       return (-1);
+               strncpy(dpt, inpt + pmpt->rm_so, len);
                dpt += len;
        }
        return(dpt - dest);
 }
-#endif
index b41f1e12fc405a7368285b60e84023e05ba3c76c..adef65f2c03aa1e4c5d3e8ed3686f31b6ebc7b78 100644 (file)
--- a/pat_rep.h
+++ b/pat_rep.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pat_rep.h,v 1.2 1996/06/23 14:20:38 deraadt Exp $     */
+/*     $OpenBSD: pat_rep.h,v 1.4 2003/06/02 23:32:08 millert Exp $     */
 /*     $NetBSD: pat_rep.h,v 1.3 1995/03/21 09:07:35 cgd Exp $  */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  */
 typedef struct replace {
        char            *nstr;  /* the new string we will substitute with */
-#      ifdef NET2_REGEX
-       regexp          *rcmp;  /* compiled regular expression used to match */
-#      else
        regex_t         rcmp;   /* compiled regular expression used to match */
-#      endif
        int             flgs;   /* print conversions? global in operation?  */
 #define        PRNT            0x1
 #define        GLOB            0x2
diff --git a/pax.1 b/pax.1
index acfb48979ad27aad7e7572cb31509665ff56ee9d..d9ef442bbf62c467170c96a90bf6ebf458472a1f 100644 (file)
--- a/pax.1
+++ b/pax.1
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: pax.1,v 1.7 1998/09/23 00:13:49 aaron Exp $
+.\"    $OpenBSD: pax.1,v 1.54 2008/06/11 07:42:50 jmc Exp $
 .\"    $NetBSD: pax.1,v 1.3 1995/03/21 09:07:37 cgd Exp $
 .\"
 .\" Copyright (c) 1992 Keith Muller.
 .\" 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 the University of
-.\"    California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
+.\" 3. Neither the name of the University nor the names of its contributors
 .\"    may be used to endorse or promote products derived from this software
 .\"    without specific prior written permission.
 .\"
 .\"
 .\"    @(#)pax.1       8.4 (Berkeley) 4/18/94
 .\"
-.Dd April 18, 1994
+.Dd $Mdocdate: June 11 2008 $
 .Dt PAX 1
-.Os BSD 4.4
+.Os
 .Sh NAME
 .Nm pax
 .Nd read and write file archives and copy directory hierarchies
 .Sh SYNOPSIS
-.Nm pax
-.Op Fl cdnv
 .Bk -words
+.Nm pax
+.Op Fl 0cdjnOvz
+.Op Fl E Ar limit
 .Op Fl f Ar archive
-.Ek
-.Bk -words
+.Op Fl G Ar group
 .Op Fl s Ar replstr
-.Ar ...
-.Ek
-.Bk -words
+.Op Fl T Ar range
 .Op Fl U Ar user
-.Ar ...
-.Ek
-.Bk -words
-.Op Fl G Ar group
-.Ar ...
-.Ek
-.Bk -words
-.Oo
-.Fl T
-.Op Ar from_date
-.Op Ar ,to_date
-.Oc
-.Ar ...
-.Ek
 .Op Ar pattern ...
 .Nm pax
 .Fl r
-.Op Fl cdiknuvDYZ
-.Bk -words
+.Op Fl 0cDdijknOuvYZz
+.Op Fl E Ar limit
 .Op Fl f Ar archive
-.Ek
-.Bk -words
+.Op Fl G Ar group
 .Op Fl o Ar options
-.Ar ...
-.Ek
-.Bk -words
 .Op Fl p Ar string
-.Ar ...
-.Ek
-.Bk -words
 .Op Fl s Ar replstr
-.Ar ...
-.Ek
-.Op Fl E Ar limit
-.Bk -words
+.Op Fl T Ar range
 .Op Fl U Ar user
-.Ar ...
-.Ek
-.Bk -words
-.Op Fl G Ar group
-.Ar ...
-.Ek
-.Bk -words
-.Oo
-.Fl T
-.Op Ar from_date
-.Op Ar ,to_date
-.Oc
-.Ar ...
-.Ek
 .Op Ar pattern ...
 .Nm pax
 .Fl w
-.Op Fl dituvHLPX
-.Bk -words
+.Op Fl 0adHijLOPtuvXz
+.Op Fl B Ar bytes
 .Op Fl b Ar blocksize
-.Ek
-.Oo
-.Op Fl a
 .Op Fl f Ar archive
-.Oc
-.Bk -words
-.Op Fl x Ar format
-.Ek
-.Bk -words
-.Op Fl s Ar replstr
-.Ar ...
-.Ek
-.Bk -words
+.Op Fl G Ar group
 .Op Fl o Ar options
-.Ar ...
-.Ek
-.Bk -words
+.Op Fl s Ar replstr
+.Op Fl T Ar range
 .Op Fl U Ar user
-.Ar ...
-.Ek
-.Bk -words
-.Op Fl G Ar group
-.Ar ...
-.Ek
-.Bk -words
-.Op Fl B Ar bytes
-.Ek
-.Bk -words
-.Oo
-.Fl T
-.Op Ar from_date
-.Op Ar ,to_date
-.Op Ar /[c][m]
-.Oc
-.Ar ...
-.Ek
+.Op Fl x Ar format
 .Op Ar file ...
 .Nm pax
-.Fl r
-.Fl w
-.Op Fl diklntuvDHLPXYZ
-.Bk -words
+.Fl rw
+.Op Fl 0DdHijkLlnOPtuvXYZ
+.Op Fl G Ar group
 .Op Fl p Ar string
-.Ar ...
-.Ek
-.Bk -words
 .Op Fl s Ar replstr
-.Ar ...
-.Ek
-.Bk -words
+.Op Fl T Ar range
 .Op Fl U Ar user
-.Ar ...
-.Ek
-.Bk -words
-.Op Fl G Ar group
-.Ar ...
-.Ek
-.Bk -words
-.Oo
-.Fl T
-.Op Ar from_date
-.Op Ar ,to_date
-.Op Ar /[c][m]
-.Oc
-.Ar ...
-.Ek
 .Op Ar file ...
 .Ar directory
+.Ek
 .Sh DESCRIPTION
-.Nm pax
-will read, write, and list the members of an archive file,
+.Nm
+will read, write, and list the members of an archive file
 and will copy directory hierarchies.
-.Nm pax 
-operation is independent of the specific archive format,
+.Nm
+operation is independent of the specific archive format
 and supports a wide variety of different archive formats.
 A list of supported archive formats can be found under the description of the
 .Fl x
@@ -196,30 +103,29 @@ The presence of the
 and the
 .Fl w
 options specifies which of the following functional modes
-.Nm pax
+.Nm
 will operate under:
 .Em list , read , write ,
 and
 .Em copy .
 .Bl -tag -width 6n
-.It <none>
+.It \*(Ltnone\*(Gt
 .Em List .
-.Nm pax
-will write to
-.Dv standard output
+.Nm
+will write to standard output
 a table of contents of the members of the archive file read from
-.Dv standard input ,
-whose pathnames match the specified
-.Ar patterns .
+standard input, whose pathnames match the specified
+.Ar pattern
+arguments.
 The table of contents contains one filename per line
 and is written using single line buffering.
 .It Fl r
 .Em Read .
-.Nm pax
-extracts the members of the archive file read from the
-.Dv standard input ,
-with pathnames matching the specified 
-.Ar patterns .
+.Nm
+extracts the members of the archive file read from the standard input,
+with pathnames matching the specified
+.Ar pattern
+arguments.
 The archive format and blocking is automatically determined on input.
 When an extracted file is a directory, the entire file hierarchy
 rooted at that directory is extracted.
@@ -230,32 +136,30 @@ the extracted files are discussed in more detail under the
 option.
 .It Fl w
 .Em Write .
-.Nm pax
-writes an archive containing the 
+.Nm
+writes an archive containing the
 .Ar file
-operands to
-.Dv standard output
+operands to standard output
 using the specified archive format.
-When no 
+When no
 .Ar file
-operands are specified, a list of files to copy with one per line is read from 
-.Dv standard input .
-When a 
+operands are specified, a list of files to copy with one per line is read from
+standard input.
+When a
 .Ar file
 operand is also a directory, the entire file hierarchy rooted
 at that directory will be included.
-.It Fl r Fl w
+.It Fl rw
 .Em Copy .
-.Nm pax
+.Nm
 copies the
 .Ar file
 operands to the destination
 .Ar directory .
-When no 
+When no
 .Ar file
 operands are specified, a list of files to copy with one per line is read from
-the
-.Dv standard input .
+the standard input.
 When a
 .Ar file
 operand is also a directory the entire file
@@ -268,7 +172,7 @@ the original and the copied files (see the
 .Fl l
 option below).
 .Pp
-.Em Warning :
+.Sy Warning :
 The destination
 .Ar directory
 must not be one of the
@@ -286,12 +190,12 @@ While processing a damaged archive during a
 or
 .Em list
 operation,
-.Nm pax
+.Nm
 will attempt to recover from media defects and will search through the archive
 to locate and process the largest number of archive members possible (see the
 .Fl E
 option for more details on error handling).
-.Sh OPERANDS
+.Pp
 The
 .Ar directory
 operand specifies a destination directory pathname.
@@ -299,7 +203,7 @@ If the
 .Ar directory
 operand does not exist, or it is not writable by the user,
 or it is not of type directory,
-.Nm pax
+.Nm
 will exit with a non-zero exit status.
 .Pp
 The
@@ -307,22 +211,21 @@ The
 operand is used to select one or more pathnames of archive members.
 Archive members are selected using the pattern matching notation described
 by
-.Xr fnmatch 3 .
-When the 
+.Xr glob 3 .
+When the
 .Ar pattern
 operand is not supplied, all members of the archive will be selected.
-When a 
+When a
 .Ar pattern
 matches a directory, the entire file hierarchy rooted at that directory will
 be selected.
 When a
 .Ar pattern
 operand does not select at least one archive member,
-.Nm pax
+.Nm
 will write these
 .Ar pattern
-operands in a diagnostic message to
-.Dv standard error
+operands in a diagnostic message to standard error
 and then exit with a non-zero exit status.
 .Pp
 The
@@ -331,63 +234,47 @@ operand specifies the pathname of a file to be copied or archived.
 When a
 .Ar file
 operand does not select at least one archive member,
-.Nm pax
+.Nm
 will write these
 .Ar file
-operand pathnames in a diagnostic message to
-.Dv standard error
+operand pathnames in a diagnostic message to standard error
 and then exit with a non-zero exit status.
-.Sh OPTIONS
-The following options are supported:
-.Bl -tag -width 4n
-.It Fl r
-Read an archive file from
-.Dv standard input
-and extract the specified
-.Ar files .
-If any intermediate directories are needed in order to extract an archive
-member, these directories will be created as if
-.Xr mkdir 2
-was called with the bitwise inclusive
-.Dv OR 
-of
-.Dv S_IRWXU , S_IRWXG ,
-and
-.Dv S_IRWXO 
-as the mode argument.
-When the selected archive format supports the specification of linked
-files and these files cannot be linked while the archive is being extracted,
-.Nm pax
-will write a diagnostic message to
-.Dv standard error
-and exit with a non-zero exit status at the completion of operation.
-.It Fl w
-Write files to the
-.Dv standard output
-in the specified archive format.
-When no
-.Ar file
-operands are specified,
-.Dv standard input
-is read for a list of pathnames with one per line without any leading or
-trailing
-.Aq blanks .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl 0
+Use the NUL
+.Pq Ql \e0
+character as a pathname terminator, instead of newline
+.Pq Ql \en .
+This applies only to the pathnames read from standard input in
+the write and copy modes,
+and to the pathnames written to standard output in list mode.
+This option is expected to be used in concert with the
+.Fl print0
+function in
+.Xr find 1
+or the
+.Fl 0
+flag in
+.Xr xargs 1 .
 .It Fl a
-Append
-.Ar files
+Append the given
+.Ar file
+operands
 to the end of an archive that was previously written.
 If an archive format is not specified with a
 .Fl x
 option, the format currently being used in the archive will be selected.
 Any attempt to append to an archive in a format different from the
-format already used in the archive will cause 
-.Nm pax
+format already used in the archive will cause
+.Nm
 to exit immediately
 with a non-zero exit status.
 The blocking size used in the archive volume where writing starts
 will continue to be used for the remainder of that archive volume.
 .Pp
-.Em Warning :
+.Sy Warning :
 Many storage devices are not able to support the operations necessary
 to perform an append operation.
 Any attempt to append to an archive stored on such a device may damage the
@@ -395,6 +282,28 @@ archive or have other unpredictable results.
 Tape drives in particular are more likely to not support an append operation.
 An archive stored in a regular file system file or on a disk device will
 usually support an append operation.
+.It Fl B Ar bytes
+Limit the number of bytes written to a single archive volume to
+.Ar bytes .
+The
+.Ar bytes
+limit can end with
+.Sq Li m ,
+.Sq Li k ,
+or
+.Sq Li b
+to specify multiplication by 1048576 (1M), 1024 (1K) or 512, respectively.
+A pair of
+.Ar bytes
+limits can be separated by
+.Sq Li x
+to indicate a product.
+.Pp
+.Em Warning :
+Only use this option when writing an archive to a device which supports
+an end of file read condition based on last (or largest) write offset
+(such as a regular file or a tape drive).
+The use of this option with a floppy or hard disk is not recommended.
 .It Fl b Ar blocksize
 When
 .Em writing
@@ -404,7 +313,7 @@ bytes per write to the archive file.
 The
 .Ar blocksize
 must be a multiple of 512 bytes with a maximum of 64512 bytes.
-Archives larger than 32256 bytes violate the
+Archive block sizes larger than 32256 bytes violate the
 .Tn POSIX
 standard and will not be portable to all systems.
 A
@@ -421,7 +330,7 @@ can be separated by
 to indicate a product.
 A specific archive device may impose additional restrictions on the size
 of blocking it will support.
-When blocking is not specified, the default 
+When blocking is not specified, the default
 .Ar blocksize
 is dependent on the specific archive format being used (see the
 .Fl x
@@ -434,28 +343,81 @@ those specified by the
 and
 .Ar file
 operands.
+.It Fl D
+This option is the same as the
+.Fl u
+option, except that the file inode change time is checked instead of the
+file modification time.
+The file inode change time can be used to select files whose inode information
+(e.g., UID, GID, etc.) is newer than a copy of the file in the destination
+.Ar directory .
 .It Fl d
 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 E Ar limit
+Limit the number of consecutive read faults while trying to read a flawed
+archive to
+.Ar limit .
+With a positive
+.Ar limit ,
+.Nm
+will attempt to recover from an archive read error and will
+continue processing starting with the next file stored in the archive.
+A
+.Ar limit
+of 0 will cause
+.Nm
+to stop operation after the first read error is detected on an archive volume.
+A
+.Ar limit
+of
+.Li NONE
+will cause
+.Nm
+to attempt to recover from read errors forever.
+The default
+.Ar limit
+is a small positive number of retries.
+.Pp
+.Em Warning :
+Using this option with
+.Li NONE
+should be used with extreme caution as
+.Nm
+may get stuck in an infinite loop on a very badly flawed archive.
 .It Fl f Ar archive
 Specify
 .Ar archive
 as the pathname of the input or output archive, overriding the default
-.Dv standard input
-(for
+standard input (for
 .Em list
 and
 .Em read )
-or
-.Dv standard output
+or standard output
 (for
 .Em write ) .
 A single archive may span multiple files and different archive devices.
 When required,
-.Nm pax
+.Nm
 will prompt for the pathname of the file or device of the next volume in the
 archive.
+.It Fl G Ar group
+Select a file based on its
+.Ar group
+name, or when starting with a
+.Cm # ,
+a numeric GID.
+A
+.Ql \e
+can be used to escape the
+.Cm # .
+Multiple
+.Fl G
+options may be supplied and checking stops with the first match.
+.It Fl H
+Follow only command-line symbolic links while performing a physical file
+system traversal.
 .It Fl i
 Interactively rename files or archive members.
 For each archive member matching a
@@ -463,27 +425,36 @@ For each archive member matching a
 operand or each file matching a
 .Ar file
 operand,
-.Nm pax
+.Nm
 will prompt to
 .Pa /dev/tty
-giving the name of the file, its file mode and its modification time.
-.Nm pax
+giving the name of the file, its file mode, and its modification time.
+.Nm
 will then read a line from
 .Pa /dev/tty .
 If this line is blank, the file or archive member is skipped.
 If this line consists of a single period, the
 file or archive member is processed with no modification to its name.
 Otherwise, its name is replaced with the contents of the line.
-.Nm pax
-will immediately exit with a non-zero exit status if 
-.Dv <EOF>
+.Nm
+will immediately exit with a non-zero exit status if
+.Dv EOF
 is encountered when reading a response or if
 .Pa /dev/tty
 cannot be opened for reading and writing.
+.It Fl j
+Use bzip2 to compress (decompress) the archive while writing (reading).
+The bzip2 utility must be installed separately.
+Incompatible with
+.Fl a .
 .It Fl k
 Do not overwrite existing files.
+.It Fl L
+Follow all symbolic links to perform a logical file system traversal.
 .It Fl l
-(The lowercase letter ``ell.'') Link files.
+(The lowercase letter
+.Dq ell . )
+Link files.
 In the
 .Em copy
 mode
@@ -498,8 +469,15 @@ 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 (unless
-.Fl d 
+.Fl d
 is also specified).
+.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 o Ar options
 Information to modify the algorithm for extracting or writing archive files
 which is specific to the archive format specified by
@@ -507,7 +485,21 @@ which is specific to the archive format specified by
 In general,
 .Ar options
 take the form:
-.Cm name=value .
+.Ar name Ns = Ns Ar value .
+.Pp
+The following options are available for the old
+.Bx
+.Em tar
+format:
+.Pp
+.Bl -tag -width Ds -compact
+.It Cm nodir
+.It Cm write_opt=nodir
+When writing archives, omit the storage of directories.
+.El
+.It Fl P
+Do not follow symbolic links, perform a physical file system traversal.
+This is the default mode.
 .It Fl p Ar string
 Specify one or more file characteristic options (privileges).
 The
@@ -520,25 +512,25 @@ and
 .Cm p .
 Multiple characteristics can be concatenated within the same string
 and multiple
-.Fl p 
+.Fl p
 options can be specified.
-The meaning of the specification characters are as follows:
+The meanings of the specification characters are as follows:
 .Bl -tag -width 2n
 .It Cm a
 Do not preserve file access times.
 By default, file access times are preserved whenever possible.
 .It Cm e
-.Sq Preserve everything ,
+.Dq Preserve everything ,
 the user ID, group ID, file mode bits,
 file access time, and file modification time.
 This is intended to be used by
 .Em root ,
 someone with all the appropriate privileges, in order to preserve all
 aspects of the files as they are recorded in the archive.
-The 
+The
 .Cm e
 flag is the sum of the
-.Cm o 
+.Cm o
 and
 .Cm p
 flags.
@@ -548,10 +540,10 @@ By default, file modification times are preserved whenever possible.
 .It Cm o
 Preserve the user ID and group ID.
 .It Cm p
-.Sq Preserve
+.Dq Preserve
 the file mode bits.
-This intended to be used by a
-.Em user 
+This is intended to be used by a
+.Em user
 with regular privileges who wants to preserve all aspects of the file other
 than the ownership.
 The file times are preserved by default, but two other flags are offered to
@@ -565,285 +557,130 @@ extracted file, subject to the permissions of the invoking
 process.
 Otherwise the attribute of the extracted file is determined as
 part of the normal file creation action.
-If neither the 
+If neither the
 .Cm e
 nor the
 .Cm o
 specification character is specified, or the user ID and group ID are not
 preserved for any reason,
-.Nm pax
+.Nm
 will not set the
-.Dv S_ISUID 
+.Dv S_ISUID
 .Em ( setuid )
 and
 .Dv S_ISGID
 .Em ( setgid )
 bits of the file mode.
 If the preservation of any of these items fails for any reason,
-.Nm pax
-will write a diagnostic message to
-.Dv standard error .
+.Nm
+will write a diagnostic message to standard error.
 Failure to preserve these items will affect the final exit status,
 but will not cause the extracted file to be deleted.
 If the file characteristic letters in any of the string option-arguments are
 duplicated or conflict with each other, the one(s) given last will take
 precedence.
 For example, if
-.Dl Fl p Ar eme
+.Fl p Ar eme
 is specified, file modification times are still preserved.
-.It Fl s Ar replstr
-Modify the file or archive member names specified by the
-.Ar pattern
-or
+.It Fl r
+Read an archive file from standard input
+and extract the specified
 .Ar file
-operands according to the substitution expression
+operands.
+If any intermediate directories are needed in order to extract an archive
+member, these directories will be created as if
+.Xr mkdir 2
+was called with the bitwise inclusive
+.Tn OR
+of
+.Dv S_IRWXU , S_IRWXG ,
+and
+.Dv S_IRWXO
+as the mode argument.
+When the selected archive format supports the specification of linked
+files and these files cannot be linked while the archive is being extracted,
+.Nm
+will write a diagnostic message to standard error
+and exit with a non-zero exit status at the completion of operation.
+.It Fl s Ar replstr
+Modify the archive member names according to the substitution expression
 .Ar replstr ,
 using the syntax of the
 .Xr ed 1
 utility regular expressions.
-The format of these regular expressions are:
+.Ar file
+or
+.Ar pattern
+arguments may be given to restrict the list of archive members to those
+specified.
+.Pp
+The format of these regular expressions is:
+.Pp
 .Dl /old/new/[gp]
+.Pp
 As in
 .Xr ed 1 ,
-.Cm old
-is a basic regular expression and
-.Cm new
-can contain an ampersand (&), \\n (where n is a digit) back-references,
+.Ar old
+is a basic regular expression (see
+.Xr re_format 7 )
+and
+.Ar new
+can contain an ampersand
+.Pq Ql & ,
+.Ql \e Ns Em n
+(where
+.Em n
+is a digit) back-references,
 or subexpression matching.
 The
-.Cm old
-string may also contain
-.Dv <newline>
-characters.
-Any non-null character can be used as a delimiter (/ is shown here).
+.Ar old
+string may also contain newline characters.
+Any non-null character can be used as a delimiter
+.Po
+.Ql /
+is shown here
+.Pc .
 Multiple
 .Fl s
 expressions can be specified.
 The expressions are applied in the order they are specified on the
 command line, terminating with the first successful substitution.
+.Pp
 The optional trailing
 .Cm g
-continues to apply the substitution expression to the pathname substring
+continues to apply the substitution expression to the pathname substring,
 which starts with the first character following the end of the last successful
-substitution. The first unsuccessful substitution stops the operation of the
+substitution.
+The first unsuccessful substitution stops the operation of the
 .Cm g
 option.
 The optional trailing
 .Cm p
 will cause the final result of a successful substitution to be written to
-.Dv standard error
-in the following format:
-.Dl <original pathname> >> <new pathname>
+standard error in the following format:
+.Pp
+.D1 Em original-pathname No \*(Gt\*(Gt Em new-pathname
+.Pp
 File or archive member names that substitute to the empty string
 are not selected and will be skipped.
-.It Fl t
-Reset the access times of any file or directory read or accessed by
-.Nm pax
-to be the same as they were before being read or accessed by
-.Nm pax .
-.It Fl u
-Ignore files that are older (having a less recent file modification time)
-than a pre-existing file or archive member with the same name.
-During
-.Em read ,
-an archive member with the same name as a file in the file system will be
-extracted if the archive member is newer than the file.
-During
-.Em write ,
-a file system member with the same name as an archive member will be
-written to the archive if it is newer than the archive member.
-During
-.Em copy ,
-the file in the destination hierarchy is replaced by the file in the source
-hierarchy or by a link to the file in the source hierarchy if the file in
-the source hierarchy is newer.
-.It Fl v
-During a
-.Em list
-operation, produce a verbose table of contents using the format of the
-.Xr ls 1
-utility with the
-.Fl l
-option.
-For pathnames representing a hard link to a previous member of the archive,
-the output has the format:
-.Dl <ls -l listing> == <link name>
-For pathnames representing a symbolic link, the output has the format:
-.Dl <ls -l listing> => <link name>
-Where <ls -l listing> is the output format specified by the 
-.Xr ls 1
-utility when used with the
-.Fl l
-option.
-Otherwise for all the other operational modes
-.Po Em read , write , Li and Em copy
-.Pc ,
-pathnames are written and flushed to
-.Dv standard error
-without a trailing
-.Dv <newline>
-as soon as processing begins on that file or
-archive member.
-The trailing
-.Dv <newline> ,
-is not buffered, and is written only after the file has been read or written.
-.It Fl x Ar format
-Specify the output archive format, with the default format being
-.Ar ustar .
-.Nm pax
-currently supports the following formats:
-.Bl -tag -width "sv4cpio"
-.It Ar cpio
-The extended cpio interchange format specified in the
-.St -p1003.2
-standard.
-The default blocksize for this format is 5120 bytes.
-Inode and device information about a file (used for detecting file hard links
-by this format) which may be truncated by this format is detected by
-.Nm pax
-and is repaired.
-.It Ar bcpio
-The old binary cpio format.
-The default blocksize for this format is 5120 bytes.
-This format is not very portable and should not be used when other formats
-are available.
-Inode and device information about a file (used for detecting file hard links
-by this format) which may be truncated by this format is detected by
-.Nm pax
-and is repaired.
-.It Ar sv4cpio
-The System V release 4 cpio.
-The default blocksize for this format is 5120 bytes.
-Inode and device information about a file (used for detecting file hard links
-by this format) which may be truncated by this format is detected by
-.Nm pax
-and is repaired.
-.It Ar sv4crc
-The System V release 4 cpio with file crc checksums.
-The default blocksize for this format is 5120 bytes.
-Inode and device information about a file (used for detecting file hard links
-by this format) which may be truncated by this format is detected by
-.Nm pax
-and is repaired.
-.It Ar tar
-The old BSD tar format as found in BSD4.3.
-The default blocksize for this format is 10240 bytes.
-Pathnames stored by this format must be 100 characters or less in length.
-Only
-.Em regular
-files,
-.Em  hard links , soft links ,
-and
-.Em  directories
-will be archived (other file system types are not supported).
-For backwards compatibility with even older tar formats, a
-.Fl o
-option can be used when writing an archive to omit the storage of directories.
-This option takes the form:
-.Dl Fl o Cm write_opt=nodir
-.It Ar ustar
-The extended tar interchange format specified in the
-.St -p1003.2
-standard.
-The default blocksize for this format is 10240 bytes.
-Pathnames stored by this format must be 250 characters or less in length.
-.El
-.Pp
-.Nm pax
-will detect and report any file that it is unable to store or extract
-as the result of any specific archive format restrictions.
-The individual archive formats may impose additional restrictions on use.
-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 B Ar bytes
-Limit the number of bytes written to a single archive volume to
-.Ar bytes .
-The
-.Ar bytes
-limit can end with
-.Sq Li m ,
-.Sq Li k ,
-or
-.Sq Li b
-to specify multiplication by 1048576 (1M), 1024 (1K) or 512, respectively.
-A pair of
-.Ar bytes
-limits can be separated by
-.Sq Li x
-to indicate a product.
-.Pp
-.Em Warning :
-Only use this option when writing an archive to a device which supports
-an end of file read condition based on last (or largest) write offset
-(such as a regular file or a tape drive). 
-The use of this option with a floppy or hard disk is not recommended.
-.It Fl D
-This option is the same as the
-.Fl u
-option, except that the file inode change time is checked instead of the
-file modification time.
-The file inode change time can be used to select files whose inode information
-(e.g. UID, GID, etc.) is newer than a copy of the file in the destination
-.Ar directory .
-.It Fl E Ar limit
-Limit the number of consecutive read faults while trying to read a flawed
-archive to
-.Ar limit .
-With a positive
-.Ar limit ,
-.Nm pax
-will attempt to recover from an archive read error and will
-continue processing starting with the next file stored in the archive.
-A
-.Ar limit
-of 0 will cause
-.Nm pax
-to stop operation after the first read error is detected on an archive volume.
-A
-.Ar limit
-of
-.Li NONE
-will cause
-.Nm pax 
-to attempt to recover from read errors forever.
-The default 
-.Ar limit
-is a small positive number of retries.
-.Pp
-.Em Warning: 
-Using this option with
-.Li NONE
-should be used with extreme caution as
-.Nm pax
-may get stuck in an infinite loop on a very badly flawed archive.
-.It Fl G Ar group
-Select a file based on its
-.Ar group
-name, or when starting with a
-.Cm # ,
-a numeric gid.
-A '\\' can be used to escape the
-.Cm # .
-Multiple 
-.Fl G
-options may be supplied and checking stops with the first match.
-.It Fl H
-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 P
-Do not follow symbolic links, perform a physical file system traversal.
-This is the default mode.
-.It Fl T Ar [from_date][,to_date][/[c][m]]
+.It Fl T Ar range
 Allow files to be selected based on a file modification or inode change
-time falling within a specified time range of 
+time falling within the specified time range.
+The range has the format:
+.Sm off
+.Bd -filled -offset indent
+.Oo Ar from_date Oc Oo ,
+.Ar to_date Oc Oo /
+.Oo Cm c Oc Op Cm m Oc
+.Ed
+.Sm on
+.Pp
+The dates specified by
 .Ar from_date
 to
 .Ar to_date
-(the dates are inclusive).
-If only a 
+are inclusive.
+If only a
 .Ar from_date
 is supplied, all files with a modification or inode change time
 equal to or younger are selected.
@@ -851,7 +688,7 @@ If only a
 .Ar to_date
 is supplied, all files with a modification or inode change time
 equal to or older will be selected.
-When the 
+When the
 .Ar from_date
 is equal to the
 .Ar to_date ,
@@ -859,94 +696,239 @@ only files with a modification or inode change time of exactly that
 time will be selected.
 .Pp
 When
-.Nm pax
-is in the 
+.Nm
+is in the
 .Em write
 or
 .Em copy
 mode, the optional trailing field
-.Ar [c][m]
+.Oo Cm c Oc Op Cm m
 can be used to determine which file time (inode change, file modification or
 both) are used in the comparison.
 If neither is specified, the default is to use file modification time only.
 The
-.Ar m
+.Cm m
 specifies the comparison of file modification time (the time when
 the file was last written).
 The
-.Ar c
+.Cm c
 specifies the comparison of inode change time (the time when the file
-inode was last changed; e.g. a change of owner, group, mode, etc).
-When 
-.Ar c
+inode was last changed; e.g., a change of owner, group, mode, etc).
+When
+.Cm c
 and
-.Ar m
+.Cm m
 are both specified, then the modification and inode change times are
 both compared.
+.Pp
 The inode change time comparison is useful in selecting files whose
 attributes were recently changed or selecting files which were recently
 created and had their modification time reset to an older time (as what
 happens when a file is extracted from an archive and the modification time
 is preserved).
 Time comparisons using both file times is useful when
-.Nm pax
+.Nm
 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.
 The format is:
-.Dl [yy[mm[dd[hh]]]]mm[.ss]
+.Pp
+.Dl [[[[[cc]yy]mm]dd]HH]MM[.SS]
+.Pp
 Where
-.Cm yy
+.Ar cc
+is the first two digits of the year (the century),
+.Ar yy
 is the last two digits of the year,
 the first
-.Cm mm
+.Ar mm
 is the month (from 01 to 12),
-.Cm dd
+.Ar dd
 is the day of the month (from 01 to 31),
-.Cm hh
+.Ar HH
 is the hour of the day (from 00 to 23),
-the second
-.Cm mm
+.Ar MM
 is the minute (from 00 to 59),
 and
-.Cm ss
+.Ar SS
 is the seconds (from 00 to 59).
 The minute field
-.Cm mm
+.Ar MM
 is required, while the other fields are optional and must be added in the
 following order:
-.Dl Cm hh , dd , mm , yy .
-The 
-.Cm ss
+.Ar HH , dd , mm ,
+.Ar yy , cc .
+.Pp
+The
+.Ar SS
 field may be added independently of the other fields.
 Time ranges are relative to the current time, so
-.Dl Fl T Ar 1234/cm
+.Ic -T 1234/cm
 would select all files with a modification or inode change time
 of 12:34 PM today or later.
-Multiple 
+Multiple
 .Fl T
 time range can be supplied and checking stops with the first match.
+.It Fl t
+Reset the access times of any file or directory read or accessed by
+.Nm
+to be the same as they were before being read or accessed by
+.Nm pax .
 .It Fl U Ar user
 Select a file based on its
 .Ar user
 name, or when starting with a
 .Cm # ,
 a numeric UID.
-A '\\' can be used to escape the
+A
+.Ql \e
+can be used to escape the
 .Cm # .
-Multiple 
+Multiple
 .Fl U
 options may be supplied and checking stops with the first match.
+.It Fl u
+Ignore files that are older (having a less recent file modification time)
+than a pre-existing file or archive member with the same name.
+During
+.Em read ,
+an archive member with the same name as a file in the file system will be
+extracted if the archive member is newer than the file.
+During
+.Em write ,
+a file system member with the same name as an archive member will be
+written to the archive if it is newer than the archive member.
+During
+.Em copy ,
+the file in the destination hierarchy is replaced by the file in the source
+hierarchy or by a link to the file in the source hierarchy if the file in
+the source hierarchy is newer.
+.It Fl v
+During a
+.Em list
+operation, produce a verbose table of contents using the format of the
+.Xr ls 1
+utility with the
+.Fl l
+option.
+For pathnames representing a hard link to a previous member of the archive,
+the output has the format:
+.Pp
+.Dl Em ls -l listing Li == Em link-name
+.Pp
+For pathnames representing a symbolic link, the output has the format:
+.Pp
+.Dl Em ls -l listing Li =\*(Gt Em link-name
+.Pp
+Where
+.Em ls -l listing
+is the output format specified by the
+.Xr ls 1
+utility when used with the
+.Fl l
+option.
+Otherwise for all the other operational modes
+.Po Em read , write , No and Em copy
+.Pc ,
+pathnames are written and flushed to standard error
+without a trailing newline
+as soon as processing begins on that file or
+archive member.
+The trailing newline
+is not buffered and is written only after the file has been read or written.
+.It Fl w
+Write files to the standard output
+in the specified archive format.
+When no
+.Ar file
+operands are specified, standard input
+is read for a list of pathnames with one per line without any leading or
+trailing
+.Aq blanks .
 .It Fl X
 When traversing the file hierarchy specified by a pathname,
 do not descend into directories that have a different device ID.
 See the
-.Li st_dev 
+.Li st_dev
 field as described in
 .Xr stat 2
 for more information about device IDs.
+.It Fl x Ar format
+Specify the output archive format, with the default format being
+.Cm ustar .
+.Nm
+currently supports the following formats:
+.Bl -tag -width "sv4cpio"
+.It Cm bcpio
+The old binary cpio format.
+The default blocksize for this format is 5120 bytes.
+This format is not very portable and should not be used when other formats
+are available.
+Inode and device information about a file (used for detecting file hard links
+by this format), which may be truncated by this format, is detected by
+.Nm
+and is repaired.
+.It Cm cpio
+The extended cpio interchange format specified in the
+.St -p1003.2
+standard.
+The default blocksize for this format is 5120 bytes.
+Inode and device information about a file (used for detecting file hard links
+by this format), which may be truncated by this format, is detected by
+.Nm
+and is repaired.
+.It Cm sv4cpio
+The System V release 4 cpio.
+The default blocksize for this format is 5120 bytes.
+Inode and device information about a file (used for detecting file hard links
+by this format), which may be truncated by this format, is detected by
+.Nm
+and is repaired.
+.It Cm sv4crc
+The System V release 4 cpio with file CRC checksums.
+The default blocksize for this format is 5120 bytes.
+Inode and device information about a file (used for detecting file hard links
+by this format), which may be truncated by this format, is detected by
+.Nm
+and is repaired.
+.It Cm tar
+The old
+.Bx
+tar format as found in
+.Bx 4.3 .
+The default blocksize for this format is 10240 bytes.
+Pathnames stored by this format must be 100 characters or less in length.
+Only
+.Em regular
+files,
+.Em hard links , soft links ,
+and
+.Em directories
+will be archived (other file system types are not supported).
+For backwards compatibility with even older tar formats, a
+.Fl o
+option can be used when writing an archive to omit the storage of directories.
+This option takes the form:
+.Pp
+.Dl Fl o Cm write_opt=nodir
+.It Cm ustar
+The extended tar interchange format specified in the
+.St -p1003.2
+standard.
+The default blocksize for this format is 10240 bytes.
+Filenames stored by this format must be 100 characters or less in length;
+the total pathname must be 255 characters or less.
+.El
+.Pp
+.Nm
+will detect and report any file that it is unable to store or extract
+as the result of any specific archive format restrictions.
+The individual archive formats may impose additional restrictions on use.
+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 Y
 This option is the same as the
 .Fl D
@@ -957,11 +939,18 @@ This option is the same as the
 .Fl u
 option, except that the modification time is checked using the
 pathname created after all the file name modifications have completed.
+.It Fl z
+Use
+.Xr gzip 1
+to compress (decompress) the archive while writing (reading).
+Incompatible with
+.Fl a .
 .El
 .Pp
 The options that operate on the names of files or archive members
 .Po Fl c ,
 .Fl i ,
+.Fl j ,
 .Fl n ,
 .Fl s ,
 .Fl u ,
@@ -999,7 +988,7 @@ Then the
 and
 .Fl Z
 options will be applied based on the final pathname.
-Finally, the 
+Finally, the
 .Fl v
 option will write the names resulting from these modifications.
 .Pp
@@ -1015,13 +1004,13 @@ based only on the user specified pathnames as modified by the
 .Fl D ,
 .Fl G ,
 .Fl T ,
-and 
+and
 .Fl U
 options (the
 .Fl D
 option only applies during a copy operation).
 Then any
-.Fl s 
+.Fl s
 and
 .Fl i
 options will modify in that order, the names of these selected files.
@@ -1044,135 +1033,131 @@ 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 ENVIRONMENT
+.Bl -tag -width Fl
+.It Ev TMPDIR
+Path in which to store temporary files.
+.El
 .Sh EXAMPLES
-The command:
-.Dl pax -w -f /dev/rst0 .\ 
-copies the contents of the current directory to the device
-.Pa /dev/rst0 .
+Copy the contents of the current directory to the device
+.Pa /dev/rst0 :
 .Pp
-The command:
-.Dl pax -v -f filename
-gives the verbose table of contents for an archive stored in
-.Pa filename .
+.Dl $ pax -w -f /dev/rst0 \&.
 .Pp
-The following commands:
-.Dl mkdir newdir
-.Dl cd olddir
-.Dl pax -rw .\ newdir
-will copy the entire
+Give the verbose table of contents for an archive stored in
+.Pa filename :
+.Pp
+.Dl $ pax -v -f filename
+.Pp
+This sequence of commands will copy the entire
 .Pa olddir
 directory hierarchy to
-.Pa newdir .
+.Pa newdir :
+.Bd -literal -offset indent
+$ mkdir newdir
+$ cd olddir
+$ pax -rw . ../newdir
+.Ed
+.Pp
+Extract files from the archive
+.Pa a.pax .
+Files rooted in
+.Pa /usr
+are extracted relative to the current working directory;
+all other files are extracted to their unmodified path.
 .Pp
-The command:
-.Dl pax -r -s ',^//*usr//*,,' -f a.pax
-reads the archive 
-.Pa a.pax ,
-with all files rooted in ``/usr'' into the archive extracted relative to the
-current directory.
+.Dl $ pax -r -s ',^/usr/,,' -f a.pax
 .Pp
-The command:
-.Dl pax -rw -i .\ dest_dir
-can be used to interactively select the files to copy from the current
-directory to
-.Pa dest_dir .
+This can be used to interactively select the files to copy from the
+current directory to
+.Pa dest_dir :
 .Pp
-The command:
-.Dl pax -r -pe -U root -G bin -f a.pax
-will extract all files from the archive
+.Dl $ pax -rw -i \&. dest_dir
+.Pp
+Extract all files from the archive
 .Pa a.pax
 which are owned by
 .Em root
 with group
 .Em bin
-and will preserve all file permissions.
+and preserve all file permissions:
+.Pp
+.Dl "$ pax -r -pe -U root -G bin -f a.pax"
 .Pp
-The command:
-.Dl pax -r -w -v -Y -Z home /backup
-will update (and list) only those files in the destination directory
+Update (and list) only those files in the destination directory
 .Pa /backup
 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 STANDARDS
-The
-.Nm pax
-utility is a superset of the
-.St -p1003.2
-standard.
-The options
-.Fl B ,
-.Fl D ,
-.Fl E ,
-.Fl G ,
-.Fl H ,
-.Fl L ,
-.Fl P ,
-.Fl T ,
-.Fl U ,
-.Fl Y ,
-.Fl Z ,
-the archive formats
-.Ar bcpio ,
-.Ar sv4cpio ,
-.Ar sv4crc ,
-.Ar tar ,
-and the flawed archive handling during
-.Ar list
-and
-.Ar read
-operations are extensions to the
-.Tn POSIX
-standard.
-.Sh SEE ALSO
-.Xr cpio 1 ,
-.Xr tar 1
-.Sh AUTHOR
-Keith Muller at the University of California, San Diego.
-.Sh ERRORS
-.Nm pax
+.Pa home :
+.Pp
+.Dl "$ pax -r -w -v -Y -Z home /backup"
+.Sh DIAGNOSTICS
+.Nm
 will exit with one of the following values:
-.Bl -tag -width 2n
+.Bl -tag -width 2n -offset indent
 .It 0
 All files were processed successfully.
-.It 1 
+.It 1
 An error occurred.
 .El
 .Pp
 Whenever
-.Nm pax
+.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
+option is specified, a diagnostic message is written to standard error
 and a non-zero exit status will be returned, but processing will continue.
 In the case where
-.Nm pax
+.Nm
 cannot create a link to a file,
-.Nm pax
+.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 pax
+.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 pax
-may have only partially created the archive which may violate the specific
+.Nm
+may have only partially created the archive, which may violate the specific
 archive format specification.
 .Pp
 If while doing a
 .Em copy ,
-.Nm pax
+.Nm
 detects a file is about to overwrite itself, the file is not copied,
-a diagnostic message is written to
-.Dv standard error
+a diagnostic message is written to standard error
 and when
-.Nm pax
+.Nm
 completes it will exit with a non-zero exit status.
+.Sh SEE ALSO
+.Xr cpio 1 ,
+.Xr tar 1
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2004
+specification.
+.Pp
+The flags
+.Op Fl 0BDEGHjLOPTUYZz ,
+the archive formats
+.Em bcpio ,
+.Em sv4cpio ,
+.Em sv4crc ,
+.Em tar ,
+and the flawed archive handling during
+.Em list
+and
+.Em read
+operations
+are extensions to that specification.
+.Sh AUTHORS
+Keith Muller at the University of California, San Diego.
diff --git a/pax.c b/pax.c
index 637e2f3ecbb2fac310d1e24ef98d737193185374..3c3d2b4719704c8b0f9917a55f419d828d60b08e 100644 (file)
--- a/pax.c
+++ b/pax.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pax.c,v 1.14 1998/09/20 02:22:22 millert Exp $        */
+/*     $OpenBSD: pax.c,v 1.28 2005/08/04 10:02:44 mpf Exp $    */
 /*     $NetBSD: pax.c,v 1.5 1996/03/26 23:54:20 mrg Exp $      */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  */
 
 #ifndef lint
-static char copyright[] =
+static const char copyright[] =
 "@(#) Copyright (c) 1992, 1993\n\
        The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)pax.c      8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)pax.c        8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: pax.c,v 1.14 1998/09/20 02:22:22 millert Exp $";
+static const char rcsid[] = "$OpenBSD: pax.c,v 1.28 2005/08/04 10:02:44 mpf Exp $";
 #endif
 #endif /* not lint */
 
@@ -63,10 +59,12 @@ static char rcsid[] = "$OpenBSD: pax.c,v 1.14 1998/09/20 02:22:22 millert Exp $"
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <err.h>
 #include <fcntl.h>
+#include <paths.h>
 #include "pax.h"
 #include "extern.h"
-static int gen_init __P((void));
+static int gen_init(void);
 
 /*
  * PAX main routines, general globals and some simple start up routines
@@ -87,13 +85,13 @@ int nflag;                  /* select first archive member match */
 int    tflag;                  /* restore access time after read */
 int    uflag;                  /* ignore older modification time files */
 int    vflag;                  /* produce verbose output */
-int    zflag;                  /* use gzip */
 int    Dflag;                  /* same as uflag except inode change time */
 int    Hflag;                  /* follow command line symlinks (write only) */
 int    Lflag;                  /* follow symlinks when writing */
 int    Xflag;                  /* archive files with same device id only */
-int    Yflag;                  /* same as Dflg except after name mode */
-int    Zflag;                  /* same as uflg except after name mode */
+int    Yflag;                  /* same as Dflag except after name mode */
+int    Zflag;                  /* same as uflag except after name mode */
+int    zeroflag;               /* use \0 as pathname terminator */
 int    vfpart;                 /* is partial verbose output in progress */
 int    patime = 1;             /* preserve file access time */
 int    pmtime = 1;             /* preserve file modification times */
@@ -108,11 +106,13 @@ char      *ltmfrmt;               /* -v locale time format (if any) */
 char   *argv0;                 /* root of argv[0] */
 sigset_t s_mask;               /* signal mask for cleanup critical sect */
 FILE   *listf = stderr;        /* file pointer to print file list to */
+char   *tempfile;              /* tempfile to use for mkstemp(3) */
+char   *tempbase;              /* basename of tempfile to use for mkstemp(3) */
 
 /*
  *     PAX - Portable Archive Interchange
  *
- *     A utility to read, write, and write lists of the members of archive
+ *     A utility to read, write, and write lists of the members of archive
  *     files and copy directory hierarchies. A variety of archive formats
  *     are supported (some are described in POSIX 1003.1 10.1):
  *
@@ -128,7 +128,7 @@ FILE        *listf = stderr;        /* file pointer to print file list to */
  *
  * 1   READ ENHANCEMENTS
  * 1.1 Operations which read archives will continue to operate even when
- *     processing archives which may be damaged, truncated, or fail to meet 
+ *     processing archives which may be damaged, truncated, or fail to meet
  *     format specs in several different ways. Damaged sections of archives
  *     are detected and avoided if possible. Attempts will be made to resync
  *     archive read operations even with badly damaged media.
@@ -143,7 +143,7 @@ FILE        *listf = stderr;        /* file pointer to print file list to */
  * 1.5 The user is notified whenever something is found during archive
  *     read operations which violates spec (but the read will continue).
  * 1.6 Multiple archive volumes can be read and may span over different
- *     archive devices 
+ *     archive devices
  * 1.7 Rigidly restores all file attributes exactly as they are stored on the
  *     archive.
  * 1.8 Modification change time ranges can be specified via multiple -T
@@ -153,14 +153,14 @@ FILE      *listf = stderr;        /* file pointer to print file list to */
  *     -U options.
  * 1.10        Files can be selected based on group (group name or gid) via one o
  *     more -G options.
- * 1.11        File modification time can be checked against exisiting file after
+ * 1.11        File modification time can be checked against existing file after
  *     name modification (-Z)
  *
  * 2   WRITE ENHANCEMENTS
  * 2.1 Write operation will stop instead of allowing a user to create a flawed
  *     flawed archive (due to any problem).
- * 2.2 Archives writtens by pax are forced to strictly conform to both the
- *     archive and pax the spceific format specifications.
+ * 2.2 Archives written by pax are forced to strictly conform to both the
+ *     archive and pax the specific format specifications.
  * 2.3 Blocking size and format is rigidly enforced on writes.
  * 2.4 Formats which may exhibit header overflow problems (they have fields
  *     too small for large file systems, such as inode number storage), use
@@ -169,11 +169,11 @@ FILE      *listf = stderr;        /* file pointer to print file list to */
  *     these fields. This removes any restrictions on using these archive
  *     formats on large file systems.
  * 2.5 Multiple archive volumes can be written and may span over different
- *     archive devices 
+ *     archive devices
  * 2.6 A archive volume record limit allows the user to specify the number
  *     of bytes stored on an archive volume. When reached the user is
  *     prompted for the next archive volume. This is specified with the
- *     non-standard -B flag. THe limit is rounded up to the next blocksize.
+ *     non-standard -B flag. The limit is rounded up to the next blocksize.
  * 2.7 All archive padding during write use zero filled sections. This makes
  *     it much easier to pull data out of flawed archive during read
  *     operations.
@@ -208,15 +208,15 @@ FILE      *listf = stderr;        /* file pointer to print file list to */
  *     more -G options.
  * 3.8 Symlinks which appear on the command line can be followed (without
  *     following other symlinks; -H flag)
- * 3.9  File inode change time can be checked against exisiting file before
+ * 3.9  File inode change time can be checked against existing file before
  *     name modification (-D)
- * 3.10 File inode change time can be checked against exisiting file after
+ * 3.10 File inode change time can be checked against existing file after
  *     name modification (-Y)
- * 3.11        File modification time can be checked against exisiting file after
+ * 3.11        File modification time can be checked against existing file after
  *     name modification (-Z)
  *
  * 4   GENERAL ENHANCEMENTS
- * 4.1 Internal structure is designed to isolate format dependent and 
+ * 4.1 Internal structure is designed to isolate format dependent and
  *     independent functions. Formats are selected via a format driver table.
  *     This encourages the addition of new archive formats by only having to
  *     write those routines which id, read and write the archive header.
@@ -229,24 +229,38 @@ FILE      *listf = stderr;        /* file pointer to print file list to */
  * Return: 0 if ok, 1 otherwise
  */
 
-#ifdef __STDC__
 int
 main(int argc, char **argv)
-#else
-int
-main(argc, argv)
-       int argc;
-       char **argv;
-#endif
 {
+       char *tmpdir;
+       size_t tdlen;
+
        /*
         * Keep a reference to cwd, so we can always come back home.
         */
        cwdfd = open(".", O_RDONLY);
        if (cwdfd < 0) {
-               syswarn(0, errno, "Can't open current working directory.");
+               syswarn(1, errno, "Can't open current working directory.");
+               return(exit_val);
+       }
+
+       /*
+        * Where should we put temporary files?
+        */
+       if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
+               tmpdir = _PATH_TMP;
+       tdlen = strlen(tmpdir);
+       while (tdlen > 0 && tmpdir[tdlen - 1] == '/')
+               tdlen--;
+       tempfile = malloc(tdlen + 1 + sizeof(_TFILE_BASE));
+       if (tempfile == NULL) {
+               paxwarn(1, "Cannot allocate memory for temp file name.");
                return(exit_val);
        }
+       if (tdlen)
+               memcpy(tempfile, tmpdir, tdlen);
+       tempbase = tempfile + tdlen;
+       *tempbase++ = '/';
 
        /*
         * parse options, determine operational mode, general init
@@ -256,9 +270,9 @@ main(argc, argv)
                return(exit_val);
 
        /*
-        * select a primary operation mode 
+        * select a primary operation mode
         */
-       switch(act) {
+       switch (act) {
        case EXTRACT:
                extract();
                break;
@@ -266,6 +280,8 @@ main(argc, argv)
                archive();
                break;
        case APPND:
+               if (gzip_program != NULL)
+                       errx(1, "can not gzip while appending");
                append();
                break;
        case COPY:
@@ -288,15 +304,11 @@ main(argc, argv)
  *     never....
  */
 
-#ifdef __STDC__
 void
 sig_cleanup(int which_sig)
-#else
-void
-sig_cleanup(which_sig)
-       int which_sig;
-#endif
 {
+       /* XXX signal races */
+
        /*
         * restore modes and times for any dirs we may have created
         * or any dirs we may have read. Set vflag and vfpart so the user
@@ -321,13 +333,8 @@ sig_cleanup(which_sig)
  *     when dealing with a medium to large sized archives.
  */
 
-#ifdef __STDC__
 static int
 gen_init(void)
-#else
-static int
-gen_init()
-#endif
 {
        struct rlimit reslimit;
        struct sigaction n_hand;
@@ -370,14 +377,14 @@ gen_init()
        /*
         * Handle posix locale
         *
-        * set user defines time printing format for -v option 
+        * set user defines time printing format for -v option
         */
        ltmfrmt = getenv("LC_TIME");
 
        /*
         * signal handling to reset stored directory times and modes. Since
         * we deal with broken pipes via failed writes we ignore it. We also
-        * deal with any file size limit thorugh failed writes. Cpu time
+        * deal with any file size limit through failed writes. Cpu time
         * limits are caught and a cleanup is forced.
         */
        if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) ||
diff --git a/pax.h b/pax.h
index bdf00a47dab19369e2a759b88147468b3bef8c6d..26477976e4feb62ee7e8ea0e1f98d504fc32e091 100644 (file)
--- a/pax.h
+++ b/pax.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pax.h,v 1.9 1997/07/23 19:15:58 kstailey Exp $        */
+/*     $OpenBSD: pax.h,v 1.17 2005/11/09 19:59:06 otto Exp $   */
 /*     $NetBSD: pax.h,v 1.3 1995/03/21 09:07:41 cgd Exp $      */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -52,7 +48,7 @@
                                /* Don't even think of changing this */
 #define DEVBLK         8192    /* default read blksize for devices */
 #define FILEBLK                10240   /* default read blksize for files */
-#define PAXPATHLEN     3072    /* maximium path length for pax. MUST be */
+#define PAXPATHLEN     3072    /* maximum path length for pax. MUST be */
                                /* longer than the system MAXPATHLEN */
 
 /*
@@ -66,7 +62,7 @@
 #define DEFOP          LIST    /* if no flags default is to LIST */
 
 /*
- * Device type of the current archive volume 
+ * Device type of the current archive volume
  */
 #define ISREG          0       /* regular file */
 #define ISCHR          1       /* character device */
 #define ISTAPE         3       /* tape drive */
 #define ISPIPE         4       /* pipe/socket */
 
+/*
+ * Pattern matching structure
+ *
+ * Used to store command line patterns
+ */
+typedef struct pattern {
+       char            *pstr;          /* pattern to match, user supplied */
+       char            *pend;          /* end of a prefix match */
+       char            *chdname;       /* the dir to change to if not NULL.  */
+       int             plen;           /* length of pstr */
+       int             flgs;           /* processing/state flags */
+#define MTCH           0x1             /* pattern has been matched */
+#define DIR_MTCH       0x2             /* pattern matched a directory */
+       struct pattern  *fow;           /* next pattern */
+} PATTERN;
+
+/*
+ * General Archive Structure (used internal to pax)
+ *
+ * This structure is used to pass information about archive members between
+ * the format independent routines and the format specific routines. When
+ * new archive formats are added, they must accept requests and supply info
+ * encoded in a structure of this type. The name fields are declared statically
+ * here, as there is only ONE of these floating around, size is not a major
+ * consideration. Eventually converting the name fields to a dynamic length
+ * may be required if and when the supporting operating system removes all
+ * restrictions on the length of pathnames it will resolve.
+ */
+typedef struct {
+       int nlen;                       /* file name length */
+       char name[PAXPATHLEN+1];        /* file name */
+       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 */
+       PATTERN *pat;                   /* ptr to pattern match (if any) */
+       struct stat sb;                 /* stat buffer see stat(2) */
+       off_t pad;                      /* bytes of padding after file xfer */
+       off_t skip;                     /* bytes of real data after header */
+                                       /* IMPORTANT. The st_size field does */
+                                       /* not always indicate the amount of */
+                                       /* data following the header. */
+       u_int32_t crc;                  /* file crc */
+       int type;                       /* type of file node */
+#define PAX_DIR                1               /* directory */
+#define PAX_CHR                2               /* character device */
+#define PAX_BLK                3               /* block device */
+#define PAX_REG                4               /* regular file */
+#define PAX_SLK                5               /* symbolic link */
+#define PAX_SCK                6               /* socket */
+#define PAX_FIF                7               /* fifo */
+#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;
+
 /*
  * Format Specific Routine Table
  *
  * The format specific routine table allows new archive formats to be quickly
  * added. Overall pax operation is independent of the actual format used to
- * form the archive. Only those routines which deal directly with the archive 
- * are tailored to the oddities of the specifc format. All other routines are
+ * form the archive. Only those routines which deal directly with the archive
+ * are tailored to the oddities of the specific format. All other routines are
  * independent of the archive format. Data flow in and out of the format
  * dependent routines pass pointers to ARCHD structure (described below).
  */
@@ -106,17 +159,17 @@ typedef struct {
        int hlk;                /* does archive store hard links info? if */
                                /* not, we do not bother to look for them */
                                /* during archive write operations */
-       int blkalgn;            /* writes must be aligned to blkalgn boundry */
+       int blkalgn;            /* writes must be aligned to blkalgn boundary */
        int inhead;             /* is the trailer encoded in a valid header? */
                                /* if not, trailers are assumed to be found */
                                /* in invalid headers (i.e like tar) */
-       int (*id)();            /* checks if a buffer is a valid header */
-                               /* returns 1 if it is, o.w. returns a 0 */
-       int (*st_rd)();         /* initialize routine for read. so format */
+       int (*id)(char *,       /* checks if a buffer is a valid header */
+           int);               /* returns 1 if it is, o.w. returns a 0 */
+       int (*st_rd)(void);     /* initialize routine for read. so format */
                                /* can set up tables etc before it starts */
                                /* reading an archive */
-       int (*rd)();            /* read header routine. passed a pointer to */
-                               /* ARCHD. It must extract the info from the */
+       int (*rd)(ARCHD *,      /* read header routine. passed a pointer to */
+           char *);            /* ARCHD. It must extract the info from the */
                                /* format and store it in the ARCHD struct. */
                                /* This routine is expected to fill all the */
                                /* fields in the ARCHD (including stat buf) */
@@ -127,12 +180,12 @@ typedef struct {
                                /* padding and the number of bytes of data */
                                /* which follow the header. This info is */
                                /* used skip to the next file header */
-       off_t (*end_rd)();      /* read cleanup. Allows format to clean up */
+       off_t (*end_rd)(void);  /* read cleanup. Allows format to clean up */
                                /* and MUST RETURN THE LENGTH OF THE TRAILER */
                                /* RECORD (so append knows how many bytes */
                                /* to move back to rewrite the trailer) */
-       int (*st_wr)();         /* initialize routine for write operations */
-       int (*wr)();            /* write archive header. Passed an ARCHD */
+       int (*st_wr)(void);     /* initialize routine for write operations */
+       int (*wr)(ARCHD *);     /* write archive header. Passed an ARCHD */
                                /* filled with the specs on the next file to */
                                /* archived. Returns a 1 if no file data is */
                                /* is to be stored; 0 if file data is to be */
@@ -142,78 +195,25 @@ typedef struct {
                                /* the proper padding can be added after */
                                /* file data. This routine must NEVER write */
                                /* a flawed archive header. */
-       int (*end_wr)();        /* end write. write the trailer and do any */
+       int (*end_wr)(void);    /* end write. write the trailer and do any */
                                /* other format specific functions needed */
-                               /* at the ecnd of a archive write */
-       int (*trail)();         /* returns 0 if a valid trailer, -1 if not */
-                               /* For formats which encode the trailer */
-                               /* outside of a valid header, a return value */
+                               /* at the end of an archive write */
+       int (*trail)(ARCHD *,   /* returns 0 if a valid trailer, -1 if not */
+           char *, int,        /* For formats which encode the trailer */
+           int *);             /* outside of a valid header, a return value */
                                /* of 1 indicates that the block passed to */
                                /* it can never contain a valid header (skip */
                                /* this block, no point in looking at it)  */
                                /* CAUTION: parameters to this function are */
                                /* different for trailers inside or outside */
                                /* of headers. See get_head() for details */
-       int (*rd_data)();       /* read/process file data from the archive */
-       int (*wr_data)();       /* write/process file data to the archive */
-       int (*options)();       /* process format specific options (-o) */
+       int (*rd_data)(ARCHD *, /* read/process file data from the archive */
+           int, off_t *);
+       int (*wr_data)(ARCHD *, /* write/process file data to the archive */
+           int, off_t *);
+       int (*options)(void);   /* process format specific options (-o) */
 } FSUB;
 
-/*
- * Pattern matching structure
- *
- * Used to store command line patterns
- */
-typedef struct pattern {
-       char            *pstr;          /* pattern to match, user supplied */
-       char            *pend;          /* end of a prefix match */
-       char            *chdname;       /* the dir to change to if not NULL.  */
-       int             plen;           /* length of pstr */
-       int             flgs;           /* processing/state flags */
-#define MTCH           0x1             /* pattern has been matched */
-#define DIR_MTCH       0x2             /* pattern matched a directory */
-       struct pattern  *fow;           /* next pattern */
-} PATTERN;
-
-/*
- * General Archive Structure (used internal to pax)
- *
- * This structure is used to pass information about archive members between
- * the format independent routines and the format specific routines. When
- * new archive formats are added, they must accept requests and supply info
- * encoded in a structure of this type. The name fields are declared statically
- * here, as there is only ONE of these floating around, size is not a major
- * consideration. Eventually converting the name fields to a dynamic length
- * may be required if and when the supporting operating system removes all
- * restrictions on the length of pathnames it will resolve.
- */
-typedef struct {
-       int nlen;                       /* file name length */
-       char name[PAXPATHLEN+1];        /* file name */
-       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 */
-       PATTERN *pat;                   /* ptr to pattern match (if any) */
-       struct stat sb;                 /* stat buffer see stat(2) */
-       off_t pad;                      /* bytes of padding after file xfer */
-       off_t skip;                     /* bytes of real data after header */
-                                       /* IMPORTANT. The st_size field does */
-                                       /* not always indicate the amount of */
-                                       /* data following the header. */
-       u_long crc;                     /* file crc */
-       int type;                       /* type of file node */
-#define PAX_DIR                1               /* directory */
-#define PAX_CHR                2               /* character device */
-#define PAX_BLK                3               /* block device */
-#define PAX_REG                4               /* regular file */
-#define PAX_SLK                5               /* symbolic link */
-#define PAX_SCK                6               /* socket */
-#define PAX_FIF                7               /* fifo */
-#define PAX_HLK                8               /* hard link */
-#define PAX_HRG                9               /* hard link to a regular file */
-#define PAX_CTG                10              /* high performance file */ 
-} ARCHD;
-
 /*
  * Format Specific Options List
  *
@@ -229,7 +229,7 @@ typedef struct oplist {
  * General Macros
  */
 #ifndef MIN
-#define               MIN(a,b) (((a)<(b))?(a):(b))
+#define        MIN(a,b) (((a)<(b))?(a):(b))
 #endif
 #define MAJOR(x)       major(x)
 #define MINOR(x)       minor(x)
@@ -238,6 +238,7 @@ typedef struct oplist {
 /*
  * General Defines
  */
-#define HEX    16
-#define OCT    8
-#define _PAX_  1
+#define HEX            16
+#define OCT            8
+#define _PAX_          1
+#define _TFILE_BASE    "paxXXXXXXXXXX"
index c5c2253c82c056e413963855a3e4fa9061ae06b3..55d3a0017c1504aef483bfaa9e2518696232efd5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sel_subs.c,v 1.7 1997/08/17 23:05:09 millert Exp $    */
+/*     $OpenBSD: sel_subs.c,v 1.18 2004/04/16 22:50:23 deraadt Exp $   */
 /*     $NetBSD: sel_subs.c,v 1.5 1995/03/21 09:07:42 cgd Exp $ */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)sel_subs.c 8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)sel_subs.c   8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] = "$OpenBSD: sel_subs.c,v 1.7 1997/08/17 23:05:09 millert Exp $";
+static const char rcsid[] = "$OpenBSD: sel_subs.c,v 1.18 2004/04/16 22:50:23 deraadt Exp $";
 #endif
 #endif /* not lint */
 
@@ -50,20 +46,22 @@ static char rcsid[] = "$OpenBSD: sel_subs.c,v 1.7 1997/08/17 23:05:09 millert Ex
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/param.h>
-#include <pwd.h>
+#include <ctype.h>
 #include <grp.h>
+#include <pwd.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <tzfile.h>
 #include <unistd.h>
-#include <stdlib.h>
 #include "pax.h"
 #include "sel_subs.h"
 #include "extern.h"
 
-static int str_sec __P((register char *, time_t *));
-static int usr_match __P((register ARCHD *));
-static int grp_match __P((register ARCHD *));
-static int trng_match __P((register ARCHD *));
+static int str_sec(const char *, time_t *);
+static int usr_match(ARCHD *);
+static int grp_match(ARCHD *);
+static int trng_match(ARCHD *);
 
 static TIME_RNG *trhead = NULL;                /* time range list head */
 static TIME_RNG *trtail = NULL;                /* time range list tail */
@@ -76,19 +74,13 @@ static GRPT **grptb = NULL;         /* group selection table */
 
 /*
  * sel_chk()
- *     check if this file matches a specfied uid, gid or time range
+ *     check if this file matches a specified uid, gid or time range
  * Return:
  *     0 if this archive member should be processed, 1 if it should be skipped
  */
 
-#ifdef __STDC__
 int
-sel_chk(register ARCHD *arcn)
-#else
-int
-sel_chk(arcn)
-       register ARCHD *arcn;
-#endif
+sel_chk(ARCHD *arcn)
 {
        if (((usrtb != NULL) && usr_match(arcn)) ||
            ((grptb != NULL) && grp_match(arcn)) ||
@@ -101,8 +93,8 @@ sel_chk(arcn)
  * User/group selection routines
  *
  * Routines to handle user selection of files based on the file uid/gid. To
- * add an entry, the user supplies either then name or the uid/gid starting with
- * a # on the command line. A \# will eascape the #.
+ * add an entry, the user supplies either the name or the uid/gid starting with
+ * a # on the command line. A \# will escape the #.
  */
 
 /*
@@ -112,19 +104,13 @@ sel_chk(arcn)
  *     0 if added ok, -1 otherwise;
  */
 
-#ifdef __STDC__
 int
-usr_add(register char *str)
-#else
-int
-usr_add(str)
-       register char *str;
-#endif
+usr_add(char *str)
 {
-       register u_int indx;
-       register USRT *pt;
-       register struct passwd *pw;
-       register uid_t uid;
+       u_int indx;
+       USRT *pt;
+       struct passwd *pw;
+       uid_t uid;
 
        /*
         * create the table if it doesn't exist
@@ -152,11 +138,7 @@ usr_add(str)
                }
                uid = (uid_t)pw->pw_uid;
        } else
-#              ifdef NET2_STAT
-               uid = (uid_t)atoi(str+1);
-#              else
                uid = (uid_t)strtoul(str+1, NULL, 10);
-#              endif
        endpwent();
 
        /*
@@ -191,16 +173,10 @@ usr_add(str)
  *     0 if this archive member should be processed, 1 if it should be skipped
  */
 
-#ifdef __STDC__
 static int
-usr_match(register ARCHD *arcn)
-#else
-static int
-usr_match(arcn)
-       register ARCHD *arcn;
-#endif
+usr_match(ARCHD *arcn)
 {
-       register USRT *pt;
+       USRT *pt;
 
        /*
         * hash and look for it in the table
@@ -225,19 +201,13 @@ usr_match(arcn)
  *     0 if added ok, -1 otherwise;
  */
 
-#ifdef __STDC__
 int
-grp_add(register char *str)
-#else
-int
-grp_add(str)
-       register char *str;
-#endif
+grp_add(char *str)
 {
-       register u_int indx;
-       register GRPT *pt;
-       register struct group *gr;
-       register gid_t gid;
+       u_int indx;
+       GRPT *pt;
+       struct group *gr;
+       gid_t gid;
 
        /*
         * create the table if it doesn't exist
@@ -265,11 +235,7 @@ grp_add(str)
                }
                gid = (gid_t)gr->gr_gid;
        } else
-#              ifdef NET2_STAT
-               gid = (gid_t)atoi(str+1);
-#              else
                gid = (gid_t)strtoul(str+1, NULL, 10);
-#              endif
        endgrent();
 
        /*
@@ -304,16 +270,10 @@ grp_add(str)
  *     0 if this archive member should be processed, 1 if it should be skipped
  */
 
-#ifdef __STDC__
-static int
-grp_match(register ARCHD *arcn)
-#else
 static int
-grp_match(arcn)
-       register ARCHD *arcn;
-#endif
+grp_match(ARCHD *arcn)
 {
-       register GRPT *pt;
+       GRPT *pt;
 
        /*
         * hash and look for it in the table
@@ -353,27 +313,21 @@ grp_match(arcn)
  * trng_add()
  *     add a time range match to the time range list.
  *     This is a non-standard pax option. Lower and upper ranges are in the
- *     format: [yy[mm[dd[hh]]]]mm[.ss] and are comma separated.
+ *     format: [[[[[cc]yy]mm]dd]HH]MM[.SS] and are comma separated.
  *     Time ranges are based on current time, so 1234 would specify a time of
  *     12:34 today.
  * Return:
  *     0 if the time range was added to the list, -1 otherwise
  */
 
-#ifdef __STDC__
-int
-trng_add(register char *str)
-#else
 int
-trng_add(str)
-       register char *str;
-#endif
+trng_add(char *str)
 {
-       register TIME_RNG *pt;
-       register char *up_pt = NULL;
-       register char *stpt;
-       register char *flgpt;
-       register int dot = 0;
+       TIME_RNG *pt;
+       char *up_pt = NULL;
+       char *stpt;
+       char *flgpt;
+       int dot = 0;
 
        /*
         * throw out the badly formed time ranges
@@ -419,7 +373,7 @@ trng_add(str)
        }
 
        /*
-        * by default we only will check file mtime, but usee can specify
+        * by default we only will check file mtime, but user can specify
         * mtime, ctime (inode change time) or both.
         */
        if ((flgpt == NULL) || (*flgpt == '\0'))
@@ -427,7 +381,7 @@ trng_add(str)
        else {
                pt->flgs = 0;
                while (*flgpt != '\0') {
-                       switch(*flgpt) {
+                       switch (*flgpt) {
                        case 'M':
                        case 'm':
                                pt->flgs |= CMPMTME;
@@ -495,7 +449,7 @@ trng_add(str)
        return(0);
 
     out:
-       paxwarn(1, "Time range format is: [yy[mm[dd[hh]]]]mm[.ss][/[c][m]]");
+       paxwarn(1, "Time range format is: [[[[[cc]yy]mm]dd]HH]MM[.SS][/[c][m]]");
        return(-1);
 }
 
@@ -506,16 +460,10 @@ trng_add(str)
  *     0 if this archive member should be processed, 1 if it should be skipped
  */
 
-#ifdef __STDC__
-static int
-trng_match(register ARCHD *arcn)
-#else
 static int
-trng_match(arcn)
-       register ARCHD *arcn;
-#endif
+trng_match(ARCHD *arcn)
 {
-       register TIME_RNG *pt;
+       TIME_RNG *pt;
 
        /*
         * have to search down the list one at a time looking for a match.
@@ -523,7 +471,7 @@ trng_match(arcn)
         */
        pt = trhead;
        while (pt != NULL) {
-               switch(pt->flgs & CMPBOTH) {
+               switch (pt->flgs & CMPBOTH) {
                case CMPBOTH:
                        /*
                         * user wants both mtime and ctime checked for this
@@ -575,87 +523,89 @@ trng_match(arcn)
 
 /*
  * str_sec()
- *     Convert a time string in the format of [yy[mm[dd[hh]]]]mm[.ss] to gmt
- *     seconds. Tval already has current time loaded into it at entry.
+ *     Convert a time string in the format of [[[[[cc]yy]mm]dd]HH]MM[.SS] to
+ *     seconds UTC. Tval already has current time loaded into it at entry.
  * Return:
  *     0 if converted ok, -1 otherwise
  */
 
-#ifdef __STDC__
-static int
-str_sec(register char *str, time_t *tval)
-#else
 static int
-str_sec(str, tval)
-       register char *str;
-       time_t *tval;
-#endif
+str_sec(const char *p, time_t *tval)
 {
-       register struct tm *lt;
-       register char *dot = NULL;
+       struct tm *lt;
+       const char *dot, *t;
+       size_t len;
+       int bigyear;
+       int yearset;
+
+       yearset = 0;
+       len = strlen(p);
+
+       for (t = p, dot = NULL; *t; ++t) {
+               if (isdigit(*t))
+                       continue;
+               if (*t == '.' && dot == NULL) {
+                       dot = t;
+                       continue;
+               }
+               return(-1);
+       }
 
        lt = localtime(tval);
-       if ((dot = strchr(str, '.')) != NULL) {
-               /*
-                * seconds (.ss)
-                */
-               *dot++ = '\0';
-               if (strlen(dot) != 2)
+
+       if (dot != NULL) {                      /* .SS */
+               if (strlen(++dot) != 2)
                        return(-1);
-               if ((lt->tm_sec = ATOI2(dot)) > 61)
+               lt->tm_sec = ATOI2(dot);
+               if (lt->tm_sec > 61)
                        return(-1);
+               len -= 3;
        } else
                lt->tm_sec = 0;
 
-       switch (strlen(str)) {
-       case 10:
-               /*
-                * year (yy)
-                * watch out for year 2000
-                */
-               if ((lt->tm_year = ATOI2(str)) < 69)
-                       lt->tm_year += 100;
-               str += 2;
+       switch (len) {
+       case 12:                                /* cc */
+               bigyear = ATOI2(p);
+               lt->tm_year = (bigyear * 100) - TM_YEAR_BASE;
+               yearset = 1;
                /* FALLTHROUGH */
-       case 8:
-               /*
-                * month (mm)
-                * watch out months are from 0 - 11 internally
-                */
-               if ((lt->tm_mon = ATOI2(str)) > 12)
+       case 10:                                /* yy */
+               if (yearset) {
+                       lt->tm_year += ATOI2(p);
+               } else {
+                       lt->tm_year = ATOI2(p);
+                       if (lt->tm_year < 69)           /* hack for 2000 ;-} */
+                               lt->tm_year += (2000 - TM_YEAR_BASE);
+                       else
+                               lt->tm_year += (1900 - TM_YEAR_BASE);
+               }
+               /* FALLTHROUGH */
+       case 8:                                 /* mm */
+               lt->tm_mon = ATOI2(p);
+               if ((lt->tm_mon > 12) || !lt->tm_mon)
                        return(-1);
-               --lt->tm_mon;
-               str += 2;
+               --lt->tm_mon;                   /* time struct is 0 - 11 */
                /* FALLTHROUGH */
-       case 6:
-               /*
-                * day (dd)
-                */
-               if ((lt->tm_mday = ATOI2(str)) > 31)
+       case 6:                                 /* dd */
+               lt->tm_mday = ATOI2(p);
+               if ((lt->tm_mday > 31) || !lt->tm_mday)
                        return(-1);
-               str += 2;
                /* FALLTHROUGH */
-       case 4:
-               /*
-                * hour (hh)
-                */
-               if ((lt->tm_hour = ATOI2(str)) > 23)
+       case 4:                                 /* HH */
+               lt->tm_hour = ATOI2(p);
+               if (lt->tm_hour > 23)
                        return(-1);
-               str += 2;
                /* FALLTHROUGH */
-       case 2:
-               /*
-                * minute (mm)
-                */
-               if ((lt->tm_min = ATOI2(str)) > 59)
+       case 2:                                 /* MM */
+               lt->tm_min = ATOI2(p);
+               if (lt->tm_min > 59)
                        return(-1);
                break;
        default:
                return(-1);
        }
-       /*
-        * convert broken-down time to GMT clock time seconds
-        */
+
+       /* convert broken-down time to UTC clock time seconds */
        if ((*tval = mktime(lt)) == -1)
                return(-1);
        return(0);
index fc86e9dfa236362632865f01dd647186ce7c027a..b699ee83ef353f35de8ce769f6601b566f12652e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sel_subs.h,v 1.2 1996/06/23 14:20:41 deraadt Exp $    */
+/*     $OpenBSD: sel_subs.h,v 1.4 2003/06/02 23:32:09 millert Exp $    */
 /*     $NetBSD: sel_subs.h,v 1.3 1995/03/21 09:07:44 cgd Exp $ */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -61,7 +57,7 @@ typedef struct grpt {
  * data structure for storing user supplied time ranges (-T option)
  */
 
-#define ATOI2(s)       ((((s)[0] - '0') * 10) + ((s)[1] - '0'))
+#define ATOI2(ar)      ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
 
 typedef struct time_rng {
        time_t          low_time;       /* lower inclusive time limit */
index 1f36fb4f28e422870e0ccc9373c2142025d4f415..e428051c3dadcedb46fa8f7ce442618b3805daa2 100644 (file)
--- a/tables.c
+++ b/tables.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tables.c,v 1.10 1998/07/03 06:01:20 deraadt Exp $     */
+/*     $OpenBSD: tables.c,v 1.25 2007/09/02 15:19:08 deraadt Exp $     */
 /*     $NetBSD: tables.c,v 1.4 1995/03/21 09:07:45 cgd Exp $   */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)tables.c   8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)tables.c     8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] = "$OpenBSD: tables.c,v 1.10 1998/07/03 06:01:20 deraadt Exp $";
+static const char rcsid[] = "$OpenBSD: tables.c,v 1.25 2007/09/02 15:19:08 deraadt Exp $";
 #endif
 #endif /* not lint */
 
@@ -71,7 +67,7 @@ static char rcsid[] = "$OpenBSD: tables.c,v 1.10 1998/07/03 06:01:20 deraadt Exp
  * 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 databases routines was not considered
+ * Trying to force the fit to the posix database routines was not considered
  * time well spent.
  */
 
@@ -80,11 +76,12 @@ static FTM **ftab = NULL;   /* file time table for updating arch */
 static NAMT **ntab = NULL;     /* interactive rename storage table */
 static DEVT **dtab = NULL;     /* device/inode mapping tables */
 static ATDIR **atab = NULL;    /* file tree directory time reset table */
-static int dirfd = -1;         /* storage for setting created dir time/mode */
-static u_long dircnt;          /* entries in dir time/mode storage */
+static DIRDATA *dirp = NULL;   /* storage for setting created dir time/mode */
+static size_t dirsize;         /* size of dirp table */
+static long dircnt = 0;                /* entries in dir time/mode storage */
 static int ffd = -1;           /* tmp file for file time table name storage */
 
-static DEVT *chk_dev __P((dev_t, int));
+static DEVT *chk_dev(dev_t, int);
 
 /*
  * hard link table routines
@@ -109,13 +106,8 @@ static DEVT *chk_dev __P((dev_t, int));
  *     0 if created, -1 if failure
  */
 
-#ifdef __STDC__
 int
 lnk_start(void)
-#else
-int
-lnk_start()
-#endif
 {
        if (ltab != NULL)
                return(0);
@@ -138,18 +130,12 @@ lnk_start()
  *     if found returns 1; if not found returns 0; -1 on error
  */
 
-#ifdef __STDC__
 int
-chk_lnk(register ARCHD *arcn)
-#else
-int
-chk_lnk(arcn)
-       register ARCHD *arcn;
-#endif
+chk_lnk(ARCHD *arcn)
 {
-       register HRDLNK *pt;
-       register HRDLNK **ppt;
-       register u_int indx;
+       HRDLNK *pt;
+       HRDLNK **ppt;
+       u_int indx;
 
        if (ltab == NULL)
                return(-1);
@@ -165,7 +151,7 @@ chk_lnk(arcn)
        indx = ((unsigned)arcn->sb.st_ino) % L_TAB_SZ;
        if ((pt = ltab[indx]) != NULL) {
                /*
-                * it's hash chain in not empty, walk down looking for it
+                * its hash chain in not empty, walk down looking for it
                 */
                ppt = &(ltab[indx]);
                while (pt != NULL) {
@@ -183,9 +169,11 @@ chk_lnk(arcn)
                         * handle hardlinks to regular files differently than
                         * other links.
                         */
-                       arcn->ln_nlen = l_strncpy(arcn->ln_name, pt->name,
-                               sizeof(arcn->ln_name) - 1);
-                       arcn->ln_name[arcn->ln_nlen] = '\0';
+                       arcn->ln_nlen = strlcpy(arcn->ln_name, pt->name,
+                               sizeof(arcn->ln_name));
+                       /* XXX truncate? */
+                       if (arcn->nlen >= sizeof(arcn->name))
+                               arcn->nlen = sizeof(arcn->name) - 1;
                        if (arcn->type == PAX_REG)
                                arcn->type = PAX_HRG;
                        else
@@ -231,18 +219,12 @@ chk_lnk(arcn)
  *     we do not want to accidently point another file at it later on.
  */
 
-#ifdef __STDC__
 void
-purg_lnk(register ARCHD *arcn)
-#else
-void
-purg_lnk(arcn)
-       register ARCHD *arcn;
-#endif
+purg_lnk(ARCHD *arcn)
 {
-       register HRDLNK *pt;
-       register HRDLNK **ppt;
-       register u_int indx;
+       HRDLNK *pt;
+       HRDLNK **ppt;
+       u_int indx;
 
        if (ltab == NULL)
                return;
@@ -291,17 +273,12 @@ purg_lnk(arcn)
  *     write phase
  */
 
-#ifdef __STDC__
 void
 lnk_end(void)
-#else
-void
-lnk_end()
-#endif
 {
-       register int i;
-       register HRDLNK *pt;
-       register HRDLNK *ppt;
+       int i;
+       HRDLNK *pt;
+       HRDLNK *ppt;
 
        if (ltab == NULL)
                return;
@@ -336,14 +313,14 @@ lnk_end()
  * An append with an -u must read the archive and store the modification time
  * for every file on that archive before starting the write phase. It is clear
  * that this is one HUGE database. To save memory space, the actual file names
- * are stored in a scatch file and indexed by an in memory hash table. The
+ * are stored in a scratch file and indexed by an in-memory hash table. The
  * hash table is indexed by hashing the file path. The nodes in the table store
  * the length of the filename and the lseek offset within the scratch file
- * where the actual name is stored. Since there are never any deletions to this
- * table, fragmentation of the scratch file is never a issue. Lookups seem to
- * not exhibit any locality at all (files in the database are rarely
- * looked up more than once...). So caching is just a waste of memory. The
- * only limitation is the amount of scatch file space available to store the
+ * where the actual name is stored. Since there are never any deletions from
+ * this table, fragmentation of the scratch file is never a issue. Lookups 
+ * seem to not exhibit any locality at all (files in the database are rarely
+ * looked up more than once...), so caching is just a waste of memory. The
+ * only limitation is the amount of scratch file space available to store the
  * path names.
  */
 
@@ -356,15 +333,9 @@ lnk_end()
  *     0 if the table and file was created ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ftime_start(void)
-#else
-int
-ftime_start()
-#endif
 {
-       char *pt;
 
        if (ftab != NULL)
                return(0);
@@ -377,14 +348,13 @@ ftime_start()
         * get random name and create temporary scratch file, unlink name
         * so it will get removed on exit
         */
-       pt = strdup("/tmp/paxXXXXXXXXXX");
-       if ((ffd = mkstemp(pt)) < 0) {
-               syswarn(1, errno, "Unable to create temporary file: %s", pt);
-               free(pt);
+       memcpy(tempbase, _TFILE_BASE, sizeof(_TFILE_BASE));
+       if ((ffd = mkstemp(tempfile)) < 0) {
+               syswarn(1, errno, "Unable to create temporary file: %s",
+                   tempfile);
                return(-1);
        }
-       (void)unlink(pt);
-       free(pt);
+       (void)unlink(tempfile);
 
        return(0);
 }
@@ -401,18 +371,12 @@ ftime_start()
  *     -1 on error
  */
 
-#ifdef __STDC__
-int
-chk_ftime(register ARCHD *arcn)
-#else
 int
-chk_ftime(arcn)
-       register ARCHD *arcn;
-#endif
+chk_ftime(ARCHD *arcn)
 {
-       register FTM *pt;
-       register int namelen;
-       register u_int indx;
+       FTM *pt;
+       int namelen;
+       u_int indx;
        char ckname[PAXPATHLEN+1];
 
        /*
@@ -511,7 +475,7 @@ chk_ftime(arcn)
  * Interactive rename table routines
  *
  * The interactive rename table keeps track of the new names that the user
- * assignes to files from tty input. Since this map is unique for each file
+ * assigns to files from tty input. Since this map is unique for each file
  * we must store it in case there is a reference to the file later in archive
  * (a link). Otherwise we will be unable to find the file we know was
  * extracted. The remapping of these files is stored in a memory based hash
@@ -526,13 +490,8 @@ chk_ftime(arcn)
  *     0 if successful, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 name_start(void)
-#else
-int
-name_start()
-#endif
 {
        if (ntab != NULL)
                return(0);
@@ -552,25 +511,17 @@ name_start()
  *     0 if added, -1 otherwise
  */
 
-#ifdef __STDC__
-int
-add_name(register char *oname, int onamelen, char *nname)
-#else
 int
-add_name(oname, onamelen, nname)
-       register char *oname;
-       int onamelen;
-       char *nname;
-#endif
+add_name(char *oname, int onamelen, char *nname)
 {
-       register NAMT *pt;
-       register u_int indx;
+       NAMT *pt;
+       u_int indx;
 
        if (ntab == NULL) {
                /*
                 * should never happen
                 */
-               paxwarn(0, "No interactive rename table, links may fail\n");
+               paxwarn(0, "No interactive rename table, links may fail");
                return(0);
        }
 
@@ -628,19 +579,11 @@ add_name(oname, onamelen, nname)
  *     new name (oname is the link to name)
  */
 
-#ifdef __STDC__
-void
-sub_name(register char *oname, int *onamelen, size_t onamesize)
-#else
 void
-sub_name(oname, onamelen, onamesize)
-       register char *oname;
-       int *onamelen;
-       size_t onamesize;
-#endif
+sub_name(char *oname, int *onamelen, size_t onamesize)
 {
-       register NAMT *pt;
-       register u_int indx;
+       NAMT *pt;
+       u_int indx;
 
        if (ntab == NULL)
                return;
@@ -660,8 +603,9 @@ sub_name(oname, onamelen, onamesize)
                         * found it, replace it with the new name
                         * and return (we know that oname has enough space)
                         */
-                       *onamelen = l_strncpy(oname, pt->nname, onamesize - 1);
-                       oname[*onamelen] = '\0';
+                       *onamelen = strlcpy(oname, pt->nname, onamesize);
+                       if (*onamelen >= onamesize)
+                               *onamelen = onamesize - 1; /* XXX truncate? */
                        return;
                }
                pt = pt->fow;
@@ -720,13 +664,8 @@ sub_name(oname, onamelen, onamesize)
  *     0 if successful, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 dev_start(void)
-#else
-int
-dev_start()
-#endif
 {
        if (dtab != NULL)
                return(0);
@@ -747,14 +686,8 @@ dev_start()
  *     0 if added ok, -1 otherwise
  */
 
-#ifdef __STDC__
-int
-add_dev(register ARCHD *arcn)
-#else
 int
-add_dev(arcn)
-       register ARCHD *arcn;
-#endif
+add_dev(ARCHD *arcn)
 {
        if (chk_dev(arcn->sb.st_dev, 1) == NULL)
                return(-1);
@@ -766,7 +699,7 @@ add_dev(arcn)
  *     check for a device value in the device table. If not found and the add
  *     flag is set, it is added. This does NOT assign any mapping values, just
  *     adds the device number as one that need to be remapped. If this device
- *     is alread mapped, just return with a pointer to that entry.
+ *     is already mapped, just return with a pointer to that entry.
  * Return:
  *     pointer to the entry for this device in the device map table. Null
  *     if the add flag is not set and the device is not in the table (it is
@@ -774,18 +707,11 @@ add_dev(arcn)
  *     is returned (indicates an error).
  */
 
-#ifdef __STDC__
 static DEVT *
 chk_dev(dev_t dev, int add)
-#else
-static DEVT *
-chk_dev(dev, add)
-       dev_t dev;
-       int add;
-#endif
 {
-       register DEVT *pt;
-       register u_int indx;
+       DEVT *pt;
+       u_int indx;
 
        if (dtab == NULL)
                return(NULL);
@@ -839,19 +765,11 @@ chk_dev(dev, add)
  *     0 if all ok, -1 otherwise.
  */
 
-#ifdef __STDC__
-int
-map_dev(register ARCHD *arcn, u_long dev_mask, u_long ino_mask)
-#else
 int
-map_dev(arcn, dev_mask, ino_mask)
-       register ARCHD *arcn;
-       u_long dev_mask;
-       u_long ino_mask;
-#endif
+map_dev(ARCHD *arcn, u_long dev_mask, u_long ino_mask)
 {
-       register DEVT *pt;
-       register DLIST *dpt;
+       DEVT *pt;
+       DLIST *dpt;
        static dev_t lastdev = 0;       /* next device number to try */
        int trc_ino = 0;
        int trc_dev = 0;
@@ -968,14 +886,14 @@ map_dev(arcn, dev_mask, ino_mask)
 /*
  * directory access/mod time reset table routines (for directories READ by pax)
  *
- * The pax -t flag requires that access times of archive files to be the same
+ * The pax -t flag requires that access times of archive files be the same
  * before being read by pax. For regular files, access time is restored after
  * the file has been copied. This database provides the same functionality for
  * directories read during file tree traversal. Restoring directory access time
  * is more complex than files since directories may be read several times until
  * all the descendants in their subtree are visited by fts. Directory access
  * and modification times are stored during the fts pre-order visit (done
- * before any descendants in the subtree is visited) and restored after the
+ * before any descendants in the subtree are visited) and restored after the
  * fts post-order visit (after all the descendants have been visited). In the
  * case of premature exit from a subtree (like from the effects of -n), any
  * directory entries left in this database are reset during final cleanup
@@ -989,13 +907,8 @@ map_dev(arcn, dev_mask, ino_mask)
  *     0 is created ok, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
 atdir_start(void)
-#else
-int
-atdir_start()
-#endif
 {
        if (atab != NULL)
                return(0);
@@ -1014,16 +927,11 @@ atdir_start()
  *     entries are for directories READ by pax
  */
 
-#ifdef __STDC__
 void
 atdir_end(void)
-#else
-void
-atdir_end()
-#endif
 {
-       register ATDIR *pt;
-       register int i;
+       ATDIR *pt;
+       int i;
 
        if (atab == NULL)
                return;
@@ -1050,21 +958,11 @@ atdir_end()
  *     and chained by inode number. This is for directories READ by pax
  */
 
-#ifdef __STDC__
 void
 add_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime)
-#else
-void
-add_atdir(fname, dev, ino, mtime, atime)
-       char *fname;
-       dev_t dev;
-       ino_t ino;
-       time_t mtime;
-       time_t atime;
-#endif
 {
-       register ATDIR *pt;
-       register u_int indx;
+       ATDIR *pt;
+       u_int indx;
 
        if (atab == NULL)
                return;
@@ -1074,7 +972,7 @@ add_atdir(fname, dev, ino, mtime, atime)
         * return (the older entry always has the correct time). The only
         * way this will happen is when the same subtree can be traversed by
         * different args to pax and the -n option is aborting fts out of a
-        * subtree before all the post-order visits have been made).
+        * subtree before all the post-order visits have been made.
         */
        indx = ((unsigned)ino) % A_TAB_SZ;
        if ((pt = atab[indx]) != NULL) {
@@ -1122,21 +1020,12 @@ add_atdir(fname, dev, ino, mtime, atime)
  *     0 if found, -1 if not found.
  */
 
-#ifdef __STDC__
 int
 get_atdir(dev_t dev, ino_t ino, time_t *mtime, time_t *atime)
-#else
-int
-get_atdir(dev, ino, mtime, atime)
-       dev_t dev;
-       ino_t ino;
-       time_t *mtime;
-       time_t *atime;
-#endif
 {
-       register ATDIR *pt;
-       register ATDIR **ppt;
-       register u_int indx;
+       ATDIR *pt;
+       ATDIR **ppt;
+       u_int indx;
 
        if (atab == NULL)
                return(-1);
@@ -1206,31 +1095,18 @@ get_atdir(dev, ino, mtime, atime)
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 dir_start(void)
-#else
-int
-dir_start()
-#endif
 {
-       char *pt;
-
-       if (dirfd != -1)
+       if (dirp != NULL)
                return(0);
 
-       /*
-        * unlink the file so it goes away at termination by itself
-        */
-       pt = strdup("/tmp/paxXXXXXXXXXX");
-       if ((dirfd = mkstemp(pt)) >= 0) {
-               (void)unlink(pt);
-               free(pt);
-               return(0);
+       dirsize = DIRP_SIZE;
+       if ((dirp = calloc(dirsize, sizeof(DIRDATA))) == NULL) {
+               paxwarn(1, "Unable to allocate memory for directory times");
+               return(-1);
        }
-       paxwarn(1, "Unable to create temporary file for directory times: %s", pt);
-       free(pt);
-       return(-1);
+       return(0);
 }
 
 /*
@@ -1246,48 +1122,43 @@ dir_start()
  *     pax spec)
  */
 
-#ifdef __STDC__
 void
-add_dir(char *name, int nlen, struct stat *psb, int frc_mode)
-#else
-void
-add_dir(name, nlen, psb, frc_mode)
-       char *name;
-       int nlen;
-       struct stat *psb;
-       int frc_mode;
-#endif
+add_dir(char *name, struct stat *psb, int frc_mode)
 {
-       DIRDATA dblk;
+       DIRDATA *dblk;
+       char realname[MAXPATHLEN], *rp;
 
-       if (dirfd < 0)
+       if (dirp == NULL)
                return;
 
-       /*
-        * get current position (where file name will start) so we can store it
-        * in the trailer
-        */
-       if ((dblk.npos = lseek(dirfd, 0L, SEEK_CUR)) < 0) {
-               paxwarn(1,"Unable to store mode and times for directory: %s",name);
-               return;
+       if (havechd && *name != '/') {
+               if ((rp = realpath(name, realname)) == NULL) {
+                       paxwarn(1, "Cannot canonicalize %s", name);
+                       return;
+               }
+               name = rp;
        }
-
-       /*
-        * write the file name followed by the trailer
-        */
-       dblk.nlen = nlen + 1;
-       dblk.mode = psb->st_mode & 0xffff;
-       dblk.mtime = psb->st_mtime;
-       dblk.atime = psb->st_atime;
-       dblk.frc_mode = frc_mode;
-       if ((write(dirfd, name, dblk.nlen) == dblk.nlen) &&
-           (write(dirfd, (char *)&dblk, sizeof(dblk)) == sizeof(dblk))) {
-               ++dircnt;
+       if (dircnt == dirsize) {
+               dblk = realloc(dirp, 2 * dirsize * sizeof(DIRDATA));
+               if (dblk == NULL) {
+                       paxwarn(1, "Unable to store mode and times for created"
+                           " directory: %s", name);
+                       return;
+               }
+               dirp = dblk;
+               dirsize *= 2;
+       }
+       dblk = &dirp[dircnt];
+       if ((dblk->name = strdup(name)) == NULL) {
+               paxwarn(1, "Unable to store mode and times for created"
+                   " directory: %s", name);
                return;
        }
-
-       paxwarn(1,"Unable to store mode and times for created directory: %s",name);
-       return;
+       dblk->mode = psb->st_mode & 0xffff;
+       dblk->mtime = psb->st_mtime;
+       dblk->atime = psb->st_atime;
+       dblk->frc_mode = frc_mode;
+       ++dircnt;
 }
 
 /*
@@ -1296,54 +1167,34 @@ add_dir(name, nlen, psb, frc_mode)
  *     by pax
  */
 
-#ifdef __STDC__
 void
 proc_dir(void)
-#else
-void
-proc_dir()
-#endif
 {
-       char name[PAXPATHLEN+1];
-       DIRDATA dblk;
-       u_long cnt;
+       DIRDATA *dblk;
+       long cnt;
 
-       if (dirfd < 0)
+       if (dirp == NULL)
                return;
        /*
         * read backwards through the file and process each directory
         */
-       for (cnt = 0; cnt < dircnt; ++cnt) {
-               /*
-                * read the trailer, then the file name, if this fails
-                * just give up.
-                */
-               if (lseek(dirfd, -((off_t)sizeof(dblk)), SEEK_CUR) < 0)
-                       break;
-               if (read(dirfd,(char *)&dblk, sizeof(dblk)) != sizeof(dblk))
-                       break;
-               if (lseek(dirfd, dblk.npos, SEEK_SET) < 0)
-                       break;
-               if (read(dirfd, name, dblk.nlen) != dblk.nlen)
-                       break;
-               if (lseek(dirfd, dblk.npos, SEEK_SET) < 0)
-                       break;
-
+       cnt = dircnt;
+       while (--cnt >= 0) {
                /*
                 * frc_mode set, make sure we set the file modes even if
                 * the user didn't ask for it (see file_subs.c for more info)
                 */
-               if (pmode || dblk.frc_mode)
-                       set_pmode(name, dblk.mode);
+               dblk = &dirp[cnt];
+               if (pmode || dblk->frc_mode)
+                       set_pmode(dblk->name, dblk->mode);
                if (patime || pmtime)
-                       set_ftime(name, dblk.mtime, dblk.atime, 0);
+                       set_ftime(dblk->name, dblk->mtime, dblk->atime, 0);
+               free(dblk->name);
        }
 
-       (void)close(dirfd);
-       dirfd = -1;
-       if (cnt != dircnt)
-               paxwarn(1,"Unable to set mode and times for created directories");
-       return;
+       free(dirp);
+       dirp = NULL;
+       dircnt = 0;
 }
 
 /*
@@ -1364,24 +1215,16 @@ proc_dir()
  *     the hash value of the string MOD (%) the table size.
  */
 
-#ifdef __STDC__
 u_int
 st_hash(char *name, int len, int tabsz)
-#else
-u_int
-st_hash(name, len, tabsz)
-       char *name;
-       int len;
-       int tabsz;
-#endif
 {
-       register char *pt;
-       register char *dest;
-       register char *end;
-       register int i;
-       register u_int key = 0;
-       register int steps;
-       register int res;
+       char *pt;
+       char *dest;
+       char *end;
+       int i;
+       u_int key = 0;
+       int steps;
+       int res;
        u_int val;
 
        /*
index 1d9c8130ba660f3938d70b40cec97d8e3f80173d..bc19f0669483f50e62a3fce335f2a62f9daccf70 100644 (file)
--- a/tables.h
+++ b/tables.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tables.h,v 1.2 1996/06/23 14:20:43 deraadt Exp $      */
+/*     $OpenBSD: tables.h,v 1.8 2006/08/05 23:05:13 ray Exp $  */
 /*     $NetBSD: tables.h,v 1.3 1995/03/21 09:07:47 cgd Exp $   */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -47,7 +43,7 @@
 /*
  * Hash Table Sizes MUST BE PRIME, if set too small performance suffers.
  * Probably safe to expect 500000 inodes per tape. Assuming good key
- * distribution (inodes) chains of under 50 long (worse case) is ok.
+ * distribution (inodes) chains of under 50 long (worst case) is ok.
  */
 #define L_TAB_SZ       2503            /* hard link hash table size */
 #define F_TAB_SZ       50503           /* file time hash table size */
@@ -55,6 +51,7 @@
 #define D_TAB_SZ       317             /* unique device mapping table */
 #define A_TAB_SZ       317             /* ftree dir access time reset table */
 #define MAXKEYLEN      64              /* max number of chars for hash */
+#define DIRP_SIZE      64              /* initial size of created dir table */
 
 /*
  * file hard link structure (hashed by dev/ino and chained) used to find the
@@ -82,7 +79,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;
 
@@ -108,7 +105,7 @@ typedef struct namt {
  * this table. (When the inode field in the archive header are too small, we
  * remap the dev on writes to remove accidental collisions).
  *
- * The list is hashed by device number using chain collision resolution. Off of 
+ * The list is hashed by device number using chain collision resolution. Off of
  * each DEVT are linked the various remaps for this device based on those bits
  * in the inode which were truncated. For example if we are just remapping to
  * avoid a device number during an update append, off the DEVT we would have
@@ -138,7 +135,7 @@ typedef struct dlist {
 } DLIST;
 
 /*
- * ftree directory access time reset table. When we are done with with a
+ * ftree directory access time reset table. When we are done with a
  * subtree we reset the access and mod time of the directory when the tflag is
  * set. Not really explicitly specified in the pax spec, but easy and fast to
  * do (and this may have even been intended in the spec, it is not clear).
@@ -161,15 +158,13 @@ typedef struct atdir {
  * times and/or modes). We must reset time in the reverse order of creation,
  * because entries are added  from the top of the file tree to the bottom.
  * We MUST reset times from leaf to root (it will not work the other
- * direction).  Entries are recorded into a spool file to make reverse
- * reading faster.
+ * direction).
  */
 
 typedef struct dirdata {
-       int nlen;       /* length of the directory name (includes \0) */
-       off_t npos;     /* position in file where this dir name starts */
-       mode_t mode;    /* file mode to restore */
+       char *name;     /* file name */
        time_t mtime;   /* mtime to set */
        time_t atime;   /* atime to set */
-       int frc_mode;   /* do we force mode settings? */
+       u_int16_t mode; /* file mode to restore */
+       u_int16_t frc_mode;     /* do we force mode settings? */
 } DIRDATA;
diff --git a/tar.1 b/tar.1
index 907eb460aeed9f240c093e6c140d5e5487a71f78..a411bc0c15a24c46914245f681fd1e220a7f9367 100644 (file)
--- a/tar.1
+++ b/tar.1
@@ -1,3 +1,4 @@
+.\"    $OpenBSD: tar.1,v 1.50 2008/06/11 00:49:08 pvalchev Exp $
 .\"
 .\" Copyright (c) 1996 SigmaSoft, Th. Lockert
 .\" All rights reserved.
 .\" 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
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\"    $OpenBSD: tar.1,v 1.17 1998/09/23 00:13:49 aaron Exp $
+.\"    $OpenBSD: tar.1,v 1.50 2008/06/11 00:49:08 pvalchev Exp $
 .\"
-.Dd June 11, 1996
+.Dd $Mdocdate: June 11 2008 $
 .Dt TAR 1
 .Os
 .Sh NAME
 .Nm tar
 .Nd tape archiver
 .Sh SYNOPSIS
-.Nm
-.No [-]{crtux}[befhmopvwzHLPXZ014578]
-.Op Ar archive
-.Op Ar blocksize
-.\" XXX how to do this right?
-.No [-C
-.Ar directory
-.No ]
-.No [-s
-.Ar replstr
-.No ]
-.Ar file1
-.Op Ar file2 ...
+.Nm tar
+.Sm off
+.No { Cm crtux No } Op Cm 014578befHhjLmOoPpqsvwXZz
+.Sm on
+.Bk -words
+.Op Ar blocking-factor | archive | replstr
+.Op Fl C Ar directory
+.Op Fl I Ar file
+.Op Ar file ...
+.Ek
+.Nm tar
+.No { Ns Fl crtux Ns }
+.Op Fl 014578eHhjLmOoPpqvwXZz
+.Op Fl b Ar blocking-factor
+.Op Fl C Ar directory
+.Op Fl f Ar archive
+.Op Fl I Ar file
+.Op Fl s Ar replstr
+.Op Ar file ...
 .Sh DESCRIPTION
 The
 .Nm
 command creates, adds files to, or extracts files from an
-archive file in \*Qtar\*U format.  A tar archive is often
-stored on a magnetic tape, but can be a floppy or a regular
-disk file.
+archive file in
+.Dq tar
+format.
+A tar archive is often stored on a magnetic tape, but can be
+stored equally well on a floppy, CD-ROM, or in a regular disk file.
+.Pp
+In the first (legacy) form, all option flags except for
+.Fl C
+and
+.Fl I
+must be contained within the first argument to
+.Nm
+and must not be prefixed by a hyphen
+.Pq Sq - .
+Option arguments, if any, are processed as subsequent arguments to
+.Nm
+and are processed in the order in which their corresponding option
+flags have been presented on the command line.
+.Pp
+In the second and preferred form, option flags may be given in any order
+and are immediately followed by their corresponding option argument
+values.
 .Pp
 One of the following flags must be present:
-.Bl -tag -width Ar
+.Bl -tag -width Ds
 .It Fl c
 Create new archive, or overwrite an existing archive,
 adding the specified files to it.
 .It Fl r
-Append the named new files to existing archive.  Note that
-this will only work on media on which an end-of-file mark
+Append the named new files to existing archive.
+Note that this will only work on media on which an end-of-file mark
 can be overwritten.
 .It Fl t
-List contents of archive.  If any files are named on the
+List contents of archive.
+If any files are named on the
 command line, only those files will be listed.
+The
+.Ar file
+arguments may be specified as glob patterns (see
+.Xr glob 3
+for more information), in which case
+.Nm
+will list all archive members that match each pattern.
 .It Fl u
 Alias for
 .Fl r .
 .It Fl x
-Extract files from archive.  If any files are named on the
+Extract files from archive.
+If any files are named on the
 command line, only those files will be extracted from the
-archive.  If more than one copy of a file exists in the
+archive.
+The
+.Ar file
+arguments may be specified as glob patterns (see
+.Xr glob 3
+for more information), in which case
+.Nm
+will extract all archive members that match each pattern.
+.Pp
+If more than one copy of a file exists in the
 archive, later copies will overwrite earlier copies during
-extraction.  The file mode and modification time are preserved
-if possible.  The file mode is subject to modification by the
+extraction.
+The file mode and modification time are preserved
+if possible.
+The file mode is subject to modification by the
 .Xr umask 2 .
 .El
 .Pp
 In addition to the flags mentioned above, any of the following
 flags may be used:
-.Bl -tag -width Ar
-.It Fl b Ar "blocking factor"
+.Bl -tag -width Ds
+.It Fl b Ar blocking-factor
 Set blocking factor to use for the archive.
 .Nm
-uses 512 byte blocks.  The default is 20, the maximum is 126.
-Archives with a blocking factor larger 63 violate the
+uses 512-byte blocks.
+The default is 20, the maximum is 126.
+Archives with a blocking factor larger than 63 violate the
 .Tn POSIX
 standard and will not be portable to all systems.
+.It Fl C Ar directory
+This is a positional argument which sets the working directory for the
+following files.
+When extracting, files will be extracted into
+the specified directory; when creating, the specified files will be matched
+from the directory.
 .It Fl e
-Stop after first error.
+Stop after the first error.
 .It Fl f Ar archive
-Filename where the archive is stored.  Defaults to
+Filename where the archive is stored.
+Defaults to
 .Pa /dev/rst0 .
+.It Fl H
+Follow symlinks given on the command line only.
 .It Fl h
 Follow symbolic links as if they were normal files
 or directories.
+In extract mode this means that a directory entry in the archive
+will not overwrite an existing symbolic link, but rather what the
+link ultimately points to.
+.It Fl I Ar file
+This is a positional argument which reads the names of files to
+archive or extract from the given file, one per line.
+.It Fl j
+Compress archive using bzip2.
+The bzip2 utility must be installed separately.
+.It Fl L
+Synonym for the
+.Fl h
+option.
 .It Fl m
 Do not preserve modification time.
 .It Fl O
@@ -111,104 +175,164 @@ is unable to decode.
 This implies the
 .Fl O
 flag.
+.It Fl P
+Do not strip leading slashes
+.Pq Sq /
+from pathnames.
+The default is to strip leading slashes.
 .It Fl p
 Preserve user and group ID as well as file mode regardless of
 the current
 .Xr umask 2 .
 The setuid and setgid bits are only preserved if the user is
-the superuser.  Only meaningful in conjunction with the
+the superuser.
+Only meaningful in conjunction with the
 .Fl x
 flag.
-.It Fl s Ar replstr
-Modify the file or archive member names specified by the
-.Ar pattern
-or
+.It Fl q
+Select the first archive member that matches each
 .Ar file
-operands according to the substitution expression
+operand.
+No more than one archive member is matched for each
+.Ar file .
+When members of type directory are matched, the file hierarchy rooted at that
+directory is also matched.
+.It Fl s Ar replstr
+Modify the archive member names according to the substitution expression
 .Ar replstr ,
 using the syntax of the
 .Xr ed 1
 utility regular expressions.
-The format of these regular expressions are:
+.Ar file
+arguments may be given to restrict the list of archive members to those
+specified.
+.Pp
+The format of these regular expressions is
+.Pp
 .Dl /old/new/[gp]
+.Pp
 As in
 .Xr ed 1 ,
-.Cm old
-is a basic regular expression and
-.Cm new
-can contain an ampersand (&), \\n (where n is a digit) back-references,
+.Va old
+is a basic regular expression (see
+.Xr re_format 7 )
+and
+.Va new
+can contain an ampersand
+.Pq Ql & ,
+.Ql \e Ns Em n
+(where
+.Em n
+is a digit) back-references,
 or subexpression matching.
 The
-.Cm old
-string may also contain
-.Dv <newline>
-characters.
-Any non-null character can be used as a delimiter (/ is shown here).
+.Va old
+string may also contain newline characters.
+Any non-null character can be used as a delimiter
+.Po
+.Ql /
+is shown here
+.Pc .
 Multiple
 .Fl s
 expressions can be specified.
 The expressions are applied in the order they are specified on the
 command line, terminating with the first successful substitution.
+.Pp
 The optional trailing
 .Cm g
-continues to apply the substitution expression to the pathname substring
+continues to apply the substitution expression to the pathname substring,
 which starts with the first character following the end of the last successful
-substitution. The first unsuccessful substitution stops the operation of the
+substitution.
+The first unsuccessful substitution stops the operation of the
 .Cm g
 option.
 The optional trailing
 .Cm p
 will cause the final result of a successful substitution to be written to
-.Dv standard error
-in the following format:
-.Dl <original pathname> >> <new pathname>
+standard error in the following format:
+.Pp
+.D1 Em original-pathname No >> Em new-pathname
+.Pp
 File or archive member names that substitute to the empty string
 are not selected and will be skipped.
 .It Fl v
 Verbose operation mode.
 .It Fl w
-Interactively rename files.  This option causes
+Interactively rename files.
+This option causes
 .Nm
 to prompt the user for the filename to use when storing or
 extracting files in an archive.
-.It Fl z
-Compress archive using gzip.
-.It Fl C Ar directory
-This is a positional argument which sets the working directory for the
-following files.  When extracting, files will be extracted into
-the specified directory; when creating, the specified files will be matched
-from the directory.
-.It Fl H
-Follow symlinks given on command line only.
-.It Fl L
-Follow all symlinks.
-.It Fl P
-Do not strip leading slashes (``/'') from pathnames.
-The default is to strip leading slashes.
 .It Fl X
 Do not cross mount points in the file system.
 .It Fl Z
-Compress archive using compress.
+Compress archive using
+.Xr compress 1 .
+.It Fl z
+Compress archive using
+.Xr gzip 1 .
 .El
 .Pp
 The options
 .Op Fl 014578
 can be used to select one of the compiled-in backup devices,
 .Pa /dev/rstN .
+.Sh ENVIRONMENT
+.Bl -tag -width Fl
+.It Ev TMPDIR
+Path in which to store temporary files.
+.It Ev TAPE
+Default tape device to use instead of
+.Pa /dev/rst0 .
+.El
 .Sh FILES
 .Bl -tag -width "/dev/rst0"
 .It Pa /dev/rst0
 default archive name
 .El
-.Sh SEE ALSO
-.Xr cpio 1 ,
-.Xr pax 1
-.Sh AUTHOR
-Keith Muller at the University of California, San Diego.
-.Sh ERRORS
+.Sh EXAMPLES
+Create an archive on the default tape drive, containing the files named
+.Pa bonvole
+and
+.Pa sekve :
+.Pp
+.Dl $ tar c bonvole sekve
+.Pp
+Output a
+.Xr gzip 1
+compressed archive containing the files
+.Pa bonvole
+and
+.Pa sekve
+to a file called
+.Pa foriru.tar.gz :
+.Pp
+.Dl $ tar zcf foriru.tar.gz bonvole sekve
+.Pp
+Verbosely create an archive, called
+.Pa backup.tar.gz ,
+of all files matching the shell
+.Xr glob 3
+function
+.Pa *.c :
+.Pp
+.Dl $ tar zcvf backup.tar.gz *.c
+.Pp
+Verbosely list, but do not extract, all files ending in
+.Pa .jpeg
+from a compressed archive named
+.Pa backup.tar.gz .
+Note that the glob pattern has been quoted to avoid expansion by the shell:
+.Pp
+.Dl $ tar tvzf backup.tar.gz '*.jpeg'
+.Pp
+For more detailed examples, see
+.Xr pax 1 .
+.Sh DIAGNOSTICS
 .Nm
 will exit with one of the following values:
-.Bl -tag -width 2n
+.Bl -tag -width 2n -offset indent
 .It 0
 All files were processed successfully.
 .It 1
@@ -219,11 +343,12 @@ Whenever
 .Nm
 cannot create a file or a link when extracting an archive or cannot
 find a file while writing an archive, or cannot preserve the user
-ID, group ID, file mode or access and modification times when the
+ID, group ID, file mode, or access and modification times when the
 .Fl p
 option is specified, a diagnostic message is written to standard
 error and a non-zero exit value will be returned, but processing
-will continue.  In the case where
+will continue.
+In the case where
 .Nm
 cannot create a link to a file,
 .Nm
@@ -240,5 +365,23 @@ be wrong.
 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
+may have only partially created the archive, which may violate the
 specific archive format specification.
+.Sh SEE ALSO
+.Xr cpio 1 ,
+.Xr pax 1
+.Sh HISTORY
+A
+.Nm
+command first appeared in
+.At v7 .
+.Sh AUTHORS
+Keith Muller at the University of California, San Diego.
+.Sh CAVEATS
+The
+.Fl j
+and
+.Fl L
+flags are not portable to other versions of
+.Nm
+where they may have a different meaning.
diff --git a/tar.c b/tar.c
index c73657d5d85afd01664dab2a269ece4a5c5ed8c2..6a0b3b32963aa4e15685d76a105d04c7626c58ba 100644 (file)
--- a/tar.c
+++ b/tar.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tar.c,v 1.13 1998/09/26 21:29:41 millert Exp $        */
+/*     $OpenBSD: tar.c,v 1.41 2006/03/04 20:24:55 otto Exp $   */
 /*     $NetBSD: tar.c,v 1.5 1995/03/21 09:07:49 cgd Exp $      */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)tar.c      8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)tar.c        8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: tar.c,v 1.13 1998/09/26 21:29:41 millert Exp $";
+static const char rcsid[] = "$OpenBSD: tar.c,v 1.41 2006/03/04 20:24:55 otto Exp $";
 #endif
 #endif /* not lint */
 
@@ -62,18 +58,26 @@ static char rcsid[] = "$OpenBSD: tar.c,v 1.13 1998/09/26 21:29:41 millert Exp $"
  * Routines for reading, writing and header identify of various versions of tar
  */
 
-static u_long tar_chksm __P((register char *, register int));
-static char *name_split __P((register char *, register int));
-static int ul_oct __P((u_long, register char *, register int, int));
-#ifndef NET2_STAT
-static int uqd_oct __P((u_quad_t, register char *, register int, int));
+static size_t expandname(char *, size_t, char **, const char *, size_t);
+static u_long tar_chksm(char *, int);
+static char *name_split(char *, int);
+static int ul_oct(u_long, char *, int, int);
+#ifndef LONG_OFF_T
+static int uqd_oct(u_quad_t, char *, int, int);
 #endif
 
+static uid_t uid_nobody;
+static uid_t uid_warn;
+static gid_t gid_nobody;
+static gid_t gid_warn;
+
 /*
  * Routines common to all versions of tar
  */
 
 static int tar_nodir;                  /* do not write dirs under old tar */
+char *gnu_name_string;                 /* GNU ././@LongLink hackery name */
+char *gnu_link_string;                 /* GNU ././@LongLink hackery link */
 
 /*
  * tar_endwr()
@@ -82,13 +86,8 @@ static int tar_nodir;                        /* do not write dirs under old tar */
  *     0 if ok, -1 otherwise (what wr_skip returns)
  */
 
-#ifdef __STDC__
 int
 tar_endwr(void)
-#else
-int
-tar_endwr()
-#endif
 {
        return(wr_skip((off_t)(NULLCNT*BLKMULT)));
 }
@@ -100,13 +99,8 @@ tar_endwr()
  *     size of trailer (2 * BLKMULT)
  */
 
-#ifdef __STDC__
 off_t
 tar_endrd(void)
-#else
-off_t
-tar_endrd()
-#endif
 {
        return((off_t)(NULLCNT*BLKMULT));
 }
@@ -122,18 +116,10 @@ tar_endrd()
  *     could never contain a header.
  */
 
-#ifdef __STDC__
-int
-tar_trail(register char *buf, register int in_resync, register int *cnt)
-#else
 int
-tar_trail(buf, in_resync, cnt)
-       register char *buf;
-       register int in_resync;
-       register int *cnt;
-#endif
+tar_trail(ARCHD *ignore, char *buf, int in_resync, int *cnt)
 {
-       register int i;
+       int i;
 
        /*
         * look for all zero, trailer is two consecutive blocks of zero
@@ -173,25 +159,16 @@ tar_trail(buf, in_resync, cnt)
  *     0 if the number fit into the string, -1 otherwise
  */
 
-#ifdef __STDC__
-static int
-ul_oct(u_long val, register char *str, register int len, int term)
-#else
 static int
-ul_oct(val, str, len, term)
-       u_long val;
-       register char *str;
-       register int len;
-       int term;
-#endif
+ul_oct(u_long val, char *str, int len, int term)
 {
-       register char *pt;
+       char *pt;
 
        /*
         * term selects the appropriate character(s) for the end of the string
         */
        pt = str + len - 1;
-       switch(term) {
+       switch (term) {
        case 3:
                *pt-- = '\0';
                break;
@@ -225,7 +202,7 @@ ul_oct(val, str, len, term)
        return(0);
 }
 
-#ifndef NET2_STAT
+#ifndef LONG_OFF_T
 /*
  * uqd_oct()
  *     convert an u_quad_t to an octal string. one of many oddball field
@@ -237,25 +214,16 @@ ul_oct(val, str, len, term)
  *     0 if the number fit into the string, -1 otherwise
  */
 
-#ifdef __STDC__
-static int
-uqd_oct(u_quad_t val, register char *str, register int len, int term)
-#else
 static int
-uqd_oct(val, str, len, term)
-       u_quad_t val;
-       register char *str;
-       register int len;
-       int term;
-#endif
+uqd_oct(u_quad_t val, char *str, int len, int term)
 {
-       register char *pt;
+       char *pt;
 
        /*
         * term selects the appropriate character(s) for the end of the string
         */
        pt = str + len - 1;
-       switch(term) {
+       switch (term) {
        case 3:
                *pt-- = '\0';
                break;
@@ -293,26 +261,19 @@ uqd_oct(val, str, len, term)
 /*
  * tar_chksm()
  *     calculate the checksum for a tar block counting the checksum field as
- *     all blanks (BLNKSUM is that value pre-calculated, the sume of 8 blanks).
+ *     all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks).
  *     NOTE: we use len to short circuit summing 0's on write since we ALWAYS
  *     pad headers with 0.
  * Return:
  *     unsigned long checksum
  */
 
-#ifdef __STDC__
 static u_long
-tar_chksm(register char *blk, register int len)
-#else
-static u_long
-tar_chksm(blk, len)
-       register char *blk;
-       register int len;
-#endif
+tar_chksm(char *blk, int len)
 {
-       register char *stop;
-       register char *pt;
-       u_long chksm = BLNKSUM; /* inital value is checksum field sum */
+       char *stop;
+       char *pt;
+       u_long chksm = BLNKSUM; /* initial value is checksum field sum */
 
        /*
         * add the part of the block before the checksum field
@@ -348,18 +309,11 @@ tar_chksm(blk, len)
  *     0 if a tar header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
-tar_id(register char *blk, int size)
-#else
-int
-tar_id(blk, size)
-       register char *blk;
-       int size;
-#endif
+tar_id(char *blk, int size)
 {
-       register HD_TAR *hd;
-       register HD_USTAR *uhd;
+       HD_TAR *hd;
+       HD_USTAR *uhd;
 
        if (size < BLKMULT)
                return(-1);
@@ -379,6 +333,7 @@ tar_id(blk, size)
                return(-1);
        if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
                return(-1);
+       force_one_volume = 1;
        return(0);
 }
 
@@ -389,13 +344,8 @@ tar_id(blk, size)
  *     0 if ok -1 otherwise
  */
 
-#ifdef __STDC__
 int
 tar_opt(void)
-#else
-int
-tar_opt()
-#endif
 {
        OPLIST *opt;
 
@@ -431,39 +381,40 @@ tar_opt()
  *     0
  */
 
-#ifdef __STDC__
 int
-tar_rd(register ARCHD *arcn, register char *buf)
-#else
-int
-tar_rd(arcn, buf)
-       register ARCHD *arcn;
-       register char *buf;
-#endif
+tar_rd(ARCHD *arcn, char *buf)
 {
-       register HD_TAR *hd;
-       register char *pt;
+       HD_TAR *hd;
+       char *pt;
 
        /*
         * we only get proper sized buffers passed to us
         */
        if (tar_id(buf, BLKMULT) < 0)
                return(-1);
+       memset(arcn, 0, sizeof(*arcn));
        arcn->org_name = arcn->name;
        arcn->sb.st_nlink = 1;
-       arcn->pat = NULL;
 
        /*
         * copy out the name and values in the stat buffer
         */
        hd = (HD_TAR *)buf;
-       arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(arcn->name) - 1);
-       arcn->name[arcn->nlen] = '\0';
+       if (hd->linkflag != LONGLINKTYPE && hd->linkflag != LONGNAMETYPE) {
+               arcn->nlen = expandname(arcn->name, sizeof(arcn->name),
+                   &gnu_name_string, hd->name, sizeof(hd->name));
+               arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
+                   &gnu_link_string, hd->linkname, sizeof(hd->linkname));
+       }
        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);
        arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
-       arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#ifdef LONG_OFF_T
+       arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#else
+       arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+#endif
        arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
        arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
 
@@ -474,16 +425,13 @@ tar_rd(arcn, buf)
        pt = &(arcn->name[arcn->nlen - 1]);
        arcn->pad = 0;
        arcn->skip = 0;
-       switch(hd->linkflag) {
+       switch (hd->linkflag) {
        case SYMTYPE:
                /*
                 * symbolic link, need to get the link name and set the type in
                 * the st_mode so -v printing will look correct.
                 */
                arcn->type = PAX_SLK;
-               arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
-                       sizeof(arcn->ln_name) - 1);
-               arcn->ln_name[arcn->ln_nlen] = '\0';
                arcn->sb.st_mode |= S_IFLNK;
                break;
        case LNKTYPE:
@@ -493,9 +441,6 @@ tar_rd(arcn, buf)
                 */
                arcn->type = PAX_HLK;
                arcn->sb.st_nlink = 2;
-               arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
-                       sizeof(arcn->ln_name) - 1);
-               arcn->ln_name[arcn->ln_nlen] = '\0';
 
                /*
                 * no idea of what type this thing really points at, but
@@ -503,6 +448,17 @@ tar_rd(arcn, buf)
                 */
                arcn->sb.st_mode |= S_IFREG;
                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->linkflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
+               arcn->pad = TAR_PAD(arcn->sb.st_size);
+               arcn->skip = arcn->sb.st_size;
+               break;
        case DIRTYPE:
                /*
                 * It is a directory, set the mode for -v printing
@@ -510,8 +466,6 @@ tar_rd(arcn, buf)
                arcn->type = PAX_DIR;
                arcn->sb.st_mode |= S_IFDIR;
                arcn->sb.st_nlink = 2;
-               arcn->ln_name[0] = '\0';
-               arcn->ln_nlen = 0;
                break;
        case AREGTYPE:
        case REGTYPE:
@@ -531,7 +485,7 @@ tar_rd(arcn, buf)
                } else {
                        /*
                         * have a file that will be followed by data. Set the
-                        * skip value to the size field and caluculate the size
+                        * skip value to the size field and calculate the size
                         * of the padding.
                         */
                        arcn->type = PAX_REG;
@@ -546,7 +500,7 @@ tar_rd(arcn, buf)
         * strip off any trailing slash.
         */
        if (*pt == '/') {
-               *pt = '\0'; 
+               *pt = '\0';
                --arcn->nlen;
        }
        return(0);
@@ -564,23 +518,17 @@ tar_rd(arcn, buf)
  *     data to write after the header, -1 if archive write failed
  */
 
-#ifdef __STDC__
 int
-tar_wr(register ARCHD *arcn)
-#else
-int
-tar_wr(arcn)
-       register ARCHD *arcn;
-#endif
+tar_wr(ARCHD *arcn)
 {
-       register HD_TAR *hd;
+       HD_TAR *hd;
        int len;
        char hdblk[sizeof(HD_TAR)];
 
        /*
         * check for those file system types which tar cannot store
         */
-       switch(arcn->type) {
+       switch (arcn->type) {
        case PAX_DIR:
                /*
                 * user asked that dirs not be written to the archive
@@ -605,7 +553,8 @@ tar_wr(arcn)
        case PAX_HLK:
        case PAX_HRG:
                if (arcn->ln_nlen > sizeof(hd->linkname)) {
-                       paxwarn(1,"Link name too long for tar %s", arcn->ln_name);
+                       paxwarn(1, "Link name too long for tar %s",
+                           arcn->ln_name);
                        return(1);
                }
                break;
@@ -621,32 +570,31 @@ tar_wr(arcn)
        len = arcn->nlen;
        if (arcn->type == PAX_DIR)
                ++len;
-       if (len >= sizeof(hd->name)) {
+       if (len > sizeof(hd->name)) {
                paxwarn(1, "File name too long for tar %s", arcn->name);
                return(1);
        }
 
        /*
-        * copy the data out of the ARCHD into the tar header based on the type
-        * of the file. Remember many tar readers want the unused fields to be
-        * padded with zero. We set the linkflag field (type), the linkname
-        * (or zero if not used),the size, and set the padding (if any) to be
-        * added after the file data (0 for all other types, as they only have
-        * a header)
+        * Copy the data out of the ARCHD into the tar header based on the type
+        * of the file. Remember, many tar readers want all fields to be
+        * padded with zero so we zero the header first.  We then set the
+        * linkflag field (type), the linkname, the size, and set the padding
+        * (if any) to be added after the file data (0 for all other types,
+        * as they only have a header).
         */
+       memset(hdblk, 0, sizeof(hdblk));
        hd = (HD_TAR *)hdblk;
-       l_strncpy(hd->name, arcn->name, sizeof(hd->name) - 1);
-       hd->name[sizeof(hd->name) - 1] = '\0';
+       fieldcpy(hd->name, sizeof(hd->name), arcn->name, sizeof(arcn->name));
        arcn->pad = 0;
 
        if (arcn->type == PAX_DIR) {
                /*
                 * directories are the same as files, except have a filename
-                * that ends with a /, we add the slash here. No data follows,
+                * that ends with a /, we add the slash here. No data follows
                 * dirs, so no pad.
                 */
                hd->linkflag = AREGTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
                hd->name[len-1] = '/';
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
                        goto out;
@@ -655,8 +603,8 @@ tar_wr(arcn)
                 * no data follows this file, so no pad
                 */
                hd->linkflag = SYMTYPE;
-               l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
-               hd->linkname[sizeof(hd->linkname) - 1] = '\0';
+               fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name,
+                   sizeof(arcn->ln_name));
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
                        goto out;
        } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
@@ -664,8 +612,8 @@ tar_wr(arcn)
                 * no data follows this file, so no pad
                 */
                hd->linkflag = LNKTYPE;
-               l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
-               hd->linkname[sizeof(hd->linkname) - 1] = '\0';
+               fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name,
+                   sizeof(arcn->ln_name));
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
                        goto out;
        } else {
@@ -673,8 +621,7 @@ tar_wr(arcn)
                 * data follows this file, so set the pad
                 */
                hd->linkflag = AREGTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                if (ul_oct((u_long)arcn->sb.st_size, hd->size,
                    sizeof(hd->size), 1)) {
 #              else
@@ -693,7 +640,7 @@ tar_wr(arcn)
        if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) ||
            ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) ||
            ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) ||
-           ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
+           ul_oct((u_long)(u_int)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
                goto out;
 
        /*
@@ -731,13 +678,8 @@ tar_wr(arcn)
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ustar_strd(void)
-#else
-int
-ustar_strd()
-#endif
 {
        if ((usrtb_start() < 0) || (grptb_start() < 0))
                return(-1);
@@ -751,13 +693,8 @@ ustar_strd()
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ustar_stwr(void)
-#else
-int
-ustar_stwr()
-#endif
 {
        if ((uidtb_start() < 0) || (gidtb_start() < 0))
                return(-1);
@@ -772,17 +709,10 @@ ustar_stwr()
  *     0 if a ustar header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ustar_id(char *blk, int size)
-#else
-int
-ustar_id(blk, size)
-       char *blk;
-       int size;
-#endif
 {
-       register HD_USTAR *hd;
+       HD_USTAR *hd;
 
        if (size < BLKMULT)
                return(-1);
@@ -794,7 +724,7 @@ ustar_id(blk, size)
         * 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.
         */
-       if (hd->name[0] == '\0')
+       if (hd->prefix[0] == '\0' && hd->name[0] == '\0')
                return(-1);
        if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0)
                return(-1);
@@ -811,19 +741,12 @@ ustar_id(blk, size)
  *     0
  */
 
-#ifdef __STDC__
 int
-ustar_rd(register ARCHD *arcn, register char *buf)
-#else
-int
-ustar_rd(arcn, buf)
-       register ARCHD *arcn;
-       register char *buf;
-#endif
+ustar_rd(ARCHD *arcn, char *buf)
 {
-       register HD_USTAR *hd;
-       register char *dest;
-       register int cnt = 0;
+       HD_USTAR *hd;
+       char *dest;
+       int cnt = 0;
        dev_t devmajor;
        dev_t devminor;
 
@@ -832,10 +755,9 @@ ustar_rd(arcn, buf)
         */
        if (ustar_id(buf, BLKMULT) < 0)
                return(-1);
+       memset(arcn, 0, sizeof(*arcn));
        arcn->org_name = arcn->name;
        arcn->sb.st_nlink = 1;
-       arcn->pat = NULL;
-       arcn->nlen = 0;
        hd = (HD_USTAR *)buf;
 
        /*
@@ -844,13 +766,21 @@ ustar_rd(arcn, buf)
         */
        dest = arcn->name;
        if (*(hd->prefix) != '\0') {
-               cnt = l_strncpy(dest, hd->prefix, sizeof(arcn->name) - 2);
+               cnt = fieldcpy(dest, sizeof(arcn->name) - 1, hd->prefix,
+                   sizeof(hd->prefix));
                dest += cnt;
                *dest++ = '/';
                cnt++;
+       } else {
+               cnt = 0;
+       }
+
+       if (hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) {
+               arcn->nlen = cnt + expandname(dest, sizeof(arcn->name) - cnt,
+                   &gnu_name_string, hd->name, sizeof(hd->name));
+               arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
+                   &gnu_link_string, hd->linkname, sizeof(hd->linkname));
        }
-       arcn->nlen = cnt + l_strncpy(dest, hd->name, sizeof(arcn->name) - cnt);
-       arcn->name[arcn->nlen] = '\0';
 
        /*
         * follow the spec to the letter. we should only have mode bits, strip
@@ -858,7 +788,11 @@ ustar_rd(arcn, buf)
         */
        arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
            0xfff);
-       arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#ifdef LONG_OFF_T
+       arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#else
+       arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+#endif
        arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
        arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
 
@@ -878,8 +812,6 @@ ustar_rd(arcn, buf)
        /*
         * set the defaults, these may be changed depending on the file type
         */
-       arcn->ln_name[0] = '\0';
-       arcn->ln_nlen = 0;
        arcn->pad = 0;
        arcn->skip = 0;
        arcn->sb.st_rdev = (dev_t)0;
@@ -887,7 +819,7 @@ ustar_rd(arcn, buf)
        /*
         * set the mode and PAX type according to the typeflag in the header
         */
-       switch(hd->typeflag) {
+       switch (hd->typeflag) {
        case FIFOTYPE:
                arcn->type = PAX_FIF;
                arcn->sb.st_mode |= S_IFIFO;
@@ -934,12 +866,17 @@ ustar_rd(arcn, buf)
                        arcn->sb.st_mode |= S_IFREG;
                        arcn->sb.st_nlink = 2;
                }
+               break;
+       case LONGLINKTYPE:
+       case LONGNAMETYPE:
                /*
-                * copy the link name
+                * GNU long link/file; we tag these here and let the
+                * pax internals deal with it -- too ugly otherwise.
                 */
-               arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
-                       sizeof(arcn->ln_name) - 1);
-               arcn->ln_name[arcn->ln_nlen] = '\0';
+               arcn->type =
+                   hd->typeflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
+               arcn->pad = TAR_PAD(arcn->sb.st_size);
+               arcn->skip = arcn->sb.st_size;
                break;
        case CONTTYPE:
        case AREGTYPE:
@@ -970,17 +907,11 @@ ustar_rd(arcn, buf)
  *     data to write after the header, -1 if archive write failed
  */
 
-#ifdef __STDC__
 int
-ustar_wr(register ARCHD *arcn)
-#else
-int
-ustar_wr(arcn)
-       register ARCHD *arcn;
-#endif
+ustar_wr(ARCHD *arcn)
 {
-       register HD_USTAR *hd;
-       register char *pt;
+       HD_USTAR *hd;
+       char *pt;
        char hdblk[sizeof(HD_USTAR)];
 
        /*
@@ -1008,6 +939,11 @@ ustar_wr(arcn)
                paxwarn(1, "File name too long for ustar %s", arcn->name);
                return(1);
        }
+
+       /*
+        * zero out the header so we don't have to worry about zero fill below
+        */
+       memset(hdblk, 0, sizeof(hdblk));
        hd = (HD_USTAR *)hdblk;
        arcn->pad = 0L;
 
@@ -1020,27 +956,24 @@ ustar_wr(arcn)
                 * occur, we remove the / and copy the first part to the prefix
                 */
                *pt = '\0';
-               l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix) - 1);
+               fieldcpy(hd->prefix, sizeof(hd->prefix), arcn->name,
+                   sizeof(arcn->name));
                *pt++ = '/';
-       } else
-               memset(hd->prefix, 0, sizeof(hd->prefix));
+       }
 
        /*
         * copy the name part. this may be the whole path or the part after
         * the prefix
         */
-       l_strncpy(hd->name, pt, sizeof(hd->name) - 1);
-       hd->name[sizeof(hd->name) - 1] = '\0';
+       fieldcpy(hd->name, sizeof(hd->name), pt,
+           sizeof(arcn->name) - (pt - arcn->name));
 
        /*
         * set the fields in the header that are type dependent
         */
-       switch(arcn->type) {
+       switch (arcn->type) {
        case PAX_DIR:
                hd->typeflag = DIRTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
-               memset(hd->devmajor, 0, sizeof(hd->devmajor));
-               memset(hd->devminor, 0, sizeof(hd->devminor));
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
                        goto out;
                break;
@@ -1050,7 +983,6 @@ ustar_wr(arcn)
                        hd->typeflag = CHRTYPE;
                else
                        hd->typeflag = BLKTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
                if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor,
                   sizeof(hd->devmajor), 3) ||
                   ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
@@ -1060,9 +992,6 @@ ustar_wr(arcn)
                break;
        case PAX_FIF:
                hd->typeflag = FIFOTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
-               memset(hd->devmajor, 0, sizeof(hd->devmajor));
-               memset(hd->devminor, 0, sizeof(hd->devminor));
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
                        goto out;
                break;
@@ -1073,10 +1002,8 @@ ustar_wr(arcn)
                        hd->typeflag = SYMTYPE;
                else
                        hd->typeflag = LNKTYPE;
-               l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
-               hd->linkname[sizeof(hd->linkname) - 1] = '\0';
-               memset(hd->devmajor, 0, sizeof(hd->devmajor));
-               memset(hd->devminor, 0, sizeof(hd->devminor));
+               fieldcpy(hd->linkname, sizeof(hd->linkname), arcn->ln_name,
+                   sizeof(arcn->ln_name));
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
                        goto out;
                break;
@@ -1090,11 +1017,8 @@ ustar_wr(arcn)
                        hd->typeflag = CONTTYPE;
                else
                        hd->typeflag = REGTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
-               memset(hd->devmajor, 0, sizeof(hd->devmajor));
-               memset(hd->devminor, 0, sizeof(hd->devminor));
                arcn->pad = TAR_PAD(arcn->sb.st_size);
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                if (ul_oct((u_long)arcn->sb.st_size, hd->size,
                    sizeof(hd->size), 3)) {
 #              else
@@ -1107,20 +1031,46 @@ ustar_wr(arcn)
                break;
        }
 
-       l_strncpy(hd->magic, TMAGIC, TMAGLEN);
-       l_strncpy(hd->version, TVERSION, TVERSLEN);
+       strncpy(hd->magic, TMAGIC, TMAGLEN);
+       strncpy(hd->version, TVERSION, TVERSLEN);
 
        /*
         * 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_uid, hd->uid, sizeof(hd->uid), 3)) {
+               if (uid_nobody == 0) {
+                       if (uid_name("nobody", &uid_nobody) == -1)
+                               goto out;
+               }
+               if (uid_warn != arcn->sb.st_uid) {
+                       uid_warn = arcn->sb.st_uid;
+                       paxwarn(1,
+                           "Ustar header field is too small for uid %lu, "
+                           "using nobody", (u_long)arcn->sb.st_uid);
+               }
+               if (ul_oct((u_long)uid_nobody, hd->uid, sizeof(hd->uid), 3))
+                       goto out;
+       }
+       if (ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3)) {
+               if (gid_nobody == 0) {
+                       if (gid_name("nobody", &gid_nobody) == -1)
+                               goto out;
+               }
+               if (gid_warn != arcn->sb.st_gid) {
+                       gid_warn = arcn->sb.st_gid;
+                       paxwarn(1,
+                           "Ustar header field is too small for gid %lu, "
+                           "using nobody", (u_long)arcn->sb.st_gid);
+               }
+               if (ul_oct((u_long)gid_nobody, hd->gid, sizeof(hd->gid), 3))
+                       goto out;
+       }
        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))
+           ul_oct((u_long)(u_int)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
                goto out;
-       l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname));
-       l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname));
+       strncpy(hd->uname, name_uid(arcn->sb.st_uid, 0), sizeof(hd->uname));
+       strncpy(hd->gname, name_gid(arcn->sb.st_gid, 0), sizeof(hd->gname));
 
        /*
         * calculate and store the checksum write the header to the archive
@@ -1139,7 +1089,7 @@ ustar_wr(arcn)
        return(1);
 
     out:
-       /*
+       /*
         * header field is out of range
         */
        paxwarn(1, "Ustar header field is too small for %s", arcn->org_name);
@@ -1158,30 +1108,25 @@ ustar_wr(arcn)
  *     the file name is too long
  */
 
-#ifdef __STDC__
-static char *
-name_split(register char *name, register int len)
-#else
 static char *
-name_split(name, len)
-       register char *name;
-       register int len;
-#endif
+name_split(char *name, int len)
 {
-       register char *start;
+       char *start;
 
        /*
         * check to see if the file name is small enough to fit in the name
         * field. if so just return a pointer to the name.
+        * The strings can fill the complete name and prefix fields
+        * without a NUL terminator.
         */
-       if (len < TNMSZ)
+       if (len <= TNMSZ)
                return(name);
        if (len > (TPFSZ + TNMSZ + 1))
                return(NULL);
 
        /*
         * we start looking at the biggest sized piece that fits in the name
-        * field. We walk foward looking for a slash to split at. The idea is
+        * field. We walk forward looking for a slash to split at. The idea is
         * to find the biggest piece to fit in the name field (or the smallest
         * prefix we can find) (the -1 is correct the biggest piece would
         * include the slash between the two parts that gets thrown away)
@@ -1212,3 +1157,20 @@ name_split(name, len)
         */
        return(start);
 }
+
+static size_t
+expandname(char *buf, size_t len, char **gnu_name, const char *name,
+    size_t limit)
+{
+       size_t nlen;
+
+       if (*gnu_name) {
+               /* *gnu_name is NUL terminated */
+               if ((nlen = strlcpy(buf, *gnu_name, len)) >= len)
+                       nlen = len - 1;
+               free(*gnu_name);
+               *gnu_name = NULL;
+       } else
+               nlen = fieldcpy(buf, len, name, limit);
+       return(nlen);
+}
diff --git a/tar.h b/tar.h
index 79a8ce49d89b526de40bb5a8ba10cd9444d9532a..506ce5818c429e141e4c99679d7b5d2243a05c62 100644 (file)
--- a/tar.h
+++ b/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.7 2003/06/02 23:32:09 millert Exp $ */
 /*     $NetBSD: tar.h,v 1.3 1995/03/21 09:07:51 cgd Exp $      */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
 #define        FIFOTYPE        '6'             /* FIFO */
 #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
  */
index d70cd7894c01eab89ed27fc3266ee1759b6a62d8..a7ba68afa651d5e6b8866b0b6b51994202c7ac3e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tty_subs.c,v 1.5 1997/07/25 18:58:39 mickey Exp $     */
+/*     $OpenBSD: tty_subs.c,v 1.12 2003/06/02 23:32:09 millert Exp $   */
 /*     $NetBSD: tty_subs.c,v 1.5 1995/03/21 09:07:52 cgd Exp $ */
 
 /*-
  * 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 the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)tty_subs.c 8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)tty_subs.c   8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: tty_subs.c,v 1.5 1997/07/25 18:58:39 mickey Exp $";
+static const char rcsid[] = "$OpenBSD: tty_subs.c,v 1.12 2003/06/02 23:32:09 millert Exp $";
 #endif
 #endif /* not lint */
 
@@ -58,11 +54,7 @@ static char rcsid[] = "$OpenBSD: tty_subs.c,v 1.5 1997/07/25 18:58:39 mickey Exp
 #include <string.h>
 #include "pax.h"
 #include "extern.h"
-#ifdef __STDC__
 #include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
 
 /*
  * routines that deal with I/O to and from the user
@@ -74,17 +66,12 @@ static FILE *ttyinf = NULL;         /* input pointing at control tty */
 
 /*
  * tty_init()
- *     try to open the controlling termina (if any) for this process. if the
+ *     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
  */
 
-#ifdef __STDC__
 int
 tty_init(void)
-#else
-int
-tty_init()
-#endif
 {
        int ttyfd;
 
@@ -110,24 +97,16 @@ tty_init()
  *     if there is no controlling terminal, just return.
  */
 
-#ifdef __STDC__
 void
-tty_prnt(char *fmt, ...)
-#else
-void
-tty_prnt(fmt, va_alist)
-       char *fmt;
-       va_dcl
-#endif
+tty_prnt(const char *fmt, ...)
 {
        va_list ap;
-#      ifdef __STDC__
+
        va_start(ap, fmt);
-#      else
-       va_start(ap);
-#      endif
-       if (ttyoutf == NULL)
+       if (ttyoutf == NULL) {
+               va_end(ap);
                return;
+       }
        (void)vfprintf(ttyoutf, fmt, ap);
        va_end(ap);
        (void)fflush(ttyoutf);
@@ -141,17 +120,10 @@ tty_prnt(fmt, va_alist)
  *     0 if data was read, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
 tty_read(char *str, int len)
-#else
-int
-tty_read(str, len)
-       char *str;
-       int len;
-#endif
 {
-       register char *pt;
+       char *pt;
 
        if ((--len <= 0) || (ttyinf == NULL) || (fgets(str,len,ttyinf) == NULL))
                return(-1);
@@ -171,23 +143,12 @@ tty_read(str, len)
  *     will be non-zero.
  */
 
-#ifdef __STDC__
 void
-paxwarn(int set, char *fmt, ...)
-#else
-void
-paxwarn(set, fmt, va_alist)
-       int set;
-       char *fmt;
-       va_dcl
-#endif
+paxwarn(int set, const char *fmt, ...)
 {
        va_list ap;
-#      ifdef __STDC__
+
        va_start(ap, fmt);
-#      else
-       va_start(ap);
-#      endif
        if (set)
                exit_val = 1;
        /*
@@ -195,6 +156,7 @@ paxwarn(set, fmt, va_alist)
         * line by itself
         */
        if (vflag && vfpart) {
+               (void)fflush(listf);
                (void)fputc('\n', stderr);
                vfpart = 0;
        }
@@ -210,24 +172,12 @@ paxwarn(set, fmt, va_alist)
  *     will be non-zero.
  */
 
-#ifdef __STDC__
-void
-syswarn(int set, int errnum, char *fmt, ...)
-#else
 void
-syswarn(set, errnum, fmt, va_alist)
-       int set;
-       int errnum;
-       char *fmt;
-       va_dcl
-#endif
+syswarn(int set, int errnum, const char *fmt, ...)
 {
        va_list ap;
-#      ifdef __STDC__
+
        va_start(ap, fmt);
-#      else
-       va_start(ap);
-#      endif
        if (set)
                exit_val = 1;
        /*
@@ -235,6 +185,7 @@ syswarn(set, errnum, fmt, va_alist)
         * line by itself
         */
        if (vflag && vfpart) {
+               (void)fflush(listf);
                (void)fputc('\n', stderr);
                vfpart = 0;
        }
@@ -246,6 +197,6 @@ syswarn(set, errnum, fmt, va_alist)
         * format and print the errno
         */
        if (errnum > 0)
-               (void)fprintf(stderr, " <%s>", strerror(errnum));
+               (void)fprintf(stderr, ": %s", strerror(errnum));
        (void)fputc('\n', stderr);
 }