aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2023-07-24 05:42:43 +0000
committerMartin Matuska <mm@FreeBSD.org>2024-05-04 11:53:07 +0000
commitcd09ca5e71a541c47752782d0b710bc95d97cbef (patch)
tree2ff5fbb504c7e48d1fc9553bfeb20f7cfcf614d2
parentd2291dbb3ccbb772fdeb9fdae88602771564e607 (diff)
downloadsrc-cd09ca5e71a541c47752782d0b710bc95d97cbef.tar.gz
src-cd09ca5e71a541c47752782d0b710bc95d97cbef.zip
libarchive: merge from vendor branch
Libarchive 3.7.0 Important changes (relevant to FreeBSD): #1814 Do not account for NULL terminator when comparing with "TRAILER!!!" #1818 Add ability to produce multi-frame zstd archives #1840 year 2038 fix for pax archives on platforms with 64-bit time_t #1860 Make single bit bitfields unsigned to avoid clang 16 warning #1869 Fix FreeBSD builds with WARNS=6 #1873 bsdunzip ported to libarchive from FreeBSD #1894 read support for zstd compression in 7zip archives #1918 ARM64 filter support in 7zip archives (cherry picked from commit e64fe029e9d3ce476e77a478318e0c3cd201ff08)
-rw-r--r--contrib/libarchive/NEWS6
-rw-r--r--contrib/libarchive/README.md16
-rw-r--r--contrib/libarchive/SECURITY.md19
-rw-r--r--contrib/libarchive/cpio/cpio.c19
-rw-r--r--contrib/libarchive/cpio/test/test_option_J_upper.c1
-rw-r--r--contrib/libarchive/cpio/test/test_option_c.c6
-rw-r--r--contrib/libarchive/cpio/test/test_option_t.c17
-rw-r--r--contrib/libarchive/libarchive/archive.h4
-rw-r--r--contrib/libarchive/libarchive/archive_digest.c60
-rw-r--r--contrib/libarchive/libarchive/archive_digest_private.h10
-rw-r--r--contrib/libarchive/libarchive/archive_entry.h2
-rw-r--r--contrib/libarchive/libarchive/archive_getdate.c119
-rw-r--r--contrib/libarchive/libarchive/archive_hmac.c15
-rw-r--r--contrib/libarchive/libarchive/archive_hmac_private.h2
-rw-r--r--contrib/libarchive/libarchive/archive_openssl_evp_private.h3
-rw-r--r--contrib/libarchive/libarchive/archive_random.c35
-rw-r--r--contrib/libarchive/libarchive/archive_read_data_into_fd.c7
-rw-r--r--contrib/libarchive/libarchive/archive_read_disk_posix.c28
-rw-r--r--contrib/libarchive/libarchive/archive_read_open_file.c4
-rw-r--r--contrib/libarchive/libarchive/archive_read_set_options.321
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_filter_zstd.c14
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_7zip.c196
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_cab.c8
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_cpio.c6
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_iso9660.c12
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_lha.c16
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_mtree.c8
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_rar.c17
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_warc.c6
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_xar.c8
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_zip.c2
-rw-r--r--contrib/libarchive/libarchive/archive_string.c4
-rw-r--r--contrib/libarchive/libarchive/archive_util.c57
-rw-r--r--contrib/libarchive/libarchive/archive_write.c31
-rw-r--r--contrib/libarchive/libarchive/archive_write_add_filter_compress.c2
-rw-r--r--contrib/libarchive/libarchive/archive_write_add_filter_zstd.c233
-rw-r--r--contrib/libarchive/libarchive/archive_write_disk_posix.c65
-rw-r--r--contrib/libarchive/libarchive/archive_write_private.h1
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_iso9660.c18
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_pax.c27
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_warc.c25
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_xar.c10
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_zip.c19
-rw-r--r--contrib/libarchive/libarchive/test/test_fuzz.c5
-rw-r--r--contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip.c346
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_deflate_arm64.7z.uu64
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_lzma2_arm.7z.uu50
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_lzma2_arm64.7z.uu54
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_solid_zstd.7z.uu9
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_zstd.7z.uu12
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_arm.7z.uu61
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_bcj.7z.uu56
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_nobcj.7z.uu56
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_rar5.c2
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_zip.c5
-rw-r--r--contrib/libarchive/libarchive/test/test_short_writes.c2
-rw-r--r--contrib/libarchive/libarchive/test/test_write_filter_zstd.c27
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_zip_compression_store.c17
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_zip_file.c17
-rw-r--r--contrib/libarchive/libarchive/test/test_write_format_zip_file_zip64.c17
-rw-r--r--contrib/libarchive/libarchive/xxhash.c4
-rw-r--r--contrib/libarchive/libarchive_fe/passphrase.c6
-rw-r--r--contrib/libarchive/tar/bsdtar.115
-rw-r--r--contrib/libarchive/tar/test/test_option_lzma.c1
-rw-r--r--contrib/libarchive/tar/util.c17
-rw-r--r--contrib/libarchive/test_utils/test_main.c29
-rw-r--r--contrib/libarchive/unzip/CMakeLists.txt37
-rw-r--r--contrib/libarchive/unzip/bsdunzip.1216
-rw-r--r--contrib/libarchive/unzip/bsdunzip.c1186
-rw-r--r--contrib/libarchive/unzip/bsdunzip_platform.h83
-rw-r--r--contrib/libarchive/unzip/test/CMakeLists.txt80
-rw-r--r--contrib/libarchive/unzip/test/test.h40
-rw-r--r--contrib/libarchive/unzip/test/test_0.c58
-rw-r--r--contrib/libarchive/unzip/test/test_C.c41
-rw-r--r--contrib/libarchive/unzip/test/test_L.c44
-rw-r--r--contrib/libarchive/unzip/test/test_P_encryption.c41
-rw-r--r--contrib/libarchive/unzip/test/test_Z1.c40
-rw-r--r--contrib/libarchive/unzip/test/test_basic.c44
-rw-r--r--contrib/libarchive/unzip/test/test_basic.zip.uu25
-rw-r--r--contrib/libarchive/unzip/test/test_d.c44
-rw-r--r--contrib/libarchive/unzip/test/test_encrypted.zip.uu13
-rw-r--r--contrib/libarchive/unzip/test/test_glob.c44
-rw-r--r--contrib/libarchive/unzip/test/test_j.c44
-rw-r--r--contrib/libarchive/unzip/test/test_n.c48
-rw-r--r--contrib/libarchive/unzip/test/test_not_exist.c36
-rw-r--r--contrib/libarchive/unzip/test/test_o.c47
-rw-r--r--contrib/libarchive/unzip/test/test_p.c39
-rw-r--r--contrib/libarchive/unzip/test/test_q.c44
-rw-r--r--contrib/libarchive/unzip/test/test_singlefile.c41
-rw-r--r--contrib/libarchive/unzip/test/test_singlefile.zip.uu8
-rw-r--r--contrib/libarchive/unzip/test/test_t.c39
-rw-r--r--contrib/libarchive/unzip/test/test_t_bad.c39
-rw-r--r--contrib/libarchive/unzip/test/test_t_bad.zip.uu25
-rw-r--r--contrib/libarchive/unzip/test/test_x.c44
-rw-r--r--lib/libarchive/tests/Makefile8
96 files changed, 4122 insertions, 436 deletions
diff --git a/contrib/libarchive/NEWS b/contrib/libarchive/NEWS
index d6324487691b..61d1ca47340e 100644
--- a/contrib/libarchive/NEWS
+++ b/contrib/libarchive/NEWS
@@ -1,4 +1,8 @@
-Wed 07, 2022: libarchive 3.6.2 released
+Jul 18, 2023: libarchive 3.7.0 released
+
+Jul 14, 2023: bsdunzip port from FreeBSD
+
+Dec 07, 2022: libarchive 3.6.2 released
Apr 08, 2022: libarchive 3.6.1 released
diff --git a/contrib/libarchive/README.md b/contrib/libarchive/README.md
index 404076237871..727ed49856b6 100644
--- a/contrib/libarchive/README.md
+++ b/contrib/libarchive/README.md
@@ -7,7 +7,7 @@ command-line tools that use the libarchive library.
## Questions? Issues?
-* http://www.libarchive.org is the home for ongoing
+* https://www.libarchive.org is the home for ongoing
libarchive development, including documentation,
and links to the libarchive mailing lists.
* To report an issue, use the issue tracker at
@@ -23,6 +23,7 @@ This distribution bundle includes the following major components:
* **tar**: the 'bsdtar' program is a full-featured 'tar' implementation built on libarchive
* **cpio**: the 'bsdcpio' program is a different interface to essentially the same functionality
* **cat**: the 'bsdcat' program is a simple replacement tool for zcat, bzcat, xzcat, and such
+* **unzip**: the 'bsdunzip' program is a simple replacement tool for Info-ZIP's unzip
* **examples**: Some small example programs that you may find useful.
* **examples/minitar**: a compact sample demonstrating use of libarchive.
* **contrib**: Various items sent to me by third parties; please contact the authors with any questions.
@@ -87,7 +88,7 @@ Currently, the library automatically detects and reads the following formats:
* ZIPX archives (with support for bzip2, ppmd8, lzma and xz compressed entries)
* GNU and BSD 'ar' archives
* 'mtree' format
- * 7-Zip archives
+ * 7-Zip archives (including archives that use zstandard compression)
* Microsoft CAB format
* LHA and LZH archives
* RAR and RAR 5.0 archives (with some limitations due to RAR's proprietary status)
@@ -192,6 +193,17 @@ questions we are asked about libarchive:
functions. On those platforms, libarchive will use the non-thread-safe
functions. Patches to improve this are of great interest to us.
+* The function `archive_write_disk_header()` is _not_ thread safe on
+ POSIX machines and could lead to security issue resulting in world
+ writeable directories. Thus it must be mutexed by the calling code.
+ This is due to calling `umask(oldumask = umask(0))`, which sets the
+ umask for the whole process to 0 for a short time frame.
+ In case other thread calls the same function in parallel, it might
+ get interrupted by it and cause the executable to use umask=0 for the
+ remaining execution.
+ This will then lead to implicitely created directories to have 777
+ permissions without sticky bit.
+
* In particular, libarchive's modules to read or write a directory
tree do use `chdir()` to optimize the directory traversals. This
can cause problems for programs that expect to do disk access from
diff --git a/contrib/libarchive/SECURITY.md b/contrib/libarchive/SECURITY.md
new file mode 100644
index 000000000000..6ca188b603fe
--- /dev/null
+++ b/contrib/libarchive/SECURITY.md
@@ -0,0 +1,19 @@
+# Security Policy
+
+If you have discovered a security vulnerability in this project, please report it
+privately. **Do not disclose it as a public issue.** This gives us time to work with you
+to fix the issue before public exposure, reducing the chance that the exploit will be
+used before a patch is released.
+
+You may submit the report in the following ways:
+
+- send an email to security@libarchive.de; and/or
+- send us a [private vulnerability report](https://github.com/libarchive/libarchive/security/advisories/new)
+
+Please provide the following information in your report:
+
+- A description of the vulnerability and its impact
+- How to reproduce the issue
+
+This project is maintained by volunteers on a reasonable-effort basis. As such, we ask
+that you give me 90 days to work on a fix before public exposure.
diff --git a/contrib/libarchive/cpio/cpio.c b/contrib/libarchive/cpio/cpio.c
index 847c92d31449..fbeae4133091 100644
--- a/contrib/libarchive/cpio/cpio.c
+++ b/contrib/libarchive/cpio/cpio.c
@@ -442,6 +442,8 @@ main(int argc, char *argv[])
archive_match_free(cpio->matching);
free_cache(cpio->gname_cache);
free_cache(cpio->uname_cache);
+ archive_read_close(cpio->archive_read_disk);
+ archive_read_free(cpio->archive_read_disk);
free(cpio->destdir);
passphrase_free(cpio->ppbuff);
return (cpio->return_value);
@@ -1151,13 +1153,9 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
time_t mtime;
static time_t now;
struct tm *ltime;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
if (!now)
time(&now);
@@ -1205,15 +1203,10 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
else
fmt = cpio->day_first ? "%e %b %H:%M" : "%b %e %H:%M";
#endif
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ ltime = localtime_s(&tmbuf, &mtime) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
ltime = localtime_r(&mtime, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = mtime;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- ltime = NULL;
- else
- ltime = &tmbuf;
#else
ltime = localtime(&mtime);
#endif
diff --git a/contrib/libarchive/cpio/test/test_option_J_upper.c b/contrib/libarchive/cpio/test/test_option_J_upper.c
index 1d7d05131b3d..e19d599e1ec7 100644
--- a/contrib/libarchive/cpio/test/test_option_J_upper.c
+++ b/contrib/libarchive/cpio/test/test_option_J_upper.c
@@ -43,6 +43,7 @@ DEFINE_TEST(test_option_J_upper)
if (strstr(p, "compression not available") != NULL) {
skipping("This version of bsdcpio was compiled "
"without xz support");
+ free(p);
return;
}
failure("-J option is broken");
diff --git a/contrib/libarchive/cpio/test/test_option_c.c b/contrib/libarchive/cpio/test/test_option_c.c
index 013caed56030..dfa62c13b13e 100644
--- a/contrib/libarchive/cpio/test/test_option_c.c
+++ b/contrib/libarchive/cpio/test/test_option_c.c
@@ -37,10 +37,10 @@ is_octal(const char *p, size_t l)
return (1);
}
-static int
+static long long int
from_octal(const char *p, size_t l)
{
- int r = 0;
+ long long int r = 0;
while (l > 0) {
r *= 8;
@@ -161,7 +161,7 @@ DEFINE_TEST(test_option_c)
assertEqualInt(from_octal(e + 24, 6), uid); /* uid */
assertEqualInt(gid, from_octal(e + 30, 6)); /* gid */
assertEqualMem(e + 36, "000001", 6); /* nlink */
- failure("file entries should have rdev == 0 (dev was 0%o)",
+ failure("file entries should have rdev == 0 (dev was 0%llo)",
from_octal(e + 6, 6));
assertEqualMem(e + 42, "000000", 6); /* rdev */
t = from_octal(e + 48, 11); /* mtime */
diff --git a/contrib/libarchive/cpio/test/test_option_t.c b/contrib/libarchive/cpio/test/test_option_t.c
index 0f2dda27cc20..9eef0da571c4 100644
--- a/contrib/libarchive/cpio/test/test_option_t.c
+++ b/contrib/libarchive/cpio/test/test_option_t.c
@@ -37,13 +37,9 @@ DEFINE_TEST(test_option_t)
char date[32];
char date2[32];
struct tm *tmptr;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
/* List reference archive, make sure the TOC is correct. */
extract_reference_file("test_option_t.cpio");
@@ -95,15 +91,10 @@ DEFINE_TEST(test_option_t)
#ifdef HAVE_LOCALE_H
setlocale(LC_ALL, "");
#endif
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ tmptr = localtime_s(&tmbuf, &mtime) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
tmptr = localtime_r(&mtime, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = mtime;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- tmptr = NULL;
- else
- tmptr = &tmbuf;
#else
tmptr = localtime(&mtime);
#endif
diff --git a/contrib/libarchive/libarchive/archive.h b/contrib/libarchive/libarchive/archive.h
index 5fa56de6c9fd..4182cc55d4a4 100644
--- a/contrib/libarchive/libarchive/archive.h
+++ b/contrib/libarchive/libarchive/archive.h
@@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3006002
+#define ARCHIVE_VERSION_NUMBER 3007000
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -157,7 +157,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.6.2"
+#define ARCHIVE_VERSION_ONLY_STRING "3.7.0"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
diff --git a/contrib/libarchive/libarchive/archive_digest.c b/contrib/libarchive/libarchive/archive_digest.c
index 3361b19ada82..08a9aeb02320 100644
--- a/contrib/libarchive/libarchive/archive_digest.c
+++ b/contrib/libarchive/libarchive/archive_digest.c
@@ -36,6 +36,11 @@
#error Cannot use both OpenSSL and libmd.
#endif
+/* Common in other bcrypt implementations, but missing from VS2008. */
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
+#endif
+
/*
* Message digest functions for Windows platform.
*/
@@ -48,6 +53,26 @@
/*
* Initialize a Message digest.
*/
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+static int
+win_crypto_init(Digest_CTX *ctx, const WCHAR *algo)
+{
+ NTSTATUS status;
+ ctx->valid = 0;
+
+ status = BCryptOpenAlgorithmProvider(&ctx->hAlg, algo, NULL, 0);
+ if (!BCRYPT_SUCCESS(status))
+ return (ARCHIVE_FAILED);
+ status = BCryptCreateHash(ctx->hAlg, &ctx->hHash, NULL, 0, NULL, 0, 0);
+ if (!BCRYPT_SUCCESS(status)) {
+ BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
+ return (ARCHIVE_FAILED);
+ }
+
+ ctx->valid = 1;
+ return (ARCHIVE_OK);
+}
+#else
static int
win_crypto_init(Digest_CTX *ctx, DWORD prov, ALG_ID algId)
{
@@ -70,6 +95,7 @@ win_crypto_init(Digest_CTX *ctx, DWORD prov, ALG_ID algId)
ctx->valid = 1;
return (ARCHIVE_OK);
}
+#endif
/*
* Update a Message digest.
@@ -81,23 +107,37 @@ win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len)
if (!ctx->valid)
return (ARCHIVE_FAILED);
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ BCryptHashData(ctx->hHash,
+ (PUCHAR)(uintptr_t)buf,
+ len, 0);
+#else
CryptHashData(ctx->hash,
(unsigned char *)(uintptr_t)buf,
(DWORD)len, 0);
+#endif
return (ARCHIVE_OK);
}
static int
win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
{
+#if !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA)
DWORD siglen = (DWORD)bufsize;
+#endif
if (!ctx->valid)
return (ARCHIVE_FAILED);
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ BCryptFinishHash(ctx->hHash, buf, (ULONG)bufsize, 0);
+ BCryptDestroyHash(ctx->hHash);
+ BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
+#else
CryptGetHashParam(ctx->hash, HP_HASHVAL, buf, &siglen, 0);
CryptDestroyHash(ctx->hash);
CryptReleaseContext(ctx->cryptProv, 0);
+#endif
ctx->valid = 0;
return (ARCHIVE_OK);
}
@@ -276,7 +316,11 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
static int
__archive_md5init(archive_md5_ctx *ctx)
{
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM));
+#else
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
+#endif
}
static int
@@ -659,7 +703,11 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
static int
__archive_sha1init(archive_sha1_ctx *ctx)
{
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM));
+#else
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
+#endif
}
static int
@@ -919,7 +967,11 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
static int
__archive_sha256init(archive_sha256_ctx *ctx)
{
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM));
+#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
+#endif
}
static int
@@ -1155,7 +1207,11 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
static int
__archive_sha384init(archive_sha384_ctx *ctx)
{
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM));
+#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
+#endif
}
static int
@@ -1415,7 +1471,11 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
static int
__archive_sha512init(archive_sha512_ctx *ctx)
{
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM));
+#else
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
+#endif
}
static int
diff --git a/contrib/libarchive/libarchive/archive_digest_private.h b/contrib/libarchive/libarchive/archive_digest_private.h
index 9b3bd6621bf3..339b4edca48d 100644
--- a/contrib/libarchive/libarchive/archive_digest_private.h
+++ b/contrib/libarchive/libarchive/archive_digest_private.h
@@ -164,6 +164,15 @@
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA512_WIN)
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+/* don't use bcrypt when XP needs to be supported */
+#include <bcrypt.h>
+typedef struct {
+ int valid;
+ BCRYPT_ALG_HANDLE hAlg;
+ BCRYPT_HASH_HANDLE hHash;
+} Digest_CTX;
+#else
#include <windows.h>
#include <wincrypt.h>
typedef struct {
@@ -172,6 +181,7 @@ typedef struct {
HCRYPTHASH hash;
} Digest_CTX;
#endif
+#endif
/* typedefs */
#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
diff --git a/contrib/libarchive/libarchive/archive_entry.h b/contrib/libarchive/libarchive/archive_entry.h
index ff64a4712a56..74033564396d 100644
--- a/contrib/libarchive/libarchive/archive_entry.h
+++ b/contrib/libarchive/libarchive/archive_entry.h
@@ -30,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3006002
+#define ARCHIVE_VERSION_NUMBER 3007000
/*
* Note: archive_entry.h is for use outside of libarchive; the
diff --git a/contrib/libarchive/libarchive/archive_getdate.c b/contrib/libarchive/libarchive/archive_getdate.c
index 39e224cb9010..20ab1b1588fe 100644
--- a/contrib/libarchive/libarchive/archive_getdate.c
+++ b/contrib/libarchive/libarchive/archive_getdate.c
@@ -698,13 +698,9 @@ Convert(time_t Month, time_t Day, time_t Year,
time_t Julian;
int i;
struct tm *ltime;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
if (Year < 69)
Year += 2000;
@@ -731,15 +727,10 @@ Convert(time_t Month, time_t Day, time_t Year,
Julian *= DAY;
Julian += Timezone;
Julian += Hours * HOUR + Minutes * MINUTE + Seconds;
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ ltime = localtime_s(&tmbuf, &Julian) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
ltime = localtime_r(&Julian, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = Julian;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- ltime = NULL;
- else
- ltime = &tmbuf;
#else
ltime = localtime(&Julian);
#endif
@@ -755,36 +746,21 @@ DSTcorrect(time_t Start, time_t Future)
time_t StartDay;
time_t FutureDay;
struct tm *ltime;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
-
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ ltime = localtime_s(&tmbuf, &Start) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
ltime = localtime_r(&Start, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = Start;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- ltime = NULL;
- else
- ltime = &tmbuf;
#else
ltime = localtime(&Start);
#endif
StartDay = (ltime->tm_hour + 1) % 24;
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ ltime = localtime_s(&tmbuf, &Future) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
ltime = localtime_r(&Future, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = Future;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- ltime = NULL;
- else
- ltime = &tmbuf;
#else
ltime = localtime(&Future);
#endif
@@ -799,24 +775,15 @@ RelativeDate(time_t Start, time_t zone, int dstmode,
{
struct tm *tm;
time_t t, now;
-#if defined(HAVE_GMTIME_R) || defined(HAVE__GMTIME64_S)
+#if defined(HAVE_GMTIME_R) || defined(HAVE_GMTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__GMTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
t = Start - zone;
-#if defined(HAVE_GMTIME_R)
+#if defined(HAVE_GMTIME_S)
+ tm = gmtime_s(&tmbuf, &t) ? NULL : &tmbuf;
+#elif defined(HAVE_GMTIME_R)
tm = gmtime_r(&t, &tmbuf);
-#elif defined(HAVE__GMTIME64_S)
- tmptime = t;
- terr = _gmtime64_s(&tmbuf, &tmptime);
- if (terr)
- tm = NULL;
- else
- tm = &tmbuf;
#else
tm = gmtime(&t);
#endif
@@ -835,25 +802,16 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
struct tm *tm;
time_t Month;
time_t Year;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
if (RelMonth == 0)
return 0;
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ tm = localtime_s(&tmbuf, &Start) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
tm = localtime_r(&Start, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = Start;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- tm = NULL;
- else
- tm = &tmbuf;
#else
tm = localtime(&Start);
#endif
@@ -993,10 +951,6 @@ __archive_get_date(time_t now, const char *p)
time_t Start;
time_t tod;
long tzone;
-#if defined(HAVE__LOCALTIME64_S) || defined(HAVE__GMTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
/* Clear out the parsed token array. */
memset(tokens, 0, sizeof(tokens));
@@ -1005,36 +959,26 @@ __archive_get_date(time_t now, const char *p)
gds = &_gds;
/* Look up the current time. */
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ tm = localtime_s(&local, &now) ? NULL : &local;
+#elif defined(HAVE_LOCALTIME_R)
tm = localtime_r(&now, &local);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = now;
- terr = _localtime64_s(&local, &tmptime);
- if (terr)
- tm = NULL;
- else
- tm = &local;
#else
memset(&local, 0, sizeof(local));
tm = localtime(&now);
#endif
if (tm == NULL)
return -1;
-#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE__LOCALTIME64_S)
+#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S)
local = *tm;
#endif
/* Look up UTC if we can and use that to determine the current
* timezone offset. */
-#if defined(HAVE_GMTIME_R)
+#if defined(HAVE_GMTIME_S)
+ gmt_ptr = gmtime_s(&gmt, &now) ? NULL : &gmt;
+#elif defined(HAVE_GMTIME_R)
gmt_ptr = gmtime_r(&now, &gmt);
-#elif defined(HAVE__GMTIME64_S)
- tmptime = now;
- terr = _gmtime64_s(&gmt, &tmptime);
- if (terr)
- gmt_ptr = NULL;
- else
- gmt_ptr = &gmt;
#else
memset(&gmt, 0, sizeof(gmt));
gmt_ptr = gmtime(&now);
@@ -1076,15 +1020,10 @@ __archive_get_date(time_t now, const char *p)
* time components instead of the local timezone. */
if (gds->HaveZone && gmt_ptr != NULL) {
now -= gds->Timezone;
-#if defined(HAVE_GMTIME_R)
+#if defined(HAVE_GMTIME_S)
+ gmt_ptr = gmtime_s(&gmt, &now) ? NULL : &gmt;
+#elif defined(HAVE_GMTIME_R)
gmt_ptr = gmtime_r(&now, &gmt);
-#elif defined(HAVE__GMTIME64_S)
- tmptime = now;
- terr = _gmtime64_s(&gmt, &tmptime);
- if (terr)
- gmt_ptr = NULL;
- else
- gmt_ptr = &gmt;
#else
gmt_ptr = gmtime(&now);
#endif
diff --git a/contrib/libarchive/libarchive/archive_hmac.c b/contrib/libarchive/libarchive/archive_hmac.c
index 0914f38e3670..edb3bf5abd42 100644
--- a/contrib/libarchive/libarchive/archive_hmac.c
+++ b/contrib/libarchive/libarchive/archive_hmac.c
@@ -231,15 +231,20 @@ static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
- OSSL_PARAM params[2];
+ EVP_MAC *mac;
- EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
+ char sha1[] = "SHA1";
+ OSSL_PARAM params[] = {
+ OSSL_PARAM_utf8_string("digest", sha1, sizeof(sha1) - 1),
+ OSSL_PARAM_END
+ };
+
+ mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
*ctx = EVP_MAC_CTX_new(mac);
+ EVP_MAC_free(mac);
if (*ctx == NULL)
return -1;
- EVP_MAC_free(mac);
- params[0] = OSSL_PARAM_construct_utf8_string("digest", (char *)"SHA1", 0);
- params[1] = OSSL_PARAM_construct_end();
+
EVP_MAC_init(*ctx, key, key_len, params);
#else
*ctx = HMAC_CTX_new();
diff --git a/contrib/libarchive/libarchive/archive_hmac_private.h b/contrib/libarchive/libarchive/archive_hmac_private.h
index 50044a045e37..d0fda7f9667a 100644
--- a/contrib/libarchive/libarchive/archive_hmac_private.h
+++ b/contrib/libarchive/libarchive/archive_hmac_private.h
@@ -77,6 +77,8 @@ typedef struct hmac_sha1_ctx archive_hmac_sha1_ctx;
#include <openssl/opensslv.h>
#include <openssl/hmac.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#include <openssl/params.h>
+
typedef EVP_MAC_CTX *archive_hmac_sha1_ctx;
#else
diff --git a/contrib/libarchive/libarchive/archive_openssl_evp_private.h b/contrib/libarchive/libarchive/archive_openssl_evp_private.h
index ebb06702d0c5..8ac4772808e6 100644
--- a/contrib/libarchive/libarchive/archive_openssl_evp_private.h
+++ b/contrib/libarchive/libarchive/archive_openssl_evp_private.h
@@ -33,7 +33,8 @@
#include <openssl/evp.h>
#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memset */
static inline EVP_MD_CTX *EVP_MD_CTX_new(void)
diff --git a/contrib/libarchive/libarchive/archive_random.c b/contrib/libarchive/libarchive/archive_random.c
index 9d1aa493f0c8..301765acd830 100644
--- a/contrib/libarchive/libarchive/archive_random.c
+++ b/contrib/libarchive/libarchive/archive_random.c
@@ -51,16 +51,27 @@ __FBSDID("$FreeBSD$");
#include <pthread.h>
#endif
-static void arc4random_buf(void *, size_t);
+static void la_arc4random_buf(void *, size_t);
#endif /* HAVE_ARC4RANDOM_BUF */
#include "archive.h"
#include "archive_random_private.h"
-#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+/* don't use bcrypt when XP needs to be supported */
+#include <bcrypt.h>
+
+/* Common in other bcrypt implementations, but missing from VS2008. */
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
+#endif
+
+#elif defined(HAVE_WINCRYPT_H)
#include <wincrypt.h>
#endif
+#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
@@ -75,6 +86,20 @@ int
archive_random(void *buf, size_t nbytes)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
+# if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ NTSTATUS status;
+ BCRYPT_ALG_HANDLE hAlg;
+
+ status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, NULL, 0);
+ if (!BCRYPT_SUCCESS(status))
+ return ARCHIVE_FAILED;
+ status = BCryptGenRandom(hAlg, buf, nbytes, 0);
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ if (!BCRYPT_SUCCESS(status))
+ return ARCHIVE_FAILED;
+
+ return ARCHIVE_OK;
+# else
HCRYPTPROV hProv;
BOOL success;
@@ -92,6 +117,10 @@ archive_random(void *buf, size_t nbytes)
}
/* TODO: Does this case really happen? */
return ARCHIVE_FAILED;
+# endif
+#elif !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
+ la_arc4random_buf(buf, nbytes);
+ return ARCHIVE_OK;
#else
arc4random_buf(buf, nbytes);
return ARCHIVE_OK;
@@ -256,7 +285,7 @@ arc4_getbyte(void)
}
static void
-arc4random_buf(void *_buf, size_t n)
+la_arc4random_buf(void *_buf, size_t n)
{
uint8_t *buf = (uint8_t *)_buf;
_ARC4_LOCK();
diff --git a/contrib/libarchive/libarchive/archive_read_data_into_fd.c b/contrib/libarchive/libarchive/archive_read_data_into_fd.c
index 1f210fce146f..81a36125a4ba 100644
--- a/contrib/libarchive/libarchive/archive_read_data_into_fd.c
+++ b/contrib/libarchive/libarchive/archive_read_data_into_fd.c
@@ -95,8 +95,13 @@ archive_read_data_into_fd(struct archive *a, int fd)
"archive_read_data_into_fd");
can_lseek = (fstat(fd, &st) == 0) && S_ISREG(st.st_mode);
- if (!can_lseek)
+ if (!can_lseek) {
nulls = calloc(1, nulls_size);
+ if (!nulls) {
+ r = ARCHIVE_FATAL;
+ goto cleanup;
+ }
+ }
while ((r = archive_read_data_block(a, &buff, &size, &target_offset)) ==
ARCHIVE_OK) {
diff --git a/contrib/libarchive/libarchive/archive_read_disk_posix.c b/contrib/libarchive/libarchive/archive_read_disk_posix.c
index 5a94ec5d4399..e9657f6a72e8 100644
--- a/contrib/libarchive/libarchive/archive_read_disk_posix.c
+++ b/contrib/libarchive/libarchive/archive_read_disk_posix.c
@@ -1670,6 +1670,11 @@ setup_current_filesystem(struct archive_read_disk *a)
else
t->current_filesystem->name_max = nm;
#endif
+ if (t->current_filesystem->name_max == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Cannot determine name_max");
+ return (ARCHIVE_FAILED);
+ }
#endif /* USE_READDIR_R */
return (ARCHIVE_OK);
}
@@ -1860,8 +1865,17 @@ setup_current_filesystem(struct archive_read_disk *a)
#if defined(USE_READDIR_R)
/* Set maximum filename length. */
+#if defined(HAVE_STATVFS)
+ t->current_filesystem->name_max = svfs.f_namelen;
+#else
t->current_filesystem->name_max = sfs.f_namelen;
#endif
+ if (t->current_filesystem->name_max == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Cannot determine name_max");
+ return (ARCHIVE_FAILED);
+ }
+#endif
return (ARCHIVE_OK);
}
@@ -1942,6 +1956,11 @@ setup_current_filesystem(struct archive_read_disk *a)
#if defined(USE_READDIR_R)
/* Set maximum filename length. */
t->current_filesystem->name_max = svfs.f_namemax;
+ if (t->current_filesystem->name_max == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Cannot determine name_max");
+ return (ARCHIVE_FAILED);
+ }
#endif
return (ARCHIVE_OK);
}
@@ -1996,6 +2015,11 @@ setup_current_filesystem(struct archive_read_disk *a)
else
t->current_filesystem->name_max = nm;
# endif /* _PC_NAME_MAX */
+ if (t->current_filesystem->name_max == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Cannot determine name_max");
+ return (ARCHIVE_FAILED);
+ }
#endif /* USE_READDIR_R */
return (ARCHIVE_OK);
}
@@ -2543,7 +2567,11 @@ tree_current_lstat(struct tree *t)
#else
if (tree_enter_working_dir(t) != 0)
return NULL;
+#ifdef HAVE_LSTAT
if (lstat(tree_current_access_path(t), &t->lst) != 0)
+#else
+ if (la_stat(tree_current_access_path(t), &t->lst) != 0)
+#endif
#endif
return NULL;
t->flags |= hasLstat;
diff --git a/contrib/libarchive/libarchive/archive_read_open_file.c b/contrib/libarchive/libarchive/archive_read_open_file.c
index 6001dfd47780..c9dcbb1cfec1 100644
--- a/contrib/libarchive/libarchive/archive_read_open_file.c
+++ b/contrib/libarchive/libarchive/archive_read_open_file.c
@@ -154,10 +154,10 @@ file_skip(struct archive *a, void *client_data, int64_t request)
#ifdef __ANDROID__
/* fileno() isn't safe on all platforms ... see above. */
if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
-#elif HAVE_FSEEKO
- if (fseeko(mine->f, skip, SEEK_CUR) != 0)
#elif HAVE__FSEEKI64
if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
+#elif HAVE_FSEEKO
+ if (fseeko(mine->f, skip, SEEK_CUR) != 0)
#else
if (fseek(mine->f, skip, SEEK_CUR) != 0)
#endif
diff --git a/contrib/libarchive/libarchive/archive_read_set_options.3 b/contrib/libarchive/libarchive/archive_read_set_options.3
index b2db4cbcb893..162b79da48f4 100644
--- a/contrib/libarchive/libarchive/archive_read_set_options.3
+++ b/contrib/libarchive/libarchive/archive_read_set_options.3
@@ -255,6 +255,27 @@ have been concatenated together.
Without this option, only the contents of
the first concatenated archive would be read.
.El
+.It Format zip
+.Bl -tag -compact -width indent
+.It Cm compat-2x
+Libarchive 2.x incorrectly encoded Unicode filenames on
+some platforms.
+This option mimics the libarchive 2.x filename handling
+so that such archives can be read correctly.
+.It Cm hdrcharset
+The value is used as a character set name that will be
+used when translating file names.
+.It Cm ignorecrc32
+Skip the CRC32 check.
+Mostly used for testing.
+.It Cm mac-ext
+Support Mac OS metadata extension that records data in special
+files beginning with a period and underscore.
+Defaults to enabled on Mac OS, disabled on other platforms.
+Use
+.Cm !mac-ext
+to disable.
+.El
.El
.\"
.Sh ERRORS
diff --git a/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c b/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c
index 39f25f1bf88e..1959b5ac3991 100644
--- a/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c
+++ b/contrib/libarchive/libarchive/archive_read_support_filter_zstd.c
@@ -115,9 +115,9 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self,
unsigned prefix;
/* Zstd frame magic values */
- const unsigned zstd_magic = 0xFD2FB528U;
- const unsigned zstd_magic_skippable_start = 0x184D2A50U;
- const unsigned zstd_magic_skippable_mask = 0xFFFFFFF0;
+ unsigned zstd_magic = 0xFD2FB528U;
+ unsigned zstd_magic_skippable_start = 0x184D2A50U;
+ unsigned zstd_magic_skippable_mask = 0xFFFFFFF0;
(void) self; /* UNUSED */
@@ -170,7 +170,7 @@ static int
zstd_bidder_init(struct archive_read_filter *self)
{
struct private_data *state;
- const size_t out_block_size = ZSTD_DStreamOutSize();
+ size_t out_block_size = ZSTD_DStreamOutSize();
void *out_block;
ZSTD_DStream *dstream;
@@ -211,6 +211,7 @@ zstd_filter_read(struct archive_read_filter *self, const void **p)
ssize_t avail_in;
ZSTD_outBuffer out;
ZSTD_inBuffer in;
+ size_t ret;
state = (struct private_data *)self->data;
@@ -219,7 +220,7 @@ zstd_filter_read(struct archive_read_filter *self, const void **p)
/* Try to fill the output buffer. */
while (out.pos < out.size && !state->eof) {
if (!state->in_frame) {
- const size_t ret = ZSTD_initDStream(state->dstream);
+ ret = ZSTD_initDStream(state->dstream);
if (ZSTD_isError(ret)) {
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC,
@@ -249,8 +250,7 @@ zstd_filter_read(struct archive_read_filter *self, const void **p)
in.pos = 0;
{
- const size_t ret =
- ZSTD_decompressStream(state->dstream, &out, &in);
+ ret = ZSTD_decompressStream(state->dstream, &out, &in);
if (ZSTD_isError(ret)) {
archive_set_error(&self->archive->archive,
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c
index 0ba4bee358b2..bb595b3e4b07 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_7zip.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_7zip.c
@@ -41,6 +41,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
+#ifdef HAVE_ZSTD_H
+#include <zstd.h>
+#endif
#include "archive.h"
#include "archive_entry.h"
@@ -80,8 +83,11 @@ __FBSDID("$FreeBSD$");
#define _7Z_IA64 0x03030401
#define _7Z_ARM 0x03030501
#define _7Z_ARMTHUMB 0x03030701
+#define _7Z_ARM64 0xa
#define _7Z_SPARC 0x03030805
+#define _7Z_ZSTD 0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
+
/*
* 7-Zip header property IDs.
*/
@@ -278,6 +284,11 @@ struct _7zip {
z_stream stream;
int stream_valid;
#endif
+ /* Decoding Zstandard data. */
+#if HAVE_ZSTD_H
+ ZSTD_DStream *zstd_dstream;
+ int zstdstream_valid;
+#endif
/* Decoding PPMd data. */
int ppmd7_stat;
CPpmd7 ppmd7_context;
@@ -397,6 +408,9 @@ static int setup_decode_folder(struct archive_read *, struct _7z_folder *,
int);
static void x86_Init(struct _7zip *);
static size_t x86_Convert(struct _7zip *, uint8_t *, size_t);
+static void arm_Init(struct _7zip *);
+static size_t arm_Convert(struct _7zip *, uint8_t *, size_t);
+static size_t arm64_Convert(struct _7zip *, uint8_t *, size_t);
static ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t);
@@ -1027,10 +1041,13 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
case _7Z_COPY:
case _7Z_BZ2:
case _7Z_DEFLATE:
+ case _7Z_ZSTD:
case _7Z_PPMD:
if (coder2 != NULL) {
if (coder2->codec != _7Z_X86 &&
- coder2->codec != _7Z_X86_BCJ2) {
+ coder2->codec != _7Z_X86_BCJ2 &&
+ coder2->codec != _7Z_ARM &&
+ coder2->codec != _7Z_ARM64) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Unsupported filter %lx for %lx",
@@ -1041,6 +1058,8 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
zip->bcj_state = 0;
if (coder2->codec == _7Z_X86)
x86_Init(zip);
+ else if (coder2->codec == _7Z_ARM)
+ arm_Init(zip);
}
break;
default:
@@ -1137,6 +1156,12 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
filters[fi].id = LZMA_FILTER_ARMTHUMB;
fi++;
break;
+#ifdef LZMA_FILTER_ARM64
+ case _7Z_ARM64:
+ filters[fi].id = LZMA_FILTER_ARM64;
+ fi++;
+ break;
+#endif
case _7Z_SPARC:
filters[fi].id = LZMA_FILTER_SPARC;
fi++;
@@ -1222,6 +1247,22 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
"BZ2 codec is unsupported");
return (ARCHIVE_FAILED);
#endif
+ case _7Z_ZSTD:
+ {
+#if defined(HAVE_ZSTD_H)
+ if (zip->zstdstream_valid) {
+ ZSTD_freeDStream(zip->zstd_dstream);
+ zip->zstdstream_valid = 0;
+ }
+ zip->zstd_dstream = ZSTD_createDStream();
+ zip->zstdstream_valid = 1;
+ break;
+#else
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "ZSTD codec is unsupported");
+ return (ARCHIVE_FAILED);
+#endif
+ }
case _7Z_DEFLATE:
#ifdef HAVE_ZLIB_H
if (zip->stream_valid)
@@ -1488,6 +1529,22 @@ decompress(struct archive_read *a, struct _7zip *zip,
t_avail_out = zip->stream.avail_out;
break;
#endif
+#ifdef HAVE_ZSTD_H
+ case _7Z_ZSTD:
+ {
+ ZSTD_inBuffer input = { t_next_in, t_avail_in, 0 }; // src, size, pos
+ ZSTD_outBuffer output = { t_next_out, t_avail_out, 0 }; // dst, size, pos
+
+ size_t const zret = ZSTD_decompressStream(zip->zstd_dstream, &output, &input);
+ if (ZSTD_isError(zret)) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Zstd decompression failed: %s", ZSTD_getErrorName(zret));
+ return ARCHIVE_FAILED;
+ }
+ t_avail_in -= input.pos;
+ t_avail_out -= output.pos;
+ break;
+ }
+#endif
case _7Z_PPMD:
{
uint64_t flush_bytes;
@@ -1572,16 +1629,23 @@ decompress(struct archive_read *a, struct _7zip *zip,
/*
* Decord BCJ.
*/
- if (zip->codec != _7Z_LZMA2 && zip->codec2 == _7Z_X86) {
- size_t l = x86_Convert(zip, buff, *outbytes);
- zip->odd_bcj_size = *outbytes - l;
- if (zip->odd_bcj_size > 0 && zip->odd_bcj_size <= 4 &&
- o_avail_in && ret != ARCHIVE_EOF) {
- memcpy(zip->odd_bcj, ((unsigned char *)buff) + l,
- zip->odd_bcj_size);
- *outbytes = l;
- } else
- zip->odd_bcj_size = 0;
+ if (zip->codec != _7Z_LZMA2) {
+ if (zip->codec2 == _7Z_X86) {
+ size_t l = x86_Convert(zip, buff, *outbytes);
+
+ zip->odd_bcj_size = *outbytes - l;
+ if (zip->odd_bcj_size > 0 && zip->odd_bcj_size <= 4 &&
+ o_avail_in && ret != ARCHIVE_EOF) {
+ memcpy(zip->odd_bcj, ((unsigned char *)buff) + l,
+ zip->odd_bcj_size);
+ *outbytes = l;
+ } else
+ zip->odd_bcj_size = 0;
+ } else if (zip->codec2 == _7Z_ARM) {
+ *outbytes = arm_Convert(zip, buff, *outbytes);
+ } else if (zip->codec2 == _7Z_ARM64) {
+ *outbytes = arm64_Convert(zip, buff, *outbytes);
+ }
}
/*
@@ -3727,6 +3791,116 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size)
return (bufferPos);
}
+static void
+arm_Init(struct _7zip *zip)
+{
+ zip->bcj_ip = 8;
+}
+
+static size_t
+arm_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
+{
+ // This function was adapted from
+ // static size_t bcj_arm(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
+ // in https://git.tukaani.org/xz-embedded.git
+
+ /*
+ * Branch/Call/Jump (BCJ) filter decoders
+ *
+ * Authors: Lasse Collin <lasse.collin@tukaani.org>
+ * Igor Pavlov <https://7-zip.org/>
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+ size_t i;
+ uint32_t addr;
+
+ for (i = 0; i + 4 <= size; i += 4) {
+ if (buf[i + 3] == 0xEB) {
+ // Calculate the transformed addr.
+ addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8)
+ | ((uint32_t)buf[i + 2] << 16);
+ addr <<= 2;
+ addr -= zip->bcj_ip + (uint32_t)i;
+ addr >>= 2;
+
+ // Store the transformed addr in buf.
+ buf[i] = (uint8_t)addr;
+ buf[i + 1] = (uint8_t)(addr >> 8);
+ buf[i + 2] = (uint8_t)(addr >> 16);
+ }
+ }
+
+ zip->bcj_ip += i;
+
+ return i;
+}
+
+static size_t
+arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
+{
+ // This function was adapted from
+ // static size_t bcj_arm64(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
+ // in https://git.tukaani.org/xz-embedded.git
+
+ /*
+ * Branch/Call/Jump (BCJ) filter decoders
+ *
+ * Authors: Lasse Collin <lasse.collin@tukaani.org>
+ * Igor Pavlov <https://7-zip.org/>
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+ size_t i;
+ uint32_t instr;
+ uint32_t addr;
+
+ for (i = 0; i + 4 <= size; i += 4) {
+ instr = (uint32_t)buf[i]
+ | ((uint32_t)buf[i+1] << 8)
+ | ((uint32_t)buf[i+2] << 16)
+ | ((uint32_t)buf[i+3] << 24);
+
+ if ((instr >> 26) == 0x25) {
+ /* BL instruction */
+ addr = instr - ((zip->bcj_ip + (uint32_t)i) >> 2);
+ instr = 0x94000000 | (addr & 0x03FFFFFF);
+
+ buf[i] = (uint8_t)instr;
+ buf[i+1] = (uint8_t)(instr >> 8);
+ buf[i+2] = (uint8_t)(instr >> 16);
+ buf[i+3] = (uint8_t)(instr >> 24);
+ } else if ((instr & 0x9F000000) == 0x90000000) {
+ /* ADRP instruction */
+ addr = ((instr >> 29) & 3) | ((instr >> 3) & 0x1FFFFC);
+
+ /* Only convert values in the range +/-512 MiB. */
+ if ((addr + 0x020000) & 0x1C0000)
+ continue;
+
+ addr -= (zip->bcj_ip + (uint32_t)i) >> 12;
+
+ instr &= 0x9000001F;
+ instr |= (addr & 3) << 29;
+ instr |= (addr & 0x03FFFC) << 3;
+ instr |= (0U - (addr & 0x020000)) & 0xE00000;
+
+ buf[i] = (uint8_t)instr;
+ buf[i+1] = (uint8_t)(instr >> 8);
+ buf[i+2] = (uint8_t)(instr >> 16);
+ buf[i+3] = (uint8_t)(instr >> 24);
+ }
+ }
+
+ zip->bcj_ip += i;
+
+ return i;
+}
+
/*
* Brought from LZMA SDK.
*
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_cab.c b/contrib/libarchive/libarchive/archive_read_support_format_cab.c
index 4d5029b1bd2e..3b552a84de12 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_cab.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_cab.c
@@ -2294,10 +2294,10 @@ lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br)
(br->cache_buffer << 48) |
((uint64_t)strm->next_in[1]) << 40 |
((uint64_t)strm->next_in[0]) << 32 |
- ((uint32_t)strm->next_in[3]) << 24 |
- ((uint32_t)strm->next_in[2]) << 16 |
- ((uint32_t)strm->next_in[5]) << 8 |
- (uint32_t)strm->next_in[4];
+ ((uint64_t)strm->next_in[3]) << 24 |
+ ((uint64_t)strm->next_in[2]) << 16 |
+ ((uint64_t)strm->next_in[5]) << 8 |
+ (uint64_t)strm->next_in[4];
strm->next_in += 6;
strm->avail_in -= 6;
br->cache_avail += 6 * 8;
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_cpio.c b/contrib/libarchive/libarchive/archive_read_support_format_cpio.c
index af94583c2a12..9ed003efd655 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_cpio.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_cpio.c
@@ -441,7 +441,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
/* Compare name to "TRAILER!!!" to test for end-of-archive. */
if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!",
- 11) == 0) {
+ 10) == 0) {
/* TODO: Store file location of start of block. */
archive_clear_error(&a->archive);
return (ARCHIVE_EOF);
@@ -985,14 +985,14 @@ archive_read_format_cpio_cleanup(struct archive_read *a)
static int64_t
le4(const unsigned char *p)
{
- return ((p[0] << 16) + (((int64_t)p[1]) << 24) + (p[2] << 0) + (p[3] << 8));
+ return ((p[0] << 16) | (((int64_t)p[1]) << 24) | (p[2] << 0) | (p[3] << 8));
}
static int64_t
be4(const unsigned char *p)
{
- return ((((int64_t)p[0]) << 24) + (p[1] << 16) + (p[2] << 8) + (p[3]));
+ return ((((int64_t)p[0]) << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
}
/*
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c b/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c
index 390ab84f43e3..b3f537bec800 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_iso9660.c
@@ -1901,7 +1901,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
* NUMBER of RRIP "PX" extension.
* Note: Old mkisofs did not record that FILE SERIAL NUMBER
* in ISO images.
- * Note2: xorriso set 0 to the location of a symlink file.
+ * Note2: xorriso set 0 to the location of a symlink file.
*/
if (file->size == 0 && location >= 0) {
/* If file->size is zero, its location points wrong place,
@@ -1955,7 +1955,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
* made by makefs is not zero and its location is
* the same as those of next regular file. That is
* the same as hard like file and it causes unexpected
- * error.
+ * error.
*/
if (file->size > 0 &&
(file->mode & AE_IFMT) == AE_IFLNK) {
@@ -2747,7 +2747,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
* If directory entries all which are descendant of
* rr_moved are still remaining, expose their.
*/
- if (iso9660->re_files.first != NULL &&
+ if (iso9660->re_files.first != NULL &&
iso9660->rr_moved != NULL &&
iso9660->rr_moved->rr_moved_has_re_only)
/* Expose "rr_moved" entry. */
@@ -3180,11 +3180,11 @@ isodate17(const unsigned char *v)
static time_t
time_from_tm(struct tm *t)
{
-#if HAVE_TIMEGM
+#if HAVE__MKGMTIME
+ return _mkgmtime(t);
+#elif HAVE_TIMEGM
/* Use platform timegm() if available. */
return (timegm(t));
-#elif HAVE__MKGMTIME64
- return (_mkgmtime64(t));
#else
/* Else use direct calculation using POSIX assumptions. */
/* First, fix up tm_yday based on the year/month/day. */
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_lha.c b/contrib/libarchive/libarchive/archive_read_support_format_lha.c
index bcfd42e1d920..fa907a346408 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_lha.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_lha.c
@@ -2009,10 +2009,10 @@ lzh_br_fillup(struct lzh_stream *strm, struct lzh_br *br)
((uint64_t)strm->next_in[0]) << 48 |
((uint64_t)strm->next_in[1]) << 40 |
((uint64_t)strm->next_in[2]) << 32 |
- ((uint32_t)strm->next_in[3]) << 24 |
- ((uint32_t)strm->next_in[4]) << 16 |
- ((uint32_t)strm->next_in[5]) << 8 |
- (uint32_t)strm->next_in[6];
+ ((uint64_t)strm->next_in[3]) << 24 |
+ ((uint64_t)strm->next_in[4]) << 16 |
+ ((uint64_t)strm->next_in[5]) << 8 |
+ (uint64_t)strm->next_in[6];
strm->next_in += 7;
strm->avail_in -= 7;
br->cache_avail += 7 * 8;
@@ -2022,10 +2022,10 @@ lzh_br_fillup(struct lzh_stream *strm, struct lzh_br *br)
(br->cache_buffer << 48) |
((uint64_t)strm->next_in[0]) << 40 |
((uint64_t)strm->next_in[1]) << 32 |
- ((uint32_t)strm->next_in[2]) << 24 |
- ((uint32_t)strm->next_in[3]) << 16 |
- ((uint32_t)strm->next_in[4]) << 8 |
- (uint32_t)strm->next_in[5];
+ ((uint64_t)strm->next_in[2]) << 24 |
+ ((uint64_t)strm->next_in[3]) << 16 |
+ ((uint64_t)strm->next_in[4]) << 8 |
+ (uint64_t)strm->next_in[5];
strm->next_in += 6;
strm->avail_in -= 6;
br->cache_avail += 6 * 8;
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_mtree.c b/contrib/libarchive/libarchive/archive_read_support_format_mtree.c
index 33a804501693..8fa1ede7adff 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_mtree.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_mtree.c
@@ -1280,7 +1280,13 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
mtree->fd = -1;
st = NULL;
}
- } else if (lstat(path, st) == -1) {
+ }
+#ifdef HAVE_LSTAT
+ else if (lstat(path, st) == -1)
+#else
+ else if (la_stat(path, st) == -1)
+#endif
+ {
st = NULL;
}
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_rar.c b/contrib/libarchive/libarchive/archive_read_support_format_rar.c
index 793e8e985214..8f239da9b39d 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_rar.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_rar.c
@@ -1830,13 +1830,9 @@ read_exttime(const char *p, struct rar *rar, const char *endp)
struct tm *tm;
time_t t;
long nsec;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
if (p + 2 > endp)
return (-1);
@@ -1868,15 +1864,10 @@ read_exttime(const char *p, struct rar *rar, const char *endp)
rem = (((unsigned)(unsigned char)*p) << 16) | (rem >> 8);
p++;
}
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ tm = localtime_s(&tmbuf, &t) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
tm = localtime_r(&t, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = t;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- tm = NULL;
- else
- tm = &tmbuf;
#else
tm = localtime(&t);
#endif
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_warc.c b/contrib/libarchive/libarchive/archive_read_support_format_warc.c
index 27329962d6d1..61ab29ea145d 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_warc.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_warc.c
@@ -530,11 +530,11 @@ strtoi_lim(const char *str, const char **ep, int llim, int ulim)
static time_t
time_from_tm(struct tm *t)
{
-#if HAVE_TIMEGM
+#if HAVE__MKGMTIME
+ return _mkgmtime(t);
+#elif HAVE_TIMEGM
/* Use platform timegm() if available. */
return (timegm(t));
-#elif HAVE__MKGMTIME64
- return (_mkgmtime64(t));
#else
/* Else use direct calculation using POSIX assumptions. */
/* First, fix up tm_yday based on the year/month/day. */
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_xar.c b/contrib/libarchive/libarchive/archive_read_support_format_xar.c
index ec5b06edacd5..ec9cb1981f3d 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_xar.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_xar.c
@@ -1127,7 +1127,7 @@ atohex(unsigned char *b, size_t bsize, const char *p, size_t psize)
x |= p[1] - '0';
else
return (-1);
-
+
*b++ = x;
bsize--;
p += 2;
@@ -1139,11 +1139,11 @@ atohex(unsigned char *b, size_t bsize, const char *p, size_t psize)
static time_t
time_from_tm(struct tm *t)
{
-#if HAVE_TIMEGM
+#if HAVE__MKGMTIME
+ return _mkgmtime(t);
+#elif HAVE_TIMEGM
/* Use platform timegm() if available. */
return (timegm(t));
-#elif HAVE__MKGMTIME64
- return (_mkgmtime64(t));
#else
/* Else use direct calculation using POSIX assumptions. */
/* First, fix up tm_yday based on the year/month/day. */
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_zip.c b/contrib/libarchive/libarchive/archive_read_support_format_zip.c
index 75df44ba93aa..0e05ea59ce67 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_zip.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_zip.c
@@ -2227,7 +2227,7 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
to_consume = zip->bzstream.total_in_lo32;
__archive_read_consume(a, to_consume);
- total_out = ((uint64_t) zip->bzstream.total_out_hi32 << 32) +
+ total_out = ((uint64_t) zip->bzstream.total_out_hi32 << 32) |
zip->bzstream.total_out_lo32;
zip->entry_bytes_remaining -= to_consume;
diff --git a/contrib/libarchive/libarchive/archive_string.c b/contrib/libarchive/libarchive/archive_string.c
index 0fd918f47909..65999c001763 100644
--- a/contrib/libarchive/libarchive/archive_string.c
+++ b/contrib/libarchive/libarchive/archive_string.c
@@ -1324,6 +1324,10 @@ free_sconv_object(struct archive_string_conv *sc)
}
#if defined(_WIN32) && !defined(__CYGWIN__)
+# if defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+# define GetOEMCP() CP_OEMCP
+# endif
+
static unsigned
my_atoi(const char *p)
{
diff --git a/contrib/libarchive/libarchive/archive_util.c b/contrib/libarchive/libarchive/archive_util.c
index 086e85d9df8e..83fcaac82003 100644
--- a/contrib/libarchive/libarchive/archive_util.c
+++ b/contrib/libarchive/libarchive/archive_util.c
@@ -42,9 +42,20 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_STRING_H
#include <string.h>
#endif
-#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+/* don't use bcrypt when XP needs to be supported */
+#include <bcrypt.h>
+
+/* Common in other bcrypt implementations, but missing from VS2008. */
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
+#endif
+
+#elif defined(HAVE_WINCRYPT_H)
#include <wincrypt.h>
#endif
+#endif
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
@@ -233,14 +244,16 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
L'm', L'n', L'o', L'p', L'q', L'r', L's', L't',
L'u', L'v', L'w', L'x', L'y', L'z'
};
- HCRYPTPROV hProv;
struct archive_wstring temp_name;
wchar_t *ws;
DWORD attr;
wchar_t *xp, *ep;
int fd;
-
- hProv = (HCRYPTPROV)NULL;
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ BCRYPT_ALG_HANDLE hAlg = NULL;
+#else
+ HCRYPTPROV hProv = (HCRYPTPROV)NULL;
+#endif
fd = -1;
ws = NULL;
@@ -314,23 +327,42 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
abort();
}
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM,
+ NULL, 0))) {
+ la_dosmaperr(GetLastError());
+ goto exit_tmpfile;
+ }
+#else
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
la_dosmaperr(GetLastError());
goto exit_tmpfile;
}
+#endif
for (;;) {
wchar_t *p;
HANDLE h;
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ CREATEFILE2_EXTENDED_PARAMETERS createExParams;
+#endif
/* Generate a random file name through CryptGenRandom(). */
p = xp;
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ if (!BCRYPT_SUCCESS(BCryptGenRandom(hAlg, (PUCHAR)p,
+ (DWORD)(ep - p)*sizeof(wchar_t), 0))) {
+ la_dosmaperr(GetLastError());
+ goto exit_tmpfile;
+ }
+#else
if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t),
(BYTE*)p)) {
la_dosmaperr(GetLastError());
goto exit_tmpfile;
}
+#endif
for (; p < ep; p++)
*p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))];
@@ -347,6 +379,17 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
/* mkstemp */
attr = FILE_ATTRIBUTE_NORMAL;
}
+# if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */
+ ZeroMemory(&createExParams, sizeof(createExParams));
+ createExParams.dwSize = sizeof(createExParams);
+ createExParams.dwFileAttributes = attr & 0xFFFF;
+ createExParams.dwFileFlags = attr & 0xFFF00000;
+ h = CreateFile2(ws,
+ GENERIC_READ | GENERIC_WRITE | DELETE,
+ 0,/* Not share */
+ CREATE_NEW,
+ &createExParams);
+#else
h = CreateFileW(ws,
GENERIC_READ | GENERIC_WRITE | DELETE,
0,/* Not share */
@@ -354,6 +397,7 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
CREATE_NEW,/* Create a new file only */
attr,
NULL);
+#endif
if (h == INVALID_HANDLE_VALUE) {
/* The same file already exists. retry with
* a new filename. */
@@ -372,8 +416,13 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
break;/* success! */
}
exit_tmpfile:
+#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
+ if (hAlg != NULL)
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+#else
if (hProv != (HCRYPTPROV)NULL)
CryptReleaseContext(hProv, 0);
+#endif
free(ws);
if (template == temp_name.s)
archive_wstring_free(&temp_name);
diff --git a/contrib/libarchive/libarchive/archive_write.c b/contrib/libarchive/libarchive/archive_write.c
index 3d3ba41f523e..452836076dfa 100644
--- a/contrib/libarchive/libarchive/archive_write.c
+++ b/contrib/libarchive/libarchive/archive_write.c
@@ -310,6 +310,25 @@ __archive_write_output(struct archive_write *a, const void *buff, size_t length)
return (__archive_write_filter(a->filter_first, buff, length));
}
+static int
+__archive_write_filters_flush(struct archive_write *a)
+{
+ struct archive_write_filter *f;
+ int ret, ret1;
+
+ ret = ARCHIVE_OK;
+ for (f = a->filter_first; f != NULL; f = f->next_filter) {
+ if (f->flush != NULL && f->bytes_written > 0) {
+ ret1 = (f->flush)(f);
+ if (ret1 < ret)
+ ret = ret1;
+ if (ret1 < ARCHIVE_WARN)
+ f->state = ARCHIVE_WRITE_FILTER_STATE_FATAL;
+ }
+ }
+ return (ret);
+}
+
int
__archive_write_nulls(struct archive_write *a, size_t length)
{
@@ -740,6 +759,18 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
return (ARCHIVE_FAILED);
}
+ /* Flush filters at boundary. */
+ r2 = __archive_write_filters_flush(a);
+ if (r2 == ARCHIVE_FAILED) {
+ return (ARCHIVE_FAILED);
+ }
+ if (r2 == ARCHIVE_FATAL) {
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return (ARCHIVE_FATAL);
+ }
+ if (r2 < ret)
+ ret = r2;
+
/* Format and write header. */
r2 = ((a->format_write_header)(a, entry));
if (r2 == ARCHIVE_FAILED) {
diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_compress.c b/contrib/libarchive/libarchive/archive_write_add_filter_compress.c
index d404fae7dba4..3ed269fce943 100644
--- a/contrib/libarchive/libarchive/archive_write_add_filter_compress.c
+++ b/contrib/libarchive/libarchive/archive_write_add_filter_compress.c
@@ -352,7 +352,7 @@ archive_compressor_compress_write(struct archive_write_filter *f,
while (length--) {
c = *bp++;
state->in_count++;
- state->cur_fcode = (c << 16) + state->cur_code;
+ state->cur_fcode = (c << 16) | state->cur_code;
i = ((c << HSHIFT) ^ state->cur_code); /* Xor hashing. */
if (state->hashtab[i] == state->cur_fcode) {
diff --git a/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c b/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c
index e85b7669c50d..f32258b460eb 100644
--- a/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c
+++ b/contrib/libarchive/libarchive/archive_write_add_filter_zstd.c
@@ -31,6 +31,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -50,10 +53,21 @@ __FBSDID("$FreeBSD$");
struct private_data {
int compression_level;
- int threads;
+ int threads;
#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
+ enum {
+ running,
+ finishing,
+ resetting,
+ } state;
+ int frame_per_file;
+ size_t min_frame_size;
+ size_t max_frame_size;
+ size_t cur_frame;
+ size_t cur_frame_in;
+ size_t cur_frame_out;
+ size_t total_in;
ZSTD_CStream *cstream;
- int64_t total_in;
ZSTD_outBuffer out;
#else
struct archive_write_program_data *pdata;
@@ -75,6 +89,7 @@ static int archive_compressor_zstd_options(struct archive_write_filter *,
static int archive_compressor_zstd_open(struct archive_write_filter *);
static int archive_compressor_zstd_write(struct archive_write_filter *,
const void *, size_t);
+static int archive_compressor_zstd_flush(struct archive_write_filter *);
static int archive_compressor_zstd_close(struct archive_write_filter *);
static int archive_compressor_zstd_free(struct archive_write_filter *);
#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
@@ -103,6 +118,7 @@ archive_write_add_filter_zstd(struct archive *_a)
f->data = data;
f->open = &archive_compressor_zstd_open;
f->options = &archive_compressor_zstd_options;
+ f->flush = &archive_compressor_zstd_flush;
f->close = &archive_compressor_zstd_close;
f->free = &archive_compressor_zstd_free;
f->code = ARCHIVE_FILTER_ZSTD;
@@ -110,6 +126,11 @@ archive_write_add_filter_zstd(struct archive *_a)
data->compression_level = CLEVEL_DEFAULT;
data->threads = 0;
#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
+ data->frame_per_file = 0;
+ data->min_frame_size = 0;
+ data->max_frame_size = SIZE_MAX;
+ data->cur_frame_in = 0;
+ data->cur_frame_out = 0;
data->cstream = ZSTD_createCStream();
if (data->cstream == NULL) {
free(data);
@@ -147,29 +168,18 @@ archive_compressor_zstd_free(struct archive_write_filter *f)
return (ARCHIVE_OK);
}
-static int string_is_numeric (const char* value)
+static int string_to_number(const char *string, intmax_t *numberp)
{
- size_t len = strlen(value);
- size_t i;
-
- if (len == 0) {
- return (ARCHIVE_WARN);
- }
- else if (len == 1 && !(value[0] >= '0' && value[0] <= '9')) {
- return (ARCHIVE_WARN);
- }
- else if (!(value[0] >= '0' && value[0] <= '9') &&
- value[0] != '-' && value[0] != '+') {
- return (ARCHIVE_WARN);
- }
-
- for (i = 1; i < len; i++) {
- if (!(value[i] >= '0' && value[i] <= '9')) {
- return (ARCHIVE_WARN);
- }
- }
-
- return (ARCHIVE_OK);
+ char *end;
+
+ if (string == NULL || *string == '\0')
+ return (ARCHIVE_WARN);
+ *numberp = strtoimax(string, &end, 10);
+ if (end == string || *end != '\0' || errno == EOVERFLOW) {
+ *numberp = 0;
+ return (ARCHIVE_WARN);
+ }
+ return (ARCHIVE_OK);
}
/*
@@ -182,13 +192,13 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
struct private_data *data = (struct private_data *)f->data;
if (strcmp(key, "compression-level") == 0) {
- int level = atoi(value);
+ intmax_t level;
+ if (string_to_number(value, &level) != ARCHIVE_OK) {
+ return (ARCHIVE_WARN);
+ }
/* If we don't have the library, hard-code the max level */
int minimum = CLEVEL_MIN;
int maximum = CLEVEL_MAX;
- if (string_is_numeric(value) != ARCHIVE_OK) {
- return (ARCHIVE_WARN);
- }
#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
maximum = ZSTD_maxCLevel();
#if ZSTD_VERSION_NUMBER >= MINVER_MINCLEVEL
@@ -207,19 +217,40 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
data->compression_level = level;
return (ARCHIVE_OK);
} else if (strcmp(key, "threads") == 0) {
- int threads = atoi(value);
- if (string_is_numeric(value) != ARCHIVE_OK) {
+ intmax_t threads;
+ if (string_to_number(value, &threads) != ARCHIVE_OK) {
return (ARCHIVE_WARN);
}
-
- int minimum = 0;
-
- if (threads < minimum) {
+ if (threads < 0) {
return (ARCHIVE_WARN);
}
-
data->threads = threads;
return (ARCHIVE_OK);
+#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
+ } else if (strcmp(key, "frame-per-file") == 0) {
+ data->frame_per_file = 1;
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "min-frame-size") == 0) {
+ intmax_t min_frame_size;
+ if (string_to_number(value, &min_frame_size) != ARCHIVE_OK) {
+ return (ARCHIVE_WARN);
+ }
+ if (min_frame_size < 0) {
+ return (ARCHIVE_WARN);
+ }
+ data->min_frame_size = min_frame_size;
+ return (ARCHIVE_OK);
+ } else if (strcmp(key, "max-frame-size") == 0) {
+ intmax_t max_frame_size;
+ if (string_to_number(value, &max_frame_size) != ARCHIVE_OK) {
+ return (ARCHIVE_WARN);
+ }
+ if (max_frame_size < 1024) {
+ return (ARCHIVE_WARN);
+ }
+ data->max_frame_size = max_frame_size;
+ return (ARCHIVE_OK);
+#endif
}
/* Note: The "warn" return is just to inform the options
@@ -281,15 +312,22 @@ archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
size_t length)
{
struct private_data *data = (struct private_data *)f->data;
- int ret;
- /* Update statistics */
- data->total_in += length;
+ return (drive_compressor(f, data, 0, buff, length));
+}
- if ((ret = drive_compressor(f, data, 0, buff, length)) != ARCHIVE_OK)
- return (ret);
+/*
+ * Flush the compressed stream.
+ */
+static int
+archive_compressor_zstd_flush(struct archive_write_filter *f)
+{
+ struct private_data *data = (struct private_data *)f->data;
- return (ARCHIVE_OK);
+ if (data->frame_per_file && data->state == running &&
+ data->cur_frame_out > data->min_frame_size)
+ data->state = finishing;
+ return (drive_compressor(f, data, 1, NULL, 0));
}
/*
@@ -300,57 +338,72 @@ archive_compressor_zstd_close(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
- /* Finish zstd frame */
- return drive_compressor(f, data, 1, NULL, 0);
+ if (data->state == running)
+ data->state = finishing;
+ return (drive_compressor(f, data, 1, NULL, 0));
}
/*
* Utility function to push input data through compressor,
* writing full output blocks as necessary.
- *
- * Note that this handles both the regular write case (finishing ==
- * false) and the end-of-archive case (finishing == true).
*/
static int
drive_compressor(struct archive_write_filter *f,
- struct private_data *data, int finishing, const void *src, size_t length)
+ struct private_data *data, int flush, const void *src, size_t length)
{
- ZSTD_inBuffer in = (ZSTD_inBuffer) { src, length, 0 };
+ ZSTD_inBuffer in = { .src = src, .size = length, .pos = 0 };
+ size_t ipos, opos, zstdret = 0;
+ int ret;
for (;;) {
- if (data->out.pos == data->out.size) {
- const int ret = __archive_write_filter(f->next_filter,
- data->out.dst, data->out.size);
+ ipos = in.pos;
+ opos = data->out.pos;
+ switch (data->state) {
+ case running:
+ if (in.pos == in.size)
+ return (ARCHIVE_OK);
+ zstdret = ZSTD_compressStream(data->cstream,
+ &data->out, &in);
+ if (ZSTD_isError(zstdret))
+ goto zstd_fatal;
+ break;
+ case finishing:
+ zstdret = ZSTD_endStream(data->cstream, &data->out);
+ if (ZSTD_isError(zstdret))
+ goto zstd_fatal;
+ if (zstdret == 0)
+ data->state = resetting;
+ break;
+ case resetting:
+ ZSTD_CCtx_reset(data->cstream, ZSTD_reset_session_only);
+ data->cur_frame++;
+ data->cur_frame_in = 0;
+ data->cur_frame_out = 0;
+ data->state = running;
+ break;
+ }
+ data->total_in += in.pos - ipos;
+ data->cur_frame_in += in.pos - ipos;
+ data->cur_frame_out += data->out.pos - opos;
+ if (data->state == running &&
+ data->cur_frame_in >= data->max_frame_size) {
+ data->state = finishing;
+ }
+ if (data->out.pos == data->out.size ||
+ (flush && data->out.pos > 0)) {
+ ret = __archive_write_filter(f->next_filter,
+ data->out.dst, data->out.pos);
if (ret != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ goto fatal;
data->out.pos = 0;
}
-
- /* If there's nothing to do, we're done. */
- if (!finishing && in.pos == in.size)
- return (ARCHIVE_OK);
-
- {
- const size_t zstdret = !finishing ?
- ZSTD_compressStream(data->cstream, &data->out, &in)
- : ZSTD_endStream(data->cstream, &data->out);
-
- if (ZSTD_isError(zstdret)) {
- archive_set_error(f->archive,
- ARCHIVE_ERRNO_MISC,
- "Zstd compression failed: %s",
- ZSTD_getErrorName(zstdret));
- return (ARCHIVE_FATAL);
- }
-
- /* If we're finishing, 0 means nothing left to flush */
- if (finishing && zstdret == 0) {
- const int ret = __archive_write_filter(f->next_filter,
- data->out.dst, data->out.pos);
- return (ret);
- }
- }
}
+zstd_fatal:
+ archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
+ "Zstd compression failed: %s",
+ ZSTD_getErrorName(zstdret));
+fatal:
+ return (ARCHIVE_FATAL);
}
#else /* HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR */
@@ -367,17 +420,9 @@ archive_compressor_zstd_open(struct archive_write_filter *f)
archive_strcpy(&as, "zstd --no-check");
if (data->compression_level < CLEVEL_STD_MIN) {
- struct archive_string as2;
- archive_string_init(&as2);
- archive_string_sprintf(&as2, " --fast=%d", -data->compression_level);
- archive_string_concat(&as, &as2);
- archive_string_free(&as2);
+ archive_string_sprintf(&as, " --fast=%d", -data->compression_level);
} else {
- struct archive_string as2;
- archive_string_init(&as2);
- archive_string_sprintf(&as2, " -%d", data->compression_level);
- archive_string_concat(&as, &as2);
- archive_string_free(&as2);
+ archive_string_sprintf(&as, " -%d", data->compression_level);
}
if (data->compression_level > CLEVEL_STD_MAX) {
@@ -385,11 +430,7 @@ archive_compressor_zstd_open(struct archive_write_filter *f)
}
if (data->threads != 0) {
- struct archive_string as2;
- archive_string_init(&as2);
- archive_string_sprintf(&as2, " --threads=%d", data->threads);
- archive_string_concat(&as, &as2);
- archive_string_free(&as2);
+ archive_string_sprintf(&as, " --threads=%d", data->threads);
}
f->write = archive_compressor_zstd_write;
@@ -408,6 +449,14 @@ archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
}
static int
+archive_compressor_zstd_flush(struct archive_write_filter *f)
+{
+ (void)f; /* UNUSED */
+
+ return (ARCHIVE_OK);
+}
+
+static int
archive_compressor_zstd_close(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
diff --git a/contrib/libarchive/libarchive/archive_write_disk_posix.c b/contrib/libarchive/libarchive/archive_write_disk_posix.c
index 1a36e6708c49..9d52dbfb3941 100644
--- a/contrib/libarchive/libarchive/archive_write_disk_posix.c
+++ b/contrib/libarchive/libarchive/archive_write_disk_posix.c
@@ -397,6 +397,7 @@ static int set_times_from_entry(struct archive_write_disk *);
static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
static ssize_t write_data_block(struct archive_write_disk *,
const char *, size_t);
+static void close_file_descriptor(struct archive_write_disk *);
static int _archive_write_disk_close(struct archive *);
static int _archive_write_disk_free(struct archive *);
@@ -514,7 +515,12 @@ lazy_stat(struct archive_write_disk *a)
* XXX At this point, symlinks should not be hit, otherwise
* XXX a race occurred. Do we want to check explicitly for that?
*/
- if (lstat(a->name, &a->st) == 0) {
+#ifdef HAVE_LSTAT
+ if (lstat(a->name, &a->st) == 0)
+#else
+ if (la_stat(a->name, &a->st) == 0)
+#endif
+ {
a->pst = &a->st;
return (ARCHIVE_OK);
}
@@ -1726,6 +1732,7 @@ _archive_write_disk_finish_entry(struct archive *_a)
r = hfs_write_data_block(
a, null_d, a->file_remaining_bytes);
if (r < 0)
+ close_file_descriptor(a);
return ((int)r);
}
#endif
@@ -1735,6 +1742,7 @@ _archive_write_disk_finish_entry(struct archive *_a)
a->filesize == 0) {
archive_set_error(&a->archive, errno,
"File size could not be restored");
+ close_file_descriptor(a);
return (ARCHIVE_FAILED);
}
#endif
@@ -1744,8 +1752,10 @@ _archive_write_disk_finish_entry(struct archive *_a)
* to see what happened.
*/
a->pst = NULL;
- if ((ret = lazy_stat(a)) != ARCHIVE_OK)
- return (ret);
+ if ((ret = lazy_stat(a)) != ARCHIVE_OK) {
+ close_file_descriptor(a);
+ return (ret);
+ }
/* We can use lseek()/write() to extend the file if
* ftruncate didn't work or isn't available. */
if (a->st.st_size < a->filesize) {
@@ -1753,11 +1763,13 @@ _archive_write_disk_finish_entry(struct archive *_a)
if (lseek(a->fd, a->filesize - 1, SEEK_SET) < 0) {
archive_set_error(&a->archive, errno,
"Seek failed");
+ close_file_descriptor(a);
return (ARCHIVE_FATAL);
}
if (write(a->fd, &nul, 1) < 0) {
archive_set_error(&a->archive, errno,
"Write to restore size failed");
+ close_file_descriptor(a);
return (ARCHIVE_FATAL);
}
a->pst = NULL;
@@ -2154,7 +2166,11 @@ restore_entry(struct archive_write_disk *a)
* then don't follow it.
*/
if (r != 0 || !S_ISDIR(a->mode))
+#ifdef HAVE_LSTAT
r = lstat(a->name, &a->st);
+#else
+ r = la_stat(a->name, &a->st);
+#endif
if (r != 0) {
archive_set_error(&a->archive, errno,
"Can't stat existing object");
@@ -2550,7 +2566,12 @@ _archive_write_disk_close(struct archive *_a)
goto skip_fixup_entry;
} else
#endif
- if (lstat(p->name, &st) != 0 ||
+ if (
+#ifdef HAVE_LSTAT
+ lstat(p->name, &st) != 0 ||
+#else
+ la_stat(p->name, &st) != 0 ||
+#endif
la_verify_filetype(st.st_mode,
p->filetype) == 0) {
goto skip_fixup_entry;
@@ -2565,7 +2586,12 @@ _archive_write_disk_close(struct archive *_a)
goto skip_fixup_entry;
} else
#endif
- if (lstat(p->name, &st) != 0 ||
+ if (
+#ifdef HAVE_LSTAT
+ lstat(p->name, &st) != 0 ||
+#else
+ la_stat(p->name, &st) != 0 ||
+#endif
la_verify_filetype(st.st_mode,
p->filetype) == 0) {
goto skip_fixup_entry;
@@ -2785,8 +2811,8 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
!(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT))
/* Platform doesn't have lstat, so we can't look for symlinks. */
(void)path; /* UNUSED */
- (void)error_number; /* UNUSED */
- (void)error_string; /* UNUSED */
+ (void)a_eno; /* UNUSED */
+ (void)a_estr; /* UNUSED */
(void)flags; /* UNUSED */
(void)checking_linkname; /* UNUSED */
return (ARCHIVE_OK);
@@ -2859,8 +2885,10 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
/* Check that we haven't hit a symlink. */
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT)
r = fstatat(chdir_fd, head, &st, AT_SYMLINK_NOFOLLOW);
-#else
+#elif defined(HAVE_LSTAT)
r = lstat(head, &st);
+#else
+ r = la_stat(head, &st);
#endif
if (r != 0) {
tail[0] = c;
@@ -3558,7 +3586,9 @@ set_time(int fd, int mode, const char *name,
(void)fd; /* UNUSED */
(void)mode; /* UNUSED */
(void)name; /* UNUSED */
+ (void)atime; /* UNUSED */
(void)atime_nsec; /* UNUSED */
+ (void)mtime; /* UNUSED */
(void)mtime_nsec; /* UNUSED */
return (ARCHIVE_WARN);
#endif
@@ -4391,7 +4421,12 @@ fixup_appledouble(struct archive_write_disk *a, const char *pathname)
*/
archive_strncpy(&datafork, pathname, p - pathname);
archive_strcat(&datafork, p + 2);
- if (lstat(datafork.s, &st) == -1 ||
+ if (
+#ifdef HAVE_LSTAT
+ lstat(datafork.s, &st) == -1 ||
+#else
+ la_stat(datafork.s, &st) == -1 ||
+#endif
(st.st_mode & AE_IFMT) != AE_IFREG)
goto skip_appledouble;
@@ -4707,5 +4742,17 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
}
#endif
+/*
+ * Close the file descriptor if one is open.
+ */
+static void close_file_descriptor(struct archive_write_disk* a)
+{
+ if (a->fd >= 0) {
+ close(a->fd);
+ a->fd = -1;
+ }
+}
+
+
#endif /* !_WIN32 || __CYGWIN__ */
diff --git a/contrib/libarchive/libarchive/archive_write_private.h b/contrib/libarchive/libarchive/archive_write_private.h
index 98518a39c39b..3a11208122ea 100644
--- a/contrib/libarchive/libarchive/archive_write_private.h
+++ b/contrib/libarchive/libarchive/archive_write_private.h
@@ -53,6 +53,7 @@ struct archive_write_filter {
const char *key, const char *value);
int (*open)(struct archive_write_filter *);
int (*write)(struct archive_write_filter *, const void *, size_t);
+ int (*flush)(struct archive_write_filter *);
int (*close)(struct archive_write_filter *);
int (*free)(struct archive_write_filter *);
void *data;
diff --git a/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c b/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c
index b3e41d4ab997..2a3ae07fa2b2 100644
--- a/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c
+++ b/contrib/libarchive/libarchive/archive_write_set_format_iso9660.c
@@ -652,7 +652,7 @@ struct iso_option {
#define VOLUME_IDENTIFIER_SIZE 32
/*
- * Usage : !zisofs [DEFAULT]
+ * Usage : !zisofs [DEFAULT]
* : Disable to generate RRIP 'ZF' extension.
* : zisofs
* : Make files zisofs file and generate RRIP 'ZF'
@@ -689,7 +689,7 @@ struct iso9660 {
uint64_t bytes_remaining;
int need_multi_extent;
- /* Temporary string buffer for Joliet extension. */
+ /* Temporary string buffer for Joliet extension. */
struct archive_string utf16be;
struct archive_string mbs;
@@ -2521,12 +2521,11 @@ get_gmoffset(struct tm *tm)
static void
get_tmfromtime(struct tm *tm, time_t *t)
{
-#if HAVE_LOCALTIME_R
+#if HAVE_LOCALTIME_S
+ localtime_s(tm, t);
+#elif HAVE_LOCALTIME_R
tzset();
localtime_r(t, tm);
-#elif HAVE__LOCALTIME64_S
- __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits
- _localtime64_s(tm, &tmp_t);
#else
memcpy(tm, localtime(t), sizeof(*tm));
#endif
@@ -4074,11 +4073,8 @@ write_information_block(struct archive_write *a)
}
memset(info.s, 0, info_size);
opt = 0;
-#if defined(HAVE__CTIME64_S)
- {
- __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
- _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
- }
+#if defined(HAVE_CTIME_S)
+ ctime_s(buf, sizeof(buf), &(iso9660->birth_time));
#elif defined(HAVE_CTIME_R)
ctime_r(&(iso9660->birth_time), buf);
#else
diff --git a/contrib/libarchive/libarchive/archive_write_set_format_pax.c b/contrib/libarchive/libarchive/archive_write_set_format_pax.c
index 2d3c7086e1f9..8ce1d18c61e5 100644
--- a/contrib/libarchive/libarchive/archive_write_set_format_pax.c
+++ b/contrib/libarchive/libarchive/archive_write_set_format_pax.c
@@ -100,6 +100,7 @@ static int has_non_ASCII(const char *);
static void sparse_list_clear(struct pax *);
static int sparse_list_add(struct pax *, int64_t, int64_t);
static char *url_encode(const char *in);
+static time_t get_ustar_max_mtime(void);
/*
* Set output format to 'restricted pax' format.
@@ -605,6 +606,8 @@ archive_write_pax_header(struct archive_write *a,
need_extension = 0;
pax = (struct pax *)a->format_data;
+ const time_t ustar_max_mtime = get_ustar_max_mtime();
+
/* Sanity check. */
if (archive_entry_pathname(entry_original) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -1126,16 +1129,13 @@ archive_write_pax_header(struct archive_write *a,
}
/*
- * Technically, the mtime field in the ustar header can
- * support 33 bits, but many platforms use signed 32-bit time
- * values. The cutoff of 0x7fffffff here is a compromise.
* Yes, this check is duplicated just below; this helps to
* avoid writing an mtime attribute just to handle a
* high-resolution timestamp in "restricted pax" mode.
*/
if (!need_extension &&
((archive_entry_mtime(entry_main) < 0)
- || (archive_entry_mtime(entry_main) >= 0x7fffffff)))
+ || (archive_entry_mtime(entry_main) >= ustar_max_mtime)))
need_extension = 1;
/* I use a star-compatible file flag attribute. */
@@ -1200,7 +1200,7 @@ archive_write_pax_header(struct archive_write *a,
if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED ||
need_extension) {
if (archive_entry_mtime(entry_main) < 0 ||
- archive_entry_mtime(entry_main) >= 0x7fffffff ||
+ archive_entry_mtime(entry_main) >= ustar_max_mtime ||
archive_entry_mtime_nsec(entry_main) != 0)
add_pax_attr_time(&(pax->pax_header), "mtime",
archive_entry_mtime(entry_main),
@@ -1438,7 +1438,7 @@ archive_write_pax_header(struct archive_write *a,
/* Copy mtime, but clip to ustar limits. */
s = archive_entry_mtime(entry_main);
if (s < 0) { s = 0; }
- if (s >= 0x7fffffff) { s = 0x7fffffff; }
+ if (s > ustar_max_mtime) { s = ustar_max_mtime; }
archive_entry_set_mtime(pax_attr_entry, s, 0);
/* Standard ustar doesn't support atime. */
@@ -2061,3 +2061,18 @@ sparse_list_add(struct pax *pax, int64_t offset, int64_t length)
return (_sparse_list_add_block(pax, offset, length, 0));
}
+static time_t
+get_ustar_max_mtime(void)
+{
+ /*
+ * Technically, the mtime field in the ustar header can
+ * support 33 bits. We are using all of them to keep
+ * tar/test/test_option_C_mtree.c simple and passing after 2038.
+ * For platforms that use signed 32-bit time values we
+ * use the 32-bit maximum.
+ */
+ if (sizeof(time_t) > sizeof(int32_t))
+ return (time_t)0x1ffffffff;
+ else
+ return (time_t)0x7fffffff;
+}
diff --git a/contrib/libarchive/libarchive/archive_write_set_format_warc.c b/contrib/libarchive/libarchive/archive_write_set_format_warc.c
index 46b05734121c..0ef003e2fc94 100644
--- a/contrib/libarchive/libarchive/archive_write_set_format_warc.c
+++ b/contrib/libarchive/libarchive/archive_write_set_format_warc.c
@@ -329,30 +329,21 @@ xstrftime(struct archive_string *as, const char *fmt, time_t t)
{
/** like strftime(3) but for time_t objects */
struct tm *rt;
-#if defined(HAVE_GMTIME_R) || defined(HAVE__GMTIME64_S)
+#if defined(HAVE_GMTIME_R) || defined(HAVE_GMTIME_S)
struct tm timeHere;
#endif
-#if defined(HAVE__GMTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
char strtime[100];
size_t len;
-#ifdef HAVE_GMTIME_R
- if ((rt = gmtime_r(&t, &timeHere)) == NULL)
- return;
-#elif defined(HAVE__GMTIME64_S)
- tmptime = t;
- terr = _gmtime64_s(&timeHere, &tmptime);
- if (terr)
- rt = NULL;
- else
- rt = &timeHere;
+#if defined(HAVE_GMTIME_S)
+ rt = gmtime_s(&timeHere, &t) ? NULL : &timeHere;
+#elif defined(HAVE_GMTIME_R)
+ rt = gmtime_r(&t, &timeHere);
#else
- if ((rt = gmtime(&t)) == NULL)
- return;
+ rt = gmtime(&t);
#endif
+ if (!rt)
+ return;
/* leave the hard yacker to our role model strftime() */
len = strftime(strtime, sizeof(strtime)-1, fmt, rt);
archive_strncat(as, strtime, len);
diff --git a/contrib/libarchive/libarchive/archive_write_set_format_xar.c b/contrib/libarchive/libarchive/archive_write_set_format_xar.c
index 9d5e5dd41cbb..7307757d37a1 100644
--- a/contrib/libarchive/libarchive/archive_write_set_format_xar.c
+++ b/contrib/libarchive/libarchive/archive_write_set_format_xar.c
@@ -906,15 +906,11 @@ xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
{
char timestr[100];
struct tm tm;
-#if defined(HAVE__GMTIME64_S)
- __time64_t tmptime;
-#endif
-#if defined(HAVE_GMTIME_R)
+#if defined(HAVE_GMTIME_S)
+ gmtime_s(&tm, &t);
+#elif defined(HAVE_GMTIME_R)
gmtime_r(&t, &tm);
-#elif defined(HAVE__GMTIME64_S)
- tmptime = t;
- _gmtime64_s(&tm, &tmptime);
#else
memcpy(&tm, gmtime(&t), sizeof(tm));
#endif
diff --git a/contrib/libarchive/libarchive/archive_write_set_format_zip.c b/contrib/libarchive/libarchive/archive_write_set_format_zip.c
index 1b48ecf9d63c..84b7d8b14e8f 100644
--- a/contrib/libarchive/libarchive/archive_write_set_format_zip.c
+++ b/contrib/libarchive/libarchive/archive_write_set_format_zip.c
@@ -1382,25 +1382,14 @@ dos_time(const time_t unix_time)
{
struct tm *t;
unsigned int dt;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
- /* This will not preserve time when creating/extracting the archive
- * on two systems with different time zones. */
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ t = localtime_s(&tmbuf, &unix_time) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
t = localtime_r(&unix_time, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = unix_time;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- t = NULL;
- else
- t = &tmbuf;
#else
t = localtime(&unix_time);
#endif
diff --git a/contrib/libarchive/libarchive/test/test_fuzz.c b/contrib/libarchive/libarchive/test/test_fuzz.c
index ba3a553db987..7f85cbb04b35 100644
--- a/contrib/libarchive/libarchive/test/test_fuzz.c
+++ b/contrib/libarchive/libarchive/test/test_fuzz.c
@@ -124,10 +124,9 @@ test_fuzz(const struct files *filesets)
newraw = realloc(rawimage, oldsize + size);
if (!assert(newraw != NULL))
{
- free(rawimage);
- rawimage = NULL;
free(tmp);
- continue;
+ size = 0;
+ break;
}
rawimage = newraw;
memcpy(rawimage + oldsize, tmp, size);
diff --git a/contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c b/contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c
index bca3ce518e21..ad99acfef258 100644
--- a/contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c
+++ b/contrib/libarchive/libarchive/test/test_read_disk_directory_traversals.c
@@ -1608,6 +1608,12 @@ test_parent(void)
int file_count;
int match_count;
int r;
+#if defined(O_PATH) || defined(O_SEARCH) || \
+ (defined(__FreeBSD__) && defined(O_EXEC))
+ const char *ignore_traversals_test4;
+
+ ignore_traversals_test4 = getenv("IGNORE_TRAVERSALS_TEST4");
+#endif
assertMakeDir("lock", 0311);
assertMakeDir("lock/dir1", 0755);
@@ -1784,7 +1790,8 @@ test_parent(void)
if (r == ARCHIVE_FAILED) {
#if defined(O_PATH) || defined(O_SEARCH) || \
(defined(__FreeBSD__) && defined(O_EXEC))
- assertEqualIntA(a, ARCHIVE_OK, r);
+ if (ignore_traversals_test4 == NULL)
+ assertEqualIntA(a, ARCHIVE_OK, r);
#endif
/* Close the disk object. */
archive_read_close(a);
diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip.c b/contrib/libarchive/libarchive/test/test_read_format_7zip.c
index 3c72595aeef7..1eca3936e5b4 100644
--- a/contrib/libarchive/libarchive/test/test_read_format_7zip.c
+++ b/contrib/libarchive/libarchive/test/test_read_format_7zip.c
@@ -30,6 +30,9 @@ __FBSDID("$FreeBSD");
#define open _open
#endif
+#define __LIBARCHIVE_BUILD
+#include <archive_crc32.h>
+
/*
* Extract a non-encoded file.
* The header of the 7z archive files is not encoded.
@@ -284,6 +287,141 @@ test_extract_all_files(const char *refname)
}
/*
+ * Extract multi files.
+ * Like test_extract_all_files, but with zstandard compression.
+ */
+static void
+test_extract_all_files_zstd(const char *refname)
+{
+ struct archive_entry *ae;
+ struct archive *a;
+ char buff[128];
+
+ extract_reference_file(refname);
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_filename(a, refname, 10240));
+
+ /* Verify directory dir1. Note that this comes before the dir1/file1 entry in recent versions of 7-Zip. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt((AE_IFDIR | 0755), archive_entry_mode(ae));
+ assertEqualString("dir1/", archive_entry_pathname(ae));
+ assertEqualInt(2764801, archive_entry_mtime(ae));
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
+
+ /* Verify regular file1. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));
+ assertEqualString("dir1/file1", archive_entry_pathname(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(13, archive_entry_size(ae));
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
+ assertEqualInt(13, archive_read_data(a, buff, sizeof(buff)));
+ assertEqualMem(buff, "aaaaaaaaaaaa\n", 13);
+
+ /* Verify regular file2. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));
+ assertEqualString("file2", archive_entry_pathname(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(26, archive_entry_size(ae));
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
+ assertEqualInt(26, archive_read_data(a, buff, sizeof(buff)));
+ assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\n", 26);
+
+ /* Verify regular file3. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));
+ assertEqualString("file3", archive_entry_pathname(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(39, archive_entry_size(ae));
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
+ assertEqualInt(39, archive_read_data(a, buff, sizeof(buff)));
+ assertEqualMem(buff, "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\n", 39);
+
+ /* Verify regular file4. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae));
+ assertEqualString("file4", archive_entry_pathname(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(52, archive_entry_size(ae));
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
+ assertEqualInt(52, archive_read_data(a, buff, sizeof(buff)));
+ assertEqualMem(buff,
+ "aaaaaaaaaaaa\nbbbbbbbbbbbb\ncccccccccccc\ndddddddddddd\n", 52);
+
+ assertEqualInt(5, archive_file_count(a));
+
+ /* End of archive. */
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ /* Verify archive format. */
+ assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
+ assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a));
+
+ /* Close the archive. */
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+/*
+ * Extract file from an archives using ZSTD compression with and without BCJ.
+ */
+static void
+test_extract_file_zstd_bcj_nobjc(const char *refname)
+{
+ struct archive_entry *ae;
+ struct archive *a;
+ char buff[4096];
+ uint32_t computed_crc = 0;
+ uint32_t expected_crc = 0xbd66eebc;
+
+ extract_reference_file(refname);
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_filename(a, refname, 10240));
+
+ /* Verify regular file: hw. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt((AE_IFREG | 0775), archive_entry_mode(ae));
+ assertEqualString("hw", archive_entry_pathname(ae));
+ assertEqualInt(1685913368, archive_entry_mtime(ae));
+ assertEqualInt(15952, archive_entry_size(ae));
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
+
+ for (;;) {
+ la_ssize_t bytes_read = archive_read_data(a, buff, sizeof(buff));
+ assert(bytes_read >= 0);
+ if (bytes_read == 0) break;
+ computed_crc = crc32(computed_crc, buff, bytes_read);
+ }
+ assertEqualInt(computed_crc, expected_crc);
+
+ assertEqualInt(1, archive_file_count(a));
+
+ /* End of archive. */
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ /* Verify archive format. */
+ assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
+ assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a));
+
+ /* Close the archive. */
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+/*
* Extract last file.
* The header of the 7z archive files is encoded with LZMA.
*/
@@ -782,6 +920,74 @@ DEFINE_TEST(test_read_format_7zip_deflate)
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
+DEFINE_TEST(test_read_format_7zip_zstd)
+{
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+
+ /* Extracting with libzstd */
+ if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
+ skipping(
+ "7zip:zstd decoding is not supported on this platform");
+ } else {
+ test_extract_all_files_zstd("test_read_format_7zip_zstd.7z");
+ }
+
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+DEFINE_TEST(test_read_format_7zip_zstd_solid)
+{
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+
+ /* Extracting with libzstd */
+ if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
+ skipping(
+ "7zip:zstd decoding is not supported on this platform");
+ } else {
+ test_extract_all_files_zstd("test_read_format_7zip_solid_zstd.7z");
+ }
+
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+DEFINE_TEST(test_read_format_7zip_zstd_bcj)
+{
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+
+ /* Extracting with libzstd */
+ if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
+ skipping(
+ "7zip:zstd decoding is not supported on this platform");
+ } else {
+ test_extract_file_zstd_bcj_nobjc("test_read_format_7zip_zstd_bcj.7z");
+ }
+
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+DEFINE_TEST(test_read_format_7zip_zstd_nobcj)
+{
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+
+ /* Extracting with libzstd */
+ if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
+ skipping(
+ "7zip:zstd decoding is not supported on this platform");
+ } else {
+ test_extract_file_zstd_bcj_nobjc("test_read_format_7zip_zstd_nobcj.7z");
+ }
+
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
DEFINE_TEST(test_read_format_7zip_empty)
{
test_empty_archive();
@@ -832,7 +1038,147 @@ DEFINE_TEST(test_read_format_7zip_lzma2)
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
+static void
+test_arm_filter(const char *refname)
+{
+ struct archive *a;
+ struct archive_entry *ae;
+ char buff[7804];
+ uint32_t computed_crc = 0;
+ uint32_t expected_crc = 0x355ec4e1;
+
+ assert((a = archive_read_new()) != NULL);
+
+ extract_reference_file(refname);
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_filename(a, refname, 10240));
+
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae));
+ assertEqualString("hw-gnueabihf", archive_entry_pathname(ae));
+ assertEqualInt(sizeof(buff), archive_entry_size(ae));
+ assertEqualInt(sizeof(buff), archive_read_data(a, buff, sizeof(buff)));
+ computed_crc = crc32(computed_crc, buff, sizeof(buff));
+ assertEqualInt(computed_crc, expected_crc);
+
+ assertEqualInt(1, archive_file_count(a));
+
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+DEFINE_TEST(test_read_format_7zip_zstd_arm)
+{
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+
+ if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
+ skipping(
+ "7zip:zstd decoding is not supported on this platform");
+ } else {
+ test_arm_filter("test_read_format_7zip_zstd_arm.7z");
+ }
+
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+DEFINE_TEST(test_read_format_7zip_lzma2_arm)
+{
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+
+ if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
+ skipping(
+ "7zip:lzma decoding is not supported on this platform");
+ } else {
+ test_arm_filter("test_read_format_7zip_lzma2_arm.7z");
+ }
+
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
DEFINE_TEST(test_read_format_7zip_ppmd)
{
test_ppmd();
}
+
+static void
+test_arm64_filter(const char *refname)
+{
+ struct archive *a;
+ struct archive_entry *ae;
+ char buff[70368];
+ uint32_t computed_crc = 0;
+ uint32_t expected_crc = 0xde97d594;
+
+ assert((a = archive_read_new()) != NULL);
+
+ extract_reference_file(refname);
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_filename(a, refname, 10240));
+
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt((AE_IFREG | 0775), archive_entry_mode(ae));
+ assertEqualString("hw-arm64", archive_entry_pathname(ae));
+ assertEqualInt(sizeof(buff), archive_entry_size(ae));
+ assertEqualInt(sizeof(buff), archive_read_data(a, buff, sizeof(buff)));
+ computed_crc = crc32(computed_crc, buff, sizeof(buff));
+ assertEqualInt(computed_crc, expected_crc);
+
+ assertEqualInt(1, archive_file_count(a));
+
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+DEFINE_TEST(test_read_format_7zip_lzma2_arm64)
+{
+#ifdef HAVE_LZMA_FILTER_ARM64
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+
+ if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
+ skipping(
+ "7zip:lzma decoding is not supported on this platform");
+ } else {
+ test_arm64_filter("test_read_format_7zip_lzma2_arm64.7z");
+ }
+
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+#else
+ skipping("This version of liblzma does not support LZMA_FILTER_ARM64");
+#endif
+}
+
+DEFINE_TEST(test_read_format_7zip_deflate_arm64)
+{
+ struct archive *a;
+
+ assert((a = archive_read_new()) != NULL);
+
+ if (ARCHIVE_OK != archive_read_support_filter_gzip(a)) {
+ skipping(
+ "7zip:deflate decoding is not supported on this platform");
+ } else {
+ test_arm64_filter("test_read_format_7zip_deflate_arm64.7z");
+ }
+
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_deflate_arm64.7z.uu b/contrib/libarchive/libarchive/test/test_read_format_7zip_deflate_arm64.7z.uu
new file mode 100644
index 000000000000..e516ca5b4792
--- /dev/null
+++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_deflate_arm64.7z.uu
@@ -0,0 +1,64 @@
+begin 664 libarchive/test/test_read_format_7zip_deflate_arm64.7z
+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
+3`#)5M-E?M]D!%08!`""`_8$`````
+`
+end
diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_lzma2_arm.7z.uu b/contrib/libarchive/libarchive/test/test_read_format_7zip_lzma2_arm.7z.uu
new file mode 100644
index 000000000000..5a6ade031f22
--- /dev/null
+++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_lzma2_arm.7z.uu
@@ -0,0 +1,50 @@
+begin 664 test_read_format_7zip_lzma2_arm.7z
+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
+D80!B`&D`:`!F````&0`4"@$```-.&5"<V0$5!@$`((#M@0``
+`
+end
diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_lzma2_arm64.7z.uu b/contrib/libarchive/libarchive/test/test_read_format_7zip_lzma2_arm64.7z.uu
new file mode 100644
index 000000000000..3792a187ff02
--- /dev/null
+++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_lzma2_arm64.7z.uu
@@ -0,0 +1,54 @@
+begin 664 libarchive/test/test_read_format_7zip_lzma2_arm64.7z
+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
+C`'(`;0`V`#0````9`!0*`0`R5;397[?9`14&`0`@@/V!````
+`
+end
diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_solid_zstd.7z.uu b/contrib/libarchive/libarchive/test/test_read_format_7zip_solid_zstd.7z.uu
new file mode 100644
index 000000000000..3bffb98f07ea
--- /dev/null
+++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_solid_zstd.7z.uu
@@ -0,0 +1,9 @@
+begin 664 test_read_format_7zip_solid_zstd.7z
+M-WJ\KR<<``1&(FS)O@`````````B`````````$V+D*,HM2_]`$@!``!0*DT8
+M!````"$````HM2_]((+%```P80IB8V0*!X"P/JZA4J4;TS.X,9C'`#4``($S
+M!ZX/T5NC)*"0H'?;G=XO-Y<-`+"F*K87M`OOZ1+1#31#M/`2YN,FY:(1).I)
+M(B(+;9$W4?0*8=3V5N;BSZ)(0UGD/'LOSN"0&#DNX!A2*5\#&8IP$1G=7-]@
+MP\EE$]Z;/%6NU^\_,X:MD?57P#S>.+BINH?CHRX,::[Q5P*!X\DH````%P8V
+?`0F`B``'"P$``2,#`0$%70`0```,@-H*`9/CZP``````
+`
+end
diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd.7z.uu b/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd.7z.uu
new file mode 100644
index 000000000000..acd49c421a6f
--- /dev/null
+++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd.7z.uu
@@ -0,0 +1,12 @@
+begin 664 test_read_format_7zip_zstd.7z
+M-WJ\KR<<``2QPP_C,`$````````C``````````+H!E<HM2_]`$@!``!0*DT8
+M!````!$````HM2_](`U%```080H!``80`BBU+_T`2`$``%`J31@$````%```
+M`"BU+_T@&ET``"!A"F(*`@#`H`'8*+4O_0!(`0``4"I-&`0````6````*+4O
+M_2`G;0``,&$*8@IC"@,4``@8V2BU+_T`2`$``%`J31@$````&0```"BU+_T@
+M-(4``$!A"F(*8PID"@04``@8(QL``($S!ZYMP-,)%[KY0NUS!EQ9<T<AN:R"
+M7Z^`KZ24FV4LJ?"A)\MX&!"$=31!F6U\W/D!@*G'-=Z@#"&#>8R#*L]U;J=*
+M@K`Q6]^1F4MZF33TE2LJK8X@%5MY%P.#1*EM98=_,9"?K'$*_A0YVC)]1ML=
+MK-5-,X82B;/_L`I&FQ!5HP#H````%P:`J`$)@(@`!PL!``$C`P$!!5T`$```
++#(#Z"@%\$`,4````
+`
+end
diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_arm.7z.uu b/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_arm.7z.uu
new file mode 100644
index 000000000000..770e99b3c10d
--- /dev/null
+++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_arm.7z.uu
@@ -0,0 +1,61 @@
+begin 644 test_read_format_7zip_zstd_arm.7z
+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
+166S@9)S9`14&`0`@@.V!````
+`
+end
diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_bcj.7z.uu b/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_bcj.7z.uu
new file mode 100644
index 000000000000..2a75db8972cf
--- /dev/null
+++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_bcj.7z.uu
@@ -0,0 +1,56 @@
+begin 664 test_read_format_7zip_zstd_bcj.7z
+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
+@=P```!D$`````!0*`0``'';'*9?9`14&`0`@@/V!````
+`
+end
diff --git a/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_nobcj.7z.uu b/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_nobcj.7z.uu
new file mode 100644
index 000000000000..c6fed0bebb84
--- /dev/null
+++ b/contrib/libarchive/libarchive/test/test_read_format_7zip_zstd_nobcj.7z.uu
@@ -0,0 +1,56 @@
+begin 664 test_read_format_7zip_zstd_nobcj.7z
+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
+3```<=L<IE]D!%08!`""`_8$`````
+`
+end
diff --git a/contrib/libarchive/libarchive/test/test_read_format_rar5.c b/contrib/libarchive/libarchive/test/test_read_format_rar5.c
index 54aae0ed1784..34f33ccb3f93 100644
--- a/contrib/libarchive/libarchive/test/test_read_format_rar5.c
+++ b/contrib/libarchive/libarchive/test/test_read_format_rar5.c
@@ -1310,6 +1310,8 @@ DEFINE_TEST(test_read_format_rar5_sfx)
assertA(size == archive_read_data(a, buff, size));
assertEqualMem(buff, test_txt, size);
+
+ EPILOGUE();
}
DEFINE_TEST(test_read_format_rar5_decode_number_out_of_bounds_read)
diff --git a/contrib/libarchive/libarchive/test/test_read_format_zip.c b/contrib/libarchive/libarchive/test/test_read_format_zip.c
index 303637dd3fe6..0bd9c1407ab7 100644
--- a/contrib/libarchive/libarchive/test/test_read_format_zip.c
+++ b/contrib/libarchive/libarchive/test/test_read_format_zip.c
@@ -746,6 +746,7 @@ DEFINE_TEST(test_read_format_zip_zstd_one_file)
if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
skipping("zstd is not fully supported on this platform");
archive_read_close(a);
+ archive_read_free(a);
return;
}
extract_reference_file(refname);
@@ -771,6 +772,7 @@ DEFINE_TEST(test_read_format_zip_zstd_one_file_blockread)
if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
skipping("zstd is not fully supported on this platform");
archive_read_close(a);
+ archive_read_free(a);
return;
}
extract_reference_file(refname);
@@ -796,6 +798,7 @@ DEFINE_TEST(test_read_format_zip_zstd_multi)
if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
skipping("zstd is not fully supported on this platform");
archive_read_close(a);
+ archive_read_free(a);
return;
}
extract_reference_file(refname);
@@ -833,6 +836,7 @@ DEFINE_TEST(test_read_format_zip_zstd_multi_blockread)
if (ARCHIVE_OK != archive_read_support_filter_zstd(a)) {
skipping("zstd is not fully supported on this platform");
archive_read_close(a);
+ archive_read_free(a);
return;
}
extract_reference_file(refname);
@@ -1017,6 +1021,7 @@ DEFINE_TEST(test_read_format_zip_lzma_alone_leak)
if(ARCHIVE_OK != archive_read_support_filter_lzma(a)) {
skipping("lzma reading is not fully supported on this platform");
archive_read_close(a);
+ archive_read_free(a);
return;
}
diff --git a/contrib/libarchive/libarchive/test/test_short_writes.c b/contrib/libarchive/libarchive/test/test_short_writes.c
index afa0206f07cd..8221cece1721 100644
--- a/contrib/libarchive/libarchive/test/test_short_writes.c
+++ b/contrib/libarchive/libarchive/test/test_short_writes.c
@@ -171,6 +171,8 @@ checker_free(struct checker *checker)
{
free(checker->shortbuf);
free(checker->fullbuf);
+ archive_read_free(checker->short_archive);
+ archive_read_free(checker->full_archive);
free(checker);
}
diff --git a/contrib/libarchive/libarchive/test/test_write_filter_zstd.c b/contrib/libarchive/libarchive/test/test_write_filter_zstd.c
index 263cea5bc49e..aa77b49860c0 100644
--- a/contrib/libarchive/libarchive/test/test_write_filter_zstd.c
+++ b/contrib/libarchive/libarchive/test/test_write_filter_zstd.c
@@ -133,6 +133,33 @@ DEFINE_TEST(test_write_filter_zstd)
archive_write_set_filter_option(a, NULL, "threads", "-1")); /* negative */
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_filter_option(a, NULL, "threads", "4"));
+#if HAVE_ZSTD_H && HAVE_LIBZSTD_COMPRESSOR
+ /* frame-per-file: boolean */
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "frame-per-file", ""));
+ /* min-frame-size: >= 0 */
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "min-frame-size", ""));
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "min-frame-size", "-1"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-size", "0"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "min-frame-size", "1048576"));
+ /* max-frame-size: >= 1024 */
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "max-frame-size", ""));
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "max-frame-size", "-1"));
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "max-frame-size", "0"));
+ assertEqualIntA(a, ARCHIVE_FAILED,
+ archive_write_set_filter_option(a, NULL, "max-frame-size", "1023"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-size", "1024"));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_write_set_filter_option(a, NULL, "max-frame-size", "1048576"));
+#endif
assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2));
for (i = 0; i < 100; i++) {
snprintf(path, sizeof(path), "file%03d", i);
diff --git a/contrib/libarchive/libarchive/test/test_write_format_zip_compression_store.c b/contrib/libarchive/libarchive/test/test_write_format_zip_compression_store.c
index ed0908787579..b52d170ccea0 100644
--- a/contrib/libarchive/libarchive/test/test_write_format_zip_compression_store.c
+++ b/contrib/libarchive/libarchive/test/test_write_format_zip_compression_store.c
@@ -129,26 +129,17 @@ static void verify_uncompressed_contents(const char *buff, size_t used)
/* Misc variables */
unsigned long crc;
struct tm *tm;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
/* p is the pointer to walk over the central directory,
* q walks over the local headers, the data and the data descriptors. */
const char *p, *q, *local_header, *extra_start;
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ tm = localtime_s(&tmbuf, &now) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
tm = localtime_r(&now, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = now;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- tm = NULL;
- else
- tm = &tmbuf;
#else
tm = localtime(&now);
#endif
diff --git a/contrib/libarchive/libarchive/test/test_write_format_zip_file.c b/contrib/libarchive/libarchive/test/test_write_format_zip_file.c
index 7796a48cdac3..4ccc30360691 100644
--- a/contrib/libarchive/libarchive/test/test_write_format_zip_file.c
+++ b/contrib/libarchive/libarchive/test/test_write_format_zip_file.c
@@ -74,13 +74,9 @@ DEFINE_TEST(test_write_format_zip_file)
struct archive_entry *ae;
time_t t = 1234567890;
struct tm *tm;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
size_t used, buffsize = 1000000;
unsigned long crc;
int file_perm = 00644;
@@ -98,15 +94,10 @@ DEFINE_TEST(test_write_format_zip_file)
zip_compression = 0;
#endif
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ tm = localtime_s(&tmbuf, &t) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
tm = localtime_r(&t, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = t;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- tm = NULL;
- else
- tm = &tmbuf;
#else
tm = localtime(&t);
#endif
diff --git a/contrib/libarchive/libarchive/test/test_write_format_zip_file_zip64.c b/contrib/libarchive/libarchive/test/test_write_format_zip_file_zip64.c
index c4161bc3a89b..6a00fe14c389 100644
--- a/contrib/libarchive/libarchive/test/test_write_format_zip_file_zip64.c
+++ b/contrib/libarchive/libarchive/test/test_write_format_zip_file_zip64.c
@@ -76,13 +76,9 @@ DEFINE_TEST(test_write_format_zip_file_zip64)
struct archive_entry *ae;
time_t t = 1234567890;
struct tm *tm;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
size_t used, buffsize = 1000000;
unsigned long crc;
int file_perm = 00644;
@@ -99,15 +95,10 @@ DEFINE_TEST(test_write_format_zip_file_zip64)
zip_compression = 0;
#endif
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ tm = localtime_s(&tmbuf, &t) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
tm = localtime_r(&t, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = t;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- tm = NULL;
- else
- tm = &tmbuf;
#else
tm = localtime(&t);
#endif
diff --git a/contrib/libarchive/libarchive/xxhash.c b/contrib/libarchive/libarchive/xxhash.c
index f96e9d93493e..beacd2391221 100644
--- a/contrib/libarchive/libarchive/xxhash.c
+++ b/contrib/libarchive/libarchive/xxhash.c
@@ -149,6 +149,10 @@ typedef struct _U32_S { U32 v; } _PACKED U32_S;
#if GCC_VERSION >= 409
__attribute__((__no_sanitize_undefined__))
+#else
+# if defined(__clang__)
+__attribute__((no_sanitize("undefined")))
+# endif
#endif
#if defined(_MSC_VER)
static __inline U32 A32(const void * x)
diff --git a/contrib/libarchive/libarchive_fe/passphrase.c b/contrib/libarchive/libarchive_fe/passphrase.c
index edf72d147182..1cae6a7bc80a 100644
--- a/contrib/libarchive/libarchive_fe/passphrase.c
+++ b/contrib/libarchive/libarchive_fe/passphrase.c
@@ -171,8 +171,10 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
int input, output, save_errno, i, need_restart;
char ch, *p, *end;
struct termios term, oterm;
+#ifdef HAVE_SIGACTION
struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
struct sigaction savetstp, savettin, savettou, savepipe;
+#endif
/* I suppose we could alloc on demand in this case (XXX). */
if (bufsiz == 0) {
@@ -221,6 +223,7 @@ restart:
oterm.c_lflag |= ECHO;
}
+#ifdef HAVE_SIGACTION
/*
* Catch signals that would otherwise cause the user to end
* up with echo turned off in the shell. Don't worry about
@@ -239,6 +242,7 @@ restart:
(void)sigaction(SIGTSTP, &sa, &savetstp);
(void)sigaction(SIGTTIN, &sa, &savettin);
(void)sigaction(SIGTTOU, &sa, &savettou);
+#endif
if (!(flags & RPP_STDIN)) {
int r = write(output, prompt, strlen(prompt));
@@ -276,6 +280,7 @@ restart:
continue;
signo[SIGTTOU] = sigttou;
}
+#ifdef HAVE_SIGACTION
(void)sigaction(SIGALRM, &savealrm, NULL);
(void)sigaction(SIGHUP, &savehup, NULL);
(void)sigaction(SIGINT, &saveint, NULL);
@@ -285,6 +290,7 @@ restart:
(void)sigaction(SIGTSTP, &savetstp, NULL);
(void)sigaction(SIGTTIN, &savettin, NULL);
(void)sigaction(SIGTTOU, &savettou, NULL);
+#endif
if (input != STDIN_FILENO)
(void)close(input);
diff --git a/contrib/libarchive/tar/bsdtar.1 b/contrib/libarchive/tar/bsdtar.1
index b57835adbef2..1b78fbc04943 100644
--- a/contrib/libarchive/tar/bsdtar.1
+++ b/contrib/libarchive/tar/bsdtar.1
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 31, 2020
+.Dd December 1, 2022
.Dt TAR 1
.Os
.Sh NAME
@@ -643,6 +643,19 @@ Specify the number of worker threads to use.
Setting threads to a special value 0 makes
.Xr zstd 1
use as many threads as there are CPU cores on the system.
+.It Cm zstd:frame-per-file
+Start a new compression frame at the beginning of each file in the
+archive.
+.It Cm zstd:min-frame-size Ns = Ns Ar N
+In combination with
+.Cm zstd:frame-per-file ,
+do not start a new compression frame unless the current frame is at least
+.Ar N
+bytes.
+.It Cm zstd:max-frame-size Ns = Ns Ar N
+Start a new compression frame as soon as the current frame exceeds
+.Ar N
+bytes.
.It Cm lzop:compression-level
A decimal integer from 1 to 9 specifying the lzop compression level.
.It Cm xz:compression-level
diff --git a/contrib/libarchive/tar/test/test_option_lzma.c b/contrib/libarchive/tar/test/test_option_lzma.c
index a618ff8a3403..ab6f13f91744 100644
--- a/contrib/libarchive/tar/test/test_option_lzma.c
+++ b/contrib/libarchive/tar/test/test_option_lzma.c
@@ -44,6 +44,7 @@ DEFINE_TEST(test_option_lzma)
if (strstr(p, "Unsupported compression") != NULL) {
skipping("This version of bsdtar was compiled "
"without lzma support");
+ free(p);
return;
}
failure("--lzma option is broken");
diff --git a/contrib/libarchive/tar/util.c b/contrib/libarchive/tar/util.c
index 231c53e2cf6b..37f0d54f4b08 100644
--- a/contrib/libarchive/tar/util.c
+++ b/contrib/libarchive/tar/util.c
@@ -668,13 +668,9 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
time_t tim;
static time_t now;
struct tm *ltime;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
/*
* We avoid collecting the entire list in memory at once by
@@ -746,15 +742,10 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
fmt = bsdtar->day_first ? DAY_FMT " %b %Y" : "%b " DAY_FMT " %Y";
else
fmt = bsdtar->day_first ? DAY_FMT " %b %H:%M" : "%b " DAY_FMT " %H:%M";
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ ltime = localtime_s(&tmbuf, &tim) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
ltime = localtime_r(&tim, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = tim;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- ltime = NULL;
- else
- ltime = &tmbuf;
#else
ltime = localtime(&tim);
#endif
diff --git a/contrib/libarchive/test_utils/test_main.c b/contrib/libarchive/test_utils/test_main.c
index 74250ad748c2..e4b884ee3c44 100644
--- a/contrib/libarchive/test_utils/test_main.c
+++ b/contrib/libarchive/test_utils/test_main.c
@@ -327,7 +327,7 @@ my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi)
int r;
memset(bhfi, 0, sizeof(*bhfi));
- h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL,
+ h = CreateFileA(path, FILE_READ_ATTRIBUTES, 0, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE)
return (0);
@@ -1432,7 +1432,7 @@ assertion_file_time(const char *file, int line,
/* Note: FILE_FLAG_BACKUP_SEMANTICS applies to open
* a directory file. If not, CreateFile() will fail when
* the pathname is a directory. */
- h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
+ h = CreateFileA(pathname, FILE_READ_ATTRIBUTES, 0, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) {
failure_start(file, line, "Can't access %s\n", pathname);
@@ -2345,7 +2345,7 @@ static void assert_version_id(char **qq, size_t *ss)
q += 3;
s -= 3;
}
-
+
/* Skip a single trailing a,b,c, or d. */
if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd')
++q;
@@ -2391,7 +2391,7 @@ void assertVersion(const char *prog, const char *base)
/* Version message should start with name of program, then space. */
assert(s > prog_len + 1);
-
+
failure("Version must start with '%s': ``%s''", base, p);
if (!assertEqualMem(q, base, prog_len)) {
free(p);
@@ -2729,7 +2729,7 @@ canNodump(void)
/* Get extended attribute value from a path */
void *
getXattr(const char *path, const char *name, size_t *sizep)
-{
+{
void *value = NULL;
#if ARCHIVE_XATTR_SUPPORT
ssize_t size;
@@ -3863,18 +3863,14 @@ main(int argc, char **argv)
int test_set[sizeof(tests) / sizeof(tests[0])];
int i = 0, j = 0, tests_run = 0, tests_failed = 0, option;
int testprogdir_len;
-#ifdef PROGRAM
+#ifdef PROGRAM
int tmp2_len;
#endif
time_t now;
struct tm *tmptr;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
struct tm tmbuf;
#endif
-#if defined(HAVE__LOCALTIME64_S)
- errno_t terr;
- __time64_t tmptime;
-#endif
char *refdir_alloc = NULL;
const char *progname;
char **saved_argv;
@@ -4109,15 +4105,10 @@ main(int argc, char **argv)
*/
now = time(NULL);
for (i = 0; ; i++) {
-#if defined(HAVE_LOCALTIME_R)
+#if defined(HAVE_LOCALTIME_S)
+ tmptr = localtime_s(&tmbuf, &now) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
tmptr = localtime_r(&now, &tmbuf);
-#elif defined(HAVE__LOCALTIME64_S)
- tmptime = now;
- terr = _localtime64_s(&tmbuf, &tmptime);
- if (terr)
- tmptr = NULL;
- else
- tmptr = &tmbuf;
#else
tmptr = localtime(&now);
#endif
diff --git a/contrib/libarchive/unzip/CMakeLists.txt b/contrib/libarchive/unzip/CMakeLists.txt
new file mode 100644
index 000000000000..13b983d89db7
--- /dev/null
+++ b/contrib/libarchive/unzip/CMakeLists.txt
@@ -0,0 +1,37 @@
+############################################
+#
+# How to build bsdunzip
+#
+############################################
+IF(ENABLE_UNZIP)
+
+ SET(bsdunzip_SOURCES
+ bsdunzip.c
+ bsdunzip_platform.h
+ ../libarchive_fe/err.c
+ ../libarchive_fe/err.h
+ ../libarchive_fe/lafe_platform.h
+ ../libarchive_fe/passphrase.c
+ ../libarchive_fe/passphrase.h
+ )
+ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libarchive_fe)
+
+ # bsdunzip documentation
+ SET(bsdunzip_MANS bsdunzip.1)
+
+ # How to build bsdunzip
+ ADD_EXECUTABLE(bsdunzip ${bsdunzip_SOURCES})
+ IF(ENABLE_UNZIP_SHARED)
+ TARGET_LINK_LIBRARIES(bsdunzip archive ${ADDITIONAL_LIBS})
+ ELSE(ENABLE_UNZIP_SHARED)
+ TARGET_LINK_LIBRARIES(bsdunzip archive_static ${ADDITIONAL_LIBS})
+ SET_TARGET_PROPERTIES(bsdunzip PROPERTIES COMPILE_DEFINITIONS
+ LIBARCHIVE_STATIC)
+ ENDIF(ENABLE_UNZIP_SHARED)
+
+ # Installation rules
+ INSTALL(TARGETS bsdunzip RUNTIME DESTINATION bin)
+ INSTALL_MAN(${bsdunzip_MANS})
+ENDIF(ENABLE_UNZIP)
+
+add_subdirectory(test)
diff --git a/contrib/libarchive/unzip/bsdunzip.1 b/contrib/libarchive/unzip/bsdunzip.1
new file mode 100644
index 000000000000..3c656ebc46e2
--- /dev/null
+++ b/contrib/libarchive/unzip/bsdunzip.1
@@ -0,0 +1,216 @@
+.\"-
+.\" 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 January 2, 2023
+.Dt BSDUNZIP 1
+.Os
+.Sh NAME
+.Nm bsdunzip
+.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 .
+.Sh CAVEATS
+The
+.Nm
+utility performs two scans of the command-line for arguments before
+and after the archive name, so as to maintain compatibility with
+Info-ZIP unzip.
+As a result, the POSIX
+.Ql --
+double-dash string used to separate options from arguments will need to
+be repeated.
+For example, to extract a "-a.jpg" from "-b.zip" with overwrite, one
+would need to invoke
+.Dl bsdunzip -o -- -a.jpg -- -b.zip
diff --git a/contrib/libarchive/unzip/bsdunzip.c b/contrib/libarchive/unzip/bsdunzip.c
new file mode 100644
index 000000000000..469c69fd6efb
--- /dev/null
+++ b/contrib/libarchive/unzip/bsdunzip.c
@@ -0,0 +1,1186 @@
+/*-
+ * 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 "bsdunzip_platform.h"
+
+#ifdef HAVE_SYS_QUEUE_H
+#include <sys/queue.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <archive.h>
+#include <archive_entry.h>
+#include "passphrase.h"
+#include "err.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) {
+#ifdef HAVE_FNMATCH
+ if (fnmatch(entry->pattern, str, C_opt ? FNM_CASEFOLD : 0) == 0)
+ return (1);
+#else
+#error "Unsupported platform: fnmatch() is required"
+#endif
+ }
+ 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) && (
+#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
+ sb.st_mtimespec.tv_sec > mtime.tv_sec ||
+ (sb.st_mtimespec.tv_sec == mtime.tv_sec &&
+ sb.st_mtimespec.tv_nsec >= mtime.tv_nsec)
+#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+ sb.st_mtim.tv_sec > mtime.tv_sec ||
+ (sb.st_mtim.tv_sec == mtime.tv_sec &&
+ sb.st_mtim.tv_nsec >= mtime.tv_nsec)
+#elif HAVE_STRUCT_STAT_ST_MTIME_N
+ sb.st_mtime > mtime.tv_sec ||
+ (sb.st_mtime == mtime.tv_sec &&
+ sb.st_mtime_n => mtime.tv_nsec)
+#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
+ sb.st_mtime > mtime.tv_sec ||
+ (sb.st_mtime == mtime.tv_sec &&
+ sb.st_mtime_usec => mtime.tv_nsec / 1000)
+#else
+ sb.st_mtime > mtime.tv_sec
+#endif
+ ))
+ 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 = lafe_readpassphrase("\nEnter password: ", passphrase_buf,
+ PPBUFF_SIZE);
+
+ 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 (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(passphrase_buf, 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] [-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:fjLlnopP: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 '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');
+
+#ifdef __GLIBC__
+ /* Prevent GNU getopt(3) from rearranging options. */
+ setenv("POSIXLY_CORRECT", "", 1);
+#endif
+ /*
+ * 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);
+
+ /* There may be residual arguments if we encountered -- */
+ while (nopts < argc)
+ add_pattern(&include, argv[nopts++]);
+
+ if (n_opt + o_opt + u_opt > 1)
+ errorx("-n, -o and -u are contradictory");
+
+ unzip(zipfile);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/contrib/libarchive/unzip/bsdunzip_platform.h b/contrib/libarchive/unzip/bsdunzip_platform.h
new file mode 100644
index 000000000000..5aff5f208eab
--- /dev/null
+++ b/contrib/libarchive/unzip/bsdunzip_platform.h
@@ -0,0 +1,83 @@
+/*-
+ * 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: src/usr.bin/tar/bsdtar_platform.h,v 1.26 2008/12/06 07:37:14 kientzle Exp $
+ */
+
+/*
+ * This header is the first thing included in any of the bsdtar
+ * source files. As far as possible, platform-specific issues should
+ * be dealt with here and not within individual source files.
+ */
+
+#ifndef BSDUNZIP_PLATFORM_H_INCLUDED
+#define BSDUNZIP_PLATFORM_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
+
+/* Get a real definition for __FBSDID if we can */
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+
+/* If not, define it so as to avoid dangling semicolons. */
+#ifndef __FBSDID
+#define __FBSDID(a) struct _undefined_hack
+#endif
+
+#ifdef HAVE_LIBARCHIVE
+/* If we're using the platform libarchive, include system headers. */
+#include <archive.h>
+#include <archive_entry.h>
+#else
+/* Otherwise, include user headers. */
+#include "archive.h"
+#include "archive_entry.h"
+#endif
+
+#ifndef HAVE_GETOPT_OPTRESET
+/*
+ * If platform doesn't use optreset for resetting getopt, declare it so
+ * C source doesn't have to know this platform-specific difference
+ */
+int optreset;
+#endif
+
+/* How to mark functions that don't return. */
+/* This facilitates use of some newer static code analysis tools. */
+#undef __LA_DEAD
+#if defined(__GNUC__) && (__GNUC__ > 2 || \
+ (__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
+#define __LA_DEAD __attribute__((__noreturn__))
+#else
+#define __LA_DEAD
+#endif
+
+#endif /* !BSDUNZIP_PLATFORM_H_INCLUDED */
diff --git a/contrib/libarchive/unzip/test/CMakeLists.txt b/contrib/libarchive/unzip/test/CMakeLists.txt
new file mode 100644
index 000000000000..bdb3445954f1
--- /dev/null
+++ b/contrib/libarchive/unzip/test/CMakeLists.txt
@@ -0,0 +1,80 @@
+############################################
+#
+# How to build bsdunzip_test
+#
+############################################
+IF(ENABLE_UNZIP AND ENABLE_TEST)
+ SET(bsdunzip_test_SOURCES
+ ../../libarchive_fe/err.c
+ ../../test_utils/test_utils.c
+ ../../test_utils/test_main.c
+ test.h
+ test_0.c
+ test_basic.c
+ test_glob.c
+ test_singlefile.c
+ test_C.c
+ test_p.c
+ test_d.c
+ test_j.c
+ test_L.c
+ test_n.c
+ test_o.c
+ test_q.c
+ test_t.c
+ test_t_bad.c
+ test_x.c
+ test_Z1.c
+ test_P_encryption.c
+ )
+
+ #
+ # Register target
+ #
+ ADD_EXECUTABLE(bsdunzip_test ${bsdunzip_test_SOURCES})
+ IF(ENABLE_ACL)
+ SET(TEST_ACL_LIBS "")
+ IF(HAVE_LIBACL)
+ LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY})
+ ENDIF(HAVE_LIBACL)
+ IF(HAVE_LIBRICHACL)
+ LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY})
+ ENDIF(HAVE_LIBRICHACL)
+ TARGET_LINK_LIBRARIES(bsdunzip_test ${TEST_ACL_LIBS})
+ ENDIF(ENABLE_ACL)
+ SET_PROPERTY(TARGET bsdunzip_test PROPERTY COMPILE_DEFINITIONS LIST_H)
+
+ #
+ # Generate list.h by grepping DEFINE_TEST() lines out of the C sources.
+ #
+ GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h
+ ${CMAKE_CURRENT_LIST_FILE} ${bsdunzip_test_SOURCES})
+ SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES
+ ${CMAKE_CURRENT_BINARY_DIR})
+
+ # list.h has a line DEFINE_TEST(testname) for every
+ # test. We can use that to define the tests for cmake by
+ # defining a DEFINE_TEST macro and reading list.h in.
+ MACRO (DEFINE_TEST _testname)
+ ADD_TEST(
+ NAME bsdunzip_${_testname}
+ COMMAND bsdunzip_test -vv
+ -p $<TARGET_FILE:bsdunzip>
+ -r ${CMAKE_CURRENT_SOURCE_DIR}
+ ${_testname})
+ ENDMACRO (DEFINE_TEST _testname)
+
+ INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h)
+ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils)
+ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/unzip/test)
+
+ # Experimental new test handling
+ ADD_CUSTOM_TARGET(run_bsdunzip_test
+ COMMAND bsdunzip_test -p $<TARGET_FILE:bsdunzip>
+ -r ${CMAKE_CURRENT_SOURCE_DIR}
+ -vv)
+ ADD_DEPENDENCIES(run_bsdunzip_test bsdunzip)
+ ADD_DEPENDENCIES(run_all_tests run_bsdunzip_test)
+ENDIF(ENABLE_UNZIP AND ENABLE_TEST)
+
diff --git a/contrib/libarchive/unzip/test/test.h b/contrib/libarchive/unzip/test/test.h
new file mode 100644
index 000000000000..8da017f68e16
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2003-2017 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/* Every test program should #include "test.h" as the first thing. */
+
+#define KNOWNREF "test_basic.zip.uu"
+#define ENVBASE "BSDUNZIP" /* Prefix for environment variables. */
+#define PROGRAM "bsdunzip" /* Name of program being tested. */
+#define PROGRAM_ALIAS "unzip" /* Generic alias for program */
+#undef LIBRARY /* Not testing a library. */
+#undef EXTRA_DUMP /* How to dump extra data */
+#undef EXTRA_ERRNO /* How to dump errno */
+/* How to generate extra version info. */
+#define EXTRA_VERSION (systemf("%s -v", testprog) ? "" : "")
+
+#include "test_common.h"
diff --git a/contrib/libarchive/unzip/test/test_0.c b/contrib/libarchive/unzip/test/test_0.c
new file mode 100644
index 000000000000..41279d388b1f
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_0.c
@@ -0,0 +1,58 @@
+/*-
+ * 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.
+ */
+#include "test.h"
+
+/*
+ * This first test does basic sanity checks on the environment. For
+ * most of these, we just exit on failure.
+ */
+#if !defined(_WIN32) || defined(__CYGWIN__)
+#define DEV_NULL "/dev/null"
+#else
+#define DEV_NULL "NUL"
+#endif
+
+DEFINE_TEST(test_0)
+{
+ struct stat st;
+
+ failure("File %s does not exist?!", testprog);
+ if (!assertEqualInt(0, stat(testprogfile, &st))) {
+ fprintf(stderr,
+ "\nFile %s does not exist; aborting test.\n\n",
+ testprog);
+ exit(1);
+ }
+
+ failure("%s is not executable?!", testprog);
+ if (!assert((st.st_mode & 0111) != 0)) {
+ fprintf(stderr,
+ "\nFile %s not executable; aborting test.\n\n",
+ testprog);
+ exit(1);
+ }
+
+ /* TODO: Ensure that our reference files are available. */
+}
diff --git a/contrib/libarchive/unzip/test/test_C.c b/contrib/libarchive/unzip/test/test_C.c
new file mode 100644
index 000000000000..fc11b970c2f3
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_C.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test C arg - match case-insensitive */
+DEFINE_TEST(test_C)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s -C %s test_basic/caps >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("contents CAPS\n", "test_basic/CAPS");
+}
diff --git a/contrib/libarchive/unzip/test/test_L.c b/contrib/libarchive/unzip/test/test_L.c
new file mode 100644
index 000000000000..4815cb2b139d
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_L.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test L arg - make names lowercase */
+DEFINE_TEST(test_L)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s -L %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("contents a\n", "test_basic/a");
+ assertTextFileContents("contents b\n", "test_basic/b");
+ assertTextFileContents("contents c\n", "test_basic/c");
+ assertTextFileContents("contents CAPS\n", "test_basic/caps");
+}
diff --git a/contrib/libarchive/unzip/test/test_P_encryption.c b/contrib/libarchive/unzip/test/test_P_encryption.c
new file mode 100644
index 000000000000..beabbaa646ee
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_P_encryption.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test P arg - password protected */
+DEFINE_TEST(test_P)
+{
+ const char *reffile = "test_encrypted.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s -P password %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("plaintext\n", "encrypted/file.txt");
+}
diff --git a/contrib/libarchive/unzip/test/test_Z1.c b/contrib/libarchive/unzip/test/test_Z1.c
new file mode 100644
index 000000000000..58dc750030dd
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_Z1.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test -Z1 arg - List filenames */
+DEFINE_TEST(test_Z1)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s -Z1 %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertTextFileContents("test_basic/\ntest_basic/a\ntest_basic/b\ntest_basic/c\ntest_basic/CAPS\n", "test.out");
+ assertEmptyFile("test.err");
+}
diff --git a/contrib/libarchive/unzip/test/test_basic.c b/contrib/libarchive/unzip/test/test_basic.c
new file mode 100644
index 000000000000..e997755e7e57
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_basic.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* This test just does a basic zip decompression */
+DEFINE_TEST(test_basic)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("contents a\n", "test_basic/a");
+ assertTextFileContents("contents b\n", "test_basic/b");
+ assertTextFileContents("contents c\n", "test_basic/c");
+ assertTextFileContents("contents CAPS\n", "test_basic/CAPS");
+}
diff --git a/contrib/libarchive/unzip/test/test_basic.zip.uu b/contrib/libarchive/unzip/test/test_basic.zip.uu
new file mode 100644
index 000000000000..b55aca950327
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_basic.zip.uu
@@ -0,0 +1,25 @@
+begin 644 test_basic.zip
+M4$L#!!0``````,J0MU8````````````````+`"``=&5S=%]B87-I8R]55`T`
+M!]PX;63U.6UDW#AM9'5X"P`!!.@#```$Z`,``%!+`P04``@`"``)C;=6````
+M```````+````#``@`'1E<W1?8F%S:6,O8554#0`'PS)M9/HY;603.&UD=7@+
+M``$$Z`,```3H`P``2\[/*TG-*RE62.0"`%!+!PAY:C`$#0````L```!02P,$
+M%``(``@`#HVW5@``````````"P````P`(`!T97-T7V)A<VEC+V)55`T`!\TR
+M;63Z.6UD.SAM9'5X"P`!!.@#```$Z`,``$O.SRM)S2LI5DCB`@!02P<(NCD=
+M+PT````+````4$L#!!0`"``(`%*-MU8```````````L````,`"``=&5S=%]B
+M87-I8R]C550-``=,,VUDTSAM9,\X;61U>`L``03H`P``!.@#``!+SL\K2<TK
+M*59(Y@(`4$L'"/L(!C8-````"P```%!+`P04``@`"`#*D+=6```````````.
+M````#P`@`'1E<W1?8F%S:6,O0T%04U54#0`'W#AM9/HY;63<.&UD=7@+``$$
+MZ`,```3H`P``2\[/*TG-*RE6<'8,".8"`%!+!P@I4T'W$`````X```!02P$"
+M%`,4``````#*D+=6````````````````"P`@````````````[4$`````=&5S
+M=%]B87-I8R]55`T`!]PX;63U.6UDW#AM9'5X"P`!!.@#```$Z`,``%!+`0(4
+M`Q0`"``(``F-MU9Y:C`$#0````L````,`"````````````"D@4D```!T97-T
+M7V)A<VEC+V%55`T`!\,R;63Z.6UD$SAM9'5X"P`!!.@#```$Z`,``%!+`0(4
+M`Q0`"``(``Z-MU:Z.1TO#0````L````,`"````````````"D@;````!T97-T
+M7V)A<VEC+V)55`T`!\TR;63Z.6UD.SAM9'5X"P`!!.@#```$Z`,``%!+`0(4
+M`Q0`"``(`%*-MU;["`8V#0````L````,`"````````````"D@1<!``!T97-T
+M7V)A<VEC+V-55`T`!TPS;633.&UDSSAM9'5X"P`!!.@#```$Z`,``%!+`0(4
+M`Q0`"``(`,J0MU8I4T'W$`````X````/`"````````````"D@7X!``!T97-T
+M7V)A<VEC+T-!4%-55`T`!]PX;63Z.6UDW#AM9'5X"P`!!.@#```$Z`,``%!+
+4!08`````!0`%`,0!``#K`0``````
+`
+end
diff --git a/contrib/libarchive/unzip/test/test_d.c b/contrib/libarchive/unzip/test/test_d.c
new file mode 100644
index 000000000000..64950cbbe165
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_d.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test d arg - extract to target dir */
+DEFINE_TEST(test_d)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s -d foobar %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("contents a\n", "foobar/test_basic/a");
+ assertTextFileContents("contents b\n", "foobar/test_basic/b");
+ assertTextFileContents("contents c\n", "foobar/test_basic/c");
+ assertTextFileContents("contents CAPS\n", "foobar/test_basic/CAPS");
+}
diff --git a/contrib/libarchive/unzip/test/test_encrypted.zip.uu b/contrib/libarchive/unzip/test/test_encrypted.zip.uu
new file mode 100644
index 000000000000..6aabeb9f5786
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_encrypted.zip.uu
@@ -0,0 +1,13 @@
+begin 644 test_encrypted.zip
+M4$L#!!0``````'*1MU8````````````````*`"``96YC<GEP=&5D+U54#0`'
+M&#IM9!LZ;608.FUD=7@+``$$Z`,```3H`P``4$L#!!0`"0!C`'*1MU8`````
+M``````H````2`"L`96YC<GEP=&5D+V9I;&4N='AT550-``<8.FUD&#IM9!@Z
+M;61U>`L``03H`P``!.@#```!F0<``@!!10,(`*_-)-RYPDYFJ$Q9+L<I#-><
+M'#C?XVBR9/=H?7U\LC!A^8<6[&CO#PM02P<(`````"@````*````4$L!`A0#
+M%```````<I&W5@````````````````H`(````````````.U!`````&5N8W)Y
+M<'1E9"]55`T`!Q@Z;60;.FUD&#IM9'5X"P`!!.@#```$Z`,``%!+`0(4`Q0`
+M"0!C`'*1MU8`````*`````H````2`"L```````````"D@4@```!E;F-R>7!T
+M960O9FEL92YT>'155`T`!Q@Z;608.FUD&#IM9'5X"P`!!.@#```$Z`,```&9
+?!P`"`$%%`P@`4$L%!@`````"``(`PP```-L`````````
+`
+end
diff --git a/contrib/libarchive/unzip/test/test_glob.c b/contrib/libarchive/unzip/test/test_glob.c
new file mode 100644
index 000000000000..b334ce4bd37d
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_glob.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test that the glob works */
+DEFINE_TEST(test_glob)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s %s test_*/[ab] >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("contents a\n", "test_basic/a");
+ assertTextFileContents("contents b\n", "test_basic/b");
+ assertFileNotExists("test_basic/c");
+ assertFileNotExists("test_basic/CAPS");
+}
diff --git a/contrib/libarchive/unzip/test/test_j.c b/contrib/libarchive/unzip/test/test_j.c
new file mode 100644
index 000000000000..a449e02644b5
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_j.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test j arg - don't make directories */
+DEFINE_TEST(test_j)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s -j %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("contents a\n", "a");
+ assertTextFileContents("contents b\n", "b");
+ assertTextFileContents("contents c\n", "c");
+ assertTextFileContents("contents CAPS\n", "CAPS");
+}
diff --git a/contrib/libarchive/unzip/test/test_n.c b/contrib/libarchive/unzip/test/test_n.c
new file mode 100644
index 000000000000..4e893f04b7ae
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_n.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test n arg - don't overrite existing files */
+DEFINE_TEST(test_n)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ assertMakeDir("test_basic", 0755);
+ assertMakeFile("test_basic/a", 0644, "orig a\n");
+ assertMakeFile("test_basic/b", 0644, "orig b\n");
+
+ extract_reference_file(reffile);
+ r = systemf("%s -n %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("orig a\n", "test_basic/a");
+ assertTextFileContents("orig b\n", "test_basic/b");
+ assertTextFileContents("contents c\n", "test_basic/c");
+ assertTextFileContents("contents CAPS\n", "test_basic/CAPS");
+}
diff --git a/contrib/libarchive/unzip/test/test_not_exist.c b/contrib/libarchive/unzip/test/test_not_exist.c
new file mode 100644
index 000000000000..aa660dc646e5
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_not_exist.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test non existant file */
+DEFINE_TEST(test_not_exist)
+{
+ int r;
+ r = systemf("%s nonexist.zip >test.out 2>test.err", testprog);
+ assert(r != 0);
+ assertEmptyFile("test.out");
+ assertNonEmptyFile("test.err");
+}
diff --git a/contrib/libarchive/unzip/test/test_o.c b/contrib/libarchive/unzip/test/test_o.c
new file mode 100644
index 000000000000..af0c4128686f
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_o.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test o arg - overrite existing files */
+DEFINE_TEST(test_o)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ assertMakeDir("test_basic", 0755);
+ assertMakeFile("test_basic/a", 0644, "orig a\n");
+ assertMakeFile("test_basic/b", 0644, "orig b\n");
+
+ extract_reference_file(reffile);
+ r = systemf("%s -o %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("contents a\n", "test_basic/a");
+ assertTextFileContents("contents b\n", "test_basic/b");
+ assertTextFileContents("contents c\n", "test_basic/c");
+ assertTextFileContents("contents CAPS\n", "test_basic/CAPS");
+}
diff --git a/contrib/libarchive/unzip/test/test_p.c b/contrib/libarchive/unzip/test/test_p.c
new file mode 100644
index 000000000000..f34a5eae8e13
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_p.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test p arg - Print to stdout */
+DEFINE_TEST(test_p)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s -p %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertTextFileContents("contents a\ncontents b\ncontents c\ncontents CAPS\n", "test.out");
+ assertEmptyFile("test.err");
+}
diff --git a/contrib/libarchive/unzip/test/test_q.c b/contrib/libarchive/unzip/test/test_q.c
new file mode 100644
index 000000000000..9a532c888366
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_q.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test q arg - Quiet */
+DEFINE_TEST(test_q)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s -q %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertEmptyFile("test.out");
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("contents a\n", "test_basic/a");
+ assertTextFileContents("contents b\n", "test_basic/b");
+ assertTextFileContents("contents c\n", "test_basic/c");
+ assertTextFileContents("contents CAPS\n", "test_basic/CAPS");
+}
diff --git a/contrib/libarchive/unzip/test/test_singlefile.c b/contrib/libarchive/unzip/test/test_singlefile.c
new file mode 100644
index 000000000000..70c376eb3932
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_singlefile.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Ensure single-file zips work */
+DEFINE_TEST(test_singlefile)
+{
+ const char *reffile = "test_singlefile.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("hello\n", "file.txt");
+}
diff --git a/contrib/libarchive/unzip/test/test_singlefile.zip.uu b/contrib/libarchive/unzip/test/test_singlefile.zip.uu
new file mode 100644
index 000000000000..589e08f12396
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_singlefile.zip.uu
@@ -0,0 +1,8 @@
+begin 644 test_singlefile.zip
+M4$L#!!0`"``(`&"6MU8```````````8````(`"``9FEL92YT>'155`T`!U1#
+M;6140VUD5$-M9'5X"P`!!.@#```$Z`,``,M(S<G)YP(`4$L'""`P.C8(````
+M!@```%!+`0(4`Q0`"``(`&"6MU8@,#HV"`````8````(`"````````````"D
+M@0````!F:6QE+G1X=%54#0`'5$-M9%1#;6140VUD=7@+``$$Z`,```3H`P``
+64$L%!@`````!``$`5@```%X`````````
+`
+end
diff --git a/contrib/libarchive/unzip/test/test_t.c b/contrib/libarchive/unzip/test/test_t.c
new file mode 100644
index 000000000000..40d8d39e54d5
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_t.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test t arg - Test zip contents */
+DEFINE_TEST(test_t)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s -t %s >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertEmptyFile("test.err");
+}
diff --git a/contrib/libarchive/unzip/test/test_t_bad.c b/contrib/libarchive/unzip/test/test_t_bad.c
new file mode 100644
index 000000000000..f9afbb40dae2
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_t_bad.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test t arg - Test zip contents, but fail! */
+DEFINE_TEST(test_t_bad)
+{
+ const char *reffile = "test_t_bad.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s -t %s >test.out 2>test.err", testprog, reffile);
+ assert(r != 0);
+ assertNonEmptyFile("test.out");
+ assertNonEmptyFile("test.err");
+}
diff --git a/contrib/libarchive/unzip/test/test_t_bad.zip.uu b/contrib/libarchive/unzip/test/test_t_bad.zip.uu
new file mode 100644
index 000000000000..ae6ad07925e6
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_t_bad.zip.uu
@@ -0,0 +1,25 @@
+begin 644 test_t_bad.zip
+M4$L#!!0``````,J0MU8````````````````+`"``=&5S=%]B87-I8R]55`T`
+M!]PX;63U.6UDW#AM9'5X"P`!!.@#```$Z`,``%!+`P04``@`"``)C;=6````
+M```````+````#``@`'1E<W1?8F%S:6,O85546``'PS)M9/HY;603.&UD=7@+
+M``$$Z`,```3H`P``2\[/*TG-*RE62.0"`%!+!PAY:C`$#0````L```!02P,$
+M%&$(``@`#HVW5@``````````"P````P`(`!T97-T7V)A<VEC+V)55`T`!\TR
+M;63Z.6UD.SAM9'5X"P`!!.@#```$Z`,``$O.SRM)S2LI5DCB`@!02P<(NCD=
+M+PT````+````4$L#!!0`"``(`%*-MU8```````````L````,`"``=&5S=%]B
+M87-I8R]C550-``=,,VUDTSAM9,\X;61U>`L``03H`P``!.@#``!+SL\K2<TK
+M*59(Y@(`4$L'"/L(!C8-````"P```%!+`P04``@`"`#*D+=6```````````.
+M````#P`@`'1E<W1?8F%S:6,O0T%04U54#0`'W#AM9/HY;63<.&UD=7@+``$$
+MZ`,```3H`P``2\[/*TG-*RE6<'8,".8"`%!+!P@I4T'W$`````X```!02P$"
+M%`,4``````#*D+=6````````````````"P`@````````````[4(`````=&5S
+M=%]B87-I8R]55`T`!]PX;63U.6UDW#AM9'5X"P`!!.@#```$Z`,``%!+`0(4
+M`Q0`"``(``F-MU9Y:C`$#0````L````,`"````````````"D@4D```!T97-T
+M7V)A<VEC+V%55`T`!\,R;63Z.6UD$SAM9'5X"P`!!.@#```$Z`,``%!+`0(4
+M`Q0`"``(``Z-MU:Z.1TO#0````L````,`"````````````"D@;````!T97-T
+M7V)A<VEC+V)55`T`!\TR;63Z.6UD.SAM9'5X"P`!!.@#```$Z`,``%!+`0(4
+M`Q0`"``(`%*-MU;["`8V#0````L````,`"````````````"D@1<!``!T97-T
+M7V)A<VEC+V-55`T`!TPS;633.&UDSSAM9'5X"P`!!.@#```$Z`,``%!+`0(4
+M`Q0`"``(`,J0MU8I4T'W$`````X````/`"````````````"D@7X!``!T97-T
+M7V)A<VEC+T-!4%-55`T`!]PX;63Z.6UDW#AM9'5X"P`!!.@#```$Z`,``%!+
+5!08`````!0`%`,0!``#K`0`````*
+`
+end
diff --git a/contrib/libarchive/unzip/test/test_x.c b/contrib/libarchive/unzip/test/test_x.c
new file mode 100644
index 000000000000..21f01bf65da8
--- /dev/null
+++ b/contrib/libarchive/unzip/test/test_x.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2023 Adrian Vovk
+ * 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+/* Test x arg - Exclude paths */
+DEFINE_TEST(test_x)
+{
+ const char *reffile = "test_basic.zip";
+ int r;
+
+ extract_reference_file(reffile);
+ r = systemf("%s %s -x test_basic/c >test.out 2>test.err", testprog, reffile);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertEmptyFile("test.err");
+
+ assertTextFileContents("contents a\n", "test_basic/a");
+ assertTextFileContents("contents b\n", "test_basic/b");
+ assertFileNotExists("test_basic/c");
+ assertTextFileContents("contents CAPS\n", "test_basic/CAPS");
+}
diff --git a/lib/libarchive/tests/Makefile b/lib/libarchive/tests/Makefile
index 3f18236fd455..2fe9bbcc7c2d 100644
--- a/lib/libarchive/tests/Makefile
+++ b/lib/libarchive/tests/Makefile
@@ -431,6 +431,7 @@ ${PACKAGE}FILES+= test_read_format_7zip_bcj2_copy_1.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_bcj2_copy_2.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_bcj2_copy_lzma.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_bcj2_deflate.7z.uu
+${PACKAGE}FILES+= test_read_format_7zip_deflate_arm64.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_bcj2_lzma1_1.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_bcj2_lzma1_2.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_bcj2_lzma2_1.7z.uu
@@ -457,11 +458,18 @@ ${PACKAGE}FILES+= test_read_format_7zip_lzma1.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_lzma1_2.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_lzma1_lzma2.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_lzma2.7z.uu
+${PACKAGE}FILES+= test_read_format_7zip_lzma2_arm.7z.uu
+${PACKAGE}FILES+= test_read_format_7zip_lzma2_arm64.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_malformed.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_malformed2.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_packinfo_digests.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_ppmd.7z.uu
+${PACKAGE}FILES+= test_read_format_7zip_solid_zstd.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_symbolic_name.7z.uu
+${PACKAGE}FILES+= test_read_format_7zip_zstd.7z.uu
+${PACKAGE}FILES+= test_read_format_7zip_zstd_arm.7z.uu
+${PACKAGE}FILES+= test_read_format_7zip_zstd_bcj.7z.uu
+${PACKAGE}FILES+= test_read_format_7zip_zstd_nobcj.7z.uu
${PACKAGE}FILES+= test_read_format_ar.ar.uu
${PACKAGE}FILES+= test_read_format_cab_1.cab.uu
${PACKAGE}FILES+= test_read_format_cab_2.cab.uu