diff options
| -rw-r--r-- | archival/tar.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/archival/tar.c b/archival/tar.c index ba7cb0f8c..7465e881b 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
| @@ -504,7 +504,6 @@ static int writeTarFile(const int tar_fd, const int verboseFlag, | |||
| 504 | volatile int vfork_exec_errno = 0; | 504 | volatile int vfork_exec_errno = 0; |
| 505 | char *zip_exec = (gzip == 1) ? "gzip" : "bzip2"; | 505 | char *zip_exec = (gzip == 1) ? "gzip" : "bzip2"; |
| 506 | 506 | ||
| 507 | |||
| 508 | if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0) | 507 | if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0) |
| 509 | bb_perror_msg_and_die("pipe"); | 508 | bb_perror_msg_and_die("pipe"); |
| 510 | 509 | ||
| @@ -585,10 +584,15 @@ static int writeTarFile(const int tar_fd, const int verboseFlag, | |||
| 585 | if (errorFlag) | 584 | if (errorFlag) |
| 586 | bb_error_msg("error exit delayed from previous errors"); | 585 | bb_error_msg("error exit delayed from previous errors"); |
| 587 | 586 | ||
| 588 | if (gzipPid && waitpid(gzipPid, NULL, 0) == -1) | 587 | if (gzipPid) { |
| 589 | bb_error_msg("waitpid failed"); | 588 | int status; |
| 590 | 589 | if (waitpid(gzipPid, &status, 0) == -1) | |
| 591 | return !errorFlag; | 590 | bb_perror_msg("waitpid"); |
| 591 | else if (!WIFEXITED(status) || WEXITSTATUS(status)) | ||
| 592 | /* gzip was killed or has exited with nonzero! */ | ||
| 593 | errorFlag = TRUE; | ||
| 594 | } | ||
| 595 | return errorFlag; | ||
| 592 | } | 596 | } |
| 593 | #else | 597 | #else |
| 594 | int writeTarFile(const int tar_fd, const int verboseFlag, | 598 | int writeTarFile(const int tar_fd, const int verboseFlag, |
| @@ -650,6 +654,29 @@ static char get_header_tar_Z(archive_handle_t *archive_handle) | |||
| 650 | #define get_header_tar_Z 0 | 654 | #define get_header_tar_Z 0 |
| 651 | #endif | 655 | #endif |
| 652 | 656 | ||
| 657 | #ifdef CHECK_FOR_CHILD_EXITCODE | ||
| 658 | /* Looks like it isn't needed - tar detects malformed (truncated) | ||
| 659 | * archive if e.g. bunzip2 fails */ | ||
| 660 | static int child_error; | ||
| 661 | |||
| 662 | static void handle_SIGCHLD(int status) | ||
| 663 | { | ||
| 664 | /* Actually, 'status' is a signo. We reuse it for other needs */ | ||
| 665 | |||
| 666 | /* Wait for any child without blocking */ | ||
| 667 | if (waitpid(-1, &status, WNOHANG) < 0) | ||
| 668 | /* wait failed?! I'm confused... */ | ||
| 669 | return; | ||
| 670 | |||
| 671 | if (WIFEXITED(status) && WEXITSTATUS(status)==0) | ||
| 672 | /* child exited with 0 */ | ||
| 673 | return; | ||
| 674 | /* Cannot happen? | ||
| 675 | if(!WIFSIGNALED(status) && !WIFEXITED(status)) return; */ | ||
| 676 | child_error = 1; | ||
| 677 | } | ||
| 678 | #endif | ||
| 679 | |||
| 653 | enum { | 680 | enum { |
| 654 | OPTBIT_KEEP_OLD = 7, | 681 | OPTBIT_KEEP_OLD = 7, |
| 655 | USE_FEATURE_TAR_CREATE( OPTBIT_CREATE ,) | 682 | USE_FEATURE_TAR_CREATE( OPTBIT_CREATE ,) |
| @@ -862,6 +889,11 @@ int tar_main(int argc, char **argv) | |||
| 862 | if (base_dir) | 889 | if (base_dir) |
| 863 | xchdir(base_dir); | 890 | xchdir(base_dir); |
| 864 | 891 | ||
| 892 | #ifdef CHECK_FOR_CHILD_EXITCODE | ||
| 893 | /* We need to know whether child (gzip/bzip/etc) exits abnormally */ | ||
| 894 | signal(SIGCHLD, handle_SIGCHLD); | ||
| 895 | #endif | ||
| 896 | |||
| 865 | /* create an archive */ | 897 | /* create an archive */ |
| 866 | if (opt & OPT_CREATE) { | 898 | if (opt & OPT_CREATE) { |
| 867 | int zipMode = 0; | 899 | int zipMode = 0; |
| @@ -869,11 +901,10 @@ int tar_main(int argc, char **argv) | |||
| 869 | zipMode = 1; | 901 | zipMode = 1; |
| 870 | if (ENABLE_FEATURE_TAR_BZIP2 && get_header_ptr == get_header_tar_bz2) | 902 | if (ENABLE_FEATURE_TAR_BZIP2 && get_header_ptr == get_header_tar_bz2) |
| 871 | zipMode = 2; | 903 | zipMode = 2; |
| 872 | writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE, | 904 | /* NB: writeTarFile() closes tar_handle->src_fd */ |
| 905 | return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE, | ||
| 873 | tar_handle->accept, | 906 | tar_handle->accept, |
| 874 | tar_handle->reject, zipMode); | 907 | tar_handle->reject, zipMode); |
| 875 | /* NB: writeTarFile() closes tar_handle->src_fd */ | ||
| 876 | return EXIT_SUCCESS; | ||
| 877 | } | 908 | } |
| 878 | 909 | ||
| 879 | while (get_header_ptr(tar_handle) == EXIT_SUCCESS) | 910 | while (get_header_ptr(tar_handle) == EXIT_SUCCESS) |
