diff --git a/src/basic/compress.c b/src/basic/compress.c index 0f62fb95f5..8cbf22005d 100644 --- a/src/basic/compress.c +++ b/src/basic/compress.c @@ -424,6 +424,32 @@ int dlopen_bzip2(int log_level) { #endif } +int dlopen_compress_journal(Compression c, int log_level) { + switch (c) { + case COMPRESSION_NONE: + return 0; + case COMPRESSION_XZ: + return dlopen_xz(log_level); + case COMPRESSION_LZ4: + return dlopen_lz4(log_level); + case COMPRESSION_ZSTD: + return dlopen_zstd(log_level); + default: + return -EOPNOTSUPP; + } +} + +int dlopen_compress(Compression c, int log_level) { + switch (c) { + case COMPRESSION_GZIP: + return dlopen_zlib(log_level); + case COMPRESSION_BZIP2: + return dlopen_bzip2(log_level); + default: + return dlopen_compress_journal(c, log_level); + } +} + static int compress_blob_xz( const void *src, uint64_t src_size, @@ -1676,7 +1702,7 @@ static int decompress_stream_write_callback(const void *data, size_t size, void } static int decompressor_new(Decompressor **ret, Compression type) { -#if HAVE_XZ || HAVE_LZ4 || HAVE_ZSTD || HAVE_ZLIB || HAVE_BZIP2 +#if HAVE_ZLIB || HAVE_BZIP2 int r; #endif @@ -1689,13 +1715,11 @@ static int decompressor_new(Decompressor **ret, Compression type) { c->type = _COMPRESSION_INVALID; switch (type) { + case COMPRESSION_NONE: + break; #if HAVE_XZ case COMPRESSION_XZ: - r = dlopen_xz(LOG_DEBUG); - if (r < 0) - return r; - if (sym_lzma_stream_decoder(&c->xz, UINT64_MAX, LZMA_TELL_UNSUPPORTED_CHECK | LZMA_CONCATENATED) != LZMA_OK) return -EIO; break; @@ -1703,10 +1727,6 @@ static int decompressor_new(Decompressor **ret, Compression type) { #if HAVE_LZ4 case COMPRESSION_LZ4: { - r = dlopen_lz4(LOG_DEBUG); - if (r < 0) - return r; - size_t rc = sym_LZ4F_createDecompressionContext(&c->d_lz4, LZ4F_VERSION); if (sym_LZ4F_isError(rc)) return -ENOMEM; @@ -1717,10 +1737,6 @@ static int decompressor_new(Decompressor **ret, Compression type) { #if HAVE_ZSTD case COMPRESSION_ZSTD: - r = dlopen_zstd(LOG_DEBUG); - if (r < 0) - return r; - c->d_zstd = sym_ZSTD_createDCtx(); if (!c->d_zstd) return -ENOMEM; @@ -1729,10 +1745,6 @@ static int decompressor_new(Decompressor **ret, Compression type) { #if HAVE_ZLIB case COMPRESSION_GZIP: - r = dlopen_zlib(LOG_DEBUG); - if (r < 0) - return r; - r = sym_inflateInit2_(&c->gzip, /* windowBits= */ ZLIB_WBITS_GZIP, ZLIB_VERSION, (int) sizeof(c->gzip)); if (r != Z_OK) return -EIO; @@ -1741,10 +1753,6 @@ static int decompressor_new(Decompressor **ret, Compression type) { #if HAVE_BZIP2 case COMPRESSION_BZIP2: - r = dlopen_bzip2(LOG_DEBUG); - if (r < 0) - return r; - r = sym_BZ2_bzDecompressInit(&c->bzip2, /* verbosity= */ 0, /* small= */ 0); if (r != BZ_OK) return -EIO; @@ -1752,7 +1760,7 @@ static int decompressor_new(Decompressor **ret, Compression type) { #endif default: - return -EOPNOTSUPP; + assert_not_reached(); } c->type = type; @@ -1774,6 +1782,13 @@ int decompress_stream( assert(fdf >= 0); assert(fdt >= 0); + if (type == COMPRESSION_NONE) + return -EOPNOTSUPP; + + r = dlopen_compress(type, LOG_DEBUG); + if (r < 0) + return r; + r = decompressor_new(&c, type); if (r < 0) return r; @@ -1897,14 +1912,12 @@ Compression compressor_type(const Compressor *c) { return c ? c->type : _COMPRESSION_INVALID; } -int decompressor_detect(Decompressor **ret, const void *data, size_t size) { -#if HAVE_XZ || HAVE_LZ4 || HAVE_ZSTD || HAVE_ZLIB || HAVE_BZIP2 +int decompressor_detect(Decompressor **decompressor, const void *data, size_t size) { int r; -#endif - assert(ret); + assert(decompressor); - if (*ret) + if (*decompressor) return 1; if (size < COMPRESSION_MAGIC_BYTES_MAX) @@ -1913,119 +1926,30 @@ int decompressor_detect(Decompressor **ret, const void *data, size_t size) { assert(data); Compression type = compression_detect_from_magic(data); - - _cleanup_(compressor_freep) Decompressor *c = new0(Decompressor, 1); - if (!c) - return -ENOMEM; - - switch (type) { - -#if HAVE_XZ - case COMPRESSION_XZ: { - r = dlopen_xz(LOG_DEBUG); - if (r < 0) - return r; - - lzma_ret xzr = sym_lzma_stream_decoder(&c->xz, UINT64_MAX, LZMA_TELL_UNSUPPORTED_CHECK | LZMA_CONCATENATED); - if (xzr != LZMA_OK) - return -EIO; - - break; - } -#endif - -#if HAVE_LZ4 - case COMPRESSION_LZ4: { - r = dlopen_lz4(LOG_DEBUG); - if (r < 0) - return r; - - size_t rc = sym_LZ4F_createDecompressionContext(&c->d_lz4, LZ4F_VERSION); - if (sym_LZ4F_isError(rc)) - return -ENOMEM; - - break; - } -#endif - -#if HAVE_ZSTD - case COMPRESSION_ZSTD: { - r = dlopen_zstd(LOG_DEBUG); - if (r < 0) - return r; - - c->d_zstd = sym_ZSTD_createDCtx(); - if (!c->d_zstd) - return -ENOMEM; - - break; - } -#endif - -#if HAVE_ZLIB - case COMPRESSION_GZIP: { - r = dlopen_zlib(LOG_DEBUG); - if (r < 0) - return r; - - r = sym_inflateInit2_(&c->gzip, /* windowBits= */ ZLIB_WBITS_GZIP, ZLIB_VERSION, (int) sizeof(c->gzip)); - if (r != Z_OK) - return -EIO; - - break; - } -#endif - -#if HAVE_BZIP2 - case COMPRESSION_BZIP2: { - r = dlopen_bzip2(LOG_DEBUG); - if (r < 0) - return r; - - r = sym_BZ2_bzDecompressInit(&c->bzip2, /* verbosity= */ 0, /* small= */ 0); - if (r != BZ_OK) - return -EIO; - - break; - } -#endif - - default: - if (type != _COMPRESSION_INVALID) - return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "Detected %s compression, but support is not compiled in.", - compression_to_string(type)); + if (type == _COMPRESSION_INVALID) type = COMPRESSION_NONE; - break; - } - c->type = type; - c->encoding = false; + log_debug("Detected compression type: %s", compression_to_string(type)); + + r = dlopen_compress(type, LOG_DEBUG); + if (r < 0) + return r; + + r = decompressor_new(decompressor, type); + if (r < 0) + return r; - log_debug("Detected compression type: %s", compression_to_string(c->type)); - *ret = TAKE_PTR(c); return 1; } -int decompressor_force_off(Decompressor **ret) { - assert(ret); +int decompressor_force_off(Decompressor **decompressor) { + assert(decompressor); - *ret = compressor_free(*ret); - - Decompressor *c = new0(Decompressor, 1); - if (!c) - return -ENOMEM; - - c->type = COMPRESSION_NONE; - c->encoding = false; - *ret = c; - return 0; + *decompressor = compressor_free(*decompressor); + return decompressor_new(decompressor, COMPRESSION_NONE); } int decompressor_push(Decompressor *c, const void *data, size_t size, DecompressorCallback callback, void *userdata) { -#if HAVE_XZ || HAVE_LZ4 || HAVE_ZSTD || HAVE_ZLIB || HAVE_BZIP2 - _cleanup_free_ uint8_t *buffer = NULL; -#endif int r; assert(c); @@ -2040,6 +1964,7 @@ int decompressor_push(Decompressor *c, const void *data, size_t size, Decompress assert(data); #if HAVE_XZ || HAVE_LZ4 || HAVE_ZSTD || HAVE_ZLIB || HAVE_BZIP2 + _cleanup_free_ uint8_t *buffer = NULL; if (c->type != COMPRESSION_NONE) { buffer = new(uint8_t, COMPRESS_PIPE_BUFFER_SIZE); if (!buffer) @@ -2203,12 +2128,14 @@ int decompressor_push(Decompressor *c, const void *data, size_t size, Decompress } int compressor_new(Compressor **ret, Compression type) { -#if HAVE_XZ || HAVE_LZ4 || HAVE_ZSTD || HAVE_ZLIB || HAVE_BZIP2 int r; -#endif assert(ret); + r = dlopen_compress(type, LOG_DEBUG); + if (r < 0) + return r; + _cleanup_(compressor_freep) Compressor *c = new0(Compressor, 1); if (!c) return -ENOMEM; @@ -2223,10 +2150,6 @@ int compressor_new(Compressor **ret, Compression type) { #if HAVE_XZ case COMPRESSION_XZ: { - r = dlopen_xz(LOG_DEBUG); - if (r < 0) - return r; - lzma_ret xzr = sym_lzma_easy_encoder(&c->xz, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64); if (xzr != LZMA_OK) return -EIO; @@ -2238,10 +2161,6 @@ int compressor_new(Compressor **ret, Compression type) { #if HAVE_LZ4 case COMPRESSION_LZ4: { - r = dlopen_lz4(LOG_DEBUG); - if (r < 0) - return r; - size_t rc = sym_LZ4F_createCompressionContext(&c->c_lz4, LZ4F_VERSION); if (sym_LZ4F_isError(rc)) return -ENOMEM; @@ -2264,10 +2183,6 @@ int compressor_new(Compressor **ret, Compression type) { #if HAVE_ZSTD case COMPRESSION_ZSTD: - r = dlopen_zstd(LOG_DEBUG); - if (r < 0) - return r; - c->c_zstd = sym_ZSTD_createCCtx(); if (!c->c_zstd) return -ENOMEM; @@ -2287,10 +2202,6 @@ int compressor_new(Compressor **ret, Compression type) { #if HAVE_ZLIB case COMPRESSION_GZIP: - r = dlopen_zlib(LOG_DEBUG); - if (r < 0) - return r; - r = sym_deflateInit2_(&c->gzip, Z_DEFAULT_COMPRESSION, /* method= */ Z_DEFLATED, @@ -2307,10 +2218,6 @@ int compressor_new(Compressor **ret, Compression type) { #if HAVE_BZIP2 case COMPRESSION_BZIP2: - r = dlopen_bzip2(LOG_DEBUG); - if (r < 0) - return r; - r = sym_BZ2_bzCompressInit(&c->bzip2, /* blockSize100k= */ 9, /* verbosity= */ 0, /* workFactor= */ 0); if (r != BZ_OK) return -EIO; diff --git a/src/basic/compress.h b/src/basic/compress.h index f46b787f0c..8b183c193d 100644 --- a/src/basic/compress.h +++ b/src/basic/compress.h @@ -52,8 +52,8 @@ int compressor_new(Compressor **ret, Compression type); int compressor_start(Compressor *c, const void *data, size_t size, void **buffer, size_t *buffer_size, size_t *buffer_allocated); int compressor_finish(Compressor *c, void **buffer, size_t *buffer_size, size_t *buffer_allocated); -int decompressor_detect(Decompressor **ret, const void *data, size_t size); -int decompressor_force_off(Decompressor **ret); +int decompressor_detect(Decompressor **decompressor, const void *data, size_t size); +int decompressor_force_off(Decompressor **decompressor); int decompressor_push(Decompressor *c, const void *data, size_t size, DecompressorCallback callback, void *userdata); Compression compressor_type(const Compressor *c); @@ -102,6 +102,12 @@ int dlopen_zstd(int log_level) _dlopen_loader_; int dlopen_zlib(int log_level) _dlopen_loader_; int dlopen_bzip2(int log_level) _dlopen_loader_; +int dlopen_compress(Compression c, int log_level); +int dlopen_compress_journal(Compression c, int log_level); +static inline int dlopen_compress_default(int log_level) { + return dlopen_compress_journal(DEFAULT_COMPRESSION, log_level); +} + static inline const char* default_compression_extension(void) { return compression_extension_to_string(DEFAULT_COMPRESSION) ?: ""; } diff --git a/src/test/test-compress.c b/src/test/test-compress.c index 6e181c5b67..bfffcc4804 100644 --- a/src/test/test-compress.c +++ b/src/test/test-compress.c @@ -44,25 +44,18 @@ TEST(compress_decompress_blob) { for (size_t t = 0; t < 2; t++) { const char *input = t == 0 ? text : data; size_t input_len = t == 0 ? sizeof(text) : sizeof(data); - bool may_fail = t == 1; - char compressed[512]; + char compressed[sizeof(data) * 4]; size_t csize; _cleanup_free_ char *decompressed = NULL; - int r; log_info("/* testing %s %s blob compression/decompression */", label, input); - r = compress_blob(c, input, input_len, compressed, sizeof(compressed), &csize, -1); - if (r == -ENOBUFS) { - log_info_errno(r, "compression failed: %m"); - ASSERT_TRUE(may_fail); - } else { - ASSERT_OK(r); - ASSERT_OK_ZERO(decompress_blob(c, compressed, csize, (void **) &decompressed, &csize, 0)); - ASSERT_NOT_NULL(decompressed); - ASSERT_EQ(memcmp(decompressed, input, input_len), 0); - } + ASSERT_OK(compress_blob(c, input, input_len, compressed, sizeof(compressed), &csize, -1)); + + ASSERT_OK_ZERO(decompress_blob(c, compressed, csize, (void **) &decompressed, &csize, 0)); + ASSERT_NOT_NULL(decompressed); + ASSERT_EQ(memcmp(decompressed, input, input_len), 0); ASSERT_FAIL(decompress_blob(c, "garbage", 7, (void **) &decompressed, &csize, 0)); } diff --git a/test/test-dlopen-note.py b/test/test-dlopen-note.py index 295a0bc69c..5cb995eed7 100755 --- a/test/test-dlopen-note.py +++ b/test/test-dlopen-note.py @@ -33,6 +33,9 @@ except ImportError: # Function filter: Maps wrapper/sentinel symbols to real symbols or an empty list (ignore). FUNCTION_FILTER = { # Filtered out (internal helpers, verbose loggers, sentinels) + 'dlopen_compress': [], + 'dlopen_compress_journal': [], + 'dlopen_compress_default': [], 'dlopen_safe': [], 'dlopen_verbose': [], 'dlopen_many_sym_or_warn_sentinel': [],