Root/tools/squashfs4/patches/110-lzma.patch

1diff -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+}
83diff -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 *);
120diff -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+}
204diff -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+}
301diff -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)
397diff -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" :
1356diff -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 
1691diff -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();
1713diff -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);
1873diff -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 }
1901diff -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 {
1928diff -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)*/;\
1947diff -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;
1958diff -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)
1970diff -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)
1982diff -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     }
2216diff -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>
2227

Archive Download this file



interactive