Hello,

as is written in compress manual page

  [...]
  Exit status is normally 0; if the last file is larger after (attempted)
  compression, the status is 2; if an error occurs, exit status is 1.

the compress utility could end with exit value 2 which does not mean fatal
error.  It is just some kind of warning.  Gnu tar is unable to recognize
this error value and it thinks that some fatal error happened in the
background..  The easiest way how to reproduce this:

  $ dd if=/dev/urandom of=testfile bs=1K count=1024
  $ tar -cZf test.tar.Z testfile
  -rw-rw-r-- praiskup/praiskup 1048576 2013-02-22 16:49 testfile
  /home/praiskup/projects/tar/src/tar: Child returned status 2
  /home/praiskup/projects/tar/src/tar: Error is not recoverable: exiting now
  $ echo $?
  2

See: https://bugzilla.redhat.com/show_bug.cgi?id=914733

I know that the 'compress' utility could be considered antique but it may
still be used by some users (this problem was originally reported
by our customer https://bugzilla.redhat.com/show_bug.cgi?id=759371).  It
is also quite pity to have such detail in tar.

I'm attaching one possible solution, could you look at it?  As usually,
I'd be glad to fix issues you see in this patch, but feel free to scratch
this and fix it by different way ;),

Thanks for comments!
Pavel




>From e337d29ad24ae5b3b4c07a6287e9b44b37c59dcb Mon Sep 17 00:00:00 2001
From: Pavel Raiskup <prais...@redhat.com>
Date: Mon, 25 Feb 2013 10:18:15 +0100
Subject: [PATCH] tar: The Lempel-Ziv coding bugfix

Do not exit with fatal error 2 after compressing tarball by the
'compress' utility (-Z option) when the child process running the
compressor exited with "just-a-warning" exit value 2.  There is still
possible to restore the old tar behavior by running
'./configure --without-compress-exit-hack' (e.g. in situations when
there resides different compress implementation on the target system).

* acinclude.m4 (TAR_COMPRESS_EXIT_HACK): New function.
* configure.ac: Use TAR_COMPRESS_EXIT_HACK.
* src/system.c (sys_wait_for_child) [#ifdef HAVE_COMPRESS_EXIT_HACK]:
Warn when the compressed data are larger then the original data if
the child process command exited with 2 while the compressing
command was called 'compress'.
* NEWS: Document.
---
 NEWS         |  7 +++++++
 acinclude.m4 | 19 +++++++++++++++++++
 configure.ac |  3 +++
 src/system.c |  7 +++++++
 4 files changed, 36 insertions(+)

diff --git a/NEWS b/NEWS
index 3108798..863cf52 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,13 @@ version 1.26.90 (Git)
 
 * Bug fixes
 
+** The Lempel-Ziv coding compression bugfix (compress)
+
+Do not exit with fatal error during compressing by the 'compress'
+utility (-Z option) when the child process running the compressor exits
+with "warning" exit value 2.  It just means that the compressed output is
+bigger then original data.  Just warn the user now instead of hard fail.
+
 ** Sparse files with large data
 
 When creating a PAX-format archive, tar no longer arbitrarily restricts
diff --git a/acinclude.m4 b/acinclude.m4
index d48c881..1367eed 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -52,3 +52,22 @@ AC_DEFUN([TAR_HEADERS_ATTR_XATTR_H],
     )
   fi
 ])
+
+# Allow maintainer to disable compress's exit-2-value hack
+AC_DEFUN([TAR_COMPRESS_EXIT_HACK],[
+  AC_ARG_WITH(
+    [compress-exit-hack],
+    AS_HELP_STRING(
+      [--without-compress-exit-hack],
+      [fail when -Z (compress) compressor exists with non-error value 2]),
+    [with_compress_exit_hack=no]
+  )
+  if test "x$with_compress_exit_hack" != xno; then
+    AC_DEFINE_UNQUOTED(
+      HAVE_COMPRESS_EXIT_HACK,
+      "$tar_cv_compressor_compress",
+      Define to name of compress utility when we don't want to fail hardly
+      if this utility exits with exit code 2.  It should just mean that the
+      compressed file is bigger than original file.)
+  fi
+])
diff --git a/configure.ac b/configure.ac
index 3303c53..b0a4f14 100644
--- a/configure.ac
+++ b/configure.ac
@@ -253,6 +253,9 @@ TAR_COMPR_PROGRAM(lzma)
 TAR_COMPR_PROGRAM(lzop)
 TAR_COMPR_PROGRAM(xz)
 
+# must be called after TAR_COMPR_PROGRAM(compress) call
+TAR_COMPRESS_EXIT_HACK
+
 AC_MSG_CHECKING(for default archive format)
 
 AC_ARG_VAR([DEFAULT_ARCHIVE_FORMAT],
diff --git a/src/system.c b/src/system.c
index e1fd263..ca0ad05 100644
--- a/src/system.c
+++ b/src/system.c
@@ -189,6 +189,13 @@ sys_wait_for_child (pid_t child_pid, bool eof)
 	  if (!(!eof && sig == SIGPIPE))
 	    FATAL_ERROR ((0, 0, _("Child died with signal %d"), sig));
 	}
+#ifdef HAVE_COMPRESS_EXIT_HACK
+      else if (!strcmp (use_compress_program_option, HAVE_COMPRESS_EXIT_HACK)
+	       && WEXITSTATUS (wait_status) == 2)
+        WARN ((0, 0, _("%lu: Child says that compressed output is larger"
+		       "then original data."),
+	       (unsigned long) child_pid));
+#endif
       else if (WEXITSTATUS (wait_status) != 0)
 	FATAL_ERROR ((0, 0, _("Child returned status %d"),
 		      WEXITSTATUS (wait_status)));
-- 
1.8.1.2

Reply via email to