aboutsummaryrefslogtreecommitdiff
path: root/archival
diff options
context:
space:
mode:
Diffstat (limited to 'archival')
-rw-r--r--archival/dpkg.c13
-rw-r--r--archival/libarchive/Kbuild.src2
-rw-r--r--archival/libarchive/filter_accept_reject_list.c8
-rw-r--r--archival/libarchive/get_header_tar.c8
-rw-r--r--archival/tar.c36
-rw-r--r--archival/unzip.c149
6 files changed, 123 insertions, 93 deletions
diff --git a/archival/dpkg.c b/archival/dpkg.c
index bf9e9992c..dae8a9747 100644
--- a/archival/dpkg.c
+++ b/archival/dpkg.c
@@ -1665,20 +1665,25 @@ static void unpack_package(deb_file_t *deb_file)
1665 archive_handle = init_archive_deb_ar(deb_file->filename); 1665 archive_handle = init_archive_deb_ar(deb_file->filename);
1666 init_archive_deb_data(archive_handle); 1666 init_archive_deb_data(archive_handle);
1667 archive_handle->dpkg__sub_archive->accept = conffile_list; 1667 archive_handle->dpkg__sub_archive->accept = conffile_list;
1668 /* Why ARCHIVE_REMEMBER_NAMES?
1669 * We want names collected in ->passed list even if conffile_list
1670 * is NULL (otherwise get_header_tar may optimize name saving out):
1671 */
1672 archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_REMEMBER_NAMES | ARCHIVE_UNLINK_OLD;
1668 archive_handle->dpkg__sub_archive->filter = filter_rename_config; 1673 archive_handle->dpkg__sub_archive->filter = filter_rename_config;
1669 archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix; 1674 archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix;
1670 archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/"; /* huh? */ 1675 archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/"; /* huh? */
1671 archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD;
1672 unpack_ar_archive(archive_handle); 1676 unpack_ar_archive(archive_handle);
1673 1677
1674 /* Create the list file */ 1678 /* Create the list file */
1675 list_filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "list"); 1679 list_filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "list");
1676 out_stream = xfopen_for_write(list_filename); 1680 out_stream = xfopen_for_write(list_filename);
1681 archive_handle->dpkg__sub_archive->passed = llist_rev(archive_handle->dpkg__sub_archive->passed);
1677 while (archive_handle->dpkg__sub_archive->passed) { 1682 while (archive_handle->dpkg__sub_archive->passed) {
1683 char *filename = llist_pop(&archive_handle->dpkg__sub_archive->passed);
1678 /* the leading . has been stripped by data_extract_all_prefix already */ 1684 /* the leading . has been stripped by data_extract_all_prefix already */
1679 fputs(archive_handle->dpkg__sub_archive->passed->data, out_stream); 1685 fprintf(out_stream, "%s\n", filename);
1680 fputc('\n', out_stream); 1686 free(filename);
1681 archive_handle->dpkg__sub_archive->passed = archive_handle->dpkg__sub_archive->passed->link;
1682 } 1687 }
1683 fclose(out_stream); 1688 fclose(out_stream);
1684 1689
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src
index e2134be4c..58457fc22 100644
--- a/archival/libarchive/Kbuild.src
+++ b/archival/libarchive/Kbuild.src
@@ -45,7 +45,7 @@ lib-$(CONFIG_UNXZ) += decompress_unxz.o
45lib-$(CONFIG_CPIO) += get_header_cpio.o 45lib-$(CONFIG_CPIO) += get_header_cpio.o
46lib-$(CONFIG_DPKG) += $(DPKG_FILES) 46lib-$(CONFIG_DPKG) += $(DPKG_FILES)
47lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES) 47lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES)
48lib-$(CONFIG_GUNZIP) += decompress_gunzip.o 48lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o
49lib-$(CONFIG_RPM2CPIO) += decompress_gunzip.o get_header_cpio.o 49lib-$(CONFIG_RPM2CPIO) += decompress_gunzip.o get_header_cpio.o
50lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o 50lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o
51lib-$(CONFIG_TAR) += get_header_tar.o 51lib-$(CONFIG_TAR) += get_header_tar.o
diff --git a/archival/libarchive/filter_accept_reject_list.c b/archival/libarchive/filter_accept_reject_list.c
index 39c811337..248374941 100644
--- a/archival/libarchive/filter_accept_reject_list.c
+++ b/archival/libarchive/filter_accept_reject_list.c
@@ -24,11 +24,13 @@ char FAST_FUNC filter_accept_reject_list(archive_handle_t *archive_handle)
24 if (reject_entry) { 24 if (reject_entry) {
25 return EXIT_FAILURE; 25 return EXIT_FAILURE;
26 } 26 }
27 accept_entry = find_list_entry2(archive_handle->accept, key);
28 27
29 /* Fail if an accept list was specified and the key wasnt in there */ 28 /* Fail if an accept list was specified and the key wasnt in there */
30 if ((accept_entry == NULL) && archive_handle->accept) { 29 if (archive_handle->accept) {
31 return EXIT_FAILURE; 30 accept_entry = find_list_entry2(archive_handle->accept, key);
31 if (!accept_entry) {
32 return EXIT_FAILURE;
33 }
32 } 34 }
33 35
34 /* Accepted */ 36 /* Accepted */
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
index 80a709144..bc09756ba 100644
--- a/archival/libarchive/get_header_tar.c
+++ b/archival/libarchive/get_header_tar.c
@@ -84,7 +84,7 @@ static unsigned long long getOctal(char *str, int len)
84 first >>= 1; /* now 7th bit = 6th bit */ 84 first >>= 1; /* now 7th bit = 6th bit */
85 v = first; /* sign-extend 8 bits to 64 */ 85 v = first; /* sign-extend 8 bits to 64 */
86 while (--len != 0) 86 while (--len != 0)
87 v = (v << 8) + (unsigned char) *str++; 87 v = (v << 8) + (uint8_t) *++str;
88 } 88 }
89 return v; 89 return v;
90} 90}
@@ -452,9 +452,11 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
452 if (cp) 452 if (cp)
453 *cp = '\0'; 453 *cp = '\0';
454 archive_handle->action_data(archive_handle); 454 archive_handle->action_data(archive_handle);
455 if (archive_handle->accept || archive_handle->reject) 455 if (archive_handle->accept || archive_handle->reject
456 || (archive_handle->ah_flags & ARCHIVE_REMEMBER_NAMES)
457 ) {
456 llist_add_to(&archive_handle->passed, file_header->name); 458 llist_add_to(&archive_handle->passed, file_header->name);
457 else /* Caller isn't interested in list of unpacked files */ 459 } else /* Caller isn't interested in list of unpacked files */
458 free(file_header->name); 460 free(file_header->name);
459 } else { 461 } else {
460 data_skip(archive_handle); 462 data_skip(archive_handle);
diff --git a/archival/tar.c b/archival/tar.c
index 9fa5a0f44..e27950b6c 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -60,8 +60,8 @@
60 60
61#if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2 61#if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2
62/* Do not pass gzip flag to writeTarFile() */ 62/* Do not pass gzip flag to writeTarFile() */
63#define writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude, gzip) \ 63#define writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude, gzip) \
64 writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude) 64 writeTarFile(tar_fd, verboseFlag, recurseFlags, include, exclude)
65#endif 65#endif
66 66
67 67
@@ -600,7 +600,7 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip)
600 600
601/* gcc 4.2.1 inlines it, making code bigger */ 601/* gcc 4.2.1 inlines it, making code bigger */
602static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, 602static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
603 int dereferenceFlag, const llist_t *include, 603 int recurseFlags, const llist_t *include,
604 const llist_t *exclude, int gzip) 604 const llist_t *exclude, int gzip)
605{ 605{
606 int errorFlag = FALSE; 606 int errorFlag = FALSE;
@@ -623,8 +623,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
623 623
624 /* Read the directory/files and iterate over them one at a time */ 624 /* Read the directory/files and iterate over them one at a time */
625 while (include) { 625 while (include) {
626 if (!recursive_action(include->data, ACTION_RECURSE | 626 if (!recursive_action(include->data, recurseFlags,
627 (dereferenceFlag ? ACTION_FOLLOWLINKS : 0),
628 writeFileToTarball, writeFileToTarball, &tbInfo, 0) 627 writeFileToTarball, writeFileToTarball, &tbInfo, 0)
629 ) { 628 ) {
630 errorFlag = TRUE; 629 errorFlag = TRUE;
@@ -664,7 +663,7 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
664} 663}
665#else 664#else
666int writeTarFile(int tar_fd, int verboseFlag, 665int writeTarFile(int tar_fd, int verboseFlag,
667 int dereferenceFlag, const llist_t *include, 666 int recurseFlags, const llist_t *include,
668 const llist_t *exclude, int gzip); 667 const llist_t *exclude, int gzip);
669#endif /* FEATURE_TAR_CREATE */ 668#endif /* FEATURE_TAR_CREATE */
670 669
@@ -696,6 +695,7 @@ static llist_t *append_file_list_to_list(llist_t *list)
696//usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt" 695//usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt"
697//usage: IF_FEATURE_SEAMLESS_Z("Z") 696//usage: IF_FEATURE_SEAMLESS_Z("Z")
698//usage: IF_FEATURE_SEAMLESS_GZ("z") 697//usage: IF_FEATURE_SEAMLESS_GZ("z")
698//usage: IF_FEATURE_SEAMLESS_XZ("J")
699//usage: IF_FEATURE_SEAMLESS_BZ2("j") 699//usage: IF_FEATURE_SEAMLESS_BZ2("j")
700//usage: IF_FEATURE_SEAMLESS_LZMA("a") 700//usage: IF_FEATURE_SEAMLESS_LZMA("a")
701//usage: IF_FEATURE_TAR_CREATE("h") 701//usage: IF_FEATURE_TAR_CREATE("h")
@@ -722,6 +722,9 @@ static llist_t *append_file_list_to_list(llist_t *list)
722//usage: IF_FEATURE_SEAMLESS_GZ( 722//usage: IF_FEATURE_SEAMLESS_GZ(
723//usage: "\n z (De)compress using gzip" 723//usage: "\n z (De)compress using gzip"
724//usage: ) 724//usage: )
725//usage: IF_FEATURE_SEAMLESS_XZ(
726//usage: "\n J (De)compress using xz"
727//usage: )
725//usage: IF_FEATURE_SEAMLESS_BZ2( 728//usage: IF_FEATURE_SEAMLESS_BZ2(
726//usage: "\n j (De)compress using bzip2" 729//usage: "\n j (De)compress using bzip2"
727//usage: ) 730//usage: )
@@ -751,6 +754,7 @@ static llist_t *append_file_list_to_list(llist_t *list)
751// o no-same-owner 754// o no-same-owner
752// p same-permissions 755// p same-permissions
753// k keep-old 756// k keep-old
757// no-recursion
754// numeric-owner 758// numeric-owner
755// no-same-permissions 759// no-same-permissions
756// overwrite 760// overwrite
@@ -767,9 +771,11 @@ enum {
767 IF_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,) 771 IF_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,)
768 IF_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,) 772 IF_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,)
769 IF_FEATURE_SEAMLESS_GZ( OPTBIT_GZIP ,) 773 IF_FEATURE_SEAMLESS_GZ( OPTBIT_GZIP ,)
770 IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,) // 16th bit 774 IF_FEATURE_SEAMLESS_XZ( OPTBIT_XZ ,) // 16th bit
775 IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,)
771 IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,) 776 IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,)
772#if ENABLE_FEATURE_TAR_LONG_OPTIONS 777#if ENABLE_FEATURE_TAR_LONG_OPTIONS
778 OPTBIT_NORECURSION,
773 IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND ,) 779 IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND ,)
774 OPTBIT_NUMERIC_OWNER, 780 OPTBIT_NUMERIC_OWNER,
775 OPTBIT_NOPRESERVE_PERM, 781 OPTBIT_NOPRESERVE_PERM,
@@ -791,14 +797,16 @@ enum {
791 OPT_INCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_INCLUDE_FROM)) + 0, // T 797 OPT_INCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_INCLUDE_FROM)) + 0, // T
792 OPT_EXCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X 798 OPT_EXCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X
793 OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z 799 OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z
800 OPT_XZ = IF_FEATURE_SEAMLESS_XZ( (1 << OPTBIT_XZ )) + 0, // J
794 OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z 801 OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z
795 OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m 802 OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m
803 OPT_NORECURSION = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NORECURSION )) + 0, // no-recursion
796 OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command 804 OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command
797 OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner 805 OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner
798 OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions 806 OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
799 OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite 807 OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite
800 808
801 OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_COMPRESS), 809 OPT_ANY_COMPRESS = (OPT_BZIP2 | OPT_LZMA | OPT_GZIP | OPT_XZ | OPT_COMPRESS),
802}; 810};
803#if ENABLE_FEATURE_TAR_LONG_OPTIONS 811#if ENABLE_FEATURE_TAR_LONG_OPTIONS
804static const char tar_longopts[] ALIGN1 = 812static const char tar_longopts[] ALIGN1 =
@@ -831,12 +839,16 @@ static const char tar_longopts[] ALIGN1 =
831# if ENABLE_FEATURE_SEAMLESS_GZ 839# if ENABLE_FEATURE_SEAMLESS_GZ
832 "gzip\0" No_argument "z" 840 "gzip\0" No_argument "z"
833# endif 841# endif
842# if ENABLE_FEATURE_SEAMLESS_XZ
843 "xz\0" No_argument "J"
844# endif
834# if ENABLE_FEATURE_SEAMLESS_Z 845# if ENABLE_FEATURE_SEAMLESS_Z
835 "compress\0" No_argument "Z" 846 "compress\0" No_argument "Z"
836# endif 847# endif
837# if ENABLE_FEATURE_TAR_NOPRESERVE_TIME 848# if ENABLE_FEATURE_TAR_NOPRESERVE_TIME
838 "touch\0" No_argument "m" 849 "touch\0" No_argument "m"
839# endif 850# endif
851 "no-recursion\0" No_argument "\xfa"
840# if ENABLE_FEATURE_TAR_TO_COMMAND 852# if ENABLE_FEATURE_TAR_TO_COMMAND
841 "to-command\0" Required_argument "\xfb" 853 "to-command\0" Required_argument "\xfb"
842# endif 854# endif
@@ -923,6 +935,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
923 IF_FEATURE_SEAMLESS_LZMA("a" ) 935 IF_FEATURE_SEAMLESS_LZMA("a" )
924 IF_FEATURE_TAR_FROM( "T:X:") 936 IF_FEATURE_TAR_FROM( "T:X:")
925 IF_FEATURE_SEAMLESS_GZ( "z" ) 937 IF_FEATURE_SEAMLESS_GZ( "z" )
938 IF_FEATURE_SEAMLESS_XZ( "J" )
926 IF_FEATURE_SEAMLESS_Z( "Z" ) 939 IF_FEATURE_SEAMLESS_Z( "Z" )
927 IF_FEATURE_TAR_NOPRESERVE_TIME("m") 940 IF_FEATURE_TAR_NOPRESERVE_TIME("m")
928 , &base_dir // -C dir 941 , &base_dir // -C dir
@@ -1052,7 +1065,9 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1052 zipMode = 2; 1065 zipMode = 2;
1053#endif 1066#endif
1054 /* NB: writeTarFile() closes tar_handle->src_fd */ 1067 /* NB: writeTarFile() closes tar_handle->src_fd */
1055 return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE, 1068 return writeTarFile(tar_handle->src_fd, verboseFlag,
1069 (opt & OPT_DEREFERENCE ? ACTION_FOLLOWLINKS : 0)
1070 | (opt & OPT_NORECURSION ? 0 : ACTION_RECURSE),
1056 tar_handle->accept, 1071 tar_handle->accept,
1057 tar_handle->reject, zipMode); 1072 tar_handle->reject, zipMode);
1058 } 1073 }
@@ -1073,6 +1088,9 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1073 if (opt & OPT_LZMA) 1088 if (opt & OPT_LZMA)
1074 USE_FOR_MMU(xformer = unpack_lzma_stream;) 1089 USE_FOR_MMU(xformer = unpack_lzma_stream;)
1075 USE_FOR_NOMMU(xformer_prog = "unlzma";) 1090 USE_FOR_NOMMU(xformer_prog = "unlzma";)
1091 if (opt & OPT_XZ)
1092 USE_FOR_MMU(xformer = unpack_xz_stream;)
1093 USE_FOR_NOMMU(xformer_prog = "unxz";)
1076 1094
1077 open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog); 1095 open_transformer_with_sig(tar_handle->src_fd, xformer, xformer_prog);
1078 /* Can't lseek over pipes */ 1096 /* Can't lseek over pipes */
diff --git a/archival/unzip.c b/archival/unzip.c
index 3c76cdafc..046027cc6 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -20,16 +20,16 @@
20 */ 20 */
21 21
22//usage:#define unzip_trivial_usage 22//usage:#define unzip_trivial_usage
23//usage: "[-opts[modifiers]] FILE[.zip] [LIST] [-x XLIST] [-d DIR]" 23//usage: "[-lnopq] FILE[.zip] [FILE]... [-x FILE...] [-d DIR]"
24//usage:#define unzip_full_usage "\n\n" 24//usage:#define unzip_full_usage "\n\n"
25//usage: "Extract files from ZIP archives\n" 25//usage: "Extract FILEs from ZIP archive\n"
26//usage: "\n -l List archive contents (with -q for short form)" 26//usage: "\n -l List contents (with -q for short form)"
27//usage: "\n -n Never overwrite files (default)" 27//usage: "\n -n Never overwrite files (default: ask)"
28//usage: "\n -o Overwrite" 28//usage: "\n -o Overwrite"
29//usage: "\n -p Send output to stdout" 29//usage: "\n -p Print to stdout"
30//usage: "\n -q Quiet" 30//usage: "\n -q Quiet"
31//usage: "\n -x XLST Exclude these files" 31//usage: "\n -x FILE Exclude FILEs"
32//usage: "\n -d DIR Extract files into DIR" 32//usage: "\n -d DIR Extract into DIR"
33 33
34#include "libbb.h" 34#include "libbb.h"
35#include "bb_archive.h" 35#include "bb_archive.h"
@@ -277,6 +277,7 @@ int unzip_main(int argc, char **argv)
277 IF_NOT_DESKTOP(const) smallint verbose = 0; 277 IF_NOT_DESKTOP(const) smallint verbose = 0;
278 smallint listing = 0; 278 smallint listing = 0;
279 smallint overwrite = O_PROMPT; 279 smallint overwrite = O_PROMPT;
280 smallint x_opt_seen;
280#if ENABLE_DESKTOP 281#if ENABLE_DESKTOP
281 uint32_t cdf_offset; 282 uint32_t cdf_offset;
282#endif 283#endif
@@ -290,7 +291,6 @@ int unzip_main(int argc, char **argv)
290 llist_t *zreject = NULL; 291 llist_t *zreject = NULL;
291 char *base_dir = NULL; 292 char *base_dir = NULL;
292 int i, opt; 293 int i, opt;
293 int opt_range = 0;
294 char key_buf[80]; 294 char key_buf[80];
295 struct stat stat_buf; 295 struct stat stat_buf;
296 296
@@ -335,81 +335,81 @@ int unzip_main(int argc, char **argv)
335 * 204372 1 file 335 * 204372 1 file
336 */ 336 */
337 337
338 x_opt_seen = 0;
338 /* '-' makes getopt return 1 for non-options */ 339 /* '-' makes getopt return 1 for non-options */
339 while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) { 340 while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) {
340 switch (opt_range) { 341 switch (opt) {
341 case 0: /* Options */ 342 case 'd': /* Extract to base directory */
342 switch (opt) { 343 base_dir = optarg;
343 case 'l': /* List */ 344 break;
344 listing = 1;
345 break;
346 345
347 case 'n': /* Never overwrite existing files */ 346 case 'l': /* List */
348 overwrite = O_NEVER; 347 listing = 1;
349 break; 348 break;
350 349
351 case 'o': /* Always overwrite existing files */ 350 case 'n': /* Never overwrite existing files */
352 overwrite = O_ALWAYS; 351 overwrite = O_NEVER;
353 break; 352 break;
354 353
355 case 'p': /* Extract files to stdout and fall through to set verbosity */ 354 case 'o': /* Always overwrite existing files */
356 dst_fd = STDOUT_FILENO; 355 overwrite = O_ALWAYS;
356 break;
357 357
358 case 'q': /* Be quiet */ 358 case 'p': /* Extract files to stdout and fall through to set verbosity */
359 quiet++; 359 dst_fd = STDOUT_FILENO;
360 break;
361 360
362 case 'v': /* Verbose list */ 361 case 'q': /* Be quiet */
363 IF_DESKTOP(verbose++;) 362 quiet++;
364 listing = 1; 363 break;
365 break;
366 364
367 case 1: /* The zip file */ 365 case 'v': /* Verbose list */
368 /* +5: space for ".zip" and NUL */ 366 IF_DESKTOP(verbose++;)
369 src_fn = xmalloc(strlen(optarg) + 5); 367 listing = 1;
370 strcpy(src_fn, optarg); 368 break;
371 opt_range++;
372 break;
373 369
374 default: 370 case 'x':
375 bb_show_usage(); 371 x_opt_seen = 1;
376 }
377 break; 372 break;
378 373
379 case 1: /* Include files */ 374 case 1:
380 if (opt == 1) { 375 if (!src_fn) {
376 /* The zip file */
377 /* +5: space for ".zip" and NUL */
378 src_fn = xmalloc(strlen(optarg) + 5);
379 strcpy(src_fn, optarg);
380 } else if (!x_opt_seen) {
381 /* Include files */
381 llist_add_to(&zaccept, optarg); 382 llist_add_to(&zaccept, optarg);
382 break; 383 } else {
383 } 384 /* Exclude files */
384 if (opt == 'd') {
385 base_dir = optarg;
386 opt_range += 2;
387 break;
388 }
389 if (opt == 'x') {
390 opt_range++;
391 break;
392 }
393 bb_show_usage();
394
395 case 2 : /* Exclude files */
396 if (opt == 1) {
397 llist_add_to(&zreject, optarg); 385 llist_add_to(&zreject, optarg);
398 break;
399 } 386 }
400 if (opt == 'd') { /* Extract to base directory */ 387 break;
401 base_dir = optarg;
402 opt_range++;
403 break;
404 }
405 /* fall through */
406 388
407 default: 389 default:
408 bb_show_usage(); 390 bb_show_usage();
409 } 391 }
410 } 392 }
411 393
412 if (src_fn == NULL) { 394#ifndef __GLIBC__
395 /*
396 * This code is needed for non-GNU getopt
397 * which doesn't understand "-" in option string.
398 * The -x option won't work properly in this case:
399 * "unzip a.zip q -x w e" will be interpreted as
400 * "unzip a.zip q w e -x" = "unzip a.zip q w e"
401 */
402 argv += optind;
403 if (argv[0]) {
404 /* +5: space for ".zip" and NUL */
405 src_fn = xmalloc(strlen(argv[0]) + 5);
406 strcpy(src_fn, argv[0]);
407 while (*++argv)
408 llist_add_to(&zaccept, *argv);
409 }
410#endif
411
412 if (!src_fn) {
413 bb_show_usage(); 413 bb_show_usage();
414 } 414 }
415 415
@@ -420,17 +420,20 @@ int unzip_main(int argc, char **argv)
420 if (overwrite == O_PROMPT) 420 if (overwrite == O_PROMPT)
421 overwrite = O_NEVER; 421 overwrite = O_NEVER;
422 } else { 422 } else {
423 static const char extn[][5] = {"", ".zip", ".ZIP"}; 423 static const char extn[][5] = { ".zip", ".ZIP" };
424 int orig_src_fn_len = strlen(src_fn); 424 char *ext = src_fn + strlen(src_fn);
425 int src_fd = -1; 425 int src_fd;
426 426
427 for (i = 0; (i < 3) && (src_fd == -1); i++) { 427 i = 0;
428 strcpy(src_fn + orig_src_fn_len, extn[i]); 428 for (;;) {
429 src_fd = open(src_fn, O_RDONLY); 429 src_fd = open(src_fn, O_RDONLY);
430 } 430 if (src_fd >= 0)
431 if (src_fd == -1) { 431 break;
432 src_fn[orig_src_fn_len] = '\0'; 432 if (++i > 2) {
433 bb_error_msg_and_die("can't open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn); 433 *ext = '\0';
434 bb_error_msg_and_die("can't open %s[.zip]", src_fn);
435 }
436 strcpy(ext, extn[i - 1]);
434 } 437 }
435 xmove_fd(src_fd, zip_fd); 438 xmove_fd(src_fd, zip_fd);
436 } 439 }
@@ -596,7 +599,7 @@ int unzip_main(int argc, char **argv)
596 printf(" creating: %s\n", dst_fn); 599 printf(" creating: %s\n", dst_fn);
597 } 600 }
598 unzip_create_leading_dirs(dst_fn); 601 unzip_create_leading_dirs(dst_fn);
599 if (bb_make_directory(dst_fn, dir_mode, 0)) { 602 if (bb_make_directory(dst_fn, dir_mode, FILEUTILS_IGNORE_CHMOD_ERR)) {
600 xfunc_die(); 603 xfunc_die();
601 } 604 }
602 } else { 605 } else {