Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/archival/tar.c
- Timestamp:
- Jan 1, 2014, 12:47:38 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.2/mindi-busybox/archival/tar.c
r2725 r3232 24 24 */ 25 25 26 /* TODO: security with -C DESTDIR option can be enhanced. 27 * Consider tar file created via: 28 * $ tar cvf bug.tar anything.txt 29 * $ ln -s /tmp symlink 30 * $ tar --append -f bug.tar symlink 31 * $ rm symlink 32 * $ mkdir symlink 33 * $ tar --append -f bug.tar symlink/evil.py 34 * 35 * This will result in an archive which contains: 36 * $ tar --list -f bug.tar 37 * anything.txt 38 * symlink 39 * symlink/evil.py 40 * 41 * Untarring it puts evil.py in '/tmp' even if the -C DESTDIR is given. 42 * This doesn't feel right, and IIRC GNU tar doesn't do that. 43 */ 44 26 45 #include <fnmatch.h> 27 46 #include "libbb.h" 28 #include " archive.h"47 #include "bb_archive.h" 29 48 /* FIXME: Stop using this non-standard feature */ 30 49 #ifndef FNM_LEADING_DIR … … 42 61 #if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2 43 62 /* 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)63 #define writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude, gzip) \ 64 writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude) 46 65 #endif 47 66 … … 246 265 PUT_OCTAL(header.gid, statbuf->st_gid); 247 266 memset(header.size, '0', sizeof(header.size)-1); /* Regular file size is handled later */ 248 PUT_OCTAL(header.mtime, statbuf->st_mtime); 267 /* users report that files with negative st_mtime cause trouble, so: */ 268 PUT_OCTAL(header.mtime, statbuf->st_mtime >= 0 ? statbuf->st_mtime : 0); 249 269 250 270 /* Enter the user and group names */ … … 298 318 header.typeflag = FIFOTYPE; 299 319 } else if (S_ISREG(statbuf->st_mode)) { 300 if (sizeof(statbuf->st_size) > 4 301 && statbuf->st_size > (off_t)0777777777777LL 320 /* header.size field is 12 bytes long */ 321 /* Does octal-encoded size fit? */ 322 uoff_t filesize = statbuf->st_size; 323 if (sizeof(filesize) <= 4 324 || filesize <= (uoff_t)0777777777777LL 302 325 ) { 326 PUT_OCTAL(header.size, filesize); 327 } 328 /* Does base256-encoded size fit? 329 * It always does unless off_t is wider than 64 bits. 330 */ 331 else if (ENABLE_FEATURE_TAR_GNU_EXTENSIONS 332 #if ULLONG_MAX > 0xffffffffffffffffLL /* 2^64-1 */ 333 && (filesize <= 0x3fffffffffffffffffffffffLL) 334 #endif 335 ) { 336 /* GNU tar uses "base-256 encoding" for very large numbers. 337 * Encoding is binary, with highest bit always set as a marker 338 * and sign in next-highest bit: 339 * 80 00 .. 00 - zero 340 * bf ff .. ff - largest positive number 341 * ff ff .. ff - minus 1 342 * c0 00 .. 00 - smallest negative number 343 */ 344 char *p8 = header.size + sizeof(header.size); 345 do { 346 *--p8 = (uint8_t)filesize; 347 filesize >>= 8; 348 } while (p8 != header.size); 349 *p8 |= 0x80; 350 } else { 303 351 bb_error_msg_and_die("can't store file '%s' " 304 352 "of size %"OFF_FMT"u, aborting", … … 306 354 } 307 355 header.typeflag = REGTYPE; 308 PUT_OCTAL(header.size, statbuf->st_size);309 356 } else { 310 357 bb_error_msg("%s: unknown file type", fileName); … … 379 426 DBG("writeFileToTarball('%s')", fileName); 380 427 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 } 428 /* Strip leading '/' and such (must be before memorizing hardlink's name) */ 429 header_name = strip_unsafe_prefix(fileName); 392 430 393 431 if (header_name[0] == '\0') … … 561 599 /* gcc 4.2.1 inlines it, making code bigger */ 562 600 static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, 563 int dereferenceFlag, const llist_t *include,601 int recurseFlags, const llist_t *include, 564 602 const llist_t *exclude, int gzip) 565 603 { … … 584 622 /* Read the directory/files and iterate over them one at a time */ 585 623 while (include) { 586 if (!recursive_action(include->data, ACTION_RECURSE | 587 (dereferenceFlag ? ACTION_FOLLOWLINKS : 0), 624 if (!recursive_action(include->data, recurseFlags, 588 625 writeFileToTarball, writeFileToTarball, &tbInfo, 0) 589 626 ) { … … 625 662 #else 626 663 int writeTarFile(int tar_fd, int verboseFlag, 627 int dereferenceFlag, const llist_t *include,664 int recurseFlags, const llist_t *include, 628 665 const llist_t *exclude, int gzip); 629 666 #endif /* FEATURE_TAR_CREATE */ … … 637 674 638 675 while (list) { 639 src_stream = xfopen_ for_read(llist_pop(&list));676 src_stream = xfopen_stdin(llist_pop(&list)); 640 677 while ((line = xmalloc_fgetline(src_stream)) != NULL) { 641 678 /* kill trailing '/' unless the string is just "/" */ … … 653 690 #endif 654 691 655 #if ENABLE_FEATURE_SEAMLESS_Z656 static 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) != 0x1f663 || xread_char(archive_handle->src_fd) != 0x9d664 ) {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 #else677 # define get_header_tar_Z NULL678 #endif679 680 #ifdef CHECK_FOR_CHILD_EXITCODE681 /* Looks like it isn't needed - tar detects malformed (truncated)682 * archive if e.g. bunzip2 fails */683 static int child_error;684 685 static 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 #endif702 703 692 //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]..." 693 //usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt" 694 //usage: IF_FEATURE_SEAMLESS_Z("Z") 695 //usage: IF_FEATURE_SEAMLESS_GZ("z") 696 //usage: IF_FEATURE_SEAMLESS_XZ("J") 697 //usage: IF_FEATURE_SEAMLESS_BZ2("j") 698 //usage: IF_FEATURE_SEAMLESS_LZMA("a") 699 //usage: IF_FEATURE_TAR_CREATE("h") 700 //usage: IF_FEATURE_TAR_NOPRESERVE_TIME("m") 701 //usage: "vO] " 702 //usage: IF_FEATURE_TAR_FROM("[-X FILE] [-T FILE] ") 703 //usage: "[-f TARFILE] [-C DIR] [FILE]..." 709 704 //usage:#define tar_full_usage "\n\n" 710 705 //usage: IF_FEATURE_TAR_CREATE("Create, extract, ") … … 717 712 //usage: "\n x Extract" 718 713 //usage: "\n t List" 719 //usage: "\nOptions:"720 714 //usage: "\n f Name of TARFILE ('-' for stdin/out)" 721 715 //usage: "\n C Change to DIR before operation" 722 716 //usage: "\n v Verbose" 717 //usage: IF_FEATURE_SEAMLESS_Z( 718 //usage: "\n Z (De)compress using compress" 719 //usage: ) 723 720 //usage: IF_FEATURE_SEAMLESS_GZ( 724 721 //usage: "\n z (De)compress using gzip" 722 //usage: ) 723 //usage: IF_FEATURE_SEAMLESS_XZ( 724 //usage: "\n J (De)compress using xz" 725 725 //usage: ) 726 726 //usage: IF_FEATURE_SEAMLESS_BZ2( … … 729 729 //usage: IF_FEATURE_SEAMLESS_LZMA( 730 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 731 //usage: ) 735 732 //usage: "\n O Extract to stdout" … … 756 753 // p same-permissions 757 754 // k keep-old 755 // no-recursion 758 756 // numeric-owner 759 757 // no-same-permissions … … 772 770 IF_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,) 773 771 IF_FEATURE_SEAMLESS_GZ( OPTBIT_GZIP ,) 774 IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,) // 16th bit 772 IF_FEATURE_SEAMLESS_XZ( OPTBIT_XZ ,) // 16th bit 773 IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,) 775 774 IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,) 776 775 #if ENABLE_FEATURE_TAR_LONG_OPTIONS 776 OPTBIT_NORECURSION, 777 777 IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND ,) 778 778 OPTBIT_NUMERIC_OWNER, … … 796 796 OPT_EXCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X 797 797 OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z 798 OPT_XZ = IF_FEATURE_SEAMLESS_XZ( (1 << OPTBIT_XZ )) + 0, // J 798 799 OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z 799 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 800 802 OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command 801 803 OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner 802 804 OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions 803 805 OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite 806 807 OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_XZ | OPT_COMPRESS), 804 808 }; 805 809 #if ENABLE_FEATURE_TAR_LONG_OPTIONS … … 834 838 "gzip\0" No_argument "z" 835 839 # endif 840 # if ENABLE_FEATURE_SEAMLESS_XZ 841 "xz\0" No_argument "J" 842 # endif 836 843 # if ENABLE_FEATURE_SEAMLESS_Z 837 844 "compress\0" No_argument "Z" … … 840 847 "touch\0" No_argument "m" 841 848 # endif 849 "no-recursion\0" No_argument "\xfa" 842 850 # if ENABLE_FEATURE_TAR_TO_COMMAND 843 851 "to-command\0" Required_argument "\xfb" … … 860 868 int tar_main(int argc UNUSED_PARAM, char **argv) 861 869 { 862 char FAST_FUNC (*get_header_ptr)(archive_handle_t *) = get_header_tar;863 870 archive_handle_t *tar_handle; 864 871 char *base_dir = NULL; … … 883 890 opt_complementary = "--:" // first arg is options 884 891 "tt:vv:" // count -t,-v 885 "?:" // bail out with usage instead of error return 886 "X::T::" // cumulative lists 892 IF_FEATURE_TAR_FROM("X::T::") // cumulative lists 887 893 #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM 888 894 "\xff::" // cumulative lists for --exclude … … 928 934 IF_FEATURE_TAR_FROM( "T:X:") 929 935 IF_FEATURE_SEAMLESS_GZ( "z" ) 936 IF_FEATURE_SEAMLESS_XZ( "J" ) 930 937 IF_FEATURE_SEAMLESS_Z( "Z" ) 931 938 IF_FEATURE_TAR_NOPRESERVE_TIME("m") … … 957 964 signal(SIGPIPE, SIG_IGN); 958 965 tar_handle->action_data = data_extract_to_command; 966 IF_FEATURE_TAR_TO_COMMAND(tar_handle->tar__to_command_shell = xstrdup(get_shell_name());) 959 967 } 960 968 … … 975 983 tar_handle->ah_flags |= ARCHIVE_O_TRUNC; 976 984 } 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 985 990 986 if (opt & OPT_NOPRESERVE_TIME) … … 1040 1036 if (ENABLE_FEATURE_TAR_AUTODETECT 1041 1037 && flags == O_RDONLY 1042 && get_header_ptr == get_header_tar1038 && !(opt & OPT_ANY_COMPRESS) 1043 1039 ) { 1044 1040 tar_handle->src_fd = open_zipped(tar_filename); … … 1054 1050 xchdir(base_dir); 1055 1051 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 1052 //if (SEAMLESS_COMPRESSION || OPT_COMPRESS) 1053 // /* We need to know whether child (gzip/bzip/etc) exits abnormally */ 1054 // signal(SIGCHLD, check_errors_in_children); 1060 1055 1061 1056 /* Create an archive */ … … 1069 1064 #endif 1070 1065 /* NB: writeTarFile() closes tar_handle->src_fd */ 1071 return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE, 1066 return writeTarFile(tar_handle->src_fd, verboseFlag, 1067 (opt & OPT_DEREFERENCE ? ACTION_FOLLOWLINKS : 0) 1068 | (opt & OPT_NORECURSION ? 0 : ACTION_RECURSE), 1072 1069 tar_handle->accept, 1073 1070 tar_handle->reject, zipMode); 1074 1071 } 1075 1072 1076 while (get_header_ptr(tar_handle) == EXIT_SUCCESS) 1073 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);) 1075 USE_FOR_NOMMU(const char *xformer_prog;) 1076 1077 if (opt & OPT_COMPRESS) 1078 USE_FOR_MMU(xformer = unpack_Z_stream;) 1079 USE_FOR_NOMMU(xformer_prog = "uncompress";) 1080 if (opt & OPT_GZIP) 1081 USE_FOR_MMU(xformer = unpack_gz_stream;) 1082 USE_FOR_NOMMU(xformer_prog = "gunzip";) 1083 if (opt & OPT_BZIP2) 1084 USE_FOR_MMU(xformer = unpack_bz2_stream;) 1085 USE_FOR_NOMMU(xformer_prog = "bunzip2";) 1086 if (opt & OPT_LZMA) 1087 USE_FOR_MMU(xformer = unpack_lzma_stream;) 1088 USE_FOR_NOMMU(xformer_prog = "unlzma";) 1089 if (opt & OPT_XZ) 1090 USE_FOR_MMU(xformer = unpack_xz_stream;) 1091 USE_FOR_NOMMU(xformer_prog = "unxz";) 1092 1093 open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); 1094 /* Can't lseek over pipes */ 1095 tar_handle->seek = seek_by_read; 1096 /*tar_handle->offset = 0; - already is */ 1097 } 1098 1099 while (get_header_tar(tar_handle) == EXIT_SUCCESS) 1077 1100 continue; 1078 1101 … … 1090 1113 close(tar_handle->src_fd); 1091 1114 1115 if (SEAMLESS_COMPRESSION || OPT_COMPRESS) { 1116 check_errors_in_children(0); 1117 return bb_got_signal; 1118 } 1092 1119 return EXIT_SUCCESS; 1093 1120 }
Note:
See TracChangeset
for help on using the changeset viewer.