wok-current 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>