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 + * + * 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 +#include +#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 + * + * 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 + * + * 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 +#include + +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 + * + * 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 + +#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 #include #include -#include #include #include #include @@ -47,6 +46,7 @@ #include #include #include +#include #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 \t\trecover filesystem data " - "using recovery file \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 \t\tselect compression\n"); + ERROR("\t\t\tCompressors available:\n"); + display_compressors("\t\t\t", COMP_DEFAULT); ERROR("-b \t\tset data block to " ". Default %d bytes\n", SQUASHFS_FILE_SIZE); - ERROR("-processors \tUse processors." - " By default will use number of\n"); - ERROR("\t\t\tprocessors available\n"); - ERROR("-read-queue \tSet input queue to " - "Mbytes. Default %d Mbytes\n", - READER_BUFFER_DEFAULT); - ERROR("-write-queue \tSet output queue to " - "Mbytes. Default %d Mbytes\n", - WRITER_BUFFER_DEFAULT); - ERROR("-fragment-queue \tSet fagment queue to " - " 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 \tAdd pseudo file definition\n"); + ERROR("-pf \tAdd list of pseudo file definitions\n"); + ERROR("-sort \tsort files according to " + "priorities in . 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 \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 \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 , 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 \t\trecover filesystem data " + "using recovery file \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 \tUse processors." + " By default will use number of\n"); + ERROR("\t\t\tprocessors available\n"); + ERROR("-read-queue \tSet input queue to " + "Mbytes. Default %d Mbytes\n", + READER_BUFFER_DEFAULT); + ERROR("-write-queue \tSet output queue to " + "Mbytes. Default %d Mbytes\n", + WRITER_BUFFER_DEFAULT); + ERROR("-fragment-queue \tSet fagment queue to " + " 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 \tsort files according to " - "priorities in . 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 \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 \tAdd pseudo file definition\n"); - ERROR("-pf \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 #include #include +#include #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 #include #include -#include #include #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 @@ -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 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 #include #include -#include #include #include #include