fix decompressing concatenated small files

pull/90/head
Dave Vasilevsky 4 years ago
parent 1d2cec0b61
commit 1aeb09b868

@ -74,7 +74,7 @@ typedef enum {
static rbuf_read_status rbuf_read(size_t bytes);
static bool rbuf_cycle(lzma_stream *stream, bool start, size_t skip);
static void rbuf_consume(size_t bytes);
static void rbuf_dispatch(void);
static void rbuf_dispatch(size_t bytes);
static bool read_header(lzma_check *check);
static bool read_block(bool force_stream, lzma_check check, off_t uoffset);
@ -300,13 +300,18 @@ static void block_capacity(io_block_t *ib, size_t incap, size_t outcap) {
}
}
// Get the next rbuf from the pipeline, and put it in gRbuf
static void rbuf_from_pipeline(void) {
queue_pop(gPipelineStartQ, (void**)&gRbufPI);
gRbuf = (io_block_t*)(gRbufPI->data);
gRbuf->insize = gRbuf->outsize = 0;
}
// Ensure at least this many bytes available
// Return 1 on success, zero on EOF, -1 on error
static rbuf_read_status rbuf_read(size_t bytes) {
if (!gRbufPI) {
queue_pop(gPipelineStartQ, (void**)&gRbufPI);
gRbuf = (io_block_t*)(gRbufPI->data);
gRbuf->insize = gRbuf->outsize = 0;
rbuf_from_pipeline();
}
if (gRbuf->insize >= bytes)
@ -339,10 +344,22 @@ static void rbuf_consume(size_t bytes) {
gRbuf->insize -= bytes;
}
static void rbuf_dispatch(void) {
pipeline_split(gRbufPI);
gRbufPI = NULL;
gRbuf = NULL;
static void rbuf_dispatch(size_t total_size) {
pipeline_item_t *prev_pi = gRbufPI;
if (gRbuf->insize > total_size) {
// We have extra data, get a place for it to live
io_block_t *prev_rbuf = gRbuf;
rbuf_from_pipeline();
size_t extra = prev_rbuf->insize - total_size;
block_capacity(gRbuf, extra, 0);
memcpy(gRbuf->input, prev_rbuf->input + total_size, extra);
gRbuf->insize = extra;
} else {
gRbufPI = NULL;
gRbuf = NULL;
}
pipeline_split(prev_pi);
}
@ -390,9 +407,10 @@ static bool read_block(bool force_stream, lzma_check check, off_t uoffset) {
gRbuf->check = check;
gRbuf->btype = BLOCK_SIZED;
if (rbuf_read(lzma_block_total_size(&block)) != RBUF_FULL)
size_t total_size = lzma_block_total_size(&block);
if (rbuf_read(total_size) != RBUF_FULL)
die("Error reading block contents");
rbuf_dispatch();
rbuf_dispatch(total_size);
}
return true;
}

@ -2,7 +2,8 @@ TESTS = \
compress-file-permissions.sh \
cppcheck-src.sh \
single-file-round-trip.sh \
xz-compatibility-c-option.sh
xz-compatibility-c-option.sh \
concatenated-small-files.sh
EXTRA_DIST = $(TESTS)

@ -0,0 +1,18 @@
#!/bin/sh
PIXZ=../src/pixz
F1=$(mktemp)
F2=$(mktemp)
EXPECTED=$(mktemp)
ACTUAL=$(mktemp)
trap "rm -f $F1 $F2 $EXPECTED $ACTUAL" EXIT
echo foo >> $EXPECTED
echo foo | $PIXZ > $F1
echo bar >> $EXPECTED
echo bar | $PIXZ > $F2
cat $F1 $F2 | $PIXZ -d > $ACTUAL
cmp $ACTUAL $EXPECTED
Loading…
Cancel
Save