]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - SQUASHFS/squashfs-tools-4.4/squashfs-tools/lzo_wrapper.c
1.1.07 release
[Ventoy.git] / SQUASHFS / squashfs-tools-4.4 / squashfs-tools / lzo_wrapper.c
1 /*
2 * Copyright (c) 2013, 2014
3 * Phillip Lougher <phillip@squashfs.org.uk>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2,
8 * or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 * lzo_wrapper.c
20 *
21 * Support for LZO compression http://www.oberhumer.com/opensource/lzo
22 */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <lzo/lzoconf.h>
28 #include <lzo/lzo1x.h>
29
30 #include "squashfs_fs.h"
31 #include "lzo_wrapper.h"
32 #include "compressor.h"
33
34 static struct lzo_algorithm lzo[] = {
35 { "lzo1x_1", LZO1X_1_MEM_COMPRESS, lzo1x_1_compress },
36 { "lzo1x_1_11", LZO1X_1_11_MEM_COMPRESS, lzo1x_1_11_compress },
37 { "lzo1x_1_12", LZO1X_1_12_MEM_COMPRESS, lzo1x_1_12_compress },
38 { "lzo1x_1_15", LZO1X_1_15_MEM_COMPRESS, lzo1x_1_15_compress },
39 { "lzo1x_999", LZO1X_999_MEM_COMPRESS, lzo1x_999_wrapper },
40 { NULL, 0, NULL }
41 };
42
43 /* default LZO compression algorithm and compression level */
44 static int algorithm = SQUASHFS_LZO1X_999;
45 static int compression_level = SQUASHFS_LZO1X_999_COMP_DEFAULT;
46
47 /* user specified compression level */
48 static int user_comp_level = -1;
49
50
51 /*
52 * This function is called by the options parsing code in mksquashfs.c
53 * to parse any -X compressor option.
54 *
55 * This function returns:
56 * >=0 (number of additional args parsed) on success
57 * -1 if the option was unrecognised, or
58 * -2 if the option was recognised, but otherwise bad in
59 * some way (e.g. invalid parameter)
60 *
61 * Note: this function sets internal compressor state, but does not
62 * pass back the results of the parsing other than success/failure.
63 * The lzo_dump_options() function is called later to get the options in
64 * a format suitable for writing to the filesystem.
65 */
66 static int lzo_options(char *argv[], int argc)
67 {
68 (void)argv;
69 (void)argc;
70 return 1;
71 }
72
73
74 /*
75 * This function is called after all options have been parsed.
76 * It is used to do post-processing on the compressor options using
77 * values that were not expected to be known at option parse time.
78 *
79 * In this case the LZO algorithm may not be known until after the
80 * compression level has been set (-Xalgorithm used after -Xcompression-level)
81 *
82 * This function returns 0 on successful post processing, or
83 * -1 on error
84 */
85 static int lzo_options_post(int block_size)
86 {
87 /*
88 * Use of compression level only makes sense for
89 * LZO1X_999 algorithm
90 */
91 if(user_comp_level != -1) {
92 if(algorithm != SQUASHFS_LZO1X_999) {
93 fprintf(stderr, "lzo: -Xcompression-level not "
94 "supported by selected %s algorithm\n",
95 lzo[algorithm].name);
96 fprintf(stderr, "lzo: -Xcompression-level is only "
97 "applicable for the lzo1x_999 algorithm\n");
98 goto failed;
99 }
100 compression_level = user_comp_level;
101 }
102
103 return 0;
104
105 failed:
106 return -1;
107 }
108
109
110 /*
111 * This function is called by mksquashfs to dump the parsed
112 * compressor options in a format suitable for writing to the
113 * compressor options field in the filesystem (stored immediately
114 * after the superblock).
115 *
116 * This function returns a pointer to the compression options structure
117 * to be stored (and the size), or NULL if there are no compression
118 * options
119 *
120 */
121 static void *lzo_dump_options(int block_size, int *size)
122 {
123 static struct lzo_comp_opts comp_opts;
124
125 /*
126 * If default compression options of SQUASHFS_LZO1X_999 and
127 * compression level of SQUASHFS_LZO1X_999_COMP_DEFAULT then
128 * don't store a compression options structure (this is compatible
129 * with the legacy implementation of LZO for Squashfs)
130 */
131 if(algorithm == SQUASHFS_LZO1X_999 &&
132 compression_level == SQUASHFS_LZO1X_999_COMP_DEFAULT)
133 return NULL;
134
135 comp_opts.algorithm = algorithm;
136 comp_opts.compression_level = algorithm == SQUASHFS_LZO1X_999 ?
137 compression_level : 0;
138
139 SQUASHFS_INSWAP_COMP_OPTS(&comp_opts);
140
141 *size = sizeof(comp_opts);
142 return &comp_opts;
143 }
144
145
146 /*
147 * This function is a helper specifically for the append mode of
148 * mksquashfs. Its purpose is to set the internal compressor state
149 * to the stored compressor options in the passed compressor options
150 * structure.
151 *
152 * In effect this function sets up the compressor options
153 * to the same state they were when the filesystem was originally
154 * generated, this is to ensure on appending, the compressor uses
155 * the same compression options that were used to generate the
156 * original filesystem.
157 *
158 * Note, even if there are no compressor options, this function is still
159 * called with an empty compressor structure (size == 0), to explicitly
160 * set the default options, this is to ensure any user supplied
161 * -X options on the appending mksquashfs command line are over-ridden
162 *
163 * This function returns 0 on sucessful extraction of options, and
164 * -1 on error
165 */
166 static int lzo_extract_options(int block_size, void *buffer, int size)
167 {
168 struct lzo_comp_opts *comp_opts = buffer;
169
170 if(size == 0) {
171 /* Set default values */
172 algorithm = SQUASHFS_LZO1X_999;
173 compression_level = SQUASHFS_LZO1X_999_COMP_DEFAULT;
174 return 0;
175 }
176
177 /* we expect a comp_opts structure of sufficient size to be present */
178 if(size < sizeof(*comp_opts))
179 goto failed;
180
181 SQUASHFS_INSWAP_COMP_OPTS(comp_opts);
182
183 /* Check comp_opts structure for correctness */
184 switch(comp_opts->algorithm) {
185 case SQUASHFS_LZO1X_1:
186 case SQUASHFS_LZO1X_1_11:
187 case SQUASHFS_LZO1X_1_12:
188 case SQUASHFS_LZO1X_1_15:
189 if(comp_opts->compression_level != 0) {
190 fprintf(stderr, "lzo: bad compression level in "
191 "compression options structure\n");
192 goto failed;
193 }
194 break;
195 case SQUASHFS_LZO1X_999:
196 if(comp_opts->compression_level < 1 ||
197 comp_opts->compression_level > 9) {
198 fprintf(stderr, "lzo: bad compression level in "
199 "compression options structure\n");
200 goto failed;
201 }
202 compression_level = comp_opts->compression_level;
203 break;
204 default:
205 fprintf(stderr, "lzo: bad algorithm in compression options "
206 "structure\n");
207 goto failed;
208 }
209
210 algorithm = comp_opts->algorithm;
211
212 return 0;
213
214 failed:
215 fprintf(stderr, "lzo: error reading stored compressor options from "
216 "filesystem!\n");
217
218 return -1;
219 }
220
221
222 static void lzo_display_options(void *buffer, int size)
223 {
224 struct lzo_comp_opts *comp_opts = buffer;
225
226 /* we expect a comp_opts structure of sufficient size to be present */
227 if(size < sizeof(*comp_opts))
228 goto failed;
229
230 SQUASHFS_INSWAP_COMP_OPTS(comp_opts);
231
232 /* Check comp_opts structure for correctness */
233 switch(comp_opts->algorithm) {
234 case SQUASHFS_LZO1X_1:
235 case SQUASHFS_LZO1X_1_11:
236 case SQUASHFS_LZO1X_1_12:
237 case SQUASHFS_LZO1X_1_15:
238 printf("\talgorithm %s\n", lzo[comp_opts->algorithm].name);
239 break;
240 case SQUASHFS_LZO1X_999:
241 if(comp_opts->compression_level < 1 ||
242 comp_opts->compression_level > 9) {
243 fprintf(stderr, "lzo: bad compression level in "
244 "compression options structure\n");
245 goto failed;
246 }
247 printf("\talgorithm %s\n", lzo[comp_opts->algorithm].name);
248 printf("\tcompression level %d\n",
249 comp_opts->compression_level);
250 break;
251 default:
252 fprintf(stderr, "lzo: bad algorithm in compression options "
253 "structure\n");
254 goto failed;
255 }
256
257 return;
258
259 failed:
260 fprintf(stderr, "lzo: error reading stored compressor options from "
261 "filesystem!\n");
262 }
263
264
265 /*
266 * This function is called by mksquashfs to initialise the
267 * compressor, before compress() is called.
268 *
269 * This function returns 0 on success, and
270 * -1 on error
271 */
272 static int squashfs_lzo_init(void **strm, int block_size, int datablock)
273 {
274 struct lzo_stream *stream;
275
276 stream = *strm = malloc(sizeof(struct lzo_stream));
277 if(stream == NULL)
278 goto failed;
279
280 stream->workspace = malloc(lzo[algorithm].size);
281 if(stream->workspace == NULL)
282 goto failed2;
283
284 stream->buffer = malloc(LZO_MAX_EXPANSION(block_size));
285 if(stream->buffer != NULL)
286 return 0;
287
288 free(stream->workspace);
289 failed2:
290 free(stream);
291 failed:
292 return -1;
293 }
294
295
296 static int lzo_compress(void *strm, void *dest, void *src, int size,
297 int block_size, int *error)
298 {
299
300 return 0;
301 }
302
303
304 static int lzo_uncompress(void *dest, void *src, int size, int outsize,
305 int *error)
306 {
307 int res;
308 lzo_uint outlen = outsize;
309
310 res = lzo1x_decompress_safe(src, size, dest, &outlen, NULL);
311 if(res != LZO_E_OK) {
312 *error = res;
313 return -1;
314 }
315
316 return outlen;
317 }
318
319
320 static void lzo_usage()
321 {
322 int i;
323
324 fprintf(stderr, "\t -Xalgorithm <algorithm>\n");
325 fprintf(stderr, "\t\tWhere <algorithm> is one of:\n");
326
327 for(i = 0; lzo[i].name; i++)
328 fprintf(stderr, "\t\t\t%s%s\n", lzo[i].name,
329 i == SQUASHFS_LZO1X_999 ? " (default)" : "");
330
331 fprintf(stderr, "\t -Xcompression-level <compression-level>\n");
332 fprintf(stderr, "\t\t<compression-level> should be 1 .. 9 (default "
333 "%d)\n", SQUASHFS_LZO1X_999_COMP_DEFAULT);
334 fprintf(stderr, "\t\tOnly applies to lzo1x_999 algorithm\n");
335 }
336
337
338 /*
339 * Helper function for lzo1x_999 compression algorithm.
340 * All other lzo1x_xxx compressors do not take a compression level,
341 * so we need to wrap lzo1x_999 to pass the compression level which
342 * is applicable to it
343 */
344 int lzo1x_999_wrapper(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst,
345 lzo_uintp compsize, lzo_voidp workspace)
346 {
347 return lzo1x_999_compress_level(src, src_len, dst, compsize,
348 workspace, NULL, 0, 0, compression_level);
349 }
350
351
352 struct compressor lzo_comp_ops = {
353 .init = squashfs_lzo_init,
354 .compress = lzo_compress,
355 .uncompress = lzo_uncompress,
356 .options = lzo_options,
357 .options_post = lzo_options_post,
358 .dump_options = lzo_dump_options,
359 .extract_options = lzo_extract_options,
360 .display_options = lzo_display_options,
361 .usage = lzo_usage,
362 .id = LZO_COMPRESSION,
363 .name = "lzo",
364 .supported = 1
365 };