]> git.ipfire.org Git - thirdparty/xz.git/commitdiff
Scripts: Fix exit status of xzdiff/xzcmp.
authorLasse Collin <lasse.collin@tukaani.org>
Mon, 11 Jan 2021 20:01:51 +0000 (22:01 +0200)
committerLasse Collin <lasse.collin@tukaani.org>
Mon, 11 Jan 2021 20:58:58 +0000 (22:58 +0200)
This is a minor fix since this affects only the situation when
the files differ and the exit status is something else than 0.
In such case there could be SIGPIPE from a decompression tool
and that would result in exit status of 2 from xzdiff/xzcmp
while the correct behavior would be to return 1 or whatever
else diff or cmp may have returned.

This commit omits the -q option from xz/gzip/bzip2/lzop arguments.
I'm not sure why the -q was used in the first place, perhaps it
hides warnings in some situation that I cannot see at the moment.
Hopefully the removal won't introduce a new bug.

With gzip the -q option was harmful because it made gzip return 2
instead of >= 128 with SIGPIPE. Ignoring exit status 2 (warning
from gzip) isn't practical because bzip2 uses exit status 2 to
indicate corrupt input file. It's better if SIGPIPE results in
exit status >= 128.

With bzip2 the removal of -q seems to be good because with -q
it prints nothing if input is corrupt. The other tools aren't
silent in this situation even with -q. On the other hand, if
zstd support is added, it will need -q since otherwise it's
noisy in normal situations.

Thanks to Étienne Mollier and Sebastian Andrzej Siewior.

src/scripts/xzdiff.in

index eb7825c1dfba992359b83831bf8eb6038e8665d5..98ac0e5dc397d6a02b7c06bd1270a7d16ec7bfaa 100644 (file)
@@ -116,23 +116,18 @@ elif test $# -eq 2; then
           if test "$1$2" = --; then
             xz_status=$(
               exec 4>&1
-              ($xz1 -cdfq - 4>&-; echo $? >&4) 3>&- |
+              ($xz1 -cdf - 4>&-; echo $? >&4) 3>&- |
                 eval "$cmp" - - >&3
             )
           elif # Reject Solaris 8's buggy /bin/bash 2.03.
               echo X | (echo X | eval "$cmp" /dev/fd/5 - >/dev/null 2>&1) 5<&0; then
+            # NOTE: xz_status will contain two numbers.
             xz_status=$(
               exec 4>&1
-              ($xz1 -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
-                ( ($xz2 -cdfq -- "$2" 4>&-; echo $? >&4) 3>&- 5<&- </dev/null |
+              ($xz1 -cdf -- "$1" 4>&-; echo $? >&4) 3>&- |
+                ( ($xz2 -cdf -- "$2" 4>&-; echo $? >&4) 3>&- 5<&- </dev/null |
                 eval "$cmp" /dev/fd/5 - >&3) 5<&0
             )
-            cmp_status=$?
-            case $xz_status in
-              *[1-9]*) xz_status=1;;
-              *) xz_status=0;;
-            esac
-            (exit $cmp_status)
           else
             F=`expr "/$2" : '.*/\(.*\)[-.][ablmotxz2]*$'` || F=$prog
             tmp=
@@ -161,10 +156,10 @@ elif test $# -eq 2; then
               mkdir -- "${TMPDIR-/tmp}/$prog.$$" || exit 2
               tmp="${TMPDIR-/tmp}/$prog.$$"
             fi
-            $xz2 -cdfq -- "$2" > "$tmp/$F" || exit 2
+            $xz2 -cdf -- "$2" > "$tmp/$F" || exit 2
             xz_status=$(
               exec 4>&1
-              ($xz1 -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
+              ($xz1 -cdf -- "$1" 4>&-; echo $? >&4) 3>&- |
                 eval "$cmp" - '"$tmp/$F"' >&3
             )
             cmp_status=$?
@@ -175,7 +170,7 @@ elif test $# -eq 2; then
       *)
         xz_status=$(
           exec 4>&1
-          ($xz1 -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
+          ($xz1 -cdf -- "$1" 4>&-; echo $? >&4) 3>&- |
             eval "$cmp" - '"$2"' >&3
         );;
     esac;;
@@ -184,7 +179,7 @@ elif test $# -eq 2; then
       *[-.][zZ] | *_z | *[-.][gx]z | *[-.]bz2 | *[-.]lzma | *.t[abglx]z | *.tbz2 | *[-.]lzo | *.tzo | -)
         xz_status=$(
           exec 4>&1
-          ($xz2 -cdfq -- "$2" 4>&-; echo $? >&4) 3>&- |
+          ($xz2 -cdf -- "$2" 4>&-; echo $? >&4) 3>&- |
             eval "$cmp" '"$1"' - >&3
          );;
       *)
@@ -197,5 +192,17 @@ else
 fi
 
 cmp_status=$?
-test "$xz_status" -eq 0 || exit 2
+for num in $xz_status ; do
+  # 0 from decompressor means successful decompression. SIGPIPE from
+  # decompressor is possible when diff or cmp exits before the whole file
+  # has been decompressed. In that case we want to retain the exit status
+  # from diff or cmp. Note that using "trap '' PIPE" is not possible
+  # because gzip changes its behavior (including exit status) if SIGPIPE
+  # is ignored.
+  test "$num" -eq 0 && continue
+  test "$num" -ge 128 \
+      && test "$(kill -l "$num" 2> /dev/null)" = "PIPE" \
+      && continue
+  exit 2
+done
 exit $cmp_status