Hi all,

Please review the following code from OpenBSD; it adds -z and -Z
options to pax(1) to gzip(1) the archives created.

Kris

Index: ar_io.c
===================================================================
RCS file: /home/ncvs/src/bin/pax/ar_io.c,v
retrieving revision 1.14
diff -u -r1.14 ar_io.c
--- ar_io.c     2001/04/26 09:22:27     1.14
+++ ar_io.c     2001/04/26 09:52:32
@@ -44,16 +44,18 @@
 #endif /* not lint */
 
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/mtio.h>
-#include <signal.h>
-#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <err.h>
+#include <errno.h>
 #include <fcntl.h>
-#include <unistd.h>
+#include <signal.h>
 #include <stdio.h>
-#include <errno.h>
+#include <string.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include "pax.h"
 #include "extern.h"
 
@@ -79,9 +81,12 @@
 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 */
+const char *gzip_program;              /* name of gzip program */
+static pid_t zpid = -1;                        /* pid of child process */
 
 static int get_phys __P((void));
 extern sigset_t s_mask;
+static void ar_start_gzip __P((int, const char *, int));
 
 /*
  * ar_open()
@@ -121,6 +126,8 @@
                        arcname = STDN;
                } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0)
                        syswarn(0, 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) {
@@ -130,6 +137,8 @@
                        syswarn(0, errno, "Failed open to write on %s", name);
                else
                        can_unlnk = 1;
+               if (arfd != -1 && gzip_program != NULL)
+                       ar_start_gzip(arfd, gzip_program, 1);
                break;
        case APPND:
                if (name == NULL) {
@@ -335,6 +344,16 @@
                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) {
+               int status;
+               kill(zpid, SIGINT);
+               waitpid(zpid, &status, 0);
+       }
+
        (void)close(arfd);
 
        if (vflag && (artyp == ISTAPE)) {
@@ -1286,4 +1305,47 @@
                continue;
        }
        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
+ar_start_gzip(int fd, const char *gzip_program, int wr)
+{
+       int fds[2];
+       char *gzip_flags;
+
+       if (pipe(fds) < 0)
+               err(1, "could not pipe");
+       zpid = fork();
+       if (zpid < 0)
+               err(1, "could not fork");
+
+       /* parent */
+       if (zpid) {
+               if (wr)
+                       dup2(fds[1], fd);
+               else
+                       dup2(fds[0], fd);
+               close(fds[0]);
+               close(fds[1]);
+       } else {
+               if (wr) {
+                       dup2(fds[0], STDIN_FILENO);
+                       dup2(fd, STDOUT_FILENO);
+                       gzip_flags = "-c";
+               } else {
+                       dup2(fds[1], STDOUT_FILENO);
+                       dup2(fd, STDIN_FILENO);
+                       gzip_flags = "-dc";
+               }
+               close(fds[0]);
+               close(fds[1]);
+               if (execlp(gzip_program, gzip_program, gzip_flags, NULL) < 0)
+                       err(1, "could not exec");
+               /* NOTREACHED */
+       }
 }
Index: extern.h
===================================================================
RCS file: /home/ncvs/src/bin/pax/extern.h,v
retrieving revision 1.10
diff -u -r1.10 extern.h
--- extern.h    2001/04/26 08:37:00     1.10
+++ extern.h    2001/04/26 09:52:32
@@ -48,6 +48,7 @@
  * ar_io.c
  */
 extern char *arcname;
+extern const char *gzip_program;
 int ar_open __P((char *));
 void ar_close __P((void));
 void ar_drain __P((void));
Index: options.c
===================================================================
RCS file: /home/ncvs/src/bin/pax/options.c,v
retrieving revision 1.17
diff -u -r1.17 options.c
--- options.c   2001/04/26 09:22:28     1.17
+++ options.c   2001/04/26 09:52:32
@@ -78,6 +78,9 @@
 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)
@@ -192,7 +195,7 @@
        /*
         * process option flags
         */
-       while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:B:DE:G:HLPT:U:XYZ"))
+       while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:zB:DE:G:HLPT:U:XYZ"))
            != -1) {
                switch (c) {
                case 'a':
@@ -376,6 +379,12 @@
                        (void)fputs("\n\n", stderr);
                        pax_usage();
                        break;
+               case 'z':
+                       /*
+                        * use gzip.  Non standard option.
+                        */
+                       gzip_program = GZIP_CMD;
+                       break;
                case 'B':
                        /*
                         * non-standard option on number of bytes written on a
@@ -694,6 +703,12 @@
                         */
                        act = EXTRACT;
                        break;
+               case 'z':
+                       /*
+                        * use gzip.  Non standard option.
+                        */
+                       gzip_program = GZIP_CMD;
+                       break;
                case 'B':
                        /*
                         * Nothing to do here, this is pax default
@@ -723,6 +738,12 @@
                         */
                        Xflag = 1;
                        break;
+               case 'Z':
+                       /*
+                        * use compress.
+                        */
+                       gzip_program = COMPRESS_CMD;
+                       break;
                case '0':
                        arcname = DEV_0;
                        break;
@@ -1075,18 +1096,18 @@
 pax_usage()
 #endif
 {
-       (void)fputs("usage: pax [-cdnv] [-E limit] [-f archive] ", stderr);
+       (void)fputs("usage: pax [-cdnvz] [-E limit] [-f archive] ", stderr);
        (void)fputs("[-s replstr] ... [-U user] ...", stderr);
        (void)fputs("\n    [-G group] ... ", stderr);
        (void)fputs("[-T [from_date][,to_date]] ... ", stderr);
        (void)fputs("[pattern ...]\n", stderr);
-       (void)fputs("       pax -r [-cdiknuvDYZ] [-E limit] ", stderr);
+       (void)fputs("       pax -r [-cdiknuvzDYZ] [-E limit] ", stderr);
        (void)fputs("[-f archive] [-o options] ... \n", stderr);
        (void)fputs("      [-p string] ... [-s replstr] ... ", stderr);
        (void)fputs("[-U user] ... [-G group] ...\n        ", stderr);
        (void)fputs("[-T [from_date][,to_date]] ... ", stderr);
        (void)fputs(" [pattern ...]\n", stderr);
-       (void)fputs("       pax -w [-dituvHLPX] [-b blocksize] ", stderr);
+       (void)fputs("       pax -w [-dituvzHLPX] [-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);
@@ -1114,7 +1135,7 @@
 tar_usage()
 #endif
 {
-       (void)fputs("usage: tar -{txru}[cevfbmopwBHLPX014578] [tapefile] ",
+       (void)fputs("usage: tar -{txru}[cevfbmopwzBHLPXZ014578] [tapefile] ",
                 stderr);
        (void)fputs("[blocksize] file1 file2...\n", stderr);
        exit(1);
Index: pax.1
===================================================================
RCS file: /home/ncvs/src/bin/pax/pax.1,v
retrieving revision 1.16
diff -u -r1.16 pax.1
--- pax.1       2001/02/13 09:50:27     1.16
+++ pax.1       2001/04/26 09:52:33
@@ -44,7 +44,7 @@
 .Nd read and write file archives and copy directory hierarchies
 .Sh SYNOPSIS
 .Nm
-.Op Fl cdnv
+.Op Fl cdnvz
 .Bk -words
 .Op Fl f Ar archive
 .Ek
@@ -71,7 +71,7 @@
 .Op Ar pattern ...\&
 .Nm
 .Fl r
-.Op Fl cdiknuvDYZ
+.Op Fl cdiknuvzDYZ
 .Bk -words
 .Op Fl f Ar archive
 .Ek
@@ -107,7 +107,7 @@
 .Op Ar pattern ...\&
 .Nm
 .Fl w
-.Op Fl dituvHLPX
+.Op Fl dituvzHLPX
 .Bk -words
 .Op Fl b Ar blocksize
 .Ek
@@ -756,6 +756,12 @@
 The individual archive formats may impose additional restrictions on use.
 Typical archive format restrictions include (but are not limited to):
 file pathname length, file size, link pathname length and the type of the file.
+.It Fl z
+Use
+.Xr gzip 1
+to compress (decompress) the archive while writing (reading).
+Incompatible with
+.Fl a .
 .It Fl B Ar bytes
 Limit the number of bytes written to a single archive volume to
 .Ar bytes .
Index: pax.c
===================================================================
RCS file: /home/ncvs/src/bin/pax/pax.c,v
retrieving revision 1.17
diff -u -r1.17 pax.c
--- pax.c       2001/04/26 09:22:28     1.17
+++ pax.c       2001/04/26 09:52:33
@@ -53,6 +53,7 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/resource.h>
+#include <err.h>
 #include <errno.h>
 #include <locale.h>
 #include <paths.h>
@@ -272,6 +273,8 @@
                archive();
                break;
        case APPND:
+               if (gzip_program != NULL)
+                       err(1, "can not gzip while appending");
                append();
                break;
        case COPY:

PGP signature

Reply via email to