blob: 944b397b3abe4a850b6fadf42f7f2ecb799062ee [file] [log] [blame]
Denis Vlasenkoab9eef22007-03-07 22:02:23 +00001/* vi: set sw=4 ts=4: */
2/*
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02003 * Common code for gunzip-like applets
Denis Vlasenkoab9eef22007-03-07 22:02:23 +00004 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02005 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Denis Vlasenkoab9eef22007-03-07 22:02:23 +00006 */
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +02007//kbuild:lib-$(CONFIG_ZCAT) += bbunzip.o
8//kbuild:lib-$(CONFIG_GUNZIP) += bbunzip.o
9//kbuild:lib-$(CONFIG_BZCAT) += bbunzip.o
10//kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o
11
Denys Vlasenko66620fa2013-11-14 09:53:52 +010012/* lzop_main() uses bbunpack(), need this: */
13//kbuild:lib-$(CONFIG_LZOP) += bbunzip.o
Denys Vlasenko9cc3d3a2016-12-23 02:42:26 +010014//kbuild:lib-$(CONFIG_LZOPCAT) += bbunzip.o
15//kbuild:lib-$(CONFIG_UNLZOP) += bbunzip.o
Denys Vlasenko548620c2016-12-08 12:24:48 +010016/* bzip2_main() too: */
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +020017//kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o
Denys Vlasenko9cc3d3a2016-12-23 02:42:26 +010018/* gzip_main() too: */
Denys Vlasenkod4e4fdb2017-07-03 21:31:16 +020019//kbuild:lib-$(CONFIG_GZIP) += bbunzip.o
Denys Vlasenko66620fa2013-11-14 09:53:52 +010020
Denys Vlasenko0c4dbd42017-09-18 16:28:43 +020021#include "libbb.h"
22#include "bb_archive.h"
23
Mike Frysinger93b51812013-03-03 00:48:53 -050024/* Note: must be kept in sync with archival/lzop.c */
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000025enum {
Denys Vlasenkoccb88a62010-05-27 02:22:54 +020026 OPT_STDOUT = 1 << 0,
27 OPT_FORCE = 1 << 1,
28 /* only some decompressors: */
Denys Vlasenko1c013fa2017-06-15 18:07:04 +020029 OPT_KEEP = 1 << 2,
30 OPT_VERBOSE = 1 << 3,
31 OPT_QUIET = 1 << 4,
32 OPT_DECOMPRESS = 1 << 5,
33 OPT_TEST = 1 << 6,
Kang-Che Sungd5e7ff02017-01-08 14:31:06 +010034 SEAMLESS_MAGIC = (1 << 31) * ENABLE_ZCAT * SEAMLESS_COMPRESSION,
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000035};
36
37static
38int open_to_or_warn(int to_fd, const char *filename, int flags, int mode)
39{
Denis Vlasenko50f7f442007-04-11 23:20:53 +000040 int fd = open3_or_warn(filename, flags, mode);
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000041 if (fd < 0) {
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000042 return 1;
43 }
Denis Vlasenko50f7f442007-04-11 23:20:53 +000044 xmove_fd(fd, to_fd);
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000045 return 0;
46}
47
Denys Vlasenko39a04f72010-05-31 14:18:57 +020048char* FAST_FUNC append_ext(char *filename, const char *expected_ext)
49{
50 return xasprintf("%s.%s", filename, expected_ext);
51}
52
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +000053int FAST_FUNC bbunpack(char **argv,
Denys Vlasenkoe7800f32014-12-07 00:42:49 +010054 IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_state_t *xstate),
Denys Vlasenko39a04f72010-05-31 14:18:57 +020055 char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext),
56 const char *expected_ext
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000057)
58{
59 struct stat stat_buf;
Denys Vlasenko8e96efa2013-02-28 18:06:09 +010060 IF_DESKTOP(long long) int status = 0;
Denis Vlasenko6c939e02007-03-07 23:22:47 +000061 char *filename, *new_name;
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000062 smallint exitcode = 0;
Denys Vlasenkoe7800f32014-12-07 00:42:49 +010063 transformer_state_t xstate;
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000064
65 do {
Denis Vlasenko6c939e02007-03-07 23:22:47 +000066 /* NB: new_name is *maybe* malloc'ed! */
67 new_name = NULL;
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000068 filename = *argv; /* can be NULL - 'streaming' bunzip2 */
Denis Vlasenko6c939e02007-03-07 23:22:47 +000069
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000070 if (filename && LONE_DASH(filename))
71 filename = NULL;
72
73 /* Open src */
74 if (filename) {
Denys Vlasenko8e96efa2013-02-28 18:06:09 +010075 if (!(option_mask32 & SEAMLESS_MAGIC)) {
76 if (stat(filename, &stat_buf) != 0) {
77 err_name:
78 bb_simple_perror_msg(filename);
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000079 err:
Denys Vlasenko8e96efa2013-02-28 18:06:09 +010080 exitcode = 1;
81 goto free_name;
82 }
83 if (open_to_or_warn(STDIN_FILENO, filename, O_RDONLY, 0))
84 goto err;
85 } else {
Denys Vlasenko41655432013-02-28 18:37:04 +010086 /* "clever zcat" with FILE */
Denys Vlasenko640ce3d2014-02-02 02:06:38 +010087 /* fail_if_not_compressed because zcat refuses uncompressed input */
88 int fd = open_zipped(filename, /*fail_if_not_compressed:*/ 1);
Denys Vlasenko8e96efa2013-02-28 18:06:09 +010089 if (fd < 0)
90 goto err_name;
91 xmove_fd(fd, STDIN_FILENO);
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000092 }
Denys Vlasenko41655432013-02-28 18:37:04 +010093 } else
94 if (option_mask32 & SEAMLESS_MAGIC) {
95 /* "clever zcat" on stdin */
Denys Vlasenko640ce3d2014-02-02 02:06:38 +010096 if (setup_unzip_on_fd(STDIN_FILENO, /*fail_if_not_compressed*/ 1))
Denys Vlasenko41655432013-02-28 18:37:04 +010097 goto err;
Denis Vlasenkoab9eef22007-03-07 22:02:23 +000098 }
99
100 /* Special cases: test, stdout */
101 if (option_mask32 & (OPT_STDOUT|OPT_TEST)) {
102 if (option_mask32 & OPT_TEST)
103 if (open_to_or_warn(STDOUT_FILENO, bb_dev_null, O_WRONLY, 0))
Denys Vlasenkof2d84782013-02-28 18:04:22 +0100104 xfunc_die();
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000105 filename = NULL;
106 }
107
Denis Vlasenko6c939e02007-03-07 23:22:47 +0000108 /* Open dst if we are going to unpack to file */
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000109 if (filename) {
Denys Vlasenko39a04f72010-05-31 14:18:57 +0200110 new_name = make_new_name(filename, expected_ext);
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000111 if (!new_name) {
112 bb_error_msg("%s: unknown suffix - ignored", filename);
113 goto err;
114 }
Denis Vlasenkoa04cc472008-06-25 20:54:45 +0000115
116 /* -f: overwrite existing output files */
117 if (option_mask32 & OPT_FORCE) {
118 unlink(new_name);
119 }
120
Denis Vlasenko6c939e02007-03-07 23:22:47 +0000121 /* O_EXCL: "real" bunzip2 doesn't overwrite files */
Denis Vlasenko5dd8a032007-10-05 15:26:08 +0000122 /* GNU gunzip does not bail out, but goes to next file */
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000123 if (open_to_or_warn(STDOUT_FILENO, new_name, O_WRONLY | O_CREAT | O_EXCL,
124 stat_buf.st_mode))
125 goto err;
126 }
127
Denis Vlasenko6c939e02007-03-07 23:22:47 +0000128 /* Check that the input is sane */
Denys Vlasenkof2d84782013-02-28 18:04:22 +0100129 if (!(option_mask32 & OPT_FORCE) && isatty(STDIN_FILENO)) {
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000130 bb_error_msg_and_die("compressed data not read from terminal, "
131 "use -f to force it");
132 }
133
Denys Vlasenko8e96efa2013-02-28 18:06:09 +0100134 if (!(option_mask32 & SEAMLESS_MAGIC)) {
Denys Vlasenkoe7800f32014-12-07 00:42:49 +0100135 init_transformer_state(&xstate);
Denys Vlasenko2a0867a2017-01-09 10:58:37 +0100136 /*xstate.signature_skipped = 0; - already is */
Denys Vlasenkob4c11c12014-12-07 00:44:00 +0100137 /*xstate.src_fd = STDIN_FILENO; - already is */
138 xstate.dst_fd = STDOUT_FILENO;
Denys Vlasenkoe7800f32014-12-07 00:42:49 +0100139 status = unpacker(&xstate);
Denys Vlasenko8e96efa2013-02-28 18:06:09 +0100140 if (status < 0)
141 exitcode = 1;
142 } else {
Denys Vlasenko41655432013-02-28 18:37:04 +0100143 if (bb_copyfd_eof(STDIN_FILENO, STDOUT_FILENO) < 0)
Denys Vlasenko8e96efa2013-02-28 18:06:09 +0100144 /* Disk full, tty closed, etc. No point in continuing */
145 xfunc_die();
Denys Vlasenko8e96efa2013-02-28 18:06:09 +0100146 }
Denys Vlasenkoc531b9a2011-10-31 01:05:16 +0100147
148 if (!(option_mask32 & OPT_STDOUT))
149 xclose(STDOUT_FILENO); /* with error check! */
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000150
151 if (filename) {
152 char *del = new_name;
Denys Vlasenkod0bc7082013-07-30 05:41:11 +0200153
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000154 if (status >= 0) {
Denys Vlasenkod0bc7082013-07-30 05:41:11 +0200155 unsigned new_name_len;
156
Denis Vlasenko1a9e9bd2008-11-01 12:54:56 +0000157 /* TODO: restore other things? */
Denys Vlasenkoe7800f32014-12-07 00:42:49 +0100158 if (xstate.mtime != 0) {
Denys Vlasenkodcbfaba2009-11-29 19:40:36 +0100159 struct timeval times[2];
Denys Vlasenko389cca42009-11-15 02:28:56 +0100160
Denys Vlasenkoe7800f32014-12-07 00:42:49 +0100161 times[1].tv_sec = times[0].tv_sec = xstate.mtime;
Denys Vlasenkodcbfaba2009-11-29 19:40:36 +0100162 times[1].tv_usec = times[0].tv_usec = 0;
Denys Vlasenkodcd27ab2009-10-05 03:03:07 +0200163 /* Note: we closed it first.
Denys Vlasenko389cca42009-11-15 02:28:56 +0100164 * On some systems calling utimes
Denys Vlasenkodcd27ab2009-10-05 03:03:07 +0200165 * then closing resets the mtime
166 * back to current time. */
Denys Vlasenkodcbfaba2009-11-29 19:40:36 +0100167 utimes(new_name, times); /* ignoring errors */
Denis Vlasenko1a9e9bd2008-11-01 12:54:56 +0000168 }
169
Denys Vlasenkod0bc7082013-07-30 05:41:11 +0200170 if (ENABLE_DESKTOP)
171 new_name_len = strlen(new_name);
172 /* Restore source filename (unless tgz -> tar case) */
173 if (new_name == filename) {
174 new_name_len = strlen(filename);
175 filename[new_name_len] = '.';
176 }
177 /* Extreme bloat for gunzip compat */
178 /* Some users do want this info... */
179 if (ENABLE_DESKTOP && (option_mask32 & OPT_VERBOSE)) {
180 unsigned percent = status
181 ? ((uoff_t)stat_buf.st_size * 100u / (unsigned long long)status)
182 : 0;
183 fprintf(stderr, "%s: %u%% - replaced with %.*s\n",
184 filename,
185 100u - percent,
186 new_name_len, new_name
187 );
188 }
189 /* Delete _source_ file */
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000190 del = filename;
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200191 if (option_mask32 & OPT_KEEP) /* ... unless -k */
192 del = NULL;
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000193 }
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200194 if (del)
195 xunlink(del);
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000196 free_name:
197 if (new_name != filename)
198 free(new_name);
199 }
200 } while (*argv && *++argv);
201
Denys Vlasenkoc531b9a2011-10-31 01:05:16 +0100202 if (option_mask32 & OPT_STDOUT)
203 xclose(STDOUT_FILENO); /* with error check! */
204
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000205 return exitcode;
206}
207
Denys Vlasenko548620c2016-12-08 12:24:48 +0100208#if ENABLE_UNCOMPRESS \
Kang-Che Sungb130f9f2017-01-08 14:28:34 +0800209 || ENABLE_FEATURE_BZIP2_DECOMPRESS \
Denys Vlasenko548620c2016-12-08 12:24:48 +0100210 || ENABLE_UNLZMA || ENABLE_LZCAT || ENABLE_LZMA \
211 || ENABLE_UNXZ || ENABLE_XZCAT || ENABLE_XZ
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000212static
Denys Vlasenko39a04f72010-05-31 14:18:57 +0200213char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext)
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000214{
215 char *extension = strrchr(filename, '.');
Denis Vlasenkobebbd8c2007-03-09 20:49:55 +0000216 if (!extension || strcmp(extension + 1, expected_ext) != 0) {
Denis Vlasenko6c939e02007-03-07 23:22:47 +0000217 /* Mimic GNU gunzip - "real" bunzip2 tries to */
218 /* unpack file anyway, to file.out */
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000219 return NULL;
220 }
221 *extension = '\0';
222 return filename;
223}
Denis Vlasenkoa4688bf2007-03-11 10:56:37 +0000224#endif
225
226
Denis Vlasenkoa4688bf2007-03-11 10:56:37 +0000227/*
Denys Vlasenkod93f19e2010-05-30 03:46:54 +0200228 * Uncompress applet for busybox (c) 2002 Glenn McGrath
Denis Vlasenkoa4688bf2007-03-11 10:56:37 +0000229 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +0200230 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Denis Vlasenkoa4688bf2007-03-11 10:56:37 +0000231 */
Pere Orga1f4447b2011-03-27 22:40:30 +0200232//usage:#define uncompress_trivial_usage
233//usage: "[-cf] [FILE]..."
234//usage:#define uncompress_full_usage "\n\n"
235//usage: "Decompress .Z file[s]\n"
Pere Orga1f4447b2011-03-27 22:40:30 +0200236//usage: "\n -c Write to stdout"
237//usage: "\n -f Overwrite"
238
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100239//config:config UNCOMPRESS
Denys Vlasenko4eed2c62017-07-18 22:01:24 +0200240//config: bool "uncompress (7.1 kb)"
Denys Vlasenkodb700332015-10-25 20:36:03 +0100241//config: default n # ancient
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100242//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200243//config: uncompress is used to decompress archives created by compress.
244//config: Not much used anymore, replaced by gzip/gunzip.
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100245
Denys Vlasenko36184a42013-11-14 09:54:24 +0100246//applet:IF_UNCOMPRESS(APPLET(uncompress, BB_DIR_BIN, BB_SUID_DROP))
Denys Vlasenko66620fa2013-11-14 09:53:52 +0100247//kbuild:lib-$(CONFIG_UNCOMPRESS) += bbunzip.o
Denys Vlasenkod93f19e2010-05-30 03:46:54 +0200248#if ENABLE_UNCOMPRESS
Denys Vlasenkod93f19e2010-05-30 03:46:54 +0200249int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
250int uncompress_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000251{
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200252// (N)compress 4.2.4.4:
253// -d If given, decompression is done instead
254// -c Write output on stdout, don't remove original
255// -b Parameter limits the max number of bits/code
256// -f Forces output file to be generated
257// -v Write compression statistics
258// -V Output vesion and compile options
259// -r Recursive. If a filename is a directory, descend into it and compress everything
Denys Vlasenkod93f19e2010-05-30 03:46:54 +0200260 getopt32(argv, "cf");
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200261
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000262 argv += optind;
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000263
Denys Vlasenkob4c11c12014-12-07 00:44:00 +0100264 return bbunpack(argv, unpack_Z_stream, make_new_name_generic, "Z");
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000265}
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000266#endif
267
268
269/*
270 * Gzip implementation for busybox
271 *
272 * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly.
273 *
274 * Originally adjusted for busybox by Sven Rudolph <sr1@inf.tu-dresden.de>
275 * based on gzip sources
276 *
277 * Adjusted further by Erik Andersen <andersen@codepoet.org> to support files as
278 * well as stdin/stdout, and to generally behave itself wrt command line
279 * handling.
280 *
281 * General cleanup to better adhere to the style guide and make use of standard
Denis Vlasenko0beaff82007-09-21 13:16:32 +0000282 * busybox functions by Glenn McGrath
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000283 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +0200284 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000285 *
286 * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
287 * Copyright (C) 1992-1993 Jean-loup Gailly
288 * The unzip code was written and put in the public domain by Mark Adler.
289 * Portions of the lzw code are derived from the public domain 'compress'
290 * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
291 * Ken Turkowski, Dave Mack and Peter Jannesen.
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000292 */
Pere Orga1f4447b2011-03-27 22:40:30 +0200293//usage:#define gunzip_trivial_usage
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200294//usage: "[-cfkt] [FILE]..."
Pere Orga1f4447b2011-03-27 22:40:30 +0200295//usage:#define gunzip_full_usage "\n\n"
296//usage: "Decompress FILEs (or stdin)\n"
Pere Orga1f4447b2011-03-27 22:40:30 +0200297//usage: "\n -c Write to stdout"
298//usage: "\n -f Force"
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200299//usage: "\n -k Keep input files"
Pere Orga1f4447b2011-03-27 22:40:30 +0200300//usage: "\n -t Test file integrity"
301//usage:
302//usage:#define gunzip_example_usage
303//usage: "$ ls -la /tmp/BusyBox*\n"
304//usage: "-rw-rw-r-- 1 andersen andersen 557009 Apr 11 10:55 /tmp/BusyBox-0.43.tar.gz\n"
305//usage: "$ gunzip /tmp/BusyBox-0.43.tar.gz\n"
306//usage: "$ ls -la /tmp/BusyBox*\n"
307//usage: "-rw-rw-r-- 1 andersen andersen 1761280 Apr 14 17:47 /tmp/BusyBox-0.43.tar\n"
308//usage:
309//usage:#define zcat_trivial_usage
Denys Vlasenkof2d84782013-02-28 18:04:22 +0100310//usage: "[FILE]..."
Pere Orga1f4447b2011-03-27 22:40:30 +0200311//usage:#define zcat_full_usage "\n\n"
312//usage: "Decompress to stdout"
313
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100314//config:config GUNZIP
Denys Vlasenko4eed2c62017-07-18 22:01:24 +0200315//config: bool "gunzip (12 kb)"
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100316//config: default y
Kang-Che Sungb130f9f2017-01-08 14:28:34 +0800317//config: select FEATURE_GZIP_DECOMPRESS
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100318//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200319//config: gunzip is used to decompress archives created by gzip.
Denys Vlasenko18e781d2017-08-02 14:12:48 +0200320//config: You can use the '-t' option to test the integrity of
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200321//config: an archive, without decompressing it.
Aaro Koskinenfbe50cf2015-10-26 23:42:32 +0200322//config:
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100323//config:config ZCAT
Denys Vlasenko4eed2c62017-07-18 22:01:24 +0200324//config: bool "zcat (25 kb)"
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100325//config: default y
Kang-Che Sungb130f9f2017-01-08 14:28:34 +0800326//config: select FEATURE_GZIP_DECOMPRESS
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100327//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200328//config: Alias to "gunzip -c".
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100329//config:
Aaro Koskinenfbe50cf2015-10-26 23:42:32 +0200330//config:config FEATURE_GUNZIP_LONG_OPTIONS
331//config: bool "Enable long options"
332//config: default y
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100333//config: depends on (GUNZIP || ZCAT) && LONG_OPTS
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100334
Denys Vlasenko36184a42013-11-14 09:54:24 +0100335//applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP))
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100336// APPLET_ODDNAME:name main location suid_type help
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100337//applet:IF_ZCAT(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat))
Kang-Che Sungb130f9f2017-01-08 14:28:34 +0800338#if ENABLE_FEATURE_GZIP_DECOMPRESS
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000339static
Denys Vlasenko39a04f72010-05-31 14:18:57 +0200340char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UNUSED_PARAM)
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000341{
342 char *extension = strrchr(filename, '.');
343
344 if (!extension)
345 return NULL;
346
Denis Vlasenkobebbd8c2007-03-09 20:49:55 +0000347 extension++;
348 if (strcmp(extension, "tgz" + 1) == 0
Denis Vlasenkoe9ad84d2008-08-05 13:10:34 +0000349#if ENABLE_FEATURE_SEAMLESS_Z
350 || (extension[0] == 'Z' && extension[1] == '\0')
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000351#endif
352 ) {
Denis Vlasenkobebbd8c2007-03-09 20:49:55 +0000353 extension[-1] = '\0';
Denis Vlasenko51742f42007-04-12 00:32:05 +0000354 } else if (strcmp(extension, "tgz") == 0) {
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000355 filename = xstrdup(filename);
356 extension = strrchr(filename, '.');
357 extension[2] = 'a';
358 extension[3] = 'r';
359 } else {
360 return NULL;
361 }
362 return filename;
363}
Aaro Koskinenfbe50cf2015-10-26 23:42:32 +0200364
365#if ENABLE_FEATURE_GUNZIP_LONG_OPTIONS
366static const char gunzip_longopts[] ALIGN1 =
367 "stdout\0" No_argument "c"
368 "to-stdout\0" No_argument "c"
369 "force\0" No_argument "f"
370 "test\0" No_argument "t"
Aaro Koskinencddc98e2015-10-26 23:42:33 +0200371 "no-name\0" No_argument "n"
Aaro Koskinenfbe50cf2015-10-26 23:42:32 +0200372 ;
373#endif
374
Denis Vlasenko52978092008-03-30 13:11:47 +0000375/*
376 * Linux kernel build uses gzip -d -n. We accept and ignore it.
377 * Man page says:
378 * -n --no-name
379 * gzip: do not save the original file name and time stamp.
380 * (The original name is always saved if the name had to be truncated.)
381 * gunzip: do not restore the original file name/time even if present
382 * (remove only the gzip suffix from the compressed file name).
383 * This option is the default when decompressing.
384 * -N --name
385 * gzip: always save the original file name and time stamp (this is the default)
386 * gunzip: restore the original file name and time stamp if present.
387 */
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +0000388int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000389int gunzip_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000390{
Aaro Koskinenfbe50cf2015-10-26 23:42:32 +0200391#if ENABLE_FEATURE_GUNZIP_LONG_OPTIONS
Denys Vlasenko036585a2017-08-08 16:38:18 +0200392 getopt32long(argv, "cfkvqdtn", gunzip_longopts);
393#else
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200394 getopt32(argv, "cfkvqdtn");
Denys Vlasenko036585a2017-08-08 16:38:18 +0200395#endif
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000396 argv += optind;
Denys Vlasenko8e96efa2013-02-28 18:06:09 +0100397
398 /* If called as zcat...
399 * Normally, "zcat" is just "gunzip -c".
400 * But if seamless magic is enabled, then we are much more clever.
401 */
Denys Vlasenkoebe3c352017-07-20 16:25:03 +0200402 if (ENABLE_ZCAT && (!ENABLE_GUNZIP || applet_name[1] == 'c'))
Denys Vlasenko8e96efa2013-02-28 18:06:09 +0100403 option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC;
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000404
Denys Vlasenkob4c11c12014-12-07 00:44:00 +0100405 return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL);
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000406}
Kang-Che Sungb130f9f2017-01-08 14:28:34 +0800407#endif /* FEATURE_GZIP_DECOMPRESS */
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000408
Denys Vlasenkod93f19e2010-05-30 03:46:54 +0200409
410/*
411 * Modified for busybox by Glenn McGrath
412 * Added support output to stdout by Thomas Lundquist <thomasez@zelow.no>
413 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +0200414 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Denys Vlasenkod93f19e2010-05-30 03:46:54 +0200415 */
Denys Vlasenkof0f94702010-06-06 01:53:38 +0200416//usage:#define bunzip2_trivial_usage
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200417//usage: "[-cfk] [FILE]..."
Denys Vlasenkof0f94702010-06-06 01:53:38 +0200418//usage:#define bunzip2_full_usage "\n\n"
419//usage: "Decompress FILEs (or stdin)\n"
Denys Vlasenkof0f94702010-06-06 01:53:38 +0200420//usage: "\n -c Write to stdout"
421//usage: "\n -f Force"
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200422//usage: "\n -k Keep input files"
Denys Vlasenkof0f94702010-06-06 01:53:38 +0200423//usage:#define bzcat_trivial_usage
Denys Vlasenkof2d84782013-02-28 18:04:22 +0100424//usage: "[FILE]..."
Denys Vlasenkof0f94702010-06-06 01:53:38 +0200425//usage:#define bzcat_full_usage "\n\n"
426//usage: "Decompress to stdout"
Denys Vlasenko66620fa2013-11-14 09:53:52 +0100427
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100428//config:config BUNZIP2
Denys Vlasenko4eed2c62017-07-18 22:01:24 +0200429//config: bool "bunzip2 (8.8 kb)"
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100430//config: default y
Kang-Che Sungb130f9f2017-01-08 14:28:34 +0800431//config: select FEATURE_BZIP2_DECOMPRESS
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100432//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200433//config: bunzip2 is a compression utility using the Burrows-Wheeler block
434//config: sorting text compression algorithm, and Huffman coding. Compression
435//config: is generally considerably better than that achieved by more
436//config: conventional LZ77/LZ78-based compressors, and approaches the
437//config: performance of the PPM family of statistical compressors.
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100438//config:
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200439//config: Unless you have a specific application which requires bunzip2, you
440//config: should probably say N here.
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100441//config:
442//config:config BZCAT
Denys Vlasenko4eed2c62017-07-18 22:01:24 +0200443//config: bool "bzcat (8.8 kb)"
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100444//config: default y
Kang-Che Sungb130f9f2017-01-08 14:28:34 +0800445//config: select FEATURE_BZIP2_DECOMPRESS
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100446//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200447//config: Alias to "bunzip2 -c".
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100448
Denys Vlasenkob9f2d9f2011-01-18 13:58:01 +0100449//applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP))
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100450// APPLET_ODDNAME:name main location suid_type help
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100451//applet:IF_BZCAT(APPLET_ODDNAME(bzcat, bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP, bzcat))
Denys Vlasenko034ceab2017-07-04 16:23:36 +0200452#if ENABLE_FEATURE_BZIP2_DECOMPRESS || ENABLE_BUNZIP2 || ENABLE_BZCAT
Denys Vlasenkod93f19e2010-05-30 03:46:54 +0200453int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
454int bunzip2_main(int argc UNUSED_PARAM, char **argv)
455{
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200456 getopt32(argv, "cfkvqdt");
Denys Vlasenkod93f19e2010-05-30 03:46:54 +0200457 argv += optind;
Denys Vlasenkoebe3c352017-07-20 16:25:03 +0200458 if (ENABLE_BZCAT && (!ENABLE_BUNZIP2 || applet_name[2] == 'c')) /* bzcat */
Denys Vlasenkod93f19e2010-05-30 03:46:54 +0200459 option_mask32 |= OPT_STDOUT;
460
Denys Vlasenkob4c11c12014-12-07 00:44:00 +0100461 return bbunpack(argv, unpack_bz2_stream, make_new_name_generic, "bz2");
Denys Vlasenkod93f19e2010-05-30 03:46:54 +0200462}
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000463#endif
464
465
466/*
467 * Small lzma deflate implementation.
468 * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
469 *
470 * Based on bunzip.c from busybox
471 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +0200472 * Licensed under GPLv2, see file LICENSE in this source tree.
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000473 */
Pere Orga1f4447b2011-03-27 22:40:30 +0200474//usage:#define unlzma_trivial_usage
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200475//usage: "[-cfk] [FILE]..."
Pere Orga1f4447b2011-03-27 22:40:30 +0200476//usage:#define unlzma_full_usage "\n\n"
477//usage: "Decompress FILE (or stdin)\n"
Pere Orga1f4447b2011-03-27 22:40:30 +0200478//usage: "\n -c Write to stdout"
479//usage: "\n -f Force"
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200480//usage: "\n -k Keep input files"
Pere Orga1f4447b2011-03-27 22:40:30 +0200481//usage:
482//usage:#define lzma_trivial_usage
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200483//usage: "-d [-cfk] [FILE]..."
Pere Orga1f4447b2011-03-27 22:40:30 +0200484//usage:#define lzma_full_usage "\n\n"
485//usage: "Decompress FILE (or stdin)\n"
Pere Orga1f4447b2011-03-27 22:40:30 +0200486//usage: "\n -d Decompress"
487//usage: "\n -c Write to stdout"
488//usage: "\n -f Force"
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200489//usage: "\n -k Keep input files"
Pere Orga1f4447b2011-03-27 22:40:30 +0200490//usage:
491//usage:#define lzcat_trivial_usage
Denys Vlasenkof2d84782013-02-28 18:04:22 +0100492//usage: "[FILE]..."
Pere Orga1f4447b2011-03-27 22:40:30 +0200493//usage:#define lzcat_full_usage "\n\n"
494//usage: "Decompress to stdout"
Pere Orga1f4447b2011-03-27 22:40:30 +0200495
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100496//config:config UNLZMA
Denys Vlasenko4eed2c62017-07-18 22:01:24 +0200497//config: bool "unlzma (8.6 kb)"
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100498//config: default y
499//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200500//config: unlzma is a compression utility using the Lempel-Ziv-Markov chain
501//config: compression algorithm, and range coding. Compression
502//config: is generally considerably better than that achieved by the bzip2
503//config: compressors.
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100504//config:
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100505//config:config LZCAT
Denys Vlasenko4eed2c62017-07-18 22:01:24 +0200506//config: bool "lzcat (8.5 kb)"
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100507//config: default y
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100508//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200509//config: Alias to "unlzma -c".
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100510//config:
511//config:config LZMA
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100512//config: bool "lzma -d"
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100513//config: default y
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100514//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200515//config: Enable this option if you want commands like "lzma -d" to work.
516//config: IOW: you'll get lzma applet, but it will always require -d option.
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100517
Denys Vlasenko36184a42013-11-14 09:54:24 +0100518//applet:IF_UNLZMA(APPLET(unlzma, BB_DIR_USR_BIN, BB_SUID_DROP))
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100519// APPLET_ODDNAME:name main location suid_type help
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100520//applet:IF_LZCAT(APPLET_ODDNAME(lzcat, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzcat))
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100521//applet:IF_LZMA( APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma))
Denys Vlasenko66620fa2013-11-14 09:53:52 +0100522//kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100523//kbuild:lib-$(CONFIG_LZCAT) += bbunzip.o
524//kbuild:lib-$(CONFIG_LZMA) += bbunzip.o
525#if ENABLE_UNLZMA || ENABLE_LZCAT || ENABLE_LZMA
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +0000526int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000527int unlzma_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000528{
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200529 IF_LZMA(int opts =) getopt32(argv, "cfkvqdt");
Denys Vlasenkoe04c8672010-05-30 03:33:50 +0200530# if ENABLE_LZMA
Denys Vlasenkoccb88a62010-05-27 02:22:54 +0200531 /* lzma without -d or -t? */
532 if (applet_name[2] == 'm' && !(opts & (OPT_DECOMPRESS|OPT_TEST)))
533 bb_show_usage();
534# endif
535 /* lzcat? */
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100536 if (ENABLE_LZCAT && applet_name[2] == 'c')
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000537 option_mask32 |= OPT_STDOUT;
538
Denys Vlasenkoccb88a62010-05-27 02:22:54 +0200539 argv += optind;
Denys Vlasenkob4c11c12014-12-07 00:44:00 +0100540 return bbunpack(argv, unpack_lzma_stream, make_new_name_generic, "lzma");
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000541}
Denis Vlasenkoab9eef22007-03-07 22:02:23 +0000542#endif
543
544
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100545//usage:#define unxz_trivial_usage
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200546//usage: "[-cfk] [FILE]..."
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100547//usage:#define unxz_full_usage "\n\n"
548//usage: "Decompress FILE (or stdin)\n"
549//usage: "\n -c Write to stdout"
550//usage: "\n -f Force"
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200551//usage: "\n -k Keep input files"
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100552//usage:
553//usage:#define xz_trivial_usage
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200554//usage: "-d [-cfk] [FILE]..."
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100555//usage:#define xz_full_usage "\n\n"
556//usage: "Decompress FILE (or stdin)\n"
557//usage: "\n -d Decompress"
558//usage: "\n -c Write to stdout"
559//usage: "\n -f Force"
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200560//usage: "\n -k Keep input files"
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100561//usage:
562//usage:#define xzcat_trivial_usage
563//usage: "[FILE]..."
564//usage:#define xzcat_full_usage "\n\n"
565//usage: "Decompress to stdout"
566
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100567//config:config UNXZ
Denys Vlasenko4eed2c62017-07-18 22:01:24 +0200568//config: bool "unxz (13 kb)"
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100569//config: default y
570//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200571//config: unxz is a unlzma successor.
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100572//config:
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100573//config:config XZCAT
Denys Vlasenko4eed2c62017-07-18 22:01:24 +0200574//config: bool "xzcat (13 kb)"
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100575//config: default y
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100576//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200577//config: Alias to "unxz -c".
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100578//config:
579//config:config XZ
580//config: bool "xz -d"
581//config: default y
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100582//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +0200583//config: Enable this option if you want commands like "xz -d" to work.
584//config: IOW: you'll get xz applet, but it will always require -d option.
Denys Vlasenkof6beef62013-11-14 11:39:00 +0100585
Denys Vlasenko36184a42013-11-14 09:54:24 +0100586//applet:IF_UNXZ(APPLET(unxz, BB_DIR_USR_BIN, BB_SUID_DROP))
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100587// APPLET_ODDNAME:name main location suid_type help
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100588//applet:IF_XZCAT(APPLET_ODDNAME(xzcat, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xzcat))
Denys Vlasenko205d48e2017-01-29 14:57:33 +0100589//applet:IF_XZ( APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz))
Denys Vlasenko66620fa2013-11-14 09:53:52 +0100590//kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100591//kbuild:lib-$(CONFIG_XZCAT) += bbunzip.o
592//kbuild:lib-$(CONFIG_XZ) += bbunzip.o
593#if ENABLE_UNXZ || ENABLE_XZCAT || ENABLE_XZ
Denys Vlasenko602ce692010-05-30 03:35:18 +0200594int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
595int unxz_main(int argc UNUSED_PARAM, char **argv)
596{
Denys Vlasenko1c013fa2017-06-15 18:07:04 +0200597 IF_XZ(int opts =) getopt32(argv, "cfkvqdt");
Denys Vlasenko602ce692010-05-30 03:35:18 +0200598# if ENABLE_XZ
599 /* xz without -d or -t? */
600 if (applet_name[2] == '\0' && !(opts & (OPT_DECOMPRESS|OPT_TEST)))
601 bb_show_usage();
602# endif
603 /* xzcat? */
Denys Vlasenkoeb3fdc82016-11-16 15:45:05 +0100604 if (ENABLE_XZCAT && applet_name[2] == 'c')
Denys Vlasenko602ce692010-05-30 03:35:18 +0200605 option_mask32 |= OPT_STDOUT;
606
607 argv += optind;
Denys Vlasenkob4c11c12014-12-07 00:44:00 +0100608 return bbunpack(argv, unpack_xz_stream, make_new_name_generic, "xz");
Denys Vlasenko602ce692010-05-30 03:35:18 +0200609}
Denys Vlasenko602ce692010-05-30 03:35:18 +0200610#endif