blob: fce5ab9e152f13c5f4026603bbf46bb328e3ffdd
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * Common code for gunzip-like applets |
4 | * |
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
6 | */ |
7 | #include "libbb.h" |
8 | #include "bb_archive.h" |
9 | |
10 | /* lzop_main() uses bbunpack(), need this: */ |
11 | //kbuild:lib-$(CONFIG_LZOP) += bbunzip.o |
12 | |
13 | /* Note: must be kept in sync with archival/lzop.c */ |
14 | enum { |
15 | OPT_STDOUT = 1 << 0, |
16 | OPT_FORCE = 1 << 1, |
17 | /* only some decompressors: */ |
18 | OPT_VERBOSE = 1 << 2, |
19 | OPT_QUIET = 1 << 3, |
20 | OPT_DECOMPRESS = 1 << 4, |
21 | OPT_TEST = 1 << 5, |
22 | SEAMLESS_MAGIC = (1 << 31) * SEAMLESS_COMPRESSION, |
23 | }; |
24 | |
25 | static |
26 | int open_to_or_warn(int to_fd, const char *filename, int flags, int mode) |
27 | { |
28 | int fd = open3_or_warn(filename, flags, mode); |
29 | if (fd < 0) { |
30 | return 1; |
31 | } |
32 | xmove_fd(fd, to_fd); |
33 | return 0; |
34 | } |
35 | |
36 | char* FAST_FUNC append_ext(char *filename, const char *expected_ext) |
37 | { |
38 | return xasprintf("%s.%s", filename, expected_ext); |
39 | } |
40 | |
41 | int FAST_FUNC bbunpack(char **argv, |
42 | IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_aux_data_t *aux), |
43 | char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext), |
44 | const char *expected_ext |
45 | ) |
46 | { |
47 | struct stat stat_buf; |
48 | IF_DESKTOP(long long) int status = 0; |
49 | char *filename, *new_name; |
50 | smallint exitcode = 0; |
51 | transformer_aux_data_t aux; |
52 | |
53 | do { |
54 | /* NB: new_name is *maybe* malloc'ed! */ |
55 | new_name = NULL; |
56 | filename = *argv; /* can be NULL - 'streaming' bunzip2 */ |
57 | |
58 | if (filename && LONE_DASH(filename)) |
59 | filename = NULL; |
60 | |
61 | /* Open src */ |
62 | if (filename) { |
63 | if (!(option_mask32 & SEAMLESS_MAGIC)) { |
64 | if (stat(filename, &stat_buf) != 0) { |
65 | err_name: |
66 | bb_simple_perror_msg(filename); |
67 | err: |
68 | exitcode = 1; |
69 | goto free_name; |
70 | } |
71 | if (open_to_or_warn(STDIN_FILENO, filename, O_RDONLY, 0)) |
72 | goto err; |
73 | } else { |
74 | /* "clever zcat" with FILE */ |
75 | /* fail_if_not_compressed because zcat refuses uncompressed input */ |
76 | int fd = open_zipped(filename, /*fail_if_not_compressed:*/ 1); |
77 | if (fd < 0) |
78 | goto err_name; |
79 | xmove_fd(fd, STDIN_FILENO); |
80 | } |
81 | } else |
82 | if (option_mask32 & SEAMLESS_MAGIC) { |
83 | /* "clever zcat" on stdin */ |
84 | if (setup_unzip_on_fd(STDIN_FILENO, /*fail_if_not_compressed*/ 1)) |
85 | goto err; |
86 | } |
87 | |
88 | /* Special cases: test, stdout */ |
89 | if (option_mask32 & (OPT_STDOUT|OPT_TEST)) { |
90 | if (option_mask32 & OPT_TEST) |
91 | if (open_to_or_warn(STDOUT_FILENO, bb_dev_null, O_WRONLY, 0)) |
92 | xfunc_die(); |
93 | filename = NULL; |
94 | } |
95 | |
96 | /* Open dst if we are going to unpack to file */ |
97 | if (filename) { |
98 | new_name = make_new_name(filename, expected_ext); |
99 | if (!new_name) { |
100 | bb_error_msg("%s: unknown suffix - ignored", filename); |
101 | goto err; |
102 | } |
103 | |
104 | /* -f: overwrite existing output files */ |
105 | if (option_mask32 & OPT_FORCE) { |
106 | unlink(new_name); |
107 | } |
108 | |
109 | /* O_EXCL: "real" bunzip2 doesn't overwrite files */ |
110 | /* GNU gunzip does not bail out, but goes to next file */ |
111 | if (open_to_or_warn(STDOUT_FILENO, new_name, O_WRONLY | O_CREAT | O_EXCL, |
112 | stat_buf.st_mode)) |
113 | goto err; |
114 | } |
115 | |
116 | /* Check that the input is sane */ |
117 | if (!(option_mask32 & OPT_FORCE) && isatty(STDIN_FILENO)) { |
118 | bb_error_msg_and_die("compressed data not read from terminal, " |
119 | "use -f to force it"); |
120 | } |
121 | |
122 | if (!(option_mask32 & SEAMLESS_MAGIC)) { |
123 | init_transformer_aux_data(&aux); |
124 | aux.check_signature = 1; |
125 | status = unpacker(&aux); |
126 | if (status < 0) |
127 | exitcode = 1; |
128 | } else { |
129 | if (bb_copyfd_eof(STDIN_FILENO, STDOUT_FILENO) < 0) |
130 | /* Disk full, tty closed, etc. No point in continuing */ |
131 | xfunc_die(); |
132 | } |
133 | |
134 | if (!(option_mask32 & OPT_STDOUT)) |
135 | xclose(STDOUT_FILENO); /* with error check! */ |
136 | |
137 | if (filename) { |
138 | char *del = new_name; |
139 | |
140 | if (status >= 0) { |
141 | unsigned new_name_len; |
142 | |
143 | /* TODO: restore other things? */ |
144 | if (aux.mtime != 0) { |
145 | struct timeval times[2]; |
146 | |
147 | times[1].tv_sec = times[0].tv_sec = aux.mtime; |
148 | times[1].tv_usec = times[0].tv_usec = 0; |
149 | /* Note: we closed it first. |
150 | * On some systems calling utimes |
151 | * then closing resets the mtime |
152 | * back to current time. */ |
153 | utimes(new_name, times); /* ignoring errors */ |
154 | } |
155 | |
156 | if (ENABLE_DESKTOP) |
157 | new_name_len = strlen(new_name); |
158 | /* Restore source filename (unless tgz -> tar case) */ |
159 | if (new_name == filename) { |
160 | new_name_len = strlen(filename); |
161 | filename[new_name_len] = '.'; |
162 | } |
163 | /* Extreme bloat for gunzip compat */ |
164 | /* Some users do want this info... */ |
165 | if (ENABLE_DESKTOP && (option_mask32 & OPT_VERBOSE)) { |
166 | unsigned percent = status |
167 | ? ((uoff_t)stat_buf.st_size * 100u / (unsigned long long)status) |
168 | : 0; |
169 | fprintf(stderr, "%s: %u%% - replaced with %.*s\n", |
170 | filename, |
171 | 100u - percent, |
172 | new_name_len, new_name |
173 | ); |
174 | } |
175 | /* Delete _source_ file */ |
176 | del = filename; |
177 | } |
178 | xunlink(del); |
179 | free_name: |
180 | if (new_name != filename) |
181 | free(new_name); |
182 | } |
183 | } while (*argv && *++argv); |
184 | |
185 | if (option_mask32 & OPT_STDOUT) |
186 | xclose(STDOUT_FILENO); /* with error check! */ |
187 | |
188 | return exitcode; |
189 | } |
190 | |
191 | #if ENABLE_UNCOMPRESS || ENABLE_BUNZIP2 || ENABLE_UNLZMA || ENABLE_UNXZ |
192 | static |
193 | char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext) |
194 | { |
195 | char *extension = strrchr(filename, '.'); |
196 | if (!extension || strcmp(extension + 1, expected_ext) != 0) { |
197 | /* Mimic GNU gunzip - "real" bunzip2 tries to */ |
198 | /* unpack file anyway, to file.out */ |
199 | return NULL; |
200 | } |
201 | *extension = '\0'; |
202 | return filename; |
203 | } |
204 | #endif |
205 | |
206 | |
207 | /* |
208 | * Uncompress applet for busybox (c) 2002 Glenn McGrath |
209 | * |
210 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
211 | */ |
212 | //usage:#define uncompress_trivial_usage |
213 | //usage: "[-cf] [FILE]..." |
214 | //usage:#define uncompress_full_usage "\n\n" |
215 | //usage: "Decompress .Z file[s]\n" |
216 | //usage: "\n -c Write to stdout" |
217 | //usage: "\n -f Overwrite" |
218 | |
219 | //config:config UNCOMPRESS |
220 | //config: bool "uncompress" |
221 | //config: default n |
222 | //config: help |
223 | //config: uncompress is used to decompress archives created by compress. |
224 | //config: Not much used anymore, replaced by gzip/gunzip. |
225 | |
226 | //applet:IF_UNCOMPRESS(APPLET(uncompress, BB_DIR_BIN, BB_SUID_DROP)) |
227 | //kbuild:lib-$(CONFIG_UNCOMPRESS) += bbunzip.o |
228 | #if ENABLE_UNCOMPRESS |
229 | static |
230 | IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(transformer_aux_data_t *aux) |
231 | { |
232 | return unpack_Z_stream(aux, STDIN_FILENO, STDOUT_FILENO); |
233 | } |
234 | int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
235 | int uncompress_main(int argc UNUSED_PARAM, char **argv) |
236 | { |
237 | getopt32(argv, "cf"); |
238 | argv += optind; |
239 | |
240 | return bbunpack(argv, unpack_uncompress, make_new_name_generic, "Z"); |
241 | } |
242 | #endif |
243 | |
244 | |
245 | /* |
246 | * Gzip implementation for busybox |
247 | * |
248 | * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly. |
249 | * |
250 | * Originally adjusted for busybox by Sven Rudolph <sr1@inf.tu-dresden.de> |
251 | * based on gzip sources |
252 | * |
253 | * Adjusted further by Erik Andersen <andersen@codepoet.org> to support files as |
254 | * well as stdin/stdout, and to generally behave itself wrt command line |
255 | * handling. |
256 | * |
257 | * General cleanup to better adhere to the style guide and make use of standard |
258 | * busybox functions by Glenn McGrath |
259 | * |
260 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
261 | * |
262 | * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface |
263 | * Copyright (C) 1992-1993 Jean-loup Gailly |
264 | * The unzip code was written and put in the public domain by Mark Adler. |
265 | * Portions of the lzw code are derived from the public domain 'compress' |
266 | * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies, |
267 | * Ken Turkowski, Dave Mack and Peter Jannesen. |
268 | */ |
269 | //usage:#define gunzip_trivial_usage |
270 | //usage: "[-cft] [FILE]..." |
271 | //usage:#define gunzip_full_usage "\n\n" |
272 | //usage: "Decompress FILEs (or stdin)\n" |
273 | //usage: "\n -c Write to stdout" |
274 | //usage: "\n -f Force" |
275 | //usage: "\n -t Test file integrity" |
276 | //usage: |
277 | //usage:#define gunzip_example_usage |
278 | //usage: "$ ls -la /tmp/BusyBox*\n" |
279 | //usage: "-rw-rw-r-- 1 andersen andersen 557009 Apr 11 10:55 /tmp/BusyBox-0.43.tar.gz\n" |
280 | //usage: "$ gunzip /tmp/BusyBox-0.43.tar.gz\n" |
281 | //usage: "$ ls -la /tmp/BusyBox*\n" |
282 | //usage: "-rw-rw-r-- 1 andersen andersen 1761280 Apr 14 17:47 /tmp/BusyBox-0.43.tar\n" |
283 | //usage: |
284 | //usage:#define zcat_trivial_usage |
285 | //usage: "[FILE]..." |
286 | //usage:#define zcat_full_usage "\n\n" |
287 | //usage: "Decompress to stdout" |
288 | |
289 | //config:config GUNZIP |
290 | //config: bool "gunzip" |
291 | //config: default y |
292 | //config: help |
293 | //config: gunzip is used to decompress archives created by gzip. |
294 | //config: You can use the `-t' option to test the integrity of |
295 | //config: an archive, without decompressing it. |
296 | |
297 | //applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP)) |
298 | //applet:IF_GUNZIP(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat)) |
299 | //kbuild:lib-$(CONFIG_GZIP) += bbunzip.o |
300 | //kbuild:lib-$(CONFIG_GUNZIP) += bbunzip.o |
301 | #if ENABLE_GUNZIP |
302 | static |
303 | char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UNUSED_PARAM) |
304 | { |
305 | char *extension = strrchr(filename, '.'); |
306 | |
307 | if (!extension) |
308 | return NULL; |
309 | |
310 | extension++; |
311 | if (strcmp(extension, "tgz" + 1) == 0 |
312 | #if ENABLE_FEATURE_SEAMLESS_Z |
313 | || (extension[0] == 'Z' && extension[1] == '\0') |
314 | #endif |
315 | ) { |
316 | extension[-1] = '\0'; |
317 | } else if (strcmp(extension, "tgz") == 0) { |
318 | filename = xstrdup(filename); |
319 | extension = strrchr(filename, '.'); |
320 | extension[2] = 'a'; |
321 | extension[3] = 'r'; |
322 | } else { |
323 | return NULL; |
324 | } |
325 | return filename; |
326 | } |
327 | static |
328 | IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(transformer_aux_data_t *aux) |
329 | { |
330 | return unpack_gz_stream(aux, STDIN_FILENO, STDOUT_FILENO); |
331 | } |
332 | /* |
333 | * Linux kernel build uses gzip -d -n. We accept and ignore it. |
334 | * Man page says: |
335 | * -n --no-name |
336 | * gzip: do not save the original file name and time stamp. |
337 | * (The original name is always saved if the name had to be truncated.) |
338 | * gunzip: do not restore the original file name/time even if present |
339 | * (remove only the gzip suffix from the compressed file name). |
340 | * This option is the default when decompressing. |
341 | * -N --name |
342 | * gzip: always save the original file name and time stamp (this is the default) |
343 | * gunzip: restore the original file name and time stamp if present. |
344 | */ |
345 | int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
346 | int gunzip_main(int argc UNUSED_PARAM, char **argv) |
347 | { |
348 | getopt32(argv, "cfvqdtn"); |
349 | argv += optind; |
350 | |
351 | /* If called as zcat... |
352 | * Normally, "zcat" is just "gunzip -c". |
353 | * But if seamless magic is enabled, then we are much more clever. |
354 | */ |
355 | if (applet_name[1] == 'c') |
356 | option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC; |
357 | |
358 | return bbunpack(argv, unpack_gunzip, make_new_name_gunzip, /*unused:*/ NULL); |
359 | } |
360 | #endif |
361 | |
362 | |
363 | /* |
364 | * Modified for busybox by Glenn McGrath |
365 | * Added support output to stdout by Thomas Lundquist <thomasez@zelow.no> |
366 | * |
367 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
368 | */ |
369 | //usage:#define bunzip2_trivial_usage |
370 | //usage: "[-cf] [FILE]..." |
371 | //usage:#define bunzip2_full_usage "\n\n" |
372 | //usage: "Decompress FILEs (or stdin)\n" |
373 | //usage: "\n -c Write to stdout" |
374 | //usage: "\n -f Force" |
375 | //usage:#define bzcat_trivial_usage |
376 | //usage: "[FILE]..." |
377 | //usage:#define bzcat_full_usage "\n\n" |
378 | //usage: "Decompress to stdout" |
379 | |
380 | //config:config BUNZIP2 |
381 | //config: bool "bunzip2" |
382 | //config: default y |
383 | //config: help |
384 | //config: bunzip2 is a compression utility using the Burrows-Wheeler block |
385 | //config: sorting text compression algorithm, and Huffman coding. Compression |
386 | //config: is generally considerably better than that achieved by more |
387 | //config: conventional LZ77/LZ78-based compressors, and approaches the |
388 | //config: performance of the PPM family of statistical compressors. |
389 | //config: |
390 | //config: Unless you have a specific application which requires bunzip2, you |
391 | //config: should probably say N here. |
392 | |
393 | //applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) |
394 | //applet:IF_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP, bzcat)) |
395 | //kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o |
396 | //kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o |
397 | #if ENABLE_BUNZIP2 |
398 | static |
399 | IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(transformer_aux_data_t *aux) |
400 | { |
401 | return unpack_bz2_stream(aux, STDIN_FILENO, STDOUT_FILENO); |
402 | } |
403 | int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
404 | int bunzip2_main(int argc UNUSED_PARAM, char **argv) |
405 | { |
406 | getopt32(argv, "cfvqdt"); |
407 | argv += optind; |
408 | if (applet_name[2] == 'c') /* bzcat */ |
409 | option_mask32 |= OPT_STDOUT; |
410 | |
411 | return bbunpack(argv, unpack_bunzip2, make_new_name_generic, "bz2"); |
412 | } |
413 | #endif |
414 | |
415 | |
416 | /* |
417 | * Small lzma deflate implementation. |
418 | * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org> |
419 | * |
420 | * Based on bunzip.c from busybox |
421 | * |
422 | * Licensed under GPLv2, see file LICENSE in this source tree. |
423 | */ |
424 | //usage:#define unlzma_trivial_usage |
425 | //usage: "[-cf] [FILE]..." |
426 | //usage:#define unlzma_full_usage "\n\n" |
427 | //usage: "Decompress FILE (or stdin)\n" |
428 | //usage: "\n -c Write to stdout" |
429 | //usage: "\n -f Force" |
430 | //usage: |
431 | //usage:#define lzma_trivial_usage |
432 | //usage: "-d [-cf] [FILE]..." |
433 | //usage:#define lzma_full_usage "\n\n" |
434 | //usage: "Decompress FILE (or stdin)\n" |
435 | //usage: "\n -d Decompress" |
436 | //usage: "\n -c Write to stdout" |
437 | //usage: "\n -f Force" |
438 | //usage: |
439 | //usage:#define lzcat_trivial_usage |
440 | //usage: "[FILE]..." |
441 | //usage:#define lzcat_full_usage "\n\n" |
442 | //usage: "Decompress to stdout" |
443 | //usage: |
444 | //usage:#define unxz_trivial_usage |
445 | //usage: "[-cf] [FILE]..." |
446 | //usage:#define unxz_full_usage "\n\n" |
447 | //usage: "Decompress FILE (or stdin)\n" |
448 | //usage: "\n -c Write to stdout" |
449 | //usage: "\n -f Force" |
450 | //usage: |
451 | //usage:#define xz_trivial_usage |
452 | //usage: "-d [-cf] [FILE]..." |
453 | //usage:#define xz_full_usage "\n\n" |
454 | //usage: "Decompress FILE (or stdin)\n" |
455 | //usage: "\n -d Decompress" |
456 | //usage: "\n -c Write to stdout" |
457 | //usage: "\n -f Force" |
458 | //usage: |
459 | //usage:#define xzcat_trivial_usage |
460 | //usage: "[FILE]..." |
461 | //usage:#define xzcat_full_usage "\n\n" |
462 | //usage: "Decompress to stdout" |
463 | |
464 | //config:config UNLZMA |
465 | //config: bool "unlzma" |
466 | //config: default y |
467 | //config: help |
468 | //config: unlzma is a compression utility using the Lempel-Ziv-Markov chain |
469 | //config: compression algorithm, and range coding. Compression |
470 | //config: is generally considerably better than that achieved by the bzip2 |
471 | //config: compressors. |
472 | //config: |
473 | //config: The BusyBox unlzma applet is limited to decompression only. |
474 | //config: On an x86 system, this applet adds about 4K. |
475 | //config: |
476 | //config:config FEATURE_LZMA_FAST |
477 | //config: bool "Optimize unlzma for speed" |
478 | //config: default n |
479 | //config: depends on UNLZMA |
480 | //config: help |
481 | //config: This option reduces decompression time by about 25% at the cost of |
482 | //config: a 1K bigger binary. |
483 | //config: |
484 | //config:config LZMA |
485 | //config: bool "Provide lzma alias which supports only unpacking" |
486 | //config: default y |
487 | //config: depends on UNLZMA |
488 | //config: help |
489 | //config: Enable this option if you want commands like "lzma -d" to work. |
490 | //config: IOW: you'll get lzma applet, but it will always require -d option. |
491 | |
492 | //applet:IF_UNLZMA(APPLET(unlzma, BB_DIR_USR_BIN, BB_SUID_DROP)) |
493 | //applet:IF_UNLZMA(APPLET_ODDNAME(lzcat, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzcat)) |
494 | //applet:IF_LZMA(APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma)) |
495 | //kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o |
496 | #if ENABLE_UNLZMA |
497 | static |
498 | IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(transformer_aux_data_t *aux) |
499 | { |
500 | return unpack_lzma_stream(aux, STDIN_FILENO, STDOUT_FILENO); |
501 | } |
502 | int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
503 | int unlzma_main(int argc UNUSED_PARAM, char **argv) |
504 | { |
505 | IF_LZMA(int opts =) getopt32(argv, "cfvqdt"); |
506 | # if ENABLE_LZMA |
507 | /* lzma without -d or -t? */ |
508 | if (applet_name[2] == 'm' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) |
509 | bb_show_usage(); |
510 | # endif |
511 | /* lzcat? */ |
512 | if (applet_name[2] == 'c') |
513 | option_mask32 |= OPT_STDOUT; |
514 | |
515 | argv += optind; |
516 | return bbunpack(argv, unpack_unlzma, make_new_name_generic, "lzma"); |
517 | } |
518 | #endif |
519 | |
520 | |
521 | //config:config UNXZ |
522 | //config: bool "unxz" |
523 | //config: default y |
524 | //config: help |
525 | //config: unxz is a unlzma successor. |
526 | //config: |
527 | //config:config XZ |
528 | //config: bool "Provide xz alias which supports only unpacking" |
529 | //config: default y |
530 | //config: depends on UNXZ |
531 | //config: help |
532 | //config: Enable this option if you want commands like "xz -d" to work. |
533 | //config: IOW: you'll get xz applet, but it will always require -d option. |
534 | |
535 | //applet:IF_UNXZ(APPLET(unxz, BB_DIR_USR_BIN, BB_SUID_DROP)) |
536 | //applet:IF_UNXZ(APPLET_ODDNAME(xzcat, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xzcat)) |
537 | //applet:IF_XZ(APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz)) |
538 | //kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o |
539 | #if ENABLE_UNXZ |
540 | static |
541 | IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(transformer_aux_data_t *aux) |
542 | { |
543 | return unpack_xz_stream(aux, STDIN_FILENO, STDOUT_FILENO); |
544 | } |
545 | int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
546 | int unxz_main(int argc UNUSED_PARAM, char **argv) |
547 | { |
548 | IF_XZ(int opts =) getopt32(argv, "cfvqdt"); |
549 | # if ENABLE_XZ |
550 | /* xz without -d or -t? */ |
551 | if (applet_name[2] == '\0' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) |
552 | bb_show_usage(); |
553 | # endif |
554 | /* xzcat? */ |
555 | if (applet_name[2] == 'c') |
556 | option_mask32 |= OPT_STDOUT; |
557 | |
558 | argv += optind; |
559 | return bbunpack(argv, unpack_unxz, make_new_name_generic, "xz"); |
560 | } |
561 | #endif |
562 |