diff options
author | Martin Matuska <mm@FreeBSD.org> | 2023-07-31 11:09:09 +0000 |
---|---|---|
committer | Martin Matuska <mm@FreeBSD.org> | 2023-07-31 11:09:09 +0000 |
commit | f8035ed8e51381281e5718a81233fa41b5b9e1d0 (patch) | |
tree | 8fecb925d415c6a0b2f0613f3db0072cb1a3cb37 | |
parent | 70968ea087e76e4f6101a83ccf2fa0b0bf686229 (diff) | |
download | src-f8035ed8e51381281e5718a81233fa41b5b9e1d0.tar.gz src-f8035ed8e51381281e5718a81233fa41b5b9e1d0.zip |
Update vendor/libarchive to libarchive/libarchive@27ca5119f
Changes to not yet connected unzip command only.
Obtained from: libarchive
Libarchive commit: 27ca5119f754d2d359a3cf4ac66c6672260a74d3
-rw-r--r-- | CMakeLists.txt | 7 | ||||
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | build/cmake/config.h.in | 6 | ||||
-rw-r--r-- | build/version | 2 | ||||
-rw-r--r-- | cat/cmdline.c | 12 | ||||
-rw-r--r-- | configure.ac | 14 | ||||
-rw-r--r-- | libarchive/archive.h | 4 | ||||
-rw-r--r-- | libarchive/archive_entry.h | 2 | ||||
-rw-r--r-- | unzip/CMakeLists.txt | 2 | ||||
-rw-r--r-- | unzip/bsdunzip.c | 66 | ||||
-rw-r--r-- | unzip/bsdunzip.h | 63 | ||||
-rw-r--r-- | unzip/cmdline.c | 250 | ||||
-rw-r--r-- | unzip/test/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unzip/test/test.h | 2 | ||||
-rw-r--r-- | unzip/test/test_version.c | 34 |
15 files changed, 425 insertions, 45 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6849ce40be2e..dc1fcc72a7fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ endif() # RelWithDebInfo : Release build with Debug Info # MinSizeRel : Release Min Size build IF(NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE) + SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE) ENDIF(NOT CMAKE_BUILD_TYPE) # Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the # value type is "UNINITIALIZED". @@ -65,6 +65,7 @@ SET(VERSION "${_major}.${_trimmed_minor}.${_trimmed_revision} SET(BSDCPIO_VERSION_STRING "${VERSION}") SET(BSDTAR_VERSION_STRING "${VERSION}") SET(BSDCAT_VERSION_STRING "${VERSION}") +SET(BSDUNZIP_VERSION_STRING "${VERSION}") SET(LIBARCHIVE_VERSION_NUMBER "${_version_number}") SET(LIBARCHIVE_VERSION_STRING "${VERSION}") @@ -1487,10 +1488,6 @@ CHECK_C_SOURCE_COMPILES( "#include <fcntl.h>\n#include <unistd.h>\nint main() {char buf[10]; return readlinkat(AT_FDCWD, \"\", buf, 0);}" HAVE_READLINKAT) -# Check for getopt uses optreset to reset -CHECK_SYMBOL_EXISTS(optreset "getopt.h" HAVE_GETOPT_OPTRESET) - - # To verify major(), we need to both include the header # of interest and verify that the result can be linked. # CHECK_FUNCTION_EXISTS doesn't accept a header argument, diff --git a/Makefile.am b/Makefile.am index e8b676443f11..83bbeee0b7e9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1451,7 +1451,9 @@ bsdcat_test_EXTRA_DIST= \ bsdunzip_SOURCES= \ unzip/bsdunzip.c \ + unzip/bsdunzip.h \ unzip/bsdunzip_platform.h \ + unzip/cmdline.c \ unzip/la_getline.c \ unzip/la_queue.h @@ -1489,7 +1491,7 @@ bsdunzip_programs= endif # -# bsdcat_test +# bsdunzip_test # bsdunzip_test_SOURCES= \ @@ -1510,6 +1512,7 @@ bsdunzip_test_SOURCES= \ unzip/test/test_q.c \ unzip/test/test_t.c \ unzip/test/test_t_bad.c \ + unzip/test/test_version.c \ unzip/test/test_x.c \ unzip/test/test_Z1.c \ unzip/test/test_P_encryption.c diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index daa5e387ae70..08a3196f2a6d 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -342,6 +342,9 @@ typedef uint64_t uintmax_t; /* Version number of bsdcat */ #cmakedefine BSDCAT_VERSION_STRING "@BSDCAT_VERSION_STRING@" +/* Version number of bsdunzip */ +#cmakedefine BSDUNZIP_VERSION_STRING "@BSDUNZIP_VERSION_STRING@" + /* Define to 1 if you have the `acl_create_entry' function. */ #cmakedefine HAVE_ACL_CREATE_ENTRY 1 @@ -645,9 +648,6 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `getline' function. */ #cmakedefine HAVE_GETLINE 1 -/* Define to 1 if platform uses `optreset` to reset `getopt` */ -#cmakedefine HAVE_GETOPT_OPTRESET 1 - /* Define to 1 if you have the `getpid' function. */ #cmakedefine HAVE_GETPID 1 diff --git a/build/version b/build/version index d24f5b31e235..414ae6d4894b 100644 --- a/build/version +++ b/build/version @@ -1 +1 @@ -3007001 +3007002 diff --git a/cat/cmdline.c b/cat/cmdline.c index cae19beb7d4c..3c4b7a8c4b9e 100644 --- a/cat/cmdline.c +++ b/cat/cmdline.c @@ -24,7 +24,7 @@ */ /* - * Command line parser for tar. + * Command line parser for bsdcat. */ #include "bsdcat_platform.h" @@ -44,12 +44,12 @@ __FBSDID("$FreeBSD$"); #include "err.h" /* - * Short options for tar. Please keep this sorted. + * Short options for bsdcat. Please keep this sorted. */ static const char *short_options = "h"; /* - * Long options for tar. Please keep this list sorted. + * Long options for bsdcat. Please keep this list sorted. * * The symbolic names for options that lack a short equivalent are * defined in bsdcat.h. Also note that so far I've found no need @@ -61,7 +61,7 @@ static const struct bsdcat_option { const char *name; int required; /* 1 if this option requires an argument. */ int equivalent; /* Equivalent short option. */ -} tar_longopts[] = { +} bsdcat_longopts[] = { { "help", 0, 'h' }, { "version", 0, OPTION_VERSION }, { NULL, 0, 0 } @@ -90,7 +90,7 @@ static const struct bsdcat_option { * -W long options: There's an obscure GNU convention (only rarely * supported even there) that allows "-W option=argument" as an * alternative way to support long options. This was supported in - * early bsdcat as a way to access long options on platforms that did + * early bsdtar as a way to access long options on platforms that did * not support getopt_long() and is preserved here for backwards * compatibility. (Of course, if I'd started with a custom * command-line parser from the beginning, I would have had normal @@ -223,7 +223,7 @@ bsdcat_getopt(struct bsdcat *bsdcat) } /* Search the table for an unambiguous match. */ - for (popt = tar_longopts; popt->name != NULL; popt++) { + for (popt = bsdcat_longopts; popt->name != NULL; popt++) { /* Short-circuit if first chars don't match. */ if (popt->name[0] != bsdcat->getopt_word[0]) continue; diff --git a/configure.ac b/configure.ac index 1bb446ba4d9b..4a4bdd628639 100644 --- a/configure.ac +++ b/configure.ac @@ -4,13 +4,14 @@ dnl First, define all of the version numbers up front. dnl In particular, this allows the version macro to be used in AC_INIT dnl These first two version numbers are updated automatically on each release. -m4_define([LIBARCHIVE_VERSION_S],[3.7.1]) -m4_define([LIBARCHIVE_VERSION_N],[3007001]) +m4_define([LIBARCHIVE_VERSION_S],[3.7.2dev]) +m4_define([LIBARCHIVE_VERSION_N],[3007002]) dnl bsdtar and bsdcpio versioning tracks libarchive m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S()) m4_define([BSDCPIO_VERSION_S],LIBARCHIVE_VERSION_S()) m4_define([BSDCAT_VERSION_S],LIBARCHIVE_VERSION_S()) +m4_define([BSDUNZIP_VERSION_S],LIBARCHIVE_VERSION_S()) AC_PREREQ([2.71]) @@ -59,6 +60,8 @@ AC_DEFINE([BSDTAR_VERSION_STRING],"BSDTAR_VERSION_S()", [Version number of bsdtar]) AC_DEFINE([BSDCAT_VERSION_STRING],"BSDTAR_VERSION_S()", [Version number of bsdcat]) +AC_DEFINE([BSDUNZIP_VERSION_STRING],"BSDUNZIP_VERSION_S()", + [Version number of bsdunzip]) # The shell variables here must be the same as the AC_SUBST() variables # below, but the shell variable names apparently cannot be the same as @@ -66,6 +69,7 @@ AC_DEFINE([BSDCAT_VERSION_STRING],"BSDTAR_VERSION_S()", BSDCPIO_VERSION_STRING=BSDCPIO_VERSION_S() BSDTAR_VERSION_STRING=BSDTAR_VERSION_S() BSDCAT_VERSION_STRING=BSDCAT_VERSION_S() +BSDUNZIP_VERSION_STRING=BSDUNZIP_VERSION_S() LIBARCHIVE_VERSION_STRING=LIBARCHIVE_VERSION_S() LIBARCHIVE_VERSION_NUMBER=LIBARCHIVE_VERSION_N() @@ -76,6 +80,7 @@ AC_SUBST(ARCHIVE_LIBTOOL_VERSION) AC_SUBST(BSDCPIO_VERSION_STRING) AC_SUBST(BSDTAR_VERSION_STRING) AC_SUBST(BSDCAT_VERSION_STRING) +AC_SUBST(BSDUNZIP_VERSION_STRING) AC_SUBST(LIBARCHIVE_VERSION_STRING) AC_SUBST(LIBARCHIVE_VERSION_NUMBER) @@ -832,11 +837,6 @@ AC_CHECK_MEMBER(struct dirent.d_namlen,,, #endif ]) -AC_CHECK_DECL([optreset], - [AC_DEFINE(HAVE_GETOPT_OPTRESET, 1, [Platform uses optreset to reset getopt])], - [], - [#include <getopt.h>]) - # Check for Extended Attributes support AC_ARG_ENABLE([xattr], AS_HELP_STRING([--disable-xattr], diff --git a/libarchive/archive.h b/libarchive/archive.h index 618b1a176098..854fefdd64e0 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -36,7 +36,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3007001 +#define ARCHIVE_VERSION_NUMBER 3007002 #include <sys/stat.h> #include <stddef.h> /* for wchar_t */ @@ -157,7 +157,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.7.1" +#define ARCHIVE_VERSION_ONLY_STRING "3.7.2dev" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index c15460b96538..e4c0ab344eba 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -30,7 +30,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3007001 +#define ARCHIVE_VERSION_NUMBER 3007002 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/unzip/CMakeLists.txt b/unzip/CMakeLists.txt index 0e3de35231df..150eb2c6b05d 100644 --- a/unzip/CMakeLists.txt +++ b/unzip/CMakeLists.txt @@ -7,7 +7,9 @@ IF(ENABLE_UNZIP) SET(bsdunzip_SOURCES bsdunzip.c + bsdunzip.h bsdunzip_platform.h + cmdline.c la_getline.c la_queue.h ../libarchive_fe/err.c diff --git a/unzip/bsdunzip.c b/unzip/bsdunzip.c index 0b6506a18adc..b8f6ff4bbf95 100644 --- a/unzip/bsdunzip.c +++ b/unzip/bsdunzip.c @@ -79,8 +79,7 @@ #endif #endif -#include <archive.h> -#include <archive_entry.h> +#include "bsdunzip.h" #include "passphrase.h" #include "err.h" @@ -90,19 +89,20 @@ static int C_opt; /* match case-insensitively */ static int c_opt; /* extract to stdout */ static const char *d_arg; /* directory */ static int f_opt; /* update existing files only */ -static char *O_arg; /* encoding */ +static const char *O_arg; /* encoding */ static int j_opt; /* junk directories */ static int L_opt; /* lowercase names */ static int n_opt; /* never overwrite */ static int o_opt; /* always overwrite */ static int p_opt; /* extract to stdout, quiet */ -static char *P_arg; /* passphrase */ +static const char *P_arg; /* passphrase */ static int q_opt; /* quiet */ static int t_opt; /* test */ static int u_opt; /* update */ static int v_opt; /* verbose/list */ static const char *y_str = ""; /* 4 digit year */ static int Z1_opt; /* zipinfo mode list files only */ +static int version_opt; /* version string */ /* debug flag */ static int unzip_debug; @@ -113,6 +113,8 @@ static int zipinfo_mode; /* running on tty? */ static int tty; +int bsdunzip_optind; + /* convenience macro */ /* XXX should differentiate between ARCHIVE_{WARN,FAIL,RETRY} */ #define ac(call) \ @@ -1089,20 +1091,30 @@ usage(void) exit(EXIT_FAILURE); } +static void +version(void) +{ + printf("bsdunzip %s - %s \n", + BSDUNZIP_VERSION_STRING, + archive_version_details()); + exit(0); +} + static int getopts(int argc, char *argv[]) { + struct bsdunzip *bsdunzip, bsdunzip_storage; int opt; + bsdunzip_optind = 1; - optind = 1; -#ifdef HAVE_GETOPT_OPTRESET - optreset = 1; -#endif - while ((opt = getopt(argc, argv, "aCcd:fI:jLlnO:opP:qtuvx:yZ1")) != -1) + bsdunzip = &bsdunzip_storage; + memset(bsdunzip, 0, sizeof(*bsdunzip)); + + bsdunzip->argv = argv; + bsdunzip->argc = argc; + + while ((opt = bsdunzip_getopt(bsdunzip)) != -1) { switch (opt) { - case '1': - Z1_opt = 1; - break; case 'a': a_opt = 1; break; @@ -1113,14 +1125,14 @@ getopts(int argc, char *argv[]) c_opt = 1; break; case 'd': - d_arg = optarg; + d_arg = bsdunzip->argument; break; case 'f': f_opt = 1; break; case 'I': case 'O': - O_arg = optarg; + O_arg = bsdunzip->argument; break; case 'j': j_opt = 1; @@ -1143,7 +1155,7 @@ getopts(int argc, char *argv[]) p_opt = 1; break; case 'P': - P_arg = optarg; + P_arg = bsdunzip->argument; break; case 'q': q_opt = 1; @@ -1158,19 +1170,30 @@ getopts(int argc, char *argv[]) v_opt = 2; break; case 'x': - add_pattern(&exclude, optarg); + add_pattern(&exclude, bsdunzip->argument); break; case 'y': y_str = " "; break; case 'Z': zipinfo_mode = 1; + if (bsdunzip->argument != NULL && + strcmp(bsdunzip->argument, "1") == 0) { + Z1_opt = 1; + } + break; + case OPTION_VERSION: + version_opt = 1; + break; + case OPTION_NONE: break; default: usage(); } - - return (optind); + if (opt == OPTION_NONE) + break; + } + return (bsdunzip_optind); } int @@ -1179,6 +1202,8 @@ main(int argc, char *argv[]) const char *zipfile; int nopts; + lafe_setprogname(*argv, "bsdunzip"); + if (isatty(STDOUT_FILENO)) tty = 1; @@ -1199,6 +1224,11 @@ main(int argc, char *argv[]) */ nopts = getopts(argc, argv); + if (version_opt == 1) { + version(); + exit(EXIT_SUCCESS); + } + /* * When more of the zipinfo mode options are implemented, this * will need to change. diff --git a/unzip/bsdunzip.h b/unzip/bsdunzip.h new file mode 100644 index 000000000000..12b65cefb466 --- /dev/null +++ b/unzip/bsdunzip.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2023, Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BSDUNZIP_H_INCLUDED +#define BSDUNZIP_H_INCLUDED + +#if defined(PLATFORM_CONFIG_H) +/* Use hand-built config.h in environments that need it. */ +#include PLATFORM_CONFIG_H +#else +/* Not having a config.h of some sort is a serious problem. */ +#include "config.h" +#endif + +#include <archive.h> +#include <archive_entry.h> + +struct bsdunzip { + /* Option parser state */ + int getopt_state; + char *getopt_word; + + /* Miscellaneous state information */ + int argc; + char **argv; + const char *argument; +}; + +struct bsdunzip_getopt_ret { + int index; + int opt; +}; + +enum { + OPTION_NONE, + OPTION_VERSION +}; + +int bsdunzip_getopt(struct bsdunzip *); + +#endif diff --git a/unzip/cmdline.c b/unzip/cmdline.c new file mode 100644 index 000000000000..95d4f99b8242 --- /dev/null +++ b/unzip/cmdline.c @@ -0,0 +1,250 @@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Command line parser for bsdunzip. + */ + +#include "bsdunzip_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include "bsdunzip.h" +#include "err.h" + +extern int bsdunzip_optind; + +/* + * Short options for bsdunzip. Please keep this sorted. + */ +static const char *short_options + = "aCcd:fI:jLlnO:opP:qtuvx:yZ:"; + +/* + * Long options for bsdunzip. Please keep this list sorted. + * + * The symbolic names for options that lack a short equivalent are + * defined in bsdunzip.h. Also note that so far I've found no need + * to support optional arguments to long options. That would be + * a small change to the code below. + */ + +static const struct bsdunzip_option { + const char *name; + int required; /* 1 if this option requires an argument. */ + int equivalent; /* Equivalent short option. */ +} bsdunzip_longopts[] = { + { "version", 0, OPTION_VERSION }, + { NULL, 0, 0 } +}; + +/* + * This getopt implementation has two key features that common + * getopt_long() implementations lack. Apart from those, it's a + * straightforward option parser, considerably simplified by not + * needing to support the wealth of exotic getopt_long() features. It + * has, of course, been shamelessly tailored for bsdunzip. (If you're + * looking for a generic getopt_long() implementation for your + * project, I recommend Gregory Pietsch's public domain getopt_long() + * implementation.) The two additional features are: + */ + +int +bsdunzip_getopt(struct bsdunzip *bsdunzip) +{ + enum { state_start = 0, state_next_word, state_short, state_long }; + + const struct bsdunzip_option *popt, *match = NULL, *match2 = NULL; + const char *p, *long_prefix = "--"; + size_t optlength; + int opt = OPTION_NONE; + int required = 0; + + bsdunzip->argument = NULL; + + /* First time through, initialize everything. */ + if (bsdunzip->getopt_state == state_start) { + /* Skip program name. */ + ++bsdunzip->argv; + --bsdunzip->argc; + if (*bsdunzip->argv == NULL) + return (-1); + bsdunzip->getopt_state = state_next_word; + } + + /* + * We're ready to look at the next word in argv. + */ + if (bsdunzip->getopt_state == state_next_word) { + /* No more arguments, so no more options. */ + if (bsdunzip->argv[0] == NULL) + return (-1); + /* Doesn't start with '-', so no more options. */ + if (bsdunzip->argv[0][0] != '-') + return (-1); + /* "--" marks end of options; consume it and return. */ + if (strcmp(bsdunzip->argv[0], "--") == 0) { + ++bsdunzip->argv; + --bsdunzip->argc; + return (-1); + } + /* Get next word for parsing. */ + bsdunzip->getopt_word = *bsdunzip->argv++; + --bsdunzip->argc; + bsdunzip_optind++; + if (bsdunzip->getopt_word[1] == '-') { + /* Set up long option parser. */ + bsdunzip->getopt_state = state_long; + bsdunzip->getopt_word += 2; /* Skip leading '--' */ + } else { + /* Set up short option parser. */ + bsdunzip->getopt_state = state_short; + ++bsdunzip->getopt_word; /* Skip leading '-' */ + } + } + + /* + * We're parsing a group of POSIX-style single-character options. + */ + if (bsdunzip->getopt_state == state_short) { + /* Peel next option off of a group of short options. */ + opt = *bsdunzip->getopt_word++; + if (opt == '\0') { + /* End of this group; recurse to get next option. */ + bsdunzip->getopt_state = state_next_word; + return bsdunzip_getopt(bsdunzip); + } + + /* Does this option take an argument? */ + p = strchr(short_options, opt); + if (p == NULL) + return ('?'); + if (p[1] == ':') + required = 1; + + /* If it takes an argument, parse that. */ + if (required) { + /* If arg is run-in, bsdunzip->getopt_word already points to it. */ + if (bsdunzip->getopt_word[0] == '\0') { + /* Otherwise, pick up the next word. */ + bsdunzip->getopt_word = *bsdunzip->argv; + if (bsdunzip->getopt_word == NULL) { + lafe_warnc(0, + "Option -%c requires an argument", + opt); + return ('?'); + } + ++bsdunzip->argv; + --bsdunzip->argc; + bsdunzip_optind++; + } + bsdunzip->getopt_state = state_next_word; + bsdunzip->argument = bsdunzip->getopt_word; + } + } + + /* We're reading a long option */ + if (bsdunzip->getopt_state == state_long) { + /* After this long option, we'll be starting a new word. */ + bsdunzip->getopt_state = state_next_word; + + /* Option name ends at '=' if there is one. */ + p = strchr(bsdunzip->getopt_word, '='); + if (p != NULL) { + optlength = (size_t)(p - bsdunzip->getopt_word); + bsdunzip->argument = (char *)(uintptr_t)(p + 1); + } else { + optlength = strlen(bsdunzip->getopt_word); + } + + /* Search the table for an unambiguous match. */ + for (popt = bsdunzip_longopts; popt->name != NULL; popt++) { + /* Short-circuit if first chars don't match. */ + if (popt->name[0] != bsdunzip->getopt_word[0]) + continue; + /* If option is a prefix of name in table, record it.*/ + if (strncmp(bsdunzip->getopt_word, popt->name, optlength) == 0) { + match2 = match; /* Record up to two matches. */ + match = popt; + /* If it's an exact match, we're done. */ + if (strlen(popt->name) == optlength) { + match2 = NULL; /* Forget the others. */ + break; + } + } + } + + /* Fail if there wasn't a unique match. */ + if (match == NULL) { + lafe_warnc(0, + "Option %s%s is not supported", + long_prefix, bsdunzip->getopt_word); + return ('?'); + } + if (match2 != NULL) { + lafe_warnc(0, + "Ambiguous option %s%s (matches --%s and --%s)", + long_prefix, bsdunzip->getopt_word, match->name, match2->name); + return ('?'); + } + + /* We've found a unique match; does it need an argument? */ + if (match->required) { + /* Argument required: get next word if necessary. */ + if (bsdunzip->argument == NULL) { + bsdunzip->argument = *bsdunzip->argv; + if (bsdunzip->argument == NULL) { + lafe_warnc(0, + "Option %s%s requires an argument", + long_prefix, match->name); + return ('?'); + } + ++bsdunzip->argv; + --bsdunzip->argc; + bsdunzip_optind++; + } + } else { + /* Argument forbidden: fail if there is one. */ + if (bsdunzip->argument != NULL) { + lafe_warnc(0, + "Option %s%s does not allow an argument", + long_prefix, match->name); + return ('?'); + } + } + return (match->equivalent); + } + + return (opt); +} diff --git a/unzip/test/CMakeLists.txt b/unzip/test/CMakeLists.txt index bdb3445954f1..20e730a9cdca 100644 --- a/unzip/test/CMakeLists.txt +++ b/unzip/test/CMakeLists.txt @@ -23,6 +23,7 @@ IF(ENABLE_UNZIP AND ENABLE_TEST) test_q.c test_t.c test_t_bad.c + test_version.c test_x.c test_Z1.c test_P_encryption.c diff --git a/unzip/test/test.h b/unzip/test/test.h index 8da017f68e16..ba876afd8e24 100644 --- a/unzip/test/test.h +++ b/unzip/test/test.h @@ -35,6 +35,6 @@ #undef EXTRA_DUMP /* How to dump extra data */ #undef EXTRA_ERRNO /* How to dump errno */ /* How to generate extra version info. */ -#define EXTRA_VERSION (systemf("%s -v", testprog) ? "" : "") +#define EXTRA_VERSION (systemf("%s --version", testprog) ? "" : "") #include "test_common.h" diff --git a/unzip/test/test_version.c b/unzip/test/test_version.c new file mode 100644 index 000000000000..efa797982d57 --- /dev/null +++ b/unzip/test/test_version.c @@ -0,0 +1,34 @@ +/*- + * Copyright (c) 2003-2017 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Test that --version option works and generates reasonable output. + */ + +DEFINE_TEST(test_version) +{ + assertVersion(testprog, "bsdunzip"); +} |