revert to spawning compress-ing program. normally we want extracts using
authorderaadt <deraadt@openbsd.org>
Mon, 9 Dec 1996 12:00:13 +0000 (12:00 +0000)
committerderaadt <deraadt@openbsd.org>
Mon, 9 Dec 1996 12:00:13 +0000 (12:00 +0000)
'z' to also work on .Z files, but libz does not deal with compressed
data. Hacking the code to deal well with pipes has proven very hard.

bin/pax/Makefile
bin/pax/ar_io.c
bin/pax/extern.h
bin/pax/options.c
bin/pax/pax.h

index 0a8a8ed..ebaa9f8 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.4 1996/09/22 20:09:52 tholo Exp $
+#      $OpenBSD: Makefile,v 1.5 1996/12/09 12:00:13 deraadt Exp $
 #      $NetBSD: Makefile,v 1.4 1995/03/21 09:07:02 cgd Exp $
 
 # To install on versions prior to BSD 4.4 the following may have to be
 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 zopen.c
-LDADD+=        -lz
-DPADD+=        ${LIBZ}
+       tar.c tty_subs.c
 MAN=   pax.1 tar.1
 LINKS= ${BINDIR}/pax ${BINDIR}/tar
 
-.PATH: ${.CURDIR}/../../usr.bin/compress
-
 .include <bsd.prog.mk>
index 3573f7c..aff14dc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ar_io.c,v 1.7 1996/11/24 18:15:59 millert Exp $       */
+/*     $OpenBSD: ar_io.c,v 1.8 1996/12/09 12:00:13 deraadt Exp $       */
 /*     $NetBSD: ar_io.c,v 1.5 1996/03/26 23:54:13 mrg Exp $    */
 
 /*-
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)ar_io.c    8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: ar_io.c,v 1.7 1996/11/24 18:15:59 millert Exp $";
+static char rcsid[] = "$OpenBSD: ar_io.c,v 1.8 1996/12/09 12:00:13 deraadt Exp $";
 #endif
 #endif /* not lint */
 
@@ -60,7 +60,6 @@ static char rcsid[] = "$OpenBSD: ar_io.c,v 1.7 1996/11/24 18:15:59 millert Exp $
 #include <errno.h>
 #include <stdlib.h>
 #include <err.h>
-#include <zlib.h>
 #include "pax.h"
 #include "extern.h"
 
@@ -85,13 +84,12 @@ 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?  */
-static gzFile gzf;                     /* file pointer for gzip archives */
-static FILE *cfp;                      /* file pointer for compress archives */
 char *arcname;                         /* printable name of archive */
+char *gzip_program;                    /* name of gzip program */
 
-FILE *zdopen __P((int, const char *));
 static int get_phys __P((void));
 extern sigset_t s_mask;
+static void ar_start_gzip __P((int));
 
 /*
  * ar_open()
@@ -113,14 +111,8 @@ ar_open(name)
 {
         struct mtget mb;
 
-       if (arfd != -1) {
-               if (zflag == GZIP_CMP)
-                       (void)gzclose(gzf);
-               else if (zflag == COMPRESS_CMP)
-                       (void)fclose(cfp);
-               else
-                       (void)close(arfd);
-       }
+       if (arfd != -1)
+               (void)close(arfd);
        arfd = -1;
        can_unlnk = did_io = io_ok = invld_rec = 0;
        artyp = ISREG;
@@ -137,15 +129,8 @@ ar_open(name)
                        arcname = STDN;
                } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0)
                        syswarn(0, errno, "Failed open to read on %s", name);
-               if (zflag == GZIP_CMP) {
-                       gzf = gzdopen(arfd, "r");
-                       if (gzf && !gz_iszipped(gzf)) {
-                               (void)lseek(arfd, 0, SEEK_SET);
-                               zflag = COMPRESS_CMP;
-                       }
-               }
-               if (zflag == COMPRESS_CMP)
-                       cfp = zdopen(arfd, "r");
+               if (zflag)
+                       ar_start_gzip(arfd);
                break;
        case ARCHIVE:
                if (name == NULL) {
@@ -155,14 +140,12 @@ ar_open(name)
                        syswarn(0, errno, "Failed open to write on %s", name);
                else
                        can_unlnk = 1;
-               if (zflag == GZIP_CMP)
-                       gzf = gzdopen(arfd, "w");
-               else if (zflag == COMPRESS_CMP)
-                       cfp = zdopen(arfd, "w");
+               if (zflag)
+                       ar_start_gzip(arfd);
                break;
        case APPND:
                if (zflag)
-                       err(1, "can not compress while appending");
+                       err(1, "can not gzip while appending");
                if (name == NULL) {
                        arfd = STDOUT_FILENO;
                        arcname = STDO;
@@ -186,12 +169,7 @@ ar_open(name)
         */
        if (fstat(arfd, &arsb) < 0) {
                syswarn(0, errno, "Failed stat on %s", arcname);
-               if (zflag == GZIP_CMP)
-                       (void)gzclose(gzf);
-               else if (zflag == COMPRESS_CMP)
-                       (void)fclose(cfp);
-               else
-                       (void)close(arfd);
+               (void)close(arfd);
                arfd = -1;
                can_unlnk = 0;
                return(-1);
@@ -199,12 +177,7 @@ ar_open(name)
        if (S_ISDIR(arsb.st_mode)) {
                paxwarn(0, "Cannot write an archive on top of a directory %s",
                    arcname);
-               if (zflag == GZIP_CMP)
-                       (void)gzclose(gzf);
-               else if (zflag == COMPRESS_CMP)
-                       (void)fclose(cfp);
-               else
-                       (void)close(arfd);
+               (void)close(arfd);
                arfd = -1;
                can_unlnk = 0;
                return(-1);
@@ -376,12 +349,7 @@ ar_close()
                can_unlnk = 0;
        }
 
-       if (zflag == GZIP_CMP)
-               (void)gzclose(gzf);
-       else if (zflag == COMPRESS_CMP)
-               (void)fclose(cfp);
-       else
-               (void)close(arfd);
+       (void)close(arfd);
 
        if (vflag && (artyp == ISTAPE)) {
                (void)fputs("done.\n", outf);
@@ -473,18 +441,8 @@ ar_drain()
        /*
         * keep reading until pipe is drained
         */
-       if (zflag == GZIP_CMP) {
-               while ((res = gzread(gzf, drbuf, sizeof(drbuf))) > 0)
-                       ;
-       }
-       else if (zflag == COMPRESS_CMP) {
-               while ((res = fread(drbuf, 1, sizeof(drbuf), cfp)) > 0)
-                       ;
-       }
-       else {
-               while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0)
-                       ;
-       }
+       while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0)
+               ;
        lstrval = res;
 }
 
@@ -554,11 +512,6 @@ ar_app_ok()
                return(-1);
        }
 
-       if (zflag) {
-               paxwarn(1, "Cannot append to a compressed archive.");
-               return(-1);
-       }
-
        if (!invld_rec)
                return(0);
        paxwarn(1,"Cannot append, device record size %d does not support %s spec",
@@ -598,34 +551,32 @@ ar_read(buf, cnt)
         */
        switch (artyp) {
        case ISTAPE:
-               if (!zflag) {
-                       if ((res = read(arfd, buf, cnt)) > 0) {
+               if ((res = read(arfd, buf, cnt)) > 0) {
+                       /*
+                        * CAUTION: tape systems may not always return the same
+                        * sized records so we leave blksz == MAXBLK. The
+                        * physical record size that a tape drive supports is
+                        * very hard to determine in a uniform and portable
+                        * manner.
+                        */
+                       io_ok = 1;
+                       if (res != rdblksz) {
                                /*
-                                * CAUTION: tape systems may not always return the same
-                                * sized records so we leave blksz == MAXBLK. The
-                                * physical record size that a tape drive supports is
-                                * very hard to determine in a uniform and portable
-                                * manner.
+                                * Record size changed. If this is 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
+                                * read). Watch out for record blocking that
+                                * violates pax spec (must be a multiple of
+                                * BLKMULT).
                                 */
-                               io_ok = 1;
-                               if (res != rdblksz) {
-                                       /*
-                                        * Record size changed. If this is 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
-                                        * read). Watch out for record blocking that
-                                        * violates pax spec (must be a multiple of
-                                        * BLKMULT).
-                                        */
-                                       rdblksz = res;
-                                       if (rdblksz % BLKMULT)
-                                               invld_rec = 1;
-                               }
-                               return(res);
+                               rdblksz = res;
+                               if (rdblksz % BLKMULT)
+                                       invld_rec = 1;
                        }
-                       break;
+                       return(res);
                }
+               break;
        case ISREG:
        case ISBLK:
        case ISCHR:
@@ -638,23 +589,9 @@ ar_read(buf, cnt)
                 * and return. Trying to do anything else with them runs the
                 * risk of failure.
                 */
-               if (zflag == GZIP_CMP) {
-                       if ((res = gzread(gzf, buf, cnt)) > 0) {
-                               io_ok = 1;
-                               return(res);
-                       }
-               }
-               else if (zflag == COMPRESS_CMP) {
-                       if ((res = fread(buf, 1, cnt, cfp)) > 0) {
-                               io_ok = 1;
-                               return(res);
-                       }
-               }
-               else {
-                       if ((res = read(arfd, buf, cnt)) > 0) {
-                               io_ok = 1;
-                               return(res);
-                       }
+               if ((res = read(arfd, buf, cnt)) > 0) {
+                       io_ok = 1;
+                       return(res);
                }
                break;
        }
@@ -701,26 +638,10 @@ ar_write(buf, bsz)
        if (lstrval <= 0)
                return(lstrval);
 
-       if (zflag == GZIP_CMP) {
-               if ((res = gzwrite(gzf, buf, bsz)) == bsz) {
-                       wr_trail = 1;
-                       io_ok = 1;
-                       return(bsz);
-               }
-       }
-       else if (zflag == COMPRESS_CMP) {
-               if ((res = fwrite(buf, 1, bsz, cfp)) == bsz) {
-                       wr_trail = 1;
-                       io_ok = 1;
-                       return(bsz);
-               }
-       }
-       else {
-               if ((res = write(arfd, buf, bsz)) == bsz) {
-                       wr_trail = 1;
-                       io_ok = 1;
-                       return(bsz);
-               }
+       if ((res = write(arfd, buf, bsz)) == bsz) {
+               wr_trail = 1;
+               io_ok = 1;
+               return(bsz);
        }
        /*
         * write broke, see what we can do with it. We try to send any partial
@@ -731,55 +652,53 @@ ar_write(buf, bsz)
        else
                lstrval = 0;
 
-       if (!zflag) {
-               switch (artyp) {
-               case ISREG:
-                       if ((res > 0) && (res % 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;
-                               if (ftruncate(arfd, cpos) < 0)
-                                       break;
-                               res = lstrval = 0;
+       switch (artyp) {
+       case ISREG:
+               if ((res > 0) && (res % 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;
-                       }
-                       if (res >= 0)
+                       cpos -= (off_t)res;
+                       if (ftruncate(arfd, cpos) < 0)
                                break;
-                       /*
-                        * if file is out of space, handle it like a return of 0
-                        */
-                       if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT))
-                               res = lstrval = 0;
+                       res = lstrval = 0;
                        break;
-               case ISTAPE:
-               case ISCHR:
-               case ISBLK:
-                       if (res >= 0)
-                               break;
-                       if (errno == EACCES) {
-                               paxwarn(0, "Write failed, archive is write protected.");
-                               res = lstrval = 0;
-                               return(0);
-                       }
-                       /*
-                        * see if we reached the end of media, if so force a change to
-                        * the next volume
-                        */
-                       if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO))
-                               res = lstrval = 0;
+               }
+               if (res >= 0)
                        break;
-               case ISPIPE:
-               default:
-                       /*
-                        * we cannot fix errors to these devices
-                        */
+               /*
+                * if file is out of space, handle it like a return of 0
+                */
+               if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT))
+                       res = lstrval = 0;
+               break;
+       case ISTAPE:
+       case ISCHR:
+       case ISBLK:
+               if (res >= 0)
                        break;
+               if (errno == EACCES) {
+                       paxwarn(0, "Write failed, archive is write protected.");
+                       res = lstrval = 0;
+                       return(0);
                }
+               /*
+                * see if we reached the end of media, if so force a change to
+                * the next volume
+                */
+               if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO))
+                       res = lstrval = 0;
+               break;
+       case ISPIPE:
+       default:
+               /*
+                * we cannot fix errors to these devices
+                */
+               break;
        }
 
        /*
@@ -852,54 +771,50 @@ ar_rdsync()
        if (io_ok)
                did_io = 1;
 
-       if (zflag)
-               io_ok = 0;
-       else {
-               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
-                        * damaged tape section. Some tape drives are stubborn and need
-                        * to be pushed.
-                        */
-                       if (io_ok) {
-                               io_ok = 0;
-                               lstrval = 1;
-                               break;
-                       }
-                       mb.mt_op = MTFSR;
-                       mb.mt_count = 1;
-                       if (ioctl(arfd, MTIOCTOP, &mb) < 0)
-                               break;
-                       lstrval = 1;
-                       break;
-               case ISREG:
-               case ISCHR:
-               case ISBLK:
-                       /*
-                        * try to step over the bad part of the device.
-                        */
+       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
+                * damaged tape section. Some tape drives are stubborn and need
+                * to be pushed.
+                */
+               if (io_ok) {
                        io_ok = 0;
-                       if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG))
-                               fsbz = BLKMULT;
-                       if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
-                               break;
-                       mpos = fsbz - (cpos % (off_t)fsbz);
-                       if (lseek(arfd, mpos, SEEK_CUR) < 0) 
-                               break;
                        lstrval = 1;
                        break;
-               case ISPIPE:
-               default:
-                       /*
-                        * cannot recover on these archive device types
-                        */
-                       io_ok = 0;
-                       break;
                }
+               mb.mt_op = MTFSR;
+               mb.mt_count = 1;
+               if (ioctl(arfd, MTIOCTOP, &mb) < 0)
+                       break;
+               lstrval = 1;
+               break;
+       case ISREG:
+       case ISCHR:
+       case ISBLK:
+               /*
+                * try to step over the bad part of the device.
+                */
+               io_ok = 0;
+               if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG))
+                       fsbz = BLKMULT;
+               if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
+                       break;
+               mpos = fsbz - (cpos % (off_t)fsbz);
+               if (lseek(arfd, mpos, SEEK_CUR) < 0) 
+                       break;
+               lstrval = 1;
+               break;
+       case ISPIPE:
+       default:
+               /*
+                * cannot recover on these archive device types
+                */
+               io_ok = 0;
+               break;
        }
        if (lstrval <= 0) {
                paxwarn(1, "Unable to recover from an archive read failure.");
@@ -933,7 +848,7 @@ ar_fow(sksz, skipped)
        off_t mpos;
 
        *skipped = 0;
-       if (zflag || sksz <= 0)
+       if (sksz <= 0)
                return(0);
 
        /*
@@ -1004,19 +919,6 @@ ar_rev(sksz)
        if (lstrval < 0)
                return(lstrval);
 
-       if (zflag) {
-               if (sksz <= 0) {
-                       lstrval = 1;
-                       return 0;
-               }
-               /*
-                * cannot go backwards on these critters
-                */
-               paxwarn(1, "Reverse positioning on pipes is not supported.");
-               lstrval = -1;
-               return(-1);
-       }
-
        switch(artyp) {
        case ISPIPE:
                if (sksz <= 0) 
@@ -1150,11 +1052,6 @@ get_phys()
        struct mtop mb;
        char scbuf[MAXBLK];
 
-       if (zflag) {
-               syswarn(1, errno, "Cannot determine archive tape blocksize.");
-               return(-1);
-       }
-
        /*
         * move to the file mark, and then back up one record and read it.
         * this should tell us the physical record size the tape is using.
@@ -1404,3 +1301,65 @@ ar_next()
        }
        return(0);
 }
+
+/*
+ * 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).
+ */
+void
+#ifdef __STDC__
+ar_start_gzip(int fd)
+#else
+ar_start_gzip(fd)
+       int fd;
+#endif
+{
+       pid_t pid;
+       int fds[2];
+       char *gzip_flags;
+
+       if (pipe(fds) < 0)
+               err(1, "could not pipe");
+       pid = fork();
+       if (pid < 0)
+               err(1, "could not fork");
+
+       /* parent */
+       if (pid) {
+               switch (act) {
+               case ARCHIVE:
+                       dup2(fds[1], fd);
+                       break;
+               case LIST:
+               case EXTRACT:
+                       dup2(fds[0], fd);
+                       break;
+               default:
+                       errx(1, "ar_start_gzip:  impossible");
+               }
+               close(fds[0]);
+               close(fds[1]);
+       } else {
+               switch (act) {
+               case ARCHIVE:
+                       dup2(fds[0], STDIN_FILENO);
+                       dup2(fd, STDOUT_FILENO);
+                       gzip_flags = "-c";
+                       break;
+               case LIST:
+               case EXTRACT:
+                       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");
+               /* NOTREACHED */
+       }
+}
index b6f42b6..908c562 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: extern.h,v 1.6 1996/10/27 06:45:10 downsj Exp $       */
+/*     $OpenBSD: extern.h,v 1.7 1996/12/09 12:00:14 deraadt Exp $      */
 /*     $NetBSD: extern.h,v 1.5 1996/03/26 23:54:16 mrg Exp $   */
 
 /*-
@@ -50,6 +50,7 @@
  * ar_io.c
  */
 extern char *arcname;
+extern char *gzip_program;
 int ar_open __P((char *));
 void ar_close __P((void));
 void ar_drain __P((void));
index f23419b..4bdffe2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: options.c,v 1.10 1996/10/27 06:45:12 downsj Exp $     */
+/*     $OpenBSD: options.c,v 1.11 1996/12/09 12:00:15 deraadt Exp $    */
 /*     $NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg Exp $  */
 
 /*-
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)options.c  8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: options.c,v 1.10 1996/10/27 06:45:12 downsj Exp $";
+static char rcsid[] = "$OpenBSD: options.c,v 1.11 1996/12/09 12:00:15 deraadt Exp $";
 #endif
 #endif /* not lint */
 
@@ -84,6 +84,9 @@ static void cpio_options __P((register int, register char **));
 static void cpio_usage __P((void));
 #endif
 
+#define GZIP_CMD       "gzip"          /* command to run as gzip */
+#define COMPRESS_CMD   "compress"      /* command to run as compress */
+
 /*
  *     Format specific routine table - MUST BE IN SORTED ORDER BY NAME
  *     (see pax.h for description of each function)
@@ -388,7 +391,8 @@ pax_options(argc, argv)
                        /*
                         * use gzip.  Non standard option.
                         */
-                       zflag = GZIP_CMP;
+                       zflag = 1;
+                       gzip_program = GZIP_CMD;
                        break;
                case 'B':
                        /*
@@ -701,7 +705,8 @@ tar_options(argc, argv)
                        /*
                         * use gzip.  Non standard option.
                         */
-                       zflag = GZIP_CMP;
+                       zflag = 1;
+                       gzip_program = GZIP_CMD;
                        break;
                case 'B':
                        /*
@@ -739,7 +744,8 @@ tar_options(argc, argv)
                        /*
                         * use compress.
                         */
-                       zflag = COMPRESS_CMP;
+                       zflag = 1;
+                       gzip_program = COMPRESS_CMD;
                        break;
                case '0':
                        arcname = DEV_0;
index 7e0993d..50a2aac 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pax.h,v 1.5 1996/10/27 06:45:14 downsj Exp $  */
+/*     $OpenBSD: pax.h,v 1.6 1996/12/09 12:00:16 deraadt Exp $ */
 /*     $NetBSD: pax.h,v 1.3 1995/03/21 09:07:41 cgd Exp $      */
 
 /*-
 #define ISTAPE         3       /* tape drive */
 #define ISPIPE         4       /* pipe/socket */
 
-/*
- * Compression types
- */
-#define        GZIP_CMP        1       /* gzip format */
-#define        COMPRESS_CMP    2       /* compress format */
-
 /*
  * Format Specific Routine Table
  *