]> git.ipfire.org Git - pakfire.git/commitdiff
compress: Move cookie onto heap
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 18 Mar 2021 18:46:22 +0000 (18:46 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 18 Mar 2021 18:46:22 +0000 (18:46 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/compress.c

index 726b57dd6eb6c06a9e3c28a30c346755eb0419e2..bea2095bfc063bff2bea4eb973b2e2ab5cfe935f 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include <lzma.h>
@@ -212,17 +213,50 @@ static ssize_t xz_write(void* data, const char* buffer, size_t size) {
 
 static int xz_close(void* data) {
        struct xz_cookie* cookie = (struct xz_cookie*)data;
+       if (!cookie)
+               return -1;
+
+       if (cookie->mode == 'w') {
+               while (1) {
+                       cookie->stream.next_out  = cookie->buffer;
+                       cookie->stream.avail_out = sizeof(cookie->buffer);
+
+                       lzma_ret ret = lzma_code(&cookie->stream, LZMA_FINISH);
+                       if (ret != LZMA_OK && ret != LZMA_STREAM_END)
+                               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;
+                       }
+
+                       if (ret == LZMA_STREAM_END)
+                               break;
+               }
+       }
 
-       // Free the deocder
        lzma_end(&cookie->stream);
 
        // Close input file
-       fclose(cookie->f);
+       int r = fclose(cookie->f);
+       free(cookie);
 
-       return 0;
+       return r;
 }
 
+static cookie_io_functions_t xz_functions = {
+       .read  = xz_read,
+       .write = xz_write,
+       .seek  = NULL,
+       .close = xz_close,
+};
+
 FILE* pakfire_xzfopen(FILE* f, const char* mode) {
+       lzma_ret ret;
+
        if (!f) {
                errno = EBADFD;
                return NULL;
@@ -233,39 +267,30 @@ FILE* pakfire_xzfopen(FILE* f, const char* mode) {
                return NULL;
        }
 
-       struct xz_cookie cookie = {
-               .f = f,
-               .mode = *mode,
-               .stream = LZMA_STREAM_INIT,
-               .done = 0,
-       };
+       struct xz_cookie* cookie = calloc(1, sizeof(*cookie));
+       if (!cookie)
+               return NULL;
 
-       lzma_ret ret;
+       cookie->f = f;
+       cookie->mode = *mode;
 
-       // Initialise the encoder/decoder
-       switch (cookie.mode) {
+       switch (cookie->mode) {
                case 'r':
-                       ret = lzma_stream_decoder(&cookie.stream, UINT64_MAX, 0);
+                       ret = lzma_stream_decoder(&cookie->stream, UINT64_MAX, 0);
                        break;
 
                case 'w':
-                       ret = lzma_easy_encoder(&cookie.stream, XZ_COMPRESSION_LEVEL, LZMA_CHECK_SHA256);
+                       ret = lzma_easy_encoder(&cookie->stream, XZ_COMPRESSION_LEVEL, LZMA_CHECK_SHA256);
                        break;
 
                default:
                        errno = ENOTSUP;
+                       free(cookie);
                        return NULL;
        }
 
        if (ret != LZMA_OK)
                return NULL;
 
-       cookie_io_functions_t functions = {
-               .read  = xz_read,
-               .write = xz_write,
-               .seek  = NULL,
-               .close = xz_close,
-       };
-
-       return fopencookie(&cookie, mode, functions);
+       return fopencookie(cookie, mode, xz_functions);
 }