From 49d54afe4e196f3dd51188394a922259dd8ff939 Mon Sep 17 00:00:00 2001 From: Eugene Rudoy Date: Mon, 6 Nov 2017 22:33:20 +0100 Subject: [PATCH 3/3] unzip: add support for a non-standard (busybox only) -J NUM option Its behavior is the same as that of tar's --strip-components=NUM. Based on https://git.busybox.net/busybox/commit?id=6c563e370d0f2f3cf36f3b274e8fe1392ca7125f function old new delta unzip_main 2964 3088 +124 .rodata 17268 17295 +27 packed_usage 1808 1833 +25 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 176/0) Total: 176 bytes Signed-off-by: Eugene Rudoy --- archival/unzip.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git archival/unzip.c archival/unzip.c index 50205eb6e..d5a601a24 100644 --- archival/unzip.c +++ archival/unzip.c @@ -51,18 +51,29 @@ //config: bool "Support compression method 95 (xz)" //config: default y //config: depends on FEATURE_UNZIP_CDF && DESKTOP +//config: +//config:config FEATURE_UNZIP_J_NUM +//config: bool "Provide non-standard -J NUM option" +//config: default n +//config: depends on UNZIP +//config: help +//config: Add support for a non-standard (busybox only) -J NUM option. +//config: Its behavior is the same as that of tar's --strip-components=NUM. //applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_UNZIP) += unzip.o //usage:#define unzip_trivial_usage -//usage: "[-lnojpq] FILE[.zip] [FILE]... [-x FILE...] [-d DIR]" +//usage: "[-lnojpq] FILE[.zip] [FILE]... [-x FILE...] [-d DIR]" IF_FEATURE_UNZIP_J_NUM(" [-J NUM]") //usage:#define unzip_full_usage "\n\n" //usage: "Extract FILEs from ZIP archive\n" //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: IF_FEATURE_UNZIP_J_NUM( +//usage: "\n -J NUM Strip NUM leading path components on extraction" +//usage: ) //usage: "\n -p Print to stdout" //usage: "\n -q Quiet" //usage: "\n -x FILE Exclude FILEs" @@ -466,8 +477,12 @@ OPT_l = (1 << 0), OPT_x = (1 << 1), OPT_j = (1 << 2), + OPT_J_num = (1 << 3), }; unsigned opts; +#if ENABLE_FEATURE_UNZIP_J_NUM + unsigned strip_components = 0; +#endif smallint quiet = 0; IF_NOT_FEATURE_UNZIP_CDF(const) smallint verbose = 0; enum { O_PROMPT, O_NEVER, O_ALWAYS }; @@ -528,7 +543,7 @@ opts = 0; /* '-' makes getopt return 1 for non-options */ - while ((i = getopt(argc, argv, "-d:lnopqxjv")) != -1) { + while ((i = getopt(argc, argv, "-d:lnopqxj" IF_FEATURE_UNZIP_J_NUM("J:") "v")) != -1) { switch (i) { case 'd': /* Extract to base directory */ base_dir = optarg; @@ -566,6 +581,13 @@ opts |= OPT_j; break; +#if ENABLE_FEATURE_UNZIP_J_NUM + case 'J': + opts |= OPT_J_num; + strip_components = xatou(optarg); + break; +#endif + case 1: if (!src_fn) { /* The zip file */ @@ -866,6 +888,36 @@ if (opts & OPT_j) /* Strip paths? */ overlapping_strcpy(dst_fn, bb_basename(dst_fn)); +#if ENABLE_FEATURE_UNZIP_J_NUM + /* we tolerate it when both -j and -J NUM are used at the same time */ + /* by making -j always win, thus 'else if' below */ + else if ((opts & OPT_J_num) && (strip_components > 0)) { + unsigned n = strip_components; + const char *dst_fn_stripped = dst_fn; + do { + dst_fn_stripped = strchr(dst_fn_stripped, '/'); + if (!dst_fn_stripped /* || dst_fn_stripped[1] == '\0' */) { + /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * from tar's --strip-component + * covered by the "DIR/ case?" check below + */ + goto skip_cmpsize; + } + dst_fn_stripped++; + } while (--n != 0); + overlapping_strcpy(dst_fn, dst_fn_stripped); + + /* + * Q: What should we do with link targets? + * A: tar behavior is + * - link targets are shortened only for hardlinks + * - softlinks are restored unchanged + * zip format supports only symlinks + * => nothing to do in regard to link targets + */ + + } +#endif /* Did this strip everything ("DIR/" case)? Then skip */ if (!dst_fn[0])