Support for tar -z option for uncompressing only
authorGlenn L McGrath <bug1@ihug.co.nz>
Sun, 10 Dec 2000 01:57:30 +0000 (01:57 -0000)
committerGlenn L McGrath <bug1@ihug.co.nz>
Sun, 10 Dec 2000 01:57:30 +0000 (01:57 -0000)
Changelog
Config.h
archival/gunzip.c
archival/tar.c
gunzip.c
tar.c

index 2c6fbabd9200cdadfd9690ec496cfd5a5e73a8d5..6a1612876371fb0c1b7c11de6d2763557ff1b70b 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,5 +1,7 @@
 0.48
 
+       * Glenn McGrath -- tar now supports uncompressing tar files,
+           define BB_FEATURE_TAR_GZIP to use the -z option.
        * Matt Kraai -- fix all usage of TRUE and FALSE so all apps now
            return EXIT_SUCCESS or EXIT_FAILURE to the system.
            Now TRUE and FALSE are set to the C standard where TRUE=1.
index 50f9e3ac789bbc68ca4c6d52b4ab8fd240934c28..d95942a6553744544f3f27b1ce7653fc928c215f 100644 (file)
--- a/Config.h
+++ b/Config.h
 // Enable support for "--exclude" and "-X" for excluding files
 #define BB_FEATURE_TAR_EXCLUDE
 //
+// Enable support for tar -z option (currently only works for inflating)
+#define BB_FEATURE_TAR_GZIP 
+//
 //// Enable reverse sort
 #define BB_FEATURE_SORT_REVERSE
 //
 #endif
 #endif
 //
+#ifdef BB_FEATURE_TAR_GZIP
+#ifndef BB_GUNZIP
+#define BB_GUNZIP
+#endif
+#endif
+//
 #if defined BB_MOUNT && defined BB_FEATURE_NFSMOUNT
 #define BB_NFSMOUNT
 #endif
index 48db7cfd79321c178902dc081dda78235a27480b..8558573baaad75c2073c971401eff4131b7269cc 100644 (file)
@@ -1084,7 +1084,7 @@ int inflate()
  *   the compressed data, from offsets inptr to insize-1 included.
  *   The magic header has already been checked. The output buffer is cleared.
  */
-int unzip(in, out)
+extern int unzip(in, out)
 int in, out;                                   /* input and output file descriptors */
 {
        int ext_header = 0;                             /* set if extended local header */
@@ -1179,7 +1179,7 @@ void clear_bufs(void)
 /* ===========================================================================
  * Initialize gunzip buffers and signals
  */
-static int gunzip_init()
+extern int gunzip_init()
 {
        foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
        if (foreground) {
index cc7ba3b80d349f12761a328c85d18a818e0e070b..8c2650e2b65a43b2605dade856b70f4ca791de4d 100644 (file)
 #include <sys/sysmacros.h>
 #include <getopt.h>
 
+#ifdef BB_FEATURE_TAR_GZIP
+extern int unzip(int in, int out);
+extern int gunzip_init();
+#endif
+
 /* Tar file constants  */
 #ifndef MAJOR
 #define MAJOR(dev) (((dev)>>8)&0xff)
@@ -129,29 +134,64 @@ struct TarInfo
 typedef struct TarInfo TarInfo;
 
 /* Local procedures to restore files from a tar file.  */
-static int readTarFile(const char* tarName, int extractFlag, int listFlag, 
+static int readTarFile(int tarFd, int extractFlag, int listFlag, 
                int tostdoutFlag, int verboseFlag, char** extractList,
                char** excludeList);
 
-
-
 #ifdef BB_FEATURE_TAR_CREATE
 /* Local procedures to save files into a tar file.  */
 static int writeTarFile(const char* tarName, int verboseFlag, char **argv,
                char** excludeList);
 #endif
 
+#ifdef BB_FEATURE_TAR_GZIP
+/* Signal handler for when child gzip process dies...  */
+void child_died()
+{
+       fflush(stdout);
+       fflush(stderr);
+       exit(EXIT_FAILURE);
+}
+
+static int tar_unzip_init(int tarFd)
+{
+       int child_pid;
+       static int unzip_pipe[2];
+       /* Cope if child dies... Otherwise we block forever in read()... */
+       signal(SIGCHLD, child_died);
+
+       if (pipe(unzip_pipe)!=0)
+               error_msg_and_die("pipe error\n");
+                       
+       if ( (child_pid = fork()) == -1)
+               error_msg_and_die("fork failure\n");
+
+       if (child_pid==0) {
+               /* child process */
+               gunzip_init();
+               unzip(tarFd, unzip_pipe[1]);
+               exit(EXIT_SUCCESS);
+       }
+       else
+               /* return fd of uncompressed data to parent process */
+               return(unzip_pipe[0]);
+}
+#endif
+
 extern int tar_main(int argc, char **argv)
 {
        char** excludeList=NULL;
        char** extractList=NULL;
+       const char *tarName="-";
 #if defined BB_FEATURE_TAR_EXCLUDE
        int excludeListSize=0;
-        char *excludeFileName ="-";
-        FILE *fileList;
-        char file[256];
+       char *excludeFileName ="-";
+       FILE *fileList;
+       char file[256];
+#endif
+#if defined BB_FEATURE_TAR_GZIP
+       int unzipFlag    = FALSE;
 #endif
-       const char *tarName="-";
        int listFlag     = FALSE;
        int extractFlag  = FALSE;
        int createFlag   = FALSE;
@@ -160,7 +200,6 @@ extern int tar_main(int argc, char **argv)
        int status       = FALSE;
        int firstOpt     = TRUE;
        int stopIt;
-                                                                                                                                                  
 
        if (argc <= 1)
                usage(tar_usage);
@@ -185,6 +224,11 @@ extern int tar_main(int argc, char **argv)
                                                goto flagError;
                                        listFlag = TRUE;
                                        break;
+#ifdef BB_FEATURE_TAR_GZIP
+                               case 'z':
+                                       unzipFlag = TRUE;
+                                       break;
+#endif
                                case 'v':
                                        verboseFlag = TRUE;
                                        break;
@@ -255,13 +299,31 @@ extern int tar_main(int argc, char **argv)
 #ifndef BB_FEATURE_TAR_CREATE
                error_msg_and_die( "This version of tar was not compiled with tar creation support.\n");
 #else
+#ifdef BB_FEATURE_TAR_GZIP
+               if (unzipFlag==TRUE)
+                       error_msg_and_die("Creation of compressed not internally support by tar, pipe to busybox gunzip\n");
+#endif
                status = writeTarFile(tarName, verboseFlag, argv, excludeList);
 #endif
        }
        if (listFlag == TRUE || extractFlag == TRUE) {
+               int tarFd;
                if (*argv)
                        extractList = argv;
-               status = readTarFile(tarName, extractFlag, listFlag, tostdoutFlag,
+               /* Open the tar file for reading.  */
+               if (!strcmp(tarName, "-"))
+                       tarFd = fileno(stdin);
+               else
+                       tarFd = open(tarName, O_RDONLY);
+               if (tarFd < 0)
+                       error_msg_and_die( "Error opening '%s': %s\n", tarName, strerror(errno));
+
+#ifdef BB_FEATURE_TAR_GZIP     
+               /* unzip tarFd in a seperate process */
+               if (unzipFlag == TRUE)
+                       tarFd = tar_unzip_init(tarFd);
+#endif                 
+               status = readTarFile(tarFd, extractFlag, listFlag, tostdoutFlag,
                                        verboseFlag, extractList, excludeList);
        }
 
@@ -521,27 +583,17 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
  * Read a tar file and extract or list the specified files within it.
  * If the list is empty than all files are extracted or listed.
  */
-static int readTarFile(const char* tarName, int extractFlag, int listFlag, 
+extern int readTarFile(int tarFd, int extractFlag, int listFlag, 
                int tostdoutFlag, int verboseFlag, char** extractList,
                char** excludeList)
 {
-       int status, tarFd=-1;
+       int status;
        int errorFlag=FALSE;
        int skipNextHeaderFlag=FALSE;
        TarHeader rawHeader;
        TarInfo header;
        char** tmpList;
 
-       /* Open the tar file for reading.  */
-       if (!strcmp(tarName, "-"))
-               tarFd = fileno(stdin);
-       else
-               tarFd = open(tarName, O_RDONLY);
-       if (tarFd < 0) {
-               error_msg( "Error opening '%s': %s\n", tarName, strerror(errno));
-               return ( FALSE);
-       }
-
        /* Set the umask for this process so it doesn't 
         * screw up permission setting for us later. */
        umask(0);
@@ -739,7 +791,7 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
        close(tarFd);
        if (status > 0) {
                /* Bummer - we read a partial header */
-               error_msg( "Error reading '%s': %s\n", tarName, strerror(errno));
+               error_msg( "Error reading tar file: %s\n", strerror(errno));
                return ( FALSE);
        }
        else if (errorFlag==TRUE) {
index 48db7cfd79321c178902dc081dda78235a27480b..8558573baaad75c2073c971401eff4131b7269cc 100644 (file)
--- a/gunzip.c
+++ b/gunzip.c
@@ -1084,7 +1084,7 @@ int inflate()
  *   the compressed data, from offsets inptr to insize-1 included.
  *   The magic header has already been checked. The output buffer is cleared.
  */
-int unzip(in, out)
+extern int unzip(in, out)
 int in, out;                                   /* input and output file descriptors */
 {
        int ext_header = 0;                             /* set if extended local header */
@@ -1179,7 +1179,7 @@ void clear_bufs(void)
 /* ===========================================================================
  * Initialize gunzip buffers and signals
  */
-static int gunzip_init()
+extern int gunzip_init()
 {
        foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
        if (foreground) {
diff --git a/tar.c b/tar.c
index cc7ba3b80d349f12761a328c85d18a818e0e070b..8c2650e2b65a43b2605dade856b70f4ca791de4d 100644 (file)
--- a/tar.c
+++ b/tar.c
 #include <sys/sysmacros.h>
 #include <getopt.h>
 
+#ifdef BB_FEATURE_TAR_GZIP
+extern int unzip(int in, int out);
+extern int gunzip_init();
+#endif
+
 /* Tar file constants  */
 #ifndef MAJOR
 #define MAJOR(dev) (((dev)>>8)&0xff)
@@ -129,29 +134,64 @@ struct TarInfo
 typedef struct TarInfo TarInfo;
 
 /* Local procedures to restore files from a tar file.  */
-static int readTarFile(const char* tarName, int extractFlag, int listFlag, 
+static int readTarFile(int tarFd, int extractFlag, int listFlag, 
                int tostdoutFlag, int verboseFlag, char** extractList,
                char** excludeList);
 
-
-
 #ifdef BB_FEATURE_TAR_CREATE
 /* Local procedures to save files into a tar file.  */
 static int writeTarFile(const char* tarName, int verboseFlag, char **argv,
                char** excludeList);
 #endif
 
+#ifdef BB_FEATURE_TAR_GZIP
+/* Signal handler for when child gzip process dies...  */
+void child_died()
+{
+       fflush(stdout);
+       fflush(stderr);
+       exit(EXIT_FAILURE);
+}
+
+static int tar_unzip_init(int tarFd)
+{
+       int child_pid;
+       static int unzip_pipe[2];
+       /* Cope if child dies... Otherwise we block forever in read()... */
+       signal(SIGCHLD, child_died);
+
+       if (pipe(unzip_pipe)!=0)
+               error_msg_and_die("pipe error\n");
+                       
+       if ( (child_pid = fork()) == -1)
+               error_msg_and_die("fork failure\n");
+
+       if (child_pid==0) {
+               /* child process */
+               gunzip_init();
+               unzip(tarFd, unzip_pipe[1]);
+               exit(EXIT_SUCCESS);
+       }
+       else
+               /* return fd of uncompressed data to parent process */
+               return(unzip_pipe[0]);
+}
+#endif
+
 extern int tar_main(int argc, char **argv)
 {
        char** excludeList=NULL;
        char** extractList=NULL;
+       const char *tarName="-";
 #if defined BB_FEATURE_TAR_EXCLUDE
        int excludeListSize=0;
-        char *excludeFileName ="-";
-        FILE *fileList;
-        char file[256];
+       char *excludeFileName ="-";
+       FILE *fileList;
+       char file[256];
+#endif
+#if defined BB_FEATURE_TAR_GZIP
+       int unzipFlag    = FALSE;
 #endif
-       const char *tarName="-";
        int listFlag     = FALSE;
        int extractFlag  = FALSE;
        int createFlag   = FALSE;
@@ -160,7 +200,6 @@ extern int tar_main(int argc, char **argv)
        int status       = FALSE;
        int firstOpt     = TRUE;
        int stopIt;
-                                                                                                                                                  
 
        if (argc <= 1)
                usage(tar_usage);
@@ -185,6 +224,11 @@ extern int tar_main(int argc, char **argv)
                                                goto flagError;
                                        listFlag = TRUE;
                                        break;
+#ifdef BB_FEATURE_TAR_GZIP
+                               case 'z':
+                                       unzipFlag = TRUE;
+                                       break;
+#endif
                                case 'v':
                                        verboseFlag = TRUE;
                                        break;
@@ -255,13 +299,31 @@ extern int tar_main(int argc, char **argv)
 #ifndef BB_FEATURE_TAR_CREATE
                error_msg_and_die( "This version of tar was not compiled with tar creation support.\n");
 #else
+#ifdef BB_FEATURE_TAR_GZIP
+               if (unzipFlag==TRUE)
+                       error_msg_and_die("Creation of compressed not internally support by tar, pipe to busybox gunzip\n");
+#endif
                status = writeTarFile(tarName, verboseFlag, argv, excludeList);
 #endif
        }
        if (listFlag == TRUE || extractFlag == TRUE) {
+               int tarFd;
                if (*argv)
                        extractList = argv;
-               status = readTarFile(tarName, extractFlag, listFlag, tostdoutFlag,
+               /* Open the tar file for reading.  */
+               if (!strcmp(tarName, "-"))
+                       tarFd = fileno(stdin);
+               else
+                       tarFd = open(tarName, O_RDONLY);
+               if (tarFd < 0)
+                       error_msg_and_die( "Error opening '%s': %s\n", tarName, strerror(errno));
+
+#ifdef BB_FEATURE_TAR_GZIP     
+               /* unzip tarFd in a seperate process */
+               if (unzipFlag == TRUE)
+                       tarFd = tar_unzip_init(tarFd);
+#endif                 
+               status = readTarFile(tarFd, extractFlag, listFlag, tostdoutFlag,
                                        verboseFlag, extractList, excludeList);
        }
 
@@ -521,27 +583,17 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
  * Read a tar file and extract or list the specified files within it.
  * If the list is empty than all files are extracted or listed.
  */
-static int readTarFile(const char* tarName, int extractFlag, int listFlag, 
+extern int readTarFile(int tarFd, int extractFlag, int listFlag, 
                int tostdoutFlag, int verboseFlag, char** extractList,
                char** excludeList)
 {
-       int status, tarFd=-1;
+       int status;
        int errorFlag=FALSE;
        int skipNextHeaderFlag=FALSE;
        TarHeader rawHeader;
        TarInfo header;
        char** tmpList;
 
-       /* Open the tar file for reading.  */
-       if (!strcmp(tarName, "-"))
-               tarFd = fileno(stdin);
-       else
-               tarFd = open(tarName, O_RDONLY);
-       if (tarFd < 0) {
-               error_msg( "Error opening '%s': %s\n", tarName, strerror(errno));
-               return ( FALSE);
-       }
-
        /* Set the umask for this process so it doesn't 
         * screw up permission setting for us later. */
        umask(0);
@@ -739,7 +791,7 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag,
        close(tarFd);
        if (status > 0) {
                /* Bummer - we read a partial header */
-               error_msg( "Error reading '%s': %s\n", tarName, strerror(errno));
+               error_msg( "Error reading tar file: %s\n", strerror(errno));
                return ( FALSE);
        }
        else if (errorFlag==TRUE) {