2211 lines
66 KiB
Diff
2211 lines
66 KiB
Diff
|
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>
|