From ad73b9440422c06805764da6058ebeb6d41a4f04 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 4 Jun 2020 04:29:04 +0200 Subject: lzma compressor: add support for the "extreme" flag Signed-off-by: David Oberhollenzer --- lib/sqfs/comp/compressor.c | 1 + lib/sqfs/comp/lzma.c | 49 +++++++++++++++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 11 deletions(-) (limited to 'lib/sqfs') diff --git a/lib/sqfs/comp/compressor.c b/lib/sqfs/comp/compressor.c index ea53339..2a0cebb 100644 --- a/lib/sqfs/comp/compressor.c +++ b/lib/sqfs/comp/compressor.c @@ -171,6 +171,7 @@ int sqfs_compressor_config_init(sqfs_compressor_config_t *cfg, cfg->opt.xz.pb = SQFS_XZ_DEFAULT_PB; break; case SQFS_COMP_LZMA: + flag_mask |= SQFS_COMP_FLAG_LZMA_ALL; break; case SQFS_COMP_LZ4: flag_mask |= SQFS_COMP_FLAG_LZ4_ALL; diff --git a/lib/sqfs/comp/lzma.c b/lib/sqfs/comp/lzma.c index 2a6cd1f..8db018d 100644 --- a/lib/sqfs/comp/lzma.c +++ b/lib/sqfs/comp/lzma.c @@ -24,6 +24,7 @@ typedef struct { sqfs_compressor_t base; size_t block_size; + sqfs_u32 flags; } lzma_compressor_t; static int lzma_write_options(sqfs_compressor_t *base, sqfs_file_t *file) @@ -39,18 +40,15 @@ static int lzma_read_options(sqfs_compressor_t *base, sqfs_file_t *file) return SQFS_ERROR_UNSUPPORTED; } -static sqfs_s32 lzma_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in, - sqfs_u32 size, sqfs_u8 *out, sqfs_u32 outsize) +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_compressor_t *lzma = (lzma_compressor_t *)base; lzma_stream strm = LZMA_STREAM_INIT; lzma_options_lzma opt; int ret; - if (outsize < LZMA_HEADER_SIZE || size >= 0x7FFFFFFF) - return SQFS_ERROR_ARG_INVALID; - - lzma_lzma_preset(&opt, LZMA_DEFAULT_LEVEL); + lzma_lzma_preset(&opt, preset); opt.dict_size = lzma->block_size; if (lzma_alone_encoder(&strm, &opt) != LZMA_OK) { @@ -83,6 +81,33 @@ static sqfs_s32 lzma_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in, 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_DEFAULT_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) { @@ -151,9 +176,7 @@ static void lzma_get_configuration(const sqfs_compressor_t *base, memset(cfg, 0, sizeof(*cfg)); cfg->id = SQFS_COMP_LZMA; cfg->block_size = lzma->block_size; - - if (base->do_block == lzma_uncomp_block) - cfg->flags |= SQFS_COMP_FLAG_UNCOMPRESS; + cfg->flags = lzma->flags; } static sqfs_object_t *lzma_create_copy(const sqfs_object_t *cmp) @@ -176,8 +199,11 @@ int lzma_compressor_create(const sqfs_compressor_config_t *cfg, { 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 & ~SQFS_COMP_FLAG_GENERIC_ALL) + if (cfg->flags & ~mask) return SQFS_ERROR_UNSUPPORTED; lzma = calloc(1, sizeof(*lzma)); @@ -186,6 +212,7 @@ int lzma_compressor_create(const sqfs_compressor_config_t *cfg, return SQFS_ERROR_ALLOC; lzma->block_size = cfg->block_size; + lzma->flags = cfg->flags; if (lzma->block_size < SQFS_META_BLOCK_SIZE) lzma->block_size = SQFS_META_BLOCK_SIZE; -- cgit v1.2.3