summaryrefslogtreecommitdiff
path: root/archival/unzip.c
diff options
context:
space:
mode:
Diffstat (limited to 'archival/unzip.c')
-rw-r--r--archival/unzip.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/archival/unzip.c b/archival/unzip.c
index 21ba172..d5bca08 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -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"
// "--------- ---------- ----- ----"