]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic: expose compression level argument in compress_blob functions
authorAndrii Chubatiuk <andrew.chubatiuk@gmail.com>
Fri, 18 Oct 2024 17:43:31 +0000 (20:43 +0300)
committerAndrii Chubatiuk <andrew.chubatiuk@gmail.com>
Fri, 7 Feb 2025 05:05:02 +0000 (07:05 +0200)
src/basic/compress.c
src/basic/compress.h
src/fuzz/fuzz-compress.c
src/libsystemd/sd-journal/journal-file.c
src/test/test-compress-benchmark.c
src/test/test-compress.c

index 61e87adddee6874fdc514c53e962bdc0691863da..7f30fe61dae461a5636f4302019c2d2e9b4da328 100644 (file)
@@ -8,6 +8,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#if HAVE_LZ4
+#include <lz4hc.h>
+#endif
+
 #if HAVE_XZ
 #include <lzma.h>
 #endif
@@ -43,6 +47,7 @@ static DLSYM_PROTOTYPE(LZ4F_freeCompressionContext) = NULL;
 static DLSYM_PROTOTYPE(LZ4F_freeDecompressionContext) = NULL;
 static DLSYM_PROTOTYPE(LZ4F_isError) = NULL;
 DLSYM_PROTOTYPE(LZ4_compress_default) = NULL;
+DLSYM_PROTOTYPE(LZ4_compress_HC) = NULL;
 DLSYM_PROTOTYPE(LZ4_decompress_safe) = NULL;
 DLSYM_PROTOTYPE(LZ4_decompress_safe_partial) = NULL;
 DLSYM_PROTOTYPE(LZ4_versionNumber) = NULL;
@@ -94,6 +99,7 @@ static DLSYM_PROTOTYPE(lzma_easy_encoder) = NULL;
 static DLSYM_PROTOTYPE(lzma_end) = NULL;
 static DLSYM_PROTOTYPE(lzma_stream_buffer_encode) = NULL;
 static DLSYM_PROTOTYPE(lzma_stream_decoder) = NULL;
+static DLSYM_PROTOTYPE(lzma_lzma_preset) = NULL;
 
 /* We can't just do _cleanup_(sym_lzma_end) because a compiler bug makes
  * this fail with:
@@ -145,12 +151,13 @@ int dlopen_lzma(void) {
                         DLSYM_ARG(lzma_easy_encoder),
                         DLSYM_ARG(lzma_end),
                         DLSYM_ARG(lzma_stream_buffer_encode),
+                        DLSYM_ARG(lzma_lzma_preset),
                         DLSYM_ARG(lzma_stream_decoder));
 }
 #endif
 
 int compress_blob_xz(const void *src, uint64_t src_size,
-                     void *dst, size_t dst_alloc_size, size_t *dst_size) {
+                     void *dst, size_t dst_alloc_size, size_t *dst_size, int level) {
 
         assert(src);
         assert(src_size > 0);
@@ -159,12 +166,12 @@ int compress_blob_xz(const void *src, uint64_t src_size,
         assert(dst_size);
 
 #if HAVE_XZ
-        static const lzma_options_lzma opt = {
+        lzma_options_lzma opt = {
                 1u << 20u, NULL, 0, LZMA_LC_DEFAULT, LZMA_LP_DEFAULT,
                 LZMA_PB_DEFAULT, LZMA_MODE_FAST, 128, LZMA_MF_HC3, 4
         };
-        static const lzma_filter filters[] = {
-                { LZMA_FILTER_LZMA2, (lzma_options_lzma*) &opt },
+        lzma_filter filters[] = {
+                { LZMA_FILTER_LZMA2, &opt },
                 { LZMA_VLI_UNKNOWN, NULL }
         };
         lzma_ret ret;
@@ -175,13 +182,19 @@ int compress_blob_xz(const void *src, uint64_t src_size,
         if (r < 0)
                 return r;
 
+        if (level >= 0) {
+                r = sym_lzma_lzma_preset(&opt, (uint32_t) level);
+                if (r < 0)
+                        return r;
+        }
+
         /* Returns < 0 if we couldn't compress the data or the
          * compressed result is longer than the original */
 
         if (src_size < 80)
                 return -ENOBUFS;
 
-        ret = sym_lzma_stream_buffer_encode((lzma_filter*) filters, LZMA_CHECK_NONE, NULL,
+        ret = sym_lzma_stream_buffer_encode(filters, LZMA_CHECK_NONE, NULL,
                                         src, src_size, dst, &out_pos, dst_alloc_size);
         if (ret != LZMA_OK)
                 return -ENOBUFS;
@@ -214,6 +227,7 @@ int dlopen_lz4(void) {
                         DLSYM_ARG(LZ4F_freeDecompressionContext),
                         DLSYM_ARG(LZ4F_isError),
                         DLSYM_ARG(LZ4_compress_default),
+                        DLSYM_ARG(LZ4_compress_HC),
                         DLSYM_ARG(LZ4_decompress_safe),
                         DLSYM_ARG(LZ4_decompress_safe_partial),
                         DLSYM_ARG(LZ4_versionNumber));
@@ -221,7 +235,7 @@ int dlopen_lz4(void) {
 #endif
 
 int compress_blob_lz4(const void *src, uint64_t src_size,
-                      void *dst, size_t dst_alloc_size, size_t *dst_size) {
+                      void *dst, size_t dst_alloc_size, size_t *dst_size, int level) {
 
         assert(src);
         assert(src_size > 0);
@@ -241,7 +255,10 @@ int compress_blob_lz4(const void *src, uint64_t src_size,
         if (src_size < 9)
                 return -ENOBUFS;
 
-        r = sym_LZ4_compress_default(src, (char*)dst + 8, src_size, (int) dst_alloc_size - 8);
+        if (level <= 0)
+                r = sym_LZ4_compress_default(src, (char*)dst + 8, src_size, (int) dst_alloc_size - 8);
+        else
+                r = sym_LZ4_compress_HC(src, (char*)dst + 8, src_size, (int) dst_alloc_size - 8, level);
         if (r <= 0)
                 return -ENOBUFS;
 
@@ -285,7 +302,7 @@ int dlopen_zstd(void) {
 
 int compress_blob_zstd(
                 const void *src, uint64_t src_size,
-                void *dst, size_t dst_alloc_size, size_t *dst_size) {
+                void *dst, size_t dst_alloc_size, size_t *dst_size, int level) {
 
         assert(src);
         assert(src_size > 0);
@@ -301,7 +318,7 @@ int compress_blob_zstd(
         if (r < 0)
                 return r;
 
-        k = sym_ZSTD_compress(dst, dst_alloc_size, src, src_size, 0);
+        k = sym_ZSTD_compress(dst, dst_alloc_size, src, src_size, level < 0 ? 0 : level);
         if (sym_ZSTD_isError(k))
                 return zstd_ret_to_errno(k);
 
index 1ad87ee8781280a552b13938ce13424abc2ea1c3..2f3ab2f39c972ae874b41d028b4089de77e19211 100644 (file)
@@ -28,11 +28,11 @@ Compression compression_from_string(const char *compression);
 bool compression_supported(Compression c);
 
 int compress_blob_xz(const void *src, uint64_t src_size,
-                     void *dst, size_t dst_alloc_size, size_t *dst_size);
+                     void *dst, size_t dst_alloc_size, size_t *dst_size, int level);
 int compress_blob_lz4(const void *src, uint64_t src_size,
-                      void *dst, size_t dst_alloc_size, size_t *dst_size);
+                      void *dst, size_t dst_alloc_size, size_t *dst_size, int level);
 int compress_blob_zstd(const void *src, uint64_t src_size,
-                       void *dst, size_t dst_alloc_size, size_t *dst_size);
+                       void *dst, size_t dst_alloc_size, size_t *dst_size, int level);
 
 int decompress_blob_xz(const void *src, uint64_t src_size,
                        void **dst, size_t* dst_size, size_t dst_max);
@@ -90,15 +90,15 @@ int dlopen_lzma(void);
 static inline int compress_blob(
                 Compression compression,
                 const void *src, uint64_t src_size,
-                void *dst, size_t dst_alloc_size, size_t *dst_size) {
+                void *dst, size_t dst_alloc_size, size_t *dst_size, int level) {
 
         switch (compression) {
         case COMPRESSION_ZSTD:
-                return compress_blob_zstd(src, src_size, dst, dst_alloc_size, dst_size);
+                return compress_blob_zstd(src, src_size, dst, dst_alloc_size, dst_size, level);
         case COMPRESSION_LZ4:
-                return compress_blob_lz4(src, src_size, dst, dst_alloc_size, dst_size);
+                return compress_blob_lz4(src, src_size, dst, dst_alloc_size, dst_size, level);
         case COMPRESSION_XZ:
-                return compress_blob_xz(src, src_size, dst, dst_alloc_size, dst_size);
+                return compress_blob_xz(src, src_size, dst, dst_alloc_size, dst_size, level);
         default:
                 return -EOPNOTSUPP;
         }
index c3f68f62dd27b27e34263fe00ab1201961ebe7fa..6fcad736b1838fc6fb60eb13ac2b3e471db8de06 100644 (file)
@@ -42,7 +42,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         }
 
         size_t csize;
-        r = compress_blob(alg, h->data, data_len, buf, size, &csize);
+        r = compress_blob(alg, h->data, data_len, buf, size, &csize, /* level = */ -1);
         if (r < 0) {
                 log_error_errno(r, "Compression failed: %m");
                 return 0;
index 508b47cbe78d0e0adfe5d8ca5fe068714c7ccc94..97f65c561cb862d607820ed2faf29eec34279861 100644 (file)
@@ -1810,7 +1810,7 @@ static int maybe_compress_payload(JournalFile *f, uint8_t *dst, const uint8_t *s
         if (c == COMPRESSION_NONE || size < f->compress_threshold_bytes)
                 return 0;
 
-        r = compress_blob(c, src, size, dst, size - 1, rsize);
+        r = compress_blob(c, src, size, dst, size - 1, rsize, /* level = */ -1);
         if (r < 0)
                 return log_debug_errno(r, "Failed to compress data object using %s, ignoring: %m", compression_to_string(c));
 
index 1727db8134d1b1dea4f37fe121f725509e586e31..c4e19f9256ecc606aa0164100d111d3d4af512b0 100644 (file)
@@ -13,7 +13,7 @@
 #include "tests.h"
 
 typedef int (compress_t)(const void *src, uint64_t src_size, void *dst,
-                         size_t dst_alloc_size, size_t *dst_size);
+                         size_t dst_alloc_size, size_t *dst_size, int level);
 typedef int (decompress_t)(const void *src, uint64_t src_size,
                            void **dst, size_t* dst_size, size_t dst_max);
 
@@ -100,7 +100,7 @@ static void test_compress_decompress(const char* label, const char* type,
 
                 memzero(buf, MIN(size + 1000, MAX_SIZE));
 
-                r = compress(text, size, buf, size, &j);
+                r = compress(text, size, buf, size, &j, /* level = */ -1);
                 /* assume compression must be successful except for small or random inputs */
                 assert_se(r >= 0 || (size < 2048 && r == -ENOBUFS) || streq(type, "random"));
 
index 86311c6217e42c6be1fbff0d91793689ef6e7395..9688e10df4a35cb4a542e20e6f2b4d94313f8ddc 100644 (file)
@@ -33,7 +33,7 @@
 #define HUGE_SIZE (4096*1024)
 
 typedef int (compress_blob_t)(const void *src, uint64_t src_size,
-                              void *dst, size_t dst_alloc_size, size_t *dst_size);
+                              void *dst, size_t dst_alloc_size, size_t *dst_size, int level);
 typedef int (decompress_blob_t)(const void *src, uint64_t src_size,
                                 void **dst,
                                 size_t* dst_size, size_t dst_max);
@@ -62,7 +62,7 @@ _unused_ static void test_compress_decompress(
         log_info("/* testing %s %s blob compression/decompression */",
                  compression, data);
 
-        r = compress(data, data_len, compressed, sizeof(compressed), &csize);
+        r = compress(data, data_len, compressed, sizeof(compressed), &csize, /* level = */ -1);
         if (r == -ENOBUFS) {
                 log_info_errno(r, "compression failed: %m");
                 assert_se(may_fail);
@@ -111,14 +111,14 @@ _unused_ static void test_decompress_startswith(const char *compression,
 
         compressed = compressed1 = malloc(BUFSIZE_1);
         assert_se(compressed1);
-        r = compress(data, data_len, compressed, BUFSIZE_1, &csize);
+        r = compress(data, data_len, compressed, BUFSIZE_1, &csize, /* level = */ -1);
         if (r == -ENOBUFS) {
                 log_info_errno(r, "compression failed: %m");
                 assert_se(may_fail);
 
                 compressed = compressed2 = malloc(BUFSIZE_2);
                 assert_se(compressed2);
-                r = compress(data, data_len, compressed, BUFSIZE_2, &csize);
+                r = compress(data, data_len, compressed, BUFSIZE_2, &csize, /* level = */ -1);
         }
         assert_se(r >= 0);
 
@@ -150,7 +150,7 @@ _unused_ static void test_decompress_startswith_short(const char *compression,
 
         log_info("/* %s with %s */", __func__, compression);
 
-        r = compress(TEXT, sizeof TEXT, buf, sizeof buf, &csize);
+        r = compress(TEXT, sizeof TEXT, buf, sizeof buf, &csize, /* level = */ -1);
         assert_se(r >= 0);
 
         for (size_t i = 1; i < strlen(TEXT); i++) {