379 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			379 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
--- a/Makefile
 | 
						|
+++ b/Makefile
 | 
						|
@@ -4,7 +4,7 @@
 | 
						|
 VERSION = 1.5.1
 | 
						|
 
 | 
						|
 CPPFLAGS += -D_GNU_SOURCE -I./include -I$(BUILDDIR)/include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) $(UUIDCPPFLAGS)
 | 
						|
-CPPFLAGS += -I./include/linux/lzma
 | 
						|
+CPPFLAGS += $(XZCPPFLAGS) -I./include/linux/lzma
 | 
						|
 
 | 
						|
 ifeq ($(WITHOUT_XATTR), 1)
 | 
						|
   CPPFLAGS += -DWITHOUT_XATTR
 | 
						|
@@ -113,8 +113,13 @@ ifeq ($(WITHOUT_LZO), 1)
 | 
						|
 else
 | 
						|
   LZOLDLIBS = -llzo2
 | 
						|
 endif
 | 
						|
+ifeq ($(WITHOUT_XZ), 1)
 | 
						|
+  CPPFLAGS += -DWITHOUT_XZ
 | 
						|
+else
 | 
						|
+  XZLDLIBS = -llzma
 | 
						|
+endif
 | 
						|
 
 | 
						|
-LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) -lm -luuid
 | 
						|
+LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) $(XZLDLIBS) -lm -luuid
 | 
						|
 $(call mkdep,mkfs.ubifs/,mkfs.ubifs,,ubi-utils/libubi.a)
 | 
						|
 
 | 
						|
 #
 | 
						|
--- a/mkfs.ubifs/compr.c
 | 
						|
+++ b/mkfs.ubifs/compr.c
 | 
						|
@@ -126,6 +126,114 @@ static inline int lzo_init(void) { retur
 | 
						|
 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 i
 | 
						|
 		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);
 | 
						|
--- a/mkfs.ubifs/compr.h
 | 
						|
+++ b/mkfs.ubifs/compr.h
 | 
						|
@@ -36,6 +36,7 @@ enum compression_type
 | 
						|
 	MKFS_UBIFS_COMPR_NONE,
 | 
						|
 	MKFS_UBIFS_COMPR_LZO,
 | 
						|
 	MKFS_UBIFS_COMPR_ZLIB,
 | 
						|
+	MKFS_UBIFS_COMPR_XZ,
 | 
						|
 };
 | 
						|
 
 | 
						|
 int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
 | 
						|
--- a/mkfs.ubifs/mkfs.ubifs.c
 | 
						|
+++ b/mkfs.ubifs/mkfs.ubifs.c
 | 
						|
@@ -99,6 +99,9 @@ struct ubifs_info info_;
 | 
						|
 static struct ubifs_info *c = &info_;
 | 
						|
 static libubi_t ubi;
 | 
						|
 
 | 
						|
+static int force_compr_set;
 | 
						|
+static int force_compr;
 | 
						|
+
 | 
						|
 /* Debug levels are: 0 (none), 1 (statistics), 2 (files) ,3 (more details) */
 | 
						|
 int debug_level;
 | 
						|
 int verbose;
 | 
						|
@@ -133,7 +136,7 @@ static struct inum_mapping **hash_table;
 | 
						|
 /* Inode creation sequence number */
 | 
						|
 static unsigned long long creat_sqnum;
 | 
						|
 
 | 
						|
-static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:j:R:l:j:UQq";
 | 
						|
+static const char *optstring = "d:r:m:o:D:yh?vVe:c:g:f:Fp:k:x:X:z:j:R:l:j:UQq";
 | 
						|
 
 | 
						|
 static const struct option longopts[] = {
 | 
						|
 	{"root",               1, NULL, 'r'},
 | 
						|
@@ -151,6 +154,7 @@ static const struct option longopts[] =
 | 
						|
 	{"reserved",           1, NULL, 'R'},
 | 
						|
 	{"compr",              1, NULL, 'x'},
 | 
						|
 	{"favor-percent",      1, NULL, 'X'},
 | 
						|
+	{"force-compr",        1, NULL, 'z'},
 | 
						|
 	{"fanout",             1, NULL, 'f'},
 | 
						|
 	{"space-fixup",        0, NULL, 'F'},
 | 
						|
 	{"keyhash",            1, NULL, 'k'},
 | 
						|
@@ -178,11 +182,13 @@ static const char *helptext =
 | 
						|
 "-o, --output=FILE        output to FILE\n"
 | 
						|
 "-j, --jrn-size=SIZE      journal size\n"
 | 
						|
 "-R, --reserved=SIZE      how much space should be reserved for the super-user\n"
 | 
						|
-"-x, --compr=TYPE         compression type - \"lzo\", \"favor_lzo\", \"zlib\" or\n"
 | 
						|
-"                         \"none\" (default: \"lzo\")\n"
 | 
						|
+"-x, --compr=TYPE         default compression type - \"lzo\", \"favor_lzo\",\n"
 | 
						|
+"                         \"zlib\" or \"none\" (default: \"lzo\")\n"
 | 
						|
 "-X, --favor-percent      may only be used with favor LZO compression and defines\n"
 | 
						|
 "                         how many percent better zlib should compress to make\n"
 | 
						|
 "                         mkfs.ubifs use zlib instead of LZO (default 20%)\n"
 | 
						|
+"-z, --force-compr=TYPE   force to build the fs with different compression -\n"
 | 
						|
+"                         \"lzo\", \"zlib\" or \"none\"\n"
 | 
						|
 "-f, --fanout=NUM         fanout NUM (default: 8)\n"
 | 
						|
 "-F, --space-fixup        file-system free space has to be fixed up on first mount\n"
 | 
						|
 "                         (requires kernel version 3.0 or greater)\n"
 | 
						|
@@ -472,6 +478,43 @@ static int open_ubi(const char *node)
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
+static const char *get_compr_str(int compr)
 | 
						|
+{
 | 
						|
+	switch (compr) {
 | 
						|
+	case UBIFS_COMPR_LZO:
 | 
						|
+		return "lzo";
 | 
						|
+	case UBIFS_COMPR_ZLIB:
 | 
						|
+		return "zlib";
 | 
						|
+	case UBIFS_COMPR_XZ:
 | 
						|
+		return "xz";
 | 
						|
+	case UBIFS_COMPR_NONE:
 | 
						|
+		return "none";
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return "unknown";
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int get_compr_option(char *opt, int *compr_type, int *favor_lzo)
 | 
						|
+{
 | 
						|
+	*compr_type = UBIFS_COMPR_LZO;
 | 
						|
+
 | 
						|
+	if (favor_lzo)
 | 
						|
+		*favor_lzo = 0;
 | 
						|
+
 | 
						|
+	if (favor_lzo && strcmp(optarg, "favor_lzo") == 0)
 | 
						|
+		*favor_lzo = 1;
 | 
						|
+	else if (strcmp(optarg, "zlib") == 0)
 | 
						|
+		*compr_type = UBIFS_COMPR_ZLIB;
 | 
						|
+	else if (strcmp(optarg, "xz") == 0)
 | 
						|
+		*compr_type = UBIFS_COMPR_XZ;
 | 
						|
+	else if (strcmp(optarg, "none") == 0)
 | 
						|
+		*compr_type = UBIFS_COMPR_NONE;
 | 
						|
+	else if (strcmp(optarg, "lzo") != 0)
 | 
						|
+		return -1;
 | 
						|
+
 | 
						|
+	return 0;
 | 
						|
+}
 | 
						|
+
 | 
						|
 static int get_options(int argc, char**argv)
 | 
						|
 {
 | 
						|
 	int opt, i;
 | 
						|
@@ -594,14 +637,13 @@ static int get_options(int argc, char**a
 | 
						|
 				return err_msg("bad key hash");
 | 
						|
 			break;
 | 
						|
 		case 'x':
 | 
						|
-			if (strcmp(optarg, "favor_lzo") == 0)
 | 
						|
-				c->favor_lzo = 1;
 | 
						|
-			else if (strcmp(optarg, "zlib") == 0)
 | 
						|
-				c->default_compr = UBIFS_COMPR_ZLIB;
 | 
						|
-			else if (strcmp(optarg, "none") == 0)
 | 
						|
-				c->default_compr = UBIFS_COMPR_NONE;
 | 
						|
-			else if (strcmp(optarg, "lzo") != 0)
 | 
						|
-				return err_msg("bad compressor name");
 | 
						|
+			if (get_compr_option(optarg, &c->default_compr,
 | 
						|
+					     &c->favor_lzo))
 | 
						|
+				return err_msg("bad compressor name '%s'",
 | 
						|
+						optarg);
 | 
						|
+			if (c->default_compr == UBIFS_COMPR_XZ)
 | 
						|
+				return err_msg("'%s' can't be used as default compressor",
 | 
						|
+						optarg);
 | 
						|
 			break;
 | 
						|
 		case 'X':
 | 
						|
 			c->favor_percent = strtol(optarg, &endp, 0);
 | 
						|
@@ -610,6 +652,12 @@ static int get_options(int argc, char**a
 | 
						|
 				return err_msg("bad favor LZO percent '%s'",
 | 
						|
 					       optarg);
 | 
						|
 			break;
 | 
						|
+		case 'z':
 | 
						|
+			if (get_compr_option(optarg, &force_compr, NULL))
 | 
						|
+				return err_msg("bad forced compressor name '%s'",
 | 
						|
+						optarg);
 | 
						|
+			force_compr_set = 1;
 | 
						|
+			break;
 | 
						|
 		case 'j':
 | 
						|
 			c->max_bud_bytes = get_bytes(optarg);
 | 
						|
 			if (c->max_bud_bytes <= 0)
 | 
						|
@@ -684,6 +732,9 @@ static int get_options(int argc, char**a
 | 
						|
 		c->min_io_size = 8;
 | 
						|
 	c->rp_size = add_space_overhead(c->rp_size);
 | 
						|
 
 | 
						|
+	if (force_compr_set == 0)
 | 
						|
+		force_compr = c->default_compr;
 | 
						|
+
 | 
						|
 	if (verbose) {
 | 
						|
 		printf("mkfs.ubifs\n");
 | 
						|
 		printf("\troot:         %s\n", root);
 | 
						|
@@ -693,17 +744,10 @@ static int get_options(int argc, char**a
 | 
						|
 		printf("\toutput:       %s\n", output);
 | 
						|
 		printf("\tjrn_size:     %llu\n", c->max_bud_bytes);
 | 
						|
 		printf("\treserved:     %llu\n", c->rp_size);
 | 
						|
-		switch (c->default_compr) {
 | 
						|
-		case UBIFS_COMPR_LZO:
 | 
						|
-			printf("\tcompr:        lzo\n");
 | 
						|
-			break;
 | 
						|
-		case UBIFS_COMPR_ZLIB:
 | 
						|
-			printf("\tcompr:        zlib\n");
 | 
						|
-			break;
 | 
						|
-		case UBIFS_COMPR_NONE:
 | 
						|
-			printf("\tcompr:        none\n");
 | 
						|
-			break;
 | 
						|
-		}
 | 
						|
+		printf("\tcompr:        %s\n", get_compr_str(c->default_compr));
 | 
						|
+		if (force_compr_set)
 | 
						|
+			printf("\tforced compr: %s\n",
 | 
						|
+			       get_compr_str(force_compr));
 | 
						|
 		printf("\tkeyhash:      %s\n", (c->key_hash == key_r5_hash) ?
 | 
						|
 						"r5" : "test");
 | 
						|
 		printf("\tfanout:       %d\n", c->fanout);
 | 
						|
@@ -1284,7 +1328,7 @@ static int add_file(const char *path_nam
 | 
						|
 			use_compr = UBIFS_COMPR_LZO;
 | 
						|
 		else
 | 
						|
 #endif
 | 
						|
-			use_compr = c->default_compr;
 | 
						|
+			use_compr = force_compr;
 | 
						|
 		compr_type = compress_data(buf, bytes_read, &dn->data,
 | 
						|
 					   &out_len, use_compr);
 | 
						|
 		dn->compr_type = cpu_to_le16(compr_type);
 | 
						|
--- a/mkfs.ubifs/mkfs.ubifs.h
 | 
						|
+++ b/mkfs.ubifs/mkfs.ubifs.h
 | 
						|
@@ -83,6 +83,9 @@
 | 
						|
 #if MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
 | 
						|
 #error MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
 | 
						|
 #endif
 | 
						|
+#if MKFS_UBIFS_COMPR_XZ != UBIFS_COMPR_XZ
 | 
						|
+#error MKFS_UBIFS_COMPR_XZ != UBIFS_COMPR_XZ
 | 
						|
+#endif
 | 
						|
 
 | 
						|
 extern int verbose;
 | 
						|
 extern int debug_level;
 | 
						|
--- a/include/mtd/ubifs-media.h
 | 
						|
+++ b/include/mtd/ubifs-media.h
 | 
						|
@@ -313,6 +313,7 @@ enum {
 | 
						|
 	UBIFS_COMPR_NONE,
 | 
						|
 	UBIFS_COMPR_LZO,
 | 
						|
 	UBIFS_COMPR_ZLIB,
 | 
						|
+	UBIFS_COMPR_XZ,
 | 
						|
 	UBIFS_COMPR_TYPES_CNT,
 | 
						|
 };
 | 
						|
 
 |