Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/archival/tar.c


Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/3.3/mindi-busybox/archival/tar.c

    r3232 r3621  
    2323 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    2424 */
    25 
    2625/* TODO: security with -C DESTDIR option can be enhanced.
    2726 * Consider tar file created via:
     
    4342 */
    4443
     44//config:config TAR
     45//config:   bool "tar"
     46//config:   default y
     47//config:   help
     48//config:     tar is an archiving program. It's commonly used with gzip to
     49//config:     create compressed archives. It's probably the most widely used
     50//config:     UNIX archive program.
     51//config:
     52//config:config FEATURE_TAR_CREATE
     53//config:   bool "Enable archive creation"
     54//config:   default y
     55//config:   depends on TAR
     56//config:   help
     57//config:     If you enable this option you'll be able to create
     58//config:     tar archives using the `-c' option.
     59//config:
     60//config:config FEATURE_TAR_AUTODETECT
     61//config:   bool "Autodetect compressed tarballs"
     62//config:   default y
     63//config:   depends on TAR && (FEATURE_SEAMLESS_Z || FEATURE_SEAMLESS_GZ || FEATURE_SEAMLESS_BZ2 || FEATURE_SEAMLESS_LZMA || FEATURE_SEAMLESS_XZ)
     64//config:   help
     65//config:     With this option tar can automatically detect compressed
     66//config:     tarballs. Currently it works only on files (not pipes etc).
     67//config:
     68//config:config FEATURE_TAR_FROM
     69//config:   bool "Enable -X (exclude from) and -T (include from) options)"
     70//config:   default y
     71//config:   depends on TAR
     72//config:   help
     73//config:     If you enable this option you'll be able to specify
     74//config:     a list of files to include or exclude from an archive.
     75//config:
     76//config:config FEATURE_TAR_OLDGNU_COMPATIBILITY
     77//config:   bool "Support for old tar header format"
     78//config:   default y
     79//config:   depends on TAR || DPKG
     80//config:   help
     81//config:     This option is required to unpack archives created in
     82//config:     the old GNU format; help to kill this old format by
     83//config:     repacking your ancient archives with the new format.
     84//config:
     85//config:config FEATURE_TAR_OLDSUN_COMPATIBILITY
     86//config:   bool "Enable untarring of tarballs with checksums produced by buggy Sun tar"
     87//config:   default y
     88//config:   depends on TAR || DPKG
     89//config:   help
     90//config:     This option is required to unpack archives created by some old
     91//config:     version of Sun's tar (it was calculating checksum using signed
     92//config:     arithmetic). It is said to be fixed in newer Sun tar, but "old"
     93//config:     tarballs still exist.
     94//config:
     95//config:config FEATURE_TAR_GNU_EXTENSIONS
     96//config:   bool "Support for GNU tar extensions (long filenames)"
     97//config:   default y
     98//config:   depends on TAR || DPKG
     99//config:   help
     100//config:     With this option busybox supports GNU long filenames and
     101//config:     linknames.
     102//config:
     103//config:config FEATURE_TAR_LONG_OPTIONS
     104//config:   bool "Enable long options"
     105//config:   default y
     106//config:   depends on TAR && LONG_OPTS
     107//config:   help
     108//config:     Enable use of long options, increases size by about 400 Bytes
     109//config:
     110//config:config FEATURE_TAR_TO_COMMAND
     111//config:   bool "Support for writing to an external program"
     112//config:   default y
     113//config:   depends on TAR && FEATURE_TAR_LONG_OPTIONS
     114//config:   help
     115//config:     If you enable this option you'll be able to instruct tar to send
     116//config:     the contents of each extracted file to the standard input of an
     117//config:     external program.
     118//config:
     119//config:config FEATURE_TAR_UNAME_GNAME
     120//config:   bool "Enable use of user and group names"
     121//config:   default y
     122//config:   depends on TAR
     123//config:   help
     124//config:     Enables use of user and group names in tar. This affects contents
     125//config:     listings (-t) and preserving permissions when unpacking (-p).
     126//config:     +200 bytes.
     127//config:
     128//config:config FEATURE_TAR_NOPRESERVE_TIME
     129//config:   bool "Enable -m (do not preserve time) option"
     130//config:   default y
     131//config:   depends on TAR
     132//config:   help
     133//config:     With this option busybox supports GNU tar -m
     134//config:     (do not preserve time) option.
     135//config:
     136//config:config FEATURE_TAR_SELINUX
     137//config:   bool "Support for extracting SELinux labels"
     138//config:   default n
     139//config:   depends on TAR && SELINUX
     140//config:   help
     141//config:     With this option busybox supports restoring SELinux labels
     142//config:     when extracting files from tar archives.
     143
     144//applet:IF_TAR(APPLET(tar, BB_DIR_BIN, BB_SUID_DROP))
     145//kbuild:lib-$(CONFIG_TAR) += tar.o
     146
    45147#include <fnmatch.h>
    46148#include "libbb.h"
     149#include "common_bufsiz.h"
    47150#include "bb_archive.h"
    48151/* FIXME: Stop using this non-standard feature */
     
    51154#endif
    52155
    53 
    54 //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
    55 #define DBG(...) ((void)0)
     156#if 0
     157# define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
     158#else
     159# define DBG(...) ((void)0)
     160#endif
     161#define DBG_OPTION_PARSING 0
    56162
    57163
    58164#define block_buf bb_common_bufsiz1
    59 
    60 
    61 #if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2
    62 /* Do not pass gzip flag to writeTarFile() */
    63 #define writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude, gzip) \
    64     writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude)
    65 #endif
     165#define INIT_G() do { setup_common_bufsiz(); } while (0)
    66166
    67167
     
    520620}
    521621
    522 #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
    523 # if !(ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2)
    524 #  define vfork_compressor(tar_fd, gzip) vfork_compressor(tar_fd)
    525 # endif
     622#if SEAMLESS_COMPRESSION
    526623/* Don't inline: vfork scares gcc and pessimizes code */
    527 static void NOINLINE vfork_compressor(int tar_fd, int gzip)
     624static void NOINLINE vfork_compressor(int tar_fd, const char *gzip)
    528625{
    529626    pid_t gzipPid;
    530 # if ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2
    531     const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
    532 # elif ENABLE_FEATURE_SEAMLESS_GZ
    533     const char *zip_exec = "gzip";
    534 # else /* only ENABLE_FEATURE_SEAMLESS_BZ2 */
    535     const char *zip_exec = "bzip2";
    536 # endif
     627
    537628    // On Linux, vfork never unpauses parent early, although standard
    538629    // allows for that. Do we want to waste bytes checking for it?
     
    547638
    548639    signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
    549 
    550 # if defined(__GNUC__) && __GNUC__
    551     /* Avoid vfork clobbering */
    552     (void) &zip_exec;
    553 # endif
    554640
    555641    gzipPid = xvfork();
     
    568654        xmove_fd(tar_fd, 1);
    569655        /* exec gzip/bzip2 program/applet */
    570         BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
     656        BB_EXECLP(gzip, gzip, "-f", (char *)0);
    571657        vfork_exec_errno = errno;
    572658        _exit(EXIT_FAILURE);
     
    591677    if (vfork_exec_errno) {
    592678        errno = vfork_exec_errno;
    593         bb_perror_msg_and_die("can't execute '%s'", zip_exec);
     679        bb_perror_msg_and_die("can't execute '%s'", gzip);
    594680    }
    595681}
    596 #endif /* ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 */
    597 
    598 
     682#endif /* SEAMLESS_COMPRESSION */
     683
     684
     685#if !SEAMLESS_COMPRESSION
     686/* Do not pass gzip flag to writeTarFile() */
     687#define writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude, gzip) \
     688    writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude)
     689#endif
    599690/* gcc 4.2.1 inlines it, making code bigger */
    600691static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
    601692    int recurseFlags, const llist_t *include,
    602     const llist_t *exclude, int gzip)
     693    const llist_t *exclude, const char *gzip)
    603694{
    604695    int errorFlag = FALSE;
     
    613704    xfstat(tbInfo.tarFd, &tbInfo.tarFileStatBuf, "can't stat tar file");
    614705
    615 #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
     706#if SEAMLESS_COMPRESSION
    616707    if (gzip)
    617708        vfork_compressor(tbInfo.tarFd, gzip);
     
    648739        bb_error_msg("error exit delayed from previous errors");
    649740
    650 #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
     741#if SEAMLESS_COMPRESSION
    651742    if (gzip) {
    652743        int status;
     
    660751    return errorFlag;
    661752}
    662 #else
    663 int writeTarFile(int tar_fd, int verboseFlag,
    664     int recurseFlags, const llist_t *include,
    665     const llist_t *exclude, int gzip);
    666 #endif /* FEATURE_TAR_CREATE */
     753#else /* !FEATURE_TAR_CREATE */
     754# define writeTarFile(...) 0
     755#endif
    667756
    668757#if ENABLE_FEATURE_TAR_FROM
     
    680769            if (cp > line)
    681770                *cp = '\0';
    682             llist_add_to(&newlist, line);
     771            llist_add_to_end(&newlist, line);
    683772        }
    684773        fclose(src_stream);
     
    686775    return newlist;
    687776}
    688 #else
    689 # define append_file_list_to_list(x) 0
    690777#endif
    691778
     
    774861    IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,)
    775862#if ENABLE_FEATURE_TAR_LONG_OPTIONS
     863    OPTBIT_STRIP_COMPONENTS,
    776864    OPTBIT_NORECURSION,
    777865    IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND   ,)
     
    798886    OPT_XZ           = IF_FEATURE_SEAMLESS_XZ(  (1 << OPTBIT_XZ          )) + 0, // J
    799887    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_NORECURSION     = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NORECURSION    )) + 0, // no-recursion
    802     OPT_2COMMAND        = IF_FEATURE_TAR_TO_COMMAND(  (1 << OPTBIT_2COMMAND       )) + 0, // to-command
    803     OPT_NUMERIC_OWNER   = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER  )) + 0, // numeric-owner
    804     OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
    805     OPT_OVERWRITE       = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE      )) + 0, // overwrite
     888    OPT_NOPRESERVE_TIME  = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m
     889    OPT_STRIP_COMPONENTS = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_STRIP_COMPONENTS)) + 0, // strip-components
     890    OPT_NORECURSION      = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NORECURSION    )) + 0, // no-recursion
     891    OPT_2COMMAND         = IF_FEATURE_TAR_TO_COMMAND(  (1 << OPTBIT_2COMMAND       )) + 0, // to-command
     892    OPT_NUMERIC_OWNER    = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER  )) + 0, // numeric-owner
     893    OPT_NOPRESERVE_PERM  = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
     894    OPT_OVERWRITE        = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE      )) + 0, // overwrite
    806895
    807896    OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_XZ | OPT_COMPRESS),
     
    847936    "touch\0"               No_argument       "m"
    848937# endif
     938    "strip-components\0"    Required_argument "\xf9"
    849939    "no-recursion\0"    No_argument       "\xfa"
    850940# if ENABLE_FEATURE_TAR_TO_COMMAND
     
    876966    llist_t *excludes = NULL;
    877967#endif
     968    INIT_G();
    878969
    879970    /* Initialise default values */
     
    892983        IF_FEATURE_TAR_FROM("X::T::") // cumulative lists
    893984#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
    894         "\xff::" // cumulative lists for --exclude
     985        "\xff::" // --exclude=PATTERN is a list
    895986#endif
    896987        IF_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd
    897988        IF_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive
    898         IF_NOT_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive
     989        IF_NOT_FEATURE_TAR_CREATE("t--x:x--t") // mutually exclusive
     990#if ENABLE_FEATURE_TAR_LONG_OPTIONS
     991        ":\xf9+" // --strip-components=NUM
     992#endif
     993    ;
    899994#if ENABLE_FEATURE_TAR_LONG_OPTIONS
    900995    applet_long_options = tar_longopts;
    901996#endif
    902997#if ENABLE_DESKTOP
     998    /* Lie to buildroot when it starts asking stupid questions. */
     999    if (argv[1] && strcmp(argv[1], "--version") == 0) {
     1000        // Output of 'tar --version' examples:
     1001        // tar (GNU tar) 1.15.1
     1002        // tar (GNU tar) 1.25
     1003        // bsdtar 2.8.3 - libarchive 2.8.3
     1004        puts("tar (busybox) " BB_VER);
     1005        return 0;
     1006    }
    9031007    if (argv[1] && argv[1][0] != '-') {
    9041008        /* Compat:
     
    9371041        IF_FEATURE_SEAMLESS_Z(   "Z"   )
    9381042        IF_FEATURE_TAR_NOPRESERVE_TIME("m")
     1043        IF_FEATURE_TAR_LONG_OPTIONS("\xf9:") // --strip-components
    9391044        , &base_dir // -C dir
    9401045        , &tar_filename // -f filename
    9411046        IF_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T
    9421047        IF_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X
     1048#if ENABLE_FEATURE_TAR_LONG_OPTIONS
     1049        , &tar_handle->tar__strip_components // --strip-components
     1050#endif
    9431051        IF_FEATURE_TAR_TO_COMMAND(, &(tar_handle->tar__to_command)) // --to-command
    9441052#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
     
    9481056        , &verboseFlag // combined count for -t and -v
    9491057        );
    950     //bb_error_msg("opt:%08x", opt);
     1058#if DBG_OPTION_PARSING
     1059    bb_error_msg("opt: 0x%08x", opt);
     1060# define showopt(o) bb_error_msg("opt & %s(%x): %x", #o, o, opt & o);
     1061    showopt(OPT_TEST            );
     1062    showopt(OPT_EXTRACT         );
     1063    showopt(OPT_BASEDIR         );
     1064    showopt(OPT_TARNAME         );
     1065    showopt(OPT_2STDOUT         );
     1066    showopt(OPT_NOPRESERVE_OWNER);
     1067    showopt(OPT_P               );
     1068    showopt(OPT_VERBOSE         );
     1069    showopt(OPT_KEEP_OLD        );
     1070    showopt(OPT_CREATE          );
     1071    showopt(OPT_DEREFERENCE     );
     1072    showopt(OPT_BZIP2           );
     1073    showopt(OPT_LZMA            );
     1074    showopt(OPT_INCLUDE_FROM    );
     1075    showopt(OPT_EXCLUDE_FROM    );
     1076    showopt(OPT_GZIP            );
     1077    showopt(OPT_XZ              );
     1078    showopt(OPT_COMPRESS        );
     1079    showopt(OPT_NOPRESERVE_TIME );
     1080    showopt(OPT_STRIP_COMPONENTS);
     1081    showopt(OPT_NORECURSION     );
     1082    showopt(OPT_2COMMAND        );
     1083    showopt(OPT_NUMERIC_OWNER   );
     1084    showopt(OPT_NOPRESERVE_PERM );
     1085    showopt(OPT_OVERWRITE       );
     1086    showopt(OPT_ANY_COMPRESS    );
     1087    bb_error_msg("base_dir:'%s'", base_dir);
     1088    bb_error_msg("tar_filename:'%s'", tar_filename);
     1089    bb_error_msg("verboseFlag:%d", verboseFlag);
     1090    bb_error_msg("tar_handle->tar__to_command:'%s'", tar_handle->tar__to_command);
     1091    bb_error_msg("tar_handle->tar__strip_components:%u", tar_handle->tar__strip_components);
     1092    return 0;
     1093# undef showopt
     1094#endif
    9511095    argv += optind;
    9521096
    953     if (verboseFlag) tar_handle->action_header = header_verbose_list;
    954     if (verboseFlag == 1) tar_handle->action_header = header_list;
     1097    if (verboseFlag)
     1098        tar_handle->action_header = header_verbose_list;
     1099    if (verboseFlag == 1)
     1100        tar_handle->action_header = header_list;
    9551101
    9561102    if (opt & OPT_EXTRACT)
     
    10381184             && !(opt & OPT_ANY_COMPRESS)
    10391185            ) {
    1040                 tar_handle->src_fd = open_zipped(tar_filename);
     1186                tar_handle->src_fd = open_zipped(tar_filename, /*fail_if_not_compressed:*/ 0);
    10411187                if (tar_handle->src_fd < 0)
    10421188                    bb_perror_msg_and_die("can't open '%s'", tar_filename);
     
    10501196        xchdir(base_dir);
    10511197
    1052     //if (SEAMLESS_COMPRESSION || OPT_COMPRESS)
     1198    //if (SEAMLESS_COMPRESSION)
    10531199    //  /* We need to know whether child (gzip/bzip/etc) exits abnormally */
    10541200    //  signal(SIGCHLD, check_errors_in_children);
    10551201
     1202#if ENABLE_FEATURE_TAR_CREATE
    10561203    /* Create an archive */
    10571204    if (opt & OPT_CREATE) {
    1058 #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
    1059         int zipMode = 0;
    1060         if (ENABLE_FEATURE_SEAMLESS_GZ && (opt & OPT_GZIP))
    1061             zipMode = 1;
    1062         if (ENABLE_FEATURE_SEAMLESS_BZ2 && (opt & OPT_BZIP2))
    1063             zipMode = 2;
    1064 #endif
     1205# if SEAMLESS_COMPRESSION
     1206        const char *zipMode = NULL;
     1207        if (opt & OPT_COMPRESS)
     1208            zipMode = "compress";
     1209        if (opt & OPT_GZIP)
     1210            zipMode = "gzip";
     1211        if (opt & OPT_BZIP2)
     1212            zipMode = "bzip2";
     1213        if (opt & OPT_LZMA)
     1214            zipMode = "lzma";
     1215        if (opt & OPT_XZ)
     1216            zipMode = "xz";
     1217# endif
    10651218        /* NB: writeTarFile() closes tar_handle->src_fd */
    10661219        return writeTarFile(tar_handle->src_fd, verboseFlag,
     
    10701223                tar_handle->reject, zipMode);
    10711224    }
     1225#endif
    10721226
    10731227    if (opt & OPT_ANY_COMPRESS) {
    1074         USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);)
     1228        USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate);)
    10751229        USE_FOR_NOMMU(const char *xformer_prog;)
    10761230
     
    10911245            USE_FOR_NOMMU(xformer_prog = "unxz";)
    10921246
    1093         open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog);
     1247        fork_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog);
    10941248        /* Can't lseek over pipes */
    10951249        tar_handle->seek = seek_by_read;
     
    10971251    }
    10981252
     1253    /* Zero processed headers (== empty file) is not a valid tarball.
     1254     * We (ab)use bb_got_signal as exitcode here,
     1255     * because check_errors_in_children() uses _it_ as error indicator.
     1256     */
     1257    bb_got_signal = EXIT_FAILURE;
     1258
    10991259    while (get_header_tar(tar_handle) == EXIT_SUCCESS)
    1100         continue;
     1260        bb_got_signal = EXIT_SUCCESS; /* saw at least one header, good */
    11011261
    11021262    /* Check that every file that should have been extracted was */
     
    11141274
    11151275    if (SEAMLESS_COMPRESSION || OPT_COMPRESS) {
     1276        /* Set bb_got_signal to 1 if a child died with !0 exitcode */
    11161277        check_errors_in_children(0);
    1117         return bb_got_signal;
    1118     }
    1119     return EXIT_SUCCESS;
     1278    }
     1279
     1280    return bb_got_signal;
    11201281}
Note: See TracChangeset for help on using the changeset viewer.