On 03/16/2016 02:06 PM, Paul Eggert wrote:
I have worked on a patch but don't have a reliable fix yet, or even a portable test case to illustrate the bug.

On further thought I found a test case and a fix, which I've attached. Normally I would just install this, but we're so close to a release that I'll wait for a word from Jim.
From 1b36e51446fe0846299a3f804a0b74c240871c5b Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 17 Mar 2016 13:08:06 -0700
Subject: [PATCH] zgrep: with -f SPECIAL, read SPECIAL just once

Problem reported by Fulvio Scapin in: http://bugs.gnu.org/22945
* NEWS: Document this.
* tests/zgrep-f: Add a test.
* zgrep.in (with_filename): With -f FILE, if FILE is not
a regular file, read it here and turn it into an -e option.
---
 NEWS          | 3 +++
 tests/zgrep-f | 8 ++++++++
 zgrep.in      | 6 ++++++
 3 files changed, 17 insertions(+)

diff --git a/NEWS b/NEWS
index 6363d71..541ad94 100644
--- a/NEWS
+++ b/NEWS
@@ -35,6 +35,9 @@ GNU gzip NEWS                                    -*- outline -*-
   gzip -k -v no longer reports that files are replaced.
   [bug present since the beginning]
 
+  zgrep -f A B C no longer reads A more than once if A is not a regular file.
+  This better supports invocations like 'zgrep -f <(COMMAND) B C' in Bash.
+  [bug introduced in gzip-1.2]
 
 * Noteworthy changes in release 1.6 (2013-06-09) [stable]
 
diff --git a/tests/zgrep-f b/tests/zgrep-f
index a8eb746..9a86550 100755
--- a/tests/zgrep-f
+++ b/tests/zgrep-f
@@ -29,6 +29,14 @@ zgrep -f - haystack.gz < n > out 2>&1 || fail=1
 
 compare out n || fail=1
 
+if ${BASH_VERSION+:} false; then
+  set +o posix
+  # This failed with gzip 1.6.
+  cat n n >nn || framework_failure_
+  eval 'zgrep -h -f <(cat n) haystack.gz haystack.gz' >out || fail=1
+  compare out nn || fail=1
+fi
+
 # This failed with gzip 1.4.
 echo a-b | zgrep -e - > /dev/null || fail=1
 
diff --git a/zgrep.in b/zgrep.in
index c24be57..da03871 100644
--- a/zgrep.in
+++ b/zgrep.in
@@ -113,12 +113,18 @@ while test $# -ne 0; do
     # The pattern is coming from a file rather than the command-line.
     # If the file is actually stdin then we need to do a little
     # magic, since we use stdin to pass the gzip output to grep.
+    # Similarly if it is not a regular file, since it might be read repeatedly.
     # Turn the -f option into an -e option by copying the file's
     # contents into OPTARG.
     case $optarg in
     (" '-'" | " '/dev/stdin'" | " '/dev/fd/0'")
       option=-e
       optarg=" '"$(sed "$escape") || exit 2;;
+    (*)
+      if eval "test ! -f $optarg"; then
+        option=-e
+        optarg=" '"$(eval 'sed "$escape" <'"$optarg") || exit 2
+      fi;;
     esac
     have_pat=1;;
   (--h | --he | --hel | --help)
-- 
2.5.0

Reply via email to