# HG changeset patch # User Christopher Rogers # Date 1292362486 0 # Node ID 13e4d4e6fcc194a9e044fdde4b5d45c6b5bcbde3 # Parent f99ea44cc9f61f3ce2affa7c50a9fb67ab288431 Add xz to squashfs tools. diff -r f99ea44cc9f6 -r 13e4d4e6fcc1 squashfs/receipt --- a/squashfs/receipt Tue Dec 14 21:27:30 2010 +0000 +++ b/squashfs/receipt Tue Dec 14 21:34:46 2010 +0000 @@ -16,9 +16,10 @@ compile_rules() { mv ${PACKAGE}${VERSION} $src 2> /dev/null - + cd $src + patch -Np1 -i ../stuff/xz.patch cd $src/squashfs-tools - sed -i 's|#XZ_SUPPORT = 1|XZ_SUPPORT = 1|g' Makefile + #sed -i 's|#XZ_SUPPORT = 1|XZ_SUPPORT = 1|g' Makefile mkdir -p ../_pkg/usr/sbin ../_pkg/sbin make || return 1 cp mksquashfs ../_pkg/usr/sbin diff -r f99ea44cc9f6 -r 13e4d4e6fcc1 squashfs/stuff/xz.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/squashfs/stuff/xz.patch Tue Dec 14 21:34:46 2010 +0000 @@ -0,0 +1,1432 @@ +diff -r 2ab2996036dd squashfs-tools/Makefile +--- a/squashfs-tools/Makefile Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/Makefile Tue Dec 14 14:18:11 2010 +0000 +@@ -20,20 +20,33 @@ + + ########### Building LZMA support ############# + # +-# Both XZ Utils liblzma (http://tukaani.org/xz/) and LZMA SDK ++# LZMA1 compression. ++# ++# Both XZ Utils liblzma (http://tukaani.org/xz/) and LZMA SDK + # (http://www.7-zip.org/sdk.html) are supported + # + # To build using XZ Utils liblzma - install the library and uncomment +-# the XZ_SUPPORT line below. ++# the LZMA_XZ_SUPPORT line below. + # + # To build using the LZMA SDK (4.65 used in development, other versions may + # work) - download and unpack it, uncomment and set LZMA_DIR to unpacked source, + # and uncomment the LZMA_SUPPORT line below. + # +-#XZ_SUPPORT = 1 ++LZMA_XZ_SUPPORT = 1 + #LZMA_SUPPORT = 1 + #LZMA_DIR = ../../../LZMA/lzma465 + ++########### Building XZ support ############# ++# ++# LZMA2 compression. ++# ++# XZ Utils liblzma (http://tukaani.org/xz/) is supported ++# ++# To build using XZ Utils liblzma - install the library and uncomment ++# the XZ_SUPPORT line below. ++# ++XZ_SUPPORT = 1 ++ + + ############ Building LZO support ############## + # +@@ -109,12 +122,20 @@ + COMPRESSORS += lzma + endif + ++ifdef LZMA_XZ_SUPPORT ++CFLAGS += -DLZMA_SUPPORT ++MKSQUASHFS_OBJS += lzma_xz_wrapper.o ++UNSQUASHFS_OBJS += lzma_xz_wrapper.o ++LIBS += -llzma ++COMPRESSORS += lzma ++endif ++ + ifdef XZ_SUPPORT +-CFLAGS += -DLZMA_SUPPORT ++CFLAGS += -DXZ_SUPPORT + MKSQUASHFS_OBJS += xz_wrapper.o + UNSQUASHFS_OBJS += xz_wrapper.o + LIBS += -llzma +-COMPRESSORS += lzma ++COMPRESSORS += xz + endif + + ifdef LZO_SUPPORT +@@ -149,11 +170,11 @@ + endif + + # +-# Both XZ_SUPPORT and LZMA_SUPPORT cannot be specified ++# Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified + # +-ifdef XZ_SUPPORT ++ifdef LZMA_XZ_SUPPORT + ifdef LZMA_SUPPORT +-$(error "Both XZ_SUPPORT and LZMA_SUPPORT cannot be specified") ++$(error "Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified") + endif + endif + +@@ -161,7 +182,7 @@ + # At least one compressor must have been selected + # + ifndef COMPRESSORS +-$(error "No compressor selected! Select one or more of GZIP, LZMA, or LZO!") ++$(error "No compressor selected! Select one or more of GZIP, LZMA, XZ or LZO!") + endif + + # +diff -r 2ab2996036dd squashfs-tools/compressor.c +--- a/squashfs-tools/compressor.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/compressor.c Tue Dec 14 14:18:11 2010 +0000 +@@ -25,31 +25,50 @@ + #include "compressor.h" + #include "squashfs_fs.h" + +-extern int gzip_compress(void **, char *, char *, int, int, int *); +-extern int gzip_uncompress(char *, char *, int, int, int *); +-extern int lzma_compress(void **, char *, char *, int, int, int *); +-extern int lzma_uncompress(char *, char *, int, int, int *); +-extern int lzo_compress(void **, char *, char *, int, int, int *); +-extern int lzo_uncompress(char *, char *, int, int, int *); +- +-struct compressor compressor[] = { +-#ifdef GZIP_SUPPORT +- { gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 }, ++#ifndef GZIP_SUPPORT ++static struct compressor gzip_comp_ops = { ++ NULL, NULL, NULL, NULL, NULL, ZLIB_COMPRESSION, "gzip", 0 ++}; + #else +- { NULL, NULL, ZLIB_COMPRESSION, "gzip", 0 }, +-#endif +-#ifdef LZMA_SUPPORT +- { lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 }, +-#else +- { NULL, NULL, LZMA_COMPRESSION, "lzma", 0 }, +-#endif +-#ifdef LZO_SUPPORT +- { lzo_compress, lzo_uncompress, LZO_COMPRESSION, "lzo", 1 }, +-#else +- { NULL, NULL, LZO_COMPRESSION, "lzo", 0 }, ++extern struct compressor gzip_comp_ops; + #endif + +- { NULL, NULL , 0, "unknown", 0} ++#ifndef LZMA_SUPPORT ++static struct compressor lzma_comp_ops = { ++ NULL, NULL, NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0 ++}; ++#else ++extern struct compressor lzma_comp_ops; ++#endif ++ ++#ifndef LZO_SUPPORT ++static struct compressor lzo_comp_ops = { ++ NULL, NULL, NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0 ++}; ++#else ++extern struct compressor lzo_comp_ops; ++#endif ++ ++#ifndef XZ_SUPPORT ++static struct compressor xz_comp_ops = { ++ NULL, NULL, NULL, NULL, NULL, XZ_COMPRESSION, "xz", 0 ++}; ++#else ++extern struct compressor xz_comp_ops; ++#endif ++ ++ ++static struct compressor unknown_comp_ops = { ++ NULL, NULL, NULL , NULL, NULL, 0, "unknown", 0 ++}; ++ ++ ++struct compressor *compressor[] = { ++ &gzip_comp_ops, ++ &lzma_comp_ops, ++ &lzo_comp_ops, ++ &xz_comp_ops, ++ &unknown_comp_ops + }; + + +@@ -57,11 +76,11 @@ + { + int i; + +- for(i = 0; compressor[i].id; i++) +- if(strcmp(compressor[i].name, name) == 0) ++ for(i = 0; compressor[i]->id; i++) ++ if(strcmp(compressor[i]->name, name) == 0) + break; + +- return &compressor[i]; ++ return compressor[i]; + } + + +@@ -69,11 +88,11 @@ + { + int i; + +- for(i = 0; compressor[i].id; i++) +- if(id == compressor[i].id) ++ for(i = 0; compressor[i]->id; i++) ++ if(id == compressor[i]->id) + break; + +- return &compressor[i]; ++ return compressor[i]; + } + + +@@ -81,10 +100,29 @@ + { + int i; + +- for(i = 0; compressor[i].id; i++) +- if(compressor[i].supported) ++ for(i = 0; compressor[i]->id; i++) ++ if(compressor[i]->supported) + fprintf(stderr, "%s\t%s%s\n", indent, +- compressor[i].name, +- strcmp(compressor[i].name, def_comp) == 0 ? ++ compressor[i]->name, ++ strcmp(compressor[i]->name, def_comp) == 0 ? + " (default)" : ""); + } ++ ++ ++void display_compressor_usage(char *def_comp) ++{ ++ int i; ++ ++ for(i = 0; compressor[i]->id; i++) ++ if(compressor[i]->supported) { ++ char *str = strcmp(compressor[i]->name, def_comp) == 0 ? ++ " (default)" : ""; ++ if(compressor[i]->usage) { ++ fprintf(stderr, "\t%s%s\n", ++ compressor[i]->name, str); ++ compressor[i]->usage(); ++ } else ++ fprintf(stderr, "\t%s (no options)%s\n", ++ compressor[i]->name, str); ++ } ++} +diff -r 2ab2996036dd squashfs-tools/compressor.h +--- a/squashfs-tools/compressor.h Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/compressor.h Tue Dec 14 14:18:11 2010 +0000 +@@ -21,8 +21,11 @@ + */ + + struct compressor { +- int (*compress)(void **, char *, char *, int, int, int *); +- int (*uncompress)(char *, char *, int, int, int *); ++ int (*init)(void **, int, int); ++ int (*compress)(void *, void *, void *, int, int, int *); ++ int (*uncompress)(void *, void *, int, int, int *); ++ int (*options)(char **, int); ++ void (*usage)(); + int id; + char *name; + int supported; +@@ -31,3 +34,25 @@ + extern struct compressor *lookup_compressor(char *); + extern struct compressor *lookup_compressor_id(int); + extern void display_compressors(char *, char *); ++extern void display_compressor_usage(char *); ++ ++static inline int compressor_options(struct compressor *comp, char *argv[], ++ int argc) ++{ ++ if(comp->options == NULL) ++ return -1; ++ ++ return comp->options(argv, argc); ++} ++ ++ ++static inline int compressor_init(struct compressor *comp, void **stream, ++ int block_size, int flags) ++{ ++ if(comp->init == NULL) ++ return 0; ++ return comp->init(stream, block_size, flags); ++} ++ ++ ++ +diff -r 2ab2996036dd squashfs-tools/gzip_wrapper.c +--- a/squashfs-tools/gzip_wrapper.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/gzip_wrapper.c Tue Dec 14 14:18:11 2010 +0000 +@@ -22,28 +22,48 @@ + #include + #include + +-int gzip_compress(void **strm, char *d, char *s, int size, int block_size, ++#include "squashfs_fs.h" ++#include "compressor.h" ++ ++static int gzip_init(void **strm, int block_size, int flags) ++{ ++ int res; ++ z_stream *stream; ++ ++ stream = *strm = malloc(sizeof(z_stream)); ++ if(stream == NULL) ++ goto failed; ++ ++ stream->zalloc = Z_NULL; ++ stream->zfree = Z_NULL; ++ stream->opaque = 0; ++ ++ res = deflateInit(stream, 9); ++ if(res != Z_OK) ++ goto failed2; ++ ++ return 0; ++ ++failed2: ++ free(stream); ++failed: ++ return -1; ++} ++ ++ ++static int gzip_compress(void *strm, void *d, void *s, int size, int block_size, + int *error) + { +- int res = 0; +- z_stream *stream = *strm; ++ int res; ++ z_stream *stream = strm; + +- if(stream == NULL) { +- if((stream = *strm = malloc(sizeof(z_stream))) == NULL) +- goto failed; +- +- stream->zalloc = Z_NULL; +- stream->zfree = Z_NULL; +- stream->opaque = 0; +- +- if((res = deflateInit(stream, 9)) != Z_OK) +- goto failed; +- } else if((res = deflateReset(stream)) != Z_OK) ++ res = deflateReset(stream); ++ if(res != Z_OK) + goto failed; + +- stream->next_in = (unsigned char *) s; ++ stream->next_in = s; + stream->avail_in = size; +- stream->next_out = (unsigned char *) d; ++ stream->next_out = d; + stream->avail_out = block_size; + + res = deflate(stream, Z_FINISH); +@@ -67,14 +87,26 @@ + } + + +-int gzip_uncompress(char *d, char *s, int size, int block_size, int *error) ++static int gzip_uncompress(void *d, void *s, int size, int block_size, int *error) + { + int res; + unsigned long bytes = block_size; + +- res = uncompress((unsigned char *) d, &bytes, +- (const unsigned char *) s, size); ++ res = uncompress(d, &bytes, s, size); + + *error = res; + return res == Z_OK ? (int) bytes : -1; + } ++ ++ ++struct compressor gzip_comp_ops = { ++ .init = gzip_init, ++ .compress = gzip_compress, ++ .uncompress = gzip_uncompress, ++ .options = NULL, ++ .usage = NULL, ++ .id = ZLIB_COMPRESSION, ++ .name = "gzip", ++ .supported = 1 ++}; ++ +diff -r 2ab2996036dd squashfs-tools/lzma_wrapper.c +--- a/squashfs-tools/lzma_wrapper.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/lzma_wrapper.c Tue Dec 14 14:18:11 2010 +0000 +@@ -17,21 +17,27 @@ + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * lzma_wrapper.c ++ * ++ * Support for LZMA1 compression using LZMA SDK (4.65 used in ++ * development, other versions may work) http://www.7-zip.org/sdk.html + */ + + #include + ++#include "squashfs_fs.h" ++#include "compressor.h" ++ + #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) + +-int lzma_compress(void **strm, char *dest, char *src, int size, int block_size, ++static int lzma_compress(void *strm, void *dest, void *src, int size, int block_size, + int *error) + { +- unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; ++ unsigned char *d = dest; + size_t props_size = LZMA_PROPS_SIZE, + outlen = block_size - LZMA_HEADER_SIZE; + int res; + +- res = LzmaCompress(d + LZMA_HEADER_SIZE, &outlen, s, size, d, ++ res = LzmaCompress(dest + LZMA_HEADER_SIZE, &outlen, src, size, dest, + &props_size, 5, block_size, 3, 0, 2, 32, 1); + + if(res == SZ_ERROR_OUTPUT_EOF) { +@@ -73,10 +79,10 @@ + } + + +-int lzma_uncompress(char *dest, char *src, int size, int block_size, ++static int lzma_uncompress(void *dest, void *src, int size, int block_size, + int *error) + { +- unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; ++ unsigned char *s = src; + size_t outlen, inlen = size - LZMA_HEADER_SIZE; + int res; + +@@ -85,9 +91,22 @@ + (s[LZMA_PROPS_SIZE + 2] << 16) | + (s[LZMA_PROPS_SIZE + 3] << 24); + +- res = LzmaUncompress(d, &outlen, s + LZMA_HEADER_SIZE, &inlen, +- s, LZMA_PROPS_SIZE); ++ res = LzmaUncompress(dest, &outlen, src + LZMA_HEADER_SIZE, &inlen, src, ++ LZMA_PROPS_SIZE); + + *error = res; + return res == SZ_OK ? outlen : -1; + } ++ ++ ++struct compressor lzma_comp_ops = { ++ .init = NULL, ++ .compress = lzma_compress, ++ .uncompress = lzma_uncompress, ++ .options = NULL, ++ .usage = NULL, ++ .id = LZMA_COMPRESSION, ++ .name = "lzma", ++ .supported = 1 ++}; ++ +diff -r 2ab2996036dd squashfs-tools/lzma_xz_wrapper.c +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/squashfs-tools/lzma_xz_wrapper.c Tue Dec 14 14:18:11 2010 +0000 +@@ -0,0 +1,156 @@ ++/* ++ * Copyright (c) 2010 ++ * Phillip Lougher ++ * ++ * 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_xz_wrapper.c ++ * ++ * Support for LZMA1 compression using XZ Utils liblzma http://tukaani.org/xz/ ++ */ ++ ++#include ++#include ++#include ++ ++#include "squashfs_fs.h" ++#include "compressor.h" ++ ++#define LZMA_PROPS_SIZE 5 ++#define LZMA_UNCOMP_SIZE 8 ++#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE) ++ ++#define LZMA_OPTIONS 5 ++#define MEMLIMIT (32 * 1024 * 1024) ++ ++static int lzma_compress(void *dummy, void *dest, void *src, int size, ++ int block_size, int *error) ++{ ++ unsigned char *d = (unsigned char *) dest; ++ lzma_options_lzma opt; ++ lzma_stream strm = LZMA_STREAM_INIT; ++ int res; ++ ++ lzma_lzma_preset(&opt, LZMA_OPTIONS); ++ opt.dict_size = block_size; ++ res = lzma_alone_encoder(&strm, &opt); ++ if(res != LZMA_OK) { ++ lzma_end(&strm); ++ goto failed; ++ } ++ ++ strm.next_out = dest; ++ strm.avail_out = block_size; ++ strm.next_in = src; ++ strm.avail_in = size; ++ ++ res = lzma_code(&strm, LZMA_FINISH); ++ lzma_end(&strm); ++ ++ if(res == LZMA_STREAM_END) { ++ /* ++ * Fill in the 8 byte little endian uncompressed size field in ++ * the LZMA header. 8 bytes is excessively large for squashfs ++ * but this is the standard LZMA header and which is expected by ++ * the kernel code ++ */ ++ ++ d[LZMA_PROPS_SIZE] = size & 255; ++ d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255; ++ d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255; ++ d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255; ++ d[LZMA_PROPS_SIZE + 4] = 0; ++ d[LZMA_PROPS_SIZE + 5] = 0; ++ d[LZMA_PROPS_SIZE + 6] = 0; ++ d[LZMA_PROPS_SIZE + 7] = 0; ++ ++ return (int) strm.total_out; ++ } ++ ++ if(res == LZMA_OK) ++ /* ++ * Output buffer overflow. Return out of buffer space ++ */ ++ return 0; ++ ++failed: ++ /* ++ * All other errors return failure, with the compressor ++ * specific error code in *error ++ */ ++ *error = res; ++ return -1; ++} ++ ++ ++static int lzma_uncompress(void *dest, void *src, int size, int block_size, ++ int *error) ++{ ++ lzma_stream strm = LZMA_STREAM_INIT; ++ int uncompressed_size = 0, res; ++ unsigned char lzma_header[LZMA_HEADER_SIZE]; ++ ++ res = lzma_alone_decoder(&strm, MEMLIMIT); ++ if(res != LZMA_OK) { ++ lzma_end(&strm); ++ goto failed; ++ } ++ ++ memcpy(lzma_header, src, LZMA_HEADER_SIZE); ++ uncompressed_size = lzma_header[LZMA_PROPS_SIZE] | ++ (lzma_header[LZMA_PROPS_SIZE + 1] << 8) | ++ (lzma_header[LZMA_PROPS_SIZE + 2] << 16) | ++ (lzma_header[LZMA_PROPS_SIZE + 3] << 24); ++ memset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE); ++ ++ strm.next_out = dest; ++ strm.avail_out = block_size; ++ strm.next_in = lzma_header; ++ strm.avail_in = LZMA_HEADER_SIZE; ++ ++ res = lzma_code(&strm, LZMA_RUN); ++ ++ if(res != LZMA_OK || strm.avail_in != 0) { ++ lzma_end(&strm); ++ goto failed; ++ } ++ ++ strm.next_in = src + LZMA_HEADER_SIZE; ++ strm.avail_in = size - LZMA_HEADER_SIZE; ++ ++ res = lzma_code(&strm, LZMA_FINISH); ++ lzma_end(&strm); ++ ++ if(res == LZMA_STREAM_END || (res == LZMA_OK && ++ strm.total_out >= uncompressed_size && strm.avail_in == 0)) ++ return uncompressed_size; ++ ++failed: ++ *error = res; ++ return -1; ++} ++ ++ ++struct compressor lzma_comp_ops = { ++ .init = NULL, ++ .compress = lzma_compress, ++ .uncompress = lzma_uncompress, ++ .options = NULL, ++ .usage = NULL, ++ .id = LZMA_COMPRESSION, ++ .name = "lzma", ++ .supported = 1 ++}; ++ +diff -r 2ab2996036dd squashfs-tools/lzo_wrapper.c +--- a/squashfs-tools/lzo_wrapper.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/lzo_wrapper.c Tue Dec 14 14:18:11 2010 +0000 +@@ -2,6 +2,9 @@ + * Copyright (c) 2010 LG Electronics + * Chan Jeong + * ++ * All modifications Copyright (c) 2010 ++ * Phillip Lougher ++ * + * 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, +@@ -25,6 +28,9 @@ + #include + #include + ++#include "squashfs_fs.h" ++#include "compressor.h" ++ + /* worst-case expansion calculation during compression, + see LZO FAQ for more information */ + #define LZO_OUTPUT_BUFFER_SIZE(size) (size + (size/16) + 64 + 3) +@@ -34,25 +40,39 @@ + lzo_bytep out; + }; + +-int lzo_compress(void **strm, char *d, char *s, int size, int block_size, ++ ++static int squashfs_lzo_init(void **strm, int block_size, int flags) ++{ ++ struct lzo_stream *stream; ++ ++ if((stream = *strm = malloc(sizeof(struct lzo_stream))) == NULL) ++ goto failed; ++ /* work memory for compression */ ++ if((stream->wrkmem = malloc(LZO1X_999_MEM_COMPRESS)) == NULL) ++ goto failed2; ++ /* temporal output buffer */ ++ if((stream->out = malloc(LZO_OUTPUT_BUFFER_SIZE(block_size))) == NULL) ++ goto failed3; ++ ++ return 0; ++ ++failed3: ++ free(stream->wrkmem); ++failed2: ++ free(stream); ++failed: ++ return -1; ++} ++ ++ ++static int lzo_compress(void *strm, void *d, void *s, int size, int block_size, + int *error) + { +- int res = 0; ++ int res; + lzo_uint outlen; +- struct lzo_stream *stream = *strm; ++ struct lzo_stream *stream = strm; + +- if(stream == NULL) { +- if((stream = *strm = malloc(sizeof(struct lzo_stream))) == NULL) +- goto failed; +- /* work memory for compression */ +- if((stream->wrkmem = malloc(LZO1X_999_MEM_COMPRESS)) == NULL) +- goto failed; +- /* temporal output buffer */ +- if((stream->out = malloc(LZO_OUTPUT_BUFFER_SIZE(block_size))) == NULL) +- goto failed; +- } +- +- res = lzo1x_999_compress((lzo_bytep)s, size, stream->out, &outlen, stream->wrkmem); ++ res = lzo1x_999_compress(s, size, stream->out, &outlen, stream->wrkmem); + if(res != LZO_E_OK) + goto failed; + if(outlen >= size) +@@ -77,13 +97,26 @@ + } + + +-int lzo_uncompress(char *d, char *s, int size, int block_size, int *error) ++static int lzo_uncompress(void *d, void *s, int size, int block_size, int *error) + { + int res; + lzo_uint bytes = block_size; + +- res = lzo1x_decompress_safe((lzo_bytep)s, size, (lzo_bytep)d, &bytes, NULL); ++ res = lzo1x_decompress_safe(s, size, d, &bytes, NULL); + + *error = res; + return res == LZO_E_OK ? bytes : -1; + } ++ ++ ++struct compressor lzo_comp_ops = { ++ .init = squashfs_lzo_init, ++ .compress = lzo_compress, ++ .uncompress = lzo_uncompress, ++ .options = NULL, ++ .usage = NULL, ++ .id = LZO_COMPRESSION, ++ .name = "lzo", ++ .supported = 1 ++}; ++ +diff -r 2ab2996036dd squashfs-tools/mksquashfs.c +--- a/squashfs-tools/mksquashfs.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/mksquashfs.c Tue Dec 14 14:18:11 2010 +0000 +@@ -384,9 +384,10 @@ + #define FRAGMENT_BUFFER_DEFAULT 64 + int writer_buffer_size; + +-/* compression operations structure */ ++/* compression operations */ + static struct compressor *comp; +-char *comp_name = COMP_DEFAULT; ++int compressor_opts_parsed = 0; ++void *stream = NULL; + + /* xattr stats */ + unsigned int xattr_bytes = 0, total_xattr_bytes = 0; +@@ -859,7 +860,7 @@ + } + + +-int mangle2(void **strm, char *d, char *s, int size, ++int mangle2(void *strm, char *d, char *s, int size, + int block_size, int uncompressed, int data_block) + { + int error, c_byte = 0; +@@ -884,9 +885,7 @@ + int mangle(char *d, char *s, int size, int block_size, + int uncompressed, int data_block) + { +- static void *stream = NULL; +- +- return mangle2(&stream, d, s, size, block_size, uncompressed, ++ return mangle2(stream, d, s, size, block_size, uncompressed, + data_block); + } + +@@ -2556,11 +2555,15 @@ + void *deflator(void *arg) + { + void *stream = NULL; +- int oldstate; ++ int res, oldstate; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); + ++ res = compressor_init(comp, &stream, block_size, 1); ++ if(res) ++ BAD_ERROR("deflator:: compressor_init failed\n"); ++ + while(1) { + struct file_buffer *file_buffer = queue_get(from_reader); + struct file_buffer *write_buffer; +@@ -2573,7 +2576,7 @@ + queue_put(from_deflate, file_buffer); + } else { + write_buffer = cache_get(writer_buffer, 0, 0); +- write_buffer->c_byte = mangle2(&stream, ++ write_buffer->c_byte = mangle2(stream, + write_buffer->data, file_buffer->data, + file_buffer->size, block_size, noD, 1); + write_buffer->sequence = file_buffer->sequence; +@@ -2593,11 +2596,15 @@ + void *frag_deflator(void *arg) + { + void *stream = NULL; +- int oldstate; ++ int res, oldstate; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); + ++ res = compressor_init(comp, &stream, block_size, 1); ++ if(res) ++ BAD_ERROR("frag_deflator:: compressor_init failed\n"); ++ + while(1) { + int c_byte, compressed_size; + struct file_buffer *file_buffer = queue_get(to_frag); +@@ -2605,7 +2612,7 @@ + cache_get(writer_buffer, file_buffer->block + + FRAG_INDEX, 1); + +- c_byte = mangle2(&stream, write_buffer->data, file_buffer->data, ++ c_byte = mangle2(stream, write_buffer->data, file_buffer->data, + file_buffer->size, block_size, noF, 1); + compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); + write_buffer->size = compressed_size; +@@ -4501,7 +4508,7 @@ + + + #define VERSION() \ +- printf("mksquashfs version 4.1 (2010/09/19)\n");\ ++ printf("mksquashfs version 4.1-CVS (2010/12/07)\n");\ + printf("copyright (C) 2010 Phillip Lougher "\ + "\n\n"); \ + printf("This program is free software; you can redistribute it and/or"\ +@@ -4521,7 +4528,7 @@ + int main(int argc, char *argv[]) + { + struct stat buf, source_buf; +- int i; ++ int res, i; + squashfs_super_block sBlk; + char *b, *root_name = NULL; + int nopad = FALSE, keep_as_directory = FALSE; +@@ -4542,14 +4549,50 @@ + goto printOptions; + source_path = argv + 1; + source = i - 2; ++ /* ++ * lookup default compressor. Note the Makefile ensures the default ++ * compressor has been built, and so we don't need to to check ++ * for failure here ++ */ ++ comp = lookup_compressor(COMP_DEFAULT); + for(; i < argc; i++) { + if(strcmp(argv[i], "-comp") == 0) { ++ if(compressor_opts_parsed) { ++ ERROR("%s: -comp must appear before -X options" ++ "\n", argv[0]); ++ exit(1); ++ } + if(++i == argc) { + ERROR("%s: -comp missing compression type\n", + argv[0]); + exit(1); + } +- comp_name = argv[i]; ++ comp = lookup_compressor(argv[i]); ++ if(!comp->supported) { ++ ERROR("%s: Compressor \"%s\" is not supported!" ++ "\n", argv[0], argv[i]); ++ ERROR("%s: Compressors available:\n", argv[0]); ++ display_compressors("", COMP_DEFAULT); ++ exit(1); ++ } ++ ++ } else if(strncmp(argv[i], "-X", 2) == 0) { ++ int args = compressor_options(comp, argv + i, argc - i); ++ if(args < 0) { ++ if(args == -1) { ++ ERROR("%s: Unrecognised compressor" ++ " option %s\n", argv[0], ++ argv[i]); ++ ERROR("%s: Did you forget to specify" ++ " -comp, or specify it after" ++ " the compressor specific" ++ " option?\n", argv[0]); ++ } ++ exit(1); ++ } ++ i += args; ++ compressor_opts_parsed = 1; ++ + } else if(strcmp(argv[i], "-pf") == 0) { + if(++i == argc) { + ERROR("%s: -pf missing filename\n", argv[0]); +@@ -4857,7 +4900,7 @@ + ERROR("-write-queue \tSet output queue to " + "Mbytes. Default %d Mbytes\n", + WRITER_BUFFER_DEFAULT); +- ERROR("-fragment-queue \tSet fagment queue to " ++ ERROR("-fragment-queue \tSet fragment queue to " + " Mbytes. Default %d Mbytes\n", + FRAGMENT_BUFFER_DEFAULT); + ERROR("\nMiscellaneous options:\n"); +@@ -4871,8 +4914,9 @@ + "-noF\n"); + ERROR("-noXattrCompression\talternative name for " + "-noX\n"); +- ERROR("\nCompressors available:\n"); +- display_compressors("", COMP_DEFAULT); ++ ERROR("\nCompressors available and compressor specific " ++ "options:\n"); ++ display_compressor_usage(COMP_DEFAULT); + exit(1); + } + } +@@ -5005,19 +5049,14 @@ + always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); + duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); + exportable = SQUASHFS_EXPORTABLE(sBlk.flags); +- } else { +- comp = lookup_compressor(comp_name); +- if(!comp->supported) { +- ERROR("FATAL_ERROR: Compressor \"%s\" is not " +- "supported!\n", comp_name); +- ERROR("Compressors available:\n"); +- display_compressors("", COMP_DEFAULT); +- EXIT_MKSQUASHFS(); +- } + } + + initialise_threads(readb_mbytes, writeb_mbytes, fragmentb_mbytes); + ++ res = compressor_init(comp, &stream, SQUASHFS_METADATA_SIZE, 0); ++ if(res) ++ BAD_ERROR("compressor_init failed\n"); ++ + if(delete) { + printf("Creating %d.%d filesystem on %s, block size %d.\n", + SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size); +diff -r 2ab2996036dd squashfs-tools/read_fs.c +--- a/squashfs-tools/read_fs.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/read_fs.c Tue Dec 14 14:18:11 2010 +0000 +@@ -363,7 +363,8 @@ + } + } + +- return files; ++ printf("Read existing filesystem, %d inodes scanned\n", files); ++ return TRUE; + + + failed: +@@ -414,6 +415,7 @@ + if(!comp->supported) { + ERROR("Filesystem on %s uses %s compression, this is" + "unsupported by this version\n", source, comp->name); ++ ERROR("Compressors available:\n"); + display_compressors("", ""); + goto failed_mount; + } +@@ -691,7 +693,7 @@ + SQUASHFS_INODE_BLK(sBlk->root_inode); + unsigned int root_inode_offset = + SQUASHFS_INODE_OFFSET(sBlk->root_inode); +- unsigned int root_inode_block, files; ++ unsigned int root_inode_block; + squashfs_inode_header inode; + unsigned int *id_table; + int res; +@@ -711,20 +713,18 @@ + if(id_table == NULL) + goto error; + +- if((files = scan_inode_table(fd, start, end, root_inode_start, +- root_inode_offset, sBlk, &inode, &inode_table, +- &root_inode_block, root_inode_size, uncompressed_file, +- uncompressed_directory, file_count, sym_count, +- dev_count, dir_count, fifo_count, sock_count, id_table)) +- == 0) { ++ res = scan_inode_table(fd, start, end, root_inode_start, ++ root_inode_offset, sBlk, &inode, &inode_table, ++ &root_inode_block, root_inode_size, uncompressed_file, ++ uncompressed_directory, file_count, sym_count, dev_count, ++ dir_count, fifo_count, sock_count, id_table); ++ if(res == 0) { + ERROR("read_filesystem: inode table read failed\n"); + goto error; + } + + *uncompressed_inode = root_inode_block; + +- printf("Read existing filesystem, %d inodes scanned\n", files); +- + if(inode.base.inode_type == SQUASHFS_DIR_TYPE || + inode.base.inode_type == SQUASHFS_LDIR_TYPE) { + if(inode.base.inode_type == SQUASHFS_DIR_TYPE) { +diff -r 2ab2996036dd squashfs-tools/squashfs_fs.h +--- a/squashfs-tools/squashfs_fs.h Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/squashfs_fs.h Tue Dec 14 14:18:11 2010 +0000 +@@ -259,6 +259,7 @@ + #define ZLIB_COMPRESSION 1 + #define LZMA_COMPRESSION 2 + #define LZO_COMPRESSION 3 ++#define XZ_COMPRESSION 4 + + struct squashfs_super_block { + unsigned int s_magic; +diff -r 2ab2996036dd squashfs-tools/unsquash-1.c +--- a/squashfs-tools/unsquash-1.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/unsquash-1.c Tue Dec 14 14:18:11 2010 +0000 +@@ -138,7 +138,7 @@ + + i.data = inode->file_size; + i.time = inode->mtime; +- i.blocks = (inode->file_size + sBlk.s.block_size - 1) >> ++ i.blocks = (i.data + sBlk.s.block_size - 1) >> + sBlk.s.block_log; + i.start = inode->start_block; + i.block_ptr = block_ptr + sizeof(*inode); +diff -r 2ab2996036dd squashfs-tools/unsquash-2.c +--- a/squashfs-tools/unsquash-2.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/unsquash-2.c Tue Dec 14 14:18:11 2010 +0000 +@@ -205,8 +205,8 @@ + i.fragment = inode->fragment; + i.offset = inode->offset; + i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? +- (inode->file_size + sBlk.s.block_size - 1) >> +- sBlk.s.block_log : inode->file_size >> ++ (i.data + sBlk.s.block_size - 1) >> ++ sBlk.s.block_log : i.data >> + sBlk.s.block_log; + i.start = inode->start_block; + i.sparse = 0; +diff -r 2ab2996036dd squashfs-tools/unsquash-3.c +--- a/squashfs-tools/unsquash-3.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/unsquash-3.c Tue Dec 14 14:18:11 2010 +0000 +@@ -188,9 +188,9 @@ + i.fragment = inode->fragment; + i.offset = inode->offset; + i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? +- (inode->file_size + sBlk.s.block_size - 1) >> ++ (i.data + sBlk.s.block_size - 1) >> + sBlk.s.block_log : +- inode->file_size >> sBlk.s.block_log; ++ i.data >> sBlk.s.block_log; + i.start = inode->start_block; + i.sparse = 1; + i.block_ptr = block_ptr + sizeof(*inode); +diff -r 2ab2996036dd squashfs-tools/unsquash-4.c +--- a/squashfs-tools/unsquash-4.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/unsquash-4.c Tue Dec 14 14:18:11 2010 +0000 +@@ -143,9 +143,9 @@ + i.fragment = inode->fragment; + i.offset = inode->offset; + i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ? +- (inode->file_size + sBlk.s.block_size - 1) >> ++ (i.data + sBlk.s.block_size - 1) >> + sBlk.s.block_log : +- inode->file_size >> sBlk.s.block_log; ++ i.data >> sBlk.s.block_log; + i.start = inode->start_block; + i.sparse = 0; + i.block_ptr = block_ptr + sizeof(*inode); +diff -r 2ab2996036dd squashfs-tools/unsquashfs.c +--- a/squashfs-tools/unsquashfs.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/unsquashfs.c Tue Dec 14 14:18:11 2010 +0000 +@@ -737,7 +737,7 @@ + int lseek_broken = FALSE; + char *zero_data = NULL; + +-int write_block(int file_fd, char *buffer, int size, int hole, int sparse) ++int write_block(int file_fd, char *buffer, int size, long long hole, int sparse) + { + off_t off = hole; + +@@ -1299,9 +1299,12 @@ + print_filename(parent_name, i); + + if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 && +- (!force || errno != EEXIST)) +- ERROR("dir_scan: failed to open directory %s, because %s\n", ++ (!force || errno != EEXIST)) { ++ ERROR("dir_scan: failed to make directory %s, because %s\n", + parent_name, strerror(errno)); ++ squashfs_closedir(dir); ++ return; ++ } + + while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) { + TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n", +@@ -1604,7 +1607,7 @@ + while(1) { + struct squashfs_file *file = queue_get(to_writer); + int file_fd; +- int hole = 0; ++ long long hole = 0; + int failed = FALSE; + int error; + +@@ -1903,7 +1906,7 @@ + + + #define VERSION() \ +- printf("unsquashfs version 4.1 (2010/09/19)\n");\ ++ printf("unsquashfs version 4.1-CVS (2010/10/23)\n");\ + printf("copyright (C) 2010 Phillip Lougher "\ + "\n\n");\ + printf("This program is free software; you can redistribute it and/or"\ +@@ -2081,7 +2084,7 @@ + ERROR("\t-da[ta-queue] \tSet data queue to " + " Mbytes. Default %d\n\t\t\t\tMbytes\n", + DATA_BUFFER_DEFAULT); +- ERROR("\t-fr[ag-queue] \tSet fagment queue to " ++ ERROR("\t-fr[ag-queue] \tSet fragment queue to " + " Mbytes. Default %d\n\t\t\t\t Mbytes\n", + FRAGMENT_BUFFER_DEFAULT); + ERROR("\t-r[egex]\t\ttreat extract names as POSIX " +diff -r 2ab2996036dd squashfs-tools/unsquashfs_xattr.c +--- a/squashfs-tools/unsquashfs_xattr.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/unsquashfs_xattr.c Tue Dec 14 14:18:11 2010 +0000 +@@ -25,7 +25,7 @@ + #include "unsquashfs.h" + #include "xattr.h" + +-#include ++#include + + extern int root_process; + +diff -r 2ab2996036dd squashfs-tools/xattr.c +--- a/squashfs-tools/xattr.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/xattr.c Tue Dec 14 14:18:11 2010 +0000 +@@ -34,7 +34,7 @@ + #include + #include + #include +-#include ++#include + + #include "squashfs_fs.h" + #include "global.h" +@@ -219,6 +219,10 @@ + break; + } + xattr_list[i].vsize = vsize; ++ ++ TRACE("read_xattrs_from_system: filename %s, xattr name %s," ++ " vsize %d\n", filename, xattr_list[i].full_name, ++ xattr_list[i].vsize); + } + free(xattr_names); + *xattrs = xattr_list; +diff -r 2ab2996036dd squashfs-tools/xz_wrapper.c +--- a/squashfs-tools/xz_wrapper.c Tue Dec 14 12:19:33 2010 +0000 ++++ b/squashfs-tools/xz_wrapper.c Tue Dec 14 14:18:11 2010 +0000 +@@ -17,69 +17,192 @@ + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * xz_wrapper.c ++ * ++ * Support for XZ (LZMA2) compression using XZ Utils liblzma http://tukaani.org/xz/ + */ + + #include + #include ++#include + #include + +-#define LZMA_PROPS_SIZE 5 +-#define LZMA_UNCOMP_SIZE 8 +-#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE) ++#include "squashfs_fs.h" ++#include "compressor.h" + +-#define LZMA_OPTIONS 5 + #define MEMLIMIT (32 * 1024 * 1024) + +-int lzma_compress(void **dummy, void *dest, void *src, int size, ++static struct bcj { ++ char *name; ++ lzma_vli id; ++ int selected; ++} 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 } ++}; ++ ++struct filter { ++ void *buffer; ++ lzma_filter filter[3]; ++ size_t length; ++}; ++ ++struct xz_stream { ++ struct filter *filter; ++ int filters; ++ lzma_options_lzma opt; ++}; ++ ++static int filter_count = 1; ++ ++ ++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; ++ } ++ ++ return -1; ++ ++failed: ++ return -2; ++} ++ ++ ++void xz_usage() ++{ ++ 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"); ++} ++ ++ ++static int xz_init(void **strm, int block_size, int flags) ++{ ++ int i, j, filters = flags ? 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)); ++ ++ 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; flags && 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) + { +- unsigned char *d = (unsigned char *) dest; +- lzma_options_lzma opt; +- lzma_stream strm = LZMA_STREAM_INIT; +- int res; ++ int i; ++ lzma_ret res = 0; ++ struct xz_stream *stream = strm; ++ struct filter *selected = NULL; + +- lzma_lzma_preset(&opt, LZMA_OPTIONS); +- opt.dict_size = block_size; +- res = lzma_alone_encoder(&strm, &opt); +- if(res != LZMA_OK) { +- lzma_end(&strm); +- goto failed; ++ stream->filter[0].buffer = dest; ++ ++ for(i = 0; i < stream->filters; i++) { ++ struct filter *filter = &stream->filter[i]; ++ ++ if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT)) ++ goto failed; ++ ++ stream->opt.dict_size = block_size; ++ 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; + } + +- strm.next_out = dest; +- strm.avail_out = block_size; +- strm.next_in = src; +- strm.avail_in = size; +- +- res = lzma_code(&strm, LZMA_FINISH); +- lzma_end(&strm); +- +- if(res == LZMA_STREAM_END) { +- /* +- * Fill in the 8 byte little endian uncompressed size field in +- * the LZMA header. 8 bytes is excessively large for squashfs +- * but this is the standard LZMA header and which is expected by +- * the kernel code +- */ +- +- d[LZMA_PROPS_SIZE] = size & 255; +- d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255; +- d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255; +- d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255; +- d[LZMA_PROPS_SIZE + 4] = 0; +- d[LZMA_PROPS_SIZE + 5] = 0; +- d[LZMA_PROPS_SIZE + 6] = 0; +- d[LZMA_PROPS_SIZE + 7] = 0; +- +- return (int) strm.total_out; +- } +- +- if(res == LZMA_OK) ++ 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 +@@ -90,49 +213,29 @@ + } + + +-int lzma_uncompress(void *dest, void *src, int size, int block_size, ++static int xz_uncompress(void *dest, void *src, int size, int block_size, + int *error) + { +- lzma_stream strm = LZMA_STREAM_INIT; +- int uncompressed_size = 0, res; +- unsigned char lzma_header[LZMA_HEADER_SIZE]; ++ size_t src_pos = 0; ++ size_t dest_pos = 0; ++ uint64_t memlimit = MEMLIMIT; + +- res = lzma_alone_decoder(&strm, MEMLIMIT); +- if(res != LZMA_OK) { +- lzma_end(&strm); +- goto failed; +- } ++ lzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL, ++ src, &src_pos, size, dest, &dest_pos, block_size); + +- memcpy(lzma_header, src, LZMA_HEADER_SIZE); +- uncompressed_size = lzma_header[LZMA_PROPS_SIZE] | +- (lzma_header[LZMA_PROPS_SIZE + 1] << 8) | +- (lzma_header[LZMA_PROPS_SIZE + 2] << 16) | +- (lzma_header[LZMA_PROPS_SIZE + 3] << 24); +- memset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE); ++ *error = res; ++ return res == LZMA_OK && size == (int) src_pos ? (int) dest_pos : -1; ++} + +- strm.next_out = dest; +- strm.avail_out = block_size; +- strm.next_in = lzma_header; +- strm.avail_in = LZMA_HEADER_SIZE; + +- res = lzma_code(&strm, LZMA_RUN); ++struct compressor xz_comp_ops = { ++ .init = xz_init, ++ .compress = xz_compress, ++ .uncompress = xz_uncompress, ++ .options = xz_options, ++ .usage = xz_usage, ++ .id = XZ_COMPRESSION, ++ .name = "xz", ++ .supported = 1 ++}; + +- if(res != LZMA_OK || strm.avail_in != 0) { +- lzma_end(&strm); +- goto failed; +- } +- +- strm.next_in = src + LZMA_HEADER_SIZE; +- strm.avail_in = size - LZMA_HEADER_SIZE; +- +- res = lzma_code(&strm, LZMA_FINISH); +- lzma_end(&strm); +- +- if(res == LZMA_STREAM_END || (res == LZMA_OK && +- strm.total_out >= uncompressed_size && strm.avail_in == 0)) +- return uncompressed_size; +- +-failed: +- *error = res; +- return -1; +-}