git: 0db84579ce20 - stable/13 - libarchive: merge from vendor branch
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 04 May 2024 12:37:36 UTC
The branch stable/13 has been updated by mm: URL: https://cgit.FreeBSD.org/src/commit/?id=0db84579ce2024b674062d961f1e3e26a253ffdd commit 0db84579ce2024b674062d961f1e3e26a253ffdd Author: Martin Matuska <mm@FreeBSD.org> AuthorDate: 2023-07-31 11:13:30 +0000 Commit: Martin Matuska <mm@FreeBSD.org> CommitDate: 2024-05-04 11:53:07 +0000 libarchive: merge from vendor branch Changes to not yet connected unzip only. (cherry picked from commit d91bfe0fb7faab2e1f0b8e160b0cf59afb8576c4) --- contrib/libarchive/cat/cmdline.c | 12 +- contrib/libarchive/unzip/bsdunzip.c | 66 +++++-- contrib/libarchive/unzip/bsdunzip.h | 63 +++++++ contrib/libarchive/unzip/cmdline.c | 250 +++++++++++++++++++++++++++ contrib/libarchive/unzip/test/test.h | 2 +- contrib/libarchive/unzip/test/test_version.c | 34 ++++ 6 files changed, 402 insertions(+), 25 deletions(-) diff --git a/contrib/libarchive/cat/cmdline.c b/contrib/libarchive/cat/cmdline.c index cae19beb7d4c..3c4b7a8c4b9e 100644 --- a/contrib/libarchive/cat/cmdline.c +++ b/contrib/libarchive/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/contrib/libarchive/unzip/bsdunzip.c b/contrib/libarchive/unzip/bsdunzip.c index 0b6506a18adc..b8f6ff4bbf95 100644 --- a/contrib/libarchive/unzip/bsdunzip.c +++ b/contrib/libarchive/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/contrib/libarchive/unzip/bsdunzip.h b/contrib/libarchive/unzip/bsdunzip.h new file mode 100644 index 000000000000..12b65cefb466 --- /dev/null +++ b/contrib/libarchive/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/contrib/libarchive/unzip/cmdline.c b/contrib/libarchive/unzip/cmdline.c new file mode 100644 index 000000000000..95d4f99b8242 --- /dev/null +++ b/contrib/libarchive/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/contrib/libarchive/unzip/test/test.h b/contrib/libarchive/unzip/test/test.h index 8da017f68e16..ba876afd8e24 100644 --- a/contrib/libarchive/unzip/test/test.h +++ b/contrib/libarchive/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/contrib/libarchive/unzip/test/test_version.c b/contrib/libarchive/unzip/test/test_version.c new file mode 100644 index 000000000000..efa797982d57 --- /dev/null +++ b/contrib/libarchive/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"); +}