aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs/comp
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-01-31 11:21:30 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-01-31 13:51:49 +0100
commitcdccc69c62579b0c13b35fad0728079652b8f3c9 (patch)
tree9fa54c710f73c5e08a9c8466e7a712eb63ee07ac /lib/sqfs/comp
parent2182129c8f359c4fa1390eaba7a65b595ccd4182 (diff)
Move library source into src sub-directory
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs/comp')
-rw-r--r--lib/sqfs/comp/compressor.c218
-rw-r--r--lib/sqfs/comp/gzip.c307
-rw-r--r--lib/sqfs/comp/internal.h46
-rw-r--r--lib/sqfs/comp/lz4.c172
-rw-r--r--lib/sqfs/comp/lzma.c281
-rw-r--r--lib/sqfs/comp/xz.c324
-rw-r--r--lib/sqfs/comp/zstd.c172
7 files changed, 0 insertions, 1520 deletions
diff --git a/lib/sqfs/comp/compressor.c b/lib/sqfs/comp/compressor.c
deleted file mode 100644
index 4c4d73c..0000000
--- a/lib/sqfs/comp/compressor.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * compressor.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#define SQFS_BUILDING_DLL
-#include "config.h"
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "internal.h"
-
-typedef int (*compressor_fun_t)(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out);
-
-static compressor_fun_t compressors[SQFS_COMP_MAX + 1] = {
-#ifdef WITH_GZIP
- [SQFS_COMP_GZIP] = gzip_compressor_create,
-#endif
-#ifdef WITH_XZ
- [SQFS_COMP_XZ] = xz_compressor_create,
- [SQFS_COMP_LZMA] = lzma_compressor_create,
-#endif
-#ifdef WITH_LZ4
- [SQFS_COMP_LZ4] = lz4_compressor_create,
-#endif
-#ifdef WITH_ZSTD
- [SQFS_COMP_ZSTD] = zstd_compressor_create,
-#endif
-};
-
-static const char *names[] = {
- [SQFS_COMP_GZIP] = "gzip",
- [SQFS_COMP_LZMA] = "lzma",
- [SQFS_COMP_LZO] = "lzo",
- [SQFS_COMP_XZ] = "xz",
- [SQFS_COMP_LZ4] = "lz4",
- [SQFS_COMP_ZSTD] = "zstd",
-};
-
-int sqfs_generic_write_options(sqfs_file_t *file, const void *data, size_t size)
-{
- sqfs_u8 buffer[64];
- sqfs_u16 header;
- int ret;
-
- /* XXX: options for all known compressors should fit into this */
- if (size >= (sizeof(buffer) - sizeof(header)))
- return SQFS_ERROR_INTERNAL;
-
- header = htole16(0x8000 | size);
- memcpy(buffer, &header, sizeof(header));
- memcpy(buffer + sizeof(header), data, size);
-
- ret = file->write_at(file, sizeof(sqfs_super_t),
- buffer, sizeof(header) + size);
- if (ret)
- return ret;
-
- return sizeof(header) + size;
-}
-
-int sqfs_generic_read_options(sqfs_file_t *file, void *data, size_t size)
-{
- sqfs_u8 buffer[64];
- sqfs_u16 header;
- int ret;
-
- /* XXX: options for all known compressors should fit into this */
- if (size >= (sizeof(buffer) - sizeof(header)))
- return SQFS_ERROR_INTERNAL;
-
- ret = file->read_at(file, sizeof(sqfs_super_t),
- buffer, sizeof(header) + size);
- if (ret)
- return ret;
-
- memcpy(&header, buffer, sizeof(header));
-
- if (le16toh(header) != (0x8000 | size))
- return SQFS_ERROR_CORRUPTED;
-
- memcpy(data, buffer + 2, size);
- return 0;
-}
-
-int sqfs_compressor_create(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out)
-{
- sqfs_u8 padd0[sizeof(cfg->opt)];
- int ret;
-
- *out = NULL;
-
- /* check compressor ID */
- if (cfg == NULL)
- return SQFS_ERROR_ARG_INVALID;
-
- if (cfg->id < SQFS_COMP_MIN || cfg->id > SQFS_COMP_MAX)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (compressors[cfg->id] == NULL)
- return SQFS_ERROR_UNSUPPORTED;
-
- /* make sure the padding bytes are cleared, so we could theoretically
- turn them into option fields in the future and remain compatible */
- memset(padd0, 0, sizeof(padd0));
-
- switch (cfg->id) {
- case SQFS_COMP_XZ:
- ret = memcmp(cfg->opt.xz.padd0, padd0,
- sizeof(cfg->opt.xz.padd0));
- break;
- case SQFS_COMP_LZMA:
- ret = memcmp(cfg->opt.lzma.padd0, padd0,
- sizeof(cfg->opt.lzma.padd0));
- break;
- case SQFS_COMP_LZO:
- ret = memcmp(cfg->opt.lzo.padd0, padd0,
- sizeof(cfg->opt.lzo.padd0));
- break;
- case SQFS_COMP_GZIP:
- ret = memcmp(cfg->opt.gzip.padd0, padd0,
- sizeof(cfg->opt.gzip.padd0));
- break;
- default:
- ret = memcmp(cfg->opt.padd0, padd0, sizeof(cfg->opt.padd0));
- break;
- }
-
- if (ret != 0)
- return SQFS_ERROR_ARG_INVALID;
-
- return compressors[cfg->id](cfg, out);
-}
-
-const char *sqfs_compressor_name_from_id(SQFS_COMPRESSOR id)
-{
- if (id < 0 || (size_t)id >= sizeof(names) / sizeof(names[0]))
- return NULL;
-
- return names[id];
-}
-
-int sqfs_compressor_id_from_name(const char *name)
-{
- size_t i;
-
- for (i = 0; i < sizeof(names) / sizeof(names[0]); ++i) {
- if (names[i] != NULL && strcmp(names[i], name) == 0)
- return i;
- }
-
- return SQFS_ERROR_UNSUPPORTED;
-}
-
-int sqfs_compressor_config_init(sqfs_compressor_config_t *cfg,
- SQFS_COMPRESSOR id,
- size_t block_size, sqfs_u16 flags)
-{
- sqfs_u32 flag_mask = SQFS_COMP_FLAG_GENERIC_ALL;
-
- memset(cfg, 0, sizeof(*cfg));
-
- switch (id) {
- case SQFS_COMP_GZIP:
- flag_mask |= SQFS_COMP_FLAG_GZIP_ALL;
- cfg->level = SQFS_GZIP_DEFAULT_LEVEL;
- cfg->opt.gzip.window_size = SQFS_GZIP_DEFAULT_WINDOW;
- break;
- case SQFS_COMP_LZO:
- cfg->opt.lzo.algorithm = SQFS_LZO_DEFAULT_ALG;
- cfg->level = SQFS_LZO_DEFAULT_LEVEL;
- break;
- case SQFS_COMP_ZSTD:
- cfg->level = SQFS_ZSTD_DEFAULT_LEVEL;
- break;
- case SQFS_COMP_XZ:
- flag_mask |= SQFS_COMP_FLAG_XZ_ALL;
- cfg->level = SQFS_XZ_DEFAULT_LEVEL;
- cfg->opt.xz.dict_size = block_size;
- cfg->opt.xz.lc = SQFS_XZ_DEFAULT_LC;
- cfg->opt.xz.lp = SQFS_XZ_DEFAULT_LP;
- cfg->opt.xz.pb = SQFS_XZ_DEFAULT_PB;
-
- if (block_size < SQFS_XZ_MIN_DICT_SIZE)
- cfg->opt.xz.dict_size = SQFS_XZ_MIN_DICT_SIZE;
- break;
- case SQFS_COMP_LZMA:
- flag_mask |= SQFS_COMP_FLAG_LZMA_ALL;
- cfg->level = SQFS_LZMA_DEFAULT_LEVEL;
- cfg->opt.lzma.dict_size = block_size;
- cfg->opt.lzma.lc = SQFS_LZMA_DEFAULT_LC;
- cfg->opt.lzma.lp = SQFS_LZMA_DEFAULT_LP;
- cfg->opt.lzma.pb = SQFS_LZMA_DEFAULT_PB;
-
- if (block_size < SQFS_LZMA_MIN_DICT_SIZE)
- cfg->opt.lzma.dict_size = SQFS_LZMA_MIN_DICT_SIZE;
- break;
- case SQFS_COMP_LZ4:
- flag_mask |= SQFS_COMP_FLAG_LZ4_ALL;
- break;
- default:
- return SQFS_ERROR_UNSUPPORTED;
- }
-
- if (flags & ~flag_mask) {
- memset(cfg, 0, sizeof(*cfg));
- return SQFS_ERROR_UNSUPPORTED;
- }
-
- cfg->id = id;
- cfg->flags = flags;
- cfg->block_size = block_size;
- return 0;
-}
diff --git a/lib/sqfs/comp/gzip.c b/lib/sqfs/comp/gzip.c
deleted file mode 100644
index beacfb8..0000000
--- a/lib/sqfs/comp/gzip.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * gzip.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#define SQFS_BUILDING_DLL
-#include "config.h"
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <zlib.h>
-
-#include "internal.h"
-
-typedef struct {
- sqfs_u32 level;
- sqfs_u16 window;
- sqfs_u16 strategies;
-} gzip_options_t;
-
-typedef struct {
- sqfs_compressor_t base;
-
- z_stream strm;
- bool compress;
-
- size_t block_size;
- gzip_options_t opt;
-} gzip_compressor_t;
-
-static void gzip_destroy(sqfs_object_t *base)
-{
- gzip_compressor_t *gzip = (gzip_compressor_t *)base;
-
- if (gzip->compress) {
- deflateEnd(&gzip->strm);
- } else {
- inflateEnd(&gzip->strm);
- }
-
- free(gzip);
-}
-
-static void gzip_get_configuration(const sqfs_compressor_t *base,
- sqfs_compressor_config_t *cfg)
-{
- const gzip_compressor_t *gzip = (const gzip_compressor_t *)base;
-
- memset(cfg, 0, sizeof(*cfg));
- cfg->id = SQFS_COMP_GZIP;
- cfg->flags = gzip->opt.strategies;
- cfg->block_size = gzip->block_size;
- cfg->level = gzip->opt.level;
- cfg->opt.gzip.window_size = gzip->opt.window;
-
- if (!gzip->compress)
- cfg->flags |= SQFS_COMP_FLAG_UNCOMPRESS;
-}
-
-static int gzip_write_options(sqfs_compressor_t *base, sqfs_file_t *file)
-{
- gzip_compressor_t *gzip = (gzip_compressor_t *)base;
- gzip_options_t opt;
-
- if (gzip->opt.level == SQFS_GZIP_DEFAULT_LEVEL &&
- gzip->opt.window == SQFS_GZIP_DEFAULT_WINDOW &&
- gzip->opt.strategies == 0) {
- return 0;
- }
-
- opt.level = htole32(gzip->opt.level);
- opt.window = htole16(gzip->opt.window);
- opt.strategies = htole16(gzip->opt.strategies);
-
- return sqfs_generic_write_options(file, &opt, sizeof(opt));
-}
-
-static int gzip_read_options(sqfs_compressor_t *base, sqfs_file_t *file)
-{
- gzip_compressor_t *gzip = (gzip_compressor_t *)base;
- gzip_options_t opt;
- int ret;
-
- ret = sqfs_generic_read_options(file, &opt, sizeof(opt));
- if (ret)
- return ret;
-
- gzip->opt.level = le32toh(opt.level);
- gzip->opt.window = le16toh(opt.window);
- gzip->opt.strategies = le16toh(opt.strategies);
-
- if (gzip->opt.level < 1 || gzip->opt.level > 9)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (gzip->opt.window < 8 || gzip->opt.window > 15)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (gzip->opt.strategies & ~SQFS_COMP_FLAG_GZIP_ALL)
- return SQFS_ERROR_UNSUPPORTED;
-
- return 0;
-}
-
-static int flag_to_zlib_strategy(int flag)
-{
- switch (flag) {
- case SQFS_COMP_FLAG_GZIP_DEFAULT:
- return Z_DEFAULT_STRATEGY;
- case SQFS_COMP_FLAG_GZIP_FILTERED:
- return Z_FILTERED;
- case SQFS_COMP_FLAG_GZIP_HUFFMAN:
- return Z_HUFFMAN_ONLY;
- case SQFS_COMP_FLAG_GZIP_RLE:
- return Z_RLE;
- case SQFS_COMP_FLAG_GZIP_FIXED:
- return Z_FIXED;
- default:
- break;
- }
-
- return 0;
-}
-
-static int find_strategy(gzip_compressor_t *gzip, const sqfs_u8 *in,
- sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize)
-{
- int ret, strategy, selected = Z_DEFAULT_STRATEGY;
- size_t i, length, minlength = 0;
-
- for (i = 0x01; i & SQFS_COMP_FLAG_GZIP_ALL; i <<= 1) {
- if ((gzip->opt.strategies & i) == 0)
- continue;
-
- ret = deflateReset(&gzip->strm);
- if (ret != Z_OK)
- return SQFS_ERROR_COMPRESSOR;
-
- strategy = flag_to_zlib_strategy(i);
-
- gzip->strm.next_in = (z_const Bytef *)in;
- gzip->strm.avail_in = size;
- gzip->strm.next_out = out;
- gzip->strm.avail_out = outsize;
-
- ret = deflateParams(&gzip->strm, gzip->opt.level, strategy);
- if (ret != Z_OK)
- return SQFS_ERROR_COMPRESSOR;
-
- ret = deflate(&gzip->strm, Z_FINISH);
-
- if (ret == Z_STREAM_END) {
- length = gzip->strm.total_out;
-
- if (minlength == 0 || length < minlength) {
- minlength = length;
- selected = strategy;
- }
- } else if (ret != Z_OK && ret != Z_BUF_ERROR) {
- return SQFS_ERROR_COMPRESSOR;
- }
- }
-
- return selected;
-}
-
-static sqfs_s32 gzip_do_block(sqfs_compressor_t *base, const sqfs_u8 *in,
- sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize)
-{
- gzip_compressor_t *gzip = (gzip_compressor_t *)base;
- int ret, strategy = 0;
- size_t written;
-
- if (size >= 0x7FFFFFFF)
- return SQFS_ERROR_ARG_INVALID;
-
- if (gzip->compress && gzip->opt.strategies != 0) {
- strategy = find_strategy(gzip, in, size, out, outsize);
- if (strategy < 0)
- return strategy;
- }
-
- if (gzip->compress) {
- ret = deflateReset(&gzip->strm);
- } else {
- ret = inflateReset(&gzip->strm);
- }
-
- if (ret != Z_OK)
- return SQFS_ERROR_COMPRESSOR;
-
- gzip->strm.next_in = (const void *)in;
- gzip->strm.avail_in = size;
- gzip->strm.next_out = out;
- gzip->strm.avail_out = outsize;
-
- if (gzip->compress && gzip->opt.strategies != 0) {
- ret = deflateParams(&gzip->strm, gzip->opt.level, strategy);
- if (ret != Z_OK)
- return SQFS_ERROR_COMPRESSOR;
- }
-
- if (gzip->compress) {
- ret = deflate(&gzip->strm, Z_FINISH);
- } else {
- ret = inflate(&gzip->strm, Z_FINISH);
- }
-
- if (ret == Z_STREAM_END) {
- written = gzip->strm.total_out;
-
- if (gzip->compress && written >= size)
- return 0;
-
- return written;
- }
-
- if (ret != Z_OK && ret != Z_BUF_ERROR)
- return SQFS_ERROR_COMPRESSOR;
-
- return 0;
-}
-
-static sqfs_object_t *gzip_create_copy(const sqfs_object_t *cmp)
-{
- gzip_compressor_t *gzip = malloc(sizeof(*gzip));
- int ret;
-
- if (gzip == NULL)
- return NULL;
-
- memcpy(gzip, cmp, sizeof(*gzip));
- memset(&gzip->strm, 0, sizeof(gzip->strm));
-
- if (gzip->compress) {
- ret = deflateInit2(&gzip->strm, gzip->opt.level, Z_DEFLATED,
- gzip->opt.window, 8, Z_DEFAULT_STRATEGY);
- } else {
- ret = inflateInit(&gzip->strm);
- }
-
- if (ret != Z_OK) {
- free(gzip);
- return NULL;
- }
-
- return (sqfs_object_t *)gzip;
-}
-
-int gzip_compressor_create(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out)
-{
- gzip_compressor_t *gzip;
- sqfs_compressor_t *base;
- int ret;
-
- if (cfg->flags & ~(SQFS_COMP_FLAG_GZIP_ALL |
- SQFS_COMP_FLAG_GENERIC_ALL)) {
- return SQFS_ERROR_UNSUPPORTED;
- }
-
- if (cfg->level < SQFS_GZIP_MIN_LEVEL ||
- cfg->level > SQFS_GZIP_MAX_LEVEL) {
- return SQFS_ERROR_UNSUPPORTED;
- }
-
- if (cfg->opt.gzip.window_size < SQFS_GZIP_MIN_WINDOW ||
- cfg->opt.gzip.window_size > SQFS_GZIP_MAX_WINDOW) {
- return SQFS_ERROR_UNSUPPORTED;
- }
-
- gzip = calloc(1, sizeof(*gzip));
- base = (sqfs_compressor_t *)gzip;
-
- if (gzip == NULL)
- return SQFS_ERROR_ALLOC;
-
- sqfs_object_init(gzip, gzip_destroy, gzip_create_copy);
-
- gzip->opt.level = cfg->level;
- gzip->opt.window = cfg->opt.gzip.window_size;
- gzip->opt.strategies = cfg->flags & SQFS_COMP_FLAG_GZIP_ALL;
- gzip->compress = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) == 0;
- gzip->block_size = cfg->block_size;
- base->get_configuration = gzip_get_configuration;
- base->do_block = gzip_do_block;
- base->write_options = gzip_write_options;
- base->read_options = gzip_read_options;
-
- if (gzip->compress) {
- ret = deflateInit2(&gzip->strm, cfg->level,
- Z_DEFLATED, cfg->opt.gzip.window_size, 8,
- Z_DEFAULT_STRATEGY);
- } else {
- ret = inflateInit(&gzip->strm);
- }
-
- if (ret != Z_OK) {
- free(gzip);
- return SQFS_ERROR_COMPRESSOR;
- }
-
- *out = base;
- return 0;
-}
diff --git a/lib/sqfs/comp/internal.h b/lib/sqfs/comp/internal.h
deleted file mode 100644
index e4c3dd8..0000000
--- a/lib/sqfs/comp/internal.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * internal.h
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#ifndef INTERNAL_H
-#define INTERNAL_H
-
-#include "config.h"
-
-#include "sqfs/predef.h"
-#include "sqfs/compressor.h"
-#include "sqfs/error.h"
-#include "sqfs/block.h"
-#include "sqfs/io.h"
-#include "util/util.h"
-
-SQFS_INTERNAL
-int sqfs_generic_write_options(sqfs_file_t *file, const void *data,
- size_t size);
-
-SQFS_INTERNAL
-int sqfs_generic_read_options(sqfs_file_t *file, void *data, size_t size);
-
-SQFS_INTERNAL
-int xz_compressor_create(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out);
-
-SQFS_INTERNAL
-int gzip_compressor_create(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out);
-
-SQFS_INTERNAL
-int lz4_compressor_create(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out);
-
-SQFS_INTERNAL
-int zstd_compressor_create(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out);
-
-SQFS_INTERNAL
-int lzma_compressor_create(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out);
-
-#endif /* INTERNAL_H */
diff --git a/lib/sqfs/comp/lz4.c b/lib/sqfs/comp/lz4.c
deleted file mode 100644
index 77f4a6e..0000000
--- a/lib/sqfs/comp/lz4.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * lz4.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#define SQFS_BUILDING_DLL
-#include "config.h"
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <lz4.h>
-#include <lz4hc.h>
-
-#include "internal.h"
-
-typedef struct {
- sqfs_compressor_t base;
- size_t block_size;
- bool high_compression;
-} lz4_compressor_t;
-
-typedef struct {
- sqfs_u32 version;
- sqfs_u32 flags;
-} lz4_options;
-
-#define LZ4LEGACY 1
-
-/* old verions of liblz4 don't have this */
-#ifndef LZ4HC_CLEVEL_MAX
-#define LZ4HC_CLEVEL_MAX 12
-#endif
-
-static int lz4_write_options(sqfs_compressor_t *base, sqfs_file_t *file)
-{
- lz4_compressor_t *lz4 = (lz4_compressor_t *)base;
- lz4_options opt = {
- .version = htole32(LZ4LEGACY),
- .flags = htole32(lz4->high_compression ?
- SQFS_COMP_FLAG_LZ4_HC : 0),
- };
-
- return sqfs_generic_write_options(file, &opt, sizeof(opt));
-}
-
-static int lz4_read_options(sqfs_compressor_t *base, sqfs_file_t *file)
-{
- lz4_options opt;
- int ret;
- (void)base;
-
- ret = sqfs_generic_read_options(file, &opt, sizeof(opt));
- if (ret)
- return ret;
-
- opt.version = le32toh(opt.version);
- opt.flags = le32toh(opt.flags);
-
- if (opt.version != LZ4LEGACY)
- return SQFS_ERROR_UNSUPPORTED;
-
- return 0;
-}
-
-static sqfs_s32 lz4_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in,
- sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize)
-{
- lz4_compressor_t *lz4 = (lz4_compressor_t *)base;
- int ret;
-
- if (size >= 0x7FFFFFFF)
- return SQFS_ERROR_ARG_INVALID;
-
- if (lz4->high_compression) {
- ret = LZ4_compress_HC((const void *)in, (void *)out,
- size, outsize, LZ4HC_CLEVEL_MAX);
- } else {
- ret = LZ4_compress_default((const void *)in, (void *)out,
- size, outsize);
- }
-
- if (ret < 0)
- return SQFS_ERROR_COMPRESSOR;
-
- return ret;
-}
-
-static sqfs_s32 lz4_uncomp_block(sqfs_compressor_t *base, const sqfs_u8 *in,
- sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize)
-{
- int ret;
- (void)base;
-
- if (outsize >= 0x7FFFFFFF)
- return SQFS_ERROR_ARG_INVALID;
-
- ret = LZ4_decompress_safe((const void *)in, (void *)out, size, outsize);
-
- if (ret < 0)
- return SQFS_ERROR_COMPRESSOR;
-
- return ret;
-}
-
-static void lz4_get_configuration(const sqfs_compressor_t *base,
- sqfs_compressor_config_t *cfg)
-{
- const lz4_compressor_t *lz4 = (const lz4_compressor_t *)base;
-
- memset(cfg, 0, sizeof(*cfg));
- cfg->id = SQFS_COMP_LZ4;
- cfg->block_size = lz4->block_size;
-
- if (lz4->high_compression)
- cfg->flags |= SQFS_COMP_FLAG_LZ4_HC;
-
- if (base->do_block == lz4_uncomp_block)
- cfg->flags |= SQFS_COMP_FLAG_UNCOMPRESS;
-}
-
-static sqfs_object_t *lz4_create_copy(const sqfs_object_t *cmp)
-{
- lz4_compressor_t *lz4 = malloc(sizeof(*lz4));
-
- if (lz4 == NULL)
- return NULL;
-
- memcpy(lz4, cmp, sizeof(*lz4));
- return (sqfs_object_t *)lz4;
-}
-
-static void lz4_destroy(sqfs_object_t *base)
-{
- free(base);
-}
-
-int lz4_compressor_create(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out)
-{
- sqfs_compressor_t *base;
- lz4_compressor_t *lz4;
-
- if (cfg->flags & ~(SQFS_COMP_FLAG_LZ4_ALL |
- SQFS_COMP_FLAG_GENERIC_ALL)) {
- return SQFS_ERROR_UNSUPPORTED;
- }
-
- if (cfg->level != 0)
- return SQFS_ERROR_UNSUPPORTED;
-
- lz4 = calloc(1, sizeof(*lz4));
- base = (sqfs_compressor_t *)lz4;
- if (lz4 == NULL)
- return SQFS_ERROR_ALLOC;
-
- sqfs_object_init(lz4, lz4_destroy, lz4_create_copy);
-
- lz4->high_compression = (cfg->flags & SQFS_COMP_FLAG_LZ4_HC) != 0;
- lz4->block_size = cfg->block_size;
-
- base->get_configuration = lz4_get_configuration;
- base->do_block = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) ?
- lz4_uncomp_block : lz4_comp_block;
- base->write_options = lz4_write_options;
- base->read_options = lz4_read_options;
-
- *out = base;
- return 0;
-}
diff --git a/lib/sqfs/comp/lzma.c b/lib/sqfs/comp/lzma.c
deleted file mode 100644
index 5456603..0000000
--- a/lib/sqfs/comp/lzma.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * lzma.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#define SQFS_BUILDING_DLL
-#include "config.h"
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <lzma.h>
-
-#include "internal.h"
-
-#define LZMA_SIZE_OFFSET (5)
-#define LZMA_SIZE_BYTES (8)
-#define LZMA_HEADER_SIZE (13)
-
-#define MEMLIMIT (64 * 1024 * 1024)
-
-typedef struct {
- sqfs_compressor_t base;
- size_t block_size;
- size_t dict_size;
-
- sqfs_u32 flags;
- sqfs_u8 level;
- sqfs_u8 lc;
- sqfs_u8 lp;
- sqfs_u8 pb;
-} lzma_compressor_t;
-
-static int lzma_write_options(sqfs_compressor_t *base, sqfs_file_t *file)
-{
- (void)base; (void)file;
- return 0;
-}
-
-static int lzma_read_options(sqfs_compressor_t *base, sqfs_file_t *file)
-{
- (void)base;
- (void)file;
- return SQFS_ERROR_UNSUPPORTED;
-}
-
-static sqfs_s32 try_compress(lzma_compressor_t *lzma, sqfs_u32 preset,
- const sqfs_u8 *in, size_t size,
- sqfs_u8 *out, size_t outsize)
-{
- lzma_stream strm = LZMA_STREAM_INIT;
- lzma_options_lzma opt;
- int ret;
-
- lzma_lzma_preset(&opt, preset);
- opt.dict_size = lzma->block_size;
- opt.lc = lzma->lc;
- opt.lp = lzma->lp;
- opt.pb = lzma->pb;
-
- if (lzma_alone_encoder(&strm, &opt) != LZMA_OK) {
- lzma_end(&strm);
- return SQFS_ERROR_COMPRESSOR;
- }
-
- strm.next_out = out;
- strm.avail_out = outsize;
- strm.next_in = in;
- strm.avail_in = size;
-
- ret = lzma_code(&strm, LZMA_FINISH);
- lzma_end(&strm);
-
- if (ret != LZMA_STREAM_END)
- return ret == LZMA_OK ? 0 : SQFS_ERROR_COMPRESSOR;
-
- if (strm.total_out > size)
- return 0;
-
- out[LZMA_SIZE_OFFSET ] = size & 0xFF;
- out[LZMA_SIZE_OFFSET + 1] = (size >> 8) & 0xFF;
- out[LZMA_SIZE_OFFSET + 2] = (size >> 16) & 0xFF;
- out[LZMA_SIZE_OFFSET + 3] = (size >> 24) & 0xFF;
- out[LZMA_SIZE_OFFSET + 4] = 0;
- out[LZMA_SIZE_OFFSET + 5] = 0;
- out[LZMA_SIZE_OFFSET + 6] = 0;
- out[LZMA_SIZE_OFFSET + 7] = 0;
- return strm.total_out;
-}
-
-static sqfs_s32 lzma_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in,
- sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize)
-{
- lzma_compressor_t *lzma = (lzma_compressor_t *)base;
- sqfs_s32 ret, smallest;
- sqfs_u32 preset;
-
- if (outsize < LZMA_HEADER_SIZE || size >= 0x7FFFFFFF)
- return SQFS_ERROR_ARG_INVALID;
-
- preset = lzma->level;
- ret = try_compress(lzma, preset, in, size, out, outsize);
- if (ret < 0 || !(lzma->flags & SQFS_COMP_FLAG_LZMA_EXTREME))
- return ret;
-
- preset |= LZMA_PRESET_EXTREME;
- smallest = ret;
-
- ret = try_compress(lzma, preset, in, size, out, outsize);
- if (ret < 0 || (ret > 0 && (smallest == 0 || ret < smallest)))
- return ret;
-
- preset &= ~LZMA_PRESET_EXTREME;
- return smallest == 0 ? 0 :
- try_compress(lzma, preset, in, size, out, outsize);
-}
-
-static sqfs_s32 lzma_uncomp_block(sqfs_compressor_t *base, const sqfs_u8 *in,
- sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize)
-{
- sqfs_u8 lzma_header[LZMA_HEADER_SIZE];
- lzma_stream strm = LZMA_STREAM_INIT;
- size_t hdrsize;
- int ret;
- (void)base;
-
- if (size >= 0x7FFFFFFF)
- return SQFS_ERROR_ARG_INVALID;
-
- if (size < sizeof(lzma_header))
- return SQFS_ERROR_CORRUPTED;
-
- hdrsize = (size_t)in[LZMA_SIZE_OFFSET] |
- ((size_t)in[LZMA_SIZE_OFFSET + 1] << 8) |
- ((size_t)in[LZMA_SIZE_OFFSET + 2] << 16) |
- ((size_t)in[LZMA_SIZE_OFFSET + 3] << 24);
-
- if (hdrsize > outsize)
- return 0;
-
- if (lzma_alone_decoder(&strm, MEMLIMIT) != LZMA_OK) {
- lzma_end(&strm);
- return SQFS_ERROR_COMPRESSOR;
- }
-
- memcpy(lzma_header, in, sizeof(lzma_header));
- memset(lzma_header + LZMA_SIZE_OFFSET, 0xFF, LZMA_SIZE_BYTES);
-
- strm.next_out = out;
- strm.avail_out = outsize;
- strm.next_in = lzma_header;
- strm.avail_in = sizeof(lzma_header);
-
- ret = lzma_code(&strm, LZMA_RUN);
-
- if (ret != LZMA_OK || strm.avail_in != 0) {
- lzma_end(&strm);
- return SQFS_ERROR_COMPRESSOR;
- }
-
- strm.next_in = in + sizeof(lzma_header);
- strm.avail_in = size - sizeof(lzma_header);
-
- ret = lzma_code(&strm, LZMA_FINISH);
- lzma_end(&strm);
-
- if (ret != LZMA_STREAM_END && ret != LZMA_OK)
- return SQFS_ERROR_COMPRESSOR;
-
- if (ret == LZMA_OK) {
- if (strm.total_out < hdrsize || strm.avail_in != 0)
- return 0;
- }
-
- return hdrsize;
-}
-
-static void lzma_get_configuration(const sqfs_compressor_t *base,
- sqfs_compressor_config_t *cfg)
-{
- const lzma_compressor_t *lzma = (const lzma_compressor_t *)base;
-
- memset(cfg, 0, sizeof(*cfg));
- cfg->id = SQFS_COMP_LZMA;
- cfg->block_size = lzma->block_size;
- cfg->flags = lzma->flags;
- cfg->level = lzma->level;
- cfg->opt.lzma.dict_size = lzma->dict_size;
- cfg->opt.lzma.lc = lzma->lc;
- cfg->opt.lzma.lp = lzma->lp;
- cfg->opt.lzma.pb = lzma->pb;
-}
-
-static sqfs_object_t *lzma_create_copy(const sqfs_object_t *cmp)
-{
- lzma_compressor_t *copy = malloc(sizeof(*copy));
-
- if (copy != NULL)
- memcpy(copy, cmp, sizeof(*copy));
-
- return (sqfs_object_t *)copy;
-}
-
-static void lzma_destroy(sqfs_object_t *base)
-{
- free(base);
-}
-
-int lzma_compressor_create(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out)
-{
- sqfs_compressor_t *base;
- lzma_compressor_t *lzma;
- sqfs_u32 mask;
-
- mask = SQFS_COMP_FLAG_GENERIC_ALL | SQFS_COMP_FLAG_LZMA_ALL;
-
- if (cfg->flags & ~mask)
- return SQFS_ERROR_UNSUPPORTED;
-
- /* XXX: values are unsigned and minimum is 0 */
- if (cfg->level > SQFS_LZMA_MAX_LEVEL)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.lzma.lc > SQFS_LZMA_MAX_LC)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.lzma.lp > SQFS_LZMA_MAX_LP)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.lzma.pb > SQFS_LZMA_MAX_PB)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.lzma.lc + cfg->opt.lzma.lp > 4)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.lzma.dict_size == 0)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.lzma.dict_size < SQFS_LZMA_MIN_DICT_SIZE)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.lzma.dict_size > SQFS_LZMA_MAX_DICT_SIZE)
- return SQFS_ERROR_UNSUPPORTED;
-
- mask = cfg->opt.lzma.dict_size;
- mask &= mask - 1;
-
- if (mask != 0) {
- if ((mask & (mask - 1)) != 0)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.lzma.dict_size != (mask | mask >> 1))
- return SQFS_ERROR_UNSUPPORTED;
- }
-
- lzma = calloc(1, sizeof(*lzma));
- base = (sqfs_compressor_t *)lzma;
- if (lzma == NULL)
- return SQFS_ERROR_ALLOC;
-
- sqfs_object_init(lzma, lzma_destroy, lzma_create_copy);
-
- lzma->block_size = cfg->block_size;
- lzma->flags = cfg->flags;
- lzma->level = cfg->level;
- lzma->dict_size = cfg->opt.lzma.dict_size;
- lzma->lc = cfg->opt.lzma.lc;
- lzma->lp = cfg->opt.lzma.lp;
- lzma->pb = cfg->opt.lzma.pb;
-
- base->get_configuration = lzma_get_configuration;
- base->do_block = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) ?
- lzma_uncomp_block : lzma_comp_block;
- base->write_options = lzma_write_options;
- base->read_options = lzma_read_options;
-
- *out = base;
- return 0;
-}
diff --git a/lib/sqfs/comp/xz.c b/lib/sqfs/comp/xz.c
deleted file mode 100644
index 13545ed..0000000
--- a/lib/sqfs/comp/xz.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * xz.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#define SQFS_BUILDING_DLL
-#include "config.h"
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <lzma.h>
-
-#include "internal.h"
-
-typedef struct {
- sqfs_compressor_t base;
- size_t block_size;
- size_t dict_size;
-
- sqfs_u8 level;
- sqfs_u8 lc;
- sqfs_u8 lp;
- sqfs_u8 pb;
-
- int flags;
-} xz_compressor_t;
-
-typedef struct {
- sqfs_u32 dict_size;
- sqfs_u32 flags;
-} xz_options_t;
-
-static bool is_dict_size_valid(size_t size)
-{
- size_t x = size & (size - 1);
-
- if (x == 0)
- return true;
-
- return size == (x | (x >> 1));
-}
-
-static int xz_write_options(sqfs_compressor_t *base, sqfs_file_t *file)
-{
- xz_compressor_t *xz = (xz_compressor_t *)base;
- xz_options_t opt;
- sqfs_u32 flags;
-
- if (xz->flags == 0 && xz->dict_size == xz->block_size)
- return 0;
-
- flags = xz->flags & SQFS_COMP_FLAG_XZ_ALL;
- flags &= ~SQFS_COMP_FLAG_XZ_EXTREME;
-
- opt.dict_size = htole32(xz->dict_size);
- opt.flags = htole32(flags);
-
- return sqfs_generic_write_options(file, &opt, sizeof(opt));
-}
-
-static int xz_read_options(sqfs_compressor_t *base, sqfs_file_t *file)
-{
- xz_compressor_t *xz = (xz_compressor_t *)base;
- xz_options_t opt;
- int ret;
-
- ret = sqfs_generic_read_options(file, &opt, sizeof(opt));
- if (ret)
- return ret;
-
- opt.dict_size = le32toh(opt.dict_size);
- opt.flags = le32toh(opt.flags);
-
- if (!is_dict_size_valid(opt.dict_size))
- return SQFS_ERROR_CORRUPTED;
-
- if (opt.flags & ~SQFS_COMP_FLAG_XZ_ALL)
- return SQFS_ERROR_UNSUPPORTED;
-
- xz->flags = opt.flags;
- xz->dict_size = opt.dict_size;
- return 0;
-}
-
-static sqfs_s32 compress(xz_compressor_t *xz, lzma_vli filter,
- const sqfs_u8 *in, sqfs_u32 size,
- sqfs_u8 *out, sqfs_u32 outsize,
- sqfs_u32 presets)
-{
- lzma_filter filters[5];
- lzma_options_lzma opt;
- size_t written = 0;
- lzma_ret ret;
- int i = 0;
-
- if (lzma_lzma_preset(&opt, presets))
- return SQFS_ERROR_COMPRESSOR;
-
- opt.lc = xz->lc;
- opt.lp = xz->lp;
- opt.pb = xz->pb;
- opt.dict_size = xz->dict_size;
-
- if (filter != LZMA_VLI_UNKNOWN) {
- filters[i].id = filter;
- filters[i].options = NULL;
- ++i;
- }
-
- filters[i].id = LZMA_FILTER_LZMA2;
- filters[i].options = &opt;
- ++i;
-
- filters[i].id = LZMA_VLI_UNKNOWN;
- filters[i].options = NULL;
- ++i;
-
- ret = lzma_stream_buffer_encode(filters, LZMA_CHECK_CRC32, NULL,
- in, size, out, &written, outsize);
-
- if (ret == LZMA_OK)
- return (written >= size) ? 0 : written;
-
- if (ret != LZMA_BUF_ERROR)
- return SQFS_ERROR_COMPRESSOR;
-
- return 0;
-}
-
-static lzma_vli flag_to_vli(int flag)
-{
- switch (flag) {
- case SQFS_COMP_FLAG_XZ_X86:
- return LZMA_FILTER_X86;
- case SQFS_COMP_FLAG_XZ_POWERPC:
- return LZMA_FILTER_POWERPC;
- case SQFS_COMP_FLAG_XZ_IA64:
- return LZMA_FILTER_IA64;
- case SQFS_COMP_FLAG_XZ_ARM:
- return LZMA_FILTER_ARM;
- case SQFS_COMP_FLAG_XZ_ARMTHUMB:
- return LZMA_FILTER_ARMTHUMB;
- case SQFS_COMP_FLAG_XZ_SPARC:
- return LZMA_FILTER_SPARC;
- default:
- break;
- }
-
- return LZMA_VLI_UNKNOWN;
-}
-
-static sqfs_s32 xz_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in,
- sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize)
-{
- xz_compressor_t *xz = (xz_compressor_t *)base;
- lzma_vli filter, selected = LZMA_VLI_UNKNOWN;
- sqfs_s32 ret, smallest;
- bool extreme;
- size_t i;
-
- if (size >= 0x7FFFFFFF)
- return SQFS_ERROR_ARG_INVALID;
-
- ret = compress(xz, LZMA_VLI_UNKNOWN, in, size, out,
- outsize, xz->level);
- if (ret < 0 || xz->flags == 0)
- return ret;
-
- smallest = ret;
- extreme = false;
-
- if (xz->flags & SQFS_COMP_FLAG_XZ_EXTREME) {
- ret = compress(xz, LZMA_VLI_UNKNOWN, in, size, out, outsize,
- xz->level | LZMA_PRESET_EXTREME);
-
- if (ret > 0 && (smallest == 0 || ret < smallest)) {
- smallest = ret;
- extreme = true;
- }
- }
-
- for (i = 1; i & SQFS_COMP_FLAG_XZ_ALL; i <<= 1) {
- if ((i & SQFS_COMP_FLAG_XZ_EXTREME) || (xz->flags & i) == 0)
- continue;
-
- filter = flag_to_vli(i);
-
- ret = compress(xz, filter, in, size, out, outsize, xz->level);
- if (ret > 0 && (smallest == 0 || ret < smallest)) {
- smallest = ret;
- selected = filter;
- extreme = false;
- }
-
- if (xz->flags & SQFS_COMP_FLAG_XZ_EXTREME) {
- ret = compress(xz, filter, in, size, out, outsize,
- xz->level | LZMA_PRESET_EXTREME);
-
- if (ret > 0 && (smallest == 0 || ret < smallest)) {
- smallest = ret;
- selected = filter;
- extreme = true;
- }
- }
- }
-
- if (smallest == 0)
- return 0;
-
- return compress(xz, selected, in, size, out, outsize,
- xz->level | (extreme ? LZMA_PRESET_EXTREME : 0));
-}
-
-static sqfs_s32 xz_uncomp_block(sqfs_compressor_t *base, const sqfs_u8 *in,
- sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize)
-{
- sqfs_u64 memlimit = 65 * 1024 * 1024;
- size_t dest_pos = 0;
- size_t src_pos = 0;
- lzma_ret ret;
- (void)base;
-
- if (outsize >= 0x7FFFFFFF)
- return SQFS_ERROR_ARG_INVALID;
-
- ret = lzma_stream_buffer_decode(&memlimit, 0, NULL,
- in, &src_pos, size,
- out, &dest_pos, outsize);
-
- if (ret == LZMA_OK && size == src_pos)
- return dest_pos;
-
- return SQFS_ERROR_COMPRESSOR;
-}
-
-static void xz_get_configuration(const sqfs_compressor_t *base,
- sqfs_compressor_config_t *cfg)
-{
- const xz_compressor_t *xz = (const xz_compressor_t *)base;
-
- memset(cfg, 0, sizeof(*cfg));
- cfg->id = SQFS_COMP_XZ;
- cfg->flags = xz->flags;
- cfg->block_size = xz->block_size;
- cfg->level = xz->level;
- cfg->opt.xz.dict_size = xz->dict_size;
- cfg->opt.xz.lc = xz->lc;
- cfg->opt.xz.lp = xz->lp;
- cfg->opt.xz.pb = xz->pb;
-
- if (base->do_block == xz_uncomp_block)
- cfg->flags |= SQFS_COMP_FLAG_UNCOMPRESS;
-}
-
-static sqfs_object_t *xz_create_copy(const sqfs_object_t *cmp)
-{
- xz_compressor_t *xz = malloc(sizeof(*xz));
-
- if (xz == NULL)
- return NULL;
-
- memcpy(xz, cmp, sizeof(*xz));
- return (sqfs_object_t *)xz;
-}
-
-static void xz_destroy(sqfs_object_t *base)
-{
- free(base);
-}
-
-int xz_compressor_create(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out)
-{
- sqfs_compressor_t *base;
- xz_compressor_t *xz;
-
- if (cfg->flags & ~(SQFS_COMP_FLAG_GENERIC_ALL |
- SQFS_COMP_FLAG_XZ_ALL)) {
- return SQFS_ERROR_UNSUPPORTED;
- }
-
- if (!is_dict_size_valid(cfg->opt.xz.dict_size))
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.xz.lc + cfg->opt.xz.lp > 4)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.xz.pb > SQFS_XZ_MAX_PB)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->level > SQFS_XZ_MAX_LEVEL)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.xz.dict_size < SQFS_XZ_MIN_DICT_SIZE)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->opt.xz.dict_size > SQFS_XZ_MAX_DICT_SIZE)
- return SQFS_ERROR_UNSUPPORTED;
-
- xz = calloc(1, sizeof(*xz));
- base = (sqfs_compressor_t *)xz;
- if (xz == NULL)
- return SQFS_ERROR_ALLOC;
-
- sqfs_object_init(xz, xz_destroy, xz_create_copy);
-
- xz->flags = cfg->flags;
- xz->dict_size = cfg->opt.xz.dict_size;
- xz->block_size = cfg->block_size;
- xz->lc = cfg->opt.xz.lc;
- xz->lp = cfg->opt.xz.lp;
- xz->pb = cfg->opt.xz.pb;
- xz->level = cfg->level;
- base->get_configuration = xz_get_configuration;
- base->do_block = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) ?
- xz_uncomp_block : xz_comp_block;
- base->write_options = xz_write_options;
- base->read_options = xz_read_options;
-
- *out = base;
- return 0;
-}
diff --git a/lib/sqfs/comp/zstd.c b/lib/sqfs/comp/zstd.c
deleted file mode 100644
index a6d7975..0000000
--- a/lib/sqfs/comp/zstd.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* SPDX-License-Identifier: LGPL-3.0-or-later */
-/*
- * zstd.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#define SQFS_BUILDING_DLL
-#include "config.h"
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <zstd.h>
-#include <zstd_errors.h>
-
-#include "internal.h"
-
-typedef struct {
- sqfs_compressor_t base;
- size_t block_size;
- ZSTD_CCtx *zctx;
- int level;
-} zstd_compressor_t;
-
-typedef struct {
- sqfs_u32 level;
-} zstd_options_t;
-
-static int zstd_write_options(sqfs_compressor_t *base, sqfs_file_t *file)
-{
- zstd_compressor_t *zstd = (zstd_compressor_t *)base;
- zstd_options_t opt;
-
- if (zstd->level == SQFS_ZSTD_DEFAULT_LEVEL)
- return 0;
-
- opt.level = htole32(zstd->level);
- return sqfs_generic_write_options(file, &opt, sizeof(opt));
-}
-
-static int zstd_read_options(sqfs_compressor_t *base, sqfs_file_t *file)
-{
- zstd_options_t opt;
- int ret;
- (void)base;
-
- ret = sqfs_generic_read_options(file, &opt, sizeof(opt));
- if (ret)
- return ret;
-
- opt.level = le32toh(opt.level);
- return 0;
-}
-
-static sqfs_s32 zstd_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in,
- sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize)
-{
- zstd_compressor_t *zstd = (zstd_compressor_t *)base;
- size_t ret;
-
- if (size >= 0x7FFFFFFF)
- return SQFS_ERROR_ARG_INVALID;
-
- ret = ZSTD_compressCCtx(zstd->zctx, out, outsize, in, size,
- zstd->level);
-
- if (ZSTD_isError(ret)) {
- if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall)
- return 0;
-
- return SQFS_ERROR_COMPRESSOR;
- }
-
- return ret < size ? ret : 0;
-}
-
-static sqfs_s32 zstd_uncomp_block(sqfs_compressor_t *base, const sqfs_u8 *in,
- sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize)
-{
- size_t ret;
- (void)base;
-
- if (outsize >= 0x7FFFFFFF)
- return SQFS_ERROR_ARG_INVALID;
-
- ret = ZSTD_decompress(out, outsize, in, size);
-
- if (ZSTD_isError(ret))
- return SQFS_ERROR_COMPRESSOR;
-
- return ret;
-}
-
-static void zstd_get_configuration(const sqfs_compressor_t *base,
- sqfs_compressor_config_t *cfg)
-{
- const zstd_compressor_t *zstd = (const zstd_compressor_t *)base;
-
- memset(cfg, 0, sizeof(*cfg));
- cfg->id = SQFS_COMP_ZSTD;
-
- cfg->block_size = zstd->block_size;
- cfg->level = zstd->level;
-
- if (base->do_block == zstd_uncomp_block)
- cfg->flags |= SQFS_COMP_FLAG_UNCOMPRESS;
-}
-
-static sqfs_object_t *zstd_create_copy(const sqfs_object_t *cmp)
-{
- zstd_compressor_t *zstd = malloc(sizeof(*zstd));
-
- if (zstd == NULL)
- return NULL;
-
- memcpy(zstd, cmp, sizeof(*zstd));
-
- zstd->zctx = ZSTD_createCCtx();
-
- if (zstd->zctx == NULL) {
- free(zstd);
- return NULL;
- }
-
- return (sqfs_object_t *)zstd;
-}
-
-static void zstd_destroy(sqfs_object_t *base)
-{
- zstd_compressor_t *zstd = (zstd_compressor_t *)base;
-
- ZSTD_freeCCtx(zstd->zctx);
- free(zstd);
-}
-
-int zstd_compressor_create(const sqfs_compressor_config_t *cfg,
- sqfs_compressor_t **out)
-{
- zstd_compressor_t *zstd;
- sqfs_compressor_t *base;
-
- if (cfg->flags & ~SQFS_COMP_FLAG_GENERIC_ALL)
- return SQFS_ERROR_UNSUPPORTED;
-
- if (cfg->level < 1 || cfg->level > (unsigned int)ZSTD_maxCLevel())
- return SQFS_ERROR_UNSUPPORTED;
-
- zstd = calloc(1, sizeof(*zstd));
- base = (sqfs_compressor_t *)zstd;
- if (zstd == NULL)
- return SQFS_ERROR_ALLOC;
-
- sqfs_object_init(zstd, zstd_destroy, zstd_create_copy);
-
- zstd->block_size = cfg->block_size;
- zstd->level = cfg->level;
- zstd->zctx = ZSTD_createCCtx();
- if (zstd->zctx == NULL) {
- free(zstd);
- return SQFS_ERROR_COMPRESSOR;
- }
-
- base->get_configuration = zstd_get_configuration;
- base->do_block = cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS ?
- zstd_uncomp_block : zstd_comp_block;
- base->write_options = zstd_write_options;
- base->read_options = zstd_read_options;
-
- *out = base;
- return 0;
-}