]> git.saurik.com Git - apple/file_cmds.git/blobdiff - pax/ar_io.c
file_cmds-321.100.10.0.1.tar.gz
[apple/file_cmds.git] / pax / ar_io.c
index 9fd73460db620aaa005b650107b17c5df02293b0..1c4b943e0fa2afc7de8121c320ee9c46d5addc97 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ar_io.c,v 1.17 1997/09/01 18:29:42 deraadt 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.
  *
  * SUCH DAMAGE.
  */
 
+#include <sys/cdefs.h>
 #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[] __attribute__((__unused__)) = "$OpenBSD: ar_io.c,v 1.17 1997/09/01 18:29:42 deraadt Exp $";
+__used static const char rcsid[] = "$OpenBSD: ar_io.c,v 1.38 2008/06/11 00:49:08 pvalchev Exp $";
 #endif
 #endif /* not lint */
 
@@ -50,8 +47,11 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ar_io.c,v 1.17 1997
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
+#ifndef __APPLE__
 #include <sys/mtio.h>
+#endif /* !__APPLE__ */
 #include <sys/param.h>
+#include <sys/wait.h>
 #include <signal.h>
 #include <string.h>
 #include <fcntl.h>
@@ -60,6 +60,7 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ar_io.c,v 1.17 1997
 #include <errno.h>
 #include <stdlib.h>
 #include <err.h>
+#include <stdint.h>
 #include "pax.h"
 #include "options.h"
 #include "extern.h"
@@ -72,8 +73,9 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ar_io.c,v 1.17 1997
 #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 */
+#define _NONE          "<NONE>"        /* pseudo name for no files */
 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 +87,16 @@ static struct stat arsb;            /* stat of archive device at open */
 static int invld_rec;                  /* tape has out of spec record size */
 static int wr_trail = 1;               /* trailer was rewritten in append */
 static int can_unlnk = 0;              /* do we unlink null archives?  */
-char *arcname;                         /* printable name of archive */
-char *gzip_program;                    /* name of gzip program */
-
-static int get_phys __P((void));
+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 */
+
+#ifndef __APPLE__
+static int get_phys(void);
+#endif /* __APPLE__ */
 extern sigset_t s_mask;
-static void ar_start_gzip __P((int));
+static void ar_start_gzip(int, const char *, int);
 
 /*
  * ar_open()
@@ -101,17 +107,12 @@ static void ar_start_gzip __P((int));
  *     -1 on failure, 0 otherwise
  */
 
-#ifdef __STDC__
-int
-ar_open(char *name)
-#else
 int
-ar_open(name)
-       char *name;
-#endif
+ar_open(const char *name)
 {
+#ifndef __APPLE__
        struct mtget mb;
-
+#endif /* __APPLE__ */
        if (arfd != -1)
                (void)close(arfd);
        arfd = -1;
@@ -129,36 +130,34 @@ ar_open(name)
                        arfd = STDIN_FILENO;
                        arcname = STDN;
                } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0)
-                       syswarn(0, errno, "Failed open to read on %s", name);
-               if (zflag)
-                       ar_start_gzip(arfd);
+                       syswarn(1, errno, "Failed open to read on %s", name);
+               if (arfd != -1 && gzip_program != NULL)
+                       ar_start_gzip(arfd, gzip_program, 0);
                break;
        case ARCHIVE:
                if (name == NULL) {
                        arfd = STDOUT_FILENO;
                        arcname = STDO;
                } else if ((arfd = open(name, AR_MODE, DMOD)) < 0)
-                       syswarn(0, errno, "Failed open to write on %s", name);
+                       syswarn(1, errno, "Failed open to write on %s", name);
                else
                        can_unlnk = 1;
-               if (zflag)
-                       ar_start_gzip(arfd);
+               if (arfd != -1 && gzip_program != NULL)
+                       ar_start_gzip(arfd, gzip_program, 1);
                break;
        case APPND:
-               if (zflag)
-                       err(1, "can not gzip while appending");
                if (name == NULL) {
                        arfd = STDOUT_FILENO;
                        arcname = STDO;
                } else if ((arfd = open(name, APP_MODE, DMOD)) < 0)
-                       syswarn(0, errno, "Failed open to read/write on %s",
+                       syswarn(1, errno, "Failed open to read/write on %s",
                                name);
                break;
        case COPY:
                /*
                 * arfd not used in COPY mode
                 */
-               arcname = "<NONE>";
+               arcname = _NONE;
                lstrval = 1;
                return(0);
        }
@@ -166,8 +165,9 @@ ar_open(name)
                return(-1);
 
        if (chdname != NULL)
-               if (chdir(chdname) != 0)
-                       syswarn(1, errno, "Failed chdir to %s", chdname);
+               if (dochdir(chdname) == -1) {
+                       return(-1);
+               }
        /*
         * set up is based on device type
         */
@@ -187,9 +187,12 @@ ar_open(name)
                return(-1);
        }
 
+#ifndef __APPLE__
        if (S_ISCHR(arsb.st_mode))
                artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE;
-       else if (S_ISBLK(arsb.st_mode))
+       else
+#endif /* !__APPLE__ */
+       if (S_ISBLK(arsb.st_mode))
                artyp = ISBLK;
        else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE))
                artyp = ISPIPE;
@@ -214,11 +217,11 @@ ar_open(name)
        /*
         * set default blksz on read. APPNDs writes rdblksz on the last volume
         * On all new archive volumes, we shift to wrblksz (if the user
-        * specified one, otherwize we will continue to use rdblksz). We
-        * must to set blocksize based on what kind of device the archive is
+        * specified one, otherwise we will continue to use rdblksz). We
+        * must set blocksize based on what kind of device the archive is
         * stored.
         */
-       switch(artyp) {
+       switch (artyp) {
        case ISTAPE:
                /*
                 * Tape drives come in at least two flavors. Those that support
@@ -281,7 +284,7 @@ ar_open(name)
                        if ((arsb.st_size % rdblksz) == 0)
                                break;
                /*
-                * When we cannont find a match, we may have a flawed archive.
+                * When we cannot find a match, we may have a flawed archive.
                 */
                if (rdblksz <= 0)
                        rdblksz = FILEBLK;
@@ -295,7 +298,7 @@ ar_open(name)
                break;
        default:
                /*
-                * should never happen, worse case, slow... 
+                * should never happen, worst case, slow...
                 */
                blksz = rdblksz = BLKMULT;
                break;
@@ -308,26 +311,16 @@ ar_open(name)
  * ar_close()
  *     closes archive device, increments volume number, and prints i/o summary
  */
-#ifdef __STDC__
 void
 ar_close(void)
-#else
-void
-ar_close()
-#endif
 {
-       FILE *outf;
+       int status;
 
        if (arfd < 0) {
                did_io = io_ok = flcnt = 0;
                return;
        }
 
-       if (act == LIST)
-               outf = stdout;
-       else
-               outf = stderr;
-
        /*
         * Close archive file. This may take a LONG while on tapes (we may be
         * forced to wait for the rewind to complete) so tell the user what is
@@ -336,11 +329,11 @@ ar_close()
         */
        if (vflag && (artyp == ISTAPE)) {
                if (vfpart)
-                       (void)putc('\n', outf);
-               (void)fprintf(outf,
+                       (void)putc('\n', listf);
+               (void)fprintf(listf,
                        "%s: Waiting for tape drive close to complete...",
                        argv0);
-               (void)fflush(outf);
+               (void)fflush(listf);
        }
 
        /*
@@ -353,12 +346,23 @@ ar_close()
                can_unlnk = 0;
        }
 
+       /*
+        * for a quick extract/list, pax frequently exits before the child
+        * process is done
+        */
+       if ((act == LIST || act == EXTRACT) && nflag && zpid > 0)
+               kill(zpid, SIGINT);
+
        (void)close(arfd);
 
+       /* Do not exit before child to ensure data integrity */
+       if (zpid > 0)
+               waitpid(zpid, &status, 0);
+
        if (vflag && (artyp == ISTAPE)) {
-               (void)fputs("done.\n", outf);
+               (void)fputs("done.\n", listf);
                vfpart = 0;
-               (void)fflush(outf);
+               (void)fflush(listf);
        }
        arfd = -1;
 
@@ -384,7 +388,7 @@ ar_close()
         * Print out a summary of I/O for this archive volume.
         */
        if (vfpart) {
-               (void)putc('\n', outf);
+               (void)putc('\n', listf);
                vfpart = 0;
        }
 
@@ -394,28 +398,29 @@ ar_close()
         * could have written anything yet.
         */
        if (frmt == NULL) {
-#      ifdef NET2_STAT
-               (void)fprintf(outf, "%s: unknown format, %lu bytes skipped.\n",
+#      ifdef LONG_OFF_T
+               (void)fprintf(listf, "%s: unknown format, %lu bytes skipped.\n",
 #      else
-               (void)fprintf(outf, "%s: unknown format, %qu bytes skipped.\n",
+               (void)fprintf(listf, "%s: unknown format, %qu bytes skipped.\n",
 #      endif
                    argv0, rdcnt);
-               (void)fflush(outf);
+               (void)fflush(listf);
                flcnt = 0;
                return;
        }
 
        if (strcmp(NM_CPIO, argv0) == 0)
-               (void)fprintf(outf, "%qu blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120);
-       else if (strcmp(NM_TAR, argv0) != 0)
-               (void)fprintf(outf,
-#      ifdef NET2_STAT
+               (void)fprintf(listf, "%qu blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120);
+       else if (strcmp(NM_TAR, argv0) != 0 && strcmp(NM_PAX, argv0) != 0)
+               (void)fprintf(listf,
+#      ifdef LONG_OFF_T
                    "%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n",
+                   argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt);
 #      else
-                   "%s: %s vol %d, %lu files, %qu bytes read, %qu bytes written.\n",
+                   "%s: %s vol %d, %lu files, %ju bytes read, %ju bytes written.\n",
+                   argv0, frmt->name, arvol-1, flcnt, (uintmax_t)rdcnt, (uintmax_t)wrcnt);
 #      endif
-                   argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt);
-       (void)fflush(outf);
+       (void)fflush(listf);
        flcnt = 0;
 }
 
@@ -426,15 +431,10 @@ ar_close()
  *     other side of the pipe from getting a SIGPIPE (pax will stop
  *     reading an archive once a format dependent trailer is detected).
  */
-#ifdef __STDC__
 void
 ar_drain(void)
-#else
-void
-ar_drain()
-#endif
 {
-       register int res;
+       int res;
        char drbuf[MAXBLK];
 
        /*
@@ -463,13 +463,8 @@ ar_drain()
  *     0 if all ready to write, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ar_set_wr(void)
-#else
-int
-ar_set_wr()
-#endif
 {
        off_t cpos;
 
@@ -479,7 +474,7 @@ ar_set_wr()
         */
        wr_trail = 0;
 
-       /* 
+       /*
         * Add any device dependent code as required here
         */
        if (artyp != ISREG)
@@ -500,19 +495,14 @@ ar_set_wr()
 /*
  * ar_app_ok()
  *     check if the last volume in the archive allows appends. We cannot check
- *     this until we are ready to write since there is no spec that says all 
+ *     this until we are ready to write since there is no spec that says all
  *     volumes in a single archive have to be of the same type...
  * Return:
  *     0 if we can append, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
 ar_app_ok(void)
-#else
-int
-ar_app_ok()
-#endif
 {
        if (artyp == ISPIPE) {
                paxwarn(1, "Cannot append to an archive obtained from a pipe.");
@@ -535,17 +525,10 @@ ar_app_ok()
  *     Number of bytes in buffer. 0 for end of file, -1 for a read error.
  */
 
-#ifdef __STDC__
 int
-ar_read(register char *buf, register int cnt)
-#else
-int
-ar_read(buf, cnt)
-       register char *buf;
-       register int cnt;
-#endif
+ar_read(char *buf, int cnt)
 {
-       register int res = 0;
+       int res = 0;
 
        /*
         * if last i/o was in error, no more reads until reset or new volume
@@ -569,10 +552,10 @@ ar_read(buf, cnt)
                        io_ok = 1;
                        if (res != rdblksz) {
                                /*
-                                * Record size changed. If this is happens on
+                                * Record size changed. If this happens on
                                 * any record after the first, we probably have
                                 * a tape drive which has a fixed record size
-                                * we are getting multiple records in a single
+                                * (we are getting multiple records in a single
                                 * read). Watch out for record blocking that
                                 * violates pax spec (must be a multiple of
                                 * BLKMULT).
@@ -622,20 +605,13 @@ ar_read(buf, cnt)
  * Return:
  *     Number of bytes written. 0 indicates end of volume reached and with no
  *     flaws (as best that can be detected). A -1 indicates an unrecoverable
- *     error in the archive occured.
+ *     error in the archive occurred.
  */
 
-#ifdef __STDC__
 int
-ar_write(register char *buf, register int bsz)
-#else
-int
-ar_write(buf, bsz)
-       register char *buf;
-       register int bsz;
-#endif
+ar_write(char *buf, int bsz)
 {
-       register int res;
+       int res;
        off_t cpos;
 
        /*
@@ -649,7 +625,15 @@ ar_write(buf, bsz)
                wr_trail = 1;
                io_ok = 1;
                return(bsz);
-       }
+       } else if (res < 0 && artyp == ISPIPE && errno == EPIPE) { /* ignore it */
+               wr_trail = 1;
+               io_ok = 1;
+               errno = 0;
+               arfd = open("/dev/null", AR_MODE, DMOD);
+               artyp = ISREG;
+               return bsz; 
+        }
+
        /*
         * write broke, see what we can do with it. We try to send any partial
         * writes that may violate pax spec to the next archive volume.
@@ -663,10 +647,10 @@ ar_write(buf, bsz)
        case ISREG:
                if ((res > 0) && (res % BLKMULT)) {
                        /*
-                        * try to fix up partial writes which are not BLKMULT
+                        * try to fix up partial writes which are not BLKMULT
                         * in size by forcing the runt record to next archive
                         * volume
-                        */
+                        */
                        if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
                                break;
                        cpos -= (off_t)res;
@@ -690,7 +674,7 @@ ar_write(buf, bsz)
                        break;
                if (errno == EACCES) {
                        paxwarn(0, "Write failed, archive is write protected.");
-                       res = lstrval = 0;
+                       lstrval = 0;
                        return(0);
                }
                /*
@@ -711,7 +695,7 @@ ar_write(buf, bsz)
        /*
         * Better tell the user the bad news...
         * if this is a block aligned archive format, we may have a bad archive
-        * if the format wants the header to start at a BLKMULT boundry. While
+        * if the format wants the header to start at a BLKMULT boundary.. While
         * we can deal with the mis-aligned data, it violates spec and other
         * archive readers will likely fail. if the format is not block
         * aligned, the user may be lucky (and the archive is ok).
@@ -750,21 +734,18 @@ ar_write(buf, bsz)
  *     0 when ok to try i/o again, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
 ar_rdsync(void)
-#else
-int
-ar_rdsync()
-#endif
 {
        long fsbz;
        off_t cpos;
        off_t mpos;
+#ifndef __APPLE__
        struct mtop mb;
+#endif /* !__APPLE__ */
 
        /*
-        * 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
         */
@@ -778,13 +759,14 @@ ar_rdsync()
        if (io_ok)
                did_io = 1;
 
-       switch(artyp) {
+       switch (artyp) {
+#ifndef __APPLE__
        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.
                 */
@@ -799,6 +781,7 @@ ar_rdsync()
                        break;
                lstrval = 1;
                break;
+#endif /* !__APPLE__ */
        case ISREG:
        case ISCHR:
        case ISBLK:
@@ -833,7 +816,7 @@ ar_rdsync()
 
 /*
  * ar_fow()
- *     Move the I/O position within the archive foward the specified number of
+ *     Move the I/O position within the archive forward the specified number of
  *     bytes as supported by the device. If we cannot move the requested
  *     number of bytes, return the actual number of bytes moved in skipped.
  * Return:
@@ -841,15 +824,8 @@ ar_rdsync()
  *     partial move (the amount moved is in skipped)
  */
 
-#ifdef __STDC__
 int
 ar_fow(off_t sksz, off_t *skipped)
-#else
-int
-ar_fow(sksz, skipped)
-       off_t sksz;
-       off_t *skipped;
-#endif
 {
        off_t cpos;
        off_t mpos;
@@ -859,7 +835,7 @@ ar_fow(sksz, skipped)
                return(0);
 
        /*
-        * we cannot move foward at EOF or error
+        * we cannot move forward at EOF or error
         */
        if (lstrval <= 0)
                return(lstrval);
@@ -868,7 +844,7 @@ ar_fow(sksz, skipped)
         * Safer to read forward on devices where it is hard to find the end of
         * the media without reading to it. With tapes we cannot be sure of the
         * number of physical blocks to skip (we do not know physical block
-        * size at this point), so we must only read foward on tapes!
+        * size at this point), so we must only read forward on tapes!
         */
        if (artyp != ISREG)
                return(0);
@@ -877,12 +853,12 @@ ar_fow(sksz, skipped)
         * figure out where we are in the archive
         */
        if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) {
-               /* 
-                * we can be asked to move farther than there are bytes in this
+               /*
+                * we can be asked to move farther than there are bytes in this
                 * volume, if so, just go to file end and let normal buf_fill()
                 * deal with the end of file (it will go to next volume by
                 * itself)
-                */
+                */
                if ((mpos = cpos + sksz) > arsb.st_size) {
                        *skipped = arsb.st_size - cpos;
                        mpos = arsb.st_size;
@@ -891,7 +867,7 @@ ar_fow(sksz, skipped)
                if (lseek(arfd, mpos, SEEK_SET) >= 0)
                        return(0);
        }
-       syswarn(1, errno, "Foward positioning operation on archive failed");
+       syswarn(1, errno, "Forward positioning operation on archive failed");
        lstrval = -1;
        return(-1);
 }
@@ -907,18 +883,14 @@ ar_fow(sksz, skipped)
  *     0 if moved the requested distance, -1 on complete failure
  */
 
-#ifdef __STDC__
 int
 ar_rev(off_t sksz)
-#else
-int
-ar_rev(sksz)
-       off_t sksz;
-#endif
 {
        off_t cpos;
+#ifndef __APPLE__
        struct mtop mb;
-       register int phyblk;
+       int phyblk;
+#endif /* __APPLE__ */
 
        /*
         * make sure we do not have try to reverse on a flawed archive
@@ -926,7 +898,7 @@ ar_rev(sksz)
        if (lstrval < 0)
                return(lstrval);
 
-       switch(artyp) {
+       switch (artyp) {
        case ISPIPE:
                if (sksz <= 0)
                        break;
@@ -959,8 +931,8 @@ ar_rev(sksz)
 
                /*
                 * we may try to go backwards past the start when the archive
-                * is only a single record. If this hapens and we are on a
-                * multi volume archive, we need to go to the end of the
+                * is only a single record. If this happens and we are on a
+                * multi-volume archive, we need to go to the end of the
                 * previous volume and continue our movement backwards from
                 * there.
                 */
@@ -981,14 +953,15 @@ ar_rev(sksz)
                        return(-1);
                }
                break;
+#ifndef __APPLE__
        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);
@@ -1029,15 +1002,16 @@ ar_rev(sksz)
                        return(-1);
                }
                break;
+#endif /* !__APPLE__ */
        }
        lstrval = 1;
        return(0);
 }
-
+#ifndef __APPLE__
 /*
  * 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...
@@ -1045,17 +1019,12 @@ ar_rev(sksz)
  *     physical block size if ok (ok > 0), -1 otherwise
  */
 
-#ifdef __STDC__
 static int
 get_phys(void)
-#else
-static int
-get_phys()
-#endif
 {
-       register int padsz = 0;
-       register int res;
-       register int phyblk;
+       int padsz = 0;
+       int res;
+       int phyblk;
        struct mtop mb;
        char scbuf[MAXBLK];
 
@@ -1103,7 +1072,7 @@ get_phys()
        }
 
        /*
-        * read foward to the file mark, then back up in front of the filemark
+        * read forward to the file mark, then back up in front of the filemark
         * (this is a bit paranoid, but should be safe to do).
         */
        while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)
@@ -1152,7 +1121,7 @@ get_phys()
        }
        return(phyblk);
 }
-
+#endif /* !__APPLE__ */
 /*
  * ar_next()
  *     prompts the user for the next volume in this archive. For some devices
@@ -1163,13 +1132,8 @@ get_phys()
  *     0 when ready to continue, -1 when all done
  */
 
-#ifdef __STDC__
 int
 ar_next(void)
-#else
-int
-ar_next()
-#endif
 {
        char buf[PAXPATHLEN+2];
        static int freeit = 0;
@@ -1186,7 +1150,8 @@ ar_next()
        if (sigprocmask(SIG_SETMASK, &o_mask, NULL) < 0)
                syswarn(0, errno, "Unable to restore signal mask");
 
-       if (done || !wr_trail || strcmp(NM_TAR, argv0) == 0)
+       if (frmt == NULL || done || !wr_trail || force_one_volume || strcmp(NM_TAR, argv0) == 0 ||
+           strcmp(NM_PAX, argv0) == 0)
                return(-1);
 
        tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0);
@@ -1212,7 +1177,7 @@ ar_next()
                else
                        tty_prnt("\n");
 
-               for(;;) {
+               for (;;) {
                        tty_prnt("Type \"y\" to continue, \".\" to quit %s,",
                                argv0);
                        tty_prnt(" or \"s\" to switch to new device.\nIf you");
@@ -1291,7 +1256,7 @@ ar_next()
                 */
                if (ar_open(buf) >= 0) {
                        if (freeit) {
-                               (void)free(arcname);
+                               (void)free((char *)arcname);
                                freeit = 0;
                        }
                        if ((arcname = strdup(buf)) == NULL) {
@@ -1315,58 +1280,39 @@ ar_next()
  * to keep the fd the same in the calling function (parent).
  */
 void
-#ifdef __STDC__
-ar_start_gzip(int fd)
-#else
-ar_start_gzip(fd)
-       int fd;
-#endif
+ar_start_gzip(int fd, const char *gzip_program, int wr)
 {
-       pid_t pid;
        int fds[2];
-       char *gzip_flags=NULL;
+       const char *gzip_flags = NULL;
 
        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 */
        }
 }