diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-05-19 21:46:34 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-05-19 21:46:34 +0200 |
commit | bc2bdb3c4f5cb969635f320beaa9e7bcf42450b2 (patch) | |
tree | 8e24aa2d76d79620558186bb0aa9a4c270c77672 /lib/comp | |
parent | 0a83c3d1709e88656be7d3f2d53259b550b57128 (diff) |
Add ZSTD compressor implementation
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/comp')
-rw-r--r-- | lib/comp/compressor.c | 3 | ||||
-rw-r--r-- | lib/comp/internal.h | 2 | ||||
-rw-r--r-- | lib/comp/zstd.c | 95 |
3 files changed, 100 insertions, 0 deletions
diff --git a/lib/comp/compressor.c b/lib/comp/compressor.c index 3b473a3..369cbea 100644 --- a/lib/comp/compressor.c +++ b/lib/comp/compressor.c @@ -20,6 +20,9 @@ static compressor_fun_t compressors[SQFS_COMP_MAX + 1] = { #ifdef WITH_LZ4 [SQFS_COMP_LZ4] = create_lz4_compressor, #endif +#ifdef WITH_ZSTD + [SQFS_COMP_ZSTD] = create_zstd_compressor, +#endif }; int generic_write_options(int fd, const void *data, size_t size) diff --git a/lib/comp/internal.h b/lib/comp/internal.h index 863f82b..8f880f4 100644 --- a/lib/comp/internal.h +++ b/lib/comp/internal.h @@ -16,4 +16,6 @@ compressor_t *create_lzo_compressor(bool compress, size_t block_size); compressor_t *create_lz4_compressor(bool compress, size_t block_size); +compressor_t *create_zstd_compressor(bool compress, size_t block_size); + #endif /* INTERNAL_H */ diff --git a/lib/comp/zstd.c b/lib/comp/zstd.c new file mode 100644 index 0000000..6c90505 --- /dev/null +++ b/lib/comp/zstd.c @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include <zstd.h> + +#include "internal.h" + +#define ZSTD_DEFAULT_COMPRESSION_LEVEL 15 + +typedef struct { + compressor_t base; + ZSTD_CCtx *zctx; +} zstd_compressor_t; + +static int zstd_write_options(compressor_t *base, int fd) +{ + (void)base; (void)fd; + return 0; +} + +static int zstd_read_options(compressor_t *base, int fd) +{ + (void)base; (void)fd; + fputs("zstd extra options are not yet implemented\n", stderr); + return -1; +} + +static ssize_t zstd_comp_block(compressor_t *base, const uint8_t *in, + size_t size, uint8_t *out, size_t outsize) +{ + zstd_compressor_t *zstd = (zstd_compressor_t *)base; + size_t ret; + + ret = ZSTD_compressCCtx(zstd->zctx, out, outsize, in, size, + ZSTD_DEFAULT_COMPRESSION_LEVEL); + + if (ZSTD_isError(ret)) { + fputs("internal error in ZSTD compressor\n", stderr); + return -1; + } + + return ret < size ? ret : 0; +} + +static ssize_t zstd_uncomp_block(compressor_t *base, const uint8_t *in, + size_t size, uint8_t *out, size_t outsize) +{ + size_t ret; + (void)base; + + ret = ZSTD_decompress(out, outsize, in, size); + + if (ZSTD_isError(ret)) { + fputs("error uncompressing ZSTD compressed data", stderr); + return -1; + } + + return ret; +} + +static void zstd_destroy(compressor_t *base) +{ + zstd_compressor_t *zstd = (zstd_compressor_t *)base; + + ZSTD_freeCCtx(zstd->zctx); + free(zstd); +} + +compressor_t *create_zstd_compressor(bool compress, size_t block_size) +{ + zstd_compressor_t *zstd = calloc(1, sizeof(*zstd)); + compressor_t *base = (compressor_t *)zstd; + (void)block_size; + + if (zstd == NULL) { + perror("creating zstd compressor"); + return NULL; + } + + zstd->zctx = ZSTD_createCCtx(); + if (zstd->zctx == NULL) { + fputs("error creating zstd compression context\n", stderr); + free(zstd); + return NULL; + } + + base->destroy = zstd_destroy; + base->do_block = compress ? zstd_comp_block : zstd_uncomp_block; + base->write_options = zstd_write_options; + base->read_options = zstd_read_options; + return base; +} |