From: Michael Tremer Date: Wed, 17 Mar 2021 11:33:12 +0000 (+0000) Subject: compress: Add write support for XZ X-Git-Tag: 0.9.28~1285^2~518 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0bed1e1da805459f25fc5b61b540b03e330ae414;p=pakfire.git compress: Add write support for XZ Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/compress.c b/src/libpakfire/compress.c index 0f0bd2ba2..726b57dd6 100644 --- a/src/libpakfire/compress.c +++ b/src/libpakfire/compress.c @@ -32,6 +32,9 @@ // Compression/Decompression buffer size #define BUFFER_SIZE 64 * 1024 +// Settings for XZ +#define XZ_COMPRESSION_LEVEL 6 + const struct compressor { char magic[MAX_MAGIC_LENGTH]; size_t magic_length; @@ -109,7 +112,6 @@ struct xz_cookie { uint8_t buffer[BUFFER_SIZE]; }; - static ssize_t xz_read(void* data, char* buffer, size_t size) { struct xz_cookie* cookie = (struct xz_cookie*)data; if (!cookie) @@ -169,6 +171,45 @@ static ssize_t xz_read(void* data, char* buffer, size_t size) { } } +static ssize_t xz_write(void* data, const char* buffer, size_t size) { + struct xz_cookie* cookie = (struct xz_cookie*)data; + if (!cookie) + return -1; + + // Do not write when mode is "r" + if (cookie->mode == 'r') + return 0; + + // Return nothing when there is no input + if (size == 0) + return 0; + + // Set input to allocated buffer + cookie->stream.next_out = (uint8_t *)buffer; + cookie->stream.avail_out = size; + + while (1) { + cookie->stream.next_out = cookie->buffer; + cookie->stream.avail_out = sizeof(cookie->buffer); + + lzma_ret ret = lzma_code(&cookie->stream, LZMA_RUN); + if (ret != LZMA_OK) + return -1; + + size_t bytes_to_write = sizeof(cookie->buffer) - cookie->stream.avail_out; + if (bytes_to_write) { + size_t bytes_written = fwrite(cookie->buffer, 1, bytes_to_write, cookie->f); + + if (bytes_written != bytes_to_write) + return -1; + } + + // Report that all data has been written + if (cookie->stream.avail_in == 0) + return size; + } +} + static int xz_close(void* data) { struct xz_cookie* cookie = (struct xz_cookie*)data; @@ -199,14 +240,29 @@ FILE* pakfire_xzfopen(FILE* f, const char* mode) { .done = 0, }; - // Initialise the decoder - lzma_ret ret = lzma_stream_decoder(&cookie.stream, UINT64_MAX, 0); + lzma_ret ret; + + // Initialise the encoder/decoder + switch (cookie.mode) { + case 'r': + ret = lzma_stream_decoder(&cookie.stream, UINT64_MAX, 0); + break; + + case 'w': + ret = lzma_easy_encoder(&cookie.stream, XZ_COMPRESSION_LEVEL, LZMA_CHECK_SHA256); + break; + + default: + errno = ENOTSUP; + return NULL; + } + if (ret != LZMA_OK) return NULL; cookie_io_functions_t functions = { .read = xz_read, - .write = NULL, + .write = xz_write, .seek = NULL, .close = xz_close, };