aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs/comp/xz.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs/comp/xz.c')
-rw-r--r--lib/sqfs/comp/xz.c324
1 files changed, 0 insertions, 324 deletions
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;
-}