From 4364bc210ed60457e08984be25def5d3eb4185b3 Mon Sep 17 00:00:00 2001 From: Imre Kaloz Date: Mon, 2 Nov 2009 09:52:54 +0000 Subject: [PATCH] sync mksquashfs4 with the CVS code to generate LZMA images SVN-Revision: 18268 --- tools/squashfs4/patches/110-lzma.patch | 2482 ++++++++++++++++++++---- 1 file changed, 2124 insertions(+), 358 deletions(-) diff --git a/tools/squashfs4/patches/110-lzma.patch b/tools/squashfs4/patches/110-lzma.patch index 1441fb42f0..5fd697085f 100644 --- a/tools/squashfs4/patches/110-lzma.patch +++ b/tools/squashfs4/patches/110-lzma.patch @@ -1,462 +1,2228 @@ -Index: squashfs4.0/squashfs-tools/mksquashfs.c -=================================================================== ---- squashfs4.0.orig/squashfs-tools/mksquashfs.c 2009-04-05 23:22:48.000000000 +0200 -+++ squashfs4.0/squashfs-tools/mksquashfs.c 2009-09-14 17:21:46.210480446 +0200 -@@ -64,6 +64,18 @@ +diff -Nur squashfs4.0/squashfs-tools/compressor.c squashfs4.0-lzma-snapshot/squashfs-tools/compressor.c +--- squashfs4.0/squashfs-tools/compressor.c 1970-01-01 01:00:00.000000000 +0100 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/compressor.c 2009-10-20 06:03:37.000000000 +0200 +@@ -0,0 +1,78 @@ ++/* ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * 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. ++ * ++ * compressor.c ++ */ ++ ++#include ++#include ++#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 *); ++ ++struct compressor compressor[] = { ++ { gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 }, ++#ifdef LZMA_SUPPORT ++ { lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 }, ++#else ++ { NULL, NULL, LZMA_COMPRESSION, "lzma", 0 }, ++#endif ++ { NULL, NULL , 0, "unknown", 0} ++}; ++ ++ ++struct compressor *lookup_compressor(char *name) ++{ ++ int i; ++ ++ for(i = 0; compressor[i].id; i++) ++ if(strcmp(compressor[i].name, name) == 0) ++ break; ++ ++ return &compressor[i]; ++} ++ ++ ++struct compressor *lookup_compressor_id(int id) ++{ ++ int i; ++ ++ for(i = 0; compressor[i].id; i++) ++ if(id == compressor[i].id) ++ break; ++ ++ return &compressor[i]; ++} ++ ++ ++void display_compressors(char *indent, char *def_comp) ++{ ++ int i; ++ ++ 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 ? ++ " (default)" : ""); ++} +diff -Nur squashfs4.0/squashfs-tools/compressor.h squashfs4.0-lzma-snapshot/squashfs-tools/compressor.h +--- squashfs4.0/squashfs-tools/compressor.h 1970-01-01 01:00:00.000000000 +0100 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/compressor.h 2009-10-20 06:03:37.000000000 +0200 +@@ -0,0 +1,33 @@ ++/* ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * 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. ++ * ++ * compressor.h ++ */ ++ ++struct compressor { ++ int (*compress)(void **, char *, char *, int, int, int *); ++ int (*uncompress)(char *, char *, int, int, int *); ++ int id; ++ char *name; ++ int supported; ++}; ++ ++extern struct compressor *lookup_compressor(char *); ++extern struct compressor *lookup_compressor_id(int); ++extern void display_compressors(char *, char *); +diff -Nur squashfs4.0/squashfs-tools/gzip_wrapper.c squashfs4.0-lzma-snapshot/squashfs-tools/gzip_wrapper.c +--- squashfs4.0/squashfs-tools/gzip_wrapper.c 1970-01-01 01:00:00.000000000 +0100 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/gzip_wrapper.c 2009-10-20 06:03:37.000000000 +0200 +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * 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. ++ * ++ * gzip_wrapper.c ++ */ ++ ++#include ++#include ++ ++int gzip_compress(void **strm, char *d, char *s, int size, int block_size, ++ int *error) ++{ ++ int res = 0; ++ 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) ++ goto failed; ++ ++ stream->next_in = (unsigned char *) s; ++ stream->avail_in = size; ++ stream->next_out = (unsigned char *) d; ++ stream->avail_out = block_size; ++ ++ res = deflate(stream, Z_FINISH); ++ if(res == Z_STREAM_END) ++ /* ++ * Success, return the compressed size. ++ */ ++ return (int) stream->total_out; ++ if(res == Z_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; ++} ++ ++ ++int gzip_uncompress(char *d, char *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); ++ ++ *error = res; ++ return res == Z_OK ? (int) bytes : -1; ++} +diff -Nur squashfs4.0/squashfs-tools/lzma_wrapper.c squashfs4.0-lzma-snapshot/squashfs-tools/lzma_wrapper.c +--- squashfs4.0/squashfs-tools/lzma_wrapper.c 1970-01-01 01:00:00.000000000 +0100 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/lzma_wrapper.c 2009-10-14 05:32:57.000000000 +0200 +@@ -0,0 +1,93 @@ ++/* ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * 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_wrapper.c ++ */ ++ ++#include ++ ++#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) ++ ++int lzma_compress(void **strm, char *dest, char *src, int size,int block_size, ++ int *error) ++{ ++ unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; ++ 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, ++ &props_size, 5, block_size, 3, 0, 2, 32, 1); ++ ++ if(res == SZ_ERROR_OUTPUT_EOF) { ++ /* ++ * Output buffer overflow. Return out of buffer space error ++ */ ++ return 0; ++ } ++ ++ if(res != SZ_OK) { ++ /* ++ * All other errors return failure, with the compressor ++ * specific error code in *error ++ */ ++ *error = res; ++ return -1; ++ } ++ ++ /* ++ * 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; ++ ++ /* ++ * Success, return the compressed size. Outlen returned by the LZMA ++ * compressor does not include the LZMA header space ++ */ ++ return outlen + LZMA_HEADER_SIZE; ++} ++ ++ ++int lzma_uncompress(char *dest, char *src, int size, int block_size, ++ int *error) ++{ ++ unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; ++ size_t outlen, inlen = size - LZMA_HEADER_SIZE; ++ int res; ++ ++ outlen = s[LZMA_PROPS_SIZE] | ++ (s[LZMA_PROPS_SIZE + 1] << 8) | ++ (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); ++ ++ *error = res; ++ return res == SZ_OK ? outlen : -1; ++} +diff -Nur squashfs4.0/squashfs-tools/Makefile squashfs4.0-lzma-snapshot/squashfs-tools/Makefile +--- squashfs4.0/squashfs-tools/Makefile 2009-04-05 04:03:36.000000000 +0200 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/Makefile 2009-10-22 06:17:12.000000000 +0200 +@@ -1,40 +1,76 @@ ++# ++# Building LZMA support ++# Download LZMA sdk (4.65 used in development, other versions may work), ++# set LZMA_DIR to unpacked source, and uncomment next line ++LZMA_SUPPORT = 1 ++LZMA_DIR = ../../lzma-4.65 ++ ++#Compression default. ++COMP_DEFAULT = gzip ++ ++INCLUDEDIR = -I. + INSTALL_DIR = /usr/local/bin + +-INCLUDEDIR = . ++MKSQUASHFS_OBJS = mksquashfs.o read_fs.o sort.o swap.o pseudo.o compressor.o \ ++ gzip_wrapper.o ++ ++UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \ ++ unsquash-4.o swap.o compressor.o gzip_wrapper.o + +-CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 ++CFLAGS = $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ ++ -D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" -O2 -Wall + ++ifdef LZMA_SUPPORT ++LZMA_OBJS = $(LZMA_DIR)/C/Alloc.o $(LZMA_DIR)/C/LzFind.o \ ++ $(LZMA_DIR)/C/LzmaDec.o $(LZMA_DIR)/C/LzmaEnc.o $(LZMA_DIR)/C/LzmaLib.o ++INCLUDEDIR += -I$(LZMA_DIR)/C ++CFLAGS += -DLZMA_SUPPORT ++MKSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) ++UNSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) ++endif ++ ++.PHONY: all + all: mksquashfs unsquashfs + +-mksquashfs: mksquashfs.o read_fs.o sort.o swap.o pseudo.o +- $(CC) mksquashfs.o read_fs.o sort.o swap.o pseudo.o -lz -lpthread -lm -o $@ ++mksquashfs: $(MKSQUASHFS_OBJS) ++ $(CC) $(MKSQUASHFS_OBJS) -lz -lpthread -lm -o $@ ++ ++mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ ++ squashfs_swap.h + +-mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h squashfs_swap.h Makefile ++read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h + +-read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h Makefile ++sort.o: sort.c squashfs_fs.h global.h sort.h + +-sort.o: sort.c squashfs_fs.h global.h sort.h Makefile ++swap.o: swap.c + +-swap.o: swap.c Makefile ++pseudo.o: pseudo.c pseudo.h + +-pseudo.o: pseudo.c pseudo.h Makefile ++compressor.o: compressor.c compressor.h + +-unsquashfs: unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o +- $(CC) unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o -lz -lpthread -lm -o $@ ++unsquashfs: $(UNSQUASHFS_OBJS) ++ $(CC) $(UNSQUASHFS_OBJS) -lz -lpthread -lm -o $@ + +-unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h squashfs_compat.h global.h Makefile ++unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h \ ++ squashfs_compat.h global.h + +-unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h global.h Makefile ++unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h \ ++ global.h + +-unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h squashfs_compat.h global.h Makefile ++unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h \ ++ squashfs_compat.h global.h + +-unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h global.h Makefile ++unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h \ ++ global.h + +-unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h global.h Makefile ++unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h \ ++ global.h + ++.PHONY: clean + clean: + -rm -f *.o mksquashfs unsquashfs + ++.PHONY: install + install: mksquashfs unsquashfs + mkdir -p $(INSTALL_DIR) + cp mksquashfs $(INSTALL_DIR) +diff -Nur squashfs4.0/squashfs-tools/mksquashfs.c squashfs4.0-lzma-snapshot/squashfs-tools/mksquashfs.c +--- squashfs4.0/squashfs-tools/mksquashfs.c 2009-04-05 23:22:48.000000000 +0200 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/mksquashfs.c 2009-10-20 06:03:38.000000000 +0200 +@@ -36,7 +36,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -47,6 +46,7 @@ + #include + #include + #include ++#include + + #ifndef linux + #define __BYTE_ORDER BYTE_ORDER +@@ -64,6 +64,7 @@ #include "global.h" #include "sort.h" #include "pseudo.h" -+#include "uncompress.h" -+ -+#ifdef USE_LZMA -+#include -+#include -+#define LZMA_DEFAULT_LEVEL 5 -+#define LZMA_DEFAULT_DICT 0 -+#define LZMA_DEFAULT_LC 1 -+#define LZMA_DEFAULT_LP 2 -+#define LZMA_DEFAULT_PB 2 -+#define LZMA_DEFAULT_FB 32 -+#endif ++#include "compressor.h" #ifdef SQUASHFS_TRACE #define TRACE(s, args...) do { \ -@@ -830,6 +842,19 @@ - rotate = (rotate + 1) % 4; +@@ -245,10 +246,8 @@ + /* list of root directory entries read from original filesystem */ + int old_root_entries = 0; + struct old_root_entry_info { +- char name[SQUASHFS_NAME_LEN + 1]; +- squashfs_inode inode; +- int type; +- int inode_number; ++ char *name; ++ struct inode_info inode; + }; + struct old_root_entry_info *old_root_entry; + +@@ -371,10 +370,15 @@ + int reader_buffer_size; + int fragment_buffer_size; + ++/* compression operations structure */ ++static struct compressor *comp; ++char *comp_name = COMP_DEFAULT; ++ + char *read_from_disk(long long start, unsigned int avail_bytes); + void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, + int type); +-extern int read_super(int fd, squashfs_super_block *sBlk, char *source); ++extern struct compressor *read_super(int fd, squashfs_super_block *sBlk, ++ char *source); + extern long long read_filesystem(char *root_name, int fd, + squashfs_super_block *sBlk, char **cinode_table, char **data_cache, + char **cdirectory_table, char **directory_data_cache, +@@ -831,83 +835,32 @@ } -+#ifdef USE_LZMA -+static void *lzma_malloc(void *p, size_t size) -+{ -+ (void)p; -+ return malloc(size); -+} -+static void lzma_free(void *p, void *addr) -+{ -+ (void)p; -+ free(addr); -+} -+static ISzAlloc lzma_alloc = { lzma_malloc, lzma_free }; -+#endif - unsigned int mangle2(z_stream **strm, char *d, char *s, int size, +-unsigned int mangle2(z_stream **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) -@@ -841,6 +866,50 @@ - if(uncompressed) - goto notcompressed; - -+#ifdef USE_LZMA -+ if (compression == LZMA_COMPRESSION) { -+ size_t outsize = block_size - LZMA_PROPS_SIZE; -+ size_t propsize = LZMA_PROPS_SIZE; -+ CLzmaEncProps props; -+ -+ LzmaEncProps_Init(&props); -+ props.level = LZMA_DEFAULT_LEVEL; -+ props.dictSize = LZMA_DEFAULT_DICT; -+ props.lc = LZMA_DEFAULT_LC; -+ props.lp = LZMA_DEFAULT_LP; -+ props.pb = LZMA_DEFAULT_PB; -+ props.fb = LZMA_DEFAULT_FB; -+ props.numThreads = 1; -+ -+ res = LzmaEncode((unsigned char *) d + LZMA_PROPS_SIZE, &outsize, -+ (unsigned char *) s, size, -+ &props, (unsigned char *) d, &propsize, -+ 1, NULL, &lzma_alloc, &lzma_alloc); -+ switch(res) { -+ case SZ_OK: -+ outsize += LZMA_PROPS_SIZE; -+ break; -+ case SZ_ERROR_DATA: -+ BAD_ERROR("lzma::compress failed, data error\n"); -+ break; -+ case SZ_ERROR_MEM: -+ BAD_ERROR("lzma::compress failed, memory allocation error\n"); -+ break; -+ case SZ_ERROR_PARAM: -+ BAD_ERROR("lzma::compress failed, invalid parameters\n"); -+ break; -+ case SZ_ERROR_OUTPUT_EOF: -+ goto notcompressed; -+ /* should not happen */ -+ default: -+ BAD_ERROR("lzma::compress failed, unknown error (%d)\n", res); -+ break; -+ } -+ -+ return outsize; -+ } -+#endif -+ - if(stream == NULL) { - if((stream = *strm = malloc(sizeof(z_stream))) == NULL) - BAD_ERROR("mangle::compress failed, not enough " -@@ -1669,17 +1738,17 @@ + { +- unsigned long c_byte; +- unsigned int res; +- z_stream *stream = *strm; +- +- if(uncompressed) +- goto notcompressed; +- +- if(stream == NULL) { +- if((stream = *strm = malloc(sizeof(z_stream))) == NULL) +- BAD_ERROR("mangle::compress failed, not enough " +- "memory\n"); +- +- stream->zalloc = Z_NULL; +- stream->zfree = Z_NULL; +- stream->opaque = 0; +- +- if((res = deflateInit(stream, 9)) != Z_OK) { +- if(res == Z_MEM_ERROR) +- BAD_ERROR("zlib::compress failed, not enough " +- "memory\n"); +- else if(res == Z_STREAM_ERROR) +- BAD_ERROR("zlib::compress failed, not a valid " +- "compression level\n"); +- else if(res == Z_VERSION_ERROR) +- BAD_ERROR("zlib::compress failed, incorrect " +- "zlib version\n"); +- else +- BAD_ERROR("zlib::compress failed, unknown " +- "error %d\n", res); +- } +- } else if((res = deflateReset(stream)) != Z_OK) { +- if(res == Z_STREAM_ERROR) +- BAD_ERROR("zlib::compress failed, stream state " +- "inconsistent\n"); +- else +- BAD_ERROR("zlib::compress failed, unknown error %d\n", +- res); +- } ++ int error, c_byte = 0; + +- stream->next_in = (unsigned char *) s; +- stream->avail_in = size; +- stream->next_out = (unsigned char *) d; +- stream->avail_out = block_size; +- +- res = deflate(stream, Z_FINISH); +- if(res != Z_STREAM_END && res != Z_OK) { +- if(res == Z_STREAM_ERROR) +- BAD_ERROR("zlib::compress failed, stream state " +- "inconsistent\n"); +- else if(res == Z_BUF_ERROR) +- BAD_ERROR("zlib::compress failed, no progress possible" +- "\n"); +- else +- BAD_ERROR("zlib::compress failed, unknown error %d\n", +- res); ++ if(!uncompressed) { ++ c_byte = comp->compress(strm, d, s, size, block_size, &error); ++ if(c_byte == -1) ++ BAD_ERROR("mangle2:: %s compress failed with error " ++ "code %d\n", comp->name, error); + } + +- c_byte = stream->total_out; +- +- if(res != Z_STREAM_END || c_byte >= size) { +-notcompressed: ++ if(c_byte == 0 || c_byte >= size) { + memcpy(d, s, size); + return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : + SQUASHFS_COMPRESSED_BIT); + } + +- return (unsigned int) c_byte; ++ return c_byte; + } + + +-unsigned int mangle(char *d, char *s, int size, int block_size, ++int mangle(char *d, char *s, int size, int block_size, + int uncompressed, int data_block) + { +- static z_stream *stream = NULL; ++ static void *stream = NULL; + + return mangle2(&stream, d, s, size, block_size, uncompressed, + data_block); +@@ -1660,8 +1613,7 @@ + pthread_mutex_unlock(&fragment_mutex); + + if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { +- int res; +- unsigned long bytes = block_size; ++ int error, res; + char *data; + + if(compressed_buffer) +@@ -1669,19 +1621,11 @@ else data = read_from_disk(start_block, size); - res = uncompress((unsigned char *) buffer->data, &bytes, -+ res = uncompress_wrapper((unsigned char *) buffer->data, &bytes, - (const unsigned char *) data, size); - if(res != Z_OK) { - if(res == Z_MEM_ERROR) +- (const unsigned char *) data, size); +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) - BAD_ERROR("zlib::uncompress failed, not enough " -+ BAD_ERROR("uncompress failed, not enough " - "memory\n"); - else if(res == Z_BUF_ERROR) +- "memory\n"); +- else if(res == Z_BUF_ERROR) - BAD_ERROR("zlib::uncompress failed, not enough " -+ BAD_ERROR("uncompress failed, not enough " - "room in output buffer\n"); - else +- "room in output buffer\n"); +- else - BAD_ERROR("zlib::uncompress failed," -+ BAD_ERROR("uncompress failed," - " unknown error %d\n", res); - } +- " unknown error %d\n", res); +- } ++ res = comp->uncompress(buffer->data, data, size, block_size, ++ &error); ++ if(res == -1) ++ BAD_ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); } else if(compressed_buffer) -@@ -4282,6 +4351,10 @@ + memcpy(buffer->data, compressed_buffer->data, size); + else +@@ -1733,9 +1677,7 @@ + entry->buffer->block = bytes; + bytes += compressed_size; + fragments_outstanding --; +- pthread_mutex_unlock(&fragment_mutex); + queue_put(to_writer, entry->buffer); +- pthread_mutex_lock(&fragment_mutex); + TRACE("fragment_locked writing fragment %d, compressed size %d" + "\n", entry->fragment, compressed_size); + free(entry); +@@ -1758,6 +1700,8 @@ + pthread_mutex_lock(&fragment_mutex); + insert_fragment_list(&frag_locked_list, entry); + pthread_mutex_unlock(&fragment_mutex); ++ ++ return TRUE; + } + + +@@ -1824,7 +1768,9 @@ + unsigned short c_byte; + char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; + ++#ifdef SQUASHFS_TRACE + long long obytes = bytes; ++#endif + + for(i = 0; i < meta_blocks; i++) { + int avail_bytes = length > SQUASHFS_METADATA_SIZE ? +@@ -2170,11 +2116,85 @@ + } + + ++static int seq = 0; ++void reader_read_process(struct dir_ent *dir_ent) ++{ ++ struct file_buffer *prev_buffer = NULL, *file_buffer; ++ int status, res, byte, count = 0; ++ int file = get_pseudo_file(dir_ent->inode->pseudo_id)->fd; ++ int child = get_pseudo_file(dir_ent->inode->pseudo_id)->child; ++ long long bytes = 0; ++ ++ while(1) { ++ file_buffer = cache_get(reader_buffer, 0, 0); ++ file_buffer->sequence = seq ++; ++ ++ byte = read_bytes(file, file_buffer->data, block_size); ++ if(byte == -1) ++ goto read_err; ++ ++ file_buffer->size = byte; ++ file_buffer->file_size = -1; ++ file_buffer->block = count ++; ++ file_buffer->error = FALSE; ++ file_buffer->fragment = FALSE; ++ bytes += byte; ++ ++ if(byte == 0) ++ break; ++ ++ /* ++ * Update estimated_uncompressed block count. This is done ++ * on every block rather than waiting for all blocks to be ++ * read incase write_file_process() is running in parallel ++ * with this. Otherwise cur uncompressed block count may ++ * get ahead of the total uncompressed block count. ++ */ ++ estimated_uncompressed ++; ++ ++ if(prev_buffer) ++ queue_put(from_reader, prev_buffer); ++ prev_buffer = file_buffer; ++ } ++ ++ /* ++ * Update inode file size now that the size of the dynamic pseudo file ++ * is known. This is needed for the -info option. ++ */ ++ dir_ent->inode->buf.st_size = bytes; ++ ++ res = waitpid(child, &status, 0); ++ if(res == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) ++ goto read_err; ++ ++ if(prev_buffer == NULL) ++ prev_buffer = file_buffer; ++ else { ++ cache_block_put(file_buffer); ++ seq --; ++ } ++ prev_buffer->file_size = bytes; ++ prev_buffer->fragment = !no_fragments && ++ (count == 2 || always_use_fragments) && (byte < block_size); ++ queue_put(from_reader, prev_buffer); ++ ++ return; ++ ++read_err: ++ if(prev_buffer) { ++ cache_block_put(file_buffer); ++ seq --; ++ file_buffer = prev_buffer; ++ } ++ file_buffer->error = TRUE; ++ queue_put(from_deflate, file_buffer); ++} ++ ++ + void reader_read_file(struct dir_ent *dir_ent) + { + struct stat *buf = &dir_ent->inode->buf, buf2; + struct file_buffer *file_buffer; +- static int index = 0; + int blocks, byte, count, expected, file, frag_block; + long long bytes, read_size; + +@@ -2202,7 +2222,7 @@ + if(file_buffer) + queue_put(from_reader, file_buffer); + file_buffer = cache_get(reader_buffer, 0, 0); +- file_buffer->sequence = index ++; ++ file_buffer->sequence = seq ++; + + byte = file_buffer->size = read_bytes(file, file_buffer->data, + block_size); +@@ -2238,7 +2258,7 @@ + + read_err: + file_buffer = cache_get(reader_buffer, 0, 0); +- file_buffer->sequence = index ++; ++ file_buffer->sequence = seq ++; + read_err2: + file_buffer->error = TRUE; + queue_put(from_deflate, file_buffer); +@@ -2262,9 +2282,14 @@ + for(i = 0; i < dir->count; i++) { + struct dir_ent *dir_ent = dir->list[i]; + struct stat *buf = &dir_ent->inode->buf; +- if(dir_ent->data) ++ if(dir_ent->inode->root_entry) + continue; + ++ if(dir_ent->inode->pseudo_file) { ++ reader_read_process(dir_ent); ++ continue; ++ } ++ + switch(buf->st_mode & S_IFMT) { + case S_IFREG: + reader_read_file(dir_ent); +@@ -2365,7 +2390,7 @@ + + void *deflator(void *arg) + { +- z_stream *stream = NULL; ++ void *stream = NULL; + int oldstate; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); +@@ -2402,7 +2427,7 @@ + + void *frag_deflator(void *arg) + { +- z_stream *stream = NULL; ++ void *stream = NULL; + int oldstate; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); +@@ -2426,8 +2451,8 @@ + write_buffer->block = bytes; + bytes += compressed_size; + fragments_outstanding --; +- pthread_mutex_unlock(&fragment_mutex); + queue_put(to_writer, write_buffer); ++ pthread_mutex_unlock(&fragment_mutex); + TRACE("Writing fragment %lld, uncompressed size %d, " + "compressed size %d\n", file_buffer->block, + file_buffer->size, compressed_size); +@@ -2674,6 +2699,98 @@ + } + + ++int write_file_process(squashfs_inode *inode, struct dir_ent *dir_ent, ++ struct file_buffer *read_buffer, int *duplicate_file) ++{ ++ long long read_size, file_bytes, start; ++ struct fragment *fragment; ++ unsigned int *block_list = NULL; ++ int block = 0, status; ++ long long sparse = 0; ++ struct file_buffer *fragment_buffer = NULL; ++ ++ *duplicate_file = FALSE; ++ ++ lock_fragments(); ++ ++ file_bytes = 0; ++ start = bytes; ++ while (1) { ++ read_size = read_buffer->file_size; ++ if(read_buffer->fragment && read_buffer->c_byte) ++ fragment_buffer = read_buffer; ++ else { ++ block_list = realloc(block_list, (block + 1) * ++ sizeof(unsigned int)); ++ if(block_list == NULL) ++ BAD_ERROR("Out of memory allocating block_list" ++ "\n"); ++ block_list[block ++] = read_buffer->c_byte; ++ if(read_buffer->c_byte) { ++ read_buffer->block = bytes; ++ bytes += read_buffer->size; ++ cache_rehash(read_buffer, read_buffer->block); ++ file_bytes += read_buffer->size; ++ queue_put(to_writer, read_buffer); ++ } else { ++ sparse += read_buffer->size; ++ cache_block_put(read_buffer); ++ } ++ } ++ inc_progress_bar(); ++ ++ if(read_size != -1) ++ break; ++ ++ read_buffer = get_file_buffer(from_deflate); ++ if(read_buffer->error) ++ goto read_err; ++ } ++ ++ unlock_fragments(); ++ fragment = get_and_fill_fragment(fragment_buffer); ++ cache_block_put(fragment_buffer); ++ ++ if(duplicate_checking) ++ add_non_dup(read_size, file_bytes, block_list, start, fragment, ++ 0, 0, FALSE); ++ file_count ++; ++ total_bytes += read_size; ++ ++ if(read_size < (1LL << 32) && start < (1LL << 32) && sparse == 0) ++ create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, ++ start, block, block_list, fragment, NULL, 0); ++ else ++ create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, ++ start, block, block_list, fragment, NULL, sparse); ++ ++ if(duplicate_checking == FALSE) ++ free(block_list); ++ ++ return 0; ++ ++read_err: ++ cur_uncompressed -= block; ++ status = read_buffer->error; ++ bytes = start; ++ if(!block_device) { ++ int res; ++ ++ queue_put(to_writer, NULL); ++ if(queue_get(from_writer) != 0) ++ EXIT_MKSQUASHFS(); ++ res = ftruncate(fd, bytes); ++ if(res != 0) ++ BAD_ERROR("Failed to truncate dest file because %s\n", ++ strerror(errno)); ++ } ++ unlock_fragments(); ++ free(block_list); ++ cache_block_put(read_buffer); ++ return status; ++} ++ ++ + int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, + long long read_size, struct file_buffer *read_buffer, + int *duplicate_file) +@@ -2941,7 +3058,10 @@ + + read_size = read_buffer->file_size; + +- if(read_size == 0) { ++ if(read_size == -1) ++ status = write_file_process(inode, dir_ent, read_buffer, ++ duplicate_file); ++ else if(read_size == 0) { + write_file_empty(inode, dir_ent, duplicate_file); + cache_block_put(read_buffer); + } else if(read_buffer->fragment && read_buffer->c_byte) +@@ -3036,6 +3156,8 @@ + + memcpy(&inode->buf, buf, sizeof(struct stat)); + inode->read = FALSE; ++ inode->root_entry = FALSE; ++ inode->pseudo_file = FALSE; + inode->inode = SQUASHFS_INVALID_BLK; + inode->nlink = 1; + +@@ -3056,7 +3178,7 @@ + + + inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, +- struct inode_info *inode_info, void *data, struct dir_info *dir) ++ struct inode_info *inode_info, struct dir_info *dir) + { + if((dir->count % DIR_ENTRIES) == 0) { + dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * +@@ -3075,8 +3197,7 @@ + NULL; + dir->list[dir->count]->inode = inode_info; + dir->list[dir->count]->dir = sub_dir; +- dir->list[dir->count]->our_dir = dir; +- dir->list[dir->count++]->data = data; ++ dir->list[dir->count++]->our_dir = dir; + dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); + } + +@@ -3128,10 +3249,10 @@ + + if(dir->count < old_root_entries) + for(i = 0; i < old_root_entries; i++) { +- if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) ++ if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) + dir->directory_count ++; +- add_dir_entry(old_root_entry[i].name, "", NULL, NULL, +- &old_root_entry[i], dir); ++ add_dir_entry(old_root_entry[i].name, "", NULL, ++ &old_root_entry[i].inode, dir); + } + + while(index < source) { +@@ -3167,10 +3288,10 @@ + + if(dir->count < old_root_entries) + for(i = 0; i < old_root_entries; i++) { +- if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) ++ if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) + dir->directory_count ++; +- add_dir_entry(old_root_entry[i].name, "", NULL, NULL, +- &old_root_entry[i], dir); ++ add_dir_entry(old_root_entry[i].name, "", NULL, ++ &old_root_entry[i].inode, dir); + } + + if((d_name = readdir(dir->linuxdir)) != NULL) { +@@ -3215,7 +3336,7 @@ + int current_count; + + while((current_count = dir_info->current_count++) < dir_info->count) +- if(dir_info->list[current_count]->data) ++ if(dir_info->list[current_count]->inode->root_entry) + continue; + else + return dir_info->list[current_count]; +@@ -3240,11 +3361,11 @@ + int current_count; + + while((current_count = dir_info->current_count++) < dir_info->count) +- if(dir_info->list[current_count]->data) +- add_dir(dir_info->list[current_count]->data->inode, +- dir_info->list[current_count]->data->inode_number, ++ if(dir_info->list[current_count]->inode->root_entry) ++ add_dir(dir_info->list[current_count]->inode->inode, ++ dir_info->list[current_count]->inode->inode_number, + dir_info->list[current_count]->name, +- dir_info->list[current_count]->data->type, dir); ++ dir_info->list[current_count]->inode->type, dir); + else + return dir_info->list[current_count]; + return NULL; +@@ -3313,7 +3434,6 @@ + dir_ent->name = dir_ent->pathname = strdup(pathname); + dir_ent->dir = dir_info; + dir_ent->our_dir = NULL; +- dir_ent->data = NULL; + dir_info->dir_ent = dir_ent; + + if(sorted) +@@ -3383,7 +3503,7 @@ + sub_dir = NULL; + + add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), +- NULL, dir); ++ dir); + } + + scan1_freedir(dir); +@@ -3399,7 +3519,7 @@ + struct dir_ent *dir_ent; + struct pseudo_entry *pseudo_ent; + struct stat buf; +- static pseudo_ino = 1; ++ static int pseudo_ino = 1; + + if(dir == NULL && (dir = scan1_opendir("")) == NULL) + return NULL; +@@ -3415,6 +3535,29 @@ + + while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) { + dir_ent = scan2_lookup(dir, pseudo_ent->name); ++ if(pseudo_ent->dev->type == 's') { ++ struct stat *buf; ++ if(dir_ent == NULL) { ++ ERROR("Pseudo set file \"%s\" does not exist " ++ "in source filesystem. Ignoring\n", ++ pseudo_ent->pathname); ++ continue; ++ } ++ if(dir_ent->inode->root_entry) { ++ ERROR("Pseudo set file \"%s\" is a pre-existing" ++ " file in the filesystem being appended" ++ " to. It cannot be modified. " ++ "Ignoring!\n", pseudo_ent->pathname); ++ continue; ++ } ++ buf = &dir_ent->inode->buf; ++ buf->st_mode = (buf->st_mode & S_IFMT) | ++ pseudo_ent->dev->mode; ++ buf->st_uid = pseudo_ent->dev->uid; ++ buf->st_gid = pseudo_ent->dev->gid; ++ continue; ++ } ++ + if(dir_ent) { + ERROR("Pseudo file \"%s\" exists in source filesystem " + "\"%s\"\n", pseudo_ent->pathname, +@@ -3444,8 +3587,29 @@ + buf.st_mtime = time(NULL); + buf.st_ino = pseudo_ino ++; + +- add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, +- lookup_inode(&buf), NULL, dir); ++ if(pseudo_ent->dev->type == 'f') { ++#ifdef USE_TMP_FILE ++ struct stat buf2; ++ int res = stat(pseudo_ent->dev->filename, &buf2); ++ if(res == -1) { ++ ERROR("Stat on pseudo file \"%s\" failed, " ++ "skipping...", pseudo_ent->pathname); ++ continue; ++ } ++ buf.st_size = buf2.st_size; ++ add_dir_entry(pseudo_ent->name, ++ pseudo_ent->dev->filename, sub_dir, ++ lookup_inode(&buf), dir); ++#else ++ struct inode_info *inode = lookup_inode(&buf); ++ inode->pseudo_id = pseudo_ent->dev->pseudo_id; ++ inode->pseudo_file = TRUE; ++ add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, ++ sub_dir, inode, dir); ++#endif ++ } else ++ add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, ++ sub_dir, lookup_inode(&buf), dir); + } + + scan2_freedir(dir); +@@ -3482,8 +3646,9 @@ + &duplicate_file); + INFO("file %s, uncompressed size %lld " + "bytes %s\n", filename, +- buf->st_size, duplicate_file ? +- "DUPLICATE" : ""); ++ (long long) buf->st_size, ++ duplicate_file ? "DUPLICATE" : ++ ""); + break; + + case S_IFDIR: +@@ -3557,6 +3722,7 @@ + INFO("file %s, uncompressed " + "size %lld bytes LINK" + "\n", filename, ++ (long long) + buf->st_size); + break; + case SQUASHFS_SYMLINK_TYPE: +@@ -3667,10 +3833,11 @@ + BAD_ERROR("Out of memory in old root directory entries " + "reallocation\n"); + +- strcpy(old_root_entry[old_root_entries].name, name); +- old_root_entry[old_root_entries].inode = inode; +- old_root_entry[old_root_entries].inode_number = inode_number; +- old_root_entry[old_root_entries++].type = type; ++ old_root_entry[old_root_entries].name = strdup(name); ++ old_root_entry[old_root_entries].inode.inode = inode; ++ old_root_entry[old_root_entries].inode.inode_number = inode_number; ++ old_root_entry[old_root_entries].inode.type = type; ++ old_root_entry[old_root_entries++].inode.root_entry = TRUE; + } + + +@@ -4137,7 +4304,7 @@ + + + #define VERSION() \ +- printf("mksquashfs version 4.0 (2009/04/05)\n");\ ++ printf("mksquashfs version 4.1-CVS (2009/09/20)\n");\ + printf("copyright (C) 2009 Phillip Lougher \n\n"); \ + printf("This program is free software; you can redistribute it and/or\n");\ + printf("modify it under the terms of the GNU General Public License\n");\ +@@ -4172,26 +4339,28 @@ + source_path = argv + 1; + source = i - 2; + for(; i < argc; i++) { +- if(strcmp(argv[i], "-pf") == 0) { ++ if(strcmp(argv[i], "-comp") == 0) { + if(++i == argc) { +- ERROR("%s: -pf missing filename\n", argv[0]); ++ ERROR("%s: -comp missing compression type\n", ++ argv[0]); + exit(1); + } +- if(read_pseudo_file(&pseudo, argv[i]) == FALSE) { +- ERROR("Failed to parse pseudo file \"%s\"\n", +- argv[i]); ++ comp_name = argv[i]; ++ } else if(strcmp(argv[i], "-pf") == 0) { ++ if(++i == argc) { ++ ERROR("%s: -pf missing filename\n", argv[0]); + exit(1); + } ++ if(read_pseudo_file(&pseudo, argv[i]) == FALSE) ++ exit(1); + } else if(strcmp(argv[i], "-p") == 0) { + if(++i == argc) { + ERROR("%s: -p missing pseudo file definition\n", argv[0]); exit(1); } -+#ifdef USE_LZMA -+ } else if(strcmp(argv[i], "-lzma") == 0) { -+ compression = LZMA_COMPRESSION; -+#endif - } else if(strcmp(argv[i], "-ef") == 0) { +- if(read_pseudo_def(&pseudo, argv[i]) == FALSE) { +- ERROR("Failed to parse pseudo definition\n"); ++ if(read_pseudo_def(&pseudo, argv[i]) == FALSE) + exit(1); +- } + } else if(strcmp(argv[i], "-recover") == 0) { if(++i == argc) { - ERROR("%s: -ef missing filename\n", argv[0]); -@@ -4410,6 +4483,9 @@ + ERROR("%s: -recover missing recovery file\n", +@@ -4394,34 +4563,16 @@ + printOptions: + ERROR("SYNTAX:%s source1 source2 ... dest [options] " + "[-e list of exclude\ndirs/files]\n", argv[0]); +- ERROR("\nOptions are\n"); +- ERROR("-version\t\tprint version, licence and " +- "copyright message\n"); +- ERROR("-recover \t\trecover filesystem data " +- "using recovery file \n"); +- ERROR("-no-recovery\t\tdon't generate a recovery " +- "file\n"); +- ERROR("-info\t\t\tprint files written to filesystem\n"); +- ERROR("-no-exports\t\tdon't make the filesystem " +- "exportable via NFS\n"); +- ERROR("-no-progress\t\tdon't display the progress " +- "bar\n"); +- ERROR("-no-sparse\t\tdon't detect sparse files\n"); ++ ERROR("\nFilesystem build options:\n"); ++ ERROR("-comp \t\tselect compression\n"); ++ ERROR("\t\t\tCompressors available:\n"); ++ display_compressors("\t\t\t", COMP_DEFAULT); ERROR("-b \t\tset data block to " ". Default %d bytes\n", SQUASHFS_FILE_SIZE); -+#ifdef USE_LZMA -+ ERROR("-lzma Enable LZMA compression\n"); -+#endif - ERROR("-processors \tUse processors." - " By default will use number of\n"); - ERROR("\t\t\tprocessors available\n"); -@@ -4804,7 +4880,7 @@ +- ERROR("-processors \tUse processors." +- " By default will use number of\n"); +- ERROR("\t\t\tprocessors available\n"); +- ERROR("-read-queue \tSet input queue to " +- "Mbytes. Default %d Mbytes\n", +- READER_BUFFER_DEFAULT); +- ERROR("-write-queue \tSet output queue to " +- "Mbytes. Default %d Mbytes\n", +- WRITER_BUFFER_DEFAULT); +- ERROR("-fragment-queue \tSet fagment queue to " +- " Mbytes. Default %d Mbytes\n", +- FRAGMENT_BUFFER_DEFAULT); ++ ERROR("-no-exports\t\tdon't make the filesystem " ++ "exportable via NFS\n"); ++ ERROR("-no-sparse\t\tdon't detect sparse files\n"); + ERROR("-noI\t\t\tdo not compress inode table\n"); + ERROR("-noD\t\t\tdo not compress data blocks\n"); + ERROR("-noF\t\t\tdo not compress fragment blocks\n"); +@@ -4430,13 +4581,34 @@ + "files larger than block size\n"); + ERROR("-no-duplicates\t\tdo not perform duplicate " + "checking\n"); +- ERROR("-noappend\t\tdo not append to existing " +- "filesystem\n"); ++ ERROR("-all-root\t\tmake all files owned by root\n"); ++ ERROR("-force-uid uid\t\tset all file uids to uid\n"); ++ ERROR("-force-gid gid\t\tset all file gids to gid\n"); ++ ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " ++ "of 4K\n"); + ERROR("-keep-as-directory\tif one source directory is " + "specified, create a root\n"); + ERROR("\t\t\tdirectory containing that directory, " + "rather than the\n"); + ERROR("\t\t\tcontents of the directory\n"); ++ ERROR("\nFilesystem filter options:\n"); ++ ERROR("-p \tAdd pseudo file definition\n"); ++ ERROR("-pf \tAdd list of pseudo file definitions\n"); ++ ERROR("-sort \tsort files according to " ++ "priorities in . One\n"); ++ ERROR("\t\t\tfile or dir with priority per line. " ++ "Priority -32768 to\n"); ++ ERROR("\t\t\t32767, default priority 0\n"); ++ ERROR("-ef \tlist of exclude dirs/files." ++ " One per line\n"); ++ ERROR("-wildcards\t\tAllow extended shell wildcards " ++ "(globbing) to be used in\n\t\t\texclude " ++ "dirs/files\n"); ++ ERROR("-regex\t\t\tAllow POSIX regular expressions to " ++ "be used in exclude\n\t\t\tdirs/files\n"); ++ ERROR("\nFilesystem append options:\n"); ++ ERROR("-noappend\t\tdo not append to existing " ++ "filesystem\n"); + ERROR("-root-becomes \twhen appending source " + "files/directories, make the\n"); + ERROR("\t\t\toriginal root become a subdirectory in " +@@ -4444,11 +4616,29 @@ + ERROR("\t\t\tcalled , rather than adding the new " + "source items\n"); + ERROR("\t\t\tto the original root\n"); +- ERROR("-all-root\t\tmake all files owned by root\n"); +- ERROR("-force-uid uid\t\tset all file uids to uid\n"); +- ERROR("-force-gid gid\t\tset all file gids to gid\n"); +- ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " +- "of 4K\n"); ++ ERROR("\nMksquashfs runtime options:\n"); ++ ERROR("-version\t\tprint version, licence and " ++ "copyright message\n"); ++ ERROR("-recover \t\trecover filesystem data " ++ "using recovery file \n"); ++ ERROR("-no-recovery\t\tdon't generate a recovery " ++ "file\n"); ++ ERROR("-info\t\t\tprint files written to filesystem\n"); ++ ERROR("-no-progress\t\tdon't display the progress " ++ "bar\n"); ++ ERROR("-processors \tUse processors." ++ " By default will use number of\n"); ++ ERROR("\t\t\tprocessors available\n"); ++ ERROR("-read-queue \tSet input queue to " ++ "Mbytes. Default %d Mbytes\n", ++ READER_BUFFER_DEFAULT); ++ ERROR("-write-queue \tSet output queue to " ++ "Mbytes. Default %d Mbytes\n", ++ WRITER_BUFFER_DEFAULT); ++ ERROR("-fragment-queue \tSet fagment queue to " ++ " Mbytes. Default %d Mbytes\n", ++ FRAGMENT_BUFFER_DEFAULT); ++ ERROR("\nMiscellaneous options:\n"); + ERROR("-root-owned\t\talternative name for -all-root" + "\n"); + ERROR("-noInodeCompression\talternative name for -noI" +@@ -4457,20 +4647,6 @@ + "\n"); + ERROR("-noFragmentCompression\talternative name for " + "-noF\n"); +- ERROR("-sort \tsort files according to " +- "priorities in . One\n"); +- ERROR("\t\t\tfile or dir with priority per line. " +- "Priority -32768 to\n"); +- ERROR("\t\t\t32767, default priority 0\n"); +- ERROR("-ef \tlist of exclude dirs/files." +- " One per line\n"); +- ERROR("-wildcards\t\tAllow extended shell wildcards " +- "(globbing) to be used in\n\t\t\texclude " +- "dirs/files\n"); +- ERROR("-regex\t\t\tAllow POSIX regular expressions to " +- "be used in exclude\n\t\t\tdirs/files\n"); +- ERROR("-p \tAdd pseudo file definition\n"); +- ERROR("-pf \tAdd list of pseudo file definitions\n"); + exit(1); + } + } +@@ -4548,11 +4724,10 @@ + fclose(fd); + } else if(strcmp(argv[i], "-e") == 0) + break; +- else if(strcmp(argv[i], "-b") == 0 || +- strcmp(argv[i], "-root-becomes") == 0 || ++ else if(strcmp(argv[i], "-root-becomes") == 0 || + strcmp(argv[i], "-sort") == 0 || + strcmp(argv[i], "-pf") == 0 || +- strcmp(argv[i], "-p") == 0) ++ strcmp(argv[i], "-comp") == 0) + i++; + + if(i != argc) { +@@ -4574,11 +4749,10 @@ + sorted ++; + } else if(strcmp(argv[i], "-e") == 0) + break; +- else if(strcmp(argv[i], "-b") == 0 || +- strcmp(argv[i], "-root-becomes") == 0 || ++ else if(strcmp(argv[i], "-root-becomes") == 0 || + strcmp(argv[i], "-ef") == 0 || + strcmp(argv[i], "-pf") == 0 || +- strcmp(argv[i], "-p") == 0) ++ strcmp(argv[i], "-comp") == 0) + i++; + + #ifdef SQUASHFS_TRACE +@@ -4586,7 +4760,8 @@ + #endif + + if(!delete) { +- if(read_super(fd, &sBlk, argv[source + 1]) == 0) { ++ comp = read_super(fd, &sBlk, argv[source + 1]); ++ if(comp == NULL) { + ERROR("Failed to read existing filesystem - will not " + "overwrite - ABORTING!\n"); + ERROR("To force Mksquashfs to write to this block " +@@ -4603,6 +4778,15 @@ + 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(); +@@ -4648,8 +4832,8 @@ + "size %d\n", SQUASHFS_MAJOR, s_minor, argv[source + 1], + block_size); + printf("All -b, -noI, -noD, -noF, no-duplicates, no-fragments, " +- "-always-use-fragments and -exportable options ignored" +- "\n"); ++ "-always-use-fragments,\n-exportable and -comp options " ++ "ignored\n"); + printf("\nIf appending is not wanted, please re-run with " + "-noappend specified!\n\n"); + +@@ -4803,8 +4987,7 @@ + sBlk.bytes_used = bytes; - /* Only compression supported */ +- /* Only compression supported */ - sBlk.compression = ZLIB_COMPRESSION; -+ sBlk.compression = compression; ++ sBlk.compression = comp->id; /* Xattrs are not currently supported */ sBlk.xattr_table_start = SQUASHFS_INVALID_BLK; -Index: squashfs4.0/squashfs-tools/squashfs_fs.h -=================================================================== ---- squashfs4.0.orig/squashfs-tools/squashfs_fs.h 2009-03-18 03:50:20.000000000 +0100 -+++ squashfs4.0/squashfs-tools/squashfs_fs.h 2009-09-14 17:20:36.310480350 +0200 -@@ -229,6 +229,7 @@ - typedef long long squashfs_inode_t; +@@ -4820,6 +5003,8 @@ - #define ZLIB_COMPRESSION 1 -+#define LZMA_COMPRESSION 2 + close(fd); - struct squashfs_super_block { - unsigned int s_magic; -Index: squashfs4.0/squashfs-tools/Makefile -=================================================================== ---- squashfs4.0.orig/squashfs-tools/Makefile 2009-04-05 04:03:36.000000000 +0200 -+++ squashfs4.0/squashfs-tools/Makefile 2009-09-14 17:20:36.310480350 +0200 -@@ -4,14 +4,20 @@ - - CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 - -+ifdef USE_LZMA -+ LZMA_CFLAGS = -DUSE_LZMA -+ LZMA_LIB = -llzma -+ CFLAGS += $(LZMA_CFLAGS) -+endif ++ delete_pseudo_files(); + - all: mksquashfs unsquashfs + if(recovery_file[0] != '\0') + unlink(recovery_file); --mksquashfs: mksquashfs.o read_fs.o sort.o swap.o pseudo.o -- $(CC) mksquashfs.o read_fs.o sort.o swap.o pseudo.o -lz -lpthread -lm -o $@ -+mksquashfs: mksquashfs.o read_fs.o sort.o swap.o pseudo.o uncompress.o -+ $(CC) mksquashfs.o read_fs.o sort.o swap.o pseudo.o uncompress.o -lz -lpthread -lm $(LZMA_LIB) -o $@ +@@ -4827,9 +5012,9 @@ + * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + + sizeof(squashfs_super_block); --mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h squashfs_swap.h Makefile -+mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h squashfs_swap.h uncompress.h Makefile +- printf("\n%sSquashfs %d.%d filesystem, data block size %d\n", +- exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR, +- block_size); ++ printf("\n%sSquashfs %d.%d filesystem, %s compressed, data block size" ++ " %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR, ++ SQUASHFS_MINOR, comp->name, block_size); + printf("\t%s data, %s metadata, %s fragments\n", + noD ? "uncompressed" : "compressed", noI ? "uncompressed" : + "compressed", no_fragments ? "no" : noF ? "uncompressed" : +diff -Nur squashfs4.0/squashfs-tools/pseudo.c squashfs4.0-lzma-snapshot/squashfs-tools/pseudo.c +--- squashfs4.0/squashfs-tools/pseudo.c 2009-04-05 04:01:58.000000000 +0200 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/pseudo.c 2009-10-20 06:03:38.000000000 +0200 +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include --read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h Makefile -+read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h uncompress.h Makefile + #include "pseudo.h" - sort.o: sort.c squashfs_fs.h global.h sort.h Makefile +@@ -55,6 +56,9 @@ + #define TRUE 1 + #define FALSE 0 -@@ -19,18 +25,20 @@ ++struct pseudo_dev **pseudo_file = NULL; ++int pseudo_count = 0; ++ + static void dump_pseudo(struct pseudo *pseudo, char *string) + { + int i; +@@ -99,7 +103,7 @@ + char *target, char *alltarget) + { + char targname[1024]; +- int i, error; ++ int i; - pseudo.o: pseudo.c pseudo.h Makefile + target = get_component(target, targname); --unsquashfs: unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o -- $(CC) unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o -lz -lpthread -lm -o $@ -+uncompress.o: uncompress.c uncompress.h +@@ -128,12 +132,8 @@ + if(target[0] == '\0') { + /* at leaf pathname component */ + pseudo->name[i].pseudo = NULL; +- pseudo->name[i].dev = malloc(sizeof(struct pseudo_dev)); +- if(pseudo->name[i].dev == NULL) +- BAD_ERROR("failed to allocate pseudo file\n"); + pseudo->name[i].pathname = strdup(alltarget); +- memcpy(pseudo->name[i].dev, pseudo_dev, +- sizeof(struct pseudo_dev)); ++ pseudo->name[i].dev = pseudo_dev; + } else { + /* recurse adding child components */ + pseudo->name[i].dev = NULL; +@@ -169,15 +169,9 @@ + if(target[0] == '\0') { + if(pseudo->name[i].dev == NULL && + pseudo_dev->type == 'd') { +- pseudo->name[i].dev = +- malloc(sizeof(struct pseudo_dev)); +- if(pseudo->name[i].dev == NULL) +- BAD_ERROR("failed to allocate " +- "pseudo file\n"); + pseudo->name[i].pathname = + strdup(alltarget); +- memcpy(pseudo->name[i].dev, pseudo_dev, +- sizeof(struct pseudo_dev)); ++ pseudo->name[i].dev = pseudo_dev; + } else + ERROR("%s already exists as a " + "directory. Ignoring %s!\n", +@@ -229,16 +223,113 @@ + } + + ++int exec_file(char *command, struct pseudo_dev *dev) ++{ ++ int child, res; ++ static pid_t pid = -1; ++ int pipefd[2]; ++#ifdef USE_TMP_FILE ++ char filename[1024]; ++ int status; ++ static int number = 0; ++#endif ++ ++ if(pid == -1) ++ pid = getpid(); ++ ++#ifdef USE_TMP_FILE ++ sprintf(filename, "/tmp/squashfs_pseudo_%d_%d", pid, number ++); ++ pipefd[1] = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); ++ if(pipefd[1] == -1) { ++ printf("open failed\n"); ++ return -1; ++ } ++#else ++ res = pipe(pipefd); ++ if(res == -1) { ++ printf("pipe failed\n"); ++ return -1; ++ } ++#endif ++ ++ child = fork(); ++ if(child == -1) { ++ printf("fork failed\n"); ++ goto failed; ++ } ++ ++ if(child == 0) { ++ close(STDOUT_FILENO); ++ res = dup(pipefd[1]); ++ if(res == -1) { ++ printf("dup failed\n"); ++ exit(EXIT_FAILURE); ++ } ++ execl("/bin/sh", "sh", "-c", command, (char *) NULL); ++ printf("execl failed\n"); ++ exit(EXIT_FAILURE); ++ } ++ ++#ifdef USE_TMP_FILE ++ res = waitpid(child, &status, 0); ++ close(pipefd[1]); ++ if(res != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0) { ++ dev->filename = strdup(filename); ++ return 0; ++ } ++failed: ++ unlink(filename); ++ return -1; ++#else ++ close(pipefd[1]); ++ dev->fd = pipefd[0]; ++ dev->child = child; ++ return 0; ++failed: ++ return -1; ++#endif ++} ++ ++ ++void add_pseudo_file(struct pseudo_dev *dev) ++{ ++ pseudo_file = realloc(pseudo_file, (pseudo_count + 1) * ++ sizeof(struct pseudo_dev *)); ++ if(pseudo_file == NULL) ++ BAD_ERROR("Failed to realloc pseudo_file\n"); ++ ++ dev->pseudo_id = pseudo_count; ++ pseudo_file[pseudo_count ++] = dev; ++} + -+unsquashfs: unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o uncompress.o -+ $(CC) unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o uncompress.o -lz -lpthread -lm $(LZMA_LIB) -o $@ ++ ++void delete_pseudo_files() ++{ ++#ifdef USE_TMP_FILE ++ int i; ++ ++ for(i = 0; i < pseudo_count; i++) ++ unlink(pseudo_file[i]->filename); ++#endif ++} ++ ++ ++struct pseudo_dev *get_pseudo_file(int pseudo_id) ++{ ++ return pseudo_file[pseudo_id]; ++} ++ ++ + int read_pseudo_def(struct pseudo **pseudo, char *def) + { +- int n; ++ int n, bytes; + unsigned int major = 0, minor = 0, mode; + char filename[2048], type, suid[100], sgid[100], *ptr; + long long uid, gid; +- struct pseudo_dev dev; ++ struct pseudo_dev *dev; --unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h squashfs_compat.h global.h Makefile -+unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h squashfs_compat.h global.h uncompress.h Makefile +- n = sscanf(def, "%s %c %o %s %s %u %u", filename, &type, &mode, suid, sgid, +- &major, &minor); ++ n = sscanf(def, "%s %c %o %s %s %n", filename, &type, &mode, suid, ++ sgid, &bytes); --unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h global.h Makefile -+unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h global.h uncompress.h Makefile + if(n < 5) { + ERROR("Not enough or invalid arguments in pseudo file " +@@ -249,7 +340,9 @@ + switch(type) { + case 'b': + case 'c': +- if(n < 7) { ++ n = sscanf(def + bytes, "%u %u", &major, &minor); ++ ++ if(n < 2) { + ERROR("Not enough or invalid arguments in pseudo file " + "definition\n"); + goto error; +@@ -265,47 +358,15 @@ + goto error; + } --unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h squashfs_compat.h global.h Makefile -+unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h squashfs_compat.h global.h uncompress.h Makefile +- /* fall through */ +- case 'd': +- if(mode > 0777) { +- ERROR("Mode %o out of range\n", mode); ++ case 'f': ++ if(def[bytes] == '\0') { ++ ERROR("Not enough arguments in pseudo file " ++ "definition\n"); + goto error; +- } +- +- uid = strtoll(suid, &ptr, 10); +- if(*ptr == '\0') { +- if(uid < 0 || uid > ((1LL << 32) - 1)) { +- ERROR("Uid %s out of range\n", suid); +- goto error; +- } +- } else { +- struct passwd *pwuid = getpwnam(suid); +- if(pwuid) +- uid = pwuid->pw_uid; +- else { +- ERROR("Uid %s invalid uid or unknown user\n", +- suid); +- goto error; +- } +- } +- +- gid = strtoll(sgid, &ptr, 10); +- if(*ptr == '\0') { +- if(gid < 0 || gid > ((1LL << 32) - 1)) { +- ERROR("Gid %s out of range\n", sgid); +- goto error; +- } +- } else { +- struct group *grgid = getgrnam(sgid); +- if(grgid) +- gid = grgid->gr_gid; +- else { +- ERROR("Gid %s invalid uid or unknown user\n", +- sgid); +- goto error; +- } +- } +- ++ } ++ break; ++ case 'd': ++ case 'm': + break; + default: + ERROR("Unsupported type %c\n", type); +@@ -313,6 +374,43 @@ + } --unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h global.h Makefile -+unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h global.h uncompress.h Makefile --unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h global.h Makefile -+unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h global.h uncompress.h Makefile ++ if(mode > 0777) { ++ ERROR("Mode %o out of range\n", mode); ++ goto error; ++ } ++ ++ uid = strtoll(suid, &ptr, 10); ++ if(*ptr == '\0') { ++ if(uid < 0 || uid > ((1LL << 32) - 1)) { ++ ERROR("Uid %s out of range\n", suid); ++ goto error; ++ } ++ } else { ++ struct passwd *pwuid = getpwnam(suid); ++ if(pwuid) ++ uid = pwuid->pw_uid; ++ else { ++ ERROR("Uid %s invalid uid or unknown user\n", suid); ++ goto error; ++ } ++ } ++ ++ gid = strtoll(sgid, &ptr, 10); ++ if(*ptr == '\0') { ++ if(gid < 0 || gid > ((1LL << 32) - 1)) { ++ ERROR("Gid %s out of range\n", sgid); ++ goto error; ++ } ++ } else { ++ struct group *grgid = getgrnam(sgid); ++ if(grgid) ++ gid = grgid->gr_gid; ++ else { ++ ERROR("Gid %s invalid uid or unknown user\n", sgid); ++ goto error; ++ } ++ } ++ + switch(type) { + case 'b': + mode |= S_IFBLK; +@@ -323,16 +421,37 @@ + case 'd': + mode |= S_IFDIR; + break; ++ case 'f': ++ mode |= S_IFREG; ++ break; + } - clean: - -rm -f *.o mksquashfs unsquashfs -Index: squashfs4.0/squashfs-tools/read_fs.c -=================================================================== ---- squashfs4.0.orig/squashfs-tools/read_fs.c 2009-03-31 06:23:14.000000000 +0200 -+++ squashfs4.0/squashfs-tools/read_fs.c 2009-09-14 17:20:36.310480350 +0200 -@@ -51,6 +51,7 @@ +- dev.type = type; +- dev.mode = mode; +- dev.uid = uid; +- dev.gid = gid; +- dev.major = major; +- dev.minor = minor; ++ dev = malloc(sizeof(struct pseudo_dev)); ++ if(dev == NULL) ++ BAD_ERROR("Failed to create pseudo_dev\n"); ++ ++ dev->type = type; ++ dev->mode = mode; ++ dev->uid = uid; ++ dev->gid = gid; ++ dev->major = major; ++ dev->minor = minor; ++ ++ if(type == 'f') { ++ int res; ++ ++ printf("Executing dynamic pseudo file\n"); ++ printf("\t\"%s\"\n", def); ++ res = exec_file(def + bytes, dev); ++ if(res == -1) { ++ ERROR("Failed to execute dynamic pseudo file definition" ++ " \"%s\"\n", def); ++ return FALSE; ++ } ++ add_pseudo_file(dev); ++ } + +- *pseudo = add_pseudo(*pseudo, &dev, filename, filename); ++ *pseudo = add_pseudo(*pseudo, dev, filename, filename); + + return TRUE; + +diff -Nur squashfs4.0/squashfs-tools/pseudo.h squashfs4.0-lzma-snapshot/squashfs-tools/pseudo.h +--- squashfs4.0/squashfs-tools/pseudo.h 2009-04-04 03:44:24.000000000 +0200 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/pseudo.h 2009-10-20 06:03:38.000000000 +0200 +@@ -27,6 +27,12 @@ + unsigned int gid; + unsigned int major; + unsigned int minor; ++ int pseudo_id; ++ int fd; ++ int child; ++#ifdef USE_TMP_FILE ++ char *filename; ++#endif + }; + + struct pseudo_entry { +@@ -46,3 +52,5 @@ + extern int read_pseudo_file(struct pseudo **, char *); + extern struct pseudo *pseudo_subdir(char *, struct pseudo *); + extern struct pseudo_entry *pseudo_readdir(struct pseudo *); ++extern struct pseudo_dev *get_pseudo_file(int); ++extern void delete_pseudo_files(); +diff -Nur squashfs4.0/squashfs-tools/read_fs.c squashfs4.0-lzma-snapshot/squashfs-tools/read_fs.c +--- squashfs4.0/squashfs-tools/read_fs.c 2009-03-31 06:23:14.000000000 +0200 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/read_fs.c 2009-10-20 06:03:38.000000000 +0200 +@@ -36,7 +36,6 @@ + #include + #include + #include +-#include + #include + + #ifndef linux +@@ -51,6 +50,7 @@ #include "squashfs_swap.h" #include "read_fs.h" #include "global.h" -+#include "uncompress.h" ++#include "compressor.h" #include -@@ -83,17 +84,17 @@ +@@ -66,7 +66,9 @@ + fprintf(stderr, s, ## args); \ + } while(0) + +-int read_block(int fd, long long start, long long *next, unsigned char *block, ++static struct compressor *comp; ++ ++int read_block(int fd, long long start, long long *next, void *block, + squashfs_super_block *sBlk) + { + unsigned short c_byte; +@@ -77,32 +79,24 @@ + + if(SQUASHFS_COMPRESSED(c_byte)) { + char buffer[SQUASHFS_METADATA_SIZE]; +- int res; +- unsigned long bytes = SQUASHFS_METADATA_SIZE; ++ int error, res; + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); read_destination(fd, start + offset, c_byte, buffer); - res = uncompress(block, &bytes, (const unsigned char *) buffer, - c_byte); -+ res = uncompress_wrapper(block, &bytes, -+ (const unsigned char *) buffer, c_byte); - if(res != Z_OK) { - if(res == Z_MEM_ERROR) +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough " -+ ERROR("uncompress failed, not enough " - "memory\n"); - else if(res == Z_BUF_ERROR) +- "memory\n"); +- else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough " -+ ERROR("uncompress failed, not enough " - "room in output buffer\n"); - else +- "room in output buffer\n"); +- else - ERROR("zlib::uncompress failed, unknown error " -+ ERROR("uncompress failed, unknown error " - "%d\n", res); +- "%d\n", res); ++ res = comp->uncompress(block, buffer, c_byte, ++ SQUASHFS_METADATA_SIZE, &error); ++ if(res == -1) { ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); return 0; } -Index: squashfs4.0/squashfs-tools/unsquashfs.c -=================================================================== ---- squashfs4.0.orig/squashfs-tools/unsquashfs.c 2009-04-05 23:23:06.000000000 +0200 -+++ squashfs4.0/squashfs-tools/unsquashfs.c 2009-09-14 17:20:36.310480350 +0200 -@@ -24,6 +24,7 @@ - #include "unsquashfs.h" + if(next) + *next = start + offset + c_byte; +- return bytes; ++ return res; + } else { + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); +- read_destination(fd, start + offset, c_byte, (char *) block); ++ read_destination(fd, start + offset, c_byte, block); + if(next) + *next = start + offset + c_byte; + return c_byte; +@@ -356,7 +350,7 @@ + } + + +-int read_super(int fd, squashfs_super_block *sBlk, char *source) ++struct compressor *read_super(int fd, squashfs_super_block *sBlk, char *source) + { + read_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block), + (char *) sBlk); +@@ -388,8 +382,18 @@ + goto failed_mount; + } + ++ /* Check the compression type */ ++ comp = lookup_compressor_id(sBlk->compression); ++ if(!comp->supported) { ++ ERROR("Filesystem on %s uses %s compression, this is" ++ "unsupported by this version\n", source, comp->name); ++ display_compressors("", ""); ++ goto failed_mount; ++ } ++ + printf("Found a valid %sSQUASHFS superblock on %s.\n", + SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source); ++ printf("\tCompression used %s\n", comp->name); + printf("\tInodes are %scompressed\n", + SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); + printf("\tData is %scompressed\n", +@@ -417,10 +421,10 @@ + TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start); + printf("\n"); + +- return TRUE; ++ return comp; + + failed_mount: +- return FALSE; ++ return NULL; + } + + +@@ -514,12 +518,17 @@ + SQUASHFS_INSWAP_ID_BLOCKS(index, indexes); + + for(i = 0; i < indexes; i++) { +- int length; +- length = read_block(fd, index[i], NULL, ++ int length = read_block(fd, index[i], NULL, + ((unsigned char *) id_table) + + (i * SQUASHFS_METADATA_SIZE), sBlk); + TRACE("Read id table block %d, from 0x%llx, length %d\n", i, + index[i], length); ++ if(length == 0) { ++ ERROR("Failed to read id table block %d, from 0x%llx, " ++ "length %d\n", i, index[i], length); ++ free(id_table); ++ return NULL; ++ } + } + + SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids); +@@ -563,6 +572,13 @@ + (i * SQUASHFS_METADATA_SIZE), sBlk); + TRACE("Read fragment table block %d, from 0x%llx, length %d\n", + i, fragment_table_index[i], length); ++ if(length == 0) { ++ ERROR("Failed to read fragment table block %d, from " ++ "0x%llx, length %d\n", i, ++ fragment_table_index[i], length); ++ free(*fragment_table); ++ return 0; ++ } + } + + for(i = 0; i < sBlk->fragments; i++) +@@ -599,6 +615,13 @@ + (i * SQUASHFS_METADATA_SIZE), sBlk); + TRACE("Read inode lookup table block %d, from 0x%llx, length " + "%d\n", i, index[i], length); ++ if(length == 0) { ++ ERROR("Failed to read inode lookup table block %d, " ++ "from 0x%llx, length %d\n", i, index[i], ++ length); ++ free(*inode_lookup_table); ++ return 0; ++ } + } + + SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes); +diff -Nur squashfs4.0/squashfs-tools/sort.c squashfs4.0-lzma-snapshot/squashfs-tools/sort.c +--- squashfs4.0/squashfs-tools/sort.c 2009-03-31 06:25:53.000000000 +0200 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/sort.c 2009-10-20 06:03:38.000000000 +0200 +@@ -198,7 +198,7 @@ + while(dir->current_count < dir->count) { + struct dir_ent *dir_ent = dir->list[dir->current_count++]; + struct stat *buf = &dir_ent->inode->buf; +- if(dir_ent->data) ++ if(dir_ent->inode->root_entry) + continue; + + switch(buf->st_mode & S_IFMT) { +@@ -254,6 +254,7 @@ + write_file(&inode, entry->dir, &duplicate_file); + INFO("file %s, uncompressed size %lld bytes %s" + "\n", entry->dir->pathname, ++ (long long) + entry->dir->inode->buf.st_size, + duplicate_file ? "DUPLICATE" : ""); + entry->dir->inode->inode = inode; +@@ -261,6 +262,7 @@ + } else + INFO("file %s, uncompressed size %lld bytes " + "LINK\n", entry->dir->pathname, ++ (long long) + entry->dir->inode->buf.st_size); + } + } +diff -Nur squashfs4.0/squashfs-tools/sort.h squashfs4.0-lzma-snapshot/squashfs-tools/sort.h +--- squashfs4.0/squashfs-tools/sort.h 2009-02-08 13:02:53.000000000 +0100 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/sort.h 2009-10-20 06:03:38.000000000 +0200 +@@ -42,17 +42,19 @@ + struct inode_info *inode; + struct dir_info *dir; + struct dir_info *our_dir; +- struct old_root_entry_info *data; + }; + + struct inode_info { +- unsigned int nlink; + struct stat buf; ++ struct inode_info *next; + squashfs_inode inode; +- unsigned int type; + unsigned int inode_number; ++ unsigned int nlink; ++ int pseudo_id; ++ char type; + char read; +- struct inode_info *next; ++ char root_entry; ++ char pseudo_file; + }; + + struct priority_entry { +diff -Nur squashfs4.0/squashfs-tools/squashfs_compat.h squashfs4.0-lzma-snapshot/squashfs-tools/squashfs_compat.h +--- squashfs4.0/squashfs-tools/squashfs_compat.h 2009-03-16 05:27:27.000000000 +0100 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/squashfs_compat.h 2009-10-20 06:03:38.000000000 +0200 +@@ -777,11 +777,10 @@ + #endif + + #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ +- int bits;\ +- int b_pos = pos % 8;\ +- unsigned long long val = 0;\ +- unsigned char *s = (unsigned char *)p + (pos / 8);\ +- unsigned char *d = ((unsigned char *) &val) + 7;\ ++ b_pos = pos % 8;\ ++ val = 0;\ ++ s = (unsigned char *)p + (pos / 8);\ ++ d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +diff -Nur squashfs4.0/squashfs-tools/squashfs_fs.h squashfs4.0-lzma-snapshot/squashfs-tools/squashfs_fs.h +--- squashfs4.0/squashfs-tools/squashfs_fs.h 2009-03-18 03:50:20.000000000 +0100 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/squashfs_fs.h 2009-10-20 06:03:38.000000000 +0200 +@@ -229,6 +229,7 @@ + typedef long long squashfs_inode_t; + + #define ZLIB_COMPRESSION 1 ++#define LZMA_COMPRESSION 2 + + struct squashfs_super_block { + unsigned int s_magic; +diff -Nur squashfs4.0/squashfs-tools/unsquash-3.c squashfs4.0-lzma-snapshot/squashfs-tools/unsquash-3.c +--- squashfs4.0/squashfs-tools/unsquash-3.c 2009-03-31 06:35:10.000000000 +0200 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/unsquash-3.c 2009-10-20 06:03:38.000000000 +0200 +@@ -36,7 +36,7 @@ + sBlk.fragment_table_start); + + if(sBlk.fragments == 0) +- return; ++ return TRUE; + + if((fragment_table = malloc(sBlk.fragments * + sizeof(squashfs_fragment_entry_3))) == NULL) +diff -Nur squashfs4.0/squashfs-tools/unsquash-4.c squashfs4.0-lzma-snapshot/squashfs-tools/unsquash-4.c +--- squashfs4.0/squashfs-tools/unsquash-4.c 2009-03-31 06:38:31.000000000 +0200 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/unsquash-4.c 2009-10-20 06:03:38.000000000 +0200 +@@ -38,7 +38,7 @@ + sBlk.fragment_table_start); + + if(sBlk.fragments == 0) +- return; ++ return TRUE; + + if((fragment_table = malloc(sBlk.fragments * + sizeof(squashfs_fragment_entry))) == NULL) +diff -Nur squashfs4.0/squashfs-tools/unsquashfs.c squashfs4.0-lzma-snapshot/squashfs-tools/unsquashfs.c +--- squashfs4.0/squashfs-tools/unsquashfs.c 2009-04-05 23:23:06.000000000 +0200 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/unsquashfs.c 2009-10-20 06:03:39.000000000 +0200 +@@ -25,6 +25,9 @@ #include "squashfs_swap.h" #include "squashfs_compat.h" -+#include "uncompress.h" #include "read_fs.h" ++#include "compressor.h" ++ ++#include struct cache *fragment_cache, *data_cache; -@@ -597,18 +598,17 @@ + struct queue *to_reader, *to_deflate, *to_writer, *from_writer; +@@ -36,6 +39,7 @@ + + struct super_block sBlk; + squashfs_operations s_ops; ++struct compressor *comp; + + int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, + dev_count = 0, fifo_count = 0; +@@ -590,31 +594,23 @@ + offset = 3; + if(SQUASHFS_COMPRESSED(c_byte)) { + char buffer[SQUASHFS_METADATA_SIZE]; +- int res; +- unsigned long bytes = SQUASHFS_METADATA_SIZE; ++ int error, res; + + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); if(read_bytes(start + offset, c_byte, buffer) == FALSE) goto failed; - res = uncompress((unsigned char *) block, &bytes, -+ res = uncompress_wrapper((unsigned char *) block, &bytes, - (const unsigned char *) buffer, c_byte); -- - if(res != Z_OK) { - if(res == Z_MEM_ERROR) +- (const unsigned char *) buffer, c_byte); ++ res = comp->uncompress(block, buffer, c_byte, ++ SQUASHFS_METADATA_SIZE, &error); + +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough " -+ ERROR("uncompress failed, not enough " - "memory\n"); - else if(res == Z_BUF_ERROR) +- "memory\n"); +- else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough " -+ ERROR("uncompress failed, not enough " - "room in output buffer\n"); - else +- "room in output buffer\n"); +- else - ERROR("zlib::uncompress failed, unknown error " -+ ERROR("uncompress failed, unknown error " - "%d\n", res); +- "%d\n", res); ++ if(res == -1) { ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); goto failed; } -@@ -645,18 +645,17 @@ + if(next) + *next = start + offset + c_byte; +- return bytes; ++ return res; + } else { + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + if(read_bytes(start + offset, c_byte, block) == FALSE) +@@ -632,36 +628,26 @@ + + int read_data_block(long long start, unsigned int size, char *block) + { +- int res; +- unsigned long bytes = block_size; ++ int error, res; + int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); + + TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, +- SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), +- SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : ++ c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" : + "uncompressed"); + + if(SQUASHFS_COMPRESSED_BLOCK(size)) { if(read_bytes(start, c_byte, data) == FALSE) goto failed; - res = uncompress((unsigned char *) block, &bytes, -+ res = uncompress_wrapper((unsigned char *) block, &bytes, - (const unsigned char *) data, c_byte); -- - if(res != Z_OK) { - if(res == Z_MEM_ERROR) +- (const unsigned char *) data, c_byte); ++ res = comp->uncompress(block, data, c_byte, block_size, &error); + +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough " -+ ERROR("uncompress failed, not enough " - "memory\n"); - else if(res == Z_BUF_ERROR) +- "memory\n"); +- else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough " -+ ERROR("uncompress failed, not enough " - "room in output buffer\n"); - else +- "room in output buffer\n"); +- else - ERROR("zlib::uncompress failed, unknown error " -+ ERROR("uncompress failed, unknown error " - "%d\n", res); +- "%d\n", res); ++ if(res == -1) { ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); goto failed; } -@@ -1459,7 +1458,7 @@ + +- return bytes; ++ return res; + } else { + if(read_bytes(start, c_byte, block) == FALSE) + goto failed; +@@ -671,7 +657,7 @@ + + failed: + ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, +- size); ++ c_byte); + return FALSE; + } + +@@ -1383,6 +1369,11 @@ + #endif + printf("Creation or last append time %s", mkfs_str ? mkfs_str : + "failed to get time\n"); ++ printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", ++ sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); ++ if(sBlk.s_major == 4) ++ printf("Compression %s\n", comp->name); ++ printf("Block size %d\n", sBlk.block_size); + printf("Filesystem is %sexportable via NFS\n", + SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); + +@@ -1409,9 +1400,6 @@ + SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); + else + printf("Duplicates are removed\n"); +- printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", +- sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); +- printf("Block size %d\n", sBlk.block_size); + if(sBlk.s_major > 1) + printf("Number of fragments %d\n", sBlk.fragments); + printf("Number of inodes %d\n", sBlk.inodes); +@@ -1459,6 +1447,18 @@ s_ops.read_inode = read_inode_4; s_ops.read_uids_guids = read_uids_guids_4; memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); -- return TRUE; -+ goto done; ++ ++ /* ++ * Check the compression type ++ */ ++ comp = lookup_compressor_id(sBlk.compression); ++ if(!comp->supported) { ++ ERROR("Filesystem uses %s compression, this is " ++ "unsupported by this version\n", comp->name); ++ ERROR("Decompressors available:\n"); ++ display_compressors("", ""); ++ goto failed_mount; ++ } + return TRUE; } - /* -@@ -1548,6 +1547,9 @@ +@@ -1548,6 +1548,11 @@ goto failed_mount; } -+done: -+ compression = sBlk.compression; -+ ++ /* ++ * 1.x, 2.x and 3.x filesystems use gzip compression. Gzip is always ++ * suppported. ++ */ ++ comp = lookup_compressor("gzip"); return TRUE; failed_mount: -@@ -1710,19 +1712,19 @@ - int res; - unsigned long bytes = block_size; +@@ -1707,32 +1712,24 @@ -- res = uncompress((unsigned char *) tmp, &bytes, -+ res = uncompress_wrapper((unsigned char *) tmp, &bytes, - (const unsigned char *) entry->data, - SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size)); + while(1) { + struct cache_entry *entry = queue_get(to_deflate); +- int res; +- unsigned long bytes = block_size; ++ int error, res; - if(res != Z_OK) { - if(res == Z_MEM_ERROR) +- res = uncompress((unsigned char *) tmp, &bytes, +- (const unsigned char *) entry->data, +- SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size)); +- +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) - ERROR("zlib::uncompress failed, not enough" -+ ERROR("uncompress failed, not enough" - "memory\n"); - else if(res == Z_BUF_ERROR) +- "memory\n"); +- else if(res == Z_BUF_ERROR) - ERROR("zlib::uncompress failed, not enough " -+ ERROR("uncompress failed, not enough " - "room in output buffer\n"); - else +- "room in output buffer\n"); +- else - ERROR("zlib::uncompress failed, unknown error " -+ ERROR("uncompress failed, unknown error " - "%d\n", res); - } else - memcpy(entry->data, tmp, bytes); -Index: squashfs4.0/squashfs-tools/mksquashfs.h -=================================================================== ---- squashfs4.0.orig/squashfs-tools/mksquashfs.h 2009-02-19 19:31:08.000000000 +0100 -+++ squashfs4.0/squashfs-tools/mksquashfs.h 2009-09-14 17:20:36.310480350 +0200 -@@ -41,4 +41,9 @@ - #define SQUASHFS_SWAP_LONG_LONGS(s, d, n) \ - memcpy(d, s, n * sizeof(long long)) - #endif -+ -+extern int uncompress_wrapper(unsigned char *dest, unsigned long *dest_len, -+ const unsigned char *src, unsigned long src_len); -+ -+ - #endif -Index: squashfs4.0/squashfs-tools/uncompress.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ squashfs4.0/squashfs-tools/uncompress.c 2009-09-14 17:20:36.310480350 +0200 -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (c) 2009 Felix Fietkau -+ * -+ * 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. -+ * -+ * uncompress.c -+ */ -+ -+ -+ -+#ifdef USE_LZMA -+#include -+#endif -+#include -+#include "squashfs_fs.h" -+ -+/* compression algorithm */ -+int compression = ZLIB_COMPRESSION; -+ -+ -+int uncompress_wrapper(unsigned char *dest, unsigned long *dest_len, -+ const unsigned char *src, unsigned long src_len) -+{ -+ int res; -+ -+#ifdef USE_LZMA -+ if (compression == LZMA_COMPRESSION) { -+ size_t slen = src_len - LZMA_PROPS_SIZE; -+ res = LzmaUncompress((unsigned char *)dest, dest_len, -+ (const unsigned char *) src + LZMA_PROPS_SIZE, &slen, -+ (const unsigned char *) src, LZMA_PROPS_SIZE); -+ switch(res) { -+ case SZ_OK: -+ res = Z_OK; -+ break; -+ case SZ_ERROR_MEM: -+ res = Z_MEM_ERROR; -+ break; -+ } -+ } else -+#endif -+ res = uncompress(dest, dest_len, src, src_len); -+ return res; -+} -+ -+ -Index: squashfs4.0/squashfs-tools/uncompress.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ squashfs4.0/squashfs-tools/uncompress.h 2009-09-14 17:20:36.310480350 +0200 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (c) 2009 Felix Fietkau -+ * -+ * 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. -+ * -+ * uncompress.h -+ */ -+ -+#ifdef USE_LZMA -+#include -+#endif -+ -+extern int compression; -+extern int uncompress_wrapper(unsigned char *dest, unsigned long *dest_len, -+ const unsigned char *src, unsigned long src_len); -+ +- "%d\n", res); +- } else +- memcpy(entry->data, tmp, bytes); ++ res = comp->uncompress(tmp, entry->data, ++ SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, ++ &error); + ++ if(res == -1) ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); ++ else ++ memcpy(entry->data, tmp, res); + + /* + * block has been either successfully decompressed, or an error + * occurred, clear pending flag, set error appropriately and + * wake up any threads waiting on this block + */ +- cache_block_ready(entry, res != Z_OK); ++ cache_block_ready(entry, res == -1); + } + } + +@@ -1913,7 +1910,7 @@ + + + #define VERSION() \ +- printf("unsquashfs version 4.0 (2009/04/05)\n");\ ++ printf("unsquashfs version 4.1-CVS (2009/08/30)\n");\ + printf("copyright (C) 2009 Phillip Lougher "\ + "\n\n");\ + printf("This program is free software; you can redistribute it and/or\n");\ +@@ -1938,7 +1935,6 @@ + int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; + int data_buffer_size = DATA_BUFFER_DEFAULT; + char *b; +- struct winsize winsize; + + pthread_mutex_init(&screen_mutex, NULL); + root_process = geteuid() == 0; +@@ -2087,6 +2083,8 @@ + "regular expressions\n"); + ERROR("\t\t\t\trather than use the default shell " + "wildcard\n\t\t\t\texpansion (globbing)\n"); ++ ERROR("\nDecompressors available:\n"); ++ display_compressors("", ""); + } + exit(1); + } +diff -Nur squashfs4.0/squashfs-tools/unsquashfs.h squashfs4.0-lzma-snapshot/squashfs-tools/unsquashfs.h +--- squashfs4.0/squashfs-tools/unsquashfs.h 2009-03-29 04:29:02.000000000 +0200 ++++ squashfs4.0-lzma-snapshot/squashfs-tools/unsquashfs.h 2009-10-20 06:03:39.000000000 +0200 +@@ -31,7 +31,6 @@ + #include + #include + #include +-#include + #include + #include + #include -- 2.25.1