OpenWrt – Rev 4

Subversion Repositories:
Rev:
--- /dev/null
+++ b/squashfs-tools/lzma_xz_options.h
@@ -0,0 +1,115 @@
+#ifndef LZMA_XZ_OPTIONS_H
+#define LZMA_XZ_OPTIONS_H
+/*
+ * Copyright (c) 2011
+ * Jonas Gorski <jonas.gorski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * lzma_options.h
+ */
+
+#include <stdint.h>
+
+#ifndef linux
+#ifdef __FreeBSD__
+#include <machine/endian.h>
+#endif
+#define __BYTE_ORDER BYTE_ORDER
+#define __BIG_ENDIAN BIG_ENDIAN
+#define __LITTLE_ENDIAN LITTLE_ENDIAN
+#else
+#include <endian.h>
+#endif
+
+
+
+struct lzma_opts {
+       uint32_t dict_size;
+       uint32_t flags;
+#define LZMA_OPT_FLT_MASK      0xffff
+#define LZMA_OPT_PRE_OFF       16
+#define LZMA_OPT_PRE_MASK      (0xf << LZMA_OPT_PRE_OFF)
+#define LZMA_OPT_EXTREME       20      
+       uint16_t bit_opts;
+#define LZMA_OPT_LC_OFF                0
+#define LZMA_OPT_LC_MASK       (0x7 << LZMA_OPT_LC_OFF)
+#define LZMA_OPT_LP_OFF                3
+#define LZMA_OPT_LP_MASK       (0x7 << LZMA_OPT_LP_OFF)
+#define LZMA_OPT_PB_OFF                6
+#define LZMA_OPT_PB_MASK       (0x7 << LZMA_OPT_PB_OFF)
+       uint16_t fb;
+};
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+extern unsigned int inswap_le32(unsigned int);
+
+#define SQUASHFS_INSWAP_LZMA_COMP_OPTS(s) { \
+       (s)->flags = inswap_le32((s)->flags); \
+       (s)->bit_opts = inswap_le16((s)->bit_opts); \
+       (s)->fb = inswap_le16((s)->fb); \
+       (s)->dict_size = inswap_le32((s)->dict_size); \
+}
+#else
+#define SQUASHFS_INSWAP_LZMA_COMP_OPTS(s)
+#endif
+
+#define MEMLIMIT (32 * 1024 * 1024)
+
+#define LZMA_OPT_LC_MIN                0
+#define LZMA_OPT_LC_MAX                4
+#define LZMA_OPT_LC_DEFAULT    3
+
+#define LZMA_OPT_LP_MIN                0
+#define LZMA_OPT_LP_MAX                4
+#define LZMA_OPT_LP_DEFAULT    0
+
+#define LZMA_OPT_PB_MIN                0
+#define LZMA_OPT_PB_MAX                4
+#define LZMA_OPT_PB_DEFAULT    2
+
+#define LZMA_OPT_FB_MIN                5
+#define LZMA_OPT_FB_MAX                273
+#define LZMA_OPT_FB_DEFAULT    64
+
+enum {
+       LZMA_OPT_LZMA = 1,
+       LZMA_OPT_XZ
+};
+
+struct lzma_xz_options {
+       int preset;
+       int extreme;
+       int lc;
+       int lp;
+       int pb;
+       int fb;
+       int dict_size;
+       int flags;
+};
+
+struct lzma_xz_options *lzma_xz_get_options(void);
+
+int lzma_xz_options(char *argv[], int argc, int lzmaver);
+
+int lzma_xz_options_post(int block_size, int lzmaver);
+
+void *lzma_xz_dump_options(int block_size, int *size, int flags);
+
+int lzma_xz_extract_options(int block_size, void *buffer, int size, int lzmaver);
+
+void lzma_xz_usage(int lzmaver);
+
+#endif
--- /dev/null
+++ b/squashfs-tools/lzma_xz_options.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2011
+ * Jonas Gorski <jonas.gorski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * lzma_options.c
+ * 
+ * Common options for LZMA1 and 2 compressors. Based on xz_wrapper.c
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <lzma.h>
+
+#include "lzma_xz_options.h"
+
+static const char const *lzmaver_str[] = { "", "lzma", "xz" };
+
+static struct lzma_xz_options options = {
+       .flags          = 0,
+       .preset         = 6,
+       .extreme        = 0,
+       .lc             = LZMA_OPT_LC_DEFAULT,
+       .lp             = LZMA_OPT_LP_DEFAULT,
+       .pb             = LZMA_OPT_PB_DEFAULT,
+       .fb             = LZMA_OPT_FB_DEFAULT,
+       .dict_size      = 0,
+};
+
+static float lzma_dict_percent = 0;
+
+struct lzma_xz_options *lzma_xz_get_options(void)
+{
+       return &options;
+}
+
+
+int lzma_xz_options(char *argv[], int argc, int lzmaver)
+{
+       const char *comp_name = lzmaver_str[lzmaver];
+       
+       if(strcmp(argv[0], "-Xpreset") == 0) {
+               int preset;
+               
+               if(argc < 2) {
+                       fprintf(stderr, "%s: -Xpreset missing preset\n", comp_name);
+                       goto failed;
+               }
+               
+               preset = atoi(argv[1]);
+               
+               if (preset < 0 || preset > 9) {
+                       fprintf(stderr, "%s: -Xpreset invalid value\n", comp_name);
+                       goto failed;
+               }
+               options.preset = preset;
+               return 1;
+       } else if(strcmp(argv[0], "-Xe") == 0) {
+               options.extreme = 1;
+               return 0;
+       } else if(strcmp(argv[0], "-Xlc") == 0) {
+               int lc;
+               
+               if(argc < 2) {
+                       fprintf(stderr, "%s: -Xlc missing lc\n", comp_name);
+                       goto failed;
+               }
+               
+               lc = atoi(argv[1]);
+               
+               if (lc < LZMA_OPT_LC_MIN || lc > LZMA_OPT_LC_MAX) {
+                       fprintf(stderr, "%s: -Xlc invalid value\n", comp_name);
+                       goto failed;
+               }
+               options.lc = lc;
+               return 1;
+       } else if(strcmp(argv[0], "-Xlp") == 0) {
+               int lp;
+               
+               if(argc < 2) {
+                       fprintf(stderr, "%s: -Xlp missing lp\n", comp_name);
+                       goto failed;
+               }
+               
+               lp = atoi(argv[1]);
+               
+               if (lp < LZMA_OPT_LP_MIN || lp > LZMA_OPT_LP_MAX) {
+                       fprintf(stderr, "%s: -Xlp invalid value\n", comp_name);
+                       goto failed;
+               }
+               options.lp = lp;
+               return 1;
+       } else if(strcmp(argv[0], "-Xpb") == 0) {
+               int pb;
+               
+               if(argc < 2) {
+                       fprintf(stderr, "%s: -Xpb missing pb\n", comp_name);
+                       goto failed;
+               }
+               
+               pb = atoi(argv[1]);
+               
+               if (pb < LZMA_OPT_PB_MIN || pb > LZMA_OPT_PB_MAX) {
+                       fprintf(stderr, "%s: -Xbp invalid value\n", comp_name);
+                       goto failed;
+               }
+               options.pb = pb;
+               return 1;       
+       } else if(strcmp(argv[0], "-Xfb") == 0) {
+               int fb;
+               
+               if(argc < 2) {
+                       fprintf(stderr, "%s: -Xfb missing fb\n", comp_name);
+                       goto failed;
+               }
+               
+               fb = atoi(argv[1]);
+               
+               if (fb < LZMA_OPT_FB_MIN || fb > LZMA_OPT_FB_MAX) {
+                       fprintf(stderr, "%s: -Xfb invalid value\n", comp_name);
+                       goto failed;
+               }
+               options.fb = fb;
+               return 1;
+       } else if(strcmp(argv[0], "-Xdict-size") == 0) {
+               char *b;
+               float size;
+
+               if(argc < 2) {
+                       fprintf(stderr, "%s: -Xdict-size missing dict-size\n", comp_name);
+                       goto failed;
+               }
+
+               size = strtof(argv[1], &b);
+               if(*b == '%') {
+                       if(size <= 0 || size > 100) {
+                               fprintf(stderr, "%s: -Xdict-size percentage "
+                                       "should be 0 < dict-size <= 100\n", comp_name);
+                               goto failed;
+                       }
+
+                       lzma_dict_percent = size;
+                       options.dict_size = 0;
+               } else {
+                       if((float) ((int) size) != size) {
+                               fprintf(stderr, "%s: -Xdict-size can't be "
+                                       "fractional unless a percentage of the"
+                                       " block size\n", comp_name);
+                               goto failed;
+                       }
+
+                       lzma_dict_percent = 0;
+                       options.dict_size = (int) size;
+
+                       if(*b == 'k' || *b == 'K')
+                               options.dict_size *= 1024;
+                       else if(*b == 'm' || *b == 'M')
+                               options.dict_size *= 1024 * 1024;
+                       else if(*b != '\0') {
+                               fprintf(stderr, "%s: -Xdict-size invalid "
+                                       "dict-size\n", comp_name);
+                               goto failed;
+                       }
+               }
+
+               return 1;
+       }
+       
+       return -1;
+       
+failed:
+       return -2;
+
+}
+
+int lzma_xz_options_post(int block_size, int lzmaver)
+{
+       const char *comp_name = lzmaver_str[lzmaver];
+       /*
+        * if -Xdict-size has been specified use this to compute the datablock
+        * dictionary size
+        */
+       if(options.dict_size || lzma_dict_percent) {
+               int dict_size_min = (lzmaver == 1 ? 4096 : 8192);
+               int n;
+
+               if(options.dict_size) {
+                       if(options.dict_size > block_size) {
+                               fprintf(stderr, "%s: -Xdict-size is larger than"
+                               " block_size\n", comp_name);
+                               goto failed;
+                       }
+               } else
+                       options.dict_size = block_size * lzma_dict_percent / 100;
+
+               if(options.dict_size < dict_size_min) {
+                       fprintf(stderr, "%s: -Xdict-size should be %i bytes "
+                               "or larger\n", comp_name, dict_size_min);
+                       goto failed;
+               }
+
+               /*
+                * dictionary_size must be storable in xz header as either
+                * 2^n or as  2^n+2^(n+1)
+               */
+               n = ffs(options.dict_size) - 1;
+               if(options.dict_size != (1 << n) &&
+                               options.dict_size != ((1 << n) + (1 << (n + 1)))) {
+                       fprintf(stderr, "%s: -Xdict-size is an unsupported "
+                               "value, dict-size must be storable in %s "
+                               "header\n", comp_name, comp_name);
+                       fprintf(stderr, "as either 2^n or as 2^n+2^(n+1).  "
+                               "Example dict-sizes are 75%%, 50%%, 37.5%%, "
+                               "25%%,\n");
+                       fprintf(stderr, "or 32K, 16K, 8K etc.\n");
+                       goto failed;
+               }
+
+       } else
+               /* No -Xdict-size specified, use defaults */
+               options.dict_size = block_size;
+
+       return 0;
+
+failed:
+       return -1;
+}
+
+static struct lzma_opts lzma_comp_opts;
+
+void *lzma_xz_dump_options(int block_size, int *size, int flags)
+{
+       /* No need to store default options */
+       if (options.preset == 6 &&
+                       options.extreme == 0 &&
+                       options.lc == LZMA_OPT_LC_DEFAULT &&
+                       options.lp == LZMA_OPT_LC_DEFAULT &&
+                       options.pb == LZMA_OPT_PB_DEFAULT &&
+                       options.fb == 0 &&
+                       options.dict_size == block_size &&
+                       flags == 0)
+               return NULL;
+       
+       *size = sizeof(struct lzma_opts);
+
+       lzma_comp_opts.flags |= flags;
+       
+       if (options.extreme)
+               lzma_comp_opts.flags |= LZMA_OPT_EXTREME;
+       
+       lzma_comp_opts.flags |= ((options.preset << LZMA_OPT_PRE_OFF) & LZMA_OPT_PRE_MASK);
+       
+       lzma_comp_opts.bit_opts = 
+                       ((options.lc << LZMA_OPT_LC_OFF) & LZMA_OPT_LC_MASK) |
+                       ((options.lp << LZMA_OPT_LP_OFF) & LZMA_OPT_LP_MASK) |
+                       ((options.pb << LZMA_OPT_PB_OFF) & LZMA_OPT_PB_MASK);
+       lzma_comp_opts.fb = options.fb;
+       lzma_comp_opts.dict_size = options.dict_size;
+       
+       SQUASHFS_INSWAP_LZMA_COMP_OPTS(&lzma_comp_opts);
+       
+       return &lzma_comp_opts;
+}
+
+int lzma_xz_extract_options(int block_size, void *buffer, int size, int lzmaver)
+{
+       if (size == 0) {
+               /* default options */
+               options.preset = 6;
+               options.extreme = 0;
+               options.lc = LZMA_OPT_LC_DEFAULT;
+               options.lp = LZMA_OPT_LC_DEFAULT;
+               options.pb = LZMA_OPT_PB_DEFAULT;
+               options.fb = LZMA_OPT_FB_DEFAULT;
+               options.dict_size = block_size;
+               options.flags = 0;
+       } else {
+               struct lzma_opts *comp_opts = buffer;
+               int n;
+               
+               if (size != sizeof(struct lzma_opts))
+                       goto failed;
+               
+               SQUASHFS_INSWAP_LZMA_COMP_OPTS(comp_opts);
+               
+               options.flags = comp_opts->flags & LZMA_OPT_FLT_MASK;
+               options.preset  = (comp_opts->flags & LZMA_OPT_PRE_MASK) >> LZMA_OPT_PRE_OFF;
+               options.extreme = !!(comp_opts->flags & LZMA_OPT_EXTREME);
+
+               options.lc = (comp_opts->bit_opts & LZMA_OPT_LC_MASK) >> LZMA_OPT_LC_OFF;
+               options.lp = (comp_opts->bit_opts & LZMA_OPT_LP_MASK) >> LZMA_OPT_LP_OFF;
+               options.pb = (comp_opts->bit_opts & LZMA_OPT_PB_MASK) >> LZMA_OPT_PB_OFF;
+               options.fb = comp_opts->fb;
+               options.dict_size = comp_opts->dict_size;
+               
+               /* check that the LZMA bit options are in range */
+               if (options.lc < LZMA_OPT_LC_MIN || options.lc > LZMA_OPT_LC_MAX ||
+                       options.lp < LZMA_OPT_LP_MIN || options.lp > LZMA_OPT_LP_MAX ||
+                       options.pb < LZMA_OPT_PB_MIN || options.pb > LZMA_OPT_PB_MAX ||
+                       options.fb < LZMA_OPT_FB_MIN || options.fb > LZMA_OPT_FB_MAX)
+                       goto failed;
+
+               /*
+                * check that the dictionary size seems correct - the dictionary
+                * size should 2^n or 2^n+2^(n+1)
+                */
+               n = ffs(options.dict_size) - 1;
+               if(options.dict_size != (1 << n) &&
+                               options.dict_size != ((1 << n) + (1 << (n + 1))))
+                       goto failed;
+               
+       }
+       
+       return 0;
+
+failed:
+       fprintf(stderr, "%s: error reading stored compressor options from "
+               "filesystem!\n", lzmaver_str[lzmaver]);
+       return -1;      
+}
+
+void lzma_xz_usage(int lzmaver)
+{
+       fprintf(stderr, "\t  -Xpreset <preset>\n");
+       fprintf(stderr, "\t\tcompression preset (0-9, default 6)\n");
+       fprintf(stderr, "\t  -Xe\n");
+       fprintf(stderr, "\t\tTry to improve compression ratio by using more ");
+       fprintf(stderr, "CPU time.\n");
+       fprintf(stderr, "\t  -Xlc <lc>\n");
+       fprintf(stderr, "\t\tNumber of literal context bits (0-4, default 3)\n");
+       fprintf(stderr, "\t  -Xlp <lp>\n");
+       fprintf(stderr, "\t\tNumber of literal position bits (0-4, default 0)\n");
+       fprintf(stderr, "\t  -Xpb <pb>\n");
+       fprintf(stderr, "\t\tNumber of position bits (0-4, default 2)\n");
+       fprintf(stderr, "\t  -Xnice <nice>\n");
+       fprintf(stderr, "\t\tNice length of a match (5-273, default 64)\n");
+       fprintf(stderr, "\t  -Xdict-size <dict-size>\n");
+       fprintf(stderr, "\t\tUse <dict-size> as the %s dictionary size.  The",
+                       lzmaver == LZMA_OPT_LZMA ? "LZMA" : "XZ");
+       fprintf(stderr, " dictionary size\n\t\tcan be specified as a");
+       fprintf(stderr, " percentage of the block size, or as an\n\t\t");
+       fprintf(stderr, "absolute value.  The dictionary size must be less");
+       fprintf(stderr, " than or equal\n\t\tto the block size and %d bytes", 
+                       lzmaver == LZMA_OPT_LZMA ? 4096 : 8192);
+       fprintf(stderr, " or larger.  It must also be\n\t\tstorable in the lzma");
+       fprintf(stderr, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
+       fprintf(stderr, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
+       fprintf(stderr, " 32K, 16K, 8K\n\t\tetc.\n");
+       
+}
--- a/squashfs-tools/lzma_xz_wrapper.c
+++ b/squashfs-tools/lzma_xz_wrapper.c
@@ -27,6 +27,7 @@
 
 #include "squashfs_fs.h"
 #include "compressor.h"
+#include "lzma_xz_options.h"
 
 #define LZMA_PROPS_SIZE 5
 #define LZMA_UNCOMP_SIZE 8
@@ -38,13 +39,27 @@
 static int lzma_compress(void *dummy, void *dest, void *src,  int size,
        int block_size, int *error)
 {
+       uint32_t preset;
        unsigned char *d = (unsigned char *) dest;
+       struct lzma_xz_options *opts = lzma_xz_get_options();
+
        lzma_options_lzma opt;
        lzma_stream strm = LZMA_STREAM_INIT;
        int res;
 
-       lzma_lzma_preset(&opt, LZMA_OPTIONS);
-       opt.dict_size = block_size;
+       preset = opts->preset;
+
+       if (opts->extreme)
+               preset |= LZMA_PRESET_EXTREME;
+
+       lzma_lzma_preset(&opt, opts->preset);
+       opt.lc = opts->lc;
+       opt.lp = opts->lp;
+       opt.pb = opts->pb;
+       if (opts->fb)
+               opt.nice_len = opts->fb;
+
+       opt.dict_size = opts->dict_size;
 
        res = lzma_alone_encoder(&strm, &opt);
        if(res != LZMA_OK) {
@@ -143,13 +158,45 @@ failed:
        return -1;
 }
 
+static int lzma_options(char *argv[], int argc)
+{
+       return lzma_xz_options(argv, argc, LZMA_OPT_LZMA);
+}
+
+
+static int lzma_options_post(int block_size)
+{
+       return lzma_xz_options_post(block_size, LZMA_OPT_LZMA);
+}
+
+
+static void *lzma_dump_options(int block_size, int *size)
+{
+       return lzma_xz_dump_options(block_size, size, 0);
+}
+
+
+static int lzma_extract_options(int block_size, void *buffer, int size)
+{
+       return lzma_xz_extract_options(block_size, buffer, size, LZMA_OPT_LZMA);
+}
+
+
+void lzma_usage()
+{
+       lzma_xz_usage(LZMA_OPT_LZMA);
+}
+
 
 struct compressor lzma_comp_ops = {
        .init = NULL,
        .compress = lzma_compress,
        .uncompress = lzma_uncompress,
-       .options = NULL,
-       .usage = NULL,
+       .options = lzma_options,
+       .options_post = lzma_options_post,
+       .dump_options = lzma_dump_options,
+       .extract_options = lzma_extract_options,
+       .usage = lzma_usage,
        .id = LZMA_COMPRESSION,
        .name = "lzma",
        .supported = 1
--- a/squashfs-tools/xz_wrapper.h
+++ b/squashfs-tools/xz_wrapper.h
@@ -24,25 +24,6 @@
  *
  */
 
-#ifndef linux
-#define __BYTE_ORDER BYTE_ORDER
-#define __BIG_ENDIAN BIG_ENDIAN
-#define __LITTLE_ENDIAN LITTLE_ENDIAN
-#else
-#include <endian.h>
-#endif
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-extern unsigned int inswap_le32(unsigned int);
-
-#define SQUASHFS_INSWAP_COMP_OPTS(s) { \
-       (s)->dictionary_size = inswap_le32((s)->dictionary_size); \
-       (s)->flags = inswap_le32((s)->flags); \
-}
-#else
-#define SQUASHFS_INSWAP_COMP_OPTS(s)
-#endif
-
 #define MEMLIMIT (32 * 1024 * 1024)
 
 struct bcj {
--- a/squashfs-tools/xz_wrapper.c
+++ b/squashfs-tools/xz_wrapper.c
@@ -30,6 +30,7 @@
 #include "squashfs_fs.h"
 #include "xz_wrapper.h"
 #include "compressor.h"
+#include "lzma_xz_options.h"
 
 static struct bcj bcj[] = {
        { "x86", LZMA_FILTER_X86, 0 },
@@ -41,22 +42,18 @@ static struct bcj bcj[] = {
        { NULL, LZMA_VLI_UNKNOWN, 0 }
 };
 
-static struct comp_opts comp_opts;
-
 static int filter_count = 1;
-static int dictionary_size = 0;
-static float dictionary_percent = 0;
 
 
 static int xz_options(char *argv[], int argc)
 {
-       int i;
-       char *name;
-
        if(strcmp(argv[0], "-Xbcj") == 0) {
+               int i;
+               char *name;
+
                if(argc < 2) {
                        fprintf(stderr, "xz: -Xbcj missing filter\n");
-                       goto failed;
+                       return -2;
                }
 
                name = argv[1];
@@ -76,190 +73,50 @@ static int xz_options(char *argv[], int
                        }
                        if(bcj[i].name == NULL) {
                                fprintf(stderr, "xz: -Xbcj unrecognised "
-                                       "filter\n");
-                               goto failed;
-                       }
-               }
-       
-               return 1;
-       } else if(strcmp(argv[0], "-Xdict-size") == 0) {
-               char *b;
-               float size;
-
-               if(argc < 2) {
-                       fprintf(stderr, "xz: -Xdict-size missing dict-size\n");
-                       goto failed;
-               }
-
-               size = strtof(argv[1], &b);
-               if(*b == '%') {
-                       if(size <= 0 || size > 100) {
-                               fprintf(stderr, "xz: -Xdict-size percentage "
-                                       "should be 0 < dict-size <= 100\n");
-                               goto failed;
-                       }
-
-                       dictionary_percent = size;
-                       dictionary_size = 0;
-               } else {
-                       if((float) ((int) size) != size) {
-                               fprintf(stderr, "xz: -Xdict-size can't be "
-                                       "fractional unless a percentage of the"
-                                       " block size\n");
-                               goto failed;
-                       }
-
-                       dictionary_percent = 0;
-                       dictionary_size = (int) size;
-
-                       if(*b == 'k' || *b == 'K')
-                               dictionary_size *= 1024;
-                       else if(*b == 'm' || *b == 'M')
-                               dictionary_size *= 1024 * 1024;
-                       else if(*b != '\0') {
-                               fprintf(stderr, "xz: -Xdict-size invalid "
-                                       "dict-size\n");
-                               goto failed;
+                                               "filter\n");
+                               return -2;
                        }
                }
-
                return 1;
+       } else {
+               return lzma_xz_options(argv, argc, LZMA_OPT_XZ);
        }
-
-       return -1;
-       
-failed:
-       return -2;
 }
 
 
 static int xz_options_post(int block_size)
 {
-       /*
-        * if -Xdict-size has been specified use this to compute the datablock
-        * dictionary size
-        */
-       if(dictionary_size || dictionary_percent) {
-               int n;
-
-               if(dictionary_size) {
-                       if(dictionary_size > block_size) {
-                               fprintf(stderr, "xz: -Xdict-size is larger than"
-                               " block_size\n");
-                               goto failed;
-                       }
-               } else
-                       dictionary_size = block_size * dictionary_percent / 100;
-
-               if(dictionary_size < 8192) {
-                       fprintf(stderr, "xz: -Xdict-size should be 8192 bytes "
-                               "or larger\n");
-                       goto failed;
-               }
-
-               /*
-                * dictionary_size must be storable in xz header as either
-                * 2^n or as  2^n+2^(n+1)
-               */
-               n = ffs(dictionary_size) - 1;
-               if(dictionary_size != (1 << n) && 
-                               dictionary_size != ((1 << n) + (1 << (n + 1)))) {
-                       fprintf(stderr, "xz: -Xdict-size is an unsupported "
-                               "value, dict-size must be storable in xz "
-                               "header\n");
-                       fprintf(stderr, "as either 2^n or as 2^n+2^(n+1).  "
-                               "Example dict-sizes are 75%%, 50%%, 37.5%%, "
-                               "25%%,\n");
-                       fprintf(stderr, "or 32K, 16K, 8K etc.\n");
-                       goto failed;
-               }
-
-       } else
-               /* No -Xdict-size specified, use defaults */
-               dictionary_size = block_size;
-
-       return 0;
-
-failed:
-       return -1;
+       return lzma_xz_options_post(block_size, LZMA_OPT_XZ);
 }
 
 
 static void *xz_dump_options(int block_size, int *size)
 {
-       int flags = 0, i;
-
-       /*
-        * don't store compressor specific options in file system if the
-        * default options are being used - no compressor options in the
-        * file system means the default options are always assumed
-        *
-        * Defaults are:
-        *  metadata dictionary size: SQUASHFS_METADATA_SIZE
-        *  datablock dictionary size: block_size
-        *  1 filter
-        */
-       if(dictionary_size == block_size && filter_count == 1)
-               return NULL;
+       int i, flags = 0;
 
        for(i = 0; bcj[i].name; i++)
                flags |= bcj[i].selected << i;
 
-       comp_opts.dictionary_size = dictionary_size;
-       comp_opts.flags = flags;
-
-       SQUASHFS_INSWAP_COMP_OPTS(&comp_opts);
-
-       *size = sizeof(comp_opts);
-       return &comp_opts;
+       return lzma_xz_dump_options(block_size, size, flags);
 }
 
 
 static int xz_extract_options(int block_size, void *buffer, int size)
 {
-       struct comp_opts *comp_opts = buffer;
-       int flags, i, n;
-
-       if(size == 0) {
-               /* set defaults */
-               dictionary_size = block_size;
-               flags = 0;
-       } else {
-               /* check passed comp opts struct is of the correct length */
-               if(size != sizeof(struct comp_opts))
-                       goto failed;
-                                        
-               SQUASHFS_INSWAP_COMP_OPTS(comp_opts);
-
-               dictionary_size = comp_opts->dictionary_size;
-               flags = comp_opts->flags;
-
-               /*
-                * check that the dictionary size seems correct - the dictionary
-                * size should 2^n or 2^n+2^(n+1)
-                */
-               n = ffs(dictionary_size) - 1;
-               if(dictionary_size != (1 << n) && 
-                               dictionary_size != ((1 << n) + (1 << (n + 1))))
-                       goto failed;
-       }
+       int ret = lzma_xz_extract_options(block_size, buffer, size, LZMA_OPT_XZ);
 
-       filter_count = 1;
-       for(i = 0; bcj[i].name; i++) {
-               if((flags >> i) & 1) {
-                       bcj[i].selected = 1;
-                       filter_count ++;
-               } else
-                       bcj[i].selected = 0;
+       if (!ret) {
+               int i;
+               struct lzma_xz_options *opts = lzma_xz_get_options();
+               for(i = 0; bcj[i].name; i++) {
+                       if((opts->flags >> i) & 1) {
+                               bcj[i].selected = 1;
+                               filter_count ++;
+                       } else
+                               bcj[i].selected = 0;
+               }
        }
-
-       return 0;
-
-failed:
-       fprintf(stderr, "xz: error reading stored compressor options from "
-               "filesystem!\n");
-
-       return -1;
+       return ret;
 }
 
 
@@ -268,6 +125,7 @@ static int xz_init(void **strm, int bloc
        int i, j, filters = datablock ? filter_count : 1;
        struct filter *filter = malloc(filters * sizeof(struct filter));
        struct xz_stream *stream;
+       struct lzma_xz_options *opts = lzma_xz_get_options();
 
        if(filter == NULL)
                goto failed;
@@ -281,7 +139,7 @@ static int xz_init(void **strm, int bloc
 
        memset(filter, 0, filters * sizeof(struct filter));
 
-       stream->dictionary_size = datablock ? dictionary_size :
+       stream->dictionary_size = datablock ? opts->dict_size :
                SQUASHFS_METADATA_SIZE;
 
        filter[0].filter[0].id = LZMA_FILTER_LZMA2;
@@ -323,14 +181,25 @@ static int xz_compress(void *strm, void
         lzma_ret res = 0;
        struct xz_stream *stream = strm;
        struct filter *selected = NULL;
+       struct lzma_xz_options *opts = lzma_xz_get_options();
 
        stream->filter[0].buffer = dest;
 
        for(i = 0; i < stream->filters; i++) {
+               uint32_t preset = opts->preset;
                struct filter *filter = &stream->filter[i];
 
-               if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT))
-                       goto failed;
+               if (opts->extreme)
+                       preset |= LZMA_PRESET_EXTREME;
+
+        if(lzma_lzma_preset(&stream->opt, preset))
+                       goto failed;
+
+        stream->opt.lc = opts->lc;
+       stream->opt.lp = opts->lp;
+       stream->opt.pb = opts->pb;
+       if (opts->fb)
+               stream->opt.nice_len = opts->fb;
 
                stream->opt.dict_size = stream->dictionary_size;
 
@@ -384,22 +253,13 @@ static int xz_uncompress(void *dest, voi
 
 void xz_usage()
 {
+       lzma_xz_usage(LZMA_OPT_XZ);
        fprintf(stderr, "\t  -Xbcj filter1,filter2,...,filterN\n");
        fprintf(stderr, "\t\tCompress using filter1,filter2,...,filterN in");
        fprintf(stderr, " turn\n\t\t(in addition to no filter), and choose");
        fprintf(stderr, " the best compression.\n");
        fprintf(stderr, "\t\tAvailable filters: x86, arm, armthumb,");
        fprintf(stderr, " powerpc, sparc, ia64\n");
-       fprintf(stderr, "\t  -Xdict-size <dict-size>\n");
-       fprintf(stderr, "\t\tUse <dict-size> as the XZ dictionary size.  The");
-       fprintf(stderr, " dictionary size\n\t\tcan be specified as a");
-       fprintf(stderr, " percentage of the block size, or as an\n\t\t");
-       fprintf(stderr, "absolute value.  The dictionary size must be less");
-       fprintf(stderr, " than or equal\n\t\tto the block size and 8192 bytes");
-       fprintf(stderr, " or larger.  It must also be\n\t\tstorable in the xz");
-       fprintf(stderr, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
-       fprintf(stderr, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
-       fprintf(stderr, " 32K, 16K, 8K\n\t\tetc.\n");
 }
 
 
--- a/squashfs-tools/Makefile
+++ b/squashfs-tools/Makefile
@@ -140,6 +140,8 @@ COMPRESSORS += xz
 endif
 
 ifneq ($(LZMA_XZ_SUPPORT)$(XZ_SUPPORT),)
+MKSQUASHFS_OBJS += lzma_xz_options.o
+UNSQUASHFS_OBJS += lzma_xz_options.o
 ifneq ($(LZMA_LIB),)
 MKSQUASHFS_OBJS += $(LZMA_LIB)
 UNSQUASHFS_OBJS += $(LZMA_LIB)