4 |
* |
* |
5 |
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
6 |
*/ |
*/ |
|
|
|
7 |
#include "libbb.h" |
#include "libbb.h" |
8 |
#include "unarchive.h" |
#include "unarchive.h" |
9 |
|
|
10 |
enum { |
enum { |
11 |
OPT_STDOUT = 0x1, |
OPT_STDOUT = 1 << 0, |
12 |
OPT_FORCE = 0x2, |
OPT_FORCE = 1 << 1, |
13 |
/* gunzip and bunzip2 only: */ |
/* only some decompressors: */ |
14 |
OPT_VERBOSE = 0x4, |
OPT_VERBOSE = 1 << 2, |
15 |
OPT_DECOMPRESS = 0x8, |
OPT_DECOMPRESS = 1 << 3, |
16 |
OPT_TEST = 0x10, |
OPT_TEST = 1 << 4, |
17 |
}; |
}; |
18 |
|
|
19 |
static |
static |
27 |
return 0; |
return 0; |
28 |
} |
} |
29 |
|
|
30 |
|
char* FAST_FUNC append_ext(char *filename, const char *expected_ext) |
31 |
|
{ |
32 |
|
return xasprintf("%s.%s", filename, expected_ext); |
33 |
|
} |
34 |
|
|
35 |
int FAST_FUNC bbunpack(char **argv, |
int FAST_FUNC bbunpack(char **argv, |
36 |
char* (*make_new_name)(char *filename), |
IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(unpack_info_t *info), |
37 |
IF_DESKTOP(long long) int (*unpacker)(unpack_info_t *info) |
char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext), |
38 |
|
const char *expected_ext |
39 |
) |
) |
40 |
{ |
{ |
41 |
struct stat stat_buf; |
struct stat stat_buf; |
74 |
|
|
75 |
/* Open dst if we are going to unpack to file */ |
/* Open dst if we are going to unpack to file */ |
76 |
if (filename) { |
if (filename) { |
77 |
new_name = make_new_name(filename); |
new_name = make_new_name(filename, expected_ext); |
78 |
if (!new_name) { |
if (!new_name) { |
79 |
bb_error_msg("%s: unknown suffix - ignored", filename); |
bb_error_msg("%s: unknown suffix - ignored", filename); |
80 |
goto err; |
goto err; |
146 |
return exitcode; |
return exitcode; |
147 |
} |
} |
148 |
|
|
149 |
#if ENABLE_BUNZIP2 || ENABLE_UNLZMA || ENABLE_UNCOMPRESS |
#if ENABLE_UNCOMPRESS || ENABLE_BUNZIP2 || ENABLE_UNLZMA || ENABLE_UNXZ |
|
|
|
150 |
static |
static |
151 |
char* make_new_name_generic(char *filename, const char *expected_ext) |
char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext) |
152 |
{ |
{ |
153 |
char *extension = strrchr(filename, '.'); |
char *extension = strrchr(filename, '.'); |
154 |
if (!extension || strcmp(extension + 1, expected_ext) != 0) { |
if (!extension || strcmp(extension + 1, expected_ext) != 0) { |
159 |
*extension = '\0'; |
*extension = '\0'; |
160 |
return filename; |
return filename; |
161 |
} |
} |
|
|
|
162 |
#endif |
#endif |
163 |
|
|
164 |
|
|
165 |
/* |
/* |
166 |
* Modified for busybox by Glenn McGrath |
* Uncompress applet for busybox (c) 2002 Glenn McGrath |
|
* Added support output to stdout by Thomas Lundquist <thomasez@zelow.no> |
|
167 |
* |
* |
168 |
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
169 |
*/ |
*/ |
170 |
|
#if ENABLE_UNCOMPRESS |
|
#if ENABLE_BUNZIP2 |
|
|
|
|
171 |
static |
static |
172 |
char* make_new_name_bunzip2(char *filename) |
IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(unpack_info_t *info UNUSED_PARAM) |
173 |
{ |
{ |
174 |
return make_new_name_generic(filename, "bz2"); |
IF_DESKTOP(long long) int status = -1; |
|
} |
|
175 |
|
|
176 |
static |
if ((xread_char(STDIN_FILENO) != 0x1f) || (xread_char(STDIN_FILENO) != 0x9d)) { |
177 |
IF_DESKTOP(long long) int unpack_bunzip2(unpack_info_t *info UNUSED_PARAM) |
bb_error_msg("invalid magic"); |
178 |
{ |
} else { |
179 |
return unpack_bz2_stream_prime(STDIN_FILENO, STDOUT_FILENO); |
status = unpack_Z_stream(STDIN_FILENO, STDOUT_FILENO); |
180 |
|
} |
181 |
|
return status; |
182 |
} |
} |
183 |
|
int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
184 |
int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int uncompress_main(int argc UNUSED_PARAM, char **argv) |
|
int bunzip2_main(int argc UNUSED_PARAM, char **argv) |
|
185 |
{ |
{ |
186 |
getopt32(argv, "cfvdt"); |
getopt32(argv, "cf"); |
187 |
argv += optind; |
argv += optind; |
|
if (applet_name[2] == 'c') |
|
|
option_mask32 |= OPT_STDOUT; |
|
188 |
|
|
189 |
return bbunpack(argv, make_new_name_bunzip2, unpack_bunzip2); |
return bbunpack(argv, unpack_uncompress, make_new_name_generic, "Z"); |
190 |
} |
} |
|
|
|
191 |
#endif |
#endif |
192 |
|
|
193 |
|
|
218 |
* See the license_msg below and the file COPYING for the software license. |
* See the license_msg below and the file COPYING for the software license. |
219 |
* See the file algorithm.doc for the compression algorithms and file formats. |
* See the file algorithm.doc for the compression algorithms and file formats. |
220 |
*/ |
*/ |
|
|
|
221 |
#if ENABLE_GUNZIP |
#if ENABLE_GUNZIP |
|
|
|
222 |
static |
static |
223 |
char* make_new_name_gunzip(char *filename) |
char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UNUSED_PARAM) |
224 |
{ |
{ |
225 |
char *extension = strrchr(filename, '.'); |
char *extension = strrchr(filename, '.'); |
226 |
|
|
244 |
} |
} |
245 |
return filename; |
return filename; |
246 |
} |
} |
|
|
|
247 |
static |
static |
248 |
IF_DESKTOP(long long) int unpack_gunzip(unpack_info_t *info) |
IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(unpack_info_t *info) |
249 |
{ |
{ |
250 |
IF_DESKTOP(long long) int status = -1; |
IF_DESKTOP(long long) int status = -1; |
251 |
|
|
271 |
} |
} |
272 |
return status; |
return status; |
273 |
} |
} |
|
|
|
274 |
/* |
/* |
275 |
* Linux kernel build uses gzip -d -n. We accept and ignore it. |
* Linux kernel build uses gzip -d -n. We accept and ignore it. |
276 |
* Man page says: |
* Man page says: |
284 |
* gzip: always save the original file name and time stamp (this is the default) |
* gzip: always save the original file name and time stamp (this is the default) |
285 |
* gunzip: restore the original file name and time stamp if present. |
* gunzip: restore the original file name and time stamp if present. |
286 |
*/ |
*/ |
|
|
|
287 |
int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
288 |
int gunzip_main(int argc UNUSED_PARAM, char **argv) |
int gunzip_main(int argc UNUSED_PARAM, char **argv) |
289 |
{ |
{ |
293 |
if (applet_name[1] == 'c') |
if (applet_name[1] == 'c') |
294 |
option_mask32 |= OPT_STDOUT; |
option_mask32 |= OPT_STDOUT; |
295 |
|
|
296 |
return bbunpack(argv, make_new_name_gunzip, unpack_gunzip); |
return bbunpack(argv, unpack_gunzip, make_new_name_gunzip, /*unused:*/ NULL); |
297 |
} |
} |
298 |
|
#endif |
299 |
|
|
300 |
|
|
301 |
|
/* |
302 |
|
* Modified for busybox by Glenn McGrath |
303 |
|
* Added support output to stdout by Thomas Lundquist <thomasez@zelow.no> |
304 |
|
* |
305 |
|
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
306 |
|
*/ |
307 |
|
//usage:#define bunzip2_trivial_usage |
308 |
|
//usage: "[OPTIONS] [FILE]..." |
309 |
|
//usage:#define bunzip2_full_usage "\n\n" |
310 |
|
//usage: "Decompress FILEs (or stdin)\n" |
311 |
|
//usage: "\nOptions:" |
312 |
|
//usage: "\n -c Write to stdout" |
313 |
|
//usage: "\n -f Force" |
314 |
|
//usage:#define bzcat_trivial_usage |
315 |
|
//usage: "FILE" |
316 |
|
//usage:#define bzcat_full_usage "\n\n" |
317 |
|
//usage: "Decompress to stdout" |
318 |
|
//applet:IF_BUNZIP2(APPLET(bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP)) |
319 |
|
//applet:IF_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP, bzcat)) |
320 |
|
#if ENABLE_BUNZIP2 |
321 |
|
static |
322 |
|
IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(unpack_info_t *info UNUSED_PARAM) |
323 |
|
{ |
324 |
|
return unpack_bz2_stream_prime(STDIN_FILENO, STDOUT_FILENO); |
325 |
|
} |
326 |
|
int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
327 |
|
int bunzip2_main(int argc UNUSED_PARAM, char **argv) |
328 |
|
{ |
329 |
|
getopt32(argv, "cfvdt"); |
330 |
|
argv += optind; |
331 |
|
if (applet_name[2] == 'c') /* bzcat */ |
332 |
|
option_mask32 |= OPT_STDOUT; |
333 |
|
|
334 |
|
return bbunpack(argv, unpack_bunzip2, make_new_name_generic, "bz2"); |
335 |
|
} |
336 |
#endif |
#endif |
337 |
|
|
338 |
|
|
344 |
* |
* |
345 |
* Licensed under GPL v2, see file LICENSE in this tarball for details. |
* Licensed under GPL v2, see file LICENSE in this tarball for details. |
346 |
*/ |
*/ |
|
|
|
347 |
#if ENABLE_UNLZMA |
#if ENABLE_UNLZMA |
|
|
|
|
static |
|
|
char* make_new_name_unlzma(char *filename) |
|
|
{ |
|
|
return make_new_name_generic(filename, "lzma"); |
|
|
} |
|
|
|
|
348 |
static |
static |
349 |
IF_DESKTOP(long long) int unpack_unlzma(unpack_info_t *info UNUSED_PARAM) |
IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(unpack_info_t *info UNUSED_PARAM) |
350 |
{ |
{ |
351 |
return unpack_lzma_stream(STDIN_FILENO, STDOUT_FILENO); |
return unpack_lzma_stream(STDIN_FILENO, STDOUT_FILENO); |
352 |
} |
} |
|
|
|
353 |
int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
354 |
int unlzma_main(int argc UNUSED_PARAM, char **argv) |
int unlzma_main(int argc UNUSED_PARAM, char **argv) |
355 |
{ |
{ |
356 |
getopt32(argv, "cf"); |
IF_LZMA(int opts =) getopt32(argv, "cfvdt"); |
357 |
argv += optind; |
# if ENABLE_LZMA |
358 |
/* lzmacat? */ |
/* lzma without -d or -t? */ |
359 |
if (applet_name[4] == 'c') |
if (applet_name[2] == 'm' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) |
360 |
|
bb_show_usage(); |
361 |
|
# endif |
362 |
|
/* lzcat? */ |
363 |
|
if (applet_name[2] == 'c') |
364 |
option_mask32 |= OPT_STDOUT; |
option_mask32 |= OPT_STDOUT; |
365 |
|
|
366 |
return bbunpack(argv, make_new_name_unlzma, unpack_unlzma); |
argv += optind; |
367 |
|
return bbunpack(argv, unpack_unlzma, make_new_name_generic, "lzma"); |
368 |
} |
} |
|
|
|
369 |
#endif |
#endif |
370 |
|
|
371 |
|
|
372 |
/* |
#if ENABLE_UNXZ |
|
* Uncompress applet for busybox (c) 2002 Glenn McGrath |
|
|
* |
|
|
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
|
|
*/ |
|
|
|
|
|
#if ENABLE_UNCOMPRESS |
|
|
|
|
|
static |
|
|
char* make_new_name_uncompress(char *filename) |
|
|
{ |
|
|
return make_new_name_generic(filename, "Z"); |
|
|
} |
|
|
|
|
373 |
static |
static |
374 |
IF_DESKTOP(long long) int unpack_uncompress(unpack_info_t *info UNUSED_PARAM) |
IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(unpack_info_t *info UNUSED_PARAM) |
375 |
{ |
{ |
376 |
IF_DESKTOP(long long) int status = -1; |
struct { |
377 |
|
uint32_t v1; |
378 |
if ((xread_char(STDIN_FILENO) != 0x1f) || (xread_char(STDIN_FILENO) != 0x9d)) { |
uint16_t v2; |
379 |
|
} magic; |
380 |
|
xread(STDIN_FILENO, &magic, 6); |
381 |
|
if (magic.v1 != XZ_MAGIC1a || magic.v2 != XZ_MAGIC2a) { |
382 |
bb_error_msg("invalid magic"); |
bb_error_msg("invalid magic"); |
383 |
} else { |
return -1; |
|
status = unpack_Z_stream(STDIN_FILENO, STDOUT_FILENO); |
|
384 |
} |
} |
385 |
return status; |
return unpack_xz_stream(STDIN_FILENO, STDOUT_FILENO); |
386 |
} |
} |
387 |
|
int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
388 |
int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
int unxz_main(int argc UNUSED_PARAM, char **argv) |
|
int uncompress_main(int argc UNUSED_PARAM, char **argv) |
|
389 |
{ |
{ |
390 |
getopt32(argv, "cf"); |
IF_XZ(int opts =) getopt32(argv, "cfvdt"); |
391 |
argv += optind; |
# if ENABLE_XZ |
392 |
|
/* xz without -d or -t? */ |
393 |
|
if (applet_name[2] == '\0' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) |
394 |
|
bb_show_usage(); |
395 |
|
# endif |
396 |
|
/* xzcat? */ |
397 |
|
if (applet_name[2] == 'c') |
398 |
|
option_mask32 |= OPT_STDOUT; |
399 |
|
|
400 |
return bbunpack(argv, make_new_name_uncompress, unpack_uncompress); |
argv += optind; |
401 |
|
return bbunpack(argv, unpack_unxz, make_new_name_generic, "xz"); |
402 |
} |
} |
|
|
|
403 |
#endif |
#endif |