wok-current rev 7649

Add xz to squashfs tools.
author Christopher Rogers <slaxemulator@gmail.com>
date Tue Dec 14 21:34:46 2010 +0000 (2010-12-14)
parents f99ea44cc9f6
children 1bea914df3b9
files squashfs/receipt squashfs/stuff/xz.patch
line diff
     1.1 --- a/squashfs/receipt	Tue Dec 14 21:27:30 2010 +0000
     1.2 +++ b/squashfs/receipt	Tue Dec 14 21:34:46 2010 +0000
     1.3 @@ -16,9 +16,10 @@
     1.4  compile_rules()
     1.5  {
     1.6  	mv ${PACKAGE}${VERSION} $src 2> /dev/null
     1.7 -
     1.8 +	cd $src
     1.9 +	patch -Np1 -i ../stuff/xz.patch
    1.10  	cd $src/squashfs-tools
    1.11 -	sed -i 's|#XZ_SUPPORT = 1|XZ_SUPPORT = 1|g' Makefile
    1.12 +	#sed -i 's|#XZ_SUPPORT = 1|XZ_SUPPORT = 1|g' Makefile
    1.13  	mkdir -p ../_pkg/usr/sbin ../_pkg/sbin
    1.14  	make || return 1
    1.15  	cp mksquashfs ../_pkg/usr/sbin
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/squashfs/stuff/xz.patch	Tue Dec 14 21:34:46 2010 +0000
     2.3 @@ -0,0 +1,1432 @@
     2.4 +diff -r 2ab2996036dd squashfs-tools/Makefile
     2.5 +--- a/squashfs-tools/Makefile	Tue Dec 14 12:19:33 2010 +0000
     2.6 ++++ b/squashfs-tools/Makefile	Tue Dec 14 14:18:11 2010 +0000
     2.7 +@@ -20,20 +20,33 @@
     2.8 + 
     2.9 + ########### Building LZMA support #############
    2.10 + #
    2.11 +-# Both XZ Utils liblzma  (http://tukaani.org/xz/) and LZMA SDK
    2.12 ++# LZMA1 compression.
    2.13 ++#
    2.14 ++# Both XZ Utils liblzma (http://tukaani.org/xz/) and LZMA SDK
    2.15 + # (http://www.7-zip.org/sdk.html) are supported
    2.16 + #
    2.17 + # To build using XZ Utils liblzma - install the library and uncomment
    2.18 +-# the XZ_SUPPORT line below.
    2.19 ++# the LZMA_XZ_SUPPORT line below.
    2.20 + #
    2.21 + # To build using the LZMA SDK (4.65 used in development, other versions may
    2.22 + # work) - download and unpack it, uncomment and set LZMA_DIR to unpacked source,
    2.23 + # and uncomment the LZMA_SUPPORT line below.
    2.24 + #
    2.25 +-#XZ_SUPPORT = 1
    2.26 ++LZMA_XZ_SUPPORT = 1
    2.27 + #LZMA_SUPPORT = 1
    2.28 + #LZMA_DIR = ../../../LZMA/lzma465
    2.29 + 
    2.30 ++########### Building XZ support #############
    2.31 ++#
    2.32 ++# LZMA2 compression.
    2.33 ++#
    2.34 ++# XZ Utils liblzma (http://tukaani.org/xz/) is supported
    2.35 ++#
    2.36 ++# To build using XZ Utils liblzma - install the library and uncomment
    2.37 ++# the XZ_SUPPORT line below.
    2.38 ++#
    2.39 ++XZ_SUPPORT = 1
    2.40 ++
    2.41 + 
    2.42 + ############ Building LZO support ##############
    2.43 + #
    2.44 +@@ -109,12 +122,20 @@
    2.45 + COMPRESSORS += lzma
    2.46 + endif
    2.47 + 
    2.48 ++ifdef LZMA_XZ_SUPPORT
    2.49 ++CFLAGS += -DLZMA_SUPPORT
    2.50 ++MKSQUASHFS_OBJS += lzma_xz_wrapper.o
    2.51 ++UNSQUASHFS_OBJS += lzma_xz_wrapper.o
    2.52 ++LIBS += -llzma
    2.53 ++COMPRESSORS += lzma
    2.54 ++endif
    2.55 ++
    2.56 + ifdef XZ_SUPPORT
    2.57 +-CFLAGS += -DLZMA_SUPPORT
    2.58 ++CFLAGS += -DXZ_SUPPORT
    2.59 + MKSQUASHFS_OBJS += xz_wrapper.o
    2.60 + UNSQUASHFS_OBJS += xz_wrapper.o
    2.61 + LIBS += -llzma
    2.62 +-COMPRESSORS += lzma
    2.63 ++COMPRESSORS += xz
    2.64 + endif
    2.65 + 
    2.66 + ifdef LZO_SUPPORT
    2.67 +@@ -149,11 +170,11 @@
    2.68 + endif
    2.69 + 
    2.70 + #
    2.71 +-# Both XZ_SUPPORT and LZMA_SUPPORT cannot be specified
    2.72 ++# Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified
    2.73 + #
    2.74 +-ifdef XZ_SUPPORT
    2.75 ++ifdef LZMA_XZ_SUPPORT
    2.76 + ifdef LZMA_SUPPORT
    2.77 +-$(error "Both XZ_SUPPORT and LZMA_SUPPORT cannot be specified")
    2.78 ++$(error "Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified")
    2.79 + endif
    2.80 + endif
    2.81 + 
    2.82 +@@ -161,7 +182,7 @@
    2.83 + # At least one compressor must have been selected
    2.84 + #
    2.85 + ifndef COMPRESSORS
    2.86 +-$(error "No compressor selected! Select one or more of GZIP, LZMA, or LZO!")
    2.87 ++$(error "No compressor selected! Select one or more of GZIP, LZMA, XZ or LZO!")
    2.88 + endif
    2.89 + 
    2.90 + #
    2.91 +diff -r 2ab2996036dd squashfs-tools/compressor.c
    2.92 +--- a/squashfs-tools/compressor.c	Tue Dec 14 12:19:33 2010 +0000
    2.93 ++++ b/squashfs-tools/compressor.c	Tue Dec 14 14:18:11 2010 +0000
    2.94 +@@ -25,31 +25,50 @@
    2.95 + #include "compressor.h"
    2.96 + #include "squashfs_fs.h"
    2.97 + 
    2.98 +-extern int gzip_compress(void **, char *, char *, int, int, int *);
    2.99 +-extern int gzip_uncompress(char *, char *, int, int, int *);
   2.100 +-extern int lzma_compress(void **, char *, char *, int, int, int *);
   2.101 +-extern int lzma_uncompress(char *, char *, int, int, int *);
   2.102 +-extern int lzo_compress(void **, char *, char *, int, int, int *);
   2.103 +-extern int lzo_uncompress(char *, char *, int, int, int *);
   2.104 +-
   2.105 +-struct compressor compressor[] = {
   2.106 +-#ifdef GZIP_SUPPORT
   2.107 +-	{ gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 },
   2.108 ++#ifndef GZIP_SUPPORT
   2.109 ++static struct compressor gzip_comp_ops =  {
   2.110 ++	NULL, NULL, NULL, NULL, NULL, ZLIB_COMPRESSION, "gzip", 0
   2.111 ++};
   2.112 + #else
   2.113 +-	{ NULL, NULL, ZLIB_COMPRESSION, "gzip", 0 },
   2.114 +-#endif
   2.115 +-#ifdef LZMA_SUPPORT
   2.116 +-	{ lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 },
   2.117 +-#else
   2.118 +-	{ NULL, NULL, LZMA_COMPRESSION, "lzma", 0 },
   2.119 +-#endif
   2.120 +-#ifdef LZO_SUPPORT
   2.121 +-	{ lzo_compress, lzo_uncompress, LZO_COMPRESSION, "lzo", 1 },
   2.122 +-#else
   2.123 +-	{ NULL, NULL, LZO_COMPRESSION, "lzo", 0 },
   2.124 ++extern struct compressor gzip_comp_ops;
   2.125 + #endif
   2.126 + 
   2.127 +-	{ NULL, NULL , 0, "unknown", 0}
   2.128 ++#ifndef LZMA_SUPPORT
   2.129 ++static struct compressor lzma_comp_ops = {
   2.130 ++	NULL, NULL, NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0
   2.131 ++};
   2.132 ++#else
   2.133 ++extern struct compressor lzma_comp_ops;
   2.134 ++#endif
   2.135 ++
   2.136 ++#ifndef LZO_SUPPORT
   2.137 ++static struct compressor lzo_comp_ops = {
   2.138 ++	NULL, NULL, NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0
   2.139 ++};
   2.140 ++#else
   2.141 ++extern struct compressor lzo_comp_ops;
   2.142 ++#endif
   2.143 ++
   2.144 ++#ifndef XZ_SUPPORT
   2.145 ++static struct compressor xz_comp_ops = {
   2.146 ++	NULL, NULL, NULL, NULL, NULL, XZ_COMPRESSION, "xz", 0
   2.147 ++};
   2.148 ++#else
   2.149 ++extern struct compressor xz_comp_ops;
   2.150 ++#endif
   2.151 ++
   2.152 ++
   2.153 ++static struct compressor unknown_comp_ops = {
   2.154 ++	NULL, NULL, NULL , NULL, NULL, 0, "unknown", 0
   2.155 ++};
   2.156 ++
   2.157 ++
   2.158 ++struct compressor *compressor[] = {
   2.159 ++	&gzip_comp_ops,
   2.160 ++	&lzma_comp_ops,
   2.161 ++	&lzo_comp_ops,
   2.162 ++	&xz_comp_ops,
   2.163 ++	&unknown_comp_ops
   2.164 + };
   2.165 + 
   2.166 + 
   2.167 +@@ -57,11 +76,11 @@
   2.168 + {
   2.169 + 	int i;
   2.170 + 
   2.171 +-	for(i = 0; compressor[i].id; i++)
   2.172 +-		if(strcmp(compressor[i].name, name) == 0)
   2.173 ++	for(i = 0; compressor[i]->id; i++)
   2.174 ++		if(strcmp(compressor[i]->name, name) == 0)
   2.175 + 			break;
   2.176 + 
   2.177 +-	return &compressor[i];
   2.178 ++	return compressor[i];
   2.179 + }
   2.180 + 
   2.181 + 
   2.182 +@@ -69,11 +88,11 @@
   2.183 + {
   2.184 + 	int i;
   2.185 + 
   2.186 +-	for(i = 0; compressor[i].id; i++)
   2.187 +-		if(id == compressor[i].id)
   2.188 ++	for(i = 0; compressor[i]->id; i++)
   2.189 ++		if(id == compressor[i]->id)
   2.190 + 			break;
   2.191 + 
   2.192 +-	return &compressor[i];
   2.193 ++	return compressor[i];
   2.194 + }
   2.195 + 
   2.196 + 
   2.197 +@@ -81,10 +100,29 @@
   2.198 + {
   2.199 + 	int i;
   2.200 + 
   2.201 +-	for(i = 0; compressor[i].id; i++)
   2.202 +-		if(compressor[i].supported)
   2.203 ++	for(i = 0; compressor[i]->id; i++)
   2.204 ++		if(compressor[i]->supported)
   2.205 + 			fprintf(stderr, "%s\t%s%s\n", indent,
   2.206 +-				compressor[i].name,
   2.207 +-				strcmp(compressor[i].name, def_comp) == 0 ?
   2.208 ++				compressor[i]->name,
   2.209 ++				strcmp(compressor[i]->name, def_comp) == 0 ?
   2.210 + 				" (default)" : "");
   2.211 + }
   2.212 ++
   2.213 ++
   2.214 ++void display_compressor_usage(char *def_comp)
   2.215 ++{
   2.216 ++	int i;
   2.217 ++
   2.218 ++	for(i = 0; compressor[i]->id; i++)
   2.219 ++		if(compressor[i]->supported) {
   2.220 ++			char *str = strcmp(compressor[i]->name, def_comp) == 0 ?
   2.221 ++				" (default)" : "";
   2.222 ++			if(compressor[i]->usage) {
   2.223 ++				fprintf(stderr, "\t%s%s\n",
   2.224 ++					compressor[i]->name, str);
   2.225 ++				compressor[i]->usage();
   2.226 ++			} else
   2.227 ++				fprintf(stderr, "\t%s (no options)%s\n",
   2.228 ++					compressor[i]->name, str);
   2.229 ++		}
   2.230 ++}
   2.231 +diff -r 2ab2996036dd squashfs-tools/compressor.h
   2.232 +--- a/squashfs-tools/compressor.h	Tue Dec 14 12:19:33 2010 +0000
   2.233 ++++ b/squashfs-tools/compressor.h	Tue Dec 14 14:18:11 2010 +0000
   2.234 +@@ -21,8 +21,11 @@
   2.235 +  */
   2.236 + 
   2.237 + struct compressor {
   2.238 +-	int (*compress)(void **, char *, char *, int, int, int *);
   2.239 +-	int (*uncompress)(char *, char *, int, int, int *);
   2.240 ++	int (*init)(void **, int, int);
   2.241 ++	int (*compress)(void *, void *, void *, int, int, int *);
   2.242 ++	int (*uncompress)(void *, void *, int, int, int *);
   2.243 ++	int (*options)(char **, int);
   2.244 ++	void (*usage)();
   2.245 + 	int id;
   2.246 + 	char *name;
   2.247 + 	int supported;
   2.248 +@@ -31,3 +34,25 @@
   2.249 + extern struct compressor *lookup_compressor(char *);
   2.250 + extern struct compressor *lookup_compressor_id(int);
   2.251 + extern void display_compressors(char *, char *);
   2.252 ++extern void display_compressor_usage(char *);
   2.253 ++
   2.254 ++static inline int compressor_options(struct compressor *comp, char *argv[],
   2.255 ++	int argc)
   2.256 ++{
   2.257 ++	if(comp->options == NULL)
   2.258 ++		return -1;
   2.259 ++
   2.260 ++	return comp->options(argv, argc);
   2.261 ++}
   2.262 ++
   2.263 ++
   2.264 ++static inline int compressor_init(struct compressor *comp, void **stream,
   2.265 ++	int block_size, int flags)
   2.266 ++{
   2.267 ++	if(comp->init == NULL)
   2.268 ++		return 0;
   2.269 ++	return comp->init(stream, block_size, flags);
   2.270 ++}
   2.271 ++
   2.272 ++
   2.273 ++
   2.274 +diff -r 2ab2996036dd squashfs-tools/gzip_wrapper.c
   2.275 +--- a/squashfs-tools/gzip_wrapper.c	Tue Dec 14 12:19:33 2010 +0000
   2.276 ++++ b/squashfs-tools/gzip_wrapper.c	Tue Dec 14 14:18:11 2010 +0000
   2.277 +@@ -22,28 +22,48 @@
   2.278 + #include <stdlib.h>
   2.279 + #include <zlib.h>
   2.280 + 
   2.281 +-int gzip_compress(void **strm, char *d, char *s, int size, int block_size,
   2.282 ++#include "squashfs_fs.h"
   2.283 ++#include "compressor.h"
   2.284 ++
   2.285 ++static int gzip_init(void **strm, int block_size, int flags)
   2.286 ++{
   2.287 ++	int res;
   2.288 ++	z_stream *stream;
   2.289 ++
   2.290 ++	stream = *strm = malloc(sizeof(z_stream));
   2.291 ++	if(stream == NULL)
   2.292 ++		goto failed;
   2.293 ++
   2.294 ++	stream->zalloc = Z_NULL;
   2.295 ++	stream->zfree = Z_NULL;
   2.296 ++	stream->opaque = 0;
   2.297 ++
   2.298 ++	res = deflateInit(stream, 9);
   2.299 ++	if(res != Z_OK)
   2.300 ++		goto failed2;
   2.301 ++
   2.302 ++	return 0;
   2.303 ++
   2.304 ++failed2:
   2.305 ++	free(stream);
   2.306 ++failed:
   2.307 ++	return -1;
   2.308 ++}
   2.309 ++
   2.310 ++
   2.311 ++static int gzip_compress(void *strm, void *d, void *s, int size, int block_size,
   2.312 + 		int *error)
   2.313 + {
   2.314 +-	int res = 0;
   2.315 +-	z_stream *stream = *strm;
   2.316 ++	int res;
   2.317 ++	z_stream *stream = strm;
   2.318 + 
   2.319 +-	if(stream == NULL) {
   2.320 +-		if((stream = *strm = malloc(sizeof(z_stream))) == NULL)
   2.321 +-			goto failed;
   2.322 +-
   2.323 +-		stream->zalloc = Z_NULL;
   2.324 +-		stream->zfree = Z_NULL;
   2.325 +-		stream->opaque = 0;
   2.326 +-
   2.327 +-		if((res = deflateInit(stream, 9)) != Z_OK)
   2.328 +-			goto failed;
   2.329 +-	} else if((res = deflateReset(stream)) != Z_OK)
   2.330 ++	res = deflateReset(stream);
   2.331 ++	if(res != Z_OK)
   2.332 + 		goto failed;
   2.333 + 
   2.334 +-	stream->next_in = (unsigned char *) s;
   2.335 ++	stream->next_in = s;
   2.336 + 	stream->avail_in = size;
   2.337 +-	stream->next_out = (unsigned char *) d;
   2.338 ++	stream->next_out = d;
   2.339 + 	stream->avail_out = block_size;
   2.340 + 
   2.341 + 	res = deflate(stream, Z_FINISH);
   2.342 +@@ -67,14 +87,26 @@
   2.343 + }
   2.344 + 
   2.345 + 
   2.346 +-int gzip_uncompress(char *d, char *s, int size, int block_size, int *error)
   2.347 ++static int gzip_uncompress(void *d, void *s, int size, int block_size, int *error)
   2.348 + {
   2.349 + 	int res;
   2.350 + 	unsigned long bytes = block_size;
   2.351 + 
   2.352 +-	res = uncompress((unsigned char *) d, &bytes,
   2.353 +-		(const unsigned char *) s, size);
   2.354 ++	res = uncompress(d, &bytes, s, size);
   2.355 + 
   2.356 + 	*error = res;
   2.357 + 	return res == Z_OK ? (int) bytes : -1;
   2.358 + }
   2.359 ++
   2.360 ++
   2.361 ++struct compressor gzip_comp_ops = {
   2.362 ++	.init = gzip_init,
   2.363 ++	.compress = gzip_compress,
   2.364 ++	.uncompress = gzip_uncompress,
   2.365 ++	.options = NULL,
   2.366 ++	.usage = NULL,
   2.367 ++	.id = ZLIB_COMPRESSION,
   2.368 ++	.name = "gzip",
   2.369 ++	.supported = 1
   2.370 ++};
   2.371 ++
   2.372 +diff -r 2ab2996036dd squashfs-tools/lzma_wrapper.c
   2.373 +--- a/squashfs-tools/lzma_wrapper.c	Tue Dec 14 12:19:33 2010 +0000
   2.374 ++++ b/squashfs-tools/lzma_wrapper.c	Tue Dec 14 14:18:11 2010 +0000
   2.375 +@@ -17,21 +17,27 @@
   2.376 +  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   2.377 +  *
   2.378 +  * lzma_wrapper.c
   2.379 ++ *
   2.380 ++ * Support for LZMA1 compression using LZMA SDK (4.65 used in
   2.381 ++ * development, other versions may work) http://www.7-zip.org/sdk.html
   2.382 +  */
   2.383 + 
   2.384 + #include <LzmaLib.h>
   2.385 + 
   2.386 ++#include "squashfs_fs.h"
   2.387 ++#include "compressor.h"
   2.388 ++
   2.389 + #define LZMA_HEADER_SIZE	(LZMA_PROPS_SIZE + 8)
   2.390 + 
   2.391 +-int lzma_compress(void **strm, char *dest, char *src, int size, int block_size,
   2.392 ++static int lzma_compress(void *strm, void *dest, void *src, int size, int block_size,
   2.393 + 		int *error)
   2.394 + {
   2.395 +-	unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
   2.396 ++	unsigned char *d = dest;
   2.397 + 	size_t props_size = LZMA_PROPS_SIZE,
   2.398 + 		outlen = block_size - LZMA_HEADER_SIZE;
   2.399 + 	int res;
   2.400 + 
   2.401 +-	res = LzmaCompress(d + LZMA_HEADER_SIZE, &outlen, s, size, d,
   2.402 ++	res = LzmaCompress(dest + LZMA_HEADER_SIZE, &outlen, src, size, dest,
   2.403 + 		&props_size, 5, block_size, 3, 0, 2, 32, 1);
   2.404 + 	
   2.405 + 	if(res == SZ_ERROR_OUTPUT_EOF) {
   2.406 +@@ -73,10 +79,10 @@
   2.407 + }
   2.408 + 
   2.409 + 
   2.410 +-int lzma_uncompress(char *dest, char *src, int size, int block_size,
   2.411 ++static int lzma_uncompress(void *dest, void *src, int size, int block_size,
   2.412 + 	int *error)
   2.413 + {
   2.414 +-	unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
   2.415 ++	unsigned char *s = src;
   2.416 + 	size_t outlen, inlen = size - LZMA_HEADER_SIZE;
   2.417 + 	int res;
   2.418 + 
   2.419 +@@ -85,9 +91,22 @@
   2.420 + 		(s[LZMA_PROPS_SIZE + 2] << 16) |
   2.421 + 		(s[LZMA_PROPS_SIZE + 3] << 24);
   2.422 + 
   2.423 +-	res = LzmaUncompress(d, &outlen, s + LZMA_HEADER_SIZE, &inlen,
   2.424 +-		s, LZMA_PROPS_SIZE);
   2.425 ++	res = LzmaUncompress(dest, &outlen, src + LZMA_HEADER_SIZE, &inlen, src,
   2.426 ++		LZMA_PROPS_SIZE);
   2.427 + 	
   2.428 + 	*error = res;
   2.429 + 	return res == SZ_OK ? outlen : -1;
   2.430 + }
   2.431 ++
   2.432 ++
   2.433 ++struct compressor lzma_comp_ops = {
   2.434 ++	.init = NULL,
   2.435 ++	.compress = lzma_compress,
   2.436 ++	.uncompress = lzma_uncompress,
   2.437 ++	.options = NULL,
   2.438 ++	.usage = NULL,
   2.439 ++	.id = LZMA_COMPRESSION,
   2.440 ++	.name = "lzma",
   2.441 ++	.supported = 1
   2.442 ++};
   2.443 ++
   2.444 +diff -r 2ab2996036dd squashfs-tools/lzma_xz_wrapper.c
   2.445 +--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   2.446 ++++ b/squashfs-tools/lzma_xz_wrapper.c	Tue Dec 14 14:18:11 2010 +0000
   2.447 +@@ -0,0 +1,156 @@
   2.448 ++/*
   2.449 ++ * Copyright (c) 2010
   2.450 ++ * Phillip Lougher <phillip@lougher.demon.co.uk>
   2.451 ++ *
   2.452 ++ * This program is free software; you can redistribute it and/or
   2.453 ++ * modify it under the terms of the GNU General Public License
   2.454 ++ * as published by the Free Software Foundation; either version 2,
   2.455 ++ * or (at your option) any later version.
   2.456 ++ *
   2.457 ++ * This program is distributed in the hope that it will be useful,
   2.458 ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
   2.459 ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   2.460 ++ * GNU General Public License for more details.
   2.461 ++ *
   2.462 ++ * You should have received a copy of the GNU General Public License
   2.463 ++ * along with this program; if not, write to the Free Software
   2.464 ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   2.465 ++ *
   2.466 ++ * lzma_xz_wrapper.c
   2.467 ++ *
   2.468 ++ * Support for LZMA1 compression using XZ Utils liblzma http://tukaani.org/xz/
   2.469 ++ */
   2.470 ++
   2.471 ++#include <stdio.h>
   2.472 ++#include <string.h>
   2.473 ++#include <lzma.h>
   2.474 ++
   2.475 ++#include "squashfs_fs.h"
   2.476 ++#include "compressor.h"
   2.477 ++
   2.478 ++#define LZMA_PROPS_SIZE 5
   2.479 ++#define LZMA_UNCOMP_SIZE 8
   2.480 ++#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE)
   2.481 ++
   2.482 ++#define LZMA_OPTIONS 5
   2.483 ++#define MEMLIMIT (32 * 1024 * 1024)
   2.484 ++
   2.485 ++static int lzma_compress(void *dummy, void *dest, void *src,  int size,
   2.486 ++	int block_size, int *error)
   2.487 ++{
   2.488 ++	unsigned char *d = (unsigned char *) dest;
   2.489 ++	lzma_options_lzma opt;
   2.490 ++	lzma_stream strm = LZMA_STREAM_INIT;
   2.491 ++	int res;
   2.492 ++
   2.493 ++	lzma_lzma_preset(&opt, LZMA_OPTIONS);
   2.494 ++	opt.dict_size = block_size;
   2.495 ++	res = lzma_alone_encoder(&strm, &opt);
   2.496 ++	if(res != LZMA_OK) {
   2.497 ++		lzma_end(&strm);
   2.498 ++		goto failed;
   2.499 ++	}
   2.500 ++
   2.501 ++	strm.next_out = dest;
   2.502 ++	strm.avail_out = block_size;
   2.503 ++	strm.next_in = src;
   2.504 ++	strm.avail_in = size;
   2.505 ++
   2.506 ++	res = lzma_code(&strm, LZMA_FINISH);
   2.507 ++	lzma_end(&strm);
   2.508 ++
   2.509 ++	if(res == LZMA_STREAM_END) {
   2.510 ++		/*
   2.511 ++	 	 * Fill in the 8 byte little endian uncompressed size field in
   2.512 ++		 * the LZMA header.  8 bytes is excessively large for squashfs
   2.513 ++		 * but this is the standard LZMA header and which is expected by
   2.514 ++		 * the kernel code
   2.515 ++	 	 */
   2.516 ++
   2.517 ++		d[LZMA_PROPS_SIZE] = size & 255;
   2.518 ++		d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255;
   2.519 ++		d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255;
   2.520 ++		d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255;
   2.521 ++		d[LZMA_PROPS_SIZE + 4] = 0;
   2.522 ++		d[LZMA_PROPS_SIZE + 5] = 0;
   2.523 ++		d[LZMA_PROPS_SIZE + 6] = 0;
   2.524 ++		d[LZMA_PROPS_SIZE + 7] = 0;
   2.525 ++
   2.526 ++		return (int) strm.total_out;
   2.527 ++	}
   2.528 ++
   2.529 ++	if(res == LZMA_OK)
   2.530 ++		/*
   2.531 ++	 	 * Output buffer overflow.  Return out of buffer space
   2.532 ++	 	 */
   2.533 ++		return 0;
   2.534 ++
   2.535 ++failed:
   2.536 ++	/*
   2.537 ++	 * All other errors return failure, with the compressor
   2.538 ++	 * specific error code in *error
   2.539 ++	 */
   2.540 ++	*error = res;
   2.541 ++	return -1;
   2.542 ++}
   2.543 ++
   2.544 ++
   2.545 ++static int lzma_uncompress(void *dest, void *src, int size, int block_size,
   2.546 ++	int *error)
   2.547 ++{
   2.548 ++	lzma_stream strm = LZMA_STREAM_INIT;
   2.549 ++	int uncompressed_size = 0, res;
   2.550 ++	unsigned char lzma_header[LZMA_HEADER_SIZE];
   2.551 ++
   2.552 ++	res = lzma_alone_decoder(&strm, MEMLIMIT);
   2.553 ++	if(res != LZMA_OK) {
   2.554 ++		lzma_end(&strm);
   2.555 ++		goto failed;
   2.556 ++	}
   2.557 ++
   2.558 ++	memcpy(lzma_header, src, LZMA_HEADER_SIZE);
   2.559 ++	uncompressed_size = lzma_header[LZMA_PROPS_SIZE] |
   2.560 ++		(lzma_header[LZMA_PROPS_SIZE + 1] << 8) |
   2.561 ++		(lzma_header[LZMA_PROPS_SIZE + 2] << 16) |
   2.562 ++		(lzma_header[LZMA_PROPS_SIZE + 3] << 24);
   2.563 ++	memset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE);
   2.564 ++
   2.565 ++	strm.next_out = dest;
   2.566 ++	strm.avail_out = block_size;
   2.567 ++	strm.next_in = lzma_header;
   2.568 ++	strm.avail_in = LZMA_HEADER_SIZE;
   2.569 ++
   2.570 ++	res = lzma_code(&strm, LZMA_RUN);
   2.571 ++
   2.572 ++	if(res != LZMA_OK || strm.avail_in != 0) {
   2.573 ++		lzma_end(&strm);
   2.574 ++		goto failed;
   2.575 ++	}
   2.576 ++
   2.577 ++	strm.next_in = src + LZMA_HEADER_SIZE;
   2.578 ++	strm.avail_in = size - LZMA_HEADER_SIZE;
   2.579 ++
   2.580 ++	res = lzma_code(&strm, LZMA_FINISH);
   2.581 ++	lzma_end(&strm);
   2.582 ++
   2.583 ++	if(res == LZMA_STREAM_END || (res == LZMA_OK &&
   2.584 ++		strm.total_out >= uncompressed_size && strm.avail_in == 0))
   2.585 ++		return uncompressed_size;
   2.586 ++
   2.587 ++failed:
   2.588 ++	*error = res;
   2.589 ++	return -1;
   2.590 ++}
   2.591 ++
   2.592 ++
   2.593 ++struct compressor lzma_comp_ops = {
   2.594 ++	.init = NULL,
   2.595 ++	.compress = lzma_compress,
   2.596 ++	.uncompress = lzma_uncompress,
   2.597 ++	.options = NULL,
   2.598 ++	.usage = NULL,
   2.599 ++	.id = LZMA_COMPRESSION,
   2.600 ++	.name = "lzma",
   2.601 ++	.supported = 1
   2.602 ++};
   2.603 ++
   2.604 +diff -r 2ab2996036dd squashfs-tools/lzo_wrapper.c
   2.605 +--- a/squashfs-tools/lzo_wrapper.c	Tue Dec 14 12:19:33 2010 +0000
   2.606 ++++ b/squashfs-tools/lzo_wrapper.c	Tue Dec 14 14:18:11 2010 +0000
   2.607 +@@ -2,6 +2,9 @@
   2.608 +  * Copyright (c) 2010 LG Electronics
   2.609 +  * Chan Jeong <chan.jeong@lge.com>
   2.610 +  *
   2.611 ++ * All modifications Copyright (c) 2010
   2.612 ++ * Phillip Lougher <phillip@lougher.demon.co.uk>
   2.613 ++ *
   2.614 +  * This program is free software; you can redistribute it and/or
   2.615 +  * modify it under the terms of the GNU General Public License
   2.616 +  * as published by the Free Software Foundation; either version 2,
   2.617 +@@ -25,6 +28,9 @@
   2.618 + #include <lzo/lzoconf.h>
   2.619 + #include <lzo/lzo1x.h>
   2.620 + 
   2.621 ++#include "squashfs_fs.h"
   2.622 ++#include "compressor.h"
   2.623 ++
   2.624 + /* worst-case expansion calculation during compression,
   2.625 +    see LZO FAQ for more information */
   2.626 + #define LZO_OUTPUT_BUFFER_SIZE(size)	(size + (size/16) + 64 + 3)
   2.627 +@@ -34,25 +40,39 @@
   2.628 + 	lzo_bytep out;
   2.629 + };
   2.630 + 
   2.631 +-int lzo_compress(void **strm, char *d, char *s, int size, int block_size,
   2.632 ++
   2.633 ++static int squashfs_lzo_init(void **strm, int block_size, int flags)
   2.634 ++{
   2.635 ++	struct lzo_stream *stream;
   2.636 ++
   2.637 ++	if((stream = *strm = malloc(sizeof(struct lzo_stream))) == NULL)
   2.638 ++		goto failed;
   2.639 ++	/* work memory for compression */
   2.640 ++	if((stream->wrkmem = malloc(LZO1X_999_MEM_COMPRESS)) == NULL)
   2.641 ++		goto failed2;
   2.642 ++	/* temporal output buffer */
   2.643 ++	if((stream->out = malloc(LZO_OUTPUT_BUFFER_SIZE(block_size))) == NULL)
   2.644 ++		goto failed3;
   2.645 ++
   2.646 ++	return 0;
   2.647 ++
   2.648 ++failed3:
   2.649 ++	free(stream->wrkmem);
   2.650 ++failed2:
   2.651 ++	free(stream);
   2.652 ++failed:
   2.653 ++	return -1;
   2.654 ++}
   2.655 ++
   2.656 ++
   2.657 ++static int lzo_compress(void *strm, void *d, void *s, int size, int block_size,
   2.658 + 		int *error)
   2.659 + {
   2.660 +-	int res = 0;
   2.661 ++	int res;
   2.662 + 	lzo_uint outlen;
   2.663 +-	struct lzo_stream *stream = *strm;
   2.664 ++	struct lzo_stream *stream = strm;
   2.665 + 
   2.666 +-	if(stream == NULL) {
   2.667 +-		if((stream = *strm = malloc(sizeof(struct lzo_stream))) == NULL)
   2.668 +-			goto failed;
   2.669 +-		/* work memory for compression */
   2.670 +-		if((stream->wrkmem = malloc(LZO1X_999_MEM_COMPRESS)) == NULL)
   2.671 +-			goto failed;
   2.672 +-		/* temporal output buffer */
   2.673 +-		if((stream->out = malloc(LZO_OUTPUT_BUFFER_SIZE(block_size))) == NULL)
   2.674 +-			goto failed;
   2.675 +-	}
   2.676 +-
   2.677 +-	res = lzo1x_999_compress((lzo_bytep)s, size, stream->out, &outlen, stream->wrkmem);
   2.678 ++	res = lzo1x_999_compress(s, size, stream->out, &outlen, stream->wrkmem);
   2.679 + 	if(res != LZO_E_OK)
   2.680 + 		goto failed;
   2.681 + 	if(outlen >= size)
   2.682 +@@ -77,13 +97,26 @@
   2.683 + }
   2.684 + 
   2.685 + 
   2.686 +-int lzo_uncompress(char *d, char *s, int size, int block_size, int *error)
   2.687 ++static int lzo_uncompress(void *d, void *s, int size, int block_size, int *error)
   2.688 + {
   2.689 + 	int res;
   2.690 + 	lzo_uint bytes = block_size;
   2.691 + 
   2.692 +-	res = lzo1x_decompress_safe((lzo_bytep)s, size, (lzo_bytep)d, &bytes, NULL);
   2.693 ++	res = lzo1x_decompress_safe(s, size, d, &bytes, NULL);
   2.694 + 
   2.695 + 	*error = res;
   2.696 + 	return res == LZO_E_OK ? bytes : -1;
   2.697 + }
   2.698 ++
   2.699 ++
   2.700 ++struct compressor lzo_comp_ops = {
   2.701 ++	.init = squashfs_lzo_init,
   2.702 ++	.compress = lzo_compress,
   2.703 ++	.uncompress = lzo_uncompress,
   2.704 ++	.options = NULL,
   2.705 ++	.usage = NULL,
   2.706 ++	.id = LZO_COMPRESSION,
   2.707 ++	.name = "lzo",
   2.708 ++	.supported = 1
   2.709 ++};
   2.710 ++
   2.711 +diff -r 2ab2996036dd squashfs-tools/mksquashfs.c
   2.712 +--- a/squashfs-tools/mksquashfs.c	Tue Dec 14 12:19:33 2010 +0000
   2.713 ++++ b/squashfs-tools/mksquashfs.c	Tue Dec 14 14:18:11 2010 +0000
   2.714 +@@ -384,9 +384,10 @@
   2.715 + #define FRAGMENT_BUFFER_DEFAULT 64
   2.716 + int writer_buffer_size;
   2.717 + 
   2.718 +-/* compression operations structure */
   2.719 ++/* compression operations */
   2.720 + static struct compressor *comp;
   2.721 +-char *comp_name = COMP_DEFAULT;
   2.722 ++int compressor_opts_parsed = 0;
   2.723 ++void *stream = NULL;
   2.724 + 
   2.725 + /* xattr stats */
   2.726 + unsigned int xattr_bytes = 0, total_xattr_bytes = 0;
   2.727 +@@ -859,7 +860,7 @@
   2.728 + }
   2.729 + 
   2.730 + 
   2.731 +-int mangle2(void **strm, char *d, char *s, int size,
   2.732 ++int mangle2(void *strm, char *d, char *s, int size,
   2.733 + 	int block_size, int uncompressed, int data_block)
   2.734 + {
   2.735 + 	int error, c_byte = 0;
   2.736 +@@ -884,9 +885,7 @@
   2.737 + int mangle(char *d, char *s, int size, int block_size,
   2.738 + 	int uncompressed, int data_block)
   2.739 + {
   2.740 +-	static void *stream = NULL;
   2.741 +-
   2.742 +-	return mangle2(&stream, d, s, size, block_size, uncompressed,
   2.743 ++	return mangle2(stream, d, s, size, block_size, uncompressed,
   2.744 + 		data_block);
   2.745 + }
   2.746 + 
   2.747 +@@ -2556,11 +2555,15 @@
   2.748 + void *deflator(void *arg)
   2.749 + {
   2.750 + 	void *stream = NULL;
   2.751 +-	int oldstate;
   2.752 ++	int res, oldstate;
   2.753 + 
   2.754 + 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
   2.755 + 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
   2.756 + 
   2.757 ++	res = compressor_init(comp, &stream, block_size, 1);
   2.758 ++	if(res)
   2.759 ++		BAD_ERROR("deflator:: compressor_init failed\n");
   2.760 ++
   2.761 + 	while(1) {
   2.762 + 		struct file_buffer *file_buffer = queue_get(from_reader);
   2.763 + 		struct file_buffer *write_buffer;
   2.764 +@@ -2573,7 +2576,7 @@
   2.765 + 			queue_put(from_deflate, file_buffer);
   2.766 + 		} else {
   2.767 + 			write_buffer = cache_get(writer_buffer, 0, 0);
   2.768 +-			write_buffer->c_byte = mangle2(&stream,
   2.769 ++			write_buffer->c_byte = mangle2(stream,
   2.770 + 				write_buffer->data, file_buffer->data,
   2.771 + 				file_buffer->size, block_size, noD, 1);
   2.772 + 			write_buffer->sequence = file_buffer->sequence;
   2.773 +@@ -2593,11 +2596,15 @@
   2.774 + void *frag_deflator(void *arg)
   2.775 + {
   2.776 + 	void *stream = NULL;
   2.777 +-	int oldstate;
   2.778 ++	int res, oldstate;
   2.779 + 
   2.780 + 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
   2.781 + 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
   2.782 + 
   2.783 ++	res = compressor_init(comp, &stream, block_size, 1);
   2.784 ++	if(res)
   2.785 ++		BAD_ERROR("frag_deflator:: compressor_init failed\n");
   2.786 ++
   2.787 + 	while(1) {
   2.788 + 		int c_byte, compressed_size;
   2.789 + 		struct file_buffer *file_buffer = queue_get(to_frag);
   2.790 +@@ -2605,7 +2612,7 @@
   2.791 + 			cache_get(writer_buffer, file_buffer->block +
   2.792 + 			FRAG_INDEX, 1);
   2.793 + 
   2.794 +-		c_byte = mangle2(&stream, write_buffer->data, file_buffer->data,
   2.795 ++		c_byte = mangle2(stream, write_buffer->data, file_buffer->data,
   2.796 + 			file_buffer->size, block_size, noF, 1);
   2.797 + 		compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
   2.798 + 		write_buffer->size = compressed_size;
   2.799 +@@ -4501,7 +4508,7 @@
   2.800 + 
   2.801 + 
   2.802 + #define VERSION() \
   2.803 +-	printf("mksquashfs version 4.1 (2010/09/19)\n");\
   2.804 ++	printf("mksquashfs version 4.1-CVS (2010/12/07)\n");\
   2.805 + 	printf("copyright (C) 2010 Phillip Lougher "\
   2.806 + 		"<phillip@lougher.demon.co.uk>\n\n"); \
   2.807 + 	printf("This program is free software; you can redistribute it and/or"\
   2.808 +@@ -4521,7 +4528,7 @@
   2.809 + int main(int argc, char *argv[])
   2.810 + {
   2.811 + 	struct stat buf, source_buf;
   2.812 +-	int i;
   2.813 ++	int res, i;
   2.814 + 	squashfs_super_block sBlk;
   2.815 + 	char *b, *root_name = NULL;
   2.816 + 	int nopad = FALSE, keep_as_directory = FALSE;
   2.817 +@@ -4542,14 +4549,50 @@
   2.818 + 		goto printOptions;
   2.819 + 	source_path = argv + 1;
   2.820 + 	source = i - 2;
   2.821 ++	/*
   2.822 ++	 * lookup default compressor.  Note the Makefile ensures the default
   2.823 ++	 * compressor has been built, and so we don't need to to check
   2.824 ++	 * for failure here
   2.825 ++	 */
   2.826 ++	comp = lookup_compressor(COMP_DEFAULT);
   2.827 + 	for(; i < argc; i++) {
   2.828 + 		if(strcmp(argv[i], "-comp") == 0) {
   2.829 ++			if(compressor_opts_parsed) {
   2.830 ++				ERROR("%s: -comp must appear before -X options"
   2.831 ++					"\n", argv[0]);
   2.832 ++				exit(1);
   2.833 ++			}
   2.834 + 			if(++i == argc) {
   2.835 + 				ERROR("%s: -comp missing compression type\n",
   2.836 + 					argv[0]);
   2.837 + 				exit(1);
   2.838 + 			}
   2.839 +-			comp_name = argv[i];
   2.840 ++			comp = lookup_compressor(argv[i]);
   2.841 ++			if(!comp->supported) {
   2.842 ++				ERROR("%s: Compressor \"%s\" is not supported!"
   2.843 ++					"\n", argv[0], argv[i]);
   2.844 ++				ERROR("%s: Compressors available:\n", argv[0]);
   2.845 ++				display_compressors("", COMP_DEFAULT);
   2.846 ++				exit(1);
   2.847 ++			}
   2.848 ++
   2.849 ++		} else if(strncmp(argv[i], "-X", 2) == 0) {
   2.850 ++			int args = compressor_options(comp, argv + i, argc - i);
   2.851 ++			if(args < 0) {
   2.852 ++				if(args == -1) {
   2.853 ++					ERROR("%s: Unrecognised compressor"
   2.854 ++						" option %s\n", argv[0],
   2.855 ++						argv[i]);
   2.856 ++					ERROR("%s: Did you forget to specify"
   2.857 ++						" -comp, or specify it after"
   2.858 ++						" the compressor specific"
   2.859 ++						" option?\n", argv[0]);
   2.860 ++					}
   2.861 ++				exit(1);
   2.862 ++			}
   2.863 ++			i += args;
   2.864 ++			compressor_opts_parsed = 1;
   2.865 ++
   2.866 + 		} else if(strcmp(argv[i], "-pf") == 0) {
   2.867 + 			if(++i == argc) {
   2.868 + 				ERROR("%s: -pf missing filename\n", argv[0]);
   2.869 +@@ -4857,7 +4900,7 @@
   2.870 + 			ERROR("-write-queue <size>\tSet output queue to <size> "
   2.871 + 				"Mbytes.  Default %d Mbytes\n",
   2.872 + 				WRITER_BUFFER_DEFAULT);
   2.873 +-			ERROR("-fragment-queue <size>\tSet fagment queue to "
   2.874 ++			ERROR("-fragment-queue <size>\tSet fragment queue to "
   2.875 + 				"<size> Mbytes.  Default %d Mbytes\n",
   2.876 + 				FRAGMENT_BUFFER_DEFAULT);
   2.877 + 			ERROR("\nMiscellaneous options:\n");
   2.878 +@@ -4871,8 +4914,9 @@
   2.879 + 				"-noF\n");
   2.880 + 			ERROR("-noXattrCompression\talternative name for "
   2.881 + 				"-noX\n");
   2.882 +-			ERROR("\nCompressors available:\n");
   2.883 +-			display_compressors("", COMP_DEFAULT);
   2.884 ++			ERROR("\nCompressors available and compressor specific "
   2.885 ++				"options:\n");
   2.886 ++			display_compressor_usage(COMP_DEFAULT);
   2.887 + 			exit(1);
   2.888 + 		}
   2.889 + 	}
   2.890 +@@ -5005,19 +5049,14 @@
   2.891 + 		always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags);
   2.892 + 		duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags);
   2.893 + 		exportable = SQUASHFS_EXPORTABLE(sBlk.flags);
   2.894 +-	} else {
   2.895 +-		comp = lookup_compressor(comp_name);
   2.896 +-		if(!comp->supported) {
   2.897 +-			ERROR("FATAL_ERROR: Compressor \"%s\" is not "
   2.898 +-				"supported!\n", comp_name);
   2.899 +-			ERROR("Compressors available:\n");
   2.900 +-			display_compressors("", COMP_DEFAULT);
   2.901 +-			EXIT_MKSQUASHFS();
   2.902 +-		}
   2.903 + 	}
   2.904 + 
   2.905 + 	initialise_threads(readb_mbytes, writeb_mbytes, fragmentb_mbytes);
   2.906 + 
   2.907 ++	res = compressor_init(comp, &stream, SQUASHFS_METADATA_SIZE, 0);
   2.908 ++	if(res)
   2.909 ++		BAD_ERROR("compressor_init failed\n");
   2.910 ++
   2.911 + 	if(delete) {
   2.912 + 		printf("Creating %d.%d filesystem on %s, block size %d.\n",
   2.913 + 			SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size);
   2.914 +diff -r 2ab2996036dd squashfs-tools/read_fs.c
   2.915 +--- a/squashfs-tools/read_fs.c	Tue Dec 14 12:19:33 2010 +0000
   2.916 ++++ b/squashfs-tools/read_fs.c	Tue Dec 14 14:18:11 2010 +0000
   2.917 +@@ -363,7 +363,8 @@
   2.918 + 		}
   2.919 + 	}
   2.920 + 	
   2.921 +-	return files;
   2.922 ++	printf("Read existing filesystem, %d inodes scanned\n", files);
   2.923 ++	return TRUE;
   2.924 + 
   2.925 + 
   2.926 + failed:
   2.927 +@@ -414,6 +415,7 @@
   2.928 + 	if(!comp->supported) {
   2.929 + 		ERROR("Filesystem on %s uses %s compression, this is"
   2.930 + 			"unsupported by this version\n", source, comp->name);
   2.931 ++		ERROR("Compressors available:\n");
   2.932 + 		display_compressors("", "");
   2.933 + 		goto failed_mount;
   2.934 + 	}
   2.935 +@@ -691,7 +693,7 @@
   2.936 + 		SQUASHFS_INODE_BLK(sBlk->root_inode);
   2.937 + 	unsigned int root_inode_offset =
   2.938 + 		SQUASHFS_INODE_OFFSET(sBlk->root_inode);
   2.939 +-	unsigned int root_inode_block, files;
   2.940 ++	unsigned int root_inode_block;
   2.941 + 	squashfs_inode_header inode;
   2.942 + 	unsigned int *id_table;
   2.943 + 	int res;
   2.944 +@@ -711,20 +713,18 @@
   2.945 + 	if(id_table == NULL)
   2.946 + 		goto error;
   2.947 + 
   2.948 +-	if((files = scan_inode_table(fd, start, end, root_inode_start,
   2.949 +-			root_inode_offset, sBlk, &inode, &inode_table,
   2.950 +-			&root_inode_block, root_inode_size, uncompressed_file,
   2.951 +-			uncompressed_directory, file_count, sym_count,
   2.952 +-			dev_count, dir_count, fifo_count, sock_count, id_table))
   2.953 +-			== 0) {
   2.954 ++	res = scan_inode_table(fd, start, end, root_inode_start,
   2.955 ++		root_inode_offset, sBlk, &inode, &inode_table,
   2.956 ++		&root_inode_block, root_inode_size, uncompressed_file,
   2.957 ++		uncompressed_directory, file_count, sym_count, dev_count,
   2.958 ++		dir_count, fifo_count, sock_count, id_table);
   2.959 ++	if(res == 0) {
   2.960 + 		ERROR("read_filesystem: inode table read failed\n");
   2.961 + 		goto error;
   2.962 + 	}
   2.963 + 
   2.964 + 	*uncompressed_inode = root_inode_block;
   2.965 + 
   2.966 +-	printf("Read existing filesystem, %d inodes scanned\n", files);
   2.967 +-
   2.968 + 	if(inode.base.inode_type == SQUASHFS_DIR_TYPE ||
   2.969 + 			inode.base.inode_type == SQUASHFS_LDIR_TYPE) {
   2.970 + 		if(inode.base.inode_type == SQUASHFS_DIR_TYPE) {
   2.971 +diff -r 2ab2996036dd squashfs-tools/squashfs_fs.h
   2.972 +--- a/squashfs-tools/squashfs_fs.h	Tue Dec 14 12:19:33 2010 +0000
   2.973 ++++ b/squashfs-tools/squashfs_fs.h	Tue Dec 14 14:18:11 2010 +0000
   2.974 +@@ -259,6 +259,7 @@
   2.975 + #define ZLIB_COMPRESSION	1
   2.976 + #define LZMA_COMPRESSION	2
   2.977 + #define LZO_COMPRESSION		3
   2.978 ++#define XZ_COMPRESSION		4
   2.979 + 
   2.980 + struct squashfs_super_block {
   2.981 + 	unsigned int		s_magic;
   2.982 +diff -r 2ab2996036dd squashfs-tools/unsquash-1.c
   2.983 +--- a/squashfs-tools/unsquash-1.c	Tue Dec 14 12:19:33 2010 +0000
   2.984 ++++ b/squashfs-tools/unsquash-1.c	Tue Dec 14 14:18:11 2010 +0000
   2.985 +@@ -138,7 +138,7 @@
   2.986 + 
   2.987 + 			i.data = inode->file_size;
   2.988 + 			i.time = inode->mtime;
   2.989 +-			i.blocks = (inode->file_size + sBlk.s.block_size - 1) >>
   2.990 ++			i.blocks = (i.data + sBlk.s.block_size - 1) >>
   2.991 + 				sBlk.s.block_log;
   2.992 + 			i.start = inode->start_block;
   2.993 + 			i.block_ptr = block_ptr + sizeof(*inode);
   2.994 +diff -r 2ab2996036dd squashfs-tools/unsquash-2.c
   2.995 +--- a/squashfs-tools/unsquash-2.c	Tue Dec 14 12:19:33 2010 +0000
   2.996 ++++ b/squashfs-tools/unsquash-2.c	Tue Dec 14 14:18:11 2010 +0000
   2.997 +@@ -205,8 +205,8 @@
   2.998 + 			i.fragment = inode->fragment;
   2.999 + 			i.offset = inode->offset;
  2.1000 + 			i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ?
  2.1001 +-				(inode->file_size + sBlk.s.block_size - 1) >>
  2.1002 +-				sBlk.s.block_log : inode->file_size >>
  2.1003 ++				(i.data + sBlk.s.block_size - 1) >>
  2.1004 ++				sBlk.s.block_log : i.data >>
  2.1005 + 				sBlk.s.block_log;
  2.1006 + 			i.start = inode->start_block;
  2.1007 + 			i.sparse = 0;
  2.1008 +diff -r 2ab2996036dd squashfs-tools/unsquash-3.c
  2.1009 +--- a/squashfs-tools/unsquash-3.c	Tue Dec 14 12:19:33 2010 +0000
  2.1010 ++++ b/squashfs-tools/unsquash-3.c	Tue Dec 14 14:18:11 2010 +0000
  2.1011 +@@ -188,9 +188,9 @@
  2.1012 + 			i.fragment = inode->fragment;
  2.1013 + 			i.offset = inode->offset;
  2.1014 + 			i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ?
  2.1015 +-				(inode->file_size + sBlk.s.block_size - 1) >>
  2.1016 ++				(i.data + sBlk.s.block_size - 1) >>
  2.1017 + 				sBlk.s.block_log :
  2.1018 +-				inode->file_size >> sBlk.s.block_log;
  2.1019 ++				i.data >> sBlk.s.block_log;
  2.1020 + 			i.start = inode->start_block;
  2.1021 + 			i.sparse = 1;
  2.1022 + 			i.block_ptr = block_ptr + sizeof(*inode);
  2.1023 +diff -r 2ab2996036dd squashfs-tools/unsquash-4.c
  2.1024 +--- a/squashfs-tools/unsquash-4.c	Tue Dec 14 12:19:33 2010 +0000
  2.1025 ++++ b/squashfs-tools/unsquash-4.c	Tue Dec 14 14:18:11 2010 +0000
  2.1026 +@@ -143,9 +143,9 @@
  2.1027 + 			i.fragment = inode->fragment;
  2.1028 + 			i.offset = inode->offset;
  2.1029 + 			i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ?
  2.1030 +-				(inode->file_size + sBlk.s.block_size - 1) >>
  2.1031 ++				(i.data + sBlk.s.block_size - 1) >>
  2.1032 + 				sBlk.s.block_log :
  2.1033 +-				inode->file_size >> sBlk.s.block_log;
  2.1034 ++				i.data >> sBlk.s.block_log;
  2.1035 + 			i.start = inode->start_block;
  2.1036 + 			i.sparse = 0;
  2.1037 + 			i.block_ptr = block_ptr + sizeof(*inode);
  2.1038 +diff -r 2ab2996036dd squashfs-tools/unsquashfs.c
  2.1039 +--- a/squashfs-tools/unsquashfs.c	Tue Dec 14 12:19:33 2010 +0000
  2.1040 ++++ b/squashfs-tools/unsquashfs.c	Tue Dec 14 14:18:11 2010 +0000
  2.1041 +@@ -737,7 +737,7 @@
  2.1042 + int lseek_broken = FALSE;
  2.1043 + char *zero_data = NULL;
  2.1044 + 
  2.1045 +-int write_block(int file_fd, char *buffer, int size, int hole, int sparse)
  2.1046 ++int write_block(int file_fd, char *buffer, int size, long long hole, int sparse)
  2.1047 + {
  2.1048 + 	off_t off = hole;
  2.1049 + 
  2.1050 +@@ -1299,9 +1299,12 @@
  2.1051 + 		print_filename(parent_name, i);
  2.1052 + 
  2.1053 + 	if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 &&
  2.1054 +-			(!force || errno != EEXIST))
  2.1055 +-		ERROR("dir_scan: failed to open directory %s, because %s\n",
  2.1056 ++			(!force || errno != EEXIST)) {
  2.1057 ++		ERROR("dir_scan: failed to make directory %s, because %s\n",
  2.1058 + 			parent_name, strerror(errno));
  2.1059 ++		squashfs_closedir(dir);
  2.1060 ++		return;
  2.1061 ++	}
  2.1062 + 
  2.1063 + 	while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) {
  2.1064 + 		TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n",
  2.1065 +@@ -1604,7 +1607,7 @@
  2.1066 + 	while(1) {
  2.1067 + 		struct squashfs_file *file = queue_get(to_writer);
  2.1068 + 		int file_fd;
  2.1069 +-		int hole = 0;
  2.1070 ++		long long hole = 0;
  2.1071 + 		int failed = FALSE;
  2.1072 + 		int error;
  2.1073 + 
  2.1074 +@@ -1903,7 +1906,7 @@
  2.1075 + 
  2.1076 + 
  2.1077 + #define VERSION() \
  2.1078 +-	printf("unsquashfs version 4.1 (2010/09/19)\n");\
  2.1079 ++	printf("unsquashfs version 4.1-CVS (2010/10/23)\n");\
  2.1080 + 	printf("copyright (C) 2010 Phillip Lougher "\
  2.1081 + 		"<phillip@lougher.demon.co.uk>\n\n");\
  2.1082 +     	printf("This program is free software; you can redistribute it and/or"\
  2.1083 +@@ -2081,7 +2084,7 @@
  2.1084 + 			ERROR("\t-da[ta-queue] <size>\tSet data queue to "
  2.1085 + 				"<size> Mbytes.  Default %d\n\t\t\t\tMbytes\n",
  2.1086 + 				DATA_BUFFER_DEFAULT);
  2.1087 +-			ERROR("\t-fr[ag-queue] <size>\tSet fagment queue to "
  2.1088 ++			ERROR("\t-fr[ag-queue] <size>\tSet fragment queue to "
  2.1089 + 				"<size> Mbytes.  Default %d\n\t\t\t\t Mbytes\n",
  2.1090 + 				FRAGMENT_BUFFER_DEFAULT);
  2.1091 + 			ERROR("\t-r[egex]\t\ttreat extract names as POSIX "
  2.1092 +diff -r 2ab2996036dd squashfs-tools/unsquashfs_xattr.c
  2.1093 +--- a/squashfs-tools/unsquashfs_xattr.c	Tue Dec 14 12:19:33 2010 +0000
  2.1094 ++++ b/squashfs-tools/unsquashfs_xattr.c	Tue Dec 14 14:18:11 2010 +0000
  2.1095 +@@ -25,7 +25,7 @@
  2.1096 + #include "unsquashfs.h"
  2.1097 + #include "xattr.h"
  2.1098 + 
  2.1099 +-#include <attr/xattr.h>
  2.1100 ++#include <sys/xattr.h>
  2.1101 + 
  2.1102 + extern int root_process;
  2.1103 + 
  2.1104 +diff -r 2ab2996036dd squashfs-tools/xattr.c
  2.1105 +--- a/squashfs-tools/xattr.c	Tue Dec 14 12:19:33 2010 +0000
  2.1106 ++++ b/squashfs-tools/xattr.c	Tue Dec 14 14:18:11 2010 +0000
  2.1107 +@@ -34,7 +34,7 @@
  2.1108 + #include <dirent.h>
  2.1109 + #include <string.h>
  2.1110 + #include <stdlib.h>
  2.1111 +-#include <attr/xattr.h>
  2.1112 ++#include <sys/xattr.h>
  2.1113 + 
  2.1114 + #include "squashfs_fs.h"
  2.1115 + #include "global.h"
  2.1116 +@@ -219,6 +219,10 @@
  2.1117 + 			break;
  2.1118 + 		}
  2.1119 + 		xattr_list[i].vsize = vsize;
  2.1120 ++
  2.1121 ++		TRACE("read_xattrs_from_system: filename %s, xattr name %s,"
  2.1122 ++			" vsize %d\n", filename, xattr_list[i].full_name,
  2.1123 ++			xattr_list[i].vsize);
  2.1124 + 	}
  2.1125 + 	free(xattr_names);
  2.1126 + 	*xattrs = xattr_list;
  2.1127 +diff -r 2ab2996036dd squashfs-tools/xz_wrapper.c
  2.1128 +--- a/squashfs-tools/xz_wrapper.c	Tue Dec 14 12:19:33 2010 +0000
  2.1129 ++++ b/squashfs-tools/xz_wrapper.c	Tue Dec 14 14:18:11 2010 +0000
  2.1130 +@@ -17,69 +17,192 @@
  2.1131 +  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  2.1132 +  *
  2.1133 +  * xz_wrapper.c
  2.1134 ++ *
  2.1135 ++ * Support for XZ (LZMA2) compression using XZ Utils liblzma http://tukaani.org/xz/
  2.1136 +  */
  2.1137 + 
  2.1138 + #include <stdio.h>
  2.1139 + #include <string.h>
  2.1140 ++#include <stdlib.h>
  2.1141 + #include <lzma.h>
  2.1142 + 
  2.1143 +-#define LZMA_PROPS_SIZE 5
  2.1144 +-#define LZMA_UNCOMP_SIZE 8
  2.1145 +-#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE)
  2.1146 ++#include "squashfs_fs.h"
  2.1147 ++#include "compressor.h"
  2.1148 + 
  2.1149 +-#define LZMA_OPTIONS 5
  2.1150 + #define MEMLIMIT (32 * 1024 * 1024)
  2.1151 + 
  2.1152 +-int lzma_compress(void **dummy, void *dest, void *src,  int size,
  2.1153 ++static struct bcj {
  2.1154 ++	char	 	*name;
  2.1155 ++	lzma_vli	id;
  2.1156 ++	int		selected;
  2.1157 ++} bcj[] = {
  2.1158 ++	{ "x86", LZMA_FILTER_X86, 0 },
  2.1159 ++	{ "powerpc", LZMA_FILTER_POWERPC, 0 },
  2.1160 ++	{ "ia64", LZMA_FILTER_IA64, 0 },
  2.1161 ++	{ "arm", LZMA_FILTER_ARM, 0 },
  2.1162 ++	{ "armthumb", LZMA_FILTER_ARMTHUMB, 0 },
  2.1163 ++	{ "sparc", LZMA_FILTER_SPARC, 0 },
  2.1164 ++	{ NULL, LZMA_VLI_UNKNOWN, 0 }
  2.1165 ++};
  2.1166 ++
  2.1167 ++struct filter {
  2.1168 ++	void		*buffer;
  2.1169 ++	lzma_filter	filter[3];
  2.1170 ++	size_t		length;
  2.1171 ++};
  2.1172 ++
  2.1173 ++struct xz_stream {
  2.1174 ++	struct filter	*filter;
  2.1175 ++	int		filters;
  2.1176 ++	lzma_options_lzma opt;
  2.1177 ++};
  2.1178 ++
  2.1179 ++static int filter_count = 1;
  2.1180 ++
  2.1181 ++
  2.1182 ++static int xz_options(char *argv[], int argc)
  2.1183 ++{
  2.1184 ++	int i;
  2.1185 ++	char *name;
  2.1186 ++
  2.1187 ++	if(strcmp(argv[0], "-Xbcj") == 0) {
  2.1188 ++		if(argc < 2) {
  2.1189 ++			fprintf(stderr, "xz: -Xbcj missing filter\n");
  2.1190 ++			goto failed;
  2.1191 ++		}
  2.1192 ++
  2.1193 ++		name = argv[1];
  2.1194 ++		while(name[0] != '\0') {
  2.1195 ++			for(i = 0; bcj[i].name; i++) {
  2.1196 ++				int n = strlen(bcj[i].name);
  2.1197 ++				if((strncmp(name, bcj[i].name, n) == 0) &&
  2.1198 ++						(name[n] == '\0' ||
  2.1199 ++						 name[n] == ',')) {
  2.1200 ++					if(bcj[i].selected == 0) {
  2.1201 ++				 		bcj[i].selected = 1;
  2.1202 ++						filter_count++;
  2.1203 ++					}
  2.1204 ++					name += name[n] == ',' ? n + 1 : n;
  2.1205 ++					break;
  2.1206 ++				}
  2.1207 ++			}
  2.1208 ++			if(bcj[i].name == NULL) {
  2.1209 ++				fprintf(stderr, "xz: -Xbcj unrecognised filter\n");
  2.1210 ++				goto failed;
  2.1211 ++			}
  2.1212 ++		}
  2.1213 ++	
  2.1214 ++		return 1;
  2.1215 ++	}
  2.1216 ++
  2.1217 ++	return -1;
  2.1218 ++	
  2.1219 ++failed:
  2.1220 ++	return -2;
  2.1221 ++}
  2.1222 ++		
  2.1223 ++
  2.1224 ++void xz_usage()
  2.1225 ++{
  2.1226 ++	fprintf(stderr, "\t  -Xbcj filter1,filter2,...,filterN\n");
  2.1227 ++	fprintf(stderr, "\t\tCompress using filter1,filter2,...,filterN in");
  2.1228 ++	fprintf(stderr, " turn\n\t\t(in addition to no filter), and choose");
  2.1229 ++	fprintf(stderr, " the best compression.\n");
  2.1230 ++	fprintf(stderr, "\t\tAvailable filters: x86, arm, armthumb,");
  2.1231 ++	fprintf(stderr, " powerpc, sparc, ia64\n");
  2.1232 ++}
  2.1233 ++
  2.1234 ++
  2.1235 ++static int xz_init(void **strm, int block_size, int flags)
  2.1236 ++{
  2.1237 ++	int i, j, filters = flags ? filter_count : 1;
  2.1238 ++	struct filter *filter = malloc(filters * sizeof(struct filter));
  2.1239 ++	struct xz_stream *stream;
  2.1240 ++
  2.1241 ++	if(filter == NULL)
  2.1242 ++		goto failed;
  2.1243 ++
  2.1244 ++	stream = *strm = malloc(sizeof(struct xz_stream));
  2.1245 ++	if(stream == NULL)
  2.1246 ++		goto failed2;
  2.1247 ++
  2.1248 ++	stream->filter = filter;
  2.1249 ++	stream->filters = filters;
  2.1250 ++
  2.1251 ++	memset(filter, 0, filters * sizeof(struct filter));
  2.1252 ++
  2.1253 ++	filter[0].filter[0].id = LZMA_FILTER_LZMA2;
  2.1254 ++	filter[0].filter[0].options = &stream->opt;
  2.1255 ++	filter[0].filter[1].id = LZMA_VLI_UNKNOWN;
  2.1256 ++
  2.1257 ++	for(i = 0, j = 1; flags && bcj[i].name; i++) {
  2.1258 ++		if(bcj[i].selected) {
  2.1259 ++			filter[j].buffer = malloc(block_size);
  2.1260 ++			if(filter[j].buffer == NULL)
  2.1261 ++				goto failed3;
  2.1262 ++			filter[j].filter[0].id = bcj[i].id;
  2.1263 ++			filter[j].filter[1].id = LZMA_FILTER_LZMA2;
  2.1264 ++			filter[j].filter[1].options = &stream->opt;
  2.1265 ++			filter[j].filter[2].id = LZMA_VLI_UNKNOWN;
  2.1266 ++			j++;
  2.1267 ++		}
  2.1268 ++	}
  2.1269 ++
  2.1270 ++	return 0;
  2.1271 ++
  2.1272 ++failed3:
  2.1273 ++	for(i = 1; i < filters; i++)
  2.1274 ++		free(filter[i].buffer);
  2.1275 ++	free(stream);
  2.1276 ++
  2.1277 ++failed2:
  2.1278 ++	free(filter);
  2.1279 ++
  2.1280 ++failed:
  2.1281 ++	return -1;
  2.1282 ++}
  2.1283 ++
  2.1284 ++
  2.1285 ++static int xz_compress(void *strm, void *dest, void *src,  int size,
  2.1286 + 	int block_size, int *error)
  2.1287 + {
  2.1288 +-	unsigned char *d = (unsigned char *) dest;
  2.1289 +-	lzma_options_lzma opt;
  2.1290 +-	lzma_stream strm = LZMA_STREAM_INIT;
  2.1291 +-	int res;
  2.1292 ++	int i;
  2.1293 ++        lzma_ret res = 0;
  2.1294 ++	struct xz_stream *stream = strm;
  2.1295 ++	struct filter *selected = NULL;
  2.1296 + 
  2.1297 +-	lzma_lzma_preset(&opt, LZMA_OPTIONS);
  2.1298 +-	opt.dict_size = block_size;
  2.1299 +-	res = lzma_alone_encoder(&strm, &opt);
  2.1300 +-	if(res != LZMA_OK) {
  2.1301 +-		lzma_end(&strm);
  2.1302 +-		goto failed;
  2.1303 ++	stream->filter[0].buffer = dest;
  2.1304 ++
  2.1305 ++	for(i = 0; i < stream->filters; i++) {
  2.1306 ++		struct filter *filter = &stream->filter[i];
  2.1307 ++
  2.1308 ++        	if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT))
  2.1309 ++                	goto failed;
  2.1310 ++
  2.1311 ++		stream->opt.dict_size = block_size;
  2.1312 ++		filter->length = 0;
  2.1313 ++		res = lzma_stream_buffer_encode(filter->filter,
  2.1314 ++			LZMA_CHECK_CRC32, NULL, src, size, filter->buffer,
  2.1315 ++			&filter->length, block_size);
  2.1316 ++	
  2.1317 ++		if(res == LZMA_OK) {
  2.1318 ++			if(!selected || selected->length > filter->length)
  2.1319 ++				selected = filter;
  2.1320 ++		} else if(res != LZMA_BUF_ERROR)
  2.1321 ++			goto failed;
  2.1322 + 	}
  2.1323 + 
  2.1324 +-	strm.next_out = dest;
  2.1325 +-	strm.avail_out = block_size;
  2.1326 +-	strm.next_in = src;
  2.1327 +-	strm.avail_in = size;
  2.1328 +-
  2.1329 +-	res = lzma_code(&strm, LZMA_FINISH);
  2.1330 +-	lzma_end(&strm);
  2.1331 +-
  2.1332 +-	if(res == LZMA_STREAM_END) {
  2.1333 +-		/*
  2.1334 +-	 	 * Fill in the 8 byte little endian uncompressed size field in
  2.1335 +-		 * the LZMA header.  8 bytes is excessively large for squashfs
  2.1336 +-		 * but this is the standard LZMA header and which is expected by
  2.1337 +-		 * the kernel code
  2.1338 +-	 	 */
  2.1339 +-
  2.1340 +-		d[LZMA_PROPS_SIZE] = size & 255;
  2.1341 +-		d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255;
  2.1342 +-		d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255;
  2.1343 +-		d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255;
  2.1344 +-		d[LZMA_PROPS_SIZE + 4] = 0;
  2.1345 +-		d[LZMA_PROPS_SIZE + 5] = 0;
  2.1346 +-		d[LZMA_PROPS_SIZE + 6] = 0;
  2.1347 +-		d[LZMA_PROPS_SIZE + 7] = 0;
  2.1348 +-
  2.1349 +-		return (int) strm.total_out;
  2.1350 +-	}
  2.1351 +-
  2.1352 +-	if(res == LZMA_OK)
  2.1353 ++	if(!selected)
  2.1354 + 		/*
  2.1355 + 	 	 * Output buffer overflow.  Return out of buffer space
  2.1356 + 	 	 */
  2.1357 + 		return 0;
  2.1358 + 
  2.1359 ++	if(selected->buffer != dest)
  2.1360 ++		memcpy(dest, selected->buffer, selected->length);
  2.1361 ++
  2.1362 ++	return (int) selected->length;
  2.1363 ++
  2.1364 + failed:
  2.1365 + 	/*
  2.1366 + 	 * All other errors return failure, with the compressor
  2.1367 +@@ -90,49 +213,29 @@
  2.1368 + }
  2.1369 + 
  2.1370 + 
  2.1371 +-int lzma_uncompress(void *dest, void *src, int size, int block_size,
  2.1372 ++static int xz_uncompress(void *dest, void *src, int size, int block_size,
  2.1373 + 	int *error)
  2.1374 + {
  2.1375 +-	lzma_stream strm = LZMA_STREAM_INIT;
  2.1376 +-	int uncompressed_size = 0, res;
  2.1377 +-	unsigned char lzma_header[LZMA_HEADER_SIZE];
  2.1378 ++	size_t src_pos = 0;
  2.1379 ++	size_t dest_pos = 0;
  2.1380 ++	uint64_t memlimit = MEMLIMIT;
  2.1381 + 
  2.1382 +-	res = lzma_alone_decoder(&strm, MEMLIMIT);
  2.1383 +-	if(res != LZMA_OK) {
  2.1384 +-		lzma_end(&strm);
  2.1385 +-		goto failed;
  2.1386 +-	}
  2.1387 ++	lzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL,
  2.1388 ++			src, &src_pos, size, dest, &dest_pos, block_size);
  2.1389 + 
  2.1390 +-	memcpy(lzma_header, src, LZMA_HEADER_SIZE);
  2.1391 +-	uncompressed_size = lzma_header[LZMA_PROPS_SIZE] |
  2.1392 +-		(lzma_header[LZMA_PROPS_SIZE + 1] << 8) |
  2.1393 +-		(lzma_header[LZMA_PROPS_SIZE + 2] << 16) |
  2.1394 +-		(lzma_header[LZMA_PROPS_SIZE + 3] << 24);
  2.1395 +-	memset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE);
  2.1396 ++	*error = res;
  2.1397 ++	return res == LZMA_OK && size == (int) src_pos ? (int) dest_pos : -1;
  2.1398 ++}
  2.1399 + 
  2.1400 +-	strm.next_out = dest;
  2.1401 +-	strm.avail_out = block_size;
  2.1402 +-	strm.next_in = lzma_header;
  2.1403 +-	strm.avail_in = LZMA_HEADER_SIZE;
  2.1404 + 
  2.1405 +-	res = lzma_code(&strm, LZMA_RUN);
  2.1406 ++struct compressor xz_comp_ops = {
  2.1407 ++	.init = xz_init,
  2.1408 ++	.compress = xz_compress,
  2.1409 ++	.uncompress = xz_uncompress,
  2.1410 ++	.options = xz_options,
  2.1411 ++	.usage = xz_usage,
  2.1412 ++	.id = XZ_COMPRESSION,
  2.1413 ++	.name = "xz",
  2.1414 ++	.supported = 1
  2.1415 ++};
  2.1416 + 
  2.1417 +-	if(res != LZMA_OK || strm.avail_in != 0) {
  2.1418 +-		lzma_end(&strm);
  2.1419 +-		goto failed;
  2.1420 +-	}
  2.1421 +-
  2.1422 +-	strm.next_in = src + LZMA_HEADER_SIZE;
  2.1423 +-	strm.avail_in = size - LZMA_HEADER_SIZE;
  2.1424 +-
  2.1425 +-	res = lzma_code(&strm, LZMA_FINISH);
  2.1426 +-	lzma_end(&strm);
  2.1427 +-
  2.1428 +-	if(res == LZMA_STREAM_END || (res == LZMA_OK &&
  2.1429 +-		strm.total_out >= uncompressed_size && strm.avail_in == 0))
  2.1430 +-		return uncompressed_size;
  2.1431 +-
  2.1432 +-failed:
  2.1433 +-	*error = res;
  2.1434 +-	return -1;
  2.1435 +-}