squashfs4: fix build breakage
[openwrt.git] / tools / squashfs4 / patches / 110-lzma.patch
1 diff -Nur squashfs4.0/squashfs-tools/compressor.c squashfs4.0-lzma-snapshot/squashfs-tools/compressor.c
2 --- squashfs4.0/squashfs-tools/compressor.c     1970-01-01 01:00:00.000000000 +0100
3 +++ squashfs4.0-lzma-snapshot/squashfs-tools/compressor.c       2009-10-20 06:03:37.000000000 +0200
4 @@ -0,0 +1,78 @@
5 +/*
6 + *
7 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
8 + * Phillip Lougher <phillip@lougher.demon.co.uk>
9 + *
10 + * This program is free software; you can redistribute it and/or
11 + * modify it under the terms of the GNU General Public License
12 + * as published by the Free Software Foundation; either version 2,
13 + * or (at your option) any later version.
14 + *
15 + * This program is distributed in the hope that it will be useful,
16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 + * GNU General Public License for more details.
19 + *
20 + * You should have received a copy of the GNU General Public License
21 + * along with this program; if not, write to the Free Software
22 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 + *
24 + * compressor.c
25 + */
26 +
27 +#include <stdio.h>
28 +#include <string.h>
29 +#include "compressor.h"
30 +#include "squashfs_fs.h"
31 +
32 +extern int gzip_compress(void **, char *, char *, int, int, int *);
33 +extern int gzip_uncompress(char *, char *, int, int, int *);
34 +extern int lzma_compress(void **, char *, char *, int, int, int *);
35 +extern int lzma_uncompress(char *, char *, int, int, int *);
36 +
37 +struct compressor compressor[] = {
38 +       { gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 },
39 +#ifdef LZMA_SUPPORT
40 +       { lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 },
41 +#else
42 +       { NULL, NULL, LZMA_COMPRESSION, "lzma", 0 },
43 +#endif
44 +       { NULL, NULL , 0, "unknown", 0}
45 +};
46 +
47 +
48 +struct compressor *lookup_compressor(char *name)
49 +{
50 +       int i;
51 +
52 +       for(i = 0; compressor[i].id; i++)
53 +               if(strcmp(compressor[i].name, name) == 0)
54 +                       break;
55 +
56 +       return &compressor[i];
57 +}
58 +
59 +
60 +struct compressor *lookup_compressor_id(int id)
61 +{
62 +       int i;
63 +
64 +       for(i = 0; compressor[i].id; i++)
65 +               if(id == compressor[i].id)
66 +                       break;
67 +
68 +       return &compressor[i];
69 +}
70 +
71 +
72 +void display_compressors(char *indent, char *def_comp)
73 +{
74 +       int i;
75 +
76 +       for(i = 0; compressor[i].id; i++)
77 +               if(compressor[i].supported)
78 +                       fprintf(stderr, "%s\t%s%s\n", indent,
79 +                               compressor[i].name,
80 +                               strcmp(compressor[i].name, def_comp) == 0 ?
81 +                               " (default)" : "");
82 +}
83 diff -Nur squashfs4.0/squashfs-tools/compressor.h squashfs4.0-lzma-snapshot/squashfs-tools/compressor.h
84 --- squashfs4.0/squashfs-tools/compressor.h     1970-01-01 01:00:00.000000000 +0100
85 +++ squashfs4.0-lzma-snapshot/squashfs-tools/compressor.h       2009-10-20 06:03:37.000000000 +0200
86 @@ -0,0 +1,33 @@
87 +/*
88 + *
89 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
90 + * Phillip Lougher <phillip@lougher.demon.co.uk>
91 + *
92 + * This program is free software; you can redistribute it and/or
93 + * modify it under the terms of the GNU General Public License
94 + * as published by the Free Software Foundation; either version 2,
95 + * or (at your option) any later version.
96 + *
97 + * This program is distributed in the hope that it will be useful,
98 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
99 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
100 + * GNU General Public License for more details.
101 + *
102 + * You should have received a copy of the GNU General Public License
103 + * along with this program; if not, write to the Free Software
104 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
105 + *
106 + * compressor.h
107 + */
108 +
109 +struct compressor {
110 +       int (*compress)(void **, char *, char *, int, int, int *);
111 +       int (*uncompress)(char *, char *, int, int, int *);
112 +       int id;
113 +       char *name;
114 +       int supported;
115 +};
116 +
117 +extern struct compressor *lookup_compressor(char *);
118 +extern struct compressor *lookup_compressor_id(int);
119 +extern void display_compressors(char *, char *);
120 diff -Nur squashfs4.0/squashfs-tools/gzip_wrapper.c squashfs4.0-lzma-snapshot/squashfs-tools/gzip_wrapper.c
121 --- squashfs4.0/squashfs-tools/gzip_wrapper.c   1970-01-01 01:00:00.000000000 +0100
122 +++ squashfs4.0-lzma-snapshot/squashfs-tools/gzip_wrapper.c     2009-10-20 06:03:37.000000000 +0200
123 @@ -0,0 +1,80 @@
124 +/*
125 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
126 + * Phillip Lougher <phillip@lougher.demon.co.uk>
127 + *
128 + * This program is free software; you can redistribute it and/or
129 + * modify it under the terms of the GNU General Public License
130 + * as published by the Free Software Foundation; either version 2,
131 + * or (at your option) any later version.
132 + *
133 + * This program is distributed in the hope that it will be useful,
134 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
135 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
136 + * GNU General Public License for more details.
137 + *
138 + * You should have received a copy of the GNU General Public License
139 + * along with this program; if not, write to the Free Software
140 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
141 + *
142 + * gzip_wrapper.c
143 + */
144 +
145 +#include <stdlib.h>
146 +#include <zlib.h>
147 +
148 +int gzip_compress(void **strm, char *d, char *s, int size, int block_size,
149 +               int *error)
150 +{
151 +       int res = 0;
152 +       z_stream *stream = *strm;
153 +
154 +       if(stream == NULL) {
155 +               if((stream = *strm = malloc(sizeof(z_stream))) == NULL)
156 +                       goto failed;
157 +
158 +               stream->zalloc = Z_NULL;
159 +               stream->zfree = Z_NULL;
160 +               stream->opaque = 0;
161 +
162 +               if((res = deflateInit(stream, 9)) != Z_OK)
163 +                       goto failed;
164 +       } else if((res = deflateReset(stream)) != Z_OK)
165 +               goto failed;
166 +
167 +       stream->next_in = (unsigned char *) s;
168 +       stream->avail_in = size;
169 +       stream->next_out = (unsigned char *) d;
170 +       stream->avail_out = block_size;
171 +
172 +       res = deflate(stream, Z_FINISH);
173 +       if(res == Z_STREAM_END)
174 +               /*
175 +                * Success, return the compressed size.
176 +                */
177 +               return (int) stream->total_out;
178 +       if(res == Z_OK)
179 +               /*
180 +                * Output buffer overflow.  Return out of buffer space
181 +                */
182 +               return 0;
183 +failed:
184 +       /*
185 +        * All other errors return failure, with the compressor
186 +        * specific error code in *error
187 +        */
188 +       *error = res;
189 +       return -1;
190 +}
191 +
192 +
193 +int gzip_uncompress(char *d, char *s, int size, int block_size, int *error)
194 +{
195 +       int res;
196 +       unsigned long bytes = block_size;
197 +
198 +       res = uncompress((unsigned char *) d, &bytes,
199 +               (const unsigned char *) s, size);
200 +
201 +       *error = res;
202 +       return res == Z_OK ? (int) bytes : -1;
203 +}
204 diff -Nur squashfs4.0/squashfs-tools/lzma_wrapper.c squashfs4.0-lzma-snapshot/squashfs-tools/lzma_wrapper.c
205 --- squashfs4.0/squashfs-tools/lzma_wrapper.c   1970-01-01 01:00:00.000000000 +0100
206 +++ squashfs4.0-lzma-snapshot/squashfs-tools/lzma_wrapper.c     2009-10-14 05:32:57.000000000 +0200
207 @@ -0,0 +1,93 @@
208 +/*
209 + * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
210 + * Phillip Lougher <phillip@lougher.demon.co.uk>
211 + *
212 + * This program is free software; you can redistribute it and/or
213 + * modify it under the terms of the GNU General Public License
214 + * as published by the Free Software Foundation; either version 2,
215 + * or (at your option) any later version.
216 + *
217 + * This program is distributed in the hope that it will be useful,
218 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
219 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
220 + * GNU General Public License for more details.
221 + *
222 + * You should have received a copy of the GNU General Public License
223 + * along with this program; if not, write to the Free Software
224 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
225 + *
226 + * lzma_wrapper.c
227 + */
228 +
229 +#include <LzmaLib.h>
230 +
231 +#define LZMA_HEADER_SIZE       (LZMA_PROPS_SIZE + 8)
232 +
233 +int lzma_compress(void **strm, char *dest, char *src,  int size,int block_size,
234 +               int *error)
235 +{
236 +       unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
237 +       size_t props_size = LZMA_PROPS_SIZE,
238 +               outlen = block_size - LZMA_HEADER_SIZE;
239 +       int res;
240 +
241 +       res = LzmaCompress(d + LZMA_HEADER_SIZE, &outlen, s, size, d,
242 +               &props_size, 5, block_size, 3, 0, 2, 32, 1);
243 +       
244 +       if(res == SZ_ERROR_OUTPUT_EOF) {
245 +               /*
246 +                * Output buffer overflow.  Return out of buffer space error
247 +                */
248 +               return 0;
249 +       }
250 +
251 +       if(res != SZ_OK) {
252 +               /*
253 +                * All other errors return failure, with the compressor
254 +                * specific error code in *error
255 +                */
256 +               *error = res;
257 +               return -1;
258 +       }
259 +
260 +       /*
261 +        * Fill in the 8 byte little endian uncompressed size field in the
262 +        * LZMA header.  8 bytes is excessively large for squashfs but
263 +        * this is the standard LZMA header and which is expected by the kernel
264 +        * code
265 +        */
266 +       d[LZMA_PROPS_SIZE] = size & 255;
267 +       d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255;
268 +       d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255;
269 +       d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255;
270 +       d[LZMA_PROPS_SIZE + 4] = 0;
271 +       d[LZMA_PROPS_SIZE + 5] = 0;
272 +       d[LZMA_PROPS_SIZE + 6] = 0;
273 +       d[LZMA_PROPS_SIZE + 7] = 0;
274 +
275 +       /*
276 +        * Success, return the compressed size.  Outlen returned by the LZMA
277 +        * compressor does not include the LZMA header space
278 +        */
279 +       return outlen + LZMA_HEADER_SIZE;
280 +}
281 +
282 +
283 +int lzma_uncompress(char *dest, char *src, int size, int block_size,
284 +       int *error)
285 +{
286 +       unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
287 +       size_t outlen, inlen = size - LZMA_HEADER_SIZE;
288 +       int res;
289 +
290 +       outlen = s[LZMA_PROPS_SIZE] |
291 +               (s[LZMA_PROPS_SIZE + 1] << 8) |
292 +               (s[LZMA_PROPS_SIZE + 2] << 16) |
293 +               (s[LZMA_PROPS_SIZE + 3] << 24);
294 +
295 +       res = LzmaUncompress(d, &outlen, s + LZMA_HEADER_SIZE, &inlen,
296 +               s, LZMA_PROPS_SIZE);
297 +       
298 +       *error = res;
299 +       return res == SZ_OK ? outlen : -1;
300 +}
301 diff -Nur squashfs4.0/squashfs-tools/Makefile squashfs4.0-lzma-snapshot/squashfs-tools/Makefile
302 --- squashfs4.0/squashfs-tools/Makefile 2009-04-05 04:03:36.000000000 +0200
303 +++ squashfs4.0-lzma-snapshot/squashfs-tools/Makefile   2009-10-22 06:17:12.000000000 +0200
304 @@ -1,40 +1,76 @@
305 +#
306 +# Building LZMA support
307 +# Download LZMA sdk (4.65 used in development, other versions may work),
308 +# set LZMA_DIR to unpacked source, and uncomment next line
309 +LZMA_SUPPORT = 1
310 +LZMA_DIR = ../../lzma-4.65
311 +
312 +#Compression default.
313 +COMP_DEFAULT = gzip
314 +
315 +INCLUDEDIR = -I.
316  INSTALL_DIR = /usr/local/bin
317  
318 -INCLUDEDIR = .
319 +MKSQUASHFS_OBJS = mksquashfs.o read_fs.o sort.o swap.o pseudo.o compressor.o \
320 +       gzip_wrapper.o
321 +
322 +UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \
323 +       unsquash-4.o swap.o compressor.o gzip_wrapper.o
324  
325 -CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2
326 +CFLAGS = $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
327 +       -D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" -O2 -Wall
328  
329 +ifdef LZMA_SUPPORT
330 +LZMA_OBJS = $(LZMA_DIR)/C/Alloc.o $(LZMA_DIR)/C/LzFind.o \
331 +       $(LZMA_DIR)/C/LzmaDec.o $(LZMA_DIR)/C/LzmaEnc.o $(LZMA_DIR)/C/LzmaLib.o
332 +INCLUDEDIR += -I$(LZMA_DIR)/C
333 +CFLAGS += -DLZMA_SUPPORT
334 +MKSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS)
335 +UNSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS)
336 +endif
337 +
338 +.PHONY: all
339  all: mksquashfs unsquashfs
340  
341 -mksquashfs: mksquashfs.o read_fs.o sort.o swap.o pseudo.o
342 -       $(CC) mksquashfs.o read_fs.o sort.o swap.o pseudo.o -lz -lpthread -lm -o $@
343 +mksquashfs: $(MKSQUASHFS_OBJS)
344 +       $(CC) $(MKSQUASHFS_OBJS) -lz -lpthread -lm -o $@
345 +
346 +mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \
347 +       squashfs_swap.h
348  
349 -mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h squashfs_swap.h Makefile
350 +read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h
351  
352 -read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h Makefile
353 +sort.o: sort.c squashfs_fs.h global.h sort.h
354  
355 -sort.o: sort.c squashfs_fs.h global.h sort.h Makefile
356 +swap.o: swap.c
357  
358 -swap.o: swap.c Makefile
359 +pseudo.o: pseudo.c pseudo.h
360  
361 -pseudo.o: pseudo.c pseudo.h Makefile
362 +compressor.o: compressor.c compressor.h
363  
364 -unsquashfs: unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o
365 -       $(CC) unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o -lz -lpthread -lm -o $@
366 +unsquashfs: $(UNSQUASHFS_OBJS)
367 +       $(CC) $(UNSQUASHFS_OBJS) -lz -lpthread -lm -o $@
368  
369 -unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h squashfs_compat.h global.h Makefile
370 +unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h \
371 +       squashfs_compat.h global.h
372  
373 -unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h global.h Makefile
374 +unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h \
375 +       global.h
376  
377 -unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h squashfs_compat.h global.h Makefile
378 +unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h \
379 +       squashfs_compat.h global.h
380  
381 -unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h global.h Makefile
382 +unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h \
383 +       global.h
384  
385 -unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h global.h Makefile
386 +unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h \
387 +       global.h
388  
389 +.PHONY: clean
390  clean:
391         -rm -f *.o mksquashfs unsquashfs
392  
393 +.PHONY: install
394  install: mksquashfs unsquashfs
395         mkdir -p $(INSTALL_DIR)
396         cp mksquashfs $(INSTALL_DIR)
397 diff -Nur squashfs4.0/squashfs-tools/mksquashfs.c squashfs4.0-lzma-snapshot/squashfs-tools/mksquashfs.c
398 --- squashfs4.0/squashfs-tools/mksquashfs.c     2009-04-05 23:22:48.000000000 +0200
399 +++ squashfs4.0-lzma-snapshot/squashfs-tools/mksquashfs.c       2009-10-20 06:03:38.000000000 +0200
400 @@ -36,7 +36,6 @@
401  #include <errno.h>
402  #include <dirent.h>
403  #include <string.h>
404 -#include <zlib.h>
405  #include <stdlib.h>
406  #include <signal.h>
407  #include <setjmp.h>
408 @@ -47,6 +46,7 @@
409  #include <math.h>
410  #include <regex.h>
411  #include <fnmatch.h>
412 +#include <sys/wait.h>
413  
414  #ifndef linux
415  #define __BYTE_ORDER BYTE_ORDER
416 @@ -64,6 +64,7 @@
417  #include "global.h"
418  #include "sort.h"
419  #include "pseudo.h"
420 +#include "compressor.h"
421  
422  #ifdef SQUASHFS_TRACE
423  #define TRACE(s, args...)      do { \
424 @@ -245,10 +246,8 @@
425  /* list of root directory entries read from original filesystem */
426  int old_root_entries = 0;
427  struct old_root_entry_info {
428 -       char                    name[SQUASHFS_NAME_LEN + 1];
429 -       squashfs_inode          inode;
430 -       int                     type;
431 -       int                     inode_number;
432 +       char                    *name;
433 +       struct inode_info       inode;
434  };
435  struct old_root_entry_info *old_root_entry;
436  
437 @@ -371,10 +370,15 @@
438  int reader_buffer_size;
439  int fragment_buffer_size;
440  
441 +/* compression operations structure */
442 +static struct compressor *comp;
443 +char *comp_name = COMP_DEFAULT;
444 +
445  char *read_from_disk(long long start, unsigned int avail_bytes);
446  void add_old_root_entry(char *name, squashfs_inode inode, int inode_number,
447         int type);
448 -extern int read_super(int fd, squashfs_super_block *sBlk, char *source);
449 +extern struct compressor  *read_super(int fd, squashfs_super_block *sBlk,
450 +       char *source);
451  extern long long read_filesystem(char *root_name, int fd,
452         squashfs_super_block *sBlk, char **cinode_table, char **data_cache,
453         char **cdirectory_table, char **directory_data_cache,
454 @@ -831,83 +835,32 @@
455  }
456  
457  
458 -unsigned int mangle2(z_stream **strm, char *d, char *s, int size,
459 +int mangle2(void **strm, char *d, char *s, int size,
460         int block_size, int uncompressed, int data_block)
461  {
462 -       unsigned long c_byte;
463 -       unsigned int res;
464 -       z_stream *stream = *strm;
465 -
466 -       if(uncompressed)
467 -               goto notcompressed;
468 -
469 -       if(stream == NULL) {
470 -               if((stream = *strm = malloc(sizeof(z_stream))) == NULL)
471 -                       BAD_ERROR("mangle::compress failed, not enough "
472 -                               "memory\n");
473 -
474 -               stream->zalloc = Z_NULL;
475 -               stream->zfree = Z_NULL;
476 -               stream->opaque = 0;
477 -
478 -               if((res = deflateInit(stream, 9)) != Z_OK) {
479 -                       if(res == Z_MEM_ERROR)
480 -                               BAD_ERROR("zlib::compress failed, not enough "
481 -                                       "memory\n");
482 -                       else if(res == Z_STREAM_ERROR)
483 -                               BAD_ERROR("zlib::compress failed, not a valid "
484 -                                       "compression level\n");
485 -                       else if(res == Z_VERSION_ERROR)
486 -                               BAD_ERROR("zlib::compress failed, incorrect "
487 -                                       "zlib version\n");
488 -                       else
489 -                               BAD_ERROR("zlib::compress failed, unknown "
490 -                                       "error %d\n", res);
491 -               }
492 -       } else if((res = deflateReset(stream)) != Z_OK) {
493 -               if(res == Z_STREAM_ERROR)
494 -                       BAD_ERROR("zlib::compress failed, stream state "
495 -                               "inconsistent\n");
496 -               else
497 -                       BAD_ERROR("zlib::compress failed, unknown error %d\n",
498 -                               res);
499 -       }
500 +       int error, c_byte = 0;
501  
502 -       stream->next_in = (unsigned char *) s;
503 -       stream->avail_in = size;
504 -       stream->next_out = (unsigned char *) d;
505 -       stream->avail_out = block_size;
506 -
507 -       res = deflate(stream, Z_FINISH);
508 -       if(res != Z_STREAM_END && res != Z_OK) {
509 -               if(res == Z_STREAM_ERROR)
510 -                       BAD_ERROR("zlib::compress failed, stream state "
511 -                               "inconsistent\n");
512 -               else if(res == Z_BUF_ERROR)
513 -                       BAD_ERROR("zlib::compress failed, no progress possible"
514 -                               "\n");
515 -               else
516 -                       BAD_ERROR("zlib::compress failed, unknown error %d\n",
517 -                               res);
518 +       if(!uncompressed) {
519 +               c_byte = comp->compress(strm, d, s, size, block_size, &error);
520 +               if(c_byte == -1)
521 +                       BAD_ERROR("mangle2:: %s compress failed with error "
522 +                               "code %d\n", comp->name, error);
523         }
524  
525 -       c_byte = stream->total_out;
526 -
527 -       if(res != Z_STREAM_END || c_byte >= size) {
528 -notcompressed:
529 +       if(c_byte == 0 || c_byte >= size) {
530                 memcpy(d, s, size);
531                 return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK :
532                         SQUASHFS_COMPRESSED_BIT);
533         }
534  
535 -       return (unsigned int) c_byte;
536 +       return c_byte;
537  }
538  
539  
540 -unsigned int mangle(char *d, char *s, int size, int block_size,
541 +int mangle(char *d, char *s, int size, int block_size,
542         int uncompressed, int data_block)
543  {
544 -       static z_stream *stream = NULL;
545 +       static void *stream = NULL;
546  
547         return mangle2(&stream, d, s, size, block_size, uncompressed,
548                 data_block);
549 @@ -1660,8 +1613,7 @@
550         pthread_mutex_unlock(&fragment_mutex);
551  
552         if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) {
553 -               int res;
554 -               unsigned long bytes = block_size;
555 +               int error, res;
556                 char *data;
557  
558                 if(compressed_buffer)
559 @@ -1669,19 +1621,11 @@
560                 else
561                         data = read_from_disk(start_block, size);
562  
563 -               res = uncompress((unsigned char *) buffer->data, &bytes,
564 -                       (const unsigned char *) data, size);
565 -               if(res != Z_OK) {
566 -                       if(res == Z_MEM_ERROR)
567 -                               BAD_ERROR("zlib::uncompress failed, not enough "
568 -                                       "memory\n");
569 -                       else if(res == Z_BUF_ERROR)
570 -                               BAD_ERROR("zlib::uncompress failed, not enough "
571 -                                       "room in output buffer\n");
572 -                       else
573 -                               BAD_ERROR("zlib::uncompress failed,"
574 -                                       "  unknown error %d\n", res);
575 -               }
576 +               res = comp->uncompress(buffer->data, data, size, block_size,
577 +                       &error);
578 +               if(res == -1)
579 +                       BAD_ERROR("%s uncompress failed with error code %d\n",
580 +                               comp->name, error);
581         } else if(compressed_buffer)
582                 memcpy(buffer->data, compressed_buffer->data, size);
583         else
584 @@ -1733,9 +1677,7 @@
585                 entry->buffer->block = bytes;
586                 bytes += compressed_size;
587                 fragments_outstanding --;
588 -               pthread_mutex_unlock(&fragment_mutex);
589                 queue_put(to_writer, entry->buffer);
590 -               pthread_mutex_lock(&fragment_mutex);
591                 TRACE("fragment_locked writing fragment %d, compressed size %d"
592                         "\n", entry->fragment, compressed_size);
593                 free(entry);
594 @@ -1758,6 +1700,8 @@
595         pthread_mutex_lock(&fragment_mutex);
596         insert_fragment_list(&frag_locked_list, entry);
597         pthread_mutex_unlock(&fragment_mutex);
598 +
599 +       return TRUE;
600  }
601  
602  
603 @@ -1824,7 +1768,9 @@
604         unsigned short c_byte;
605         char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2];
606         
607 +#ifdef SQUASHFS_TRACE
608         long long obytes = bytes;
609 +#endif
610  
611         for(i = 0; i < meta_blocks; i++) {
612                 int avail_bytes = length > SQUASHFS_METADATA_SIZE ?
613 @@ -2170,11 +2116,85 @@
614  }
615  
616  
617 +static int seq = 0;
618 +void reader_read_process(struct dir_ent *dir_ent)
619 +{
620 +       struct file_buffer *prev_buffer = NULL, *file_buffer;
621 +       int status, res, byte, count = 0;
622 +       int file = get_pseudo_file(dir_ent->inode->pseudo_id)->fd;
623 +       int child = get_pseudo_file(dir_ent->inode->pseudo_id)->child;
624 +       long long bytes = 0;
625 +
626 +       while(1) {
627 +               file_buffer = cache_get(reader_buffer, 0, 0);
628 +               file_buffer->sequence = seq ++;
629 +
630 +               byte = read_bytes(file, file_buffer->data, block_size);
631 +               if(byte == -1)
632 +                       goto read_err;
633 +
634 +               file_buffer->size = byte;
635 +               file_buffer->file_size = -1;
636 +               file_buffer->block = count ++;
637 +               file_buffer->error = FALSE;
638 +               file_buffer->fragment = FALSE;
639 +               bytes += byte;
640 +
641 +               if(byte == 0)
642 +                       break;
643 +
644 +               /*
645 +                * Update estimated_uncompressed block count.  This is done
646 +                * on every block rather than waiting for all blocks to be
647 +                * read incase write_file_process() is running in parallel
648 +                * with this.  Otherwise cur uncompressed block count may
649 +                * get ahead of the total uncompressed block count.
650 +                */ 
651 +               estimated_uncompressed ++;
652 +
653 +               if(prev_buffer)
654 +                       queue_put(from_reader, prev_buffer);
655 +               prev_buffer = file_buffer;
656 +       }
657 +
658 +       /*
659 +        * Update inode file size now that the size of the dynamic pseudo file
660 +        * is known.  This is needed for the -info option.
661 +        */
662 +       dir_ent->inode->buf.st_size = bytes;
663 +
664 +       res = waitpid(child, &status, 0);
665 +       if(res == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
666 +               goto read_err;
667 +
668 +       if(prev_buffer == NULL)
669 +               prev_buffer = file_buffer;
670 +       else {
671 +               cache_block_put(file_buffer);
672 +               seq --;
673 +       }
674 +       prev_buffer->file_size = bytes;
675 +       prev_buffer->fragment = !no_fragments &&
676 +               (count == 2 || always_use_fragments) && (byte < block_size);
677 +       queue_put(from_reader, prev_buffer);
678 +
679 +       return;
680 +
681 +read_err:
682 +       if(prev_buffer) {
683 +               cache_block_put(file_buffer);
684 +               seq --;
685 +               file_buffer = prev_buffer;
686 +       }
687 +       file_buffer->error = TRUE;
688 +       queue_put(from_deflate, file_buffer);
689 +}
690 +
691 +
692  void reader_read_file(struct dir_ent *dir_ent)
693  {
694         struct stat *buf = &dir_ent->inode->buf, buf2;
695         struct file_buffer *file_buffer;
696 -       static int index = 0;
697         int blocks, byte, count, expected, file, frag_block;
698         long long bytes, read_size;
699  
700 @@ -2202,7 +2222,7 @@
701                 if(file_buffer)
702                         queue_put(from_reader, file_buffer);
703                 file_buffer = cache_get(reader_buffer, 0, 0);
704 -               file_buffer->sequence = index ++;
705 +               file_buffer->sequence = seq ++;
706  
707                 byte = file_buffer->size = read_bytes(file, file_buffer->data,
708                         block_size);
709 @@ -2238,7 +2258,7 @@
710  
711  read_err:
712         file_buffer = cache_get(reader_buffer, 0, 0);
713 -       file_buffer->sequence = index ++;
714 +       file_buffer->sequence = seq ++;
715  read_err2:
716         file_buffer->error = TRUE;
717         queue_put(from_deflate, file_buffer);
718 @@ -2262,9 +2282,14 @@
719         for(i = 0; i < dir->count; i++) {
720                 struct dir_ent *dir_ent = dir->list[i];
721                 struct stat *buf = &dir_ent->inode->buf;
722 -               if(dir_ent->data)
723 +               if(dir_ent->inode->root_entry)
724                         continue;
725  
726 +               if(dir_ent->inode->pseudo_file) {
727 +                       reader_read_process(dir_ent);
728 +                       continue;
729 +               }
730 +
731                 switch(buf->st_mode & S_IFMT) {
732                         case S_IFREG:
733                                 reader_read_file(dir_ent);
734 @@ -2365,7 +2390,7 @@
735  
736  void *deflator(void *arg)
737  {
738 -       z_stream *stream = NULL;
739 +       void *stream = NULL;
740         int oldstate;
741  
742         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
743 @@ -2402,7 +2427,7 @@
744  
745  void *frag_deflator(void *arg)
746  {
747 -       z_stream *stream = NULL;
748 +       void *stream = NULL;
749         int oldstate;
750  
751         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
752 @@ -2426,8 +2451,8 @@
753                         write_buffer->block = bytes;
754                         bytes += compressed_size;
755                         fragments_outstanding --;
756 -                       pthread_mutex_unlock(&fragment_mutex);
757                         queue_put(to_writer, write_buffer);
758 +                       pthread_mutex_unlock(&fragment_mutex);
759                         TRACE("Writing fragment %lld, uncompressed size %d, "
760                                 "compressed size %d\n", file_buffer->block,
761                                 file_buffer->size, compressed_size);
762 @@ -2674,6 +2699,98 @@
763  }
764  
765  
766 +int write_file_process(squashfs_inode *inode, struct dir_ent *dir_ent,
767 +       struct file_buffer *read_buffer, int *duplicate_file)
768 +{
769 +       long long read_size, file_bytes, start;
770 +       struct fragment *fragment;
771 +       unsigned int *block_list = NULL;
772 +       int block = 0, status;
773 +       long long sparse = 0;
774 +       struct file_buffer *fragment_buffer = NULL;
775 +
776 +       *duplicate_file = FALSE;
777 +
778 +       lock_fragments();
779 +
780 +       file_bytes = 0;
781 +       start = bytes;
782 +       while (1) {
783 +               read_size = read_buffer->file_size;
784 +               if(read_buffer->fragment && read_buffer->c_byte)
785 +                       fragment_buffer = read_buffer;
786 +               else {
787 +                       block_list = realloc(block_list, (block + 1) *
788 +                               sizeof(unsigned int));
789 +                       if(block_list == NULL)
790 +                               BAD_ERROR("Out of memory allocating block_list"
791 +                                       "\n");
792 +                       block_list[block ++] = read_buffer->c_byte;
793 +                       if(read_buffer->c_byte) {
794 +                               read_buffer->block = bytes;
795 +                               bytes += read_buffer->size;
796 +                               cache_rehash(read_buffer, read_buffer->block);
797 +                               file_bytes += read_buffer->size;
798 +                               queue_put(to_writer, read_buffer);
799 +                       } else {
800 +                               sparse += read_buffer->size;
801 +                               cache_block_put(read_buffer);
802 +                       }
803 +               }
804 +               inc_progress_bar();
805 +
806 +               if(read_size != -1)
807 +                       break;
808 +
809 +               read_buffer = get_file_buffer(from_deflate);
810 +               if(read_buffer->error)
811 +                       goto read_err;
812 +       }
813 +
814 +       unlock_fragments();
815 +       fragment = get_and_fill_fragment(fragment_buffer);
816 +       cache_block_put(fragment_buffer);
817 +
818 +       if(duplicate_checking)
819 +               add_non_dup(read_size, file_bytes, block_list, start, fragment,
820 +                       0, 0, FALSE);
821 +       file_count ++;
822 +       total_bytes += read_size;
823 +
824 +       if(read_size < (1LL << 32) && start < (1LL << 32) && sparse == 0)
825 +               create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size,
826 +                       start, block, block_list, fragment, NULL, 0);
827 +       else
828 +               create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size,
829 +                       start, block, block_list, fragment, NULL, sparse);
830 +
831 +       if(duplicate_checking == FALSE)
832 +               free(block_list);
833 +
834 +       return 0;
835 +
836 +read_err:
837 +       cur_uncompressed -= block;
838 +       status = read_buffer->error;
839 +       bytes = start;
840 +       if(!block_device) {
841 +               int res;
842 +
843 +               queue_put(to_writer, NULL);
844 +               if(queue_get(from_writer) != 0)
845 +                       EXIT_MKSQUASHFS();
846 +               res = ftruncate(fd, bytes);
847 +               if(res != 0)
848 +                       BAD_ERROR("Failed to truncate dest file because %s\n",
849 +                               strerror(errno));
850 +       }
851 +       unlock_fragments();
852 +       free(block_list);
853 +       cache_block_put(read_buffer);
854 +       return status;
855 +}
856 +
857 +
858  int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent,
859         long long read_size, struct file_buffer *read_buffer,
860         int *duplicate_file)
861 @@ -2941,7 +3058,10 @@
862         
863         read_size = read_buffer->file_size;
864  
865 -       if(read_size == 0) {
866 +       if(read_size == -1)
867 +               status = write_file_process(inode, dir_ent, read_buffer,
868 +                       duplicate_file);
869 +       else if(read_size == 0) {
870                 write_file_empty(inode, dir_ent, duplicate_file);
871                 cache_block_put(read_buffer);
872         } else if(read_buffer->fragment && read_buffer->c_byte)
873 @@ -3036,6 +3156,8 @@
874  
875         memcpy(&inode->buf, buf, sizeof(struct stat));
876         inode->read = FALSE;
877 +       inode->root_entry = FALSE;
878 +       inode->pseudo_file = FALSE;
879         inode->inode = SQUASHFS_INVALID_BLK;
880         inode->nlink = 1;
881  
882 @@ -3056,7 +3178,7 @@
883  
884  
885  inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir,
886 -       struct inode_info *inode_info, void *data, struct dir_info *dir)
887 +       struct inode_info *inode_info, struct dir_info *dir)
888  {
889         if((dir->count % DIR_ENTRIES) == 0) {
890                 dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) *
891 @@ -3075,8 +3197,7 @@
892                 NULL;
893         dir->list[dir->count]->inode = inode_info;
894         dir->list[dir->count]->dir = sub_dir;
895 -       dir->list[dir->count]->our_dir = dir;
896 -       dir->list[dir->count++]->data = data;
897 +       dir->list[dir->count++]->our_dir = dir;
898         dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry);
899  }
900  
901 @@ -3128,10 +3249,10 @@
902  
903         if(dir->count < old_root_entries)
904                 for(i = 0; i < old_root_entries; i++) {
905 -                       if(old_root_entry[i].type == SQUASHFS_DIR_TYPE)
906 +                       if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE)
907                                 dir->directory_count ++;
908 -                       add_dir_entry(old_root_entry[i].name, "", NULL, NULL,
909 -                               &old_root_entry[i], dir);
910 +                       add_dir_entry(old_root_entry[i].name, "", NULL,
911 +                               &old_root_entry[i].inode, dir);
912                 }
913  
914         while(index < source) {
915 @@ -3167,10 +3288,10 @@
916  
917         if(dir->count < old_root_entries)
918                 for(i = 0; i < old_root_entries; i++) {
919 -                       if(old_root_entry[i].type == SQUASHFS_DIR_TYPE)
920 +                       if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE)
921                                 dir->directory_count ++;
922 -                       add_dir_entry(old_root_entry[i].name, "", NULL, NULL,
923 -                               &old_root_entry[i], dir);
924 +                       add_dir_entry(old_root_entry[i].name, "", NULL,
925 +                               &old_root_entry[i].inode, dir);
926                 }
927  
928         if((d_name = readdir(dir->linuxdir)) != NULL) {
929 @@ -3215,7 +3336,7 @@
930         int current_count;
931  
932         while((current_count = dir_info->current_count++) < dir_info->count)
933 -               if(dir_info->list[current_count]->data)
934 +               if(dir_info->list[current_count]->inode->root_entry)
935                         continue;
936                 else 
937                         return dir_info->list[current_count];
938 @@ -3240,11 +3361,11 @@
939         int current_count;
940  
941         while((current_count = dir_info->current_count++) < dir_info->count)
942 -               if(dir_info->list[current_count]->data)
943 -                       add_dir(dir_info->list[current_count]->data->inode,
944 -                               dir_info->list[current_count]->data->inode_number,
945 +               if(dir_info->list[current_count]->inode->root_entry)
946 +                       add_dir(dir_info->list[current_count]->inode->inode,
947 +                               dir_info->list[current_count]->inode->inode_number,
948                                 dir_info->list[current_count]->name,
949 -                               dir_info->list[current_count]->data->type, dir);
950 +                               dir_info->list[current_count]->inode->type, dir);
951                 else 
952                         return dir_info->list[current_count];
953         return NULL;    
954 @@ -3313,7 +3434,6 @@
955         dir_ent->name = dir_ent->pathname = strdup(pathname);
956         dir_ent->dir = dir_info;
957         dir_ent->our_dir = NULL;
958 -       dir_ent->data = NULL;
959         dir_info->dir_ent = dir_ent;
960  
961         if(sorted)
962 @@ -3383,7 +3503,7 @@
963                         sub_dir = NULL;
964  
965                 add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf),
966 -                       NULL, dir);
967 +                       dir);
968         }
969  
970         scan1_freedir(dir);
971 @@ -3399,7 +3519,7 @@
972         struct dir_ent *dir_ent;
973         struct pseudo_entry *pseudo_ent;
974         struct stat buf;
975 -       static pseudo_ino = 1;
976 +       static int pseudo_ino = 1;
977         
978         if(dir == NULL && (dir = scan1_opendir("")) == NULL)
979                 return NULL;
980 @@ -3415,6 +3535,29 @@
981  
982         while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) {
983                 dir_ent = scan2_lookup(dir, pseudo_ent->name);
984 +               if(pseudo_ent->dev->type == 's') {
985 +                       struct stat *buf;
986 +                       if(dir_ent == NULL) {
987 +                               ERROR("Pseudo set file \"%s\" does not exist "
988 +                                       "in source filesystem.  Ignoring\n",
989 +                                       pseudo_ent->pathname);
990 +                               continue;
991 +                       }
992 +                       if(dir_ent->inode->root_entry) {
993 +                               ERROR("Pseudo set file \"%s\" is a pre-existing"
994 +                                       " file in the filesystem being appended"
995 +                                       "  to.  It cannot be modified. "
996 +                                       "Ignoring!\n", pseudo_ent->pathname);
997 +                               continue;
998 +                       }
999 +                       buf = &dir_ent->inode->buf;
1000 +                       buf->st_mode = (buf->st_mode & S_IFMT) |
1001 +                               pseudo_ent->dev->mode;
1002 +                       buf->st_uid = pseudo_ent->dev->uid;
1003 +                       buf->st_gid = pseudo_ent->dev->gid;
1004 +                       continue;
1005 +               }
1006 +
1007                 if(dir_ent) {
1008                         ERROR("Pseudo file \"%s\" exists in source filesystem "
1009                                 "\"%s\"\n", pseudo_ent->pathname,
1010 @@ -3444,8 +3587,29 @@
1011                 buf.st_mtime = time(NULL);
1012                 buf.st_ino = pseudo_ino ++;
1013  
1014 -               add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir,
1015 -                       lookup_inode(&buf), NULL, dir);
1016 +               if(pseudo_ent->dev->type == 'f') {
1017 +#ifdef USE_TMP_FILE
1018 +                       struct stat buf2;
1019 +                       int res = stat(pseudo_ent->dev->filename, &buf2);
1020 +                       if(res == -1) {
1021 +                               ERROR("Stat on pseudo file \"%s\" failed, "
1022 +                                       "skipping...", pseudo_ent->pathname);
1023 +                               continue;
1024 +                       }
1025 +                       buf.st_size = buf2.st_size;
1026 +                       add_dir_entry(pseudo_ent->name,
1027 +                               pseudo_ent->dev->filename, sub_dir,
1028 +                               lookup_inode(&buf), dir);
1029 +#else
1030 +                       struct inode_info *inode = lookup_inode(&buf);
1031 +                       inode->pseudo_id = pseudo_ent->dev->pseudo_id;
1032 +                       inode->pseudo_file = TRUE;              
1033 +                       add_dir_entry(pseudo_ent->name, pseudo_ent->pathname,
1034 +                               sub_dir, inode, dir);
1035 +#endif
1036 +               } else
1037 +                       add_dir_entry(pseudo_ent->name, pseudo_ent->pathname,
1038 +                               sub_dir, lookup_inode(&buf), dir);
1039         }
1040  
1041         scan2_freedir(dir);
1042 @@ -3482,8 +3646,9 @@
1043                                                 &duplicate_file);
1044                                         INFO("file %s, uncompressed size %lld "
1045                                                 "bytes %s\n", filename,
1046 -                                               buf->st_size, duplicate_file ?
1047 -                                               "DUPLICATE" : "");
1048 +                                               (long long) buf->st_size,
1049 +                                               duplicate_file ?  "DUPLICATE" :
1050 +                                                "");
1051                                         break;
1052  
1053                                 case S_IFDIR:
1054 @@ -3557,6 +3722,7 @@
1055                                                 INFO("file %s, uncompressed "
1056                                                         "size %lld bytes LINK"
1057                                                         "\n", filename,
1058 +                                                       (long long)
1059                                                         buf->st_size);
1060                                         break;
1061                                 case SQUASHFS_SYMLINK_TYPE:
1062 @@ -3667,10 +3833,11 @@
1063                 BAD_ERROR("Out of memory in old root directory entries "
1064                         "reallocation\n");
1065  
1066 -       strcpy(old_root_entry[old_root_entries].name, name);
1067 -       old_root_entry[old_root_entries].inode = inode;
1068 -       old_root_entry[old_root_entries].inode_number = inode_number;
1069 -       old_root_entry[old_root_entries++].type = type;
1070 +       old_root_entry[old_root_entries].name = strdup(name);
1071 +       old_root_entry[old_root_entries].inode.inode = inode;
1072 +       old_root_entry[old_root_entries].inode.inode_number = inode_number;
1073 +       old_root_entry[old_root_entries].inode.type = type;
1074 +       old_root_entry[old_root_entries++].inode.root_entry = TRUE;
1075  }
1076  
1077  
1078 @@ -4137,7 +4304,7 @@
1079  
1080  
1081  #define VERSION() \
1082 -       printf("mksquashfs version 4.0 (2009/04/05)\n");\
1083 +       printf("mksquashfs version 4.1-CVS (2009/09/20)\n");\
1084         printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>\n\n"); \
1085         printf("This program is free software; you can redistribute it and/or\n");\
1086         printf("modify it under the terms of the GNU General Public License\n");\
1087 @@ -4172,26 +4339,28 @@
1088         source_path = argv + 1;
1089         source = i - 2;
1090         for(; i < argc; i++) {
1091 -               if(strcmp(argv[i], "-pf") == 0) {
1092 +               if(strcmp(argv[i], "-comp") == 0) {
1093                         if(++i == argc) {
1094 -                               ERROR("%s: -pf missing filename\n", argv[0]);
1095 +                               ERROR("%s: -comp missing compression type\n",
1096 +                                       argv[0]);
1097                                 exit(1);
1098                         }
1099 -                       if(read_pseudo_file(&pseudo, argv[i]) == FALSE) {
1100 -                               ERROR("Failed to parse pseudo file \"%s\"\n",
1101 -                                       argv[i]);
1102 +                       comp_name = argv[i];
1103 +               } else if(strcmp(argv[i], "-pf") == 0) {
1104 +                       if(++i == argc) {
1105 +                               ERROR("%s: -pf missing filename\n", argv[0]);
1106                                 exit(1);
1107                         }
1108 +                       if(read_pseudo_file(&pseudo, argv[i]) == FALSE)
1109 +                               exit(1);
1110                 } else if(strcmp(argv[i], "-p") == 0) {
1111                         if(++i == argc) {
1112                                 ERROR("%s: -p missing pseudo file definition\n",
1113                                         argv[0]);
1114                                 exit(1);
1115                         }
1116 -                       if(read_pseudo_def(&pseudo, argv[i]) == FALSE) {
1117 -                               ERROR("Failed to parse pseudo definition\n");
1118 +                       if(read_pseudo_def(&pseudo, argv[i]) == FALSE)
1119                                 exit(1);
1120 -                       }
1121                 } else if(strcmp(argv[i], "-recover") == 0) {
1122                         if(++i == argc) {
1123                                 ERROR("%s: -recover missing recovery file\n",
1124 @@ -4394,34 +4563,16 @@
1125  printOptions:
1126                         ERROR("SYNTAX:%s source1 source2 ...  dest [options] "
1127                                 "[-e list of exclude\ndirs/files]\n", argv[0]);
1128 -                       ERROR("\nOptions are\n");
1129 -                       ERROR("-version\t\tprint version, licence and "
1130 -                               "copyright message\n");
1131 -                       ERROR("-recover <name>\t\trecover filesystem data "
1132 -                               "using recovery file <name>\n");
1133 -                       ERROR("-no-recovery\t\tdon't generate a recovery "
1134 -                               "file\n");
1135 -                       ERROR("-info\t\t\tprint files written to filesystem\n");
1136 -                       ERROR("-no-exports\t\tdon't make the filesystem "
1137 -                               "exportable via NFS\n");
1138 -                       ERROR("-no-progress\t\tdon't display the progress "
1139 -                               "bar\n");
1140 -                       ERROR("-no-sparse\t\tdon't detect sparse files\n");
1141 +                       ERROR("\nFilesystem build options:\n");
1142 +                       ERROR("-comp <comp>\t\tselect <comp> compression\n");
1143 +                       ERROR("\t\t\tCompressors available:\n");
1144 +                       display_compressors("\t\t\t", COMP_DEFAULT);
1145                         ERROR("-b <block_size>\t\tset data block to "
1146                                 "<block_size>.  Default %d bytes\n",
1147                                 SQUASHFS_FILE_SIZE);
1148 -                       ERROR("-processors <number>\tUse <number> processors."
1149 -                               "  By default will use number of\n");
1150 -                       ERROR("\t\t\tprocessors available\n");
1151 -                       ERROR("-read-queue <size>\tSet input queue to <size> "
1152 -                               "Mbytes.  Default %d Mbytes\n",
1153 -                               READER_BUFFER_DEFAULT);
1154 -                       ERROR("-write-queue <size>\tSet output queue to <size> "
1155 -                               "Mbytes.  Default %d Mbytes\n",
1156 -                               WRITER_BUFFER_DEFAULT);
1157 -                       ERROR("-fragment-queue <size>\tSet fagment queue to "
1158 -                               "<size> Mbytes.  Default %d Mbytes\n",
1159 -                               FRAGMENT_BUFFER_DEFAULT);
1160 +                       ERROR("-no-exports\t\tdon't make the filesystem "
1161 +                               "exportable via NFS\n");
1162 +                       ERROR("-no-sparse\t\tdon't detect sparse files\n");
1163                         ERROR("-noI\t\t\tdo not compress inode table\n");
1164                         ERROR("-noD\t\t\tdo not compress data blocks\n");
1165                         ERROR("-noF\t\t\tdo not compress fragment blocks\n");
1166 @@ -4430,13 +4581,34 @@
1167                                 "files larger than block size\n");
1168                         ERROR("-no-duplicates\t\tdo not perform duplicate "
1169                                 "checking\n");
1170 -                       ERROR("-noappend\t\tdo not append to existing "
1171 -                               "filesystem\n");
1172 +                       ERROR("-all-root\t\tmake all files owned by root\n");
1173 +                       ERROR("-force-uid uid\t\tset all file uids to uid\n");
1174 +                       ERROR("-force-gid gid\t\tset all file gids to gid\n");
1175 +                       ERROR("-nopad\t\t\tdo not pad filesystem to a multiple "
1176 +                               "of 4K\n");
1177                         ERROR("-keep-as-directory\tif one source directory is "
1178                                 "specified, create a root\n");
1179                         ERROR("\t\t\tdirectory containing that directory, "
1180                                 "rather than the\n");
1181                         ERROR("\t\t\tcontents of the directory\n");
1182 +                       ERROR("\nFilesystem filter options:\n");
1183 +                       ERROR("-p <pseudo-definition>\tAdd pseudo file definition\n");
1184 +                       ERROR("-pf <pseudo-file>\tAdd list of pseudo file definitions\n");
1185 +                       ERROR("-sort <sort_file>\tsort files according to "
1186 +                               "priorities in <sort_file>.  One\n");
1187 +                       ERROR("\t\t\tfile or dir with priority per line.  "
1188 +                               "Priority -32768 to\n");
1189 +                       ERROR("\t\t\t32767, default priority 0\n");
1190 +                       ERROR("-ef <exclude_file>\tlist of exclude dirs/files."
1191 +                               "  One per line\n");
1192 +                       ERROR("-wildcards\t\tAllow extended shell wildcards "
1193 +                               "(globbing) to be used in\n\t\t\texclude "
1194 +                               "dirs/files\n");
1195 +                       ERROR("-regex\t\t\tAllow POSIX regular expressions to "
1196 +                               "be used in exclude\n\t\t\tdirs/files\n");
1197 +                       ERROR("\nFilesystem append options:\n");
1198 +                       ERROR("-noappend\t\tdo not append to existing "
1199 +                               "filesystem\n");
1200                         ERROR("-root-becomes <name>\twhen appending source "
1201                                 "files/directories, make the\n");
1202                         ERROR("\t\t\toriginal root become a subdirectory in "
1203 @@ -4444,11 +4616,29 @@
1204                         ERROR("\t\t\tcalled <name>, rather than adding the new "
1205                                 "source items\n");
1206                         ERROR("\t\t\tto the original root\n");
1207 -                       ERROR("-all-root\t\tmake all files owned by root\n");
1208 -                       ERROR("-force-uid uid\t\tset all file uids to uid\n");
1209 -                       ERROR("-force-gid gid\t\tset all file gids to gid\n");
1210 -                       ERROR("-nopad\t\t\tdo not pad filesystem to a multiple "
1211 -                               "of 4K\n");
1212 +                       ERROR("\nMksquashfs runtime options:\n");
1213 +                       ERROR("-version\t\tprint version, licence and "
1214 +                               "copyright message\n");
1215 +                       ERROR("-recover <name>\t\trecover filesystem data "
1216 +                               "using recovery file <name>\n");
1217 +                       ERROR("-no-recovery\t\tdon't generate a recovery "
1218 +                               "file\n");
1219 +                       ERROR("-info\t\t\tprint files written to filesystem\n");
1220 +                       ERROR("-no-progress\t\tdon't display the progress "
1221 +                               "bar\n");
1222 +                       ERROR("-processors <number>\tUse <number> processors."
1223 +                               "  By default will use number of\n");
1224 +                       ERROR("\t\t\tprocessors available\n");
1225 +                       ERROR("-read-queue <size>\tSet input queue to <size> "
1226 +                               "Mbytes.  Default %d Mbytes\n",
1227 +                               READER_BUFFER_DEFAULT);
1228 +                       ERROR("-write-queue <size>\tSet output queue to <size> "
1229 +                               "Mbytes.  Default %d Mbytes\n",
1230 +                               WRITER_BUFFER_DEFAULT);
1231 +                       ERROR("-fragment-queue <size>\tSet fagment queue to "
1232 +                               "<size> Mbytes.  Default %d Mbytes\n",
1233 +                               FRAGMENT_BUFFER_DEFAULT);
1234 +                       ERROR("\nMiscellaneous options:\n");
1235                         ERROR("-root-owned\t\talternative name for -all-root"
1236                                 "\n");
1237                         ERROR("-noInodeCompression\talternative name for -noI"
1238 @@ -4457,20 +4647,6 @@
1239                                 "\n");
1240                         ERROR("-noFragmentCompression\talternative name for "
1241                                 "-noF\n");
1242 -                       ERROR("-sort <sort_file>\tsort files according to "
1243 -                               "priorities in <sort_file>.  One\n");
1244 -                       ERROR("\t\t\tfile or dir with priority per line.  "
1245 -                               "Priority -32768 to\n");
1246 -                       ERROR("\t\t\t32767, default priority 0\n");
1247 -                       ERROR("-ef <exclude_file>\tlist of exclude dirs/files."
1248 -                               "  One per line\n");
1249 -                       ERROR("-wildcards\t\tAllow extended shell wildcards "
1250 -                               "(globbing) to be used in\n\t\t\texclude "
1251 -                               "dirs/files\n");
1252 -                       ERROR("-regex\t\t\tAllow POSIX regular expressions to "
1253 -                               "be used in exclude\n\t\t\tdirs/files\n");
1254 -                       ERROR("-p <pseudo-definition>\tAdd pseudo file definition\n");
1255 -                       ERROR("-pf <pseudo-file>\tAdd list of pseudo file definitions\n");
1256                         exit(1);
1257                 }
1258         }
1259 @@ -4548,11 +4724,10 @@
1260                         fclose(fd);
1261                 } else if(strcmp(argv[i], "-e") == 0)
1262                         break;
1263 -               else if(strcmp(argv[i], "-b") == 0 ||
1264 -                               strcmp(argv[i], "-root-becomes") == 0 ||
1265 +               else if(strcmp(argv[i], "-root-becomes") == 0 ||
1266                                 strcmp(argv[i], "-sort") == 0 ||
1267                                 strcmp(argv[i], "-pf") == 0 ||
1268 -                               strcmp(argv[i], "-p") == 0)
1269 +                               strcmp(argv[i], "-comp") == 0)
1270                         i++;
1271  
1272         if(i != argc) {
1273 @@ -4574,11 +4749,10 @@
1274                         sorted ++;
1275                 } else if(strcmp(argv[i], "-e") == 0)
1276                         break;
1277 -               else if(strcmp(argv[i], "-b") == 0 ||
1278 -                               strcmp(argv[i], "-root-becomes") == 0 ||
1279 +               else if(strcmp(argv[i], "-root-becomes") == 0 ||
1280                                 strcmp(argv[i], "-ef") == 0 ||
1281                                 strcmp(argv[i], "-pf") == 0 ||
1282 -                               strcmp(argv[i], "-p") == 0)
1283 +                               strcmp(argv[i], "-comp") == 0)
1284                         i++;
1285  
1286  #ifdef SQUASHFS_TRACE
1287 @@ -4586,7 +4760,8 @@
1288  #endif
1289  
1290         if(!delete) {
1291 -               if(read_super(fd, &sBlk, argv[source + 1]) == 0) {
1292 +               comp = read_super(fd, &sBlk, argv[source + 1]);
1293 +               if(comp == NULL) {
1294                         ERROR("Failed to read existing filesystem - will not "
1295                                 "overwrite - ABORTING!\n");
1296                         ERROR("To force Mksquashfs to write to this block "
1297 @@ -4603,6 +4778,15 @@
1298                 always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags);
1299                 duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags);
1300                 exportable = SQUASHFS_EXPORTABLE(sBlk.flags);
1301 +       } else {
1302 +               comp = lookup_compressor(comp_name);
1303 +               if(!comp->supported) {
1304 +                       ERROR("FATAL_ERROR: Compressor \"%s\" is not "
1305 +                               "supported!\n", comp_name);
1306 +                       ERROR("Compressors available:\n");
1307 +                       display_compressors("", COMP_DEFAULT);
1308 +                       EXIT_MKSQUASHFS();
1309 +               }
1310         }
1311  
1312         initialise_threads();
1313 @@ -4648,8 +4832,8 @@
1314                         "size %d\n", SQUASHFS_MAJOR, s_minor, argv[source + 1],
1315                         block_size);
1316                 printf("All -b, -noI, -noD, -noF, no-duplicates, no-fragments, "
1317 -                       "-always-use-fragments and -exportable options ignored"
1318 -                       "\n");
1319 +                       "-always-use-fragments,\n-exportable and -comp options "
1320 +                       "ignored\n");
1321                 printf("\nIf appending is not wanted, please re-run with "
1322                         "-noappend specified!\n\n");
1323  
1324 @@ -4803,8 +4987,7 @@
1325  
1326         sBlk.bytes_used = bytes;
1327  
1328 -       /* Only compression supported */
1329 -       sBlk.compression = ZLIB_COMPRESSION;
1330 +       sBlk.compression = comp->id;
1331  
1332         /* Xattrs are not currently supported */
1333         sBlk.xattr_table_start = SQUASHFS_INVALID_BLK;
1334 @@ -4820,6 +5003,8 @@
1335  
1336         close(fd);
1337  
1338 +       delete_pseudo_files();
1339 +
1340         if(recovery_file[0] != '\0')
1341                 unlink(recovery_file);
1342  
1343 @@ -4827,9 +5012,9 @@
1344                 * sizeof(unsigned short) + guid_count * sizeof(unsigned short) +
1345                 sizeof(squashfs_super_block);
1346  
1347 -       printf("\n%sSquashfs %d.%d filesystem, data block size %d\n",
1348 -               exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR,
1349 -               block_size);
1350 +       printf("\n%sSquashfs %d.%d filesystem, %s compressed, data block size"
1351 +               " %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR,
1352 +               SQUASHFS_MINOR, comp->name, block_size);
1353         printf("\t%s data, %s metadata, %s fragments\n",
1354                 noD ? "uncompressed" : "compressed", noI ?  "uncompressed" :
1355                 "compressed", no_fragments ? "no" : noF ? "uncompressed" :
1356 diff -Nur squashfs4.0/squashfs-tools/pseudo.c squashfs4.0-lzma-snapshot/squashfs-tools/pseudo.c
1357 --- squashfs4.0/squashfs-tools/pseudo.c 2009-04-05 04:01:58.000000000 +0200
1358 +++ squashfs4.0-lzma-snapshot/squashfs-tools/pseudo.c   2009-10-20 06:03:38.000000000 +0200
1359 @@ -30,6 +30,7 @@
1360  #include <string.h>
1361  #include <stdlib.h>
1362  #include <sys/types.h>
1363 +#include <sys/wait.h>
1364  
1365  #include "pseudo.h"
1366  
1367 @@ -55,6 +56,9 @@
1368  #define TRUE 1
1369  #define FALSE 0
1370  
1371 +struct pseudo_dev **pseudo_file = NULL;
1372 +int pseudo_count = 0;
1373 +
1374  static void dump_pseudo(struct pseudo *pseudo, char *string)
1375  {
1376         int i;
1377 @@ -99,7 +103,7 @@
1378         char *target, char *alltarget)
1379  {
1380         char targname[1024];
1381 -       int i, error;
1382 +       int i;
1383  
1384         target = get_component(target, targname);
1385  
1386 @@ -128,12 +132,8 @@
1387                 if(target[0] == '\0') {
1388                         /* at leaf pathname component */
1389                         pseudo->name[i].pseudo = NULL;
1390 -                       pseudo->name[i].dev = malloc(sizeof(struct pseudo_dev));
1391 -                       if(pseudo->name[i].dev == NULL)
1392 -                               BAD_ERROR("failed to allocate pseudo file\n");
1393                         pseudo->name[i].pathname = strdup(alltarget);
1394 -                       memcpy(pseudo->name[i].dev, pseudo_dev,
1395 -                               sizeof(struct pseudo_dev));
1396 +                       pseudo->name[i].dev = pseudo_dev;
1397                 } else {
1398                         /* recurse adding child components */
1399                         pseudo->name[i].dev = NULL;
1400 @@ -169,15 +169,9 @@
1401                         if(target[0] == '\0') {
1402                                 if(pseudo->name[i].dev == NULL &&
1403                                                 pseudo_dev->type == 'd') {
1404 -                                       pseudo->name[i].dev =
1405 -                                               malloc(sizeof(struct pseudo_dev));
1406 -                                       if(pseudo->name[i].dev == NULL)
1407 -                                               BAD_ERROR("failed to allocate "
1408 -                                                       "pseudo file\n");
1409                                         pseudo->name[i].pathname =
1410                                                 strdup(alltarget);
1411 -                                       memcpy(pseudo->name[i].dev, pseudo_dev,
1412 -                                               sizeof(struct pseudo_dev));
1413 +                                       pseudo->name[i].dev = pseudo_dev;
1414                                 } else
1415                                         ERROR("%s already exists as a "
1416                                                 "directory.  Ignoring %s!\n",
1417 @@ -229,16 +223,113 @@
1418  }
1419  
1420  
1421 +int exec_file(char *command, struct pseudo_dev *dev)
1422 +{
1423 +       int child, res;
1424 +       static pid_t pid = -1;
1425 +       int pipefd[2];
1426 +#ifdef USE_TMP_FILE
1427 +       char filename[1024];
1428 +       int status;
1429 +       static int number = 0;
1430 +#endif
1431 +
1432 +       if(pid == -1)
1433 +               pid = getpid();
1434 +
1435 +#ifdef USE_TMP_FILE
1436 +       sprintf(filename, "/tmp/squashfs_pseudo_%d_%d", pid, number ++);
1437 +       pipefd[1] = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
1438 +       if(pipefd[1] == -1) {
1439 +               printf("open failed\n");
1440 +               return -1;
1441 +       }
1442 +#else
1443 +       res = pipe(pipefd);
1444 +       if(res == -1) {
1445 +               printf("pipe failed\n");
1446 +               return -1;
1447 +       }
1448 +#endif
1449 +
1450 +       child = fork();
1451 +       if(child == -1) {
1452 +               printf("fork failed\n");
1453 +               goto failed;
1454 +       }
1455 +
1456 +       if(child == 0) {
1457 +               close(STDOUT_FILENO);
1458 +               res = dup(pipefd[1]);
1459 +               if(res == -1) {
1460 +                       printf("dup failed\n");
1461 +                       exit(EXIT_FAILURE);
1462 +               }
1463 +               execl("/bin/sh", "sh", "-c", command, (char *) NULL);
1464 +               printf("execl failed\n");
1465 +               exit(EXIT_FAILURE);
1466 +       }
1467 +
1468 +#ifdef USE_TMP_FILE
1469 +       res = waitpid(child, &status, 0);
1470 +       close(pipefd[1]);
1471 +       if(res != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0) {
1472 +               dev->filename = strdup(filename);
1473 +               return 0;
1474 +       }
1475 +failed:
1476 +       unlink(filename);
1477 +       return -1;
1478 +#else
1479 +       close(pipefd[1]);
1480 +       dev->fd = pipefd[0];
1481 +       dev->child = child;
1482 +       return 0;
1483 +failed:
1484 +       return -1;
1485 +#endif
1486 +}
1487 +
1488 +
1489 +void add_pseudo_file(struct pseudo_dev *dev)
1490 +{
1491 +       pseudo_file = realloc(pseudo_file, (pseudo_count + 1) *
1492 +               sizeof(struct pseudo_dev *));
1493 +       if(pseudo_file == NULL)
1494 +               BAD_ERROR("Failed to realloc pseudo_file\n");
1495 +
1496 +       dev->pseudo_id = pseudo_count;
1497 +       pseudo_file[pseudo_count ++] = dev;
1498 +}
1499 +
1500 +
1501 +void delete_pseudo_files()
1502 +{
1503 +#ifdef USE_TMP_FILE
1504 +       int i;
1505 +
1506 +       for(i = 0; i < pseudo_count; i++)
1507 +               unlink(pseudo_file[i]->filename);
1508 +#endif
1509 +}
1510 +
1511 +
1512 +struct pseudo_dev *get_pseudo_file(int pseudo_id)
1513 +{
1514 +       return pseudo_file[pseudo_id];
1515 +}
1516 +
1517 +
1518  int read_pseudo_def(struct pseudo **pseudo, char *def)
1519  {
1520 -       int n;
1521 +       int n, bytes;
1522         unsigned int major = 0, minor = 0, mode;
1523         char filename[2048], type, suid[100], sgid[100], *ptr;
1524         long long uid, gid;
1525 -       struct pseudo_dev dev;
1526 +       struct pseudo_dev *dev;
1527  
1528 -       n = sscanf(def, "%s %c %o %s %s %u %u", filename, &type, &mode, suid, sgid,
1529 -                       &major, &minor);
1530 +       n = sscanf(def, "%s %c %o %s %s %n", filename, &type, &mode, suid,
1531 +                       sgid, &bytes);
1532  
1533         if(n < 5) {
1534                 ERROR("Not enough or invalid arguments in pseudo file "
1535 @@ -249,7 +340,9 @@
1536         switch(type) {
1537         case 'b':
1538         case 'c':
1539 -               if(n < 7) {
1540 +               n = sscanf(def + bytes,  "%u %u", &major, &minor);
1541 +
1542 +               if(n < 2) {
1543                         ERROR("Not enough or invalid arguments in pseudo file "
1544                                 "definition\n");
1545                         goto error;
1546 @@ -265,47 +358,15 @@
1547                         goto error;
1548                 }
1549  
1550 -               /* fall through */
1551 -       case 'd':
1552 -               if(mode > 0777) {
1553 -                       ERROR("Mode %o out of range\n", mode);
1554 +       case 'f':
1555 +               if(def[bytes] == '\0') {
1556 +                       ERROR("Not enough arguments in pseudo file "
1557 +                               "definition\n");
1558                         goto error;
1559 -               }
1560 -
1561 -               uid = strtoll(suid, &ptr, 10);
1562 -               if(*ptr == '\0') {
1563 -                       if(uid < 0 || uid > ((1LL << 32) - 1)) {
1564 -                               ERROR("Uid %s out of range\n", suid);
1565 -                               goto error;
1566 -                       }
1567 -               } else {
1568 -                       struct passwd *pwuid = getpwnam(suid);
1569 -                       if(pwuid)
1570 -                               uid = pwuid->pw_uid;
1571 -                       else {
1572 -                               ERROR("Uid %s invalid uid or unknown user\n",
1573 -                                       suid);
1574 -                               goto error;
1575 -                       }
1576 -               }
1577 -               
1578 -               gid = strtoll(sgid, &ptr, 10);
1579 -               if(*ptr == '\0') {
1580 -                       if(gid < 0 || gid > ((1LL << 32) - 1)) {
1581 -                               ERROR("Gid %s out of range\n", sgid);
1582 -                               goto error;
1583 -                       }
1584 -               } else {
1585 -                       struct group *grgid = getgrnam(sgid);
1586 -                       if(grgid)
1587 -                               gid = grgid->gr_gid;
1588 -                       else {
1589 -                               ERROR("Gid %s invalid uid or unknown user\n",
1590 -                                       sgid);
1591 -                               goto error;
1592 -                       }
1593 -               }
1594 -
1595 +               }       
1596 +               break;
1597 +       case 'd':
1598 +       case 'm':
1599                 break;
1600         default:
1601                 ERROR("Unsupported type %c\n", type);
1602 @@ -313,6 +374,43 @@
1603         }
1604  
1605  
1606 +       if(mode > 0777) {
1607 +               ERROR("Mode %o out of range\n", mode);
1608 +               goto error;
1609 +       }
1610 +
1611 +       uid = strtoll(suid, &ptr, 10);
1612 +       if(*ptr == '\0') {
1613 +               if(uid < 0 || uid > ((1LL << 32) - 1)) {
1614 +                       ERROR("Uid %s out of range\n", suid);
1615 +                       goto error;
1616 +               }
1617 +       } else {
1618 +               struct passwd *pwuid = getpwnam(suid);
1619 +               if(pwuid)
1620 +                       uid = pwuid->pw_uid;
1621 +               else {
1622 +                       ERROR("Uid %s invalid uid or unknown user\n", suid);
1623 +                       goto error;
1624 +               }
1625 +       }
1626 +               
1627 +       gid = strtoll(sgid, &ptr, 10);
1628 +       if(*ptr == '\0') {
1629 +               if(gid < 0 || gid > ((1LL << 32) - 1)) {
1630 +                       ERROR("Gid %s out of range\n", sgid);
1631 +                       goto error;
1632 +               }
1633 +       } else {
1634 +               struct group *grgid = getgrnam(sgid);
1635 +               if(grgid)
1636 +                       gid = grgid->gr_gid;
1637 +               else {
1638 +                       ERROR("Gid %s invalid uid or unknown user\n", sgid);
1639 +                       goto error;
1640 +               }
1641 +       }
1642 +
1643         switch(type) {
1644         case 'b':
1645                 mode |= S_IFBLK;
1646 @@ -323,16 +421,37 @@
1647         case 'd':
1648                 mode |= S_IFDIR;
1649                 break;
1650 +       case 'f':
1651 +               mode |= S_IFREG;
1652 +               break;
1653         }
1654  
1655 -       dev.type = type;
1656 -       dev.mode = mode;
1657 -       dev.uid = uid;
1658 -       dev.gid = gid;
1659 -       dev.major = major;
1660 -       dev.minor = minor;
1661 +       dev = malloc(sizeof(struct pseudo_dev));
1662 +       if(dev == NULL)
1663 +               BAD_ERROR("Failed to create pseudo_dev\n");
1664 +
1665 +       dev->type = type;
1666 +       dev->mode = mode;
1667 +       dev->uid = uid;
1668 +       dev->gid = gid;
1669 +       dev->major = major;
1670 +       dev->minor = minor;
1671 +
1672 +       if(type == 'f') {
1673 +               int res;
1674 +
1675 +               printf("Executing dynamic pseudo file\n");
1676 +               printf("\t\"%s\"\n", def);
1677 +               res = exec_file(def + bytes, dev);
1678 +               if(res == -1) {
1679 +                       ERROR("Failed to execute dynamic pseudo file definition"
1680 +                               " \"%s\"\n", def);
1681 +                       return FALSE;
1682 +               }
1683 +               add_pseudo_file(dev);
1684 +       }
1685  
1686 -       *pseudo = add_pseudo(*pseudo, &dev, filename, filename);
1687 +       *pseudo = add_pseudo(*pseudo, dev, filename, filename);
1688  
1689         return TRUE;
1690  
1691 diff -Nur squashfs4.0/squashfs-tools/pseudo.h squashfs4.0-lzma-snapshot/squashfs-tools/pseudo.h
1692 --- squashfs4.0/squashfs-tools/pseudo.h 2009-04-04 03:44:24.000000000 +0200
1693 +++ squashfs4.0-lzma-snapshot/squashfs-tools/pseudo.h   2009-10-20 06:03:38.000000000 +0200
1694 @@ -27,6 +27,12 @@
1695         unsigned int    gid;
1696         unsigned int    major;
1697         unsigned int    minor;
1698 +       int             pseudo_id;
1699 +       int             fd;
1700 +       int             child;
1701 +#ifdef USE_TMP_FILE
1702 +       char            *filename;
1703 +#endif
1704  };
1705  
1706  struct pseudo_entry {
1707 @@ -46,3 +52,5 @@
1708  extern int read_pseudo_file(struct pseudo **, char *);
1709  extern struct pseudo *pseudo_subdir(char *, struct pseudo *);
1710  extern struct pseudo_entry *pseudo_readdir(struct pseudo *);
1711 +extern struct pseudo_dev *get_pseudo_file(int);
1712 +extern void delete_pseudo_files();
1713 diff -Nur squashfs4.0/squashfs-tools/read_fs.c squashfs4.0-lzma-snapshot/squashfs-tools/read_fs.c
1714 --- squashfs4.0/squashfs-tools/read_fs.c        2009-03-31 06:23:14.000000000 +0200
1715 +++ squashfs4.0-lzma-snapshot/squashfs-tools/read_fs.c  2009-10-20 06:03:38.000000000 +0200
1716 @@ -36,7 +36,6 @@
1717  #include <fcntl.h>
1718  #include <errno.h>
1719  #include <string.h>
1720 -#include <zlib.h>
1721  #include <sys/mman.h>
1722  
1723  #ifndef linux
1724 @@ -51,6 +50,7 @@
1725  #include "squashfs_swap.h"
1726  #include "read_fs.h"
1727  #include "global.h"
1728 +#include "compressor.h"
1729  
1730  #include <stdlib.h>
1731  
1732 @@ -66,7 +66,9 @@
1733                                                 fprintf(stderr, s, ## args); \
1734                                         } while(0)
1735  
1736 -int read_block(int fd, long long start, long long *next, unsigned char *block,
1737 +static struct compressor *comp;
1738 +
1739 +int read_block(int fd, long long start, long long *next, void *block,
1740         squashfs_super_block *sBlk)
1741  {
1742         unsigned short c_byte;
1743 @@ -77,32 +79,24 @@
1744  
1745         if(SQUASHFS_COMPRESSED(c_byte)) {
1746                 char buffer[SQUASHFS_METADATA_SIZE];
1747 -               int res;
1748 -               unsigned long bytes = SQUASHFS_METADATA_SIZE;
1749 +               int error, res;
1750  
1751                 c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
1752                 read_destination(fd, start + offset, c_byte, buffer);
1753  
1754 -               res = uncompress(block, &bytes, (const unsigned char *) buffer,
1755 -                       c_byte);
1756 -               if(res != Z_OK) {
1757 -                       if(res == Z_MEM_ERROR)
1758 -                               ERROR("zlib::uncompress failed, not enough "
1759 -                                       "memory\n");
1760 -                       else if(res == Z_BUF_ERROR)
1761 -                               ERROR("zlib::uncompress failed, not enough "
1762 -                                       "room in output buffer\n");
1763 -                       else
1764 -                               ERROR("zlib::uncompress failed, unknown error "
1765 -                                       "%d\n", res);
1766 +               res = comp->uncompress(block, buffer, c_byte,
1767 +                       SQUASHFS_METADATA_SIZE, &error);
1768 +               if(res == -1) {
1769 +                       ERROR("%s uncompress failed with error code %d\n",
1770 +                               comp->name, error);
1771                         return 0;
1772                 }
1773                 if(next)
1774                         *next = start + offset + c_byte;
1775 -               return bytes;
1776 +               return res;
1777         } else {
1778                 c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
1779 -               read_destination(fd, start + offset, c_byte, (char *) block);
1780 +               read_destination(fd, start + offset, c_byte, block);
1781                 if(next)
1782                         *next = start + offset + c_byte;
1783                 return c_byte;
1784 @@ -356,7 +350,7 @@
1785  }
1786  
1787  
1788 -int read_super(int fd, squashfs_super_block *sBlk, char *source)
1789 +struct compressor *read_super(int fd, squashfs_super_block *sBlk, char *source)
1790  {
1791         read_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block),
1792                 (char *) sBlk);
1793 @@ -388,8 +382,18 @@
1794                 goto failed_mount;
1795         }
1796  
1797 +       /* Check the compression type */
1798 +       comp = lookup_compressor_id(sBlk->compression);
1799 +       if(!comp->supported) {
1800 +               ERROR("Filesystem on %s uses %s compression, this is"
1801 +                       "unsupported by this version\n", source, comp->name);
1802 +               display_compressors("", "");
1803 +               goto failed_mount;
1804 +       }
1805 +
1806         printf("Found a valid %sSQUASHFS superblock on %s.\n",
1807                 SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source);
1808 +       printf("\tCompression used %s\n", comp->name);
1809         printf("\tInodes are %scompressed\n",
1810                 SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : "");
1811         printf("\tData is %scompressed\n",
1812 @@ -417,10 +421,10 @@
1813         TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start);
1814         printf("\n");
1815  
1816 -       return TRUE;
1817 +       return comp;
1818  
1819  failed_mount:
1820 -       return FALSE;
1821 +       return NULL;
1822  }
1823  
1824  
1825 @@ -514,12 +518,17 @@
1826         SQUASHFS_INSWAP_ID_BLOCKS(index, indexes);
1827  
1828         for(i = 0; i < indexes; i++) {
1829 -               int length;
1830 -               length = read_block(fd, index[i], NULL,
1831 +               int length = read_block(fd, index[i], NULL,
1832                         ((unsigned char *) id_table) +
1833                         (i * SQUASHFS_METADATA_SIZE), sBlk);
1834                 TRACE("Read id table block %d, from 0x%llx, length %d\n", i,
1835                         index[i], length);
1836 +               if(length == 0) {
1837 +                       ERROR("Failed to read id table block %d, from 0x%llx, "
1838 +                               "length %d\n", i, index[i], length);
1839 +                       free(id_table);
1840 +                       return NULL;
1841 +               }
1842         }
1843  
1844         SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids);
1845 @@ -563,6 +572,13 @@
1846                         (i * SQUASHFS_METADATA_SIZE), sBlk);
1847                 TRACE("Read fragment table block %d, from 0x%llx, length %d\n",
1848                         i, fragment_table_index[i], length);
1849 +               if(length == 0) {
1850 +                       ERROR("Failed to read fragment table block %d, from "
1851 +                               "0x%llx, length %d\n", i,
1852 +                               fragment_table_index[i], length);
1853 +                       free(*fragment_table);
1854 +                       return 0;
1855 +               }
1856         }
1857  
1858         for(i = 0; i < sBlk->fragments; i++)
1859 @@ -599,6 +615,13 @@
1860                         (i * SQUASHFS_METADATA_SIZE), sBlk);
1861                 TRACE("Read inode lookup table block %d, from 0x%llx, length "
1862                         "%d\n", i, index[i], length);
1863 +               if(length == 0) {
1864 +                       ERROR("Failed to read inode lookup table block %d, "
1865 +                               "from 0x%llx, length %d\n", i, index[i],
1866 +                               length);
1867 +                       free(*inode_lookup_table);
1868 +                       return 0;
1869 +               }
1870         }
1871  
1872         SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes);
1873 diff -Nur squashfs4.0/squashfs-tools/sort.c squashfs4.0-lzma-snapshot/squashfs-tools/sort.c
1874 --- squashfs4.0/squashfs-tools/sort.c   2009-03-31 06:25:53.000000000 +0200
1875 +++ squashfs4.0-lzma-snapshot/squashfs-tools/sort.c     2009-10-20 06:03:38.000000000 +0200
1876 @@ -198,7 +198,7 @@
1877         while(dir->current_count < dir->count) {
1878                 struct dir_ent *dir_ent = dir->list[dir->current_count++];
1879                 struct stat *buf = &dir_ent->inode->buf;
1880 -               if(dir_ent->data)
1881 +               if(dir_ent->inode->root_entry)
1882                         continue;
1883  
1884                 switch(buf->st_mode & S_IFMT) {
1885 @@ -254,6 +254,7 @@
1886                                 write_file(&inode, entry->dir, &duplicate_file);
1887                                 INFO("file %s, uncompressed size %lld bytes %s"
1888                                         "\n", entry->dir->pathname,
1889 +                                       (long long)
1890                                         entry->dir->inode->buf.st_size,
1891                                         duplicate_file ? "DUPLICATE" : "");
1892                                 entry->dir->inode->inode = inode;
1893 @@ -261,6 +262,7 @@
1894                         } else
1895                                 INFO("file %s, uncompressed size %lld bytes "
1896                                         "LINK\n", entry->dir->pathname,
1897 +                                       (long long)
1898                                         entry->dir->inode->buf.st_size);
1899                 }
1900  }
1901 diff -Nur squashfs4.0/squashfs-tools/sort.h squashfs4.0-lzma-snapshot/squashfs-tools/sort.h
1902 --- squashfs4.0/squashfs-tools/sort.h   2009-02-08 13:02:53.000000000 +0100
1903 +++ squashfs4.0-lzma-snapshot/squashfs-tools/sort.h     2009-10-20 06:03:38.000000000 +0200
1904 @@ -42,17 +42,19 @@
1905         struct inode_info       *inode;
1906         struct dir_info         *dir;
1907         struct dir_info         *our_dir;
1908 -       struct old_root_entry_info *data;
1909  };
1910  
1911  struct inode_info {
1912 -       unsigned int            nlink;
1913         struct stat             buf;
1914 +       struct inode_info       *next;
1915         squashfs_inode          inode;
1916 -       unsigned int            type;
1917         unsigned int            inode_number;
1918 +       unsigned int            nlink;
1919 +       int                     pseudo_id;
1920 +       char                    type;
1921         char                    read;
1922 -       struct inode_info       *next;
1923 +       char                    root_entry;
1924 +       char                    pseudo_file;
1925  };
1926  
1927  struct priority_entry {
1928 diff -Nur squashfs4.0/squashfs-tools/squashfs_compat.h squashfs4.0-lzma-snapshot/squashfs-tools/squashfs_compat.h
1929 --- squashfs4.0/squashfs-tools/squashfs_compat.h        2009-03-16 05:27:27.000000000 +0100
1930 +++ squashfs4.0-lzma-snapshot/squashfs-tools/squashfs_compat.h  2009-10-20 06:03:38.000000000 +0200
1931 @@ -777,11 +777,10 @@
1932  #endif
1933  
1934  #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
1935 -       int bits;\
1936 -       int b_pos = pos % 8;\
1937 -       unsigned long long val = 0;\
1938 -       unsigned char *s = (unsigned char *)p + (pos / 8);\
1939 -       unsigned char *d = ((unsigned char *) &val) + 7;\
1940 +       b_pos = pos % 8;\
1941 +       val = 0;\
1942 +       s = (unsigned char *)p + (pos / 8);\
1943 +       d = ((unsigned char *) &val) + 7;\
1944         for(bits = 0; bits < (tbits + b_pos); bits += 8) \
1945                 *d-- = *s++;\
1946         value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
1947 diff -Nur squashfs4.0/squashfs-tools/squashfs_fs.h squashfs4.0-lzma-snapshot/squashfs-tools/squashfs_fs.h
1948 --- squashfs4.0/squashfs-tools/squashfs_fs.h    2009-03-18 03:50:20.000000000 +0100
1949 +++ squashfs4.0-lzma-snapshot/squashfs-tools/squashfs_fs.h      2009-10-20 06:03:38.000000000 +0200
1950 @@ -229,6 +229,7 @@
1951  typedef long long              squashfs_inode_t;
1952  
1953  #define ZLIB_COMPRESSION       1
1954 +#define LZMA_COMPRESSION       2
1955  
1956  struct squashfs_super_block {
1957         unsigned int            s_magic;
1958 diff -Nur squashfs4.0/squashfs-tools/unsquash-3.c squashfs4.0-lzma-snapshot/squashfs-tools/unsquash-3.c
1959 --- squashfs4.0/squashfs-tools/unsquash-3.c     2009-03-31 06:35:10.000000000 +0200
1960 +++ squashfs4.0-lzma-snapshot/squashfs-tools/unsquash-3.c       2009-10-20 06:03:38.000000000 +0200
1961 @@ -36,7 +36,7 @@
1962                 sBlk.fragment_table_start);
1963  
1964         if(sBlk.fragments == 0)
1965 -               return;
1966 +               return TRUE;
1967  
1968         if((fragment_table = malloc(sBlk.fragments *
1969                         sizeof(squashfs_fragment_entry_3))) == NULL)
1970 diff -Nur squashfs4.0/squashfs-tools/unsquash-4.c squashfs4.0-lzma-snapshot/squashfs-tools/unsquash-4.c
1971 --- squashfs4.0/squashfs-tools/unsquash-4.c     2009-03-31 06:38:31.000000000 +0200
1972 +++ squashfs4.0-lzma-snapshot/squashfs-tools/unsquash-4.c       2009-10-20 06:03:38.000000000 +0200
1973 @@ -38,7 +38,7 @@
1974                 sBlk.fragment_table_start);
1975  
1976         if(sBlk.fragments == 0)
1977 -               return;
1978 +               return TRUE;
1979  
1980         if((fragment_table = malloc(sBlk.fragments *
1981                         sizeof(squashfs_fragment_entry))) == NULL)
1982 diff -Nur squashfs4.0/squashfs-tools/unsquashfs.c squashfs4.0-lzma-snapshot/squashfs-tools/unsquashfs.c
1983 --- squashfs4.0/squashfs-tools/unsquashfs.c     2009-04-05 23:23:06.000000000 +0200
1984 +++ squashfs4.0-lzma-snapshot/squashfs-tools/unsquashfs.c       2009-10-20 06:03:39.000000000 +0200
1985 @@ -25,6 +25,7 @@
1986  #include "squashfs_swap.h"
1987  #include "squashfs_compat.h"
1988  #include "read_fs.h"
1989 +#include "compressor.h"
1990  
1991  struct cache *fragment_cache, *data_cache;
1992  struct queue *to_reader, *to_deflate, *to_writer, *from_writer;
1993 @@ -36,6 +39,7 @@
1994  
1995  struct super_block sBlk;
1996  squashfs_operations s_ops;
1997 +struct compressor *comp;
1998  
1999  int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0,
2000         dev_count = 0, fifo_count = 0;
2001 @@ -590,31 +594,23 @@
2002                 offset = 3;
2003         if(SQUASHFS_COMPRESSED(c_byte)) {
2004                 char buffer[SQUASHFS_METADATA_SIZE];
2005 -               int res;
2006 -               unsigned long bytes = SQUASHFS_METADATA_SIZE;
2007 +               int error, res;
2008  
2009                 c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
2010                 if(read_bytes(start + offset, c_byte, buffer) == FALSE)
2011                         goto failed;
2012  
2013 -               res = uncompress((unsigned char *) block, &bytes,
2014 -                       (const unsigned char *) buffer, c_byte);
2015 +               res = comp->uncompress(block, buffer, c_byte,
2016 +                       SQUASHFS_METADATA_SIZE, &error);
2017  
2018 -               if(res != Z_OK) {
2019 -                       if(res == Z_MEM_ERROR)
2020 -                               ERROR("zlib::uncompress failed, not enough "
2021 -                                       "memory\n");
2022 -                       else if(res == Z_BUF_ERROR)
2023 -                               ERROR("zlib::uncompress failed, not enough "
2024 -                                       "room in output buffer\n");
2025 -                       else
2026 -                               ERROR("zlib::uncompress failed, unknown error "
2027 -                                       "%d\n", res);
2028 +               if(res == -1) {
2029 +                       ERROR("%s uncompress failed with error code %d\n",
2030 +                               comp->name, error);
2031                         goto failed;
2032                 }
2033                 if(next)
2034                         *next = start + offset + c_byte;
2035 -               return bytes;
2036 +               return res;
2037         } else {
2038                 c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
2039                 if(read_bytes(start + offset, c_byte, block) == FALSE)
2040 @@ -632,36 +628,26 @@
2041  
2042  int read_data_block(long long start, unsigned int size, char *block)
2043  {
2044 -       int res;
2045 -       unsigned long bytes = block_size;
2046 +       int error, res;
2047         int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size);
2048  
2049         TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start,
2050 -               SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte),
2051 -               SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" :
2052 +               c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" :
2053                 "uncompressed");
2054  
2055         if(SQUASHFS_COMPRESSED_BLOCK(size)) {
2056                 if(read_bytes(start, c_byte, data) == FALSE)
2057                         goto failed;
2058  
2059 -               res = uncompress((unsigned char *) block, &bytes,
2060 -                       (const unsigned char *) data, c_byte);
2061 +               res = comp->uncompress(block, data, c_byte, block_size, &error);
2062  
2063 -               if(res != Z_OK) {
2064 -                       if(res == Z_MEM_ERROR)
2065 -                               ERROR("zlib::uncompress failed, not enough "
2066 -                                       "memory\n");
2067 -                       else if(res == Z_BUF_ERROR)
2068 -                               ERROR("zlib::uncompress failed, not enough "
2069 -                                       "room in output buffer\n");
2070 -                       else
2071 -                               ERROR("zlib::uncompress failed, unknown error "
2072 -                                       "%d\n", res);
2073 +               if(res == -1) {
2074 +                       ERROR("%s uncompress failed with error code %d\n",
2075 +                               comp->name, error);
2076                         goto failed;
2077                 }
2078  
2079 -               return bytes;
2080 +               return res;
2081         } else {
2082                 if(read_bytes(start, c_byte, block) == FALSE)
2083                         goto failed;
2084 @@ -671,7 +657,7 @@
2085  
2086  failed:
2087         ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start,
2088 -               size);
2089 +               c_byte);
2090         return FALSE;
2091  }
2092  
2093 @@ -1383,6 +1369,11 @@
2094  #endif
2095         printf("Creation or last append time %s", mkfs_str ? mkfs_str :
2096                 "failed to get time\n");
2097 +       printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n",
2098 +               sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0));
2099 +       if(sBlk.s_major == 4)
2100 +               printf("Compression %s\n", comp->name);
2101 +       printf("Block size %d\n", sBlk.block_size);
2102         printf("Filesystem is %sexportable via NFS\n",
2103                 SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not ");
2104  
2105 @@ -1409,9 +1400,6 @@
2106                         SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not ");
2107         else
2108                 printf("Duplicates are removed\n");
2109 -       printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n",
2110 -               sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0));
2111 -       printf("Block size %d\n", sBlk.block_size);
2112         if(sBlk.s_major > 1)
2113                 printf("Number of fragments %d\n", sBlk.fragments);
2114         printf("Number of inodes %d\n", sBlk.inodes);
2115 @@ -1459,6 +1447,18 @@
2116                 s_ops.read_inode = read_inode_4;
2117                 s_ops.read_uids_guids = read_uids_guids_4;
2118                 memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4));
2119 +
2120 +               /*
2121 +                * Check the compression type
2122 +                */
2123 +               comp = lookup_compressor_id(sBlk.compression);
2124 +               if(!comp->supported) {
2125 +                       ERROR("Filesystem uses %s compression, this is "
2126 +                               "unsupported by this version\n", comp->name);
2127 +                       ERROR("Decompressors available:\n");
2128 +                       display_compressors("", "");
2129 +                       goto failed_mount;
2130 +               }
2131                 return TRUE;
2132         }
2133  
2134 @@ -1548,6 +1548,11 @@
2135                 goto failed_mount;
2136         }
2137  
2138 +       /*
2139 +        * 1.x, 2.x and 3.x filesystems use gzip compression.  Gzip is always
2140 +        * suppported.
2141 +        */
2142 +       comp = lookup_compressor("gzip");
2143         return TRUE;
2144  
2145  failed_mount:
2146 @@ -1707,32 +1712,24 @@
2147  
2148         while(1) {
2149                 struct cache_entry *entry = queue_get(to_deflate);
2150 -               int res;
2151 -               unsigned long bytes = block_size;
2152 +               int error, res;
2153  
2154 -               res = uncompress((unsigned char *) tmp, &bytes,
2155 -                       (const unsigned char *) entry->data,
2156 -                       SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size));
2157 -
2158 -               if(res != Z_OK) {
2159 -                       if(res == Z_MEM_ERROR)
2160 -                               ERROR("zlib::uncompress failed, not enough"
2161 -                                       "memory\n");
2162 -                       else if(res == Z_BUF_ERROR)
2163 -                               ERROR("zlib::uncompress failed, not enough "
2164 -                                       "room in output buffer\n");
2165 -                       else
2166 -                               ERROR("zlib::uncompress failed, unknown error "
2167 -                                       "%d\n", res);
2168 -               } else
2169 -                       memcpy(entry->data, tmp, bytes);
2170 +               res = comp->uncompress(tmp, entry->data,
2171 +                       SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size,
2172 +                       &error);
2173 +
2174 +               if(res == -1)
2175 +                       ERROR("%s uncompress failed with error code %d\n",
2176 +                               comp->name, error);
2177 +               else
2178 +                       memcpy(entry->data, tmp, res);
2179  
2180                 /*
2181                  * block has been either successfully decompressed, or an error
2182                  * occurred, clear pending flag, set error appropriately and
2183                  * wake up any threads waiting on this block
2184                  */ 
2185 -               cache_block_ready(entry, res != Z_OK);
2186 +               cache_block_ready(entry, res == -1);
2187         }
2188  }
2189  
2190 @@ -1913,7 +1910,7 @@
2191  
2192  
2193  #define VERSION() \
2194 -       printf("unsquashfs version 4.0 (2009/04/05)\n");\
2195 +       printf("unsquashfs version 4.1-CVS (2009/08/30)\n");\
2196         printf("copyright (C) 2009 Phillip Lougher <phillip@lougher.demon.co.uk>"\
2197                 "\n\n");\
2198         printf("This program is free software; you can redistribute it and/or\n");\
2199 @@ -1938,7 +1935,6 @@
2200         int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT;
2201         int data_buffer_size = DATA_BUFFER_DEFAULT;
2202         char *b;
2203 -       struct winsize winsize;
2204  
2205         pthread_mutex_init(&screen_mutex, NULL);
2206         root_process = geteuid() == 0;
2207 @@ -2087,6 +2083,8 @@
2208                                 "regular expressions\n");
2209                         ERROR("\t\t\t\trather than use the default shell "
2210                                 "wildcard\n\t\t\t\texpansion (globbing)\n");
2211 +                       ERROR("\nDecompressors available:\n");
2212 +                       display_compressors("", "");
2213                 }
2214                 exit(1);
2215         }
2216 diff -Nur squashfs4.0/squashfs-tools/unsquashfs.h squashfs4.0-lzma-snapshot/squashfs-tools/unsquashfs.h
2217 --- squashfs4.0/squashfs-tools/unsquashfs.h     2009-03-29 04:29:02.000000000 +0200
2218 +++ squashfs4.0-lzma-snapshot/squashfs-tools/unsquashfs.h       2009-10-20 06:03:39.000000000 +0200
2219 @@ -31,7 +31,6 @@
2220  #include <fcntl.h>
2221  #include <errno.h>
2222  #include <string.h>
2223 -#include <zlib.h>
2224  #include <sys/mman.h>
2225  #include <utime.h>
2226  #include <pwd.h>