tools/mtd-utils: add XZ compression support to mkfs.ubifs
[openwrt.git] / tools / mtd-utils / patches / 136-mkfs.ubifs-xz-support.patch
1 --- a/Makefile
2 +++ b/Makefile
3 @@ -1,7 +1,7 @@
4  
5  # -*- sh -*-
6  
7 -CPPFLAGS += -I./include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) -I./include/linux/lzma
8 +CPPFLAGS += -I./include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) $(XZCPPFLAGS) -I./include/linux/lzma
9  
10  ifeq ($(WITHOUT_XATTR), 1)
11    CPPFLAGS += -DWITHOUT_XATTR
12 --- a/mkfs.ubifs/compr.c
13 +++ b/mkfs.ubifs/compr.c
14 @@ -127,6 +127,114 @@ static inline int lzo_init(void) { retur
15  static inline void lzo_fini(void) { }
16  #endif
17  
18 +#ifndef WITHOUT_XZ
19 +
20 +#include <lzma.h>
21 +
22 +struct xz_ctx {
23 +       lzma_filter     filters[3];
24 +       lzma_options_lzma opts;
25 +};
26 +
27 +static struct xz_ctx *xz_ctx;
28 +
29 +#define LZMA_COMPRESSION_LEVEL 9
30 +
31 +static struct xz_ctx *xz_ctx_init(void)
32 +{
33 +       struct xz_ctx *ctx;
34 +       lzma_options_lzma *opts_lzma;
35 +       uint32_t preset;
36 +       int ret;
37 +
38 +       ctx = malloc(sizeof(struct xz_ctx));
39 +       if (ctx == NULL)
40 +               goto err;
41 +
42 +       memset(ctx, 0, sizeof(struct xz_ctx));
43 +
44 +       opts_lzma = &ctx->opts;
45 +
46 +       preset = LZMA_COMPRESSION_LEVEL | LZMA_PRESET_EXTREME;
47 +       ret = lzma_lzma_preset(opts_lzma, preset);
48 +       if (ret)
49 +               goto err_free_ctx;
50 +
51 +       /* TODO: allow to specify LZMA options via command line */
52 +#if 0
53 +       opts_lzma->lc = 3;
54 +       opts_lzma->lp = 0;
55 +       opts_lzma->pb = 2;
56 +       opts_lzma->nice_len = 64;
57 +#else
58 +       opts_lzma->lc = 0;
59 +       opts_lzma->lp = 2;
60 +       opts_lzma->pb = 2;
61 +       opts_lzma->nice_len = 64;
62 +#endif
63 +
64 +       ctx->filters[0].id = LZMA_FILTER_LZMA2;
65 +       ctx->filters[0].options = opts_lzma;
66 +       ctx->filters[1].id = LZMA_VLI_UNKNOWN;
67 +
68 +       return ctx;
69 +
70 +err_free_ctx:
71 +       free(ctx);
72 +err:
73 +       return NULL;
74 +}
75 +
76 +static void xz_ctx_free(struct xz_ctx *ctx)
77 +{
78 +       free(ctx);
79 +}
80 +
81 +static int xz_init(void)
82 +{
83 +       xz_ctx = xz_ctx_init();
84 +       if (xz_ctx == NULL)
85 +               return -1;
86 +
87 +       return 0;
88 +}
89 +
90 +static void xz_fini(void)
91 +{
92 +       xz_ctx_free(xz_ctx);
93 +}
94 +
95 +static int xz_compress(void *in_buf, size_t in_len, void *out_buf,
96 +                      size_t *out_len)
97 +{
98 +       size_t ret_len;
99 +       lzma_ret ret_xz;
100 +       int ret;
101 +
102 +       ret = -1;
103 +
104 +       ret_len = 0;
105 +       ret_xz = lzma_stream_buffer_encode(xz_ctx->filters, LZMA_CHECK_CRC32,
106 +                                          NULL, in_buf, in_len, out_buf,
107 +                                          &ret_len, *out_len);
108 +       if (ret_xz != LZMA_OK) {
109 +               fprintf(stderr, "XZ error: %d\n", (int) ret_xz);
110 +               goto out;
111 +       }
112 +
113 +       *out_len = ret_len;
114 +
115 +       ret = 0;
116 +out:
117 +       return ret;
118 +}
119 +#else
120 +static inline int xz_init(void) { return 0; }
121 +static inline void xz_fini(void) { }
122 +static inline int xz_compress(void *in_buf, size_t in_len, void *out_buf,
123 +                             size_t *out_len) { return -1; }
124 +#endif
125 +
126  static int no_compress(void *in_buf, size_t in_len, void *out_buf,
127                        size_t *out_len)
128  {
129 @@ -199,6 +307,9 @@ int compress_data(void *in_buf, size_t i
130                 case MKFS_UBIFS_COMPR_LZO:
131                         ret = lzo_compress(in_buf, in_len, out_buf, out_len);
132                         break;
133 +               case MKFS_UBIFS_COMPR_XZ:
134 +                       ret = xz_compress(in_buf, in_len, out_buf, out_len);
135 +                       break;
136                 case MKFS_UBIFS_COMPR_ZLIB:
137                         ret = zlib_deflate(in_buf, in_len, out_buf, out_len);
138                         break;
139 @@ -226,12 +337,18 @@ int init_compression(void)
140         if (ret)
141                 goto err;
142  
143 +       ret = xz_init();
144 +       if (ret)
145 +               goto err_lzo;
146 +
147         zlib_buf = malloc(UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR);
148         if (!zlib_buf)
149 -               goto err_lzo;
150 +               goto err_xz;
151  
152         return 0;
153  
154 +err_xz:
155 +       xz_fini();
156  err_lzo:
157         lzo_fini();
158  err:
159 @@ -241,6 +358,7 @@ err:
160  void destroy_compression(void)
161  {
162         free(zlib_buf);
163 +       xz_fini();
164         lzo_fini();
165         if (errcnt)
166                 fprintf(stderr, "%llu compression errors occurred\n", errcnt);
167 --- a/mkfs.ubifs/compr.h
168 +++ b/mkfs.ubifs/compr.h
169 @@ -36,6 +36,7 @@ enum compression_type
170         MKFS_UBIFS_COMPR_NONE,
171         MKFS_UBIFS_COMPR_LZO,
172         MKFS_UBIFS_COMPR_ZLIB,
173 +       MKFS_UBIFS_COMPR_XZ,
174  };
175  
176  int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
177 --- a/mkfs.ubifs/Makefile
178 +++ b/mkfs.ubifs/Makefile
179 @@ -6,21 +6,33 @@ ALL_SOURCES=*.[ch] hashtable/*.[ch]
180  
181  TARGETS = mkfs.ubifs
182  
183 +MKFS_UBIFS_OBJS = $(addprefix $(BUILDDIR)/,\
184 +       crc16.o lpt.o compr.o devtable.o \
185 +       hashtable/hashtable.o hashtable/hashtable_itr.o)
186 +
187  ifeq ($(WITHOUT_LZO), 1)
188    CPPFLAGS += -DWITHOUT_LZO
189  else
190    LZOLDLIBS = -llzo2
191  endif
192  
193 -LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) -lm -luuid -L$(BUILDDIR)/../ubi-utils/ -lubi
194 +ifeq ($(WITHOUT_XZ), 1)
195 +  CPPFLAGS += -DWITHOUT_XZ
196 +else
197 +ifneq ($(LZMA_STATIC_LIB),)
198 +  MKFS_UBIFS_OBJS += $(LZMA_STATIC_LIB)
199 +else
200 +  XZLDLIBS = -llzma
201 +endif
202 +endif
203 +
204 +LDLIBS_mkfs.ubifs = -lz $(LZOLDLIBS) $(XZLDLIBS) -lm -luuid -L$(BUILDDIR)/../ubi-utils/ -lubi
205  LDLIBS_mkfs.ubifs += -L$(BUILDDIR)/../lib -lmtd
206 -LDLIBS_mkfs.ubifs += $(ZLIBLDFLAGS) $(LZOLDFLAGS)
207 +LDLIBS_mkfs.ubifs += $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(XZLDFLAGS)
208  
209  include ../common.mk
210  
211 -$(BUILDDIR)/mkfs.ubifs: $(addprefix $(BUILDDIR)/,\
212 -       crc16.o lpt.o compr.o devtable.o \
213 -       hashtable/hashtable.o hashtable/hashtable_itr.o)
214 +$(BUILDDIR)/mkfs.ubifs: $(MKFS_UBIFS_OBJS)
215  
216  clean::
217         rm -f $(BUILDDIR)/hashtable/*.o cscope.*
218 --- a/mkfs.ubifs/mkfs.ubifs.c
219 +++ b/mkfs.ubifs/mkfs.ubifs.c
220 @@ -178,8 +178,8 @@ static const char *helptext =
221  "-o, --output=FILE        output to FILE\n"
222  "-j, --jrn-size=SIZE      journal size\n"
223  "-R, --reserved=SIZE      how much space should be reserved for the super-user\n"
224 -"-x, --compr=TYPE         compression type - \"lzo\", \"favor_lzo\", \"zlib\" or\n"
225 -"                         \"none\" (default: \"lzo\")\n"
226 +"-x, --compr=TYPE         compression type - \"lzo\", \"favor_lzo\", \"zlib\",\n"
227 +"                         \"xz\" or \"none\" (default: \"lzo\")\n"
228  "-X, --favor-percent      may only be used with favor LZO compression and defines\n"
229  "                         how many percent better zlib should compress to make\n"
230  "                         mkfs.ubifs use zlib instead of LZO (default 20%)\n"
231 @@ -208,7 +208,7 @@ static const char *helptext =
232  "-h, --help               display this help text\n\n"
233  "Note, SIZE is specified in bytes, but it may also be specified in Kilobytes,\n"
234  "Megabytes, and Gigabytes if a KiB, MiB, or GiB suffix is used.\n\n"
235 -"If you specify \"lzo\" or \"zlib\" compressors, mkfs.ubifs will use this compressor\n"
236 +"If you specify \"lzo\", \"xz\" or \"zlib\" compressors, mkfs.ubifs will use this compressor\n"
237  "for all data. The \"none\" disables any data compression. The \"favor_lzo\" is not\n"
238  "really a separate compressor. It is just a method of combining \"lzo\" and \"zlib\"\n"
239  "compressors. Namely, mkfs.ubifs tries to compress data with both \"lzo\" and \"zlib\"\n"
240 @@ -653,10 +653,13 @@ static int get_options(int argc, char**a
241                                 c->favor_lzo = 1;
242                         else if (strcmp(optarg, "zlib") == 0)
243                                 c->default_compr = UBIFS_COMPR_ZLIB;
244 +                       else if (strcmp(optarg, "xz") == 0)
245 +                               c->default_compr = UBIFS_COMPR_XZ;
246                         else if (strcmp(optarg, "none") == 0)
247                                 c->default_compr = UBIFS_COMPR_NONE;
248                         else if (strcmp(optarg, "lzo") != 0)
249 -                               return err_msg("bad compressor name");
250 +                               return err_msg("bad compressor name '%s'",
251 +                                              optarg);
252                         break;
253                 case 'X':
254                         c->favor_percent = strtol(optarg, &endp, 0);
255 @@ -765,6 +768,9 @@ static int get_options(int argc, char**a
256                 case UBIFS_COMPR_ZLIB:
257                         printf("\tcompr:        zlib\n");
258                         break;
259 +               case UBIFS_COMPR_XZ:
260 +                       printf("\tcompr:        xz\n");
261 +                       break;
262                 case UBIFS_COMPR_NONE:
263                         printf("\tcompr:        none\n");
264                         break;
265 --- a/mkfs.ubifs/mkfs.ubifs.h
266 +++ b/mkfs.ubifs/mkfs.ubifs.h
267 @@ -77,6 +77,9 @@
268  #if MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
269  #error MKFS_UBIFS_COMPR_ZLIB != UBIFS_COMPR_ZLIB
270  #endif
271 +#if MKFS_UBIFS_COMPR_XZ != UBIFS_COMPR_XZ
272 +#error MKFS_UBIFS_COMPR_XZ != UBIFS_COMPR_XZ
273 +#endif
274  
275  extern int verbose;
276  extern int debug_level;
277 --- a/mkfs.ubifs/ubifs-media.h
278 +++ b/mkfs.ubifs/ubifs-media.h
279 @@ -303,6 +303,7 @@ enum {
280         UBIFS_COMPR_NONE,
281         UBIFS_COMPR_LZO,
282         UBIFS_COMPR_ZLIB,
283 +       UBIFS_COMPR_XZ,
284         UBIFS_COMPR_TYPES_CNT,
285  };
286