[PATCH 3/3] unzip: add support for a non-standard (busybox only) -J NUM option
Eugene Rudoy
gene.devel at gmail.com
Tue Nov 7 07:03:38 UTC 2017
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 <gene.devel at gmail.com>
---
archival/unzip.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 54 insertions(+), 2 deletions(-)
diff --git a/archival/unzip.c b/archival/unzip.c
index 50205eb6e..d5a601a24 100644
--- a/archival/unzip.c
+++ b/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"
@@ -472,8 +483,12 @@ int unzip_main(int argc, char **argv)
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 };
@@ -534,7 +549,7 @@ int unzip_main(int argc, char **argv)
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;
@@ -572,6 +587,13 @@ int unzip_main(int argc, char **argv)
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 */
@@ -872,6 +894,36 @@ int unzip_main(int argc, char **argv)
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])
--
2.15.0
More information about the busybox
mailing list