unzip: implement -j, closes 9126

function                                             old     new   delta
unzip_main                                          2642    2703     +61
packed_usage                                       31747   31770     +23
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 84/0)               Total: 84 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2017-07-20 20:04:49 +02:00
parent bff9bbc73f
commit 997ad2c64a

View File

@ -62,6 +62,7 @@
//usage: "\n -l List contents (with -q for short form)"
//usage: "\n -n Never overwrite files (default: ask)"
//usage: "\n -o Overwrite"
//usage: "\n -j Do not restore paths"
//usage: "\n -p Print to stdout"
//usage: "\n -q Quiet"
//usage: "\n -x FILE Exclude FILEs"
@ -455,13 +456,16 @@ static int get_lstat_mode(const char *dst_fn)
int unzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int unzip_main(int argc, char **argv)
{
enum { O_PROMPT, O_NEVER, O_ALWAYS };
enum {
OPT_l = (1 << 0),
OPT_x = (1 << 1),
OPT_j = (1 << 2),
};
unsigned opts;
smallint quiet = 0;
IF_NOT_FEATURE_UNZIP_CDF(const) smallint verbose = 0;
smallint listing = 0;
enum { O_PROMPT, O_NEVER, O_ALWAYS };
smallint overwrite = O_PROMPT;
smallint x_opt_seen;
uint32_t cdf_offset;
unsigned long total_usize;
unsigned long total_size;
@ -472,7 +476,7 @@ int unzip_main(int argc, char **argv)
llist_t *zaccept = NULL;
llist_t *zreject = NULL;
char *base_dir = NULL;
int i, opt;
int i;
char key_buf[80]; /* must match size used by my_fgets80 */
/* -q, -l and -v: UnZip 5.52 of 28 February 2005, by Info-ZIP:
@ -516,16 +520,16 @@ int unzip_main(int argc, char **argv)
* 204372 1 file
*/
x_opt_seen = 0;
opts = 0;
/* '-' makes getopt return 1 for non-options */
while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) {
switch (opt) {
while ((i = getopt(argc, argv, "-d:lnopqxjv")) != -1) {
switch (i) {
case 'd': /* Extract to base directory */
base_dir = optarg;
break;
case 'l': /* List */
listing = 1;
opts |= OPT_l;
break;
case 'n': /* Never overwrite existing files */
@ -545,11 +549,15 @@ int unzip_main(int argc, char **argv)
case 'v': /* Verbose list */
IF_FEATURE_UNZIP_CDF(verbose++;)
listing = 1;
opts |= OPT_l;
break;
case 'x':
x_opt_seen = 1;
opts |= OPT_x;
break;
case 'j':
opts |= OPT_j;
break;
case 1:
@ -558,7 +566,7 @@ int unzip_main(int argc, char **argv)
/* +5: space for ".zip" and NUL */
src_fn = xmalloc(strlen(optarg) + 5);
strcpy(src_fn, optarg);
} else if (!x_opt_seen) {
} else if (!(opts & OPT_x)) {
/* Include files */
llist_add_to(&zaccept, optarg);
} else {
@ -626,7 +634,7 @@ int unzip_main(int argc, char **argv)
if (quiet <= 1) { /* not -qq */
if (quiet == 0)
printf("Archive: %s\n", src_fn);
if (listing) {
if (opts & OPT_l) {
puts(verbose ?
" Length Method Size Cmpr Date Time CRC-32 Name\n"
"-------- ------ ------- ---- ---------- ----- -------- ----"
@ -778,13 +786,19 @@ int unzip_main(int argc, char **argv)
free(dst_fn);
dst_fn = xzalloc(zip.fmt.filename_len + 1);
xread(zip_fd, dst_fn, zip.fmt.filename_len);
/* Skip extra header bytes */
unzip_skip(zip.fmt.extra_len);
/* Guard against "/abspath", "/../" and similar attacks */
overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn));
if (opts & OPT_j) /* Strip paths? */
overlapping_strcpy(dst_fn, bb_basename(dst_fn));
/* Did this strip everything ("DIR/" case)? Then skip */
if (!dst_fn[0])
goto skip_cmpsize;
/* Filter zip entries */
if (find_list_entry(zreject, dst_fn)
|| (zaccept && !find_list_entry(zaccept, dst_fn))
@ -792,7 +806,7 @@ int unzip_main(int argc, char **argv)
goto skip_cmpsize;
}
if (listing) {
if (opts & OPT_l) {
/* List entry */
char dtbuf[sizeof("mm-dd-yyyy hh:mm")];
sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u",
@ -960,7 +974,7 @@ int unzip_main(int argc, char **argv)
total_entries++;
}
if (listing && quiet <= 1) {
if ((opts & OPT_l) && quiet <= 1) {
if (!verbose) {
// " Length Date Time Name\n"
// "--------- ---------- ----- ----"