*/
#include <fnmatch.h>
-#include <getopt.h>
#include "libbb.h"
#include "unarchive.h"
#define FNM_LEADING_DIR 0
#endif
+
#define block_buf bb_common_bufsiz1
+
+#if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2
+/* Do not pass gzip flag to writeTarFile() */
+#define writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude, gzip) \
+ writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude)
+#endif
+
+
#if ENABLE_FEATURE_TAR_CREATE
/* Tar file constants */
*/
typedef struct HardLinkInfo HardLinkInfo;
struct HardLinkInfo {
- HardLinkInfo *next; /* Next entry in list */
- dev_t dev; /* Device number */
- ino_t ino; /* Inode number */
- short linkCount; /* (Hard) Link Count */
- char name[1]; /* Start of filename (must be last) */
+ HardLinkInfo *next; /* Next entry in list */
+ dev_t dev; /* Device number */
+ ino_t ino; /* Inode number */
+ short linkCount; /* (Hard) Link Count */
+ char name[1]; /* Start of filename (must be last) */
};
/* Some info to be carried along when creating a new tarball */
typedef struct TarBallInfo TarBallInfo;
struct TarBallInfo {
- int tarFd; /* Open-for-write file descriptor
- for the tarball */
- struct stat statBuf; /* Stat info for the tarball, letting
- us know the inode and device that the
- tarball lives, so we can avoid trying
- to include the tarball into itself */
- int verboseFlag; /* Whether to print extra stuff or not */
- const llist_t *excludeList; /* List of files to not include */
- HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */
- HardLinkInfo *hlInfo; /* Hard Link Info for the current file */
+ int tarFd; /* Open-for-write file descriptor
+ * for the tarball */
+ struct stat statBuf; /* Stat info for the tarball, letting
+ * us know the inode and device that the
+ * tarball lives, so we can avoid trying
+ * to include the tarball into itself */
+ int verboseFlag; /* Whether to print extra stuff or not */
+ const llist_t *excludeList; /* List of files to not include */
+ HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */
+ HardLinkInfo *hlInfo; /* Hard Link Info for the current file */
};
/* A nice enum with all the possible tar file content types */
if (tbInfo->verboseFlag) {
FILE *vbFd = stdout;
- if (tbInfo->tarFd == STDOUT_FILENO) /* If the archive goes to stdout, verbose to stderr */
+ /* If archive goes to stdout, verbose goes to stderr */
+ if (tbInfo->tarFd == STDOUT_FILENO)
vbFd = stderr;
/* GNU "tar cvvf" prints "extended" listing a-la "ls -l" */
/* We don't have such excesses here: for us "v" == "vv" */
#define exclude_file(excluded_files, file) 0
#endif
-static int writeFileToTarball(const char *fileName, struct stat *statbuf,
- void *userData, int depth ATTRIBUTE_UNUSED)
+static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statbuf,
+ void *userData, int depth UNUSED_PARAM)
{
struct TarBallInfo *tbInfo = (struct TarBallInfo *) userData;
const char *header_name;
return TRUE;
}
-static int writeTarFile(const int tar_fd, const int verboseFlag,
- const unsigned long dereferenceFlag, const llist_t *include,
- const llist_t *exclude, const int gzip)
+#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
+#if !(ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2)
+#define vfork_compressor(tar_fd, gzip) vfork_compressor(tar_fd)
+#endif
+/* Don't inline: vfork scares gcc and pessimizes code */
+static void NOINLINE vfork_compressor(int tar_fd, int gzip)
{
- pid_t gzipPid = 0;
- int errorFlag = FALSE;
- struct TarBallInfo tbInfo;
-
- tbInfo.hlInfoHead = NULL;
-
- fchmod(tar_fd, 0644);
- tbInfo.tarFd = tar_fd;
- tbInfo.verboseFlag = verboseFlag;
-
- /* Store the stat info for the tarball's file, so
- * can avoid including the tarball into itself.... */
- if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
- bb_perror_msg_and_die("cannot stat tar file");
-
- if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) {
-// On Linux, vfork never unpauses parent early, although standard
-// allows for that. Do we want to waste bytes checking for it?
-#define WAIT_FOR_CHILD 0
-
- volatile int vfork_exec_errno = 0;
-#if WAIT_FOR_CHILD
- struct { int rd; int wr; } gzipStatusPipe;
+ pid_t gzipPid;
+#if ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2
+ const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
+#elif ENABLE_FEATURE_SEAMLESS_GZ
+ const char *zip_exec = "gzip";
+#else /* only ENABLE_FEATURE_SEAMLESS_BZ2 */
+ const char *zip_exec = "bzip2";
#endif
- struct { int rd; int wr; } gzipDataPipe;
- const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
-
- xpipe(&gzipDataPipe.rd);
+ // On Linux, vfork never unpauses parent early, although standard
+ // allows for that. Do we want to waste bytes checking for it?
+#define WAIT_FOR_CHILD 0
+ volatile int vfork_exec_errno = 0;
+ struct fd_pair gzipDataPipe;
#if WAIT_FOR_CHILD
- xpipe(&gzipStatusPipe.rd);
+ struct fd_pair gzipStatusPipe;
+ xpiped_pair(gzipStatusPipe);
#endif
+ xpiped_pair(gzipDataPipe);
- signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
+ signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
#if defined(__GNUC__) && __GNUC__
- /* Avoid vfork clobbering */
- (void) &include;
- (void) &errorFlag;
- (void) &zip_exec;
+ /* Avoid vfork clobbering */
+ (void) &zip_exec;
#endif
- gzipPid = vfork();
- if (gzipPid < 0)
- bb_perror_msg_and_die("vfork gzip");
+ gzipPid = vfork();
+ if (gzipPid < 0)
+ bb_perror_msg_and_die("vfork");
- if (gzipPid == 0) {
- /* child */
- /* NB: close _first_, then move fds! */
- close(gzipDataPipe.wr);
+ if (gzipPid == 0) {
+ /* child */
+ /* NB: close _first_, then move fds! */
+ close(gzipDataPipe.wr);
#if WAIT_FOR_CHILD
- close(gzipStatusPipe.rd);
- /* gzipStatusPipe.wr will close only on exec -
- * parent waits for this close to happen */
- fcntl(gzipStatusPipe.wr, F_SETFD, FD_CLOEXEC);
+ close(gzipStatusPipe.rd);
+ /* gzipStatusPipe.wr will close only on exec -
+ * parent waits for this close to happen */
+ fcntl(gzipStatusPipe.wr, F_SETFD, FD_CLOEXEC);
#endif
- xmove_fd(gzipDataPipe.rd, 0);
- xmove_fd(tbInfo.tarFd, 1);
- /* exec gzip/bzip2 program/applet */
- BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
- vfork_exec_errno = errno;
- _exit(1);
- }
+ xmove_fd(gzipDataPipe.rd, 0);
+ xmove_fd(tar_fd, 1);
+ /* exec gzip/bzip2 program/applet */
+ BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
+ vfork_exec_errno = errno;
+ _exit(EXIT_FAILURE);
+ }
- /* parent */
- xmove_fd(gzipDataPipe.wr, tbInfo.tarFd);
- close(gzipDataPipe.rd);
+ /* parent */
+ xmove_fd(gzipDataPipe.wr, tar_fd);
+ close(gzipDataPipe.rd);
#if WAIT_FOR_CHILD
- close(gzipStatusPipe.wr);
- while (1) {
- char buf;
- int n;
+ close(gzipStatusPipe.wr);
+ while (1) {
+ char buf;
+ int n;
+
+ /* Wait until child execs (or fails to) */
+ n = full_read(gzipStatusPipe.rd, &buf, 1);
+ if (n < 0 /* && errno == EAGAIN */)
+ continue; /* try it again */
+ }
+ close(gzipStatusPipe.rd);
+#endif
+ if (vfork_exec_errno) {
+ errno = vfork_exec_errno;
+ bb_perror_msg_and_die("cannot exec %s", zip_exec);
+ }
+}
+#endif /* ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 */
- /* Wait until child execs (or fails to) */
- n = full_read(gzipStatusPipe.rd, &buf, 1);
- if (n < 0 /* && errno == EAGAIN */)
- continue; /* try it again */
- }
- close(gzipStatusPipe.rd);
+/* gcc 4.2.1 inlines it, making code bigger */
+static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
+ int dereferenceFlag, const llist_t *include,
+ const llist_t *exclude, int gzip)
+{
+ int errorFlag = FALSE;
+ struct TarBallInfo tbInfo;
+
+ tbInfo.hlInfoHead = NULL;
+ tbInfo.tarFd = tar_fd;
+ tbInfo.verboseFlag = verboseFlag;
+
+ /* Store the stat info for the tarball's file, so
+ * can avoid including the tarball into itself.... */
+ if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
+ bb_perror_msg_and_die("cannot stat tar file");
+
+#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
+ if (gzip)
+ vfork_compressor(tbInfo.tarFd, gzip);
#endif
- if (vfork_exec_errno) {
- errno = vfork_exec_errno;
- bb_perror_msg_and_die("cannot exec %s", zip_exec);
- }
- }
tbInfo.excludeList = exclude;
if (errorFlag)
bb_error_msg("error exit delayed from previous errors");
- if (gzipPid) {
+#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
+ if (gzip) {
int status;
- if (safe_waitpid(gzipPid, &status, 0) == -1)
+ if (safe_waitpid(-1, &status, 0) == -1)
bb_perror_msg("waitpid");
else if (!WIFEXITED(status) || WEXITSTATUS(status))
/* gzip was killed or has exited with nonzero! */
errorFlag = TRUE;
}
+#endif
return errorFlag;
}
#else
-int writeTarFile(const int tar_fd, const int verboseFlag,
- const unsigned long dereferenceFlag, const llist_t *include,
- const llist_t *exclude, const int gzip);
+int writeTarFile(int tar_fd, int verboseFlag,
+ int dereferenceFlag, const llist_t *include,
+ const llist_t *exclude, int gzip);
#endif /* FEATURE_TAR_CREATE */
#if ENABLE_FEATURE_TAR_FROM
static llist_t *append_file_list_to_list(llist_t *list)
{
FILE *src_stream;
- llist_t *cur = list;
- llist_t *tmp;
char *line;
llist_t *newlist = NULL;
- while (cur) {
- src_stream = xfopen(cur->data, "r");
- tmp = cur;
- cur = cur->link;
- free(tmp);
- while ((line = xmalloc_getline(src_stream)) != NULL) {
+ while (list) {
+ src_stream = xfopen_for_read(llist_pop(&list));
+ while ((line = xmalloc_fgetline(src_stream)) != NULL) {
/* kill trailing '/' unless the string is just "/" */
char *cp = last_char_is(line, '/');
if (cp > line)
#define append_file_list_to_list(x) 0
#endif
-#if ENABLE_FEATURE_TAR_COMPRESS
-static char get_header_tar_Z(archive_handle_t *archive_handle)
+#if ENABLE_FEATURE_SEAMLESS_Z
+static char FAST_FUNC get_header_tar_Z(archive_handle_t *archive_handle)
{
/* Can't lseek over pipes */
archive_handle->seek = seek_by_read;
bb_error_msg_and_die("invalid magic");
}
- archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress, "uncompress");
+ open_transformer(archive_handle->src_fd, unpack_Z_stream, "uncompress");
archive_handle->offset = 0;
while (get_header_tar(archive_handle) == EXIT_SUCCESS)
continue;
enum {
OPTBIT_KEEP_OLD = 7,
- USE_FEATURE_TAR_CREATE( OPTBIT_CREATE ,)
- USE_FEATURE_TAR_CREATE( OPTBIT_DEREFERENCE ,)
- USE_FEATURE_TAR_BZIP2( OPTBIT_BZIP2 ,)
- USE_FEATURE_TAR_LZMA( OPTBIT_LZMA ,)
- USE_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,)
- USE_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,)
- USE_FEATURE_TAR_GZIP( OPTBIT_GZIP ,)
- USE_FEATURE_TAR_COMPRESS(OPTBIT_COMPRESS ,)
+ USE_FEATURE_TAR_CREATE( OPTBIT_CREATE ,)
+ USE_FEATURE_TAR_CREATE( OPTBIT_DEREFERENCE ,)
+ USE_FEATURE_SEAMLESS_BZ2( OPTBIT_BZIP2 ,)
+ USE_FEATURE_SEAMLESS_LZMA(OPTBIT_LZMA ,)
+ USE_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,)
+ USE_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,)
+ USE_FEATURE_SEAMLESS_GZ( OPTBIT_GZIP ,)
+ USE_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,)
OPTBIT_NOPRESERVE_OWN,
OPTBIT_NOPRESERVE_PERM,
+ OPTBIT_NUMERIC_OWNER,
OPT_TEST = 1 << 0, // t
OPT_EXTRACT = 1 << 1, // x
OPT_BASEDIR = 1 << 2, // C
OPT_P = 1 << 5, // p
OPT_VERBOSE = 1 << 6, // v
OPT_KEEP_OLD = 1 << 7, // k
- OPT_CREATE = USE_FEATURE_TAR_CREATE( (1<<OPTBIT_CREATE )) + 0, // c
- OPT_DEREFERENCE = USE_FEATURE_TAR_CREATE( (1<<OPTBIT_DEREFERENCE )) + 0, // h
- OPT_BZIP2 = USE_FEATURE_TAR_BZIP2( (1<<OPTBIT_BZIP2 )) + 0, // j
- OPT_LZMA = USE_FEATURE_TAR_LZMA( (1<<OPTBIT_LZMA )) + 0, // a
- OPT_INCLUDE_FROM = USE_FEATURE_TAR_FROM( (1<<OPTBIT_INCLUDE_FROM)) + 0, // T
- OPT_EXCLUDE_FROM = USE_FEATURE_TAR_FROM( (1<<OPTBIT_EXCLUDE_FROM)) + 0, // X
- OPT_GZIP = USE_FEATURE_TAR_GZIP( (1<<OPTBIT_GZIP )) + 0, // z
- OPT_COMPRESS = USE_FEATURE_TAR_COMPRESS((1<<OPTBIT_COMPRESS )) + 0, // Z
+ OPT_CREATE = USE_FEATURE_TAR_CREATE( (1 << OPTBIT_CREATE )) + 0, // c
+ OPT_DEREFERENCE = USE_FEATURE_TAR_CREATE( (1 << OPTBIT_DEREFERENCE )) + 0, // h
+ OPT_BZIP2 = USE_FEATURE_SEAMLESS_BZ2( (1 << OPTBIT_BZIP2 )) + 0, // j
+ OPT_LZMA = USE_FEATURE_SEAMLESS_LZMA((1 << OPTBIT_LZMA )) + 0, // a
+ OPT_INCLUDE_FROM = USE_FEATURE_TAR_FROM( (1 << OPTBIT_INCLUDE_FROM)) + 0, // T
+ OPT_EXCLUDE_FROM = USE_FEATURE_TAR_FROM( (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X
+ OPT_GZIP = USE_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z
+ OPT_COMPRESS = USE_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z
OPT_NOPRESERVE_OWN = 1 << OPTBIT_NOPRESERVE_OWN , // no-same-owner
OPT_NOPRESERVE_PERM = 1 << OPTBIT_NOPRESERVE_PERM, // no-same-permissions
+ OPT_NUMERIC_OWNER = 1 << OPTBIT_NUMERIC_OWNER,
};
#if ENABLE_FEATURE_TAR_LONG_OPTIONS
static const char tar_longopts[] ALIGN1 =
"create\0" No_argument "c"
"dereference\0" No_argument "h"
# endif
-# if ENABLE_FEATURE_TAR_BZIP2
+# if ENABLE_FEATURE_SEAMLESS_BZ2
"bzip2\0" No_argument "j"
# endif
-# if ENABLE_FEATURE_TAR_LZMA
+# if ENABLE_FEATURE_SEAMLESS_LZMA
"lzma\0" No_argument "a"
# endif
# if ENABLE_FEATURE_TAR_FROM
"files-from\0" Required_argument "T"
"exclude-from\0" Required_argument "X"
# endif
-# if ENABLE_FEATURE_TAR_GZIP
+# if ENABLE_FEATURE_SEAMLESS_GZ
"gzip\0" No_argument "z"
# endif
-# if ENABLE_FEATURE_TAR_COMPRESS
+# if ENABLE_FEATURE_SEAMLESS_Z
"compress\0" No_argument "Z"
# endif
+ "numeric-owner\0" No_argument "\xfc"
"no-same-owner\0" No_argument "\xfd"
"no-same-permissions\0" No_argument "\xfe"
/* --exclude takes next bit position in option mask, */
#endif
int tar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int tar_main(int argc, char **argv)
+int tar_main(int argc UNUSED_PARAM, char **argv)
{
- char (*get_header_ptr)(archive_handle_t *) = get_header_tar;
+ char FAST_FUNC (*get_header_ptr)(archive_handle_t *) = get_header_tar;
archive_handle_t *tar_handle;
char *base_dir = NULL;
const char *tar_filename = "-";
/* Initialise default values */
tar_handle = init_handle();
- tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS
- | ARCHIVE_PRESERVE_DATE
- | ARCHIVE_EXTRACT_UNCONDITIONAL;
+ tar_handle->ah_flags = ARCHIVE_CREATE_LEADING_DIRS
+ | ARCHIVE_PRESERVE_DATE
+ | ARCHIVE_EXTRACT_UNCONDITIONAL;
+
+ /* Apparently only root's tar preserves perms (see bug 3844) */
+ if (getuid() != 0)
+ tar_handle->ah_flags |= ARCHIVE_NOPRESERVE_PERM;
/* Prepend '-' to the first argument if required */
opt_complementary = "--:" // first arg is options
#endif
opt = getopt32(argv,
"txC:f:Opvk"
- USE_FEATURE_TAR_CREATE( "ch" )
- USE_FEATURE_TAR_BZIP2( "j" )
- USE_FEATURE_TAR_LZMA( "a" )
- USE_FEATURE_TAR_FROM( "T:X:")
- USE_FEATURE_TAR_GZIP( "z" )
- USE_FEATURE_TAR_COMPRESS("Z" )
+ USE_FEATURE_TAR_CREATE( "ch" )
+ USE_FEATURE_SEAMLESS_BZ2( "j" )
+ USE_FEATURE_SEAMLESS_LZMA("a" )
+ USE_FEATURE_TAR_FROM( "T:X:")
+ USE_FEATURE_SEAMLESS_GZ( "z" )
+ USE_FEATURE_SEAMLESS_Z( "Z" )
, &base_dir // -C dir
, &tar_filename // -f filename
USE_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T
, &verboseFlag // combined count for -t and -v
, &verboseFlag // combined count for -t and -v
);
+ argv += optind;
if (verboseFlag) tar_handle->action_header = header_verbose_list;
if (verboseFlag == 1) tar_handle->action_header = header_list;
tar_handle->action_data = data_extract_to_stdout;
if (opt & OPT_KEEP_OLD)
- tar_handle->flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL;
+ tar_handle->ah_flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL;
if (opt & OPT_NOPRESERVE_OWN)
- tar_handle->flags |= ARCHIVE_NOPRESERVE_OWN;
+ tar_handle->ah_flags |= ARCHIVE_NOPRESERVE_OWN;
if (opt & OPT_NOPRESERVE_PERM)
- tar_handle->flags |= ARCHIVE_NOPRESERVE_PERM;
+ tar_handle->ah_flags |= ARCHIVE_NOPRESERVE_PERM;
+
+ if (opt & OPT_NUMERIC_OWNER)
+ tar_handle->ah_flags |= ARCHIVE_NUMERIC_OWNER;
if (opt & OPT_GZIP)
get_header_ptr = get_header_tar_gz;
tar_handle->accept = append_file_list_to_list(tar_handle->accept);
#endif
- /* Check if we are reading from stdin */
- if (argv[optind] && *argv[optind] == '-') {
- /* Default is to read from stdin, so just skip to next arg */
- optind++;
- }
-
/* Setup an array of filenames to work with */
/* TODO: This is the same as in ar, separate function ? */
- while (optind < argc) {
+ while (*argv) {
/* kill trailing '/' unless the string is just "/" */
- char *cp = last_char_is(argv[optind], '/');
- if (cp > argv[optind])
+ char *cp = last_char_is(*argv, '/');
+ if (cp > *argv)
*cp = '\0';
- llist_add_to_end(&tar_handle->accept, argv[optind]);
- optind++;
+ llist_add_to_end(&tar_handle->accept, *argv);
+ argv++;
}
if (tar_handle->accept || tar_handle->reject)
tar_stream = stdout;
/* Mimicking GNU tar 1.15.1: */
- flags = O_WRONLY|O_CREAT|O_TRUNC;
- /* was doing unlink; open(O_WRONLY|O_CREAT|O_EXCL); why? */
+ flags = O_WRONLY | O_CREAT | O_TRUNC;
} else {
tar_stream = stdin;
flags = O_RDONLY;
tar_handle->src_fd = fileno(tar_stream);
tar_handle->seek = seek_by_read;
} else {
- tar_handle->src_fd = xopen(tar_filename, flags);
+ if (ENABLE_FEATURE_TAR_AUTODETECT && flags == O_RDONLY) {
+ get_header_ptr = get_header_tar;
+ tar_handle->src_fd = open_zipped(tar_filename);
+ if (tar_handle->src_fd < 0)
+ bb_perror_msg_and_die("can't open '%s'", tar_filename);
+ } else {
+ tar_handle->src_fd = xopen(tar_filename, flags);
+ }
}
}
/* create an archive */
if (opt & OPT_CREATE) {
+#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
int zipMode = 0;
- if (ENABLE_FEATURE_TAR_GZIP && get_header_ptr == get_header_tar_gz)
+ if (ENABLE_FEATURE_SEAMLESS_GZ && (opt & OPT_GZIP))
zipMode = 1;
- if (ENABLE_FEATURE_TAR_BZIP2 && get_header_ptr == get_header_tar_bz2)
+ if (ENABLE_FEATURE_SEAMLESS_BZ2 && (opt & OPT_BZIP2))
zipMode = 2;
+#endif
/* NB: writeTarFile() closes tar_handle->src_fd */
return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE,
tar_handle->accept,
}
while (get_header_ptr(tar_handle) == EXIT_SUCCESS)
- /* nothing */;
+ continue;
/* Check that every file that should have been extracted was */
while (tar_handle->accept) {