diff options
Diffstat (limited to 'mkfs.ubifs/compr.c')
-rw-r--r-- | mkfs.ubifs/compr.c | 120 |
1 files changed, 119 insertions, 1 deletions
diff --git a/mkfs.ubifs/compr.c b/mkfs.ubifs/compr.c index da5c879..d0b5a0c 100644 --- a/mkfs.ubifs/compr.c +++ b/mkfs.ubifs/compr.c @@ -126,6 +126,114 @@ static inline int lzo_init(void) { return 0; } static inline void lzo_fini(void) { } #endif +#ifndef WITHOUT_XZ + +#include <lzma.h> + +struct xz_ctx { + lzma_filter filters[3]; + lzma_options_lzma opts; +}; + +static struct xz_ctx *xz_ctx; + +#define LZMA_COMPRESSION_LEVEL 9 + +static struct xz_ctx *xz_ctx_init(void) +{ + struct xz_ctx *ctx; + lzma_options_lzma *opts_lzma; + uint32_t preset; + int ret; + + ctx = malloc(sizeof(struct xz_ctx)); + if (ctx == NULL) + goto err; + + memset(ctx, 0, sizeof(struct xz_ctx)); + + opts_lzma = &ctx->opts; + + preset = LZMA_COMPRESSION_LEVEL | LZMA_PRESET_EXTREME; + ret = lzma_lzma_preset(opts_lzma, preset); + if (ret) + goto err_free_ctx; + + /* TODO: allow to specify LZMA options via command line */ +#if 0 + opts_lzma->lc = 3; + opts_lzma->lp = 0; + opts_lzma->pb = 2; + opts_lzma->nice_len = 64; +#else + opts_lzma->lc = 0; + opts_lzma->lp = 2; + opts_lzma->pb = 2; + opts_lzma->nice_len = 64; +#endif + + ctx->filters[0].id = LZMA_FILTER_LZMA2; + ctx->filters[0].options = opts_lzma; + ctx->filters[1].id = LZMA_VLI_UNKNOWN; + + return ctx; + +err_free_ctx: + free(ctx); +err: + return NULL; +} + +static void xz_ctx_free(struct xz_ctx *ctx) +{ + free(ctx); +} + +static int xz_init(void) +{ + xz_ctx = xz_ctx_init(); + if (xz_ctx == NULL) + return -1; + + return 0; +} + +static void xz_fini(void) +{ + xz_ctx_free(xz_ctx); +} + +static int xz_compress(void *in_buf, size_t in_len, void *out_buf, + size_t *out_len) +{ + size_t ret_len; + lzma_ret ret_xz; + int ret; + + ret = -1; + + ret_len = 0; + ret_xz = lzma_stream_buffer_encode(xz_ctx->filters, LZMA_CHECK_CRC32, + NULL, in_buf, in_len, out_buf, + &ret_len, *out_len); + if (ret_xz != LZMA_OK) { + fprintf(stderr, "XZ error: %d\n", (int) ret_xz); + goto out; + } + + *out_len = ret_len; + + ret = 0; +out: + return ret; +} +#else +static inline int xz_init(void) { return 0; } +static inline void xz_fini(void) { } +static inline int xz_compress(void *in_buf, size_t in_len, void *out_buf, + size_t *out_len) { return -1; } +#endif + static int no_compress(void *in_buf, size_t in_len, void *out_buf, size_t *out_len) { @@ -198,6 +306,9 @@ int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len, case MKFS_UBIFS_COMPR_LZO: ret = lzo_compress(in_buf, in_len, out_buf, out_len); break; + case MKFS_UBIFS_COMPR_XZ: + ret = xz_compress(in_buf, in_len, out_buf, out_len); + break; case MKFS_UBIFS_COMPR_ZLIB: ret = zlib_deflate(in_buf, in_len, out_buf, out_len); break; @@ -225,12 +336,18 @@ int init_compression(void) if (ret) goto err; + ret = xz_init(); + if (ret) + goto err_lzo; + zlib_buf = malloc(UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR); if (!zlib_buf) - goto err_lzo; + goto err_xz; return 0; +err_xz: + xz_fini(); err_lzo: lzo_fini(); err: @@ -240,6 +357,7 @@ err: void destroy_compression(void) { free(zlib_buf); + xz_fini(); lzo_fini(); if (errcnt) fprintf(stderr, "%llu compression errors occurred\n", errcnt); |