From dd4e6ead142e58568aec89d76b0b2e867ee983f2 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 6 May 2021 13:10:54 +0200 Subject: Fix: allow concatenated xz streams Some xz compressed tarballs (e.g. from kernel.org) are not made up of a single xz stream, but rather contain several, independendly compressed streams. In that case, the xz decompressor hits an LZMA_STREAM_END early on and reports EOF. If you are lucky, the tar reader bails (premature end-of-file). If you are unlucky, it happens exactely between two records and is interpeted as regular end-of-file. As this seems to be a normal use case for xz, it has a flag to just read across the seams and only report end-of-stream if the action is set to finish. This commit adds the flag to the initialization propperly sets the lzma_action depending on whether the underlying stream hit EOF or not. Signed-off-by: David Oberhollenzer --- lib/fstream/uncompress/xz.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/fstream/uncompress/xz.c b/lib/fstream/uncompress/xz.c index 0e48468..0fd9ce6 100644 --- a/lib/fstream/uncompress/xz.c +++ b/lib/fstream/uncompress/xz.c @@ -18,6 +18,7 @@ static int precache(istream_t *base) { istream_xz_t *xz = (istream_xz_t *)base; istream_t *wrapped = ((istream_comp_t *)base)->wrapped; + lzma_action action; lzma_ret ret_xz; int ret; @@ -26,13 +27,15 @@ static int precache(istream_t *base) if (ret != 0) return ret; + action = wrapped->eof ? LZMA_FINISH : LZMA_RUN; + xz->strm.avail_in = wrapped->buffer_used; xz->strm.next_in = wrapped->buffer; xz->strm.avail_out = BUFSZ - base->buffer_used; xz->strm.next_out = base->buffer + base->buffer_used; - ret_xz = lzma_code(&xz->strm, LZMA_RUN); + ret_xz = lzma_code(&xz->strm, action); base->buffer_used = BUFSZ - xz->strm.avail_out; wrapped->buffer_offset = wrapped->buffer_used - @@ -77,7 +80,7 @@ istream_comp_t *istream_xz_create(const char *filename) return NULL; } - ret_xz = lzma_stream_decoder(&xz->strm, memlimit, 0); + ret_xz = lzma_stream_decoder(&xz->strm, memlimit, LZMA_CONCATENATED); if (ret_xz != LZMA_OK) { fprintf(stderr, -- cgit v1.2.3