diff -r 2ab2996036dd squashfs-tools/Makefile
--- a/squashfs-tools/Makefile	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/Makefile	Tue Dec 14 14:18:11 2010 +0000
@@ -20,20 +20,33 @@
 
 ########### Building LZMA support #############
 #
-# Both XZ Utils liblzma  (http://tukaani.org/xz/) and LZMA SDK
+# LZMA1 compression.
+#
+# Both XZ Utils liblzma (http://tukaani.org/xz/) and LZMA SDK
 # (http://www.7-zip.org/sdk.html) are supported
 #
 # To build using XZ Utils liblzma - install the library and uncomment
-# the XZ_SUPPORT line below.
+# the LZMA_XZ_SUPPORT line below.
 #
 # To build using the LZMA SDK (4.65 used in development, other versions may
 # work) - download and unpack it, uncomment and set LZMA_DIR to unpacked source,
 # and uncomment the LZMA_SUPPORT line below.
 #
-#XZ_SUPPORT = 1
+LZMA_XZ_SUPPORT = 1
 #LZMA_SUPPORT = 1
 #LZMA_DIR = ../../../LZMA/lzma465
 
+########### Building XZ support #############
+#
+# LZMA2 compression.
+#
+# XZ Utils liblzma (http://tukaani.org/xz/) is supported
+#
+# To build using XZ Utils liblzma - install the library and uncomment
+# the XZ_SUPPORT line below.
+#
+XZ_SUPPORT = 1
+
 
 ############ Building LZO support ##############
 #
@@ -109,12 +122,20 @@
 COMPRESSORS += lzma
 endif
 
+ifdef LZMA_XZ_SUPPORT
+CFLAGS += -DLZMA_SUPPORT
+MKSQUASHFS_OBJS += lzma_xz_wrapper.o
+UNSQUASHFS_OBJS += lzma_xz_wrapper.o
+LIBS += -llzma
+COMPRESSORS += lzma
+endif
+
 ifdef XZ_SUPPORT
-CFLAGS += -DLZMA_SUPPORT
+CFLAGS += -DXZ_SUPPORT
 MKSQUASHFS_OBJS += xz_wrapper.o
 UNSQUASHFS_OBJS += xz_wrapper.o
 LIBS += -llzma
-COMPRESSORS += lzma
+COMPRESSORS += xz
 endif
 
 ifdef LZO_SUPPORT
@@ -149,11 +170,11 @@
 endif
 
 #
-# Both XZ_SUPPORT and LZMA_SUPPORT cannot be specified
+# Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified
 #
-ifdef XZ_SUPPORT
+ifdef LZMA_XZ_SUPPORT
 ifdef LZMA_SUPPORT
-$(error "Both XZ_SUPPORT and LZMA_SUPPORT cannot be specified")
+$(error "Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified")
 endif
 endif
 
@@ -161,7 +182,7 @@
 # At least one compressor must have been selected
 #
 ifndef COMPRESSORS
-$(error "No compressor selected! Select one or more of GZIP, LZMA, or LZO!")
+$(error "No compressor selected! Select one or more of GZIP, LZMA, XZ or LZO!")
 endif
 
 #
diff -r 2ab2996036dd squashfs-tools/compressor.c
--- a/squashfs-tools/compressor.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/compressor.c	Tue Dec 14 14:18:11 2010 +0000
@@ -25,31 +25,50 @@
 #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 *);
-extern int lzo_compress(void **, char *, char *, int, int, int *);
-extern int lzo_uncompress(char *, char *, int, int, int *);
-
-struct compressor compressor[] = {
-#ifdef GZIP_SUPPORT
-	{ gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 },
+#ifndef GZIP_SUPPORT
+static struct compressor gzip_comp_ops =  {
+	NULL, NULL, NULL, NULL, NULL, ZLIB_COMPRESSION, "gzip", 0
+};
 #else
-	{ NULL, NULL, ZLIB_COMPRESSION, "gzip", 0 },
-#endif
-#ifdef LZMA_SUPPORT
-	{ lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 },
-#else
-	{ NULL, NULL, LZMA_COMPRESSION, "lzma", 0 },
-#endif
-#ifdef LZO_SUPPORT
-	{ lzo_compress, lzo_uncompress, LZO_COMPRESSION, "lzo", 1 },
-#else
-	{ NULL, NULL, LZO_COMPRESSION, "lzo", 0 },
+extern struct compressor gzip_comp_ops;
 #endif
 
-	{ NULL, NULL , 0, "unknown", 0}
+#ifndef LZMA_SUPPORT
+static struct compressor lzma_comp_ops = {
+	NULL, NULL, NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0
+};
+#else
+extern struct compressor lzma_comp_ops;
+#endif
+
+#ifndef LZO_SUPPORT
+static struct compressor lzo_comp_ops = {
+	NULL, NULL, NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0
+};
+#else
+extern struct compressor lzo_comp_ops;
+#endif
+
+#ifndef XZ_SUPPORT
+static struct compressor xz_comp_ops = {
+	NULL, NULL, NULL, NULL, NULL, XZ_COMPRESSION, "xz", 0
+};
+#else
+extern struct compressor xz_comp_ops;
+#endif
+
+
+static struct compressor unknown_comp_ops = {
+	NULL, NULL, NULL , NULL, NULL, 0, "unknown", 0
+};
+
+
+struct compressor *compressor[] = {
+	&gzip_comp_ops,
+	&lzma_comp_ops,
+	&lzo_comp_ops,
+	&xz_comp_ops,
+	&unknown_comp_ops
 };
 
 
@@ -57,11 +76,11 @@
 {
 	int i;
 
-	for(i = 0; compressor[i].id; i++)
-		if(strcmp(compressor[i].name, name) == 0)
+	for(i = 0; compressor[i]->id; i++)
+		if(strcmp(compressor[i]->name, name) == 0)
 			break;
 
-	return &compressor[i];
+	return compressor[i];
 }
 
 
@@ -69,11 +88,11 @@
 {
 	int i;
 
-	for(i = 0; compressor[i].id; i++)
-		if(id == compressor[i].id)
+	for(i = 0; compressor[i]->id; i++)
+		if(id == compressor[i]->id)
 			break;
 
-	return &compressor[i];
+	return compressor[i];
 }
 
 
@@ -81,10 +100,29 @@
 {
 	int i;
 
-	for(i = 0; compressor[i].id; i++)
-		if(compressor[i].supported)
+	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 ?
+				compressor[i]->name,
+				strcmp(compressor[i]->name, def_comp) == 0 ?
 				" (default)" : "");
 }
+
+
+void display_compressor_usage(char *def_comp)
+{
+	int i;
+
+	for(i = 0; compressor[i]->id; i++)
+		if(compressor[i]->supported) {
+			char *str = strcmp(compressor[i]->name, def_comp) == 0 ?
+				" (default)" : "";
+			if(compressor[i]->usage) {
+				fprintf(stderr, "\t%s%s\n",
+					compressor[i]->name, str);
+				compressor[i]->usage();
+			} else
+				fprintf(stderr, "\t%s (no options)%s\n",
+					compressor[i]->name, str);
+		}
+}
diff -r 2ab2996036dd squashfs-tools/compressor.h
--- a/squashfs-tools/compressor.h	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/compressor.h	Tue Dec 14 14:18:11 2010 +0000
@@ -21,8 +21,11 @@
  */
 
 struct compressor {
-	int (*compress)(void **, char *, char *, int, int, int *);
-	int (*uncompress)(char *, char *, int, int, int *);
+	int (*init)(void **, int, int);
+	int (*compress)(void *, void *, void *, int, int, int *);
+	int (*uncompress)(void *, void *, int, int, int *);
+	int (*options)(char **, int);
+	void (*usage)();
 	int id;
 	char *name;
 	int supported;
@@ -31,3 +34,25 @@
 extern struct compressor *lookup_compressor(char *);
 extern struct compressor *lookup_compressor_id(int);
 extern void display_compressors(char *, char *);
+extern void display_compressor_usage(char *);
+
+static inline int compressor_options(struct compressor *comp, char *argv[],
+	int argc)
+{
+	if(comp->options == NULL)
+		return -1;
+
+	return comp->options(argv, argc);
+}
+
+
+static inline int compressor_init(struct compressor *comp, void **stream,
+	int block_size, int flags)
+{
+	if(comp->init == NULL)
+		return 0;
+	return comp->init(stream, block_size, flags);
+}
+
+
+
diff -r 2ab2996036dd squashfs-tools/gzip_wrapper.c
--- a/squashfs-tools/gzip_wrapper.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/gzip_wrapper.c	Tue Dec 14 14:18:11 2010 +0000
@@ -22,28 +22,48 @@
 #include <stdlib.h>
 #include <zlib.h>
 
-int gzip_compress(void **strm, char *d, char *s, int size, int block_size,
+#include "squashfs_fs.h"
+#include "compressor.h"
+
+static int gzip_init(void **strm, int block_size, int flags)
+{
+	int res;
+	z_stream *stream;
+
+	stream = *strm = malloc(sizeof(z_stream));
+	if(stream == NULL)
+		goto failed;
+
+	stream->zalloc = Z_NULL;
+	stream->zfree = Z_NULL;
+	stream->opaque = 0;
+
+	res = deflateInit(stream, 9);
+	if(res != Z_OK)
+		goto failed2;
+
+	return 0;
+
+failed2:
+	free(stream);
+failed:
+	return -1;
+}
+
+
+static int gzip_compress(void *strm, void *d, void *s, int size, int block_size,
 		int *error)
 {
-	int res = 0;
-	z_stream *stream = *strm;
+	int res;
+	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)
+	res = deflateReset(stream);
+	if(res != Z_OK)
 		goto failed;
 
-	stream->next_in = (unsigned char *) s;
+	stream->next_in = s;
 	stream->avail_in = size;
-	stream->next_out = (unsigned char *) d;
+	stream->next_out = d;
 	stream->avail_out = block_size;
 
 	res = deflate(stream, Z_FINISH);
@@ -67,14 +87,26 @@
 }
 
 
-int gzip_uncompress(char *d, char *s, int size, int block_size, int *error)
+static int gzip_uncompress(void *d, void *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);
+	res = uncompress(d, &bytes, s, size);
 
 	*error = res;
 	return res == Z_OK ? (int) bytes : -1;
 }
+
+
+struct compressor gzip_comp_ops = {
+	.init = gzip_init,
+	.compress = gzip_compress,
+	.uncompress = gzip_uncompress,
+	.options = NULL,
+	.usage = NULL,
+	.id = ZLIB_COMPRESSION,
+	.name = "gzip",
+	.supported = 1
+};
+
diff -r 2ab2996036dd squashfs-tools/lzma_wrapper.c
--- a/squashfs-tools/lzma_wrapper.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/lzma_wrapper.c	Tue Dec 14 14:18:11 2010 +0000
@@ -17,21 +17,27 @@
  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
  * lzma_wrapper.c
+ *
+ * Support for LZMA1 compression using LZMA SDK (4.65 used in
+ * development, other versions may work) http://www.7-zip.org/sdk.html
  */
 
 #include <LzmaLib.h>
 
+#include "squashfs_fs.h"
+#include "compressor.h"
+
 #define LZMA_HEADER_SIZE	(LZMA_PROPS_SIZE + 8)
 
-int lzma_compress(void **strm, char *dest, char *src, int size, int block_size,
+static int lzma_compress(void *strm, void *dest, void *src, int size, int block_size,
 		int *error)
 {
-	unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
+	unsigned char *d = dest;
 	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,
+	res = LzmaCompress(dest + LZMA_HEADER_SIZE, &outlen, src, size, dest,
 		&props_size, 5, block_size, 3, 0, 2, 32, 1);
 	
 	if(res == SZ_ERROR_OUTPUT_EOF) {
@@ -73,10 +79,10 @@
 }
 
 
-int lzma_uncompress(char *dest, char *src, int size, int block_size,
+static int lzma_uncompress(void *dest, void *src, int size, int block_size,
 	int *error)
 {
-	unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
+	unsigned char *s = src;
 	size_t outlen, inlen = size - LZMA_HEADER_SIZE;
 	int res;
 
@@ -85,9 +91,22 @@
 		(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);
+	res = LzmaUncompress(dest, &outlen, src + LZMA_HEADER_SIZE, &inlen, src,
+		LZMA_PROPS_SIZE);
 	
 	*error = res;
 	return res == SZ_OK ? outlen : -1;
 }
+
+
+struct compressor lzma_comp_ops = {
+	.init = NULL,
+	.compress = lzma_compress,
+	.uncompress = lzma_uncompress,
+	.options = NULL,
+	.usage = NULL,
+	.id = LZMA_COMPRESSION,
+	.name = "lzma",
+	.supported = 1
+};
+
diff -r 2ab2996036dd squashfs-tools/lzma_xz_wrapper.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/squashfs-tools/lzma_xz_wrapper.c	Tue Dec 14 14:18:11 2010 +0000
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2010
+ * 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_xz_wrapper.c
+ *
+ * Support for LZMA1 compression using XZ Utils liblzma http://tukaani.org/xz/
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <lzma.h>
+
+#include "squashfs_fs.h"
+#include "compressor.h"
+
+#define LZMA_PROPS_SIZE 5
+#define LZMA_UNCOMP_SIZE 8
+#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE)
+
+#define LZMA_OPTIONS 5
+#define MEMLIMIT (32 * 1024 * 1024)
+
+static int lzma_compress(void *dummy, void *dest, void *src,  int size,
+	int block_size, int *error)
+{
+	unsigned char *d = (unsigned char *) dest;
+	lzma_options_lzma opt;
+	lzma_stream strm = LZMA_STREAM_INIT;
+	int res;
+
+	lzma_lzma_preset(&opt, LZMA_OPTIONS);
+	opt.dict_size = block_size;
+	res = lzma_alone_encoder(&strm, &opt);
+	if(res != LZMA_OK) {
+		lzma_end(&strm);
+		goto failed;
+	}
+
+	strm.next_out = dest;
+	strm.avail_out = block_size;
+	strm.next_in = src;
+	strm.avail_in = size;
+
+	res = lzma_code(&strm, LZMA_FINISH);
+	lzma_end(&strm);
+
+	if(res == LZMA_STREAM_END) {
+		/*
+	 	 * 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;
+
+		return (int) strm.total_out;
+	}
+
+	if(res == LZMA_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;
+}
+
+
+static int lzma_uncompress(void *dest, void *src, int size, int block_size,
+	int *error)
+{
+	lzma_stream strm = LZMA_STREAM_INIT;
+	int uncompressed_size = 0, res;
+	unsigned char lzma_header[LZMA_HEADER_SIZE];
+
+	res = lzma_alone_decoder(&strm, MEMLIMIT);
+	if(res != LZMA_OK) {
+		lzma_end(&strm);
+		goto failed;
+	}
+
+	memcpy(lzma_header, src, LZMA_HEADER_SIZE);
+	uncompressed_size = lzma_header[LZMA_PROPS_SIZE] |
+		(lzma_header[LZMA_PROPS_SIZE + 1] << 8) |
+		(lzma_header[LZMA_PROPS_SIZE + 2] << 16) |
+		(lzma_header[LZMA_PROPS_SIZE + 3] << 24);
+	memset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE);
+
+	strm.next_out = dest;
+	strm.avail_out = block_size;
+	strm.next_in = lzma_header;
+	strm.avail_in = LZMA_HEADER_SIZE;
+
+	res = lzma_code(&strm, LZMA_RUN);
+
+	if(res != LZMA_OK || strm.avail_in != 0) {
+		lzma_end(&strm);
+		goto failed;
+	}
+
+	strm.next_in = src + LZMA_HEADER_SIZE;
+	strm.avail_in = size - LZMA_HEADER_SIZE;
+
+	res = lzma_code(&strm, LZMA_FINISH);
+	lzma_end(&strm);
+
+	if(res == LZMA_STREAM_END || (res == LZMA_OK &&
+		strm.total_out >= uncompressed_size && strm.avail_in == 0))
+		return uncompressed_size;
+
+failed:
+	*error = res;
+	return -1;
+}
+
+
+struct compressor lzma_comp_ops = {
+	.init = NULL,
+	.compress = lzma_compress,
+	.uncompress = lzma_uncompress,
+	.options = NULL,
+	.usage = NULL,
+	.id = LZMA_COMPRESSION,
+	.name = "lzma",
+	.supported = 1
+};
+
diff -r 2ab2996036dd squashfs-tools/lzo_wrapper.c
--- a/squashfs-tools/lzo_wrapper.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/lzo_wrapper.c	Tue Dec 14 14:18:11 2010 +0000
@@ -2,6 +2,9 @@
  * Copyright (c) 2010 LG Electronics
  * Chan Jeong <chan.jeong@lge.com>
  *
+ * All modifications Copyright (c) 2010
+ * 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,
@@ -25,6 +28,9 @@
 #include <lzo/lzoconf.h>
 #include <lzo/lzo1x.h>
 
+#include "squashfs_fs.h"
+#include "compressor.h"
+
 /* worst-case expansion calculation during compression,
    see LZO FAQ for more information */
 #define LZO_OUTPUT_BUFFER_SIZE(size)	(size + (size/16) + 64 + 3)
@@ -34,25 +40,39 @@
 	lzo_bytep out;
 };
 
-int lzo_compress(void **strm, char *d, char *s, int size, int block_size,
+
+static int squashfs_lzo_init(void **strm, int block_size, int flags)
+{
+	struct lzo_stream *stream;
+
+	if((stream = *strm = malloc(sizeof(struct lzo_stream))) == NULL)
+		goto failed;
+	/* work memory for compression */
+	if((stream->wrkmem = malloc(LZO1X_999_MEM_COMPRESS)) == NULL)
+		goto failed2;
+	/* temporal output buffer */
+	if((stream->out = malloc(LZO_OUTPUT_BUFFER_SIZE(block_size))) == NULL)
+		goto failed3;
+
+	return 0;
+
+failed3:
+	free(stream->wrkmem);
+failed2:
+	free(stream);
+failed:
+	return -1;
+}
+
+
+static int lzo_compress(void *strm, void *d, void *s, int size, int block_size,
 		int *error)
 {
-	int res = 0;
+	int res;
 	lzo_uint outlen;
-	struct lzo_stream *stream = *strm;
+	struct lzo_stream *stream = strm;
 
-	if(stream == NULL) {
-		if((stream = *strm = malloc(sizeof(struct lzo_stream))) == NULL)
-			goto failed;
-		/* work memory for compression */
-		if((stream->wrkmem = malloc(LZO1X_999_MEM_COMPRESS)) == NULL)
-			goto failed;
-		/* temporal output buffer */
-		if((stream->out = malloc(LZO_OUTPUT_BUFFER_SIZE(block_size))) == NULL)
-			goto failed;
-	}
-
-	res = lzo1x_999_compress((lzo_bytep)s, size, stream->out, &outlen, stream->wrkmem);
+	res = lzo1x_999_compress(s, size, stream->out, &outlen, stream->wrkmem);
 	if(res != LZO_E_OK)
 		goto failed;
 	if(outlen >= size)
@@ -77,13 +97,26 @@
 }
 
 
-int lzo_uncompress(char *d, char *s, int size, int block_size, int *error)
+static int lzo_uncompress(void *d, void *s, int size, int block_size, int *error)
 {
 	int res;
 	lzo_uint bytes = block_size;
 
-	res = lzo1x_decompress_safe((lzo_bytep)s, size, (lzo_bytep)d, &bytes, NULL);
+	res = lzo1x_decompress_safe(s, size, d, &bytes, NULL);
 
 	*error = res;
 	return res == LZO_E_OK ? bytes : -1;
 }
+
+
+struct compressor lzo_comp_ops = {
+	.init = squashfs_lzo_init,
+	.compress = lzo_compress,
+	.uncompress = lzo_uncompress,
+	.options = NULL,
+	.usage = NULL,
+	.id = LZO_COMPRESSION,
+	.name = "lzo",
+	.supported = 1
+};
+
diff -r 2ab2996036dd squashfs-tools/mksquashfs.c
--- a/squashfs-tools/mksquashfs.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/mksquashfs.c	Tue Dec 14 14:18:11 2010 +0000
@@ -384,9 +384,10 @@
 #define FRAGMENT_BUFFER_DEFAULT 64
 int writer_buffer_size;
 
-/* compression operations structure */
+/* compression operations */
 static struct compressor *comp;
-char *comp_name = COMP_DEFAULT;
+int compressor_opts_parsed = 0;
+void *stream = NULL;
 
 /* xattr stats */
 unsigned int xattr_bytes = 0, total_xattr_bytes = 0;
@@ -859,7 +860,7 @@
 }
 
 
-int mangle2(void **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)
 {
 	int error, c_byte = 0;
@@ -884,9 +885,7 @@
 int mangle(char *d, char *s, int size, int block_size,
 	int uncompressed, int data_block)
 {
-	static void *stream = NULL;
-
-	return mangle2(&stream, d, s, size, block_size, uncompressed,
+	return mangle2(stream, d, s, size, block_size, uncompressed,
 		data_block);
 }
 
@@ -2556,11 +2555,15 @@
 void *deflator(void *arg)
 {
 	void *stream = NULL;
-	int oldstate;
+	int res, oldstate;
 
 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
 
+	res = compressor_init(comp, &stream, block_size, 1);
+	if(res)
+		BAD_ERROR("deflator:: compressor_init failed\n");
+
 	while(1) {
 		struct file_buffer *file_buffer = queue_get(from_reader);
 		struct file_buffer *write_buffer;
@@ -2573,7 +2576,7 @@
 			queue_put(from_deflate, file_buffer);
 		} else {
 			write_buffer = cache_get(writer_buffer, 0, 0);
-			write_buffer->c_byte = mangle2(&stream,
+			write_buffer->c_byte = mangle2(stream,
 				write_buffer->data, file_buffer->data,
 				file_buffer->size, block_size, noD, 1);
 			write_buffer->sequence = file_buffer->sequence;
@@ -2593,11 +2596,15 @@
 void *frag_deflator(void *arg)
 {
 	void *stream = NULL;
-	int oldstate;
+	int res, oldstate;
 
 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
 
+	res = compressor_init(comp, &stream, block_size, 1);
+	if(res)
+		BAD_ERROR("frag_deflator:: compressor_init failed\n");
+
 	while(1) {
 		int c_byte, compressed_size;
 		struct file_buffer *file_buffer = queue_get(to_frag);
@@ -2605,7 +2612,7 @@
 			cache_get(writer_buffer, file_buffer->block +
 			FRAG_INDEX, 1);
 
-		c_byte = mangle2(&stream, write_buffer->data, file_buffer->data,
+		c_byte = mangle2(stream, write_buffer->data, file_buffer->data,
 			file_buffer->size, block_size, noF, 1);
 		compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
 		write_buffer->size = compressed_size;
@@ -4501,7 +4508,7 @@
 
 
 #define VERSION() \
-	printf("mksquashfs version 4.1 (2010/09/19)\n");\
+	printf("mksquashfs version 4.1-CVS (2010/12/07)\n");\
 	printf("copyright (C) 2010 Phillip Lougher "\
 		"<phillip@lougher.demon.co.uk>\n\n"); \
 	printf("This program is free software; you can redistribute it and/or"\
@@ -4521,7 +4528,7 @@
 int main(int argc, char *argv[])
 {
 	struct stat buf, source_buf;
-	int i;
+	int res, i;
 	squashfs_super_block sBlk;
 	char *b, *root_name = NULL;
 	int nopad = FALSE, keep_as_directory = FALSE;
@@ -4542,14 +4549,50 @@
 		goto printOptions;
 	source_path = argv + 1;
 	source = i - 2;
+	/*
+	 * lookup default compressor.  Note the Makefile ensures the default
+	 * compressor has been built, and so we don't need to to check
+	 * for failure here
+	 */
+	comp = lookup_compressor(COMP_DEFAULT);
 	for(; i < argc; i++) {
 		if(strcmp(argv[i], "-comp") == 0) {
+			if(compressor_opts_parsed) {
+				ERROR("%s: -comp must appear before -X options"
+					"\n", argv[0]);
+				exit(1);
+			}
 			if(++i == argc) {
 				ERROR("%s: -comp missing compression type\n",
 					argv[0]);
 				exit(1);
 			}
-			comp_name = argv[i];
+			comp = lookup_compressor(argv[i]);
+			if(!comp->supported) {
+				ERROR("%s: Compressor \"%s\" is not supported!"
+					"\n", argv[0], argv[i]);
+				ERROR("%s: Compressors available:\n", argv[0]);
+				display_compressors("", COMP_DEFAULT);
+				exit(1);
+			}
+
+		} else if(strncmp(argv[i], "-X", 2) == 0) {
+			int args = compressor_options(comp, argv + i, argc - i);
+			if(args < 0) {
+				if(args == -1) {
+					ERROR("%s: Unrecognised compressor"
+						" option %s\n", argv[0],
+						argv[i]);
+					ERROR("%s: Did you forget to specify"
+						" -comp, or specify it after"
+						" the compressor specific"
+						" option?\n", argv[0]);
+					}
+				exit(1);
+			}
+			i += args;
+			compressor_opts_parsed = 1;
+
 		} else if(strcmp(argv[i], "-pf") == 0) {
 			if(++i == argc) {
 				ERROR("%s: -pf missing filename\n", argv[0]);
@@ -4857,7 +4900,7 @@
 			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 "
+			ERROR("-fragment-queue <size>\tSet fragment queue to "
 				"<size> Mbytes.  Default %d Mbytes\n",
 				FRAGMENT_BUFFER_DEFAULT);
 			ERROR("\nMiscellaneous options:\n");
@@ -4871,8 +4914,9 @@
 				"-noF\n");
 			ERROR("-noXattrCompression\talternative name for "
 				"-noX\n");
-			ERROR("\nCompressors available:\n");
-			display_compressors("", COMP_DEFAULT);
+			ERROR("\nCompressors available and compressor specific "
+				"options:\n");
+			display_compressor_usage(COMP_DEFAULT);
 			exit(1);
 		}
 	}
@@ -5005,19 +5049,14 @@
 		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(readb_mbytes, writeb_mbytes, fragmentb_mbytes);
 
+	res = compressor_init(comp, &stream, SQUASHFS_METADATA_SIZE, 0);
+	if(res)
+		BAD_ERROR("compressor_init failed\n");
+
 	if(delete) {
 		printf("Creating %d.%d filesystem on %s, block size %d.\n",
 			SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size);
diff -r 2ab2996036dd squashfs-tools/read_fs.c
--- a/squashfs-tools/read_fs.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/read_fs.c	Tue Dec 14 14:18:11 2010 +0000
@@ -363,7 +363,8 @@
 		}
 	}
 	
-	return files;
+	printf("Read existing filesystem, %d inodes scanned\n", files);
+	return TRUE;
 
 
 failed:
@@ -414,6 +415,7 @@
 	if(!comp->supported) {
 		ERROR("Filesystem on %s uses %s compression, this is"
 			"unsupported by this version\n", source, comp->name);
+		ERROR("Compressors available:\n");
 		display_compressors("", "");
 		goto failed_mount;
 	}
@@ -691,7 +693,7 @@
 		SQUASHFS_INODE_BLK(sBlk->root_inode);
 	unsigned int root_inode_offset =
 		SQUASHFS_INODE_OFFSET(sBlk->root_inode);
-	unsigned int root_inode_block, files;
+	unsigned int root_inode_block;
 	squashfs_inode_header inode;
 	unsigned int *id_table;
 	int res;
@@ -711,20 +713,18 @@
 	if(id_table == NULL)
 		goto error;
 
-	if((files = scan_inode_table(fd, start, end, root_inode_start,
-			root_inode_offset, sBlk, &inode, &inode_table,
-			&root_inode_block, root_inode_size, uncompressed_file,
-			uncompressed_directory, file_count, sym_count,
-			dev_count, dir_count, fifo_count, sock_count, id_table))
-			== 0) {
+	res = scan_inode_table(fd, start, end, root_inode_start,
+		root_inode_offset, sBlk, &inode, &inode_table,
+		&root_inode_block, root_inode_size, uncompressed_file,
+		uncompressed_directory, file_count, sym_count, dev_count,
+		dir_count, fifo_count, sock_count, id_table);
+	if(res == 0) {
 		ERROR("read_filesystem: inode table read failed\n");
 		goto error;
 	}
 
 	*uncompressed_inode = root_inode_block;
 
-	printf("Read existing filesystem, %d inodes scanned\n", files);
-
 	if(inode.base.inode_type == SQUASHFS_DIR_TYPE ||
 			inode.base.inode_type == SQUASHFS_LDIR_TYPE) {
 		if(inode.base.inode_type == SQUASHFS_DIR_TYPE) {
diff -r 2ab2996036dd squashfs-tools/squashfs_fs.h
--- a/squashfs-tools/squashfs_fs.h	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/squashfs_fs.h	Tue Dec 14 14:18:11 2010 +0000
@@ -259,6 +259,7 @@
 #define ZLIB_COMPRESSION	1
 #define LZMA_COMPRESSION	2
 #define LZO_COMPRESSION		3
+#define XZ_COMPRESSION		4
 
 struct squashfs_super_block {
 	unsigned int		s_magic;
diff -r 2ab2996036dd squashfs-tools/unsquash-1.c
--- a/squashfs-tools/unsquash-1.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/unsquash-1.c	Tue Dec 14 14:18:11 2010 +0000
@@ -138,7 +138,7 @@
 
 			i.data = inode->file_size;
 			i.time = inode->mtime;
-			i.blocks = (inode->file_size + sBlk.s.block_size - 1) >>
+			i.blocks = (i.data + sBlk.s.block_size - 1) >>
 				sBlk.s.block_log;
 			i.start = inode->start_block;
 			i.block_ptr = block_ptr + sizeof(*inode);
diff -r 2ab2996036dd squashfs-tools/unsquash-2.c
--- a/squashfs-tools/unsquash-2.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/unsquash-2.c	Tue Dec 14 14:18:11 2010 +0000
@@ -205,8 +205,8 @@
 			i.fragment = inode->fragment;
 			i.offset = inode->offset;
 			i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ?
-				(inode->file_size + sBlk.s.block_size - 1) >>
-				sBlk.s.block_log : inode->file_size >>
+				(i.data + sBlk.s.block_size - 1) >>
+				sBlk.s.block_log : i.data >>
 				sBlk.s.block_log;
 			i.start = inode->start_block;
 			i.sparse = 0;
diff -r 2ab2996036dd squashfs-tools/unsquash-3.c
--- a/squashfs-tools/unsquash-3.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/unsquash-3.c	Tue Dec 14 14:18:11 2010 +0000
@@ -188,9 +188,9 @@
 			i.fragment = inode->fragment;
 			i.offset = inode->offset;
 			i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ?
-				(inode->file_size + sBlk.s.block_size - 1) >>
+				(i.data + sBlk.s.block_size - 1) >>
 				sBlk.s.block_log :
-				inode->file_size >> sBlk.s.block_log;
+				i.data >> sBlk.s.block_log;
 			i.start = inode->start_block;
 			i.sparse = 1;
 			i.block_ptr = block_ptr + sizeof(*inode);
diff -r 2ab2996036dd squashfs-tools/unsquash-4.c
--- a/squashfs-tools/unsquash-4.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/unsquash-4.c	Tue Dec 14 14:18:11 2010 +0000
@@ -143,9 +143,9 @@
 			i.fragment = inode->fragment;
 			i.offset = inode->offset;
 			i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ?
-				(inode->file_size + sBlk.s.block_size - 1) >>
+				(i.data + sBlk.s.block_size - 1) >>
 				sBlk.s.block_log :
-				inode->file_size >> sBlk.s.block_log;
+				i.data >> sBlk.s.block_log;
 			i.start = inode->start_block;
 			i.sparse = 0;
 			i.block_ptr = block_ptr + sizeof(*inode);
diff -r 2ab2996036dd squashfs-tools/unsquashfs.c
--- a/squashfs-tools/unsquashfs.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/unsquashfs.c	Tue Dec 14 14:18:11 2010 +0000
@@ -737,7 +737,7 @@
 int lseek_broken = FALSE;
 char *zero_data = NULL;
 
-int write_block(int file_fd, char *buffer, int size, int hole, int sparse)
+int write_block(int file_fd, char *buffer, int size, long long hole, int sparse)
 {
 	off_t off = hole;
 
@@ -1299,9 +1299,12 @@
 		print_filename(parent_name, i);
 
 	if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 &&
-			(!force || errno != EEXIST))
-		ERROR("dir_scan: failed to open directory %s, because %s\n",
+			(!force || errno != EEXIST)) {
+		ERROR("dir_scan: failed to make directory %s, because %s\n",
 			parent_name, strerror(errno));
+		squashfs_closedir(dir);
+		return;
+	}
 
 	while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) {
 		TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n",
@@ -1604,7 +1607,7 @@
 	while(1) {
 		struct squashfs_file *file = queue_get(to_writer);
 		int file_fd;
-		int hole = 0;
+		long long hole = 0;
 		int failed = FALSE;
 		int error;
 
@@ -1903,7 +1906,7 @@
 
 
 #define VERSION() \
-	printf("unsquashfs version 4.1 (2010/09/19)\n");\
+	printf("unsquashfs version 4.1-CVS (2010/10/23)\n");\
 	printf("copyright (C) 2010 Phillip Lougher "\
 		"<phillip@lougher.demon.co.uk>\n\n");\
     	printf("This program is free software; you can redistribute it and/or"\
@@ -2081,7 +2084,7 @@
 			ERROR("\t-da[ta-queue] <size>\tSet data queue to "
 				"<size> Mbytes.  Default %d\n\t\t\t\tMbytes\n",
 				DATA_BUFFER_DEFAULT);
-			ERROR("\t-fr[ag-queue] <size>\tSet fagment queue to "
+			ERROR("\t-fr[ag-queue] <size>\tSet fragment queue to "
 				"<size> Mbytes.  Default %d\n\t\t\t\t Mbytes\n",
 				FRAGMENT_BUFFER_DEFAULT);
 			ERROR("\t-r[egex]\t\ttreat extract names as POSIX "
diff -r 2ab2996036dd squashfs-tools/unsquashfs_xattr.c
--- a/squashfs-tools/unsquashfs_xattr.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/unsquashfs_xattr.c	Tue Dec 14 14:18:11 2010 +0000
@@ -25,7 +25,7 @@
 #include "unsquashfs.h"
 #include "xattr.h"
 
-#include <attr/xattr.h>
+#include <sys/xattr.h>
 
 extern int root_process;
 
diff -r 2ab2996036dd squashfs-tools/xattr.c
--- a/squashfs-tools/xattr.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/xattr.c	Tue Dec 14 14:18:11 2010 +0000
@@ -34,7 +34,7 @@
 #include <dirent.h>
 #include <string.h>
 #include <stdlib.h>
-#include <attr/xattr.h>
+#include <sys/xattr.h>
 
 #include "squashfs_fs.h"
 #include "global.h"
@@ -219,6 +219,10 @@
 			break;
 		}
 		xattr_list[i].vsize = vsize;
+
+		TRACE("read_xattrs_from_system: filename %s, xattr name %s,"
+			" vsize %d\n", filename, xattr_list[i].full_name,
+			xattr_list[i].vsize);
 	}
 	free(xattr_names);
 	*xattrs = xattr_list;
diff -r 2ab2996036dd squashfs-tools/xz_wrapper.c
--- a/squashfs-tools/xz_wrapper.c	Tue Dec 14 12:19:33 2010 +0000
+++ b/squashfs-tools/xz_wrapper.c	Tue Dec 14 14:18:11 2010 +0000
@@ -17,69 +17,192 @@
  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
  * xz_wrapper.c
+ *
+ * Support for XZ (LZMA2) compression using XZ Utils liblzma http://tukaani.org/xz/
  */
 
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 #include <lzma.h>
 
-#define LZMA_PROPS_SIZE 5
-#define LZMA_UNCOMP_SIZE 8
-#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE)
+#include "squashfs_fs.h"
+#include "compressor.h"
 
-#define LZMA_OPTIONS 5
 #define MEMLIMIT (32 * 1024 * 1024)
 
-int lzma_compress(void **dummy, void *dest, void *src,  int size,
+static struct bcj {
+	char	 	*name;
+	lzma_vli	id;
+	int		selected;
+} bcj[] = {
+	{ "x86", LZMA_FILTER_X86, 0 },
+	{ "powerpc", LZMA_FILTER_POWERPC, 0 },
+	{ "ia64", LZMA_FILTER_IA64, 0 },
+	{ "arm", LZMA_FILTER_ARM, 0 },
+	{ "armthumb", LZMA_FILTER_ARMTHUMB, 0 },
+	{ "sparc", LZMA_FILTER_SPARC, 0 },
+	{ NULL, LZMA_VLI_UNKNOWN, 0 }
+};
+
+struct filter {
+	void		*buffer;
+	lzma_filter	filter[3];
+	size_t		length;
+};
+
+struct xz_stream {
+	struct filter	*filter;
+	int		filters;
+	lzma_options_lzma opt;
+};
+
+static int filter_count = 1;
+
+
+static int xz_options(char *argv[], int argc)
+{
+	int i;
+	char *name;
+
+	if(strcmp(argv[0], "-Xbcj") == 0) {
+		if(argc < 2) {
+			fprintf(stderr, "xz: -Xbcj missing filter\n");
+			goto failed;
+		}
+
+		name = argv[1];
+		while(name[0] != '\0') {
+			for(i = 0; bcj[i].name; i++) {
+				int n = strlen(bcj[i].name);
+				if((strncmp(name, bcj[i].name, n) == 0) &&
+						(name[n] == '\0' ||
+						 name[n] == ',')) {
+					if(bcj[i].selected == 0) {
+				 		bcj[i].selected = 1;
+						filter_count++;
+					}
+					name += name[n] == ',' ? n + 1 : n;
+					break;
+				}
+			}
+			if(bcj[i].name == NULL) {
+				fprintf(stderr, "xz: -Xbcj unrecognised filter\n");
+				goto failed;
+			}
+		}
+	
+		return 1;
+	}
+
+	return -1;
+	
+failed:
+	return -2;
+}
+		
+
+void xz_usage()
+{
+	fprintf(stderr, "\t  -Xbcj filter1,filter2,...,filterN\n");
+	fprintf(stderr, "\t\tCompress using filter1,filter2,...,filterN in");
+	fprintf(stderr, " turn\n\t\t(in addition to no filter), and choose");
+	fprintf(stderr, " the best compression.\n");
+	fprintf(stderr, "\t\tAvailable filters: x86, arm, armthumb,");
+	fprintf(stderr, " powerpc, sparc, ia64\n");
+}
+
+
+static int xz_init(void **strm, int block_size, int flags)
+{
+	int i, j, filters = flags ? filter_count : 1;
+	struct filter *filter = malloc(filters * sizeof(struct filter));
+	struct xz_stream *stream;
+
+	if(filter == NULL)
+		goto failed;
+
+	stream = *strm = malloc(sizeof(struct xz_stream));
+	if(stream == NULL)
+		goto failed2;
+
+	stream->filter = filter;
+	stream->filters = filters;
+
+	memset(filter, 0, filters * sizeof(struct filter));
+
+	filter[0].filter[0].id = LZMA_FILTER_LZMA2;
+	filter[0].filter[0].options = &stream->opt;
+	filter[0].filter[1].id = LZMA_VLI_UNKNOWN;
+
+	for(i = 0, j = 1; flags && bcj[i].name; i++) {
+		if(bcj[i].selected) {
+			filter[j].buffer = malloc(block_size);
+			if(filter[j].buffer == NULL)
+				goto failed3;
+			filter[j].filter[0].id = bcj[i].id;
+			filter[j].filter[1].id = LZMA_FILTER_LZMA2;
+			filter[j].filter[1].options = &stream->opt;
+			filter[j].filter[2].id = LZMA_VLI_UNKNOWN;
+			j++;
+		}
+	}
+
+	return 0;
+
+failed3:
+	for(i = 1; i < filters; i++)
+		free(filter[i].buffer);
+	free(stream);
+
+failed2:
+	free(filter);
+
+failed:
+	return -1;
+}
+
+
+static int xz_compress(void *strm, void *dest, void *src,  int size,
 	int block_size, int *error)
 {
-	unsigned char *d = (unsigned char *) dest;
-	lzma_options_lzma opt;
-	lzma_stream strm = LZMA_STREAM_INIT;
-	int res;
+	int i;
+        lzma_ret res = 0;
+	struct xz_stream *stream = strm;
+	struct filter *selected = NULL;
 
-	lzma_lzma_preset(&opt, LZMA_OPTIONS);
-	opt.dict_size = block_size;
-	res = lzma_alone_encoder(&strm, &opt);
-	if(res != LZMA_OK) {
-		lzma_end(&strm);
-		goto failed;
+	stream->filter[0].buffer = dest;
+
+	for(i = 0; i < stream->filters; i++) {
+		struct filter *filter = &stream->filter[i];
+
+        	if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT))
+                	goto failed;
+
+		stream->opt.dict_size = block_size;
+		filter->length = 0;
+		res = lzma_stream_buffer_encode(filter->filter,
+			LZMA_CHECK_CRC32, NULL, src, size, filter->buffer,
+			&filter->length, block_size);
+	
+		if(res == LZMA_OK) {
+			if(!selected || selected->length > filter->length)
+				selected = filter;
+		} else if(res != LZMA_BUF_ERROR)
+			goto failed;
 	}
 
-	strm.next_out = dest;
-	strm.avail_out = block_size;
-	strm.next_in = src;
-	strm.avail_in = size;
-
-	res = lzma_code(&strm, LZMA_FINISH);
-	lzma_end(&strm);
-
-	if(res == LZMA_STREAM_END) {
-		/*
-	 	 * 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;
-
-		return (int) strm.total_out;
-	}
-
-	if(res == LZMA_OK)
+	if(!selected)
 		/*
 	 	 * Output buffer overflow.  Return out of buffer space
 	 	 */
 		return 0;
 
+	if(selected->buffer != dest)
+		memcpy(dest, selected->buffer, selected->length);
+
+	return (int) selected->length;
+
 failed:
 	/*
 	 * All other errors return failure, with the compressor
@@ -90,49 +213,29 @@
 }
 
 
-int lzma_uncompress(void *dest, void *src, int size, int block_size,
+static int xz_uncompress(void *dest, void *src, int size, int block_size,
 	int *error)
 {
-	lzma_stream strm = LZMA_STREAM_INIT;
-	int uncompressed_size = 0, res;
-	unsigned char lzma_header[LZMA_HEADER_SIZE];
+	size_t src_pos = 0;
+	size_t dest_pos = 0;
+	uint64_t memlimit = MEMLIMIT;
 
-	res = lzma_alone_decoder(&strm, MEMLIMIT);
-	if(res != LZMA_OK) {
-		lzma_end(&strm);
-		goto failed;
-	}
+	lzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL,
+			src, &src_pos, size, dest, &dest_pos, block_size);
 
-	memcpy(lzma_header, src, LZMA_HEADER_SIZE);
-	uncompressed_size = lzma_header[LZMA_PROPS_SIZE] |
-		(lzma_header[LZMA_PROPS_SIZE + 1] << 8) |
-		(lzma_header[LZMA_PROPS_SIZE + 2] << 16) |
-		(lzma_header[LZMA_PROPS_SIZE + 3] << 24);
-	memset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE);
+	*error = res;
+	return res == LZMA_OK && size == (int) src_pos ? (int) dest_pos : -1;
+}
 
-	strm.next_out = dest;
-	strm.avail_out = block_size;
-	strm.next_in = lzma_header;
-	strm.avail_in = LZMA_HEADER_SIZE;
 
-	res = lzma_code(&strm, LZMA_RUN);
+struct compressor xz_comp_ops = {
+	.init = xz_init,
+	.compress = xz_compress,
+	.uncompress = xz_uncompress,
+	.options = xz_options,
+	.usage = xz_usage,
+	.id = XZ_COMPRESSION,
+	.name = "xz",
+	.supported = 1
+};
 
-	if(res != LZMA_OK || strm.avail_in != 0) {
-		lzma_end(&strm);
-		goto failed;
-	}
-
-	strm.next_in = src + LZMA_HEADER_SIZE;
-	strm.avail_in = size - LZMA_HEADER_SIZE;
-
-	res = lzma_code(&strm, LZMA_FINISH);
-	lzma_end(&strm);
-
-	if(res == LZMA_STREAM_END || (res == LZMA_OK &&
-		strm.total_out >= uncompressed_size && strm.avail_in == 0))
-		return uncompressed_size;
-
-failed:
-	*error = res;
-	return -1;
-}
