X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=archival%2Ftar.c;h=280ded4e14e325811e2cf976a050bac6e7ba4b27;hb=619d9b5e6848a72350126ea9c1e413fd133181e3;hp=caf4363dea69f63cae561d5623c5890f65160061;hpb=e6a2f4cc5a47d3022bdf5ca2cacbaa5a8c5baf7a;p=oweals%2Fbusybox.git diff --git a/archival/tar.c b/archival/tar.c index caf4363de..280ded4e1 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -22,124 +22,95 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -/* TODO: security with -C DESTDIR option can be enhanced. - * Consider tar file created via: - * $ tar cvf bug.tar anything.txt - * $ ln -s /tmp symlink - * $ tar --append -f bug.tar symlink - * $ rm symlink - * $ mkdir symlink - * $ tar --append -f bug.tar symlink/evil.py - * - * This will result in an archive which contains: - * $ tar --list -f bug.tar - * anything.txt - * symlink - * symlink/evil.py - * - * Untarring it puts evil.py in '/tmp' even if the -C DESTDIR is given. - * This doesn't feel right, and IIRC GNU tar doesn't do that. - */ //config:config TAR -//config: bool "tar" +//config: bool "tar (40 kb)" //config: default y //config: help -//config: tar is an archiving program. It's commonly used with gzip to -//config: create compressed archives. It's probably the most widely used -//config: UNIX archive program. +//config: tar is an archiving program. It's commonly used with gzip to +//config: create compressed archives. It's probably the most widely used +//config: UNIX archive program. +//config: +//config:config FEATURE_TAR_LONG_OPTIONS +//config: bool "Enable long options" +//config: default y +//config: depends on TAR && LONG_OPTS //config: //config:config FEATURE_TAR_CREATE -//config: bool "Enable archive creation" +//config: bool "Enable -c (archive creation)" //config: default y //config: depends on TAR -//config: help -//config: If you enable this option you'll be able to create -//config: tar archives using the `-c' option. //config: //config:config FEATURE_TAR_AUTODETECT //config: bool "Autodetect compressed tarballs" //config: default y //config: depends on TAR && (FEATURE_SEAMLESS_Z || FEATURE_SEAMLESS_GZ || FEATURE_SEAMLESS_BZ2 || FEATURE_SEAMLESS_LZMA || FEATURE_SEAMLESS_XZ) //config: help -//config: With this option tar can automatically detect compressed -//config: tarballs. Currently it works only on files (not pipes etc). +//config: With this option tar can automatically detect compressed +//config: tarballs. Currently it works only on files (not pipes etc). //config: //config:config FEATURE_TAR_FROM //config: bool "Enable -X (exclude from) and -T (include from) options)" //config: default y //config: depends on TAR //config: help -//config: If you enable this option you'll be able to specify -//config: a list of files to include or exclude from an archive. +//config: If you enable this option you'll be able to specify +//config: a list of files to include or exclude from an archive. //config: //config:config FEATURE_TAR_OLDGNU_COMPATIBILITY -//config: bool "Support for old tar header format" +//config: bool "Support old tar header format" //config: default y //config: depends on TAR || DPKG //config: help -//config: This option is required to unpack archives created in -//config: the old GNU format; help to kill this old format by -//config: repacking your ancient archives with the new format. +//config: This option is required to unpack archives created in +//config: the old GNU format; help to kill this old format by +//config: repacking your ancient archives with the new format. //config: //config:config FEATURE_TAR_OLDSUN_COMPATIBILITY //config: bool "Enable untarring of tarballs with checksums produced by buggy Sun tar" //config: default y //config: depends on TAR || DPKG //config: help -//config: This option is required to unpack archives created by some old -//config: version of Sun's tar (it was calculating checksum using signed -//config: arithmetic). It is said to be fixed in newer Sun tar, but "old" -//config: tarballs still exist. +//config: This option is required to unpack archives created by some old +//config: version of Sun's tar (it was calculating checksum using signed +//config: arithmetic). It is said to be fixed in newer Sun tar, but "old" +//config: tarballs still exist. //config: //config:config FEATURE_TAR_GNU_EXTENSIONS -//config: bool "Support for GNU tar extensions (long filenames)" +//config: bool "Support GNU tar extensions (long filenames)" //config: default y //config: depends on TAR || DPKG -//config: help -//config: With this option busybox supports GNU long filenames and -//config: linknames. -//config: -//config:config FEATURE_TAR_LONG_OPTIONS -//config: bool "Enable long options" -//config: default y -//config: depends on TAR && LONG_OPTS -//config: help -//config: Enable use of long options, increases size by about 400 Bytes //config: //config:config FEATURE_TAR_TO_COMMAND -//config: bool "Support for writing to an external program" +//config: bool "Support writing to an external program (--to-command)" //config: default y //config: depends on TAR && FEATURE_TAR_LONG_OPTIONS //config: help -//config: If you enable this option you'll be able to instruct tar to send -//config: the contents of each extracted file to the standard input of an -//config: external program. +//config: If you enable this option you'll be able to instruct tar to send +//config: the contents of each extracted file to the standard input of an +//config: external program. //config: //config:config FEATURE_TAR_UNAME_GNAME //config: bool "Enable use of user and group names" //config: default y //config: depends on TAR //config: help -//config: Enables use of user and group names in tar. This affects contents -//config: listings (-t) and preserving permissions when unpacking (-p). -//config: +200 bytes. +//config: Enable use of user and group names in tar. This affects contents +//config: listings (-t) and preserving permissions when unpacking (-p). +//config: +200 bytes. //config: //config:config FEATURE_TAR_NOPRESERVE_TIME -//config: bool "Enable -m (do not preserve time) option" +//config: bool "Enable -m (do not preserve time) GNU option" //config: default y //config: depends on TAR -//config: help -//config: With this option busybox supports GNU tar -m -//config: (do not preserve time) option. //config: //config:config FEATURE_TAR_SELINUX -//config: bool "Support for extracting SELinux labels" +//config: bool "Support extracting SELinux labels" //config: default n //config: depends on TAR && SELINUX //config: help -//config: With this option busybox supports restoring SELinux labels -//config: when extracting files from tar archives. +//config: With this option busybox supports restoring SELinux labels +//config: when extracting files from tar archives. //applet:IF_TAR(APPLET(tar, BB_DIR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_TAR) += tar.o @@ -162,6 +133,7 @@ #define block_buf bb_common_bufsiz1 +#define INIT_G() do { setup_common_bufsiz(); } while (0) #if ENABLE_FEATURE_TAR_CREATE @@ -306,6 +278,23 @@ static void chksum_and_xwrite(int fd, struct tar_header_t* hp) xwrite(fd, hp, sizeof(*hp)); } +static void replace_symlink_placeholders(llist_t *list) +{ + while (list) { + char *target; + + target = list->data + strlen(list->data) + 1; + if (symlink(target, list->data)) { + /* shared message */ + bb_error_msg_and_die("can't create %slink '%s' to '%s'", + "sym", + list->data, target + ); + } + list = list->link; + } +} + #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS static void writeLongname(int fd, int type, const char *name, int dir) { @@ -539,8 +528,8 @@ static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statb /* * Check to see if we are dealing with a hard link. * If so - - * Treat the first occurance of a given dev/inode as a file while - * treating any additional occurances as hard links. This is done + * Treat the first occurrence of a given dev/inode as a file while + * treating any additional occurrences as hard links. This is done * by adding the file information to the HardLinkInfo linked list. */ tbInfo->hlInfo = NULL; @@ -964,6 +953,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM llist_t *excludes = NULL; #endif + INIT_G(); /* Initialise default values */ tar_handle = init_handle(); @@ -978,7 +968,6 @@ int tar_main(int argc UNUSED_PARAM, char **argv) /* Prepend '-' to the first argument if required */ opt_complementary = "--:" // first arg is options "tt:vv:" // count -t,-v - IF_FEATURE_TAR_FROM("X::T::") // cumulative lists #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM "\xff::" // --exclude=PATTERN is a list #endif @@ -1030,13 +1019,13 @@ int tar_main(int argc UNUSED_PARAM, char **argv) #endif opt = getopt32(argv, "txC:f:Oopvk" - IF_FEATURE_TAR_CREATE( "ch" ) - IF_FEATURE_SEAMLESS_BZ2( "j" ) - IF_FEATURE_SEAMLESS_LZMA("a" ) - IF_FEATURE_TAR_FROM( "T:X:") - IF_FEATURE_SEAMLESS_GZ( "z" ) - IF_FEATURE_SEAMLESS_XZ( "J" ) - IF_FEATURE_SEAMLESS_Z( "Z" ) + IF_FEATURE_TAR_CREATE( "ch" ) + IF_FEATURE_SEAMLESS_BZ2( "j" ) + IF_FEATURE_SEAMLESS_LZMA("a" ) + IF_FEATURE_TAR_FROM( "T:*X:*") + IF_FEATURE_SEAMLESS_GZ( "z" ) + IF_FEATURE_SEAMLESS_XZ( "J" ) + IF_FEATURE_SEAMLESS_Z( "Z" ) IF_FEATURE_TAR_NOPRESERVE_TIME("m") IF_FEATURE_TAR_LONG_OPTIONS("\xf9:") // --strip-components , &base_dir // -C dir @@ -1197,9 +1186,10 @@ int tar_main(int argc UNUSED_PARAM, char **argv) // /* We need to know whether child (gzip/bzip/etc) exits abnormally */ // signal(SIGCHLD, check_errors_in_children); +#if ENABLE_FEATURE_TAR_CREATE /* Create an archive */ if (opt & OPT_CREATE) { -#if SEAMLESS_COMPRESSION +# if SEAMLESS_COMPRESSION const char *zipMode = NULL; if (opt & OPT_COMPRESS) zipMode = "compress"; @@ -1211,7 +1201,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) zipMode = "lzma"; if (opt & OPT_XZ) zipMode = "xz"; -#endif +# endif /* NB: writeTarFile() closes tar_handle->src_fd */ return writeTarFile(tar_handle->src_fd, verboseFlag, (opt & OPT_DEREFERENCE ? ACTION_FOLLOWLINKS : 0) @@ -1219,26 +1209,32 @@ int tar_main(int argc UNUSED_PARAM, char **argv) tar_handle->accept, tar_handle->reject, zipMode); } +#endif if (opt & OPT_ANY_COMPRESS) { USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_state_t *xstate);) USE_FOR_NOMMU(const char *xformer_prog;) - if (opt & OPT_COMPRESS) - USE_FOR_MMU(xformer = unpack_Z_stream;) + if (opt & OPT_COMPRESS) { + USE_FOR_MMU(IF_FEATURE_SEAMLESS_Z(xformer = unpack_Z_stream;)) USE_FOR_NOMMU(xformer_prog = "uncompress";) - if (opt & OPT_GZIP) - USE_FOR_MMU(xformer = unpack_gz_stream;) + } + if (opt & OPT_GZIP) { + USE_FOR_MMU(IF_FEATURE_SEAMLESS_GZ(xformer = unpack_gz_stream;)) USE_FOR_NOMMU(xformer_prog = "gunzip";) - if (opt & OPT_BZIP2) - USE_FOR_MMU(xformer = unpack_bz2_stream;) + } + if (opt & OPT_BZIP2) { + USE_FOR_MMU(IF_FEATURE_SEAMLESS_BZ2(xformer = unpack_bz2_stream;)) USE_FOR_NOMMU(xformer_prog = "bunzip2";) - if (opt & OPT_LZMA) - USE_FOR_MMU(xformer = unpack_lzma_stream;) + } + if (opt & OPT_LZMA) { + USE_FOR_MMU(IF_FEATURE_SEAMLESS_LZMA(xformer = unpack_lzma_stream;)) USE_FOR_NOMMU(xformer_prog = "unlzma";) - if (opt & OPT_XZ) - USE_FOR_MMU(xformer = unpack_xz_stream;) + } + if (opt & OPT_XZ) { + USE_FOR_MMU(IF_FEATURE_SEAMLESS_XZ(xformer = unpack_xz_stream;)) USE_FOR_NOMMU(xformer_prog = "unxz";) + } fork_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); /* Can't lseek over pipes */ @@ -1255,6 +1251,8 @@ int tar_main(int argc UNUSED_PARAM, char **argv) while (get_header_tar(tar_handle) == EXIT_SUCCESS) bb_got_signal = EXIT_SUCCESS; /* saw at least one header, good */ + replace_symlink_placeholders(tar_handle->symlink_placeholders); + /* Check that every file that should have been extracted was */ while (tar_handle->accept) { if (!find_list_entry(tar_handle->reject, tar_handle->accept->data)