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 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 source tree.
  24 */
  25
  26#include <fnmatch.h>
  27#include "libbb.h"
  28#include "archive.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        xfstat(tbInfo.tarFd, &tbInfo.tarFileStatBuf, "can't stat tar file");
 576
 577#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
 578        if (gzip)
 579                vfork_compressor(tbInfo.tarFd, gzip);
 580#endif
 581
 582        tbInfo.excludeList = exclude;
 583
 584        /* Read the directory/files and iterate over them one at a time */
 585        while (include) {
 586                if (!recursive_action(include->data, ACTION_RECURSE |
 587                                (dereferenceFlag ? ACTION_FOLLOWLINKS : 0),
 588                                writeFileToTarball, writeFileToTarball, &tbInfo, 0)
 589                ) {
 590                        errorFlag = TRUE;
 591                }
 592                include = include->link;
 593        }
 594        /* Write two empty blocks to the end of the archive */
 595        memset(block_buf, 0, 2*TAR_BLOCK_SIZE);
 596        xwrite(tbInfo.tarFd, block_buf, 2*TAR_BLOCK_SIZE);
 597
 598        /* To be pedantically correct, we would check if the tarball
 599         * is smaller than 20 tar blocks, and pad it if it was smaller,
 600         * but that isn't necessary for GNU tar interoperability, and
 601         * so is considered a waste of space */
 602
 603        /* Close so the child process (if any) will exit */
 604        close(tbInfo.tarFd);
 605
 606        /* Hang up the tools, close up shop, head home */
 607        if (ENABLE_FEATURE_CLEAN_UP)
 608                freeHardLinkInfo(&tbInfo.hlInfoHead);
 609
 610        if (errorFlag)
 611                bb_error_msg("error exit delayed from previous errors");
 612
 613#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
 614        if (gzip) {
 615                int status;
 616                if (safe_waitpid(-1, &status, 0) == -1)
 617                        bb_perror_msg("waitpid");
 618                else if (!WIFEXITED(status) || WEXITSTATUS(status))
 619                        /* gzip was killed or has exited with nonzero! */
 620                        errorFlag = TRUE;
 621        }
 622#endif
 623        return errorFlag;
 624}
 625#else
 626int writeTarFile(int tar_fd, int verboseFlag,
 627        int dereferenceFlag, const llist_t *include,
 628        const llist_t *exclude, int gzip);
 629#endif /* FEATURE_TAR_CREATE */
 630
 631#if ENABLE_FEATURE_TAR_FROM
 632static llist_t *append_file_list_to_list(llist_t *list)
 633{
 634        FILE *src_stream;
 635        char *line;
 636        llist_t *newlist = NULL;
 637
 638        while (list) {
 639                src_stream = xfopen_for_read(llist_pop(&list));
 640                while ((line = xmalloc_fgetline(src_stream)) != NULL) {
 641                        /* kill trailing '/' unless the string is just "/" */
 642                        char *cp = last_char_is(line, '/');
 643                        if (cp > line)
 644                                *cp = '\0';
 645                        llist_add_to(&newlist, line);
 646                }
 647                fclose(src_stream);
 648        }
 649        return newlist;
 650}
 651#else
 652# define append_file_list_to_list(x) 0
 653#endif
 654
 655#if ENABLE_FEATURE_SEAMLESS_Z
 656static char FAST_FUNC get_header_tar_Z(archive_handle_t *archive_handle)
 657{
 658        /* Can't lseek over pipes */
 659        archive_handle->seek = seek_by_read;
 660
 661        /* do the decompression, and cleanup */
 662        if (xread_char(archive_handle->src_fd) != 0x1f
 663         || xread_char(archive_handle->src_fd) != 0x9d
 664        ) {
 665                bb_error_msg_and_die("invalid magic");
 666        }
 667
 668        open_transformer(archive_handle->src_fd, unpack_Z_stream, "uncompress");
 669        archive_handle->offset = 0;
 670        while (get_header_tar(archive_handle) == EXIT_SUCCESS)
 671                continue;
 672
 673        /* Can only do one file at a time */
 674        return EXIT_FAILURE;
 675}
 676#else
 677# define get_header_tar_Z NULL
 678#endif
 679
 680#ifdef CHECK_FOR_CHILD_EXITCODE
 681/* Looks like it isn't needed - tar detects malformed (truncated)
 682 * archive if e.g. bunzip2 fails */
 683static int child_error;
 684
 685static void handle_SIGCHLD(int status)
 686{
 687        /* Actually, 'status' is a signo. We reuse it for other needs */
 688
 689        /* Wait for any child without blocking */
 690        if (wait_any_nohang(&status) < 0)
 691                /* wait failed?! I'm confused... */
 692                return;
 693
 694        if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
 695                /* child exited with 0 */
 696                return;
 697        /* Cannot happen?
 698        if (!WIFSIGNALED(status) && !WIFEXITED(status)) return; */
 699        child_error = 1;
 700}
 701#endif
 702
 703//usage:#define tar_trivial_usage
 704//usage:       "-[" IF_FEATURE_TAR_CREATE("c") "xt" IF_FEATURE_SEAMLESS_GZ("z")
 705//usage:        IF_FEATURE_SEAMLESS_BZ2("j") IF_FEATURE_SEAMLESS_LZMA("a")
 706//usage:        IF_FEATURE_SEAMLESS_Z("Z") IF_FEATURE_TAR_NOPRESERVE_TIME("m") "vO] "
 707//usage:        IF_FEATURE_TAR_FROM("[-X FILE] ")
 708//usage:       "[-f TARFILE] [-C DIR] [FILE]..."
 709//usage:#define tar_full_usage "\n\n"
 710//usage:        IF_FEATURE_TAR_CREATE("Create, extract, ")
 711//usage:        IF_NOT_FEATURE_TAR_CREATE("Extract ")
 712//usage:        "or list files from a tar file\n"
 713//usage:     "\nOperation:"
 714//usage:        IF_FEATURE_TAR_CREATE(
 715//usage:     "\n        c       Create"
 716//usage:        )
 717//usage:     "\n        x       Extract"
 718//usage:     "\n        t       List"
 719//usage:     "\nOptions:"
 720//usage:     "\n        f       Name of TARFILE ('-' for stdin/out)"
 721//usage:     "\n        C       Change to DIR before operation"
 722//usage:     "\n        v       Verbose"
 723//usage:        IF_FEATURE_SEAMLESS_GZ(
 724//usage:     "\n        z       (De)compress using gzip"
 725//usage:        )
 726//usage:        IF_FEATURE_SEAMLESS_BZ2(
 727//usage:     "\n        j       (De)compress using bzip2"
 728//usage:        )
 729//usage:        IF_FEATURE_SEAMLESS_LZMA(
 730//usage:     "\n        a       (De)compress using lzma"
 731//usage:        )
 732//usage:        IF_FEATURE_SEAMLESS_Z(
 733//usage:     "\n        Z       (De)compress using compress"
 734//usage:        )
 735//usage:     "\n        O       Extract to stdout"
 736//usage:        IF_FEATURE_TAR_CREATE(
 737//usage:     "\n        h       Follow symlinks"
 738//usage:        )
 739//usage:        IF_FEATURE_TAR_NOPRESERVE_TIME(
 740//usage:     "\n        m       Don't restore mtime"
 741//usage:        )
 742//usage:        IF_FEATURE_TAR_FROM(
 743//usage:        IF_FEATURE_TAR_LONG_OPTIONS(
 744//usage:     "\n        exclude File to exclude"
 745//usage:        )
 746//usage:     "\n        X       File with names to exclude"
 747//usage:     "\n        T       File with names to include"
 748//usage:        )
 749//usage:
 750//usage:#define tar_example_usage
 751//usage:       "$ zcat /tmp/tarball.tar.gz | tar -xf -\n"
 752//usage:       "$ tar -cf /tmp/tarball.tar /usr/local\n"
 753
 754// Supported but aren't in --help:
 755//      o       no-same-owner
 756//      p       same-permissions
 757//      k       keep-old
 758//      numeric-owner
 759//      no-same-permissions
 760//      overwrite
 761//IF_FEATURE_TAR_TO_COMMAND(
 762//      to-command
 763//)
 764
 765enum {
 766        OPTBIT_KEEP_OLD = 8,
 767        IF_FEATURE_TAR_CREATE(   OPTBIT_CREATE      ,)
 768        IF_FEATURE_TAR_CREATE(   OPTBIT_DEREFERENCE ,)
 769        IF_FEATURE_SEAMLESS_BZ2( OPTBIT_BZIP2       ,)
 770        IF_FEATURE_SEAMLESS_LZMA(OPTBIT_LZMA        ,)
 771        IF_FEATURE_TAR_FROM(     OPTBIT_INCLUDE_FROM,)
 772        IF_FEATURE_TAR_FROM(     OPTBIT_EXCLUDE_FROM,)
 773        IF_FEATURE_SEAMLESS_GZ(  OPTBIT_GZIP        ,)
 774        IF_FEATURE_SEAMLESS_Z(   OPTBIT_COMPRESS    ,) // 16th bit
 775        IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,)
 776#if ENABLE_FEATURE_TAR_LONG_OPTIONS
 777        IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND   ,)
 778        OPTBIT_NUMERIC_OWNER,
 779        OPTBIT_NOPRESERVE_PERM,
 780        OPTBIT_OVERWRITE,
 781#endif
 782        OPT_TEST         = 1 << 0, // t
 783        OPT_EXTRACT      = 1 << 1, // x
 784        OPT_BASEDIR      = 1 << 2, // C
 785        OPT_TARNAME      = 1 << 3, // f
 786        OPT_2STDOUT      = 1 << 4, // O
 787        OPT_NOPRESERVE_OWNER = 1 << 5, // o == no-same-owner
 788        OPT_P            = 1 << 6, // p
 789        OPT_VERBOSE      = 1 << 7, // v
 790        OPT_KEEP_OLD     = 1 << 8, // k
 791        OPT_CREATE       = IF_FEATURE_TAR_CREATE(   (1 << OPTBIT_CREATE      )) + 0, // c
 792        OPT_DEREFERENCE  = IF_FEATURE_TAR_CREATE(   (1 << OPTBIT_DEREFERENCE )) + 0, // h
 793        OPT_BZIP2        = IF_FEATURE_SEAMLESS_BZ2( (1 << OPTBIT_BZIP2       )) + 0, // j
 794        OPT_LZMA         = IF_FEATURE_SEAMLESS_LZMA((1 << OPTBIT_LZMA        )) + 0, // a
 795        OPT_INCLUDE_FROM = IF_FEATURE_TAR_FROM(     (1 << OPTBIT_INCLUDE_FROM)) + 0, // T
 796        OPT_EXCLUDE_FROM = IF_FEATURE_TAR_FROM(     (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X
 797        OPT_GZIP         = IF_FEATURE_SEAMLESS_GZ(  (1 << OPTBIT_GZIP        )) + 0, // z
 798        OPT_COMPRESS     = IF_FEATURE_SEAMLESS_Z(   (1 << OPTBIT_COMPRESS    )) + 0, // Z
 799        OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m
 800        OPT_2COMMAND        = IF_FEATURE_TAR_TO_COMMAND(  (1 << OPTBIT_2COMMAND       )) + 0, // to-command
 801        OPT_NUMERIC_OWNER   = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER  )) + 0, // numeric-owner
 802        OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
 803        OPT_OVERWRITE       = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE      )) + 0, // overwrite
 804};
 805#if ENABLE_FEATURE_TAR_LONG_OPTIONS
 806static const char tar_longopts[] ALIGN1 =
 807        "list\0"                No_argument       "t"
 808        "extract\0"             No_argument       "x"
 809        "directory\0"           Required_argument "C"
 810        "file\0"                Required_argument "f"
 811        "to-stdout\0"           No_argument       "O"
 812        /* do not restore owner */
 813        /* Note: GNU tar handles 'o' as no-same-owner only on extract,
 814         * on create, 'o' is --old-archive. We do not support --old-archive. */
 815        "no-same-owner\0"       No_argument       "o"
 816        "same-permissions\0"    No_argument       "p"
 817        "verbose\0"             No_argument       "v"
 818        "keep-old\0"            No_argument       "k"
 819# if ENABLE_FEATURE_TAR_CREATE
 820        "create\0"              No_argument       "c"
 821        "dereference\0"         No_argument       "h"
 822# endif
 823# if ENABLE_FEATURE_SEAMLESS_BZ2
 824        "bzip2\0"               No_argument       "j"
 825# endif
 826# if ENABLE_FEATURE_SEAMLESS_LZMA
 827        "lzma\0"                No_argument       "a"
 828# endif
 829# if ENABLE_FEATURE_TAR_FROM
 830        "files-from\0"          Required_argument "T"
 831        "exclude-from\0"        Required_argument "X"
 832# endif
 833# if ENABLE_FEATURE_SEAMLESS_GZ
 834        "gzip\0"                No_argument       "z"
 835# endif
 836# if ENABLE_FEATURE_SEAMLESS_Z
 837        "compress\0"            No_argument       "Z"
 838# endif
 839# if ENABLE_FEATURE_TAR_NOPRESERVE_TIME
 840        "touch\0"               No_argument       "m"
 841# endif
 842# if ENABLE_FEATURE_TAR_TO_COMMAND
 843        "to-command\0"          Required_argument "\xfb"
 844# endif
 845        /* use numeric uid/gid from tar header, not textual */
 846        "numeric-owner\0"       No_argument       "\xfc"
 847        /* do not restore mode */
 848        "no-same-permissions\0" No_argument       "\xfd"
 849        /* on unpack, open with O_TRUNC and !O_EXCL */
 850        "overwrite\0"           No_argument       "\xfe"
 851        /* --exclude takes next bit position in option mask, */
 852        /* therefore we have to put it _after_ --no-same-permissions */
 853# if ENABLE_FEATURE_TAR_FROM
 854        "exclude\0"             Required_argument "\xff"
 855# endif
 856        ;
 857#endif
 858
 859int tar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 860int tar_main(int argc UNUSED_PARAM, char **argv)
 861{
 862        char FAST_FUNC (*get_header_ptr)(archive_handle_t *) = get_header_tar;
 863        archive_handle_t *tar_handle;
 864        char *base_dir = NULL;
 865        const char *tar_filename = "-";
 866        unsigned opt;
 867        int verboseFlag = 0;
 868#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
 869        llist_t *excludes = NULL;
 870#endif
 871
 872        /* Initialise default values */
 873        tar_handle = init_handle();
 874        tar_handle->ah_flags = ARCHIVE_CREATE_LEADING_DIRS
 875                             | ARCHIVE_RESTORE_DATE
 876                             | ARCHIVE_UNLINK_OLD;
 877
 878        /* Apparently only root's tar preserves perms (see bug 3844) */
 879        if (getuid() != 0)
 880                tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_PERM;
 881
 882        /* Prepend '-' to the first argument if required */
 883        opt_complementary = "--:" // first arg is options
 884                "tt:vv:" // count -t,-v
 885                "?:" // bail out with usage instead of error return
 886                "X::T::" // cumulative lists
 887#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
 888                "\xff::" // cumulative lists for --exclude
 889#endif
 890                IF_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd
 891                IF_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive
 892                IF_NOT_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive
 893#if ENABLE_FEATURE_TAR_LONG_OPTIONS
 894        applet_long_options = tar_longopts;
 895#endif
 896#if ENABLE_DESKTOP
 897        if (argv[1] && argv[1][0] != '-') {
 898                /* Compat:
 899                 * 1st argument without dash handles options with parameters
 900                 * differently from dashed one: it takes *next argv[i]*
 901                 * as paramenter even if there are more chars in 1st argument:
 902                 *  "tar fx TARFILE" - "x" is not taken as f's param
 903                 *  but is interpreted as -x option
 904                 *  "tar -xf TARFILE" - dashed equivalent of the above
 905                 *  "tar -fx ..." - "x" is taken as f's param
 906                 * getopt32 wouldn't handle 1st command correctly.
 907                 * Unfortunately, people do use such commands.
 908                 * We massage argv[1] to work around it by moving 'f'
 909                 * to the end of the string.
 910                 * More contrived "tar fCx TARFILE DIR" still fails,
 911                 * but such commands are much less likely to be used.
 912                 */
 913                char *f = strchr(argv[1], 'f');
 914                if (f) {
 915                        while (f[1] != '\0') {
 916                                *f = f[1];
 917                                f++;
 918                        }
 919                        *f = 'f';
 920                }
 921        }
 922#endif
 923        opt = getopt32(argv,
 924                "txC:f:Oopvk"
 925                IF_FEATURE_TAR_CREATE(   "ch"  )
 926                IF_FEATURE_SEAMLESS_BZ2( "j"   )
 927                IF_FEATURE_SEAMLESS_LZMA("a"   )
 928                IF_FEATURE_TAR_FROM(     "T:X:")
 929                IF_FEATURE_SEAMLESS_GZ(  "z"   )
 930                IF_FEATURE_SEAMLESS_Z(   "Z"   )
 931                IF_FEATURE_TAR_NOPRESERVE_TIME("m")
 932                , &base_dir // -C dir
 933                , &tar_filename // -f filename
 934                IF_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T
 935                IF_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X
 936                IF_FEATURE_TAR_TO_COMMAND(, &(tar_handle->tar__to_command)) // --to-command
 937#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
 938                , &excludes // --exclude
 939#endif
 940                , &verboseFlag // combined count for -t and -v
 941                , &verboseFlag // combined count for -t and -v
 942                );
 943        //bb_error_msg("opt:%08x", opt);
 944        argv += optind;
 945
 946        if (verboseFlag) tar_handle->action_header = header_verbose_list;
 947        if (verboseFlag == 1) tar_handle->action_header = header_list;
 948
 949        if (opt & OPT_EXTRACT)
 950                tar_handle->action_data = data_extract_all;
 951
 952        if (opt & OPT_2STDOUT)
 953                tar_handle->action_data = data_extract_to_stdout;
 954
 955        if (opt & OPT_2COMMAND) {
 956                putenv((char*)"TAR_FILETYPE=f");
 957                signal(SIGPIPE, SIG_IGN);
 958                tar_handle->action_data = data_extract_to_command;
 959        }
 960
 961        if (opt & OPT_KEEP_OLD)
 962                tar_handle->ah_flags &= ~ARCHIVE_UNLINK_OLD;
 963
 964        if (opt & OPT_NUMERIC_OWNER)
 965                tar_handle->ah_flags |= ARCHIVE_NUMERIC_OWNER;
 966
 967        if (opt & OPT_NOPRESERVE_OWNER)
 968                tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_OWNER;
 969
 970        if (opt & OPT_NOPRESERVE_PERM)
 971                tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_PERM;
 972
 973        if (opt & OPT_OVERWRITE) {
 974                tar_handle->ah_flags &= ~ARCHIVE_UNLINK_OLD;
 975                tar_handle->ah_flags |= ARCHIVE_O_TRUNC;
 976        }
 977
 978        if (opt & OPT_GZIP)
 979                get_header_ptr = get_header_tar_gz;
 980
 981        if (opt & OPT_BZIP2)
 982                get_header_ptr = get_header_tar_bz2;
 983
 984        if (opt & OPT_LZMA)
 985                get_header_ptr = get_header_tar_lzma;
 986
 987        if (opt & OPT_COMPRESS)
 988                get_header_ptr = get_header_tar_Z;
 989
 990        if (opt & OPT_NOPRESERVE_TIME)
 991                tar_handle->ah_flags &= ~ARCHIVE_RESTORE_DATE;
 992
 993#if ENABLE_FEATURE_TAR_FROM
 994        tar_handle->reject = append_file_list_to_list(tar_handle->reject);
 995# if ENABLE_FEATURE_TAR_LONG_OPTIONS
 996        /* Append excludes to reject */
 997        while (excludes) {
 998                llist_t *next = excludes->link;
 999                excludes->link = tar_handle->reject;
1000                tar_handle->reject = excludes;
1001                excludes = next;
1002        }
1003# endif
1004        tar_handle->accept = append_file_list_to_list(tar_handle->accept);
1005#endif
1006
1007        /* Setup an array of filenames to work with */
1008        /* TODO: This is the same as in ar, make a separate function? */
1009        while (*argv) {
1010                /* kill trailing '/' unless the string is just "/" */
1011                char *cp = last_char_is(*argv, '/');
1012                if (cp > *argv)
1013                        *cp = '\0';
1014                llist_add_to_end(&tar_handle->accept, *argv);
1015                argv++;
1016        }
1017
1018        if (tar_handle->accept || tar_handle->reject)
1019                tar_handle->filter = filter_accept_reject_list;
1020
1021        /* Open the tar file */
1022        {
1023                int tar_fd = STDIN_FILENO;
1024                int flags = O_RDONLY;
1025
1026                if (opt & OPT_CREATE) {
1027                        /* Make sure there is at least one file to tar up */
1028                        if (tar_handle->accept == NULL)
1029                                bb_error_msg_and_die("empty archive");
1030
1031                        tar_fd = STDOUT_FILENO;
1032                        /* Mimicking GNU tar 1.15.1: */
1033                        flags = O_WRONLY | O_CREAT | O_TRUNC;
1034                }
1035
1036                if (LONE_DASH(tar_filename)) {
1037                        tar_handle->src_fd = tar_fd;
1038                        tar_handle->seek = seek_by_read;
1039                } else {
1040                        if (ENABLE_FEATURE_TAR_AUTODETECT
1041                         && flags == O_RDONLY
1042                         && get_header_ptr == get_header_tar
1043                        ) {
1044                                tar_handle->src_fd = open_zipped(tar_filename);
1045                                if (tar_handle->src_fd < 0)
1046                                        bb_perror_msg_and_die("can't open '%s'", tar_filename);
1047                        } else {
1048                                tar_handle->src_fd = xopen(tar_filename, flags);
1049                        }
1050                }
1051        }
1052
1053        if (base_dir)
1054                xchdir(base_dir);
1055
1056#ifdef CHECK_FOR_CHILD_EXITCODE
1057        /* We need to know whether child (gzip/bzip/etc) exits abnormally */
1058        signal(SIGCHLD, handle_SIGCHLD);
1059#endif
1060
1061        /* Create an archive */
1062        if (opt & OPT_CREATE) {
1063#if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
1064                int zipMode = 0;
1065                if (ENABLE_FEATURE_SEAMLESS_GZ && (opt & OPT_GZIP))
1066                        zipMode = 1;
1067                if (ENABLE_FEATURE_SEAMLESS_BZ2 && (opt & OPT_BZIP2))
1068                        zipMode = 2;
1069#endif
1070                /* NB: writeTarFile() closes tar_handle->src_fd */
1071                return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE,
1072                                tar_handle->accept,
1073                                tar_handle->reject, zipMode);
1074        }
1075
1076        while (get_header_ptr(tar_handle) == EXIT_SUCCESS)
1077                continue;
1078
1079        /* Check that every file that should have been extracted was */
1080        while (tar_handle->accept) {
1081                if (!find_list_entry(tar_handle->reject, tar_handle->accept->data)
1082                 && !find_list_entry(tar_handle->passed, tar_handle->accept->data)
1083                ) {
1084                        bb_error_msg_and_die("%s: not found in archive",
1085                                tar_handle->accept->data);
1086                }
1087                tar_handle->accept = tar_handle->accept->link;
1088        }
1089        if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */)
1090                close(tar_handle->src_fd);
1091
1092        return EXIT_SUCCESS;
1093}
1094