Merge branch 'upstream'
authorBdale Garbee <bdale@gag.com>
Mon, 11 Aug 2008 20:51:53 +0000 (17:51 -0300)
committerBdale Garbee <bdale@gag.com>
Mon, 11 Aug 2008 20:51:53 +0000 (17:51 -0300)
Conflicts:

Makefile
ar_io.c
cpio.1
options.c
pat_rep.c
pax.1
pax.c
tar.1
tar.c

1  2 
Makefile
ar_io.c
ar_subs.c
cache.c
cpio.c
gen_subs.c
options.c
sel_subs.c
tar.c

diff --combined Makefile
index 8a94849ac9695880c580f594255fb173c84185e7,9ea2e86dcc6a2dac9ba3ef4308f269a6e9c09e91..72f59b1338500ef4798c0e2c33ab635134842d43
+++ b/Makefile
@@@ -1,25 -1,21 +1,38 @@@
+ #     $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 +=
+ #
+ # -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 LONG_OFF_T, pax will compile but will
+ #             NOT RUN PROPERLY.
+ #
  PROG=   pax
  SRCS= ar_io.c ar_subs.c buf_subs.c cache.c cpio.c file_subs.c ftree.c\
        gen_subs.c getoldopt.c options.c pat_rep.c pax.c sel_subs.c tables.c\
 -      tar.c tty_subs.c
 -MAN=  pax.1 tar.1 cpio.1
 -LINKS=        ${BINDIR}/pax ${BINDIR}/tar ${BINDIR}/pax ${BINDIR}/cpio
 +      tar.c tty_subs.c fgetln.c strmode.c
 +OBJS= $(SRCS:.c=.o)
 +MAN=  pax.1
  
 -.include <bsd.prog.mk>
 +CFLAGS= -Wall -O2 -g\
 +      -DNET2_STAT -D_PATH_DEFTAPE=\"/dev/rmt0\" -DDEBIAN -D_GNU_SOURCE
 +
 +prefix=/usr/local
 +
 +pax:  $(OBJS)
 +      $(CC) $(CFLAGS) $(OBJS) -o $@ $(LIBS)
 +
 +clean:
 +      $(RM) *.o
 +
 +realclean: clean
 +      $(RM) $(PROG)
 +
 +install:
 +      install -d -m 755 $(prefix)/bin $(prefix)/share/man/man1
 +      install -s -m 755 $(PROG) $(prefix)/bin
 +      install    -m 644 $(MAN)  $(prefix)/share/man/man1
diff --combined ar_io.c
index 4cc4a97a3be09019a9aae35a11444b2f20d6b237,2a833bb2f65d333c5b285d553cc8d7de916d01ab..6679547a0de7e12ff50f37ca69d31fd8cb2a1b13
+++ b/ar_io.c
@@@ -1,4 -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 +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 +48,7 @@@
  #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 +69,8 @@@
  #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 +82,14 @@@ static struct stat arsb;           /* stat of ar
  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()
   *    -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;
  
                        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 filter through compressor 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:
                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;
        /*
         * 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
                        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;
                break;
        default:
                /*
-                * should never happen, worse case, slow... 
+                * should never happen, worst case, slow...
                 */
                blksz = rdblksz = BLKMULT;
                break;
   * 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;
                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;
         * 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",
                (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",
   *    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];
  
        /*
   *    0 if all ready to write, -1 otherwise
   */
  
- #ifdef __STDC__
  int
  ar_set_wr(void)
- #else
- int
- ar_set_wr()
- #endif
  {
        off_t cpos;
  
         */
        wr_trail = 0;
  
-       /* 
+       /*
         * Add any device dependent code as required here
         */
        if (artyp != ISREG)
  /*
   * 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.");
   *    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
                        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).
   * 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;
  
        /*
        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;
        /*
         * 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).
   *    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;
        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
         */
        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.
                 */
  
  /*
   * 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:
   *    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;
                return(0);
  
        /*
-        * we cannot move foward at EOF or error
+        * we cannot move forward at EOF or error
         */
        if (lstrval <= 0)
                return(lstrval);
         * 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);
         * 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;
                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);
  }
   *    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
        if (lstrval < 0)
                return(lstrval);
  
-       switch(artyp) {
+       switch (artyp) {
        case ISPIPE:
                if (sksz <= 0)
                        break;
  
                /*
                 * 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.
                 */
                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);
  /*
   * 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...
   *    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];
  
        }
  
        /*
-        * 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)
   *    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;
        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);
                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");
                 */
                if (ar_open(buf) >= 0) {
                        if (freeit) {
-                               (void)free(arcname);
+                               (void)free((char *)arcname);
                                freeit = 0;
                        }
                        if ((arcname = strdup(buf)) == NULL) {
  
  /*
   * ar_start_gzip()
 - * starts the gzip compression/decompression process as a child, using magic
 - * to keep the fd the same in the calling function (parent).
 + * starts the compress, gzip or bzip2 compression/decompression process
 + * as a child, using magic 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 */
        }
  }
diff --combined ar_subs.c
index eaf3362cd9bff4f6a09a48eb257b981deb70f5db,73aefdabb489f2ab41851a548784608da5688f1a..382462cd6540f148abe3258affcc8650a0426d8c
+++ b/ar_subs.c
@@@ -1,4 -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.
   *
  
  #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 */
  
  #include <sys/types.h>
  #include <sys/time.h>
 +#include <time.h>
  #include <sys/stat.h>
  #include <sys/param.h>
  #include <signal.h>
@@@ -61,9 -56,9 +57,9 @@@
  #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;
  
  /*
@@@ -80,16 -75,11 +76,11 @@@ u_long flcnt;                              /* number of files pro
   *    (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;
  
         * 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.
   *    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;
         * 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
  
                /*
                 * 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
                }
  
                /*
-                * 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))) {
                        if (vflag > 1)
                                ls_list(arcn, now, listf);
                        else {
-                               (void)fputs(arcn->name, listf);
+                               (void)safe_print(arcn->name, listf);
                                vfpart = 1;
                        }
                }
                                (void)putc('\n', listf);
                                vfpart = 0;
                        }
-                       continue;
+                       goto popd;
                }
                /*
                 * we have a file with data here. If we can not create it, skip
                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
                if (!res)
                        (void)rd_skip(cnt + arcn->pad);
  
+ popd:
                /*
                 * if required, chdir around.
                 */
   *    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;
  
        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;
  
        /*
        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);
  
        /*
                         */
                        if ((res = chk_ftime(arcn)) < 0)
                                break;
-                       if (res > 0)
+                       if (res > 0) {
+                               ftree_skipped_newer(arcn);
                                continue;
+                       }
                }
  
                /*
                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);
                        if (vflag > 1)
                                ls_list(arcn, now, listf);
                        else {
-                               (void)fputs(arcn->name, listf);
+                               (void)safe_print(arcn->name, listf);
                                vfpart = 1;
                        }
                }
                }
                wr_one = 1;
                if (res > 0) {
-                       /* 
+                       /*
                         * format write says no file data needs to be stored
                         * so we are done messing with this file
                         */
                        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
   *    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
   *    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;
  
        /*
         * 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;
        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)
                (void)fputs("done.\n", listf);
                vfpart = 0;
        }
-        
        /*
         * go to the writing phase to add the new members
         */
   *    write a new archive
   */
  
- #ifdef __STDC__
  void
  archive(void)
- #else
- void
- archive()
- #endif
  {
        ARCHD archd;
  
   *    (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;
         * 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) {
  
        /*
         * 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;
                        /*
                         * 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
                        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)
                }
  
                /*
-                * 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))) {
                }
  
                if (vflag) {
-                       (void)fputs(arcn->name, listf);
+                       (void)safe_print(arcn->name, listf);
                        vfpart = 1;
                }
                ++flcnt;
   *    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. */
  
        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)
                        /*
                         * 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
                                 */
         * 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
                 */
   *    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;
  
        res = BLKMULT;
        hdsz = 0;
        hdend = hdbuf;
-       for(;;) {
+       for (;;) {
                for (;;) {
                        /*
                         * fill the buffer with at least the smallest header
                        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
diff --combined cache.c
index 0e4730a7a76b9dcf8bd6313f03f7bade34753b4f,44eda1f518a7c826521d208a4d313f9a1cbb20ac..4f80b7cc62cce5f7afd64f1cc6add66a92e4e167
+++ b/cache.c
@@@ -1,4 -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 +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 +72,13 @@@ static GIDC **grptb = NULL;        /* group na
  
  /*
   * 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;
  
  
  /*
   * 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;
  
  
  /*
   * 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;
  
  
  /*
   * 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;
  
   *    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("");
         * No entry for this uid, we will add it
         */
        if (!pwopn) {
 +#ifdef DEBIAN
 +              setpwent();
 +#else
                setpassent(1);
 +#endif
                ++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 {
                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);
   *    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("");
         * No entry for this gid, we will add it
         */
        if (!gropn) {
 +#ifdef DEBIAN
 +              setgrent();
 +#else
                setgroupent(1);
 +#endif
                ++gropn;
        }
        if (ptr == NULL)
-               ptr = (GIDC *)malloc(sizeof(GIDC));
+               ptr = gidtb[gid % GID_SZ] = malloc(sizeof(GIDC));
  
        if ((gr = getgrgid(gid)) == NULL) {
                /*
                        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 {
                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);
   *    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
        }
  
        if (!pwopn) {
 +#ifdef DEBIAN
 +              setpwent();
 +#else
                setpassent(1);
 +#endif
                ++pwopn;
        }
  
        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,
                *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);
   *    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
        }
  
        if (!gropn) {
 +#ifdef DEBIAN
 +              setgrent();
 +#else
                setgroupent(1);
 +#endif
                ++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,
                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 --combined cpio.c
index eb486fe47a8269eca16cb74bf7ce0fc407f7543b,4a9796028b8cdf1a2bdb27f6fd5f04ab3c766cc5..2019e6d9c379305f76a6cfaec4e5a317958457ea
--- 1/cpio.c
--- 2/cpio.c
+++ b/cpio.c
@@@ -1,4 -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.
   *
  
  #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 */
  
  #include <sys/types.h>
 +#include <sys/sysmacros.h>
  #include <sys/time.h>
  #include <sys/stat.h>
  #include <sys/param.h>
@@@ -59,9 -54,9 +55,9 @@@
  #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
@@@ -80,13 -75,8 +76,8 @@@ static int swp_head;         /* binary cpio he
   *      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());
  }
   *    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
   *    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;
  }
  
  /*
-  * 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;
  
        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));
  }
  
   *    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
   *    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
   *      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))
   *    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
        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
  
        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));
   *      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)));
  }
   *    0 if ok, -1 otherwise (what dev_start() returns)
   */
  
- #ifdef __STDC__
  int
  cpio_stwr(void)
- #else
- int
- cpio_stwr()
- #endif
  {
        return(dev_start());
  }
   *    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)];
  
        /*
        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
  /*
   * 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))
   *      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))
   *      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());
   *    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
        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
                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);
   *      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)))));
   *    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());
   *    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)];
  
         */
        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:
                 * 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
            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),
   *      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);
   *    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
        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));
                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);
   *      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)))));
   * 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;
                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 --combined gen_subs.c
index 69fe3738eac20dee3bf645bdfc93b2a23748289f,7e66f62cd0ac7e6d22175ad420c75126d97de1e6..07c9e96b26db9c73c573433d11c70957a8dc979d
@@@ -1,4 -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.
   *
  
  #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 */
  
  #include <sys/types.h>
 +#include <sys/sysmacros.h>
  #include <sys/time.h>
 +#include <time.h>
  #include <sys/stat.h>
  #include <sys/param.h>
  #include <stdio.h>
 -#include <tzfile.h>
 +#include "tzfile.h"
  #include <utmp.h>
  #include <unistd.h>
  #include <stdlib.h>
  #include <string.h>
+ #include <vis.h>
  #include "pax.h"
  #include "extern.h"
  
 +#include "strmode.h"
 +
  /*
   * a collection of general purpose subroutines used by pax
   */
  #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;
        }
         */
        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);
        /*
         * 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) {
                /*
        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);
+       }
  }
  
  /*
   *    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;
                                break;
                }
        } else {
-               while ((str < stop) && (*str >= '0') && (*str <= '7'))
+               while ((str < stop) && (*str >= '0') && (*str <= '7'))
                        tval = (tval << 3) + (*str++ - '0');
        }
        return(tval);
   *    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;
  
        /*
        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
   *    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;
                                break;
                }
        } else {
-               while ((str < stop) && (*str >= '0') && (*str <= '7'))
+               while ((str < stop) && (*str >= '0') && (*str <= '7'))
                        tval = (tval << 3) + (*str++ - '0');
        }
        return(tval);
   *    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;
  
        /*
        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);
+ }
diff --combined options.c
index 49592e662eb0fa78ca31b517db8d9e9dd02c94a7,fa198891e54540d81c5c95c0c22f59a88be1972b..4cc16d723e888b56a24f00739bfa9493cbfbe525
+++ b/options.c
@@@ -1,4 -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 +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 */
  
@@@ -64,8 -60,6 +60,8 @@@
  #include "tar.h"
  #include "extern.h"
  
 +#include "fgetln.h"    /* added, David */
 +
  /*
   * Routines which handle command line options
   */
@@@ -74,16 -68,23 +70,23 @@@ static char flgch[] = FLGCH;       /* list o
  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 */
@@@ -138,26 -139,24 +141,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)
  {
  
        /*
        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);
  }
  
  /*
   *    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:ijklno: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':
                        /*
                        /*
                         * use bzip2.  Non standard option.
                         */
-                       zflag = 1;
                        gzip_program = BZIP2_CMD;
                        break;
                case 'k':
                         * specify file characteristic options
                         */
                        for (pt = optarg; *pt != '\0'; ++pt) {
-                               switch(*pt) {
+                               switch (*pt) {
                                case 'a':
                                        /*
                                         * do not preserve access time
                                        break;
                                case 'p':
                                        /*
-                                        * preserver file mode bits
+                                        * preserve file mode bits
                                         */
                                        pmode = 1;
                                        break;
                        /*
                         * use gzip.  Non standard option.
                         */
-                       zflag = 1;
                        gzip_program = GZIP_CMD;
                        break;
                case 'B':
                        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)
                        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;
   *    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.
         * process option flags
         */
        while ((c = getoldopt(argc, argv,
-           "b:cef:hjmopruts:vwxzBC:HLOPXZ014578"))
-           != EOF) {
-               switch(c) {
+           "b:cef:hjmopqruts:vwxzBC:HI:LOPXZ014578")) != -1) {
+               switch (c) {
                case 'b':
                        /*
                         * specify blocksize in 512-byte blocks
                        /*
                         * use bzip2.  Non standard option.
                         */
-                       zflag = 1;
                        gzip_program = BZIP2_CMD;
                        break;
                case 'm':
                         */
                        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
                        pmode = 1;
                        pids = 1;
                        break;
+               case 'q':
+                       /*
+                        * select first match for a pattern only
+                        */
+                       nflag = 1;
+                       break;
                case 'r':
                case 'u':
                        /*
                        /*
                         * use gzip.  Non standard option.
                         */
-                       zflag = 1;
                        gzip_program = GZIP_CMD;
                        break;
                case 'B':
                         */
                        break;
                case 'C':
+                       havechd++;
                        chdname = optarg;
                        break;
                case 'H':
                         */
                        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
                        /*
                         * use compress.
                         */
-                       zflag = 1;
                        gzip_program = COMPRESS_CMD;
                        break;
                case '0':
        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
         */
        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)
                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();
+                               }
+                               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 (ftree_add(*argv++, 0) < 0)
+                               }
+                       } 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!
        }
  }
  
+ int mkpath(char *);
  int
  mkpath(path)
        char *path;
  {
        struct stat sb;
-       register char *slash;
+       char *slash;
        int done = 0;
  
        slash = 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;
        dflag = 1;
        act = -1;
        nodirs = 1;
-       while ((c=getopt(argc,argv,"abcdfijklmoprstuvzABC:E:F:H:I:LO:SZ6")) != EOF)
+       while ((c=getopt(argc,argv,"abcdfijklmoprstuvzABC:E:F:H:I:LO:SZ6")) != -1)
                switch (c) {
                        case 'a':
                                /*
                                /*
                                 * use bzip2.  Non standard option.
                                 */
-                               zflag = 1;
                                gzip_program = BZIP2_CMD;
                                break;
                        case 'k':
                                /*
                                 * use gzip.  Non standard option.
                                 */
-                               zflag = 1;
                                gzip_program = GZIP_CMD;
                                break;
                        case 'A':
                                        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':
                                /*
                                 * use compress.  Non standard option.
                                 */
-                               zflag = 1;
                                gzip_program = COMPRESS_CMD;
                                break;
                        case '6':
                         * 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:
   *    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;
   *    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));
  }
   *    pointer to next OPLIST entry or NULL (end of list).
   */
  
- #ifdef __STDC__
  OPLIST *
  opt_next(void)
- #else
- OPLIST *
- opt_next()
- #endif
  {
        OPLIST *opt;
  
   *    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);
   * 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
                        *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';
   *    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
  #     endif
                return(0);
  
-       switch(*expr) {
+       switch (*expr) {
        case 'b':
                t = num;
                num *= 512;
                break;
        }
  
-       switch(*expr) {
+       switch (*expr) {
                case '\0':
                        break;
                case '*':
        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.
   *    0
   */
  
- #ifdef __STDC__
  static int
  no_op(void)
- #else
- static int
- no_op()
- #endif
  {
        return(0);
  }
   *    print the usage summary to the user
   */
  
- #ifdef __STDC__
  void
  pax_usage(void)
- #else
- void
- pax_usage()
- #endif
  {
-       (void)fputs("usage: pax [-cdjnvz] [-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 [-cdijknuvzDYZ] [-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 [-dijtuvzHLPX] [-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);
  }
  
   *    print the usage summary to the user
   */
  
- #ifdef __STDC__
  void
  tar_usage(void)
- #else
- void
- tar_usage()
- #endif
  {
-       (void)fputs("usage: tar -{txru}[cevfbjmopswzBHLPXZ014578] [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);
  }
   *    print the usage summary to the user
   */
  
- #ifdef __STDC__
  void
  cpio_usage(void)
- #else
- void
- cpio_usage()
- #endif
  {
-       (void)fputs("usage: cpio -o [-aABcjLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr);
-       (void)fputs("               [-F archive] < name-list [> archive]\n", stderr);
-       (void)fputs("       cpio -i [-bBcdfjmnrsStuvVzZ6] [-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);
  }
diff --combined sel_subs.c
index d11b50cd007d818778d866a1a61fda21b828b163,55d3a0017c1504aef483bfaa9e2518696232efd5..b12c3edf50e4e3dda05f85654402caaf033b1279
@@@ -1,4 -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.
   *
  
  #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 */
  
  #include <sys/types.h>
  #include <sys/time.h>
 +#include <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 */
@@@ -77,19 -74,13 +75,13 @@@ static GRPT **grptb = NULL;                /* group s
  
  /*
   * 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)) ||
   * 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 #.
   */
  
  /*
   *    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
                }
                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();
  
        /*
   *    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
   *    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
                }
                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();
  
        /*
   *    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
   * 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
        }
  
        /*
-        * 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'))
        else {
                pt->flgs = 0;
                while (*flgpt != '\0') {
-                       switch(*flgpt) {
+                       switch (*flgpt) {
                        case 'M':
                        case 'm':
                                pt->flgs |= CMPMTME;
        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);
  }
  
   *    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.
         */
        pt = trhead;
        while (pt != NULL) {
-               switch(pt->flgs & CMPBOTH) {
+               switch (pt->flgs & CMPBOTH) {
                case CMPBOTH:
                        /*
                         * user wants both mtime and ctime checked for this
  
  /*
   * 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);
diff --combined tar.c
index af7f2141f8a4614ce3d795d2dc570637e34fd17c,6a0b3b32963aa4e15685d76a105d04c7626c58ba..97639346d557bddd16a12bf7c7b9cedc5cceb397
--- 1/tar.c
--- 2/tar.c
+++ b/tar.c
@@@ -1,4 -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.
   *
  
  #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 */
  
  #include <sys/types.h>
 +#include <sys/sysmacros.h>
  #include <sys/time.h>
  #include <sys/stat.h>
  #include <sys/param.h>
   * 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()
   *    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)));
  }
   *    size of trailer (2 * BLKMULT)
   */
  
- #ifdef __STDC__
  off_t
  tar_endrd(void)
- #else
- off_t
- tar_endrd()
- #endif
  {
        return((off_t)(NULLCNT*BLKMULT));
  }
   *    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
   *    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;
        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
   *    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;
  /*
   * 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
   *    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);
                return(-1);
        if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
                return(-1);
+       force_one_volume = 1;
        return(0);
  }
  
   *    0 if ok -1 otherwise
   */
  
- #ifdef __STDC__
  int
  tar_opt(void)
- #else
- int
- tar_opt()
- #endif
  {
        OPLIST *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;
  
        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:
                 */
                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
                 */
                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
                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:
                } 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;
         * strip off any trailing slash.
         */
        if (*pt == '/') {
-               *pt = '\0'; 
+               *pt = '\0';
                --arcn->nlen;
        }
        return(0);
   *    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
        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;
        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;
                 * 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)) {
                 * 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 {
                 * 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
        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;
  
        /*
   *    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);
   *    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);
   *    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);
         * 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);
   *    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;
  
         */
        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;
  
        /*
         * see if the filename is split into two parts. if, so joint the parts.
         * we copy the prefix first and add a / between the prefix and name.
 +       *
 +       * the length passed to l_strncpy must be the length of the field
 +       * being copied *from*, since these fields are NOT null terminated
 +       * when full.  the destination buffer is plenty big enough to hold
 +       * the longest supported ustar path length, so there's no need
 +       * to check against that.
         */
        dest = arcn->name;
        if (*(hd->prefix) != '\0') {
-               cnt = l_strncpy(dest, hd->prefix, sizeof(hd->prefix));
+               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(hd->name));
-       arcn->name[arcn->nlen] = '\0';
  
        /*
         * follow the spec to the letter. we should only have mode bits, strip
         */
        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;
  
        /*
         * 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;
        /*
         * 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;
                        arcn->sb.st_mode |= S_IFREG;
                        arcn->sb.st_nlink = 2;
                }
+               break;
+       case LONGLINKTYPE:
+       case LONGNAMETYPE:
                /*
-                * copy the link name
-                *
-                * see comment above (for hd->name) regarding the length
-                * passed to l_strncpy
+                * 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(hd->linkname));
-               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:
   *    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)];
  
        /*
                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;
  
                 * occur, we remove the / and copy the first part to the prefix
                 */
                *pt = '\0';
-               l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix));
+               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));
+       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));
-               hd->devmajor[0] = '0';
-               memset(hd->devminor, 0, sizeof(hd->devminor));
-               hd->devminor[0] = '0';
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
                        goto out;
                break;
                        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,
                break;
        case PAX_FIF:
                hd->typeflag = FIFOTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
-               memset(hd->devmajor, 0, sizeof(hd->devmajor));
-               hd->devmajor[0] = '0';
-               memset(hd->devminor, 0, sizeof(hd->devminor));
-               hd->devminor[0] = '0';
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
                        goto out;
                break;
                        hd->typeflag = SYMTYPE;
                else
                        hd->typeflag = LNKTYPE;
-               l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
-               memset(hd->devmajor, 0, sizeof(hd->devmajor));
-               hd->devmajor[0] = '0';
-               memset(hd->devminor, 0, sizeof(hd->devminor));
-               hd->devminor[0] = '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), 3))
                        goto out;
                break;
                        hd->typeflag = CONTTYPE;
                else
                        hd->typeflag = REGTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
-               memset(hd->devmajor, 0, sizeof(hd->devmajor));
-               hd->devmajor[0] = '0';
-               memset(hd->devminor, 0, sizeof(hd->devminor));
-               hd->devminor[0] = '0';
                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
                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
        return(1);
  
      out:
-       /*
+       /*
         * header field is out of range
         */
        paxwarn(1, "Ustar header field is too small for %s", arcn->org_name);
   *    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)
                return(name);
  
        /*
         * 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)
         */
        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);
+ }