diff options
Diffstat (limited to 'archival/tar.c')
-rw-r--r-- | archival/tar.c | 103 |
1 files changed, 36 insertions, 67 deletions
diff --git a/archival/tar.c b/archival/tar.c index 2b752f640..fcd128a91 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -692,54 +692,6 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
692 | # define append_file_list_to_list(x) 0 | 692 | # define append_file_list_to_list(x) 0 |
693 | #endif | 693 | #endif |
694 | 694 | ||
695 | #if ENABLE_FEATURE_SEAMLESS_Z | ||
696 | static char FAST_FUNC get_header_tar_Z(archive_handle_t *archive_handle) | ||
697 | { | ||
698 | /* Can't lseek over pipes */ | ||
699 | archive_handle->seek = seek_by_read; | ||
700 | |||
701 | /* do the decompression, and cleanup */ | ||
702 | if (xread_char(archive_handle->src_fd) != 0x1f | ||
703 | || xread_char(archive_handle->src_fd) != 0x9d | ||
704 | ) { | ||
705 | bb_error_msg_and_die("invalid magic"); | ||
706 | } | ||
707 | |||
708 | open_transformer(archive_handle->src_fd, unpack_Z_stream, "uncompress"); | ||
709 | archive_handle->offset = 0; | ||
710 | while (get_header_tar(archive_handle) == EXIT_SUCCESS) | ||
711 | continue; | ||
712 | |||
713 | /* Can only do one file at a time */ | ||
714 | return EXIT_FAILURE; | ||
715 | } | ||
716 | #else | ||
717 | # define get_header_tar_Z NULL | ||
718 | #endif | ||
719 | |||
720 | #ifdef CHECK_FOR_CHILD_EXITCODE | ||
721 | /* Looks like it isn't needed - tar detects malformed (truncated) | ||
722 | * archive if e.g. bunzip2 fails */ | ||
723 | static int child_error; | ||
724 | |||
725 | static void handle_SIGCHLD(int status) | ||
726 | { | ||
727 | /* Actually, 'status' is a signo. We reuse it for other needs */ | ||
728 | |||
729 | /* Wait for any child without blocking */ | ||
730 | if (wait_any_nohang(&status) < 0) | ||
731 | /* wait failed?! I'm confused... */ | ||
732 | return; | ||
733 | |||
734 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0) | ||
735 | /* child exited with 0 */ | ||
736 | return; | ||
737 | /* Cannot happen? | ||
738 | if (!WIFSIGNALED(status) && !WIFEXITED(status)) return; */ | ||
739 | child_error = 1; | ||
740 | } | ||
741 | #endif | ||
742 | |||
743 | //usage:#define tar_trivial_usage | 695 | //usage:#define tar_trivial_usage |
744 | //usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt" | 696 | //usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt" |
745 | //usage: IF_FEATURE_SEAMLESS_Z("Z") | 697 | //usage: IF_FEATURE_SEAMLESS_Z("Z") |
@@ -845,6 +797,8 @@ enum { | |||
845 | OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner | 797 | OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner |
846 | OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions | 798 | OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions |
847 | OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite | 799 | OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite |
800 | |||
801 | OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_COMPRESS), | ||
848 | }; | 802 | }; |
849 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS | 803 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS |
850 | static const char tar_longopts[] ALIGN1 = | 804 | static const char tar_longopts[] ALIGN1 = |
@@ -903,7 +857,6 @@ static const char tar_longopts[] ALIGN1 = | |||
903 | int tar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 857 | int tar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
904 | int tar_main(int argc UNUSED_PARAM, char **argv) | 858 | int tar_main(int argc UNUSED_PARAM, char **argv) |
905 | { | 859 | { |
906 | char FAST_FUNC (*get_header_ptr)(archive_handle_t *) = get_header_tar; | ||
907 | archive_handle_t *tar_handle; | 860 | archive_handle_t *tar_handle; |
908 | char *base_dir = NULL; | 861 | char *base_dir = NULL; |
909 | const char *tar_filename = "-"; | 862 | const char *tar_filename = "-"; |
@@ -1019,18 +972,6 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1019 | tar_handle->ah_flags |= ARCHIVE_O_TRUNC; | 972 | tar_handle->ah_flags |= ARCHIVE_O_TRUNC; |
1020 | } | 973 | } |
1021 | 974 | ||
1022 | if (opt & OPT_GZIP) | ||
1023 | get_header_ptr = get_header_tar_gz; | ||
1024 | |||
1025 | if (opt & OPT_BZIP2) | ||
1026 | get_header_ptr = get_header_tar_bz2; | ||
1027 | |||
1028 | if (opt & OPT_LZMA) | ||
1029 | get_header_ptr = get_header_tar_lzma; | ||
1030 | |||
1031 | if (opt & OPT_COMPRESS) | ||
1032 | get_header_ptr = get_header_tar_Z; | ||
1033 | |||
1034 | if (opt & OPT_NOPRESERVE_TIME) | 975 | if (opt & OPT_NOPRESERVE_TIME) |
1035 | tar_handle->ah_flags &= ~ARCHIVE_RESTORE_DATE; | 976 | tar_handle->ah_flags &= ~ARCHIVE_RESTORE_DATE; |
1036 | 977 | ||
@@ -1083,7 +1024,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1083 | } else { | 1024 | } else { |
1084 | if (ENABLE_FEATURE_TAR_AUTODETECT | 1025 | if (ENABLE_FEATURE_TAR_AUTODETECT |
1085 | && flags == O_RDONLY | 1026 | && flags == O_RDONLY |
1086 | && get_header_ptr == get_header_tar | 1027 | && !(opt & OPT_ANY_COMPRESS) |
1087 | ) { | 1028 | ) { |
1088 | tar_handle->src_fd = open_zipped(tar_filename); | 1029 | tar_handle->src_fd = open_zipped(tar_filename); |
1089 | if (tar_handle->src_fd < 0) | 1030 | if (tar_handle->src_fd < 0) |
@@ -1097,10 +1038,9 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1097 | if (base_dir) | 1038 | if (base_dir) |
1098 | xchdir(base_dir); | 1039 | xchdir(base_dir); |
1099 | 1040 | ||
1100 | #ifdef CHECK_FOR_CHILD_EXITCODE | 1041 | //if (SEAMLESS_COMPRESSION || OPT_COMPRESS) |
1101 | /* We need to know whether child (gzip/bzip/etc) exits abnormally */ | 1042 | // /* We need to know whether child (gzip/bzip/etc) exits abnormally */ |
1102 | signal(SIGCHLD, handle_SIGCHLD); | 1043 | // signal(SIGCHLD, check_errors_in_children); |
1103 | #endif | ||
1104 | 1044 | ||
1105 | /* Create an archive */ | 1045 | /* Create an archive */ |
1106 | if (opt & OPT_CREATE) { | 1046 | if (opt & OPT_CREATE) { |
@@ -1117,7 +1057,30 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1117 | tar_handle->reject, zipMode); | 1057 | tar_handle->reject, zipMode); |
1118 | } | 1058 | } |
1119 | 1059 | ||
1120 | while (get_header_ptr(tar_handle) == EXIT_SUCCESS) | 1060 | if (opt & OPT_ANY_COMPRESS) { |
1061 | USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);) | ||
1062 | USE_FOR_NOMMU(const char *xformer_prog;) | ||
1063 | |||
1064 | if (opt & OPT_COMPRESS) | ||
1065 | USE_FOR_MMU(xformer = unpack_Z_stream;) | ||
1066 | USE_FOR_NOMMU(xformer_prog = "uncompress";) | ||
1067 | if (opt & OPT_GZIP) | ||
1068 | USE_FOR_MMU(xformer = unpack_gz_stream;) | ||
1069 | USE_FOR_NOMMU(xformer_prog = "gunzip";) | ||
1070 | if (opt & OPT_BZIP2) | ||
1071 | USE_FOR_MMU(xformer = unpack_bz2_stream;) | ||
1072 | USE_FOR_NOMMU(xformer_prog = "bunzip2";) | ||
1073 | if (opt & OPT_LZMA) | ||
1074 | USE_FOR_MMU(xformer = unpack_lzma_stream;) | ||
1075 | USE_FOR_NOMMU(xformer_prog = "unlzma";) | ||
1076 | |||
1077 | open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); | ||
1078 | /* Can't lseek over pipes */ | ||
1079 | tar_handle->seek = seek_by_read; | ||
1080 | /*tar_handle->offset = 0; - already is */ | ||
1081 | } | ||
1082 | |||
1083 | while (get_header_tar(tar_handle) == EXIT_SUCCESS) | ||
1121 | continue; | 1084 | continue; |
1122 | 1085 | ||
1123 | /* Check that every file that should have been extracted was */ | 1086 | /* Check that every file that should have been extracted was */ |
@@ -1133,5 +1096,11 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1133 | if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */) | 1096 | if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */) |
1134 | close(tar_handle->src_fd); | 1097 | close(tar_handle->src_fd); |
1135 | 1098 | ||
1099 | #if !ENABLE_PLATFORM_MINGW32 | ||
1100 | if (SEAMLESS_COMPRESSION || OPT_COMPRESS) { | ||
1101 | check_errors_in_children(0); | ||
1102 | return bb_got_signal; | ||
1103 | } | ||
1104 | #endif | ||
1136 | return EXIT_SUCCESS; | 1105 | return EXIT_SUCCESS; |
1137 | } | 1106 | } |