wok rev 4702

squashfs: add lzma support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Jan 03 18:38:54 2010 +0100 (2010-01-03)
parents 0c0c693fe4c6
children 335b02e4e8c8
files squashfs/receipt squashfs/stuff/lzma.u
line diff
     1.1 --- a/squashfs/receipt	Sun Jan 03 17:41:36 2010 +0100
     1.2 +++ b/squashfs/receipt	Sun Jan 03 18:38:54 2010 +0100
     1.3 @@ -19,6 +19,16 @@
     1.4  
     1.5  	cd $src/squashfs-tools
     1.6  	mkdir -p ../_pkg/usr/sbin ../_pkg/sbin
     1.7 +	if [ ! -d ../LZMA/lzma465 ]; then
     1.8 +		SF_MIRROR=http://switch.dl.sourceforge.net/sourceforge
     1.9 +		[ -s lzma465.tar.bz2 ] || 
    1.10 +		wget $SF_MIRROR/sevenzip/lzma465.tar.bz2
    1.11 +		mkdir -p ../LZMA/lzma465
    1.12 +		tar xjf lzma465.tar.bz2 -C ../LZMA/lzma465
    1.13 +	fi
    1.14 +	if [ ! -f lzma_wrapper.c ]; then
    1.15 +		patch -p2 -i ../../stuff/lzma.u
    1.16 +	fi
    1.17  	make || return 1
    1.18  	cp mksquashfs ../_pkg/usr/sbin
    1.19  	cp unsquashfs ../_pkg/sbin
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/squashfs/stuff/lzma.u	Sun Jan 03 18:38:54 2010 +0100
     2.3 @@ -0,0 +1,2235 @@
     2.4 +--- squashfs-4.0/squashfs-tools/Makefile
     2.5 ++++ squashfs-4.0/squashfs-tools/Makefile
     2.6 +@@ -1,40 +1,76 @@
     2.7 ++#
     2.8 ++# Building LZMA support
     2.9 ++# Download LZMA sdk (4.65 used in development, other versions may work),
    2.10 ++# set LZMA_DIR to unpacked source, and uncomment next line
    2.11 ++LZMA_SUPPORT = 1
    2.12 ++LZMA_DIR = ../LZMA/lzma465
    2.13 ++
    2.14 ++#Compression default.
    2.15 ++COMP_DEFAULT = gzip
    2.16 ++
    2.17 ++INCLUDEDIR = -I.
    2.18 + INSTALL_DIR = /usr/local/bin
    2.19 + 
    2.20 +-INCLUDEDIR = .
    2.21 ++MKSQUASHFS_OBJS = mksquashfs.o read_fs.o sort.o swap.o pseudo.o compressor.o \
    2.22 ++	gzip_wrapper.o
    2.23 + 
    2.24 +-CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2
    2.25 ++UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \
    2.26 ++	unsquash-4.o swap.o compressor.o gzip_wrapper.o
    2.27 + 
    2.28 ++CFLAGS = $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
    2.29 ++	-D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" -O2 -Wall
    2.30 ++
    2.31 ++ifdef LZMA_SUPPORT
    2.32 ++LZMA_OBJS = $(LZMA_DIR)/C/Alloc.o $(LZMA_DIR)/C/LzFind.o \
    2.33 ++	$(LZMA_DIR)/C/LzmaDec.o $(LZMA_DIR)/C/LzmaEnc.o $(LZMA_DIR)/C/LzmaLib.o
    2.34 ++INCLUDEDIR += -I$(LZMA_DIR)/C
    2.35 ++CFLAGS += -DLZMA_SUPPORT
    2.36 ++MKSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS)
    2.37 ++UNSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS)
    2.38 ++endif
    2.39 ++
    2.40 ++.PHONY: all
    2.41 + all: mksquashfs unsquashfs
    2.42 + 
    2.43 +-mksquashfs: mksquashfs.o read_fs.o sort.o swap.o pseudo.o
    2.44 +-	$(CC) mksquashfs.o read_fs.o sort.o swap.o pseudo.o -lz -lpthread -lm -o $@
    2.45 ++mksquashfs: $(MKSQUASHFS_OBJS)
    2.46 ++	$(CC) $(MKSQUASHFS_OBJS) -lz -lpthread -lm -o $@
    2.47 + 
    2.48 +-mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h squashfs_swap.h Makefile
    2.49 ++mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \
    2.50 ++	squashfs_swap.h
    2.51 + 
    2.52 +-read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h Makefile
    2.53 ++read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h
    2.54 + 
    2.55 +-sort.o: sort.c squashfs_fs.h global.h sort.h Makefile
    2.56 ++sort.o: sort.c squashfs_fs.h global.h sort.h
    2.57 + 
    2.58 +-swap.o: swap.c Makefile
    2.59 ++swap.o: swap.c
    2.60 + 
    2.61 +-pseudo.o: pseudo.c pseudo.h Makefile
    2.62 ++pseudo.o: pseudo.c pseudo.h
    2.63 + 
    2.64 +-unsquashfs: unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o
    2.65 +-	$(CC) unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o -lz -lpthread -lm -o $@
    2.66 ++compressor.o: compressor.c compressor.h
    2.67 + 
    2.68 +-unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h squashfs_compat.h global.h Makefile
    2.69 ++unsquashfs: $(UNSQUASHFS_OBJS)
    2.70 ++	$(CC) $(UNSQUASHFS_OBJS) -lz -lpthread -lm -o $@
    2.71 + 
    2.72 +-unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h global.h Makefile
    2.73 ++unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h \
    2.74 ++	squashfs_compat.h global.h
    2.75 + 
    2.76 +-unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h squashfs_compat.h global.h Makefile
    2.77 ++unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h \
    2.78 ++	global.h
    2.79 + 
    2.80 +-unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h global.h Makefile
    2.81 ++unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h \
    2.82 ++	squashfs_compat.h global.h
    2.83 + 
    2.84 +-unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h global.h Makefile
    2.85 ++unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h \
    2.86 ++	global.h
    2.87 + 
    2.88 ++unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h \
    2.89 ++	global.h
    2.90 ++
    2.91 ++.PHONY: clean
    2.92 + clean:
    2.93 + 	-rm -f *.o mksquashfs unsquashfs
    2.94 + 
    2.95 ++.PHONY: install
    2.96 + install: mksquashfs unsquashfs
    2.97 + 	mkdir -p $(INSTALL_DIR)
    2.98 + 	cp mksquashfs $(INSTALL_DIR)
    2.99 +
   2.100 +--- squashfs-4.0/squashfs-tools/compressor.c	Thu Jan  1 01:00:00 1970
   2.101 ++++ squashfs-4.0/squashfs-tools/compressor.c	Sat Aug 29 03:05:34 2009
   2.102 +@@ -0,0 +1,78 @@
   2.103 ++/*
   2.104 ++ *
   2.105 ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
   2.106 ++ * Phillip Lougher <phillip@lougher.demon.co.uk>
   2.107 ++ *
   2.108 ++ * This program is free software; you can redistribute it and/or
   2.109 ++ * modify it under the terms of the GNU General Public License
   2.110 ++ * as published by the Free Software Foundation; either version 2,
   2.111 ++ * or (at your option) any later version.
   2.112 ++ *
   2.113 ++ * This program is distributed in the hope that it will be useful,
   2.114 ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
   2.115 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   2.116 ++ * GNU General Public License for more details.
   2.117 ++ *
   2.118 ++ * You should have received a copy of the GNU General Public License
   2.119 ++ * along with this program; if not, write to the Free Software
   2.120 ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   2.121 ++ *
   2.122 ++ * compressor.c
   2.123 ++ */
   2.124 ++
   2.125 ++#include <stdio.h>
   2.126 ++#include <string.h>
   2.127 ++#include "compressor.h"
   2.128 ++#include "squashfs_fs.h"
   2.129 ++
   2.130 ++extern int gzip_compress(void **, char *, char *, int, int, int *);
   2.131 ++extern int gzip_uncompress(char *, char *, int, int, int *);
   2.132 ++extern int lzma_compress(void **, char *, char *, int, int, int *);
   2.133 ++extern int lzma_uncompress(char *, char *, int, int, int *);
   2.134 ++
   2.135 ++struct compressor compressor[] = {
   2.136 ++	{ gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 },
   2.137 ++#ifdef LZMA_SUPPORT
   2.138 ++	{ lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 },
   2.139 ++#else
   2.140 ++	{ NULL, NULL, LZMA_COMPRESSION, "lzma", 0 },
   2.141 ++#endif
   2.142 ++	{ NULL, NULL , 0, "unknown", 0}
   2.143 ++};
   2.144 ++
   2.145 ++
   2.146 ++struct compressor *lookup_compressor(char *name)
   2.147 ++{
   2.148 ++	int i;
   2.149 ++
   2.150 ++	for(i = 0; compressor[i].id; i++)
   2.151 ++		if(strcmp(compressor[i].name, name) == 0)
   2.152 ++			break;
   2.153 ++
   2.154 ++	return &compressor[i];
   2.155 ++}
   2.156 ++
   2.157 ++
   2.158 ++struct compressor *lookup_compressor_id(int id)
   2.159 ++{
   2.160 ++	int i;
   2.161 ++
   2.162 ++	for(i = 0; compressor[i].id; i++)
   2.163 ++		if(id == compressor[i].id)
   2.164 ++			break;
   2.165 ++
   2.166 ++	return &compressor[i];
   2.167 ++}
   2.168 ++
   2.169 ++
   2.170 ++void display_compressors(char *indent, char *def_comp)
   2.171 ++{
   2.172 ++	int i;
   2.173 ++
   2.174 ++	for(i = 0; compressor[i].id; i++)
   2.175 ++		if(compressor[i].supported)
   2.176 ++			fprintf(stderr, "%s\t%s%s\n", indent,
   2.177 ++				compressor[i].name,
   2.178 ++				strcmp(compressor[i].name, def_comp) == 0 ?
   2.179 ++				" (default)" : "");
   2.180 ++}
   2.181 +
   2.182 +--- squashfs-4.0/squashfs-tools/compressor.h	Thu Jan  1 01:00:00 1970
   2.183 ++++ squashfs-4.0/squashfs-tools/compressor.h	Mon Aug 24 20:28:04 2009
   2.184 +@@ -0,0 +1,33 @@
   2.185 ++/*
   2.186 ++ *
   2.187 ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
   2.188 ++ * Phillip Lougher <phillip@lougher.demon.co.uk>
   2.189 ++ *
   2.190 ++ * This program is free software; you can redistribute it and/or
   2.191 ++ * modify it under the terms of the GNU General Public License
   2.192 ++ * as published by the Free Software Foundation; either version 2,
   2.193 ++ * or (at your option) any later version.
   2.194 ++ *
   2.195 ++ * This program is distributed in the hope that it will be useful,
   2.196 ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
   2.197 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   2.198 ++ * GNU General Public License for more details.
   2.199 ++ *
   2.200 ++ * You should have received a copy of the GNU General Public License
   2.201 ++ * along with this program; if not, write to the Free Software
   2.202 ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   2.203 ++ *
   2.204 ++ * compressor.h
   2.205 ++ */
   2.206 ++
   2.207 ++struct compressor {
   2.208 ++	int (*compress)(void **, char *, char *, int, int, int *);
   2.209 ++	int (*uncompress)(char *, char *, int, int, int *);
   2.210 ++	int id;
   2.211 ++	char *name;
   2.212 ++	int supported;
   2.213 ++};
   2.214 ++
   2.215 ++extern struct compressor *lookup_compressor(char *);
   2.216 ++extern struct compressor *lookup_compressor_id(int);
   2.217 ++extern void display_compressors(char *, char *);
   2.218 +
   2.219 +--- squashfs-4.0/squashfs-tools/gzip_wrapper.c	Thu Jan  1 01:00:00 1970
   2.220 ++++ squashfs-4.0/squashfs-tools/gzip_wrapper.c	Fri Aug  7 22:12:53 2009
   2.221 +@@ -0,0 +1,80 @@
   2.222 ++/*
   2.223 ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
   2.224 ++ * Phillip Lougher <phillip@lougher.demon.co.uk>
   2.225 ++ *
   2.226 ++ * This program is free software; you can redistribute it and/or
   2.227 ++ * modify it under the terms of the GNU General Public License
   2.228 ++ * as published by the Free Software Foundation; either version 2,
   2.229 ++ * or (at your option) any later version.
   2.230 ++ *
   2.231 ++ * This program is distributed in the hope that it will be useful,
   2.232 ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
   2.233 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   2.234 ++ * GNU General Public License for more details.
   2.235 ++ *
   2.236 ++ * You should have received a copy of the GNU General Public License
   2.237 ++ * along with this program; if not, write to the Free Software
   2.238 ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   2.239 ++ *
   2.240 ++ * gzip_wrapper.c
   2.241 ++ */
   2.242 ++
   2.243 ++#include <stdlib.h>
   2.244 ++#include <zlib.h>
   2.245 ++
   2.246 ++int gzip_compress(void **strm, char *d, char *s, int size, int block_size,
   2.247 ++		int *error)
   2.248 ++{
   2.249 ++	int res = 0;
   2.250 ++	z_stream *stream = *strm;
   2.251 ++
   2.252 ++	if(stream == NULL) {
   2.253 ++		if((stream = *strm = malloc(sizeof(z_stream))) == NULL)
   2.254 ++			goto failed;
   2.255 ++
   2.256 ++		stream->zalloc = Z_NULL;
   2.257 ++		stream->zfree = Z_NULL;
   2.258 ++		stream->opaque = 0;
   2.259 ++
   2.260 ++		if((res = deflateInit(stream, 9)) != Z_OK)
   2.261 ++			goto failed;
   2.262 ++	} else if((res = deflateReset(stream)) != Z_OK)
   2.263 ++		goto failed;
   2.264 ++
   2.265 ++	stream->next_in = (unsigned char *) s;
   2.266 ++	stream->avail_in = size;
   2.267 ++	stream->next_out = (unsigned char *) d;
   2.268 ++	stream->avail_out = block_size;
   2.269 ++
   2.270 ++	res = deflate(stream, Z_FINISH);
   2.271 ++	if(res == Z_STREAM_END)
   2.272 ++		/*
   2.273 ++		 * Success, return the compressed size.
   2.274 ++		 */
   2.275 ++		return (int) stream->total_out;
   2.276 ++	if(res == Z_OK)
   2.277 ++		/*
   2.278 ++		 * Output buffer overflow.  Return out of buffer space
   2.279 ++		 */
   2.280 ++		return 0;
   2.281 ++failed:
   2.282 ++	/*
   2.283 ++	 * All other errors return failure, with the compressor
   2.284 ++	 * specific error code in *error
   2.285 ++	 */
   2.286 ++	*error = res;
   2.287 ++	return -1;
   2.288 ++}
   2.289 ++
   2.290 ++
   2.291 ++int gzip_uncompress(char *d, char *s, int size, int block_size, int *error)
   2.292 ++{
   2.293 ++	int res;
   2.294 ++	unsigned long bytes = block_size;
   2.295 ++
   2.296 ++	res = uncompress((unsigned char *) d, &bytes,
   2.297 ++		(const unsigned char *) s, size);
   2.298 ++
   2.299 ++	*error = res;
   2.300 ++	return res == Z_OK ? (int) bytes : -1;
   2.301 ++}
   2.302 +
   2.303 +--- squashfs-4.0/squashfs-tools/lzma_wrapper.c	Thu Jan  1 01:00:00 1970
   2.304 ++++ squashfs-4.0/squashfs-tools/lzma_wrapper.c	Wed Oct 14 05:32:57 2009
   2.305 +@@ -0,0 +1,93 @@
   2.306 ++/*
   2.307 ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
   2.308 ++ * Phillip Lougher <phillip@lougher.demon.co.uk>
   2.309 ++ *
   2.310 ++ * This program is free software; you can redistribute it and/or
   2.311 ++ * modify it under the terms of the GNU General Public License
   2.312 ++ * as published by the Free Software Foundation; either version 2,
   2.313 ++ * or (at your option) any later version.
   2.314 ++ *
   2.315 ++ * This program is distributed in the hope that it will be useful,
   2.316 ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
   2.317 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   2.318 ++ * GNU General Public License for more details.
   2.319 ++ *
   2.320 ++ * You should have received a copy of the GNU General Public License
   2.321 ++ * along with this program; if not, write to the Free Software
   2.322 ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   2.323 ++ *
   2.324 ++ * lzma_wrapper.c
   2.325 ++ */
   2.326 ++
   2.327 ++#include <LzmaLib.h>
   2.328 ++
   2.329 ++#define LZMA_HEADER_SIZE	(LZMA_PROPS_SIZE + 8)
   2.330 ++
   2.331 ++int lzma_compress(void **strm, char *dest, char *src,  int size,int block_size,
   2.332 ++		int *error)
   2.333 ++{
   2.334 ++	unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
   2.335 ++	size_t props_size = LZMA_PROPS_SIZE,
   2.336 ++		outlen = block_size - LZMA_HEADER_SIZE;
   2.337 ++	int res;
   2.338 ++
   2.339 ++	res = LzmaCompress(d + LZMA_HEADER_SIZE, &outlen, s, size, d,
   2.340 ++		&props_size, 5, block_size, 3, 0, 2, 32, 1);
   2.341 ++	
   2.342 ++	if(res == SZ_ERROR_OUTPUT_EOF) {
   2.343 ++		/*
   2.344 ++		 * Output buffer overflow.  Return out of buffer space error
   2.345 ++		 */
   2.346 ++		return 0;
   2.347 ++	}
   2.348 ++
   2.349 ++	if(res != SZ_OK) {
   2.350 ++		/*
   2.351 ++		 * All other errors return failure, with the compressor
   2.352 ++		 * specific error code in *error
   2.353 ++		 */
   2.354 ++		*error = res;
   2.355 ++		return -1;
   2.356 ++	}
   2.357 ++
   2.358 ++	/*
   2.359 ++	 * Fill in the 8 byte little endian uncompressed size field in the
   2.360 ++	 * LZMA header.  8 bytes is excessively large for squashfs but
   2.361 ++	 * this is the standard LZMA header and which is expected by the kernel
   2.362 ++	 * code
   2.363 ++	 */
   2.364 ++	d[LZMA_PROPS_SIZE] = size & 255;
   2.365 ++	d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255;
   2.366 ++	d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255;
   2.367 ++	d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255;
   2.368 ++	d[LZMA_PROPS_SIZE + 4] = 0;
   2.369 ++	d[LZMA_PROPS_SIZE + 5] = 0;
   2.370 ++	d[LZMA_PROPS_SIZE + 6] = 0;
   2.371 ++	d[LZMA_PROPS_SIZE + 7] = 0;
   2.372 ++
   2.373 ++	/*
   2.374 ++	 * Success, return the compressed size.  Outlen returned by the LZMA
   2.375 ++	 * compressor does not include the LZMA header space
   2.376 ++	 */
   2.377 ++	return outlen + LZMA_HEADER_SIZE;
   2.378 ++}
   2.379 ++
   2.380 ++
   2.381 ++int lzma_uncompress(char *dest, char *src, int size, int block_size,
   2.382 ++	int *error)
   2.383 ++{
   2.384 ++	unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
   2.385 ++	size_t outlen, inlen = size - LZMA_HEADER_SIZE;
   2.386 ++	int res;
   2.387 ++
   2.388 ++	outlen = s[LZMA_PROPS_SIZE] |
   2.389 ++		(s[LZMA_PROPS_SIZE + 1] << 8) |
   2.390 ++		(s[LZMA_PROPS_SIZE + 2] << 16) |
   2.391 ++		(s[LZMA_PROPS_SIZE + 3] << 24);
   2.392 ++
   2.393 ++	res = LzmaUncompress(d, &outlen, s + LZMA_HEADER_SIZE, &inlen,
   2.394 ++		s, LZMA_PROPS_SIZE);
   2.395 ++	
   2.396 ++	*error = res;
   2.397 ++	return res == SZ_OK ? outlen : -1;
   2.398 ++}
   2.399 +
   2.400 +--- squashfs-4.0/squashfs-tools/mksquashfs.c	Sun Apr  5 23:22:48 2009
   2.401 ++++ squashfs-4.0/squashfs-tools/mksquashfs.c	Tue Dec  8 19:02:54 2009
   2.402 +@@ -36,7 +36,6 @@
   2.403 + #include <errno.h>
   2.404 + #include <dirent.h>
   2.405 + #include <string.h>
   2.406 +-#include <zlib.h>
   2.407 + #include <stdlib.h>
   2.408 + #include <signal.h>
   2.409 + #include <setjmp.h>
   2.410 +@@ -47,6 +46,7 @@
   2.411 + #include <math.h>
   2.412 + #include <regex.h>
   2.413 + #include <fnmatch.h>
   2.414 ++#include <sys/wait.h>
   2.415 + 
   2.416 + #ifndef linux
   2.417 + #define __BYTE_ORDER BYTE_ORDER
   2.418 +@@ -64,6 +64,7 @@
   2.419 + #include "global.h"
   2.420 + #include "sort.h"
   2.421 + #include "pseudo.h"
   2.422 ++#include "compressor.h"
   2.423 + 
   2.424 + #ifdef SQUASHFS_TRACE
   2.425 + #define TRACE(s, args...)	do { \
   2.426 +@@ -245,10 +246,8 @@
   2.427 + /* list of root directory entries read from original filesystem */
   2.428 + int old_root_entries = 0;
   2.429 + struct old_root_entry_info {
   2.430 +-	char			name[SQUASHFS_NAME_LEN + 1];
   2.431 +-	squashfs_inode		inode;
   2.432 +-	int			type;
   2.433 +-	int			inode_number;
   2.434 ++	char			*name;
   2.435 ++	struct inode_info	inode;
   2.436 + };
   2.437 + struct old_root_entry_info *old_root_entry;
   2.438 + 
   2.439 +@@ -371,10 +370,15 @@
   2.440 + int reader_buffer_size;
   2.441 + int fragment_buffer_size;
   2.442 + 
   2.443 ++/* compression operations structure */
   2.444 ++static struct compressor *comp;
   2.445 ++char *comp_name = COMP_DEFAULT;
   2.446 ++
   2.447 + char *read_from_disk(long long start, unsigned int avail_bytes);
   2.448 + void add_old_root_entry(char *name, squashfs_inode inode, int inode_number,
   2.449 + 	int type);
   2.450 +-extern int read_super(int fd, squashfs_super_block *sBlk, char *source);
   2.451 ++extern struct compressor  *read_super(int fd, squashfs_super_block *sBlk,
   2.452 ++	char *source);
   2.453 + extern long long read_filesystem(char *root_name, int fd,
   2.454 + 	squashfs_super_block *sBlk, char **cinode_table, char **data_cache,
   2.455 + 	char **cdirectory_table, char **directory_data_cache,
   2.456 +@@ -831,83 +835,32 @@
   2.457 + }
   2.458 + 
   2.459 + 
   2.460 +-unsigned int mangle2(z_stream **strm, char *d, char *s, int size,
   2.461 ++int mangle2(void **strm, char *d, char *s, int size,
   2.462 + 	int block_size, int uncompressed, int data_block)
   2.463 + {
   2.464 +-	unsigned long c_byte;
   2.465 +-	unsigned int res;
   2.466 +-	z_stream *stream = *strm;
   2.467 ++	int error, c_byte = 0;
   2.468 + 
   2.469 +-	if(uncompressed)
   2.470 +-		goto notcompressed;
   2.471 +-
   2.472 +-	if(stream == NULL) {
   2.473 +-		if((stream = *strm = malloc(sizeof(z_stream))) == NULL)
   2.474 +-			BAD_ERROR("mangle::compress failed, not enough "
   2.475 +-				"memory\n");
   2.476 +-
   2.477 +-		stream->zalloc = Z_NULL;
   2.478 +-		stream->zfree = Z_NULL;
   2.479 +-		stream->opaque = 0;
   2.480 +-
   2.481 +-		if((res = deflateInit(stream, 9)) != Z_OK) {
   2.482 +-			if(res == Z_MEM_ERROR)
   2.483 +-				BAD_ERROR("zlib::compress failed, not enough "
   2.484 +-					"memory\n");
   2.485 +-			else if(res == Z_STREAM_ERROR)
   2.486 +-				BAD_ERROR("zlib::compress failed, not a valid "
   2.487 +-					"compression level\n");
   2.488 +-			else if(res == Z_VERSION_ERROR)
   2.489 +-				BAD_ERROR("zlib::compress failed, incorrect "
   2.490 +-					"zlib version\n");
   2.491 +-			else
   2.492 +-				BAD_ERROR("zlib::compress failed, unknown "
   2.493 +-					"error %d\n", res);
   2.494 +-		}
   2.495 +-	} else if((res = deflateReset(stream)) != Z_OK) {
   2.496 +-		if(res == Z_STREAM_ERROR)
   2.497 +-			BAD_ERROR("zlib::compress failed, stream state "
   2.498 +-				"inconsistent\n");
   2.499 +-		else
   2.500 +-			BAD_ERROR("zlib::compress failed, unknown error %d\n",
   2.501 +-				res);
   2.502 ++	if(!uncompressed) {
   2.503 ++		c_byte = comp->compress(strm, d, s, size, block_size, &error);
   2.504 ++		if(c_byte == -1)
   2.505 ++			BAD_ERROR("mangle2:: %s compress failed with error "
   2.506 ++				"code %d\n", comp->name, error);
   2.507 + 	}
   2.508 + 
   2.509 +-	stream->next_in = (unsigned char *) s;
   2.510 +-	stream->avail_in = size;
   2.511 +-	stream->next_out = (unsigned char *) d;
   2.512 +-	stream->avail_out = block_size;
   2.513 +-
   2.514 +-	res = deflate(stream, Z_FINISH);
   2.515 +-	if(res != Z_STREAM_END && res != Z_OK) {
   2.516 +-		if(res == Z_STREAM_ERROR)
   2.517 +-			BAD_ERROR("zlib::compress failed, stream state "
   2.518 +-				"inconsistent\n");
   2.519 +-		else if(res == Z_BUF_ERROR)
   2.520 +-			BAD_ERROR("zlib::compress failed, no progress possible"
   2.521 +-				"\n");
   2.522 +-		else
   2.523 +-			BAD_ERROR("zlib::compress failed, unknown error %d\n",
   2.524 +-				res);
   2.525 +-	}
   2.526 +-
   2.527 +-	c_byte = stream->total_out;
   2.528 +-
   2.529 +-	if(res != Z_STREAM_END || c_byte >= size) {
   2.530 +-notcompressed:
   2.531 ++	if(c_byte == 0 || c_byte >= size) {
   2.532 + 		memcpy(d, s, size);
   2.533 + 		return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK :
   2.534 + 			SQUASHFS_COMPRESSED_BIT);
   2.535 + 	}
   2.536 + 
   2.537 +-	return (unsigned int) c_byte;
   2.538 ++	return c_byte;
   2.539 + }
   2.540 + 
   2.541 + 
   2.542 +-unsigned int mangle(char *d, char *s, int size, int block_size,
   2.543 ++int mangle(char *d, char *s, int size, int block_size,
   2.544 + 	int uncompressed, int data_block)
   2.545 + {
   2.546 +-	static z_stream *stream = NULL;
   2.547 ++	static void *stream = NULL;
   2.548 + 
   2.549 + 	return mangle2(&stream, d, s, size, block_size, uncompressed,
   2.550 + 		data_block);
   2.551 +@@ -1660,8 +1613,7 @@
   2.552 + 	pthread_mutex_unlock(&fragment_mutex);
   2.553 + 
   2.554 + 	if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) {
   2.555 +-		int res;
   2.556 +-		unsigned long bytes = block_size;
   2.557 ++		int error, res;
   2.558 + 		char *data;
   2.559 + 
   2.560 + 		if(compressed_buffer)
   2.561 +@@ -1669,19 +1621,11 @@
   2.562 + 		else
   2.563 + 			data = read_from_disk(start_block, size);
   2.564 + 
   2.565 +-		res = uncompress((unsigned char *) buffer->data, &bytes,
   2.566 +-			(const unsigned char *) data, size);
   2.567 +-		if(res != Z_OK) {
   2.568 +-			if(res == Z_MEM_ERROR)
   2.569 +-				BAD_ERROR("zlib::uncompress failed, not enough "
   2.570 +-					"memory\n");
   2.571 +-			else if(res == Z_BUF_ERROR)
   2.572 +-				BAD_ERROR("zlib::uncompress failed, not enough "
   2.573 +-					"room in output buffer\n");
   2.574 +-			else
   2.575 +-				BAD_ERROR("zlib::uncompress failed,"
   2.576 +-					"  unknown error %d\n", res);
   2.577 +-		}
   2.578 ++		res = comp->uncompress(buffer->data, data, size, block_size,
   2.579 ++			&error);
   2.580 ++		if(res == -1)
   2.581 ++			BAD_ERROR("%s uncompress failed with error code %d\n",
   2.582 ++				comp->name, error);
   2.583 + 	} else if(compressed_buffer)
   2.584 + 		memcpy(buffer->data, compressed_buffer->data, size);
   2.585 + 	else
   2.586 +@@ -1733,9 +1677,7 @@
   2.587 + 		entry->buffer->block = bytes;
   2.588 + 		bytes += compressed_size;
   2.589 + 		fragments_outstanding --;
   2.590 +-		pthread_mutex_unlock(&fragment_mutex);
   2.591 + 		queue_put(to_writer, entry->buffer);
   2.592 +-		pthread_mutex_lock(&fragment_mutex);
   2.593 + 		TRACE("fragment_locked writing fragment %d, compressed size %d"
   2.594 + 			"\n", entry->fragment, compressed_size);
   2.595 + 		free(entry);
   2.596 +@@ -1758,6 +1700,8 @@
   2.597 + 	pthread_mutex_lock(&fragment_mutex);
   2.598 + 	insert_fragment_list(&frag_locked_list, entry);
   2.599 + 	pthread_mutex_unlock(&fragment_mutex);
   2.600 ++
   2.601 ++	return TRUE;
   2.602 + }
   2.603 + 
   2.604 + 
   2.605 +@@ -1824,7 +1768,9 @@
   2.606 + 	unsigned short c_byte;
   2.607 + 	char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2];
   2.608 + 	
   2.609 ++#ifdef SQUASHFS_TRACE
   2.610 + 	long long obytes = bytes;
   2.611 ++#endif
   2.612 + 
   2.613 + 	for(i = 0; i < meta_blocks; i++) {
   2.614 + 		int avail_bytes = length > SQUASHFS_METADATA_SIZE ?
   2.615 +@@ -2170,11 +2116,85 @@
   2.616 + }
   2.617 + 
   2.618 + 
   2.619 ++static int seq = 0;
   2.620 ++void reader_read_process(struct dir_ent *dir_ent)
   2.621 ++{
   2.622 ++	struct file_buffer *prev_buffer = NULL, *file_buffer;
   2.623 ++	int status, res, byte, count = 0;
   2.624 ++	int file = get_pseudo_file(dir_ent->inode->pseudo_id)->fd;
   2.625 ++	int child = get_pseudo_file(dir_ent->inode->pseudo_id)->child;
   2.626 ++	long long bytes = 0;
   2.627 ++
   2.628 ++	while(1) {
   2.629 ++		file_buffer = cache_get(reader_buffer, 0, 0);
   2.630 ++		file_buffer->sequence = seq ++;
   2.631 ++
   2.632 ++		byte = read_bytes(file, file_buffer->data, block_size);
   2.633 ++		if(byte == -1)
   2.634 ++			goto read_err;
   2.635 ++
   2.636 ++		file_buffer->size = byte;
   2.637 ++		file_buffer->file_size = -1;
   2.638 ++		file_buffer->block = count ++;
   2.639 ++		file_buffer->error = FALSE;
   2.640 ++		file_buffer->fragment = FALSE;
   2.641 ++		bytes += byte;
   2.642 ++
   2.643 ++		if(byte == 0)
   2.644 ++			break;
   2.645 ++
   2.646 ++		/*
   2.647 ++		 * Update estimated_uncompressed block count.  This is done
   2.648 ++		 * on every block rather than waiting for all blocks to be
   2.649 ++		 * read incase write_file_process() is running in parallel
   2.650 ++		 * with this.  Otherwise cur uncompressed block count may
   2.651 ++		 * get ahead of the total uncompressed block count.
   2.652 ++		 */ 
   2.653 ++		estimated_uncompressed ++;
   2.654 ++
   2.655 ++		if(prev_buffer)
   2.656 ++			queue_put(from_reader, prev_buffer);
   2.657 ++		prev_buffer = file_buffer;
   2.658 ++	}
   2.659 ++
   2.660 ++	/*
   2.661 ++ 	 * Update inode file size now that the size of the dynamic pseudo file
   2.662 ++	 * is known.  This is needed for the -info option.
   2.663 ++	 */
   2.664 ++	dir_ent->inode->buf.st_size = bytes;
   2.665 ++
   2.666 ++	res = waitpid(child, &status, 0);
   2.667 ++	if(res == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
   2.668 ++		goto read_err;
   2.669 ++
   2.670 ++	if(prev_buffer == NULL)
   2.671 ++		prev_buffer = file_buffer;
   2.672 ++	else {
   2.673 ++		cache_block_put(file_buffer);
   2.674 ++		seq --;
   2.675 ++	}
   2.676 ++	prev_buffer->file_size = bytes;
   2.677 ++	prev_buffer->fragment = !no_fragments &&
   2.678 ++		(count == 2 || always_use_fragments) && (byte < block_size);
   2.679 ++	queue_put(from_reader, prev_buffer);
   2.680 ++
   2.681 ++	return;
   2.682 ++
   2.683 ++read_err:
   2.684 ++	if(prev_buffer) {
   2.685 ++		cache_block_put(file_buffer);
   2.686 ++		seq --;
   2.687 ++		file_buffer = prev_buffer;
   2.688 ++	}
   2.689 ++	file_buffer->error = TRUE;
   2.690 ++	queue_put(from_deflate, file_buffer);
   2.691 ++}
   2.692 ++
   2.693 ++
   2.694 + void reader_read_file(struct dir_ent *dir_ent)
   2.695 + {
   2.696 + 	struct stat *buf = &dir_ent->inode->buf, buf2;
   2.697 + 	struct file_buffer *file_buffer;
   2.698 +-	static int index = 0;
   2.699 + 	int blocks, byte, count, expected, file, frag_block;
   2.700 + 	long long bytes, read_size;
   2.701 + 
   2.702 +@@ -2202,7 +2222,7 @@
   2.703 + 		if(file_buffer)
   2.704 + 			queue_put(from_reader, file_buffer);
   2.705 + 		file_buffer = cache_get(reader_buffer, 0, 0);
   2.706 +-		file_buffer->sequence = index ++;
   2.707 ++		file_buffer->sequence = seq ++;
   2.708 + 
   2.709 + 		byte = file_buffer->size = read_bytes(file, file_buffer->data,
   2.710 + 			block_size);
   2.711 +@@ -2238,7 +2258,7 @@
   2.712 + 
   2.713 + read_err:
   2.714 + 	file_buffer = cache_get(reader_buffer, 0, 0);
   2.715 +-	file_buffer->sequence = index ++;
   2.716 ++	file_buffer->sequence = seq ++;
   2.717 + read_err2:
   2.718 + 	file_buffer->error = TRUE;
   2.719 + 	queue_put(from_deflate, file_buffer);
   2.720 +@@ -2262,9 +2282,14 @@
   2.721 + 	for(i = 0; i < dir->count; i++) {
   2.722 + 		struct dir_ent *dir_ent = dir->list[i];
   2.723 + 		struct stat *buf = &dir_ent->inode->buf;
   2.724 +-		if(dir_ent->data)
   2.725 ++		if(dir_ent->inode->root_entry)
   2.726 + 			continue;
   2.727 + 
   2.728 ++		if(dir_ent->inode->pseudo_file) {
   2.729 ++			reader_read_process(dir_ent);
   2.730 ++			continue;
   2.731 ++		}
   2.732 ++
   2.733 + 		switch(buf->st_mode & S_IFMT) {
   2.734 + 			case S_IFREG:
   2.735 + 				reader_read_file(dir_ent);
   2.736 +@@ -2365,7 +2390,7 @@
   2.737 + 
   2.738 + void *deflator(void *arg)
   2.739 + {
   2.740 +-	z_stream *stream = NULL;
   2.741 ++	void *stream = NULL;
   2.742 + 	int oldstate;
   2.743 + 
   2.744 + 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
   2.745 +@@ -2402,7 +2427,7 @@
   2.746 + 
   2.747 + void *frag_deflator(void *arg)
   2.748 + {
   2.749 +-	z_stream *stream = NULL;
   2.750 ++	void *stream = NULL;
   2.751 + 	int oldstate;
   2.752 + 
   2.753 + 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
   2.754 +@@ -2426,8 +2451,8 @@
   2.755 + 			write_buffer->block = bytes;
   2.756 + 			bytes += compressed_size;
   2.757 + 			fragments_outstanding --;
   2.758 +-			pthread_mutex_unlock(&fragment_mutex);
   2.759 + 			queue_put(to_writer, write_buffer);
   2.760 ++			pthread_mutex_unlock(&fragment_mutex);
   2.761 + 			TRACE("Writing fragment %lld, uncompressed size %d, "
   2.762 + 				"compressed size %d\n", file_buffer->block,
   2.763 + 				file_buffer->size, compressed_size);
   2.764 +@@ -2674,6 +2699,98 @@
   2.765 + }
   2.766 + 
   2.767 + 
   2.768 ++int write_file_process(squashfs_inode *inode, struct dir_ent *dir_ent,
   2.769 ++	struct file_buffer *read_buffer, int *duplicate_file)
   2.770 ++{
   2.771 ++	long long read_size, file_bytes, start;
   2.772 ++	struct fragment *fragment;
   2.773 ++	unsigned int *block_list = NULL;
   2.774 ++	int block = 0, status;
   2.775 ++	long long sparse = 0;
   2.776 ++	struct file_buffer *fragment_buffer = NULL;
   2.777 ++
   2.778 ++	*duplicate_file = FALSE;
   2.779 ++
   2.780 ++	lock_fragments();
   2.781 ++
   2.782 ++	file_bytes = 0;
   2.783 ++	start = bytes;
   2.784 ++	while (1) {
   2.785 ++		read_size = read_buffer->file_size;
   2.786 ++		if(read_buffer->fragment && read_buffer->c_byte)
   2.787 ++			fragment_buffer = read_buffer;
   2.788 ++		else {
   2.789 ++			block_list = realloc(block_list, (block + 1) *
   2.790 ++				sizeof(unsigned int));
   2.791 ++			if(block_list == NULL)
   2.792 ++				BAD_ERROR("Out of memory allocating block_list"
   2.793 ++					"\n");
   2.794 ++			block_list[block ++] = read_buffer->c_byte;
   2.795 ++			if(read_buffer->c_byte) {
   2.796 ++				read_buffer->block = bytes;
   2.797 ++				bytes += read_buffer->size;
   2.798 ++				cache_rehash(read_buffer, read_buffer->block);
   2.799 ++				file_bytes += read_buffer->size;
   2.800 ++				queue_put(to_writer, read_buffer);
   2.801 ++			} else {
   2.802 ++				sparse += read_buffer->size;
   2.803 ++				cache_block_put(read_buffer);
   2.804 ++			}
   2.805 ++		}
   2.806 ++		inc_progress_bar();
   2.807 ++
   2.808 ++		if(read_size != -1)
   2.809 ++			break;
   2.810 ++
   2.811 ++		read_buffer = get_file_buffer(from_deflate);
   2.812 ++		if(read_buffer->error)
   2.813 ++			goto read_err;
   2.814 ++	}
   2.815 ++
   2.816 ++	unlock_fragments();
   2.817 ++	fragment = get_and_fill_fragment(fragment_buffer);
   2.818 ++	cache_block_put(fragment_buffer);
   2.819 ++
   2.820 ++	if(duplicate_checking)
   2.821 ++		add_non_dup(read_size, file_bytes, block_list, start, fragment,
   2.822 ++			0, 0, FALSE);
   2.823 ++	file_count ++;
   2.824 ++	total_bytes += read_size;
   2.825 ++
   2.826 ++	if(read_size < (1LL << 32) && start < (1LL << 32) && sparse == 0)
   2.827 ++		create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size,
   2.828 ++			start, block, block_list, fragment, NULL, 0);
   2.829 ++	else
   2.830 ++		create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size,
   2.831 ++			start, block, block_list, fragment, NULL, sparse);
   2.832 ++
   2.833 ++	if(duplicate_checking == FALSE)
   2.834 ++		free(block_list);
   2.835 ++
   2.836 ++	return 0;
   2.837 ++
   2.838 ++read_err:
   2.839 ++	cur_uncompressed -= block;
   2.840 ++	status = read_buffer->error;
   2.841 ++	bytes = start;
   2.842 ++	if(!block_device) {
   2.843 ++		int res;
   2.844 ++
   2.845 ++		queue_put(to_writer, NULL);
   2.846 ++		if(queue_get(from_writer) != 0)
   2.847 ++			EXIT_MKSQUASHFS();
   2.848 ++		res = ftruncate(fd, bytes);
   2.849 ++		if(res != 0)
   2.850 ++			BAD_ERROR("Failed to truncate dest file because %s\n",
   2.851 ++				strerror(errno));
   2.852 ++	}
   2.853 ++	unlock_fragments();
   2.854 ++	free(block_list);
   2.855 ++	cache_block_put(read_buffer);
   2.856 ++	return status;
   2.857 ++}
   2.858 ++
   2.859 ++
   2.860 + int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent,
   2.861 + 	long long read_size, struct file_buffer *read_buffer,
   2.862 + 	int *duplicate_file)
   2.863 +@@ -2941,7 +3058,10 @@
   2.864 + 	
   2.865 + 	read_size = read_buffer->file_size;
   2.866 + 
   2.867 +-	if(read_size == 0) {
   2.868 ++	if(read_size == -1)
   2.869 ++		status = write_file_process(inode, dir_ent, read_buffer,
   2.870 ++			duplicate_file);
   2.871 ++	else if(read_size == 0) {
   2.872 + 		write_file_empty(inode, dir_ent, duplicate_file);
   2.873 + 		cache_block_put(read_buffer);
   2.874 + 	} else if(read_buffer->fragment && read_buffer->c_byte)
   2.875 +@@ -3036,6 +3156,8 @@
   2.876 + 
   2.877 + 	memcpy(&inode->buf, buf, sizeof(struct stat));
   2.878 + 	inode->read = FALSE;
   2.879 ++	inode->root_entry = FALSE;
   2.880 ++	inode->pseudo_file = FALSE;
   2.881 + 	inode->inode = SQUASHFS_INVALID_BLK;
   2.882 + 	inode->nlink = 1;
   2.883 + 
   2.884 +@@ -3056,7 +3178,7 @@
   2.885 + 
   2.886 + 
   2.887 + inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir,
   2.888 +-	struct inode_info *inode_info, void *data, struct dir_info *dir)
   2.889 ++	struct inode_info *inode_info, struct dir_info *dir)
   2.890 + {
   2.891 + 	if((dir->count % DIR_ENTRIES) == 0) {
   2.892 + 		dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) *
   2.893 +@@ -3075,8 +3197,7 @@
   2.894 + 		NULL;
   2.895 + 	dir->list[dir->count]->inode = inode_info;
   2.896 + 	dir->list[dir->count]->dir = sub_dir;
   2.897 +-	dir->list[dir->count]->our_dir = dir;
   2.898 +-	dir->list[dir->count++]->data = data;
   2.899 ++	dir->list[dir->count++]->our_dir = dir;
   2.900 + 	dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry);
   2.901 + }
   2.902 + 
   2.903 +@@ -3128,10 +3249,10 @@
   2.904 + 
   2.905 + 	if(dir->count < old_root_entries)
   2.906 + 		for(i = 0; i < old_root_entries; i++) {
   2.907 +-			if(old_root_entry[i].type == SQUASHFS_DIR_TYPE)
   2.908 ++			if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE)
   2.909 + 				dir->directory_count ++;
   2.910 +-			add_dir_entry(old_root_entry[i].name, "", NULL, NULL,
   2.911 +-				&old_root_entry[i], dir);
   2.912 ++			add_dir_entry(old_root_entry[i].name, "", NULL,
   2.913 ++				&old_root_entry[i].inode, dir);
   2.914 + 		}
   2.915 + 
   2.916 + 	while(index < source) {
   2.917 +@@ -3167,10 +3288,10 @@
   2.918 + 
   2.919 + 	if(dir->count < old_root_entries)
   2.920 + 		for(i = 0; i < old_root_entries; i++) {
   2.921 +-			if(old_root_entry[i].type == SQUASHFS_DIR_TYPE)
   2.922 ++			if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE)
   2.923 + 				dir->directory_count ++;
   2.924 +-			add_dir_entry(old_root_entry[i].name, "", NULL, NULL,
   2.925 +-				&old_root_entry[i], dir);
   2.926 ++			add_dir_entry(old_root_entry[i].name, "", NULL,
   2.927 ++				&old_root_entry[i].inode, dir);
   2.928 + 		}
   2.929 + 
   2.930 + 	if((d_name = readdir(dir->linuxdir)) != NULL) {
   2.931 +@@ -3215,7 +3336,7 @@
   2.932 + 	int current_count;
   2.933 + 
   2.934 + 	while((current_count = dir_info->current_count++) < dir_info->count)
   2.935 +-		if(dir_info->list[current_count]->data)
   2.936 ++		if(dir_info->list[current_count]->inode->root_entry)
   2.937 + 			continue;
   2.938 + 		else 
   2.939 + 			return dir_info->list[current_count];
   2.940 +@@ -3240,11 +3361,11 @@
   2.941 + 	int current_count;
   2.942 + 
   2.943 + 	while((current_count = dir_info->current_count++) < dir_info->count)
   2.944 +-		if(dir_info->list[current_count]->data)
   2.945 +-			add_dir(dir_info->list[current_count]->data->inode,
   2.946 +-				dir_info->list[current_count]->data->inode_number,
   2.947 ++		if(dir_info->list[current_count]->inode->root_entry)
   2.948 ++			add_dir(dir_info->list[current_count]->inode->inode,
   2.949 ++				dir_info->list[current_count]->inode->inode_number,
   2.950 + 				dir_info->list[current_count]->name,
   2.951 +-				dir_info->list[current_count]->data->type, dir);
   2.952 ++				dir_info->list[current_count]->inode->type, dir);
   2.953 + 		else 
   2.954 + 			return dir_info->list[current_count];
   2.955 + 	return NULL;	
   2.956 +@@ -3313,7 +3434,6 @@
   2.957 + 	dir_ent->name = dir_ent->pathname = strdup(pathname);
   2.958 + 	dir_ent->dir = dir_info;
   2.959 + 	dir_ent->our_dir = NULL;
   2.960 +-	dir_ent->data = NULL;
   2.961 + 	dir_info->dir_ent = dir_ent;
   2.962 + 
   2.963 + 	if(sorted)
   2.964 +@@ -3383,7 +3503,7 @@
   2.965 + 			sub_dir = NULL;
   2.966 + 
   2.967 + 		add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf),
   2.968 +-			NULL, dir);
   2.969 ++			dir);
   2.970 + 	}
   2.971 + 
   2.972 + 	scan1_freedir(dir);
   2.973 +@@ -3399,7 +3519,7 @@
   2.974 + 	struct dir_ent *dir_ent;
   2.975 + 	struct pseudo_entry *pseudo_ent;
   2.976 + 	struct stat buf;
   2.977 +-	static pseudo_ino = 1;
   2.978 ++	static int pseudo_ino = 1;
   2.979 + 	
   2.980 + 	if(dir == NULL && (dir = scan1_opendir("")) == NULL)
   2.981 + 		return NULL;
   2.982 +@@ -3415,6 +3535,29 @@
   2.983 + 
   2.984 + 	while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) {
   2.985 + 		dir_ent = scan2_lookup(dir, pseudo_ent->name);
   2.986 ++		if(pseudo_ent->dev->type == 's') {
   2.987 ++			struct stat *buf;
   2.988 ++			if(dir_ent == NULL) {
   2.989 ++				ERROR("Pseudo set file \"%s\" does not exist "
   2.990 ++					"in source filesystem.  Ignoring\n",
   2.991 ++					pseudo_ent->pathname);
   2.992 ++				continue;
   2.993 ++			}
   2.994 ++			if(dir_ent->inode->root_entry) {
   2.995 ++				ERROR("Pseudo set file \"%s\" is a pre-existing"
   2.996 ++					" file in the filesystem being appended"
   2.997 ++					"  to.  It cannot be modified. "
   2.998 ++					"Ignoring!\n", pseudo_ent->pathname);
   2.999 ++				continue;
  2.1000 ++			}
  2.1001 ++			buf = &dir_ent->inode->buf;
  2.1002 ++			buf->st_mode = (buf->st_mode & S_IFMT) |
  2.1003 ++				pseudo_ent->dev->mode;
  2.1004 ++			buf->st_uid = pseudo_ent->dev->uid;
  2.1005 ++			buf->st_gid = pseudo_ent->dev->gid;
  2.1006 ++			continue;
  2.1007 ++		}
  2.1008 ++
  2.1009 + 		if(dir_ent) {
  2.1010 + 			ERROR("Pseudo file \"%s\" exists in source filesystem "
  2.1011 + 				"\"%s\"\n", pseudo_ent->pathname,
  2.1012 +@@ -3444,8 +3587,29 @@
  2.1013 + 		buf.st_mtime = time(NULL);
  2.1014 + 		buf.st_ino = pseudo_ino ++;
  2.1015 + 
  2.1016 +-		add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir,
  2.1017 +-			lookup_inode(&buf), NULL, dir);
  2.1018 ++		if(pseudo_ent->dev->type == 'f') {
  2.1019 ++#ifdef USE_TMP_FILE
  2.1020 ++			struct stat buf2;
  2.1021 ++			int res = stat(pseudo_ent->dev->filename, &buf2);
  2.1022 ++			if(res == -1) {
  2.1023 ++				ERROR("Stat on pseudo file \"%s\" failed, "
  2.1024 ++					"skipping...", pseudo_ent->pathname);
  2.1025 ++				continue;
  2.1026 ++			}
  2.1027 ++			buf.st_size = buf2.st_size;
  2.1028 ++			add_dir_entry(pseudo_ent->name,
  2.1029 ++				pseudo_ent->dev->filename, sub_dir,
  2.1030 ++				lookup_inode(&buf), dir);
  2.1031 ++#else
  2.1032 ++			struct inode_info *inode = lookup_inode(&buf);
  2.1033 ++			inode->pseudo_id = pseudo_ent->dev->pseudo_id;
  2.1034 ++			inode->pseudo_file = TRUE;		
  2.1035 ++			add_dir_entry(pseudo_ent->name, pseudo_ent->pathname,
  2.1036 ++				sub_dir, inode, dir);
  2.1037 ++#endif
  2.1038 ++		} else
  2.1039 ++			add_dir_entry(pseudo_ent->name, pseudo_ent->pathname,
  2.1040 ++				sub_dir, lookup_inode(&buf), dir);
  2.1041 + 	}
  2.1042 + 
  2.1043 + 	scan2_freedir(dir);
  2.1044 +@@ -3482,8 +3646,9 @@
  2.1045 + 						&duplicate_file);
  2.1046 + 					INFO("file %s, uncompressed size %lld "
  2.1047 + 						"bytes %s\n", filename,
  2.1048 +-						buf->st_size, duplicate_file ?
  2.1049 +-						"DUPLICATE" : "");
  2.1050 ++						(long long) buf->st_size,
  2.1051 ++						duplicate_file ?  "DUPLICATE" :
  2.1052 ++						 "");
  2.1053 + 					break;
  2.1054 + 
  2.1055 + 				case S_IFDIR:
  2.1056 +@@ -3557,6 +3722,7 @@
  2.1057 + 						INFO("file %s, uncompressed "
  2.1058 + 							"size %lld bytes LINK"
  2.1059 + 							"\n", filename,
  2.1060 ++							(long long)
  2.1061 + 							buf->st_size);
  2.1062 + 					break;
  2.1063 + 				case SQUASHFS_SYMLINK_TYPE:
  2.1064 +@@ -3667,10 +3833,11 @@
  2.1065 + 		BAD_ERROR("Out of memory in old root directory entries "
  2.1066 + 			"reallocation\n");
  2.1067 + 
  2.1068 +-	strcpy(old_root_entry[old_root_entries].name, name);
  2.1069 +-	old_root_entry[old_root_entries].inode = inode;
  2.1070 +-	old_root_entry[old_root_entries].inode_number = inode_number;
  2.1071 +-	old_root_entry[old_root_entries++].type = type;
  2.1072 ++	old_root_entry[old_root_entries].name = strdup(name);
  2.1073 ++	old_root_entry[old_root_entries].inode.inode = inode;
  2.1074 ++	old_root_entry[old_root_entries].inode.inode_number = inode_number;
  2.1075 ++	old_root_entry[old_root_entries].inode.type = type;
  2.1076 ++	old_root_entry[old_root_entries++].inode.root_entry = TRUE;
  2.1077 + }
  2.1078 + 
  2.1079 + 
  2.1080 +@@ -4137,7 +4304,7 @@
  2.1081 + 
  2.1082 + 
  2.1083 + #define VERSION() \
  2.1084 +-	printf("mksquashfs version 4.0 (2009/04/05)\n");\
  2.1085 ++	printf("mksquashfs version 4.1-CVS (2009/12/08)\n");\
  2.1086 + 	printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \
  2.1087 + 	printf("This program is free software; you can redistribute it and/or\n");\
  2.1088 + 	printf("modify it under the terms of the GNU General Public License\n");\
  2.1089 +@@ -4172,26 +4339,28 @@
  2.1090 + 	source_path = argv + 1;
  2.1091 + 	source = i - 2;
  2.1092 + 	for(; i < argc; i++) {
  2.1093 +-		if(strcmp(argv[i], "-pf") == 0) {
  2.1094 ++		if(strcmp(argv[i], "-comp") == 0) {
  2.1095 + 			if(++i == argc) {
  2.1096 +-				ERROR("%s: -pf missing filename\n", argv[0]);
  2.1097 ++				ERROR("%s: -comp missing compression type\n",
  2.1098 ++					argv[0]);
  2.1099 + 				exit(1);
  2.1100 + 			}
  2.1101 +-			if(read_pseudo_file(&pseudo, argv[i]) == FALSE) {
  2.1102 +-				ERROR("Failed to parse pseudo file \"%s\"\n",
  2.1103 +-					argv[i]);
  2.1104 ++			comp_name = argv[i];
  2.1105 ++		} else if(strcmp(argv[i], "-pf") == 0) {
  2.1106 ++			if(++i == argc) {
  2.1107 ++				ERROR("%s: -pf missing filename\n", argv[0]);
  2.1108 + 				exit(1);
  2.1109 + 			}
  2.1110 ++			if(read_pseudo_file(&pseudo, argv[i]) == FALSE)
  2.1111 ++				exit(1);
  2.1112 + 		} else if(strcmp(argv[i], "-p") == 0) {
  2.1113 + 			if(++i == argc) {
  2.1114 + 				ERROR("%s: -p missing pseudo file definition\n",
  2.1115 + 					argv[0]);
  2.1116 + 				exit(1);
  2.1117 + 			}
  2.1118 +-			if(read_pseudo_def(&pseudo, argv[i]) == FALSE) {
  2.1119 +-				ERROR("Failed to parse pseudo definition\n");
  2.1120 ++			if(read_pseudo_def(&pseudo, argv[i]) == FALSE)
  2.1121 + 				exit(1);
  2.1122 +-			}
  2.1123 + 		} else if(strcmp(argv[i], "-recover") == 0) {
  2.1124 + 			if(++i == argc) {
  2.1125 + 				ERROR("%s: -recover missing recovery file\n",
  2.1126 +@@ -4394,34 +4563,16 @@
  2.1127 + printOptions:
  2.1128 + 			ERROR("SYNTAX:%s source1 source2 ...  dest [options] "
  2.1129 + 				"[-e list of exclude\ndirs/files]\n", argv[0]);
  2.1130 +-			ERROR("\nOptions are\n");
  2.1131 +-			ERROR("-version\t\tprint version, licence and "
  2.1132 +-				"copyright message\n");
  2.1133 +-			ERROR("-recover <name>\t\trecover filesystem data "
  2.1134 +-				"using recovery file <name>\n");
  2.1135 +-			ERROR("-no-recovery\t\tdon't generate a recovery "
  2.1136 +-				"file\n");
  2.1137 +-			ERROR("-info\t\t\tprint files written to filesystem\n");
  2.1138 +-			ERROR("-no-exports\t\tdon't make the filesystem "
  2.1139 +-				"exportable via NFS\n");
  2.1140 +-			ERROR("-no-progress\t\tdon't display the progress "
  2.1141 +-				"bar\n");
  2.1142 +-			ERROR("-no-sparse\t\tdon't detect sparse files\n");
  2.1143 ++			ERROR("\nFilesystem build options:\n");
  2.1144 ++			ERROR("-comp <comp>\t\tselect <comp> compression\n");
  2.1145 ++			ERROR("\t\t\tCompressors available:\n");
  2.1146 ++			display_compressors("\t\t\t", COMP_DEFAULT);
  2.1147 + 			ERROR("-b <block_size>\t\tset data block to "
  2.1148 + 				"<block_size>.  Default %d bytes\n",
  2.1149 + 				SQUASHFS_FILE_SIZE);
  2.1150 +-			ERROR("-processors <number>\tUse <number> processors."
  2.1151 +-				"  By default will use number of\n");
  2.1152 +-			ERROR("\t\t\tprocessors available\n");
  2.1153 +-			ERROR("-read-queue <size>\tSet input queue to <size> "
  2.1154 +-				"Mbytes.  Default %d Mbytes\n",
  2.1155 +-				READER_BUFFER_DEFAULT);
  2.1156 +-			ERROR("-write-queue <size>\tSet output queue to <size> "
  2.1157 +-				"Mbytes.  Default %d Mbytes\n",
  2.1158 +-				WRITER_BUFFER_DEFAULT);
  2.1159 +-			ERROR("-fragment-queue <size>\tSet fagment queue to "
  2.1160 +-				"<size> Mbytes.  Default %d Mbytes\n",
  2.1161 +-				FRAGMENT_BUFFER_DEFAULT);
  2.1162 ++			ERROR("-no-exports\t\tdon't make the filesystem "
  2.1163 ++				"exportable via NFS\n");
  2.1164 ++			ERROR("-no-sparse\t\tdon't detect sparse files\n");
  2.1165 + 			ERROR("-noI\t\t\tdo not compress inode table\n");
  2.1166 + 			ERROR("-noD\t\t\tdo not compress data blocks\n");
  2.1167 + 			ERROR("-noF\t\t\tdo not compress fragment blocks\n");
  2.1168 +@@ -4430,13 +4581,34 @@
  2.1169 + 				"files larger than block size\n");
  2.1170 + 			ERROR("-no-duplicates\t\tdo not perform duplicate "
  2.1171 + 				"checking\n");
  2.1172 +-			ERROR("-noappend\t\tdo not append to existing "
  2.1173 +-				"filesystem\n");
  2.1174 ++			ERROR("-all-root\t\tmake all files owned by root\n");
  2.1175 ++			ERROR("-force-uid uid\t\tset all file uids to uid\n");
  2.1176 ++			ERROR("-force-gid gid\t\tset all file gids to gid\n");
  2.1177 ++			ERROR("-nopad\t\t\tdo not pad filesystem to a multiple "
  2.1178 ++				"of 4K\n");
  2.1179 + 			ERROR("-keep-as-directory\tif one source directory is "
  2.1180 + 				"specified, create a root\n");
  2.1181 + 			ERROR("\t\t\tdirectory containing that directory, "
  2.1182 + 				"rather than the\n");
  2.1183 + 			ERROR("\t\t\tcontents of the directory\n");
  2.1184 ++			ERROR("\nFilesystem filter options:\n");
  2.1185 ++			ERROR("-p <pseudo-definition>\tAdd pseudo file definition\n");
  2.1186 ++			ERROR("-pf <pseudo-file>\tAdd list of pseudo file definitions\n");
  2.1187 ++			ERROR("-sort <sort_file>\tsort files according to "
  2.1188 ++				"priorities in <sort_file>.  One\n");
  2.1189 ++			ERROR("\t\t\tfile or dir with priority per line.  "
  2.1190 ++				"Priority -32768 to\n");
  2.1191 ++			ERROR("\t\t\t32767, default priority 0\n");
  2.1192 ++			ERROR("-ef <exclude_file>\tlist of exclude dirs/files."
  2.1193 ++				"  One per line\n");
  2.1194 ++			ERROR("-wildcards\t\tAllow extended shell wildcards "
  2.1195 ++				"(globbing) to be used in\n\t\t\texclude "
  2.1196 ++				"dirs/files\n");
  2.1197 ++			ERROR("-regex\t\t\tAllow POSIX regular expressions to "
  2.1198 ++				"be used in exclude\n\t\t\tdirs/files\n");
  2.1199 ++			ERROR("\nFilesystem append options:\n");
  2.1200 ++			ERROR("-noappend\t\tdo not append to existing "
  2.1201 ++				"filesystem\n");
  2.1202 + 			ERROR("-root-becomes <name>\twhen appending source "
  2.1203 + 				"files/directories, make the\n");
  2.1204 + 			ERROR("\t\t\toriginal root become a subdirectory in "
  2.1205 +@@ -4444,11 +4616,29 @@
  2.1206 + 			ERROR("\t\t\tcalled <name>, rather than adding the new "
  2.1207 + 				"source items\n");
  2.1208 + 			ERROR("\t\t\tto the original root\n");
  2.1209 +-			ERROR("-all-root\t\tmake all files owned by root\n");
  2.1210 +-			ERROR("-force-uid uid\t\tset all file uids to uid\n");
  2.1211 +-			ERROR("-force-gid gid\t\tset all file gids to gid\n");
  2.1212 +-			ERROR("-nopad\t\t\tdo not pad filesystem to a multiple "
  2.1213 +-				"of 4K\n");
  2.1214 ++			ERROR("\nMksquashfs runtime options:\n");
  2.1215 ++			ERROR("-version\t\tprint version, licence and "
  2.1216 ++				"copyright message\n");
  2.1217 ++			ERROR("-recover <name>\t\trecover filesystem data "
  2.1218 ++				"using recovery file <name>\n");
  2.1219 ++			ERROR("-no-recovery\t\tdon't generate a recovery "
  2.1220 ++				"file\n");
  2.1221 ++			ERROR("-info\t\t\tprint files written to filesystem\n");
  2.1222 ++			ERROR("-no-progress\t\tdon't display the progress "
  2.1223 ++				"bar\n");
  2.1224 ++			ERROR("-processors <number>\tUse <number> processors."
  2.1225 ++				"  By default will use number of\n");
  2.1226 ++			ERROR("\t\t\tprocessors available\n");
  2.1227 ++			ERROR("-read-queue <size>\tSet input queue to <size> "
  2.1228 ++				"Mbytes.  Default %d Mbytes\n",
  2.1229 ++				READER_BUFFER_DEFAULT);
  2.1230 ++			ERROR("-write-queue <size>\tSet output queue to <size> "
  2.1231 ++				"Mbytes.  Default %d Mbytes\n",
  2.1232 ++				WRITER_BUFFER_DEFAULT);
  2.1233 ++			ERROR("-fragment-queue <size>\tSet fagment queue to "
  2.1234 ++				"<size> Mbytes.  Default %d Mbytes\n",
  2.1235 ++				FRAGMENT_BUFFER_DEFAULT);
  2.1236 ++			ERROR("\nMiscellaneous options:\n");
  2.1237 + 			ERROR("-root-owned\t\talternative name for -all-root"
  2.1238 + 				"\n");
  2.1239 + 			ERROR("-noInodeCompression\talternative name for -noI"
  2.1240 +@@ -4457,20 +4647,8 @@
  2.1241 + 				"\n");
  2.1242 + 			ERROR("-noFragmentCompression\talternative name for "
  2.1243 + 				"-noF\n");
  2.1244 +-			ERROR("-sort <sort_file>\tsort files according to "
  2.1245 +-				"priorities in <sort_file>.  One\n");
  2.1246 +-			ERROR("\t\t\tfile or dir with priority per line.  "
  2.1247 +-				"Priority -32768 to\n");
  2.1248 +-			ERROR("\t\t\t32767, default priority 0\n");
  2.1249 +-			ERROR("-ef <exclude_file>\tlist of exclude dirs/files."
  2.1250 +-				"  One per line\n");
  2.1251 +-			ERROR("-wildcards\t\tAllow extended shell wildcards "
  2.1252 +-				"(globbing) to be used in\n\t\t\texclude "
  2.1253 +-				"dirs/files\n");
  2.1254 +-			ERROR("-regex\t\t\tAllow POSIX regular expressions to "
  2.1255 +-				"be used in exclude\n\t\t\tdirs/files\n");
  2.1256 +-			ERROR("-p <pseudo-definition>\tAdd pseudo file definition\n");
  2.1257 +-			ERROR("-pf <pseudo-file>\tAdd list of pseudo file definitions\n");
  2.1258 ++			ERROR("\nCompressors available:\n");
  2.1259 ++			display_compressors("", COMP_DEFAULT);
  2.1260 + 			exit(1);
  2.1261 + 		}
  2.1262 + 	}
  2.1263 +@@ -4548,11 +4726,10 @@
  2.1264 + 			fclose(fd);
  2.1265 + 		} else if(strcmp(argv[i], "-e") == 0)
  2.1266 + 			break;
  2.1267 +-		else if(strcmp(argv[i], "-b") == 0 ||
  2.1268 +-				strcmp(argv[i], "-root-becomes") == 0 ||
  2.1269 ++		else if(strcmp(argv[i], "-root-becomes") == 0 ||
  2.1270 + 				strcmp(argv[i], "-sort") == 0 ||
  2.1271 + 				strcmp(argv[i], "-pf") == 0 ||
  2.1272 +-				strcmp(argv[i], "-p") == 0)
  2.1273 ++				strcmp(argv[i], "-comp") == 0)
  2.1274 + 			i++;
  2.1275 + 
  2.1276 + 	if(i != argc) {
  2.1277 +@@ -4574,11 +4751,10 @@
  2.1278 + 			sorted ++;
  2.1279 + 		} else if(strcmp(argv[i], "-e") == 0)
  2.1280 + 			break;
  2.1281 +-		else if(strcmp(argv[i], "-b") == 0 ||
  2.1282 +-				strcmp(argv[i], "-root-becomes") == 0 ||
  2.1283 ++		else if(strcmp(argv[i], "-root-becomes") == 0 ||
  2.1284 + 				strcmp(argv[i], "-ef") == 0 ||
  2.1285 + 				strcmp(argv[i], "-pf") == 0 ||
  2.1286 +-				strcmp(argv[i], "-p") == 0)
  2.1287 ++				strcmp(argv[i], "-comp") == 0)
  2.1288 + 			i++;
  2.1289 + 
  2.1290 + #ifdef SQUASHFS_TRACE
  2.1291 +@@ -4586,7 +4762,8 @@
  2.1292 + #endif
  2.1293 + 
  2.1294 + 	if(!delete) {
  2.1295 +-	        if(read_super(fd, &sBlk, argv[source + 1]) == 0) {
  2.1296 ++	        comp = read_super(fd, &sBlk, argv[source + 1]);
  2.1297 ++	        if(comp == NULL) {
  2.1298 + 			ERROR("Failed to read existing filesystem - will not "
  2.1299 + 				"overwrite - ABORTING!\n");
  2.1300 + 			ERROR("To force Mksquashfs to write to this block "
  2.1301 +@@ -4603,6 +4780,15 @@
  2.1302 + 		always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags);
  2.1303 + 		duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags);
  2.1304 + 		exportable = SQUASHFS_EXPORTABLE(sBlk.flags);
  2.1305 ++	} else {
  2.1306 ++		comp = lookup_compressor(comp_name);
  2.1307 ++		if(!comp->supported) {
  2.1308 ++			ERROR("FATAL_ERROR: Compressor \"%s\" is not "
  2.1309 ++				"supported!\n", comp_name);
  2.1310 ++			ERROR("Compressors available:\n");
  2.1311 ++			display_compressors("", COMP_DEFAULT);
  2.1312 ++			EXIT_MKSQUASHFS();
  2.1313 ++		}
  2.1314 + 	}
  2.1315 + 
  2.1316 + 	initialise_threads();
  2.1317 +@@ -4648,8 +4834,8 @@
  2.1318 + 			"size %d\n", SQUASHFS_MAJOR, s_minor, argv[source + 1],
  2.1319 + 			block_size);
  2.1320 + 		printf("All -b, -noI, -noD, -noF, no-duplicates, no-fragments, "
  2.1321 +-			"-always-use-fragments and -exportable options ignored"
  2.1322 +-			"\n");
  2.1323 ++			"-always-use-fragments,\n-exportable and -comp options "
  2.1324 ++			"ignored\n");
  2.1325 + 		printf("\nIf appending is not wanted, please re-run with "
  2.1326 + 			"-noappend specified!\n\n");
  2.1327 + 
  2.1328 +@@ -4803,8 +4989,7 @@
  2.1329 + 
  2.1330 + 	sBlk.bytes_used = bytes;
  2.1331 + 
  2.1332 +-	/* Only compression supported */
  2.1333 +-	sBlk.compression = ZLIB_COMPRESSION;
  2.1334 ++	sBlk.compression = comp->id;
  2.1335 + 
  2.1336 + 	/* Xattrs are not currently supported */
  2.1337 + 	sBlk.xattr_table_start = SQUASHFS_INVALID_BLK;
  2.1338 +@@ -4820,6 +5005,8 @@
  2.1339 + 
  2.1340 + 	close(fd);
  2.1341 + 
  2.1342 ++	delete_pseudo_files();
  2.1343 ++
  2.1344 + 	if(recovery_file[0] != '\0')
  2.1345 + 		unlink(recovery_file);
  2.1346 + 
  2.1347 +@@ -4827,9 +5014,9 @@
  2.1348 + 		* sizeof(unsigned short) + guid_count * sizeof(unsigned short) +
  2.1349 + 		sizeof(squashfs_super_block);
  2.1350 + 
  2.1351 +-	printf("\n%sSquashfs %d.%d filesystem, data block size %d\n",
  2.1352 +-		exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR,
  2.1353 +-		block_size);
  2.1354 ++	printf("\n%sSquashfs %d.%d filesystem, %s compressed, data block size"
  2.1355 ++		" %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR,
  2.1356 ++		SQUASHFS_MINOR, comp->name, block_size);
  2.1357 + 	printf("\t%s data, %s metadata, %s fragments\n",
  2.1358 + 		noD ? "uncompressed" : "compressed", noI ?  "uncompressed" :
  2.1359 + 		"compressed", no_fragments ? "no" : noF ? "uncompressed" :
  2.1360 +
  2.1361 +--- squashfs-4.0/squashfs-tools/par_mksquashfs/README	Thu Jan  1 01:00:00 1970
  2.1362 ++++ squashfs-4.0/squashfs-tools/par_mksquashfs/README	Mon Nov  6 01:27:32 2006
  2.1363 +@@ -0,0 +1,2 @@
  2.1364 ++par_mksquashfs is now the standard mksquashfs, and so this directory is now empty.
  2.1365 ++
  2.1366 +
  2.1367 +--- squashfs-4.0/squashfs-tools/pseudo.c	Sun Apr  5 04:01:58 2009
  2.1368 ++++ squashfs-4.0/squashfs-tools/pseudo.c	Thu Sep 10 06:17:48 2009
  2.1369 +@@ -30,6 +30,7 @@
  2.1370 + #include <string.h>
  2.1371 + #include <stdlib.h>
  2.1372 + #include <sys/types.h>
  2.1373 ++#include <sys/wait.h>
  2.1374 + 
  2.1375 + #include "pseudo.h"
  2.1376 + 
  2.1377 +@@ -55,6 +56,9 @@
  2.1378 + #define TRUE 1
  2.1379 + #define FALSE 0
  2.1380 + 
  2.1381 ++struct pseudo_dev **pseudo_file = NULL;
  2.1382 ++int pseudo_count = 0;
  2.1383 ++
  2.1384 + static void dump_pseudo(struct pseudo *pseudo, char *string)
  2.1385 + {
  2.1386 + 	int i;
  2.1387 +@@ -99,7 +103,7 @@
  2.1388 + 	char *target, char *alltarget)
  2.1389 + {
  2.1390 + 	char targname[1024];
  2.1391 +-	int i, error;
  2.1392 ++	int i;
  2.1393 + 
  2.1394 + 	target = get_component(target, targname);
  2.1395 + 
  2.1396 +@@ -128,12 +132,8 @@
  2.1397 + 		if(target[0] == '\0') {
  2.1398 + 			/* at leaf pathname component */
  2.1399 + 			pseudo->name[i].pseudo = NULL;
  2.1400 +-			pseudo->name[i].dev = malloc(sizeof(struct pseudo_dev));
  2.1401 +-			if(pseudo->name[i].dev == NULL)
  2.1402 +-				BAD_ERROR("failed to allocate pseudo file\n");
  2.1403 + 			pseudo->name[i].pathname = strdup(alltarget);
  2.1404 +-			memcpy(pseudo->name[i].dev, pseudo_dev,
  2.1405 +-				sizeof(struct pseudo_dev));
  2.1406 ++			pseudo->name[i].dev = pseudo_dev;
  2.1407 + 		} else {
  2.1408 + 			/* recurse adding child components */
  2.1409 + 			pseudo->name[i].dev = NULL;
  2.1410 +@@ -169,15 +169,9 @@
  2.1411 + 			if(target[0] == '\0') {
  2.1412 + 				if(pseudo->name[i].dev == NULL &&
  2.1413 + 						pseudo_dev->type == 'd') {
  2.1414 +-					pseudo->name[i].dev =
  2.1415 +-						malloc(sizeof(struct pseudo_dev));
  2.1416 +-					if(pseudo->name[i].dev == NULL)
  2.1417 +-						BAD_ERROR("failed to allocate "
  2.1418 +-							"pseudo file\n");
  2.1419 + 					pseudo->name[i].pathname =
  2.1420 + 						strdup(alltarget);
  2.1421 +-					memcpy(pseudo->name[i].dev, pseudo_dev,
  2.1422 +-						sizeof(struct pseudo_dev));
  2.1423 ++					pseudo->name[i].dev = pseudo_dev;
  2.1424 + 				} else
  2.1425 + 					ERROR("%s already exists as a "
  2.1426 + 						"directory.  Ignoring %s!\n",
  2.1427 +@@ -229,16 +223,113 @@
  2.1428 + }
  2.1429 + 
  2.1430 + 
  2.1431 ++int exec_file(char *command, struct pseudo_dev *dev)
  2.1432 ++{
  2.1433 ++	int child, res;
  2.1434 ++	static pid_t pid = -1;
  2.1435 ++	int pipefd[2];
  2.1436 ++#ifdef USE_TMP_FILE
  2.1437 ++	char filename[1024];
  2.1438 ++	int status;
  2.1439 ++	static int number = 0;
  2.1440 ++#endif
  2.1441 ++
  2.1442 ++	if(pid == -1)
  2.1443 ++		pid = getpid();
  2.1444 ++
  2.1445 ++#ifdef USE_TMP_FILE
  2.1446 ++	sprintf(filename, "/tmp/squashfs_pseudo_%d_%d", pid, number ++);
  2.1447 ++	pipefd[1] = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
  2.1448 ++	if(pipefd[1] == -1) {
  2.1449 ++		printf("open failed\n");
  2.1450 ++		return -1;
  2.1451 ++	}
  2.1452 ++#else
  2.1453 ++	res = pipe(pipefd);
  2.1454 ++	if(res == -1) {
  2.1455 ++		printf("pipe failed\n");
  2.1456 ++		return -1;
  2.1457 ++	}
  2.1458 ++#endif
  2.1459 ++
  2.1460 ++	child = fork();
  2.1461 ++	if(child == -1) {
  2.1462 ++		printf("fork failed\n");
  2.1463 ++		goto failed;
  2.1464 ++	}
  2.1465 ++
  2.1466 ++	if(child == 0) {
  2.1467 ++		close(STDOUT_FILENO);
  2.1468 ++		res = dup(pipefd[1]);
  2.1469 ++		if(res == -1) {
  2.1470 ++			printf("dup failed\n");
  2.1471 ++			exit(EXIT_FAILURE);
  2.1472 ++		}
  2.1473 ++		execl("/bin/sh", "sh", "-c", command, (char *) NULL);
  2.1474 ++		printf("execl failed\n");
  2.1475 ++		exit(EXIT_FAILURE);
  2.1476 ++	}
  2.1477 ++
  2.1478 ++#ifdef USE_TMP_FILE
  2.1479 ++	res = waitpid(child, &status, 0);
  2.1480 ++	close(pipefd[1]);
  2.1481 ++	if(res != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0) {
  2.1482 ++		dev->filename = strdup(filename);
  2.1483 ++		return 0;
  2.1484 ++	}
  2.1485 ++failed:
  2.1486 ++	unlink(filename);
  2.1487 ++	return -1;
  2.1488 ++#else
  2.1489 ++	close(pipefd[1]);
  2.1490 ++	dev->fd = pipefd[0];
  2.1491 ++	dev->child = child;
  2.1492 ++	return 0;
  2.1493 ++failed:
  2.1494 ++	return -1;
  2.1495 ++#endif
  2.1496 ++}
  2.1497 ++
  2.1498 ++
  2.1499 ++void add_pseudo_file(struct pseudo_dev *dev)
  2.1500 ++{
  2.1501 ++	pseudo_file = realloc(pseudo_file, (pseudo_count + 1) *
  2.1502 ++		sizeof(struct pseudo_dev *));
  2.1503 ++	if(pseudo_file == NULL)
  2.1504 ++		BAD_ERROR("Failed to realloc pseudo_file\n");
  2.1505 ++
  2.1506 ++	dev->pseudo_id = pseudo_count;
  2.1507 ++	pseudo_file[pseudo_count ++] = dev;
  2.1508 ++}
  2.1509 ++
  2.1510 ++
  2.1511 ++void delete_pseudo_files()
  2.1512 ++{
  2.1513 ++#ifdef USE_TMP_FILE
  2.1514 ++	int i;
  2.1515 ++
  2.1516 ++	for(i = 0; i < pseudo_count; i++)
  2.1517 ++		unlink(pseudo_file[i]->filename);
  2.1518 ++#endif
  2.1519 ++}
  2.1520 ++
  2.1521 ++
  2.1522 ++struct pseudo_dev *get_pseudo_file(int pseudo_id)
  2.1523 ++{
  2.1524 ++	return pseudo_file[pseudo_id];
  2.1525 ++}
  2.1526 ++
  2.1527 ++
  2.1528 + int read_pseudo_def(struct pseudo **pseudo, char *def)
  2.1529 + {
  2.1530 +-	int n;
  2.1531 ++	int n, bytes;
  2.1532 + 	unsigned int major = 0, minor = 0, mode;
  2.1533 + 	char filename[2048], type, suid[100], sgid[100], *ptr;
  2.1534 + 	long long uid, gid;
  2.1535 +-	struct pseudo_dev dev;
  2.1536 ++	struct pseudo_dev *dev;
  2.1537 + 
  2.1538 +-	n = sscanf(def, "%s %c %o %s %s %u %u", filename, &type, &mode, suid, sgid,
  2.1539 +-			&major, &minor);
  2.1540 ++	n = sscanf(def, "%s %c %o %s %s %n", filename, &type, &mode, suid,
  2.1541 ++			sgid, &bytes);
  2.1542 + 
  2.1543 + 	if(n < 5) {
  2.1544 + 		ERROR("Not enough or invalid arguments in pseudo file "
  2.1545 +@@ -249,7 +340,9 @@
  2.1546 + 	switch(type) {
  2.1547 + 	case 'b':
  2.1548 + 	case 'c':
  2.1549 +-		if(n < 7) {
  2.1550 ++		n = sscanf(def + bytes,  "%u %u", &major, &minor);
  2.1551 ++
  2.1552 ++		if(n < 2) {
  2.1553 + 			ERROR("Not enough or invalid arguments in pseudo file "
  2.1554 + 				"definition\n");
  2.1555 + 			goto error;
  2.1556 +@@ -265,54 +358,59 @@
  2.1557 + 			goto error;
  2.1558 + 		}
  2.1559 + 
  2.1560 +-		/* fall through */
  2.1561 +-	case 'd':
  2.1562 +-		if(mode > 0777) {
  2.1563 +-			ERROR("Mode %o out of range\n", mode);
  2.1564 ++	case 'f':
  2.1565 ++		if(def[bytes] == '\0') {
  2.1566 ++			ERROR("Not enough arguments in pseudo file "
  2.1567 ++				"definition\n");
  2.1568 + 			goto error;
  2.1569 +-		}
  2.1570 +-
  2.1571 +-		uid = strtoll(suid, &ptr, 10);
  2.1572 +-		if(*ptr == '\0') {
  2.1573 +-			if(uid < 0 || uid > ((1LL << 32) - 1)) {
  2.1574 +-				ERROR("Uid %s out of range\n", suid);
  2.1575 +-				goto error;
  2.1576 +-			}
  2.1577 +-		} else {
  2.1578 +-			struct passwd *pwuid = getpwnam(suid);
  2.1579 +-			if(pwuid)
  2.1580 +-				uid = pwuid->pw_uid;
  2.1581 +-			else {
  2.1582 +-				ERROR("Uid %s invalid uid or unknown user\n",
  2.1583 +-					suid);
  2.1584 +-				goto error;
  2.1585 +-			}
  2.1586 +-		}
  2.1587 +-		
  2.1588 +-		gid = strtoll(sgid, &ptr, 10);
  2.1589 +-		if(*ptr == '\0') {
  2.1590 +-			if(gid < 0 || gid > ((1LL << 32) - 1)) {
  2.1591 +-				ERROR("Gid %s out of range\n", sgid);
  2.1592 +-				goto error;
  2.1593 +-			}
  2.1594 +-		} else {
  2.1595 +-			struct group *grgid = getgrnam(sgid);
  2.1596 +-			if(grgid)
  2.1597 +-				gid = grgid->gr_gid;
  2.1598 +-			else {
  2.1599 +-				ERROR("Gid %s invalid uid or unknown user\n",
  2.1600 +-					sgid);
  2.1601 +-				goto error;
  2.1602 +-			}
  2.1603 +-		}
  2.1604 +-
  2.1605 ++		}	
  2.1606 + 		break;
  2.1607 ++	case 'd':
  2.1608 ++	case 'm':
  2.1609 ++		break;
  2.1610 + 	default:
  2.1611 + 		ERROR("Unsupported type %c\n", type);
  2.1612 + 		goto error;
  2.1613 + 	}
  2.1614 + 
  2.1615 + 
  2.1616 ++	if(mode > 0777) {
  2.1617 ++		ERROR("Mode %o out of range\n", mode);
  2.1618 ++		goto error;
  2.1619 ++	}
  2.1620 ++
  2.1621 ++	uid = strtoll(suid, &ptr, 10);
  2.1622 ++	if(*ptr == '\0') {
  2.1623 ++		if(uid < 0 || uid > ((1LL << 32) - 1)) {
  2.1624 ++			ERROR("Uid %s out of range\n", suid);
  2.1625 ++			goto error;
  2.1626 ++		}
  2.1627 ++	} else {
  2.1628 ++		struct passwd *pwuid = getpwnam(suid);
  2.1629 ++		if(pwuid)
  2.1630 ++			uid = pwuid->pw_uid;
  2.1631 ++		else {
  2.1632 ++			ERROR("Uid %s invalid uid or unknown user\n", suid);
  2.1633 ++			goto error;
  2.1634 ++		}
  2.1635 ++	}
  2.1636 ++		
  2.1637 ++	gid = strtoll(sgid, &ptr, 10);
  2.1638 ++	if(*ptr == '\0') {
  2.1639 ++		if(gid < 0 || gid > ((1LL << 32) - 1)) {
  2.1640 ++			ERROR("Gid %s out of range\n", sgid);
  2.1641 ++			goto error;
  2.1642 ++		}
  2.1643 ++	} else {
  2.1644 ++		struct group *grgid = getgrnam(sgid);
  2.1645 ++		if(grgid)
  2.1646 ++			gid = grgid->gr_gid;
  2.1647 ++		else {
  2.1648 ++			ERROR("Gid %s invalid uid or unknown user\n", sgid);
  2.1649 ++			goto error;
  2.1650 ++		}
  2.1651 ++	}
  2.1652 ++
  2.1653 + 	switch(type) {
  2.1654 + 	case 'b':
  2.1655 + 		mode |= S_IFBLK;
  2.1656 +@@ -323,16 +421,37 @@
  2.1657 + 	case 'd':
  2.1658 + 		mode |= S_IFDIR;
  2.1659 + 		break;
  2.1660 ++	case 'f':
  2.1661 ++		mode |= S_IFREG;
  2.1662 ++		break;
  2.1663 + 	}
  2.1664 + 
  2.1665 +-	dev.type = type;
  2.1666 +-	dev.mode = mode;
  2.1667 +-	dev.uid = uid;
  2.1668 +-	dev.gid = gid;
  2.1669 +-	dev.major = major;
  2.1670 +-	dev.minor = minor;
  2.1671 ++	dev = malloc(sizeof(struct pseudo_dev));
  2.1672 ++	if(dev == NULL)
  2.1673 ++		BAD_ERROR("Failed to create pseudo_dev\n");
  2.1674 + 
  2.1675 +-	*pseudo = add_pseudo(*pseudo, &dev, filename, filename);
  2.1676 ++	dev->type = type;
  2.1677 ++	dev->mode = mode;
  2.1678 ++	dev->uid = uid;
  2.1679 ++	dev->gid = gid;
  2.1680 ++	dev->major = major;
  2.1681 ++	dev->minor = minor;
  2.1682 ++
  2.1683 ++	if(type == 'f') {
  2.1684 ++		int res;
  2.1685 ++
  2.1686 ++		printf("Executing dynamic pseudo file\n");
  2.1687 ++		printf("\t\"%s\"\n", def);
  2.1688 ++		res = exec_file(def + bytes, dev);
  2.1689 ++		if(res == -1) {
  2.1690 ++			ERROR("Failed to execute dynamic pseudo file definition"
  2.1691 ++				" \"%s\"\n", def);
  2.1692 ++			return FALSE;
  2.1693 ++		}
  2.1694 ++		add_pseudo_file(dev);
  2.1695 ++	}
  2.1696 ++
  2.1697 ++	*pseudo = add_pseudo(*pseudo, dev, filename, filename);
  2.1698 + 
  2.1699 + 	return TRUE;
  2.1700 + 
  2.1701 +
  2.1702 +--- squashfs-4.0/squashfs-tools/pseudo.h	Sat Apr  4 03:44:24 2009
  2.1703 ++++ squashfs-4.0/squashfs-tools/pseudo.h	Fri Sep 11 14:10:58 2009
  2.1704 +@@ -27,6 +27,12 @@
  2.1705 + 	unsigned int	gid;
  2.1706 + 	unsigned int	major;
  2.1707 + 	unsigned int	minor;
  2.1708 ++	int		pseudo_id;
  2.1709 ++	int		fd;
  2.1710 ++	int		child;
  2.1711 ++#ifdef USE_TMP_FILE
  2.1712 ++	char		*filename;
  2.1713 ++#endif
  2.1714 + };
  2.1715 + 
  2.1716 + struct pseudo_entry {
  2.1717 +@@ -46,3 +52,5 @@
  2.1718 + extern int read_pseudo_file(struct pseudo **, char *);
  2.1719 + extern struct pseudo *pseudo_subdir(char *, struct pseudo *);
  2.1720 + extern struct pseudo_entry *pseudo_readdir(struct pseudo *);
  2.1721 ++extern struct pseudo_dev *get_pseudo_file(int);
  2.1722 ++extern void delete_pseudo_files();
  2.1723 +
  2.1724 +--- squashfs-4.0/squashfs-tools/read_fs.c	Tue Mar 31 06:23:14 2009
  2.1725 ++++ squashfs-4.0/squashfs-tools/read_fs.c	Mon Aug 24 20:28:04 2009
  2.1726 +@@ -36,7 +36,6 @@
  2.1727 + #include <fcntl.h>
  2.1728 + #include <errno.h>
  2.1729 + #include <string.h>
  2.1730 +-#include <zlib.h>
  2.1731 + #include <sys/mman.h>
  2.1732 + 
  2.1733 + #ifndef linux
  2.1734 +@@ -51,6 +50,7 @@
  2.1735 + #include "squashfs_swap.h"
  2.1736 + #include "read_fs.h"
  2.1737 + #include "global.h"
  2.1738 ++#include "compressor.h"
  2.1739 + 
  2.1740 + #include <stdlib.h>
  2.1741 + 
  2.1742 +@@ -66,7 +66,9 @@
  2.1743 + 						fprintf(stderr, s, ## args); \
  2.1744 + 					} while(0)
  2.1745 + 
  2.1746 +-int read_block(int fd, long long start, long long *next, unsigned char *block,
  2.1747 ++static struct compressor *comp;
  2.1748 ++
  2.1749 ++int read_block(int fd, long long start, long long *next, void *block,
  2.1750 + 	squashfs_super_block *sBlk)
  2.1751 + {
  2.1752 + 	unsigned short c_byte;
  2.1753 +@@ -77,32 +79,24 @@
  2.1754 + 
  2.1755 + 	if(SQUASHFS_COMPRESSED(c_byte)) {
  2.1756 + 		char buffer[SQUASHFS_METADATA_SIZE];
  2.1757 +-		int res;
  2.1758 +-		unsigned long bytes = SQUASHFS_METADATA_SIZE;
  2.1759 ++		int error, res;
  2.1760 + 
  2.1761 + 		c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
  2.1762 + 		read_destination(fd, start + offset, c_byte, buffer);
  2.1763 + 
  2.1764 +-		res = uncompress(block, &bytes, (const unsigned char *) buffer,
  2.1765 +-			c_byte);
  2.1766 +-		if(res != Z_OK) {
  2.1767 +-			if(res == Z_MEM_ERROR)
  2.1768 +-				ERROR("zlib::uncompress failed, not enough "
  2.1769 +-					"memory\n");
  2.1770 +-			else if(res == Z_BUF_ERROR)
  2.1771 +-				ERROR("zlib::uncompress failed, not enough "
  2.1772 +-					"room in output buffer\n");
  2.1773 +-			else
  2.1774 +-				ERROR("zlib::uncompress failed, unknown error "
  2.1775 +-					"%d\n", res);
  2.1776 ++		res = comp->uncompress(block, buffer, c_byte,
  2.1777 ++			SQUASHFS_METADATA_SIZE, &error);
  2.1778 ++		if(res == -1) {
  2.1779 ++			ERROR("%s uncompress failed with error code %d\n",
  2.1780 ++				comp->name, error);
  2.1781 + 			return 0;
  2.1782 + 		}
  2.1783 + 		if(next)
  2.1784 + 			*next = start + offset + c_byte;
  2.1785 +-		return bytes;
  2.1786 ++		return res;
  2.1787 + 	} else {
  2.1788 + 		c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
  2.1789 +-		read_destination(fd, start + offset, c_byte, (char *) block);
  2.1790 ++		read_destination(fd, start + offset, c_byte, block);
  2.1791 + 		if(next)
  2.1792 + 			*next = start + offset + c_byte;
  2.1793 + 		return c_byte;
  2.1794 +@@ -356,7 +350,7 @@
  2.1795 + }
  2.1796 + 
  2.1797 + 
  2.1798 +-int read_super(int fd, squashfs_super_block *sBlk, char *source)
  2.1799 ++struct compressor *read_super(int fd, squashfs_super_block *sBlk, char *source)
  2.1800 + {
  2.1801 + 	read_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block),
  2.1802 + 		(char *) sBlk);
  2.1803 +@@ -388,8 +382,18 @@
  2.1804 + 		goto failed_mount;
  2.1805 + 	}
  2.1806 + 
  2.1807 ++	/* Check the compression type */
  2.1808 ++	comp = lookup_compressor_id(sBlk->compression);
  2.1809 ++	if(!comp->supported) {
  2.1810 ++		ERROR("Filesystem on %s uses %s compression, this is"
  2.1811 ++			"unsupported by this version\n", source, comp->name);
  2.1812 ++		display_compressors("", "");
  2.1813 ++		goto failed_mount;
  2.1814 ++	}
  2.1815 ++
  2.1816 + 	printf("Found a valid %sSQUASHFS superblock on %s.\n",
  2.1817 + 		SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source);
  2.1818 ++	printf("\tCompression used %s\n", comp->name);
  2.1819 + 	printf("\tInodes are %scompressed\n",
  2.1820 + 		SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : "");
  2.1821 + 	printf("\tData is %scompressed\n",
  2.1822 +@@ -417,10 +421,10 @@
  2.1823 + 	TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start);
  2.1824 + 	printf("\n");
  2.1825 + 
  2.1826 +-	return TRUE;
  2.1827 ++	return comp;
  2.1828 + 
  2.1829 + failed_mount:
  2.1830 +-	return FALSE;
  2.1831 ++	return NULL;
  2.1832 + }
  2.1833 + 
  2.1834 + 
  2.1835 +@@ -514,12 +518,17 @@
  2.1836 + 	SQUASHFS_INSWAP_ID_BLOCKS(index, indexes);
  2.1837 + 
  2.1838 + 	for(i = 0; i < indexes; i++) {
  2.1839 +-		int length;
  2.1840 +-		length = read_block(fd, index[i], NULL,
  2.1841 ++		int length = read_block(fd, index[i], NULL,
  2.1842 + 			((unsigned char *) id_table) +
  2.1843 + 			(i * SQUASHFS_METADATA_SIZE), sBlk);
  2.1844 + 		TRACE("Read id table block %d, from 0x%llx, length %d\n", i,
  2.1845 + 			index[i], length);
  2.1846 ++		if(length == 0) {
  2.1847 ++			ERROR("Failed to read id table block %d, from 0x%llx, "
  2.1848 ++				"length %d\n", i, index[i], length);
  2.1849 ++			free(id_table);
  2.1850 ++			return NULL;
  2.1851 ++		}
  2.1852 + 	}
  2.1853 + 
  2.1854 + 	SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids);
  2.1855 +@@ -563,6 +572,13 @@
  2.1856 + 			(i * SQUASHFS_METADATA_SIZE), sBlk);
  2.1857 + 		TRACE("Read fragment table block %d, from 0x%llx, length %d\n",
  2.1858 + 			i, fragment_table_index[i], length);
  2.1859 ++		if(length == 0) {
  2.1860 ++			ERROR("Failed to read fragment table block %d, from "
  2.1861 ++				"0x%llx, length %d\n", i,
  2.1862 ++				fragment_table_index[i], length);
  2.1863 ++			free(*fragment_table);
  2.1864 ++			return 0;
  2.1865 ++		}
  2.1866 + 	}
  2.1867 + 
  2.1868 + 	for(i = 0; i < sBlk->fragments; i++)
  2.1869 +@@ -599,6 +615,13 @@
  2.1870 + 			(i * SQUASHFS_METADATA_SIZE), sBlk);
  2.1871 + 		TRACE("Read inode lookup table block %d, from 0x%llx, length "
  2.1872 + 			"%d\n", i, index[i], length);
  2.1873 ++		if(length == 0) {
  2.1874 ++			ERROR("Failed to read inode lookup table block %d, "
  2.1875 ++				"from 0x%llx, length %d\n", i, index[i],
  2.1876 ++				length);
  2.1877 ++			free(*inode_lookup_table);
  2.1878 ++			return 0;
  2.1879 ++		}
  2.1880 + 	}
  2.1881 + 
  2.1882 + 	SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes);
  2.1883 +
  2.1884 +--- squashfs-4.0/squashfs-tools/sort.c	Tue Mar 31 06:25:53 2009
  2.1885 ++++ squashfs-4.0/squashfs-tools/sort.c	Sat Aug 29 07:41:45 2009
  2.1886 +@@ -198,7 +198,7 @@
  2.1887 + 	while(dir->current_count < dir->count) {
  2.1888 + 		struct dir_ent *dir_ent = dir->list[dir->current_count++];
  2.1889 + 		struct stat *buf = &dir_ent->inode->buf;
  2.1890 +-		if(dir_ent->data)
  2.1891 ++		if(dir_ent->inode->root_entry)
  2.1892 + 			continue;
  2.1893 + 
  2.1894 + 		switch(buf->st_mode & S_IFMT) {
  2.1895 +@@ -254,6 +254,7 @@
  2.1896 + 				write_file(&inode, entry->dir, &duplicate_file);
  2.1897 + 				INFO("file %s, uncompressed size %lld bytes %s"
  2.1898 + 					"\n", entry->dir->pathname,
  2.1899 ++					(long long)
  2.1900 + 					entry->dir->inode->buf.st_size,
  2.1901 + 					duplicate_file ? "DUPLICATE" : "");
  2.1902 + 				entry->dir->inode->inode = inode;
  2.1903 +@@ -261,6 +262,7 @@
  2.1904 + 			} else
  2.1905 + 				INFO("file %s, uncompressed size %lld bytes "
  2.1906 + 					"LINK\n", entry->dir->pathname,
  2.1907 ++					(long long)
  2.1908 + 					entry->dir->inode->buf.st_size);
  2.1909 + 		}
  2.1910 + }
  2.1911 +
  2.1912 +--- squashfs-4.0/squashfs-tools/sort.h	Sun Feb  8 13:02:53 2009
  2.1913 ++++ squashfs-4.0/squashfs-tools/sort.h	Thu Sep 10 05:50:01 2009
  2.1914 +@@ -42,17 +42,19 @@
  2.1915 + 	struct inode_info	*inode;
  2.1916 + 	struct dir_info		*dir;
  2.1917 + 	struct dir_info		*our_dir;
  2.1918 +-	struct old_root_entry_info *data;
  2.1919 + };
  2.1920 + 
  2.1921 + struct inode_info {
  2.1922 +-	unsigned int		nlink;
  2.1923 + 	struct stat		buf;
  2.1924 ++	struct inode_info	*next;
  2.1925 + 	squashfs_inode		inode;
  2.1926 +-	unsigned int		type;
  2.1927 + 	unsigned int		inode_number;
  2.1928 ++	unsigned int		nlink;
  2.1929 ++	int			pseudo_id;
  2.1930 ++	char			type;
  2.1931 + 	char			read;
  2.1932 +-	struct inode_info	*next;
  2.1933 ++	char			root_entry;
  2.1934 ++	char			pseudo_file;
  2.1935 + };
  2.1936 + 
  2.1937 + struct priority_entry {
  2.1938 +
  2.1939 +--- squashfs-4.0/squashfs-tools/squashfs_compat.h	Mon Mar 16 05:27:27 2009
  2.1940 ++++ squashfs-4.0/squashfs-tools/squashfs_compat.h	Tue Apr 21 02:52:24 2009
  2.1941 +@@ -777,11 +777,10 @@
  2.1942 + #endif
  2.1943 + 
  2.1944 + #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
  2.1945 +-	int bits;\
  2.1946 +-	int b_pos = pos % 8;\
  2.1947 +-	unsigned long long val = 0;\
  2.1948 +-	unsigned char *s = (unsigned char *)p + (pos / 8);\
  2.1949 +-	unsigned char *d = ((unsigned char *) &val) + 7;\
  2.1950 ++	b_pos = pos % 8;\
  2.1951 ++	val = 0;\
  2.1952 ++	s = (unsigned char *)p + (pos / 8);\
  2.1953 ++	d = ((unsigned char *) &val) + 7;\
  2.1954 + 	for(bits = 0; bits < (tbits + b_pos); bits += 8) \
  2.1955 + 		*d-- = *s++;\
  2.1956 + 	value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
  2.1957 +
  2.1958 +--- squashfs-4.0/squashfs-tools/squashfs_fs.h	Wed Mar 18 03:50:20 2009
  2.1959 ++++ squashfs-4.0/squashfs-tools/squashfs_fs.h	Thu Jul 30 06:45:38 2009
  2.1960 +@@ -229,6 +229,7 @@
  2.1961 + typedef long long		squashfs_inode_t;
  2.1962 + 
  2.1963 + #define ZLIB_COMPRESSION	1
  2.1964 ++#define LZMA_COMPRESSION	2
  2.1965 + 
  2.1966 + struct squashfs_super_block {
  2.1967 + 	unsigned int		s_magic;
  2.1968 +
  2.1969 +--- squashfs-4.0/squashfs-tools/unsquash-3.c	Tue Mar 31 06:35:10 2009
  2.1970 ++++ squashfs-4.0/squashfs-tools/unsquash-3.c	Tue Apr 21 02:58:22 2009
  2.1971 +@@ -36,7 +36,7 @@
  2.1972 + 		sBlk.fragment_table_start);
  2.1973 + 
  2.1974 + 	if(sBlk.fragments == 0)
  2.1975 +-		return;
  2.1976 ++		return TRUE;
  2.1977 + 
  2.1978 + 	if((fragment_table = malloc(sBlk.fragments *
  2.1979 + 			sizeof(squashfs_fragment_entry_3))) == NULL)
  2.1980 +
  2.1981 +--- squashfs-4.0/squashfs-tools/unsquash-4.c	Tue Mar 31 06:38:31 2009
  2.1982 ++++ squashfs-4.0/squashfs-tools/unsquash-4.c	Tue Apr 21 02:59:16 2009
  2.1983 +@@ -38,7 +38,7 @@
  2.1984 + 		sBlk.fragment_table_start);
  2.1985 + 
  2.1986 + 	if(sBlk.fragments == 0)
  2.1987 +-		return;
  2.1988 ++		return TRUE;
  2.1989 + 
  2.1990 + 	if((fragment_table = malloc(sBlk.fragments *
  2.1991 + 			sizeof(squashfs_fragment_entry))) == NULL)
  2.1992 +
  2.1993 +--- squashfs-4.0/squashfs-tools/unsquashfs.c	Sun Apr  5 23:23:06 2009
  2.1994 ++++ squashfs-4.0/squashfs-tools/unsquashfs.c	Sun Aug 30 16:10:31 2009
  2.1995 +@@ -25,7 +25,10 @@
  2.1996 + #include "squashfs_swap.h"
  2.1997 + #include "squashfs_compat.h"
  2.1998 + #include "read_fs.h"
  2.1999 ++#include "compressor.h"
  2.2000 + 
  2.2001 ++#include <sys/sysinfo.h>
  2.2002 ++
  2.2003 + struct cache *fragment_cache, *data_cache;
  2.2004 + struct queue *to_reader, *to_deflate, *to_writer, *from_writer;
  2.2005 + pthread_t *thread, *deflator_thread;
  2.2006 +@@ -36,6 +39,7 @@
  2.2007 + 
  2.2008 + struct super_block sBlk;
  2.2009 + squashfs_operations s_ops;
  2.2010 ++struct compressor *comp;
  2.2011 + 
  2.2012 + int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0,
  2.2013 + 	dev_count = 0, fifo_count = 0;
  2.2014 +@@ -590,31 +594,23 @@
  2.2015 + 		offset = 3;
  2.2016 + 	if(SQUASHFS_COMPRESSED(c_byte)) {
  2.2017 + 		char buffer[SQUASHFS_METADATA_SIZE];
  2.2018 +-		int res;
  2.2019 +-		unsigned long bytes = SQUASHFS_METADATA_SIZE;
  2.2020 ++		int error, res;
  2.2021 + 
  2.2022 + 		c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
  2.2023 + 		if(read_bytes(start + offset, c_byte, buffer) == FALSE)
  2.2024 + 			goto failed;
  2.2025 + 
  2.2026 +-		res = uncompress((unsigned char *) block, &bytes,
  2.2027 +-			(const unsigned char *) buffer, c_byte);
  2.2028 ++		res = comp->uncompress(block, buffer, c_byte,
  2.2029 ++			SQUASHFS_METADATA_SIZE, &error);
  2.2030 + 
  2.2031 +-		if(res != Z_OK) {
  2.2032 +-			if(res == Z_MEM_ERROR)
  2.2033 +-				ERROR("zlib::uncompress failed, not enough "
  2.2034 +-					"memory\n");
  2.2035 +-			else if(res == Z_BUF_ERROR)
  2.2036 +-				ERROR("zlib::uncompress failed, not enough "
  2.2037 +-					"room in output buffer\n");
  2.2038 +-			else
  2.2039 +-				ERROR("zlib::uncompress failed, unknown error "
  2.2040 +-					"%d\n", res);
  2.2041 ++		if(res == -1) {
  2.2042 ++			ERROR("%s uncompress failed with error code %d\n",
  2.2043 ++				comp->name, error);
  2.2044 + 			goto failed;
  2.2045 + 		}
  2.2046 + 		if(next)
  2.2047 + 			*next = start + offset + c_byte;
  2.2048 +-		return bytes;
  2.2049 ++		return res;
  2.2050 + 	} else {
  2.2051 + 		c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
  2.2052 + 		if(read_bytes(start + offset, c_byte, block) == FALSE)
  2.2053 +@@ -632,36 +628,26 @@
  2.2054 + 
  2.2055 + int read_data_block(long long start, unsigned int size, char *block)
  2.2056 + {
  2.2057 +-	int res;
  2.2058 +-	unsigned long bytes = block_size;
  2.2059 ++	int error, res;
  2.2060 + 	int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size);
  2.2061 + 
  2.2062 + 	TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start,
  2.2063 +-		SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte),
  2.2064 +-		SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" :
  2.2065 ++		c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" :
  2.2066 + 		"uncompressed");
  2.2067 + 
  2.2068 + 	if(SQUASHFS_COMPRESSED_BLOCK(size)) {
  2.2069 + 		if(read_bytes(start, c_byte, data) == FALSE)
  2.2070 + 			goto failed;
  2.2071 + 
  2.2072 +-		res = uncompress((unsigned char *) block, &bytes,
  2.2073 +-			(const unsigned char *) data, c_byte);
  2.2074 ++		res = comp->uncompress(block, data, c_byte, block_size, &error);
  2.2075 + 
  2.2076 +-		if(res != Z_OK) {
  2.2077 +-			if(res == Z_MEM_ERROR)
  2.2078 +-				ERROR("zlib::uncompress failed, not enough "
  2.2079 +-					"memory\n");
  2.2080 +-			else if(res == Z_BUF_ERROR)
  2.2081 +-				ERROR("zlib::uncompress failed, not enough "
  2.2082 +-					"room in output buffer\n");
  2.2083 +-			else
  2.2084 +-				ERROR("zlib::uncompress failed, unknown error "
  2.2085 +-					"%d\n", res);
  2.2086 ++		if(res == -1) {
  2.2087 ++			ERROR("%s uncompress failed with error code %d\n",
  2.2088 ++				comp->name, error);
  2.2089 + 			goto failed;
  2.2090 + 		}
  2.2091 + 
  2.2092 +-		return bytes;
  2.2093 ++		return res;
  2.2094 + 	} else {
  2.2095 + 		if(read_bytes(start, c_byte, block) == FALSE)
  2.2096 + 			goto failed;
  2.2097 +@@ -671,7 +657,7 @@
  2.2098 + 
  2.2099 + failed:
  2.2100 + 	ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start,
  2.2101 +-		size);
  2.2102 ++		c_byte);
  2.2103 + 	return FALSE;
  2.2104 + }
  2.2105 + 
  2.2106 +@@ -1383,6 +1369,11 @@
  2.2107 + #endif
  2.2108 + 	printf("Creation or last append time %s", mkfs_str ? mkfs_str :
  2.2109 + 		"failed to get time\n");
  2.2110 ++	printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n",
  2.2111 ++		sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0));
  2.2112 ++	if(sBlk.s_major == 4)
  2.2113 ++		printf("Compression %s\n", comp->name);
  2.2114 ++	printf("Block size %d\n", sBlk.block_size);
  2.2115 + 	printf("Filesystem is %sexportable via NFS\n",
  2.2116 + 		SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not ");
  2.2117 + 
  2.2118 +@@ -1409,9 +1400,6 @@
  2.2119 + 			SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not ");
  2.2120 + 	else
  2.2121 + 		printf("Duplicates are removed\n");
  2.2122 +-	printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n",
  2.2123 +-		sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0));
  2.2124 +-	printf("Block size %d\n", sBlk.block_size);
  2.2125 + 	if(sBlk.s_major > 1)
  2.2126 + 		printf("Number of fragments %d\n", sBlk.fragments);
  2.2127 + 	printf("Number of inodes %d\n", sBlk.inodes);
  2.2128 +@@ -1459,6 +1447,18 @@
  2.2129 + 		s_ops.read_inode = read_inode_4;
  2.2130 + 		s_ops.read_uids_guids = read_uids_guids_4;
  2.2131 + 		memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4));
  2.2132 ++
  2.2133 ++		/*
  2.2134 ++		 * Check the compression type
  2.2135 ++		 */
  2.2136 ++		comp = lookup_compressor_id(sBlk.compression);
  2.2137 ++		if(!comp->supported) {
  2.2138 ++			ERROR("Filesystem uses %s compression, this is "
  2.2139 ++				"unsupported by this version\n", comp->name);
  2.2140 ++			ERROR("Decompressors available:\n");
  2.2141 ++			display_compressors("", "");
  2.2142 ++			goto failed_mount;
  2.2143 ++		}
  2.2144 + 		return TRUE;
  2.2145 + 	}
  2.2146 + 
  2.2147 +@@ -1548,6 +1548,11 @@
  2.2148 + 		goto failed_mount;
  2.2149 + 	}
  2.2150 + 
  2.2151 ++	/*
  2.2152 ++	 * 1.x, 2.x and 3.x filesystems use gzip compression.  Gzip is always
  2.2153 ++	 * suppported.
  2.2154 ++	 */
  2.2155 ++	comp = lookup_compressor("gzip");
  2.2156 + 	return TRUE;
  2.2157 + 
  2.2158 + failed_mount:
  2.2159 +@@ -1707,32 +1712,24 @@
  2.2160 + 
  2.2161 + 	while(1) {
  2.2162 + 		struct cache_entry *entry = queue_get(to_deflate);
  2.2163 +-		int res;
  2.2164 +-		unsigned long bytes = block_size;
  2.2165 ++		int error, res;
  2.2166 + 
  2.2167 +-		res = uncompress((unsigned char *) tmp, &bytes,
  2.2168 +-			(const unsigned char *) entry->data,
  2.2169 +-			SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size));
  2.2170 ++		res = comp->uncompress(tmp, entry->data,
  2.2171 ++			SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size,
  2.2172 ++			&error);
  2.2173 + 
  2.2174 +-		if(res != Z_OK) {
  2.2175 +-			if(res == Z_MEM_ERROR)
  2.2176 +-				ERROR("zlib::uncompress failed, not enough"
  2.2177 +-					"memory\n");
  2.2178 +-			else if(res == Z_BUF_ERROR)
  2.2179 +-				ERROR("zlib::uncompress failed, not enough "
  2.2180 +-					"room in output buffer\n");
  2.2181 +-			else
  2.2182 +-				ERROR("zlib::uncompress failed, unknown error "
  2.2183 +-					"%d\n", res);
  2.2184 +-		} else
  2.2185 +-			memcpy(entry->data, tmp, bytes);
  2.2186 ++		if(res == -1)
  2.2187 ++			ERROR("%s uncompress failed with error code %d\n",
  2.2188 ++				comp->name, error);
  2.2189 ++		else
  2.2190 ++			memcpy(entry->data, tmp, res);
  2.2191 + 
  2.2192 + 		/*
  2.2193 + 		 * block has been either successfully decompressed, or an error
  2.2194 +  		 * occurred, clear pending flag, set error appropriately and
  2.2195 +  		 * wake up any threads waiting on this block
  2.2196 +  		 */ 
  2.2197 +-		cache_block_ready(entry, res != Z_OK);
  2.2198 ++		cache_block_ready(entry, res == -1);
  2.2199 + 	}
  2.2200 + }
  2.2201 + 
  2.2202 +@@ -1913,7 +1910,7 @@
  2.2203 + 
  2.2204 + 
  2.2205 + #define VERSION() \
  2.2206 +-	printf("unsquashfs version 4.0 (2009/04/05)\n");\
  2.2207 ++	printf("unsquashfs version 4.0 (CVS 2009/08/30)\n");\
  2.2208 + 	printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>"\
  2.2209 + 		"\n\n");\
  2.2210 +     	printf("This program is free software; you can redistribute it and/or\n");\
  2.2211 +@@ -1938,7 +1935,6 @@
  2.2212 + 	int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT;
  2.2213 + 	int data_buffer_size = DATA_BUFFER_DEFAULT;
  2.2214 + 	char *b;
  2.2215 +-	struct winsize winsize;
  2.2216 + 
  2.2217 + 	pthread_mutex_init(&screen_mutex, NULL);
  2.2218 + 	root_process = geteuid() == 0;
  2.2219 +@@ -2087,6 +2083,8 @@
  2.2220 + 				"regular expressions\n");
  2.2221 + 			ERROR("\t\t\t\trather than use the default shell "
  2.2222 + 				"wildcard\n\t\t\t\texpansion (globbing)\n");
  2.2223 ++			ERROR("\nDecompressors available:\n");
  2.2224 ++			display_compressors("", "");
  2.2225 + 		}
  2.2226 + 		exit(1);
  2.2227 + 	}
  2.2228 +
  2.2229 +--- squashfs-4.0/squashfs-tools/unsquashfs.h	Sun Mar 29 04:29:02 2009
  2.2230 ++++ squashfs-4.0/squashfs-tools/unsquashfs.h	Fri Jul 31 19:24:38 2009
  2.2231 +@@ -31,7 +31,6 @@
  2.2232 + #include <fcntl.h>
  2.2233 + #include <errno.h>
  2.2234 + #include <string.h>
  2.2235 +-#include <zlib.h>
  2.2236 + #include <sys/mman.h>
  2.2237 + #include <utime.h>
  2.2238 + #include <pwd.h>