* very different now (i.e., cleaner, less global variables, etc.)
*
* Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
- * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org>
+ * Copyright (C) 1999-2002 by Erik Andersen <andersee@debian.org>
*
* Based in part in the tar implementation in sash
* Copyright (c) 1999 by David I. Bell
#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"
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);
}
}
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. */
error_msg_and_die("Cowardly refusing to create an empty archive");
/* Open the tar file for writing. */
- if (!strcmp(tarName, "-"))
+ 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,
+ if (! recursive_action(*argv++, TRUE, FALSE, FALSE,
writeFileToTarball, writeFileToTarball,
- (void*) &tbInfo) == FALSE) {
+ (void*) &tbInfo)) {
errorFlag = TRUE;
}
}
* so is considered a waste of space */
/* Hang up the tools, close up shop, head home */
- close(tarFd);
- if (errorFlag == TRUE) {
+ 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
{
FILE *src_stream;
char *line;
- char *line_ptr;
src_stream = xfopen(filename, "r");
while ((line = get_line_from_file(src_stream)) != NULL) {
- line_ptr = last_char_is(line, '\n');
- if (line_ptr) {
- *line_ptr = '\0';
- }
+ chomp (line);
append_file_to_list(line, name_list, num_of_entries);
free(line);
}
exclude_count++;
}
- if (found == FALSE) {
+ if (! found) {
new_include_list = realloc(new_include_list, sizeof(char *) * (include_count + 2));
new_include_list[new_include_count] = include_list[include_count];
new_include_count++;
int tar_main(int argc, char **argv)
{
enum untar_funct_e {
- /* These are optional */
- untar_from_file = 1,
- untar_from_stdin = 2,
- untar_unzip = 4,
+ /* This is optional */
+ untar_unzip = 1,
/* Require one and only one of these */
- untar_list = 8,
- untar_create = 16,
- untar_extract = 32
+ untar_list = 2,
+ untar_create = 4,
+ untar_extract = 8
};
FILE *src_stream = NULL;
char **exclude_list = NULL;
char *src_filename = NULL;
char *dst_prefix = NULL;
- char *file_list_name = NULL;
int opt;
unsigned short untar_funct = 0;
unsigned short untar_funct_required = 0;
break;
case 'f': // archive filename
if (strcmp(optarg, "-") == 0) {
- // Untar from stdin to stdout
- untar_funct |= untar_from_stdin;
+ src_filename = NULL;
} else {
- untar_funct |= untar_from_file;
src_filename = xstrdup(optarg);
}
break;
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':
append_file_to_list(argv[optind], &include_list, &include_list_count);
optind++;
}
-
if (extract_function & (extract_list | extract_all_to_fs)) {
if (dst_prefix == NULL) {
dst_prefix = xstrdup("./");
}
/* Setup the source of the tar data */
- if (untar_funct & untar_from_file) {
+ if (src_filename != NULL) {
src_stream = xfopen(src_filename, "r");
} else {
src_stream = stdin;
/* 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, &argv[argc - 1], include_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);
}
#endif // CONFIG_FEATURE_TAR_GZIP
+#ifdef CONFIG_FEATURE_CLEAN_UP
if (src_filename) {
free(src_filename);
}
- if (file_list_name) {
- free(file_list_name);
- }
+#endif
return(EXIT_SUCCESS);
}