The branch stable/13 has been updated by mm:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=0db84579ce2024b674062d961f1e3e26a253ffdd

commit 0db84579ce2024b674062d961f1e3e26a253ffdd
Author:     Martin Matuska <m...@freebsd.org>
AuthorDate: 2023-07-31 11:13:30 +0000
Commit:     Martin Matuska <m...@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");
+}

Reply via email to