From: Michael Tremer Date: Fri, 19 Mar 2021 17:55:33 +0000 (+0000) Subject: compress: Support compression with ZSTD X-Git-Tag: 0.9.28~1285^2~507 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=99a1527a5a8d34d8fc9df015081d4e54eb4b73a1;p=pakfire.git compress: Support compression with ZSTD Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/compress.c b/src/libpakfire/compress.c index a18799029..0991146db 100644 --- a/src/libpakfire/compress.c +++ b/src/libpakfire/compress.c @@ -354,12 +354,69 @@ static ssize_t zstd_read(void* data, char* buffer, size_t size) { } } +static ssize_t zstd_write(void* data, const char* buffer, size_t size) { + struct zstd_cookie* cookie = (struct zstd_cookie*)data; + if (!cookie) + return -1; + + // Do not write when mode is "r" + if (cookie->mode == 'r') + return -1; + + // Return nothing when there is no input + if (size == 0) + return 0; + + // Configure input buffer + cookie->in.src = buffer; + cookie->in.pos = 0; + cookie->in.size = size; + + while (1) { + cookie->out.pos = 0; + + size_t r = ZSTD_compressStream(cookie->cstream, &cookie->out, &cookie->in); + if (ZSTD_isError(r)) + return -1; + + if (cookie->out.pos > 0) { + size_t bytes_written = fwrite(cookie->buffer, 1, cookie->out.pos, cookie->f); + + if (bytes_written != cookie->out.pos) + return -1; + } + + // Return when all input has been written + if (cookie->in.pos == size) + return size; + } +} + static int zstd_close(void* data) { struct zstd_cookie* cookie = (struct zstd_cookie*)data; if (!cookie) return -1; - // XXX handle write + if (cookie->mode == 'w') { + while (1) { + // Reset output buffer + cookie->out.pos = 0; + + size_t r = ZSTD_endStream(cookie->cstream, &cookie->out); + if (ZSTD_isError(r)) + return -1; + + if (cookie->out.pos > 0) { + size_t bytes_written = fwrite(cookie->buffer, 1, cookie->out.pos, cookie->f); + + if (bytes_written != cookie->out.pos) + return -1; + } + + if (r == 0) + break; + } + } int r = fclose(cookie->f); @@ -375,7 +432,7 @@ static int zstd_close(void* data) { static cookie_io_functions_t zstd_functions = { .read = zstd_read, - //.write = zstd_write, + .write = zstd_write, .seek = NULL, .close = zstd_close, }; diff --git a/tests/libpakfire/compress.c b/tests/libpakfire/compress.c index 36132b974..a07bbf852 100644 --- a/tests/libpakfire/compress.c +++ b/tests/libpakfire/compress.c @@ -55,17 +55,13 @@ static int read_test(const struct test* t, return EXIT_SUCCESS; } -static int test_xzfopen_read(const struct test* t) { - return read_test(t, pakfire_xzfopen, "data/compress/data.xz"); -} - -static int test_xzfopen_write(const struct test* t) { +static int write_test(const struct test* t, FILE* (function)(FILE* f, const char* mode)) { // Create a backend storage file FILE* f = test_mktemp(); ASSERT(f); // Open compressed file for writing - f = pakfire_xzfopen(f, "w"); + f = function(f, "w"); ASSERT(f); // Write some data and close fwrite @@ -79,10 +75,22 @@ static int test_xzfopen_write(const struct test* t) { return EXIT_SUCCESS; } +static int test_xzfopen_read(const struct test* t) { + return read_test(t, pakfire_xzfopen, "data/compress/data.xz"); +} + +static int test_xzfopen_write(const struct test* t) { + return write_test(t, pakfire_xzfopen); +} + static int test_zstdfopen_read(const struct test* t) { return read_test(t, pakfire_zstdfopen, "data/compress/data.zst"); } +static int test_zstdfopen_write(const struct test* t) { + return write_test(t, pakfire_zstdfopen); +} + static int test_xfopen(const struct test* t) { return read_test(t, pakfire_xfopen, "data/compress/data.xz"); } @@ -94,6 +102,7 @@ int main(int argc, char** argv) { // ZSTD testsuite_add_test(test_zstdfopen_read); + testsuite_add_test(test_zstdfopen_write); testsuite_add_test(test_xfopen);