summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Vereshchagin <evvers@ya.ru>2020-05-04 14:57:39 +0300
committerGitHub <noreply@github.com>2020-05-04 14:57:39 +0300
commit80cf50120c7102207f277ab57d9f21e160dbfb08 (patch)
treee64a2835407e867553a362bec77dd208f837d783
parentddd6a22a0fb034c763495fa1f3b6ebdd6a669e27 (diff)
parent8012d5c08eb9ca1c19a749bdf940c5feeed6e830 (diff)
downloadsystemd-80cf50120c7102207f277ab57d9f21e160dbfb08.tar.gz
Merge pull request #15422 from nolange/add_zstd_coredump
coredump: add zstandard support for coredumps
-rw-r--r--.mkosi/mkosi.arch1
-rw-r--r--.mkosi/mkosi.debian2
-rw-r--r--.mkosi/mkosi.fedora2
-rw-r--r--.mkosi/mkosi.ubuntu2
-rw-r--r--README1
-rw-r--r--meson.build48
-rw-r--r--meson_options.txt2
-rw-r--r--src/basic/build.h7
-rw-r--r--src/coredump/coredump.c2
-rw-r--r--src/coredump/coredumpctl.c4
-rw-r--r--src/journal/compress.c239
-rw-r--r--src/journal/compress.h7
-rw-r--r--src/journal/test-compress.c92
-rw-r--r--src/shared/meson.build1
-rw-r--r--src/test/meson.build2
-rwxr-xr-xtravis-ci/managers/debian.sh4
16 files changed, 357 insertions, 59 deletions
diff --git a/.mkosi/mkosi.arch b/.mkosi/mkosi.arch
index 350d7cd2b8..965e26e411 100644
--- a/.mkosi/mkosi.arch
+++ b/.mkosi/mkosi.arch
@@ -52,6 +52,7 @@ BuildPackages=
python-lxml
qrencode
xz
+ zstd
Packages=
libidn2
diff --git a/.mkosi/mkosi.debian b/.mkosi/mkosi.debian
index e85612bef1..ff0c8ffc07 100644
--- a/.mkosi/mkosi.debian
+++ b/.mkosi/mkosi.debian
@@ -50,6 +50,7 @@ BuildPackages=
libsmartcols-dev
libtool
libxkbcommon-dev
+ libzstd-dev
m4
meson
pkg-config
@@ -59,6 +60,7 @@ BuildPackages=
uuid-dev
xsltproc
xz-utils
+ zstd
Packages=
libqrencode4
diff --git a/.mkosi/mkosi.fedora b/.mkosi/mkosi.fedora
index 9769b05447..8afaa3ce55 100644
--- a/.mkosi/mkosi.fedora
+++ b/.mkosi/mkosi.fedora
@@ -47,6 +47,7 @@ BuildPackages=
libselinux-devel
libxkbcommon-devel
libxslt
+ libzstd-devel
lz4
lz4-devel
m4
@@ -62,6 +63,7 @@ BuildPackages=
tree
valgrind-devel
xz-devel
+ zstd
Packages=
coreutils
diff --git a/.mkosi/mkosi.ubuntu b/.mkosi/mkosi.ubuntu
index 1e4005f070..fc3192ccad 100644
--- a/.mkosi/mkosi.ubuntu
+++ b/.mkosi/mkosi.ubuntu
@@ -51,6 +51,7 @@ BuildPackages=
libsmartcols-dev
libtool
libxkbcommon-dev
+ libzstd-dev
m4
meson
pkg-config
@@ -61,6 +62,7 @@ BuildPackages=
uuid-dev
xsltproc
xz-utils
+ zstd
Packages=
libqrencode3
diff --git a/README b/README
index b2c8d28411..4f4a21eeca 100644
--- a/README
+++ b/README
@@ -150,6 +150,7 @@ REQUIREMENTS:
libselinux (optional)
liblzma (optional)
liblz4 >= 1.3.0 / 130 (optional)
+ libzstd >= 1.4.0 (optional)
libgcrypt (optional)
libqrencode (optional)
libmicrohttpd (optional)
diff --git a/meson.build b/meson.build
index 6c9299e27b..fef3c27cf4 100644
--- a/meson.build
+++ b/meson.build
@@ -1195,6 +1195,18 @@ else
endif
conf.set10('HAVE_LZ4', have)
+want_zstd = get_option('zstd')
+if want_zstd != 'false' and not skip_deps
+ libzstd = dependency('libzstd',
+ required : want_zstd == 'true',
+ version : '>= 1.4.0')
+ have = libzstd.found()
+else
+ have = false
+ libzstd = []
+endif
+conf.set10('HAVE_ZSTD', have)
+
want_xkbcommon = get_option('xkbcommon')
if want_xkbcommon != 'false' and not skip_deps
libxkbcommon = dependency('xkbcommon',
@@ -1543,6 +1555,7 @@ libsystemd = shared_library(
dependencies : [threads,
librt,
libxz,
+ libzstd,
liblz4],
link_depends : libsystemd_sym,
install : true,
@@ -1566,6 +1579,7 @@ install_libsystemd_static = static_library(
dependencies : [threads,
librt,
libxz,
+ libzstd,
liblz4,
libcap,
libblkid,
@@ -1727,7 +1741,8 @@ executable(
dependencies : [threads,
libxz,
liblz4,
- libselinux],
+ libselinux,
+ libzstd],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
@@ -1751,7 +1766,8 @@ public_programs += executable(
libqrencode,
libxz,
liblz4,
- libpcre2],
+ libpcre2,
+ libzstd],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootbindir)
@@ -1906,7 +1922,8 @@ if conf.get('ENABLE_LOGIND') == 1
link_with : [libshared],
dependencies : [threads,
liblz4,
- libxz],
+ libxz,
+ libzstd],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootbindir)
@@ -2036,7 +2053,8 @@ public_programs += executable(
libcap,
libselinux,
libxz,
- liblz4],
+ liblz4,
+ libzstd],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootbindir)
@@ -2386,7 +2404,8 @@ if conf.get('ENABLE_MACHINED') == 1
link_with : [libshared],
dependencies : [threads,
libxz,
- liblz4],
+ liblz4,
+ libzstd],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootbindir)
@@ -2467,7 +2486,8 @@ if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_LIBCURL') == 1
libcurl,
libgnutls,
libxz,
- liblz4],
+ liblz4,
+ libzstd],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
@@ -2484,7 +2504,8 @@ if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1
libmicrohttpd,
libgnutls,
libxz,
- liblz4],
+ liblz4,
+ libzstd],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
@@ -2498,7 +2519,8 @@ if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1
libmicrohttpd,
libgnutls,
libxz,
- liblz4],
+ liblz4,
+ libzstd],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
@@ -2514,7 +2536,8 @@ if conf.get('ENABLE_COREDUMP') == 1
libacl,
libdw,
libxz,
- liblz4],
+ liblz4,
+ libzstd],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
@@ -2526,7 +2549,8 @@ if conf.get('ENABLE_COREDUMP') == 1
link_with : [libshared],
dependencies : [threads,
libxz,
- liblz4],
+ liblz4,
+ libzstd],
install_rpath : rootlibexecdir,
install : true)
endif
@@ -2541,7 +2565,8 @@ if conf.get('ENABLE_PSTORE') == 1
libacl,
libdw,
libxz,
- liblz4],
+ liblz4,
+ libzstd],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
@@ -3496,6 +3521,7 @@ foreach tuple : [
['SMACK'],
['zlib'],
['xz'],
+ ['zstd'],
['lz4'],
['bzip2'],
['ACL'],
diff --git a/meson_options.txt b/meson_options.txt
index 104a7ea043..0229179c99 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -316,6 +316,8 @@ option('xz', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'xz compression support')
option('lz4', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'lz4 compression support')
+option('zstd', type : 'combo', choices : ['auto', 'true', 'false'],
+ description : 'zstd compression support')
option('xkbcommon', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'xkbcommon keymap support')
option('pcre2', type : 'combo', choices : ['auto', 'true', 'false'],
diff --git a/src/basic/build.h b/src/basic/build.h
index c47e912eb0..d160af5bc7 100644
--- a/src/basic/build.h
+++ b/src/basic/build.h
@@ -87,6 +87,12 @@
#define _LZ4_FEATURE_ "-LZ4"
#endif
+#if HAVE_ZSTD
+#define _ZSTD_FEATURE_ "+ZSTD"
+#else
+#define _ZSTD_FEATURE_ "-ZSTD"
+#endif
+
#if HAVE_SECCOMP
#define _SECCOMP_FEATURE_ "+SECCOMP"
#else
@@ -146,6 +152,7 @@
_ACL_FEATURE_ " " \
_XZ_FEATURE_ " " \
_LZ4_FEATURE_ " " \
+ _ZSTD_FEATURE_ " " \
_SECCOMP_FEATURE_ " " \
_BLKID_FEATURE_ " " \
_ELFUTILS_FEATURE_ " " \
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index b88b284584..ff4238c91d 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -420,7 +420,7 @@ static int save_external_coredump(
goto fail;
}
-#if HAVE_XZ || HAVE_LZ4
+#if HAVE_XZ || HAVE_LZ4 || HAVE_ZSTD
/* If we will remove the coredump anyway, do not compress. */
if (arg_compress && !maybe_remove_external_coredump(NULL, st.st_size)) {
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c
index a848268177..60a02b770b 100644
--- a/src/coredump/coredumpctl.c
+++ b/src/coredump/coredumpctl.c
@@ -765,7 +765,7 @@ static int save_core(sd_journal *j, FILE *file, char **path, bool *unlink_temp)
if (access(filename, R_OK) < 0)
return log_error_errno(errno, "File \"%s\" is not readable: %m", filename);
- if (path && !endswith(filename, ".xz") && !endswith(filename, ".lz4")) {
+ if (path && !ENDSWITH_SET(filename, ".xz", ".lz4", ".zst")) {
*path = TAKE_PTR(filename);
return 0;
@@ -824,7 +824,7 @@ static int save_core(sd_journal *j, FILE *file, char **path, bool *unlink_temp)
}
if (filename) {
-#if HAVE_XZ || HAVE_LZ4
+#if HAVE_XZ || HAVE_LZ4 || HAVE_ZSTD
_cleanup_close_ int fdf;
fdf = open(filename, O_RDONLY | O_CLOEXEC);
diff --git a/src/journal/compress.c b/src/journal/compress.c
index 4e00e4fc5e..2bbfc7644a 100644
--- a/src/journal/compress.c
+++ b/src/journal/compress.c
@@ -16,6 +16,11 @@
#include <lz4frame.h>
#endif
+#if HAVE_ZSTD
+#include <zstd.h>
+#include <zstd_errors.h>
+#endif
+
#include "alloc-util.h"
#include "compress.h"
#include "fd-util.h"
@@ -33,6 +38,22 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_compressionContext_t, LZ4F_freeCompressionConte
DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_decompressionContext_t, LZ4F_freeDecompressionContext);
#endif
+#if HAVE_ZSTD
+DEFINE_TRIVIAL_CLEANUP_FUNC(ZSTD_CCtx *, ZSTD_freeCCtx);
+DEFINE_TRIVIAL_CLEANUP_FUNC(ZSTD_DCtx *, ZSTD_freeDCtx);
+
+static int zstd_ret_to_errno(size_t ret) {
+ switch (ZSTD_getErrorCode(ret)) {
+ case ZSTD_error_dstSize_tooSmall:
+ return -ENOBUFS;
+ case ZSTD_error_memory_allocation:
+ return -ENOMEM;
+ default:
+ return -EBADMSG;
+ }
+}
+#endif
+
#define ALIGN_8(l) ALIGN_TO(l, sizeof(size_t))
static const char* const object_compressed_table[_OBJECT_COMPRESSED_MAX] = {
@@ -668,12 +689,230 @@ int decompress_stream_lz4(int in, int out, uint64_t max_bytes) {
#endif
}
+int compress_stream_zstd(int fdf, int fdt, uint64_t max_bytes) {
+#if HAVE_ZSTD
+ _cleanup_(ZSTD_freeCCtxp) ZSTD_CCtx *cctx = NULL;
+ _cleanup_free_ void *in_buff = NULL, *out_buff = NULL;
+ size_t in_allocsize, out_allocsize;
+ size_t z;
+ uint64_t left = max_bytes, in_bytes = 0;
+ /* This can be used in the future to add uncompressed size to the header */
+ uint64_t in_totalsize = 0;
+
+ assert(fdf >= 0);
+ assert(fdt >= 0);
+
+ /* Create the context and buffers */
+ in_allocsize = ZSTD_CStreamInSize();
+ out_allocsize = ZSTD_CStreamOutSize();
+ in_buff = malloc(in_allocsize);
+ out_buff = malloc(out_allocsize);
+ cctx = ZSTD_createCCtx();
+ if (!cctx || !out_buff || !in_buff)
+ return -ENOMEM;
+
+ if (in_totalsize) {
+ z = ZSTD_CCtx_setPledgedSrcSize(cctx, in_totalsize);
+ if (z)
+ log_debug("Failed to enable ZSTD input size, ignoring: %s", ZSTD_getErrorName(z));
+ }
+ z = ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1);
+ if (ZSTD_isError(z))
+ log_debug("Failed to enable ZSTD checksum, ignoring: %s", ZSTD_getErrorName(z));
+
+ /* This loop read from the input file, compresses that entire chunk,
+ * and writes all output produced to the output file.
+ */
+ for (;;) {
+ bool is_last_chunk;
+ ZSTD_inBuffer input = {
+ .src = in_buff,
+ .size = 0,
+ .pos = 0
+ };
+ ssize_t red;
+
+ red = loop_read(fdf, in_buff, in_allocsize, true);
+ if (red < 0)
+ return red;
+ is_last_chunk = red == 0;
+
+ in_bytes += (size_t) red;
+ input.size = (size_t) red;
+
+ for (bool finished = false; !finished;) {
+ ZSTD_outBuffer output = {
+ .dst = out_buff,
+ .size = out_allocsize,
+ .pos = 0
+ };
+ size_t remaining;
+ ssize_t wrote;
+
+ /* Compress into the output buffer and write all of the
+ * output to the file so we can reuse the buffer next
+ * iteration.
+ */
+ remaining = ZSTD_compressStream2(
+ cctx, &output, &input,
+ is_last_chunk ? ZSTD_e_end : ZSTD_e_continue);
+
+ if (ZSTD_isError(remaining)) {
+ log_debug("ZSTD encoder failed: %s", ZSTD_getErrorName(remaining));
+ return zstd_ret_to_errno(remaining);
+ }
+
+ if (left < output.pos)
+ return -EFBIG;
+
+ wrote = loop_write(fdt, output.dst, output.pos, 1);
+ if (wrote < 0)
+ return wrote;
+
+ left -= output.pos;
+
+ /* If we're on the last chunk we're finished when zstd
+ * returns 0, which means its consumed all the input AND
+ * finished the frame. Otherwise, we're finished when
+ * we've consumed all the input.
+ */
+ finished = is_last_chunk ? (remaining == 0) : (input.pos == input.size);
+ }
+
+ /* zstd only returns 0 when the input is completely consumed */
+ assert(input.pos == input.size);
+ if (is_last_chunk)
+ break;
+ }
+
+ log_debug(
+ "ZSTD compression finished (%" PRIu64 " -> %" PRIu64 " bytes, %.1f%%)",
+ in_bytes,
+ max_bytes - left,
+ (double) (max_bytes - left) / in_bytes * 100);
+
+ return 0;
+#else
+ return -EPROTONOSUPPORT;
+#endif
+}
+
+int decompress_stream_zstd(int fdf, int fdt, uint64_t max_bytes) {
+#if HAVE_ZSTD
+ _cleanup_(ZSTD_freeDCtxp) ZSTD_DCtx *dctx = NULL;
+ _cleanup_free_ void *in_buff = NULL, *out_buff = NULL;
+ size_t in_allocsize, out_allocsize;
+ size_t last_result = 0;
+ uint64_t left = max_bytes, in_bytes = 0;
+
+ assert(fdf >= 0);
+ assert(fdt >= 0);
+
+ /* Create the context and buffers */
+ in_allocsize = ZSTD_DStreamInSize();
+ out_allocsize = ZSTD_DStreamOutSize();
+ in_buff = malloc(in_allocsize);
+ out_buff = malloc(out_allocsize);
+ dctx = ZSTD_createDCtx();
+ if (!dctx || !out_buff || !in_buff)
+ return -ENOMEM;
+
+ /* This loop assumes that the input file is one or more concatenated
+ * zstd streams. This example won't work if there is trailing non-zstd
+ * data at the end, but streaming decompression in general handles this
+ * case. ZSTD_decompressStream() returns 0 exactly when the frame is
+ * completed, and doesn't consume input after the frame.
+ */
+ for (;;) {
+ bool has_error = false;
+ ZSTD_inBuffer input = {
+ .src = in_buff,
+ .size = 0,
+ .pos = 0
+ };
+ ssize_t red;
+
+ red = loop_read(fdf, in_buff, in_allocsize, true);
+ if (red < 0)
+ return red;
+ if (red == 0)
+ break;
+
+ in_bytes += (size_t) red;
+ input.size = (size_t) red;
+ input.pos = 0;
+
+ /* Given a valid frame, zstd won't consume the last byte of the
+ * frame until it has flushed all of the decompressed data of
+ * the frame. So input.pos < input.size means frame is not done
+ * or there is still output available.
+ */
+ while (input.pos < input.size) {
+ ZSTD_outBuffer output = {
+ .dst = out_buff,
+ .size = out_allocsize,
+ .pos = 0
+ };
+ ssize_t wrote;
+ /* The return code is zero if the frame is complete, but
+ * there may be multiple frames concatenated together.
+ * Zstd will automatically reset the context when a
+ * frame is complete. Still, calling ZSTD_DCtx_reset()
+ * can be useful to reset the context to a clean state,
+ * for instance if the last decompression call returned
+ * an error.
+ */
+ last_result = ZSTD_decompressStream(dctx, &output, &input);
+ if (ZSTD_isError(last_result)) {
+ has_error = true;
+ break;
+ }
+
+ if (left < output.pos)
+ return -EFBIG;
+
+ wrote = loop_write(fdt, output.dst, output.pos, 1);
+ if (wrote < 0)
+ return wrote;
+
+ left -= output.pos;
+ }
+ if (has_error)
+ break;
+ }
+
+ if (in_bytes == 0)
+ return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "ZSTD decoder failed: no data read");
+
+ if (last_result != 0) {
+ /* The last return value from ZSTD_decompressStream did not end
+ * on a frame, but we reached the end of the file! We assume
+ * this is an error, and the input was truncated.
+ */
+ log_debug("ZSTD decoder failed: %s", ZSTD_getErrorName(last_result));
+ return zstd_ret_to_errno(last_result);
+ }
+
+ log_debug(
+ "ZSTD decompression finished (%" PRIu64 " -> %" PRIu64 " bytes, %.1f%%)",
+ in_bytes,
+ max_bytes - left,
+ (double) (max_bytes - left) / in_bytes * 100);
+ return 0;
+#else
+ log_debug("Cannot decompress file. Compiled without ZSTD support.");
+ return -EPROTONOSUPPORT;
+#endif
+}
+
int decompress_stream(const char *filename, int fdf, int fdt, uint64_t max_bytes) {
if (endswith(filename, ".lz4"))
return decompress_stream_lz4(fdf, fdt, max_bytes);
else if (endswith(filename, ".xz"))
return decompress_stream_xz(fdf, fdt, max_bytes);
+ else if (endswith(filename, ".zst"))
+ return decompress_stream_zstd(fdf, fdt, max_bytes);
else
return -EPROTONOSUPPORT;
}
diff --git a/src/journal/compress.h b/src/journal/compress.h
index 56411484ce..74ef592f43 100644
--- a/src/journal/compress.h
+++ b/src/journal/compress.h
@@ -52,11 +52,16 @@ int decompress_startswith(int compression,
int compress_stream_xz(int fdf, int fdt, uint64_t max_bytes);
int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes);
+int compress_stream_zstd(int fdf, int fdt, uint64_t max_bytes);
int decompress_stream_xz(int fdf, int fdt, uint64_t max_size);
int decompress_stream_lz4(int fdf, int fdt, uint64_t max_size);
+int decompress_stream_zstd(int fdf, int fdt, uint64_t max_size);
-#if HAVE_LZ4
+#if HAVE_ZSTD
+# define compress_stream compress_stream_zstd
+# define COMPRESSED_EXT ".zst"
+#elif HAVE_LZ4
# define compress_stream compress_stream_lz4
# define COMPRESSED_EXT ".lz4"
#else
diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c
index 0b2898e109..c9d295b3c1 100644
--- a/src/journal/test-compress.c
+++ b/src/journal/test-compress.c
@@ -44,20 +44,20 @@ typedef int (decompress_sw_t)(const void *src, uint64_t src_size,
typedef int (compress_stream_t)(int fdf, int fdt, uint64_t max_bytes);
typedef int (decompress_stream_t)(int fdf, int fdt, uint64_t max_size);
-#if HAVE_XZ || HAVE_LZ4
-static void test_compress_decompress(int compression,
- compress_blob_t compress,
- decompress_blob_t decompress,
- const char *data,
- size_t data_len,
- bool may_fail) {
+#if HAVE_XZ || HAVE_LZ4 || HAVE_ZSTD
+_unused_ static void test_compress_decompress(const char *compression,
+ compress_blob_t compress,
+ decompress_blob_t decompress,
+ const char *data,
+ size_t data_len,
+ bool may_fail) {
char compressed[512];
size_t csize, usize = 0;
_cleanup_free_ char *decompressed = NULL;
int r;
log_info("/* testing %s %s blob compression/decompression */",
- object_compressed_to_string(compression), data);
+ compression, data);
r = compress(data, data_len, compressed, sizeof(compressed), &csize);
if (r == -ENOBUFS) {
@@ -88,12 +88,12 @@ static void test_compress_decompress(int compression,
memzero(decompressed, usize);
}
-static void test_decompress_startswith(int compression,
- compress_blob_t compress,
- decompress_sw_t decompress_sw,
- const char *data,
- size_t data_len,
- bool may_fail) {
+_unused_ static void test_decompress_startswith(const char *compression,
+ compress_blob_t compress,
+ decompress_sw_t decompress_sw,
+ const char *data,
+ size_t data_len,
+ bool may_fail) {
char *compressed;
_cleanup_free_ char *compressed1 = NULL, *compressed2 = NULL, *decompressed = NULL;
@@ -101,7 +101,7 @@ static void test_decompress_startswith(int compression,
int r;
log_info("/* testing decompress_startswith with %s on %.20s text */",
- object_compressed_to_string(compression), data);
+ compression, data);
#define BUFSIZE_1 512
#define BUFSIZE_2 20000
@@ -136,9 +136,9 @@ static void test_decompress_startswith(int compression,
assert_se(r > 0);
}
-static void test_decompress_startswith_short(int compression,
- compress_blob_t compress,
- decompress_sw_t decompress_sw) {
+_unused_ static void test_decompress_startswith_short(const char *compression,
+ compress_blob_t compress,
+ decompress_sw_t decompress_sw) {
#define TEXT "HUGE=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
@@ -146,7 +146,7 @@ static void test_decompress_startswith_short(int compression,
size_t i, csize;
int r;
- log_info("/* %s with %s */", __func__, object_compressed_to_string(compression));
+ log_info("/* %s with %s */", __func__, compression);
r = compress(TEXT, sizeof TEXT, buf, sizeof buf, &csize);
assert_se(r == 0);
@@ -162,11 +162,11 @@ static void test_decompress_startswith_short(int compression,
}
}
-static void test_compress_stream(int compression,
- const char* cat,
- compress_stream_t compress,
- decompress_stream_t decompress,
- const char *srcfile) {
+_unused_ static void test_compress_stream(const char *compression,
+ const char *cat,
+ compress_stream_t compress,
+ decompress_stream_t decompress,
+ const char *srcfile) {
_cleanup_close_ int src = -1, dst = -1, dst2 = -1;
_cleanup_(unlink_tempfilep) char
@@ -182,8 +182,7 @@ static void test_compress_stream(int compression,
return;
}
- log_debug("/* testing %s compression */",
- object_compressed_to_string(compression));
+ log_debug("/* testing %s compression */", compression);
log_debug("/* create source from %s */", srcfile);
@@ -266,8 +265,8 @@ static void test_lz4_decompress_partial(void) {
#endif
int main(int argc, char *argv[]) {
-#if HAVE_XZ || HAVE_LZ4
- const char text[] =
+#if HAVE_XZ || HAVE_LZ4 || HAVE_ZSTD
+ _unused_ const char text[] =
"text\0foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF"
"foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF";
@@ -288,60 +287,67 @@ int main(int argc, char *argv[]) {
random_bytes(data + 7, sizeof(data) - 7);
#if HAVE_XZ
- test_compress_decompress(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_blob_xz,
+ test_compress_decompress("XZ", compress_blob_xz, decompress_blob_xz,
text, sizeof(text), false);
- test_compress_decompress(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_blob_xz,
+ test_compress_decompress("XZ", compress_blob_xz, decompress_blob_xz,
data, sizeof(data), true);
- test_decompress_startswith(OBJECT_COMPRESSED_XZ,
+ test_decompress_startswith("XZ",
compress_blob_xz, decompress_startswith_xz,
text, sizeof(text), false);
- test_decompress_startswith(OBJECT_COMPRESSED_XZ,
+ test_decompress_startswith("XZ",
compress_blob_xz, decompress_startswith_xz,
data, sizeof(data), true);
- test_decompress_startswith(OBJECT_COMPRESSED_XZ,
+ test_decompress_startswith("XZ",
compress_blob_xz, decompress_startswith_xz,
huge, HUGE_SIZE, true);
- test_compress_stream(OBJECT_COMPRESSED_XZ, "xzcat",
+ test_compress_stream("XZ", "xzcat",
compress_stream_xz, decompress_stream_xz, srcfile);
- test_decompress_startswith_short(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_startswith_xz);
+ test_decompress_startswith_short("XZ", compress_blob_xz, decompress_startswith_xz);
#else
log_info("/* XZ test skipped */");
#endif
#if HAVE_LZ4
- test_compress_decompress(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_blob_lz4,
+ test_compress_decompress("LZ4", compress_blob_lz4, decompress_blob_lz4,
text, sizeof(text), false);
- test_compress_decompress(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_blob_lz4,
+ test_compress_decompress("LZ4", compress_blob_lz4, decompress_blob_lz4,
data, sizeof(data), true);
- test_decompress_startswith(OBJECT_COMPRESSED_LZ4,
+ test_decompress_startswith("LZ4",
compress_blob_lz4, decompress_startswith_lz4,
text, sizeof(text), false);
- test_decompress_startswith(OBJECT_COMPRESSED_LZ4,
+ test_decompress_startswith("LZ4",
compress_blob_lz4, decompress_startswith_lz4,
data, sizeof(data), true);
- test_decompress_startswith(OBJECT_COMPRESSED_LZ4,
+ test_decompress_startswith("LZ4",
compress_blob_lz4, decompress_startswith_lz4,
huge, HUGE_SIZE, true);
- test_compress_stream(OBJECT_COMPRESSED_LZ4, "lz4cat",
+ test_compress_stream("LZ4", "lz4cat",
compress_stream_lz4, decompress_stream_lz4, srcfile);
test_lz4_decompress_partial();
- test_decompress_startswith_short(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_startswith_lz4);
+ test_decompress_startswith_short("LZ4", compress_blob_lz4, decompress_startswith_lz4);
#else
log_info("/* LZ4 test skipped */");
#endif
+#if HAVE_ZSTD
+ test_compress_stream("ZSTD", "zstdcat",
+ compress_stream_zstd, decompress_stream_zstd, srcfile);
+#else
+ log_info("/* ZSTD test skipped */");
+#endif
+
return 0;
#else
- log_info("/* XZ and LZ4 tests skipped */");
+ log_info("/* XZ, LZ4 and ZSTD tests skipped */");
return EXIT_TEST_SKIP;
#endif
}
diff --git a/src/shared/meson.build b/src/shared/meson.build
index e608ea8a1d..41d214890c 100644
--- a/src/shared/meson.build
+++ b/src/shared/meson.build
@@ -329,6 +329,7 @@ libshared_deps = [threads,
librt,
libseccomp,
libselinux,
+ libzstd,
libxz]
libshared_sym_path = '@0@/libshared.sym'.format(meson.current_source_dir())
diff --git a/src/test/meson.build b/src/test/meson.build
index 7f96be8f55..b133980e45 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -893,12 +893,14 @@ tests += [
[libjournal_core,
libshared],
[liblz4,
+ libzstd,
libxz]],
[['src/journal/test-compress-benchmark.c'],
[libjournal_core,
libshared],
[liblz4,
+ libzstd,
libxz],
'', 'timeout=90'],
diff --git a/travis-ci/managers/debian.sh b/travis-ci/managers/debian.sh
index ac86e6274e..82f3b36606 100755
--- a/travis-ci/managers/debian.sh
+++ b/travis-ci/managers/debian.sh
@@ -22,7 +22,9 @@ ADDITIONAL_DEPS=(python3-libevdev
libpwquality-dev
libfdisk-dev
libp11-kit-dev
- libssl-dev)
+ libssl-dev
+ libzstd-dev
+ zstd)
function info() {
echo -e "\033[33;1m$1\033[0m"