xref: /aosp_15_r20/external/squashfs-tools/squashfs-tools/lz4_wrapper.c (revision 79398b2563bcbbbab54656397863972d8fa68df1)
1*79398b25SAndroid Build Coastguard Worker /*
2*79398b25SAndroid Build Coastguard Worker  * Copyright (c) 2013
3*79398b25SAndroid Build Coastguard Worker  * Phillip Lougher <[email protected]>
4*79398b25SAndroid Build Coastguard Worker  *
5*79398b25SAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or
6*79398b25SAndroid Build Coastguard Worker  * modify it under the terms of the GNU General Public License
7*79398b25SAndroid Build Coastguard Worker  * as published by the Free Software Foundation; either version 2,
8*79398b25SAndroid Build Coastguard Worker  * or (at your option) any later version.
9*79398b25SAndroid Build Coastguard Worker  *
10*79398b25SAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
11*79398b25SAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*79398b25SAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*79398b25SAndroid Build Coastguard Worker  * GNU General Public License for more details.
14*79398b25SAndroid Build Coastguard Worker  *
15*79398b25SAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License
16*79398b25SAndroid Build Coastguard Worker  * along with this program; if not, write to the Free Software
17*79398b25SAndroid Build Coastguard Worker  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18*79398b25SAndroid Build Coastguard Worker  *
19*79398b25SAndroid Build Coastguard Worker  * lz4_wrapper.c
20*79398b25SAndroid Build Coastguard Worker  *
21*79398b25SAndroid Build Coastguard Worker  * Support for LZ4 compression http://fastcompression.blogspot.com/p/lz4.html
22*79398b25SAndroid Build Coastguard Worker  */
23*79398b25SAndroid Build Coastguard Worker 
24*79398b25SAndroid Build Coastguard Worker #include <stdio.h>
25*79398b25SAndroid Build Coastguard Worker #include <string.h>
26*79398b25SAndroid Build Coastguard Worker #include <stdlib.h>
27*79398b25SAndroid Build Coastguard Worker #include <lz4.h>
28*79398b25SAndroid Build Coastguard Worker #include <lz4hc.h>
29*79398b25SAndroid Build Coastguard Worker 
30*79398b25SAndroid Build Coastguard Worker #include "squashfs_fs.h"
31*79398b25SAndroid Build Coastguard Worker #include "lz4_wrapper.h"
32*79398b25SAndroid Build Coastguard Worker #include "compressor.h"
33*79398b25SAndroid Build Coastguard Worker 
34*79398b25SAndroid Build Coastguard Worker static int hc = 0;
35*79398b25SAndroid Build Coastguard Worker 
36*79398b25SAndroid Build Coastguard Worker /*
37*79398b25SAndroid Build Coastguard Worker  * This function is called by the options parsing code in mksquashfs.c
38*79398b25SAndroid Build Coastguard Worker  * to parse any -X compressor option.
39*79398b25SAndroid Build Coastguard Worker  *
40*79398b25SAndroid Build Coastguard Worker  * This function returns:
41*79398b25SAndroid Build Coastguard Worker  *	>=0 (number of additional args parsed) on success
42*79398b25SAndroid Build Coastguard Worker  *	-1 if the option was unrecognised, or
43*79398b25SAndroid Build Coastguard Worker  *	-2 if the option was recognised, but otherwise bad in
44*79398b25SAndroid Build Coastguard Worker  *	   some way (e.g. invalid parameter)
45*79398b25SAndroid Build Coastguard Worker  *
46*79398b25SAndroid Build Coastguard Worker  * Note: this function sets internal compressor state, but does not
47*79398b25SAndroid Build Coastguard Worker  * pass back the results of the parsing other than success/failure.
48*79398b25SAndroid Build Coastguard Worker  * The lz4_dump_options() function is called later to get the options in
49*79398b25SAndroid Build Coastguard Worker  * a format suitable for writing to the filesystem.
50*79398b25SAndroid Build Coastguard Worker  */
lz4_options(char * argv[],int argc)51*79398b25SAndroid Build Coastguard Worker static int lz4_options(char *argv[], int argc)
52*79398b25SAndroid Build Coastguard Worker {
53*79398b25SAndroid Build Coastguard Worker 	if(strcmp(argv[0], "-Xhc") == 0) {
54*79398b25SAndroid Build Coastguard Worker 		hc = 1;
55*79398b25SAndroid Build Coastguard Worker 		return 0;
56*79398b25SAndroid Build Coastguard Worker 	}
57*79398b25SAndroid Build Coastguard Worker 
58*79398b25SAndroid Build Coastguard Worker 	return -1;
59*79398b25SAndroid Build Coastguard Worker }
60*79398b25SAndroid Build Coastguard Worker 
61*79398b25SAndroid Build Coastguard Worker 
62*79398b25SAndroid Build Coastguard Worker /*
63*79398b25SAndroid Build Coastguard Worker  * This function is called by mksquashfs to dump the parsed
64*79398b25SAndroid Build Coastguard Worker  * compressor options in a format suitable for writing to the
65*79398b25SAndroid Build Coastguard Worker  * compressor options field in the filesystem (stored immediately
66*79398b25SAndroid Build Coastguard Worker  * after the superblock).
67*79398b25SAndroid Build Coastguard Worker  *
68*79398b25SAndroid Build Coastguard Worker  * This function returns a pointer to the compression options structure
69*79398b25SAndroid Build Coastguard Worker  * to be stored (and the size), or NULL if there are no compression
70*79398b25SAndroid Build Coastguard Worker  * options
71*79398b25SAndroid Build Coastguard Worker  *
72*79398b25SAndroid Build Coastguard Worker  * Currently LZ4 always returns a comp_opts structure, with
73*79398b25SAndroid Build Coastguard Worker  * the version indicating LZ4_LEGACY stream fomat.  This is to
74*79398b25SAndroid Build Coastguard Worker  * easily accomodate changes in the kernel code to different
75*79398b25SAndroid Build Coastguard Worker  * stream formats
76*79398b25SAndroid Build Coastguard Worker  */
lz4_dump_options(int block_size,int * size)77*79398b25SAndroid Build Coastguard Worker static void *lz4_dump_options(int block_size, int *size)
78*79398b25SAndroid Build Coastguard Worker {
79*79398b25SAndroid Build Coastguard Worker 	static struct lz4_comp_opts comp_opts;
80*79398b25SAndroid Build Coastguard Worker 
81*79398b25SAndroid Build Coastguard Worker 	comp_opts.version = LZ4_LEGACY;
82*79398b25SAndroid Build Coastguard Worker 	comp_opts.flags = hc ? LZ4_HC : 0;
83*79398b25SAndroid Build Coastguard Worker 	SQUASHFS_INSWAP_COMP_OPTS(&comp_opts);
84*79398b25SAndroid Build Coastguard Worker 
85*79398b25SAndroid Build Coastguard Worker 	*size = sizeof(comp_opts);
86*79398b25SAndroid Build Coastguard Worker 	return &comp_opts;
87*79398b25SAndroid Build Coastguard Worker }
88*79398b25SAndroid Build Coastguard Worker 
89*79398b25SAndroid Build Coastguard Worker 
90*79398b25SAndroid Build Coastguard Worker /*
91*79398b25SAndroid Build Coastguard Worker  * This function is a helper specifically for the append mode of
92*79398b25SAndroid Build Coastguard Worker  * mksquashfs.  Its purpose is to set the internal compressor state
93*79398b25SAndroid Build Coastguard Worker  * to the stored compressor options in the passed compressor options
94*79398b25SAndroid Build Coastguard Worker  * structure.
95*79398b25SAndroid Build Coastguard Worker  *
96*79398b25SAndroid Build Coastguard Worker  * In effect this function sets up the compressor options
97*79398b25SAndroid Build Coastguard Worker  * to the same state they were when the filesystem was originally
98*79398b25SAndroid Build Coastguard Worker  * generated, this is to ensure on appending, the compressor uses
99*79398b25SAndroid Build Coastguard Worker  * the same compression options that were used to generate the
100*79398b25SAndroid Build Coastguard Worker  * original filesystem.
101*79398b25SAndroid Build Coastguard Worker  *
102*79398b25SAndroid Build Coastguard Worker  * Note, even if there are no compressor options, this function is still
103*79398b25SAndroid Build Coastguard Worker  * called with an empty compressor structure (size == 0), to explicitly
104*79398b25SAndroid Build Coastguard Worker  * set the default options, this is to ensure any user supplied
105*79398b25SAndroid Build Coastguard Worker  * -X options on the appending mksquashfs command line are over-ridden
106*79398b25SAndroid Build Coastguard Worker  *
107*79398b25SAndroid Build Coastguard Worker  * This function returns 0 on sucessful extraction of options, and
108*79398b25SAndroid Build Coastguard Worker  *			-1 on error
109*79398b25SAndroid Build Coastguard Worker  */
lz4_extract_options(int block_size,void * buffer,int size)110*79398b25SAndroid Build Coastguard Worker static int lz4_extract_options(int block_size, void *buffer, int size)
111*79398b25SAndroid Build Coastguard Worker {
112*79398b25SAndroid Build Coastguard Worker 	struct lz4_comp_opts *comp_opts = buffer;
113*79398b25SAndroid Build Coastguard Worker 
114*79398b25SAndroid Build Coastguard Worker 	/* we expect a comp_opts structure to be present */
115*79398b25SAndroid Build Coastguard Worker 	if(size < sizeof(*comp_opts))
116*79398b25SAndroid Build Coastguard Worker 		goto failed;
117*79398b25SAndroid Build Coastguard Worker 
118*79398b25SAndroid Build Coastguard Worker 	SQUASHFS_INSWAP_COMP_OPTS(comp_opts);
119*79398b25SAndroid Build Coastguard Worker 
120*79398b25SAndroid Build Coastguard Worker 	/* we expect the stream format to be LZ4_LEGACY */
121*79398b25SAndroid Build Coastguard Worker 	if(comp_opts->version != LZ4_LEGACY) {
122*79398b25SAndroid Build Coastguard Worker 		fprintf(stderr, "lz4: unknown LZ4 version\n");
123*79398b25SAndroid Build Coastguard Worker 		goto failed;
124*79398b25SAndroid Build Coastguard Worker 	}
125*79398b25SAndroid Build Coastguard Worker 
126*79398b25SAndroid Build Coastguard Worker 	/*
127*79398b25SAndroid Build Coastguard Worker 	 * Check compression flags, currently only LZ4_HC ("high compression")
128*79398b25SAndroid Build Coastguard Worker 	 * can be set.
129*79398b25SAndroid Build Coastguard Worker 	 */
130*79398b25SAndroid Build Coastguard Worker 	if(comp_opts->flags == LZ4_HC)
131*79398b25SAndroid Build Coastguard Worker 		hc = 1;
132*79398b25SAndroid Build Coastguard Worker 	else if(comp_opts->flags != 0) {
133*79398b25SAndroid Build Coastguard Worker 		fprintf(stderr, "lz4: unknown LZ4 flags\n");
134*79398b25SAndroid Build Coastguard Worker 		goto failed;
135*79398b25SAndroid Build Coastguard Worker 	}
136*79398b25SAndroid Build Coastguard Worker 
137*79398b25SAndroid Build Coastguard Worker 	return 0;
138*79398b25SAndroid Build Coastguard Worker 
139*79398b25SAndroid Build Coastguard Worker failed:
140*79398b25SAndroid Build Coastguard Worker 	fprintf(stderr, "lz4: error reading stored compressor options from "
141*79398b25SAndroid Build Coastguard Worker 		"filesystem!\n");
142*79398b25SAndroid Build Coastguard Worker 
143*79398b25SAndroid Build Coastguard Worker 	return -1;
144*79398b25SAndroid Build Coastguard Worker }
145*79398b25SAndroid Build Coastguard Worker 
146*79398b25SAndroid Build Coastguard Worker 
147*79398b25SAndroid Build Coastguard Worker /*
148*79398b25SAndroid Build Coastguard Worker  * This function is a helper specifically for unsquashfs.
149*79398b25SAndroid Build Coastguard Worker  * Its purpose is to check that the compression options are
150*79398b25SAndroid Build Coastguard Worker  * understood by this version of LZ4.
151*79398b25SAndroid Build Coastguard Worker  *
152*79398b25SAndroid Build Coastguard Worker  * This is important for LZ4 because the format understood by the
153*79398b25SAndroid Build Coastguard Worker  * Linux kernel may change from the already obsolete legacy format
154*79398b25SAndroid Build Coastguard Worker  * currently supported.
155*79398b25SAndroid Build Coastguard Worker  *
156*79398b25SAndroid Build Coastguard Worker  * If this does happen, then this version of LZ4 will not be able to decode
157*79398b25SAndroid Build Coastguard Worker  * the newer format.  So we need to check for this.
158*79398b25SAndroid Build Coastguard Worker  *
159*79398b25SAndroid Build Coastguard Worker  * This function returns 0 on sucessful checking of options, and
160*79398b25SAndroid Build Coastguard Worker  *			-1 on error
161*79398b25SAndroid Build Coastguard Worker  */
lz4_check_options(int block_size,void * buffer,int size)162*79398b25SAndroid Build Coastguard Worker static int lz4_check_options(int block_size, void *buffer, int size)
163*79398b25SAndroid Build Coastguard Worker {
164*79398b25SAndroid Build Coastguard Worker 	struct lz4_comp_opts *comp_opts = buffer;
165*79398b25SAndroid Build Coastguard Worker 
166*79398b25SAndroid Build Coastguard Worker 	/* we expect a comp_opts structure to be present */
167*79398b25SAndroid Build Coastguard Worker 	if(size < sizeof(*comp_opts))
168*79398b25SAndroid Build Coastguard Worker 		goto failed;
169*79398b25SAndroid Build Coastguard Worker 
170*79398b25SAndroid Build Coastguard Worker 	SQUASHFS_INSWAP_COMP_OPTS(comp_opts);
171*79398b25SAndroid Build Coastguard Worker 
172*79398b25SAndroid Build Coastguard Worker 	/* we expect the stream format to be LZ4_LEGACY */
173*79398b25SAndroid Build Coastguard Worker 	if(comp_opts->version != LZ4_LEGACY) {
174*79398b25SAndroid Build Coastguard Worker 		fprintf(stderr, "lz4: unknown LZ4 version\n");
175*79398b25SAndroid Build Coastguard Worker 		goto failed;
176*79398b25SAndroid Build Coastguard Worker 	}
177*79398b25SAndroid Build Coastguard Worker 
178*79398b25SAndroid Build Coastguard Worker 	return 0;
179*79398b25SAndroid Build Coastguard Worker 
180*79398b25SAndroid Build Coastguard Worker failed:
181*79398b25SAndroid Build Coastguard Worker 	fprintf(stderr, "lz4: error reading stored compressor options from "
182*79398b25SAndroid Build Coastguard Worker 		"filesystem!\n");
183*79398b25SAndroid Build Coastguard Worker 	return -1;
184*79398b25SAndroid Build Coastguard Worker }
185*79398b25SAndroid Build Coastguard Worker 
186*79398b25SAndroid Build Coastguard Worker 
lz4_display_options(void * buffer,int size)187*79398b25SAndroid Build Coastguard Worker void lz4_display_options(void *buffer, int size)
188*79398b25SAndroid Build Coastguard Worker {
189*79398b25SAndroid Build Coastguard Worker 	struct lz4_comp_opts *comp_opts = buffer;
190*79398b25SAndroid Build Coastguard Worker 
191*79398b25SAndroid Build Coastguard Worker 	/* check passed comp opts struct is of the correct length */
192*79398b25SAndroid Build Coastguard Worker 	if(size < sizeof(*comp_opts))
193*79398b25SAndroid Build Coastguard Worker 		goto failed;
194*79398b25SAndroid Build Coastguard Worker 
195*79398b25SAndroid Build Coastguard Worker 	SQUASHFS_INSWAP_COMP_OPTS(comp_opts);
196*79398b25SAndroid Build Coastguard Worker 
197*79398b25SAndroid Build Coastguard Worker 	/* we expect the stream format to be LZ4_LEGACY */
198*79398b25SAndroid Build Coastguard Worker 	if(comp_opts->version != LZ4_LEGACY) {
199*79398b25SAndroid Build Coastguard Worker 		fprintf(stderr, "lz4: unknown LZ4 version\n");
200*79398b25SAndroid Build Coastguard Worker 		goto failed;
201*79398b25SAndroid Build Coastguard Worker 	}
202*79398b25SAndroid Build Coastguard Worker 
203*79398b25SAndroid Build Coastguard Worker 	/*
204*79398b25SAndroid Build Coastguard Worker 	 * Check compression flags, currently only LZ4_HC ("high compression")
205*79398b25SAndroid Build Coastguard Worker 	 * can be set.
206*79398b25SAndroid Build Coastguard Worker 	 */
207*79398b25SAndroid Build Coastguard Worker 	if(comp_opts->flags & ~LZ4_FLAGS_MASK) {
208*79398b25SAndroid Build Coastguard Worker 		fprintf(stderr, "lz4: unknown LZ4 flags\n");
209*79398b25SAndroid Build Coastguard Worker 		goto failed;
210*79398b25SAndroid Build Coastguard Worker 	}
211*79398b25SAndroid Build Coastguard Worker 
212*79398b25SAndroid Build Coastguard Worker 	if(comp_opts->flags & LZ4_HC)
213*79398b25SAndroid Build Coastguard Worker 		printf("\tHigh Compression option specified (-Xhc)\n");
214*79398b25SAndroid Build Coastguard Worker 
215*79398b25SAndroid Build Coastguard Worker 	return;
216*79398b25SAndroid Build Coastguard Worker 
217*79398b25SAndroid Build Coastguard Worker failed:
218*79398b25SAndroid Build Coastguard Worker 	fprintf(stderr, "lz4: error reading stored compressor options from "
219*79398b25SAndroid Build Coastguard Worker 		"filesystem!\n");
220*79398b25SAndroid Build Coastguard Worker }
221*79398b25SAndroid Build Coastguard Worker 
222*79398b25SAndroid Build Coastguard Worker 
lz4_compress(void * strm,void * dest,void * src,int size,int block_size,int * error)223*79398b25SAndroid Build Coastguard Worker static int lz4_compress(void *strm, void *dest, void *src,  int size,
224*79398b25SAndroid Build Coastguard Worker 	int block_size, int *error)
225*79398b25SAndroid Build Coastguard Worker {
226*79398b25SAndroid Build Coastguard Worker 	int res;
227*79398b25SAndroid Build Coastguard Worker 
228*79398b25SAndroid Build Coastguard Worker 	if(hc)
229*79398b25SAndroid Build Coastguard Worker 		res = LZ4_compress_HC(src, dest, size, block_size,
230*79398b25SAndroid Build Coastguard Worker 				      LZ4HC_CLEVEL_DEFAULT);
231*79398b25SAndroid Build Coastguard Worker 	else
232*79398b25SAndroid Build Coastguard Worker 		res = LZ4_compress_default(src, dest, size, block_size);
233*79398b25SAndroid Build Coastguard Worker 
234*79398b25SAndroid Build Coastguard Worker 	if(res == 0) {
235*79398b25SAndroid Build Coastguard Worker 		/*
236*79398b25SAndroid Build Coastguard Worker 	 	 * Output buffer overflow.  Return out of buffer space
237*79398b25SAndroid Build Coastguard Worker 	 	 */
238*79398b25SAndroid Build Coastguard Worker 		return 0;
239*79398b25SAndroid Build Coastguard Worker 	} else if(res < 0) {
240*79398b25SAndroid Build Coastguard Worker 		/*
241*79398b25SAndroid Build Coastguard Worker 	 	 * All other errors return failure, with the compressor
242*79398b25SAndroid Build Coastguard Worker 	 	 * specific error code in *error
243*79398b25SAndroid Build Coastguard Worker 	 	 */
244*79398b25SAndroid Build Coastguard Worker 		*error = res;
245*79398b25SAndroid Build Coastguard Worker 		return -1;
246*79398b25SAndroid Build Coastguard Worker 	}
247*79398b25SAndroid Build Coastguard Worker 
248*79398b25SAndroid Build Coastguard Worker 	return res;
249*79398b25SAndroid Build Coastguard Worker }
250*79398b25SAndroid Build Coastguard Worker 
251*79398b25SAndroid Build Coastguard Worker 
lz4_uncompress(void * dest,void * src,int size,int outsize,int * error)252*79398b25SAndroid Build Coastguard Worker static int lz4_uncompress(void *dest, void *src, int size, int outsize,
253*79398b25SAndroid Build Coastguard Worker 	int *error)
254*79398b25SAndroid Build Coastguard Worker {
255*79398b25SAndroid Build Coastguard Worker 	int res = LZ4_decompress_safe(src, dest, size, outsize);
256*79398b25SAndroid Build Coastguard Worker 	if(res < 0) {
257*79398b25SAndroid Build Coastguard Worker 		*error = res;
258*79398b25SAndroid Build Coastguard Worker 		return -1;
259*79398b25SAndroid Build Coastguard Worker 	}
260*79398b25SAndroid Build Coastguard Worker 
261*79398b25SAndroid Build Coastguard Worker 	return res;
262*79398b25SAndroid Build Coastguard Worker }
263*79398b25SAndroid Build Coastguard Worker 
264*79398b25SAndroid Build Coastguard Worker 
lz4_usage()265*79398b25SAndroid Build Coastguard Worker void lz4_usage()
266*79398b25SAndroid Build Coastguard Worker {
267*79398b25SAndroid Build Coastguard Worker 	fprintf(stderr, "\t  -Xhc\n");
268*79398b25SAndroid Build Coastguard Worker 	fprintf(stderr, "\t\tCompress using LZ4 High Compression\n");
269*79398b25SAndroid Build Coastguard Worker }
270*79398b25SAndroid Build Coastguard Worker 
271*79398b25SAndroid Build Coastguard Worker 
272*79398b25SAndroid Build Coastguard Worker struct compressor lz4_comp_ops = {
273*79398b25SAndroid Build Coastguard Worker 	.compress = lz4_compress,
274*79398b25SAndroid Build Coastguard Worker 	.uncompress = lz4_uncompress,
275*79398b25SAndroid Build Coastguard Worker 	.options = lz4_options,
276*79398b25SAndroid Build Coastguard Worker 	.dump_options = lz4_dump_options,
277*79398b25SAndroid Build Coastguard Worker 	.extract_options = lz4_extract_options,
278*79398b25SAndroid Build Coastguard Worker 	.check_options = lz4_check_options,
279*79398b25SAndroid Build Coastguard Worker 	.display_options = lz4_display_options,
280*79398b25SAndroid Build Coastguard Worker 	.usage = lz4_usage,
281*79398b25SAndroid Build Coastguard Worker 	.id = LZ4_COMPRESSION,
282*79398b25SAndroid Build Coastguard Worker 	.name = "lz4",
283*79398b25SAndroid Build Coastguard Worker 	.supported = 1
284*79398b25SAndroid Build Coastguard Worker };
285