From ee26abcab9faf037cf87438cca20d54e5b0edd05 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sat, 23 Sep 2023 11:00:27 +0200 Subject: Cleanup: move xfrm stream wrappers to libxfrm Signed-off-by: David Oberhollenzer --- lib/xfrm/src/istream.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++ lib/xfrm/src/ostream.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 307 insertions(+) create mode 100644 lib/xfrm/src/istream.c create mode 100644 lib/xfrm/src/ostream.c (limited to 'lib/xfrm/src') diff --git a/lib/xfrm/src/istream.c b/lib/xfrm/src/istream.c new file mode 100644 index 0000000..ecf0887 --- /dev/null +++ b/lib/xfrm/src/istream.c @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * istream.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#include "config.h" +#include "compat.h" +#include "sqfs/io.h" +#include "sqfs/error.h" +#include "xfrm/compress.h" +#include "xfrm/wrap.h" + +#include +#include +#include +#include +#include + +#define BUFSZ (262144) + +typedef struct istream_xfrm_t { + sqfs_istream_t base; + + sqfs_istream_t *wrapped; + xfrm_stream_t *xfrm; + + size_t buffer_offset; + size_t buffer_used; + sqfs_u8 uncompressed[BUFSZ]; +} istream_xfrm_t; + +static int precache(sqfs_istream_t *base) +{ + istream_xfrm_t *xfrm = (istream_xfrm_t *)base; + int ret; + + if (xfrm->buffer_offset > 0 && + xfrm->buffer_offset < xfrm->buffer_used) { + memmove(xfrm->uncompressed, + xfrm->uncompressed + xfrm->buffer_offset, + xfrm->buffer_used - xfrm->buffer_offset); + } + + xfrm->buffer_used -= xfrm->buffer_offset; + xfrm->buffer_offset = 0; + + for (;;) { + sqfs_u32 in_off = 0, out_off = xfrm->buffer_used; + int mode = XFRM_STREAM_FLUSH_NONE; + const sqfs_u8 *ptr; + size_t avail; + + ret = xfrm->wrapped->get_buffered_data(xfrm->wrapped, &ptr, + &avail, BUFSZ); + if (ret < 0) + return ret; + if (ret > 0) + mode = XFRM_STREAM_FLUSH_FULL; + + ret = xfrm->xfrm->process_data(xfrm->xfrm, + ptr, avail, + xfrm->uncompressed + out_off, + BUFSZ - out_off, + &in_off, &out_off, mode); + + if (ret == XFRM_STREAM_ERROR) + return SQFS_ERROR_COMPRESSOR; + + xfrm->buffer_used = out_off; + xfrm->wrapped->advance_buffer(xfrm->wrapped, in_off); + + if (ret == XFRM_STREAM_BUFFER_FULL || out_off >= BUFSZ) + break; + + if (mode == XFRM_STREAM_FLUSH_FULL) + break; + } + + return 0; +} + +static int xfrm_get_buffered_data(sqfs_istream_t *strm, const sqfs_u8 **out, + size_t *size, size_t want) +{ + istream_xfrm_t *xfrm = (istream_xfrm_t *)strm; + + if (want > BUFSZ) + want = BUFSZ; + + if (xfrm->buffer_used == 0 || + (xfrm->buffer_used - xfrm->buffer_offset) < want) { + int ret = precache(strm); + if (ret) + return ret; + } + + *out = xfrm->uncompressed + xfrm->buffer_offset; + *size = xfrm->buffer_used - xfrm->buffer_offset; + return (*size == 0) ? 1 : 0; +} + +static void xfrm_advance_buffer(sqfs_istream_t *strm, size_t count) +{ + istream_xfrm_t *xfrm = (istream_xfrm_t *)strm; + + assert(count <= xfrm->buffer_used); + + xfrm->buffer_offset += count; + + assert(xfrm->buffer_offset <= xfrm->buffer_used); +} + +static const char *xfrm_get_filename(sqfs_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); +} + +sqfs_istream_t *istream_xfrm_create(sqfs_istream_t *strm, xfrm_stream_t *xfrm) +{ + istream_xfrm_t *stream = calloc(1, sizeof(*stream)); + sqfs_istream_t *base = (sqfs_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->get_buffered_data = xfrm_get_buffered_data; + base->advance_buffer = xfrm_advance_buffer; + base->get_filename = xfrm_get_filename; + return base; +fail: + fprintf(stderr, "%s: error initializing decompressor stream.\n", + strm->get_filename(strm)); + return NULL; +} diff --git a/lib/xfrm/src/ostream.c b/lib/xfrm/src/ostream.c new file mode 100644 index 0000000..8e33a91 --- /dev/null +++ b/lib/xfrm/src/ostream.c @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * ostream.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#include "config.h" +#include "compat.h" +#include "sqfs/io.h" +#include "sqfs/error.h" +#include "xfrm/compress.h" +#include "xfrm/wrap.h" + +#include +#include +#include +#include +#include + +#define BUFSZ (262144) + +typedef struct ostream_xfrm_t { + sqfs_ostream_t base; + + sqfs_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, ioret; + + 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) + return SQFS_ERROR_COMPRESSOR; + + ioret = xfrm->wrapped->append(xfrm->wrapped, + xfrm->outbuf, off_out); + if (ioret) + return ioret; + + off_out = 0; + + if (ret == XFRM_STREAM_END) + break; + } + + 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(sqfs_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) { + int ret = flush_inbuf(xfrm, false); + if (ret) + return ret; + } + + diff = BUFSZ - xfrm->inbuf_used; + + if (diff > size) + diff = size; + + if (data == NULL) { + memset(xfrm->inbuf + xfrm->inbuf_used, 0, diff); + } else { + memcpy(xfrm->inbuf + xfrm->inbuf_used, data, diff); + data = (const char *)data + diff; + } + + xfrm->inbuf_used += diff; + size -= diff; + } + + return 0; +} + +static int xfrm_flush(sqfs_ostream_t *strm) +{ + ostream_xfrm_t *xfrm = (ostream_xfrm_t *)strm; + + if (xfrm->inbuf_used > 0) { + int ret = flush_inbuf(xfrm, true); + if (ret) + return ret; + } + + return xfrm->wrapped->flush(xfrm->wrapped); +} + +static const char *xfrm_get_filename(sqfs_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); +} + +sqfs_ostream_t *ostream_xfrm_create(sqfs_ostream_t *strm, xfrm_stream_t *xfrm) +{ + ostream_xfrm_t *stream = calloc(1, sizeof(*stream)); + sqfs_ostream_t *base = (sqfs_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; +} -- cgit v1.2.3