wok diff squashfs/stuff/lzma.u @ 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
children 9f7f4d06661f
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/squashfs/stuff/lzma.u	Sun Jan 03 18:38:54 2010 +0100
     1.3 @@ -0,0 +1,2235 @@
     1.4 +--- squashfs-4.0/squashfs-tools/Makefile
     1.5 ++++ squashfs-4.0/squashfs-tools/Makefile
     1.6 +@@ -1,40 +1,76 @@
     1.7 ++#
     1.8 ++# Building LZMA support
     1.9 ++# Download LZMA sdk (4.65 used in development, other versions may work),
    1.10 ++# set LZMA_DIR to unpacked source, and uncomment next line
    1.11 ++LZMA_SUPPORT = 1
    1.12 ++LZMA_DIR = ../LZMA/lzma465
    1.13 ++
    1.14 ++#Compression default.
    1.15 ++COMP_DEFAULT = gzip
    1.16 ++
    1.17 ++INCLUDEDIR = -I.
    1.18 + INSTALL_DIR = /usr/local/bin
    1.19 + 
    1.20 +-INCLUDEDIR = .
    1.21 ++MKSQUASHFS_OBJS = mksquashfs.o read_fs.o sort.o swap.o pseudo.o compressor.o \
    1.22 ++	gzip_wrapper.o
    1.23 + 
    1.24 +-CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2
    1.25 ++UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \
    1.26 ++	unsquash-4.o swap.o compressor.o gzip_wrapper.o
    1.27 + 
    1.28 ++CFLAGS = $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
    1.29 ++	-D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" -O2 -Wall
    1.30 ++
    1.31 ++ifdef LZMA_SUPPORT
    1.32 ++LZMA_OBJS = $(LZMA_DIR)/C/Alloc.o $(LZMA_DIR)/C/LzFind.o \
    1.33 ++	$(LZMA_DIR)/C/LzmaDec.o $(LZMA_DIR)/C/LzmaEnc.o $(LZMA_DIR)/C/LzmaLib.o
    1.34 ++INCLUDEDIR += -I$(LZMA_DIR)/C
    1.35 ++CFLAGS += -DLZMA_SUPPORT
    1.36 ++MKSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS)
    1.37 ++UNSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS)
    1.38 ++endif
    1.39 ++
    1.40 ++.PHONY: all
    1.41 + all: mksquashfs unsquashfs
    1.42 + 
    1.43 +-mksquashfs: mksquashfs.o read_fs.o sort.o swap.o pseudo.o
    1.44 +-	$(CC) mksquashfs.o read_fs.o sort.o swap.o pseudo.o -lz -lpthread -lm -o $@
    1.45 ++mksquashfs: $(MKSQUASHFS_OBJS)
    1.46 ++	$(CC) $(MKSQUASHFS_OBJS) -lz -lpthread -lm -o $@
    1.47 + 
    1.48 +-mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h squashfs_swap.h Makefile
    1.49 ++mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \
    1.50 ++	squashfs_swap.h
    1.51 + 
    1.52 +-read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h Makefile
    1.53 ++read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h
    1.54 + 
    1.55 +-sort.o: sort.c squashfs_fs.h global.h sort.h Makefile
    1.56 ++sort.o: sort.c squashfs_fs.h global.h sort.h
    1.57 + 
    1.58 +-swap.o: swap.c Makefile
    1.59 ++swap.o: swap.c
    1.60 + 
    1.61 +-pseudo.o: pseudo.c pseudo.h Makefile
    1.62 ++pseudo.o: pseudo.c pseudo.h
    1.63 + 
    1.64 +-unsquashfs: unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o
    1.65 +-	$(CC) unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o -lz -lpthread -lm -o $@
    1.66 ++compressor.o: compressor.c compressor.h
    1.67 + 
    1.68 +-unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h squashfs_compat.h global.h Makefile
    1.69 ++unsquashfs: $(UNSQUASHFS_OBJS)
    1.70 ++	$(CC) $(UNSQUASHFS_OBJS) -lz -lpthread -lm -o $@
    1.71 + 
    1.72 +-unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h global.h Makefile
    1.73 ++unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h \
    1.74 ++	squashfs_compat.h global.h
    1.75 + 
    1.76 +-unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h squashfs_compat.h global.h Makefile
    1.77 ++unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h \
    1.78 ++	global.h
    1.79 + 
    1.80 +-unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h global.h Makefile
    1.81 ++unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h \
    1.82 ++	squashfs_compat.h global.h
    1.83 + 
    1.84 +-unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h global.h Makefile
    1.85 ++unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h \
    1.86 ++	global.h
    1.87 + 
    1.88 ++unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h \
    1.89 ++	global.h
    1.90 ++
    1.91 ++.PHONY: clean
    1.92 + clean:
    1.93 + 	-rm -f *.o mksquashfs unsquashfs
    1.94 + 
    1.95 ++.PHONY: install
    1.96 + install: mksquashfs unsquashfs
    1.97 + 	mkdir -p $(INSTALL_DIR)
    1.98 + 	cp mksquashfs $(INSTALL_DIR)
    1.99 +
   1.100 +--- squashfs-4.0/squashfs-tools/compressor.c	Thu Jan  1 01:00:00 1970
   1.101 ++++ squashfs-4.0/squashfs-tools/compressor.c	Sat Aug 29 03:05:34 2009
   1.102 +@@ -0,0 +1,78 @@
   1.103 ++/*
   1.104 ++ *
   1.105 ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
   1.106 ++ * Phillip Lougher <phillip@lougher.demon.co.uk>
   1.107 ++ *
   1.108 ++ * This program is free software; you can redistribute it and/or
   1.109 ++ * modify it under the terms of the GNU General Public License
   1.110 ++ * as published by the Free Software Foundation; either version 2,
   1.111 ++ * or (at your option) any later version.
   1.112 ++ *
   1.113 ++ * This program is distributed in the hope that it will be useful,
   1.114 ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
   1.115 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   1.116 ++ * GNU General Public License for more details.
   1.117 ++ *
   1.118 ++ * You should have received a copy of the GNU General Public License
   1.119 ++ * along with this program; if not, write to the Free Software
   1.120 ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   1.121 ++ *
   1.122 ++ * compressor.c
   1.123 ++ */
   1.124 ++
   1.125 ++#include <stdio.h>
   1.126 ++#include <string.h>
   1.127 ++#include "compressor.h"
   1.128 ++#include "squashfs_fs.h"
   1.129 ++
   1.130 ++extern int gzip_compress(void **, char *, char *, int, int, int *);
   1.131 ++extern int gzip_uncompress(char *, char *, int, int, int *);
   1.132 ++extern int lzma_compress(void **, char *, char *, int, int, int *);
   1.133 ++extern int lzma_uncompress(char *, char *, int, int, int *);
   1.134 ++
   1.135 ++struct compressor compressor[] = {
   1.136 ++	{ gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 },
   1.137 ++#ifdef LZMA_SUPPORT
   1.138 ++	{ lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 },
   1.139 ++#else
   1.140 ++	{ NULL, NULL, LZMA_COMPRESSION, "lzma", 0 },
   1.141 ++#endif
   1.142 ++	{ NULL, NULL , 0, "unknown", 0}
   1.143 ++};
   1.144 ++
   1.145 ++
   1.146 ++struct compressor *lookup_compressor(char *name)
   1.147 ++{
   1.148 ++	int i;
   1.149 ++
   1.150 ++	for(i = 0; compressor[i].id; i++)
   1.151 ++		if(strcmp(compressor[i].name, name) == 0)
   1.152 ++			break;
   1.153 ++
   1.154 ++	return &compressor[i];
   1.155 ++}
   1.156 ++
   1.157 ++
   1.158 ++struct compressor *lookup_compressor_id(int id)
   1.159 ++{
   1.160 ++	int i;
   1.161 ++
   1.162 ++	for(i = 0; compressor[i].id; i++)
   1.163 ++		if(id == compressor[i].id)
   1.164 ++			break;
   1.165 ++
   1.166 ++	return &compressor[i];
   1.167 ++}
   1.168 ++
   1.169 ++
   1.170 ++void display_compressors(char *indent, char *def_comp)
   1.171 ++{
   1.172 ++	int i;
   1.173 ++
   1.174 ++	for(i = 0; compressor[i].id; i++)
   1.175 ++		if(compressor[i].supported)
   1.176 ++			fprintf(stderr, "%s\t%s%s\n", indent,
   1.177 ++				compressor[i].name,
   1.178 ++				strcmp(compressor[i].name, def_comp) == 0 ?
   1.179 ++				" (default)" : "");
   1.180 ++}
   1.181 +
   1.182 +--- squashfs-4.0/squashfs-tools/compressor.h	Thu Jan  1 01:00:00 1970
   1.183 ++++ squashfs-4.0/squashfs-tools/compressor.h	Mon Aug 24 20:28:04 2009
   1.184 +@@ -0,0 +1,33 @@
   1.185 ++/*
   1.186 ++ *
   1.187 ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
   1.188 ++ * Phillip Lougher <phillip@lougher.demon.co.uk>
   1.189 ++ *
   1.190 ++ * This program is free software; you can redistribute it and/or
   1.191 ++ * modify it under the terms of the GNU General Public License
   1.192 ++ * as published by the Free Software Foundation; either version 2,
   1.193 ++ * or (at your option) any later version.
   1.194 ++ *
   1.195 ++ * This program is distributed in the hope that it will be useful,
   1.196 ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
   1.197 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   1.198 ++ * GNU General Public License for more details.
   1.199 ++ *
   1.200 ++ * You should have received a copy of the GNU General Public License
   1.201 ++ * along with this program; if not, write to the Free Software
   1.202 ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   1.203 ++ *
   1.204 ++ * compressor.h
   1.205 ++ */
   1.206 ++
   1.207 ++struct compressor {
   1.208 ++	int (*compress)(void **, char *, char *, int, int, int *);
   1.209 ++	int (*uncompress)(char *, char *, int, int, int *);
   1.210 ++	int id;
   1.211 ++	char *name;
   1.212 ++	int supported;
   1.213 ++};
   1.214 ++
   1.215 ++extern struct compressor *lookup_compressor(char *);
   1.216 ++extern struct compressor *lookup_compressor_id(int);
   1.217 ++extern void display_compressors(char *, char *);
   1.218 +
   1.219 +--- squashfs-4.0/squashfs-tools/gzip_wrapper.c	Thu Jan  1 01:00:00 1970
   1.220 ++++ squashfs-4.0/squashfs-tools/gzip_wrapper.c	Fri Aug  7 22:12:53 2009
   1.221 +@@ -0,0 +1,80 @@
   1.222 ++/*
   1.223 ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
   1.224 ++ * Phillip Lougher <phillip@lougher.demon.co.uk>
   1.225 ++ *
   1.226 ++ * This program is free software; you can redistribute it and/or
   1.227 ++ * modify it under the terms of the GNU General Public License
   1.228 ++ * as published by the Free Software Foundation; either version 2,
   1.229 ++ * or (at your option) any later version.
   1.230 ++ *
   1.231 ++ * This program is distributed in the hope that it will be useful,
   1.232 ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
   1.233 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   1.234 ++ * GNU General Public License for more details.
   1.235 ++ *
   1.236 ++ * You should have received a copy of the GNU General Public License
   1.237 ++ * along with this program; if not, write to the Free Software
   1.238 ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   1.239 ++ *
   1.240 ++ * gzip_wrapper.c
   1.241 ++ */
   1.242 ++
   1.243 ++#include <stdlib.h>
   1.244 ++#include <zlib.h>
   1.245 ++
   1.246 ++int gzip_compress(void **strm, char *d, char *s, int size, int block_size,
   1.247 ++		int *error)
   1.248 ++{
   1.249 ++	int res = 0;
   1.250 ++	z_stream *stream = *strm;
   1.251 ++
   1.252 ++	if(stream == NULL) {
   1.253 ++		if((stream = *strm = malloc(sizeof(z_stream))) == NULL)
   1.254 ++			goto failed;
   1.255 ++
   1.256 ++		stream->zalloc = Z_NULL;
   1.257 ++		stream->zfree = Z_NULL;
   1.258 ++		stream->opaque = 0;
   1.259 ++
   1.260 ++		if((res = deflateInit(stream, 9)) != Z_OK)
   1.261 ++			goto failed;
   1.262 ++	} else if((res = deflateReset(stream)) != Z_OK)
   1.263 ++		goto failed;
   1.264 ++
   1.265 ++	stream->next_in = (unsigned char *) s;
   1.266 ++	stream->avail_in = size;
   1.267 ++	stream->next_out = (unsigned char *) d;
   1.268 ++	stream->avail_out = block_size;
   1.269 ++
   1.270 ++	res = deflate(stream, Z_FINISH);
   1.271 ++	if(res == Z_STREAM_END)
   1.272 ++		/*
   1.273 ++		 * Success, return the compressed size.
   1.274 ++		 */
   1.275 ++		return (int) stream->total_out;
   1.276 ++	if(res == Z_OK)
   1.277 ++		/*
   1.278 ++		 * Output buffer overflow.  Return out of buffer space
   1.279 ++		 */
   1.280 ++		return 0;
   1.281 ++failed:
   1.282 ++	/*
   1.283 ++	 * All other errors return failure, with the compressor
   1.284 ++	 * specific error code in *error
   1.285 ++	 */
   1.286 ++	*error = res;
   1.287 ++	return -1;
   1.288 ++}
   1.289 ++
   1.290 ++
   1.291 ++int gzip_uncompress(char *d, char *s, int size, int block_size, int *error)
   1.292 ++{
   1.293 ++	int res;
   1.294 ++	unsigned long bytes = block_size;
   1.295 ++
   1.296 ++	res = uncompress((unsigned char *) d, &bytes,
   1.297 ++		(const unsigned char *) s, size);
   1.298 ++
   1.299 ++	*error = res;
   1.300 ++	return res == Z_OK ? (int) bytes : -1;
   1.301 ++}
   1.302 +
   1.303 +--- squashfs-4.0/squashfs-tools/lzma_wrapper.c	Thu Jan  1 01:00:00 1970
   1.304 ++++ squashfs-4.0/squashfs-tools/lzma_wrapper.c	Wed Oct 14 05:32:57 2009
   1.305 +@@ -0,0 +1,93 @@
   1.306 ++/*
   1.307 ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
   1.308 ++ * Phillip Lougher <phillip@lougher.demon.co.uk>
   1.309 ++ *
   1.310 ++ * This program is free software; you can redistribute it and/or
   1.311 ++ * modify it under the terms of the GNU General Public License
   1.312 ++ * as published by the Free Software Foundation; either version 2,
   1.313 ++ * or (at your option) any later version.
   1.314 ++ *
   1.315 ++ * This program is distributed in the hope that it will be useful,
   1.316 ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
   1.317 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   1.318 ++ * GNU General Public License for more details.
   1.319 ++ *
   1.320 ++ * You should have received a copy of the GNU General Public License
   1.321 ++ * along with this program; if not, write to the Free Software
   1.322 ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   1.323 ++ *
   1.324 ++ * lzma_wrapper.c
   1.325 ++ */
   1.326 ++
   1.327 ++#include <LzmaLib.h>
   1.328 ++
   1.329 ++#define LZMA_HEADER_SIZE	(LZMA_PROPS_SIZE + 8)
   1.330 ++
   1.331 ++int lzma_compress(void **strm, char *dest, char *src,  int size,int block_size,
   1.332 ++		int *error)
   1.333 ++{
   1.334 ++	unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
   1.335 ++	size_t props_size = LZMA_PROPS_SIZE,
   1.336 ++		outlen = block_size - LZMA_HEADER_SIZE;
   1.337 ++	int res;
   1.338 ++
   1.339 ++	res = LzmaCompress(d + LZMA_HEADER_SIZE, &outlen, s, size, d,
   1.340 ++		&props_size, 5, block_size, 3, 0, 2, 32, 1);
   1.341 ++	
   1.342 ++	if(res == SZ_ERROR_OUTPUT_EOF) {
   1.343 ++		/*
   1.344 ++		 * Output buffer overflow.  Return out of buffer space error
   1.345 ++		 */
   1.346 ++		return 0;
   1.347 ++	}
   1.348 ++
   1.349 ++	if(res != SZ_OK) {
   1.350 ++		/*
   1.351 ++		 * All other errors return failure, with the compressor
   1.352 ++		 * specific error code in *error
   1.353 ++		 */
   1.354 ++		*error = res;
   1.355 ++		return -1;
   1.356 ++	}
   1.357 ++
   1.358 ++	/*
   1.359 ++	 * Fill in the 8 byte little endian uncompressed size field in the
   1.360 ++	 * LZMA header.  8 bytes is excessively large for squashfs but
   1.361 ++	 * this is the standard LZMA header and which is expected by the kernel
   1.362 ++	 * code
   1.363 ++	 */
   1.364 ++	d[LZMA_PROPS_SIZE] = size & 255;
   1.365 ++	d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255;
   1.366 ++	d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255;
   1.367 ++	d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255;
   1.368 ++	d[LZMA_PROPS_SIZE + 4] = 0;
   1.369 ++	d[LZMA_PROPS_SIZE + 5] = 0;
   1.370 ++	d[LZMA_PROPS_SIZE + 6] = 0;
   1.371 ++	d[LZMA_PROPS_SIZE + 7] = 0;
   1.372 ++
   1.373 ++	/*
   1.374 ++	 * Success, return the compressed size.  Outlen returned by the LZMA
   1.375 ++	 * compressor does not include the LZMA header space
   1.376 ++	 */
   1.377 ++	return outlen + LZMA_HEADER_SIZE;
   1.378 ++}
   1.379 ++
   1.380 ++
   1.381 ++int lzma_uncompress(char *dest, char *src, int size, int block_size,
   1.382 ++	int *error)
   1.383 ++{
   1.384 ++	unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
   1.385 ++	size_t outlen, inlen = size - LZMA_HEADER_SIZE;
   1.386 ++	int res;
   1.387 ++
   1.388 ++	outlen = s[LZMA_PROPS_SIZE] |
   1.389 ++		(s[LZMA_PROPS_SIZE + 1] << 8) |
   1.390 ++		(s[LZMA_PROPS_SIZE + 2] << 16) |
   1.391 ++		(s[LZMA_PROPS_SIZE + 3] << 24);
   1.392 ++
   1.393 ++	res = LzmaUncompress(d, &outlen, s + LZMA_HEADER_SIZE, &inlen,
   1.394 ++		s, LZMA_PROPS_SIZE);
   1.395 ++	
   1.396 ++	*error = res;
   1.397 ++	return res == SZ_OK ? outlen : -1;
   1.398 ++}
   1.399 +
   1.400 +--- squashfs-4.0/squashfs-tools/mksquashfs.c	Sun Apr  5 23:22:48 2009
   1.401 ++++ squashfs-4.0/squashfs-tools/mksquashfs.c	Tue Dec  8 19:02:54 2009
   1.402 +@@ -36,7 +36,6 @@
   1.403 + #include <errno.h>
   1.404 + #include <dirent.h>
   1.405 + #include <string.h>
   1.406 +-#include <zlib.h>
   1.407 + #include <stdlib.h>
   1.408 + #include <signal.h>
   1.409 + #include <setjmp.h>
   1.410 +@@ -47,6 +46,7 @@
   1.411 + #include <math.h>
   1.412 + #include <regex.h>
   1.413 + #include <fnmatch.h>
   1.414 ++#include <sys/wait.h>
   1.415 + 
   1.416 + #ifndef linux
   1.417 + #define __BYTE_ORDER BYTE_ORDER
   1.418 +@@ -64,6 +64,7 @@
   1.419 + #include "global.h"
   1.420 + #include "sort.h"
   1.421 + #include "pseudo.h"
   1.422 ++#include "compressor.h"
   1.423 + 
   1.424 + #ifdef SQUASHFS_TRACE
   1.425 + #define TRACE(s, args...)	do { \
   1.426 +@@ -245,10 +246,8 @@
   1.427 + /* list of root directory entries read from original filesystem */
   1.428 + int old_root_entries = 0;
   1.429 + struct old_root_entry_info {
   1.430 +-	char			name[SQUASHFS_NAME_LEN + 1];
   1.431 +-	squashfs_inode		inode;
   1.432 +-	int			type;
   1.433 +-	int			inode_number;
   1.434 ++	char			*name;
   1.435 ++	struct inode_info	inode;
   1.436 + };
   1.437 + struct old_root_entry_info *old_root_entry;
   1.438 + 
   1.439 +@@ -371,10 +370,15 @@
   1.440 + int reader_buffer_size;
   1.441 + int fragment_buffer_size;
   1.442 + 
   1.443 ++/* compression operations structure */
   1.444 ++static struct compressor *comp;
   1.445 ++char *comp_name = COMP_DEFAULT;
   1.446 ++
   1.447 + char *read_from_disk(long long start, unsigned int avail_bytes);
   1.448 + void add_old_root_entry(char *name, squashfs_inode inode, int inode_number,
   1.449 + 	int type);
   1.450 +-extern int read_super(int fd, squashfs_super_block *sBlk, char *source);
   1.451 ++extern struct compressor  *read_super(int fd, squashfs_super_block *sBlk,
   1.452 ++	char *source);
   1.453 + extern long long read_filesystem(char *root_name, int fd,
   1.454 + 	squashfs_super_block *sBlk, char **cinode_table, char **data_cache,
   1.455 + 	char **cdirectory_table, char **directory_data_cache,
   1.456 +@@ -831,83 +835,32 @@
   1.457 + }
   1.458 + 
   1.459 + 
   1.460 +-unsigned int mangle2(z_stream **strm, char *d, char *s, int size,
   1.461 ++int mangle2(void **strm, char *d, char *s, int size,
   1.462 + 	int block_size, int uncompressed, int data_block)
   1.463 + {
   1.464 +-	unsigned long c_byte;
   1.465 +-	unsigned int res;
   1.466 +-	z_stream *stream = *strm;
   1.467 ++	int error, c_byte = 0;
   1.468 + 
   1.469 +-	if(uncompressed)
   1.470 +-		goto notcompressed;
   1.471 +-
   1.472 +-	if(stream == NULL) {
   1.473 +-		if((stream = *strm = malloc(sizeof(z_stream))) == NULL)
   1.474 +-			BAD_ERROR("mangle::compress failed, not enough "
   1.475 +-				"memory\n");
   1.476 +-
   1.477 +-		stream->zalloc = Z_NULL;
   1.478 +-		stream->zfree = Z_NULL;
   1.479 +-		stream->opaque = 0;
   1.480 +-
   1.481 +-		if((res = deflateInit(stream, 9)) != Z_OK) {
   1.482 +-			if(res == Z_MEM_ERROR)
   1.483 +-				BAD_ERROR("zlib::compress failed, not enough "
   1.484 +-					"memory\n");
   1.485 +-			else if(res == Z_STREAM_ERROR)
   1.486 +-				BAD_ERROR("zlib::compress failed, not a valid "
   1.487 +-					"compression level\n");
   1.488 +-			else if(res == Z_VERSION_ERROR)
   1.489 +-				BAD_ERROR("zlib::compress failed, incorrect "
   1.490 +-					"zlib version\n");
   1.491 +-			else
   1.492 +-				BAD_ERROR("zlib::compress failed, unknown "
   1.493 +-					"error %d\n", res);
   1.494 +-		}
   1.495 +-	} else if((res = deflateReset(stream)) != Z_OK) {
   1.496 +-		if(res == Z_STREAM_ERROR)
   1.497 +-			BAD_ERROR("zlib::compress failed, stream state "
   1.498 +-				"inconsistent\n");
   1.499 +-		else
   1.500 +-			BAD_ERROR("zlib::compress failed, unknown error %d\n",
   1.501 +-				res);
   1.502 ++	if(!uncompressed) {
   1.503 ++		c_byte = comp->compress(strm, d, s, size, block_size, &error);
   1.504 ++		if(c_byte == -1)
   1.505 ++			BAD_ERROR("mangle2:: %s compress failed with error "
   1.506 ++				"code %d\n", comp->name, error);
   1.507 + 	}
   1.508 + 
   1.509 +-	stream->next_in = (unsigned char *) s;
   1.510 +-	stream->avail_in = size;
   1.511 +-	stream->next_out = (unsigned char *) d;
   1.512 +-	stream->avail_out = block_size;
   1.513 +-
   1.514 +-	res = deflate(stream, Z_FINISH);
   1.515 +-	if(res != Z_STREAM_END && res != Z_OK) {
   1.516 +-		if(res == Z_STREAM_ERROR)
   1.517 +-			BAD_ERROR("zlib::compress failed, stream state "
   1.518 +-				"inconsistent\n");
   1.519 +-		else if(res == Z_BUF_ERROR)
   1.520 +-			BAD_ERROR("zlib::compress failed, no progress possible"
   1.521 +-				"\n");
   1.522 +-		else
   1.523 +-			BAD_ERROR("zlib::compress failed, unknown error %d\n",
   1.524 +-				res);
   1.525 +-	}
   1.526 +-
   1.527 +-	c_byte = stream->total_out;
   1.528 +-
   1.529 +-	if(res != Z_STREAM_END || c_byte >= size) {
   1.530 +-notcompressed:
   1.531 ++	if(c_byte == 0 || c_byte >= size) {
   1.532 + 		memcpy(d, s, size);
   1.533 + 		return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK :
   1.534 + 			SQUASHFS_COMPRESSED_BIT);
   1.535 + 	}
   1.536 + 
   1.537 +-	return (unsigned int) c_byte;
   1.538 ++	return c_byte;
   1.539 + }
   1.540 + 
   1.541 + 
   1.542 +-unsigned int mangle(char *d, char *s, int size, int block_size,
   1.543 ++int mangle(char *d, char *s, int size, int block_size,
   1.544 + 	int uncompressed, int data_block)
   1.545 + {
   1.546 +-	static z_stream *stream = NULL;
   1.547 ++	static void *stream = NULL;
   1.548 + 
   1.549 + 	return mangle2(&stream, d, s, size, block_size, uncompressed,
   1.550 + 		data_block);
   1.551 +@@ -1660,8 +1613,7 @@
   1.552 + 	pthread_mutex_unlock(&fragment_mutex);
   1.553 + 
   1.554 + 	if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) {
   1.555 +-		int res;
   1.556 +-		unsigned long bytes = block_size;
   1.557 ++		int error, res;
   1.558 + 		char *data;
   1.559 + 
   1.560 + 		if(compressed_buffer)
   1.561 +@@ -1669,19 +1621,11 @@
   1.562 + 		else
   1.563 + 			data = read_from_disk(start_block, size);
   1.564 + 
   1.565 +-		res = uncompress((unsigned char *) buffer->data, &bytes,
   1.566 +-			(const unsigned char *) data, size);
   1.567 +-		if(res != Z_OK) {
   1.568 +-			if(res == Z_MEM_ERROR)
   1.569 +-				BAD_ERROR("zlib::uncompress failed, not enough "
   1.570 +-					"memory\n");
   1.571 +-			else if(res == Z_BUF_ERROR)
   1.572 +-				BAD_ERROR("zlib::uncompress failed, not enough "
   1.573 +-					"room in output buffer\n");
   1.574 +-			else
   1.575 +-				BAD_ERROR("zlib::uncompress failed,"
   1.576 +-					"  unknown error %d\n", res);
   1.577 +-		}
   1.578 ++		res = comp->uncompress(buffer->data, data, size, block_size,
   1.579 ++			&error);
   1.580 ++		if(res == -1)
   1.581 ++			BAD_ERROR("%s uncompress failed with error code %d\n",
   1.582 ++				comp->name, error);
   1.583 + 	} else if(compressed_buffer)
   1.584 + 		memcpy(buffer->data, compressed_buffer->data, size);
   1.585 + 	else
   1.586 +@@ -1733,9 +1677,7 @@
   1.587 + 		entry->buffer->block = bytes;
   1.588 + 		bytes += compressed_size;
   1.589 + 		fragments_outstanding --;
   1.590 +-		pthread_mutex_unlock(&fragment_mutex);
   1.591 + 		queue_put(to_writer, entry->buffer);
   1.592 +-		pthread_mutex_lock(&fragment_mutex);
   1.593 + 		TRACE("fragment_locked writing fragment %d, compressed size %d"
   1.594 + 			"\n", entry->fragment, compressed_size);
   1.595 + 		free(entry);
   1.596 +@@ -1758,6 +1700,8 @@
   1.597 + 	pthread_mutex_lock(&fragment_mutex);
   1.598 + 	insert_fragment_list(&frag_locked_list, entry);
   1.599 + 	pthread_mutex_unlock(&fragment_mutex);
   1.600 ++
   1.601 ++	return TRUE;
   1.602 + }
   1.603 + 
   1.604 + 
   1.605 +@@ -1824,7 +1768,9 @@
   1.606 + 	unsigned short c_byte;
   1.607 + 	char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2];
   1.608 + 	
   1.609 ++#ifdef SQUASHFS_TRACE
   1.610 + 	long long obytes = bytes;
   1.611 ++#endif
   1.612 + 
   1.613 + 	for(i = 0; i < meta_blocks; i++) {
   1.614 + 		int avail_bytes = length > SQUASHFS_METADATA_SIZE ?
   1.615 +@@ -2170,11 +2116,85 @@
   1.616 + }
   1.617 + 
   1.618 + 
   1.619 ++static int seq = 0;
   1.620 ++void reader_read_process(struct dir_ent *dir_ent)
   1.621 ++{
   1.622 ++	struct file_buffer *prev_buffer = NULL, *file_buffer;
   1.623 ++	int status, res, byte, count = 0;
   1.624 ++	int file = get_pseudo_file(dir_ent->inode->pseudo_id)->fd;
   1.625 ++	int child = get_pseudo_file(dir_ent->inode->pseudo_id)->child;
   1.626 ++	long long bytes = 0;
   1.627 ++
   1.628 ++	while(1) {
   1.629 ++		file_buffer = cache_get(reader_buffer, 0, 0);
   1.630 ++		file_buffer->sequence = seq ++;
   1.631 ++
   1.632 ++		byte = read_bytes(file, file_buffer->data, block_size);
   1.633 ++		if(byte == -1)
   1.634 ++			goto read_err;
   1.635 ++
   1.636 ++		file_buffer->size = byte;
   1.637 ++		file_buffer->file_size = -1;
   1.638 ++		file_buffer->block = count ++;
   1.639 ++		file_buffer->error = FALSE;
   1.640 ++		file_buffer->fragment = FALSE;
   1.641 ++		bytes += byte;
   1.642 ++
   1.643 ++		if(byte == 0)
   1.644 ++			break;
   1.645 ++
   1.646 ++		/*
   1.647 ++		 * Update estimated_uncompressed block count.  This is done
   1.648 ++		 * on every block rather than waiting for all blocks to be
   1.649 ++		 * read incase write_file_process() is running in parallel
   1.650 ++		 * with this.  Otherwise cur uncompressed block count may
   1.651 ++		 * get ahead of the total uncompressed block count.
   1.652 ++		 */ 
   1.653 ++		estimated_uncompressed ++;
   1.654 ++
   1.655 ++		if(prev_buffer)
   1.656 ++			queue_put(from_reader, prev_buffer);
   1.657 ++		prev_buffer = file_buffer;
   1.658 ++	}
   1.659 ++
   1.660 ++	/*
   1.661 ++ 	 * Update inode file size now that the size of the dynamic pseudo file
   1.662 ++	 * is known.  This is needed for the -info option.
   1.663 ++	 */
   1.664 ++	dir_ent->inode->buf.st_size = bytes;
   1.665 ++
   1.666 ++	res = waitpid(child, &status, 0);
   1.667 ++	if(res == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
   1.668 ++		goto read_err;
   1.669 ++
   1.670 ++	if(prev_buffer == NULL)
   1.671 ++		prev_buffer = file_buffer;
   1.672 ++	else {
   1.673 ++		cache_block_put(file_buffer);
   1.674 ++		seq --;
   1.675 ++	}
   1.676 ++	prev_buffer->file_size = bytes;
   1.677 ++	prev_buffer->fragment = !no_fragments &&
   1.678 ++		(count == 2 || always_use_fragments) && (byte < block_size);
   1.679 ++	queue_put(from_reader, prev_buffer);
   1.680 ++
   1.681 ++	return;
   1.682 ++
   1.683 ++read_err:
   1.684 ++	if(prev_buffer) {
   1.685 ++		cache_block_put(file_buffer);
   1.686 ++		seq --;
   1.687 ++		file_buffer = prev_buffer;
   1.688 ++	}
   1.689 ++	file_buffer->error = TRUE;
   1.690 ++	queue_put(from_deflate, file_buffer);
   1.691 ++}
   1.692 ++
   1.693 ++
   1.694 + void reader_read_file(struct dir_ent *dir_ent)
   1.695 + {
   1.696 + 	struct stat *buf = &dir_ent->inode->buf, buf2;
   1.697 + 	struct file_buffer *file_buffer;
   1.698 +-	static int index = 0;
   1.699 + 	int blocks, byte, count, expected, file, frag_block;
   1.700 + 	long long bytes, read_size;
   1.701 + 
   1.702 +@@ -2202,7 +2222,7 @@
   1.703 + 		if(file_buffer)
   1.704 + 			queue_put(from_reader, file_buffer);
   1.705 + 		file_buffer = cache_get(reader_buffer, 0, 0);
   1.706 +-		file_buffer->sequence = index ++;
   1.707 ++		file_buffer->sequence = seq ++;
   1.708 + 
   1.709 + 		byte = file_buffer->size = read_bytes(file, file_buffer->data,
   1.710 + 			block_size);
   1.711 +@@ -2238,7 +2258,7 @@
   1.712 + 
   1.713 + read_err:
   1.714 + 	file_buffer = cache_get(reader_buffer, 0, 0);
   1.715 +-	file_buffer->sequence = index ++;
   1.716 ++	file_buffer->sequence = seq ++;
   1.717 + read_err2:
   1.718 + 	file_buffer->error = TRUE;
   1.719 + 	queue_put(from_deflate, file_buffer);
   1.720 +@@ -2262,9 +2282,14 @@
   1.721 + 	for(i = 0; i < dir->count; i++) {
   1.722 + 		struct dir_ent *dir_ent = dir->list[i];
   1.723 + 		struct stat *buf = &dir_ent->inode->buf;
   1.724 +-		if(dir_ent->data)
   1.725 ++		if(dir_ent->inode->root_entry)
   1.726 + 			continue;
   1.727 + 
   1.728 ++		if(dir_ent->inode->pseudo_file) {
   1.729 ++			reader_read_process(dir_ent);
   1.730 ++			continue;
   1.731 ++		}
   1.732 ++
   1.733 + 		switch(buf->st_mode & S_IFMT) {
   1.734 + 			case S_IFREG:
   1.735 + 				reader_read_file(dir_ent);
   1.736 +@@ -2365,7 +2390,7 @@
   1.737 + 
   1.738 + void *deflator(void *arg)
   1.739 + {
   1.740 +-	z_stream *stream = NULL;
   1.741 ++	void *stream = NULL;
   1.742 + 	int oldstate;
   1.743 + 
   1.744 + 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
   1.745 +@@ -2402,7 +2427,7 @@
   1.746 + 
   1.747 + void *frag_deflator(void *arg)
   1.748 + {
   1.749 +-	z_stream *stream = NULL;
   1.750 ++	void *stream = NULL;
   1.751 + 	int oldstate;
   1.752 + 
   1.753 + 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
   1.754 +@@ -2426,8 +2451,8 @@
   1.755 + 			write_buffer->block = bytes;
   1.756 + 			bytes += compressed_size;
   1.757 + 			fragments_outstanding --;
   1.758 +-			pthread_mutex_unlock(&fragment_mutex);
   1.759 + 			queue_put(to_writer, write_buffer);
   1.760 ++			pthread_mutex_unlock(&fragment_mutex);
   1.761 + 			TRACE("Writing fragment %lld, uncompressed size %d, "
   1.762 + 				"compressed size %d\n", file_buffer->block,
   1.763 + 				file_buffer->size, compressed_size);
   1.764 +@@ -2674,6 +2699,98 @@
   1.765 + }
   1.766 + 
   1.767 + 
   1.768 ++int write_file_process(squashfs_inode *inode, struct dir_ent *dir_ent,
   1.769 ++	struct file_buffer *read_buffer, int *duplicate_file)
   1.770 ++{
   1.771 ++	long long read_size, file_bytes, start;
   1.772 ++	struct fragment *fragment;
   1.773 ++	unsigned int *block_list = NULL;
   1.774 ++	int block = 0, status;
   1.775 ++	long long sparse = 0;
   1.776 ++	struct file_buffer *fragment_buffer = NULL;
   1.777 ++
   1.778 ++	*duplicate_file = FALSE;
   1.779 ++
   1.780 ++	lock_fragments();
   1.781 ++
   1.782 ++	file_bytes = 0;
   1.783 ++	start = bytes;
   1.784 ++	while (1) {
   1.785 ++		read_size = read_buffer->file_size;
   1.786 ++		if(read_buffer->fragment && read_buffer->c_byte)
   1.787 ++			fragment_buffer = read_buffer;
   1.788 ++		else {
   1.789 ++			block_list = realloc(block_list, (block + 1) *
   1.790 ++				sizeof(unsigned int));
   1.791 ++			if(block_list == NULL)
   1.792 ++				BAD_ERROR("Out of memory allocating block_list"
   1.793 ++					"\n");
   1.794 ++			block_list[block ++] = read_buffer->c_byte;
   1.795 ++			if(read_buffer->c_byte) {
   1.796 ++				read_buffer->block = bytes;
   1.797 ++				bytes += read_buffer->size;
   1.798 ++				cache_rehash(read_buffer, read_buffer->block);
   1.799 ++				file_bytes += read_buffer->size;
   1.800 ++				queue_put(to_writer, read_buffer);
   1.801 ++			} else {
   1.802 ++				sparse += read_buffer->size;
   1.803 ++				cache_block_put(read_buffer);
   1.804 ++			}
   1.805 ++		}
   1.806 ++		inc_progress_bar();
   1.807 ++
   1.808 ++		if(read_size != -1)
   1.809 ++			break;
   1.810 ++
   1.811 ++		read_buffer = get_file_buffer(from_deflate);
   1.812 ++		if(read_buffer->error)
   1.813 ++			goto read_err;
   1.814 ++	}
   1.815 ++
   1.816 ++	unlock_fragments();
   1.817 ++	fragment = get_and_fill_fragment(fragment_buffer);
   1.818 ++	cache_block_put(fragment_buffer);
   1.819 ++
   1.820 ++	if(duplicate_checking)
   1.821 ++		add_non_dup(read_size, file_bytes, block_list, start, fragment,
   1.822 ++			0, 0, FALSE);
   1.823 ++	file_count ++;
   1.824 ++	total_bytes += read_size;
   1.825 ++
   1.826 ++	if(read_size < (1LL << 32) && start < (1LL << 32) && sparse == 0)
   1.827 ++		create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size,
   1.828 ++			start, block, block_list, fragment, NULL, 0);
   1.829 ++	else
   1.830 ++		create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size,
   1.831 ++			start, block, block_list, fragment, NULL, sparse);
   1.832 ++
   1.833 ++	if(duplicate_checking == FALSE)
   1.834 ++		free(block_list);
   1.835 ++
   1.836 ++	return 0;
   1.837 ++
   1.838 ++read_err:
   1.839 ++	cur_uncompressed -= block;
   1.840 ++	status = read_buffer->error;
   1.841 ++	bytes = start;
   1.842 ++	if(!block_device) {
   1.843 ++		int res;
   1.844 ++
   1.845 ++		queue_put(to_writer, NULL);
   1.846 ++		if(queue_get(from_writer) != 0)
   1.847 ++			EXIT_MKSQUASHFS();
   1.848 ++		res = ftruncate(fd, bytes);
   1.849 ++		if(res != 0)
   1.850 ++			BAD_ERROR("Failed to truncate dest file because %s\n",
   1.851 ++				strerror(errno));
   1.852 ++	}
   1.853 ++	unlock_fragments();
   1.854 ++	free(block_list);
   1.855 ++	cache_block_put(read_buffer);
   1.856 ++	return status;
   1.857 ++}
   1.858 ++
   1.859 ++
   1.860 + int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent,
   1.861 + 	long long read_size, struct file_buffer *read_buffer,
   1.862 + 	int *duplicate_file)
   1.863 +@@ -2941,7 +3058,10 @@
   1.864 + 	
   1.865 + 	read_size = read_buffer->file_size;
   1.866 + 
   1.867 +-	if(read_size == 0) {
   1.868 ++	if(read_size == -1)
   1.869 ++		status = write_file_process(inode, dir_ent, read_buffer,
   1.870 ++			duplicate_file);
   1.871 ++	else if(read_size == 0) {
   1.872 + 		write_file_empty(inode, dir_ent, duplicate_file);
   1.873 + 		cache_block_put(read_buffer);
   1.874 + 	} else if(read_buffer->fragment && read_buffer->c_byte)
   1.875 +@@ -3036,6 +3156,8 @@
   1.876 + 
   1.877 + 	memcpy(&inode->buf, buf, sizeof(struct stat));
   1.878 + 	inode->read = FALSE;
   1.879 ++	inode->root_entry = FALSE;
   1.880 ++	inode->pseudo_file = FALSE;
   1.881 + 	inode->inode = SQUASHFS_INVALID_BLK;
   1.882 + 	inode->nlink = 1;
   1.883 + 
   1.884 +@@ -3056,7 +3178,7 @@
   1.885 + 
   1.886 + 
   1.887 + inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir,
   1.888 +-	struct inode_info *inode_info, void *data, struct dir_info *dir)
   1.889 ++	struct inode_info *inode_info, struct dir_info *dir)
   1.890 + {
   1.891 + 	if((dir->count % DIR_ENTRIES) == 0) {
   1.892 + 		dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) *
   1.893 +@@ -3075,8 +3197,7 @@
   1.894 + 		NULL;
   1.895 + 	dir->list[dir->count]->inode = inode_info;
   1.896 + 	dir->list[dir->count]->dir = sub_dir;
   1.897 +-	dir->list[dir->count]->our_dir = dir;
   1.898 +-	dir->list[dir->count++]->data = data;
   1.899 ++	dir->list[dir->count++]->our_dir = dir;
   1.900 + 	dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry);
   1.901 + }
   1.902 + 
   1.903 +@@ -3128,10 +3249,10 @@
   1.904 + 
   1.905 + 	if(dir->count < old_root_entries)
   1.906 + 		for(i = 0; i < old_root_entries; i++) {
   1.907 +-			if(old_root_entry[i].type == SQUASHFS_DIR_TYPE)
   1.908 ++			if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE)
   1.909 + 				dir->directory_count ++;
   1.910 +-			add_dir_entry(old_root_entry[i].name, "", NULL, NULL,
   1.911 +-				&old_root_entry[i], dir);
   1.912 ++			add_dir_entry(old_root_entry[i].name, "", NULL,
   1.913 ++				&old_root_entry[i].inode, dir);
   1.914 + 		}
   1.915 + 
   1.916 + 	while(index < source) {
   1.917 +@@ -3167,10 +3288,10 @@
   1.918 + 
   1.919 + 	if(dir->count < old_root_entries)
   1.920 + 		for(i = 0; i < old_root_entries; i++) {
   1.921 +-			if(old_root_entry[i].type == SQUASHFS_DIR_TYPE)
   1.922 ++			if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE)
   1.923 + 				dir->directory_count ++;
   1.924 +-			add_dir_entry(old_root_entry[i].name, "", NULL, NULL,
   1.925 +-				&old_root_entry[i], dir);
   1.926 ++			add_dir_entry(old_root_entry[i].name, "", NULL,
   1.927 ++				&old_root_entry[i].inode, dir);
   1.928 + 		}
   1.929 + 
   1.930 + 	if((d_name = readdir(dir->linuxdir)) != NULL) {
   1.931 +@@ -3215,7 +3336,7 @@
   1.932 + 	int current_count;
   1.933 + 
   1.934 + 	while((current_count = dir_info->current_count++) < dir_info->count)
   1.935 +-		if(dir_info->list[current_count]->data)
   1.936 ++		if(dir_info->list[current_count]->inode->root_entry)
   1.937 + 			continue;
   1.938 + 		else 
   1.939 + 			return dir_info->list[current_count];
   1.940 +@@ -3240,11 +3361,11 @@
   1.941 + 	int current_count;
   1.942 + 
   1.943 + 	while((current_count = dir_info->current_count++) < dir_info->count)
   1.944 +-		if(dir_info->list[current_count]->data)
   1.945 +-			add_dir(dir_info->list[current_count]->data->inode,
   1.946 +-				dir_info->list[current_count]->data->inode_number,
   1.947 ++		if(dir_info->list[current_count]->inode->root_entry)
   1.948 ++			add_dir(dir_info->list[current_count]->inode->inode,
   1.949 ++				dir_info->list[current_count]->inode->inode_number,
   1.950 + 				dir_info->list[current_count]->name,
   1.951 +-				dir_info->list[current_count]->data->type, dir);
   1.952 ++				dir_info->list[current_count]->inode->type, dir);
   1.953 + 		else 
   1.954 + 			return dir_info->list[current_count];
   1.955 + 	return NULL;	
   1.956 +@@ -3313,7 +3434,6 @@
   1.957 + 	dir_ent->name = dir_ent->pathname = strdup(pathname);
   1.958 + 	dir_ent->dir = dir_info;
   1.959 + 	dir_ent->our_dir = NULL;
   1.960 +-	dir_ent->data = NULL;
   1.961 + 	dir_info->dir_ent = dir_ent;
   1.962 + 
   1.963 + 	if(sorted)
   1.964 +@@ -3383,7 +3503,7 @@
   1.965 + 			sub_dir = NULL;
   1.966 + 
   1.967 + 		add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf),
   1.968 +-			NULL, dir);
   1.969 ++			dir);
   1.970 + 	}
   1.971 + 
   1.972 + 	scan1_freedir(dir);
   1.973 +@@ -3399,7 +3519,7 @@
   1.974 + 	struct dir_ent *dir_ent;
   1.975 + 	struct pseudo_entry *pseudo_ent;
   1.976 + 	struct stat buf;
   1.977 +-	static pseudo_ino = 1;
   1.978 ++	static int pseudo_ino = 1;
   1.979 + 	
   1.980 + 	if(dir == NULL && (dir = scan1_opendir("")) == NULL)
   1.981 + 		return NULL;
   1.982 +@@ -3415,6 +3535,29 @@
   1.983 + 
   1.984 + 	while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) {
   1.985 + 		dir_ent = scan2_lookup(dir, pseudo_ent->name);
   1.986 ++		if(pseudo_ent->dev->type == 's') {
   1.987 ++			struct stat *buf;
   1.988 ++			if(dir_ent == NULL) {
   1.989 ++				ERROR("Pseudo set file \"%s\" does not exist "
   1.990 ++					"in source filesystem.  Ignoring\n",
   1.991 ++					pseudo_ent->pathname);
   1.992 ++				continue;
   1.993 ++			}
   1.994 ++			if(dir_ent->inode->root_entry) {
   1.995 ++				ERROR("Pseudo set file \"%s\" is a pre-existing"
   1.996 ++					" file in the filesystem being appended"
   1.997 ++					"  to.  It cannot be modified. "
   1.998 ++					"Ignoring!\n", pseudo_ent->pathname);
   1.999 ++				continue;
  1.1000 ++			}
  1.1001 ++			buf = &dir_ent->inode->buf;
  1.1002 ++			buf->st_mode = (buf->st_mode & S_IFMT) |
  1.1003 ++				pseudo_ent->dev->mode;
  1.1004 ++			buf->st_uid = pseudo_ent->dev->uid;
  1.1005 ++			buf->st_gid = pseudo_ent->dev->gid;
  1.1006 ++			continue;
  1.1007 ++		}
  1.1008 ++
  1.1009 + 		if(dir_ent) {
  1.1010 + 			ERROR("Pseudo file \"%s\" exists in source filesystem "
  1.1011 + 				"\"%s\"\n", pseudo_ent->pathname,
  1.1012 +@@ -3444,8 +3587,29 @@
  1.1013 + 		buf.st_mtime = time(NULL);
  1.1014 + 		buf.st_ino = pseudo_ino ++;
  1.1015 + 
  1.1016 +-		add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir,
  1.1017 +-			lookup_inode(&buf), NULL, dir);
  1.1018 ++		if(pseudo_ent->dev->type == 'f') {
  1.1019 ++#ifdef USE_TMP_FILE
  1.1020 ++			struct stat buf2;
  1.1021 ++			int res = stat(pseudo_ent->dev->filename, &buf2);
  1.1022 ++			if(res == -1) {
  1.1023 ++				ERROR("Stat on pseudo file \"%s\" failed, "
  1.1024 ++					"skipping...", pseudo_ent->pathname);
  1.1025 ++				continue;
  1.1026 ++			}
  1.1027 ++			buf.st_size = buf2.st_size;
  1.1028 ++			add_dir_entry(pseudo_ent->name,
  1.1029 ++				pseudo_ent->dev->filename, sub_dir,
  1.1030 ++				lookup_inode(&buf), dir);
  1.1031 ++#else
  1.1032 ++			struct inode_info *inode = lookup_inode(&buf);
  1.1033 ++			inode->pseudo_id = pseudo_ent->dev->pseudo_id;
  1.1034 ++			inode->pseudo_file = TRUE;		
  1.1035 ++			add_dir_entry(pseudo_ent->name, pseudo_ent->pathname,
  1.1036 ++				sub_dir, inode, dir);
  1.1037 ++#endif
  1.1038 ++		} else
  1.1039 ++			add_dir_entry(pseudo_ent->name, pseudo_ent->pathname,
  1.1040 ++				sub_dir, lookup_inode(&buf), dir);
  1.1041 + 	}
  1.1042 + 
  1.1043 + 	scan2_freedir(dir);
  1.1044 +@@ -3482,8 +3646,9 @@
  1.1045 + 						&duplicate_file);
  1.1046 + 					INFO("file %s, uncompressed size %lld "
  1.1047 + 						"bytes %s\n", filename,
  1.1048 +-						buf->st_size, duplicate_file ?
  1.1049 +-						"DUPLICATE" : "");
  1.1050 ++						(long long) buf->st_size,
  1.1051 ++						duplicate_file ?  "DUPLICATE" :
  1.1052 ++						 "");
  1.1053 + 					break;
  1.1054 + 
  1.1055 + 				case S_IFDIR:
  1.1056 +@@ -3557,6 +3722,7 @@
  1.1057 + 						INFO("file %s, uncompressed "
  1.1058 + 							"size %lld bytes LINK"
  1.1059 + 							"\n", filename,
  1.1060 ++							(long long)
  1.1061 + 							buf->st_size);
  1.1062 + 					break;
  1.1063 + 				case SQUASHFS_SYMLINK_TYPE:
  1.1064 +@@ -3667,10 +3833,11 @@
  1.1065 + 		BAD_ERROR("Out of memory in old root directory entries "
  1.1066 + 			"reallocation\n");
  1.1067 + 
  1.1068 +-	strcpy(old_root_entry[old_root_entries].name, name);
  1.1069 +-	old_root_entry[old_root_entries].inode = inode;
  1.1070 +-	old_root_entry[old_root_entries].inode_number = inode_number;
  1.1071 +-	old_root_entry[old_root_entries++].type = type;
  1.1072 ++	old_root_entry[old_root_entries].name = strdup(name);
  1.1073 ++	old_root_entry[old_root_entries].inode.inode = inode;
  1.1074 ++	old_root_entry[old_root_entries].inode.inode_number = inode_number;
  1.1075 ++	old_root_entry[old_root_entries].inode.type = type;
  1.1076 ++	old_root_entry[old_root_entries++].inode.root_entry = TRUE;
  1.1077 + }
  1.1078 + 
  1.1079 + 
  1.1080 +@@ -4137,7 +4304,7 @@
  1.1081 + 
  1.1082 + 
  1.1083 + #define VERSION() \
  1.1084 +-	printf("mksquashfs version 4.0 (2009/04/05)\n");\
  1.1085 ++	printf("mksquashfs version 4.1-CVS (2009/12/08)\n");\
  1.1086 + 	printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \
  1.1087 + 	printf("This program is free software; you can redistribute it and/or\n");\
  1.1088 + 	printf("modify it under the terms of the GNU General Public License\n");\
  1.1089 +@@ -4172,26 +4339,28 @@
  1.1090 + 	source_path = argv + 1;
  1.1091 + 	source = i - 2;
  1.1092 + 	for(; i < argc; i++) {
  1.1093 +-		if(strcmp(argv[i], "-pf") == 0) {
  1.1094 ++		if(strcmp(argv[i], "-comp") == 0) {
  1.1095 + 			if(++i == argc) {
  1.1096 +-				ERROR("%s: -pf missing filename\n", argv[0]);
  1.1097 ++				ERROR("%s: -comp missing compression type\n",
  1.1098 ++					argv[0]);
  1.1099 + 				exit(1);
  1.1100 + 			}
  1.1101 +-			if(read_pseudo_file(&pseudo, argv[i]) == FALSE) {
  1.1102 +-				ERROR("Failed to parse pseudo file \"%s\"\n",
  1.1103 +-					argv[i]);
  1.1104 ++			comp_name = argv[i];
  1.1105 ++		} else if(strcmp(argv[i], "-pf") == 0) {
  1.1106 ++			if(++i == argc) {
  1.1107 ++				ERROR("%s: -pf missing filename\n", argv[0]);
  1.1108 + 				exit(1);
  1.1109 + 			}
  1.1110 ++			if(read_pseudo_file(&pseudo, argv[i]) == FALSE)
  1.1111 ++				exit(1);
  1.1112 + 		} else if(strcmp(argv[i], "-p") == 0) {
  1.1113 + 			if(++i == argc) {
  1.1114 + 				ERROR("%s: -p missing pseudo file definition\n",
  1.1115 + 					argv[0]);
  1.1116 + 				exit(1);
  1.1117 + 			}
  1.1118 +-			if(read_pseudo_def(&pseudo, argv[i]) == FALSE) {
  1.1119 +-				ERROR("Failed to parse pseudo definition\n");
  1.1120 ++			if(read_pseudo_def(&pseudo, argv[i]) == FALSE)
  1.1121 + 				exit(1);
  1.1122 +-			}
  1.1123 + 		} else if(strcmp(argv[i], "-recover") == 0) {
  1.1124 + 			if(++i == argc) {
  1.1125 + 				ERROR("%s: -recover missing recovery file\n",
  1.1126 +@@ -4394,34 +4563,16 @@
  1.1127 + printOptions:
  1.1128 + 			ERROR("SYNTAX:%s source1 source2 ...  dest [options] "
  1.1129 + 				"[-e list of exclude\ndirs/files]\n", argv[0]);
  1.1130 +-			ERROR("\nOptions are\n");
  1.1131 +-			ERROR("-version\t\tprint version, licence and "
  1.1132 +-				"copyright message\n");
  1.1133 +-			ERROR("-recover <name>\t\trecover filesystem data "
  1.1134 +-				"using recovery file <name>\n");
  1.1135 +-			ERROR("-no-recovery\t\tdon't generate a recovery "
  1.1136 +-				"file\n");
  1.1137 +-			ERROR("-info\t\t\tprint files written to filesystem\n");
  1.1138 +-			ERROR("-no-exports\t\tdon't make the filesystem "
  1.1139 +-				"exportable via NFS\n");
  1.1140 +-			ERROR("-no-progress\t\tdon't display the progress "
  1.1141 +-				"bar\n");
  1.1142 +-			ERROR("-no-sparse\t\tdon't detect sparse files\n");
  1.1143 ++			ERROR("\nFilesystem build options:\n");
  1.1144 ++			ERROR("-comp <comp>\t\tselect <comp> compression\n");
  1.1145 ++			ERROR("\t\t\tCompressors available:\n");
  1.1146 ++			display_compressors("\t\t\t", COMP_DEFAULT);
  1.1147 + 			ERROR("-b <block_size>\t\tset data block to "
  1.1148 + 				"<block_size>.  Default %d bytes\n",
  1.1149 + 				SQUASHFS_FILE_SIZE);
  1.1150 +-			ERROR("-processors <number>\tUse <number> processors."
  1.1151 +-				"  By default will use number of\n");
  1.1152 +-			ERROR("\t\t\tprocessors available\n");
  1.1153 +-			ERROR("-read-queue <size>\tSet input queue to <size> "
  1.1154 +-				"Mbytes.  Default %d Mbytes\n",
  1.1155 +-				READER_BUFFER_DEFAULT);
  1.1156 +-			ERROR("-write-queue <size>\tSet output queue to <size> "
  1.1157 +-				"Mbytes.  Default %d Mbytes\n",
  1.1158 +-				WRITER_BUFFER_DEFAULT);
  1.1159 +-			ERROR("-fragment-queue <size>\tSet fagment queue to "
  1.1160 +-				"<size> Mbytes.  Default %d Mbytes\n",
  1.1161 +-				FRAGMENT_BUFFER_DEFAULT);
  1.1162 ++			ERROR("-no-exports\t\tdon't make the filesystem "
  1.1163 ++				"exportable via NFS\n");
  1.1164 ++			ERROR("-no-sparse\t\tdon't detect sparse files\n");
  1.1165 + 			ERROR("-noI\t\t\tdo not compress inode table\n");
  1.1166 + 			ERROR("-noD\t\t\tdo not compress data blocks\n");
  1.1167 + 			ERROR("-noF\t\t\tdo not compress fragment blocks\n");
  1.1168 +@@ -4430,13 +4581,34 @@
  1.1169 + 				"files larger than block size\n");
  1.1170 + 			ERROR("-no-duplicates\t\tdo not perform duplicate "
  1.1171 + 				"checking\n");
  1.1172 +-			ERROR("-noappend\t\tdo not append to existing "
  1.1173 +-				"filesystem\n");
  1.1174 ++			ERROR("-all-root\t\tmake all files owned by root\n");
  1.1175 ++			ERROR("-force-uid uid\t\tset all file uids to uid\n");
  1.1176 ++			ERROR("-force-gid gid\t\tset all file gids to gid\n");
  1.1177 ++			ERROR("-nopad\t\t\tdo not pad filesystem to a multiple "
  1.1178 ++				"of 4K\n");
  1.1179 + 			ERROR("-keep-as-directory\tif one source directory is "
  1.1180 + 				"specified, create a root\n");
  1.1181 + 			ERROR("\t\t\tdirectory containing that directory, "
  1.1182 + 				"rather than the\n");
  1.1183 + 			ERROR("\t\t\tcontents of the directory\n");
  1.1184 ++			ERROR("\nFilesystem filter options:\n");
  1.1185 ++			ERROR("-p <pseudo-definition>\tAdd pseudo file definition\n");
  1.1186 ++			ERROR("-pf <pseudo-file>\tAdd list of pseudo file definitions\n");
  1.1187 ++			ERROR("-sort <sort_file>\tsort files according to "
  1.1188 ++				"priorities in <sort_file>.  One\n");
  1.1189 ++			ERROR("\t\t\tfile or dir with priority per line.  "
  1.1190 ++				"Priority -32768 to\n");
  1.1191 ++			ERROR("\t\t\t32767, default priority 0\n");
  1.1192 ++			ERROR("-ef <exclude_file>\tlist of exclude dirs/files."
  1.1193 ++				"  One per line\n");
  1.1194 ++			ERROR("-wildcards\t\tAllow extended shell wildcards "
  1.1195 ++				"(globbing) to be used in\n\t\t\texclude "
  1.1196 ++				"dirs/files\n");
  1.1197 ++			ERROR("-regex\t\t\tAllow POSIX regular expressions to "
  1.1198 ++				"be used in exclude\n\t\t\tdirs/files\n");
  1.1199 ++			ERROR("\nFilesystem append options:\n");
  1.1200 ++			ERROR("-noappend\t\tdo not append to existing "
  1.1201 ++				"filesystem\n");
  1.1202 + 			ERROR("-root-becomes <name>\twhen appending source "
  1.1203 + 				"files/directories, make the\n");
  1.1204 + 			ERROR("\t\t\toriginal root become a subdirectory in "
  1.1205 +@@ -4444,11 +4616,29 @@
  1.1206 + 			ERROR("\t\t\tcalled <name>, rather than adding the new "
  1.1207 + 				"source items\n");
  1.1208 + 			ERROR("\t\t\tto the original root\n");
  1.1209 +-			ERROR("-all-root\t\tmake all files owned by root\n");
  1.1210 +-			ERROR("-force-uid uid\t\tset all file uids to uid\n");
  1.1211 +-			ERROR("-force-gid gid\t\tset all file gids to gid\n");
  1.1212 +-			ERROR("-nopad\t\t\tdo not pad filesystem to a multiple "
  1.1213 +-				"of 4K\n");
  1.1214 ++			ERROR("\nMksquashfs runtime options:\n");
  1.1215 ++			ERROR("-version\t\tprint version, licence and "
  1.1216 ++				"copyright message\n");
  1.1217 ++			ERROR("-recover <name>\t\trecover filesystem data "
  1.1218 ++				"using recovery file <name>\n");
  1.1219 ++			ERROR("-no-recovery\t\tdon't generate a recovery "
  1.1220 ++				"file\n");
  1.1221 ++			ERROR("-info\t\t\tprint files written to filesystem\n");
  1.1222 ++			ERROR("-no-progress\t\tdon't display the progress "
  1.1223 ++				"bar\n");
  1.1224 ++			ERROR("-processors <number>\tUse <number> processors."
  1.1225 ++				"  By default will use number of\n");
  1.1226 ++			ERROR("\t\t\tprocessors available\n");
  1.1227 ++			ERROR("-read-queue <size>\tSet input queue to <size> "
  1.1228 ++				"Mbytes.  Default %d Mbytes\n",
  1.1229 ++				READER_BUFFER_DEFAULT);
  1.1230 ++			ERROR("-write-queue <size>\tSet output queue to <size> "
  1.1231 ++				"Mbytes.  Default %d Mbytes\n",
  1.1232 ++				WRITER_BUFFER_DEFAULT);
  1.1233 ++			ERROR("-fragment-queue <size>\tSet fagment queue to "
  1.1234 ++				"<size> Mbytes.  Default %d Mbytes\n",
  1.1235 ++				FRAGMENT_BUFFER_DEFAULT);
  1.1236 ++			ERROR("\nMiscellaneous options:\n");
  1.1237 + 			ERROR("-root-owned\t\talternative name for -all-root"
  1.1238 + 				"\n");
  1.1239 + 			ERROR("-noInodeCompression\talternative name for -noI"
  1.1240 +@@ -4457,20 +4647,8 @@
  1.1241 + 				"\n");
  1.1242 + 			ERROR("-noFragmentCompression\talternative name for "
  1.1243 + 				"-noF\n");
  1.1244 +-			ERROR("-sort <sort_file>\tsort files according to "
  1.1245 +-				"priorities in <sort_file>.  One\n");
  1.1246 +-			ERROR("\t\t\tfile or dir with priority per line.  "
  1.1247 +-				"Priority -32768 to\n");
  1.1248 +-			ERROR("\t\t\t32767, default priority 0\n");
  1.1249 +-			ERROR("-ef <exclude_file>\tlist of exclude dirs/files."
  1.1250 +-				"  One per line\n");
  1.1251 +-			ERROR("-wildcards\t\tAllow extended shell wildcards "
  1.1252 +-				"(globbing) to be used in\n\t\t\texclude "
  1.1253 +-				"dirs/files\n");
  1.1254 +-			ERROR("-regex\t\t\tAllow POSIX regular expressions to "
  1.1255 +-				"be used in exclude\n\t\t\tdirs/files\n");
  1.1256 +-			ERROR("-p <pseudo-definition>\tAdd pseudo file definition\n");
  1.1257 +-			ERROR("-pf <pseudo-file>\tAdd list of pseudo file definitions\n");
  1.1258 ++			ERROR("\nCompressors available:\n");
  1.1259 ++			display_compressors("", COMP_DEFAULT);
  1.1260 + 			exit(1);
  1.1261 + 		}
  1.1262 + 	}
  1.1263 +@@ -4548,11 +4726,10 @@
  1.1264 + 			fclose(fd);
  1.1265 + 		} else if(strcmp(argv[i], "-e") == 0)
  1.1266 + 			break;
  1.1267 +-		else if(strcmp(argv[i], "-b") == 0 ||
  1.1268 +-				strcmp(argv[i], "-root-becomes") == 0 ||
  1.1269 ++		else if(strcmp(argv[i], "-root-becomes") == 0 ||
  1.1270 + 				strcmp(argv[i], "-sort") == 0 ||
  1.1271 + 				strcmp(argv[i], "-pf") == 0 ||
  1.1272 +-				strcmp(argv[i], "-p") == 0)
  1.1273 ++				strcmp(argv[i], "-comp") == 0)
  1.1274 + 			i++;
  1.1275 + 
  1.1276 + 	if(i != argc) {
  1.1277 +@@ -4574,11 +4751,10 @@
  1.1278 + 			sorted ++;
  1.1279 + 		} else if(strcmp(argv[i], "-e") == 0)
  1.1280 + 			break;
  1.1281 +-		else if(strcmp(argv[i], "-b") == 0 ||
  1.1282 +-				strcmp(argv[i], "-root-becomes") == 0 ||
  1.1283 ++		else if(strcmp(argv[i], "-root-becomes") == 0 ||
  1.1284 + 				strcmp(argv[i], "-ef") == 0 ||
  1.1285 + 				strcmp(argv[i], "-pf") == 0 ||
  1.1286 +-				strcmp(argv[i], "-p") == 0)
  1.1287 ++				strcmp(argv[i], "-comp") == 0)
  1.1288 + 			i++;
  1.1289 + 
  1.1290 + #ifdef SQUASHFS_TRACE
  1.1291 +@@ -4586,7 +4762,8 @@
  1.1292 + #endif
  1.1293 + 
  1.1294 + 	if(!delete) {
  1.1295 +-	        if(read_super(fd, &sBlk, argv[source + 1]) == 0) {
  1.1296 ++	        comp = read_super(fd, &sBlk, argv[source + 1]);
  1.1297 ++	        if(comp == NULL) {
  1.1298 + 			ERROR("Failed to read existing filesystem - will not "
  1.1299 + 				"overwrite - ABORTING!\n");
  1.1300 + 			ERROR("To force Mksquashfs to write to this block "
  1.1301 +@@ -4603,6 +4780,15 @@
  1.1302 + 		always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags);
  1.1303 + 		duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags);
  1.1304 + 		exportable = SQUASHFS_EXPORTABLE(sBlk.flags);
  1.1305 ++	} else {
  1.1306 ++		comp = lookup_compressor(comp_name);
  1.1307 ++		if(!comp->supported) {
  1.1308 ++			ERROR("FATAL_ERROR: Compressor \"%s\" is not "
  1.1309 ++				"supported!\n", comp_name);
  1.1310 ++			ERROR("Compressors available:\n");
  1.1311 ++			display_compressors("", COMP_DEFAULT);
  1.1312 ++			EXIT_MKSQUASHFS();
  1.1313 ++		}
  1.1314 + 	}
  1.1315 + 
  1.1316 + 	initialise_threads();
  1.1317 +@@ -4648,8 +4834,8 @@
  1.1318 + 			"size %d\n", SQUASHFS_MAJOR, s_minor, argv[source + 1],
  1.1319 + 			block_size);
  1.1320 + 		printf("All -b, -noI, -noD, -noF, no-duplicates, no-fragments, "
  1.1321 +-			"-always-use-fragments and -exportable options ignored"
  1.1322 +-			"\n");
  1.1323 ++			"-always-use-fragments,\n-exportable and -comp options "
  1.1324 ++			"ignored\n");
  1.1325 + 		printf("\nIf appending is not wanted, please re-run with "
  1.1326 + 			"-noappend specified!\n\n");
  1.1327 + 
  1.1328 +@@ -4803,8 +4989,7 @@
  1.1329 + 
  1.1330 + 	sBlk.bytes_used = bytes;
  1.1331 + 
  1.1332 +-	/* Only compression supported */
  1.1333 +-	sBlk.compression = ZLIB_COMPRESSION;
  1.1334 ++	sBlk.compression = comp->id;
  1.1335 + 
  1.1336 + 	/* Xattrs are not currently supported */
  1.1337 + 	sBlk.xattr_table_start = SQUASHFS_INVALID_BLK;
  1.1338 +@@ -4820,6 +5005,8 @@
  1.1339 + 
  1.1340 + 	close(fd);
  1.1341 + 
  1.1342 ++	delete_pseudo_files();
  1.1343 ++
  1.1344 + 	if(recovery_file[0] != '\0')
  1.1345 + 		unlink(recovery_file);
  1.1346 + 
  1.1347 +@@ -4827,9 +5014,9 @@
  1.1348 + 		* sizeof(unsigned short) + guid_count * sizeof(unsigned short) +
  1.1349 + 		sizeof(squashfs_super_block);
  1.1350 + 
  1.1351 +-	printf("\n%sSquashfs %d.%d filesystem, data block size %d\n",
  1.1352 +-		exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR,
  1.1353 +-		block_size);
  1.1354 ++	printf("\n%sSquashfs %d.%d filesystem, %s compressed, data block size"
  1.1355 ++		" %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR,
  1.1356 ++		SQUASHFS_MINOR, comp->name, block_size);
  1.1357 + 	printf("\t%s data, %s metadata, %s fragments\n",
  1.1358 + 		noD ? "uncompressed" : "compressed", noI ?  "uncompressed" :
  1.1359 + 		"compressed", no_fragments ? "no" : noF ? "uncompressed" :
  1.1360 +
  1.1361 +--- squashfs-4.0/squashfs-tools/par_mksquashfs/README	Thu Jan  1 01:00:00 1970
  1.1362 ++++ squashfs-4.0/squashfs-tools/par_mksquashfs/README	Mon Nov  6 01:27:32 2006
  1.1363 +@@ -0,0 +1,2 @@
  1.1364 ++par_mksquashfs is now the standard mksquashfs, and so this directory is now empty.
  1.1365 ++
  1.1366 +
  1.1367 +--- squashfs-4.0/squashfs-tools/pseudo.c	Sun Apr  5 04:01:58 2009
  1.1368 ++++ squashfs-4.0/squashfs-tools/pseudo.c	Thu Sep 10 06:17:48 2009
  1.1369 +@@ -30,6 +30,7 @@
  1.1370 + #include <string.h>
  1.1371 + #include <stdlib.h>
  1.1372 + #include <sys/types.h>
  1.1373 ++#include <sys/wait.h>
  1.1374 + 
  1.1375 + #include "pseudo.h"
  1.1376 + 
  1.1377 +@@ -55,6 +56,9 @@
  1.1378 + #define TRUE 1
  1.1379 + #define FALSE 0
  1.1380 + 
  1.1381 ++struct pseudo_dev **pseudo_file = NULL;
  1.1382 ++int pseudo_count = 0;
  1.1383 ++
  1.1384 + static void dump_pseudo(struct pseudo *pseudo, char *string)
  1.1385 + {
  1.1386 + 	int i;
  1.1387 +@@ -99,7 +103,7 @@
  1.1388 + 	char *target, char *alltarget)
  1.1389 + {
  1.1390 + 	char targname[1024];
  1.1391 +-	int i, error;
  1.1392 ++	int i;
  1.1393 + 
  1.1394 + 	target = get_component(target, targname);
  1.1395 + 
  1.1396 +@@ -128,12 +132,8 @@
  1.1397 + 		if(target[0] == '\0') {
  1.1398 + 			/* at leaf pathname component */
  1.1399 + 			pseudo->name[i].pseudo = NULL;
  1.1400 +-			pseudo->name[i].dev = malloc(sizeof(struct pseudo_dev));
  1.1401 +-			if(pseudo->name[i].dev == NULL)
  1.1402 +-				BAD_ERROR("failed to allocate pseudo file\n");
  1.1403 + 			pseudo->name[i].pathname = strdup(alltarget);
  1.1404 +-			memcpy(pseudo->name[i].dev, pseudo_dev,
  1.1405 +-				sizeof(struct pseudo_dev));
  1.1406 ++			pseudo->name[i].dev = pseudo_dev;
  1.1407 + 		} else {
  1.1408 + 			/* recurse adding child components */
  1.1409 + 			pseudo->name[i].dev = NULL;
  1.1410 +@@ -169,15 +169,9 @@
  1.1411 + 			if(target[0] == '\0') {
  1.1412 + 				if(pseudo->name[i].dev == NULL &&
  1.1413 + 						pseudo_dev->type == 'd') {
  1.1414 +-					pseudo->name[i].dev =
  1.1415 +-						malloc(sizeof(struct pseudo_dev));
  1.1416 +-					if(pseudo->name[i].dev == NULL)
  1.1417 +-						BAD_ERROR("failed to allocate "
  1.1418 +-							"pseudo file\n");
  1.1419 + 					pseudo->name[i].pathname =
  1.1420 + 						strdup(alltarget);
  1.1421 +-					memcpy(pseudo->name[i].dev, pseudo_dev,
  1.1422 +-						sizeof(struct pseudo_dev));
  1.1423 ++					pseudo->name[i].dev = pseudo_dev;
  1.1424 + 				} else
  1.1425 + 					ERROR("%s already exists as a "
  1.1426 + 						"directory.  Ignoring %s!\n",
  1.1427 +@@ -229,16 +223,113 @@
  1.1428 + }
  1.1429 + 
  1.1430 + 
  1.1431 ++int exec_file(char *command, struct pseudo_dev *dev)
  1.1432 ++{
  1.1433 ++	int child, res;
  1.1434 ++	static pid_t pid = -1;
  1.1435 ++	int pipefd[2];
  1.1436 ++#ifdef USE_TMP_FILE
  1.1437 ++	char filename[1024];
  1.1438 ++	int status;
  1.1439 ++	static int number = 0;
  1.1440 ++#endif
  1.1441 ++
  1.1442 ++	if(pid == -1)
  1.1443 ++		pid = getpid();
  1.1444 ++
  1.1445 ++#ifdef USE_TMP_FILE
  1.1446 ++	sprintf(filename, "/tmp/squashfs_pseudo_%d_%d", pid, number ++);
  1.1447 ++	pipefd[1] = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
  1.1448 ++	if(pipefd[1] == -1) {
  1.1449 ++		printf("open failed\n");
  1.1450 ++		return -1;
  1.1451 ++	}
  1.1452 ++#else
  1.1453 ++	res = pipe(pipefd);
  1.1454 ++	if(res == -1) {
  1.1455 ++		printf("pipe failed\n");
  1.1456 ++		return -1;
  1.1457 ++	}
  1.1458 ++#endif
  1.1459 ++
  1.1460 ++	child = fork();
  1.1461 ++	if(child == -1) {
  1.1462 ++		printf("fork failed\n");
  1.1463 ++		goto failed;
  1.1464 ++	}
  1.1465 ++
  1.1466 ++	if(child == 0) {
  1.1467 ++		close(STDOUT_FILENO);
  1.1468 ++		res = dup(pipefd[1]);
  1.1469 ++		if(res == -1) {
  1.1470 ++			printf("dup failed\n");
  1.1471 ++			exit(EXIT_FAILURE);
  1.1472 ++		}
  1.1473 ++		execl("/bin/sh", "sh", "-c", command, (char *) NULL);
  1.1474 ++		printf("execl failed\n");
  1.1475 ++		exit(EXIT_FAILURE);
  1.1476 ++	}
  1.1477 ++
  1.1478 ++#ifdef USE_TMP_FILE
  1.1479 ++	res = waitpid(child, &status, 0);
  1.1480 ++	close(pipefd[1]);
  1.1481 ++	if(res != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0) {
  1.1482 ++		dev->filename = strdup(filename);
  1.1483 ++		return 0;
  1.1484 ++	}
  1.1485 ++failed:
  1.1486 ++	unlink(filename);
  1.1487 ++	return -1;
  1.1488 ++#else
  1.1489 ++	close(pipefd[1]);
  1.1490 ++	dev->fd = pipefd[0];
  1.1491 ++	dev->child = child;
  1.1492 ++	return 0;
  1.1493 ++failed:
  1.1494 ++	return -1;
  1.1495 ++#endif
  1.1496 ++}
  1.1497 ++
  1.1498 ++
  1.1499 ++void add_pseudo_file(struct pseudo_dev *dev)
  1.1500 ++{
  1.1501 ++	pseudo_file = realloc(pseudo_file, (pseudo_count + 1) *
  1.1502 ++		sizeof(struct pseudo_dev *));
  1.1503 ++	if(pseudo_file == NULL)
  1.1504 ++		BAD_ERROR("Failed to realloc pseudo_file\n");
  1.1505 ++
  1.1506 ++	dev->pseudo_id = pseudo_count;
  1.1507 ++	pseudo_file[pseudo_count ++] = dev;
  1.1508 ++}
  1.1509 ++
  1.1510 ++
  1.1511 ++void delete_pseudo_files()
  1.1512 ++{
  1.1513 ++#ifdef USE_TMP_FILE
  1.1514 ++	int i;
  1.1515 ++
  1.1516 ++	for(i = 0; i < pseudo_count; i++)
  1.1517 ++		unlink(pseudo_file[i]->filename);
  1.1518 ++#endif
  1.1519 ++}
  1.1520 ++
  1.1521 ++
  1.1522 ++struct pseudo_dev *get_pseudo_file(int pseudo_id)
  1.1523 ++{
  1.1524 ++	return pseudo_file[pseudo_id];
  1.1525 ++}
  1.1526 ++
  1.1527 ++
  1.1528 + int read_pseudo_def(struct pseudo **pseudo, char *def)
  1.1529 + {
  1.1530 +-	int n;
  1.1531 ++	int n, bytes;
  1.1532 + 	unsigned int major = 0, minor = 0, mode;
  1.1533 + 	char filename[2048], type, suid[100], sgid[100], *ptr;
  1.1534 + 	long long uid, gid;
  1.1535 +-	struct pseudo_dev dev;
  1.1536 ++	struct pseudo_dev *dev;
  1.1537 + 
  1.1538 +-	n = sscanf(def, "%s %c %o %s %s %u %u", filename, &type, &mode, suid, sgid,
  1.1539 +-			&major, &minor);
  1.1540 ++	n = sscanf(def, "%s %c %o %s %s %n", filename, &type, &mode, suid,
  1.1541 ++			sgid, &bytes);
  1.1542 + 
  1.1543 + 	if(n < 5) {
  1.1544 + 		ERROR("Not enough or invalid arguments in pseudo file "
  1.1545 +@@ -249,7 +340,9 @@
  1.1546 + 	switch(type) {
  1.1547 + 	case 'b':
  1.1548 + 	case 'c':
  1.1549 +-		if(n < 7) {
  1.1550 ++		n = sscanf(def + bytes,  "%u %u", &major, &minor);
  1.1551 ++
  1.1552 ++		if(n < 2) {
  1.1553 + 			ERROR("Not enough or invalid arguments in pseudo file "
  1.1554 + 				"definition\n");
  1.1555 + 			goto error;
  1.1556 +@@ -265,54 +358,59 @@
  1.1557 + 			goto error;
  1.1558 + 		}
  1.1559 + 
  1.1560 +-		/* fall through */
  1.1561 +-	case 'd':
  1.1562 +-		if(mode > 0777) {
  1.1563 +-			ERROR("Mode %o out of range\n", mode);
  1.1564 ++	case 'f':
  1.1565 ++		if(def[bytes] == '\0') {
  1.1566 ++			ERROR("Not enough arguments in pseudo file "
  1.1567 ++				"definition\n");
  1.1568 + 			goto error;
  1.1569 +-		}
  1.1570 +-
  1.1571 +-		uid = strtoll(suid, &ptr, 10);
  1.1572 +-		if(*ptr == '\0') {
  1.1573 +-			if(uid < 0 || uid > ((1LL << 32) - 1)) {
  1.1574 +-				ERROR("Uid %s out of range\n", suid);
  1.1575 +-				goto error;
  1.1576 +-			}
  1.1577 +-		} else {
  1.1578 +-			struct passwd *pwuid = getpwnam(suid);
  1.1579 +-			if(pwuid)
  1.1580 +-				uid = pwuid->pw_uid;
  1.1581 +-			else {
  1.1582 +-				ERROR("Uid %s invalid uid or unknown user\n",
  1.1583 +-					suid);
  1.1584 +-				goto error;
  1.1585 +-			}
  1.1586 +-		}
  1.1587 +-		
  1.1588 +-		gid = strtoll(sgid, &ptr, 10);
  1.1589 +-		if(*ptr == '\0') {
  1.1590 +-			if(gid < 0 || gid > ((1LL << 32) - 1)) {
  1.1591 +-				ERROR("Gid %s out of range\n", sgid);
  1.1592 +-				goto error;
  1.1593 +-			}
  1.1594 +-		} else {
  1.1595 +-			struct group *grgid = getgrnam(sgid);
  1.1596 +-			if(grgid)
  1.1597 +-				gid = grgid->gr_gid;
  1.1598 +-			else {
  1.1599 +-				ERROR("Gid %s invalid uid or unknown user\n",
  1.1600 +-					sgid);
  1.1601 +-				goto error;
  1.1602 +-			}
  1.1603 +-		}
  1.1604 +-
  1.1605 ++		}	
  1.1606 + 		break;
  1.1607 ++	case 'd':
  1.1608 ++	case 'm':
  1.1609 ++		break;
  1.1610 + 	default:
  1.1611 + 		ERROR("Unsupported type %c\n", type);
  1.1612 + 		goto error;
  1.1613 + 	}
  1.1614 + 
  1.1615 + 
  1.1616 ++	if(mode > 0777) {
  1.1617 ++		ERROR("Mode %o out of range\n", mode);
  1.1618 ++		goto error;
  1.1619 ++	}
  1.1620 ++
  1.1621 ++	uid = strtoll(suid, &ptr, 10);
  1.1622 ++	if(*ptr == '\0') {
  1.1623 ++		if(uid < 0 || uid > ((1LL << 32) - 1)) {
  1.1624 ++			ERROR("Uid %s out of range\n", suid);
  1.1625 ++			goto error;
  1.1626 ++		}
  1.1627 ++	} else {
  1.1628 ++		struct passwd *pwuid = getpwnam(suid);
  1.1629 ++		if(pwuid)
  1.1630 ++			uid = pwuid->pw_uid;
  1.1631 ++		else {
  1.1632 ++			ERROR("Uid %s invalid uid or unknown user\n", suid);
  1.1633 ++			goto error;
  1.1634 ++		}
  1.1635 ++	}
  1.1636 ++		
  1.1637 ++	gid = strtoll(sgid, &ptr, 10);
  1.1638 ++	if(*ptr == '\0') {
  1.1639 ++		if(gid < 0 || gid > ((1LL << 32) - 1)) {
  1.1640 ++			ERROR("Gid %s out of range\n", sgid);
  1.1641 ++			goto error;
  1.1642 ++		}
  1.1643 ++	} else {
  1.1644 ++		struct group *grgid = getgrnam(sgid);
  1.1645 ++		if(grgid)
  1.1646 ++			gid = grgid->gr_gid;
  1.1647 ++		else {
  1.1648 ++			ERROR("Gid %s invalid uid or unknown user\n", sgid);
  1.1649 ++			goto error;
  1.1650 ++		}
  1.1651 ++	}
  1.1652 ++
  1.1653 + 	switch(type) {
  1.1654 + 	case 'b':
  1.1655 + 		mode |= S_IFBLK;
  1.1656 +@@ -323,16 +421,37 @@
  1.1657 + 	case 'd':
  1.1658 + 		mode |= S_IFDIR;
  1.1659 + 		break;
  1.1660 ++	case 'f':
  1.1661 ++		mode |= S_IFREG;
  1.1662 ++		break;
  1.1663 + 	}
  1.1664 + 
  1.1665 +-	dev.type = type;
  1.1666 +-	dev.mode = mode;
  1.1667 +-	dev.uid = uid;
  1.1668 +-	dev.gid = gid;
  1.1669 +-	dev.major = major;
  1.1670 +-	dev.minor = minor;
  1.1671 ++	dev = malloc(sizeof(struct pseudo_dev));
  1.1672 ++	if(dev == NULL)
  1.1673 ++		BAD_ERROR("Failed to create pseudo_dev\n");
  1.1674 + 
  1.1675 +-	*pseudo = add_pseudo(*pseudo, &dev, filename, filename);
  1.1676 ++	dev->type = type;
  1.1677 ++	dev->mode = mode;
  1.1678 ++	dev->uid = uid;
  1.1679 ++	dev->gid = gid;
  1.1680 ++	dev->major = major;
  1.1681 ++	dev->minor = minor;
  1.1682 ++
  1.1683 ++	if(type == 'f') {
  1.1684 ++		int res;
  1.1685 ++
  1.1686 ++		printf("Executing dynamic pseudo file\n");
  1.1687 ++		printf("\t\"%s\"\n", def);
  1.1688 ++		res = exec_file(def + bytes, dev);
  1.1689 ++		if(res == -1) {
  1.1690 ++			ERROR("Failed to execute dynamic pseudo file definition"
  1.1691 ++				" \"%s\"\n", def);
  1.1692 ++			return FALSE;
  1.1693 ++		}
  1.1694 ++		add_pseudo_file(dev);
  1.1695 ++	}
  1.1696 ++
  1.1697 ++	*pseudo = add_pseudo(*pseudo, dev, filename, filename);
  1.1698 + 
  1.1699 + 	return TRUE;
  1.1700 + 
  1.1701 +
  1.1702 +--- squashfs-4.0/squashfs-tools/pseudo.h	Sat Apr  4 03:44:24 2009
  1.1703 ++++ squashfs-4.0/squashfs-tools/pseudo.h	Fri Sep 11 14:10:58 2009
  1.1704 +@@ -27,6 +27,12 @@
  1.1705 + 	unsigned int	gid;
  1.1706 + 	unsigned int	major;
  1.1707 + 	unsigned int	minor;
  1.1708 ++	int		pseudo_id;
  1.1709 ++	int		fd;
  1.1710 ++	int		child;
  1.1711 ++#ifdef USE_TMP_FILE
  1.1712 ++	char		*filename;
  1.1713 ++#endif
  1.1714 + };
  1.1715 + 
  1.1716 + struct pseudo_entry {
  1.1717 +@@ -46,3 +52,5 @@
  1.1718 + extern int read_pseudo_file(struct pseudo **, char *);
  1.1719 + extern struct pseudo *pseudo_subdir(char *, struct pseudo *);
  1.1720 + extern struct pseudo_entry *pseudo_readdir(struct pseudo *);
  1.1721 ++extern struct pseudo_dev *get_pseudo_file(int);
  1.1722 ++extern void delete_pseudo_files();
  1.1723 +
  1.1724 +--- squashfs-4.0/squashfs-tools/read_fs.c	Tue Mar 31 06:23:14 2009
  1.1725 ++++ squashfs-4.0/squashfs-tools/read_fs.c	Mon Aug 24 20:28:04 2009
  1.1726 +@@ -36,7 +36,6 @@
  1.1727 + #include <fcntl.h>
  1.1728 + #include <errno.h>
  1.1729 + #include <string.h>
  1.1730 +-#include <zlib.h>
  1.1731 + #include <sys/mman.h>
  1.1732 + 
  1.1733 + #ifndef linux
  1.1734 +@@ -51,6 +50,7 @@
  1.1735 + #include "squashfs_swap.h"
  1.1736 + #include "read_fs.h"
  1.1737 + #include "global.h"
  1.1738 ++#include "compressor.h"
  1.1739 + 
  1.1740 + #include <stdlib.h>
  1.1741 + 
  1.1742 +@@ -66,7 +66,9 @@
  1.1743 + 						fprintf(stderr, s, ## args); \
  1.1744 + 					} while(0)
  1.1745 + 
  1.1746 +-int read_block(int fd, long long start, long long *next, unsigned char *block,
  1.1747 ++static struct compressor *comp;
  1.1748 ++
  1.1749 ++int read_block(int fd, long long start, long long *next, void *block,
  1.1750 + 	squashfs_super_block *sBlk)
  1.1751 + {
  1.1752 + 	unsigned short c_byte;
  1.1753 +@@ -77,32 +79,24 @@
  1.1754 + 
  1.1755 + 	if(SQUASHFS_COMPRESSED(c_byte)) {
  1.1756 + 		char buffer[SQUASHFS_METADATA_SIZE];
  1.1757 +-		int res;
  1.1758 +-		unsigned long bytes = SQUASHFS_METADATA_SIZE;
  1.1759 ++		int error, res;
  1.1760 + 
  1.1761 + 		c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
  1.1762 + 		read_destination(fd, start + offset, c_byte, buffer);
  1.1763 + 
  1.1764 +-		res = uncompress(block, &bytes, (const unsigned char *) buffer,
  1.1765 +-			c_byte);
  1.1766 +-		if(res != Z_OK) {
  1.1767 +-			if(res == Z_MEM_ERROR)
  1.1768 +-				ERROR("zlib::uncompress failed, not enough "
  1.1769 +-					"memory\n");
  1.1770 +-			else if(res == Z_BUF_ERROR)
  1.1771 +-				ERROR("zlib::uncompress failed, not enough "
  1.1772 +-					"room in output buffer\n");
  1.1773 +-			else
  1.1774 +-				ERROR("zlib::uncompress failed, unknown error "
  1.1775 +-					"%d\n", res);
  1.1776 ++		res = comp->uncompress(block, buffer, c_byte,
  1.1777 ++			SQUASHFS_METADATA_SIZE, &error);
  1.1778 ++		if(res == -1) {
  1.1779 ++			ERROR("%s uncompress failed with error code %d\n",
  1.1780 ++				comp->name, error);
  1.1781 + 			return 0;
  1.1782 + 		}
  1.1783 + 		if(next)
  1.1784 + 			*next = start + offset + c_byte;
  1.1785 +-		return bytes;
  1.1786 ++		return res;
  1.1787 + 	} else {
  1.1788 + 		c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
  1.1789 +-		read_destination(fd, start + offset, c_byte, (char *) block);
  1.1790 ++		read_destination(fd, start + offset, c_byte, block);
  1.1791 + 		if(next)
  1.1792 + 			*next = start + offset + c_byte;
  1.1793 + 		return c_byte;
  1.1794 +@@ -356,7 +350,7 @@
  1.1795 + }
  1.1796 + 
  1.1797 + 
  1.1798 +-int read_super(int fd, squashfs_super_block *sBlk, char *source)
  1.1799 ++struct compressor *read_super(int fd, squashfs_super_block *sBlk, char *source)
  1.1800 + {
  1.1801 + 	read_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block),
  1.1802 + 		(char *) sBlk);
  1.1803 +@@ -388,8 +382,18 @@
  1.1804 + 		goto failed_mount;
  1.1805 + 	}
  1.1806 + 
  1.1807 ++	/* Check the compression type */
  1.1808 ++	comp = lookup_compressor_id(sBlk->compression);
  1.1809 ++	if(!comp->supported) {
  1.1810 ++		ERROR("Filesystem on %s uses %s compression, this is"
  1.1811 ++			"unsupported by this version\n", source, comp->name);
  1.1812 ++		display_compressors("", "");
  1.1813 ++		goto failed_mount;
  1.1814 ++	}
  1.1815 ++
  1.1816 + 	printf("Found a valid %sSQUASHFS superblock on %s.\n",
  1.1817 + 		SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source);
  1.1818 ++	printf("\tCompression used %s\n", comp->name);
  1.1819 + 	printf("\tInodes are %scompressed\n",
  1.1820 + 		SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : "");
  1.1821 + 	printf("\tData is %scompressed\n",
  1.1822 +@@ -417,10 +421,10 @@
  1.1823 + 	TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start);
  1.1824 + 	printf("\n");
  1.1825 + 
  1.1826 +-	return TRUE;
  1.1827 ++	return comp;
  1.1828 + 
  1.1829 + failed_mount:
  1.1830 +-	return FALSE;
  1.1831 ++	return NULL;
  1.1832 + }
  1.1833 + 
  1.1834 + 
  1.1835 +@@ -514,12 +518,17 @@
  1.1836 + 	SQUASHFS_INSWAP_ID_BLOCKS(index, indexes);
  1.1837 + 
  1.1838 + 	for(i = 0; i < indexes; i++) {
  1.1839 +-		int length;
  1.1840 +-		length = read_block(fd, index[i], NULL,
  1.1841 ++		int length = read_block(fd, index[i], NULL,
  1.1842 + 			((unsigned char *) id_table) +
  1.1843 + 			(i * SQUASHFS_METADATA_SIZE), sBlk);
  1.1844 + 		TRACE("Read id table block %d, from 0x%llx, length %d\n", i,
  1.1845 + 			index[i], length);
  1.1846 ++		if(length == 0) {
  1.1847 ++			ERROR("Failed to read id table block %d, from 0x%llx, "
  1.1848 ++				"length %d\n", i, index[i], length);
  1.1849 ++			free(id_table);
  1.1850 ++			return NULL;
  1.1851 ++		}
  1.1852 + 	}
  1.1853 + 
  1.1854 + 	SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids);
  1.1855 +@@ -563,6 +572,13 @@
  1.1856 + 			(i * SQUASHFS_METADATA_SIZE), sBlk);
  1.1857 + 		TRACE("Read fragment table block %d, from 0x%llx, length %d\n",
  1.1858 + 			i, fragment_table_index[i], length);
  1.1859 ++		if(length == 0) {
  1.1860 ++			ERROR("Failed to read fragment table block %d, from "
  1.1861 ++				"0x%llx, length %d\n", i,
  1.1862 ++				fragment_table_index[i], length);
  1.1863 ++			free(*fragment_table);
  1.1864 ++			return 0;
  1.1865 ++		}
  1.1866 + 	}
  1.1867 + 
  1.1868 + 	for(i = 0; i < sBlk->fragments; i++)
  1.1869 +@@ -599,6 +615,13 @@
  1.1870 + 			(i * SQUASHFS_METADATA_SIZE), sBlk);
  1.1871 + 		TRACE("Read inode lookup table block %d, from 0x%llx, length "
  1.1872 + 			"%d\n", i, index[i], length);
  1.1873 ++		if(length == 0) {
  1.1874 ++			ERROR("Failed to read inode lookup table block %d, "
  1.1875 ++				"from 0x%llx, length %d\n", i, index[i],
  1.1876 ++				length);
  1.1877 ++			free(*inode_lookup_table);
  1.1878 ++			return 0;
  1.1879 ++		}
  1.1880 + 	}
  1.1881 + 
  1.1882 + 	SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes);
  1.1883 +
  1.1884 +--- squashfs-4.0/squashfs-tools/sort.c	Tue Mar 31 06:25:53 2009
  1.1885 ++++ squashfs-4.0/squashfs-tools/sort.c	Sat Aug 29 07:41:45 2009
  1.1886 +@@ -198,7 +198,7 @@
  1.1887 + 	while(dir->current_count < dir->count) {
  1.1888 + 		struct dir_ent *dir_ent = dir->list[dir->current_count++];
  1.1889 + 		struct stat *buf = &dir_ent->inode->buf;
  1.1890 +-		if(dir_ent->data)
  1.1891 ++		if(dir_ent->inode->root_entry)
  1.1892 + 			continue;
  1.1893 + 
  1.1894 + 		switch(buf->st_mode & S_IFMT) {
  1.1895 +@@ -254,6 +254,7 @@
  1.1896 + 				write_file(&inode, entry->dir, &duplicate_file);
  1.1897 + 				INFO("file %s, uncompressed size %lld bytes %s"
  1.1898 + 					"\n", entry->dir->pathname,
  1.1899 ++					(long long)
  1.1900 + 					entry->dir->inode->buf.st_size,
  1.1901 + 					duplicate_file ? "DUPLICATE" : "");
  1.1902 + 				entry->dir->inode->inode = inode;
  1.1903 +@@ -261,6 +262,7 @@
  1.1904 + 			} else
  1.1905 + 				INFO("file %s, uncompressed size %lld bytes "
  1.1906 + 					"LINK\n", entry->dir->pathname,
  1.1907 ++					(long long)
  1.1908 + 					entry->dir->inode->buf.st_size);
  1.1909 + 		}
  1.1910 + }
  1.1911 +
  1.1912 +--- squashfs-4.0/squashfs-tools/sort.h	Sun Feb  8 13:02:53 2009
  1.1913 ++++ squashfs-4.0/squashfs-tools/sort.h	Thu Sep 10 05:50:01 2009
  1.1914 +@@ -42,17 +42,19 @@
  1.1915 + 	struct inode_info	*inode;
  1.1916 + 	struct dir_info		*dir;
  1.1917 + 	struct dir_info		*our_dir;
  1.1918 +-	struct old_root_entry_info *data;
  1.1919 + };
  1.1920 + 
  1.1921 + struct inode_info {
  1.1922 +-	unsigned int		nlink;
  1.1923 + 	struct stat		buf;
  1.1924 ++	struct inode_info	*next;
  1.1925 + 	squashfs_inode		inode;
  1.1926 +-	unsigned int		type;
  1.1927 + 	unsigned int		inode_number;
  1.1928 ++	unsigned int		nlink;
  1.1929 ++	int			pseudo_id;
  1.1930 ++	char			type;
  1.1931 + 	char			read;
  1.1932 +-	struct inode_info	*next;
  1.1933 ++	char			root_entry;
  1.1934 ++	char			pseudo_file;
  1.1935 + };
  1.1936 + 
  1.1937 + struct priority_entry {
  1.1938 +
  1.1939 +--- squashfs-4.0/squashfs-tools/squashfs_compat.h	Mon Mar 16 05:27:27 2009
  1.1940 ++++ squashfs-4.0/squashfs-tools/squashfs_compat.h	Tue Apr 21 02:52:24 2009
  1.1941 +@@ -777,11 +777,10 @@
  1.1942 + #endif
  1.1943 + 
  1.1944 + #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
  1.1945 +-	int bits;\
  1.1946 +-	int b_pos = pos % 8;\
  1.1947 +-	unsigned long long val = 0;\
  1.1948 +-	unsigned char *s = (unsigned char *)p + (pos / 8);\
  1.1949 +-	unsigned char *d = ((unsigned char *) &val) + 7;\
  1.1950 ++	b_pos = pos % 8;\
  1.1951 ++	val = 0;\
  1.1952 ++	s = (unsigned char *)p + (pos / 8);\
  1.1953 ++	d = ((unsigned char *) &val) + 7;\
  1.1954 + 	for(bits = 0; bits < (tbits + b_pos); bits += 8) \
  1.1955 + 		*d-- = *s++;\
  1.1956 + 	value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
  1.1957 +
  1.1958 +--- squashfs-4.0/squashfs-tools/squashfs_fs.h	Wed Mar 18 03:50:20 2009
  1.1959 ++++ squashfs-4.0/squashfs-tools/squashfs_fs.h	Thu Jul 30 06:45:38 2009
  1.1960 +@@ -229,6 +229,7 @@
  1.1961 + typedef long long		squashfs_inode_t;
  1.1962 + 
  1.1963 + #define ZLIB_COMPRESSION	1
  1.1964 ++#define LZMA_COMPRESSION	2
  1.1965 + 
  1.1966 + struct squashfs_super_block {
  1.1967 + 	unsigned int		s_magic;
  1.1968 +
  1.1969 +--- squashfs-4.0/squashfs-tools/unsquash-3.c	Tue Mar 31 06:35:10 2009
  1.1970 ++++ squashfs-4.0/squashfs-tools/unsquash-3.c	Tue Apr 21 02:58:22 2009
  1.1971 +@@ -36,7 +36,7 @@
  1.1972 + 		sBlk.fragment_table_start);
  1.1973 + 
  1.1974 + 	if(sBlk.fragments == 0)
  1.1975 +-		return;
  1.1976 ++		return TRUE;
  1.1977 + 
  1.1978 + 	if((fragment_table = malloc(sBlk.fragments *
  1.1979 + 			sizeof(squashfs_fragment_entry_3))) == NULL)
  1.1980 +
  1.1981 +--- squashfs-4.0/squashfs-tools/unsquash-4.c	Tue Mar 31 06:38:31 2009
  1.1982 ++++ squashfs-4.0/squashfs-tools/unsquash-4.c	Tue Apr 21 02:59:16 2009
  1.1983 +@@ -38,7 +38,7 @@
  1.1984 + 		sBlk.fragment_table_start);
  1.1985 + 
  1.1986 + 	if(sBlk.fragments == 0)
  1.1987 +-		return;
  1.1988 ++		return TRUE;
  1.1989 + 
  1.1990 + 	if((fragment_table = malloc(sBlk.fragments *
  1.1991 + 			sizeof(squashfs_fragment_entry))) == NULL)
  1.1992 +
  1.1993 +--- squashfs-4.0/squashfs-tools/unsquashfs.c	Sun Apr  5 23:23:06 2009
  1.1994 ++++ squashfs-4.0/squashfs-tools/unsquashfs.c	Sun Aug 30 16:10:31 2009
  1.1995 +@@ -25,7 +25,10 @@
  1.1996 + #include "squashfs_swap.h"
  1.1997 + #include "squashfs_compat.h"
  1.1998 + #include "read_fs.h"
  1.1999 ++#include "compressor.h"
  1.2000 + 
  1.2001 ++#include <sys/sysinfo.h>
  1.2002 ++
  1.2003 + struct cache *fragment_cache, *data_cache;
  1.2004 + struct queue *to_reader, *to_deflate, *to_writer, *from_writer;
  1.2005 + pthread_t *thread, *deflator_thread;
  1.2006 +@@ -36,6 +39,7 @@
  1.2007 + 
  1.2008 + struct super_block sBlk;
  1.2009 + squashfs_operations s_ops;
  1.2010 ++struct compressor *comp;
  1.2011 + 
  1.2012 + int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0,
  1.2013 + 	dev_count = 0, fifo_count = 0;
  1.2014 +@@ -590,31 +594,23 @@
  1.2015 + 		offset = 3;
  1.2016 + 	if(SQUASHFS_COMPRESSED(c_byte)) {
  1.2017 + 		char buffer[SQUASHFS_METADATA_SIZE];
  1.2018 +-		int res;
  1.2019 +-		unsigned long bytes = SQUASHFS_METADATA_SIZE;
  1.2020 ++		int error, res;
  1.2021 + 
  1.2022 + 		c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
  1.2023 + 		if(read_bytes(start + offset, c_byte, buffer) == FALSE)
  1.2024 + 			goto failed;
  1.2025 + 
  1.2026 +-		res = uncompress((unsigned char *) block, &bytes,
  1.2027 +-			(const unsigned char *) buffer, c_byte);
  1.2028 ++		res = comp->uncompress(block, buffer, c_byte,
  1.2029 ++			SQUASHFS_METADATA_SIZE, &error);
  1.2030 + 
  1.2031 +-		if(res != Z_OK) {
  1.2032 +-			if(res == Z_MEM_ERROR)
  1.2033 +-				ERROR("zlib::uncompress failed, not enough "
  1.2034 +-					"memory\n");
  1.2035 +-			else if(res == Z_BUF_ERROR)
  1.2036 +-				ERROR("zlib::uncompress failed, not enough "
  1.2037 +-					"room in output buffer\n");
  1.2038 +-			else
  1.2039 +-				ERROR("zlib::uncompress failed, unknown error "
  1.2040 +-					"%d\n", res);
  1.2041 ++		if(res == -1) {
  1.2042 ++			ERROR("%s uncompress failed with error code %d\n",
  1.2043 ++				comp->name, error);
  1.2044 + 			goto failed;
  1.2045 + 		}
  1.2046 + 		if(next)
  1.2047 + 			*next = start + offset + c_byte;
  1.2048 +-		return bytes;
  1.2049 ++		return res;
  1.2050 + 	} else {
  1.2051 + 		c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
  1.2052 + 		if(read_bytes(start + offset, c_byte, block) == FALSE)
  1.2053 +@@ -632,36 +628,26 @@
  1.2054 + 
  1.2055 + int read_data_block(long long start, unsigned int size, char *block)
  1.2056 + {
  1.2057 +-	int res;
  1.2058 +-	unsigned long bytes = block_size;
  1.2059 ++	int error, res;
  1.2060 + 	int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size);
  1.2061 + 
  1.2062 + 	TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start,
  1.2063 +-		SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte),
  1.2064 +-		SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" :
  1.2065 ++		c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" :
  1.2066 + 		"uncompressed");
  1.2067 + 
  1.2068 + 	if(SQUASHFS_COMPRESSED_BLOCK(size)) {
  1.2069 + 		if(read_bytes(start, c_byte, data) == FALSE)
  1.2070 + 			goto failed;
  1.2071 + 
  1.2072 +-		res = uncompress((unsigned char *) block, &bytes,
  1.2073 +-			(const unsigned char *) data, c_byte);
  1.2074 ++		res = comp->uncompress(block, data, c_byte, block_size, &error);
  1.2075 + 
  1.2076 +-		if(res != Z_OK) {
  1.2077 +-			if(res == Z_MEM_ERROR)
  1.2078 +-				ERROR("zlib::uncompress failed, not enough "
  1.2079 +-					"memory\n");
  1.2080 +-			else if(res == Z_BUF_ERROR)
  1.2081 +-				ERROR("zlib::uncompress failed, not enough "
  1.2082 +-					"room in output buffer\n");
  1.2083 +-			else
  1.2084 +-				ERROR("zlib::uncompress failed, unknown error "
  1.2085 +-					"%d\n", res);
  1.2086 ++		if(res == -1) {
  1.2087 ++			ERROR("%s uncompress failed with error code %d\n",
  1.2088 ++				comp->name, error);
  1.2089 + 			goto failed;
  1.2090 + 		}
  1.2091 + 
  1.2092 +-		return bytes;
  1.2093 ++		return res;
  1.2094 + 	} else {
  1.2095 + 		if(read_bytes(start, c_byte, block) == FALSE)
  1.2096 + 			goto failed;
  1.2097 +@@ -671,7 +657,7 @@
  1.2098 + 
  1.2099 + failed:
  1.2100 + 	ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start,
  1.2101 +-		size);
  1.2102 ++		c_byte);
  1.2103 + 	return FALSE;
  1.2104 + }
  1.2105 + 
  1.2106 +@@ -1383,6 +1369,11 @@
  1.2107 + #endif
  1.2108 + 	printf("Creation or last append time %s", mkfs_str ? mkfs_str :
  1.2109 + 		"failed to get time\n");
  1.2110 ++	printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n",
  1.2111 ++		sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0));
  1.2112 ++	if(sBlk.s_major == 4)
  1.2113 ++		printf("Compression %s\n", comp->name);
  1.2114 ++	printf("Block size %d\n", sBlk.block_size);
  1.2115 + 	printf("Filesystem is %sexportable via NFS\n",
  1.2116 + 		SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not ");
  1.2117 + 
  1.2118 +@@ -1409,9 +1400,6 @@
  1.2119 + 			SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not ");
  1.2120 + 	else
  1.2121 + 		printf("Duplicates are removed\n");
  1.2122 +-	printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n",
  1.2123 +-		sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0));
  1.2124 +-	printf("Block size %d\n", sBlk.block_size);
  1.2125 + 	if(sBlk.s_major > 1)
  1.2126 + 		printf("Number of fragments %d\n", sBlk.fragments);
  1.2127 + 	printf("Number of inodes %d\n", sBlk.inodes);
  1.2128 +@@ -1459,6 +1447,18 @@
  1.2129 + 		s_ops.read_inode = read_inode_4;
  1.2130 + 		s_ops.read_uids_guids = read_uids_guids_4;
  1.2131 + 		memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4));
  1.2132 ++
  1.2133 ++		/*
  1.2134 ++		 * Check the compression type
  1.2135 ++		 */
  1.2136 ++		comp = lookup_compressor_id(sBlk.compression);
  1.2137 ++		if(!comp->supported) {
  1.2138 ++			ERROR("Filesystem uses %s compression, this is "
  1.2139 ++				"unsupported by this version\n", comp->name);
  1.2140 ++			ERROR("Decompressors available:\n");
  1.2141 ++			display_compressors("", "");
  1.2142 ++			goto failed_mount;
  1.2143 ++		}
  1.2144 + 		return TRUE;
  1.2145 + 	}
  1.2146 + 
  1.2147 +@@ -1548,6 +1548,11 @@
  1.2148 + 		goto failed_mount;
  1.2149 + 	}
  1.2150 + 
  1.2151 ++	/*
  1.2152 ++	 * 1.x, 2.x and 3.x filesystems use gzip compression.  Gzip is always
  1.2153 ++	 * suppported.
  1.2154 ++	 */
  1.2155 ++	comp = lookup_compressor("gzip");
  1.2156 + 	return TRUE;
  1.2157 + 
  1.2158 + failed_mount:
  1.2159 +@@ -1707,32 +1712,24 @@
  1.2160 + 
  1.2161 + 	while(1) {
  1.2162 + 		struct cache_entry *entry = queue_get(to_deflate);
  1.2163 +-		int res;
  1.2164 +-		unsigned long bytes = block_size;
  1.2165 ++		int error, res;
  1.2166 + 
  1.2167 +-		res = uncompress((unsigned char *) tmp, &bytes,
  1.2168 +-			(const unsigned char *) entry->data,
  1.2169 +-			SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size));
  1.2170 ++		res = comp->uncompress(tmp, entry->data,
  1.2171 ++			SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size,
  1.2172 ++			&error);
  1.2173 + 
  1.2174 +-		if(res != Z_OK) {
  1.2175 +-			if(res == Z_MEM_ERROR)
  1.2176 +-				ERROR("zlib::uncompress failed, not enough"
  1.2177 +-					"memory\n");
  1.2178 +-			else if(res == Z_BUF_ERROR)
  1.2179 +-				ERROR("zlib::uncompress failed, not enough "
  1.2180 +-					"room in output buffer\n");
  1.2181 +-			else
  1.2182 +-				ERROR("zlib::uncompress failed, unknown error "
  1.2183 +-					"%d\n", res);
  1.2184 +-		} else
  1.2185 +-			memcpy(entry->data, tmp, bytes);
  1.2186 ++		if(res == -1)
  1.2187 ++			ERROR("%s uncompress failed with error code %d\n",
  1.2188 ++				comp->name, error);
  1.2189 ++		else
  1.2190 ++			memcpy(entry->data, tmp, res);
  1.2191 + 
  1.2192 + 		/*
  1.2193 + 		 * block has been either successfully decompressed, or an error
  1.2194 +  		 * occurred, clear pending flag, set error appropriately and
  1.2195 +  		 * wake up any threads waiting on this block
  1.2196 +  		 */ 
  1.2197 +-		cache_block_ready(entry, res != Z_OK);
  1.2198 ++		cache_block_ready(entry, res == -1);
  1.2199 + 	}
  1.2200 + }
  1.2201 + 
  1.2202 +@@ -1913,7 +1910,7 @@
  1.2203 + 
  1.2204 + 
  1.2205 + #define VERSION() \
  1.2206 +-	printf("unsquashfs version 4.0 (2009/04/05)\n");\
  1.2207 ++	printf("unsquashfs version 4.0 (CVS 2009/08/30)\n");\
  1.2208 + 	printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>"\
  1.2209 + 		"\n\n");\
  1.2210 +     	printf("This program is free software; you can redistribute it and/or\n");\
  1.2211 +@@ -1938,7 +1935,6 @@
  1.2212 + 	int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT;
  1.2213 + 	int data_buffer_size = DATA_BUFFER_DEFAULT;
  1.2214 + 	char *b;
  1.2215 +-	struct winsize winsize;
  1.2216 + 
  1.2217 + 	pthread_mutex_init(&screen_mutex, NULL);
  1.2218 + 	root_process = geteuid() == 0;
  1.2219 +@@ -2087,6 +2083,8 @@
  1.2220 + 				"regular expressions\n");
  1.2221 + 			ERROR("\t\t\t\trather than use the default shell "
  1.2222 + 				"wildcard\n\t\t\t\texpansion (globbing)\n");
  1.2223 ++			ERROR("\nDecompressors available:\n");
  1.2224 ++			display_compressors("", "");
  1.2225 + 		}
  1.2226 + 		exit(1);
  1.2227 + 	}
  1.2228 +
  1.2229 +--- squashfs-4.0/squashfs-tools/unsquashfs.h	Sun Mar 29 04:29:02 2009
  1.2230 ++++ squashfs-4.0/squashfs-tools/unsquashfs.h	Fri Jul 31 19:24:38 2009
  1.2231 +@@ -31,7 +31,6 @@
  1.2232 + #include <fcntl.h>
  1.2233 + #include <errno.h>
  1.2234 + #include <string.h>
  1.2235 +-#include <zlib.h>
  1.2236 + #include <sys/mman.h>
  1.2237 + #include <utime.h>
  1.2238 + #include <pwd.h>