bzip2 compressed files are allowed to contain multiple streams of
compressed data.  So if we arrive at BZ_STREAM_END but are not at
EOF, restart the decompressor.  Decompress any data which remains
in the stream before reading any more.

Also remove write only member bufN

2011-04-08  Jon TURNEY  <jon.tur...@dronecode.org.uk>

        * compress_bz.h (compress): Remove unused bufN member.
        * compress_bz.cc (read): Handle bzip2 files containing multiple
        streams

Signed-off-by: Jon TURNEY <jon.tur...@dronecode.org.uk>
---
 compress_bz.cc |   35 ++++++++++++++++++++---------------
 compress_bz.h  |    1 -
 2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/compress_bz.cc b/compress_bz.cc
index f45f434..fb23529 100644
--- a/compress_bz.cc
+++ b/compress_bz.cc
@@ -37,7 +37,6 @@ compress_bz::compress_bz (io_stream * parent) : peeklen (0), 
position (0)
 
   initialisedOk = 0;
   endReached = 0;
-  bufN = 0;
   writing = 0;
   strm.bzalloc = 0;
   strm.bzfree = 0;
@@ -78,34 +77,26 @@ compress_bz::read (void *buffer, size_t len)
       else
         return tmpread;
   }
-  
+
   strm.avail_out = len;
   strm.next_out = (char *) buffer;
   int rlen = 1;
   while (1)
     {
-      if (original->error ())
-       {
-         lasterr = original->error ();
-         return -1;
-       }
+      int ret = BZ2_bzDecompress (&strm);
+
       if (strm.avail_in == 0 && rlen > 0)
        {
          rlen = original->read (buf, 4096);
          if (rlen < 0)
            {
-             if (original->error ())
-               lasterr = original->error ();
-             else
-               lasterr = rlen;
+              lasterr = original->error ();
              return -1;
            }
-         bufN = rlen;
          strm.avail_in = rlen;
          strm.next_in = buf;
        }
-      int
-       ret = BZ2_bzDecompress (&strm);
+
       if (ret != BZ_OK && ret != BZ_STREAM_END)
        {
          lasterr = ret;
@@ -119,7 +110,21 @@ compress_bz::read (void *buffer, size_t len)
        }
       if (ret == BZ_STREAM_END)
        {
-         endReached = 1;
+          /* Are we also at EOF? */
+          if (rlen == 0)
+            {
+              endReached = 1;
+            }
+          else
+            {
+              /* BZ_SSTREAM_END but not at EOF means the file contains
+                 another stream */
+              BZ2_bzDecompressEnd (&strm);
+              BZ2_bzDecompressInit (&(strm), 0, 0);
+              /* This doesn't reinitialize strm, so strm.next_in still
+                 points at strm.avail_in bytes left to decompress in buf */
+            }
+
          position += len - strm.avail_out;
          return len - strm.avail_out;
        }
diff --git a/compress_bz.h b/compress_bz.h
index 24f68a7..39a0d5b 100644
--- a/compress_bz.h
+++ b/compress_bz.h
@@ -64,7 +64,6 @@ private:
   bz_stream strm;
   int initialisedOk;
   int endReached;
-  int bufN;
   char buf[4096];
   int writing;
   size_t position;
-- 
1.7.4

Reply via email to