Package: analog
Version: 2:6.0-17~lenny1
Severity: normal
Tags: patch

Multi-stream bz2 files are created if you concatenate two "normal" bz2
files. Analog's current code stops at the end of the first stream. This
happens without error, and simply shows up as an unexplained failure to
read to the end of the log file.

The attached patch checks if the end-of-stream is also the end-of-file,
and if not, it opens the next stream and continues on.

A workaround is to use
        UNCOMPRESS *.bz2 "bzcat"
in your configuration file, thus overriding the built-in bzip code.

-- System Information:
Debian Release: 5.0
  APT prefers stable
  APT policy: (500, 'stable')
Architecture: i386 (i686)

Kernel: Linux 2.6.26-1-686 (SMP w/2 CPU cores)
Locale: LANG=en_IE.UTF-8, LC_CTYPE=en_IE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages analog depends on:
ii  debconf [debconf-2.0]  1.5.24            Debian configuration management sy
ii  libbz2-1.0             1.0.5-1           high-quality block-sorting file co
ii  libc6                  2.7-18            GNU C Library: Shared libraries
ii  libgd2-xpm             2.0.36~rc1~dfsg-3 GD Graphics Library version 2
ii  libjpeg62              6b-14             The Independent JPEG Group's JPEG 
ii  libpcre3               7.6-2.1           Perl 5 Compatible Regular Expressi
ii  libpng12-0             1.2.27-2+lenny2   PNG library - runtime
ii  perl                   5.10.0-19         Larry Wall's Practical Extraction 
ii  zlib1g                 1:1.2.3.3.dfsg-12 compression library - runtime

analog recommends no packages.

Versions of packages analog suggests:
ii  apache2                  2.2.9-10+lenny2 Apache HTTP Server metapackage
ii  apache2-mpm-prefork [htt 2.2.9-10+lenny2 Apache HTTP Server - traditional n
pn  rmagic                   <none>          (no description available)

-- debconf information excluded
--- input.c.old	2004-12-19 13:51:30.000000000 +0000
+++ input.c	2009-04-02 10:07:38.000000000 +0100
@@ -377,6 +377,9 @@
 choice getmoredata(Logfile *lf, char *start, size_t length) {
 #ifndef LINE_PARSER
   int bze;
+  void* unusedPtr;
+  char* unusedData;
+  int unusedCount;
 #endif
   int n;
 
@@ -397,9 +400,53 @@
       n = 0;  /* unzReadCurrentFile() returns -1 on error */
     break;
   case LF_BZ2:
-    n = BZ2_bzRead(&bze, (BZFILE *)(lf->file2), (void *)start, length);
-    if (bze != BZ_OK && bze != BZ_STREAM_END)
-      n = 0;  /* return value from BZ2_bzRead() undefined on error */
+    n = 0;
+    // Multiple BZ2 streams may occur in a single file. If we reach the end of
+    // a stream before we have enough bytes, open the next stream and go again
+    while (n < length) {
+      n = n + BZ2_bzRead(&bze, (BZFILE *)(lf->file2), (void *)start + n, length - n);
+
+      if (bze != BZ_OK && bze != BZ_STREAM_END) {
+        n = 0;  /* return value from BZ2_bzRead() undefined on error */
+        break;
+      }
+
+      if (bze == BZ_STREAM_END) {
+        // Is this really the end of the file, or is there another stream?
+        // Check for "unused" data (see the bzip docs for what this is)
+        BZ2_bzReadGetUnused(&bze, (BZFILE *)(lf->file2), &unusedPtr, &unusedCount);
+        if (bze != BZ_OK) {
+          n = 0;  // Something's wrong, give up
+          break;
+        }
+
+        if (unusedCount == 0 && feof((FILE *)(lf->file))) {
+          break;  // Real end-of-file
+        }
+
+        // Put the unused data somewhere safe for a moment
+        unusedData = malloc(unusedCount);
+        memcpy(unusedData, unusedPtr, unusedCount);
+
+        // Close the old stream
+        BZ2_bzReadClose(&bze, (BZFILE *)(lf->file2));
+        if (bze != BZ_OK) {
+          n = 0;  // Something's wrong, give up
+          break;
+        }
+
+        // Open the new stream
+        lf->file2 = (void *)BZ2_bzReadOpen(&bze, (FILE *)(lf->file),
+                  0, 0, unusedData, unusedCount);
+        if (bze != BZ_OK || (BZFILE *)(lf->file2)==NULL) {
+          n = 0;  // Something's wrong, give up
+          break;
+        }
+
+        // Unused data is copied immediately by bzReadOpen
+        free(unusedData);
+      }
+    }
     break;
 #endif
   default:

Reply via email to