xzdiff was clobbering the exit status from diff in a case statement
used to analyze the exit statuses from "xz" when its operands were
two compressed files.  Save and restore diff's exit status to fix
this.

The bug is inherited from zdiff in GNU gzip and was fixed there on
2009-10-09.

Reported-by: Peter Pallinger <[email protected]>
Signed-off-by: Jonathan Nieder <[email protected]>
---
Hi,

Peter Pallinger wrote[*]:

> It always returns 0 instead of 1 (i.e. if the files differ).
> Simple way to check:
> cp /etc/hosts /etc/hostname /tmp/
> cd /tmp
> diff -q host* ; echo $?
> xz host*
> xzdiff -q host* ; echo $?
[...]
> xzcmp behaves the same way, as they are the same program.
>
> I've already filed a bug report with a patch in the ubuntu bug tracker:
> https://bugs.launchpad.net/ubuntu/+source/xz-utils/+bug/816325

How about this?  It is a little simpler, I hope.

Thoughts welcome as always; e.g., if people have ideas for simplifying
the test script, I'm all ears. :)

Thanks,
Jonathan

 src/scripts/xzdiff.in |    2 +
 tests/Makefile.am     |    4 ++-
 tests/test_scripts.sh |   63 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+), 1 deletions(-)
 create mode 100755 tests/test_scripts.sh

diff --git a/src/scripts/xzdiff.in b/src/scripts/xzdiff.in
index 0fa446f6..e6e38429 100644
--- a/src/scripts/xzdiff.in
+++ b/src/scripts/xzdiff.in
@@ -126,10 +126,12 @@ elif test $# -eq 2; then
                 ( ($xz2 -cdfq -- "$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=
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d0807ae4..0469264a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -10,6 +10,7 @@ EXTRA_DIST = \
        tests.h \
        test_files.sh \
        test_compress.sh \
+       test_scripts.sh \
        bcj_test.c \
        compress_prepared_bcj_sparc \
        compress_prepared_bcj_x86
@@ -42,7 +43,8 @@ TESTS = \
        test_block_header \
        test_index \
        test_files.sh \
-       test_compress.sh
+       test_compress.sh \
+       test_scripts.sh
 
 clean-local:
        -rm -f compress_generated_*
diff --git a/tests/test_scripts.sh b/tests/test_scripts.sh
new file mode 100755
index 00000000..6e83d397
--- /dev/null
+++ b/tests/test_scripts.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+###############################################################################
+#
+# Author: Jonathan Nieder
+#
+# This file has been put into the public domain.
+# You can do whatever you want with this file.
+#
+###############################################################################
+
+# If scripts weren't built, this test is skipped.
+XZ=../src/xz/xz
+XZDIFF=../src/scripts/xzdiff
+test -x "$XZ" || XZ=
+test -r "$XZDIFF" || XZDIFF=
+if test -z "$XZ" || test -z "$XZDIFF"; then
+       (exit 77)
+       exit 77
+fi
+
+temporaries="tmp_preimage.xz tmp_samepostimage.xz tmp_otherpostimage.xz"
+rm -f $temporaries
+trap "rm -f $temporaries" 0
+
+PATH=$(pwd)/../src/xz:$PATH
+
+if echo unchanged | "$XZ" > tmp_preimage.xz &&
+   echo unchanged | "$XZ" > tmp_samepostimage.xz &&
+   echo changed | "$XZ" > tmp_otherpostimage.xz ; then
+       :
+else
+       echo "Compressing preimage or postimage failed"
+       (exit 1)
+       exit 1
+fi
+
+sh "$XZDIFF" tmp_preimage.xz tmp_samepostimage.xz >/dev/null
+status=$?
+if test "$status" != 0 ; then
+       echo "xzdiff with no changes exited with status $status != 0"
+       (exit 1)
+       exit 1
+fi
+
+sh "$XZDIFF" tmp_preimage.xz tmp_otherpostimage.xz >/dev/null
+status=$?
+if test "$status" != 1 ; then
+       echo "xzdiff with changes exited with status $status != 1"
+       (exit 1)
+       exit 1
+fi
+
+sh "$XZDIFF" tmp_preimage.xz tmp_missingpostimage.xz >/dev/null 2>&1
+status=$?
+if test "$status" != 2 ; then
+       echo "xzdiff with missing operand exited with status $status != 2"
+       (exit 1)
+       exit 1
+fi
+
+(exit 0)
+exit 0
-- 
1.7.6


Reply via email to