aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog2
-rw-r--r--Config.h9
-rw-r--r--archival/gunzip.c4
-rw-r--r--archival/tar.c96
-rw-r--r--gunzip.c4
-rw-r--r--tar.c96
6 files changed, 163 insertions, 48 deletions
diff --git a/Changelog b/Changelog
index 2c6fbabd9..6a1612876 100644
--- 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.
diff --git a/Config.h b/Config.h
index 50f9e3ac7..d95942a65 100644
--- a/Config.h
+++ b/Config.h
@@ -225,6 +225,9 @@
// 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
//
@@ -324,6 +327,12 @@
#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
diff --git a/archival/gunzip.c b/archival/gunzip.c
index 48db7cfd7..8558573ba 100644
--- a/archival/gunzip.c
+++ b/archival/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/archival/tar.c b/archival/tar.c
index cc7ba3b80..8c2650e2b 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -52,6 +52,11 @@
#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) {
diff --git a/gunzip.c b/gunzip.c
index 48db7cfd7..8558573ba 100644
--- 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 cc7ba3b80..8c2650e2b 100644
--- a/tar.c
+++ b/tar.c
@@ -52,6 +52,11 @@
#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) {