summaryrefslogtreecommitdiff
path: root/mkfs.ubifs/compr.c
diff options
context:
space:
mode:
Diffstat (limited to 'mkfs.ubifs/compr.c')
-rw-r--r--mkfs.ubifs/compr.c120
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);