diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/common/comp_opt.c | 47 | ||||
-rw-r--r-- | lib/sqfs/comp/compressor.c | 9 | ||||
-rw-r--r-- | lib/sqfs/comp/lzma.c | 60 |
3 files changed, 97 insertions, 19 deletions
diff --git a/lib/common/comp_opt.c b/lib/common/comp_opt.c index c279f1e..8864a0e 100644 --- a/lib/common/comp_opt.c +++ b/lib/common/comp_opt.c @@ -136,6 +136,8 @@ int compressor_cfg_init_options(sqfs_compressor_config_t *cfg, num_flags = sizeof(xz_flags) / sizeof(xz_flags[0]); break; case SQFS_COMP_LZMA: + min_level = SQFS_LZMA_MIN_LEVEL; + max_level = SQFS_LZMA_MAX_LEVEL; flags = lzma_flags; num_flags = sizeof(lzma_flags) / sizeof(lzma_flags[0]); break; @@ -200,6 +202,9 @@ int compressor_cfg_init_options(sqfs_compressor_config_t *cfg, case SQFS_COMP_XZ: cfg->opt.xz.level = level; break; + case SQFS_COMP_LZMA: + cfg->opt.lzma.level = level; + break; default: goto fail_opt; } @@ -215,13 +220,15 @@ int compressor_cfg_init_options(sqfs_compressor_config_t *cfg, goto fail_lzo_alg; break; case OPT_DICT: - if (cfg->id != SQFS_COMP_XZ) + if (cfg->id != SQFS_COMP_XZ && + cfg->id != SQFS_COMP_LZMA) { goto fail_opt; + } if (value == NULL) goto fail_value; - if (parse_size("Parsing XZ dictionary size", + if (parse_size("Parsing LZMA dictionary size", &dict_size, value, cfg->block_size)) { return -1; } @@ -229,8 +236,10 @@ int compressor_cfg_init_options(sqfs_compressor_config_t *cfg, cfg->opt.xz.dict_size = dict_size; break; case OPT_LC: - if (cfg->id != SQFS_COMP_XZ) + if (cfg->id != SQFS_COMP_XZ && + cfg->id != SQFS_COMP_LZMA) { goto fail_opt; + } if (value == NULL) goto fail_value; @@ -240,8 +249,10 @@ int compressor_cfg_init_options(sqfs_compressor_config_t *cfg, goto fail_lc; break; case OPT_LP: - if (cfg->id != SQFS_COMP_XZ) + if (cfg->id != SQFS_COMP_XZ && + cfg->id != SQFS_COMP_LZMA) { goto fail_opt; + } if (value == NULL) goto fail_value; @@ -251,8 +262,10 @@ int compressor_cfg_init_options(sqfs_compressor_config_t *cfg, goto fail_lp; break; case OPT_PB: - if (cfg->id != SQFS_COMP_XZ) + if (cfg->id != SQFS_COMP_XZ && + cfg->id != SQFS_COMP_LZMA) { goto fail_opt; + } if (value == NULL) goto fail_value; @@ -268,8 +281,10 @@ int compressor_cfg_init_options(sqfs_compressor_config_t *cfg, } } - if (cfg->id == SQFS_COMP_XZ && (cfg->opt.xz.lp + cfg->opt.xz.lc) > 4) - goto fail_sum_lp_lc; + if (cfg->id == SQFS_COMP_XZ || cfg->id == SQFS_COMP_LZMA) { + if ((cfg->opt.xz.lp + cfg->opt.xz.lc) > 4) + goto fail_sum_lp_lc; + } return 0; fail_sum_lp_lc: @@ -362,12 +377,12 @@ static void lzo_print_help(void) printf("\t%s\n", lzo_algs[i]); } -static void xz_print_help(void) +static void xz_lzma_print_help(void) { size_t i; printf( -"Available options for xz compressor:\n" +"Available options for LZMA and XZ (LZMA v2) compressors:\n" "\n" " dictsize=<value> Dictionary size. Either a value in bytes or a\n" " percentage of the block size. Defaults to 100%%.\n" @@ -375,7 +390,7 @@ static void xz_print_help(void) " can also be used for kibi and mebi bytes\n" " respecitively.\n" " level=<value> Compression level. Value from %d to %d.\n" -" Defaults to %d.\n" +" For XZ, defaults to %d, for LZMA defaults to %d.\n" " lc=<value> Number of literal context bits.\n" " How many of the highest bits of the previous\n" " uncompressed byte to take into account when\n" @@ -390,16 +405,21 @@ static void xz_print_help(void) " of the input data, i.e. pb=0 means single byte\n" " allignment, pb=1 means 16 bit, 2 means 32 bit.\n" " Default is %d.\n" +" extreme If this flag is set, try to crunch the data extra hard\n" +" without increasing the decompressors memory\n" +" requirements." "\n" "If values are set, the sum of lc + lp must not exceed 4.\n" "The maximum for pb is %d.\n" "\n" -"In additon to the options, one or more bcj filters can be specified.\n" +"In additon to the options, for the XZ compressor, one or more bcj filters\n" +"can be specified.\n" "If multiple filters are provided, the one yielding the best compression\n" "ratio will be used.\n" "\n" "The following filters are available:\n", - SQFS_XZ_MIN_LEVEL, SQFS_XZ_MAX_LEVEL, SQFS_XZ_DEFAULT_LEVEL, + SQFS_XZ_MIN_LEVEL, SQFS_XZ_MAX_LEVEL, + SQFS_XZ_DEFAULT_LEVEL, SQFS_LZMA_DEFAULT_LEVEL, SQFS_XZ_DEFAULT_LC, SQFS_XZ_DEFAULT_LP, SQFS_XZ_DEFAULT_PB, SQFS_XZ_MAX_PB); @@ -419,7 +439,8 @@ static void zstd_print_help(void) static const compressor_help_fun_t helpfuns[SQFS_COMP_MAX + 1] = { [SQFS_COMP_GZIP] = gzip_print_help, - [SQFS_COMP_XZ] = xz_print_help, + [SQFS_COMP_XZ] = xz_lzma_print_help, + [SQFS_COMP_LZMA] = xz_lzma_print_help, [SQFS_COMP_LZO] = lzo_print_help, [SQFS_COMP_LZ4] = lz4_print_help, [SQFS_COMP_ZSTD] = zstd_print_help, diff --git a/lib/sqfs/comp/compressor.c b/lib/sqfs/comp/compressor.c index 2a0cebb..521471d 100644 --- a/lib/sqfs/comp/compressor.c +++ b/lib/sqfs/comp/compressor.c @@ -98,6 +98,10 @@ int sqfs_compressor_create(const sqfs_compressor_config_t *cfg, 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)); @@ -172,6 +176,11 @@ int sqfs_compressor_config_init(sqfs_compressor_config_t *cfg, break; case SQFS_COMP_LZMA: flag_mask |= SQFS_COMP_FLAG_LZMA_ALL; + cfg->opt.lzma.dict_size = block_size; + cfg->opt.lzma.level = SQFS_LZMA_DEFAULT_LEVEL; + cfg->opt.lzma.lc = SQFS_LZMA_DEFAULT_LC; + cfg->opt.lzma.lp = SQFS_LZMA_DEFAULT_LP; + cfg->opt.lzma.pb = SQFS_LZMA_DEFAULT_PB; 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 8db018d..59871b1 100644 --- a/lib/sqfs/comp/lzma.c +++ b/lib/sqfs/comp/lzma.c @@ -18,13 +18,18 @@ #define LZMA_SIZE_BYTES (8) #define LZMA_HEADER_SIZE (13) -#define LZMA_DEFAULT_LEVEL (5) -#define MEMLIMIT (32 * 1024 * 1024) +#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) @@ -50,6 +55,9 @@ static sqfs_s32 try_compress(lzma_compressor_t *lzma, sqfs_u32 preset, 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); @@ -91,7 +99,7 @@ static sqfs_s32 lzma_comp_block(sqfs_compressor_t *base, const sqfs_u8 *in, if (outsize < LZMA_HEADER_SIZE || size >= 0x7FFFFFFF) return SQFS_ERROR_ARG_INVALID; - preset = LZMA_DEFAULT_LEVEL; + preset = lzma->level; ret = try_compress(lzma, preset, in, size, out, outsize); if (ret < 0 || !(lzma->flags & SQFS_COMP_FLAG_LZMA_EXTREME)) return ret; @@ -177,6 +185,11 @@ static void lzma_get_configuration(const sqfs_compressor_t *base, cfg->id = SQFS_COMP_LZMA; cfg->block_size = lzma->block_size; cfg->flags = lzma->flags; + cfg->opt.lzma.dict_size = lzma->dict_size; + cfg->opt.lzma.level = lzma->level; + 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) @@ -206,6 +219,36 @@ int lzma_compressor_create(const sqfs_compressor_config_t *cfg, if (cfg->flags & ~mask) return SQFS_ERROR_UNSUPPORTED; + /* XXX: values are unsigned and minimum is 0 */ + if (cfg->opt.lzma.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; + + 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) @@ -213,9 +256,14 @@ int lzma_compressor_create(const sqfs_compressor_config_t *cfg, 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; + lzma->dict_size = cfg->opt.lzma.dict_size; + lzma->level = cfg->opt.lzma.level; + lzma->lc = cfg->opt.lzma.lc; + lzma->lp = cfg->opt.lzma.lp; + lzma->pb = cfg->opt.lzma.pb; + + if (lzma->dict_size < SQFS_META_BLOCK_SIZE) + lzma->dict_size = SQFS_META_BLOCK_SIZE; base->get_configuration = lzma_get_configuration; base->do_block = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) ? |