gzip -cdf now handles concatenation of gzip'd and uncompressed data
authorMark Adler <madler@alumni.caltech.edu>
Wed, 3 Feb 2010 09:11:33 +0000 (10:11 +0100)
committerJim Meyering <meyering@redhat.com>
Thu, 4 Feb 2010 06:29:14 +0000 (07:29 +0100)
* util.c (copy): Change semantics so as to honor a decremented inptr.
* gzip.c (get_method): When needed (-cdf), decrement inptr rather
than clearing it -- and output the first magic byte.

gnulib
gzip.c
util.c

diff --git a/gnulib b/gnulib
index a5b5500500ba4d6aaa9a1b3bb214f6917dc1ac3c..9d0ad652de159d08e5f679842f8a2a5658196361 160000 (submodule)
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit a5b5500500ba4d6aaa9a1b3bb214f6917dc1ac3c
+Subproject commit 9d0ad652de159d08e5f679842f8a2a5658196361
diff --git a/gzip.c b/gzip.c
index f523be73e4fb19203e57a76b2271c86493a5a374..141397e6e25b8f5e1cfd69c7ae10b9a24621c9a9 100644 (file)
--- a/gzip.c
+++ b/gzip.c
@@ -1239,6 +1239,7 @@ local int get_method(in)
 {
     uch flags;     /* compression flags */
     char magic[2]; /* magic header */
+    int imagic0;   /* first magic byte or EOF */
     int imagic1;   /* like magic[1], but can represent EOF */
     ulg stamp;     /* time stamp */
 
@@ -1246,12 +1247,14 @@ local int get_method(in)
      * premature end of file: use try_byte instead of get_byte.
      */
     if (force && to_stdout) {
-        magic[0] = (char)try_byte();
+        imagic0 = try_byte();
+        magic[0] = (char) imagic0;
         imagic1 = try_byte ();
         magic[1] = (char) imagic1;
         /* If try_byte returned EOF, magic[1] == (char) EOF.  */
     } else {
         magic[0] = (char)get_byte();
+        imagic0 = 0;
         if (magic[0]) {
             magic[1] = (char)get_byte();
             imagic1 = 0; /* avoid lint warning */
@@ -1395,8 +1398,13 @@ local int get_method(in)
     } else if (force && to_stdout && !list) { /* pass input unchanged */
         method = STORED;
         work = copy;
-        inptr = 0;
+        if (imagic1 != EOF)
+            inptr--;
         last_member = 1;
+        if (imagic0 != EOF) {
+            write_buf(fileno(stdout), magic, 1);
+            bytes_out++;
+        }
     }
     if (method >= 0) return method;
 
diff --git a/util.c b/util.c
index 1de2701ee7c28d88ffd825d6aa56009bd8719e0c..80b1075baa154f14784b624c0390d76405ad56c5 100644 (file)
--- a/util.c
+++ b/util.c
@@ -44,21 +44,25 @@ extern ulg crc_32_tab[];   /* crc table, defined below */
 
 /* ===========================================================================
  * Copy input to output unchanged: zcat == cat with --force.
- * IN assertion: insize bytes have already been read in inbuf.
+ * IN assertion: insize bytes have already been read in inbuf and inptr bytes
+ * already processed or copied.
  */
 int copy(in, out)
     int in, out;   /* input and output file descriptors */
 {
+    int got;
+
     errno = 0;
-    while (insize != 0 && (int)insize != -1) {
-        write_buf(out, (char*)inbuf, insize);
-        bytes_out += insize;
-        insize = read_buffer (in, (char *) inbuf, INBUFSIZ);
-    }
-    if ((int)insize == -1) {
-        read_error();
+    while (insize > inptr) {
+        write_buf(out, (char*)inbuf + inptr, insize - inptr);
+        bytes_out += insize - inptr;
+        got = read_buffer (in, (char *) inbuf, INBUFSIZ);
+        if (got == -1)
+            read_error();
+        bytes_in += got;
+        insize = (unsigned)got;
+        inptr = 0;
     }
-    bytes_in = bytes_out;
     return OK;
 }