diff options
Diffstat (limited to 'lib/comp/lz4.c')
-rw-r--r-- | lib/comp/lz4.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/lib/comp/lz4.c b/lib/comp/lz4.c new file mode 100644 index 0000000..f9c753d --- /dev/null +++ b/lib/comp/lz4.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include <lz4.h> +#include <lz4hc.h> + +#include "internal.h" + +typedef struct { + compressor_t base; +} lz4_compressor_t; + +typedef struct { + uint32_t version; + uint32_t flags; +} lz4_options; + +#define LZ4LEGACY 1 + +static int lz4_write_options(compressor_t *base, int fd) +{ + lz4_options opt = { + .version = htole32(LZ4LEGACY), + .flags = htole32(0), + }; + (void)base; + + return generic_write_options(fd, &opt, sizeof(opt)); +} + +static int lz4_read_options(compressor_t *base, int fd) +{ + lz4_options opt; + (void)base; + + if (generic_read_options(fd, &opt, sizeof(opt))) + return -1; + + opt.version = le32toh(opt.version); + opt.flags = le32toh(opt.flags); + + if (opt.version != LZ4LEGACY) { + fprintf(stderr, "unsupported lz4 version '%d'\n", opt.version); + return -1; + } + + return 0; +} + +static ssize_t lz4_comp_block(compressor_t *base, const uint8_t *in, + size_t size, uint8_t *out, size_t outsize) +{ + int ret; + (void)base; + + ret = LZ4_compress_default((void *)in, (void *)out, size, outsize); + + if (ret < 0) { + fputs("internal error in lz4 compressor\n", stderr); + return -1; + } + + return ret; +} + +static ssize_t lz4_uncomp_block(compressor_t *base, const uint8_t *in, + size_t size, uint8_t *out, size_t outsize) +{ + int ret; + (void)base; + + ret = LZ4_decompress_safe((void *)in, (void *)out, size, outsize); + + if (ret < 0) { + fputs("internal error in lz4 decompressor\n", stderr); + return -1; + } + + return ret; +} + +static void lz4_destroy(compressor_t *base) +{ + free(base); +} + +compressor_t *create_lz4_compressor(bool compress, size_t block_size) +{ + lz4_compressor_t *lz4 = calloc(1, sizeof(*lz4)); + compressor_t *base = (compressor_t *)lz4; + (void)block_size; + + if (lz4 == NULL) { + perror("creating lz4 compressor"); + return NULL; + } + + base->destroy = lz4_destroy; + base->do_block = compress ? lz4_comp_block : lz4_uncomp_block; + base->write_options = lz4_write_options; + base->read_options = lz4_read_options; + return base; +} |