aboutsummaryrefslogtreecommitdiff
path: root/archival/tar.c
diff options
context:
space:
mode:
Diffstat (limited to 'archival/tar.c')
-rw-r--r--archival/tar.c103
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
696static 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 */
723static int child_error;
724
725static 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
850static const char tar_longopts[] ALIGN1 = 804static const char tar_longopts[] ALIGN1 =
@@ -903,7 +857,6 @@ static const char tar_longopts[] ALIGN1 =
903int tar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 857int tar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
904int tar_main(int argc UNUSED_PARAM, char **argv) 858int 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}