From c9f5cfd3df2706da940a39d6d816ad084ba80fbd Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Mon, 14 Sep 2020 14:59:31 +0200 Subject: Implement istream decompression support Signed-off-by: David Oberhollenzer --- lib/fstream/uncompress/xz.c | 93 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 lib/fstream/uncompress/xz.c (limited to 'lib/fstream/uncompress/xz.c') diff --git a/lib/fstream/uncompress/xz.c b/lib/fstream/uncompress/xz.c new file mode 100644 index 0000000..0e48468 --- /dev/null +++ b/lib/fstream/uncompress/xz.c @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * xz.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#include "../internal.h" + +#include + +typedef struct { + istream_comp_t base; + + lzma_stream strm; +} istream_xz_t; + +static int precache(istream_t *base) +{ + istream_xz_t *xz = (istream_xz_t *)base; + istream_t *wrapped = ((istream_comp_t *)base)->wrapped; + lzma_ret ret_xz; + int ret; + + for (;;) { + ret = istream_precache(wrapped); + if (ret != 0) + return ret; + + 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); + + base->buffer_used = BUFSZ - xz->strm.avail_out; + wrapped->buffer_offset = wrapped->buffer_used - + xz->strm.avail_in; + + if (ret_xz == LZMA_BUF_ERROR) + break; + + if (ret_xz == LZMA_STREAM_END) { + base->eof = true; + break; + } + + if (ret_xz != LZMA_OK) { + fprintf(stderr, + "%s: internal error in xz decoder.\n", + wrapped->get_filename(wrapped)); + return -1; + } + } + + return 0; +} + +static void cleanup(istream_comp_t *base) +{ + istream_xz_t *xz = (istream_xz_t *)base; + + lzma_end(&xz->strm); +} + +istream_comp_t *istream_xz_create(const char *filename) +{ + istream_xz_t *xz = calloc(1, sizeof(*xz)); + istream_comp_t *base = (istream_comp_t *)xz; + sqfs_u64 memlimit = 65 * 1024 * 1024; + lzma_ret ret_xz; + + if (xz == NULL) { + fprintf(stderr, "%s: creating xz decoder: %s.\n", + filename, strerror(errno)); + return NULL; + } + + ret_xz = lzma_stream_decoder(&xz->strm, memlimit, 0); + + if (ret_xz != LZMA_OK) { + fprintf(stderr, + "%s: error initializing xz decoder.\n", + filename); + free(xz); + return NULL; + } + + ((istream_t *)base)->precache = precache; + base->cleanup = cleanup; + return base; +} -- cgit v1.2.3