git: 277283585540 - stable/13 - unzip: swtich to bsdunzip from libarchive
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 04 May 2024 12:37:38 UTC
The branch stable/13 has been updated by mm: URL: https://cgit.FreeBSD.org/src/commit/?id=277283585540b41170373730d54e3d1917b0bb18 commit 277283585540b41170373730d54e3d1917b0bb18 Author: Martin Matuska <mm@FreeBSD.org> AuthorDate: 2023-07-31 11:54:58 +0000 Commit: Martin Matuska <mm@FreeBSD.org> CommitDate: 2024-05-04 11:53:07 +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) (cherry picked from commit b5a3a89c50671a1ad29e7c43fe15e7b16feac239) --- 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 | 201 ------ usr.bin/unzip/unzip.c | 1132 -------------------------------- 8 files changed, 188 insertions(+), 1334 deletions(-) diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 98450e1cafbd..5d31c374166d 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -1123,6 +1123,8 @@ .. uniq .. + unzip + .. vmstat .. xargs diff --git a/lib/libarchive/config_freebsd.h b/lib/libarchive/config_freebsd.h index aefbcd4b46bd..49b212c2204c 100644 --- a/lib/libarchive/config_freebsd.h +++ b/lib/libarchive/config_freebsd.h @@ -109,6 +109,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 @@ -121,6 +123,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 @@ -199,6 +203,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 3204a0741389..7193ab58b5a3 100644 --- a/usr.bin/unzip/Makefile +++ b/usr.bin/unzip/Makefile @@ -1,5 +1,31 @@ -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 6b808b3ad9f9..000000000000 --- a/usr.bin/unzip/unzip.1 +++ /dev/null @@ -1,201 +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. -.\" -.Dd January 2, 2023 -.Dt UNZIP 1 -.Os -.Sh NAME -.Nm unzip -.Nd extract files from a ZIP archive -.Sh SYNOPSIS -.Nm -.Op Fl aCcfjLlnopqtuvy -.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 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 des@FreeBSD.org . -It uses the -.Xr archive 3 -library developed by -.An Tim Kientzle Aq Mt kientzle@FreeBSD.org . diff --git a/usr.bin/unzip/unzip.c b/usr.bin/unzip/unzip.c deleted file mode 100644 index c0036e71b5b7..000000000000 --- a/usr.bin/unzip/unzip.c +++ /dev/null @@ -1,1132 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2009, 2010 Joerg Sonnenberger <joerg@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. - * - * 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 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 - * 0xf3ffc07f = 11110011111111111100000001111111b - * White-listed: 9..10, 13, >= 32 - * 0x00002600 = 00000000000000000010011000000000b - * - * See the proginfo/txtvsbin.txt in the zip sources for a detailed discussion. - */ -#define BYTE_IS_BINARY(x) ((x) < 32 && (0xf3ffc07fU & (1U << (x)))) -#define BYTE_IS_TEXT(x) ((x) >= 32 || (0x00002600U & (1U << (x)))) *** 641 LINES SKIPPED ***