busybox/archival/tar.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Mini tar implementation for busybox
   4 *
   5 * Modified to use common extraction code used by ar, cpio, dpkg-deb, dpkg
   6 *  by Glenn McGrath
   7 *
   8 * Note, that as of BusyBox-0.43, tar has been completely rewritten from the
   9 * ground up.  It still has remnants of the old code lying about, but it is
  10 * very different now (i.e., cleaner, less global variables, etc.)
  11 *
  12 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
  13 *
  14 * Based in part in the tar implementation in sash
  15 *  Copyright (c) 1999 by David I. Bell
  16 *  Permission is granted to use, distribute, or modify this source,
  17 *  provided that this copyright notice remains intact.
  18 *  Permission to distribute sash derived code under the GPL has been granted.
  19 *
  20 * Based in part on the tar implementation from busybox-0.28
  21 *  Copyright (C) 1995 Bruce Perens
  22 *
  23 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  24 */
  25
  26#include <fnmatch.h>
  27#include "libbb.h"
  28#include "unarchive.h"
  29/* FIXME: Stop using this non-standard feature */
  30#ifndef FNM_LEADING_DIR
  31# define FNM_LEADING_DIR 0
  32#endif
  33
  34
  35//#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
  36#define DBG(...) ((void)0)
  37
  38
  39#define block_buf bb_common_bufsiz1
  40
  41
  42#if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2
  43/* Do not pass gzip flag to writeTarFile() */
  44#define writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude, gzip) \
  45        writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude)
  46#endif
  47
  48
  49#if ENABLE_FEATURE_TAR_CREATE
  50
  51/*
  52** writeTarFile(), writeFileToTarball(), and writeTarHeader() are
  53** the only functions that deal with the HardLinkInfo structure.
  54** Even these functions use the xxxHardLinkInfo() functions.
  55*/
  56typedef struct HardLinkInfo {
  57        struct HardLinkInfo *next; /* Next entry in list */
  58        dev_t dev;                 /* Device number */
  59        ino_t ino;                 /* Inode number */
  60//      short linkCount;           /* (Hard) Link Count */
  61        char name[1];              /* Start of filename (must be last) */
  62} HardLinkInfo;
  63
  64/* Some info to be carried along when creating a new tarball */
  65typedef struct TarBallInfo {
  66        int tarFd;                      /* Open-for-write file descriptor
  67                                         * for the tarball */
  68        int verboseFlag;                /* Whether to print extra stuff or not */
  69        const llist_t *excludeList;     /* List of files to not include */
  70        HardLinkInfo *hlInfoHead;       /* Hard Link Tracking Information */
  71        HardLinkInfo *hlInfo;           /* Hard Link Info for the current file */
  72//TODO: save only st_dev + st_ino
  73        struct stat tarFileStatBuf;     /* Stat info for the tarball, letting
  74                                         * us know the inode and device that the
  75                                         * tarball lives, so we can avoid trying
  76                                         * to include the tarball into itself */
  77} TarBallInfo;
  78
  79/* A nice enum with all the possible tar file content types */
  80enum {
  81        REGTYPE = '0',          /* regular file */
  82        REGTYPE0 = '\0',        /* regular file (ancient bug compat) */
  83        LNKTYPE = '1',          /* hard link */
  84        SYMTYPE = '2',          /* symbolic link */
  85        CHRTYPE = '3',          /* character special */
  86        BLKTYPE = '4',          /* block special */
  87        DIRTYPE = '5',          /* directory */
  88        FIFOTYPE = '6',         /* FIFO special */
  89        CONTTYPE = '7',         /* reserved */
  90        GNULONGLINK = 'K',      /* GNU long (>100 chars) link name */
  91        GNULONGNAME = 'L',      /* GNU long (>100 chars) file name */
  92};
  93
  94/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */
  95static void addHardLinkInfo(HardLinkInfo **hlInfoHeadPtr,
  96                                        struct stat *statbuf,
  97                                        const char *fileName)
  98{
  99        /* Note: hlInfoHeadPtr can never be NULL! */
 100        HardLinkInfo *hlInfo;
 101
 102        hlInfo = xmalloc(sizeof(HardLinkInfo) + strlen(fileName));
 103        hlInfo->next = *hlInfoHeadPtr;
 104        *hlInfoHeadPtr = hlInfo;
 105        hlInfo->dev = statbuf->st_dev;
 106        hlInfo->ino = statbuf->st_ino;
 107//      hlInfo->linkCount = statbuf->st_nlink;
 108        strcpy(hlInfo->name, fileName);
 109}
 110
 111static void freeHardLinkInfo(HardLinkInfo **hlInfoHeadPtr)
 112{
 113        HardLinkInfo *hlInfo;
 114        HardLinkInfo *hlInfoNext;
 115
 116        if (hlInfoHeadPtr) {
 117                hlInfo = *hlInfoHeadPtr;
 118                while (hlInfo) {
 119                        hlInfoNext = hlInfo->next;
 120                        free(hlInfo);
 121                        hlInfo = hlInfoNext;
 122                }
 123                *hlInfoHeadPtr = NULL;
 124        }
 125}
 126
 127/* Might be faster (and bigger) if the dev/ino were stored in numeric order ;) */
 128static HardLinkInfo *findHardLinkInfo(HardLinkInfo *hlInfo, struct stat *statbuf)
 129{
 130        while (hlInfo) {
 131                if (statbuf->st_ino == hlInfo->ino
 132                 && statbuf->st_dev == hlInfo->dev
 133                ) {
 134                        DBG("found hardlink:'%s'", hlInfo->name);
 135                        break;
 136                }
 137                hlInfo = hlInfo->next;
 138        }
 139        return hlInfo;
 140}
 141
 142/* Put an octal string into the specified buffer.
 143 * The number is zero padded and possibly null terminated.
 144 * Stores low-order bits only if whole value does not fit. */
 145static void putOctal(char *cp, int len, off_t value)
 146{
 147        char tempBuffer[sizeof(off_t)*3 + 1];
 148        char *tempString = tempBuffer;
 149        int width;
 150
 151        width = sprintf(tempBuffer, "%0*"OFF_FMT"o", len, value);
 152        tempString += (width - len);
 153
 154        /* If string has leading zeroes, we can drop one */
 155        /* and field will have trailing '\0' */
 156        /* (increases chances of compat with other tars) */
 157        if (tempString[0] == '0')
 158                tempString++;
 159
 160        /* Copy the string to the field */
 161        memcpy(cp, tempString, len);
 162}
 163#define PUT_OCTAL(a, b) putOctal((a), sizeof(a), (b))
 164
 165static void chksum_and_xwrite(int fd, struct tar_header_t* hp)
 166{
 167        /* POSIX says that checksum is done on unsigned bytes
 168         * (Sun and HP-UX gets it wrong... more details in
 169         * GNU tar source) */
 170        const unsigned char *cp;
 171        int chksum, size;
 172
 173        strcpy(hp->magic, "ustar  ");
 174
 175        /* Calculate and store the checksum (i.e., the sum of all of the bytes of
 176         * the header).  The checksum field must be filled with blanks for the
 177         * calculation.  The checksum field is formatted differently from the
 178         * other fields: it has 6 digits, a null, then a space -- rather than
 179         * digits, followed by a null like the other fields... */
 180        memset(hp->chksum, ' ', sizeof(hp->chksum));
 181        cp = (const unsigned char *) hp;
 182        chksum = 0;
 183        size = sizeof(*hp);
 184        do { chksum += *cp++; } while (--size);
 185        putOctal(hp->chksum, sizeof(hp->chksum)-1, chksum);
 186
 187        /* Now write the header out to disk */
 188        xwrite(fd, hp, sizeof(*hp));
 189}
 190
 191#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
 192static void writeLongname(int fd, int type, const char *name, int dir)
 193{
 194        static const struct {
 195                char mode[8];             /* 100-107 */
 196                char uid[8];              /* 108-115 */
 197                char gid[8];              /* 116-123 */
 198                char size[12];            /* 124-135 */
 199                char mtime[12];           /* 136-147 */
 200        } prefilled = {
 201                "0000000",
 202                "0000000",
 203                "0000000",
 204                "00000000000",
 205                "00000000000",
 206        };
 207        struct tar_header_t header;
 208        int size;
 209
 210        dir = !!dir; /* normalize: 0/1 */
 211        size = strlen(name) + 1 + dir; /* GNU tar uses strlen+1 */
 212        /* + dir: account for possible '/' */
 213
 214        memset(&header, 0, sizeof(header));
 215        strcpy(header.name, "././@LongLink");
 216        memcpy(header.mode, prefilled.mode, sizeof(prefilled));
 217        PUT_OCTAL(header.size, size);
 218        header.typeflag = type;
 219        chksum_and_xwrite(fd, &header);
 220
 221        /* Write filename[/] and pad the block. */
 222        /* dir=0: writes 'name<NUL>', pads */
 223        /* dir=1: writes 'name', writes '/<NUL>', pads */
 224        dir *= 2;
 225        xwrite(fd, name, size - dir);
 226        xwrite(fd, "/", dir);
 227        size = (-size) & (TAR_BLOCK_SIZE-1);
 228        memset(&header, 0, size);
 229        xwrite(fd, &header, size);
 230}
 231#endif
 232
 233/* Write out a tar header for the specified file/directory/whatever */
 234static int writeTarHeader(struct TarBallInfo *tbInfo,
 235                const char *header_name, const char *fileName, struct stat *statbuf)
 236{
 237        struct tar_header_t header;
 238
 239        memset(&header, 0, sizeof(header));
 240
 241        strncpy(header.name, header_name, sizeof(header.name));
 242
 243        /* POSIX says to mask mode with 07777. */
 244        PUT_OCTAL(header.mode, statbuf->st_mode & 07777);
 245        PUT_OCTAL(header.uid, statbuf->st_uid);
 246        PUT_OCTAL(header.gid, statbuf->st_gid);
 247        memset(header.size, '0', sizeof(header.size)-1); /* Regular file size is handled later */
 248        PUT_OCTAL(header.mtime, statbuf->st_mtime);
 249
 250        /* Enter the user and group names */
 251        safe_strncpy(header.uname, get_cached_username(statbuf->st_uid), sizeof(header.uname));
 252        safe_strncpy(header.gname, get_cached_groupname(statbuf->st_gid), sizeof(header.gname));
 253
 254        if (tbInfo->hlInfo) {
 255                /* This is a hard link */
 256                header.typeflag = LNKTYPE;
 257                strncpy(header.linkname, tbInfo->hlInfo->name,
 258                                sizeof(header.linkname));
 259#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
 260                /* Write out long linkname if needed */
 261                if (header.linkname[sizeof(header.linkname)-1])
 262                        writeLongname(tbInfo->tarFd, GNULONGLINK,
 263                                        tbInfo->hlInfo->name, 0);
 264#endif
 265        } else if (S_ISLNK(statbuf->st_mode)) {
 266                char *lpath = xmalloc_readlink_or_warn(fileName);
 267                if (!lpath)
 268                        return FALSE;
 269                header.typeflag = SYMTYPE;
 270                strncpy(header.linkname, lpath, sizeof(header.linkname));
 271#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
 272                /* Write out long linkname if needed */
 273                if (header.linkname[sizeof(header.linkname)-1])
 274                        writeLongname(tbInfo->tarFd, GNULONGLINK, lpath, 0);
 275#else
 276                /* If it is larger than 100 bytes, bail out */
 277                if (header.linkname[sizeof(header.linkname)-1]) {
 278                        free(lpath);
 279                        bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported");
 280                        return FALSE;
 281                }
 282#endif
 283                free(lpath);
 284        } else if (S_ISDIR(statbuf->st_mode)) {
 285                header.typeflag = DIRTYPE;
 286                /* Append '/' only if there is a space for it */
 287                if (!header.name[sizeof(header.name)-1])
 288                        header.name[strlen(header.name)] = '/';
 289        } else if (S_ISCHR(statbuf->st_mode)) {
 290                header.typeflag = CHRTYPE;
 291                PUT_OCTAL(header.devmajor, major(statbuf->st_rdev));
 292                PUT_OCTAL(header.devminor, minor(statbuf->st_rdev));
 293        } else if (S_ISBLK(statbuf->st_mode)) {
 294                header.typeflag = BLKTYPE;
 295                PUT_OCTAL(header.devmajor, major(statbuf->st_rdev));
 296                PUT_OCTAL(header.devminor, minor(statbuf->st_rdev));
 297        } else if (S_ISFIFO(statbuf->st_mode)) {
 298                header.typeflag = FIFOTYPE;
 299        } else if (S_ISREG(statbuf->st_mode)) {
 300                if (sizeof(statbuf->st_size) > 4
 301                 && statbuf->st_size > (off_t)0777777777777LL
 302                ) {
 303                        bb_error_msg_and_die("can't store file '%s' "
 304                                "of size %"OFF_FMT"u, aborting",
 305                                fileName, statbuf->st_size);
 306                }
 307                header.typeflag = REGTYPE;
 308                PUT_OCTAL(header.size, statbuf->st_size);
 309        } else {
 310                bb_error_msg("%s: unknown file type", fileName);
 311                return FALSE;
 312        }
 313
 314#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
 315        /* Write out long name if needed */
 316        /* (we, like GNU tar, output long linkname *before* long name) */
 317        if (header.name[sizeof(header.name)-1])
 318                writeLongname(tbInfo->tarFd, GNULONGNAME,
 319                                header_name, S_ISDIR(statbuf->st_mode));
 320#endif
 321
 322        /* Now write the header out to disk */
 323        chksum_and_xwrite(tbInfo->tarFd, &header);
 324
 325        /* Now do the verbose thing (or not) */
 326        if (tbInfo->verboseFlag) {
 327                FILE *vbFd = stdout;
 328
 329                /* If archive goes to stdout, verbose goes to stderr */
 330                if (tbInfo->tarFd == STDOUT_FILENO)
 331                        vbFd = stderr;
 332                /* GNU "tar cvvf" prints "extended" listing a-la "ls -l" */
 333                /* We don't have such excesses here: for us "v" == "vv" */
 334                /* '/' is probably a GNUism */
 335                fprintf(vbFd, "%s%s\n", header_name,
 336                                S_ISDIR(statbuf->st_mode) ? "/" : "");
 337        }
 338
 339        return TRUE;
 340}
 341
 342#if ENABLE_FEATURE_TAR_FROM
 343static int exclude_file(const llist_t *excluded_files, const char *file)
 344{
 345        while (excluded_files) {
 346                if (excluded_files->data[0] == '/') {
 347                        if (fnmatch(excluded_files->data, file,
 348                                        FNM_PATHNAME | FNM_LEADING_DIR) == 0)
 349                                return 1;
 350                } else {
 351                        const char *p;
 352
 353                        for (p = file; p[0] != '\0'; p++) {
 354                                if ((p == file || p[-1] == '/')
 355                                 && p[0] != '/'
 356                                 && fnmatch(excluded_files->data, p,
 357                                                FNM_PATHNAME | FNM_LEADING_DIR) == 0
 358                                ) {
 359                                        return 1;
 360                                }
 361                        }
 362                }
 363                excluded_files = excluded_files->link;
 364        }
 365
 366        return 0;
 367}
 368#else
 369# define exclude_file(excluded_files, file) 0
 370#endif
 371
 372static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statbuf,
 373                        void *userData, int depth UNUSED_PARAM)
 374{
 375        struct TarBallInfo *tbInfo = (struct TarBallInfo *) userData;
 376        const char *header_name;
 377        int inputFileFd = -1;
 378
 379        DBG("writeFileToTarball('%s')", fileName);
 380
 381        /* Strip leading '/' (must be before memorizing hardlink's name) */
 382        header_name = fileName;
 383        while (header_name[0] == '/') {
 384                static smallint warned;
 385
 386                if (!warned) {
 387                        bb_error_msg("removing leading '/' from member names");
 388                        warned = 1;
 389                }
 390                header_name++;
 391        }
 392
 393        if (header_name[0] == '\0')
 394                return TRUE;
 395
 396        /* It is against the rules to archive a socket */
 397        if (S_ISSOCK(statbuf->st_mode)) {
 398                bb_error_msg("%s: socket ignored", fileName);
 399                return TRUE;
 400        }
 401
 402        /*
 403         * Check to see if we are dealing with a hard link.
 404         * If so -
 405         * Treat the first occurance of a given dev/inode as a file while
 406         * treating any additional occurances as hard links.  This is done
 407         * by adding the file information to the HardLinkInfo linked list.
 408         */
 409        tbInfo->hlInfo = NULL;
 410        if (!S_ISDIR(statbuf->st_mode) && statbuf->st_nlink > 1) {
 411                DBG("'%s': st_nlink > 1", header_name);
 412                tbInfo->hlInfo = findHardLinkInfo(tbInfo->hlInfoHead, statbuf);
 413                if (tbInfo->hlInfo == NULL) {
 414                        DBG("'%s': addHardLinkInfo", header_name);
 415                        addHardLinkInfo(&tbInfo->hlInfoHead, statbuf, header_name);
 416                }
 417        }
 418
 419        /* It is a bad idea to store the archive we are in the process of creating,
 420         * so check the device and inode to be sure that this particular file isn't
 421         * the new tarball */
 422        if (tbInfo->tarFileStatBuf.st_dev == statbuf->st_dev
 423         && tbInfo->tarFileStatBuf.st_ino == statbuf->st_ino
 424        ) {
 425                bb_error_msg("%s: file is the archive; skipping", fileName);
 426                return TRUE;
 427        }
 428
 429        if (exclude_file(tbInfo->excludeList, header_name))
 430                return SKIP;
 431
 432#if !ENABLE_FEATURE_TAR_GNU_EXTENSIONS
 433        if (strlen(header_name) >= NAME_SIZE) {
 434                bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported");
 435                return TRUE;
 436        }
 437#endif
 438
 439        /* Is this a regular file? */
 440        if (tbInfo->hlInfo == NULL && S_ISREG(statbuf->st_mode)) {
 441                /* open the file we want to archive, and make sure all is well */
 442                inputFileFd = open_or_warn(fileName, O_RDONLY);
 443                if (inputFileFd < 0) {
 444                        return FALSE;
 445                }
 446        }
 447
 448        /* Add an entry to the tarball */
 449        if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) {
 450                return FALSE;
 451        }
 452
 453        /* If it was a regular file, write out the body */
 454        if (inputFileFd >= 0) {
 455                size_t readSize;
 456                /* Write the file to the archive. */
 457                /* We record size into header first, */
 458                /* and then write out file. If file shrinks in between, */
 459                /* tar will be corrupted. So we don't allow for that. */
 460                /* NB: GNU tar 1.16 warns and pads with zeroes */
 461                /* or even seeks back and updates header */
 462                bb_copyfd_exact_size(inputFileFd, tbInfo->tarFd, statbuf->st_size);
 463                ////off_t readSize;
 464                ////readSize = bb_copyfd_size(inputFileFd, tbInfo->tarFd, statbuf->st_size);
 465                ////if (readSize != statbuf->st_size && readSize >= 0) {
 466                ////    bb_error_msg_and_die("short read from %s, aborting", fileName);
 467                ////}
 468
 469                /* Check that file did not grow in between? */
 470                /* if (safe_read(inputFileFd, 1) == 1) warn but continue? */
 471
 472                close(inputFileFd);
 473
 474                /* Pad the file up to the tar block size */
 475                /* (a few tricks here in the name of code size) */
 476                readSize = (-(int)statbuf->st_size) & (TAR_BLOCK_SIZE-1);
 477                memset(block_buf, 0, readSize);
 478                xwrite(tbInfo->tarFd, block_buf, readSize);
 479        }
 480
 481        return TRUE;
 482}
 483
 484#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
 485# if !(ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2)
 486#  define vfork_compressor(tar_fd, gzip) vfork_compressor(tar_fd)
 487# endif
 488/* Don't inline: vfork scares gcc and pessimizes code */
 489static void NOINLINE vfork_compressor(int tar_fd, int gzip)
 490{
 491        pid_t gzipPid;
 492# if ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2
 493        const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
 494# elif ENABLE_FEATURE_SEAMLESS_GZ
 495        const char *zip_exec = "gzip";
 496# else /* only ENABLE_FEATURE_SEAMLESS_BZ2 */
 497        const char *zip_exec = "bzip2";
 498# endif
 499        // On Linux, vfork never unpauses parent early, although standard
 500        // allows for that. Do we want to waste bytes checking for it?
 501# define WAIT_FOR_CHILD 0
 502        volatile int vfork_exec_errno = 0;
 503        struct fd_pair gzipDataPipe;
 504# if WAIT_FOR_CHILD
 505        struct fd_pair gzipStatusPipe;
 506        xpiped_pair(gzipStatusPipe);
 507# endif
 508        xpiped_pair(gzipDataPipe);
 509
 510        signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
 511
 512# if defined(__GNUC__) && __GNUC__
 513        /* Avoid vfork clobbering */
 514        (void) &zip_exec;
 515# endif
 516
 517        gzipPid = xvfork();
 518
 519        if (gzipPid == 0) {
 520                /* child */
 521                /* NB: close _first_, then move fds! */
 522                close(gzipDataPipe.wr);
 523# if WAIT_FOR_CHILD
 524                close(gzipStatusPipe.rd);
 525                /* gzipStatusPipe.wr will close only on exec -
 526                 * parent waits for this close to happen */
 527                fcntl(gzipStatusPipe.wr, F_SETFD, FD_CLOEXEC);
 528# endif
 529                xmove_fd(gzipDataPipe.rd, 0);
 530                xmove_fd(tar_fd, 1);
 531                /* exec gzip/bzip2 program/applet */
 532                BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
 533                vfork_exec_errno = errno;
 534                _exit(EXIT_FAILURE);
 535        }
 536
 537        /* parent */
 538        xmove_fd(gzipDataPipe.wr, tar_fd);
 539        close(gzipDataPipe.rd);
 540# if WAIT_FOR_CHILD
 541        close(gzipStatusPipe.wr);
 542        while (1) {
 543                char buf;
 544                int n;
 545
 546                /* Wait until child execs (or fails to) */
 547                n = full_read(gzipStatusPipe.rd, &buf, 1);
 548                if (n < 0 /* && errno == EAGAIN */)
 549                        continue;       /* try it again */
 550        }
 551        close(gzipStatusPipe.rd);
 552# endif
 553        if (vfork_exec_errno) {
 554                errno = vfork_exec_errno;
 555                bb_perror_msg_and_die("can't execute '%s'", zip_exec);
 556        }
 557}
 558#endif /* ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 */
 559
 560
 561/* gcc 4.2.1 inlines it, making code bigger */
 562static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
 563        int dereferenceFlag, const llist_t *include,
 564        const llist_t *exclude, int gzip)
 565{
 566        int errorFlag = FALSE;
 567        struct TarBallInfo tbInfo;
 568
 569        tbInfo.hlInfoHead = NULL;
 570        tbInfo.tarFd = tar_fd;
 571        tbInfo.verboseFlag = verboseFlag;
 572
 573        /* Store the stat info for the tarball's file, so
 574         * can avoid including the tarball into itself....  */
 575        if (fstat(tbInfo.tarFd, &tbInfo.tarFileStatBuf) < 0)
 576                bb_perror_msg_and_die("can't stat tar file");
 577
 578#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
 579        if (gzip)
 580                vfork_compressor(tbInfo.tarFd, gzip);
 581#endif
 582
 583        tbInfo.excludeList = exclude;
 584
 585        /* Read the directory/files and iterate over them one at a time */
 586        while (include) {
 587                if (!recursive_action(include->data, ACTION_RECURSE |
 588                                (dereferenceFlag ? ACTION_FOLLOWLINKS : 0),
 589                                writeFileToTarball, writeFileToTarball, &tbInfo, 0)
 590                ) {
 591                        errorFlag = TRUE;
 592                }
 593                include = include->link;
 594        }
 595        /* Write two empty blocks to the end of the archive */
 596        memset(block_buf, 0, 2*TAR_BLOCK_SIZE);
 597        xwrite(tbInfo.tarFd, block_buf, 2*TAR_BLOCK_SIZE);
 598
 599        /* To be pedantically correct, we would check if the tarball
 600         * is smaller than 20 tar blocks, and pad it if it was smaller,
 601         * but that isn't necessary for GNU tar interoperability, and
 602         * so is considered a waste of space */
 603
 604        /* Close so the child process (if any) will exit */
 605        close(tbInfo.tarFd);
 606
 607        /* Hang up the tools, close up shop, head home */
 608        if (ENABLE_FEATURE_CLEAN_UP)
 609                freeHardLinkInfo(&tbInfo.hlInfoHead);
 610
 611        if (errorFlag)
 612                bb_error_msg("error exit delayed from previous errors");
 613
 614#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
 615        if (gzip) {
 616                int status;
 617                if (safe_waitpid(-1, &status, 0) == -1)
 618                        bb_perror_msg("waitpid");
 619                else if (!WIFEXITED(status) || WEXITSTATUS(status))
 620                        /* gzip was killed or has exited with nonzero! */
 621                        errorFlag = TRUE;
 622        }
 623#endif
 624        return errorFlag;
 625}
 626#else
 627int writeTarFile(int tar_fd, int verboseFlag,
 628        int dereferenceFlag, const llist_t *include,
 629        const llist_t *exclude, int gzip);
 630#endif /* FEATURE_TAR_CREATE */
 631
 632#if ENABLE_FEATURE_TAR_FROM
 633static llist_t *append_file_list_to_list(llist_t *list)
 634{
 635        FILE *src_stream;
 636        char *line;
 637        llist_t *newlist = NULL;
 638
 639        while (list) {
 640                src_stream = xfopen_for_read(llist_pop(&list));
 641                while ((line = xmalloc_fgetline(src_stream)) != NULL) {
 642                        /* kill trailing '/' unless the string is just "/" */
 643                        char *cp = last_char_is(line, '/');
 644                        if (cp > line)
 645                                *cp = '\0';
 646                        llist_add_to(&newlist, line);
 647                }
 648                fclose(src_stream);
 649        }
 650        return newlist;
 651}
 652#else
 653# define append_file_list_to_list(x) 0
 654#endif
 655
 656#if ENABLE_FEATURE_SEAMLESS_Z
 657static char FAST_FUNC get_header_tar_Z(archive_handle_t *archive_handle)
 658{
 659        /* Can't lseek over pipes */
 660        archive_handle->seek = seek_by_read;
 661
 662        /* do the decompression, and cleanup */
 663        if (xread_char(archive_handle->src_fd) != 0x1f
 664         || xread_char(archive_handle->src_fd) != 0x9d
 665        ) {
 666                bb_error_msg_and_die("invalid magic");
 667        }
 668
 669        open_transformer(archive_handle->src_fd, unpack_Z_stream, "uncompress");
 670        archive_handle->offset = 0;
 671        while (get_header_tar(archive_handle) == EXIT_SUCCESS)
 672                continue;
 673
 674        /* Can only do one file at a time */
 675        return EXIT_FAILURE;
 676}
 677#else
 678# define get_header_tar_Z NULL
 679#endif
 680
 681#ifdef CHECK_FOR_CHILD_EXITCODE
 682/* Looks like it isn't needed - tar detects malformed (truncated)
 683 * archive if e.g. bunzip2 fails */
 684static int child_error;
 685
 686static void handle_SIGCHLD(int status)
 687{
 688        /* Actually, 'status' is a signo. We reuse it for other needs */
 689
 690        /* Wait for any child without blocking */
 691        if (wait_any_nohang(&status) < 0)
 692                /* wait failed?! I'm confused... */
 693                return;
 694
 695        if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
 696                /* child exited with 0 */
 697                return;
 698        /* Cannot happen?
 699        if (!WIFSIGNALED(status) && !WIFEXITED(status)) return; */
 700        child_error = 1;
 701}
 702#endif
 703
 704//usage:#define tar_trivial_usage
 705//usage:       "-[" IF_FEATURE_TAR_CREATE("c") "xt" IF_FEATURE_SEAMLESS_GZ("z")
 706//usage:        IF_FEATURE_SEAMLESS_BZ2("j") IF_FEATURE_SEAMLESS_LZMA("a")
 707//usage:        IF_FEATURE_SEAMLESS_Z("Z") IF_FEATURE_TAR_NOPRESERVE_TIME("m") "vO] "
 708//usage:        IF_FEATURE_TAR_FROM("[-X FILE] ")
 709//usage:       "[-f TARFILE] [-C DIR] [FILE]..."
 710//usage:#define tar_full_usage "\n\n"
 711//usage:        IF_FEATURE_TAR_CREATE("Create, extract, ")
 712//usage:        IF_NOT_FEATURE_TAR_CREATE("Extract ")
 713//usage:        "or list files from a tar file\n"
 714//usage:     "\nOperation:"
 715//usage:        IF_FEATURE_TAR_CREATE(
 716//usage:     "\n        c       Create"
 717//usage:        )
 718//usage:     "\n        x       Extract"
 719//usage:     "\n        t       List"
 720//usage:     "\nOptions:"
 721//usage:     "\n        f       Name of TARFILE ('-' for stdin/out)"
 722//usage:     "\n        C       Change to DIR before operation"
 723//usage:     "\n        v       Verbose"
 724//usage:        IF_FEATURE_SEAMLESS_GZ(
 725//usage:     "\n        z       (De)compress using gzip"
 726//usage:        )
 727//usage:        IF_FEATURE_SEAMLESS_BZ2(
 728//usage:     "\n        j       (De)compress using bzip2"
 729//usage:        )
 730//usage:        IF_FEATURE_SEAMLESS_LZMA(
 731//usage:     "\n        a       (De)compress using lzma"
 732//usage:        )
 733//usage:        IF_FEATURE_SEAMLESS_Z(
 734//usage:     "\n        Z       (De)compress using compress"
 735//usage:        )
 736//usage:     "\n        O       Extract to stdout"
 737//usage:        IF_FEATURE_TAR_CREATE(
 738//usage:     "\n        h       Follow symlinks"
 739//usage:        )
 740//usage:        IF_FEATURE_TAR_NOPRESERVE_TIME(
 741//usage:     "\n        m       Don't restore mtime"
 742//usage:        )
 743//usage:        IF_FEATURE_TAR_FROM(
 744//usage:        IF_FEATURE_TAR_LONG_OPTIONS(
 745//usage:     "\n        exclude File to exclude"
 746//usage:        )
 747//usage:     "\n        X       File with names to exclude"
 748//usage:     "\n        T       File with names to include"
 749//usage:        )
 750//usage:
 751//usage:#define tar_example_usage
 752//usage:       "$ zcat /tmp/tarball.tar.gz | tar -xf -\n"
 753//usage:       "$ tar -cf /tmp/tarball.tar /usr/local\n"
 754
 755// Supported but aren't in --help:
 756//      o       no-same-owner
 757//      p       same-permissions
 758//      k       keep-old
 759//      numeric-owner
 760//      no-same-permissions
 761//      overwrite
 762//IF_FEATURE_TAR_TO_COMMAND(
 763//      to-command
 764//)
 765
 766enum {
 767        OPTBIT_KEEP_OLD = 8,
 768        IF_FEATURE_TAR_CREATE(   OPTBIT_CREATE      ,)
 769        IF_FEATURE_TAR_CREATE(   OPTBIT_DEREFERENCE ,)
 770        IF_FEATURE_SEAMLESS_BZ2( OPTBIT_BZIP2       ,)
 771        IF_FEATURE_SEAMLESS_LZMA(OPTBIT_LZMA        ,)
 772        IF_FEATURE_TAR_FROM(     OPTBIT_INCLUDE_FROM,)
 773        IF_FEATURE_TAR_FROM(     OPTBIT_EXCLUDE_FROM,)
 774        IF_FEATURE_SEAMLESS_GZ(  OPTBIT_GZIP        ,)
 775        IF_FEATURE_SEAMLESS_Z(   OPTBIT_COMPRESS    ,) // 16th bit
 776        IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,)
 777#if ENABLE_FEATURE_TAR_LONG_OPTIONS
 778        IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND   ,)
 779        OPTBIT_NUMERIC_OWNER,
 780        OPTBIT_NOPRESERVE_PERM,
 781        OPTBIT_OVERWRITE,
 782#endif
 783        OPT_TEST         = 1 << 0, // t
 784        OPT_EXTRACT      = 1 << 1, // x
 785        OPT_BASEDIR      = 1 << 2, // C
 786        OPT_TARNAME      = 1 << 3, // f
 787        OPT_2STDOUT      = 1 << 4, // O
 788        OPT_NOPRESERVE_OWNER = 1 << 5, // o == no-same-owner
 789        OPT_P            = 1 << 6, // p
 790        OPT_VERBOSE      = 1 << 7, // v
 791        OPT_KEEP_OLD     = 1 << 8, // k
 792        OPT_CREATE       = IF_FEATURE_TAR_CREATE(   (1 << OPTBIT_CREATE      )) + 0, // c
 793        OPT_DEREFERENCE  = IF_FEATURE_TAR_CREATE(   (1 << OPTBIT_DEREFERENCE )) + 0, // h
 794        OPT_BZIP2        = IF_FEATURE_SEAMLESS_BZ2( (1 << OPTBIT_BZIP2       )) + 0, // j
 795        OPT_LZMA         = IF_FEATURE_SEAMLESS_LZMA((1 << OPTBIT_LZMA        )) + 0, // a
 796        OPT_INCLUDE_FROM = IF_FEATURE_TAR_FROM(     (1 << OPTBIT_INCLUDE_FROM)) + 0, // T
 797        OPT_EXCLUDE_FROM = IF_FEATURE_TAR_FROM(     (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X
 798        OPT_GZIP         = IF_FEATURE_SEAMLESS_GZ(  (1 << OPTBIT_GZIP        )) + 0, // z
 799        OPT_COMPRESS     = IF_FEATURE_SEAMLESS_Z(   (1 << OPTBIT_COMPRESS    )) + 0, // Z
 800        OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m
 801        OPT_2COMMAND        = IF_FEATURE_TAR_TO_COMMAND(  (1 << OPTBIT_2COMMAND       )) + 0, // to-command
 802        OPT_NUMERIC_OWNER   = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER  )) + 0, // numeric-owner
 803        OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
 804        OPT_OVERWRITE       = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE      )) + 0, // overwrite
 805};
 806#if ENABLE_FEATURE_TAR_LONG_OPTIONS
 807static const char tar_longopts[] ALIGN1 =
 808        "list\0"                No_argument       "t"
 809        "extract\0"             No_argument       "x"
 810        "directory\0"           Required_argument "C"
 811        "file\0"                Required_argument "f"
 812        "to-stdout\0"           No_argument       "O"
 813        /* do not restore owner */
 814        /* Note: GNU tar handles 'o' as no-same-owner only on extract,
 815         * on create, 'o' is --old-archive. We do not support --old-archive. */
 816        "no-same-owner\0"       No_argument       "o"
 817        "same-permissions\0"    No_argument       "p"
 818        "verbose\0"             No_argument       "v"
 819        "keep-old\0"            No_argument       "k"
 820# if ENABLE_FEATURE_TAR_CREATE
 821        "create\0"              No_argument       "c"
 822        "dereference\0"         No_argument       "h"
 823# endif
 824# if ENABLE_FEATURE_SEAMLESS_BZ2
 825        "bzip2\0"               No_argument       "j"
 826# endif
 827# if ENABLE_FEATURE_SEAMLESS_LZMA
 828        "lzma\0"                No_argument       "a"
 829# endif
 830# if ENABLE_FEATURE_TAR_FROM
 831        "files-from\0"          Required_argument "T"
 832        "exclude-from\0"        Required_argument "X"
 833# endif
 834# if ENABLE_FEATURE_SEAMLESS_GZ
 835        "gzip\0"                No_argument       "z"
 836# endif
 837# if ENABLE_FEATURE_SEAMLESS_Z
 838        "compress\0"            No_argument       "Z"
 839# endif
 840# if ENABLE_FEATURE_TAR_NOPRESERVE_TIME
 841        "touch\0"               No_argument       "m"
 842# endif
 843# if ENABLE_FEATURE_TAR_TO_COMMAND
 844        "to-command\0"          Required_argument "\xfb"
 845# endif
 846        /* use numeric uid/gid from tar header, not textual */
 847        "numeric-owner\0"       No_argument       "\xfc"
 848        /* do not restore mode */
 849        "no-same-permissions\0" No_argument       "\xfd"
 850        /* on unpack, open with O_TRUNC and !O_EXCL */
 851        "overwrite\0"           No_argument       "\xfe"
 852        /* --exclude takes next bit position in option mask, */
 853        /* therefore we have to put it _after_ --no-same-permissions */
 854# if ENABLE_FEATURE_TAR_FROM
 855        "exclude\0"             Required_argument "\xff"
 856# endif
 857        ;
 858#endif
 859
 860int tar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 861int tar_main(int argc UNUSED_PARAM, char **argv)
 862{
 863        char FAST_FUNC (*get_header_ptr)(archive_handle_t *) = get_header_tar;
 864        archive_handle_t *tar_handle;
 865        char *base_dir = NULL;
 866        const char *tar_filename = "-";
 867        unsigned opt;
 868        int verboseFlag = 0;
 869#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
 870        llist_t *excludes = NULL;
 871#endif
 872
 873        /* Initialise default values */
 874        tar_handle = init_handle();
 875        tar_handle->ah_flags = ARCHIVE_CREATE_LEADING_DIRS
 876                             | ARCHIVE_RESTORE_DATE
 877                             | ARCHIVE_UNLINK_OLD;
 878
 879        /* Apparently only root's tar preserves perms (see bug 3844) */
 880        if (getuid() != 0)
 881                tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_PERM;
 882
 883        /* Prepend '-' to the first argument if required */
 884        opt_complementary = "--:" // first arg is options
 885                "tt:vv:" // count -t,-v
 886                "?:" // bail out with usage instead of error return
 887                "X::T::" // cumulative lists
 888#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
 889                "\xff::" // cumulative lists for --exclude
 890#endif
 891                IF_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd
 892                IF_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive
 893                IF_NOT_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive
 894#if ENABLE_FEATURE_TAR_LONG_OPTIONS
 895        applet_long_options = tar_longopts;
 896#endif
 897#if ENABLE_DESKTOP
 898        if (argv[1] && argv[1][0] != '-') {
 899                /* Compat:
 900                 * 1st argument without dash handles options with parameters
 901                 * differently from dashed one: it takes *next argv[i]*
 902                 * as paramenter even if there are more chars in 1st argument:
 903                 *  "tar fx TARFILE" - "x" is not taken as f's param
 904                 *  but is interpreted as -x option
 905                 *  "tar -xf TARFILE" - dashed equivalent of the above
 906                 *  "tar -fx ..." - "x" is taken as f's param
 907                 * getopt32 wouldn't handle 1st command correctly.
 908                 * Unfortunately, people do use such commands.
 909                 * We massage argv[1] to work around it by moving 'f'
 910                 * to the end of the string.
 911                 * More contrived "tar fCx TARFILE DIR" still fails,
 912                 * but such commands are much less likely to be used.
 913                 */
 914                char *f = strchr(argv[1], 'f');
 915                if (f) {
 916                        while (f[1] != '\0') {
 917                                *f = f[1];
 918                                f++;
 919                        }
 920                        *f = 'f';
 921                }
 922        }
 923#endif
 924        opt = getopt32(argv,
 925                "txC:f:Oopvk"
 926                IF_FEATURE_TAR_CREATE(   "ch"  )
 927                IF_FEATURE_SEAMLESS_BZ2( "j"   )
 928                IF_FEATURE_SEAMLESS_LZMA("a"   )
 929                IF_FEATURE_TAR_FROM(     "T:X:")
 930                IF_FEATURE_SEAMLESS_GZ(  "z"   )
 931                IF_FEATURE_SEAMLESS_Z(   "Z"   )
 932                IF_FEATURE_TAR_NOPRESERVE_TIME("m")
 933                , &base_dir // -C dir
 934                , &tar_filename // -f filename
 935                IF_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T
 936                IF_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X
 937                IF_FEATURE_TAR_TO_COMMAND(, &(tar_handle->tar__to_command)) // --to-command
 938#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
 939                , &excludes // --exclude
 940#endif
 941                , &verboseFlag // combined count for -t and -v
 942                , &verboseFlag // combined count for -t and -v
 943                );
 944        //bb_error_msg("opt:%08x", opt);
 945        argv += optind;
 946
 947        if (verboseFlag) tar_handle->action_header = header_verbose_list;
 948        if (verboseFlag == 1) tar_handle->action_header = header_list;
 949
 950        if (opt & OPT_EXTRACT)
 951                tar_handle->action_data = data_extract_all;
 952
 953        if (opt & OPT_2STDOUT)
 954                tar_handle->action_data = data_extract_to_stdout;
 955
 956        if (opt & OPT_2COMMAND) {
 957                putenv((char*)"TAR_FILETYPE=f");
 958                signal(SIGPIPE, SIG_IGN);
 959                tar_handle->action_data = data_extract_to_command;
 960        }
 961
 962        if (opt & OPT_KEEP_OLD)
 963                tar_handle->ah_flags &= ~ARCHIVE_UNLINK_OLD;
 964
 965        if (opt & OPT_NUMERIC_OWNER)
 966                tar_handle->ah_flags |= ARCHIVE_NUMERIC_OWNER;
 967
 968        if (opt & OPT_NOPRESERVE_OWNER)
 969                tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_OWNER;
 970
 971        if (opt & OPT_NOPRESERVE_PERM)
 972                tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_PERM;
 973
 974        if (opt & OPT_OVERWRITE) {
 975                tar_handle->ah_flags &= ~ARCHIVE_UNLINK_OLD;
 976                tar_handle->ah_flags |= ARCHIVE_O_TRUNC;
 977        }
 978
 979        if (opt & OPT_GZIP)
 980                get_header_ptr = get_header_tar_gz;
 981
 982        if (opt & OPT_BZIP2)
 983                get_header_ptr = get_header_tar_bz2;
 984
 985        if (opt & OPT_LZMA)
 986                get_header_ptr = get_header_tar_lzma;
 987
 988        if (opt & OPT_COMPRESS)
 989                get_header_ptr = get_header_tar_Z;
 990
 991        if (opt & OPT_NOPRESERVE_TIME)
 992                tar_handle->ah_flags &= ~ARCHIVE_RESTORE_DATE;
 993
 994#if ENABLE_FEATURE_TAR_FROM
 995        tar_handle->reject = append_file_list_to_list(tar_handle->reject);
 996# if ENABLE_FEATURE_TAR_LONG_OPTIONS
 997        /* Append excludes to reject */
 998        while (excludes) {
 999                llist_t *next = excludes->link;
1000                excludes->link = tar_handle->reject;
1001                tar_handle->reject = excludes;
1002                excludes = next;
1003        }
1004# endif
1005        tar_handle->accept = append_file_list_to_list(tar_handle->accept);
1006#endif
1007
1008        /* Setup an array of filenames to work with */
1009        /* TODO: This is the same as in ar, make a separate function? */
1010        while (*argv) {
1011                /* kill trailing '/' unless the string is just "/" */
1012                char *cp = last_char_is(*argv, '/');
1013                if (cp > *argv)
1014                        *cp = '\0';
1015                llist_add_to_end(&tar_handle->accept, *argv);
1016                argv++;
1017        }
1018
1019        if (tar_handle->accept || tar_handle->reject)
1020                tar_handle->filter = filter_accept_reject_list;
1021
1022        /* Open the tar file */
1023        {
1024                int tar_fd = STDIN_FILENO;
1025                int flags = O_RDONLY;
1026
1027                if (opt & OPT_CREATE) {
1028                        /* Make sure there is at least one file to tar up */
1029                        if (tar_handle->accept == NULL)
1030                                bb_error_msg_and_die("empty archive");
1031
1032                        tar_fd = STDOUT_FILENO;
1033                        /* Mimicking GNU tar 1.15.1: */
1034                        flags = O_WRONLY | O_CREAT | O_TRUNC;
1035                }
1036
1037                if (LONE_DASH(tar_filename)) {
1038                        tar_handle->src_fd = tar_fd;
1039                        tar_handle->seek = seek_by_read;
1040                } else {
1041                        if (ENABLE_FEATURE_TAR_AUTODETECT && flags == O_RDONLY) {
1042                                get_header_ptr = get_header_tar;
1043                                tar_handle->src_fd = open_zipped(tar_filename);
1044                                if (tar_handle->src_fd < 0)
1045                                        bb_perror_msg_and_die("can't open '%s'", tar_filename);
1046                        } else {
1047                                tar_handle->src_fd = xopen(tar_filename, flags);
1048                        }
1049                }
1050        }
1051
1052        if (base_dir)
1053                xchdir(base_dir);
1054
1055#ifdef CHECK_FOR_CHILD_EXITCODE
1056        /* We need to know whether child (gzip/bzip/etc) exits abnormally */
1057        signal(SIGCHLD, handle_SIGCHLD);
1058#endif
1059
1060        /* Create an archive */
1061        if (opt & OPT_CREATE) {
1062#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
1063                int zipMode = 0;
1064                if (ENABLE_FEATURE_SEAMLESS_GZ && (opt & OPT_GZIP))
1065                        zipMode = 1;
1066                if (ENABLE_FEATURE_SEAMLESS_BZ2 && (opt & OPT_BZIP2))
1067                        zipMode = 2;
1068#endif
1069                /* NB: writeTarFile() closes tar_handle->src_fd */
1070                return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE,
1071                                tar_handle->accept,
1072                                tar_handle->reject, zipMode);
1073        }
1074
1075        while (get_header_ptr(tar_handle) == EXIT_SUCCESS)
1076                continue;
1077
1078        /* Check that every file that should have been extracted was */
1079        while (tar_handle->accept) {
1080                if (!find_list_entry(tar_handle->reject, tar_handle->accept->data)
1081                 && !find_list_entry(tar_handle->passed, tar_handle->accept->data)
1082                ) {
1083                        bb_error_msg_and_die("%s: not found in archive",
1084                                tar_handle->accept->data);
1085                }
1086                tar_handle->accept = tar_handle->accept->link;
1087        }
1088        if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */)
1089                close(tar_handle->src_fd);
1090
1091        return EXIT_SUCCESS;
1092}
1093