diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2021-06-04 12:16:55 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2021-06-04 12:16:55 +0200 |
commit | abcdc94c9939d6b085e2b76f76817df9be5fe2cc (patch) | |
tree | 290bd5e923cbdb5aef978ba5c9edb8ed65ff44da /lib/fstream | |
parent | 08612cbb353fca3f4cac1ae0a004d76f73ef878e (diff) |
Fix: allow concatenated Bzip2 streams
This is a followup to dd4e6ead142e58568aec89d76b0b2e867ee983f2.
Basically the same problem occours with Bzip2, but it so far it wasn't
possible to find a sampel that reproduces it.
Unlike libxz, the libbz2 API does not support concatenated streams by
itself and will choke when trying to decompress after the stream end,
so this commit adds a workaround to simply initialize the decompressor
on-the-fly and tear it down again when and end-of-stream is returned.
The end-of-file condition is only set when there actually is no more
data to read. Otherwise, the decompressor will be re-initialized in
the next round.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/fstream')
-rw-r--r-- | lib/fstream/uncompress/bzip2.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/lib/fstream/uncompress/bzip2.c b/lib/fstream/uncompress/bzip2.c index b5fae5c..429950a 100644 --- a/lib/fstream/uncompress/bzip2.c +++ b/lib/fstream/uncompress/bzip2.c @@ -11,6 +11,7 @@ typedef struct { istream_comp_t base; + bool initialized; bz_stream strm; } istream_bzip2_t; @@ -21,6 +22,17 @@ static int precache(istream_t *base) int ret; for (;;) { + if (!bzip2->initialized) { + if (BZ2_bzDecompressInit(&bzip2->strm, 0, 0) != BZ_OK) { + fprintf(stderr, "%s: error initializing " + "bzip2 decompressor.\n", + wrapped->get_filename(wrapped)); + return -1; + } + + bzip2->initialized = true; + } + ret = istream_precache(wrapped); if (ret != 0) return ret; @@ -48,8 +60,16 @@ static int precache(istream_t *base) bzip2->strm.avail_in; if (ret == BZ_STREAM_END) { - base->eof = true; - break; + if (istream_precache(wrapped)) + return -1; + + BZ2_bzDecompressEnd(&bzip2->strm); + bzip2->initialized = false; + + if (wrapped->buffer_used == 0) { + base->eof = true; + break; + } } } @@ -60,7 +80,8 @@ static void cleanup(istream_comp_t *base) { istream_bzip2_t *bzip2 = (istream_bzip2_t *)base; - BZ2_bzDecompressEnd(&bzip2->strm); + if (bzip2->initialized) + BZ2_bzDecompressEnd(&bzip2->strm); } istream_comp_t *istream_bzip2_create(const char *filename) @@ -74,13 +95,6 @@ istream_comp_t *istream_bzip2_create(const char *filename) return NULL; } - if (BZ2_bzDecompressInit(&bzip2->strm, 0, 0) != BZ_OK) { - fprintf(stderr, "%s: error initializing bzip2 decompressor.\n", - filename); - free(bzip2); - return NULL; - } - ((istream_t *)base)->precache = precache; base->cleanup = cleanup; return base; |