mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
Merge pull request #15422 from nolange/add_zstd_coredump
coredump: add zstandard support for coredumps
This commit is contained in:
commit
80cf50120c
@ -52,6 +52,7 @@ BuildPackages=
|
||||
python-lxml
|
||||
qrencode
|
||||
xz
|
||||
zstd
|
||||
|
||||
Packages=
|
||||
libidn2
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
1
README
1
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)
|
||||
|
48
meson.build
48
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'],
|
||||
|
@ -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'],
|
||||
|
@ -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_ " " \
|
||||
|
@ -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)) {
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -329,6 +329,7 @@ libshared_deps = [threads,
|
||||
librt,
|
||||
libseccomp,
|
||||
libselinux,
|
||||
libzstd,
|
||||
libxz]
|
||||
|
||||
libshared_sym_path = '@0@/libshared.sym'.format(meson.current_source_dir())
|
||||
|
@ -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'],
|
||||
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user