FreeBSD Bugzilla – Attachment 243738 Details for
Bug 272845
[exp-run] Bsdunzip from libarchive
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Bsdunzip patch
bsdunzip.patch (text/plain), 80.86 KB, created by
Martin Matuska
on 2023-07-31 13:50:41 UTC
(
hide
)
Description:
Bsdunzip patch
Filename:
MIME Type:
Creator:
Martin Matuska
Created:
2023-07-31 13:50:41 UTC
Size:
80.86 KB
patch
obsolete
>commit ce9e9e8012c8b61d5c8f5d58009b3b329b2aada4 >Author: Martin Matuska <mm@FreeBSD.org> >Date: Mon Jul 31 13:54:58 2023 +0200 > > unzip: swtich to bsdunzip from libarchive > > Unzip from FreeBSD has been ported to libarchive. > Change usr.bin/unzip to use bsdunzip from libarchive. > >diff --git a/contrib/libarchive/unzip/bsdunzip.h b/contrib/libarchive/unzip/bsdunzip.h >index 12b65cefb466..3853178189c7 100644 >--- a/contrib/libarchive/unzip/bsdunzip.h >+++ b/contrib/libarchive/unzip/bsdunzip.h >@@ -1,63 +1,65 @@ > /*- > * 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 *); > >+extern int bsdunzip_optind; >+ > #endif >diff --git a/contrib/libarchive/unzip/cmdline.c b/contrib/libarchive/unzip/cmdline.c >index 95d4f99b8242..76eb423de116 100644 >--- a/contrib/libarchive/unzip/cmdline.c >+++ b/contrib/libarchive/unzip/cmdline.c >@@ -1,250 +1,248 @@ > /*- > * 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/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 >@@ -1,1184 +1,1186 @@ > # $FreeBSD$ > # > # Please see the file src/etc/mtree/README before making changes to this file. > # > > /set type=dir uname=root gname=wheel mode=0755 tags=package=tests > . > bin > cat > .. > chflags > .. > chmod > .. > cp > .. > date > .. > dd > .. > echo > .. > expr > .. > ln > .. > ls > .. > mkdir > .. > mv > .. > pax > .. > pkill > .. > pwait > .. > rm > .. > rmdir > .. > sh > builtins > .. > errors > .. > execution > .. > expansion > .. > invocation > .. > parameters > .. > parser > .. > set-e > .. > .. > sleep > .. > test > .. > timeout > .. > .. > cddl > lib > .. > sbin > .. > usr.bin > ctfconvert > .. > ztest > .. > .. > usr.sbin > dtrace > common > aggs > .. > arithmetic > .. > arrays > .. > assocs > .. > begin > .. > bitfields > .. > buffering > .. > builtinvar > .. > cg > .. > clauses > .. > cpc > .. > decls > .. > drops > .. > dtraceUtil > .. > end > .. > env > .. > enum > .. > error > .. > exit > .. > fbtprovider > .. > funcs > .. > grammar > .. > include > .. > inline > .. > io > .. > ip > .. > java_api > .. > json > .. > kinst > .. > lexer > .. > llquantize > .. > mdb > .. > mib > .. > misc > .. > multiaggs > .. > offsetof > .. > operators > .. > pid > .. > plockstat > .. > pointers > .. > pragma > .. > predicates > .. > preprocessor > .. > print > .. > printa > .. > printf > .. > privs > .. > probes > .. > proc > .. > profile-n > .. > providers > .. > raise > .. > rates > .. > safety > .. > scalars > .. > sched > .. > scripting > .. > sdt > .. > sizeof > .. > speculation > .. > stability > .. > stack > .. > stackdepth > .. > stop > .. > strlen > .. > strtoll > .. > struct > .. > sugar > .. > syscall > .. > sysevent > .. > tick-n > .. > trace > .. > tracemem > .. > translators > .. > typedef > .. > types > .. > uctf > .. > union > .. > usdt > .. > ustack > .. > vars > .. > version > .. > .. > i386 > arrays > .. > funcs > .. > pid > .. > ustack > .. > .. > amd64 > arrays > .. > .. > .. > zfsd > .. > .. > .. > etc > rc.d > .. > .. > examples > .. > games > .. > gnu > lib > .. > usr.bin > diff > .. > .. > .. > lib > atf > libatf-c > detail > .. > .. > libatf-c++ > detail > .. > .. > test-programs > .. > .. > csu > dynamic > .. > dynamiclib > .. > static > .. > .. > googletest > gmock > .. > gmock_main > .. > gtest > .. > gtest_main > .. > .. > libarchive > .. > libbe > .. > libc > c063 > .. > db > .. > gen > execve > .. > posix_spawn > .. > .. > hash > data > .. > .. > iconv > .. > inet > .. > locale > .. > net > getaddrinfo > data > .. > .. > .. > nss > .. > regex > data > .. > .. > resolv > .. > rpc > .. > ssp > .. > setjmp > .. > stdio > .. > stdlib > .. > string > .. > sys > .. > time > .. > tls > dso > .. > .. > termios > .. > ttyio > .. > .. > libcam > .. > libcasper > services > cap_dns > .. > cap_grp > .. > cap_pwd > .. > cap_sysctl > .. > .. > .. > libcrypt > .. > libdevdctl > .. > libexecinfo > .. > libkvm > .. > libmp > .. > libnv > .. > libproc > .. > libregex > data > .. > .. > librt > .. > libsbuf > .. > libsysdecode > .. > libthr > dlopen > .. > .. > libutil > .. > libxo > .. > msun > .. > .. > libexec > atf > atf-check > .. > atf-pytest-wrapper > .. > atf-sh > .. > .. > rc > .. > rtld-elf > .. > tftpd > .. > .. > sbin > bectl > .. > dhclient > .. > devd > .. > growfs > .. > ifconfig > .. > ipfw > .. > md5 > .. > mdconfig > .. > newfs_msdos > .. > nvmecontrol > .. > pfctl > files > .. > .. > ping > .. > route > .. > sysctl > .. > .. > secure > lib > .. > libexec > .. > usr.bin > .. > usr.sbin > .. > .. > share > examples > tests > atf > .. > googletest > .. > plain > .. > tap > .. > .. > .. > zoneinfo > .. > .. > sys > acl > .. > aio > .. > audit > .. > auditpipe > .. > capsicum > .. > cddl > zfs > bin > .. > include > .. > tests > acl > cifs > .. > nontrivial > .. > trivial > .. > .. > atime > .. > bootfs > .. > cache > .. > cachefile > .. > clean_mirror > .. > cli_root > zfs_upgrade > .. > zfs_promote > .. > zfs_clone > .. > zfs_property > .. > zfs_destroy > .. > zpool_create > .. > zpool_history > .. > zpool_expand > .. > zpool_remove > .. > zfs_mount > .. > zfs_unshare > .. > zdb > .. > zpool_online > .. > zpool_get > .. > zpool_export > .. > zfs_copies > .. > zfs_get > .. > zfs > .. > zpool_clear > .. > zpool_import > blockfiles > .. > .. > zpool > .. > zpool_offline > .. > zpool_replace > .. > zfs_rollback > .. > zpool_set > .. > zfs_send > .. > zfs_set > .. > zpool_detach > .. > zfs_diff > .. > zpool_scrub > .. > zfs_inherit > .. > zfs_snapshot > .. > zfs_share > .. > zpool_destroy > .. > zpool_status > .. > zfs_unmount > .. > zfs_receive > .. > zfs_create > .. > zpool_upgrade > blockfiles > .. > .. > zpool_add > .. > zfs_rename > .. > zpool_attach > .. > zfs_reservation > .. > .. > cli_user > misc > .. > zfs_list > .. > zpool_iostat > .. > zpool_list > .. > .. > compression > .. > ctime > .. > delegate > .. > devices > .. > exec > .. > grow_pool > .. > grow_replicas > .. > history > .. > hotplug > .. > hotspare > .. > inheritance > .. > interop > .. > inuse > .. > iscsi > .. > large_files > .. > largest_pool > .. > link_count > .. > migration > .. > mmap > .. > mount > .. > mv_files > .. > nestedfs > .. > no_space > .. > online_offline > .. > pool_names > .. > poolversion > .. > quota > .. > redundancy > .. > refquota > .. > refreserv > .. > rename_dirs > .. > replacement > .. > reservation > .. > rootpool > .. > rsend > .. > scrub_mirror > .. > slog > .. > snapshot > .. > snapused > .. > sparse > .. > threadsappend > .. > truncate > .. > txg_integrity > .. > userquota > .. > utils_test > .. > write_dirs > .. > xattr > .. > zfsd > .. > zil > .. > zinject > .. > zones > .. > zvol > zvol_ENOSPC > .. > zvol_cli > .. > zvol_misc > .. > zvol_swap > .. > .. > zvol_thrash > .. > .. > .. > .. > compat32 > .. > devrandom > .. > dtrace > .. > fifo > .. > file > .. > fs > fusefs > .. > tarfs > .. > tmpfs > .. > .. > geom > class > concat > .. > eli > .. > gate > .. > gpt > .. > mirror > .. > multipath > .. > nop > .. > part > .. > raid3 > .. > shsec > .. > stripe > .. > uzip > etalon > .. > .. > .. > .. > kern > acct > .. > execve > .. > pipe > .. > .. > kqueue > libkqueue > .. > .. > mac > bsdextended > .. > ipacl > .. > portacl > .. > .. > mqueue > .. > net > if_ovpn > .. > routing > .. > .. > netgraph > .. > netinet > .. > netinet6 > frag6 > .. > .. > netipsec > tunnel > .. > .. > netlink > .. > netmap > .. > netpfil > common > .. > ipfw > .. > pf > ioctl > .. > .. > .. > opencrypto > .. > pjdfstest > chflags > .. > chmod > .. > chown > .. > ftruncate > .. > granular > .. > link > .. > mkdir > .. > mkfifo > .. > mknod > .. > open > .. > rename > .. > rmdir > .. > symlink > .. > truncate > .. > unlink > .. > utimensat > .. > .. > posixshm > .. > sys > .. > vfs > .. > vm > .. > vmm > .. > .. > usr.bin > apply > .. > asa > .. > awk > bugs-fixed > .. > netbsd > .. > .. > basename > .. > bintrans > .. > bmake > archives > fmt_44bsd > .. > fmt_44bsd_mod > .. > fmt_oldbsd > .. > .. > basic > t0 > .. > t1 > .. > t2 > .. > t3 > .. > .. > execution > ellipsis > .. > empty > .. > joberr > .. > plus > .. > .. > shell > builtin > .. > meta > .. > path > .. > path_select > .. > replace > .. > select > .. > .. > suffixes > basic > .. > src_wild1 > .. > src_wild2 > .. > .. > syntax > directive-t0 > .. > enl > .. > funny-targets > .. > semi > .. > .. > sysmk > t0 > 2 > 1 > .. > .. > mk > .. > .. > t1 > 2 > 1 > .. > .. > mk > .. > .. > t2 > 2 > 1 > .. > .. > mk > .. > .. > .. > variables > modifier_M > .. > modifier_t > .. > opt_V > .. > t0 > .. > .. > .. > bsdcat > .. > calendar > .. > cmp > .. > compress > .. > cpio > .. > col > .. > comm > .. > csplit > .. > cut > .. > dc > .. > diff > .. > diff3 > .. > dirname > .. > du > .. > factor > .. > file2c > .. > file > .. > find > .. > fold > .. > getconf > .. > gh-bc > .. > grep > .. > gzip > .. > head > .. > hexdump > .. > ident > .. > indent > .. > join > .. > jot > .. > lastcomm > .. > limits > .. > locale > .. > m4 > .. > mkimg > .. > mktemp > .. > ncal > .. > opensm > .. > patch > .. > pr > .. > printf > .. > procstat > .. > renice > .. > rs > .. > sdiff > .. > sed > regress.multitest.out > .. > .. > seq > .. > soelim > .. > sort > .. > split > .. > stat > .. > tail > .. > tar > .. > tftp > .. > tr > .. > truncate > .. > tsort > .. > units > .. > unifdef > .. > uniq > .. >+ unzip >+ .. > vmstat > .. > wc > .. > xargs > .. > xinstall > .. > xo > .. > yacc > yacc > .. > .. > .. > usr.sbin > chown > .. > daemon > .. > etcupdate > .. > extattr > .. > fstyp > .. > jail > .. > makefs > .. > mixer > .. > newsyslog > .. > nmtree > .. > praudit > .. > pw > .. > rpcbind > .. > sa > .. > .. > .. > > # vim: set expandtab ts=4 sw=4: >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 >@@ -1,267 +1,272 @@ > /*- > * SPDX-License-Identifier: BSD-2-Clause > * > * Copyright (c) 2003-2007 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. > * > * $FreeBSD$ > */ > #define __LIBARCHIVE_CONFIG_H_INCLUDED 1 > > #include <osreldate.h> > > /* FreeBSD 5.0 and later has ACL and extattr support. */ > #if __FreeBSD__ > 4 > #define ARCHIVE_ACL_FREEBSD 1 > #define ARCHIVE_XATTR_FREEBSD 1 > #define HAVE_ACL_GET_PERM_NP 1 > #define HAVE_ARC4RANDOM_BUF 1 > #define HAVE_STRUCT_XVFSCONF 1 > #define HAVE_SYS_ACL_H 1 > #define HAVE_SYS_EXTATTR_H 1 > #if __FreeBSD__ > 7 > /* FreeBSD 8.0 and later has NFSv4 ACL support */ > #define ARCHIVE_ACL_FREEBSD_NFS4 1 > #define HAVE_ACL_GET_LINK_NP 1 > #define HAVE_ACL_IS_TRIVIAL_NP 1 > #define HAVE_ACL_SET_LINK_NP 1 > #endif /* __FreeBSD__ > 7 */ > #endif /* __FreeBSD__ > 4 */ > > #ifdef WITH_OPENSSL > #define HAVE_LIBCRYPTO 1 > #define HAVE_OPENSSL_EVP_H 1 > #define HAVE_OPENSSL_MD5_H 1 > #define HAVE_OPENSSL_RIPEMD_H 1 > #define HAVE_OPENSSL_SHA_H 1 > #define HAVE_OPENSSL_SHA256_INIT 1 > #define HAVE_OPENSSL_SHA384_INIT 1 > #define HAVE_OPENSSL_SHA512_INIT 1 > #define HAVE_PKCS5_PBKDF2_HMAC_SHA1 1 > #define HAVE_SHA256 1 > #define HAVE_SHA384 1 > #define HAVE_SHA512 1 > #else > #define HAVE_LIBMD 1 > #define HAVE_MD5_H 1 > #define HAVE_MD5INIT 1 > #define HAVE_RIPEMD_H 1 > #define HAVE_SHA_H 1 > #define HAVE_SHA1 1 > #define HAVE_SHA1_INIT 1 > #define HAVE_SHA256 1 > #define HAVE_SHA256_H 1 > #define HAVE_SHA256_INIT 1 > #define HAVE_SHA512 1 > #define HAVE_SHA512_H 1 > #define HAVE_SHA512_INIT 1 > #endif > > #define HAVE_BSDXML_H 1 > #define HAVE_BZLIB_H 1 > #define HAVE_CHFLAGS 1 > #define HAVE_CHOWN 1 > #define HAVE_CHROOT 1 > #define HAVE_CTIME_R 1 > #define HAVE_CTYPE_H 1 > #define HAVE_DECL_EXTATTR_NAMESPACE_USER 1 > #define HAVE_DECL_INT32_MAX 1 > #define HAVE_DECL_INT32_MIN 1 > #define HAVE_DECL_INT64_MAX 1 > #define HAVE_DECL_INT64_MIN 1 > #define HAVE_DECL_INTMAX_MAX 1 > #define HAVE_DECL_INTMAX_MIN 1 > #define HAVE_DECL_SIZE_MAX 1 > #define HAVE_DECL_SSIZE_MAX 1 > #define HAVE_DECL_STRERROR_R 1 > #define HAVE_DECL_UINT32_MAX 1 > #define HAVE_DECL_UINT64_MAX 1 > #define HAVE_DECL_UINTMAX_MAX 1 > #define HAVE_DIRENT_H 1 > #define HAVE_DIRFD 1 > #define HAVE_DLFCN_H 1 > #ifndef __linux__ > #define HAVE_D_MD_ORDER 1 > #endif > #define HAVE_EFTYPE 1 > #define HAVE_EILSEQ 1 > #define HAVE_ERRNO_H 1 > #define HAVE_FCHDIR 1 > #define HAVE_FCHFLAGS 1 > #define HAVE_FCHMOD 1 > #define HAVE_FCHOWN 1 > #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 > #define HAVE_FSTATAT 1 > #define HAVE_FSTATFS 1 > #define HAVE_FSTATVFS 1 > #define HAVE_FTRUNCATE 1 > #define HAVE_FUTIMES 1 > #define HAVE_FUTIMESAT 1 > #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 > #define HAVE_GETVFSBYNAME 1 > #define HAVE_GMTIME_R 1 > #define HAVE_GRP_H 1 > #define HAVE_INTMAX_T 1 > #define HAVE_INTTYPES_H 1 > #define HAVE_LANGINFO_H 1 > #define HAVE_LCHFLAGS 1 > #define HAVE_LCHMOD 1 > #define HAVE_LCHOWN 1 > #define HAVE_LIBZ 1 > #define HAVE_LIMITS_H 1 > #define HAVE_LINK 1 > #define HAVE_LINKAT 1 > #define HAVE_LOCALE_H 1 > #define HAVE_LOCALTIME_R 1 > #define HAVE_LONG_LONG_INT 1 > #define HAVE_LSTAT 1 > #define HAVE_LUTIMES 1 > #define HAVE_MBRTOWC 1 > #define HAVE_MEMMOVE 1 > #define HAVE_MEMORY_H 1 > #define HAVE_MEMSET 1 > #define HAVE_MKDIR 1 > #define HAVE_MKFIFO 1 > #define HAVE_MKNOD 1 > #define HAVE_MKSTEMP 1 > #define HAVE_NL_LANGINFO 1 > #define HAVE_OPENAT 1 > #define HAVE_PATHS_H 1 > #define HAVE_PIPE 1 > #define HAVE_POLL 1 > #define HAVE_POLL_H 1 > #define HAVE_POSIX_SPAWNP 1 > #define HAVE_PTHREAD_H 1 > #define HAVE_PWD_H 1 > #define HAVE_READDIR_R 1 > #define HAVE_READLINK 1 > #define HAVE_READLINKAT 1 > #ifndef __linux__ > #define HAVE_READPASSPHRASE 1 > #define HAVE_READPASSPHRASE_H 1 > #endif > #define HAVE_REGEX_H 1 > #define HAVE_SELECT 1 > #define HAVE_SETENV 1 > #define HAVE_SETLOCALE 1 > #define HAVE_SIGACTION 1 > #define HAVE_SIGNAL_H 1 > #define HAVE_SPAWN_H 1 > #define HAVE_STATFS 1 > #define HAVE_STATVFS 1 > #define HAVE_STDARG_H 1 > #define HAVE_STDINT_H 1 > #define HAVE_STDLIB_H 1 > #define HAVE_STRCHR 1 > #define HAVE_STRDUP 1 > #define HAVE_STRERROR 1 > #define HAVE_STRERROR_R 1 > #define HAVE_STRFTIME 1 > #define HAVE_STRINGS_H 1 > #define HAVE_STRING_H 1 > #define HAVE_STRNLEN 1 > #define HAVE_STRRCHR 1 > #define HAVE_STRUCT_STATFS_F_NAMEMAX 1 > #define HAVE_STRUCT_STAT_ST_BIRTHTIME 1 > #define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1 > #define HAVE_STRUCT_STAT_ST_BLKSIZE 1 > #define HAVE_STRUCT_STAT_ST_FLAGS 1 > #define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 > #define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1 > #define HAVE_STRUCT_TM_TM_GMTOFF 1 > #define HAVE_SYMLINK 1 > #define HAVE_SYS_CDEFS_H 1 > #define HAVE_SYS_IOCTL_H 1 > #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 > #define HAVE_SYS_TIME_H 1 > #define HAVE_SYS_TYPES_H 1 > #define HAVE_SYS_UTSNAME_H 1 > #define HAVE_SYS_WAIT_H 1 > #define HAVE_TIMEGM 1 > #define HAVE_TIME_H 1 > #define HAVE_TZSET 1 > #define HAVE_UINTMAX_T 1 > #define HAVE_UNISTD_H 1 > #define HAVE_UNLINKAT 1 > #define HAVE_UNSETENV 1 > #define HAVE_UNSIGNED_LONG_LONG 1 > #define HAVE_UNSIGNED_LONG_LONG_INT 1 > #define HAVE_UTIME 1 > #define HAVE_UTIMES 1 > #define HAVE_UTIME_H 1 > #define HAVE_VFORK 1 > #define HAVE_VPRINTF 1 > #define HAVE_WCHAR_H 1 > #define HAVE_WCHAR_T 1 > #define HAVE_WCRTOMB 1 > #define HAVE_WCSCMP 1 > #define HAVE_WCSCPY 1 > #define HAVE_WCSLEN 1 > #define HAVE_WCTOMB 1 > #define HAVE_WCTYPE_H 1 > #define HAVE_WMEMCMP 1 > #define HAVE_WMEMCPY 1 > #define HAVE_WMEMMOVE 1 > #define HAVE_ZLIB_H 1 > #define TIME_WITH_SYS_TIME 1 > > #if __FreeBSD_version >= 1100056 > #define HAVE_FUTIMENS 1 > #define HAVE_UTIMENSAT 1 > #endif > > /* FreeBSD 4 and earlier lack intmax_t/uintmax_t */ > #if __FreeBSD__ < 5 > #define intmax_t int64_t > #define uintmax_t uint64_t > #endif > > /* FreeBSD defines for archive_hash.h */ > #ifdef WITH_OPENSSL > #define ARCHIVE_CRYPTO_MD5_OPENSSL 1 > #define ARCHIVE_CRYPTO_RMD160_OPENSSL 1 > #define ARCHIVE_CRYPTO_SHA1_OPENSSL > #define ARCHIVE_CRYPTO_SHA256_OPENSSL 1 > #define ARCHIVE_CRYPTO_SHA384_OPENSSL 1 > #define ARCHIVE_CRYPTO_SHA512_OPENSSL 1 > #else > #define ARCHIVE_CRYPTO_MD5_LIBMD 1 > #define ARCHIVE_CRYPTO_SHA1_LIBMD 1 > #define ARCHIVE_CRYPTO_SHA256_LIBMD 1 > #define ARCHIVE_CRYPTO_SHA512_LIBMD 1 > #endif >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 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 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 <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. >- * >- * $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 >- * 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)))) >- >-static int >-check_binary(const unsigned char *buf, size_t len) >-{ >- int rv; >- for (rv = 1; len--; ++buf) { >- if (BYTE_IS_BINARY(*buf)) >- return 1; >- if (BYTE_IS_TEXT(*buf)) >- rv = 0; >- } >- >- return rv; >-} >- >-/* >- * Extract to a file descriptor >- */ >-static int >-extract2fd(struct archive *a, char *pathname, int fd) >-{ >- int cr, text, warn; >- ssize_t len; >- unsigned char *p, *q, *end; >- >- text = a_opt; >- warn = 0; >- cr = 0; >- >- /* loop over file contents and write to fd */ >- for (int n = 0; ; n++) { >- if (fd != STDOUT_FILENO) >- if (tty && (n % 4) == 0) >- info(" %c\b\b", spinner[(n / 4) % sizeof spinner]); >- >- len = archive_read_data(a, buffer, sizeof buffer); >- >- if (len < 0) >- ac(len); >- >- /* left over CR from previous buffer */ >- if (a_opt && cr) { >- if (len == 0 || buffer[0] != '\n') >- if (write(fd, "\r", 1) != 1) >- error("write('%s')", pathname); >- cr = 0; >- } >- >- /* EOF */ >- if (len == 0) >- break; >- end = buffer + len; >- >- /* >- * Detect whether this is a text file. The correct way to >- * do this is to check the least significant bit of the >- * "internal file attributes" field of the corresponding >- * file header in the central directory, but libarchive >- * does not provide access to this field, so we have to >- * guess by looking for non-ASCII characters in the >- * buffer. Hopefully we won't guess wrong. If we do >- * guess wrong, we print a warning message later. >- */ >- if (a_opt && n == 0) { >- if (check_binary(buffer, len)) >- text = 0; >- } >- >- /* simple case */ >- if (!a_opt || !text) { >- if (write(fd, buffer, len) != len) >- error("write('%s')", pathname); >- continue; >- } >- >- /* hard case: convert \r\n to \n (sigh...) */ >- for (p = buffer; p < end; p = q + 1) { >- for (q = p; q < end; q++) { >- if (!warn && BYTE_IS_BINARY(*q)) { >- warningx("%s may be corrupted due" >- " to weak text file detection" >- " heuristic", pathname); >- warn = 1; >- } >- if (q[0] != '\r') >- continue; >- if (&q[1] == end) { >- cr = 1; >- break; >- } >- if (q[1] == '\n') >- break; >- } >- if (write(fd, p, q - p) != q - p) >- error("write('%s')", pathname); >- } >- } >- >- return text; >-} >- >-/* >- * Extract a regular file. >- */ >-static void >-extract_file(struct archive *a, struct archive_entry *e, char **path) >-{ >- int mode; >- struct timespec mtime; >- struct stat sb; >- struct timespec ts[2]; >- int fd, check, text; >- const char *linkname; >- >- mode = archive_entry_mode(e) & 0777; >- if (mode == 0) >- mode = 0644; >- mtime.tv_sec = archive_entry_mtime(e); >- mtime.tv_nsec = archive_entry_mtime_nsec(e); >- >- /* look for existing file of same name */ >-recheck: >- if (lstat(*path, &sb) == 0) { >- if (u_opt || f_opt) { >- /* check if up-to-date */ >- if (S_ISREG(sb.st_mode) && >- (sb.st_mtim.tv_sec > mtime.tv_sec || >- (sb.st_mtim.tv_sec == mtime.tv_sec && >- sb.st_mtim.tv_nsec >= mtime.tv_nsec))) >- return; >- (void)unlink(*path); >- } else if (o_opt) { >- /* overwrite */ >- (void)unlink(*path); >- } else if (n_opt) { >- /* do not overwrite */ >- return; >- } else { >- check = handle_existing_file(path); >- if (check == 0) >- goto recheck; >- if (check == -1) >- return; /* do not overwrite */ >- } >- } else { >- if (f_opt) >- return; >- } >- >- ts[0].tv_sec = 0; >- ts[0].tv_nsec = UTIME_NOW; >- ts[1] = mtime; >- >- /* process symlinks */ >- linkname = archive_entry_symlink(e); >- if (linkname != NULL) { >- if (symlink(linkname, *path) != 0) >- error("symlink('%s')", *path); >- info(" extracting: %s -> %s\n", *path, linkname); >- if (lchmod(*path, mode) != 0) >- warning("Cannot set mode for '%s'", *path); >- /* set access and modification time */ >- if (utimensat(AT_FDCWD, *path, ts, AT_SYMLINK_NOFOLLOW) != 0) >- warning("utimensat('%s')", *path); >- return; >- } >- >- if ((fd = open(*path, O_RDWR|O_CREAT|O_TRUNC, mode)) < 0) >- error("open('%s')", *path); >- >- info(" extracting: %s", *path); >- >- text = extract2fd(a, *path, fd); >- >- if (tty) >- info(" \b\b"); >- if (text) >- info(" (text)"); >- info("\n"); >- >- /* set access and modification time */ >- if (futimens(fd, ts) != 0) >- error("futimens('%s')", *path); >- if (close(fd) != 0) >- error("close('%s')", *path); >-} >- >-/* >- * Extract a zipfile entry: first perform some sanity checks to ensure >- * that it is either a directory or a regular file and that the path is >- * not absolute and does not try to break out of the current directory; >- * then call either extract_dir() or extract_file() as appropriate. >- * >- * This is complicated a bit by the various ways in which we need to >- * manipulate the path name. Case conversion (if requested by the -L >- * option) happens first, but the include / exclude patterns are applied >- * to the full converted path name, before the directory part of the path >- * is removed in accordance with the -j option. Sanity checks are >- * intentionally done earlier than they need to be, so the user will get a >- * warning about insecure paths even for files or directories which >- * wouldn't be extracted anyway. >- */ >-static void >-extract(struct archive *a, struct archive_entry *e) >-{ >- char *pathname, *realpathname; >- mode_t filetype; >- char *p, *q; >- >- if ((pathname = pathdup(archive_entry_pathname(e))) == NULL) { >- warningx("skipping empty or unreadable filename entry"); >- ac(archive_read_data_skip(a)); >- return; >- } >- filetype = archive_entry_filetype(e); >- >- /* sanity checks */ >- if (pathname[0] == '/' || >- strncmp(pathname, "../", 3) == 0 || >- strstr(pathname, "/../") != NULL) { >- warningx("skipping insecure entry '%s'", pathname); >- ac(archive_read_data_skip(a)); >- free(pathname); >- return; >- } >- >- /* I don't think this can happen in a zipfile.. */ >- if (!S_ISDIR(filetype) && !S_ISREG(filetype) && !S_ISLNK(filetype)) { >- warningx("skipping non-regular entry '%s'", pathname); >- ac(archive_read_data_skip(a)); >- free(pathname); >- return; >- } >- >- /* skip directories in -j case */ >- if (S_ISDIR(filetype) && j_opt) { >- ac(archive_read_data_skip(a)); >- free(pathname); >- return; >- } >- >- /* apply include / exclude patterns */ >- if (!accept_pathname(pathname)) { >- ac(archive_read_data_skip(a)); >- free(pathname); >- return; >- } >- >- /* apply -j and -d */ >- if (j_opt) { >- for (p = q = pathname; *p; ++p) >- if (*p == '/') >- q = p + 1; >- realpathname = pathcat(d_arg, q); >- } else { >- realpathname = pathcat(d_arg, pathname); >- } >- >- /* ensure that parent directory exists */ >- make_parent(realpathname); >- >- if (S_ISDIR(filetype)) >- extract_dir(a, e, realpathname); >- else >- extract_file(a, e, &realpathname); >- >- free(realpathname); >- free(pathname); >-} >- >-static void >-extract_stdout(struct archive *a, struct archive_entry *e) >-{ >- char *pathname; >- mode_t filetype; >- >- if ((pathname = pathdup(archive_entry_pathname(e))) == NULL) { >- warningx("skipping empty or unreadable filename entry"); >- ac(archive_read_data_skip(a)); >- return; >- } >- filetype = archive_entry_filetype(e); >- >- /* I don't think this can happen in a zipfile.. */ >- if (!S_ISDIR(filetype) && !S_ISREG(filetype) && !S_ISLNK(filetype)) { >- warningx("skipping non-regular entry '%s'", pathname); >- ac(archive_read_data_skip(a)); >- free(pathname); >- return; >- } >- >- /* skip directories in -j case */ >- if (S_ISDIR(filetype)) { >- ac(archive_read_data_skip(a)); >- free(pathname); >- return; >- } >- >- /* apply include / exclude patterns */ >- if (!accept_pathname(pathname)) { >- ac(archive_read_data_skip(a)); >- free(pathname); >- return; >- } >- >- if (c_opt) >- info("x %s\n", pathname); >- >- (void)extract2fd(a, pathname, STDOUT_FILENO); >- >- free(pathname); >-} >- >-/* >- * Print the name of an entry to stdout. >- */ >-static void >-list(struct archive *a, struct archive_entry *e) >-{ >- char buf[20]; >- time_t mtime; >- struct tm *tm; >- >- mtime = archive_entry_mtime(e); >- tm = localtime(&mtime); >- if (*y_str) >- strftime(buf, sizeof(buf), "%m-%d-%G %R", tm); >- else >- strftime(buf, sizeof(buf), "%m-%d-%g %R", tm); >- >- if (!zipinfo_mode) { >- if (v_opt == 1) { >- printf(" %8ju %s %s\n", >- (uintmax_t)archive_entry_size(e), >- buf, archive_entry_pathname(e)); >- } else if (v_opt == 2) { >- printf("%8ju Stored %7ju 0%% %s %08x %s\n", >- (uintmax_t)archive_entry_size(e), >- (uintmax_t)archive_entry_size(e), >- buf, >- 0U, >- archive_entry_pathname(e)); >- } >- } else { >- if (Z1_opt) >- printf("%s\n",archive_entry_pathname(e)); >- } >- ac(archive_read_data_skip(a)); >-} >- >-/* >- * Extract to memory to check CRC >- */ >-static int >-test(struct archive *a, struct archive_entry *e) >-{ >- ssize_t len; >- int error_count; >- >- error_count = 0; >- if (S_ISDIR(archive_entry_filetype(e))) >- return 0; >- >- info(" testing: %s\t", archive_entry_pathname(e)); >- while ((len = archive_read_data(a, buffer, sizeof buffer)) > 0) >- /* nothing */; >- if (len < 0) { >- info(" %s\n", archive_error_string(a)); >- ++error_count; >- } else { >- info(" OK\n"); >- } >- >- /* shouldn't be necessary, but it doesn't hurt */ >- ac(archive_read_data_skip(a)); >- >- return error_count; >-} >- >-/* >- * Callback function for reading passphrase. >- * Originally from cpio.c and passphrase.c, libarchive. >- */ >-#define PPBUFF_SIZE 1024 >-static const char * >-passphrase_callback(struct archive *a, void *_client_data) >-{ >- char *p; >- >- (void)a; /* UNUSED */ >- (void)_client_data; /* UNUSED */ >- >- if (passphrase_buf == NULL) { >- passphrase_buf = malloc(PPBUFF_SIZE); >- if (passphrase_buf == NULL) { >- errno = ENOMEM; >- error("malloc()"); >- } >- } >- >- p = readpassphrase("\nEnter password: ", passphrase_buf, >- PPBUFF_SIZE, RPP_ECHO_OFF); >- >- if (p == NULL && errno != EINTR) >- error("Error reading password"); >- >- return p; >-} >- >-/* >- * Main loop: open the zipfile, iterate over its contents and decide what >- * to do with each entry. >- */ >-static void >-unzip(const char *fn) >-{ >- struct archive *a; >- struct archive_entry *e; >- int ret; >- uintmax_t total_size, file_count, error_count; >- >- if ((a = archive_read_new()) == NULL) >- error("archive_read_new failed"); >- >- ac(archive_read_support_format_zip(a)); >- >- if (O_arg) >- ac(archive_read_set_format_option(a, "zip", "hdrcharset", O_arg)); >- >- if (P_arg) >- archive_read_add_passphrase(a, P_arg); >- else >- archive_read_set_passphrase_callback(a, NULL, >- &passphrase_callback); >- >- ac(archive_read_open_filename(a, fn, 8192)); >- >- if (!zipinfo_mode) { >- if (!p_opt && !q_opt) >- printf("Archive: %s\n", fn); >- if (v_opt == 1) { >- printf(" Length %sDate Time Name\n", y_str); >- printf(" -------- %s---- ---- ----\n", y_str); >- } else if (v_opt == 2) { >- printf(" Length Method Size Ratio %sDate Time CRC-32 Name\n", y_str); >- printf("-------- ------ ------- ----- %s---- ---- ------ ----\n", y_str); >- } >- } >- >- total_size = 0; >- file_count = 0; >- error_count = 0; >- for (;;) { >- ret = archive_read_next_header(a, &e); >- if (ret == ARCHIVE_EOF) >- break; >- ac(ret); >- if (!zipinfo_mode) { >- if (t_opt) >- error_count += test(a, e); >- else if (v_opt) >- list(a, e); >- else if (p_opt || c_opt) >- extract_stdout(a, e); >- else >- extract(a, e); >- } else { >- if (Z1_opt) >- list(a, e); >- } >- >- total_size += archive_entry_size(e); >- ++file_count; >- } >- >- if (zipinfo_mode) { >- if (v_opt == 1) { >- printf(" -------- %s-------\n", y_str); >- printf(" %8ju %s%ju file%s\n", >- total_size, y_str, file_count, file_count != 1 ? "s" : ""); >- } else if (v_opt == 2) { >- printf("-------- ------- --- %s-------\n", y_str); >- printf("%8ju %7ju 0%% %s%ju file%s\n", >- total_size, total_size, y_str, file_count, >- file_count != 1 ? "s" : ""); >- } >- } >- >- ac(archive_read_free(a)); >- >- if (passphrase_buf != NULL) { >- memset_s(passphrase_buf, PPBUFF_SIZE, 0, PPBUFF_SIZE); >- free(passphrase_buf); >- } >- >- if (t_opt) { >- if (error_count > 0) { >- errorx("%ju checksum error(s) found.", error_count); >- } >- else { >- printf("No errors detected in compressed data of %s.\n", >- fn); >- } >- } >-} >- >-static void >-usage(void) >-{ >- >- fprintf(stderr, >-"Usage: unzip [-aCcfjLlnopqtuvyZ1] [{-O|-I} encoding] [-d dir] [-x pattern] [-P password] zipfile\n" >-" [member ...]\n"); >- exit(EXIT_FAILURE); >-} >- >-static int >-getopts(int argc, char *argv[]) >-{ >- int opt; >- >- optreset = optind = 1; >- while ((opt = getopt(argc, argv, "aCcd:fI:jLlnO:opP:qtuvx:yZ1")) != -1) >- switch (opt) { >- case '1': >- Z1_opt = 1; >- break; >- case 'a': >- a_opt = 1; >- break; >- case 'C': >- C_opt = 1; >- break; >- case 'c': >- c_opt = 1; >- break; >- case 'd': >- d_arg = optarg; >- break; >- case 'f': >- f_opt = 1; >- break; >- case 'I': >- case 'O': >- O_arg = optarg; >- case 'j': >- j_opt = 1; >- break; >- case 'L': >- L_opt = 1; >- break; >- case 'l': >- if (v_opt == 0) >- v_opt = 1; >- break; >- case 'n': >- n_opt = 1; >- break; >- case 'o': >- o_opt = 1; >- q_opt = 1; >- break; >- case 'p': >- p_opt = 1; >- break; >- case 'P': >- P_arg = optarg; >- break; >- case 'q': >- q_opt = 1; >- break; >- case 't': >- t_opt = 1; >- break; >- case 'u': >- u_opt = 1; >- break; >- case 'v': >- v_opt = 2; >- break; >- case 'x': >- add_pattern(&exclude, optarg); >- break; >- case 'y': >- y_str = " "; >- break; >- case 'Z': >- zipinfo_mode = 1; >- break; >- default: >- usage(); >- } >- >- return (optind); >-} >- >-int >-main(int argc, char *argv[]) >-{ >- const char *zipfile; >- int nopts; >- >- if (isatty(STDOUT_FILENO)) >- tty = 1; >- >- if (getenv("UNZIP_DEBUG") != NULL) >- unzip_debug = 1; >- for (int i = 0; i < argc; ++i) >- debug("%s%c", argv[i], (i < argc - 1) ? ' ' : '\n'); >- >- /* >- * Info-ZIP's unzip(1) expects certain options to come before the >- * zipfile name, and others to come after - though it does not >- * enforce this. For simplicity, we accept *all* options both >- * before and after the zipfile name. >- */ >- nopts = getopts(argc, argv); >- >- /* >- * When more of the zipinfo mode options are implemented, this >- * will need to change. >- */ >- if (zipinfo_mode && !Z1_opt) { >- printf("Zipinfo mode needs additional options\n"); >- exit(EXIT_FAILURE); >- } >- >- if (argc <= nopts) >- usage(); >- zipfile = argv[nopts++]; >- >- if (strcmp(zipfile, "-") == 0) >- zipfile = NULL; /* STDIN */ >- >- while (nopts < argc && *argv[nopts] != '-') >- add_pattern(&include, argv[nopts++]); >- >- nopts--; /* fake argv[0] */ >- nopts += getopts(argc - nopts, argv + nopts); >- >- if (n_opt + o_opt + u_opt > 1) >- errorx("-n, -o and -u are contradictory"); >- >- unzip(zipfile); >- >- exit(EXIT_SUCCESS); >-}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 272845
: 243738