]> git.ipfire.org Git - pakfire.git/commitdiff
compress: Support compression with ZSTD
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 19 Mar 2021 17:55:33 +0000 (17:55 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 19 Mar 2021 17:55:33 +0000 (17:55 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/compress.c
tests/libpakfire/compress.c

index a1879902982baf5785d573e8a039b1f51f95cd90..0991146db1329c70f294b7b8912d23cb900694c1 100644 (file)
@@ -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,
 };
index 36132b97436065660b00bc38322c72a7f688d365..a07bbf85207b8f9aa1deed2f4dc0e43c0fc6cc27 100644 (file)
@@ -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);