aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-12-17 19:08:20 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-12-17 19:08:20 +0000
commitc88894602dc97d3c5d5194b86517a5da5d260612 (patch)
treef75b881c57bf9312b963d53e240b9c14fec3f972
parentb131b271a0d89b1ff04fd721530f424d0a15f0b2 (diff)
downloadbusybox-w32-c88894602dc97d3c5d5194b86517a5da5d260612.tar.gz
busybox-w32-c88894602dc97d3c5d5194b86517a5da5d260612.tar.bz2
busybox-w32-c88894602dc97d3c5d5194b86517a5da5d260612.zip
tar: report error if child dies while writing out the end of tarball
(e.g. out of disk space).
-rw-r--r--archival/tar.c47
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
594int writeTarFile(const int tar_fd, const int verboseFlag, 598int 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 */
660static int child_error;
661
662static 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
653enum { 680enum {
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)