diff --git a/include/comp/compressor.h b/include/comp/compressor.h index 61f391f..34bc586 100644 --- a/include/comp/compressor.h +++ b/include/comp/compressor.h @@ -16,6 +16,10 @@ typedef struct compressor_stream_t { void (*flush)(struct compressor_stream_t *stream); + ssize_t (*do_block)(struct compressor_stream_t *stream, + const uint8_t *in, uint8_t *out, + size_t insize, size_t outsize); + void (*destroy)(struct compressor_stream_t *stream); } compressor_stream_t; diff --git a/lib/comp/lzma.c b/lib/comp/lzma.c index d4efad1..7fbb343 100644 --- a/lib/comp/lzma.c +++ b/lib/comp/lzma.c @@ -92,6 +92,62 @@ static void lzma_flush(compressor_stream_t *base) lzma->action = LZMA_FINISH; } +static ssize_t lzma_comp_block(compressor_stream_t *base, + const uint8_t *in, uint8_t *out, + size_t insize, size_t outsize) +{ + lzma_filter filters[5]; + lzma_options_lzma opt; + size_t written = 0; + lzma_ret ret; + (void)base; + + if (lzma_lzma_preset(&opt, LZMA_PRESET_DEFAULT)) { + fputs("error initializing LZMA options\n", stderr); + return -1; + } + + filters[0].id = LZMA_FILTER_LZMA2; + filters[0].options = &opt; + + filters[1].id = LZMA_VLI_UNKNOWN; + filters[1].options = NULL; + + ret = lzma_stream_buffer_encode(filters, LZMA_CHECK_CRC32, NULL, + in, insize, out, &written, outsize); + + if (ret == LZMA_OK) + return written; + + if (ret != LZMA_BUF_ERROR) { + fputs("lzma block compress failed\n", stderr); + return -1; + } + + return 0; +} + +static ssize_t lzma_uncomp_block(compressor_stream_t *base, + const uint8_t *in, uint8_t *out, + size_t insize, size_t outsize) +{ + uint64_t memlimit = 32 * 1024 * 1024; + size_t dest_pos = 0; + size_t src_pos = 0; + lzma_ret ret; + (void)base; + + ret = lzma_stream_buffer_decode(&memlimit, 0, NULL, + in, &src_pos, insize, + out, &dest_pos, outsize); + + if (ret == LZMA_OK && insize == src_pos) + return (ssize_t)dest_pos; + + fputs("lzma block extract failed\n", stderr); + return -1; +} + static void lzma_destroy(compressor_stream_t *base) { lzma_stream_t *lzma = (lzma_stream_t *)base; @@ -134,8 +190,12 @@ static compressor_stream_t *create_stream(bool compress) ret = lzma_stream_encoder(&lzma->strm, filters, LZMA_CHECK_CRC32); + + base->do_block = lzma_comp_block; } else { ret = lzma_stream_decoder(&lzma->strm, UINT64_MAX, 0); + + base->do_block = lzma_uncomp_block; } if (ret != LZMA_OK) diff --git a/lib/comp/none.c b/lib/comp/none.c index eb1341c..6d54e59 100644 --- a/lib/comp/none.c +++ b/lib/comp/none.c @@ -52,6 +52,19 @@ static ssize_t dummy_read(compressor_stream_t *base, return size; } +static ssize_t dummy_do_block(compressor_stream_t *base, + const uint8_t *in, uint8_t *out, + size_t insize, size_t outsize) +{ + (void)base; + + if (outsize < insize) + return 0; + + memcpy(out, in, insize); + return insize; +} + static void dummy_flush(compressor_stream_t *base) { (void)base; @@ -77,6 +90,7 @@ static compressor_stream_t *create_dummy_stream(compressor_t *cmp) base->write = dummy_write; base->read = dummy_read; base->flush = dummy_flush; + base->do_block = dummy_do_block; base->destroy = dummy_destroy; return base; } diff --git a/lib/comp/zlib.c b/lib/comp/zlib.c index 8e63796..7f54d2b 100644 --- a/lib/comp/zlib.c +++ b/lib/comp/zlib.c @@ -112,6 +112,46 @@ static void zlib_destroy(compressor_stream_t *base) free(zlib); } +static ssize_t zlib_do_block(compressor_stream_t *base, + const uint8_t *in, uint8_t *out, + size_t insize, size_t outsize) +{ + zlib_stream_t *zlib = (zlib_stream_t *)base; + int ret; + + if (zlib->compress) { + ret = deflateReset(&zlib->strm); + } else { + ret = inflateReset(&zlib->strm); + } + + if (ret != Z_OK) { + fputs("resetting zlib stream failed\n", stderr); + return -1; + } + + zlib->strm.next_in = (void *)in; + zlib->strm.avail_in = insize; + zlib->strm.next_out = out; + zlib->strm.avail_out = outsize; + + if (zlib->compress) { + ret = deflate(&zlib->strm, Z_FINISH); + } else { + ret = inflate(&zlib->strm, Z_FINISH); + } + + if (ret == Z_STREAM_END) + return (ssize_t)zlib->strm.total_out; + + if (ret != Z_OK) { + fputs("zlib block processing failed\n", stderr); + return -1; + } + + return 0; +} + static compressor_stream_t *create_stream(bool compress) { zlib_stream_t *zlib = calloc(1, sizeof(*zlib)); @@ -130,6 +170,7 @@ static compressor_stream_t *create_stream(bool compress) base->write = zlib_write; base->read = zlib_read; base->flush = zlib_flush; + base->do_block = zlib_do_block; base->destroy = zlib_destroy; if (compress) {