#include <sys/types.h>
#include <unistd.h>
+#if HAVE_LZ4
+#include <lz4hc.h>
+#endif
+
#if HAVE_XZ
#include <lzma.h>
#endif
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;
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:
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);
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;
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;
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));
#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);
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;
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);
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);
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);
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;
}
}
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;
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));
#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);
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"));
#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);
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);
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);
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++) {