123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898 |
- From 5fb9fdfb8757fc9afb6318a3dcf9dce0a97de352 Mon Sep 17 00:00:00 2001
- From: Phillip Lougher <[email protected]>
- Date: Wed, 19 Apr 2023 18:35:53 +0100
- Subject: [PATCH] xz_wrapper: make new OpenWrt extended options non-default
- The reason why these options are being made non-default are
- described here:
- https://github.com/plougher/squashfs-tools/pull/218#issuecomment-1515197256
- The new options can be enabled by editing the Makefile or by defining
- XZ_EXTENDED_OPTIONS on the Make command line, e.g.
- % CONFIG=1 XZ_SUPPORT=1 XZ_EXTENDED_OPTIONS=1 make
- Signed-off-by: Phillip Lougher <[email protected]>
- ---
- squashfs-tools/Makefile | 12 +
- squashfs-tools/xz_wrapper.c | 117 +----
- squashfs-tools/xz_wrapper_extended.c | 664 +++++++++++++++++++++++++++
- 3 files changed, 679 insertions(+), 114 deletions(-)
- create mode 100644 squashfs-tools/xz_wrapper_extended.c
- --- a/squashfs-tools/Makefile
- +++ b/squashfs-tools/Makefile
- @@ -39,6 +39,10 @@ GZIP_SUPPORT = 1
- #
- #XZ_SUPPORT = 1
-
- +# Enable support for OpenWrt extended compression options by uncommenting
- +# next line. Do not do this unless you understand the implications.
- +#XZ_EXTENDED_OPTIONS = 1
- +
-
- ############ Building LZO support ##############
- #
- @@ -197,6 +201,7 @@ INSTALL_MANPAGES_DIR ?= $(INSTALL_PREFIX
- LZMA_XZ_SUPPORT ?= 0
- LZMA_SUPPORT ?= 0
- LZMA_DIR ?= ../../../../LZMA/lzma465
- +XZ_EXTENDED_OPTIONS ?= 0
- endif
-
-
- @@ -248,8 +253,13 @@ endif
-
- ifeq ($(XZ_SUPPORT),1)
- CFLAGS += -DXZ_SUPPORT
- +ifeq ($(XZ_EXTENDED_OPTIONS),1)
- +MKSQUASHFS_OBJS += xz_wrapper_extended.o
- +UNSQUASHFS_OBJS += xz_wrapper_extended.o
- +else
- MKSQUASHFS_OBJS += xz_wrapper.o
- UNSQUASHFS_OBJS += xz_wrapper.o
- +endif
- LIBS += -llzma
- COMPRESSORS += xz
- endif
- @@ -428,6 +438,8 @@ lz4_wrapper.o: lz4_wrapper.c squashfs_fs
-
- xz_wrapper.o: xz_wrapper.c squashfs_fs.h xz_wrapper.h compressor.h
-
- +xz_wrapper_extended.o: xz_wrapper_extended.c squashfs_fs.h xz_wrapper.h compressor.h
- +
- unsquashfs: $(UNSQUASHFS_OBJS)
- $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) $(UNSQUASHFS_OBJS) $(LIBS) -o $@
- ln -sf unsquashfs sqfscat
- --- a/squashfs-tools/xz_wrapper.c
- +++ b/squashfs-tools/xz_wrapper.c
- @@ -44,10 +44,7 @@ static struct bcj bcj[] = {
- static int filter_count = 1;
- static int dictionary_size = 0;
- static float dictionary_percent = 0;
- -static int preset = LZMA_PRESET_DEFAULT;
- -static int lc = -1;
- -static int lp = -1;
- -static int pb = -1;
- +
-
- /*
- * This function is called by the options parsing code in mksquashfs.c
- @@ -56,11 +53,6 @@ static int pb = -1;
- * Two specific options are supported:
- * -Xbcj
- * -Xdict-size
- - * -Xpreset
- - * -Xe
- - * -Xlc
- - * -Xlp
- - * -Xpb
- *
- * This function returns:
- * >=0 (number of additional args parsed) on success
- @@ -149,85 +141,6 @@ static int xz_options(char *argv[], int
- }
-
- return 1;
- - } else if(strcmp(argv[0], "-Xpreset") == 0) {
- - char *b;
- - long val;
- -
- - if(argc < 2) {
- - fprintf(stderr, "xz: -Xpreset missing preset-level "
- - "(valid value 0-9)\n");
- - goto failed;
- - }
- -
- - val = strtol(argv[1], &b, 10);
- - if (*b != '\0' || (int) val < 0 || (int) val & ~LZMA_PRESET_LEVEL_MASK) {
- - fprintf(stderr, "xz: -Xpreset can't be "
- - "negative or more than the max preset\n");
- - goto failed;
- - }
- -
- - preset &= ~LZMA_PRESET_LEVEL_MASK;
- - preset |= (int) val;
- -
- - return 1;
- - } else if(strcmp(argv[0], "-Xe") == 0) {
- - preset |= LZMA_PRESET_EXTREME;
- -
- - return 0;
- - } else if(strcmp(argv[0], "-Xlc") == 0) {
- - char *b;
- - long val;
- -
- - if(argc < 2) {
- - fprintf(stderr, "xz: -Xlc missing value\n");
- - goto failed;
- - }
- -
- - val = strtol(argv[1], &b, 10);
- - if (*b != '\0' || (int) val < LZMA_LCLP_MIN || (int) val > LZMA_LCLP_MAX) {
- - fprintf(stderr, "xz: -Xlc invalid value\n");
- - goto failed;
- - }
- -
- - lc = (int) val;
- -
- - return 1;
- - } else if(strcmp(argv[0], "-Xlp") == 0) {
- - char *b;
- - long val;
- -
- - if(argc < 2) {
- - fprintf(stderr, "xz: -Xlp missing value\n");
- - goto failed;
- - }
- -
- - val = strtol(argv[1], &b, 10);
- - if (*b != '\0' || (int) val < LZMA_LCLP_MIN || (int) val > LZMA_LCLP_MAX) {
- - fprintf(stderr, "xz: -Xlp invalid value\n");
- - goto failed;
- - }
- -
- - lp = (int) val;
- -
- - return 1;
- - } else if(strcmp(argv[0], "-Xpb") == 0) {
- - char *b;
- - long val;
- -
- - if(argc < 2) {
- - fprintf(stderr, "xz: -Xpb missing value\n");
- - goto failed;
- - }
- -
- - val = strtol(argv[1], &b, 10);
- - if (*b != '\0' || (int) val < LZMA_PB_MIN || (int) val > LZMA_PB_MAX) {
- - fprintf(stderr, "xz: -Xpb invalid value\n");
- - goto failed;
- - }
- -
- - pb = (int) val;
- -
- - return 1;
- }
-
- return -1;
- @@ -533,20 +446,11 @@ static int xz_compress(void *strm, void
- for(i = 0; i < stream->filters; i++) {
- struct filter *filter = &stream->filter[i];
-
- - if(lzma_lzma_preset(&stream->opt, preset))
- + if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT))
- goto failed;
-
- stream->opt.dict_size = stream->dictionary_size;
-
- - if (lc >= 0)
- - stream->opt.lc = lc;
- -
- - if (lp >= 0)
- - stream->opt.lp = lp;
- -
- - if (pb >= 0)
- - stream->opt.pb = pb;
- -
- filter->length = 0;
- res = lzma_stream_buffer_encode(filter->filter,
- LZMA_CHECK_CRC32, NULL, src, size, filter->buffer,
- @@ -617,28 +521,13 @@ static void xz_usage(FILE *stream)
- fprintf(stream, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
- fprintf(stream, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
- fprintf(stream, " 32K, 16K, 8K\n\t\tetc.\n");
- - fprintf(stream, "\t -Xpreset <preset-level>\n");
- - fprintf(stream, "\t\tUse <preset-value> as the custom preset to use");
- - fprintf(stream, " on compress.\n\t\t<preset-level> should be 0 .. 9");
- - fprintf(stream, " (default 6)\n");
- - fprintf(stream, "\t -Xe\n");
- - fprintf(stream, "\t\tEnable additional compression settings by passing");
- - fprintf(stream, " the EXTREME\n\t\tflag to the compression flags.\n");
- - fprintf(stream, "\t -Xlc <value>\n");
- - fprintf(stream, "\t -Xlp <value>\n");
- - fprintf(stream, "\t -Xpb <value>\n");
- }
-
-
- static int option_args(char *option)
- {
- if(strcmp(option, "-Xbcj") == 0 ||
- - strcmp(option, "-Xdict-size") == 0 ||
- - strcmp(option, "-Xpreset") == 0 ||
- - strcmp(option, "-Xe") == 0 ||
- - strcmp(option, "-Xlc") == 0 ||
- - strcmp(option, "-Xlp") == 0 ||
- - strcmp(option, "-Xpb") == 0)
- + strcmp(option, "-Xdict-size") == 0)
- return 1;
-
- return 0;
- --- /dev/null
- +++ b/squashfs-tools/xz_wrapper_extended.c
- @@ -0,0 +1,664 @@
- +/*
- + * Copyright (c) 2010, 2011, 2012, 2013, 2021, 2022
- + * Phillip Lougher <[email protected]>
- + *
- + * 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.
- + *
- + * xz_wrapper_extended.c
- + *
- + * Support for XZ (LZMA2) compression using XZ Utils liblzma
- + * http://tukaani.org/xz/
- + *
- + * This file supports OpenWrt extended XZ compression options.
- + */
- +
- +#include <stdio.h>
- +#include <string.h>
- +#include <stdlib.h>
- +#include <lzma.h>
- +
- +#include "squashfs_fs.h"
- +#include "xz_wrapper.h"
- +#include "compressor.h"
- +
- +static struct bcj bcj[] = {
- + { "x86", LZMA_FILTER_X86, 0 },
- + { "powerpc", LZMA_FILTER_POWERPC, 0 },
- + { "ia64", LZMA_FILTER_IA64, 0 },
- + { "arm", LZMA_FILTER_ARM, 0 },
- + { "armthumb", LZMA_FILTER_ARMTHUMB, 0 },
- + { "sparc", LZMA_FILTER_SPARC, 0 },
- + { NULL, LZMA_VLI_UNKNOWN, 0 }
- +};
- +
- +static int filter_count = 1;
- +static int dictionary_size = 0;
- +static float dictionary_percent = 0;
- +static int preset = LZMA_PRESET_DEFAULT;
- +static int lc = -1;
- +static int lp = -1;
- +static int pb = -1;
- +
- +/*
- + * This function is called by the options parsing code in mksquashfs.c
- + * to parse any -X compressor option.
- + *
- + * Two specific options are supported:
- + * -Xbcj
- + * -Xdict-size
- + * -Xpreset
- + * -Xe
- + * -Xlc
- + * -Xlp
- + * -Xpb
- + *
- + * This function returns:
- + * >=0 (number of additional args parsed) on success
- + * -1 if the option was unrecognised, or
- + * -2 if the option was recognised, but otherwise bad in
- + * some way (e.g. invalid parameter)
- + *
- + * Note: this function sets internal compressor state, but does not
- + * pass back the results of the parsing other than success/failure.
- + * The xz_dump_options() function is called later to get the options in
- + * a format suitable for writing to the filesystem.
- + */
- +static int xz_options(char *argv[], int argc)
- +{
- + int i;
- + char *name;
- +
- + if(strcmp(argv[0], "-Xbcj") == 0) {
- + if(argc < 2) {
- + fprintf(stderr, "xz: -Xbcj missing filter\n");
- + goto failed;
- + }
- +
- + name = argv[1];
- + while(name[0] != '\0') {
- + for(i = 0; bcj[i].name; i++) {
- + int n = strlen(bcj[i].name);
- + if((strncmp(name, bcj[i].name, n) == 0) &&
- + (name[n] == '\0' ||
- + name[n] == ',')) {
- + if(bcj[i].selected == 0) {
- + bcj[i].selected = 1;
- + filter_count++;
- + }
- + name += name[n] == ',' ? n + 1 : n;
- + break;
- + }
- + }
- + 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;
- + }
- + }
- +
- + return 1;
- + } else if(strcmp(argv[0], "-Xpreset") == 0) {
- + char *b;
- + long val;
- +
- + if(argc < 2) {
- + fprintf(stderr, "xz: -Xpreset missing preset-level "
- + "(valid value 0-9)\n");
- + goto failed;
- + }
- +
- + val = strtol(argv[1], &b, 10);
- + if (*b != '\0' || (int) val < 0 || (int) val & ~LZMA_PRESET_LEVEL_MASK) {
- + fprintf(stderr, "xz: -Xpreset can't be "
- + "negative or more than the max preset\n");
- + goto failed;
- + }
- +
- + preset &= ~LZMA_PRESET_LEVEL_MASK;
- + preset |= (int) val;
- +
- + return 1;
- + } else if(strcmp(argv[0], "-Xe") == 0) {
- + preset |= LZMA_PRESET_EXTREME;
- +
- + return 0;
- + } else if(strcmp(argv[0], "-Xlc") == 0) {
- + char *b;
- + long val;
- +
- + if(argc < 2) {
- + fprintf(stderr, "xz: -Xlc missing value\n");
- + goto failed;
- + }
- +
- + val = strtol(argv[1], &b, 10);
- + if (*b != '\0' || (int) val < LZMA_LCLP_MIN || (int) val > LZMA_LCLP_MAX) {
- + fprintf(stderr, "xz: -Xlc invalid value\n");
- + goto failed;
- + }
- +
- + lc = (int) val;
- +
- + return 1;
- + } else if(strcmp(argv[0], "-Xlp") == 0) {
- + char *b;
- + long val;
- +
- + if(argc < 2) {
- + fprintf(stderr, "xz: -Xlp missing value\n");
- + goto failed;
- + }
- +
- + val = strtol(argv[1], &b, 10);
- + if (*b != '\0' || (int) val < LZMA_LCLP_MIN || (int) val > LZMA_LCLP_MAX) {
- + fprintf(stderr, "xz: -Xlp invalid value\n");
- + goto failed;
- + }
- +
- + lp = (int) val;
- +
- + return 1;
- + } else if(strcmp(argv[0], "-Xpb") == 0) {
- + char *b;
- + long val;
- +
- + if(argc < 2) {
- + fprintf(stderr, "xz: -Xpb missing value\n");
- + goto failed;
- + }
- +
- + val = strtol(argv[1], &b, 10);
- + if (*b != '\0' || (int) val < LZMA_PB_MIN || (int) val > LZMA_PB_MAX) {
- + fprintf(stderr, "xz: -Xpb invalid value\n");
- + goto failed;
- + }
- +
- + pb = (int) val;
- +
- + return 1;
- + }
- +
- + return -1;
- +
- +failed:
- + return -2;
- +}
- +
- +
- +/*
- + * This function is called after all options have been parsed.
- + * It is used to do post-processing on the compressor options using
- + * values that were not expected to be known at option parse time.
- + *
- + * In this case block_size may not be known until after -Xdict-size has
- + * been processed (in the case where -b is specified after -Xdict-size)
- + *
- + * This function returns 0 on successful post processing, or
- + * -1 on error
- + */
- +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;
- +}
- +
- +
- +/*
- + * This function is called by mksquashfs to dump the parsed
- + * compressor options in a format suitable for writing to the
- + * compressor options field in the filesystem (stored immediately
- + * after the superblock).
- + *
- + * This function returns a pointer to the compression options structure
- + * to be stored (and the size), or NULL if there are no compression
- + * options
- + */
- +static void *xz_dump_options(int block_size, int *size)
- +{
- + static struct comp_opts comp_opts;
- + 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;
- +
- + 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;
- +}
- +
- +
- +/*
- + * This function is a helper specifically for the append mode of
- + * mksquashfs. Its purpose is to set the internal compressor state
- + * to the stored compressor options in the passed compressor options
- + * structure.
- + *
- + * In effect this function sets up the compressor options
- + * to the same state they were when the filesystem was originally
- + * generated, this is to ensure on appending, the compressor uses
- + * the same compression options that were used to generate the
- + * original filesystem.
- + *
- + * Note, even if there are no compressor options, this function is still
- + * called with an empty compressor structure (size == 0), to explicitly
- + * set the default options, this is to ensure any user supplied
- + * -X options on the appending mksquashfs command line are over-ridden
- + *
- + * This function returns 0 on sucessful extraction of options, and
- + * -1 on error
- + */
- +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;
- + }
- +
- + 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;
- + }
- +
- + return 0;
- +
- +failed:
- + fprintf(stderr, "xz: error reading stored compressor options from "
- + "filesystem!\n");
- +
- + return -1;
- +}
- +
- +
- +static void xz_display_options(void *buffer, int size)
- +{
- + struct comp_opts *comp_opts = buffer;
- + int dictionary_size, flags, printed;
- + int i, n;
- +
- + /* 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;
- +
- + printf("\tDictionary size %d\n", dictionary_size);
- +
- + printed = 0;
- + for(i = 0; bcj[i].name; i++) {
- + if((flags >> i) & 1) {
- + if(printed)
- + printf(", ");
- + else
- + printf("\tFilters selected: ");
- + printf("%s", bcj[i].name);
- + printed = 1;
- + }
- + }
- +
- + if(!printed)
- + printf("\tNo filters specified\n");
- + else
- + printf("\n");
- +
- + return;
- +
- +failed:
- + fprintf(stderr, "xz: error reading stored compressor options from "
- + "filesystem!\n");
- +}
- +
- +
- +/*
- + * This function is called by mksquashfs to initialise the
- + * compressor, before compress() is called.
- + *
- + * This function returns 0 on success, and
- + * -1 on error
- + */
- +static int xz_init(void **strm, int block_size, int datablock)
- +{
- + int i, j, filters = datablock ? filter_count : 1;
- + struct filter *filter = malloc(filters * sizeof(struct filter));
- + struct xz_stream *stream;
- +
- + if(filter == NULL)
- + goto failed;
- +
- + stream = *strm = malloc(sizeof(struct xz_stream));
- + if(stream == NULL)
- + goto failed2;
- +
- + stream->filter = filter;
- + stream->filters = filters;
- +
- + memset(filter, 0, filters * sizeof(struct filter));
- +
- + stream->dictionary_size = datablock ? dictionary_size :
- + SQUASHFS_METADATA_SIZE;
- +
- + filter[0].filter[0].id = LZMA_FILTER_LZMA2;
- + filter[0].filter[0].options = &stream->opt;
- + filter[0].filter[1].id = LZMA_VLI_UNKNOWN;
- +
- + for(i = 0, j = 1; datablock && bcj[i].name; i++) {
- + if(bcj[i].selected) {
- + filter[j].buffer = malloc(block_size);
- + if(filter[j].buffer == NULL)
- + goto failed3;
- + filter[j].filter[0].id = bcj[i].id;
- + filter[j].filter[1].id = LZMA_FILTER_LZMA2;
- + filter[j].filter[1].options = &stream->opt;
- + filter[j].filter[2].id = LZMA_VLI_UNKNOWN;
- + j++;
- + }
- + }
- +
- + return 0;
- +
- +failed3:
- + for(i = 1; i < filters; i++)
- + free(filter[i].buffer);
- + free(stream);
- +
- +failed2:
- + free(filter);
- +
- +failed:
- + return -1;
- +}
- +
- +
- +static int xz_compress(void *strm, void *dest, void *src, int size,
- + int block_size, int *error)
- +{
- + int i;
- + lzma_ret res = 0;
- + struct xz_stream *stream = strm;
- + struct filter *selected = NULL;
- +
- + stream->filter[0].buffer = dest;
- +
- + for(i = 0; i < stream->filters; i++) {
- + struct filter *filter = &stream->filter[i];
- +
- + if(lzma_lzma_preset(&stream->opt, preset))
- + goto failed;
- +
- + stream->opt.dict_size = stream->dictionary_size;
- +
- + if (lc >= 0)
- + stream->opt.lc = lc;
- +
- + if (lp >= 0)
- + stream->opt.lp = lp;
- +
- + if (pb >= 0)
- + stream->opt.pb = pb;
- +
- + filter->length = 0;
- + res = lzma_stream_buffer_encode(filter->filter,
- + LZMA_CHECK_CRC32, NULL, src, size, filter->buffer,
- + &filter->length, block_size);
- +
- + if(res == LZMA_OK) {
- + if(!selected || selected->length > filter->length)
- + selected = filter;
- + } else if(res != LZMA_BUF_ERROR)
- + goto failed;
- + }
- +
- + if(!selected)
- + /*
- + * Output buffer overflow. Return out of buffer space
- + */
- + return 0;
- +
- + if(selected->buffer != dest)
- + memcpy(dest, selected->buffer, selected->length);
- +
- + return (int) selected->length;
- +
- +failed:
- + /*
- + * All other errors return failure, with the compressor
- + * specific error code in *error
- + */
- + *error = res;
- + return -1;
- +}
- +
- +
- +static int xz_uncompress(void *dest, void *src, int size, int outsize,
- + int *error)
- +{
- + size_t src_pos = 0;
- + size_t dest_pos = 0;
- + uint64_t memlimit = MEMLIMIT;
- +
- + lzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL,
- + src, &src_pos, size, dest, &dest_pos, outsize);
- +
- + if(res == LZMA_OK && size == (int) src_pos)
- + return (int) dest_pos;
- + else {
- + *error = res;
- + return -1;
- + }
- +}
- +
- +
- +static void xz_usage(FILE *stream)
- +{
- + fprintf(stream, "\t -Xbcj filter1,filter2,...,filterN\n");
- + fprintf(stream, "\t\tCompress using filter1,filter2,...,filterN in");
- + fprintf(stream, " turn\n\t\t(in addition to no filter), and choose");
- + fprintf(stream, " the best compression.\n");
- + fprintf(stream, "\t\tAvailable filters: x86, arm, armthumb,");
- + fprintf(stream, " powerpc, sparc, ia64\n");
- + fprintf(stream, "\t -Xdict-size <dict-size>\n");
- + fprintf(stream, "\t\tUse <dict-size> as the XZ dictionary size. The");
- + fprintf(stream, " dictionary size\n\t\tcan be specified as a");
- + fprintf(stream, " percentage of the block size, or as an\n\t\t");
- + fprintf(stream, "absolute value. The dictionary size must be less");
- + fprintf(stream, " than or equal\n\t\tto the block size and 8192 bytes");
- + fprintf(stream, " or larger. It must also be\n\t\tstorable in the xz");
- + fprintf(stream, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
- + fprintf(stream, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
- + fprintf(stream, " 32K, 16K, 8K\n\t\tetc.\n");
- + fprintf(stream, "\t -Xpreset <preset-level>\n");
- + fprintf(stream, "\t\tUse <preset-value> as the custom preset to use");
- + fprintf(stream, " on compress.\n\t\t<preset-level> should be 0 .. 9");
- + fprintf(stream, " (default 6)\n");
- + fprintf(stream, "\t -Xe\n");
- + fprintf(stream, "\t\tEnable additional compression settings by passing");
- + fprintf(stream, " the EXTREME\n\t\tflag to the compression flags.\n");
- + fprintf(stream, "\t -Xlc <value>\n");
- + fprintf(stream, "\t -Xlp <value>\n");
- + fprintf(stream, "\t -Xpb <value>\n");
- +}
- +
- +
- +static int option_args(char *option)
- +{
- + if(strcmp(option, "-Xbcj") == 0 ||
- + strcmp(option, "-Xdict-size") == 0 ||
- + strcmp(option, "-Xpreset") == 0 ||
- + strcmp(option, "-Xe") == 0 ||
- + strcmp(option, "-Xlc") == 0 ||
- + strcmp(option, "-Xlp") == 0 ||
- + strcmp(option, "-Xpb") == 0)
- + return 1;
- +
- + return 0;
- +}
- +
- +
- +struct compressor xz_comp_ops = {
- + .init = xz_init,
- + .compress = xz_compress,
- + .uncompress = xz_uncompress,
- + .options = xz_options,
- + .options_post = xz_options_post,
- + .dump_options = xz_dump_options,
- + .extract_options = xz_extract_options,
- + .display_options = xz_display_options,
- + .usage = xz_usage,
- + .option_args = option_args,
- + .id = XZ_COMPRESSION,
- + .name = "xz",
- + .supported = 1
- +};
|