b5fb80dffaafa15b94cff81b067450b453a577a4
[openwrt.git] / tools / squashfs4 / patches / 160-expose_lzma_xz_options.patch
1 --- /dev/null
2 +++ b/squashfs-tools/lzma_xz_options.h
3 @@ -0,0 +1,112 @@
4 +#ifndef LZMA_XZ_OPTIONS_H
5 +#define LZMA_XZ_OPTIONS_H
6 +/*
7 + * Copyright (c) 2011
8 + * Jonas Gorski <jonas.gorski@gmail.com>
9 + *
10 + * This program is free software; you can redistribute it and/or
11 + * modify it under the terms of the GNU General Public License
12 + * as published by the Free Software Foundation; either version 2,
13 + * or (at your option) any later version.
14 + *
15 + * This program is distributed in the hope that it will be useful,
16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 + * GNU General Public License for more details.
19 + *
20 + * You should have received a copy of the GNU General Public License
21 + * along with this program; if not, write to the Free Software
22 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 + *
24 + * lzma_options.h
25 + */
26 +
27 +#include <stdint.h>
28 +
29 +#ifndef linux
30 +#define __BYTE_ORDER BYTE_ORDER
31 +#define __BIG_ENDIAN BIG_ENDIAN
32 +#define __LITTLE_ENDIAN LITTLE_ENDIAN
33 +#else
34 +#include <endian.h>
35 +#endif
36 +
37 +
38 +
39 +struct lzma_opts {
40 +       uint32_t flags;
41 +#define LZMA_OPT_FLT_MASK      0xffff
42 +#define LZMA_OPT_PRE_OFF       16
43 +#define LZMA_OPT_PRE_MASK      (0xf << LZMA_OPT_PRE_OFF)
44 +#define LZMA_OPT_EXTREME       20      
45 +       uint16_t bit_opts;
46 +#define LZMA_OPT_LC_OFF                0
47 +#define LZMA_OPT_LC_MASK       (0x7 << LZMA_OPT_LC_OFF)
48 +#define LZMA_OPT_LP_OFF                3
49 +#define LZMA_OPT_LP_MASK       (0x7 << LZMA_OPT_LP_OFF)
50 +#define LZMA_OPT_PB_OFF                6
51 +#define LZMA_OPT_PB_MASK       (0x7 << LZMA_OPT_PB_OFF)
52 +       uint16_t fb;
53 +       uint32_t dict_size;
54 +};
55 +
56 +#if __BYTE_ORDER == __BIG_ENDIAN
57 +extern unsigned int inswap_le32(unsigned int);
58 +
59 +#define SQUASHFS_INSWAP_LZMA_COMP_OPTS(s) { \
60 +       (s)->flags = inswap_le32((s)->flags); \
61 +       (s)->bit_opts = inswap_le16((s)->bit_opts); \
62 +       (s)->fb = inswap_le16((s)->fb); \
63 +       (s)->dict_size = inswap_le32((s)->dict_size); \
64 +}
65 +#else
66 +#define SQUASHFS_INSWAP_LZMA_COMP_OPTS(s)
67 +#endif
68 +
69 +#define MEMLIMIT (32 * 1024 * 1024)
70 +
71 +#define LZMA_OPT_LC_MIN                0
72 +#define LZMA_OPT_LC_MAX                4
73 +#define LZMA_OPT_LC_DEFAULT    3
74 +
75 +#define LZMA_OPT_LP_MIN                0
76 +#define LZMA_OPT_LP_MAX                4
77 +#define LZMA_OPT_LP_DEFAULT    0
78 +
79 +#define LZMA_OPT_PB_MIN                0
80 +#define LZMA_OPT_PB_MAX                4
81 +#define LZMA_OPT_PB_DEFAULT    2
82 +
83 +#define LZMA_OPT_FB_MIN                5
84 +#define LZMA_OPT_FB_MAX                273
85 +#define LZMA_OPT_FB_DEFAULT    64
86 +
87 +enum {
88 +       LZMA_OPT_LZMA = 1,
89 +       LZMA_OPT_XZ
90 +};
91 +
92 +struct lzma_xz_options {
93 +       int preset;
94 +       int extreme;
95 +       int lc;
96 +       int lp;
97 +       int pb;
98 +       int fb;
99 +       int dict_size;
100 +       int flags;
101 +};
102 +
103 +struct lzma_xz_options *lzma_xz_get_options(void);
104 +
105 +int lzma_xz_options(char *argv[], int argc, int lzmaver);
106 +
107 +int lzma_xz_options_post(int block_size, int lzmaver);
108 +
109 +void *lzma_xz_dump_options(int block_size, int *size, int flags);
110 +
111 +int lzma_xz_extract_options(int block_size, void *buffer, int size, int lzmaver);
112 +
113 +void lzma_xz_usage(int lzmaver);
114 +
115 +#endif
116 --- /dev/null
117 +++ b/squashfs-tools/lzma_xz_options.c
118 @@ -0,0 +1,365 @@
119 +/*
120 + * Copyright (c) 2011
121 + * Jonas Gorski <jonas.gorski@gmail.com>
122 + *
123 + * This program is free software; you can redistribute it and/or
124 + * modify it under the terms of the GNU General Public License
125 + * as published by the Free Software Foundation; either version 2,
126 + * or (at your option) any later version.
127 + *
128 + * This program is distributed in the hope that it will be useful,
129 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
130 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
131 + * GNU General Public License for more details.
132 + *
133 + * You should have received a copy of the GNU General Public License
134 + * along with this program; if not, write to the Free Software
135 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
136 + *
137 + * lzma_options.c
138 + * 
139 + * Common options for LZMA1 and 2 compressors. Based on xz_wrapper.c
140 + */
141 +
142 +#include <stdio.h>
143 +#include <string.h>
144 +#include <stdlib.h>
145 +
146 +#include <lzma.h>
147 +
148 +#include "lzma_xz_options.h"
149 +
150 +static const char const *lzmaver_str[] = { "", "lzma", "xz" };
151 +
152 +static struct lzma_xz_options options = {
153 +       .flags          = 0,
154 +       .preset         = 6,
155 +       .extreme        = 0,
156 +       .lc             = LZMA_OPT_LC_DEFAULT,
157 +       .lp             = LZMA_OPT_LP_DEFAULT,
158 +       .pb             = LZMA_OPT_PB_DEFAULT,
159 +       .fb             = LZMA_OPT_FB_DEFAULT,
160 +       .dict_size      = 0,
161 +};
162 +
163 +static float lzma_dict_percent = 0;
164 +
165 +struct lzma_xz_options *lzma_xz_get_options(void)
166 +{
167 +       return &options;
168 +}
169 +
170 +
171 +int lzma_xz_options(char *argv[], int argc, int lzmaver)
172 +{
173 +       const char *comp_name = lzmaver_str[lzmaver];
174 +       
175 +       if(strcmp(argv[0], "-Xpreset") == 0) {
176 +               int preset;
177 +               
178 +               if(argc < 2) {
179 +                       fprintf(stderr, "%s: -Xpreset missing preset\n", comp_name);
180 +                       goto failed;
181 +               }
182 +               
183 +               preset = atoi(argv[1]);
184 +               
185 +               if (preset < 0 || preset > 9) {
186 +                       fprintf(stderr, "%s: -Xpreset invalid value\n", comp_name);
187 +                       goto failed;
188 +               }
189 +               options.preset = preset;
190 +               return 1;
191 +       } else if(strcmp(argv[0], "-Xe") == 0) {
192 +               options.extreme = 1;
193 +               return 0;
194 +       } else if(strcmp(argv[0], "-Xlc") == 0) {
195 +               int lc;
196 +               
197 +               if(argc < 2) {
198 +                       fprintf(stderr, "%s: -Xlc missing lc\n", comp_name);
199 +                       goto failed;
200 +               }
201 +               
202 +               lc = atoi(argv[1]);
203 +               
204 +               if (lc < LZMA_OPT_LC_MIN || lc > LZMA_OPT_LC_MAX) {
205 +                       fprintf(stderr, "%s: -Xlc invalid value\n", comp_name);
206 +                       goto failed;
207 +               }
208 +               options.lc = lc;
209 +               return 1;
210 +       } else if(strcmp(argv[0], "-Xlp") == 0) {
211 +               int lp;
212 +               
213 +               if(argc < 2) {
214 +                       fprintf(stderr, "%s: -Xlp missing lp\n", comp_name);
215 +                       goto failed;
216 +               }
217 +               
218 +               lp = atoi(argv[1]);
219 +               
220 +               if (lp < LZMA_OPT_LP_MIN || lp > LZMA_OPT_LP_MAX) {
221 +                       fprintf(stderr, "%s: -Xlp invalid value\n", comp_name);
222 +                       goto failed;
223 +               }
224 +               options.lp = lp;
225 +               return 1;
226 +       } else if(strcmp(argv[0], "-Xpb") == 0) {
227 +               int pb;
228 +               
229 +               if(argc < 2) {
230 +                       fprintf(stderr, "%s: -Xpb missing pb\n", comp_name);
231 +                       goto failed;
232 +               }
233 +               
234 +               pb = atoi(argv[1]);
235 +               
236 +               if (pb < LZMA_OPT_PB_MIN || pb > LZMA_OPT_PB_MAX) {
237 +                       fprintf(stderr, "%s: -Xbp invalid value\n", comp_name);
238 +                       goto failed;
239 +               }
240 +               options.pb = pb;
241 +               return 1;       
242 +       } else if(strcmp(argv[0], "-Xfb") == 0) {
243 +               int fb;
244 +               
245 +               if(argc < 2) {
246 +                       fprintf(stderr, "%s: -Xfb missing fb\n", comp_name);
247 +                       goto failed;
248 +               }
249 +               
250 +               fb = atoi(argv[1]);
251 +               
252 +               if (fb < LZMA_OPT_FB_MIN || fb > LZMA_OPT_FB_MAX) {
253 +                       fprintf(stderr, "%s: -Xfb invalid value\n", comp_name);
254 +                       goto failed;
255 +               }
256 +               options.fb = fb;
257 +               return 1;
258 +       } else if(strcmp(argv[0], "-Xdict-size") == 0) {
259 +               char *b;
260 +               float size;
261 +
262 +               if(argc < 2) {
263 +                       fprintf(stderr, "%s: -Xdict-size missing dict-size\n", comp_name);
264 +                       goto failed;
265 +               }
266 +
267 +               size = strtof(argv[1], &b);
268 +               if(*b == '%') {
269 +                       if(size <= 0 || size > 100) {
270 +                               fprintf(stderr, "%s: -Xdict-size percentage "
271 +                                       "should be 0 < dict-size <= 100\n", comp_name);
272 +                               goto failed;
273 +                       }
274 +
275 +                       lzma_dict_percent = size;
276 +                       options.dict_size = 0;
277 +               } else {
278 +                       if((float) ((int) size) != size) {
279 +                               fprintf(stderr, "%s: -Xdict-size can't be "
280 +                                       "fractional unless a percentage of the"
281 +                                       " block size\n", comp_name);
282 +                               goto failed;
283 +                       }
284 +
285 +                       lzma_dict_percent = 0;
286 +                       options.dict_size = (int) size;
287 +
288 +                       if(*b == 'k' || *b == 'K')
289 +                               options.dict_size *= 1024;
290 +                       else if(*b == 'm' || *b == 'M')
291 +                               options.dict_size *= 1024 * 1024;
292 +                       else if(*b != '\0') {
293 +                               fprintf(stderr, "%s: -Xdict-size invalid "
294 +                                       "dict-size\n", comp_name);
295 +                               goto failed;
296 +                       }
297 +               }
298 +
299 +               return 1;
300 +       }
301 +       
302 +       return -1;
303 +       
304 +failed:
305 +       return -2;
306 +
307 +}
308 +
309 +int lzma_xz_options_post(int block_size, int lzmaver)
310 +{
311 +       const char *comp_name = lzmaver_str[lzmaver];
312 +       /*
313 +        * if -Xdict-size has been specified use this to compute the datablock
314 +        * dictionary size
315 +        */
316 +       if(options.dict_size || lzma_dict_percent) {
317 +               int dict_size_min = (lzmaver == 1 ? 4096 : 8192);
318 +               int n;
319 +
320 +               if(options.dict_size) {
321 +                       if(options.dict_size > block_size) {
322 +                               fprintf(stderr, "%s: -Xdict-size is larger than"
323 +                               " block_size\n", comp_name);
324 +                               goto failed;
325 +                       }
326 +               } else
327 +                       options.dict_size = block_size * lzma_dict_percent / 100;
328 +
329 +               if(options.dict_size < dict_size_min) {
330 +                       fprintf(stderr, "%s: -Xdict-size should be %i bytes "
331 +                               "or larger\n", comp_name, dict_size_min);
332 +                       goto failed;
333 +               }
334 +
335 +               /*
336 +                * dictionary_size must be storable in xz header as either
337 +                * 2^n or as  2^n+2^(n+1)
338 +               */
339 +               n = ffs(options.dict_size) - 1;
340 +               if(options.dict_size != (1 << n) &&
341 +                               options.dict_size != ((1 << n) + (1 << (n + 1)))) {
342 +                       fprintf(stderr, "%s: -Xdict-size is an unsupported "
343 +                               "value, dict-size must be storable in %s "
344 +                               "header\n", comp_name, comp_name);
345 +                       fprintf(stderr, "as either 2^n or as 2^n+2^(n+1).  "
346 +                               "Example dict-sizes are 75%%, 50%%, 37.5%%, "
347 +                               "25%%,\n");
348 +                       fprintf(stderr, "or 32K, 16K, 8K etc.\n");
349 +                       goto failed;
350 +               }
351 +
352 +       } else
353 +               /* No -Xdict-size specified, use defaults */
354 +               options.dict_size = block_size;
355 +
356 +       return 0;
357 +
358 +failed:
359 +       return -1;
360 +}
361 +
362 +static struct lzma_opts lzma_comp_opts;
363 +
364 +void *lzma_xz_dump_options(int block_size, int *size, int flags)
365 +{
366 +       /* No need to store default options */
367 +       if (options.preset == 6 &&
368 +                       options.extreme == 0 &&
369 +                       options.lc == LZMA_OPT_LC_DEFAULT &&
370 +                       options.lp == LZMA_OPT_LC_DEFAULT &&
371 +                       options.pb == LZMA_OPT_PB_DEFAULT &&
372 +                       options.fb == 0 &&
373 +                       options.dict_size == block_size &&
374 +                       flags == 0)
375 +               return NULL;
376 +       
377 +       *size = sizeof(struct lzma_opts);
378 +
379 +       lzma_comp_opts.flags |= flags;
380 +       
381 +       if (options.extreme)
382 +               lzma_comp_opts.flags |= LZMA_OPT_EXTREME;
383 +       
384 +       lzma_comp_opts.flags |= ((options.preset << LZMA_OPT_PRE_OFF) & LZMA_OPT_PRE_MASK);
385 +       
386 +       lzma_comp_opts.bit_opts = 
387 +                       ((options.lc << LZMA_OPT_LC_OFF) & LZMA_OPT_LC_MASK) |
388 +                       ((options.lp << LZMA_OPT_LP_OFF) & LZMA_OPT_LP_MASK) |
389 +                       ((options.pb << LZMA_OPT_PB_OFF) & LZMA_OPT_PB_MASK);
390 +       lzma_comp_opts.fb = options.fb;
391 +       lzma_comp_opts.dict_size = options.dict_size;
392 +       
393 +       SQUASHFS_INSWAP_LZMA_COMP_OPTS(&lzma_comp_opts);
394 +       
395 +       return &lzma_comp_opts;
396 +}
397 +
398 +int lzma_xz_extract_options(int block_size, void *buffer, int size, int lzmaver)
399 +{
400 +       if (size == 0) {
401 +               /* default options */
402 +               options.preset = 6;
403 +               options.extreme = 0;
404 +               options.lc = LZMA_OPT_LC_DEFAULT;
405 +               options.lp = LZMA_OPT_LC_DEFAULT;
406 +               options.pb = LZMA_OPT_PB_DEFAULT;
407 +               options.fb = LZMA_OPT_FB_DEFAULT;
408 +               options.dict_size = block_size;
409 +               options.flags = 0;
410 +       } else {
411 +               struct lzma_opts *comp_opts = buffer;
412 +               int n;
413 +               
414 +               if (size != sizeof(struct lzma_opts))
415 +                       goto failed;
416 +               
417 +               SQUASHFS_INSWAP_LZMA_COMP_OPTS(&comp_opts);
418 +               
419 +               options.flags = comp_opts->flags & LZMA_OPT_FLT_MASK;
420 +               options.preset  = (comp_opts->flags & LZMA_OPT_PRE_MASK) >> LZMA_OPT_PRE_OFF;
421 +               options.extreme = !!(comp_opts->flags & LZMA_OPT_EXTREME);
422 +
423 +               options.lc = (comp_opts->bit_opts & LZMA_OPT_LC_MASK) >> LZMA_OPT_LC_OFF;
424 +               options.lp = (comp_opts->bit_opts & LZMA_OPT_LP_MASK) >> LZMA_OPT_LP_OFF;
425 +               options.pb = (comp_opts->bit_opts & LZMA_OPT_PB_MASK) >> LZMA_OPT_PB_OFF;
426 +               options.fb = comp_opts->fb;
427 +               options.dict_size = comp_opts->dict_size;
428 +               
429 +               /* check that the LZMA bit options are in range */
430 +               if (options.lc < LZMA_OPT_LC_MIN || options.lc > LZMA_OPT_LC_MAX ||
431 +                       options.lp < LZMA_OPT_LP_MIN || options.lp > LZMA_OPT_LP_MAX ||
432 +                       options.pb < LZMA_OPT_PB_MIN || options.pb > LZMA_OPT_PB_MAX ||
433 +                       options.fb < LZMA_OPT_FB_MIN || options.fb > LZMA_OPT_FB_MAX)
434 +                       goto failed;
435 +
436 +               /*
437 +                * check that the dictionary size seems correct - the dictionary
438 +                * size should 2^n or 2^n+2^(n+1)
439 +                */
440 +               n = ffs(options.dict_size) - 1;
441 +               if(options.dict_size != (1 << n) &&
442 +                               options.dict_size != ((1 << n) + (1 << (n + 1))))
443 +                       goto failed;
444 +               
445 +       }
446 +       
447 +       return 0;
448 +
449 +failed:
450 +       fprintf(stderr, "%s: error reading stored compressor options from "
451 +               "filesystem!\n", lzmaver_str[lzmaver]);
452 +       return -1;      
453 +}
454 +
455 +void lzma_xz_usage(int lzmaver)
456 +{
457 +       fprintf(stderr, "\t  -Xpreset <preset>\n");
458 +       fprintf(stderr, "\t\tcompression preset (0-9, default 6)\n");
459 +       fprintf(stderr, "\t  -Xe\n");
460 +       fprintf(stderr, "\t\tTry to improve compression ratio by using more ");
461 +       fprintf(stderr, "CPU time.\n");
462 +       fprintf(stderr, "\t  -Xlc <lc>\n");
463 +       fprintf(stderr, "\t\tNumber of literal context bits (0-4, default 3)\n");
464 +       fprintf(stderr, "\t  -Xlp <lp>\n");
465 +       fprintf(stderr, "\t\tNumber of literal position bits (0-4, default 0)\n");
466 +       fprintf(stderr, "\t  -Xpb <pb>\n");
467 +       fprintf(stderr, "\t\tNumber of position bits (0-4, default 2)\n");
468 +       fprintf(stderr, "\t  -Xnice <nice>\n");
469 +       fprintf(stderr, "\t\tNice length of a match (5-273, default 64)\n");
470 +       fprintf(stderr, "\t  -Xdict-size <dict-size>\n");
471 +       fprintf(stderr, "\t\tUse <dict-size> as the %s dictionary size.  The",
472 +                       lzmaver == LZMA_OPT_LZMA ? "LZMA" : "XZ");
473 +       fprintf(stderr, " dictionary size\n\t\tcan be specified as a");
474 +       fprintf(stderr, " percentage of the block size, or as an\n\t\t");
475 +       fprintf(stderr, "absolute value.  The dictionary size must be less");
476 +       fprintf(stderr, " than or equal\n\t\tto the block size and %d bytes", 
477 +                       lzmaver == LZMA_OPT_LZMA ? 4096 : 8192);
478 +       fprintf(stderr, " or larger.  It must also be\n\t\tstorable in the lzma");
479 +       fprintf(stderr, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
480 +       fprintf(stderr, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
481 +       fprintf(stderr, " 32K, 16K, 8K\n\t\tetc.\n");
482 +       
483 +}
484 --- a/squashfs-tools/lzma_xz_wrapper.c
485 +++ b/squashfs-tools/lzma_xz_wrapper.c
486 @@ -27,6 +27,7 @@
487  
488  #include "squashfs_fs.h"
489  #include "compressor.h"
490 +#include "lzma_xz_options.h"
491  
492  #define LZMA_PROPS_SIZE 5
493  #define LZMA_UNCOMP_SIZE 8
494 @@ -38,13 +39,27 @@
495  static int lzma_compress(void *dummy, void *dest, void *src,  int size,
496         int block_size, int *error)
497  {
498 +       uint32_t preset;
499         unsigned char *d = (unsigned char *) dest;
500 +       struct lzma_xz_options *opts = lzma_xz_get_options();
501 +
502         lzma_options_lzma opt;
503         lzma_stream strm = LZMA_STREAM_INIT;
504         int res;
505  
506 -       lzma_lzma_preset(&opt, LZMA_OPTIONS);
507 -       opt.dict_size = block_size;
508 +       preset = opts->preset;
509 +
510 +       if (opts->extreme)
511 +               preset |= LZMA_PRESET_EXTREME;
512 +
513 +       lzma_lzma_preset(&opt, opts->preset);
514 +       opt.lc = opts->lc;
515 +       opt.lp = opts->lp;
516 +       opt.pb = opts->pb;
517 +       if (opts->fb)
518 +               opt.nice_len = opts->fb;
519 +
520 +       opt.dict_size = opts->dict_size;
521  
522         res = lzma_alone_encoder(&strm, &opt);
523         if(res != LZMA_OK) {
524 @@ -143,13 +158,45 @@ failed:
525         return -1;
526  }
527  
528 +static int lzma_options(char *argv[], int argc)
529 +{
530 +       return lzma_xz_options(argv, argc, LZMA_OPT_LZMA);
531 +}
532 +
533 +
534 +static int lzma_options_post(int block_size)
535 +{
536 +       return lzma_xz_options_post(block_size, LZMA_OPT_LZMA);
537 +}
538 +
539 +
540 +static void *lzma_dump_options(int block_size, int *size)
541 +{
542 +       return lzma_xz_dump_options(block_size, size, 0);
543 +}
544 +
545 +
546 +static int lzma_extract_options(int block_size, void *buffer, int size)
547 +{
548 +       return lzma_xz_extract_options(block_size, buffer, size, LZMA_OPT_LZMA);
549 +}
550 +
551 +
552 +void lzma_usage()
553 +{
554 +       lzma_xz_usage(LZMA_OPT_LZMA);
555 +}
556 +
557  
558  struct compressor lzma_comp_ops = {
559         .init = NULL,
560         .compress = lzma_compress,
561         .uncompress = lzma_uncompress,
562 -       .options = NULL,
563 -       .usage = NULL,
564 +       .options = lzma_options,
565 +       .options_post = lzma_options_post,
566 +       .dump_options = lzma_dump_options,
567 +       .extract_options = lzma_extract_options,
568 +       .usage = lzma_usage,
569         .id = LZMA_COMPRESSION,
570         .name = "lzma",
571         .supported = 1
572 --- a/squashfs-tools/xz_wrapper.h
573 +++ b/squashfs-tools/xz_wrapper.h
574 @@ -24,25 +24,6 @@
575   *
576   */
577  
578 -#ifndef linux
579 -#define __BYTE_ORDER BYTE_ORDER
580 -#define __BIG_ENDIAN BIG_ENDIAN
581 -#define __LITTLE_ENDIAN LITTLE_ENDIAN
582 -#else
583 -#include <endian.h>
584 -#endif
585 -
586 -#if __BYTE_ORDER == __BIG_ENDIAN
587 -extern unsigned int inswap_le32(unsigned int);
588 -
589 -#define SQUASHFS_INSWAP_COMP_OPTS(s) { \
590 -       (s)->dictionary_size = inswap_le32((s)->dictionary_size); \
591 -       (s)->flags = inswap_le32((s)->flags); \
592 -}
593 -#else
594 -#define SQUASHFS_INSWAP_COMP_OPTS(s)
595 -#endif
596 -
597  #define MEMLIMIT (32 * 1024 * 1024)
598  
599  struct bcj {
600 --- a/squashfs-tools/xz_wrapper.c
601 +++ b/squashfs-tools/xz_wrapper.c
602 @@ -30,6 +30,7 @@
603  #include "squashfs_fs.h"
604  #include "xz_wrapper.h"
605  #include "compressor.h"
606 +#include "lzma_xz_options.h"
607  
608  static struct bcj bcj[] = {
609         { "x86", LZMA_FILTER_X86, 0 },
610 @@ -41,22 +42,18 @@ static struct bcj bcj[] = {
611         { NULL, LZMA_VLI_UNKNOWN, 0 }
612  };
613  
614 -static struct comp_opts comp_opts;
615 -
616  static int filter_count = 1;
617 -static int dictionary_size = 0;
618 -static float dictionary_percent = 0;
619  
620  
621  static int xz_options(char *argv[], int argc)
622  {
623 -       int i;
624 -       char *name;
625 -
626         if(strcmp(argv[0], "-Xbcj") == 0) {
627 +               int i;
628 +               char *name;
629 +
630                 if(argc < 2) {
631                         fprintf(stderr, "xz: -Xbcj missing filter\n");
632 -                       goto failed;
633 +                       return -2;
634                 }
635  
636                 name = argv[1];
637 @@ -76,190 +73,50 @@ static int xz_options(char *argv[], int 
638                         }
639                         if(bcj[i].name == NULL) {
640                                 fprintf(stderr, "xz: -Xbcj unrecognised "
641 -                                       "filter\n");
642 -                               goto failed;
643 -                       }
644 -               }
645 -       
646 -               return 1;
647 -       } else if(strcmp(argv[0], "-Xdict-size") == 0) {
648 -               char *b;
649 -               float size;
650 -
651 -               if(argc < 2) {
652 -                       fprintf(stderr, "xz: -Xdict-size missing dict-size\n");
653 -                       goto failed;
654 -               }
655 -
656 -               size = strtof(argv[1], &b);
657 -               if(*b == '%') {
658 -                       if(size <= 0 || size > 100) {
659 -                               fprintf(stderr, "xz: -Xdict-size percentage "
660 -                                       "should be 0 < dict-size <= 100\n");
661 -                               goto failed;
662 -                       }
663 -
664 -                       dictionary_percent = size;
665 -                       dictionary_size = 0;
666 -               } else {
667 -                       if((float) ((int) size) != size) {
668 -                               fprintf(stderr, "xz: -Xdict-size can't be "
669 -                                       "fractional unless a percentage of the"
670 -                                       " block size\n");
671 -                               goto failed;
672 -                       }
673 -
674 -                       dictionary_percent = 0;
675 -                       dictionary_size = (int) size;
676 -
677 -                       if(*b == 'k' || *b == 'K')
678 -                               dictionary_size *= 1024;
679 -                       else if(*b == 'm' || *b == 'M')
680 -                               dictionary_size *= 1024 * 1024;
681 -                       else if(*b != '\0') {
682 -                               fprintf(stderr, "xz: -Xdict-size invalid "
683 -                                       "dict-size\n");
684 -                               goto failed;
685 +                                               "filter\n");
686 +                               return -2;
687                         }
688                 }
689 -
690                 return 1;
691 +       } else {
692 +               return lzma_xz_options(argv, argc, LZMA_OPT_XZ);
693         }
694 -
695 -       return -1;
696 -       
697 -failed:
698 -       return -2;
699  }
700  
701  
702  static int xz_options_post(int block_size)
703  {
704 -       /*
705 -        * if -Xdict-size has been specified use this to compute the datablock
706 -        * dictionary size
707 -        */
708 -       if(dictionary_size || dictionary_percent) {
709 -               int n;
710 -
711 -               if(dictionary_size) {
712 -                       if(dictionary_size > block_size) {
713 -                               fprintf(stderr, "xz: -Xdict-size is larger than"
714 -                               " block_size\n");
715 -                               goto failed;
716 -                       }
717 -               } else
718 -                       dictionary_size = block_size * dictionary_percent / 100;
719 -
720 -               if(dictionary_size < 8192) {
721 -                       fprintf(stderr, "xz: -Xdict-size should be 8192 bytes "
722 -                               "or larger\n");
723 -                       goto failed;
724 -               }
725 -
726 -               /*
727 -                * dictionary_size must be storable in xz header as either
728 -                * 2^n or as  2^n+2^(n+1)
729 -               */
730 -               n = ffs(dictionary_size) - 1;
731 -               if(dictionary_size != (1 << n) && 
732 -                               dictionary_size != ((1 << n) + (1 << (n + 1)))) {
733 -                       fprintf(stderr, "xz: -Xdict-size is an unsupported "
734 -                               "value, dict-size must be storable in xz "
735 -                               "header\n");
736 -                       fprintf(stderr, "as either 2^n or as 2^n+2^(n+1).  "
737 -                               "Example dict-sizes are 75%%, 50%%, 37.5%%, "
738 -                               "25%%,\n");
739 -                       fprintf(stderr, "or 32K, 16K, 8K etc.\n");
740 -                       goto failed;
741 -               }
742 -
743 -       } else
744 -               /* No -Xdict-size specified, use defaults */
745 -               dictionary_size = block_size;
746 -
747 -       return 0;
748 -
749 -failed:
750 -       return -1;
751 +       return lzma_xz_options_post(block_size, LZMA_OPT_XZ);
752  }
753  
754  
755  static void *xz_dump_options(int block_size, int *size)
756  {
757 -       int flags = 0, i;
758 -
759 -       /*
760 -        * don't store compressor specific options in file system if the
761 -        * default options are being used - no compressor options in the
762 -        * file system means the default options are always assumed
763 -        *
764 -        * Defaults are:
765 -        *  metadata dictionary size: SQUASHFS_METADATA_SIZE
766 -        *  datablock dictionary size: block_size
767 -        *  1 filter
768 -        */
769 -       if(dictionary_size == block_size && filter_count == 1)
770 -               return NULL;
771 +       int i, flags = 0;
772  
773         for(i = 0; bcj[i].name; i++)
774                 flags |= bcj[i].selected << i;
775  
776 -       comp_opts.dictionary_size = dictionary_size;
777 -       comp_opts.flags = flags;
778 -
779 -       SQUASHFS_INSWAP_COMP_OPTS(&comp_opts);
780 -
781 -       *size = sizeof(comp_opts);
782 -       return &comp_opts;
783 +       return lzma_xz_dump_options(block_size, size, flags);
784  }
785  
786  
787  static int xz_extract_options(int block_size, void *buffer, int size)
788  {
789 -       struct comp_opts *comp_opts = buffer;
790 -       int flags, i, n;
791 -
792 -       if(size == 0) {
793 -               /* set defaults */
794 -               dictionary_size = block_size;
795 -               flags = 0;
796 -       } else {
797 -               /* check passed comp opts struct is of the correct length */
798 -               if(size != sizeof(struct comp_opts))
799 -                       goto failed;
800 -                                        
801 -               SQUASHFS_INSWAP_COMP_OPTS(comp_opts);
802 -
803 -               dictionary_size = comp_opts->dictionary_size;
804 -               flags = comp_opts->flags;
805 -
806 -               /*
807 -                * check that the dictionary size seems correct - the dictionary
808 -                * size should 2^n or 2^n+2^(n+1)
809 -                */
810 -               n = ffs(dictionary_size) - 1;
811 -               if(dictionary_size != (1 << n) && 
812 -                               dictionary_size != ((1 << n) + (1 << (n + 1))))
813 -                       goto failed;
814 -       }
815 +       int ret = lzma_xz_extract_options(block_size, buffer, size, LZMA_OPT_XZ);
816  
817 -       filter_count = 1;
818 -       for(i = 0; bcj[i].name; i++) {
819 -               if((flags >> i) & 1) {
820 -                       bcj[i].selected = 1;
821 -                       filter_count ++;
822 -               } else
823 -                       bcj[i].selected = 0;
824 +       if (!ret) {
825 +               int i;
826 +               struct lzma_xz_options *opts = lzma_xz_get_options();
827 +               for(i = 0; bcj[i].name; i++) {
828 +                       if((opts->flags >> i) & 1) {
829 +                               bcj[i].selected = 1;
830 +                               filter_count ++;
831 +                       } else
832 +                               bcj[i].selected = 0;
833 +               }
834         }
835 -
836 -       return 0;
837 -
838 -failed:
839 -       fprintf(stderr, "xz: error reading stored compressor options from "
840 -               "filesystem!\n");
841 -
842 -       return -1;
843 +       return ret;
844  }
845  
846  
847 @@ -268,6 +125,7 @@ static int xz_init(void **strm, int bloc
848         int i, j, filters = datablock ? filter_count : 1;
849         struct filter *filter = malloc(filters * sizeof(struct filter));
850         struct xz_stream *stream;
851 +       struct lzma_xz_options *opts = lzma_xz_get_options();
852  
853         if(filter == NULL)
854                 goto failed;
855 @@ -281,7 +139,7 @@ static int xz_init(void **strm, int bloc
856  
857         memset(filter, 0, filters * sizeof(struct filter));
858  
859 -       stream->dictionary_size = datablock ? dictionary_size :
860 +       stream->dictionary_size = datablock ? opts->dict_size :
861                 SQUASHFS_METADATA_SIZE;
862  
863         filter[0].filter[0].id = LZMA_FILTER_LZMA2;
864 @@ -323,14 +181,25 @@ static int xz_compress(void *strm, void 
865          lzma_ret res = 0;
866         struct xz_stream *stream = strm;
867         struct filter *selected = NULL;
868 +       struct lzma_xz_options *opts = lzma_xz_get_options();
869  
870         stream->filter[0].buffer = dest;
871  
872         for(i = 0; i < stream->filters; i++) {
873 +               uint32_t preset = opts->preset;
874                 struct filter *filter = &stream->filter[i];
875  
876 -               if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT))
877 -                       goto failed;
878 +               if (opts->extreme)
879 +                       preset |= LZMA_PRESET_EXTREME;
880 +
881 +        if(lzma_lzma_preset(&stream->opt, preset))
882 +                       goto failed;
883 +
884 +        stream->opt.lc = opts->lc;
885 +       stream->opt.lp = opts->lp;
886 +       stream->opt.pb = opts->pb;
887 +       if (opts->fb)
888 +               stream->opt.nice_len = opts->fb;
889  
890                 stream->opt.dict_size = stream->dictionary_size;
891  
892 @@ -384,22 +253,13 @@ static int xz_uncompress(void *dest, voi
893  
894  void xz_usage()
895  {
896 +       lzma_xz_usage(LZMA_OPT_XZ);
897         fprintf(stderr, "\t  -Xbcj filter1,filter2,...,filterN\n");
898         fprintf(stderr, "\t\tCompress using filter1,filter2,...,filterN in");
899         fprintf(stderr, " turn\n\t\t(in addition to no filter), and choose");
900         fprintf(stderr, " the best compression.\n");
901         fprintf(stderr, "\t\tAvailable filters: x86, arm, armthumb,");
902         fprintf(stderr, " powerpc, sparc, ia64\n");
903 -       fprintf(stderr, "\t  -Xdict-size <dict-size>\n");
904 -       fprintf(stderr, "\t\tUse <dict-size> as the XZ dictionary size.  The");
905 -       fprintf(stderr, " dictionary size\n\t\tcan be specified as a");
906 -       fprintf(stderr, " percentage of the block size, or as an\n\t\t");
907 -       fprintf(stderr, "absolute value.  The dictionary size must be less");
908 -       fprintf(stderr, " than or equal\n\t\tto the block size and 8192 bytes");
909 -       fprintf(stderr, " or larger.  It must also be\n\t\tstorable in the xz");
910 -       fprintf(stderr, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
911 -       fprintf(stderr, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
912 -       fprintf(stderr, " 32K, 16K, 8K\n\t\tetc.\n");
913  }
914  
915  
916 --- a/squashfs-tools/Makefile
917 +++ b/squashfs-tools/Makefile
918 @@ -140,6 +140,8 @@ COMPRESSORS += xz
919  endif
920  
921  ifneq ($(LZMA_XZ_SUPPORT)$(XZ_SUPPORT),)
922 +MKSQUASHFS_OBJS += lzma_xz_options.o
923 +UNSQUASHFS_OBJS += lzma_xz_options.o
924  ifneq ($(LZMA_LIB),)
925  MKSQUASHFS_OBJS += $(LZMA_LIB)
926  UNSQUASHFS_OBJS += $(LZMA_LIB)