1f5e8c0f128f48463630358bcea6063d0024cfd5aplougher/*
28a4692825eb1840d52f2f921e40346d0f8c7e702Phillip Lougher * Copyright (c) 2010, 2011, 2012, 2013
383d42a3fc898962aa1f1e8387f2ccb1114e0d294Phillip Lougher * Phillip Lougher <phillip@squashfs.org.uk>
4f5e8c0f128f48463630358bcea6063d0024cfd5aplougher *
5f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * This program is free software; you can redistribute it and/or
6f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * modify it under the terms of the GNU General Public License
7f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * as published by the Free Software Foundation; either version 2,
8f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * or (at your option) any later version.
9f5e8c0f128f48463630358bcea6063d0024cfd5aplougher *
10f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * This program is distributed in the hope that it will be useful,
11f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * but WITHOUT ANY WARRANTY; without even the implied warranty of
12f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * GNU General Public License for more details.
14f5e8c0f128f48463630358bcea6063d0024cfd5aplougher *
15f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * You should have received a copy of the GNU General Public License
16f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * along with this program; if not, write to the Free Software
17f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18f5e8c0f128f48463630358bcea6063d0024cfd5aplougher *
19f5e8c0f128f48463630358bcea6063d0024cfd5aplougher * xz_wrapper.c
2067dfce9c3751f0580633e8a33cea28bcfbefec04plougher *
21e08e77659d1e2eac07c9ab5dffafaa70aff41c07plougher * Support for XZ (LZMA2) compression using XZ Utils liblzma
22e08e77659d1e2eac07c9ab5dffafaa70aff41c07plougher * http://tukaani.org/xz/
23f5e8c0f128f48463630358bcea6063d0024cfd5aplougher */
2467dfce9c3751f0580633e8a33cea28bcfbefec04plougher
2567dfce9c3751f0580633e8a33cea28bcfbefec04plougher#include <stdio.h>
2667dfce9c3751f0580633e8a33cea28bcfbefec04plougher#include <string.h>
277b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher#include <stdlib.h>
2867dfce9c3751f0580633e8a33cea28bcfbefec04plougher#include <lzma.h>
2967dfce9c3751f0580633e8a33cea28bcfbefec04plougher
3067dfce9c3751f0580633e8a33cea28bcfbefec04plougher#include "squashfs_fs.h"
311ffc835b6020c6559f0d598a41b1483c50a8945fplougher#include "xz_wrapper.h"
3267dfce9c3751f0580633e8a33cea28bcfbefec04plougher#include "compressor.h"
3367dfce9c3751f0580633e8a33cea28bcfbefec04plougher
3490f6b8dc8e5525e70a625bb61f82546811e0bc9bplougherstatic struct bcj bcj[] = {
357b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	{ "x86", LZMA_FILTER_X86, 0 },
367b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	{ "powerpc", LZMA_FILTER_POWERPC, 0 },
377b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	{ "ia64", LZMA_FILTER_IA64, 0 },
387b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	{ "arm", LZMA_FILTER_ARM, 0 },
397b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	{ "armthumb", LZMA_FILTER_ARMTHUMB, 0 },
407b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	{ "sparc", LZMA_FILTER_SPARC, 0 },
417b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	{ NULL, LZMA_VLI_UNKNOWN, 0 }
4267dfce9c3751f0580633e8a33cea28bcfbefec04plougher};
4367dfce9c3751f0580633e8a33cea28bcfbefec04plougher
447b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougherstatic int filter_count = 1;
4514c30adab9ca2147a06975bbe99308f5f54b16f0plougherstatic int dictionary_size = 0;
4614c30adab9ca2147a06975bbe99308f5f54b16f0plougherstatic float dictionary_percent = 0;
477b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
487b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
49668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher/*
50668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * This function is called by the options parsing code in mksquashfs.c
51668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * to parse any -X compressor option.
52668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *
53668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * Two specific options are supported:
54668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *	-Xbcj
55668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *	-Xdict-size
56668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *
5765ad363b09a9a96b3501f28c35fe21f23cb59013Phillip Lougher * This function returns:
5865ad363b09a9a96b3501f28c35fe21f23cb59013Phillip Lougher *	>=0 (number of additional args parsed) on success
5965ad363b09a9a96b3501f28c35fe21f23cb59013Phillip Lougher *	-1 if the option was unrecognised, or
6065ad363b09a9a96b3501f28c35fe21f23cb59013Phillip Lougher *	-2 if the option was recognised, but otherwise bad in
6165ad363b09a9a96b3501f28c35fe21f23cb59013Phillip Lougher *	   some way (e.g. invalid parameter)
62668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *
63668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * Note: this function sets internal compressor state, but does not
64668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * pass back the results of the parsing other than success/failure.
65668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * The xz_dump_options() function is called later to get the options in
66668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * a format suitable for writing to the filesystem.
67668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher */
687b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougherstatic int xz_options(char *argv[], int argc)
6967dfce9c3751f0580633e8a33cea28bcfbefec04plougher{
707b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	int i;
717b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	char *name;
727b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
737b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	if(strcmp(argv[0], "-Xbcj") == 0) {
747b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		if(argc < 2) {
757b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			fprintf(stderr, "xz: -Xbcj missing filter\n");
767b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			goto failed;
777b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		}
787b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
797b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		name = argv[1];
807b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		while(name[0] != '\0') {
817b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			for(i = 0; bcj[i].name; i++) {
827b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher				int n = strlen(bcj[i].name);
837b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher				if((strncmp(name, bcj[i].name, n) == 0) &&
847b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher						(name[n] == '\0' ||
857b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher						 name[n] == ',')) {
867b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher					if(bcj[i].selected == 0) {
877b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher				 		bcj[i].selected = 1;
887b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher						filter_count++;
897b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher					}
907b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher					name += name[n] == ',' ? n + 1 : n;
917b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher					break;
927b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher				}
937b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			}
947b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			if(bcj[i].name == NULL) {
95e08e77659d1e2eac07c9ab5dffafaa70aff41c07plougher				fprintf(stderr, "xz: -Xbcj unrecognised "
96e08e77659d1e2eac07c9ab5dffafaa70aff41c07plougher					"filter\n");
977b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher				goto failed;
987b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			}
997b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		}
1007b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
1017b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		return 1;
102d7f0fd36de82019ebf2ecfe3eb9d356a47c2e966plougher	} else if(strcmp(argv[0], "-Xdict-size") == 0) {
10314c30adab9ca2147a06975bbe99308f5f54b16f0plougher		char *b;
10414c30adab9ca2147a06975bbe99308f5f54b16f0plougher		float size;
10514c30adab9ca2147a06975bbe99308f5f54b16f0plougher
10614c30adab9ca2147a06975bbe99308f5f54b16f0plougher		if(argc < 2) {
107d7f0fd36de82019ebf2ecfe3eb9d356a47c2e966plougher			fprintf(stderr, "xz: -Xdict-size missing dict-size\n");
10814c30adab9ca2147a06975bbe99308f5f54b16f0plougher			goto failed;
10914c30adab9ca2147a06975bbe99308f5f54b16f0plougher		}
11014c30adab9ca2147a06975bbe99308f5f54b16f0plougher
11114c30adab9ca2147a06975bbe99308f5f54b16f0plougher		size = strtof(argv[1], &b);
11214c30adab9ca2147a06975bbe99308f5f54b16f0plougher		if(*b == '%') {
11314c30adab9ca2147a06975bbe99308f5f54b16f0plougher			if(size <= 0 || size > 100) {
114d7f0fd36de82019ebf2ecfe3eb9d356a47c2e966plougher				fprintf(stderr, "xz: -Xdict-size percentage "
115d7f0fd36de82019ebf2ecfe3eb9d356a47c2e966plougher					"should be 0 < dict-size <= 100\n");
11614c30adab9ca2147a06975bbe99308f5f54b16f0plougher				goto failed;
11714c30adab9ca2147a06975bbe99308f5f54b16f0plougher			}
11814c30adab9ca2147a06975bbe99308f5f54b16f0plougher
11914c30adab9ca2147a06975bbe99308f5f54b16f0plougher			dictionary_percent = size;
12014c30adab9ca2147a06975bbe99308f5f54b16f0plougher			dictionary_size = 0;
12114c30adab9ca2147a06975bbe99308f5f54b16f0plougher		} else {
12214c30adab9ca2147a06975bbe99308f5f54b16f0plougher			if((float) ((int) size) != size) {
123d7f0fd36de82019ebf2ecfe3eb9d356a47c2e966plougher				fprintf(stderr, "xz: -Xdict-size can't be "
12414c30adab9ca2147a06975bbe99308f5f54b16f0plougher					"fractional unless a percentage of the"
12514c30adab9ca2147a06975bbe99308f5f54b16f0plougher					" block size\n");
12614c30adab9ca2147a06975bbe99308f5f54b16f0plougher				goto failed;
12714c30adab9ca2147a06975bbe99308f5f54b16f0plougher			}
12814c30adab9ca2147a06975bbe99308f5f54b16f0plougher
12914c30adab9ca2147a06975bbe99308f5f54b16f0plougher			dictionary_percent = 0;
13014c30adab9ca2147a06975bbe99308f5f54b16f0plougher			dictionary_size = (int) size;
13114c30adab9ca2147a06975bbe99308f5f54b16f0plougher
13214c30adab9ca2147a06975bbe99308f5f54b16f0plougher			if(*b == 'k' || *b == 'K')
13314c30adab9ca2147a06975bbe99308f5f54b16f0plougher				dictionary_size *= 1024;
13414c30adab9ca2147a06975bbe99308f5f54b16f0plougher			else if(*b == 'm' || *b == 'M')
13514c30adab9ca2147a06975bbe99308f5f54b16f0plougher				dictionary_size *= 1024 * 1024;
13614c30adab9ca2147a06975bbe99308f5f54b16f0plougher			else if(*b != '\0') {
137e08e77659d1e2eac07c9ab5dffafaa70aff41c07plougher				fprintf(stderr, "xz: -Xdict-size invalid "
138e08e77659d1e2eac07c9ab5dffafaa70aff41c07plougher					"dict-size\n");
13914c30adab9ca2147a06975bbe99308f5f54b16f0plougher				goto failed;
14014c30adab9ca2147a06975bbe99308f5f54b16f0plougher			}
14114c30adab9ca2147a06975bbe99308f5f54b16f0plougher		}
14214c30adab9ca2147a06975bbe99308f5f54b16f0plougher
14314c30adab9ca2147a06975bbe99308f5f54b16f0plougher		return 1;
1447b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	}
1457b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
1467b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	return -1;
147d886567331690a0781c695a590e43ac37b78ad10plougher
148d886567331690a0781c695a590e43ac37b78ad10plougherfailed:
149d886567331690a0781c695a590e43ac37b78ad10plougher	return -2;
1507b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher}
15114c30adab9ca2147a06975bbe99308f5f54b16f0plougher
15214c30adab9ca2147a06975bbe99308f5f54b16f0plougher
153668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher/*
154668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * This function is called after all options have been parsed.
155668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * It is used to do post-processing on the compressor options using
156668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * values that were not expected to be known at option parse time.
157668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *
158668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * In this case block_size may not be known until after -Xdict-size has
159668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * been processed (in the case where -b is specified after -Xdict-size)
160668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *
161668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * This function returns 0 on successful post processing, or
162668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *			-1 on error
163668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher */
16414c30adab9ca2147a06975bbe99308f5f54b16f0plougherstatic int xz_options_post(int block_size)
16514c30adab9ca2147a06975bbe99308f5f54b16f0plougher{
166a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	/*
167a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	 * if -Xdict-size has been specified use this to compute the datablock
168a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	 * dictionary size
169a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	 */
170a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	if(dictionary_size || dictionary_percent) {
171a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		int n;
172a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher
173a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		if(dictionary_size) {
174a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher			if(dictionary_size > block_size) {
175a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher				fprintf(stderr, "xz: -Xdict-size is larger than"
176a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher				" block_size\n");
177a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher				goto failed;
178a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher			}
179a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		} else
180a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher			dictionary_size = block_size * dictionary_percent / 100;
18114c30adab9ca2147a06975bbe99308f5f54b16f0plougher
182a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		if(dictionary_size < 8192) {
183a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher			fprintf(stderr, "xz: -Xdict-size should be 8192 bytes "
184a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher				"or larger\n");
18514c30adab9ca2147a06975bbe99308f5f54b16f0plougher			goto failed;
18614c30adab9ca2147a06975bbe99308f5f54b16f0plougher		}
18714c30adab9ca2147a06975bbe99308f5f54b16f0plougher
188a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		/*
189a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		 * dictionary_size must be storable in xz header as either
190a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		 * 2^n or as  2^n+2^(n+1)
191a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	 	*/
192a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		n = ffs(dictionary_size) - 1;
193a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		if(dictionary_size != (1 << n) &&
194a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher				dictionary_size != ((1 << n) + (1 << (n + 1)))) {
195a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher			fprintf(stderr, "xz: -Xdict-size is an unsupported "
196a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher				"value, dict-size must be storable in xz "
197a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher				"header\n");
198a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher			fprintf(stderr, "as either 2^n or as 2^n+2^(n+1).  "
199a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher				"Example dict-sizes are 75%%, 50%%, 37.5%%, "
200a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher				"25%%,\n");
201a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher			fprintf(stderr, "or 32K, 16K, 8K etc.\n");
202a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher			goto failed;
203a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		}
20414c30adab9ca2147a06975bbe99308f5f54b16f0plougher
205a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	} else
206a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		/* No -Xdict-size specified, use defaults */
207a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		dictionary_size = block_size;
20817f039dcdb5ce2b556efff0ba49b475176790d90plougher
20917f039dcdb5ce2b556efff0ba49b475176790d90plougher	return 0;
21014c30adab9ca2147a06975bbe99308f5f54b16f0plougher
21114c30adab9ca2147a06975bbe99308f5f54b16f0plougherfailed:
21214c30adab9ca2147a06975bbe99308f5f54b16f0plougher	return -1;
21314c30adab9ca2147a06975bbe99308f5f54b16f0plougher}
21414c30adab9ca2147a06975bbe99308f5f54b16f0plougher
2157b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
216668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher/*
217668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * This function is called by mksquashfs to dump the parsed
218668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * compressor options in a format suitable for writing to the
219668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * compressor options field in the filesystem (stored immediately
220668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * after the superblock).
221668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *
222668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * This function returns a pointer to the compression options structure
223668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * to be stored (and the size), or NULL if there are no compression
224668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * options
225668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher */
226a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougherstatic void *xz_dump_options(int block_size, int *size)
22717f039dcdb5ce2b556efff0ba49b475176790d90plougher{
2285dfb7d6b00f94dee3cb2c9a1a143b2aeea86b957Phillip Lougher	static struct comp_opts comp_opts;
22917f039dcdb5ce2b556efff0ba49b475176790d90plougher	int flags = 0, i;
23017f039dcdb5ce2b556efff0ba49b475176790d90plougher
23117f039dcdb5ce2b556efff0ba49b475176790d90plougher	/*
23217f039dcdb5ce2b556efff0ba49b475176790d90plougher	 * don't store compressor specific options in file system if the
23317f039dcdb5ce2b556efff0ba49b475176790d90plougher	 * default options are being used - no compressor options in the
23417f039dcdb5ce2b556efff0ba49b475176790d90plougher	 * file system means the default options are always assumed
235a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	 *
236a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	 * Defaults are:
237a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	 *  metadata dictionary size: SQUASHFS_METADATA_SIZE
238a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	 *  datablock dictionary size: block_size
239a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	 *  1 filter
24017f039dcdb5ce2b556efff0ba49b475176790d90plougher	 */
241a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	if(dictionary_size == block_size && filter_count == 1)
24217f039dcdb5ce2b556efff0ba49b475176790d90plougher		return NULL;
24317f039dcdb5ce2b556efff0ba49b475176790d90plougher
24417f039dcdb5ce2b556efff0ba49b475176790d90plougher	for(i = 0; bcj[i].name; i++)
245c2b23524dea29c795bf7114c090bba1b77ea8055plougher		flags |= bcj[i].selected << i;
24617f039dcdb5ce2b556efff0ba49b475176790d90plougher
24717f039dcdb5ce2b556efff0ba49b475176790d90plougher	comp_opts.dictionary_size = dictionary_size;
24817f039dcdb5ce2b556efff0ba49b475176790d90plougher	comp_opts.flags = flags;
24917f039dcdb5ce2b556efff0ba49b475176790d90plougher
2501ffc835b6020c6559f0d598a41b1483c50a8945fplougher	SQUASHFS_INSWAP_COMP_OPTS(&comp_opts);
2511ffc835b6020c6559f0d598a41b1483c50a8945fplougher
25217f039dcdb5ce2b556efff0ba49b475176790d90plougher	*size = sizeof(comp_opts);
25317f039dcdb5ce2b556efff0ba49b475176790d90plougher	return &comp_opts;
25417f039dcdb5ce2b556efff0ba49b475176790d90plougher}
25517f039dcdb5ce2b556efff0ba49b475176790d90plougher
25617f039dcdb5ce2b556efff0ba49b475176790d90plougher
257668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher/*
258668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * This function is a helper specifically for the append mode of
259668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * mksquashfs.  Its purpose is to set the internal compressor state
260668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * to the stored compressor options in the passed compressor options
261668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * structure.
262668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *
263668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * In effect this function sets up the compressor options
264668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * to the same state they were when the filesystem was originally
265668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * generated, this is to ensure on appending, the compressor uses
266668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * the same compression options that were used to generate the
267668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * original filesystem.
268668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *
269668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * Note, even if there are no compressor options, this function is still
270668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * called with an empty compressor structure (size == 0), to explicitly
271668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * set the default options, this is to ensure any user supplied
272668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * -X options on the appending mksquashfs command line are over-ridden
273668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *
274668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * This function returns 0 on sucessful extraction of options, and
275668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *			-1 on error
276668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher */
277afeaf3a7dc0853af656c1000b364a92e4d093fedplougherstatic int xz_extract_options(int block_size, void *buffer, int size)
278afeaf3a7dc0853af656c1000b364a92e4d093fedplougher{
279afeaf3a7dc0853af656c1000b364a92e4d093fedplougher	struct comp_opts *comp_opts = buffer;
28039c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher	int flags, i, n;
281afeaf3a7dc0853af656c1000b364a92e4d093fedplougher
282afeaf3a7dc0853af656c1000b364a92e4d093fedplougher	if(size == 0) {
283afeaf3a7dc0853af656c1000b364a92e4d093fedplougher		/* set defaults */
284afeaf3a7dc0853af656c1000b364a92e4d093fedplougher		dictionary_size = block_size;
285afeaf3a7dc0853af656c1000b364a92e4d093fedplougher		flags = 0;
286afeaf3a7dc0853af656c1000b364a92e4d093fedplougher	} else {
28739c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher		/* check passed comp opts struct is of the correct length */
28839c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher		if(size != sizeof(struct comp_opts))
28939c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher			goto failed;
29039c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher
291fc54d8f5676c4773522a9ede6c4527ac9b1a30efPhillip Lougher		SQUASHFS_INSWAP_COMP_OPTS(comp_opts);
2921ffc835b6020c6559f0d598a41b1483c50a8945fplougher
293afeaf3a7dc0853af656c1000b364a92e4d093fedplougher		dictionary_size = comp_opts->dictionary_size;
294afeaf3a7dc0853af656c1000b364a92e4d093fedplougher		flags = comp_opts->flags;
29539c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher
29639c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher		/*
29739c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher		 * check that the dictionary size seems correct - the dictionary
29839c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher		 * size should 2^n or 2^n+2^(n+1)
29939c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher		 */
30039c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher		n = ffs(dictionary_size) - 1;
30139c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher		if(dictionary_size != (1 << n) &&
30239c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher				dictionary_size != ((1 << n) + (1 << (n + 1))))
30339c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher			goto failed;
304afeaf3a7dc0853af656c1000b364a92e4d093fedplougher	}
305afeaf3a7dc0853af656c1000b364a92e4d093fedplougher
306a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	filter_count = 1;
307a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	for(i = 0; bcj[i].name; i++) {
308a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		if((flags >> i) & 1) {
309a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher			bcj[i].selected = 1;
310a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher			filter_count ++;
311a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		} else
312a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher			bcj[i].selected = 0;
313a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher	}
314afeaf3a7dc0853af656c1000b364a92e4d093fedplougher
315afeaf3a7dc0853af656c1000b364a92e4d093fedplougher	return 0;
31639c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher
31739c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougherfailed:
31839c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher	fprintf(stderr, "xz: error reading stored compressor options from "
31939c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher		"filesystem!\n");
32039c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher
32139c2b484186d266a8d589d6f79f6b472b7e9c8c2Phillip Lougher	return -1;
322afeaf3a7dc0853af656c1000b364a92e4d093fedplougher}
323afeaf3a7dc0853af656c1000b364a92e4d093fedplougher
3247aa2f2a969f8bd684f1c31a14af9d6bba453d7f8plougher
3253fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Loughervoid xz_display_options(void *buffer, int size)
3263fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher{
3273fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	struct comp_opts *comp_opts = buffer;
3283fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	int dictionary_size, flags, printed;
3293fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	int i, n;
3303fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher
3313fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	/* check passed comp opts struct is of the correct length */
3320b44cade81d66659cb69620999dfb318e51a0697Phillip Lougher	if(size != sizeof(struct comp_opts))
3333fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher		goto failed;
3343fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher
3353fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	SQUASHFS_INSWAP_COMP_OPTS(comp_opts);
3363fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher
3373fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	dictionary_size = comp_opts->dictionary_size;
3383fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	flags = comp_opts->flags;
3393fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher
3403fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	/*
3413fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	 * check that the dictionary size seems correct - the dictionary
3423fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	 * size should 2^n or 2^n+2^(n+1)
3433fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	 */
3443fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	n = ffs(dictionary_size) - 1;
3453fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	if(dictionary_size != (1 << n) &&
3463fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher			dictionary_size != ((1 << n) + (1 << (n + 1))))
3473fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher		goto failed;
3483fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher
3493fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	printf("\tDictionary size %d\n", dictionary_size);
3503fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher
3513fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	printed = 0;
3523fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	for(i = 0; bcj[i].name; i++) {
3533fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher		if((flags >> i) & 1) {
3543fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher			if(printed)
3553fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher				printf(", ");
3563fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher			else
3573fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher				printf("\tFilters selected: ");
3583fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher			printf("%s", bcj[i].name);
3593fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher			printed = 1;
3603fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher		}
3613fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	}
3623fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher
3633fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	if(!printed)
3643fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher		printf("\tNo filters specified\n");
3653fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	else
3663fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher		printf("\n");
3673fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher
3683fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	return;
3693fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher
3703fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougherfailed:
3713fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	fprintf(stderr, "xz: error reading stored compressor options from "
3723fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher		"filesystem!\n");
3733fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher}
3743fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher
3753fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher
376668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher/*
377668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * This function is called by mksquashfs to initialise the
378668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * compressor, before compress() is called.
379668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *
380668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher * This function returns 0 on success, and
381668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher *			-1 on error
382668d2131d389b6b817df96484d924c2c7e93841fPhillip Lougher */
38365f163658a72a87ce95341ac6a423a40f2b5fc07plougherstatic int xz_init(void **strm, int block_size, int datablock)
3847b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher{
38565f163658a72a87ce95341ac6a423a40f2b5fc07plougher	int i, j, filters = datablock ? filter_count : 1;
3867b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	struct filter *filter = malloc(filters * sizeof(struct filter));
3877b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	struct xz_stream *stream;
3887b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
3897b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	if(filter == NULL)
3907b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		goto failed;
3917b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
3927b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	stream = *strm = malloc(sizeof(struct xz_stream));
3937b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	if(stream == NULL)
3947b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		goto failed2;
39567dfce9c3751f0580633e8a33cea28bcfbefec04plougher
3967b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	stream->filter = filter;
3977b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	stream->filters = filters;
39867dfce9c3751f0580633e8a33cea28bcfbefec04plougher
3997b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	memset(filter, 0, filters * sizeof(struct filter));
40067dfce9c3751f0580633e8a33cea28bcfbefec04plougher
40165f163658a72a87ce95341ac6a423a40f2b5fc07plougher	stream->dictionary_size = datablock ? dictionary_size :
402a45c9d2b6df15a359591717b71d948040efb6cd4Phillip Lougher		SQUASHFS_METADATA_SIZE;
40314c30adab9ca2147a06975bbe99308f5f54b16f0plougher
4047b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	filter[0].filter[0].id = LZMA_FILTER_LZMA2;
4057b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	filter[0].filter[0].options = &stream->opt;
4067b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	filter[0].filter[1].id = LZMA_VLI_UNKNOWN;
40767dfce9c3751f0580633e8a33cea28bcfbefec04plougher
40865f163658a72a87ce95341ac6a423a40f2b5fc07plougher	for(i = 0, j = 1; datablock && bcj[i].name; i++) {
4097b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		if(bcj[i].selected) {
4107b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			filter[j].buffer = malloc(block_size);
4117b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			if(filter[j].buffer == NULL)
4127b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher				goto failed3;
4137b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			filter[j].filter[0].id = bcj[i].id;
4147b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			filter[j].filter[1].id = LZMA_FILTER_LZMA2;
4157b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			filter[j].filter[1].options = &stream->opt;
4167b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			filter[j].filter[2].id = LZMA_VLI_UNKNOWN;
4177b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			j++;
4187b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		}
4197b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	}
4207b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4217b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	return 0;
4227b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4237b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougherfailed3:
4247b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	for(i = 1; i < filters; i++)
4257b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		free(filter[i].buffer);
4267b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	free(stream);
4277b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4287b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougherfailed2:
4297b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	free(filter);
4307b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4317b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougherfailed:
4327b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	return -1;
4337b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher}
4347b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4357b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4367b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougherstatic int xz_compress(void *strm, void *dest, void *src,  int size,
4377b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	int block_size, int *error)
4387b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher{
4397b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	int i;
4407b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher        lzma_ret res = 0;
4417b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	struct xz_stream *stream = strm;
4427b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	struct filter *selected = NULL;
4437b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4447b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	stream->filter[0].buffer = dest;
4457b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4467b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	for(i = 0; i < stream->filters; i++) {
4477b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		struct filter *filter = &stream->filter[i];
4487b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4497b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher        	if(lzma_lzma_preset(&stream->opt, LZMA_PRESET_DEFAULT))
4507b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher                	goto failed;
4517b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
45214c30adab9ca2147a06975bbe99308f5f54b16f0plougher		stream->opt.dict_size = stream->dictionary_size;
45314c30adab9ca2147a06975bbe99308f5f54b16f0plougher
4547b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		filter->length = 0;
4557b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		res = lzma_stream_buffer_encode(filter->filter,
4567b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			LZMA_CHECK_CRC32, NULL, src, size, filter->buffer,
4577b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			&filter->length, block_size);
4587b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4597b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		if(res == LZMA_OK) {
4607b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			if(!selected || selected->length > filter->length)
4617b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher				selected = filter;
4627b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		} else if(res != LZMA_BUF_ERROR)
4637b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher			goto failed;
4647b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	}
4657b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4667b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	if(!selected)
46767dfce9c3751f0580633e8a33cea28bcfbefec04plougher		/*
46867dfce9c3751f0580633e8a33cea28bcfbefec04plougher	 	 * Output buffer overflow.  Return out of buffer space
46967dfce9c3751f0580633e8a33cea28bcfbefec04plougher	 	 */
47067dfce9c3751f0580633e8a33cea28bcfbefec04plougher		return 0;
47167dfce9c3751f0580633e8a33cea28bcfbefec04plougher
4727b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	if(selected->buffer != dest)
4737b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher		memcpy(dest, selected->buffer, selected->length);
4747b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
4757b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	return (int) selected->length;
4767b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
47767dfce9c3751f0580633e8a33cea28bcfbefec04plougherfailed:
47867dfce9c3751f0580633e8a33cea28bcfbefec04plougher	/*
47967dfce9c3751f0580633e8a33cea28bcfbefec04plougher	 * All other errors return failure, with the compressor
48067dfce9c3751f0580633e8a33cea28bcfbefec04plougher	 * specific error code in *error
48167dfce9c3751f0580633e8a33cea28bcfbefec04plougher	 */
48267dfce9c3751f0580633e8a33cea28bcfbefec04plougher	*error = res;
48367dfce9c3751f0580633e8a33cea28bcfbefec04plougher	return -1;
48467dfce9c3751f0580633e8a33cea28bcfbefec04plougher}
48567dfce9c3751f0580633e8a33cea28bcfbefec04plougher
48667dfce9c3751f0580633e8a33cea28bcfbefec04plougher
4878a4692825eb1840d52f2f921e40346d0f8c7e702Phillip Lougherstatic int xz_uncompress(void *dest, void *src, int size, int outsize,
48867dfce9c3751f0580633e8a33cea28bcfbefec04plougher	int *error)
48967dfce9c3751f0580633e8a33cea28bcfbefec04plougher{
49067dfce9c3751f0580633e8a33cea28bcfbefec04plougher	size_t src_pos = 0;
49167dfce9c3751f0580633e8a33cea28bcfbefec04plougher	size_t dest_pos = 0;
49267dfce9c3751f0580633e8a33cea28bcfbefec04plougher	uint64_t memlimit = MEMLIMIT;
4937b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher
49467dfce9c3751f0580633e8a33cea28bcfbefec04plougher	lzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL,
4958a4692825eb1840d52f2f921e40346d0f8c7e702Phillip Lougher			src, &src_pos, size, dest, &dest_pos, outsize);
49667dfce9c3751f0580633e8a33cea28bcfbefec04plougher
4978b0edf380a8e22a1df314212705e6145bc746f8ePhillip Lougher	if(res == LZMA_OK && size == (int) src_pos)
4988b0edf380a8e22a1df314212705e6145bc746f8ePhillip Lougher		return (int) dest_pos;
4998b0edf380a8e22a1df314212705e6145bc746f8ePhillip Lougher	else {
5008b0edf380a8e22a1df314212705e6145bc746f8ePhillip Lougher		*error = res;
5018b0edf380a8e22a1df314212705e6145bc746f8ePhillip Lougher		return -1;
5028b0edf380a8e22a1df314212705e6145bc746f8ePhillip Lougher	}
50367dfce9c3751f0580633e8a33cea28bcfbefec04plougher}
50467dfce9c3751f0580633e8a33cea28bcfbefec04plougher
50567dfce9c3751f0580633e8a33cea28bcfbefec04plougher
5066d2d0853e045219e9d252576714966ac7831dc53ploughervoid xz_usage()
5076d2d0853e045219e9d252576714966ac7831dc53plougher{
5086d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, "\t  -Xbcj filter1,filter2,...,filterN\n");
5096d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, "\t\tCompress using filter1,filter2,...,filterN in");
5106d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, " turn\n\t\t(in addition to no filter), and choose");
5116d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, " the best compression.\n");
5126d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, "\t\tAvailable filters: x86, arm, armthumb,");
5136d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, " powerpc, sparc, ia64\n");
5146d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, "\t  -Xdict-size <dict-size>\n");
5156d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, "\t\tUse <dict-size> as the XZ dictionary size.  The");
5166d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, " dictionary size\n\t\tcan be specified as a");
5176d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, " percentage of the block size, or as an\n\t\t");
5186d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, "absolute value.  The dictionary size must be less");
51930d49e70cf81bdda75a9b2a735aa0aea33953692Phillip Lougher	fprintf(stderr, " than or equal\n\t\tto the block size and 8192 bytes");
5206d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, " or larger.  It must also be\n\t\tstorable in the xz");
5216d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, " header as either 2^n or as 2^n+2^(n+1).\n\t\t");
5226d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, "Example dict-sizes are 75%%, 50%%, 37.5%%, 25%%, or");
5236d2d0853e045219e9d252576714966ac7831dc53plougher	fprintf(stderr, " 32K, 16K, 8K\n\t\tetc.\n");
5246d2d0853e045219e9d252576714966ac7831dc53plougher}
5256d2d0853e045219e9d252576714966ac7831dc53plougher
5266d2d0853e045219e9d252576714966ac7831dc53plougher
52767dfce9c3751f0580633e8a33cea28bcfbefec04plougherstruct compressor xz_comp_ops = {
5287b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	.init = xz_init,
52967dfce9c3751f0580633e8a33cea28bcfbefec04plougher	.compress = xz_compress,
53067dfce9c3751f0580633e8a33cea28bcfbefec04plougher	.uncompress = xz_uncompress,
5317b6b352b70dcd9f8e71027e8a4c1e4807fc7240dplougher	.options = xz_options,
53214c30adab9ca2147a06975bbe99308f5f54b16f0plougher	.options_post = xz_options_post,
53317f039dcdb5ce2b556efff0ba49b475176790d90plougher	.dump_options = xz_dump_options,
534afeaf3a7dc0853af656c1000b364a92e4d093fedplougher	.extract_options = xz_extract_options,
5353fcced11c3e4b49b2b687010304b5156935a3b2cPhillip Lougher	.display_options = xz_display_options,
5367aa2f2a969f8bd684f1c31a14af9d6bba453d7f8plougher	.usage = xz_usage,
53767dfce9c3751f0580633e8a33cea28bcfbefec04plougher	.id = XZ_COMPRESSION,
53867dfce9c3751f0580633e8a33cea28bcfbefec04plougher	.name = "xz",
53967dfce9c3751f0580633e8a33cea28bcfbefec04plougher	.supported = 1
54067dfce9c3751f0580633e8a33cea28bcfbefec04plougher};
541