aboutsummaryrefslogtreecommitdiff
path: root/lib/io
diff options
context:
space:
mode:
Diffstat (limited to 'lib/io')
-rw-r--r--lib/io/Makemodule.am30
-rw-r--r--lib/io/compress/bzip2.c96
-rw-r--r--lib/io/compress/gzip.c92
-rw-r--r--lib/io/compress/ostream_compressor.c106
-rw-r--r--lib/io/compress/xz.c80
-rw-r--r--lib/io/compress/zstd.c94
-rw-r--r--lib/io/internal.h52
-rw-r--r--lib/io/uncompress/autodetect.c55
-rw-r--r--lib/io/uncompress/bzip2.c118
-rw-r--r--lib/io/uncompress/gzip.c91
-rw-r--r--lib/io/uncompress/istream_compressor.c67
-rw-r--r--lib/io/uncompress/xz.c96
-rw-r--r--lib/io/uncompress/zstd.c81
-rw-r--r--lib/io/xfrm.c67
-rw-r--r--lib/io/xfrm/istream.c106
-rw-r--r--lib/io/xfrm/ostream.c144
16 files changed, 253 insertions, 1122 deletions
diff --git a/lib/io/Makemodule.am b/lib/io/Makemodule.am
index 63ce958..918ce50 100644
--- a/lib/io/Makemodule.am
+++ b/lib/io/Makemodule.am
@@ -1,11 +1,8 @@
libio_a_SOURCES = lib/io/internal.h
libio_a_SOURCES += include/io/istream.h lib/io/ostream.c lib/io/printf.c
libio_a_SOURCES += include/io/ostream.h lib/io/istream.c lib/io/get_line.c
-libio_a_SOURCES += include/io/xfrm.h lib/io/xfrm.c
-libio_a_SOURCES += include/io/file.h include/io/std.h
-libio_a_SOURCES += lib/io/compress/ostream_compressor.c
-libio_a_SOURCES += lib/io/uncompress/istream_compressor.c
-libio_a_SOURCES += lib/io/uncompress/autodetect.c
+libio_a_SOURCES += include/io/xfrm.h include/io/file.h include/io/std.h
+libio_a_SOURCES += lib/io/xfrm/ostream.c lib/io/xfrm/istream.c
libio_a_CFLAGS = $(AM_CFLAGS) $(ZLIB_CFLAGS) $(XZ_CFLAGS)
libio_a_CFLAGS += $(ZSTD_CFLAGS) $(BZIP2_CFLAGS)
libio_a_CPPFLAGS = $(AM_CPPFLAGS)
@@ -19,27 +16,4 @@ libio_a_SOURCES += lib/io/unix/ostream.c
libio_a_SOURCES += lib/io/unix/istream.c
endif
-if WITH_XZ
-libio_a_SOURCES += lib/io/compress/xz.c lib/io/uncompress/xz.c
-libio_a_CPPFLAGS += -DWITH_XZ
-endif
-
-if WITH_GZIP
-libio_a_SOURCES += lib/io/compress/gzip.c
-libio_a_SOURCES += lib/io/uncompress/gzip.c
-libio_a_CPPFLAGS += -DWITH_GZIP
-endif
-
-if WITH_ZSTD
-libio_a_SOURCES += lib/io/compress/zstd.c
-libio_a_SOURCES += lib/io/uncompress/zstd.c
-libio_a_CPPFLAGS += -DWITH_ZSTD
-endif
-
-if WITH_BZIP2
-libio_a_SOURCES += lib/io/compress/bzip2.c
-libio_a_SOURCES += lib/io/uncompress/bzip2.c
-libio_a_CPPFLAGS += -DWITH_BZIP2
-endif
-
noinst_LIBRARIES += libio.a
diff --git a/lib/io/compress/bzip2.c b/lib/io/compress/bzip2.c
deleted file mode 100644
index 7f0c09a..0000000
--- a/lib/io/compress/bzip2.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * bzip2.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "../internal.h"
-
-#include <bzlib.h>
-
-typedef struct {
- ostream_comp_t base;
-
- bz_stream strm;
-} ostream_bzip2_t;
-
-static int flush_inbuf(ostream_comp_t *base, bool finish)
-{
- ostream_bzip2_t *bzip2 = (ostream_bzip2_t *)base;
- size_t have;
- int ret;
-
- bzip2->strm.next_in = (char *)base->inbuf;
-
- if (base->inbuf_used > sizeof(base->inbuf))
- base->inbuf_used = sizeof(base->inbuf);
-
- if ((sizeof(size_t) > sizeof(unsigned int)) &&
- (base->inbuf_used > (size_t)UINT_MAX)) {
- bzip2->strm.avail_in = UINT_MAX;
- } else {
- bzip2->strm.avail_in = (unsigned int)base->inbuf_used;
- }
-
- for (;;) {
- bzip2->strm.next_out = (char *)base->outbuf;
- bzip2->strm.avail_out = sizeof(base->outbuf);
-
- ret = BZ2_bzCompress(&bzip2->strm, finish ? BZ_FINISH : BZ_RUN);
-
- if (ret < 0 && ret != BZ_OUTBUFF_FULL) {
- fprintf(stderr, "%s: internal error in bzip2 "
- "compressor.\n",
- base->wrapped->get_filename(base->wrapped));
- return -1;
- }
-
- have = sizeof(base->outbuf) - bzip2->strm.avail_out;
-
- if (base->wrapped->append(base->wrapped, base->outbuf, have))
- return -1;
-
- if (ret == BZ_STREAM_END || ret == BZ_OUTBUFF_FULL ||
- bzip2->strm.avail_in == 0) {
- break;
- }
- }
-
- if (bzip2->strm.avail_in > 0) {
- memmove(base->inbuf, bzip2->strm.next_in,
- bzip2->strm.avail_in);
- }
-
- base->inbuf_used = bzip2->strm.avail_in;
- return 0;
-}
-
-static void cleanup(ostream_comp_t *base)
-{
- ostream_bzip2_t *bzip2 = (ostream_bzip2_t *)base;
-
- BZ2_bzCompressEnd(&bzip2->strm);
-}
-
-ostream_comp_t *ostream_bzip2_create(const char *filename)
-{
- ostream_bzip2_t *bzip2 = calloc(1, sizeof(*bzip2));
- ostream_comp_t *base = (ostream_comp_t *)bzip2;
-
- if (bzip2 == NULL) {
- fprintf(stderr, "%s: creating bzip2 compressor: %s.\n",
- filename, strerror(errno));
- return NULL;
- }
-
- if (BZ2_bzCompressInit(&bzip2->strm, 9, 0, 30) != BZ_OK) {
- fprintf(stderr, "%s: error initializing bzip2 compressor.\n",
- filename);
- free(bzip2);
- return NULL;
- }
-
- base->flush_inbuf = flush_inbuf;
- base->cleanup = cleanup;
- return base;
-}
diff --git a/lib/io/compress/gzip.c b/lib/io/compress/gzip.c
deleted file mode 100644
index b73a258..0000000
--- a/lib/io/compress/gzip.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * gzip.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "../internal.h"
-
-#include <zlib.h>
-
-typedef struct {
- ostream_comp_t base;
-
- z_stream strm;
-} ostream_gzip_t;
-
-static int flush_inbuf(ostream_comp_t *base, bool finish)
-{
- ostream_gzip_t *gzip = (ostream_gzip_t *)base;
- size_t have;
- int ret;
-
- if (base->inbuf_used > sizeof(base->inbuf))
- base->inbuf_used = sizeof(base->inbuf);
-
- if (sizeof(size_t) > sizeof(uInt)) {
- gzip->strm.avail_in = ~((uInt)0);
-
- if ((size_t)gzip->strm.avail_in > base->inbuf_used)
- gzip->strm.avail_in = (uInt)base->inbuf_used;
- } else {
- gzip->strm.avail_in = (uInt)base->inbuf_used;
- }
-
- gzip->strm.next_in = base->inbuf;
-
- do {
- gzip->strm.avail_out = BUFSZ;
- gzip->strm.next_out = base->outbuf;
-
- ret = deflate(&gzip->strm, finish ? Z_FINISH : Z_NO_FLUSH);
-
- if (ret == Z_STREAM_ERROR) {
- fprintf(stderr,
- "%s: internal error in gzip compressor.\n",
- base->wrapped->get_filename(base->wrapped));
- return -1;
- }
-
- have = BUFSZ - gzip->strm.avail_out;
-
- if (base->wrapped->append(base->wrapped, base->outbuf, have))
- return -1;
- } while (gzip->strm.avail_out == 0);
-
- base->inbuf_used = 0;
- return 0;
-}
-
-static void cleanup(ostream_comp_t *base)
-{
- ostream_gzip_t *gzip = (ostream_gzip_t *)base;
-
- deflateEnd(&gzip->strm);
-}
-
-ostream_comp_t *ostream_gzip_create(const char *filename)
-{
- ostream_gzip_t *gzip = calloc(1, sizeof(*gzip));
- ostream_comp_t *base = (ostream_comp_t *)gzip;
- int ret;
-
- if (gzip == NULL) {
- fprintf(stderr, "%s: creating gzip wrapper: %s.\n",
- filename, strerror(errno));
- return NULL;
- }
-
- ret = deflateInit2(&gzip->strm, 9, Z_DEFLATED, 16 + 15, 8,
- Z_DEFAULT_STRATEGY);
- if (ret != Z_OK) {
- fprintf(stderr,
- "%s: internal error creating gzip compressor.\n",
- filename);
- free(gzip);
- return NULL;
- }
-
- base->flush_inbuf = flush_inbuf;
- base->cleanup = cleanup;
- return base;
-}
diff --git a/lib/io/compress/ostream_compressor.c b/lib/io/compress/ostream_compressor.c
deleted file mode 100644
index a5f16d5..0000000
--- a/lib/io/compress/ostream_compressor.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * ostream_compressor.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "../internal.h"
-
-static int comp_append(ostream_t *strm, const void *data, size_t size)
-{
- ostream_comp_t *comp = (ostream_comp_t *)strm;
- size_t diff;
-
- while (size > 0) {
- if (comp->inbuf_used >= BUFSZ) {
- if (comp->flush_inbuf(comp, false))
- return -1;
- }
-
- diff = BUFSZ - comp->inbuf_used;
-
- if (diff > size)
- diff = size;
-
- memcpy(comp->inbuf + comp->inbuf_used, data, diff);
-
- comp->inbuf_used += diff;
- data = (const char *)data + diff;
- size -= diff;
- }
-
- return 0;
-}
-
-static int comp_flush(ostream_t *strm)
-{
- ostream_comp_t *comp = (ostream_comp_t *)strm;
-
- if (comp->inbuf_used > 0) {
- if (comp->flush_inbuf(comp, true))
- return -1;
- }
-
- return comp->wrapped->flush(comp->wrapped);
-}
-
-static const char *comp_get_filename(ostream_t *strm)
-{
- ostream_comp_t *comp = (ostream_comp_t *)strm;
-
- return comp->wrapped->get_filename(comp->wrapped);
-}
-
-static void comp_destroy(sqfs_object_t *obj)
-{
- ostream_comp_t *comp = (ostream_comp_t *)obj;
-
- comp->cleanup(comp);
- sqfs_drop(comp->wrapped);
- free(comp);
-}
-
-ostream_t *ostream_compressor_create(ostream_t *strm, int comp_id)
-{
- ostream_comp_t *comp = NULL;
- ostream_t *base;
-
- switch (comp_id) {
- case IO_COMPRESSOR_GZIP:
-#ifdef WITH_GZIP
- comp = ostream_gzip_create(strm->get_filename(strm));
-#endif
- break;
- case IO_COMPRESSOR_XZ:
-#ifdef WITH_XZ
- comp = ostream_xz_create(strm->get_filename(strm));
-#endif
- break;
- case IO_COMPRESSOR_ZSTD:
-#if defined(WITH_ZSTD) && defined(HAVE_ZSTD_STREAM)
- comp = ostream_zstd_create(strm->get_filename(strm));
-#endif
- break;
- case IO_COMPRESSOR_BZIP2:
-#ifdef WITH_BZIP2
- comp = ostream_bzip2_create(strm->get_filename(strm));
-#endif
- break;
- default:
- break;
- }
-
- if (comp == NULL)
- return NULL;
-
- sqfs_object_init(comp, comp_destroy, NULL);
-
- comp->wrapped = sqfs_grab(strm);
- comp->inbuf_used = 0;
-
- base = (ostream_t *)comp;
- base->append = comp_append;
- base->flush = comp_flush;
- base->get_filename = comp_get_filename;
- return base;
-}
diff --git a/lib/io/compress/xz.c b/lib/io/compress/xz.c
deleted file mode 100644
index 65bda0b..0000000
--- a/lib/io/compress/xz.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * xz.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "../internal.h"
-
-#include <lzma.h>
-
-typedef struct {
- ostream_comp_t base;
-
- lzma_stream strm;
-} ostream_xz_t;
-
-static int flush_inbuf(ostream_comp_t *base, bool finish)
-{
- ostream_xz_t *xz = (ostream_xz_t *)base;
- lzma_ret ret_xz;
- size_t have;
-
- xz->strm.next_in = base->inbuf;
- xz->strm.avail_in = base->inbuf_used;
-
- do {
- xz->strm.next_out = base->outbuf;
- xz->strm.avail_out = BUFSZ;
-
- ret_xz = lzma_code(&xz->strm, finish ? LZMA_FINISH : LZMA_RUN);
-
- if ((ret_xz != LZMA_OK) && (ret_xz != LZMA_STREAM_END)) {
- fprintf(stderr,
- "%s: internal error in XZ compressor.\n",
- base->wrapped->get_filename(base->wrapped));
- return -1;
- }
-
- have = BUFSZ - xz->strm.avail_out;
-
- if (base->wrapped->append(base->wrapped, base->outbuf, have))
- return -1;
- } while (xz->strm.avail_out == 0);
-
- base->inbuf_used = 0;
- return 0;
-}
-
-static void cleanup(ostream_comp_t *base)
-{
- ostream_xz_t *xz = (ostream_xz_t *)base;
-
- lzma_end(&xz->strm);
-}
-
-ostream_comp_t *ostream_xz_create(const char *filename)
-{
- ostream_xz_t *xz = calloc(1, sizeof(*xz));
- ostream_comp_t *base = (ostream_comp_t *)xz;
- lzma_ret ret_xz;
-
- if (xz == NULL) {
- fprintf(stderr, "%s: creating xz wrapper: %s.\n",
- filename, strerror(errno));
- return NULL;
- }
-
- ret_xz = lzma_easy_encoder(&xz->strm, LZMA_PRESET_DEFAULT,
- LZMA_CHECK_CRC64);
- if (ret_xz != LZMA_OK) {
- fprintf(stderr, "%s: error initializing XZ compressor\n",
- filename);
- free(xz);
- return NULL;
- }
-
- base->flush_inbuf = flush_inbuf;
- base->cleanup = cleanup;
- return base;
-}
diff --git a/lib/io/compress/zstd.c b/lib/io/compress/zstd.c
deleted file mode 100644
index c0b002e..0000000
--- a/lib/io/compress/zstd.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * zstd.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "../internal.h"
-
-#include <zstd.h>
-
-#ifdef HAVE_ZSTD_STREAM
-typedef struct {
- ostream_comp_t base;
-
- ZSTD_CStream *strm;
-} ostream_zstd_t;
-
-static int flush_inbuf(ostream_comp_t *base, bool finish)
-{
- ostream_zstd_t *zstd = (ostream_zstd_t *)base;
- ZSTD_EndDirective op;
- ZSTD_outBuffer out;
- ZSTD_inBuffer in;
- size_t ret;
-
- op = finish ? ZSTD_e_end : ZSTD_e_continue;
-
- do {
- memset(&in, 0, sizeof(in));
- memset(&out, 0, sizeof(out));
-
- in.src = base->inbuf;
- in.size = base->inbuf_used;
-
- out.dst = base->outbuf;
- out.size = BUFSZ;
-
- ret = ZSTD_compressStream2(zstd->strm, &out, &in, op);
-
- if (ZSTD_isError(ret)) {
- fprintf(stderr, "%s: error in zstd compressor.\n",
- base->wrapped->get_filename(base->wrapped));
- return -1;
- }
-
- if (base->wrapped->append(base->wrapped, base->outbuf,
- out.pos)) {
- return -1;
- }
-
- if (in.pos < in.size) {
- base->inbuf_used = in.size - in.pos;
-
- memmove(base->inbuf, base->inbuf + in.pos,
- base->inbuf_used);
- } else {
- base->inbuf_used = 0;
- }
- } while (finish && ret != 0);
-
- return 0;
-}
-
-static void cleanup(ostream_comp_t *base)
-{
- ostream_zstd_t *zstd = (ostream_zstd_t *)base;
-
- ZSTD_freeCStream(zstd->strm);
-}
-
-ostream_comp_t *ostream_zstd_create(const char *filename)
-{
- ostream_zstd_t *zstd = calloc(1, sizeof(*zstd));
- ostream_comp_t *base = (ostream_comp_t *)zstd;
-
- if (zstd == NULL) {
- fprintf(stderr, "%s: creating zstd wrapper: %s.\n",
- filename, strerror(errno));
- return NULL;
- }
-
- zstd->strm = ZSTD_createCStream();
- if (zstd->strm == NULL) {
- fprintf(stderr, "%s: error creating zstd decoder.\n",
- filename);
- free(zstd);
- return NULL;
- }
-
- base->flush_inbuf = flush_inbuf;
- base->cleanup = cleanup;
- return base;
-}
-#endif /* HAVE_ZSTD_STREAM */
diff --git a/lib/io/internal.h b/lib/io/internal.h
index 4ac38f5..25a0196 100644
--- a/lib/io/internal.h
+++ b/lib/io/internal.h
@@ -14,6 +14,7 @@
#include "io/file.h"
#include "io/xfrm.h"
#include "io/std.h"
+#include "xfrm/compress.h"
#include <string.h>
#include <stdlib.h>
@@ -27,55 +28,4 @@
#define BUFSZ (262144)
-typedef struct ostream_comp_t {
- ostream_t base;
-
- ostream_t *wrapped;
-
- size_t inbuf_used;
-
- sqfs_u8 inbuf[BUFSZ];
- sqfs_u8 outbuf[BUFSZ];
-
- int (*flush_inbuf)(struct ostream_comp_t *ostrm, bool finish);
-
- void (*cleanup)(struct ostream_comp_t *ostrm);
-} ostream_comp_t;
-
-typedef struct istream_comp_t {
- istream_t base;
-
- istream_t *wrapped;
-
- sqfs_u8 uncompressed[BUFSZ];
-
- bool eof;
-
- void (*cleanup)(struct istream_comp_t *strm);
-} istream_comp_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-SQFS_INTERNAL ostream_comp_t *ostream_gzip_create(const char *filename);
-
-SQFS_INTERNAL ostream_comp_t *ostream_xz_create(const char *filename);
-
-SQFS_INTERNAL ostream_comp_t *ostream_zstd_create(const char *filename);
-
-SQFS_INTERNAL ostream_comp_t *ostream_bzip2_create(const char *filename);
-
-SQFS_INTERNAL istream_comp_t *istream_gzip_create(const char *filename);
-
-SQFS_INTERNAL istream_comp_t *istream_xz_create(const char *filename);
-
-SQFS_INTERNAL istream_comp_t *istream_zstd_create(const char *filename);
-
-SQFS_INTERNAL istream_comp_t *istream_bzip2_create(const char *filename);
-
-#ifdef __cplusplus
-}
-#endif
-
#endif /* INTERNAL_H */
diff --git a/lib/io/uncompress/autodetect.c b/lib/io/uncompress/autodetect.c
deleted file mode 100644
index dde33c8..0000000
--- a/lib/io/uncompress/autodetect.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * autodetect.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "../internal.h"
-
-static const struct {
- int id;
- const sqfs_u8 *value;
- size_t len;
-} magic[] = {
- { IO_COMPRESSOR_GZIP, (const sqfs_u8 *)"\x1F\x8B\x08", 3 },
- { IO_COMPRESSOR_XZ, (const sqfs_u8 *)("\xFD" "7zXZ"), 6 },
- { IO_COMPRESSOR_ZSTD, (const sqfs_u8 *)"\x28\xB5\x2F\xFD", 4 },
- { IO_COMPRESSOR_BZIP2, (const sqfs_u8 *)"BZh", 3 },
-};
-
-int istream_detect_compressor(istream_t *strm,
- int (*probe)(const sqfs_u8 *data, size_t size))
-{
- size_t i;
- int ret;
-
- ret = istream_precache(strm);
- if (ret != 0)
- return ret;
-
- if (probe != NULL) {
- ret = probe(strm->buffer + strm->buffer_offset,
- strm->buffer_used - strm->buffer_offset);
- if (ret < 0)
- return ret;
-
- /* XXX: this means the data is uncompressed. We do this check
- first since it might be perfectly OK for the uncompressed
- data to contain a magic number from the table. */
- if (ret > 0)
- return 0;
- }
-
- for (i = 0; i < sizeof(magic) / sizeof(magic[0]); ++i) {
- if ((strm->buffer_used - strm->buffer_offset) < magic[i].len)
- continue;
-
- ret = memcmp(strm->buffer + strm->buffer_offset,
- magic[i].value, magic[i].len);
-
- if (ret == 0)
- return magic[i].id;
- }
-
- return 0;
-}
diff --git a/lib/io/uncompress/bzip2.c b/lib/io/uncompress/bzip2.c
deleted file mode 100644
index 3b44383..0000000
--- a/lib/io/uncompress/bzip2.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * bzip2.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "../internal.h"
-
-#include <bzlib.h>
-
-typedef struct {
- istream_comp_t base;
-
- bool initialized;
- bz_stream strm;
-} istream_bzip2_t;
-
-static int precache(istream_t *base)
-{
- istream_bzip2_t *bzip2 = (istream_bzip2_t *)base;
- istream_t *wrapped = ((istream_comp_t *)base)->wrapped;
- size_t avail;
- int ret;
-
- for (;;) {
- if (!bzip2->initialized) {
- if (BZ2_bzDecompressInit(&bzip2->strm, 0, 0) != BZ_OK) {
- fprintf(stderr, "%s: error initializing "
- "bzip2 decompressor.\n",
- wrapped->get_filename(wrapped));
- return -1;
- }
-
- bzip2->initialized = true;
- }
-
- ret = istream_precache(wrapped);
- if (ret != 0)
- return ret;
-
- avail = wrapped->buffer_used;
- if ((sizeof(size_t) > sizeof(unsigned int)) &&
- (avail > (size_t)UINT_MAX)) {
- avail = UINT_MAX;
- }
-
- bzip2->strm.next_in = (char *)wrapped->buffer;
- bzip2->strm.avail_in = (unsigned int)avail;
-
- if (base->buffer_used > BUFSZ)
- base->buffer_used = BUFSZ;
-
- avail = BUFSZ - base->buffer_used;
-
- if ((sizeof(size_t) > sizeof(unsigned int)) &&
- (avail > (size_t)UINT_MAX)) {
- avail = UINT_MAX;
- }
-
- bzip2->strm.next_out = (char *)base->buffer + base->buffer_used;
- bzip2->strm.avail_out = (unsigned int)avail;
-
- if (bzip2->strm.avail_out < 1)
- break;
-
- ret = BZ2_bzDecompress(&bzip2->strm);
-
- if (ret < 0) {
- fprintf(stderr, "%s: internal error in bzip2 "
- "decompressor.\n",
- wrapped->get_filename(wrapped));
- return -1;
- }
-
- base->buffer_used = BUFSZ - bzip2->strm.avail_out;
- wrapped->buffer_offset = wrapped->buffer_used -
- bzip2->strm.avail_in;
-
- if (ret == BZ_STREAM_END) {
- if (istream_precache(wrapped))
- return -1;
-
- BZ2_bzDecompressEnd(&bzip2->strm);
- bzip2->initialized = false;
-
- if (wrapped->buffer_used == 0) {
- base->eof = true;
- break;
- }
- }
- }
-
- return 0;
-}
-
-static void cleanup(istream_comp_t *base)
-{
- istream_bzip2_t *bzip2 = (istream_bzip2_t *)base;
-
- if (bzip2->initialized)
- BZ2_bzDecompressEnd(&bzip2->strm);
-}
-
-istream_comp_t *istream_bzip2_create(const char *filename)
-{
- istream_bzip2_t *bzip2 = calloc(1, sizeof(*bzip2));
- istream_comp_t *base = (istream_comp_t *)bzip2;
-
- if (bzip2 == NULL) {
- fprintf(stderr, "%s: creating bzip2 compressor: %s.\n",
- filename, strerror(errno));
- return NULL;
- }
-
- ((istream_t *)base)->precache = precache;
- base->cleanup = cleanup;
- return base;
-}
diff --git a/lib/io/uncompress/gzip.c b/lib/io/uncompress/gzip.c
deleted file mode 100644
index bce7f0a..0000000
--- a/lib/io/uncompress/gzip.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * gzip.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "../internal.h"
-
-#include <zlib.h>
-
-typedef struct {
- istream_comp_t base;
-
- z_stream strm;
-} istream_gzip_t;
-
-static int precache(istream_t *base)
-{
- istream_t *wrapped = ((istream_comp_t *)base)->wrapped;
- istream_gzip_t *gzip = (istream_gzip_t *)base;
- int ret;
-
- for (;;) {
- ret = istream_precache(wrapped);
- if (ret != 0)
- return ret;
-
- gzip->strm.avail_in = (uInt)wrapped->buffer_used;
- gzip->strm.avail_out = (uInt)(BUFSZ - base->buffer_used);
-
- gzip->strm.next_in = wrapped->buffer;
- gzip->strm.next_out = base->buffer + base->buffer_used;
-
- ret = inflate(&gzip->strm, Z_NO_FLUSH);
-
- wrapped->buffer_offset = wrapped->buffer_used -
- gzip->strm.avail_in;
-
- base->buffer_used = BUFSZ - gzip->strm.avail_out;
-
- if (ret == Z_BUF_ERROR)
- break;
-
- if (ret == Z_STREAM_END) {
- base->eof = true;
- break;
- }
-
- if (ret != Z_OK) {
- fprintf(stderr,
- "%s: internal error in gzip decoder.\n",
- wrapped->get_filename(wrapped));
- return -1;
- }
- }
-
- return 0;
-}
-
-static void cleanup(istream_comp_t *base)
-{
- istream_gzip_t *gzip = (istream_gzip_t *)base;
-
- inflateEnd(&gzip->strm);
-}
-
-istream_comp_t *istream_gzip_create(const char *filename)
-{
- istream_gzip_t *gzip = calloc(1, sizeof(*gzip));
- istream_comp_t *base = (istream_comp_t *)gzip;
- int ret;
-
- if (gzip == NULL) {
- fprintf(stderr, "%s: creating gzip decoder: %s.\n",
- filename, strerror(errno));
- return NULL;
- }
-
- ret = inflateInit2(&gzip->strm, 16 + 15);
- if (ret != Z_OK) {
- fprintf(stderr,
- "%s: internal error creating gzip reader.\n",
- filename);
- free(gzip);
- return NULL;
- }
-
- ((istream_t *)base)->precache = precache;
- base->cleanup = cleanup;
- return base;
-}
diff --git a/lib/io/uncompress/istream_compressor.c b/lib/io/uncompress/istream_compressor.c
deleted file mode 100644
index d4e1aea..0000000
--- a/lib/io/uncompress/istream_compressor.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * istream_compressor.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "../internal.h"
-
-static const char *comp_get_filename(istream_t *strm)
-{
- istream_comp_t *comp = (istream_comp_t *)strm;
-
- return comp->wrapped->get_filename(comp->wrapped);
-}
-
-static void comp_destroy(sqfs_object_t *obj)
-{
- istream_comp_t *comp = (istream_comp_t *)obj;
-
- comp->cleanup(comp);
- sqfs_drop(comp->wrapped);
- free(comp);
-}
-
-istream_t *istream_compressor_create(istream_t *strm, int comp_id)
-{
- istream_comp_t *comp = NULL;
- istream_t *base;
-
- switch (comp_id) {
- case IO_COMPRESSOR_GZIP:
-#ifdef WITH_GZIP
- comp = istream_gzip_create(strm->get_filename(strm));
-#endif
- break;
- case IO_COMPRESSOR_XZ:
-#ifdef WITH_XZ
- comp = istream_xz_create(strm->get_filename(strm));
-#endif
- break;
- case IO_COMPRESSOR_ZSTD:
-#if defined(WITH_ZSTD) && defined(HAVE_ZSTD_STREAM)
- comp = istream_zstd_create(strm->get_filename(strm));
-#endif
- break;
- case IO_COMPRESSOR_BZIP2:
-#ifdef WITH_BZIP2
- comp = istream_bzip2_create(strm->get_filename(strm));
-#endif
- break;
- default:
- break;
- }
-
- if (comp == NULL)
- return NULL;
-
- sqfs_object_init(comp, comp_destroy, NULL);
-
- comp->wrapped = sqfs_grab(strm);
-
- base = (istream_t *)comp;
- base->get_filename = comp_get_filename;
- base->buffer = comp->uncompressed;
- base->eof = false;
- return base;
-}
diff --git a/lib/io/uncompress/xz.c b/lib/io/uncompress/xz.c
deleted file mode 100644
index 0fd9ce6..0000000
--- a/lib/io/uncompress/xz.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * xz.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "../internal.h"
-
-#include <lzma.h>
-
-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_action action;
- lzma_ret ret_xz;
- int ret;
-
- for (;;) {
- ret = istream_precache(wrapped);
- 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, action);
-
- 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, LZMA_CONCATENATED);
-
- 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;
-}
diff --git a/lib/io/uncompress/zstd.c b/lib/io/uncompress/zstd.c
deleted file mode 100644
index fd22cbf..0000000
--- a/lib/io/uncompress/zstd.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * zstd.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "../internal.h"
-
-#include <zstd.h>
-
-#ifdef HAVE_ZSTD_STREAM
-typedef struct {
- istream_comp_t base;
-
- ZSTD_DStream* strm;
-} istream_zstd_t;
-
-static int precache(istream_t *base)
-{
- istream_zstd_t *zstd = (istream_zstd_t *)base;
- istream_t *wrapped = ((istream_comp_t *)base)->wrapped;
- ZSTD_outBuffer out;
- ZSTD_inBuffer in;
- size_t ret;
-
- if (istream_precache(wrapped))
- return -1;
-
- memset(&in, 0, sizeof(in));
- memset(&out, 0, sizeof(out));
-
- in.src = wrapped->buffer;
- in.size = wrapped->buffer_used;
-
- out.dst = ((istream_comp_t *)base)->uncompressed + base->buffer_used;
- out.size = BUFSZ - base->buffer_used;
-
- ret = ZSTD_decompressStream(zstd->strm, &out, &in);
-
- if (ZSTD_isError(ret)) {
- fprintf(stderr, "%s: error in zstd decoder.\n",
- wrapped->get_filename(wrapped));
- return -1;
- }
-
- wrapped->buffer_offset = in.pos;
- base->buffer_used += out.pos;
- return 0;
-}
-
-static void cleanup(istream_comp_t *base)
-{
- istream_zstd_t *zstd = (istream_zstd_t *)base;
-
- ZSTD_freeDStream(zstd->strm);
-}
-
-istream_comp_t *istream_zstd_create(const char *filename)
-{
- istream_zstd_t *zstd = calloc(1, sizeof(*zstd));
- istream_comp_t *base = (istream_comp_t *)zstd;
-
- if (zstd == NULL) {
- fprintf(stderr, "%s: creating zstd decoder: %s.\n",
- filename, strerror(errno));
- return NULL;
- }
-
- zstd->strm = ZSTD_createDStream();
- if (zstd->strm == NULL) {
- fprintf(stderr, "%s: error creating zstd decoder.\n",
- filename);
- free(zstd);
- return NULL;
- }
-
- ((istream_t *)base)->precache = precache;
- base->cleanup = cleanup;
- return base;
-}
-#endif /* HAVE_ZSTD_STREAM */
diff --git a/lib/io/xfrm.c b/lib/io/xfrm.c
deleted file mode 100644
index 22fd953..0000000
--- a/lib/io/xfrm.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * compressor.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "internal.h"
-
-int io_compressor_id_from_name(const char *name)
-{
- if (strcmp(name, "gzip") == 0)
- return IO_COMPRESSOR_GZIP;
-
- if (strcmp(name, "xz") == 0)
- return IO_COMPRESSOR_XZ;
-
- if (strcmp(name, "zstd") == 0)
- return IO_COMPRESSOR_ZSTD;
-
- if (strcmp(name, "bzip2") == 0)
- return IO_COMPRESSOR_BZIP2;
-
- return -1;
-}
-
-const char *io_compressor_name_from_id(int id)
-{
- if (id == IO_COMPRESSOR_GZIP)
- return "gzip";
-
- if (id == IO_COMPRESSOR_XZ)
- return "xz";
-
- if (id == IO_COMPRESSOR_ZSTD)
- return "zstd";
-
- if (id == IO_COMPRESSOR_BZIP2)
- return "bzip2";
-
- return NULL;
-}
-
-bool io_compressor_exists(int id)
-{
- switch (id) {
-#ifdef WITH_GZIP
- case IO_COMPRESSOR_GZIP:
- return true;
-#endif
-#ifdef WITH_XZ
- case IO_COMPRESSOR_XZ:
- return true;
-#endif
-#if defined(WITH_ZSTD) && defined(HAVE_ZSTD_STREAM)
- case IO_COMPRESSOR_ZSTD:
- return true;
-#endif
-#ifdef WITH_BZIP2
- case IO_COMPRESSOR_BZIP2:
- return true;
-#endif
- default:
- break;
- }
-
- return false;
-}
diff --git a/lib/io/xfrm/istream.c b/lib/io/xfrm/istream.c
new file mode 100644
index 0000000..4a1ad77
--- /dev/null
+++ b/lib/io/xfrm/istream.c
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * istream.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "../internal.h"
+
+typedef struct istream_xfrm_t {
+ istream_t base;
+
+ istream_t *wrapped;
+ xfrm_stream_t *xfrm;
+
+ sqfs_u8 uncompressed[BUFSZ];
+} istream_xfrm_t;
+
+static int xfrm_precache(istream_t *base)
+{
+ istream_xfrm_t *xfrm = (istream_xfrm_t *)base;
+ int ret;
+
+ ret = istream_precache(xfrm->wrapped);
+ if (ret != 0)
+ return ret;
+
+ for (;;) {
+ const sqfs_u32 in_sz = xfrm->wrapped->buffer_used;
+ const sqfs_u32 out_sz = sizeof(xfrm->uncompressed);
+ sqfs_u32 in_off = 0, out_off = base->buffer_used;
+ int mode = XFRM_STREAM_FLUSH_NONE;
+
+ if (xfrm->wrapped->eof)
+ mode = XFRM_STREAM_FLUSH_FULL;
+
+ ret = xfrm->xfrm->process_data(xfrm->xfrm,
+ xfrm->wrapped->buffer, in_sz,
+ base->buffer + out_off,
+ out_sz - out_off,
+ &in_off, &out_off, mode);
+
+ if (ret == XFRM_STREAM_ERROR) {
+ fprintf(stderr, "%s: internal error in decompressor.\n",
+ base->get_filename(base));
+ return -1;
+ }
+
+ base->buffer_used = out_off;
+ xfrm->wrapped->buffer_offset = in_off;
+
+ if (ret == XFRM_STREAM_BUFFER_FULL || out_off >= out_sz)
+ break;
+
+ ret = istream_precache(xfrm->wrapped);
+ if (ret != 0)
+ return ret;
+
+ if (xfrm->wrapped->eof && xfrm->wrapped->buffer_used == 0) {
+ if (base->buffer_used == 0)
+ base->eof = true;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static const char *xfrm_get_filename(istream_t *strm)
+{
+ istream_xfrm_t *xfrm = (istream_xfrm_t *)strm;
+
+ return xfrm->wrapped->get_filename(xfrm->wrapped);
+}
+
+static void xfrm_destroy(sqfs_object_t *obj)
+{
+ istream_xfrm_t *xfrm = (istream_xfrm_t *)obj;
+
+ sqfs_drop(xfrm->xfrm);
+ sqfs_drop(xfrm->wrapped);
+ free(xfrm);
+}
+
+istream_t *istream_xfrm_create(istream_t *strm, xfrm_stream_t *xfrm)
+{
+ istream_xfrm_t *stream = calloc(1, sizeof(*stream));
+ istream_t *base = (istream_t *)stream;
+
+ if (stream == NULL)
+ goto fail;
+
+ sqfs_object_init(stream, xfrm_destroy, NULL);
+
+ stream->wrapped = sqfs_grab(strm);
+ stream->xfrm = sqfs_grab(xfrm);
+
+ base->precache = xfrm_precache;
+ base->get_filename = xfrm_get_filename;
+ base->buffer = stream->uncompressed;
+ base->eof = false;
+ return base;
+fail:
+ fprintf(stderr, "%s: error initializing decompressor stream.\n",
+ strm->get_filename(strm));
+ return NULL;
+}
diff --git a/lib/io/xfrm/ostream.c b/lib/io/xfrm/ostream.c
new file mode 100644
index 0000000..bd94515
--- /dev/null
+++ b/lib/io/xfrm/ostream.c
@@ -0,0 +1,144 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * ostream.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "../internal.h"
+
+typedef struct ostream_xfrm_t {
+ ostream_t base;
+
+ ostream_t *wrapped;
+ xfrm_stream_t *xfrm;
+
+ size_t inbuf_used;
+
+ sqfs_u8 inbuf[BUFSZ];
+ sqfs_u8 outbuf[BUFSZ];
+} ostream_xfrm_t;
+
+static int flush_inbuf(ostream_xfrm_t *xfrm, bool finish)
+{
+ const sqfs_u32 avail_out = sizeof(xfrm->outbuf);
+ const sqfs_u32 avail_in = xfrm->inbuf_used;
+ const int mode = finish ? XFRM_STREAM_FLUSH_FULL :
+ XFRM_STREAM_FLUSH_NONE;
+ sqfs_u32 off_in = 0, off_out = 0;
+ int ret;
+
+ while (finish || off_in < avail_in) {
+ ret = xfrm->xfrm->process_data(xfrm->xfrm,
+ xfrm->inbuf + off_in,
+ avail_in - off_in,
+ xfrm->outbuf + off_out,
+ avail_out - off_out,
+ &off_in, &off_out, mode);
+
+ if (ret == XFRM_STREAM_ERROR) {
+ fprintf(stderr,
+ "%s: internal error in compressor.\n",
+ xfrm->wrapped->get_filename(xfrm->wrapped));
+ return -1;
+ }
+
+ if (ostream_append(xfrm->wrapped, xfrm->outbuf, off_out))
+ return -1;
+
+ off_out = 0;
+
+ if (ret == XFRM_STREAM_END)
+ break;
+ }
+
+ if (off_out > 0) {
+ if (ostream_append(xfrm->wrapped, xfrm->outbuf, off_out))
+ return -1;
+ }
+
+ if (off_in < avail_in) {
+ memmove(xfrm->inbuf, xfrm->inbuf + off_in, avail_in - off_in);
+ xfrm->inbuf_used -= off_in;
+ } else {
+ xfrm->inbuf_used = 0;
+ }
+
+ return 0;
+}
+
+static int xfrm_append(ostream_t *strm, const void *data, size_t size)
+{
+ ostream_xfrm_t *xfrm = (ostream_xfrm_t *)strm;
+ size_t diff;
+
+ while (size > 0) {
+ if (xfrm->inbuf_used >= BUFSZ) {
+ if (flush_inbuf(xfrm, false))
+ return -1;
+ }
+
+ diff = BUFSZ - xfrm->inbuf_used;
+
+ if (diff > size)
+ diff = size;
+
+ memcpy(xfrm->inbuf + xfrm->inbuf_used, data, diff);
+
+ xfrm->inbuf_used += diff;
+ data = (const char *)data + diff;
+ size -= diff;
+ }
+
+ return 0;
+}
+
+static int xfrm_flush(ostream_t *strm)
+{
+ ostream_xfrm_t *xfrm = (ostream_xfrm_t *)strm;
+
+ if (xfrm->inbuf_used > 0) {
+ if (flush_inbuf(xfrm, true))
+ return -1;
+ }
+
+ return xfrm->wrapped->flush(xfrm->wrapped);
+}
+
+static const char *xfrm_get_filename(ostream_t *strm)
+{
+ ostream_xfrm_t *xfrm = (ostream_xfrm_t *)strm;
+
+ return xfrm->wrapped->get_filename(xfrm->wrapped);
+}
+
+static void xfrm_destroy(sqfs_object_t *obj)
+{
+ ostream_xfrm_t *xfrm = (ostream_xfrm_t *)obj;
+
+ sqfs_drop(xfrm->wrapped);
+ sqfs_drop(xfrm->xfrm);
+ free(xfrm);
+}
+
+ostream_t *ostream_xfrm_create(ostream_t *strm, xfrm_stream_t *xfrm)
+{
+ ostream_xfrm_t *stream = calloc(1, sizeof(*stream));
+ ostream_t *base = (ostream_t *)stream;
+
+ if (stream == NULL)
+ goto fail;
+
+ sqfs_object_init(stream, xfrm_destroy, NULL);
+
+ stream->wrapped = sqfs_grab(strm);
+ stream->xfrm = sqfs_grab(xfrm);
+ stream->inbuf_used = 0;
+ base->append = xfrm_append;
+ base->flush = xfrm_flush;
+ base->get_filename = xfrm_get_filename;
+ return base;
+fail:
+ fprintf(stderr, "%s: error initializing compressor.\n",
+ strm->get_filename(strm));
+ return NULL;
+}