--- /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 + * + * 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 + +#ifndef linux +#ifdef __FreeBSD__ +#include +#endif +#define __BYTE_ORDER BYTE_ORDER +#define __BIG_ENDIAN BIG_ENDIAN +#define __LITTLE_ENDIAN LITTLE_ENDIAN +#else +#include +#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 + * + * 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 +#include +#include + +#include + +#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 \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 \n"); + fprintf(stderr, "\t\tNumber of literal context bits (0-4, default 3)\n"); + fprintf(stderr, "\t -Xlp \n"); + fprintf(stderr, "\t\tNumber of literal position bits (0-4, default 0)\n"); + fprintf(stderr, "\t -Xpb \n"); + fprintf(stderr, "\t\tNumber of position bits (0-4, default 2)\n"); + fprintf(stderr, "\t -Xnice \n"); + fprintf(stderr, "\t\tNice length of a match (5-273, default 64)\n"); + fprintf(stderr, "\t -Xdict-size \n"); + fprintf(stderr, "\t\tUse 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 -#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 \n"); - fprintf(stderr, "\t\tUse 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)