tar: report error if child dies while writing out the end of tarball
(e.g. out of disk space).
diff --git a/archival/tar.c b/archival/tar.c
index ba7cb0f..7465e88 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -504,7 +504,6 @@
 		volatile int vfork_exec_errno = 0;
 		char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
 
-
 		if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0)
 			bb_perror_msg_and_die("pipe");
 
@@ -585,10 +584,15 @@
 	if (errorFlag)
 		bb_error_msg("error exit delayed from previous errors");
 
-	if (gzipPid && waitpid(gzipPid, NULL, 0) == -1)
-		bb_error_msg("waitpid failed");
-
-	return !errorFlag;
+	if (gzipPid) {
+		int status;
+		if (waitpid(gzipPid, &status, 0) == -1)
+			bb_perror_msg("waitpid");
+		else if (!WIFEXITED(status) || WEXITSTATUS(status))
+			/* gzip was killed or has exited with nonzero! */
+			errorFlag = TRUE;
+	}
+	return errorFlag;
 }
 #else
 int writeTarFile(const int tar_fd, const int verboseFlag,
@@ -650,6 +654,29 @@
 #define get_header_tar_Z	0
 #endif
 
+#ifdef CHECK_FOR_CHILD_EXITCODE
+/* Looks like it isn't needed - tar detects malformed (truncated)
+ * archive if e.g. bunzip2 fails */
+static int child_error;
+
+static void handle_SIGCHLD(int status)
+{
+	/* Actually, 'status' is a signo. We reuse it for other needs */
+
+	/* Wait for any child without blocking */
+	if (waitpid(-1, &status, WNOHANG) < 0)
+		/* wait failed?! I'm confused... */
+		return;
+
+	if (WIFEXITED(status) && WEXITSTATUS(status)==0)
+		/* child exited with 0 */
+		return;
+	/* Cannot happen? 
+	if(!WIFSIGNALED(status) && !WIFEXITED(status)) return; */
+	child_error = 1;
+}
+#endif
+
 enum {
 	OPTBIT_KEEP_OLD = 7,
 	USE_FEATURE_TAR_CREATE(  OPTBIT_CREATE      ,)
@@ -862,6 +889,11 @@
 	if (base_dir)
 		xchdir(base_dir);
 
+#ifdef CHECK_FOR_CHILD_EXITCODE
+	/* We need to know whether child (gzip/bzip/etc) exits abnormally */
+	signal(SIGCHLD, handle_SIGCHLD);
+#endif
+
 	/* create an archive */
 	if (opt & OPT_CREATE) {
 		int zipMode = 0;
@@ -869,11 +901,10 @@
 			zipMode = 1;
 		if (ENABLE_FEATURE_TAR_BZIP2 && get_header_ptr == get_header_tar_bz2)
 			zipMode = 2;
-		writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE,
+		/* NB: writeTarFile() closes tar_handle->src_fd */
+		return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE,
 				tar_handle->accept,
 				tar_handle->reject, zipMode);
-		/* NB: writeTarFile() closes tar_handle->src_fd */
-		return EXIT_SUCCESS;
 	}
 
 	while (get_header_ptr(tar_handle) == EXIT_SUCCESS)