wok-next view squashfs/stuff/xz.patch @ 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 | |
children |
line source
1 diff -r 2ab2996036dd squashfs-tools/Makefile
2 --- a/squashfs-tools/Makefile Tue Dec 14 12:19:33 2010 +0000
3 +++ b/squashfs-tools/Makefile Tue Dec 14 14:18:11 2010 +0000
4 @@ -20,20 +20,33 @@
6 ########### Building LZMA support #############
7 #
8 -# Both XZ Utils liblzma (http://tukaani.org/xz/) and LZMA SDK
9 +# LZMA1 compression.
10 +#
11 +# Both XZ Utils liblzma (http://tukaani.org/xz/) and LZMA SDK
12 # (http://www.7-zip.org/sdk.html) are supported
13 #
14 # To build using XZ Utils liblzma - install the library and uncomment
15 -# the XZ_SUPPORT line below.
16 +# the LZMA_XZ_SUPPORT line below.
17 #
18 # To build using the LZMA SDK (4.65 used in development, other versions may
19 # work) - download and unpack it, uncomment and set LZMA_DIR to unpacked source,
20 # and uncomment the LZMA_SUPPORT line below.
21 #
22 -#XZ_SUPPORT = 1
23 +LZMA_XZ_SUPPORT = 1
24 #LZMA_SUPPORT = 1
25 #LZMA_DIR = ../../../LZMA/lzma465
27 +########### Building XZ support #############
28 +#
29 +# LZMA2 compression.
30 +#
31 +# XZ Utils liblzma (http://tukaani.org/xz/) is supported
32 +#
33 +# To build using XZ Utils liblzma - install the library and uncomment
34 +# the XZ_SUPPORT line below.
35 +#
36 +XZ_SUPPORT = 1
37 +
39 ############ Building LZO support ##############
40 #
41 @@ -109,12 +122,20 @@
42 COMPRESSORS += lzma
43 endif
45 +ifdef LZMA_XZ_SUPPORT
46 +CFLAGS += -DLZMA_SUPPORT
47 +MKSQUASHFS_OBJS += lzma_xz_wrapper.o
48 +UNSQUASHFS_OBJS += lzma_xz_wrapper.o
49 +LIBS += -llzma
50 +COMPRESSORS += lzma
51 +endif
52 +
53 ifdef XZ_SUPPORT
54 -CFLAGS += -DLZMA_SUPPORT
55 +CFLAGS += -DXZ_SUPPORT
56 MKSQUASHFS_OBJS += xz_wrapper.o
57 UNSQUASHFS_OBJS += xz_wrapper.o
58 LIBS += -llzma
59 -COMPRESSORS += lzma
60 +COMPRESSORS += xz
61 endif
63 ifdef LZO_SUPPORT
64 @@ -149,11 +170,11 @@
65 endif
67 #
68 -# Both XZ_SUPPORT and LZMA_SUPPORT cannot be specified
69 +# Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified
70 #
71 -ifdef XZ_SUPPORT
72 +ifdef LZMA_XZ_SUPPORT
73 ifdef LZMA_SUPPORT
74 -$(error "Both XZ_SUPPORT and LZMA_SUPPORT cannot be specified")
75 +$(error "Both LZMA_XZ_SUPPORT and LZMA_SUPPORT cannot be specified")
76 endif
77 endif
79 @@ -161,7 +182,7 @@
80 # At least one compressor must have been selected
81 #
82 ifndef COMPRESSORS
83 -$(error "No compressor selected! Select one or more of GZIP, LZMA, or LZO!")
84 +$(error "No compressor selected! Select one or more of GZIP, LZMA, XZ or LZO!")
85 endif
87 #
88 diff -r 2ab2996036dd squashfs-tools/compressor.c
89 --- a/squashfs-tools/compressor.c Tue Dec 14 12:19:33 2010 +0000
90 +++ b/squashfs-tools/compressor.c Tue Dec 14 14:18:11 2010 +0000
91 @@ -25,31 +25,50 @@
92 #include "compressor.h"
93 #include "squashfs_fs.h"
95 -extern int gzip_compress(void **, char *, char *, int, int, int *);
96 -extern int gzip_uncompress(char *, char *, int, int, int *);
97 -extern int lzma_compress(void **, char *, char *, int, int, int *);
98 -extern int lzma_uncompress(char *, char *, int, int, int *);
99 -extern int lzo_compress(void **, char *, char *, int, int, int *);
100 -extern int lzo_uncompress(char *, char *, int, int, int *);
101 -
102 -struct compressor compressor[] = {
103 -#ifdef GZIP_SUPPORT
104 - { gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 },
105 +#ifndef GZIP_SUPPORT
106 +static struct compressor gzip_comp_ops = {
107 + NULL, NULL, NULL, NULL, NULL, ZLIB_COMPRESSION, "gzip", 0
108 +};
109 #else
110 - { NULL, NULL, ZLIB_COMPRESSION, "gzip", 0 },
111 -#endif
112 -#ifdef LZMA_SUPPORT
113 - { lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 },
114 -#else
115 - { NULL, NULL, LZMA_COMPRESSION, "lzma", 0 },
116 -#endif
117 -#ifdef LZO_SUPPORT
118 - { lzo_compress, lzo_uncompress, LZO_COMPRESSION, "lzo", 1 },
119 -#else
120 - { NULL, NULL, LZO_COMPRESSION, "lzo", 0 },
121 +extern struct compressor gzip_comp_ops;
122 #endif
124 - { NULL, NULL , 0, "unknown", 0}
125 +#ifndef LZMA_SUPPORT
126 +static struct compressor lzma_comp_ops = {
127 + NULL, NULL, NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0
128 +};
129 +#else
130 +extern struct compressor lzma_comp_ops;
131 +#endif
132 +
133 +#ifndef LZO_SUPPORT
134 +static struct compressor lzo_comp_ops = {
135 + NULL, NULL, NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0
136 +};
137 +#else
138 +extern struct compressor lzo_comp_ops;
139 +#endif
140 +
141 +#ifndef XZ_SUPPORT
142 +static struct compressor xz_comp_ops = {
143 + NULL, NULL, NULL, NULL, NULL, XZ_COMPRESSION, "xz", 0
144 +};
145 +#else
146 +extern struct compressor xz_comp_ops;
147 +#endif
148 +
149 +
150 +static struct compressor unknown_comp_ops = {
151 + NULL, NULL, NULL , NULL, NULL, 0, "unknown", 0
152 +};
153 +
154 +
155 +struct compressor *compressor[] = {
156 + &gzip_comp_ops,
157 + &lzma_comp_ops,
158 + &lzo_comp_ops,
159 + &xz_comp_ops,
160 + &unknown_comp_ops
161 };
164 @@ -57,11 +76,11 @@
165 {
166 int i;
168 - for(i = 0; compressor[i].id; i++)
169 - if(strcmp(compressor[i].name, name) == 0)
170 + for(i = 0; compressor[i]->id; i++)
171 + if(strcmp(compressor[i]->name, name) == 0)
172 break;
174 - return &compressor[i];
175 + return compressor[i];
176 }
179 @@ -69,11 +88,11 @@
180 {
181 int i;
183 - for(i = 0; compressor[i].id; i++)
184 - if(id == compressor[i].id)
185 + for(i = 0; compressor[i]->id; i++)
186 + if(id == compressor[i]->id)
187 break;
189 - return &compressor[i];
190 + return compressor[i];
191 }
194 @@ -81,10 +100,29 @@
195 {
196 int i;
198 - for(i = 0; compressor[i].id; i++)
199 - if(compressor[i].supported)
200 + for(i = 0; compressor[i]->id; i++)
201 + if(compressor[i]->supported)
202 fprintf(stderr, "%s\t%s%s\n", indent,
203 - compressor[i].name,
204 - strcmp(compressor[i].name, def_comp) == 0 ?
205 + compressor[i]->name,
206 + strcmp(compressor[i]->name, def_comp) == 0 ?
207 " (default)" : "");
208 }
209 +
210 +
211 +void display_compressor_usage(char *def_comp)
212 +{
213 + int i;
214 +
215 + for(i = 0; compressor[i]->id; i++)
216 + if(compressor[i]->supported) {
217 + char *str = strcmp(compressor[i]->name, def_comp) == 0 ?
218 + " (default)" : "";
219 + if(compressor[i]->usage) {
220 + fprintf(stderr, "\t%s%s\n",
221 + compressor[i]->name, str);
222 + compressor[i]->usage();
223 + } else
224 + fprintf(stderr, "\t%s (no options)%s\n",
225 + compressor[i]->name, str);
226 + }
227 +}
228 diff -r 2ab2996036dd squashfs-tools/compressor.h
229 --- a/squashfs-tools/compressor.h Tue Dec 14 12:19:33 2010 +0000
230 +++ b/squashfs-tools/compressor.h Tue Dec 14 14:18:11 2010 +0000
231 @@ -21,8 +21,11 @@
232 */
234 struct compressor {
235 - int (*compress)(void **, char *, char *, int, int, int *);
236 - int (*uncompress)(char *, char *, int, int, int *);
237 + int (*init)(void **, int, int);
238 + int (*compress)(void *, void *, void *, int, int, int *);
239 + int (*uncompress)(void *, void *, int, int, int *);
240 + int (*options)(char **, int);
241 + void (*usage)();
242 int id;
243 char *name;
244 int supported;
245 @@ -31,3 +34,25 @@
246 extern struct compressor *lookup_compressor(char *);
247 extern struct compressor *lookup_compressor_id(int);
248 extern void display_compressors(char *, char *);
249 +extern void display_compressor_usage(char *);
250 +
251 +static inline int compressor_options(struct compressor *comp, char *argv[],
252 + int argc)
253 +{
254 + if(comp->options == NULL)
255 + return -1;
256 +
257 + return comp->options(argv, argc);
258 +}
259 +
260 +
261 +static inline int compressor_init(struct compressor *comp, void **stream,
262 + int block_size, int flags)
263 +{
264 + if(comp->init == NULL)
265 + return 0;
266 + return comp->init(stream, block_size, flags);
267 +}
268 +
269 +
270 +
271 diff -r 2ab2996036dd squashfs-tools/gzip_wrapper.c
272 --- a/squashfs-tools/gzip_wrapper.c Tue Dec 14 12:19:33 2010 +0000
273 +++ b/squashfs-tools/gzip_wrapper.c Tue Dec 14 14:18:11 2010 +0000
274 @@ -22,28 +22,48 @@
275 #include <stdlib.h>
276 #include <zlib.h>
278 -int gzip_compress(void **strm, char *d, char *s, int size, int block_size,
279 +#include "squashfs_fs.h"
280 +#include "compressor.h"
281 +
282 +static int gzip_init(void **strm, int block_size, int flags)
283 +{
284 + int res;
285 + z_stream *stream;
286 +
287 + stream = *strm = malloc(sizeof(z_stream));
288 + if(stream == NULL)
289 + goto failed;
290 +
291 + stream->zalloc = Z_NULL;
292 + stream->zfree = Z_NULL;
293 + stream->opaque = 0;
294 +
295 + res = deflateInit(stream, 9);
296 + if(res != Z_OK)
297 + goto failed2;
298 +
299 + return 0;
300 +
301 +failed2:
302 + free(stream);
303 +failed:
304 + return -1;
305 +}
306 +
307 +
308 +static int gzip_compress(void *strm, void *d, void *s, int size, int block_size,
309 int *error)
310 {
311 - int res = 0;
312 - z_stream *stream = *strm;
313 + int res;
314 + z_stream *stream = strm;
316 - if(stream == NULL) {
317 - if((stream = *strm = malloc(sizeof(z_stream))) == NULL)
318 - goto failed;
319 -
320 - stream->zalloc = Z_NULL;
321 - stream->zfree = Z_NULL;
322 - stream->opaque = 0;
323 -
324 - if((res = deflateInit(stream, 9)) != Z_OK)
325 - goto failed;
326 - } else if((res = deflateReset(stream)) != Z_OK)
327 + res = deflateReset(stream);
328 + if(res != Z_OK)
329 goto failed;
331 - stream->next_in = (unsigned char *) s;
332 + stream->next_in = s;
333 stream->avail_in = size;
334 - stream->next_out = (unsigned char *) d;
335 + stream->next_out = d;
336 stream->avail_out = block_size;
338 res = deflate(stream, Z_FINISH);
339 @@ -67,14 +87,26 @@
340 }
343 -int gzip_uncompress(char *d, char *s, int size, int block_size, int *error)
344 +static int gzip_uncompress(void *d, void *s, int size, int block_size, int *error)
345 {
346 int res;
347 unsigned long bytes = block_size;
349 - res = uncompress((unsigned char *) d, &bytes,
350 - (const unsigned char *) s, size);
351 + res = uncompress(d, &bytes, s, size);
353 *error = res;
354 return res == Z_OK ? (int) bytes : -1;
355 }
356 +
357 +
358 +struct compressor gzip_comp_ops = {
359 + .init = gzip_init,
360 + .compress = gzip_compress,
361 + .uncompress = gzip_uncompress,
362 + .options = NULL,
363 + .usage = NULL,
364 + .id = ZLIB_COMPRESSION,
365 + .name = "gzip",
366 + .supported = 1
367 +};
368 +
369 diff -r 2ab2996036dd squashfs-tools/lzma_wrapper.c
370 --- a/squashfs-tools/lzma_wrapper.c Tue Dec 14 12:19:33 2010 +0000
371 +++ b/squashfs-tools/lzma_wrapper.c Tue Dec 14 14:18:11 2010 +0000
372 @@ -17,21 +17,27 @@
373 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
374 *
375 * lzma_wrapper.c
376 + *
377 + * Support for LZMA1 compression using LZMA SDK (4.65 used in
378 + * development, other versions may work) http://www.7-zip.org/sdk.html
379 */
381 #include <LzmaLib.h>
383 +#include "squashfs_fs.h"
384 +#include "compressor.h"
385 +
386 #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
388 -int lzma_compress(void **strm, char *dest, char *src, int size, int block_size,
389 +static int lzma_compress(void *strm, void *dest, void *src, int size, int block_size,
390 int *error)
391 {
392 - unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
393 + unsigned char *d = dest;
394 size_t props_size = LZMA_PROPS_SIZE,
395 outlen = block_size - LZMA_HEADER_SIZE;
396 int res;
398 - res = LzmaCompress(d + LZMA_HEADER_SIZE, &outlen, s, size, d,
399 + res = LzmaCompress(dest + LZMA_HEADER_SIZE, &outlen, src, size, dest,
400 &props_size, 5, block_size, 3, 0, 2, 32, 1);
402 if(res == SZ_ERROR_OUTPUT_EOF) {
403 @@ -73,10 +79,10 @@
404 }
407 -int lzma_uncompress(char *dest, char *src, int size, int block_size,
408 +static int lzma_uncompress(void *dest, void *src, int size, int block_size,
409 int *error)
410 {
411 - unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src;
412 + unsigned char *s = src;
413 size_t outlen, inlen = size - LZMA_HEADER_SIZE;
414 int res;
416 @@ -85,9 +91,22 @@
417 (s[LZMA_PROPS_SIZE + 2] << 16) |
418 (s[LZMA_PROPS_SIZE + 3] << 24);
420 - res = LzmaUncompress(d, &outlen, s + LZMA_HEADER_SIZE, &inlen,
421 - s, LZMA_PROPS_SIZE);
422 + res = LzmaUncompress(dest, &outlen, src + LZMA_HEADER_SIZE, &inlen, src,
423 + LZMA_PROPS_SIZE);
425 *error = res;
426 return res == SZ_OK ? outlen : -1;
427 }
428 +
429 +
430 +struct compressor lzma_comp_ops = {
431 + .init = NULL,
432 + .compress = lzma_compress,
433 + .uncompress = lzma_uncompress,
434 + .options = NULL,
435 + .usage = NULL,
436 + .id = LZMA_COMPRESSION,
437 + .name = "lzma",
438 + .supported = 1
439 +};
440 +
441 diff -r 2ab2996036dd squashfs-tools/lzma_xz_wrapper.c
442 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
443 +++ b/squashfs-tools/lzma_xz_wrapper.c Tue Dec 14 14:18:11 2010 +0000
444 @@ -0,0 +1,156 @@
445 +/*
446 + * Copyright (c) 2010
447 + * Phillip Lougher <phillip@lougher.demon.co.uk>
448 + *
449 + * This program is free software; you can redistribute it and/or
450 + * modify it under the terms of the GNU General Public License
451 + * as published by the Free Software Foundation; either version 2,
452 + * or (at your option) any later version.
453 + *
454 + * This program is distributed in the hope that it will be useful,
455 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
456 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
457 + * GNU General Public License for more details.
458 + *
459 + * You should have received a copy of the GNU General Public License
460 + * along with this program; if not, write to the Free Software
461 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
462 + *
463 + * lzma_xz_wrapper.c
464 + *
465 + * Support for LZMA1 compression using XZ Utils liblzma http://tukaani.org/xz/
466 + */
467 +
468 +#include <stdio.h>
469 +#include <string.h>
470 +#include <lzma.h>
471 +
472 +#include "squashfs_fs.h"
473 +#include "compressor.h"
474 +
475 +#define LZMA_PROPS_SIZE 5
476 +#define LZMA_UNCOMP_SIZE 8
477 +#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE)
478 +
479 +#define LZMA_OPTIONS 5
480 +#define MEMLIMIT (32 * 1024 * 1024)
481 +
482 +static int lzma_compress(void *dummy, void *dest, void *src, int size,
483 + int block_size, int *error)
484 +{
485 + unsigned char *d = (unsigned char *) dest;
486 + lzma_options_lzma opt;
487 + lzma_stream strm = LZMA_STREAM_INIT;
488 + int res;
489 +
490 + lzma_lzma_preset(&opt, LZMA_OPTIONS);
491 + opt.dict_size = block_size;
492 + res = lzma_alone_encoder(&strm, &opt);
493 + if(res != LZMA_OK) {
494 + lzma_end(&strm);
495 + goto failed;
496 + }
497 +
498 + strm.next_out = dest;
499 + strm.avail_out = block_size;
500 + strm.next_in = src;
501 + strm.avail_in = size;
502 +
503 + res = lzma_code(&strm, LZMA_FINISH);
504 + lzma_end(&strm);
505 +
506 + if(res == LZMA_STREAM_END) {
507 + /*
508 + * Fill in the 8 byte little endian uncompressed size field in
509 + * the LZMA header. 8 bytes is excessively large for squashfs
510 + * but this is the standard LZMA header and which is expected by
511 + * the kernel code
512 + */
513 +
514 + d[LZMA_PROPS_SIZE] = size & 255;
515 + d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255;
516 + d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255;
517 + d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255;
518 + d[LZMA_PROPS_SIZE + 4] = 0;
519 + d[LZMA_PROPS_SIZE + 5] = 0;
520 + d[LZMA_PROPS_SIZE + 6] = 0;
521 + d[LZMA_PROPS_SIZE + 7] = 0;
522 +
523 + return (int) strm.total_out;
524 + }
525 +
526 + if(res == LZMA_OK)
527 + /*
528 + * Output buffer overflow. Return out of buffer space
529 + */
530 + return 0;
531 +
532 +failed:
533 + /*
534 + * All other errors return failure, with the compressor
535 + * specific error code in *error
536 + */
537 + *error = res;
538 + return -1;
539 +}
540 +
541 +
542 +static int lzma_uncompress(void *dest, void *src, int size, int block_size,
543 + int *error)
544 +{
545 + lzma_stream strm = LZMA_STREAM_INIT;
546 + int uncompressed_size = 0, res;
547 + unsigned char lzma_header[LZMA_HEADER_SIZE];
548 +
549 + res = lzma_alone_decoder(&strm, MEMLIMIT);
550 + if(res != LZMA_OK) {
551 + lzma_end(&strm);
552 + goto failed;
553 + }
554 +
555 + memcpy(lzma_header, src, LZMA_HEADER_SIZE);
556 + uncompressed_size = lzma_header[LZMA_PROPS_SIZE] |
557 + (lzma_header[LZMA_PROPS_SIZE + 1] << 8) |
558 + (lzma_header[LZMA_PROPS_SIZE + 2] << 16) |
559 + (lzma_header[LZMA_PROPS_SIZE + 3] << 24);
560 + memset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE);
561 +
562 + strm.next_out = dest;
563 + strm.avail_out = block_size;
564 + strm.next_in = lzma_header;
565 + strm.avail_in = LZMA_HEADER_SIZE;
566 +
567 + res = lzma_code(&strm, LZMA_RUN);
568 +
569 + if(res != LZMA_OK || strm.avail_in != 0) {
570 + lzma_end(&strm);
571 + goto failed;
572 + }
573 +
574 + strm.next_in = src + LZMA_HEADER_SIZE;
575 + strm.avail_in = size - LZMA_HEADER_SIZE;
576 +
577 + res = lzma_code(&strm, LZMA_FINISH);
578 + lzma_end(&strm);
579 +
580 + if(res == LZMA_STREAM_END || (res == LZMA_OK &&
581 + strm.total_out >= uncompressed_size && strm.avail_in == 0))
582 + return uncompressed_size;
583 +
584 +failed:
585 + *error = res;
586 + return -1;
587 +}
588 +
589 +
590 +struct compressor lzma_comp_ops = {
591 + .init = NULL,
592 + .compress = lzma_compress,
593 + .uncompress = lzma_uncompress,
594 + .options = NULL,
595 + .usage = NULL,
596 + .id = LZMA_COMPRESSION,
597 + .name = "lzma",
598 + .supported = 1
599 +};
600 +
601 diff -r 2ab2996036dd squashfs-tools/lzo_wrapper.c
602 --- a/squashfs-tools/lzo_wrapper.c Tue Dec 14 12:19:33 2010 +0000
603 +++ b/squashfs-tools/lzo_wrapper.c Tue Dec 14 14:18:11 2010 +0000
604 @@ -2,6 +2,9 @@
605 * Copyright (c) 2010 LG Electronics
606 * Chan Jeong <chan.jeong@lge.com>
607 *
608 + * All modifications Copyright (c) 2010
609 + * Phillip Lougher <phillip@lougher.demon.co.uk>
610 + *
611 * This program is free software; you can redistribute it and/or
612 * modify it under the terms of the GNU General Public License
613 * as published by the Free Software Foundation; either version 2,
614 @@ -25,6 +28,9 @@
615 #include <lzo/lzoconf.h>
616 #include <lzo/lzo1x.h>
618 +#include "squashfs_fs.h"
619 +#include "compressor.h"
620 +
621 /* worst-case expansion calculation during compression,
622 see LZO FAQ for more information */
623 #define LZO_OUTPUT_BUFFER_SIZE(size) (size + (size/16) + 64 + 3)
624 @@ -34,25 +40,39 @@
625 lzo_bytep out;
626 };
628 -int lzo_compress(void **strm, char *d, char *s, int size, int block_size,
629 +
630 +static int squashfs_lzo_init(void **strm, int block_size, int flags)
631 +{
632 + struct lzo_stream *stream;
633 +
634 + if((stream = *strm = malloc(sizeof(struct lzo_stream))) == NULL)
635 + goto failed;
636 + /* work memory for compression */
637 + if((stream->wrkmem = malloc(LZO1X_999_MEM_COMPRESS)) == NULL)
638 + goto failed2;
639 + /* temporal output buffer */
640 + if((stream->out = malloc(LZO_OUTPUT_BUFFER_SIZE(block_size))) == NULL)
641 + goto failed3;
642 +
643 + return 0;
644 +
645 +failed3:
646 + free(stream->wrkmem);
647 +failed2:
648 + free(stream);
649 +failed:
650 + return -1;
651 +}
652 +
653 +
654 +static int lzo_compress(void *strm, void *d, void *s, int size, int block_size,
655 int *error)
656 {
657 - int res = 0;
658 + int res;
659 lzo_uint outlen;
660 - struct lzo_stream *stream = *strm;
661 + struct lzo_stream *stream = strm;
663 - if(stream == NULL) {
664 - if((stream = *strm = malloc(sizeof(struct lzo_stream))) == NULL)
665 - goto failed;
666 - /* work memory for compression */
667 - if((stream->wrkmem = malloc(LZO1X_999_MEM_COMPRESS)) == NULL)
668 - goto failed;
669 - /* temporal output buffer */
670 - if((stream->out = malloc(LZO_OUTPUT_BUFFER_SIZE(block_size))) == NULL)
671 - goto failed;
672 - }
673 -
674 - res = lzo1x_999_compress((lzo_bytep)s, size, stream->out, &outlen, stream->wrkmem);
675 + res = lzo1x_999_compress(s, size, stream->out, &outlen, stream->wrkmem);
676 if(res != LZO_E_OK)
677 goto failed;
678 if(outlen >= size)
679 @@ -77,13 +97,26 @@
680 }
683 -int lzo_uncompress(char *d, char *s, int size, int block_size, int *error)
684 +static int lzo_uncompress(void *d, void *s, int size, int block_size, int *error)
685 {
686 int res;
687 lzo_uint bytes = block_size;
689 - res = lzo1x_decompress_safe((lzo_bytep)s, size, (lzo_bytep)d, &bytes, NULL);
690 + res = lzo1x_decompress_safe(s, size, d, &bytes, NULL);
692 *error = res;
693 return res == LZO_E_OK ? bytes : -1;
694 }
695 +
696 +
697 +struct compressor lzo_comp_ops = {
698 + .init = squashfs_lzo_init,
699 + .compress = lzo_compress,
700 + .uncompress = lzo_uncompress,
701 + .options = NULL,
702 + .usage = NULL,
703 + .id = LZO_COMPRESSION,
704 + .name = "lzo",
705 + .supported = 1
706 +};
707 +
708 diff -r 2ab2996036dd squashfs-tools/mksquashfs.c
709 --- a/squashfs-tools/mksquashfs.c Tue Dec 14 12:19:33 2010 +0000
710 +++ b/squashfs-tools/mksquashfs.c Tue Dec 14 14:18:11 2010 +0000
711 @@ -384,9 +384,10 @@
712 #define FRAGMENT_BUFFER_DEFAULT 64
713 int writer_buffer_size;
715 -/* compression operations structure */
716 +/* compression operations */
717 static struct compressor *comp;
718 -char *comp_name = COMP_DEFAULT;
719 +int compressor_opts_parsed = 0;
720 +void *stream = NULL;
722 /* xattr stats */
723 unsigned int xattr_bytes = 0, total_xattr_bytes = 0;
724 @@ -859,7 +860,7 @@
725 }
728 -int mangle2(void **strm, char *d, char *s, int size,
729 +int mangle2(void *strm, char *d, char *s, int size,
730 int block_size, int uncompressed, int data_block)
731 {
732 int error, c_byte = 0;
733 @@ -884,9 +885,7 @@
734 int mangle(char *d, char *s, int size, int block_size,
735 int uncompressed, int data_block)
736 {
737 - static void *stream = NULL;
738 -
739 - return mangle2(&stream, d, s, size, block_size, uncompressed,
740 + return mangle2(stream, d, s, size, block_size, uncompressed,
741 data_block);
742 }
744 @@ -2556,11 +2555,15 @@
745 void *deflator(void *arg)
746 {
747 void *stream = NULL;
748 - int oldstate;
749 + int res, oldstate;
751 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
752 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
754 + res = compressor_init(comp, &stream, block_size, 1);
755 + if(res)
756 + BAD_ERROR("deflator:: compressor_init failed\n");
757 +
758 while(1) {
759 struct file_buffer *file_buffer = queue_get(from_reader);
760 struct file_buffer *write_buffer;
761 @@ -2573,7 +2576,7 @@
762 queue_put(from_deflate, file_buffer);
763 } else {
764 write_buffer = cache_get(writer_buffer, 0, 0);
765 - write_buffer->c_byte = mangle2(&stream,
766 + write_buffer->c_byte = mangle2(stream,
767 write_buffer->data, file_buffer->data,
768 file_buffer->size, block_size, noD, 1);
769 write_buffer->sequence = file_buffer->sequence;
770 @@ -2593,11 +2596,15 @@
771 void *frag_deflator(void *arg)
772 {
773 void *stream = NULL;
774 - int oldstate;
775 + int res, oldstate;
777 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
778 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
780 + res = compressor_init(comp, &stream, block_size, 1);
781 + if(res)
782 + BAD_ERROR("frag_deflator:: compressor_init failed\n");
783 +
784 while(1) {
785 int c_byte, compressed_size;
786 struct file_buffer *file_buffer = queue_get(to_frag);
787 @@ -2605,7 +2612,7 @@
788 cache_get(writer_buffer, file_buffer->block +
789 FRAG_INDEX, 1);
791 - c_byte = mangle2(&stream, write_buffer->data, file_buffer->data,
792 + c_byte = mangle2(stream, write_buffer->data, file_buffer->data,
793 file_buffer->size, block_size, noF, 1);
794 compressed_size = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
795 write_buffer->size = compressed_size;
796 @@ -4501,7 +4508,7 @@
799 #define VERSION() \
800 - printf("mksquashfs version 4.1 (2010/09/19)\n");\
801 + printf("mksquashfs version 4.1-CVS (2010/12/07)\n");\
802 printf("copyright (C) 2010 Phillip Lougher "\
803 "<phillip@lougher.demon.co.uk>\n\n"); \
804 printf("This program is free software; you can redistribute it and/or"\
805 @@ -4521,7 +4528,7 @@
806 int main(int argc, char *argv[])
807 {
808 struct stat buf, source_buf;
809 - int i;
810 + int res, i;
811 squashfs_super_block sBlk;
812 char *b, *root_name = NULL;
813 int nopad = FALSE, keep_as_directory = FALSE;
814 @@ -4542,14 +4549,50 @@
815 goto printOptions;
816 source_path = argv + 1;
817 source = i - 2;
818 + /*
819 + * lookup default compressor. Note the Makefile ensures the default
820 + * compressor has been built, and so we don't need to to check
821 + * for failure here
822 + */
823 + comp = lookup_compressor(COMP_DEFAULT);
824 for(; i < argc; i++) {
825 if(strcmp(argv[i], "-comp") == 0) {
826 + if(compressor_opts_parsed) {
827 + ERROR("%s: -comp must appear before -X options"
828 + "\n", argv[0]);
829 + exit(1);
830 + }
831 if(++i == argc) {
832 ERROR("%s: -comp missing compression type\n",
833 argv[0]);
834 exit(1);
835 }
836 - comp_name = argv[i];
837 + comp = lookup_compressor(argv[i]);
838 + if(!comp->supported) {
839 + ERROR("%s: Compressor \"%s\" is not supported!"
840 + "\n", argv[0], argv[i]);
841 + ERROR("%s: Compressors available:\n", argv[0]);
842 + display_compressors("", COMP_DEFAULT);
843 + exit(1);
844 + }
845 +
846 + } else if(strncmp(argv[i], "-X", 2) == 0) {
847 + int args = compressor_options(comp, argv + i, argc - i);
848 + if(args < 0) {
849 + if(args == -1) {
850 + ERROR("%s: Unrecognised compressor"
851 + " option %s\n", argv[0],
852 + argv[i]);
853 + ERROR("%s: Did you forget to specify"
854 + " -comp, or specify it after"
855 + " the compressor specific"
856 + " option?\n", argv[0]);
857 + }
858 + exit(1);
859 + }
860 + i += args;
861 + compressor_opts_parsed = 1;
862 +
863 } else if(strcmp(argv[i], "-pf") == 0) {
864 if(++i == argc) {
865 ERROR("%s: -pf missing filename\n", argv[0]);
866 @@ -4857,7 +4900,7 @@
867 ERROR("-write-queue <size>\tSet output queue to <size> "
868 "Mbytes. Default %d Mbytes\n",
869 WRITER_BUFFER_DEFAULT);
870 - ERROR("-fragment-queue <size>\tSet fagment queue to "
871 + ERROR("-fragment-queue <size>\tSet fragment queue to "
872 "<size> Mbytes. Default %d Mbytes\n",
873 FRAGMENT_BUFFER_DEFAULT);
874 ERROR("\nMiscellaneous options:\n");
875 @@ -4871,8 +4914,9 @@
876 "-noF\n");
877 ERROR("-noXattrCompression\talternative name for "
878 "-noX\n");
879 - ERROR("\nCompressors available:\n");
880 - display_compressors("", COMP_DEFAULT);
881 + ERROR("\nCompressors available and compressor specific "
882 + "options:\n");
883 + display_compressor_usage(COMP_DEFAULT);
884 exit(1);
885 }
886 }
887 @@ -5005,19 +5049,14 @@
888 always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags);
889 duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags);
890 exportable = SQUASHFS_EXPORTABLE(sBlk.flags);
891 - } else {
892 - comp = lookup_compressor(comp_name);
893 - if(!comp->supported) {
894 - ERROR("FATAL_ERROR: Compressor \"%s\" is not "
895 - "supported!\n", comp_name);
896 - ERROR("Compressors available:\n");
897 - display_compressors("", COMP_DEFAULT);
898 - EXIT_MKSQUASHFS();
899 - }
900 }
902 initialise_threads(readb_mbytes, writeb_mbytes, fragmentb_mbytes);
904 + res = compressor_init(comp, &stream, SQUASHFS_METADATA_SIZE, 0);
905 + if(res)
906 + BAD_ERROR("compressor_init failed\n");
907 +
908 if(delete) {
909 printf("Creating %d.%d filesystem on %s, block size %d.\n",
910 SQUASHFS_MAJOR, s_minor, argv[source + 1], block_size);
911 diff -r 2ab2996036dd squashfs-tools/read_fs.c
912 --- a/squashfs-tools/read_fs.c Tue Dec 14 12:19:33 2010 +0000
913 +++ b/squashfs-tools/read_fs.c Tue Dec 14 14:18:11 2010 +0000
914 @@ -363,7 +363,8 @@
915 }
916 }
918 - return files;
919 + printf("Read existing filesystem, %d inodes scanned\n", files);
920 + return TRUE;
923 failed:
924 @@ -414,6 +415,7 @@
925 if(!comp->supported) {
926 ERROR("Filesystem on %s uses %s compression, this is"
927 "unsupported by this version\n", source, comp->name);
928 + ERROR("Compressors available:\n");
929 display_compressors("", "");
930 goto failed_mount;
931 }
932 @@ -691,7 +693,7 @@
933 SQUASHFS_INODE_BLK(sBlk->root_inode);
934 unsigned int root_inode_offset =
935 SQUASHFS_INODE_OFFSET(sBlk->root_inode);
936 - unsigned int root_inode_block, files;
937 + unsigned int root_inode_block;
938 squashfs_inode_header inode;
939 unsigned int *id_table;
940 int res;
941 @@ -711,20 +713,18 @@
942 if(id_table == NULL)
943 goto error;
945 - if((files = scan_inode_table(fd, start, end, root_inode_start,
946 - root_inode_offset, sBlk, &inode, &inode_table,
947 - &root_inode_block, root_inode_size, uncompressed_file,
948 - uncompressed_directory, file_count, sym_count,
949 - dev_count, dir_count, fifo_count, sock_count, id_table))
950 - == 0) {
951 + res = scan_inode_table(fd, start, end, root_inode_start,
952 + root_inode_offset, sBlk, &inode, &inode_table,
953 + &root_inode_block, root_inode_size, uncompressed_file,
954 + uncompressed_directory, file_count, sym_count, dev_count,
955 + dir_count, fifo_count, sock_count, id_table);
956 + if(res == 0) {
957 ERROR("read_filesystem: inode table read failed\n");
958 goto error;
959 }
961 *uncompressed_inode = root_inode_block;
963 - printf("Read existing filesystem, %d inodes scanned\n", files);
964 -
965 if(inode.base.inode_type == SQUASHFS_DIR_TYPE ||
966 inode.base.inode_type == SQUASHFS_LDIR_TYPE) {
967 if(inode.base.inode_type == SQUASHFS_DIR_TYPE) {
968 diff -r 2ab2996036dd squashfs-tools/squashfs_fs.h
969 --- a/squashfs-tools/squashfs_fs.h Tue Dec 14 12:19:33 2010 +0000
970 +++ b/squashfs-tools/squashfs_fs.h Tue Dec 14 14:18:11 2010 +0000
971 @@ -259,6 +259,7 @@
972 #define ZLIB_COMPRESSION 1
973 #define LZMA_COMPRESSION 2
974 #define LZO_COMPRESSION 3
975 +#define XZ_COMPRESSION 4
977 struct squashfs_super_block {
978 unsigned int s_magic;
979 diff -r 2ab2996036dd squashfs-tools/unsquash-1.c
980 --- a/squashfs-tools/unsquash-1.c Tue Dec 14 12:19:33 2010 +0000
981 +++ b/squashfs-tools/unsquash-1.c Tue Dec 14 14:18:11 2010 +0000
982 @@ -138,7 +138,7 @@
984 i.data = inode->file_size;
985 i.time = inode->mtime;
986 - i.blocks = (inode->file_size + sBlk.s.block_size - 1) >>
987 + i.blocks = (i.data + sBlk.s.block_size - 1) >>
988 sBlk.s.block_log;
989 i.start = inode->start_block;
990 i.block_ptr = block_ptr + sizeof(*inode);
991 diff -r 2ab2996036dd squashfs-tools/unsquash-2.c
992 --- a/squashfs-tools/unsquash-2.c Tue Dec 14 12:19:33 2010 +0000
993 +++ b/squashfs-tools/unsquash-2.c Tue Dec 14 14:18:11 2010 +0000
994 @@ -205,8 +205,8 @@
995 i.fragment = inode->fragment;
996 i.offset = inode->offset;
997 i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ?
998 - (inode->file_size + sBlk.s.block_size - 1) >>
999 - sBlk.s.block_log : inode->file_size >>
1000 + (i.data + sBlk.s.block_size - 1) >>
1001 + sBlk.s.block_log : i.data >>
1002 sBlk.s.block_log;
1003 i.start = inode->start_block;
1004 i.sparse = 0;
1005 diff -r 2ab2996036dd squashfs-tools/unsquash-3.c
1006 --- a/squashfs-tools/unsquash-3.c Tue Dec 14 12:19:33 2010 +0000
1007 +++ b/squashfs-tools/unsquash-3.c Tue Dec 14 14:18:11 2010 +0000
1008 @@ -188,9 +188,9 @@
1009 i.fragment = inode->fragment;
1010 i.offset = inode->offset;
1011 i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ?
1012 - (inode->file_size + sBlk.s.block_size - 1) >>
1013 + (i.data + sBlk.s.block_size - 1) >>
1014 sBlk.s.block_log :
1015 - inode->file_size >> sBlk.s.block_log;
1016 + i.data >> sBlk.s.block_log;
1017 i.start = inode->start_block;
1018 i.sparse = 1;
1019 i.block_ptr = block_ptr + sizeof(*inode);
1020 diff -r 2ab2996036dd squashfs-tools/unsquash-4.c
1021 --- a/squashfs-tools/unsquash-4.c Tue Dec 14 12:19:33 2010 +0000
1022 +++ b/squashfs-tools/unsquash-4.c Tue Dec 14 14:18:11 2010 +0000
1023 @@ -143,9 +143,9 @@
1024 i.fragment = inode->fragment;
1025 i.offset = inode->offset;
1026 i.blocks = inode->fragment == SQUASHFS_INVALID_FRAG ?
1027 - (inode->file_size + sBlk.s.block_size - 1) >>
1028 + (i.data + sBlk.s.block_size - 1) >>
1029 sBlk.s.block_log :
1030 - inode->file_size >> sBlk.s.block_log;
1031 + i.data >> sBlk.s.block_log;
1032 i.start = inode->start_block;
1033 i.sparse = 0;
1034 i.block_ptr = block_ptr + sizeof(*inode);
1035 diff -r 2ab2996036dd squashfs-tools/unsquashfs.c
1036 --- a/squashfs-tools/unsquashfs.c Tue Dec 14 12:19:33 2010 +0000
1037 +++ b/squashfs-tools/unsquashfs.c Tue Dec 14 14:18:11 2010 +0000
1038 @@ -737,7 +737,7 @@
1039 int lseek_broken = FALSE;
1040 char *zero_data = NULL;
1042 -int write_block(int file_fd, char *buffer, int size, int hole, int sparse)
1043 +int write_block(int file_fd, char *buffer, int size, long long hole, int sparse)
1044 {
1045 off_t off = hole;
1047 @@ -1299,9 +1299,12 @@
1048 print_filename(parent_name, i);
1050 if(!lsonly && mkdir(parent_name, (mode_t) dir->mode) == -1 &&
1051 - (!force || errno != EEXIST))
1052 - ERROR("dir_scan: failed to open directory %s, because %s\n",
1053 + (!force || errno != EEXIST)) {
1054 + ERROR("dir_scan: failed to make directory %s, because %s\n",
1055 parent_name, strerror(errno));
1056 + squashfs_closedir(dir);
1057 + return;
1058 + }
1060 while(squashfs_readdir(dir, &name, &start_block, &offset, &type)) {
1061 TRACE("dir_scan: name %s, start_block %d, offset %d, type %d\n",
1062 @@ -1604,7 +1607,7 @@
1063 while(1) {
1064 struct squashfs_file *file = queue_get(to_writer);
1065 int file_fd;
1066 - int hole = 0;
1067 + long long hole = 0;
1068 int failed = FALSE;
1069 int error;
1071 @@ -1903,7 +1906,7 @@
1074 #define VERSION() \
1075 - printf("unsquashfs version 4.1 (2010/09/19)\n");\
1076 + printf("unsquashfs version 4.1-CVS (2010/10/23)\n");\
1077 printf("copyright (C) 2010 Phillip Lougher "\
1078 "<phillip@lougher.demon.co.uk>\n\n");\
1079 printf("This program is free software; you can redistribute it and/or"\
1080 @@ -2081,7 +2084,7 @@
1081 ERROR("\t-da[ta-queue] <size>\tSet data queue to "
1082 "<size> Mbytes. Default %d\n\t\t\t\tMbytes\n",
1083 DATA_BUFFER_DEFAULT);
1084 - ERROR("\t-fr[ag-queue] <size>\tSet fagment queue to "
1085 + ERROR("\t-fr[ag-queue] <size>\tSet fragment queue to "
1086 "<size> Mbytes. Default %d\n\t\t\t\t Mbytes\n",
1087 FRAGMENT_BUFFER_DEFAULT);
1088 ERROR("\t-r[egex]\t\ttreat extract names as POSIX "
1089 diff -r 2ab2996036dd squashfs-tools/unsquashfs_xattr.c
1090 --- a/squashfs-tools/unsquashfs_xattr.c Tue Dec 14 12:19:33 2010 +0000
1091 +++ b/squashfs-tools/unsquashfs_xattr.c Tue Dec 14 14:18:11 2010 +0000
1092 @@ -25,7 +25,7 @@
1093 #include "unsquashfs.h"
1094 #include "xattr.h"
1096 -#include <attr/xattr.h>
1097 +#include <sys/xattr.h>
1099 extern int root_process;
1101 diff -r 2ab2996036dd squashfs-tools/xattr.c
1102 --- a/squashfs-tools/xattr.c Tue Dec 14 12:19:33 2010 +0000
1103 +++ b/squashfs-tools/xattr.c Tue Dec 14 14:18:11 2010 +0000
1104 @@ -34,7 +34,7 @@
1105 #include <dirent.h>
1106 #include <string.h>
1107 #include <stdlib.h>
1108 -#include <attr/xattr.h>
1109 +#include <sys/xattr.h>
1111 #include "squashfs_fs.h"
1112 #include "global.h"
1113 @@ -219,6 +219,10 @@
1114 break;
1115 }
1116 xattr_list[i].vsize = vsize;
1117 +
1118 + TRACE("read_xattrs_from_system: filename %s, xattr name %s,"
1119 + " vsize %d\n", filename, xattr_list[i].full_name,
1120 + xattr_list[i].vsize);
1121 }
1122 free(xattr_names);
1123 *xattrs = xattr_list;
1124 diff -r 2ab2996036dd squashfs-tools/xz_wrapper.c
1125 --- a/squashfs-tools/xz_wrapper.c Tue Dec 14 12:19:33 2010 +0000
1126 +++ b/squashfs-tools/xz_wrapper.c Tue Dec 14 14:18:11 2010 +0000
1127 @@ -17,69 +17,192 @@
1128 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1129 *
1130 * xz_wrapper.c
1131 + *
1132 + * Support for XZ (LZMA2) compression using XZ Utils liblzma http://tukaani.org/xz/
1133 */
1135 #include <stdio.h>
1136 #include <string.h>
1137 +#include <stdlib.h>
1138 #include <lzma.h>
1140 -#define LZMA_PROPS_SIZE 5
1141 -#define LZMA_UNCOMP_SIZE 8
1142 -#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + LZMA_UNCOMP_SIZE)
1143 +#include "squashfs_fs.h"
1144 +#include "compressor.h"
1146 -#define LZMA_OPTIONS 5
1147 #define MEMLIMIT (32 * 1024 * 1024)
1149 -int lzma_compress(void **dummy, void *dest, void *src, int size,
1150 +static struct bcj {
1151 + char *name;
1152 + lzma_vli id;
1153 + int selected;
1154 +} bcj[] = {
1155 + { "x86", LZMA_FILTER_X86, 0 },
1156 + { "powerpc", LZMA_FILTER_POWERPC, 0 },
1157 + { "ia64", LZMA_FILTER_IA64, 0 },
1158 + { "arm", LZMA_FILTER_ARM, 0 },
1159 + { "armthumb", LZMA_FILTER_ARMTHUMB, 0 },
1160 + { "sparc", LZMA_FILTER_SPARC, 0 },
1161 + { NULL, LZMA_VLI_UNKNOWN, 0 }
1162 +};
1163 +
1164 +struct filter {
1165 + void *buffer;
1166 + lzma_filter filter[3];
1167 + size_t length;
1168 +};
1169 +
1170 +struct xz_stream {
1171 + struct filter *filter;
1172 + int filters;
1173 + lzma_options_lzma opt;
1174 +};
1175 +
1176 +static int filter_count = 1;
1177 +
1178 +
1179 +static int xz_options(char *argv[], int argc)
1180 +{
1181 + int i;
1182 + char *name;
1183 +
1184 + if(strcmp(argv[0], "-Xbcj") == 0) {
1185 + if(argc < 2) {
1186 + fprintf(stderr, "xz: -Xbcj missing filter\n");
1187 + goto failed;
1188 + }
1189 +
1190 + name = argv[1];
1191 + while(name[0] != '\0') {
1192 + for(i = 0; bcj[i].name; i++) {
1193 + int n = strlen(bcj[i].name);
1194 + if((strncmp(name, bcj[i].name, n) == 0) &&
1195 + (name[n] == '\0' ||
1196 + name[n] == ',')) {
1197 + if(bcj[i].selected == 0) {
1198 + bcj[i].selected = 1;
1199 + filter_count++;
1200 + }
1201 + name += name[n] == ',' ? n + 1 : n;
1202 + break;
1203 + }
1204 + }
1205 + if(bcj[i].name == NULL) {
1206 + fprintf(stderr, "xz: -Xbcj unrecognised filter\n");
1207 + goto failed;
1208 + }
1209 + }
1210 +
1211 + return 1;
1212 + }
1213 +
1214 + return -1;
1215 +
1216 +failed:
1217 + return -2;
1218 +}
1219 +
1220 +
1221 +void xz_usage()
1222 +{
1223 + fprintf(stderr, "\t -Xbcj filter1,filter2,...,filterN\n");
1224 + fprintf(stderr, "\t\tCompress using filter1,filter2,...,filterN in");
1225 + fprintf(stderr, " turn\n\t\t(in addition to no filter), and choose");
1226 + fprintf(stderr, " the best compression.\n");
1227 + fprintf(stderr, "\t\tAvailable filters: x86, arm, armthumb,");
1228 + fprintf(stderr, " powerpc, sparc, ia64\n");
1229 +}
1230 +
1231 +
1232 +static int xz_init(void **strm, int block_size, int flags)
1233 +{
1234 + int i, j, filters = flags ? filter_count : 1;
1235 + struct filter *filter = malloc(filters * sizeof(struct filter));
1236 + struct xz_stream *stream;
1237 +
1238 + if(filter == NULL)
1239 + goto failed;
1240 +
1241 + stream = *strm = malloc(sizeof(struct xz_stream));
1242 + if(stream == NULL)
1243 + goto failed2;
1244 +
1245 + stream->filter = filter;
1246 + stream->filters = filters;
1247 +
1248 + memset(filter, 0, filters * sizeof(struct filter));
1249 +
1250 + filter[0].filter[0].id = LZMA_FILTER_LZMA2;
1251 + filter[0].filter[0].options = &stream->opt;
1252 + filter[0].filter[1].id = LZMA_VLI_UNKNOWN;
1253 +
1254 + for(i = 0, j = 1; flags && bcj[i].name; i++) {
1255 + if(bcj[i].selected) {
1256 + filter[j].buffer = malloc(block_size);
1257 + if(filter[j].buffer == NULL)
1258 + goto failed3;
1259 + filter[j].filter[0].id = bcj[i].id;
1260 + filter[j].filter[1].id = LZMA_FILTER_LZMA2;
1261 + filter[j].filter[1].options = &stream->opt;
1262 + filter[j].filter[2].id = LZMA_VLI_UNKNOWN;
1263 + j++;
1264 + }
1265 + }
1266 +
1267 + return 0;
1268 +
1269 +failed3:
1270 + for(i = 1; i < filters; i++)
1271 + free(filter[i].buffer);
1272 + free(stream);
1273 +
1274 +failed2:
1275 + free(filter);
1276 +
1277 +failed:
1278 + return -1;
1279 +}
1280 +
1281 +
1282 +static int xz_compress(void *strm, void *dest, void *src, int size,
1283 int block_size, int *error)
1284 {
1285 - unsigned char *d = (unsigned char *) dest;
1286 - lzma_options_lzma opt;
1287 - lzma_stream strm = LZMA_STREAM_INIT;
1288 - int res;
1289 + int i;
1290 + lzma_ret res = 0;
1291 + struct xz_stream *stream = strm;
1292 + struct filter *selected = NULL;
1294 - lzma_lzma_preset(&opt, LZMA_OPTIONS);
1295 - opt.dict_size = block_size;
1296 - res = lzma_alone_encoder(&strm, &opt);
1297 - if(res != LZMA_OK) {
1298 - lzma_end(&strm);
1299 - goto failed;
1300 + stream->filter[0].buffer = dest;
1301 +
1302 + for(i = 0; i < stream->filters; i++) {
1303 + struct filter *filter = &stream->filter[i];
1304 +
1305 + if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT))
1306 + goto failed;
1307 +
1308 + stream->opt.dict_size = block_size;
1309 + filter->length = 0;
1310 + res = lzma_stream_buffer_encode(filter->filter,
1311 + LZMA_CHECK_CRC32, NULL, src, size, filter->buffer,
1312 + &filter->length, block_size);
1313 +
1314 + if(res == LZMA_OK) {
1315 + if(!selected || selected->length > filter->length)
1316 + selected = filter;
1317 + } else if(res != LZMA_BUF_ERROR)
1318 + goto failed;
1319 }
1321 - strm.next_out = dest;
1322 - strm.avail_out = block_size;
1323 - strm.next_in = src;
1324 - strm.avail_in = size;
1325 -
1326 - res = lzma_code(&strm, LZMA_FINISH);
1327 - lzma_end(&strm);
1328 -
1329 - if(res == LZMA_STREAM_END) {
1330 - /*
1331 - * Fill in the 8 byte little endian uncompressed size field in
1332 - * the LZMA header. 8 bytes is excessively large for squashfs
1333 - * but this is the standard LZMA header and which is expected by
1334 - * the kernel code
1335 - */
1336 -
1337 - d[LZMA_PROPS_SIZE] = size & 255;
1338 - d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255;
1339 - d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255;
1340 - d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255;
1341 - d[LZMA_PROPS_SIZE + 4] = 0;
1342 - d[LZMA_PROPS_SIZE + 5] = 0;
1343 - d[LZMA_PROPS_SIZE + 6] = 0;
1344 - d[LZMA_PROPS_SIZE + 7] = 0;
1345 -
1346 - return (int) strm.total_out;
1347 - }
1348 -
1349 - if(res == LZMA_OK)
1350 + if(!selected)
1351 /*
1352 * Output buffer overflow. Return out of buffer space
1353 */
1354 return 0;
1356 + if(selected->buffer != dest)
1357 + memcpy(dest, selected->buffer, selected->length);
1358 +
1359 + return (int) selected->length;
1360 +
1361 failed:
1362 /*
1363 * All other errors return failure, with the compressor
1364 @@ -90,49 +213,29 @@
1365 }
1368 -int lzma_uncompress(void *dest, void *src, int size, int block_size,
1369 +static int xz_uncompress(void *dest, void *src, int size, int block_size,
1370 int *error)
1371 {
1372 - lzma_stream strm = LZMA_STREAM_INIT;
1373 - int uncompressed_size = 0, res;
1374 - unsigned char lzma_header[LZMA_HEADER_SIZE];
1375 + size_t src_pos = 0;
1376 + size_t dest_pos = 0;
1377 + uint64_t memlimit = MEMLIMIT;
1379 - res = lzma_alone_decoder(&strm, MEMLIMIT);
1380 - if(res != LZMA_OK) {
1381 - lzma_end(&strm);
1382 - goto failed;
1383 - }
1384 + lzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL,
1385 + src, &src_pos, size, dest, &dest_pos, block_size);
1387 - memcpy(lzma_header, src, LZMA_HEADER_SIZE);
1388 - uncompressed_size = lzma_header[LZMA_PROPS_SIZE] |
1389 - (lzma_header[LZMA_PROPS_SIZE + 1] << 8) |
1390 - (lzma_header[LZMA_PROPS_SIZE + 2] << 16) |
1391 - (lzma_header[LZMA_PROPS_SIZE + 3] << 24);
1392 - memset(lzma_header + LZMA_PROPS_SIZE, 255, LZMA_UNCOMP_SIZE);
1393 + *error = res;
1394 + return res == LZMA_OK && size == (int) src_pos ? (int) dest_pos : -1;
1395 +}
1397 - strm.next_out = dest;
1398 - strm.avail_out = block_size;
1399 - strm.next_in = lzma_header;
1400 - strm.avail_in = LZMA_HEADER_SIZE;
1402 - res = lzma_code(&strm, LZMA_RUN);
1403 +struct compressor xz_comp_ops = {
1404 + .init = xz_init,
1405 + .compress = xz_compress,
1406 + .uncompress = xz_uncompress,
1407 + .options = xz_options,
1408 + .usage = xz_usage,
1409 + .id = XZ_COMPRESSION,
1410 + .name = "xz",
1411 + .supported = 1
1412 +};
1414 - if(res != LZMA_OK || strm.avail_in != 0) {
1415 - lzma_end(&strm);
1416 - goto failed;
1417 - }
1418 -
1419 - strm.next_in = src + LZMA_HEADER_SIZE;
1420 - strm.avail_in = size - LZMA_HEADER_SIZE;
1421 -
1422 - res = lzma_code(&strm, LZMA_FINISH);
1423 - lzma_end(&strm);
1424 -
1425 - if(res == LZMA_STREAM_END || (res == LZMA_OK &&
1426 - strm.total_out >= uncompressed_size && strm.avail_in == 0))
1427 - return uncompressed_size;
1428 -
1429 -failed:
1430 - *error = res;
1431 - return -1;
1432 -}