aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-06-04 04:57:08 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-06-04 04:57:08 +0200
commit0f23f0396aede08a5d0c95d75b272f1b1787a365 (patch)
tree2e0eda82a0a4151cd01b129bb404db2cd3e95581 /lib/sqfs
parentad73b9440422c06805764da6058ebeb6d41a4f04 (diff)
lzma compressor: support micro management options
The LZMA compressor (through the xz-utils library) supports basically the same options for micro management as the XZ compressor. This commit enables support for those options in the compressor, the option parser and adds an option field to the configuration structure. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs')
-rw-r--r--lib/sqfs/comp/compressor.c9
-rw-r--r--lib/sqfs/comp/lzma.c60
2 files changed, 63 insertions, 6 deletions
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) ?