The branch main has been updated by mm:

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

commit b5a3a89c50671a1ad29e7c43fe15e7b16feac239
Author:     Martin Matuska <m...@freebsd.org>
AuthorDate: 2023-07-31 11:54:58 +0000
Commit:     Martin Matuska <m...@freebsd.org>
CommitDate: 2023-08-04 10:45:41 +0000

    unzip: swtich to bsdunzip from libarchive
    
    Unzip from FreeBSD has been ported to libarchive.
    Change usr.bin/unzip to use bsdunzip from libarchive.
    
    Differential Revision:  https://reviews.freebsd.org/D41239
    PR:                     272845 (exp-run)
    MFC after:              1 month
---
 etc/mtree/BSD.tests.dist               |    2 +
 lib/libarchive/config_freebsd.h        |    5 +
 usr.bin/unzip/Makefile                 |   28 +-
 usr.bin/unzip/tests/Makefile           |   74 +++
 usr.bin/unzip/tests/Makefile.depend    |   24 +
 usr.bin/unzip/tests/functional_test.sh |   56 ++
 usr.bin/unzip/unzip.1                  |  207 ------
 usr.bin/unzip/unzip.c                  | 1141 --------------------------------
 8 files changed, 188 insertions(+), 1349 deletions(-)

diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
index 9312a6c2980b..943924c56bae 100644
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -1134,6 +1134,8 @@
         ..
         uniq
         ..
+        unzip
+        ..
         vmstat
         ..
         wc
diff --git a/lib/libarchive/config_freebsd.h b/lib/libarchive/config_freebsd.h
index 408bd1f12dbc..5211513610f3 100644
--- a/lib/libarchive/config_freebsd.h
+++ b/lib/libarchive/config_freebsd.h
@@ -113,6 +113,8 @@
 #define HAVE_FCNTL 1
 #define HAVE_FCNTL_H 1
 #define HAVE_FDOPENDIR 1
+#define HAVE_FNMATCH 1
+#define HAVE_FNMATCH_H 1
 #define HAVE_FORK 1
 #define HAVE_FSEEKO 1
 #define HAVE_FSTAT 1
@@ -125,6 +127,8 @@
 #define HAVE_GETEUID 1
 #define HAVE_GETGRGID_R 1
 #define HAVE_GETGRNAM_R 1
+#define HAVE_GETLINE 1
+#define HAVE_GETOPT_OPTRESET 1
 #define HAVE_GETPID 1
 #define HAVE_GETPWNAM_R 1
 #define HAVE_GETPWUID_R 1
@@ -205,6 +209,7 @@
 #define HAVE_SYS_MOUNT_H 1
 #define HAVE_SYS_PARAM_H 1
 #define HAVE_SYS_POLL_H 1
+#define HAVE_SYS_QUEUE_H 1
 #define HAVE_SYS_SELECT_H 1
 #define HAVE_SYS_STATVFS_H 1
 #define HAVE_SYS_STAT_H 1
diff --git a/usr.bin/unzip/Makefile b/usr.bin/unzip/Makefile
index c1713e95222b..e0b5ac74246d 100644
--- a/usr.bin/unzip/Makefile
+++ b/usr.bin/unzip/Makefile
@@ -1,6 +1,32 @@
 # $FreeBSD$
 
-PROG = unzip
+.include <src.opts.mk>
+
+_LIBARCHIVEDIR=        ${SRCTOP}/contrib/libarchive
+_LIBARCHIVECONFDIR=    ${SRCTOP}/lib/libarchive
+
+PROG=  bsdunzip
+
+BSDUNZIP_VERSION_STRING!= sed -n 
'/define.*ARCHIVE_VERSION_ONLY_STRING/{s,[^0-9.],,gp;q;}' \
+                       ${_LIBARCHIVEDIR}/libarchive/archive.h
+
+.PATH: ${_LIBARCHIVEDIR}/unzip
+SRCS=  bsdunzip.c
+
+.PATH: ${_LIBARCHIVEDIR}/libarchive_fe
+SRCS+= cmdline.c err.c passphrase.c
+
+CFLAGS+= -DBSDUNZIP_VERSION_STRING=\"${BSDUNZIP_VERSION_STRING}\"
+CFLAGS+= -DPLATFORM_CONFIG_H=\"${_LIBARCHIVECONFDIR}/config_freebsd.h\"
+CFLAGS+= -I${_LIBARCHIVEDIR}/unzip -I${_LIBARCHIVEDIR}/libarchive_fe
+
 LIBADD=        archive
 
+SYMLINKS=bsdunzip ${BINDIR}/unzip
+MLINKS= bsdunzip.1 unzip.1
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
 .include <bsd.prog.mk>
+# DO NOT DELETE
diff --git a/usr.bin/unzip/tests/Makefile b/usr.bin/unzip/tests/Makefile
new file mode 100644
index 000000000000..577c0936a151
--- /dev/null
+++ b/usr.bin/unzip/tests/Makefile
@@ -0,0 +1,74 @@
+# $FreeBSD$
+
+PACKAGE=       tests
+
+_LIBARCHIVEDIR=        ${SRCTOP}/contrib/libarchive
+
+ATF_TESTS_SH+= functional_test
+
+BINDIR=                ${TESTSDIR}
+
+PROGS+=                bsdunzip_test
+
+CFLAGS+=       
-DPLATFORM_CONFIG_H=\"${SRCTOP}/lib/libarchive/config_freebsd.h\"
+CFLAGS+=       -I${SRCTOP}/lib/libarchive -I${.OBJDIR}
+
+CFLAGS+=       -I${.OBJDIR}
+CFLAGS+=       -I${_LIBARCHIVEDIR}/unzip -I${_LIBARCHIVEDIR}/unzip/test
+CFLAGS+=       -I${_LIBARCHIVEDIR}/libarchive
+CFLAGS+=       -I${_LIBARCHIVEDIR}/libarchive_fe -I${_LIBARCHIVEDIR}/test_utils
+
+# Uncomment to link against dmalloc
+#LDADD+= -L/usr/local/lib -ldmalloc
+#CFLAGS+= -I/usr/local/include -DUSE_DMALLOC
+
+CFLAGS.test_utils.c+=  -Wno-cast-align
+
+.PATH: ${_LIBARCHIVEDIR}/libarchive_fe
+UNZIP_SRCS+= err.c
+
+.PATH: ${_LIBARCHIVEDIR}/unzip/test
+TESTS_SRCS=    \
+       test_0.c                                \
+       test_C.c                                \
+       test_L.c                                \
+       test_P_encryption.c                     \
+       test_Z1.c                               \
+       test_basic.c                            \
+       test_d.c                                \
+       test_glob.c                             \
+       test_j.c                                \
+       test_n.c                                \
+       test_not_exist.c                        \
+       test_o.c                                \
+       test_p.c                                \
+       test_q.c                                \
+       test_singlefile.c                       \
+       test_t.c                                \
+       test_t_bad.c                            \
+       test_version.c                          \
+       test_x.c
+
+SRCS.bsdunzip_test= list.h                     \
+       ${UNZIP_SRCS}                           \
+       ${TESTS_SRCS}
+
+.PATH: ${_LIBARCHIVEDIR}/test_utils
+SRCS.bsdunzip_test+=   test_main.c             \
+                       test_utils.c
+
+LIBADD.bsdunzip_test=  archive
+
+list.h: ${TESTS_SRCS} Makefile
+       @(cd ${_LIBARCHIVEDIR}/unzip/test && \
+       grep -h DEFINE_TEST ${.ALLSRC:N*Makefile}) > ${.TARGET}.tmp
+       @mv ${.TARGET}.tmp ${.TARGET}
+
+CLEANFILES+=   list.h list.h.tmp
+
+${PACKAGE}FILES+= test_basic.zip.uu
+${PACKAGE}FILES+= test_encrypted.zip.uu
+${PACKAGE}FILES+= test_singlefile.zip.uu
+${PACKAGE}FILES+= test_t_bad.zip.uu
+
+.include <bsd.test.mk>
diff --git a/usr.bin/unzip/tests/Makefile.depend 
b/usr.bin/unzip/tests/Makefile.depend
new file mode 100644
index 000000000000..138ae4120671
--- /dev/null
+++ b/usr.bin/unzip/tests/Makefile.depend
@@ -0,0 +1,24 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+       gnu/lib/csu \
+       include \
+       include/xlocale \
+       lib/${CSU_DIR} \
+       lib/libarchive \
+       lib/libbz2 \
+       lib/libc \
+       lib/libcompiler_rt \
+       lib/libexpat \
+       lib/liblzma \
+       lib/libthr \
+       lib/libz \
+       secure/lib/libcrypto \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.bin/unzip/tests/functional_test.sh 
b/usr.bin/unzip/tests/functional_test.sh
new file mode 100755
index 000000000000..1b39e057d538
--- /dev/null
+++ b/usr.bin/unzip/tests/functional_test.sh
@@ -0,0 +1,56 @@
+#
+# Copyright 2015 EMC Corp.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "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 COPYRIGHT
+# OWNER OR CONTRIBUTORS 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.
+#
+# $FreeBSD$
+
+SRCDIR=$(atf_get_srcdir)
+TESTER="${SRCDIR}/bsdunzip_test"
+export BSDUNZIP=$(which bsdunzip)
+
+check()
+{
+       local testcase=${1}; shift
+
+       # For some odd reason /bin/sh spuriously writes
+       # "write error on stdout" with some of the testcases
+       #
+       # Probably an issue with how they're written as it calls system(3) to
+       # clean up directories..
+       atf_check -e ignore -o ignore -s exit:0 ${TESTER} -d -r "${SRCDIR}" -v 
"${testcase}"
+}
+
+atf_init_test_cases()
+{
+       # Redirect stderr to stdout for the usage message because if you don't
+       # kyua list/kyua test will break:
+       # https://github.com/jmmv/kyua/issues/149
+       testcases=$(${TESTER} -h 2>&1 | awk 'p != 0 && $1 ~ /^[0-9]+:/ { print 
$NF } /Available tests:/ { p=1 }')
+       for testcase in ${testcases}; do
+               atf_test_case ${testcase}
+               eval "${testcase}_body() { check ${testcase}; }"
+               atf_add_test_case ${testcase}
+       done
+}
diff --git a/usr.bin/unzip/unzip.1 b/usr.bin/unzip/unzip.1
deleted file mode 100644
index fd826fbe1c05..000000000000
--- a/usr.bin/unzip/unzip.1
+++ /dev/null
@@ -1,207 +0,0 @@
-.\"-
-.\" Copyright (c) 2007-2008 Dag-Erling Smørgrav
-.\" 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd June 27, 2023
-.Dt UNZIP 1
-.Os
-.Sh NAME
-.Nm unzip
-.Nd extract files from a ZIP archive
-.Sh SYNOPSIS
-.Nm
-.Op Fl aCcfjLlnopqtuvy
-.Op { Fl O | Fl I No } Ar encoding
-.Op Fl d Ar dir
-.Op Fl x Ar pattern
-.Op Fl P Ar password
-.Ar zipfile
-.Op Ar member ...
-.Sh DESCRIPTION
-.\" ...
-The following options are available:
-.Bl -tag -width Fl
-.It Fl a
-When extracting a text file, convert DOS-style line endings to
-Unix-style line endings.
-.It Fl C
-Match file names case-insensitively.
-.It Fl c
-Extract to stdout/screen.
-When extracting files from the zipfile, they are written to stdout.
-This is similar to
-.Fl p ,
-but does not suppress normal output.
-.It Fl d Ar dir
-Extract files into the specified directory rather than the current
-directory.
-.It Fl f
-Update existing.
-Extract only files from the zipfile if a file with the same name
-already exists on disk and is older than the former.
-Otherwise, the file is silently skipped.
-.It Fl I Ar encoding
-.It Fl O Ar encoding
-Convert filenames from the specified encoding.
-.It Fl j
-Ignore directories stored in the zipfile; instead, extract all files
-directly into the extraction directory.
-.It Fl L
-Convert the names of the extracted files and directories to lowercase.
-.It Fl l
-List, rather than extract, the contents of the zipfile.
-.It Fl n
-No overwrite.
-When extracting a file from the zipfile, if a file with the same name
-already exists on disk, the file is silently skipped.
-.It Fl o
-Overwrite.
-When extracting a file from the zipfile, if a file with the same name
-already exists on disk, the existing file is replaced with the file
-from the zipfile.
-.It Fl p
-Extract to stdout.
-When extracting files from the zipfile, they are written to stdout.
-The normal output is suppressed as if
-.Fl q
-was specified.
-.It Fl P Ar password
-Extract encrypted files using a password.
-Putting a password on the command line using this option can be
-insecure.
-.It Fl q
-Quiet: print less information while extracting.
-.It Fl t
-Test: do not extract anything, but verify the checksum of every file
-in the archive.
-.It Fl u
-Update.
-When extracting a file from the zipfile, if a file with the same name
-already exists on disk, the existing file is replaced with the file
-from the zipfile if and only if the latter is newer than the former.
-Otherwise, the file is silently skipped.
-.It Fl v
-List verbosely, rather than extract, the contents of the zipfile.
-This differs from
-.Fl l
-by using the long listing.
-Note that most of the data is currently fake and does not reflect the
-content of the archive.
-.It Fl x Ar pattern
-Exclude files matching the pattern
-.Ar pattern .
-.It Fl y
-Print four digit years in listings instead of two.
-.It Fl Z Ar mode
-Emulate
-.Xr zipinfo 1L
-mode.
-Enabling
-.Xr zipinfo 1L
-mode changes the way in which additional arguments are parsed.
-Currently only
-.Xr zipinfo 1L
-mode 1 is supported, which lists the file names one per line.
-.It Ar [member ...]
-Optional list of members to extract from the zipfile.
-Can include patterns, e.g.,
-.Ar 'memberdir/*'
-will extract all files and dirs below memberdir.
-.El
-.Pp
-Note that only one of
-.Fl n ,
-.Fl o ,
-and
-.Fl u
-may be specified.
-If specified filename is
-.Qq - ,
-then data is read from
-.Va stdin .
-.Sh ENVIRONMENT
-If the
-.Ev UNZIP_DEBUG
-environment variable is defined, the
-.Fl q
-command-line option has no effect, and additional debugging
-information will be printed to
-.Va stderr .
-.Sh COMPATIBILITY
-The
-.Nm
-utility aims to be sufficiently compatible with other implementations
-to serve as a drop-in replacement in the context of the
-.Xr ports 7
-system.
-No attempt has been made to replicate functionality which is not
-required for that purpose.
-.Pp
-For compatibility reasons, command-line options will be recognized if
-they are listed not only before but also after the name of the
-zipfile.
-.Pp
-Normally, the
-.Fl a
-option should only affect files which are marked as text files in the
-zipfile's central directory.
-Since the
-.Xr archive 3
-library does not provide access to that information, it is not available
-to the
-.Nm
-utility.
-Instead, the
-.Nm
-utility will assume that a file is a text file if no non-ASCII
-characters are present within the first block of data decompressed for
-that file.
-If non-ASCII characters appear in subsequent blocks of data, a warning
-will be issued.
-.Pp
-The
-.Nm
-utility is only able to process ZIP archives handled by
-.Xr libarchive 3 .
-Depending on the installed version of
-.Xr libarchive 3 ,
-this may or may not include self-extracting or ZIPX archives.
-.Sh SEE ALSO
-.Xr libarchive 3
-.Sh HISTORY
-The
-.Nm
-utility appeared in
-.Fx 8.0 .
-.Sh AUTHORS
-The
-.Nm
-utility and this manual page were written by
-.An Dag-Erling Sm\(/orgrav Aq Mt d...@freebsd.org .
-It uses the
-.Xr archive 3
-library developed by
-.An Tim Kientzle Aq Mt kient...@freebsd.org .
diff --git a/usr.bin/unzip/unzip.c b/usr.bin/unzip/unzip.c
deleted file mode 100644
index 1200aa53e7e3..000000000000
--- a/usr.bin/unzip/unzip.c
+++ /dev/null
@@ -1,1141 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2009, 2010 Joerg Sonnenberger <jo...@netbsd.org>
- * Copyright (c) 2007-2008 Dag-Erling Smørgrav
- * 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
- *    in this position and unchanged.
- * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD$
- *
- * This file would be much shorter if we didn't care about command-line
- * compatibility with Info-ZIP's UnZip, which requires us to duplicate
- * parts of libarchive in order to gain more detailed control of its
- * behaviour for the purpose of implementing the -n, -o, -L and -a
- * options.
- */
-
-#include <sys/queue.h>
-#include <sys/stat.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <fnmatch.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <archive.h>
-#include <archive_entry.h>
-#include <readpassphrase.h>
-
-/* command-line options */
-static int              a_opt;         /* convert EOL */
-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 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 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 */
-
-/* debug flag */
-static int              unzip_debug;
-
-/* zipinfo mode */
-static int              zipinfo_mode;
-
-/* running on tty? */
-static int              tty;
-
-/* convenience macro */
-/* XXX should differentiate between ARCHIVE_{WARN,FAIL,RETRY} */
-#define ac(call)                                               \
-       do {                                                    \
-               int acret = (call);                             \
-               if (acret != ARCHIVE_OK)                        \
-                       errorx("%s", archive_error_string(a));  \
-       } while (0)
-
-/*
- * Indicates that last info() did not end with EOL.  This helps error() et
- * al. avoid printing an error message on the same line as an incomplete
- * informational message.
- */
-static int noeol;
-
-/* for an interactive passphrase input */
-static char *passphrase_buf;
-
-/* fatal error message + errno */
-static void
-error(const char *fmt, ...)
-{
-       va_list ap;
-
-       if (noeol)
-               fprintf(stdout, "\n");
-       fflush(stdout);
-       fprintf(stderr, "unzip: ");
-       va_start(ap, fmt);
-       vfprintf(stderr, fmt, ap);
-       va_end(ap);
-       fprintf(stderr, ": %s\n", strerror(errno));
-       exit(EXIT_FAILURE);
-}
-
-/* fatal error message, no errno */
-static void
-errorx(const char *fmt, ...)
-{
-       va_list ap;
-
-       if (noeol)
-               fprintf(stdout, "\n");
-       fflush(stdout);
-       fprintf(stderr, "unzip: ");
-       va_start(ap, fmt);
-       vfprintf(stderr, fmt, ap);
-       va_end(ap);
-       fprintf(stderr, "\n");
-       exit(EXIT_FAILURE);
-}
-
-/* non-fatal error message + errno */
-static void
-warning(const char *fmt, ...)
-{
-       va_list ap;
-
-       if (noeol)
-               fprintf(stdout, "\n");
-       fflush(stdout);
-       fprintf(stderr, "unzip: ");
-       va_start(ap, fmt);
-       vfprintf(stderr, fmt, ap);
-       va_end(ap);
-       fprintf(stderr, ": %s\n", strerror(errno));
-}
-
-/* non-fatal error message, no errno */
-static void
-warningx(const char *fmt, ...)
-{
-       va_list ap;
-
-       if (noeol)
-               fprintf(stdout, "\n");
-       fflush(stdout);
-       fprintf(stderr, "unzip: ");
-       va_start(ap, fmt);
-       vfprintf(stderr, fmt, ap);
-       va_end(ap);
-       fprintf(stderr, "\n");
-}
-
-/* informational message (if not -q) */
-static void
-info(const char *fmt, ...)
-{
-       va_list ap;
-
-       if (q_opt && !unzip_debug)
-               return;
-       va_start(ap, fmt);
-       vfprintf(stdout, fmt, ap);
-       va_end(ap);
-       fflush(stdout);
-
-       if (*fmt == '\0')
-               noeol = 1;
-       else
-               noeol = fmt[strlen(fmt) - 1] != '\n';
-}
-
-/* debug message (if unzip_debug) */
-static void
-debug(const char *fmt, ...)
-{
-       va_list ap;
-
-       if (!unzip_debug)
-               return;
-       va_start(ap, fmt);
-       vfprintf(stderr, fmt, ap);
-       va_end(ap);
-       fflush(stderr);
-
-       if (*fmt == '\0')
-               noeol = 1;
-       else
-               noeol = fmt[strlen(fmt) - 1] != '\n';
-}
-
-/* duplicate a path name, possibly converting to lower case */
-static char *
-pathdup(const char *path)
-{
-       char *str;
-       size_t i, len;
-
-       if (path == NULL || path[0] == '\0')
-               return (NULL);
-
-       len = strlen(path);
-       while (len && path[len - 1] == '/')
-               len--;
-       if ((str = malloc(len + 1)) == NULL) {
-               errno = ENOMEM;
-               error("malloc()");
-       }
-       if (L_opt) {
-               for (i = 0; i < len; ++i)
-                       str[i] = tolower((unsigned char)path[i]);
-       } else {
-               memcpy(str, path, len);
-       }
-       str[len] = '\0';
-
-       return (str);
-}
-
-/* concatenate two path names */
-static char *
-pathcat(const char *prefix, const char *path)
-{
-       char *str;
-       size_t prelen, len;
-
-       prelen = prefix ? strlen(prefix) + 1 : 0;
-       len = strlen(path) + 1;
-       if ((str = malloc(prelen + len)) == NULL) {
-               errno = ENOMEM;
-               error("malloc()");
-       }
-       if (prefix) {
-               memcpy(str, prefix, prelen);    /* includes zero */
-               str[prelen - 1] = '/';          /* splat zero */
-       }
-       memcpy(str + prelen, path, len);        /* includes zero */
-
-       return (str);
-}
-
-/*
- * Pattern lists for include / exclude processing
- */
-struct pattern {
-       STAILQ_ENTRY(pattern) link;
-       char pattern[];
-};
-
-STAILQ_HEAD(pattern_list, pattern);
-static struct pattern_list include = STAILQ_HEAD_INITIALIZER(include);
-static struct pattern_list exclude = STAILQ_HEAD_INITIALIZER(exclude);
-
-/*
- * Add an entry to a pattern list
- */
-static void
-add_pattern(struct pattern_list *list, const char *pattern)
-{
-       struct pattern *entry;
-       size_t len;
-
-       debug("adding pattern '%s'\n", pattern);
-       len = strlen(pattern);
-       if ((entry = malloc(sizeof *entry + len + 1)) == NULL) {
-               errno = ENOMEM;
-               error("malloc()");
-       }
-       memcpy(entry->pattern, pattern, len + 1);
-       STAILQ_INSERT_TAIL(list, entry, link);
-}
-
-/*
- * Match a string against a list of patterns
- */
-static int
-match_pattern(struct pattern_list *list, const char *str)
-{
-       struct pattern *entry;
-
-       STAILQ_FOREACH(entry, list, link) {
-               if (fnmatch(entry->pattern, str, C_opt ? FNM_CASEFOLD : 0) == 0)
-                       return (1);
-       }
-       return (0);
-}
-
-/*
- * Verify that a given pathname is in the include list and not in the
- * exclude list.
- */
-static int
-accept_pathname(const char *pathname)
-{
-
-       if (!STAILQ_EMPTY(&include) && !match_pattern(&include, pathname))
-               return (0);
-       if (!STAILQ_EMPTY(&exclude) && match_pattern(&exclude, pathname))
-               return (0);
-       return (1);
-}
-
-/*
- * Create the specified directory with the specified mode, taking certain
- * precautions on they way.
- */
-static void
-make_dir(const char *path, int mode)
-{
-       struct stat sb;
-
-       if (lstat(path, &sb) == 0) {
-               if (S_ISDIR(sb.st_mode))
-                       return;
-               /*
-                * Normally, we should either ask the user about removing
-                * the non-directory of the same name as a directory we
-                * wish to create, or respect the -n or -o command-line
-                * options.  However, this may lead to a later failure or
-                * even compromise (if this non-directory happens to be a
-                * symlink to somewhere unsafe), so we don't.
-                */
-
-               /*
-                * Don't check unlink() result; failure will cause mkdir()
-                * to fail later, which we will catch.
-                */
-               (void)unlink(path);
-       }
-       if (mkdir(path, mode) != 0 && errno != EEXIST)
-               error("mkdir('%s')", path);
-}
-
-/*
- * Ensure that all directories leading up to (but not including) the
- * specified path exist.
- *
- * XXX inefficient + modifies the file in-place
- */
-static void
-make_parent(char *path)
-{
-       struct stat sb;
-       char *sep;
-
-       sep = strrchr(path, '/');
-       if (sep == NULL || sep == path)
-               return;
-       *sep = '\0';
-       if (lstat(path, &sb) == 0) {
-               if (S_ISDIR(sb.st_mode)) {
-                       *sep = '/';
-                       return;
-               }
-               unlink(path);
-       }
-       make_parent(path);
-       mkdir(path, 0755);
-       *sep = '/';
-
-#if 0
-       for (sep = path; (sep = strchr(sep, '/')) != NULL; sep++) {
-               /* root in case of absolute d_arg */
-               if (sep == path)
-                       continue;
-               *sep = '\0';
-               make_dir(path, 0755);
-               *sep = '/';
-       }
-#endif
-}
-
-/*
- * Extract a directory.
- */
-static void
-extract_dir(struct archive *a, struct archive_entry *e, const char *path)
-{
-       int mode;
-
-       /*
-        * Dropbox likes to create '/' directory entries, just ignore
-        * such junk.
-        */
-       if (*path == '\0')
-               return;
-
-       mode = archive_entry_mode(e) & 0777;
-       if (mode == 0)
-               mode = 0755;
-
-       /*
-        * Some zipfiles contain directories with weird permissions such
-        * as 0644 or 0444.  This can cause strange issues such as being
-        * unable to extract files into the directory we just created, or
-        * the user being unable to remove the directory later without
-        * first manually changing its permissions.  Therefore, we whack
-        * the permissions into shape, assuming that the user wants full
-        * access and that anyone who gets read access also gets execute
-        * access.
-        */
-       mode |= 0700;
-       if (mode & 0040)
-               mode |= 0010;
-       if (mode & 0004)
-               mode |= 0001;
-
-       info("   creating: %s/\n", path);
-       make_dir(path, mode);
-       ac(archive_read_data_skip(a));
-}
-
-static unsigned char buffer[8192];
-static char spinner[] = { '|', '/', '-', '\\' };
-
-static int
-handle_existing_file(char **path)
-{
-       size_t alen;
-       ssize_t len;
-       char buf[4];
-
-       for (;;) {
-               fprintf(stderr,
-                   "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ",
-                   *path);
-               if (fgets(buf, sizeof(buf), stdin) == NULL) {
-                       clearerr(stdin);
-                       printf("NULL\n(EOF or read error, "
-                           "treating as \"[N]one\"...)\n");
-                       n_opt = 1;
-                       return -1;
-               }
-               switch (*buf) {
-               case 'A':
-                       o_opt = 1;
-                       /* FALLTHROUGH */
-               case 'y':
-               case 'Y':
-                       (void)unlink(*path);
-                       return 1;
-               case 'N':
-                       n_opt = 1;
-                       /* FALLTHROUGH */
-               case 'n':
-                       return -1;
-               case 'r':
-               case 'R':
-                       printf("New name: ");
-                       fflush(stdout);
-                       free(*path);
-                       *path = NULL;
-                       alen = 0;
-                       len = getline(path, &alen, stdin);
-                       if ((*path)[len - 1] == '\n')
-                               (*path)[len - 1] = '\0';
-                       return 0;
-               default:
-                       break;
-               }
-       }
-}
-
-/*
- * Detect binary files by a combination of character white list and
- * black list. NUL bytes and other control codes without use in text files
- * result directly in switching the file to binary mode. Otherwise, at least
- * one white-listed byte has to be found.
- *
- * Black-listed: 0..6, 14..25, 28..31
*** 655 LINES SKIPPED ***

Reply via email to