Added tar -cz support (creating gzipped tar files without a gzip pipe)
This commit is contained in:
parent
967c3d4406
commit
f2f26e7fdd
@ -18,7 +18,7 @@ bool 'tar' CONFIG_TAR
|
|||||||
if [ "$CONFIG_TAR" = "y" ] ; then
|
if [ "$CONFIG_TAR" = "y" ] ; then
|
||||||
bool ' Enable archive creation' CONFIG_FEATURE_TAR_CREATE
|
bool ' Enable archive creation' CONFIG_FEATURE_TAR_CREATE
|
||||||
bool ' Enable -X and --exclude options (exclude files)' CONFIG_FEATURE_TAR_EXCLUDE
|
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
|
fi
|
||||||
if [ "$CONFIG_CPIO" = "y" -o "$CONFIG_TAR" = "y" ] ; then
|
if [ "$CONFIG_CPIO" = "y" -o "$CONFIG_TAR" = "y" ] ; then
|
||||||
bool ' Enable tape drive support' CONFIG_FEATURE_UNARCHIVE_TAPE
|
bool ' Enable tape drive support' CONFIG_FEATURE_UNARCHIVE_TAPE
|
||||||
|
119
archival/tar.c
119
archival/tar.c
@ -47,6 +47,9 @@
|
|||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include "unarchive.h"
|
#include "unarchive.h"
|
||||||
#include "busybox.h"
|
#include "busybox.h"
|
||||||
|
|
||||||
@ -305,9 +308,10 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *header_name,
|
|||||||
write(tbInfo->tarFd, "\0", 1);
|
write(tbInfo->tarFd, "\0", 1);
|
||||||
}
|
}
|
||||||
/* Now do the verbose thing (or not) */
|
/* Now do the verbose thing (or not) */
|
||||||
if (tbInfo->verboseFlag==TRUE) {
|
|
||||||
|
if (tbInfo->verboseFlag) {
|
||||||
FILE *vbFd = stdout;
|
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;
|
vbFd = stderr;
|
||||||
fprintf(vbFd, "%s\n", header.name);
|
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,
|
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;
|
int errorFlag=FALSE;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
struct TarBallInfo tbInfo;
|
struct TarBallInfo tbInfo;
|
||||||
tbInfo.verboseFlag = verboseFlag;
|
|
||||||
tbInfo.hlInfoHead = NULL;
|
tbInfo.hlInfoHead = NULL;
|
||||||
|
|
||||||
/* Make sure there is at least one file to tar up. */
|
/* 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");
|
error_msg_and_die("Cowardly refusing to create an empty archive");
|
||||||
|
|
||||||
/* Open the tar file for writing. */
|
/* Open the tar file for writing. */
|
||||||
if (tarName == NULL)
|
if (tarName == NULL) {
|
||||||
tbInfo.tarFd = fileno(stdout);
|
tbInfo.tarFd = fileno(stdout);
|
||||||
else
|
tbInfo.verboseFlag = verboseFlag ? 2 : 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
|
tbInfo.verboseFlag = verboseFlag ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (tbInfo.tarFd < 0) {
|
if (tbInfo.tarFd < 0) {
|
||||||
perror_msg( "Error opening '%s'", tarName);
|
perror_msg( "Error opening '%s'", tarName);
|
||||||
freeHardLinkInfo(&tbInfo.hlInfoHead);
|
freeHardLinkInfo(&tbInfo.hlInfoHead);
|
||||||
return ( FALSE);
|
return ( FALSE);
|
||||||
}
|
}
|
||||||
tbInfo.excludeList=excludeList;
|
|
||||||
/* Store the stat info for the tarball's file, so
|
/* Store the stat info for the tarball's file, so
|
||||||
* can avoid including the tarball into itself.... */
|
* can avoid including the tarball into itself.... */
|
||||||
if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
|
if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
|
||||||
error_msg_and_die(io_error, tarName, strerror(errno));
|
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 */
|
/* Read the directory/files and iterate over them one at a time */
|
||||||
while (*argv != NULL) {
|
while (*argv != NULL) {
|
||||||
if (! recursive_action(*argv++, TRUE, FALSE, FALSE,
|
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 */
|
* so is considered a waste of space */
|
||||||
|
|
||||||
/* Hang up the tools, close up shop, head home */
|
/* Hang up the tools, close up shop, head home */
|
||||||
close(tarFd);
|
close(tbInfo.tarFd);
|
||||||
if (errorFlag) {
|
if (errorFlag)
|
||||||
error_msg("Error exit delayed from previous errors");
|
error_msg("Error exit delayed from previous errors");
|
||||||
freeHardLinkInfo(&tbInfo.hlInfoHead);
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
freeHardLinkInfo(&tbInfo.hlInfoHead);
|
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
|
#endif //tar_create
|
||||||
|
|
||||||
@ -653,10 +724,7 @@ int tar_main(int argc, char **argv)
|
|||||||
case 'p':
|
case 'p':
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
if (extract_function & extract_list) {
|
extract_function |= extract_verbose_list;
|
||||||
extract_function |= extract_verbose_list;
|
|
||||||
}
|
|
||||||
extract_function |= extract_list;
|
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_FEATURE_TAR_GZIP
|
#ifdef CONFIG_FEATURE_TAR_GZIP
|
||||||
case 'z':
|
case 'z':
|
||||||
@ -711,22 +779,23 @@ int tar_main(int argc, char **argv)
|
|||||||
/* create an archive */
|
/* create an archive */
|
||||||
else if (untar_funct & untar_create) {
|
else if (untar_funct & untar_create) {
|
||||||
int verboseFlag = FALSE;
|
int verboseFlag = FALSE;
|
||||||
|
int gzipFlag = FALSE;
|
||||||
|
|
||||||
#ifdef CONFIG_FEATURE_TAR_GZIP
|
#ifdef CONFIG_FEATURE_TAR_GZIP
|
||||||
if (untar_funct & untar_unzip) {
|
if (untar_funct & untar_unzip)
|
||||||
error_msg_and_die("Creation of compressed tarfile not internally support by tar, pipe to busybox gunzip");
|
gzipFlag = TRUE;
|
||||||
}
|
|
||||||
#endif // CONFIG_FEATURE_TAR_GZIP
|
#endif // CONFIG_FEATURE_TAR_GZIP
|
||||||
if (extract_function & extract_verbose_list) {
|
if (extract_function & extract_verbose_list)
|
||||||
verboseFlag = TRUE;
|
verboseFlag = TRUE;
|
||||||
}
|
|
||||||
writeTarFile(src_filename, verboseFlag, include_list, exclude_list);
|
writeTarFile(src_filename, verboseFlag, include_list, exclude_list, gzipFlag);
|
||||||
}
|
}
|
||||||
#endif // CONFIG_FEATURE_TAR_CREATE
|
#endif // CONFIG_FEATURE_TAR_CREATE
|
||||||
|
|
||||||
/* Cleanups */
|
/* Cleanups */
|
||||||
#ifdef CONFIG_FEATURE_TAR_GZIP
|
#ifdef CONFIG_FEATURE_TAR_GZIP
|
||||||
if (untar_funct & untar_unzip) {
|
if ( !( untar_funct & untar_create ) && ( untar_funct & untar_unzip )) {
|
||||||
fclose(src_stream);
|
fclose(src_stream);
|
||||||
close(gz_fd);
|
close(gz_fd);
|
||||||
gz_close(gunzip_pid);
|
gz_close(gunzip_pid);
|
||||||
|
Loading…
Reference in New Issue
Block a user