diff options
author | Gluzskiy Alexandr <sss123next@list.ru> | 2009-12-20 13:07:39 +0200 |
---|---|---|
committer | Gluzskiy Alexandr <sss123next@list.ru> | 2009-12-20 13:07:39 +0200 |
commit | 79d0bf8461392b78a93cc328c49ed2ae86c7ef42 (patch) | |
tree | c210d37c2ff4ec3ef141a130c8b9c74b8ef8e40b /sys-fs | |
parent | 7bbc767351c3050014a09b7d08cfd0d47e6c81c2 (diff) |
modified: ../dev-python/genshi/files/version_info.patch
modified: ../games-sports/xmoto/xmoto-9999.ebuild
new file: squashfs-tools/squashfs-tools-4.0-lzma.patch
new file: squashfs-tools/squashfs-tools-4.0-r1.ebuild
Diffstat (limited to 'sys-fs')
-rw-r--r-- | sys-fs/squashfs-tools/squashfs-tools-4.0-lzma.patch | 2210 | ||||
-rw-r--r-- | sys-fs/squashfs-tools/squashfs-tools-4.0-r1.ebuild | 49 |
2 files changed, 2259 insertions, 0 deletions
diff --git a/sys-fs/squashfs-tools/squashfs-tools-4.0-lzma.patch b/sys-fs/squashfs-tools/squashfs-tools-4.0-lzma.patch new file mode 100644 index 0000000..9a7c78c --- /dev/null +++ b/sys-fs/squashfs-tools/squashfs-tools-4.0-lzma.patch @@ -0,0 +1,2210 @@ +diff -Naurp squashfs-tools/compressor.c squashfs-tools-lzma/compressor.c +--- squashfs-tools/compressor.c 1970-01-01 00:00:00.000000000 +0000 ++++ squashfs-tools-lzma/compressor.c 2009-10-20 04:03:37.000000000 +0000 +@@ -0,0 +1,78 @@ ++/* ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2, ++ * or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * compressor.c ++ */ ++ ++#include <stdio.h> ++#include <string.h> ++#include "compressor.h" ++#include "squashfs_fs.h" ++ ++extern int gzip_compress(void **, char *, char *, int, int, int *); ++extern int gzip_uncompress(char *, char *, int, int, int *); ++extern int lzma_compress(void **, char *, char *, int, int, int *); ++extern int lzma_uncompress(char *, char *, int, int, int *); ++ ++struct compressor compressor[] = { ++ { gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 }, ++#ifdef LZMA_SUPPORT ++ { lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 }, ++#else ++ { NULL, NULL, LZMA_COMPRESSION, "lzma", 0 }, ++#endif ++ { NULL, NULL , 0, "unknown", 0} ++}; ++ ++ ++struct compressor *lookup_compressor(char *name) ++{ ++ int i; ++ ++ for(i = 0; compressor[i].id; i++) ++ if(strcmp(compressor[i].name, name) == 0) ++ break; ++ ++ return &compressor[i]; ++} ++ ++ ++struct compressor *lookup_compressor_id(int id) ++{ ++ int i; ++ ++ for(i = 0; compressor[i].id; i++) ++ if(id == compressor[i].id) ++ break; ++ ++ return &compressor[i]; ++} ++ ++ ++void display_compressors(char *indent, char *def_comp) ++{ ++ int i; ++ ++ for(i = 0; compressor[i].id; i++) ++ if(compressor[i].supported) ++ fprintf(stderr, "%s\t%s%s\n", indent, ++ compressor[i].name, ++ strcmp(compressor[i].name, def_comp) == 0 ? ++ " (default)" : ""); ++} +diff -Naurp squashfs-tools/compressor.h squashfs-tools-lzma/compressor.h +--- squashfs-tools/compressor.h 1970-01-01 00:00:00.000000000 +0000 ++++ squashfs-tools-lzma/compressor.h 2009-10-20 04:03:37.000000000 +0000 +@@ -0,0 +1,33 @@ ++/* ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2, ++ * or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * compressor.h ++ */ ++ ++struct compressor { ++ int (*compress)(void **, char *, char *, int, int, int *); ++ int (*uncompress)(char *, char *, int, int, int *); ++ int id; ++ char *name; ++ int supported; ++}; ++ ++extern struct compressor *lookup_compressor(char *); ++extern struct compressor *lookup_compressor_id(int); ++extern void display_compressors(char *, char *); +diff -Naurp squashfs-tools/gzip_wrapper.c squashfs-tools-lzma/gzip_wrapper.c +--- squashfs-tools/gzip_wrapper.c 1970-01-01 00:00:00.000000000 +0000 ++++ squashfs-tools-lzma/gzip_wrapper.c 2009-10-20 04:03:37.000000000 +0000 +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2, ++ * or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * gzip_wrapper.c ++ */ ++ ++#include <stdlib.h> ++#include <zlib.h> ++ ++int gzip_compress(void **strm, char *d, char *s, int size, int block_size, ++ int *error) ++{ ++ int res = 0; ++ z_stream *stream = *strm; ++ ++ if(stream == NULL) { ++ if((stream = *strm = malloc(sizeof(z_stream))) == NULL) ++ goto failed; ++ ++ stream->zalloc = Z_NULL; ++ stream->zfree = Z_NULL; ++ stream->opaque = 0; ++ ++ if((res = deflateInit(stream, 9)) != Z_OK) ++ goto failed; ++ } else if((res = deflateReset(stream)) != Z_OK) ++ goto failed; ++ ++ stream->next_in = (unsigned char *) s; ++ stream->avail_in = size; ++ stream->next_out = (unsigned char *) d; ++ stream->avail_out = block_size; ++ ++ res = deflate(stream, Z_FINISH); ++ if(res == Z_STREAM_END) ++ /* ++ * Success, return the compressed size. ++ */ ++ return (int) stream->total_out; ++ if(res == Z_OK) ++ /* ++ * Output buffer overflow. Return out of buffer space ++ */ ++ return 0; ++failed: ++ /* ++ * All other errors return failure, with the compressor ++ * specific error code in *error ++ */ ++ *error = res; ++ return -1; ++} ++ ++ ++int gzip_uncompress(char *d, char *s, int size, int block_size, int *error) ++{ ++ int res; ++ unsigned long bytes = block_size; ++ ++ res = uncompress((unsigned char *) d, &bytes, ++ (const unsigned char *) s, size); ++ ++ *error = res; ++ return res == Z_OK ? (int) bytes : -1; ++} +diff -Naurp squashfs-tools/lzma_wrapper.c squashfs-tools-lzma/lzma_wrapper.c +--- squashfs-tools/lzma_wrapper.c 1970-01-01 00:00:00.000000000 +0000 ++++ squashfs-tools-lzma/lzma_wrapper.c 2009-10-14 03:32:57.000000000 +0000 +@@ -0,0 +1,93 @@ ++/* ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher <phillip@lougher.demon.co.uk> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2, ++ * or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * lzma_wrapper.c ++ */ ++ ++#include <LzmaLib.h> ++ ++#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) ++ ++int lzma_compress(void **strm, char *dest, char *src, int size,int block_size, ++ int *error) ++{ ++ unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; ++ size_t props_size = LZMA_PROPS_SIZE, ++ outlen = block_size - LZMA_HEADER_SIZE; ++ int res; ++ ++ res = LzmaCompress(d + LZMA_HEADER_SIZE, &outlen, s, size, d, ++ &props_size, 5, block_size, 3, 0, 2, 32, 1); ++ ++ if(res == SZ_ERROR_OUTPUT_EOF) { ++ /* ++ * Output buffer overflow. Return out of buffer space error ++ */ ++ return 0; ++ } ++ ++ if(res != SZ_OK) { ++ /* ++ * All other errors return failure, with the compressor ++ * specific error code in *error ++ */ ++ *error = res; ++ return -1; ++ } ++ ++ /* ++ * Fill in the 8 byte little endian uncompressed size field in the ++ * LZMA header. 8 bytes is excessively large for squashfs but ++ * this is the standard LZMA header and which is expected by the kernel ++ * code ++ */ ++ d[LZMA_PROPS_SIZE] = size & 255; ++ d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255; ++ d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255; ++ d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255; ++ d[LZMA_PROPS_SIZE + 4] = 0; ++ d[LZMA_PROPS_SIZE + 5] = 0; ++ d[LZMA_PROPS_SIZE + 6] = 0; ++ d[LZMA_PROPS_SIZE + 7] = 0; ++ ++ /* ++ * Success, return the compressed size. Outlen returned by the LZMA ++ * compressor does not include the LZMA header space ++ */ ++ return outlen + LZMA_HEADER_SIZE; ++} ++ ++ ++int lzma_uncompress(char *dest, char *src, int size, int block_size, ++ int *error) ++{ ++ unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; ++ size_t outlen, inlen = size - LZMA_HEADER_SIZE; ++ int res; ++ ++ outlen = s[LZMA_PROPS_SIZE] | ++ (s[LZMA_PROPS_SIZE + 1] << 8) | ++ (s[LZMA_PROPS_SIZE + 2] << 16) | ++ (s[LZMA_PROPS_SIZE + 3] << 24); ++ ++ res = LzmaUncompress(d, &outlen, s + LZMA_HEADER_SIZE, &inlen, ++ s, LZMA_PROPS_SIZE); ++ ++ *error = res; ++ return res == SZ_OK ? outlen : -1; ++} +diff -Naurp squashfs-tools/Makefile squashfs-tools-lzma/Makefile +--- squashfs-tools/Makefile 2009-04-05 02:03:36.000000000 +0000 ++++ squashfs-tools-lzma/Makefile 2009-10-22 04:17:12.000000000 +0000 +@@ -1,40 +1,76 @@ ++# ++# Building LZMA support ++# Download LZMA sdk (4.65 used in development, other versions may work), ++# set LZMA_DIR to unpacked source, and uncomment next line ++LZMA_SUPPORT = 1 ++LZMA_DIR = ../../ ++ ++#Compression default. ++COMP_DEFAULT = gzip ++ ++INCLUDEDIR = -I. + INSTALL_DIR = /usr/local/bin + +-INCLUDEDIR = . ++MKSQUASHFS_OBJS = mksquashfs.o read_fs.o sort.o swap.o pseudo.o compressor.o \ ++ gzip_wrapper.o ++ ++UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \ ++ unsquash-4.o swap.o compressor.o gzip_wrapper.o + +-CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 ++CFLAGS := $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ ++ -D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" -O2 -Wall + ++ifdef LZMA_SUPPORT ++LZMA_OBJS = $(LZMA_DIR)/C/Alloc.o $(LZMA_DIR)/C/LzFind.o \ ++ $(LZMA_DIR)/C/LzmaDec.o $(LZMA_DIR)/C/LzmaEnc.o $(LZMA_DIR)/C/LzmaLib.o ++INCLUDEDIR += -I$(LZMA_DIR)/C ++CFLAGS += -DLZMA_SUPPORT -I../../C ++MKSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) ++UNSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) ++endif ++ ++.PHONY: all + all: mksquashfs unsquashfs + +-mksquashfs: mksquashfs.o read_fs.o sort.o swap.o pseudo.o +- $(CC) mksquashfs.o read_fs.o sort.o swap.o pseudo.o -lz -lpthread -lm -o $@ ++mksquashfs: $(MKSQUASHFS_OBJS) ++ $(CC) $(MKSQUASHFS_OBJS) -lz -lpthread -lm -o $@ ++ ++mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ ++ squashfs_swap.h + +-mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h squashfs_swap.h Makefile ++read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h + +-read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h Makefile ++sort.o: sort.c squashfs_fs.h global.h sort.h + +-sort.o: sort.c squashfs_fs.h global.h sort.h Makefile ++swap.o: swap.c + +-swap.o: swap.c Makefile ++pseudo.o: pseudo.c pseudo.h + +-pseudo.o: pseudo.c pseudo.h Makefile ++compressor.o: compressor.c compressor.h + +-unsquashfs: unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o +- $(CC) unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o -lz -lpthread -lm -o $@ ++unsquashfs: $(UNSQUASHFS_OBJS) ++ $(CC) $(UNSQUASHFS_OBJS) -lz -lpthread -lm -o $@ + +-unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h squashfs_compat.h global.h Makefile ++unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h \ ++ squashfs_compat.h global.h + +-unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h global.h Makefile ++unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h \ ++ global.h + +-unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h squashfs_compat.h global.h Makefile ++unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h \ ++ squashfs_compat.h global.h + +-unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h global.h Makefile ++unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h \ ++ global.h + +-unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h global.h Makefile ++unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h \ ++ global.h + ++.PHONY: clean + clean: + -rm -f *.o mksquashfs unsquashfs + ++.PHONY: install + install: mksquashfs unsquashfs + mkdir -p $(INSTALL_DIR) + cp mksquashfs $(INSTALL_DIR) +diff -Naurp squashfs-tools/mksquashfs.c squashfs-tools-lzma/mksquashfs.c +--- squashfs-tools/mksquashfs.c 2009-04-05 21:22:48.000000000 +0000 ++++ squashfs-tools-lzma/mksquashfs.c 2009-10-20 04:03:38.000000000 +0000 +@@ -36,7 +36,6 @@ + #include <errno.h> + #include <dirent.h> + #include <string.h> +-#include <zlib.h> + #include <stdlib.h> + #include <signal.h> + #include <setjmp.h> +@@ -47,6 +46,7 @@ + #include <math.h> + #include <regex.h> + #include <fnmatch.h> ++#include <sys/wait.h> + + #ifndef linux + #define __BYTE_ORDER BYTE_ORDER +@@ -64,6 +64,7 @@ + #include "global.h" + #include "sort.h" + #include "pseudo.h" ++#include "compressor.h" + + #ifdef SQUASHFS_TRACE + #define TRACE(s, args...) do { \ +@@ -245,10 +246,8 @@ char **source_path; + /* list of root directory entries read from original filesystem */ + int old_root_entries = 0; + struct old_root_entry_info { +- char name[SQUASHFS_NAME_LEN + 1]; +- squashfs_inode inode; +- int type; +- int inode_number; ++ char *name; ++ struct inode_info inode; + }; + struct old_root_entry_info *old_root_entry; + +@@ -371,10 +370,15 @@ int writer_buffer_size; + int reader_buffer_size; + int fragment_buffer_size; + ++/* compression operations structure */ ++static struct compressor *comp; ++char *comp_name = COMP_DEFAULT; ++ + char *read_from_disk(long long start, unsigned int avail_bytes); + void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, + int type); +-extern int read_super(int fd, squashfs_super_block *sBlk, char *source); ++extern struct compressor *read_super(int fd, squashfs_super_block *sBlk, ++ char *source); + extern long long read_filesystem(char *root_name, int fd, + squashfs_super_block *sBlk, char **cinode_table, char **data_cache, + char **cdirectory_table, char **directory_data_cache, +@@ -831,83 +835,32 @@ void sigalrm_handler() + } + + +-unsigned int mangle2(z_stream **strm, char *d, char *s, int size, ++int mangle2(void **strm, char *d, char *s, int size, + int block_size, int uncompressed, int data_block) + { +- unsigned long c_byte; +- unsigned int res; +- z_stream *stream = *strm; +- +- if(uncompressed) +- goto notcompressed; +- +- if(stream == NULL) { +- if((stream = *strm = malloc(sizeof(z_stream))) == NULL) +- BAD_ERROR("mangle::compress failed, not enough " +- "memory\n"); +- +- stream->zalloc = Z_NULL; +- stream->zfree = Z_NULL; +- stream->opaque = 0; +- +- if((res = deflateInit(stream, 9)) != Z_OK) { +- if(res == Z_MEM_ERROR) +- BAD_ERROR("zlib::compress failed, not enough " +- "memory\n"); +- else if(res == Z_STREAM_ERROR) +- BAD_ERROR("zlib::compress failed, not a valid " +- "compression level\n"); +- else if(res == Z_VERSION_ERROR) +- BAD_ERROR("zlib::compress failed, incorrect " +- "zlib version\n"); +- else +- BAD_ERROR("zlib::compress failed, unknown " +- "error %d\n", res); +- } +- } else if((res = deflateReset(stream)) != Z_OK) { +- if(res == Z_STREAM_ERROR) +- BAD_ERROR("zlib::compress failed, stream state " +- "inconsistent\n"); +- else +- BAD_ERROR("zlib::compress failed, unknown error %d\n", +- res); +- } ++ int error, c_byte = 0; + +- stream->next_in = (unsigned char *) s; +- stream->avail_in = size; +- stream->next_out = (unsigned char *) d; +- stream->avail_out = block_size; +- +- res = deflate(stream, Z_FINISH); +- if(res != Z_STREAM_END && res != Z_OK) { +- if(res == Z_STREAM_ERROR) +- BAD_ERROR("zlib::compress failed, stream state " +- "inconsistent\n"); +- else if(res == Z_BUF_ERROR) +- BAD_ERROR("zlib::compress failed, no progress possible" +- "\n"); +- else +- BAD_ERROR("zlib::compress failed, unknown error %d\n", +- res); ++ if(!uncompressed) { ++ c_byte = comp->compress(strm, d, s, size, block_size, &error); ++ if(c_byte == -1) ++ BAD_ERROR("mangle2:: %s compress failed with error " ++ "code %d\n", comp->name, error); + } + +- c_byte = stream->total_out; +- +- if(res != Z_STREAM_END || c_byte >= size) { +-notcompressed: ++ if(c_byte == 0 || c_byte >= size) { + memcpy(d, s, size); + return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : + SQUASHFS_COMPRESSED_BIT); + } + +- return (unsigned int) c_byte; ++ return c_byte; + } + + +-unsigned int mangle(char *d, char *s, int size, int block_size, ++int mangle(char *d, char *s, int size, int block_size, + int uncompressed, int data_block) + { +- static z_stream *stream = NULL; ++ static void *stream = NULL; + + return mangle2(&stream, d, s, size, block_size, uncompressed, + data_block); +@@ -1660,8 +1613,7 @@ struct file_buffer *get_fragment(struct + pthread_mutex_unlock(&fragment_mutex); + + if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { +- int res; +- unsigned long bytes = block_size; ++ int error, res; + char *data; + + if(compressed_buffer) +@@ -1669,19 +1621,11 @@ struct file_buffer *get_fragment(struct + else + data = read_from_disk(start_block, size); + +- res = uncompress((unsigned char *) buffer->data, &bytes, +- (const unsigned char *) data, size); +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) +- BAD_ERROR("zlib::uncompress failed, not enough " +- "memory\n"); +- else if(res == Z_BUF_ERROR) +- BAD_ERROR("zlib::uncompress failed, not enough " +- "room in output buffer\n"); +- else +- BAD_ERROR("zlib::uncompress failed," +- " unknown error %d\n", res); +- } ++ res = comp->uncompress(buffer->data, data, size, block_size, ++ &error); ++ if(res == -1) ++ BAD_ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); + } else if(compressed_buffer) + memcpy(buffer->data, compressed_buffer->data, size); + else +@@ -1733,9 +1677,7 @@ void unlock_fragments() + entry->buffer->block = bytes; + bytes += compressed_size; + fragments_outstanding --; +- pthread_mutex_unlock(&fragment_mutex); + queue_put(to_writer, entry->buffer); +- pthread_mutex_lock(&fragment_mutex); + TRACE("fragment_locked writing fragment %d, compressed size %d" + "\n", entry->fragment, compressed_size); + free(entry); +@@ -1758,6 +1700,8 @@ int add_pending_fragment(struct file_buf + pthread_mutex_lock(&fragment_mutex); + insert_fragment_list(&frag_locked_list, entry); + pthread_mutex_unlock(&fragment_mutex); ++ ++ return TRUE; + } + + +@@ -1824,7 +1768,9 @@ long long generic_write_table(int length + unsigned short c_byte; + char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; + ++#ifdef SQUASHFS_TRACE + long long obytes = bytes; ++#endif + + for(i = 0; i < meta_blocks; i++) { + int avail_bytes = length > SQUASHFS_METADATA_SIZE ? +@@ -2170,11 +2116,85 @@ struct file_info *duplicate(long long fi + } + + ++static int seq = 0; ++void reader_read_process(struct dir_ent *dir_ent) ++{ ++ struct file_buffer *prev_buffer = NULL, *file_buffer; ++ int status, res, byte, count = 0; ++ int file = get_pseudo_file(dir_ent->inode->pseudo_id)->fd; ++ int child = get_pseudo_file(dir_ent->inode->pseudo_id)->child; ++ long long bytes = 0; ++ ++ while(1) { ++ file_buffer = cache_get(reader_buffer, 0, 0); ++ file_buffer->sequence = seq ++; ++ ++ byte = read_bytes(file, file_buffer->data, block_size); ++ if(byte == -1) ++ goto read_err; ++ ++ file_buffer->size = byte; ++ file_buffer->file_size = -1; ++ file_buffer->block = count ++; ++ file_buffer->error = FALSE; ++ file_buffer->fragment = FALSE; ++ bytes += byte; ++ ++ if(byte == 0) ++ break; ++ ++ /* ++ * Update estimated_uncompressed block count. This is done ++ * on every block rather than waiting for all blocks to be ++ * read incase write_file_process() is running in parallel ++ * with this. Otherwise cur uncompressed block count may ++ * get ahead of the total uncompressed block count. ++ */ ++ estimated_uncompressed ++; ++ ++ if(prev_buffer) ++ queue_put(from_reader, prev_buffer); ++ prev_buffer = file_buffer; ++ } ++ ++ /* ++ * Update inode file size now that the size of the dynamic pseudo file ++ * is known. This is needed for the -info option. ++ */ ++ dir_ent->inode->buf.st_size = bytes; ++ ++ res = waitpid(child, &status, 0); ++ if(res == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) ++ goto read_err; ++ ++ if(prev_buffer == NULL) ++ prev_buffer = file_buffer; ++ else { ++ cache_block_put(file_buffer); ++ seq --; ++ } ++ prev_buffer->file_size = bytes; ++ prev_buffer->fragment = !no_fragments && ++ (count == 2 || always_use_fragments) && (byte < block_size); ++ queue_put(from_reader, prev_buffer); ++ ++ return; ++ ++read_err: ++ if(prev_buffer) { ++ cache_block_put(file_buffer); ++ seq --; ++ file_buffer = prev_buffer; ++ } ++ file_buffer->error = TRUE; ++ queue_put(from_deflate, file_buffer); ++} ++ ++ + void reader_read_file(struct dir_ent *dir_ent) + { + struct stat *buf = &dir_ent->inode->buf, buf2; + struct file_buffer *file_buffer; +- static int index = 0; + int blocks, byte, count, expected, file, frag_block; + long long bytes, read_size; + +@@ -2202,7 +2222,7 @@ again: + if(file_buffer) + queue_put(from_reader, file_buffer); + file_buffer = cache_get(reader_buffer, 0, 0); +- file_buffer->sequence = index ++; ++ file_buffer->sequence = seq ++; + + byte = file_buffer->size = read_bytes(file, file_buffer->data, + block_size); +@@ -2238,7 +2258,7 @@ again: + + read_err: + file_buffer = cache_get(reader_buffer, 0, 0); +- file_buffer->sequence = index ++; ++ file_buffer->sequence = seq ++; + read_err2: + file_buffer->error = TRUE; + queue_put(from_deflate, file_buffer); +@@ -2262,9 +2282,14 @@ void reader_scan(struct dir_info *dir) { + for(i = 0; i < dir->count; i++) { + struct dir_ent *dir_ent = dir->list[i]; + struct stat *buf = &dir_ent->inode->buf; +- if(dir_ent->data) ++ if(dir_ent->inode->root_entry) + continue; + ++ if(dir_ent->inode->pseudo_file) { ++ reader_read_process(dir_ent); ++ continue; ++ } ++ + switch(buf->st_mode & S_IFMT) { + case S_IFREG: + reader_read_file(dir_ent); +@@ -2365,7 +2390,7 @@ int all_zero(struct file_buffer *file_bu + + void *deflator(void *arg) + { +- z_stream *stream = NULL; ++ void *stream = NULL; + int oldstate; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); +@@ -2402,7 +2427,7 @@ void *deflator(void *arg) + + void *frag_deflator(void *arg) + { +- z_stream *stream = NULL; ++ void *stream = NULL; + int oldstate; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); +@@ -2426,8 +2451,8 @@ void *frag_deflator(void *arg) + write_buffer->block = bytes; + bytes += compressed_size; + fragments_outstanding --; +- pthread_mutex_unlock(&fragment_mutex); + queue_put(to_writer, write_buffer); ++ pthread_mutex_unlock(&fragment_mutex); + TRACE("Writing fragment %lld, uncompressed size %d, " + "compressed size %d\n", file_buffer->block, + file_buffer->size, compressed_size); +@@ -2674,6 +2699,98 @@ void write_file_frag(squashfs_inode *ino + } + + ++int write_file_process(squashfs_inode *inode, struct dir_ent *dir_ent, ++ struct file_buffer *read_buffer, int *duplicate_file) ++{ ++ long long read_size, file_bytes, start; ++ struct fragment *fragment; ++ unsigned int *block_list = NULL; ++ int block = 0, status; ++ long long sparse = 0; ++ struct file_buffer *fragment_buffer = NULL; ++ ++ *duplicate_file = FALSE; ++ ++ lock_fragments(); ++ ++ file_bytes = 0; ++ start = bytes; ++ while (1) { ++ read_size = read_buffer->file_size; ++ if(read_buffer->fragment && read_buffer->c_byte) ++ fragment_buffer = read_buffer; ++ else { ++ block_list = realloc(block_list, (block + 1) * ++ sizeof(unsigned int)); ++ if(block_list == NULL) ++ BAD_ERROR("Out of memory allocating block_list" ++ "\n"); ++ block_list[block ++] = read_buffer->c_byte; ++ if(read_buffer->c_byte) { ++ read_buffer->block = bytes; ++ bytes += read_buffer->size; ++ cache_rehash(read_buffer, read_buffer->block); ++ file_bytes += read_buffer->size; ++ queue_put(to_writer, read_buffer); ++ } else { ++ sparse += read_buffer->size; ++ cache_block_put(read_buffer); ++ } ++ } ++ inc_progress_bar(); ++ ++ if(read_size != -1) ++ break; ++ ++ read_buffer = get_file_buffer(from_deflate); ++ if(read_buffer->error) ++ goto read_err; ++ } ++ ++ unlock_fragments(); ++ fragment = get_and_fill_fragment(fragment_buffer); ++ cache_block_put(fragment_buffer); ++ ++ if(duplicate_checking) ++ add_non_dup(read_size, file_bytes, block_list, start, fragment, ++ 0, 0, FALSE); ++ file_count ++; ++ total_bytes += read_size; ++ ++ if(read_size < (1LL << 32) && start < (1LL << 32) && sparse == 0) ++ create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, ++ start, block, block_list, fragment, NULL, 0); ++ else ++ create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, ++ start, block, block_list, fragment, NULL, sparse); ++ ++ if(duplicate_checking == FALSE) ++ free(block_list); ++ ++ return 0; ++ ++read_err: ++ cur_uncompressed -= block; ++ status = read_buffer->error; ++ bytes = start; ++ if(!block_device) { ++ int res; ++ ++ queue_put(to_writer, NULL); ++ if(queue_get(from_writer) != 0) ++ EXIT_MKSQUASHFS(); ++ res = ftruncate(fd, bytes); ++ if(res != 0) ++ BAD_ERROR("Failed to truncate dest file because %s\n", ++ strerror(errno)); ++ } ++ unlock_fragments(); ++ free(block_list); ++ cache_block_put(read_buffer); ++ return status; ++} ++ ++ + int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, + long long read_size, struct file_buffer *read_buffer, + int *duplicate_file) +@@ -2941,7 +3058,10 @@ again: + + read_size = read_buffer->file_size; + +- if(read_size == 0) { ++ if(read_size == -1) ++ status = write_file_process(inode, dir_ent, read_buffer, ++ duplicate_file); ++ else if(read_size == 0) { + write_file_empty(inode, dir_ent, duplicate_file); + cache_block_put(read_buffer); + } else if(read_buffer->fragment && read_buffer->c_byte) +@@ -3036,6 +3156,8 @@ struct inode_info *lookup_inode(struct s + + memcpy(&inode->buf, buf, sizeof(struct stat)); + inode->read = FALSE; ++ inode->root_entry = FALSE; ++ inode->pseudo_file = FALSE; + inode->inode = SQUASHFS_INVALID_BLK; + inode->nlink = 1; + +@@ -3056,7 +3178,7 @@ struct inode_info *lookup_inode(struct s + + + inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, +- struct inode_info *inode_info, void *data, struct dir_info *dir) ++ struct inode_info *inode_info, struct dir_info *dir) + { + if((dir->count % DIR_ENTRIES) == 0) { + dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * +@@ -3075,8 +3197,7 @@ inline void add_dir_entry(char *name, ch + NULL; + dir->list[dir->count]->inode = inode_info; + dir->list[dir->count]->dir = sub_dir; +- dir->list[dir->count]->our_dir = dir; +- dir->list[dir->count++]->data = data; ++ dir->list[dir->count++]->our_dir = dir; + dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); + } + +@@ -3128,10 +3249,10 @@ int scan1_encomp_readdir(char *pathname, + + if(dir->count < old_root_entries) + for(i = 0; i < old_root_entries; i++) { +- if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) ++ if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) + dir->directory_count ++; +- add_dir_entry(old_root_entry[i].name, "", NULL, NULL, +- &old_root_entry[i], dir); ++ add_dir_entry(old_root_entry[i].name, "", NULL, ++ &old_root_entry[i].inode, dir); + } + + while(index < source) { +@@ -3167,10 +3288,10 @@ int scan1_single_readdir(char *pathname, + + if(dir->count < old_root_entries) + for(i = 0; i < old_root_entries; i++) { +- if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) ++ if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) + dir->directory_count ++; +- add_dir_entry(old_root_entry[i].name, "", NULL, NULL, +- &old_root_entry[i], dir); ++ add_dir_entry(old_root_entry[i].name, "", NULL, ++ &old_root_entry[i].inode, dir); + } + + if((d_name = readdir(dir->linuxdir)) != NULL) { +@@ -3215,7 +3336,7 @@ struct dir_ent *scan2_readdir(struct dir + int current_count; + + while((current_count = dir_info->current_count++) < dir_info->count) +- if(dir_info->list[current_count]->data) ++ if(dir_info->list[current_count]->inode->root_entry) + continue; + else + return dir_info->list[current_count]; +@@ -3240,11 +3361,11 @@ struct dir_ent *scan3_readdir(struct dir + int current_count; + + while((current_count = dir_info->current_count++) < dir_info->count) +- if(dir_info->list[current_count]->data) +- add_dir(dir_info->list[current_count]->data->inode, +- dir_info->list[current_count]->data->inode_number, ++ if(dir_info->list[current_count]->inode->root_entry) ++ add_dir(dir_info->list[current_count]->inode->inode, ++ dir_info->list[current_count]->inode->inode_number, + dir_info->list[current_count]->name, +- dir_info->list[current_count]->data->type, dir); ++ dir_info->list[current_count]->inode->type, dir); + else + return dir_info->list[current_count]; + return NULL; +@@ -3313,7 +3434,6 @@ void dir_scan(squashfs_inode *inode, cha + dir_ent->name = dir_ent->pathname = strdup(pathname); + dir_ent->dir = dir_info; + dir_ent->our_dir = NULL; +- dir_ent->data = NULL; + dir_info->dir_ent = dir_ent; + + if(sorted) +@@ -3383,7 +3503,7 @@ struct dir_info *dir_scan1(char *pathnam + sub_dir = NULL; + + add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), +- NULL, dir); ++ dir); + } + + scan1_freedir(dir); +@@ -3399,7 +3519,7 @@ struct dir_info *dir_scan2(struct dir_in + struct dir_ent *dir_ent; + struct pseudo_entry *pseudo_ent; + struct stat buf; +- static pseudo_ino = 1; ++ static int pseudo_ino = 1; + + if(dir == NULL && (dir = scan1_opendir("")) == NULL) + return NULL; +@@ -3415,6 +3535,29 @@ struct dir_info *dir_scan2(struct dir_in + + while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) { + dir_ent = scan2_lookup(dir, pseudo_ent->name); ++ if(pseudo_ent->dev->type == 's') { ++ struct stat *buf; ++ if(dir_ent == NULL) { ++ ERROR("Pseudo set file \"%s\" does not exist " ++ "in source filesystem. Ignoring\n", ++ pseudo_ent->pathname); ++ continue; ++ } ++ if(dir_ent->inode->root_entry) { ++ ERROR("Pseudo set file \"%s\" is a pre-existing" ++ " file in the filesystem being appended" ++ " to. It cannot be modified. " ++ "Ignoring!\n", pseudo_ent->pathname); ++ continue; ++ } ++ buf = &dir_ent->inode->buf; ++ buf->st_mode = (buf->st_mode & S_IFMT) | ++ pseudo_ent->dev->mode; ++ buf->st_uid = pseudo_ent->dev->uid; ++ buf->st_gid = pseudo_ent->dev->gid; ++ continue; ++ } ++ + if(dir_ent) { + ERROR("Pseudo file \"%s\" exists in source filesystem " + "\"%s\"\n", pseudo_ent->pathname, +@@ -3444,8 +3587,29 @@ struct dir_info *dir_scan2(struct dir_in + buf.st_mtime = time(NULL); + buf.st_ino = pseudo_ino ++; + +- add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, +- lookup_inode(&buf), NULL, dir); ++ if(pseudo_ent->dev->type == 'f') { ++#ifdef USE_TMP_FILE ++ struct stat buf2; ++ int res = stat(pseudo_ent->dev->filename, &buf2); ++ if(res == -1) { ++ ERROR("Stat on pseudo file \"%s\" failed, " ++ "skipping...", pseudo_ent->pathname); ++ continue; ++ } ++ buf.st_size = buf2.st_size; ++ add_dir_entry(pseudo_ent->name, ++ pseudo_ent->dev->filename, sub_dir, ++ lookup_inode(&buf), dir); ++#else ++ struct inode_info *inode = lookup_inode(&buf); ++ inode->pseudo_id = pseudo_ent->dev->pseudo_id; ++ inode->pseudo_file = TRUE; ++ add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, ++ sub_dir, inode, dir); ++#endif ++ } else ++ add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, ++ sub_dir, lookup_inode(&buf), dir); + } + + scan2_freedir(dir); +@@ -3482,8 +3646,9 @@ void dir_scan3(squashfs_inode *inode, st + &duplicate_file); + INFO("file %s, uncompressed size %lld " + "bytes %s\n", filename, +- buf->st_size, duplicate_file ? +- "DUPLICATE" : ""); ++ (long long) buf->st_size, ++ duplicate_file ? "DUPLICATE" : ++ ""); + break; + + case S_IFDIR: +@@ -3557,6 +3722,7 @@ void dir_scan3(squashfs_inode *inode, st + INFO("file %s, uncompressed " + "size %lld bytes LINK" + "\n", filename, ++ (long long) + buf->st_size); + break; + case SQUASHFS_SYMLINK_TYPE: +@@ -3667,10 +3833,11 @@ void add_old_root_entry(char *name, squa + BAD_ERROR("Out of memory in old root directory entries " + "reallocation\n"); + +- strcpy(old_root_entry[old_root_entries].name, name); +- old_root_entry[old_root_entries].inode = inode; +- old_root_entry[old_root_entries].inode_number = inode_number; +- old_root_entry[old_root_entries++].type = type; ++ old_root_entry[old_root_entries].name = strdup(name); ++ old_root_entry[old_root_entries].inode.inode = inode; ++ old_root_entry[old_root_entries].inode.inode_number = inode_number; ++ old_root_entry[old_root_entries].inode.type = type; ++ old_root_entry[old_root_entries++].inode.root_entry = TRUE; + } + + +@@ -4172,26 +4339,28 @@ int main(int argc, char *argv[]) + source_path = argv + 1; + source = i - 2; + for(; i < argc; i++) { +- if(strcmp(argv[i], "-pf") == 0) { ++ if(strcmp(argv[i], "-comp") == 0) { + if(++i == argc) { +- ERROR("%s: -pf missing filename\n", argv[0]); ++ ERROR("%s: -comp missing compression type\n", ++ argv[0]); + exit(1); + } +- if(read_pseudo_file(&pseudo, argv[i]) == FALSE) { +- ERROR("Failed to parse pseudo file \"%s\"\n", +- argv[i]); ++ comp_name = argv[i]; ++ } else if(strcmp(argv[i], "-pf") == 0) { ++ if(++i == argc) { ++ ERROR("%s: -pf missing filename\n", argv[0]); + exit(1); + } ++ if(read_pseudo_file(&pseudo, argv[i]) == FALSE) ++ exit(1); + } else if(strcmp(argv[i], "-p") == 0) { + if(++i == argc) { + ERROR("%s: -p missing pseudo file definition\n", + argv[0]); + exit(1); + } +- if(read_pseudo_def(&pseudo, argv[i]) == FALSE) { +- ERROR("Failed to parse pseudo definition\n"); ++ if(read_pseudo_def(&pseudo, argv[i]) == FALSE) + exit(1); +- } + } else if(strcmp(argv[i], "-recover") == 0) { + if(++i == argc) { + ERROR("%s: -recover missing recovery file\n", +@@ -4394,34 +4563,16 @@ int main(int argc, char *argv[]) + printOptions: + ERROR("SYNTAX:%s source1 source2 ... dest [options] " + "[-e list of exclude\ndirs/files]\n", argv[0]); +- ERROR("\nOptions are\n"); +- ERROR("-version\t\tprint version, licence and " +- "copyright message\n"); +- ERROR("-recover <name>\t\trecover filesystem data " +- "using recovery file <name>\n"); +- ERROR("-no-recovery\t\tdon't generate a recovery " +- "file\n"); +- ERROR("-info\t\t\tprint files written to filesystem\n"); +- ERROR("-no-exports\t\tdon't make the filesystem " +- "exportable via NFS\n"); +- ERROR("-no-progress\t\tdon't display the progress " +- "bar\n"); +- ERROR("-no-sparse\t\tdon't detect sparse files\n"); ++ ERROR("\nFilesystem build options:\n"); ++ ERROR("-comp <comp>\t\tselect <comp> compression\n"); ++ ERROR("\t\t\tCompressors available:\n"); ++ display_compressors("\t\t\t", COMP_DEFAULT); + ERROR("-b <block_size>\t\tset data block to " + "<block_size>. Default %d bytes\n", + SQUASHFS_FILE_SIZE); +- ERROR("-processors <number>\tUse <number> processors." +- " By default will use number of\n"); +- ERROR("\t\t\tprocessors available\n"); +- ERROR("-read-queue <size>\tSet input queue to <size> " +- "Mbytes. Default %d Mbytes\n", +- READER_BUFFER_DEFAULT); +- ERROR("-write-queue <size>\tSet output queue to <size> " +- "Mbytes. Default %d Mbytes\n", +- WRITER_BUFFER_DEFAULT); +- ERROR("-fragment-queue <size>\tSet fagment queue to " +- "<size> Mbytes. Default %d Mbytes\n", +- FRAGMENT_BUFFER_DEFAULT); ++ ERROR("-no-exports\t\tdon't make the filesystem " ++ "exportable via NFS\n"); ++ ERROR("-no-sparse\t\tdon't detect sparse files\n"); + ERROR("-noI\t\t\tdo not compress inode table\n"); + ERROR("-noD\t\t\tdo not compress data blocks\n"); + ERROR("-noF\t\t\tdo not compress fragment blocks\n"); +@@ -4430,13 +4581,34 @@ printOptions: + "files larger than block size\n"); + ERROR("-no-duplicates\t\tdo not perform duplicate " + "checking\n"); +- ERROR("-noappend\t\tdo not append to existing " +- "filesystem\n"); ++ ERROR("-all-root\t\tmake all files owned by root\n"); ++ ERROR("-force-uid uid\t\tset all file uids to uid\n"); ++ ERROR("-force-gid gid\t\tset all file gids to gid\n"); ++ ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " ++ "of 4K\n"); + ERROR("-keep-as-directory\tif one source directory is " + "specified, create a root\n"); + ERROR("\t\t\tdirectory containing that directory, " + "rather than the\n"); + ERROR("\t\t\tcontents of the directory\n"); ++ ERROR("\nFilesystem filter options:\n"); ++ ERROR("-p <pseudo-definition>\tAdd pseudo file definition\n"); ++ ERROR("-pf <pseudo-file>\tAdd list of pseudo file definitions\n"); ++ ERROR("-sort <sort_file>\tsort files according to " ++ "priorities in <sort_file>. One\n"); ++ ERROR("\t\t\tfile or dir with priority per line. " ++ "Priority -32768 to\n"); ++ ERROR("\t\t\t32767, default priority 0\n"); ++ ERROR("-ef <exclude_file>\tlist of exclude dirs/files." ++ " One per line\n"); ++ ERROR("-wildcards\t\tAllow extended shell wildcards " ++ "(globbing) to be used in\n\t\t\texclude " ++ "dirs/files\n"); ++ ERROR("-regex\t\t\tAllow POSIX regular expressions to " ++ "be used in exclude\n\t\t\tdirs/files\n"); ++ ERROR("\nFilesystem append options:\n"); ++ ERROR("-noappend\t\tdo not append to existing " ++ "filesystem\n"); + ERROR("-root-becomes <name>\twhen appending source " + "files/directories, make the\n"); + ERROR("\t\t\toriginal root become a subdirectory in " +@@ -4444,11 +4616,29 @@ printOptions: + ERROR("\t\t\tcalled <name>, rather than adding the new " + "source items\n"); + ERROR("\t\t\tto the original root\n"); +- ERROR("-all-root\t\tmake all files owned by root\n"); +- ERROR("-force-uid uid\t\tset all file uids to uid\n"); +- ERROR("-force-gid gid\t\tset all file gids to gid\n"); +- ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " +- "of 4K\n"); ++ ERROR("\nMksquashfs runtime options:\n"); ++ ERROR("-version\t\tprint version, licence and " ++ "copyright message\n"); ++ ERROR("-recover <name>\t\trecover filesystem data " ++ "using recovery file <name>\n"); ++ ERROR("-no-recovery\t\tdon't generate a recovery " ++ "file\n"); ++ ERROR("-info\t\t\tprint files written to filesystem\n"); ++ ERROR("-no-progress\t\tdon't display the progress " ++ "bar\n"); ++ ERROR("-processors <number>\tUse <number> processors." ++ " By default will use number of\n"); ++ ERROR("\t\t\tprocessors available\n"); ++ ERROR("-read-queue <size>\tSet input queue to <size> " ++ "Mbytes. Default %d Mbytes\n", ++ READER_BUFFER_DEFAULT); ++ ERROR("-write-queue <size>\tSet output queue to <size> " ++ "Mbytes. Default %d Mbytes\n", ++ WRITER_BUFFER_DEFAULT); ++ ERROR("-fragment-queue <size>\tSet fagment queue to " ++ "<size> Mbytes. Default %d Mbytes\n", ++ FRAGMENT_BUFFER_DEFAULT); ++ ERROR("\nMiscellaneous options:\n"); + ERROR("-root-owned\t\talternative name for -all-root" + "\n"); + ERROR("-noInodeCompression\talternative name for -noI" +@@ -4457,20 +4647,6 @@ printOptions: + "\n"); + ERROR("-noFragmentCompression\talternative name for " + "-noF\n"); +- ERROR("-sort <sort_file>\tsort files according to " +- "priorities in <sort_file>. One\n"); +- ERROR("\t\t\tfile or dir with priority per line. " +- "Priority -32768 to\n"); +- ERROR("\t\t\t32767, default priority 0\n"); +- ERROR("-ef <exclude_file>\tlist of exclude dirs/files." +- " One per line\n"); +- ERROR("-wildcards\t\tAllow extended shell wildcards " +- "(globbing) to be used in\n\t\t\texclude " +- "dirs/files\n"); +- ERROR("-regex\t\t\tAllow POSIX regular expressions to " +- "be used in exclude\n\t\t\tdirs/files\n"); +- ERROR("-p <pseudo-definition>\tAdd pseudo file definition\n"); +- ERROR("-pf <pseudo-file>\tAdd list of pseudo file definitions\n"); + exit(1); + } + } +@@ -4548,11 +4724,10 @@ printOptions: + fclose(fd); + } else if(strcmp(argv[i], "-e") == 0) + break; +- else if(strcmp(argv[i], "-b") == 0 || +- strcmp(argv[i], "-root-becomes") == 0 || ++ else if(strcmp(argv[i], "-root-becomes") == 0 || + strcmp(argv[i], "-sort") == 0 || + strcmp(argv[i], "-pf") == 0 || +- strcmp(argv[i], "-p") == 0) ++ strcmp(argv[i], "-comp") == 0) + i++; + + if(i != argc) { +@@ -4574,11 +4749,10 @@ printOptions: + sorted ++; + } else if(strcmp(argv[i], "-e") == 0) + break; +- else if(strcmp(argv[i], "-b") == 0 || +- strcmp(argv[i], "-root-becomes") == 0 || ++ else if(strcmp(argv[i], "-root-becomes") == 0 || + strcmp(argv[i], "-ef") == 0 || + strcmp(argv[i], "-pf") == 0 || +- strcmp(argv[i], "-p") == 0) ++ strcmp(argv[i], "-comp") == 0) + i++; + + #ifdef SQUASHFS_TRACE +@@ -4586,7 +4760,8 @@ printOptions: + #endif + + if(!delete) { +- if(read_super(fd, &sBlk, argv[source + 1]) == 0) { ++ comp = read_super(fd, &sBlk, argv[source + 1]); ++ if(comp == NULL) { + ERROR("Failed to read existing filesystem - will not " + "overwrite - ABORTING!\n"); + ERROR("To force Mksquashfs to write to this block " +@@ -4603,6 +4778,15 @@ printOptions: + always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); + duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); + exportable = SQUASHFS_EXPORTABLE(sBlk.flags); ++ } else { ++ comp = lookup_compressor(comp_name); ++ if(!comp->supported) { ++ ERROR("FATAL_ERROR: Compressor \"%s\" is not " ++ "supported!\n", comp_name); ++ ERROR("Compressors available:\n"); ++ display_compressors("", COMP_DEFAULT); ++ EXIT_MKSQUASHFS(); ++ } + } + + initialise_threads(); +@@ -4648,8 +4832,8 @@ printOptions: + "size %d\n", SQUASHFS_MAJOR, s_minor, argv[source + 1], + block_size); + printf("All -b, -noI, -noD, -noF, no-duplicates, no-fragments, " +- "-always-use-fragments and -exportable options ignored" +- "\n"); ++ "-always-use-fragments,\n-exportable and -comp options " ++ "ignored\n"); + printf("\nIf appending is not wanted, please re-run with " + "-noappend specified!\n\n"); + +@@ -4803,8 +4987,7 @@ restore_filesystem: + + sBlk.bytes_used = bytes; + +- /* Only compression supported */ +- sBlk.compression = ZLIB_COMPRESSION; ++ sBlk.compression = comp->id; + + /* Xattrs are not currently supported */ + sBlk.xattr_table_start = SQUASHFS_INVALID_BLK; +@@ -4820,6 +5003,8 @@ restore_filesystem: + + close(fd); + ++ delete_pseudo_files(); ++ + if(recovery_file[0] != '\0') + unlink(recovery_file); + +@@ -4827,9 +5012,9 @@ restore_filesystem: + * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + + sizeof(squashfs_super_block); + +- printf("\n%sSquashfs %d.%d filesystem, data block size %d\n", +- exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR, +- block_size); ++ printf("\n%sSquashfs %d.%d filesystem, %s compressed, data block size" ++ " %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR, ++ SQUASHFS_MINOR, comp->name, block_size); + printf("\t%s data, %s metadata, %s fragments\n", + noD ? "uncompressed" : "compressed", noI ? "uncompressed" : + "compressed", no_fragments ? "no" : noF ? "uncompressed" : +diff -Naurp squashfs-tools/pseudo.c squashfs-tools-lzma/pseudo.c +--- squashfs-tools/pseudo.c 2009-04-05 02:01:58.000000000 +0000 ++++ squashfs-tools-lzma/pseudo.c 2009-10-20 04:03:38.000000000 +0000 +@@ -30,6 +30,7 @@ + #include <string.h> + #include <stdlib.h> + #include <sys/types.h> ++#include <sys/wait.h> + + #include "pseudo.h" + +@@ -55,6 +56,9 @@ + #define TRUE 1 + #define FALSE 0 + ++struct pseudo_dev **pseudo_file = NULL; ++int pseudo_count = 0; ++ + static void dump_pseudo(struct pseudo *pseudo, char *string) + { + int i; +@@ -99,7 +103,7 @@ struct pseudo *add_pseudo(struct pseudo + char *target, char *alltarget) + { + char targname[1024]; +- int i, error; ++ int i; + + target = get_component(target, targname); + +@@ -128,12 +132,8 @@ struct pseudo *add_pseudo(struct pseudo + if(target[0] == '\0') { + /* at leaf pathname component */ + pseudo->name[i].pseudo = NULL; +- pseudo->name[i].dev = malloc(sizeof(struct pseudo_dev)); +- if(pseudo->name[i].dev == NULL) +- BAD_ERROR("failed to allocate pseudo file\n"); + pseudo->name[i].pathname = strdup(alltarget); +- memcpy(pseudo->name[i].dev, pseudo_dev, +- sizeof(struct pseudo_dev)); ++ pseudo->name[i].dev = pseudo_dev; + } else { + /* recurse adding child components */ + pseudo->name[i].dev = NULL; +@@ -169,15 +169,9 @@ struct pseudo *add_pseudo(struct pseudo + if(target[0] == '\0') { + if(pseudo->name[i].dev == NULL && + pseudo_dev->type == 'd') { +- pseudo->name[i].dev = +- malloc(sizeof(struct pseudo_dev)); +- if(pseudo->name[i].dev == NULL) +- BAD_ERROR("failed to allocate " +- "pseudo file\n"); + pseudo->name[i].pathname = + strdup(alltarget); +- memcpy(pseudo->name[i].dev, pseudo_dev, +- sizeof(struct pseudo_dev)); ++ pseudo->name[i].dev = pseudo_dev; + } else + ERROR("%s already exists as a " + "directory. Ignoring %s!\n", +@@ -229,16 +223,113 @@ struct pseudo_entry *pseudo_readdir(stru + } + + ++int exec_file(char *command, struct pseudo_dev *dev) ++{ ++ int child, res; ++ static pid_t pid = -1; ++ int pipefd[2]; ++#ifdef USE_TMP_FILE ++ char filename[1024]; ++ int status; ++ static int number = 0; ++#endif ++ ++ if(pid == -1) ++ pid = getpid(); ++ ++#ifdef USE_TMP_FILE ++ sprintf(filename, "/tmp/squashfs_pseudo_%d_%d", pid, number ++); ++ pipefd[1] = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); ++ if(pipefd[1] == -1) { ++ printf("open failed\n"); ++ return -1; ++ } ++#else ++ res = pipe(pipefd); ++ if(res == -1) { ++ printf("pipe failed\n"); ++ return -1; ++ } ++#endif ++ ++ child = fork(); ++ if(child == -1) { ++ printf("fork failed\n"); ++ goto failed; ++ } ++ ++ if(child == 0) { ++ close(STDOUT_FILENO); ++ res = dup(pipefd[1]); ++ if(res == -1) { ++ printf("dup failed\n"); ++ exit(EXIT_FAILURE); ++ } ++ execl("/bin/sh", "sh", "-c", command, (char *) NULL); ++ printf("execl failed\n"); ++ exit(EXIT_FAILURE); ++ } ++ ++#ifdef USE_TMP_FILE ++ res = waitpid(child, &status, 0); ++ close(pipefd[1]); ++ if(res != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0) { ++ dev->filename = strdup(filename); ++ return 0; ++ } ++failed: ++ unlink(filename); ++ return -1; ++#else ++ close(pipefd[1]); ++ dev->fd = pipefd[0]; ++ dev->child = child; ++ return 0; ++failed: ++ return -1; ++#endif ++} ++ ++ ++void add_pseudo_file(struct pseudo_dev *dev) ++{ ++ pseudo_file = realloc(pseudo_file, (pseudo_count + 1) * ++ sizeof(struct pseudo_dev *)); ++ if(pseudo_file == NULL) ++ BAD_ERROR("Failed to realloc pseudo_file\n"); ++ ++ dev->pseudo_id = pseudo_count; ++ pseudo_file[pseudo_count ++] = dev; ++} ++ ++ ++void delete_pseudo_files() ++{ ++#ifdef USE_TMP_FILE ++ int i; ++ ++ for(i = 0; i < pseudo_count; i++) ++ unlink(pseudo_file[i]->filename); ++#endif ++} ++ ++ ++struct pseudo_dev *get_pseudo_file(int pseudo_id) ++{ ++ return pseudo_file[pseudo_id]; ++} ++ ++ + int read_pseudo_def(struct pseudo **pseudo, char *def) + { +- int n; ++ int n, bytes; + unsigned int major = 0, minor = 0, mode; + char filename[2048], type, suid[100], sgid[100], *ptr; + long long uid, gid; +- struct pseudo_dev dev; ++ struct pseudo_dev *dev; + +- n = sscanf(def, "%s %c %o %s %s %u %u", filename, &type, &mode, suid, sgid, +- &major, &minor); ++ n = sscanf(def, "%s %c %o %s %s %n", filename, &type, &mode, suid, ++ sgid, &bytes); + + if(n < 5) { + ERROR("Not enough or invalid arguments in pseudo file " +@@ -249,7 +340,9 @@ int read_pseudo_def(struct pseudo **pseu + switch(type) { + case 'b': + case 'c': +- if(n < 7) { ++ n = sscanf(def + bytes, "%u %u", &major, &minor); ++ ++ if(n < 2) { + ERROR("Not enough or invalid arguments in pseudo file " + "definition\n"); + goto error; +@@ -265,47 +358,15 @@ int read_pseudo_def(struct pseudo **pseu + goto error; + } + +- /* fall through */ +- case 'd': +- if(mode > 0777) { +- ERROR("Mode %o out of range\n", mode); ++ case 'f': ++ if(def[bytes] == '\0') { ++ ERROR("Not enough arguments in pseudo file " ++ "definition\n"); + goto error; +- } +- +- uid = strtoll(suid, &ptr, 10); +- if(*ptr == '\0') { +- if(uid < 0 || uid > ((1LL << 32) - 1)) { +- ERROR("Uid %s out of range\n", suid); +- goto error; +- } +- } else { +- struct passwd *pwuid = getpwnam(suid); +- if(pwuid) +- uid = pwuid->pw_uid; +- else { +- ERROR("Uid %s invalid uid or unknown user\n", +- suid); +- goto error; +- } +- } +- +- gid = strtoll(sgid, &ptr, 10); +- if(*ptr == '\0') { +- if(gid < 0 || gid > ((1LL << 32) - 1)) { +- ERROR("Gid %s out of range\n", sgid); +- goto error; +- } +- } else { +- struct group *grgid = getgrnam(sgid); +- if(grgid) +- gid = grgid->gr_gid; +- else { +- ERROR("Gid %s invalid uid or unknown user\n", +- sgid); +- goto error; +- } +- } +- ++ } ++ break; ++ case 'd': ++ case 'm': + break; + default: + ERROR("Unsupported type %c\n", type); +@@ -313,6 +374,43 @@ int read_pseudo_def(struct pseudo **pseu + } + + ++ if(mode > 0777) { ++ ERROR("Mode %o out of range\n", mode); ++ goto error; ++ } ++ ++ uid = strtoll(suid, &ptr, 10); ++ if(*ptr == '\0') { ++ if(uid < 0 || uid > ((1LL << 32) - 1)) { ++ ERROR("Uid %s out of range\n", suid); ++ goto error; ++ } ++ } else { ++ struct passwd *pwuid = getpwnam(suid); ++ if(pwuid) ++ uid = pwuid->pw_uid; ++ else { ++ ERROR("Uid %s invalid uid or unknown user\n", suid); ++ goto error; ++ } ++ } ++ ++ gid = strtoll(sgid, &ptr, 10); ++ if(*ptr == '\0') { ++ if(gid < 0 || gid > ((1LL << 32) - 1)) { ++ ERROR("Gid %s out of range\n", sgid); ++ goto error; ++ } ++ } else { ++ struct group *grgid = getgrnam(sgid); ++ if(grgid) ++ gid = grgid->gr_gid; ++ else { ++ ERROR("Gid %s invalid uid or unknown user\n", sgid); ++ goto error; ++ } ++ } ++ + switch(type) { + case 'b': + mode |= S_IFBLK; +@@ -323,16 +421,37 @@ int read_pseudo_def(struct pseudo **pseu + case 'd': + mode |= S_IFDIR; + break; ++ case 'f': ++ mode |= S_IFREG; ++ break; + } + +- dev.type = type; +- dev.mode = mode; +- dev.uid = uid; +- dev.gid = gid; +- dev.major = major; +- dev.minor = minor; ++ dev = malloc(sizeof(struct pseudo_dev)); ++ if(dev == NULL) ++ BAD_ERROR("Failed to create pseudo_dev\n"); ++ ++ dev->type = type; ++ dev->mode = mode; ++ dev->uid = uid; ++ dev->gid = gid; ++ dev->major = major; ++ dev->minor = minor; ++ ++ if(type == 'f') { ++ int res; ++ ++ printf("Executing dynamic pseudo file\n"); ++ printf("\t\"%s\"\n", def); ++ res = exec_file(def + bytes, dev); ++ if(res == -1) { ++ ERROR("Failed to execute dynamic pseudo file definition" ++ " \"%s\"\n", def); ++ return FALSE; ++ } ++ add_pseudo_file(dev); ++ } + +- *pseudo = add_pseudo(*pseudo, &dev, filename, filename); ++ *pseudo = add_pseudo(*pseudo, dev, filename, filename); + + return TRUE; + +diff -Naurp squashfs-tools/pseudo.h squashfs-tools-lzma/pseudo.h +--- squashfs-tools/pseudo.h 2009-04-04 01:44:24.000000000 +0000 ++++ squashfs-tools-lzma/pseudo.h 2009-10-20 04:03:38.000000000 +0000 +@@ -27,6 +27,12 @@ struct pseudo_dev { + unsigned int gid; + unsigned int major; + unsigned int minor; ++ int pseudo_id; ++ int fd; ++ int child; ++#ifdef USE_TMP_FILE ++ char *filename; ++#endif + }; + + struct pseudo_entry { +@@ -46,3 +52,5 @@ extern int read_pseudo_def(struct pseudo + extern int read_pseudo_file(struct pseudo **, char *); + extern struct pseudo *pseudo_subdir(char *, struct pseudo *); + extern struct pseudo_entry *pseudo_readdir(struct pseudo *); ++extern struct pseudo_dev *get_pseudo_file(int); ++extern void delete_pseudo_files(); +diff -Naurp squashfs-tools/read_fs.c squashfs-tools-lzma/read_fs.c +--- squashfs-tools/read_fs.c 2009-03-31 04:23:14.000000000 +0000 ++++ squashfs-tools-lzma/read_fs.c 2009-10-20 04:03:38.000000000 +0000 +@@ -36,7 +36,6 @@ extern unsigned int get_guid(unsigned in + #include <fcntl.h> + #include <errno.h> + #include <string.h> +-#include <zlib.h> + #include <sys/mman.h> + + #ifndef linux +@@ -51,6 +50,7 @@ extern unsigned int get_guid(unsigned in + #include "squashfs_swap.h" + #include "read_fs.h" + #include "global.h" ++#include "compressor.h" + + #include <stdlib.h> + +@@ -66,7 +66,9 @@ extern unsigned int get_guid(unsigned in + fprintf(stderr, s, ## args); \ + } while(0) + +-int read_block(int fd, long long start, long long *next, unsigned char *block, ++static struct compressor *comp; ++ ++int read_block(int fd, long long start, long long *next, void *block, + squashfs_super_block *sBlk) + { + unsigned short c_byte; +@@ -77,32 +79,24 @@ int read_block(int fd, long long start, + + if(SQUASHFS_COMPRESSED(c_byte)) { + char buffer[SQUASHFS_METADATA_SIZE]; +- int res; +- unsigned long bytes = SQUASHFS_METADATA_SIZE; ++ int error, res; + + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + read_destination(fd, start + offset, c_byte, buffer); + +- res = uncompress(block, &bytes, (const unsigned char *) buffer, +- c_byte); +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "memory\n"); +- else if(res == Z_BUF_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "room in output buffer\n"); +- else +- ERROR("zlib::uncompress failed, unknown error " +- "%d\n", res); ++ res = comp->uncompress(block, buffer, c_byte, ++ SQUASHFS_METADATA_SIZE, &error); ++ if(res == -1) { ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); + return 0; + } + if(next) + *next = start + offset + c_byte; +- return bytes; ++ return res; + } else { + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); +- read_destination(fd, start + offset, c_byte, (char *) block); ++ read_destination(fd, start + offset, c_byte, block); + if(next) + *next = start + offset + c_byte; + return c_byte; +@@ -356,7 +350,7 @@ failed: + } + + +-int read_super(int fd, squashfs_super_block *sBlk, char *source) ++struct compressor *read_super(int fd, squashfs_super_block *sBlk, char *source) + { + read_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block), + (char *) sBlk); +@@ -388,8 +382,18 @@ int read_super(int fd, squashfs_super_bl + goto failed_mount; + } + ++ /* Check the compression type */ ++ comp = lookup_compressor_id(sBlk->compression); ++ if(!comp->supported) { ++ ERROR("Filesystem on %s uses %s compression, this is" ++ "unsupported by this version\n", source, comp->name); ++ display_compressors("", ""); ++ goto failed_mount; ++ } ++ + printf("Found a valid %sSQUASHFS superblock on %s.\n", + SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source); ++ printf("\tCompression used %s\n", comp->name); + printf("\tInodes are %scompressed\n", + SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); + printf("\tData is %scompressed\n", +@@ -417,10 +421,10 @@ int read_super(int fd, squashfs_super_bl + TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start); + printf("\n"); + +- return TRUE; ++ return comp; + + failed_mount: +- return FALSE; ++ return NULL; + } + + +@@ -514,12 +518,17 @@ unsigned int *read_id_table(int fd, squa + SQUASHFS_INSWAP_ID_BLOCKS(index, indexes); + + for(i = 0; i < indexes; i++) { +- int length; +- length = read_block(fd, index[i], NULL, ++ int length = read_block(fd, index[i], NULL, + ((unsigned char *) id_table) + + (i * SQUASHFS_METADATA_SIZE), sBlk); + TRACE("Read id table block %d, from 0x%llx, length %d\n", i, + index[i], length); ++ if(length == 0) { ++ ERROR("Failed to read id table block %d, from 0x%llx, " ++ "length %d\n", i, index[i], length); ++ free(id_table); ++ return NULL; ++ } + } + + SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids); +@@ -563,6 +572,13 @@ int read_fragment_table(int fd, squashfs + (i * SQUASHFS_METADATA_SIZE), sBlk); + TRACE("Read fragment table block %d, from 0x%llx, length %d\n", + i, fragment_table_index[i], length); ++ if(length == 0) { ++ ERROR("Failed to read fragment table block %d, from " ++ "0x%llx, length %d\n", i, ++ fragment_table_index[i], length); ++ free(*fragment_table); ++ return 0; ++ } + } + + for(i = 0; i < sBlk->fragments; i++) +@@ -599,6 +615,13 @@ int read_inode_lookup_table(int fd, squa + (i * SQUASHFS_METADATA_SIZE), sBlk); + TRACE("Read inode lookup table block %d, from 0x%llx, length " + "%d\n", i, index[i], length); ++ if(length == 0) { ++ ERROR("Failed to read inode lookup table block %d, " ++ "from 0x%llx, length %d\n", i, index[i], ++ length); ++ free(*inode_lookup_table); ++ return 0; ++ } + } + + SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes); +diff -Naurp squashfs-tools/sort.c squashfs-tools-lzma/sort.c +--- squashfs-tools/sort.c 2009-03-31 04:25:53.000000000 +0000 ++++ squashfs-tools-lzma/sort.c 2009-10-20 04:03:38.000000000 +0000 +@@ -198,7 +198,7 @@ void generate_file_priorities(struct dir + while(dir->current_count < dir->count) { + struct dir_ent *dir_ent = dir->list[dir->current_count++]; + struct stat *buf = &dir_ent->inode->buf; +- if(dir_ent->data) ++ if(dir_ent->inode->root_entry) + continue; + + switch(buf->st_mode & S_IFMT) { +@@ -254,6 +254,7 @@ void sort_files_and_write(struct dir_inf + write_file(&inode, entry->dir, &duplicate_file); + INFO("file %s, uncompressed size %lld bytes %s" + "\n", entry->dir->pathname, ++ (long long) + entry->dir->inode->buf.st_size, + duplicate_file ? "DUPLICATE" : ""); + entry->dir->inode->inode = inode; +@@ -261,6 +262,7 @@ void sort_files_and_write(struct dir_inf + } else + INFO("file %s, uncompressed size %lld bytes " + "LINK\n", entry->dir->pathname, ++ (long long) + entry->dir->inode->buf.st_size); + } + } +diff -Naurp squashfs-tools/sort.h squashfs-tools-lzma/sort.h +--- squashfs-tools/sort.h 2009-02-08 12:02:53.000000000 +0000 ++++ squashfs-tools-lzma/sort.h 2009-10-20 04:03:38.000000000 +0000 +@@ -42,17 +42,19 @@ struct dir_ent { + struct inode_info *inode; + struct dir_info *dir; + struct dir_info *our_dir; +- struct old_root_entry_info *data; + }; + + struct inode_info { +- unsigned int nlink; + struct stat buf; ++ struct inode_info *next; + squashfs_inode inode; +- unsigned int type; + unsigned int inode_number; ++ unsigned int nlink; ++ int pseudo_id; ++ char type; + char read; +- struct inode_info *next; ++ char root_entry; ++ char pseudo_file; + }; + + struct priority_entry { +diff -Naurp squashfs-tools/squashfs_compat.h squashfs-tools-lzma/squashfs_compat.h +--- squashfs-tools/squashfs_compat.h 2009-03-16 04:27:27.000000000 +0000 ++++ squashfs-tools-lzma/squashfs_compat.h 2009-10-20 04:03:38.000000000 +0000 +@@ -777,11 +777,10 @@ typedef union squashfs_inode_header_2 sq + #endif + + #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ +- int bits;\ +- int b_pos = pos % 8;\ +- unsigned long long val = 0;\ +- unsigned char *s = (unsigned char *)p + (pos / 8);\ +- unsigned char *d = ((unsigned char *) &val) + 7;\ ++ b_pos = pos % 8;\ ++ val = 0;\ ++ s = (unsigned char *)p + (pos / 8);\ ++ d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +diff -Naurp squashfs-tools/squashfs_fs.h squashfs-tools-lzma/squashfs_fs.h +--- squashfs-tools/squashfs_fs.h 2009-03-18 02:50:20.000000000 +0000 ++++ squashfs-tools-lzma/squashfs_fs.h 2009-10-20 04:03:38.000000000 +0000 +@@ -229,6 +229,7 @@ typedef long long squashfs_block_t; + typedef long long squashfs_inode_t; + + #define ZLIB_COMPRESSION 1 ++#define LZMA_COMPRESSION 2 + + struct squashfs_super_block { + unsigned int s_magic; +diff -Naurp squashfs-tools/unsquash-3.c squashfs-tools-lzma/unsquash-3.c +--- squashfs-tools/unsquash-3.c 2009-03-31 04:35:10.000000000 +0000 ++++ squashfs-tools-lzma/unsquash-3.c 2009-10-20 04:03:38.000000000 +0000 +@@ -36,7 +36,7 @@ int read_fragment_table_3() + sBlk.fragment_table_start); + + if(sBlk.fragments == 0) +- return; ++ return TRUE; + + if((fragment_table = malloc(sBlk.fragments * + sizeof(squashfs_fragment_entry_3))) == NULL) +diff -Naurp squashfs-tools/unsquash-4.c squashfs-tools-lzma/unsquash-4.c +--- squashfs-tools/unsquash-4.c 2009-03-31 04:38:31.000000000 +0000 ++++ squashfs-tools-lzma/unsquash-4.c 2009-10-20 04:03:38.000000000 +0000 +@@ -38,7 +38,7 @@ int read_fragment_table_4() + sBlk.fragment_table_start); + + if(sBlk.fragments == 0) +- return; ++ return TRUE; + + if((fragment_table = malloc(sBlk.fragments * + sizeof(squashfs_fragment_entry))) == NULL) +diff -Naurp squashfs-tools/unsquashfs.c squashfs-tools-lzma/unsquashfs.c +--- squashfs-tools/unsquashfs.c 2009-04-05 21:23:06.000000000 +0000 ++++ squashfs-tools-lzma/unsquashfs.c 2009-10-20 04:03:39.000000000 +0000 +@@ -25,6 +25,9 @@ + #include "squashfs_swap.h" + #include "squashfs_compat.h" + #include "read_fs.h" ++#include "compressor.h" ++ ++#include <sys/sysinfo.h> + + struct cache *fragment_cache, *data_cache; + struct queue *to_reader, *to_deflate, *to_writer, *from_writer; +@@ -36,6 +39,7 @@ int processors = -1; + + struct super_block sBlk; + squashfs_operations s_ops; ++struct compressor *comp; + + int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, + dev_count = 0, fifo_count = 0; +@@ -590,31 +594,23 @@ int read_block(long long start, long lon + offset = 3; + if(SQUASHFS_COMPRESSED(c_byte)) { + char buffer[SQUASHFS_METADATA_SIZE]; +- int res; +- unsigned long bytes = SQUASHFS_METADATA_SIZE; ++ int error, res; + + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + if(read_bytes(start + offset, c_byte, buffer) == FALSE) + goto failed; + +- res = uncompress((unsigned char *) block, &bytes, +- (const unsigned char *) buffer, c_byte); ++ res = comp->uncompress(block, buffer, c_byte, ++ SQUASHFS_METADATA_SIZE, &error); + +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "memory\n"); +- else if(res == Z_BUF_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "room in output buffer\n"); +- else +- ERROR("zlib::uncompress failed, unknown error " +- "%d\n", res); ++ if(res == -1) { ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); + goto failed; + } + if(next) + *next = start + offset + c_byte; +- return bytes; ++ return res; + } else { + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + if(read_bytes(start + offset, c_byte, block) == FALSE) +@@ -632,36 +628,26 @@ failed: + + int read_data_block(long long start, unsigned int size, char *block) + { +- int res; +- unsigned long bytes = block_size; ++ int error, res; + int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); + + TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, +- SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), +- SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : ++ c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" : + "uncompressed"); + + if(SQUASHFS_COMPRESSED_BLOCK(size)) { + if(read_bytes(start, c_byte, data) == FALSE) + goto failed; + +- res = uncompress((unsigned char *) block, &bytes, +- (const unsigned char *) data, c_byte); ++ res = comp->uncompress(block, data, c_byte, block_size, &error); + +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "memory\n"); +- else if(res == Z_BUF_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "room in output buffer\n"); +- else +- ERROR("zlib::uncompress failed, unknown error " +- "%d\n", res); ++ if(res == -1) { ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); + goto failed; + } + +- return bytes; ++ return res; + } else { + if(read_bytes(start, c_byte, block) == FALSE) + goto failed; +@@ -671,7 +657,7 @@ int read_data_block(long long start, uns + + failed: + ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, +- size); ++ c_byte); + return FALSE; + } + +@@ -1383,6 +1369,11 @@ void squashfs_stat(char *source) + #endif + printf("Creation or last append time %s", mkfs_str ? mkfs_str : + "failed to get time\n"); ++ printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", ++ sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); ++ if(sBlk.s_major == 4) ++ printf("Compression %s\n", comp->name); ++ printf("Block size %d\n", sBlk.block_size); + printf("Filesystem is %sexportable via NFS\n", + SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); + +@@ -1409,9 +1400,6 @@ void squashfs_stat(char *source) + SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); + else + printf("Duplicates are removed\n"); +- printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", +- sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); +- printf("Block size %d\n", sBlk.block_size); + if(sBlk.s_major > 1) + printf("Number of fragments %d\n", sBlk.fragments); + printf("Number of inodes %d\n", sBlk.inodes); +@@ -1459,6 +1447,18 @@ int read_super(char *source) + s_ops.read_inode = read_inode_4; + s_ops.read_uids_guids = read_uids_guids_4; + memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); ++ ++ /* ++ * Check the compression type ++ */ ++ comp = lookup_compressor_id(sBlk.compression); ++ if(!comp->supported) { ++ ERROR("Filesystem uses %s compression, this is " ++ "unsupported by this version\n", comp->name); ++ ERROR("Decompressors available:\n"); ++ display_compressors("", ""); ++ goto failed_mount; ++ } + return TRUE; + } + +@@ -1548,6 +1548,11 @@ int read_super(char *source) + goto failed_mount; + } + ++ /* ++ * 1.x, 2.x and 3.x filesystems use gzip compression. Gzip is always ++ * suppported. ++ */ ++ comp = lookup_compressor("gzip"); + return TRUE; + + failed_mount: +@@ -1707,32 +1712,24 @@ void *deflator(void *arg) + + while(1) { + struct cache_entry *entry = queue_get(to_deflate); +- int res; +- unsigned long bytes = block_size; ++ int error, res; + +- res = uncompress((unsigned char *) tmp, &bytes, +- (const unsigned char *) entry->data, +- SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size)); +- +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) +- ERROR("zlib::uncompress failed, not enough" +- "memory\n"); +- else if(res == Z_BUF_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "room in output buffer\n"); +- else +- ERROR("zlib::uncompress failed, unknown error " +- "%d\n", res); +- } else +- memcpy(entry->data, tmp, bytes); ++ res = comp->uncompress(tmp, entry->data, ++ SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, ++ &error); ++ ++ if(res == -1) ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); ++ else ++ memcpy(entry->data, tmp, res); + + /* + * block has been either successfully decompressed, or an error + * occurred, clear pending flag, set error appropriately and + * wake up any threads waiting on this block + */ +- cache_block_ready(entry, res != Z_OK); ++ cache_block_ready(entry, res == -1); + } + } + +@@ -1938,7 +1935,6 @@ int main(int argc, char *argv[]) + int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; + int data_buffer_size = DATA_BUFFER_DEFAULT; + char *b; +- struct winsize winsize; + + pthread_mutex_init(&screen_mutex, NULL); + root_process = geteuid() == 0; +@@ -2087,6 +2083,8 @@ options: + "regular expressions\n"); + ERROR("\t\t\t\trather than use the default shell " + "wildcard\n\t\t\t\texpansion (globbing)\n"); ++ ERROR("\nDecompressors available:\n"); ++ display_compressors("", ""); + } + exit(1); + } +diff -Naurp squashfs-tools/unsquashfs.h squashfs-tools-lzma/unsquashfs.h +--- squashfs-tools/unsquashfs.h 2009-03-29 02:29:02.000000000 +0000 ++++ squashfs-tools-lzma/unsquashfs.h 2009-10-20 04:03:39.000000000 +0000 +@@ -31,7 +31,6 @@ + #include <fcntl.h> + #include <errno.h> + #include <string.h> +-#include <zlib.h> + #include <sys/mman.h> + #include <utime.h> + #include <pwd.h> diff --git a/sys-fs/squashfs-tools/squashfs-tools-4.0-r1.ebuild b/sys-fs/squashfs-tools/squashfs-tools-4.0-r1.ebuild new file mode 100644 index 0000000..4f2051d --- /dev/null +++ b/sys-fs/squashfs-tools/squashfs-tools-4.0-r1.ebuild @@ -0,0 +1,49 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/sys-fs/squashfs-tools/squashfs-tools-4.0.ebuild,v 1.8 2009/12/07 23:01:46 vapier Exp $ + +inherit toolchain-funcs eutils + +MY_PV=${PV} +DESCRIPTION="Tool for creating compressed filesystem type squashfs" +HOMEPAGE="http://squashfs.sourceforge.net/" +SRC_URI="mirror://sourceforge/squashfs/squashfs${MY_PV}.tar.gz + lzma? ( mirror://sourceforge/sevenzip/lzma465.tar.bz2 )" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="alpha amd64 arm hppa ia64 m68k ~mips ppc ppc64 s390 sh sparc x86" +IUSE="lzma" + +RDEPEND="sys-libs/zlib" + +S=${WORKDIR}/squashfs${MY_PV}/squashfs-tools + +src_unpack() { + unpack ${A} + cd "${S}" + + if use lzma ; then + EPATCH_OPTS="-p1" epatch "${FILESDIR}/${P}-lzma.patch" + fi + + sed -i \ + -e 's:-O2:$(CFLAGS):' \ + -e '/-lz/s:$: $(LDFLAGS):' \ + Makefile || die "sed failed" + sed -i -e 's:get_nprocs():sysconf(_SC_NPROCESSORS_ONLN):' *.c +} + +src_compile() { + emake CC="$(tc-getCC)" || die +} + +src_install() { + dobin mksquashfs unsquashfs || die + cd .. + dodoc README ACKNOWLEDGEMENTS CHANGES PERFORMANCE.README +} + +pkg_postinst() { + ewarn "This version of mksquashfs requires a 2.6.29 kernel or better." +} |