Added tar -cz support (creating gzipped tar files without a gzip pipe)

This commit is contained in:
Robert Griebl 2002-07-23 22:05:47 +00:00
parent 967c3d4406
commit f2f26e7fdd
2 changed files with 95 additions and 26 deletions

View File

@ -18,7 +18,7 @@ bool 'tar' CONFIG_TAR
if [ "$CONFIG_TAR" = "y" ] ; then
bool ' Enable archive creation' CONFIG_FEATURE_TAR_CREATE
bool ' Enable -X and --exclude options (exclude files)' CONFIG_FEATURE_TAR_EXCLUDE
bool ' Enable -z option (currently only for extracting)' CONFIG_FEATURE_TAR_GZIP
bool ' Enable -z option' CONFIG_FEATURE_TAR_GZIP
fi
if [ "$CONFIG_CPIO" = "y" -o "$CONFIG_TAR" = "y" ] ; then
bool ' Enable tape drive support' CONFIG_FEATURE_UNARCHIVE_TAPE

View File

@ -47,6 +47,9 @@
#include <fnmatch.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include "unarchive.h"
#include "busybox.h"
@ -305,9 +308,10 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *header_name,
write(tbInfo->tarFd, "\0", 1);
}
/* Now do the verbose thing (or not) */
if (tbInfo->verboseFlag==TRUE) {
if (tbInfo->verboseFlag) {
FILE *vbFd = stdout;
if (tbInfo->tarFd == fileno(stdout)) // If the archive goes to stdout, verbose to stderr
if (tbInfo->verboseFlag == 2) // If the archive goes to stdout, verbose to stderr
vbFd = stderr;
fprintf(vbFd, "%s\n", header.name);
}
@ -445,13 +449,17 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void*
}
static int writeTarFile(const char* tarName, int verboseFlag, char **argv,
char** excludeList)
char** excludeList, int gzip)
{
int tarFd=-1;
#ifdef CONFIG_FEATURE_TAR_GZIP
int gzipDataPipe [2] = { -1, -1 };
int gzipStatusPipe [2] = { -1, -1 };
pid_t gzipPid = 0;
#endif
int errorFlag=FALSE;
ssize_t size;
struct TarBallInfo tbInfo;
tbInfo.verboseFlag = verboseFlag;
tbInfo.hlInfoHead = NULL;
/* Make sure there is at least one file to tar up. */
@ -459,21 +467,78 @@ static int writeTarFile(const char* tarName, int verboseFlag, char **argv,
error_msg_and_die("Cowardly refusing to create an empty archive");
/* Open the tar file for writing. */
if (tarName == NULL)
if (tarName == NULL) {
tbInfo.tarFd = fileno(stdout);
else
tbInfo.verboseFlag = verboseFlag ? 2 : 0;
}
else {
tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
tbInfo.verboseFlag = verboseFlag ? 1 : 0;
}
if (tbInfo.tarFd < 0) {
perror_msg( "Error opening '%s'", tarName);
freeHardLinkInfo(&tbInfo.hlInfoHead);
return ( FALSE);
}
tbInfo.excludeList=excludeList;
/* Store the stat info for the tarball's file, so
* can avoid including the tarball into itself.... */
if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
error_msg_and_die(io_error, tarName, strerror(errno));
#ifdef CONFIG_FEATURE_TAR_GZIP
if ( gzip ) {
if ( socketpair ( AF_UNIX, SOCK_STREAM, 0, gzipDataPipe ) < 0 || pipe ( gzipStatusPipe ) < 0 )
perror_msg_and_die ( "Failed to create gzip pipe" );
signal ( SIGPIPE, SIG_IGN ); // we only want EPIPE on errors
gzipPid = fork ( );
if ( gzipPid == 0 ) {
dup2 ( gzipDataPipe [0], 0 );
close ( gzipDataPipe [1] );
if ( tbInfo. tarFd != 1 );
dup2 ( tbInfo. tarFd, 1 );
close ( gzipStatusPipe [0] );
fcntl( gzipStatusPipe [1], F_SETFD, FD_CLOEXEC ); // close on exec shows sucess
execl ( "/bin/gzip", "gzip", "-f", 0 );
write ( gzipStatusPipe [1], "", 1 );
close ( gzipStatusPipe [1] );
exit ( -1 );
}
else if ( gzipPid > 0 ) {
close ( gzipDataPipe [0] );
close ( gzipStatusPipe [1] );
while ( 1 ) {
char buf;
int n = read ( gzipStatusPipe [0], &buf, 1 );
if ( n == 1 )
error_msg_and_die ( "Could not exec gzip process" ); // socket was not closed => error
else if (( n < 0 ) && ( errno==EAGAIN || errno==EINTR ))
continue; // try it again
break;
}
close ( gzipStatusPipe [0] );
tbInfo. tarFd = gzipDataPipe [1];
}
else {
perror_msg_and_die ( "Failed to fork gzip process" );
}
}
#endif
tbInfo.excludeList=excludeList;
/* Read the directory/files and iterate over them one at a time */
while (*argv != NULL) {
if (! recursive_action(*argv++, TRUE, FALSE, FALSE,
@ -493,14 +558,20 @@ static int writeTarFile(const char* tarName, int verboseFlag, char **argv,
* so is considered a waste of space */
/* Hang up the tools, close up shop, head home */
close(tarFd);
if (errorFlag) {
close(tbInfo.tarFd);
if (errorFlag)
error_msg("Error exit delayed from previous errors");
freeHardLinkInfo(&tbInfo.hlInfoHead);
return(FALSE);
}
freeHardLinkInfo(&tbInfo.hlInfoHead);
return( TRUE);
#ifdef CONFIG_FEATURE_TAR_GZIP
if ( gzip && gzipPid ) {
if ( waitpid ( gzipPid, NULL, 0 ) == -1 )
printf ( "Couldnt wait ?" );
}
#endif
return !errorFlag;
}
#endif //tar_create
@ -653,10 +724,7 @@ int tar_main(int argc, char **argv)
case 'p':
break;
case 'v':
if (extract_function & extract_list) {
extract_function |= extract_verbose_list;
}
extract_function |= extract_list;
extract_function |= extract_verbose_list;
break;
#ifdef CONFIG_FEATURE_TAR_GZIP
case 'z':
@ -711,22 +779,23 @@ int tar_main(int argc, char **argv)
/* create an archive */
else if (untar_funct & untar_create) {
int verboseFlag = FALSE;
int gzipFlag = FALSE;
#ifdef CONFIG_FEATURE_TAR_GZIP
if (untar_funct & untar_unzip) {
error_msg_and_die("Creation of compressed tarfile not internally support by tar, pipe to busybox gunzip");
}
if (untar_funct & untar_unzip)
gzipFlag = TRUE;
#endif // CONFIG_FEATURE_TAR_GZIP
if (extract_function & extract_verbose_list) {
if (extract_function & extract_verbose_list)
verboseFlag = TRUE;
}
writeTarFile(src_filename, verboseFlag, include_list, exclude_list);
writeTarFile(src_filename, verboseFlag, include_list, exclude_list, gzipFlag);
}
#endif // CONFIG_FEATURE_TAR_CREATE
/* Cleanups */
#ifdef CONFIG_FEATURE_TAR_GZIP
if (untar_funct & untar_unzip) {
if ( !( untar_funct & untar_create ) && ( untar_funct & untar_unzip )) {
fclose(src_stream);
close(gz_fd);
gz_close(gunzip_pid);