2
0
mirror of https://github.com/vasi/pixz synced 2024-10-30 15:21:41 +00:00

Merge pull request #90 from vasi/vasi-small-concat

fix decompressing concatenated small files
This commit is contained in:
Dave Vasilevsky 2020-11-15 17:44:33 -05:00 committed by GitHub
commit ec33de7b18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 11 deletions

View File

@ -74,7 +74,7 @@ typedef enum {
static rbuf_read_status rbuf_read(size_t bytes); static rbuf_read_status rbuf_read(size_t bytes);
static bool rbuf_cycle(lzma_stream *stream, bool start, size_t skip); static bool rbuf_cycle(lzma_stream *stream, bool start, size_t skip);
static void rbuf_consume(size_t bytes); 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_header(lzma_check *check);
static bool read_block(bool force_stream, lzma_check check, off_t uoffset); 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 // Ensure at least this many bytes available
// Return 1 on success, zero on EOF, -1 on error // Return 1 on success, zero on EOF, -1 on error
static rbuf_read_status rbuf_read(size_t bytes) { static rbuf_read_status rbuf_read(size_t bytes) {
if (!gRbufPI) { if (!gRbufPI) {
queue_pop(gPipelineStartQ, (void**)&gRbufPI); rbuf_from_pipeline();
gRbuf = (io_block_t*)(gRbufPI->data);
gRbuf->insize = gRbuf->outsize = 0;
} }
if (gRbuf->insize >= bytes) if (gRbuf->insize >= bytes)
@ -339,10 +344,22 @@ static void rbuf_consume(size_t bytes) {
gRbuf->insize -= bytes; gRbuf->insize -= bytes;
} }
static void rbuf_dispatch(void) { static void rbuf_dispatch(size_t total_size) {
pipeline_split(gRbufPI); pipeline_item_t *prev_pi = gRbufPI;
gRbufPI = NULL; if (gRbuf->insize > total_size) {
gRbuf = NULL; // 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->check = check;
gRbuf->btype = BLOCK_SIZED; 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"); die("Error reading block contents");
rbuf_dispatch(); rbuf_dispatch(total_size);
} }
return true; return true;
} }

View File

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

View File

@ -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