Browse Source

Merge topic 'update-libarchive'

ff95dc7f44 libarchive: Set build options the way we need for CMake
3f00851b3e libarchive: Add missing cm3p prefixes on includes
4e5c2aadb1 libarchive: Rename cm_get_date wrapper to cm_parse_date
cf04a5cf27 Merge branch 'upstream-LibArchive' into update-libarchive
bb6def24fe LibArchive 2025-06-01 (9525f90c)
b2c42d8207 libarchive: Update script to get 3.8.1

Acked-by: Kitware Robot <[email protected]>
Acked-by: buildbot <[email protected]>
Merge-request: !11258
Brad King 3 weeks ago
parent
commit
cca334aa26
81 changed files with 4255 additions and 1224 deletions
  1. 2 2
      Source/CMakeLists.txt
  2. 1 0
      Source/Modules/CMakeBuildUtilities.cmake
  3. 2 2
      Source/cmArchiveWrite.cxx
  4. 3 3
      Source/cmCTest.cxx
  5. 0 11
      Source/cm_get_date.c
  6. 11 0
      Source/cm_parse_date.c
  7. 1 1
      Source/cm_parse_date.h
  8. 1 1
      Utilities/Scripts/update-libarchive.bash
  9. 64 11
      Utilities/cmlibarchive/CMakeLists.txt
  10. 1 1
      Utilities/cmlibarchive/COPYING
  11. 1 1
      Utilities/cmlibarchive/build/cmake/CreatePkgConfigFile.cmake
  12. 30 1
      Utilities/cmlibarchive/build/cmake/config.h.in
  13. 8 0
      Utilities/cmlibarchive/build/utils/gen_archive_string_composition_h.sh
  14. 1 1
      Utilities/cmlibarchive/build/version
  15. 12 7
      Utilities/cmlibarchive/libarchive/CMakeLists.txt
  16. 53 2
      Utilities/cmlibarchive/libarchive/archive.h
  17. 12 2
      Utilities/cmlibarchive/libarchive/archive_acl.c
  18. 1 1
      Utilities/cmlibarchive/libarchive/archive_acl_private.h
  19. 1 1
      Utilities/cmlibarchive/libarchive/archive_cmdline.c
  20. 8 0
      Utilities/cmlibarchive/libarchive/archive_cryptor_private.h
  21. 203 130
      Utilities/cmlibarchive/libarchive/archive_digest.c
  22. 25 10
      Utilities/cmlibarchive/libarchive/archive_digest_private.h
  23. 1 1
      Utilities/cmlibarchive/libarchive/archive_disk_acl_darwin.c
  24. 2 2
      Utilities/cmlibarchive/libarchive/archive_disk_acl_freebsd.c
  25. 32 22
      Utilities/cmlibarchive/libarchive/archive_entry.c
  26. 56 25
      Utilities/cmlibarchive/libarchive/archive_entry.h
  27. 6 25
      Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c
  28. 8 0
      Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c
  29. 1 1
      Utilities/cmlibarchive/libarchive/archive_entry_locale.h
  30. 8 5
      Utilities/cmlibarchive/libarchive/archive_entry_private.h
  31. 1 1
      Utilities/cmlibarchive/libarchive/archive_hmac_private.h
  32. 35 63
      Utilities/cmlibarchive/libarchive/archive_match.c
  33. 2 2
      Utilities/cmlibarchive/libarchive/archive_options.c
  34. 2 2
      Utilities/cmlibarchive/libarchive/archive_options_private.h
  35. 1 1
      Utilities/cmlibarchive/libarchive/archive_pack_dev.h
  36. 57 10
      Utilities/cmlibarchive/libarchive/archive_parse_date.c
  37. 1 1
      Utilities/cmlibarchive/libarchive/archive_platform_acl.h
  38. 1 1
      Utilities/cmlibarchive/libarchive/archive_platform_xattr.h
  39. 1 1
      Utilities/cmlibarchive/libarchive/archive_random_private.h
  40. 1 1
      Utilities/cmlibarchive/libarchive/archive_rb.h
  41. 0 6
      Utilities/cmlibarchive/libarchive/archive_read.c
  42. 5 4
      Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
  43. 4 3
      Utilities/cmlibarchive/libarchive/archive_read_disk_private.h
  44. 32 37
      Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
  45. 15 0
      Utilities/cmlibarchive/libarchive/archive_read_format.3
  46. 31 11
      Utilities/cmlibarchive/libarchive/archive_read_open_fd.c
  47. 47 23
      Utilities/cmlibarchive/libarchive/archive_read_open_file.c
  48. 38 13
      Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
  49. 2 1
      Utilities/cmlibarchive/libarchive/archive_read_support_filter_compress.c
  50. 255 47
      Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
  51. 6 1
      Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
  52. 15 7
      Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
  53. 1 1
      Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c
  54. 16 57
      Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
  55. 116 62
      Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
  56. 57 30
      Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c
  57. 145 99
      Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
  58. 5 2
      Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c
  59. 336 7
      Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
  60. 3 23
      Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
  61. 61 34
      Utilities/cmlibarchive/libarchive/archive_string.c
  62. 1 2
      Utilities/cmlibarchive/libarchive/archive_string_composition.h
  63. 10 1
      Utilities/cmlibarchive/libarchive/archive_string_sprintf.c
  64. 163 0
      Utilities/cmlibarchive/libarchive/archive_time.c
  65. 18 8
      Utilities/cmlibarchive/libarchive/archive_time_private.h
  66. 16 60
      Utilities/cmlibarchive/libarchive/archive_util.c
  67. 397 8
      Utilities/cmlibarchive/libarchive/archive_version_details.c
  68. 4 31
      Utilities/cmlibarchive/libarchive/archive_windows.c
  69. 1 1
      Utilities/cmlibarchive/libarchive/archive_windows.h
  70. 1 1
      Utilities/cmlibarchive/libarchive/archive_write.c
  71. 18 1
      Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c
  72. 37 39
      Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
  73. 263 35
      Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
  74. 8 8
      Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c
  75. 14 3
      Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
  76. 98 15
      Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
  77. 3 3
      Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c
  78. 568 124
      Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
  79. 735 54
      Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
  80. 35 8
      Utilities/cmlibarchive/libarchive/archive_write_set_options.3
  81. 18 2
      Utilities/cmlibarchive/libarchive/libarchive-formats.5

+ 2 - 2
Source/CMakeLists.txt

@@ -797,8 +797,8 @@ add_library(
   cmFastbuildUtilityTargetGenerator.cxx
   cmFastbuildUtilityTargetGenerator.cxx
   cmFastbuildUtilityTargetGenerator.h
   cmFastbuildUtilityTargetGenerator.h
 
 
-  cm_get_date.h
-  cm_get_date.c
+  cm_parse_date.h
+  cm_parse_date.c
   cm_utf8.h
   cm_utf8.h
   cm_utf8.c
   cm_utf8.c
   cm_codecvt.hxx
   cm_codecvt.hxx

+ 1 - 0
Source/Modules/CMakeBuildUtilities.cmake

@@ -290,6 +290,7 @@ else()
   set(ENABLE_CAT_SHARED OFF)
   set(ENABLE_CAT_SHARED OFF)
   set(ENABLE_UNZIP OFF)
   set(ENABLE_UNZIP OFF)
   set(ENABLE_UNZIP_SHARED OFF)
   set(ENABLE_UNZIP_SHARED OFF)
+  set(ENABLE_WIN32_XMLLITE OFF)
   set(ENABLE_XATTR OFF)
   set(ENABLE_XATTR OFF)
   set(ENABLE_ACL OFF)
   set(ENABLE_ACL OFF)
   set(ENABLE_ICONV OFF)
   set(ENABLE_ICONV OFF)

+ 2 - 2
Source/cmArchiveWrite.cxx

@@ -20,7 +20,7 @@
 #include "cmsys/Encoding.hxx"
 #include "cmsys/Encoding.hxx"
 #include "cmsys/FStream.hxx"
 #include "cmsys/FStream.hxx"
 
 
-#include "cm_get_date.h"
+#include "cm_parse_date.h"
 
 
 #include "cmLocale.h"
 #include "cmLocale.h"
 #include "cmStringAlgorithms.h"
 #include "cmStringAlgorithms.h"
@@ -345,7 +345,7 @@ bool cmArchiveWrite::AddFile(char const* file, size_t skip, char const* prefix)
   if (!this->MTime.empty()) {
   if (!this->MTime.empty()) {
     time_t now;
     time_t now;
     time(&now);
     time(&now);
-    time_t t = cm_get_date(now, this->MTime.c_str());
+    time_t t = cm_parse_date(now, this->MTime.c_str());
     if (t == -1) {
     if (t == -1) {
       this->Error = cmStrCat("unable to parse mtime '", this->MTime, '\'');
       this->Error = cmStrCat("unable to parse mtime '", this->MTime, '\'');
       return false;
       return false;

+ 3 - 3
Source/cmCTest.cxx

@@ -38,7 +38,7 @@
 #  include <unistd.h> // IWYU pragma: keep
 #  include <unistd.h> // IWYU pragma: keep
 #endif
 #endif
 
 
-#include "cm_get_date.h"
+#include "cm_parse_date.h"
 
 
 #include "cmCMakePresetsGraph.h"
 #include "cmCMakePresetsGraph.h"
 #include "cmCTestBuildAndTest.h"
 #include "cmCTestBuildAndTest.h"
@@ -214,7 +214,7 @@ struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag)
   char buf[1024];
   char buf[1024];
   std::snprintf(buf, sizeof(buf), "%d%02d%02d %s", lctime->tm_year + 1900,
   std::snprintf(buf, sizeof(buf), "%d%02d%02d %s", lctime->tm_year + 1900,
                 lctime->tm_mon + 1, lctime->tm_mday, str.c_str());
                 lctime->tm_mon + 1, lctime->tm_mday, str.c_str());
-  time_t ntime = cm_get_date(tctime, buf);
+  time_t ntime = cm_parse_date(tctime, buf);
   cmCTestLog(this, DEBUG,
   cmCTestLog(this, DEBUG,
              "   Get the nightly start time: " << ntime << std::endl);
              "   Get the nightly start time: " << ntime << std::endl);
   tctime = time(nullptr);
   tctime = time(nullptr);
@@ -2742,7 +2742,7 @@ void cmCTest::SetStopTime(std::string const& time_str)
            lctime->tm_mon + 1, lctime->tm_mday, time_str.c_str(),
            lctime->tm_mon + 1, lctime->tm_mday, time_str.c_str(),
            tzone_offset);
            tzone_offset);
 
 
-  time_t stop_time = cm_get_date(current_time, buf);
+  time_t stop_time = cm_parse_date(current_time, buf);
   if (stop_time == -1) {
   if (stop_time == -1) {
     this->Impl->StopTime = std::chrono::system_clock::time_point();
     this->Impl->StopTime = std::chrono::system_clock::time_point();
     return;
     return;

+ 0 - 11
Source/cm_get_date.c

@@ -1,11 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file LICENSE.rst or https://cmake.org/licensing for details.  */
-#include "cm_get_date.h"
-
-// FIXME: This suppresses use of localtime_r because archive_getdate.c
-// depends the rest of libarchive's checks for that.
-#define CM_GET_DATE
-
-#define __archive_get_date cm_get_date
-
-#include "../Utilities/cmlibarchive/libarchive/archive_getdate.c"

+ 11 - 0
Source/cm_parse_date.c

@@ -0,0 +1,11 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file LICENSE.rst or https://cmake.org/licensing for details.  */
+#include "cm_parse_date.h"
+
+// FIXME: This suppresses use of localtime_r because archive_parse_date.c
+// depends the rest of libarchive's checks for that.
+#define CM_PARSE_DATE
+
+#define archive_parse_date cm_parse_date
+
+#include "../Utilities/cmlibarchive/libarchive/archive_parse_date.c"

+ 1 - 1
Source/cm_get_date.h → Source/cm_parse_date.h

@@ -9,7 +9,7 @@ extern "C" {
 #endif
 #endif
 
 
 /** Parse a date/time string.  Treat relative times with respect to 'now'. */
 /** Parse a date/time string.  Treat relative times with respect to 'now'. */
-time_t cm_get_date(time_t now, char const* str);
+time_t cm_parse_date(time_t now, char const* str);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 } /* extern "C" */
 } /* extern "C" */

+ 1 - 1
Utilities/Scripts/update-libarchive.bash

@@ -8,7 +8,7 @@ readonly name="LibArchive"
 readonly ownership="LibArchive Upstream <[email protected]>"
 readonly ownership="LibArchive Upstream <[email protected]>"
 readonly subtree="Utilities/cmlibarchive"
 readonly subtree="Utilities/cmlibarchive"
 readonly repo="https://github.com/libarchive/libarchive.git"
 readonly repo="https://github.com/libarchive/libarchive.git"
-readonly tag="v3.7.9"
+readonly tag="v3.8.1"
 readonly shortlog=false
 readonly shortlog=false
 readonly paths="
 readonly paths="
   CMakeLists.txt
   CMakeLists.txt

+ 64 - 11
Utilities/cmlibarchive/CMakeLists.txt

@@ -98,6 +98,11 @@ set(MACHO_CURRENT_VERSION "${MACHO_COMPATIBILITY_VERSION}.${_revision}")
 # saving and restoring the state of the variables.
 # saving and restoring the state of the variables.
 INCLUDE(${CMake_SOURCE_DIR}/Modules/CMakePushCheckState.cmake)
 INCLUDE(${CMake_SOURCE_DIR}/Modules/CMakePushCheckState.cmake)
 
 
+if(0) # XXX(cmake): do not let pkg-config override our search paths
+# Enable the pkg-config helpers.
+INCLUDE(FindPkgConfig)
+endif() # XXX(cmake): end
+
 # Initialize the state of the variables. This initialization is not
 # Initialize the state of the variables. This initialization is not
 # necessary but this shows you what value the variables initially have.
 # necessary but this shows you what value the variables initially have.
 SET(CMAKE_REQUIRED_DEFINITIONS)
 SET(CMAKE_REQUIRED_DEFINITIONS)
@@ -250,6 +255,7 @@ OPTION(ENABLE_ZLIB "Enable the use of the system ZLIB library if found" ON)
 OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON)
 OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON)
 OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON)
 OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON)
 OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON)
 OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON)
+OPTION(ENABLE_WIN32_XMLLITE "Enable the use of the Windows XmlLite library if found" ON)
 OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON)
 OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON)
 OPTION(ENABLE_PCRE2POSIX "Enable the use of the system PCRE2POSIX library if found" ON)
 OPTION(ENABLE_PCRE2POSIX "Enable the use of the system PCRE2POSIX library if found" ON)
 OPTION(ENABLE_LIBGCC "Enable the use of the system LibGCC library if found" ON)
 OPTION(ENABLE_LIBGCC "Enable the use of the system LibGCC library if found" ON)
@@ -378,10 +384,12 @@ ENDMACRO (GENERATE_LIST_H)
 # Generate installation rules for man pages.
 # Generate installation rules for man pages.
 #
 #
 MACRO (INSTALL_MAN __mans)
 MACRO (INSTALL_MAN __mans)
-  FOREACH (_man ${ARGV})
-    STRING(REGEX REPLACE "^.+[.]([1-9])" "\\1" _mansect ${_man})
-    INSTALL(FILES ${_man} DESTINATION "share/man/man${_mansect}")
-  ENDFOREACH (_man)
+  IF(ENABLE_INSTALL)
+    FOREACH (_man ${ARGV})
+      STRING(REGEX REPLACE "^.+[.]([1-9])" "\\1" _mansect ${_man})
+      INSTALL(FILES ${_man} DESTINATION "share/man/man${_mansect}")
+    ENDFOREACH (_man)
+  ENDIF(ENABLE_INSTALL)
 ENDMACRO (INSTALL_MAN __mans)
 ENDMACRO (INSTALL_MAN __mans)
 #
 #
 # Find out what macro is needed to use libraries on Windows.
 # Find out what macro is needed to use libraries on Windows.
@@ -602,6 +610,7 @@ IF(ENABLE_LIBB2)
   FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBB2 DEFAULT_MSG LIBB2_LIBRARY LIBB2_INCLUDE_DIR)
   FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBB2 DEFAULT_MSG LIBB2_LIBRARY LIBB2_INCLUDE_DIR)
 ELSE(ENABLE_LIBB2)
 ELSE(ENABLE_LIBB2)
   SET(LIBB2_FOUND FALSE) # Override cached value
   SET(LIBB2_FOUND FALSE) # Override cached value
+  UNSET(LIBB2_PKGCONFIG_VERSION CACHE)
 ENDIF(ENABLE_LIBB2)
 ENDIF(ENABLE_LIBB2)
 IF(LIBB2_FOUND)
 IF(LIBB2_FOUND)
   SET(HAVE_LIBB2 1)
   SET(HAVE_LIBB2 1)
@@ -614,8 +623,13 @@ IF(LIBB2_FOUND)
   SET(CMAKE_REQUIRED_INCLUDES ${LIBB2_INCLUDE_DIR})
   SET(CMAKE_REQUIRED_INCLUDES ${LIBB2_INCLUDE_DIR})
   CHECK_FUNCTION_EXISTS(blake2sp_init HAVE_LIBB2)
   CHECK_FUNCTION_EXISTS(blake2sp_init HAVE_LIBB2)
   CMAKE_POP_CHECK_STATE()
   CMAKE_POP_CHECK_STATE()
+  pkg_check_modules(LIBB2 libb2)
+  IF(LIBB2_VERSION)
+    SET(LIBB2_PKGCONFIG_VERSION LIBB2_VERSION)
+  ENDIF(LIBB2_VERSION)
 ELSE(LIBB2_FOUND)
 ELSE(LIBB2_FOUND)
   SET(ARCHIVE_BLAKE2 TRUE)
   SET(ARCHIVE_BLAKE2 TRUE)
+  UNSET(LIBB2_PKGCONFIG_VERSION CACHE)
 ENDIF(LIBB2_FOUND)
 ENDIF(LIBB2_FOUND)
 #
 #
 # Find LZ4
 # Find LZ4
@@ -681,6 +695,7 @@ IF(ZSTD_FOUND)
   SET(CMAKE_REQUIRED_INCLUDES ${ZSTD_INCLUDE_DIR})
   SET(CMAKE_REQUIRED_INCLUDES ${ZSTD_INCLUDE_DIR})
   CHECK_FUNCTION_EXISTS(ZSTD_decompressStream HAVE_LIBZSTD)
   CHECK_FUNCTION_EXISTS(ZSTD_decompressStream HAVE_LIBZSTD)
   CHECK_FUNCTION_EXISTS(ZSTD_compressStream HAVE_ZSTD_compressStream)
   CHECK_FUNCTION_EXISTS(ZSTD_compressStream HAVE_ZSTD_compressStream)
+  CHECK_FUNCTION_EXISTS(ZSTD_minCLevel HAVE_ZSTD_minCLevel)
   #
   #
   # TODO: test for static library.
   # TODO: test for static library.
   #
   #
@@ -690,7 +705,6 @@ ENDIF(ZSTD_FOUND)
 MARK_AS_ADVANCED(CLEAR ZSTD_INCLUDE_DIR)
 MARK_AS_ADVANCED(CLEAR ZSTD_INCLUDE_DIR)
 MARK_AS_ADVANCED(CLEAR ZSTD_LIBRARY)
 MARK_AS_ADVANCED(CLEAR ZSTD_LIBRARY)
 
 
-
 #
 #
 # Check headers
 # Check headers
 #
 #
@@ -824,7 +838,7 @@ IF(ENABLE_MBEDTLS)
     LA_CHECK_INCLUDE_FILE("mbedtls/aes.h" HAVE_MBEDTLS_AES_H)
     LA_CHECK_INCLUDE_FILE("mbedtls/aes.h" HAVE_MBEDTLS_AES_H)
     LA_CHECK_INCLUDE_FILE("mbedtls/md.h" HAVE_MBEDTLS_MD_H)
     LA_CHECK_INCLUDE_FILE("mbedtls/md.h" HAVE_MBEDTLS_MD_H)
     LA_CHECK_INCLUDE_FILE("mbedtls/pkcs5.h" HAVE_MBEDTLS_PKCS5_H)
     LA_CHECK_INCLUDE_FILE("mbedtls/pkcs5.h" HAVE_MBEDTLS_PKCS5_H)
-
+    LA_CHECK_INCLUDE_FILE("mbedtls/version.h" HAVE_MBEDTLS_VERSION_H)
   ENDIF(MBEDTLS_FOUND)
   ENDIF(MBEDTLS_FOUND)
   MARK_AS_ADVANCED(CLEAR MBEDTLS_INCLUDE_DIRS)
   MARK_AS_ADVANCED(CLEAR MBEDTLS_INCLUDE_DIRS)
   MARK_AS_ADVANCED(CLEAR MBEDCRYPTO_LIBRARY)
   MARK_AS_ADVANCED(CLEAR MBEDCRYPTO_LIBRARY)
@@ -847,7 +861,7 @@ IF(ENABLE_NETTLE)
     LA_CHECK_INCLUDE_FILE("nettle/pbkdf2.h" HAVE_NETTLE_PBKDF2_H)
     LA_CHECK_INCLUDE_FILE("nettle/pbkdf2.h" HAVE_NETTLE_PBKDF2_H)
     LA_CHECK_INCLUDE_FILE("nettle/ripemd160.h" HAVE_NETTLE_RIPEMD160_H)
     LA_CHECK_INCLUDE_FILE("nettle/ripemd160.h" HAVE_NETTLE_RIPEMD160_H)
     LA_CHECK_INCLUDE_FILE("nettle/sha.h" HAVE_NETTLE_SHA_H)
     LA_CHECK_INCLUDE_FILE("nettle/sha.h" HAVE_NETTLE_SHA_H)
-
+    LA_CHECK_INCLUDE_FILE("nettle/version.h" HAVE_NETTLE_VERSION_H)
   ENDIF(NETTLE_FOUND)
   ENDIF(NETTLE_FOUND)
   MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR)
   MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR)
   MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES)
   MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES)
@@ -866,6 +880,7 @@ IF(ENABLE_OPENSSL AND NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
     set(CMAKE_REQUIRED_LIBRARIES OpenSSL::Crypto)
     set(CMAKE_REQUIRED_LIBRARIES OpenSSL::Crypto)
     SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
     SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
     LA_CHECK_INCLUDE_FILE("openssl/evp.h" HAVE_OPENSSL_EVP_H)
     LA_CHECK_INCLUDE_FILE("openssl/evp.h" HAVE_OPENSSL_EVP_H)
+    LA_CHECK_INCLUDE_FILE("openssl/opensslv.h" HAVE_OPENSSL_OPENSSLV_H)
     CHECK_FUNCTION_EXISTS(PKCS5_PBKDF2_HMAC_SHA1 HAVE_PKCS5_PBKDF2_HMAC_SHA1)
     CHECK_FUNCTION_EXISTS(PKCS5_PBKDF2_HMAC_SHA1 HAVE_PKCS5_PBKDF2_HMAC_SHA1)
   ENDIF(OPENSSL_FOUND)
   ENDIF(OPENSSL_FOUND)
 ELSE()
 ELSE()
@@ -1074,7 +1089,6 @@ main(int argc, char **argv)
         	"${OUTPUT}\n"
         	"${OUTPUT}\n"
         	"Source file was:\n${SOURCE}\n")
         	"Source file was:\n${SOURCE}\n")
 	ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
 	ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
-
       ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
       ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
       ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO})
       ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO})
     ENDFOREACH(CRYPTO)
     ENDFOREACH(CRYPTO)
@@ -1168,6 +1182,7 @@ IF(ENABLE_ICONV)
       CHECK_ICONV("libiconv" "const")
       CHECK_ICONV("libiconv" "const")
       CHECK_ICONV("libiconv" "")
       CHECK_ICONV("libiconv" "")
       IF (HAVE_ICONV)
       IF (HAVE_ICONV)
+        SET(HAVE_LIBICONV 1)
         LIST(APPEND ADDITIONAL_LIBS ${LIBICONV_PATH})
         LIST(APPEND ADDITIONAL_LIBS ${LIBICONV_PATH})
       ENDIF(HAVE_ICONV)
       ENDIF(HAVE_ICONV)
     ENDIF(NOT HAVE_ICONV AND LIBICONV_PATH)
     ENDIF(NOT HAVE_ICONV AND LIBICONV_PATH)
@@ -1211,6 +1226,7 @@ ELSE(ENABLE_ICONV)
   # (once enabled).
   # (once enabled).
   UNSET(HAVE_LOCALE_CHARSET CACHE)
   UNSET(HAVE_LOCALE_CHARSET CACHE)
   UNSET(HAVE_ICONV CACHE)
   UNSET(HAVE_ICONV CACHE)
+  UNSET(HAVE_LIBICONV CACHE)
   UNSET(HAVE_ICONV_libc_ CACHE)
   UNSET(HAVE_ICONV_libc_ CACHE)
   UNSET(HAVE_ICONV_libc_const CACHE)
   UNSET(HAVE_ICONV_libc_const CACHE)
   UNSET(HAVE_ICONV_libiconv_ CACHE)
   UNSET(HAVE_ICONV_libiconv_ CACHE)
@@ -1240,6 +1256,7 @@ IF(LIBXML2_FOUND)
   SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
   SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
   CHECK_INCLUDE_FILES("libxml/xmlreader.h" HAVE_LIBXML_XMLREADER_H)
   CHECK_INCLUDE_FILES("libxml/xmlreader.h" HAVE_LIBXML_XMLREADER_H)
   CHECK_INCLUDE_FILES("libxml/xmlwriter.h" HAVE_LIBXML_XMLWRITER_H)
   CHECK_INCLUDE_FILES("libxml/xmlwriter.h" HAVE_LIBXML_XMLWRITER_H)
+  CHECK_INCLUDE_FILES("libxml/xmlversion.h" HAVE_LIBXML_XMLVERSION_H)
   # Test if a macro is needed for the library.
   # Test if a macro is needed for the library.
   TRY_MACRO_FOR_LIBRARY(
   TRY_MACRO_FOR_LIBRARY(
     "${ICONV_INCLUDE_DIR};${LIBXML2_INCLUDE_DIR}"
     "${ICONV_INCLUDE_DIR};${LIBXML2_INCLUDE_DIR}"
@@ -1267,6 +1284,25 @@ ELSE(LIBXML2_FOUND)
     SET(HAVE_LIBEXPAT 1)
     SET(HAVE_LIBEXPAT 1)
     LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H)
     LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H)
     CMAKE_POP_CHECK_STATE()	# Restore the state of the variables
     CMAKE_POP_CHECK_STATE()	# Restore the state of the variables
+  ELSE(EXPAT_FOUND)
+    IF(WIN32 AND ENABLE_WIN32_XMLLITE)
+      # Check linkage as well; versions of mingw-w64 before v11.0.0
+      # do not contain an import library for xmllite.
+      cmake_push_check_state()
+      SET(CMAKE_REQUIRED_LIBRARIES "xmllite" "uuid")
+      check_c_source_compiles("
+      #include <initguid.h>
+      #include <xmllite.h>
+      int main() {
+        return CreateXmlReader(&IID_IXmlReader, NULL, NULL);
+      }
+      " HAVE_XMLLITE_H)
+      cmake_pop_check_state()
+      IF(HAVE_XMLLITE_H)
+        SET(XMLLITE_FOUND TRUE)
+        LIST(APPEND ADDITIONAL_LIBS "xmllite" "uuid")
+      ENDIF()
+    ENDIF()
   ENDIF(EXPAT_FOUND)
   ENDIF(EXPAT_FOUND)
 ENDIF(LIBXML2_FOUND)
 ENDIF(LIBXML2_FOUND)
 
 
@@ -1757,11 +1793,16 @@ IF(ENABLE_XATTR)
   CHECK_LIBRARY_EXISTS(attr "setxattr" "" HAVE_LIBATTR)
   CHECK_LIBRARY_EXISTS(attr "setxattr" "" HAVE_LIBATTR)
   IF(HAVE_LIBATTR)
   IF(HAVE_LIBATTR)
     SET(CMAKE_REQUIRED_LIBRARIES "attr")
     SET(CMAKE_REQUIRED_LIBRARIES "attr")
-  ELSE()
+	  pkg_check_modules(LIBATTR libattr)
+	  IF(LIBATTR_VERSION)
+	    SET(LIBATTR_PKGCONFIG_VERSION ${LIBATTR_VERSION})
+	  ENDIF(LIBATTR_VERSION)
+  ELSE(HAVE_LIBATTR)
     CHECK_LIBRARY_EXISTS(gnu "setxattr" "" HAVE_LIBATTR_GNU)
     CHECK_LIBRARY_EXISTS(gnu "setxattr" "" HAVE_LIBATTR_GNU)
     IF(HAVE_LIBATTR_GNU)
     IF(HAVE_LIBATTR_GNU)
       SET(CMAKE_REQUIRED_LIBRARIES "gnu")
       SET(CMAKE_REQUIRED_LIBRARIES "gnu")
     ENDIF()
     ENDIF()
+    UNSET(LIBATTR_PKGCONFIG_VERSION CACHE)
   ENDIF(HAVE_LIBATTR)
   ENDIF(HAVE_LIBATTR)
   CHECK_SYMBOL_EXISTS(EXTATTR_NAMESPACE_USER "sys/types.h;sys/extattr.h" HAVE_DECL_EXTATTR_NAMESPACE_USER)
   CHECK_SYMBOL_EXISTS(EXTATTR_NAMESPACE_USER "sys/types.h;sys/extattr.h" HAVE_DECL_EXTATTR_NAMESPACE_USER)
   CHECK_SYMBOL_EXISTS(XATTR_NOFOLLOW "sys/xattr.h" HAVE_DECL_XATTR_NOFOLLOW)
   CHECK_SYMBOL_EXISTS(XATTR_NOFOLLOW "sys/xattr.h" HAVE_DECL_XATTR_NOFOLLOW)
@@ -1879,6 +1920,12 @@ IF(ENABLE_ACL)
     SET(CMAKE_REQUIRED_LIBRARIES "acl")
     SET(CMAKE_REQUIRED_LIBRARIES "acl")
     FIND_LIBRARY(ACL_LIBRARY NAMES acl)
     FIND_LIBRARY(ACL_LIBRARY NAMES acl)
     LIST(APPEND ADDITIONAL_LIBS ${ACL_LIBRARY})
     LIST(APPEND ADDITIONAL_LIBS ${ACL_LIBRARY})
+	  pkg_check_modules(LIBACL libacl)
+	  IF(LIBACL_VERSION)
+	    SET(LIBACL_PKGCONFIG_VERSION ${LIBACL_VERSION})
+	  ENDIF(LIBACL_VERSION)
+  ELSE(HAVE_LIBACL)
+    UNSET(LIBACL_PKGCONFIG_VERSION CACHE)
   ENDIF(HAVE_LIBACL)
   ENDIF(HAVE_LIBACL)
 
 
   CHECK_TYPE_EXISTS(acl_t "sys/types.h;sys/acl.h" HAVE_ACL_T)
   CHECK_TYPE_EXISTS(acl_t "sys/types.h;sys/acl.h" HAVE_ACL_T)
@@ -2018,6 +2065,12 @@ int main(void) { return ACL_SYNCHRONIZE; }" HAVE_DECL_ACL_SYNCHRONIZE)
     SET(CMAKE_REQUIRED_LIBRARIES "richacl")
     SET(CMAKE_REQUIRED_LIBRARIES "richacl")
     FIND_LIBRARY(RICHACL_LIBRARY NAMES richacl)
     FIND_LIBRARY(RICHACL_LIBRARY NAMES richacl)
     LIST(APPEND ADDITIONAL_LIBS ${RICHACL_LIBRARY})
     LIST(APPEND ADDITIONAL_LIBS ${RICHACL_LIBRARY})
+	  pkg_check_modules(LIBRICHACL librichacl)
+	  IF(LIBRICHACL_VERSION)
+	    SET(LIBRICHACL_PKGCONFIG_VERSION ${LIBRICHACL_VERSION})
+	  ENDIF(LIBRICHACL_VERSION)
+  ELSE(HAVE_LIBRICHACL)
+    UNSET(LIBRICHACL_PKGCONFIG_VERSION CACHE)
   ENDIF(HAVE_LIBRICHACL)
   ENDIF(HAVE_LIBRICHACL)
 
 
   CHECK_STRUCT_HAS_MEMBER("struct richace" e_type "sys/richacl.h"
   CHECK_STRUCT_HAS_MEMBER("struct richace" e_type "sys/richacl.h"
@@ -2121,7 +2174,7 @@ ENDIF()
 #
 #
 # Register installation of PDF documents.
 # Register installation of PDF documents.
 #
 #
-IF(WIN32 AND NOT CYGWIN)
+IF(WIN32 AND NOT CYGWIN AND ENABLE_INSTALL)
   #
   #
   # On Windows platform, It's better that we install PDF documents
   # On Windows platform, It's better that we install PDF documents
   # on one's computer.
   # on one's computer.
@@ -2133,7 +2186,7 @@ IF(WIN32 AND NOT CYGWIN)
             FILES_MATCHING PATTERN "*.pdf"
             FILES_MATCHING PATTERN "*.pdf"
     )
     )
   ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf)
   ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf)
-ENDIF(WIN32 AND NOT CYGWIN)
+ENDIF(WIN32 AND NOT CYGWIN AND ENABLE_INSTALL)
 #
 #
 #
 #
 #
 #

+ 1 - 1
Utilities/cmlibarchive/COPYING

@@ -20,7 +20,7 @@ the actual statements in the files are controlling.
    libarchive/mtree.5
    libarchive/mtree.5
 
 
 * The following source files are in the public domain:
 * The following source files are in the public domain:
-   libarchive/archive_getdate.c
+   libarchive/archive_parse_date.c
 
 
 * The following source files are triple-licensed with the ability to choose
 * The following source files are triple-licensed with the ability to choose
   from CC0 1.0 Universal, OpenSSL or Apache 2.0 licenses:
   from CC0 1.0 Universal, OpenSSL or Apache 2.0 licenses:

+ 1 - 1
Utilities/cmlibarchive/build/cmake/CreatePkgConfigFile.cmake

@@ -29,5 +29,5 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc.in
 # And install it, of course ;).
 # And install it, of course ;).
 IF(ENABLE_INSTALL)
 IF(ENABLE_INSTALL)
   INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/build/pkgconfig/libarchive.pc
   INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/build/pkgconfig/libarchive.pc
-          DESTINATION "lib/pkgconfig")
+          DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
 ENDIF()
 ENDIF()

+ 30 - 1
Utilities/cmlibarchive/build/cmake/config.h.in

@@ -513,6 +513,9 @@
 /* Define to 1 if you have the `gcc' library (-lgcc). */
 /* Define to 1 if you have the `gcc' library (-lgcc). */
 #cmakedefine HAVE_LIBGCC 1
 #cmakedefine HAVE_LIBGCC 1
 
 
+/* Define to 1 if you have the `iconv' library (-liconv). */
+#cmakedefine HAVE_LIBICONV 1
+
 /* Define to 1 if you have the `lz4' library (-llz4). */
 /* Define to 1 if you have the `lz4' library (-llz4). */
 #cmakedefine HAVE_LIBLZ4 1
 #cmakedefine HAVE_LIBLZ4 1
 
 
@@ -549,6 +552,9 @@
 /* Define to 1 if you have the <libxml/xmlwriter.h> header file. */
 /* Define to 1 if you have the <libxml/xmlwriter.h> header file. */
 #cmakedefine HAVE_LIBXML_XMLWRITER_H 1
 #cmakedefine HAVE_LIBXML_XMLWRITER_H 1
 
 
+/* Define to 1 if you have the <libxml/xmlversion.h> header file. */
+#cmakedefine HAVE_LIBXML_XMLVERSION_H 1
+
 /* Define to 1 if you have the `z' library (-lz). */
 /* Define to 1 if you have the `z' library (-lz). */
 #cmakedefine HAVE_LIBZ 1
 #cmakedefine HAVE_LIBZ 1
 
 
@@ -558,6 +564,9 @@
 /* Define to 1 if you have the ZSTD_compressStream function. */
 /* Define to 1 if you have the ZSTD_compressStream function. */
 #cmakedefine HAVE_ZSTD_compressStream 1
 #cmakedefine HAVE_ZSTD_compressStream 1
 
 
+/* Define to 1 if you have the ZSTD_minCLevel function. */
+#cmakedefine HAVE_ZSTD_minCLevel 1
+
 /* Define to 1 if you have the <limits.h> header file. */
 /* Define to 1 if you have the <limits.h> header file. */
 #cmakedefine HAVE_LIMITS_H 1
 #cmakedefine HAVE_LIMITS_H 1
 
 
@@ -649,6 +658,9 @@
 /* Define to 1 if you have the <mbedtls/pkcs5.h> header file. */
 /* Define to 1 if you have the <mbedtls/pkcs5.h> header file. */
 #cmakedefine HAVE_MBEDTLS_PKCS5_H 1
 #cmakedefine HAVE_MBEDTLS_PKCS5_H 1
 
 
+/* Define to 1 if you have the <mbedtls/pkcs5.h> header file. */
+#cmakedefine HAVE_MBEDTLS_VERSION_H 1
+
 /* Define to 1 if you have the `mbrtowc' function. */
 /* Define to 1 if you have the `mbrtowc' function. */
 #cmakedefine HAVE_MBRTOWC 1
 #cmakedefine HAVE_MBRTOWC 1
 
 
@@ -694,6 +706,9 @@
 /* Define to 1 if you have the <nettle/sha.h> header file. */
 /* Define to 1 if you have the <nettle/sha.h> header file. */
 #cmakedefine HAVE_NETTLE_SHA_H 1
 #cmakedefine HAVE_NETTLE_SHA_H 1
 
 
+/* Define to 1 if you have the <nettle/version.h> header file. */
+#cmakedefine HAVE_NETTLE_VERSION_H 1
+
 /* Define to 1 if you have the `nl_langinfo' function. */
 /* Define to 1 if you have the `nl_langinfo' function. */
 #cmakedefine HAVE_NL_LANGINFO 1
 #cmakedefine HAVE_NL_LANGINFO 1
 
 
@@ -703,6 +718,9 @@
 /* Define to 1 if you have the <openssl/evp.h> header file. */
 /* Define to 1 if you have the <openssl/evp.h> header file. */
 #cmakedefine HAVE_OPENSSL_EVP_H 1
 #cmakedefine HAVE_OPENSSL_EVP_H 1
 
 
+/* Define to 1 if you have the <openssl/opensslv.h> header file. */
+#cmakedefine HAVE_OPENSSL_OPENSSLV_H 1
+
 /* Define to 1 if you have the <paths.h> header file. */
 /* Define to 1 if you have the <paths.h> header file. */
 #cmakedefine HAVE_PATHS_H 1
 #cmakedefine HAVE_PATHS_H 1
 
 
@@ -922,7 +940,6 @@
 /* Define to 1 if you have the <sys/stat.h> header file. */
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #cmakedefine HAVE_SYS_STAT_H 1
 #cmakedefine HAVE_SYS_STAT_H 1
 
 
-
 /* Define to 1 if you have the <sys/sysmacros.h> header file. */
 /* Define to 1 if you have the <sys/sysmacros.h> header file. */
 #cmakedefine HAVE_SYS_SYSMACROS_H 1
 #cmakedefine HAVE_SYS_SYSMACROS_H 1
 
 
@@ -1046,6 +1063,9 @@
 /* Define to 1 if you have a working FS_IOC_GETFLAGS */
 /* Define to 1 if you have a working FS_IOC_GETFLAGS */
 #cmakedefine HAVE_WORKING_FS_IOC_GETFLAGS 1
 #cmakedefine HAVE_WORKING_FS_IOC_GETFLAGS 1
 
 
+/* Define to 1 if you have the Windows `xmllite' library (-lxmllite). */
+#cmakedefine HAVE_XMLLITE_H 1
+
 /* Define to 1 if you have the <zlib.h> header file. */
 /* Define to 1 if you have the <zlib.h> header file. */
 #cmakedefine HAVE_ZLIB_H 1
 #cmakedefine HAVE_ZLIB_H 1
 
 
@@ -1103,6 +1123,15 @@
 /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
 /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
 #cmakedefine TIME_WITH_SYS_TIME 1
 #cmakedefine TIME_WITH_SYS_TIME 1
 
 
+/* Version number of package */
+#cmakedefine LIBATTR_PKGCONFIG_VERSION "@LIBATTR_PKGCONFIG_VERSION@"
+
+/* Version number of package */
+#cmakedefine LIBACL_PKGCONFIG_VERSION "@LIBACL_PKGCONFIG_VERSION@"
+
+/* Version number of package */
+#cmakedefine LIBRICHACL_PKGCONFIG_VERSION "@LIBRICHACL_PKGCONFIG_VERSION@"
+
 /*
 /*
  * Some platform requires a macro to use extension functions.
  * Some platform requires a macro to use extension functions.
  */
  */

+ 8 - 0
Utilities/cmlibarchive/build/utils/gen_archive_string_composition_h.sh

@@ -1,4 +1,12 @@
 #!/bin/sh
 #!/bin/sh
+set -eu
+
+if [ $# != 1 ]
+then
+	echo "Usage: $0 path/to/UnicodeData.txt"
+	exit 1
+fi
+
 #
 #
 # This needs http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt
 # This needs http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt
 #
 #

+ 1 - 1
Utilities/cmlibarchive/build/version

@@ -1 +1 @@
-3007009
+3008001

+ 12 - 7
Utilities/cmlibarchive/libarchive/CMakeLists.txt

@@ -38,8 +38,6 @@ SET(libarchive_SOURCES
   archive_entry_stat.c
   archive_entry_stat.c
   archive_entry_strmode.c
   archive_entry_strmode.c
   archive_entry_xattr.c
   archive_entry_xattr.c
-  archive_getdate.c
-  archive_getdate.h
   archive_hmac.c
   archive_hmac.c
   archive_hmac_private.h
   archive_hmac_private.h
   archive_match.c
   archive_match.c
@@ -49,6 +47,7 @@ SET(libarchive_SOURCES
   archive_options_private.h
   archive_options_private.h
   archive_pack_dev.h
   archive_pack_dev.h
   archive_pack_dev.c
   archive_pack_dev.c
+  archive_parse_date.c
   archive_pathmatch.c
   archive_pathmatch.c
   archive_pathmatch.h
   archive_pathmatch.h
   archive_platform.h
   archive_platform.h
@@ -117,6 +116,8 @@ SET(libarchive_SOURCES
   archive_string.h
   archive_string.h
   archive_string_composition.h
   archive_string_composition.h
   archive_string_sprintf.c
   archive_string_sprintf.c
+  archive_time.c
+  archive_time_private.h
   archive_util.c
   archive_util.c
   archive_version_details.c
   archive_version_details.c
   archive_virtual.c
   archive_virtual.c
@@ -256,7 +257,7 @@ IF(BUILD_SHARED_LIBS)
   ADD_LIBRARY(archive SHARED ${libarchive_SOURCES} ${include_HEADERS})
   ADD_LIBRARY(archive SHARED ${libarchive_SOURCES} ${include_HEADERS})
   TARGET_INCLUDE_DIRECTORIES(archive PUBLIC .)
   TARGET_INCLUDE_DIRECTORIES(archive PUBLIC .)
   TARGET_LINK_LIBRARIES(archive ${ADDITIONAL_LIBS})
   TARGET_LINK_LIBRARIES(archive ${ADDITIONAL_LIBS})
-  SET_TARGET_PROPERTIES(archive PROPERTIES 
+  SET_TARGET_PROPERTIES(archive PROPERTIES
                         VERSION ${SOVERSION_FULL}
                         VERSION ${SOVERSION_FULL}
                         SOVERSION ${SOVERSION}
                         SOVERSION ${SOVERSION}
                         MACHO_COMPATIBILITY_VERSION ${MACHO_COMPATIBILITY_VERSION}
                         MACHO_COMPATIBILITY_VERSION ${MACHO_COMPATIBILITY_VERSION}
@@ -274,18 +275,22 @@ IF(NOT WIN32 OR CYGWIN OR NOT BUILD_SHARED_LIBS)
   SET_TARGET_PROPERTIES(archive_static PROPERTIES OUTPUT_NAME archive)
   SET_TARGET_PROPERTIES(archive_static PROPERTIES OUTPUT_NAME archive)
 ENDIF(NOT WIN32 OR CYGWIN OR NOT BUILD_SHARED_LIBS)
 ENDIF(NOT WIN32 OR CYGWIN OR NOT BUILD_SHARED_LIBS)
 
 
+if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
+    set(CMAKE_INSTALL_LIBDIR "lib")
+endif()
+
 IF(ENABLE_INSTALL)
 IF(ENABLE_INSTALL)
   # How to install the libraries
   # How to install the libraries
   IF(BUILD_SHARED_LIBS)
   IF(BUILD_SHARED_LIBS)
     INSTALL(TARGETS archive
     INSTALL(TARGETS archive
             RUNTIME DESTINATION bin
             RUNTIME DESTINATION bin
-            LIBRARY DESTINATION lib
-            ARCHIVE DESTINATION lib)
+            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
   ENDIF(BUILD_SHARED_LIBS)
   ENDIF(BUILD_SHARED_LIBS)
   INSTALL(TARGETS archive_static
   INSTALL(TARGETS archive_static
           RUNTIME DESTINATION bin
           RUNTIME DESTINATION bin
-          LIBRARY DESTINATION lib
-          ARCHIVE DESTINATION lib)
+          LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+          ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
   INSTALL_MAN(${libarchive_MANS})
   INSTALL_MAN(${libarchive_MANS})
   INSTALL(FILES ${include_HEADERS} DESTINATION include)
   INSTALL(FILES ${include_HEADERS} DESTINATION include)
 ENDIF()
 ENDIF()

+ 53 - 2
Utilities/cmlibarchive/libarchive/archive.h

@@ -34,12 +34,15 @@
  * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
  * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
  */
  */
 /* Note: Compiler will complain if this does not match archive_entry.h! */
 /* Note: Compiler will complain if this does not match archive_entry.h! */
-#define	ARCHIVE_VERSION_NUMBER 3007009
+#define	ARCHIVE_VERSION_NUMBER 3008001
 
 
 #include <sys/stat.h>
 #include <sys/stat.h>
 #include <stddef.h>  /* for wchar_t */
 #include <stddef.h>  /* for wchar_t */
 #include <stdio.h> /* For FILE * */
 #include <stdio.h> /* For FILE * */
+#if ARCHIVE_VERSION_NUMBER < 4000000
+/* time_t is slated to be removed from public includes in 4.0 */
 #include <time.h> /* For time_t */
 #include <time.h> /* For time_t */
+#endif
 
 
 /*
 /*
  * Note: archive.h is for use outside of libarchive; the configuration
  * Note: archive.h is for use outside of libarchive; the configuration
@@ -63,12 +66,15 @@
 #define __LA_INT64_T_DEFINED
 #define __LA_INT64_T_DEFINED
 # if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
 # if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
 typedef __int64 la_int64_t;
 typedef __int64 la_int64_t;
+typedef unsigned __int64 la_uint64_t;
 # else
 # else
 # include <unistd.h>  /* ssize_t */
 # include <unistd.h>  /* ssize_t */
 #  if defined(_SCO_DS) || defined(__osf__)
 #  if defined(_SCO_DS) || defined(__osf__)
 typedef long long la_int64_t;
 typedef long long la_int64_t;
+typedef unsigned long long la_uint64_t;
 #  else
 #  else
 typedef int64_t la_int64_t;
 typedef int64_t la_int64_t;
+typedef uint64_t la_uint64_t;
 #  endif
 #  endif
 # endif
 # endif
 #endif
 #endif
@@ -94,6 +100,22 @@ typedef ssize_t la_ssize_t;
 # endif
 # endif
 #endif
 #endif
 
 
+#if ARCHIVE_VERSION_NUMBER < 4000000
+/* Use the platform types for time_t */
+#define __LA_TIME_T time_t
+#else
+/* Use 64-bits integer types for time_t */
+#define __LA_TIME_T la_int64_t
+#endif
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+/* Use the platform types for dev_t */
+#define __LA_DEV_T dev_t
+#else
+/* Use 64-bits integer types for dev_t */
+#define __LA_DEV_T la_int64_t
+#endif
+
 /* Large file support for Android */
 /* Large file support for Android */
 #if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
 #if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
 #include "android_lf.h"
 #include "android_lf.h"
@@ -152,7 +174,7 @@ __LA_DECL int		archive_version_number(void);
 /*
 /*
  * Textual name/version of the library, useful for version displays.
  * Textual name/version of the library, useful for version displays.
  */
  */
-#define	ARCHIVE_VERSION_ONLY_STRING "3.7.9"
+#define	ARCHIVE_VERSION_ONLY_STRING "3.8.1"
 #define	ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
 #define	ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
 __LA_DECL const char *	archive_version_string(void);
 __LA_DECL const char *	archive_version_string(void);
 
 
@@ -175,6 +197,23 @@ __LA_DECL const char *  archive_liblzma_version(void);
 __LA_DECL const char *  archive_bzlib_version(void);
 __LA_DECL const char *  archive_bzlib_version(void);
 __LA_DECL const char *  archive_liblz4_version(void);
 __LA_DECL const char *  archive_liblz4_version(void);
 __LA_DECL const char *  archive_libzstd_version(void);
 __LA_DECL const char *  archive_libzstd_version(void);
+__LA_DECL const char *  archive_liblzo2_version(void);
+__LA_DECL const char *  archive_libexpat_version(void);
+__LA_DECL const char *  archive_libbsdxml_version(void);
+__LA_DECL const char *  archive_libxml2_version(void);
+__LA_DECL const char *  archive_mbedtls_version(void);
+__LA_DECL const char *  archive_nettle_version(void);
+__LA_DECL const char *  archive_openssl_version(void);
+__LA_DECL const char *  archive_libmd_version(void);
+__LA_DECL const char *  archive_commoncrypto_version(void);
+__LA_DECL const char *  archive_cng_version(void);
+__LA_DECL const char *  archive_wincrypt_version(void);
+__LA_DECL const char *  archive_librichacl_version(void);
+__LA_DECL const char *  archive_libacl_version(void);
+__LA_DECL const char *  archive_libattr_version(void);
+__LA_DECL const char *  archive_libiconv_version(void);
+__LA_DECL const char *  archive_libpcre_version(void);
+__LA_DECL const char *  archive_libpcre2_version(void);
 
 
 /* Declare our basic types. */
 /* Declare our basic types. */
 struct archive;
 struct archive;
@@ -446,6 +485,8 @@ __LA_DECL int archive_read_support_format_by_code(struct archive *, int);
 __LA_DECL int archive_read_support_format_cab(struct archive *);
 __LA_DECL int archive_read_support_format_cab(struct archive *);
 __LA_DECL int archive_read_support_format_cpio(struct archive *);
 __LA_DECL int archive_read_support_format_cpio(struct archive *);
 __LA_DECL int archive_read_support_format_empty(struct archive *);
 __LA_DECL int archive_read_support_format_empty(struct archive *);
+/* archive_read_support_format_gnutar() is an alias for historical reasons
+ * of archive_read_support_format_tar(). */
 __LA_DECL int archive_read_support_format_gnutar(struct archive *);
 __LA_DECL int archive_read_support_format_gnutar(struct archive *);
 __LA_DECL int archive_read_support_format_iso9660(struct archive *);
 __LA_DECL int archive_read_support_format_iso9660(struct archive *);
 __LA_DECL int archive_read_support_format_lha(struct archive *);
 __LA_DECL int archive_read_support_format_lha(struct archive *);
@@ -825,6 +866,10 @@ __LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const ch
 __LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext);
 __LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext);
 __LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
 __LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
 __LA_DECL int archive_write_zip_set_compression_store(struct archive *);
 __LA_DECL int archive_write_zip_set_compression_store(struct archive *);
+__LA_DECL int archive_write_zip_set_compression_lzma(struct archive *);
+__LA_DECL int archive_write_zip_set_compression_xz(struct archive *);
+__LA_DECL int archive_write_zip_set_compression_bzip2(struct archive *);
+__LA_DECL int archive_write_zip_set_compression_zstd(struct archive *);
 /* Deprecated; use archive_write_open2 instead */
 /* Deprecated; use archive_write_open2 instead */
 __LA_DECL int archive_write_open(struct archive *, void *,
 __LA_DECL int archive_write_open(struct archive *, void *,
 		     archive_open_callback *, archive_write_callback *,
 		     archive_open_callback *, archive_write_callback *,
@@ -1080,6 +1125,10 @@ __LA_DECL int		 archive_compression(struct archive *)
 				__LA_DEPRECATED;
 				__LA_DEPRECATED;
 #endif
 #endif
 
 
+/* Parses a date string relative to the current time.
+ * NOTE: This is not intended for general date parsing, and the resulting timestamp should only be used for libarchive. */
+__LA_DECL time_t	archive_parse_date(time_t now, const char *datestr);
+
 __LA_DECL int		 archive_errno(struct archive *);
 __LA_DECL int		 archive_errno(struct archive *);
 __LA_DECL const char	*archive_error_string(struct archive *);
 __LA_DECL const char	*archive_error_string(struct archive *);
 __LA_DECL const char	*archive_format_name(struct archive *);
 __LA_DECL const char	*archive_format_name(struct archive *);
@@ -1198,8 +1247,10 @@ __LA_DECL int	archive_match_include_gname_w(struct archive *,
 		    const wchar_t *);
 		    const wchar_t *);
 
 
 /* Utility functions */
 /* Utility functions */
+#if ARCHIVE_VERSION_NUMBER < 4000000
 /* Convenience function to sort a NULL terminated list of strings */
 /* Convenience function to sort a NULL terminated list of strings */
 __LA_DECL int archive_utility_string_sort(char **);
 __LA_DECL int archive_utility_string_sort(char **);
+#endif
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

+ 12 - 2
Utilities/cmlibarchive/libarchive/archive_acl.c

@@ -1189,8 +1189,13 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
 		/* Set remaining fields to blank. */
 		/* Set remaining fields to blank. */
 		for (n = fields; n < numfields; ++n)
 		for (n = fields; n < numfields; ++n)
 			field[n].start = field[n].end = NULL;
 			field[n].start = field[n].end = NULL;
+		
+		if (field[0].start == NULL || field[0].end == NULL) {
+			/* This should never happen */
+			return (ARCHIVE_FATAL);
+		}
 
 
-		if (field[0].start != NULL && *(field[0].start) == L'#') {
+		if (*(field[0].start) == L'#') {
 			/* Comment, skip entry */
 			/* Comment, skip entry */
 			continue;
 			continue;
 		}
 		}
@@ -1683,7 +1688,12 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text,
 		for (n = fields; n < numfields; ++n)
 		for (n = fields; n < numfields; ++n)
 			field[n].start = field[n].end = NULL;
 			field[n].start = field[n].end = NULL;
 
 
-		if (field[0].start != NULL && *(field[0].start) == '#') {
+		if (field[0].start == NULL || field[0].end == NULL) {
+			/* This should never happen */
+			return (ARCHIVE_FATAL);
+		}
+
+		if (*(field[0].start) == '#') {
 			/* Comment, skip entry */
 			/* Comment, skip entry */
 			continue;
 			continue;
 		}
 		}

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_acl_private.h

@@ -80,4 +80,4 @@ int archive_acl_from_text_l(struct archive_acl *, const char * /* text */,
 int archive_acl_from_text_nl(struct archive_acl *, const char * /* text */,
 int archive_acl_from_text_nl(struct archive_acl *, const char * /* text */,
     size_t /* size of text */, int /* type */, struct archive_string_conv *);
     size_t /* size of text */, int /* type */, struct archive_string_conv *);
 
 
-#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
+#endif /* !ARCHIVE_ACL_PRIVATE_H_INCLUDED */

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_cmdline.c

@@ -71,7 +71,7 @@ get_argument(struct archive_string *as, const char *p)
 	archive_string_empty(as);
 	archive_string_empty(as);
 
 
 	/* Skip beginning space characters. */
 	/* Skip beginning space characters. */
-	while (*s != '\0' && *s == ' ')
+	while (*s == ' ')
 		s++;
 		s++;
 	/* Copy non-space characters. */
 	/* Copy non-space characters. */
 	while (*s != '\0' && *s != ' ') {
 	while (*s != '\0' && *s != ' ') {

+ 8 - 0
Utilities/cmlibarchive/libarchive/archive_cryptor_private.h

@@ -64,6 +64,7 @@ typedef struct {
 
 
 #elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
 #elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
 #include <bcrypt.h>
 #include <bcrypt.h>
+#define	ARCHIVE_CRYPTOR_USE_CNG 1
 
 
 /* Common in other bcrypt implementations, but missing from VS2008. */
 /* Common in other bcrypt implementations, but missing from VS2008. */
 #ifndef BCRYPT_SUCCESS
 #ifndef BCRYPT_SUCCESS
@@ -86,6 +87,7 @@ typedef struct {
 #include <mbedtls/aes.h>
 #include <mbedtls/aes.h>
 #include <mbedtls/md.h>
 #include <mbedtls/md.h>
 #include <mbedtls/pkcs5.h>
 #include <mbedtls/pkcs5.h>
+#define	ARCHIVE_CRYPTOR_USE_MBED 1
 
 
 #define AES_MAX_KEY_SIZE 32
 #define AES_MAX_KEY_SIZE 32
 #define AES_BLOCK_SIZE 16
 #define AES_BLOCK_SIZE 16
@@ -105,6 +107,7 @@ typedef struct {
 #endif
 #endif
 #include <nettle/aes.h>
 #include <nettle/aes.h>
 #include <nettle/version.h>
 #include <nettle/version.h>
+#define	ARCHIVE_CRYPTOR_USE_NETTLE 1
 
 
 typedef struct {
 typedef struct {
 #if NETTLE_VERSION_MAJOR < 3
 #if NETTLE_VERSION_MAJOR < 3
@@ -125,6 +128,7 @@ typedef struct {
 
 
 #elif defined(HAVE_LIBCRYPTO)
 #elif defined(HAVE_LIBCRYPTO)
 #include "archive_openssl_evp_private.h"
 #include "archive_openssl_evp_private.h"
+#define	ARCHIVE_CRYPTOR_USE_OPENSSL 1
 #define AES_BLOCK_SIZE	16
 #define AES_BLOCK_SIZE	16
 #define AES_MAX_KEY_SIZE 32
 #define AES_MAX_KEY_SIZE 32
 
 
@@ -140,6 +144,10 @@ typedef struct {
 
 
 #else
 #else
 
 
+#if defined(_WIN32) && !defined(__CYGWIN__) && !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA)
+#define ARCHIVE_CRYPTOR_USE_WINCRYPT 1
+#endif
+
 #define AES_BLOCK_SIZE	16
 #define AES_BLOCK_SIZE	16
 #define AES_MAX_KEY_SIZE 32
 #define AES_MAX_KEY_SIZE 32
 typedef int archive_crypto_ctx;
 typedef int archive_crypto_ctx;

+ 203 - 130
Utilities/cmlibarchive/libarchive/archive_digest.c

@@ -229,13 +229,42 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
 #pragma clang diagnostic pop
 #pragma clang diagnostic pop
 #endif
 #endif
 
 
+#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
+
+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
+__archive_md5update(archive_md5_ctx *ctx, const void *indata,
+    size_t insize)
+{
+  return (win_crypto_Update(ctx, indata, insize));
+}
+
+static int
+__archive_md5final(archive_md5_ctx *ctx, void *md)
+{
+  return (win_crypto_Final(md, 16, ctx));
+}
+
 #elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
 #elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
 
 
 static int
 static int
 __archive_md5init(archive_md5_ctx *ctx)
 __archive_md5init(archive_md5_ctx *ctx)
 {
 {
   mbedtls_md5_init(ctx);
   mbedtls_md5_init(ctx);
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_md5_starts(ctx) == 0)
+#else
   if (mbedtls_md5_starts_ret(ctx) == 0)
   if (mbedtls_md5_starts_ret(ctx) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -245,7 +274,11 @@ static int
 __archive_md5update(archive_md5_ctx *ctx, const void *indata,
 __archive_md5update(archive_md5_ctx *ctx, const void *indata,
     size_t insize)
     size_t insize)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_md5_update(ctx, indata, insize) == 0)
+#else
   if (mbedtls_md5_update_ret(ctx, indata, insize) == 0)
   if (mbedtls_md5_update_ret(ctx, indata, insize) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -254,7 +287,11 @@ __archive_md5update(archive_md5_ctx *ctx, const void *indata,
 static int
 static int
 __archive_md5final(archive_md5_ctx *ctx, void *md)
 __archive_md5final(archive_md5_ctx *ctx, void *md)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_md5_finish(ctx, md) == 0) {
+#else
   if (mbedtls_md5_finish_ret(ctx, md) == 0) {
   if (mbedtls_md5_finish_ret(ctx, md) == 0) {
+#endif
     mbedtls_md5_free(ctx);
     mbedtls_md5_free(ctx);
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   } else {
   } else {
@@ -322,31 +359,6 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
   return (ARCHIVE_OK);
   return (ARCHIVE_OK);
 }
 }
 
 
-#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
-
-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
-__archive_md5update(archive_md5_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  return (win_crypto_Update(ctx, indata, insize));
-}
-
-static int
-__archive_md5final(archive_md5_ctx *ctx, void *md)
-{
-  return (win_crypto_Final(md, 16, ctx));
-}
-
 #else
 #else
 
 
 static int
 static int
@@ -431,7 +443,11 @@ static int
 __archive_ripemd160init(archive_rmd160_ctx *ctx)
 __archive_ripemd160init(archive_rmd160_ctx *ctx)
 {
 {
   mbedtls_ripemd160_init(ctx);
   mbedtls_ripemd160_init(ctx);
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_ripemd160_starts(ctx) == 0)
+#else
   if (mbedtls_ripemd160_starts_ret(ctx) == 0)
   if (mbedtls_ripemd160_starts_ret(ctx) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -441,7 +457,11 @@ static int
 __archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
 __archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
     size_t insize)
     size_t insize)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_ripemd160_update(ctx, indata, insize) == 0)
+#else
   if (mbedtls_ripemd160_update_ret(ctx, indata, insize) == 0)
   if (mbedtls_ripemd160_update_ret(ctx, indata, insize) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -450,7 +470,11 @@ __archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
 static int
 static int
 __archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
 __archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_ripemd160_finish(ctx, md) == 0) {
+#else
   if (mbedtls_ripemd160_finish_ret(ctx, md) == 0) {
   if (mbedtls_ripemd160_finish_ret(ctx, md) == 0) {
+#endif
     mbedtls_ripemd160_free(ctx);
     mbedtls_ripemd160_free(ctx);
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   } else {
   } else {
@@ -616,13 +640,42 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
   return (ARCHIVE_OK);
   return (ARCHIVE_OK);
 }
 }
 
 
+#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
+
+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
+__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
+    size_t insize)
+{
+  return (win_crypto_Update(ctx, indata, insize));
+}
+
+static int
+__archive_sha1final(archive_sha1_ctx *ctx, void *md)
+{
+  return (win_crypto_Final(md, 20, ctx));
+}
+
 #elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
 #elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
 
 
 static int
 static int
 __archive_sha1init(archive_sha1_ctx *ctx)
 __archive_sha1init(archive_sha1_ctx *ctx)
 {
 {
   mbedtls_sha1_init(ctx);
   mbedtls_sha1_init(ctx);
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha1_starts(ctx) == 0)
+#else
   if (mbedtls_sha1_starts_ret(ctx) == 0)
   if (mbedtls_sha1_starts_ret(ctx) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -632,7 +685,11 @@ static int
 __archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
 __archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
     size_t insize)
     size_t insize)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha1_update(ctx, indata, insize) == 0)
+#else
   if (mbedtls_sha1_update_ret(ctx, indata, insize) == 0)
   if (mbedtls_sha1_update_ret(ctx, indata, insize) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -641,7 +698,11 @@ __archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
 static int
 static int
 __archive_sha1final(archive_sha1_ctx *ctx, void *md)
 __archive_sha1final(archive_sha1_ctx *ctx, void *md)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha1_finish(ctx, md) == 0) {
+#else
   if (mbedtls_sha1_finish_ret(ctx, md) == 0) {
   if (mbedtls_sha1_finish_ret(ctx, md) == 0) {
+#endif
     mbedtls_sha1_free(ctx);
     mbedtls_sha1_free(ctx);
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   } else {
   } else {
@@ -709,31 +770,6 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
   return (ARCHIVE_OK);
   return (ARCHIVE_OK);
 }
 }
 
 
-#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
-
-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
-__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  return (win_crypto_Update(ctx, indata, insize));
-}
-
-static int
-__archive_sha1final(archive_sha1_ctx *ctx, void *md)
-{
-  return (win_crypto_Final(md, 20, ctx));
-}
-
 #else
 #else
 
 
 static int
 static int
@@ -884,13 +920,42 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
   return (ARCHIVE_OK);
   return (ARCHIVE_OK);
 }
 }
 
 
+#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
+
+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
+__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
+    size_t insize)
+{
+  return (win_crypto_Update(ctx, indata, insize));
+}
+
+static int
+__archive_sha256final(archive_sha256_ctx *ctx, void *md)
+{
+  return (win_crypto_Final(md, 32, ctx));
+}
+
 #elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
 #elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
 
 
 static int
 static int
 __archive_sha256init(archive_sha256_ctx *ctx)
 __archive_sha256init(archive_sha256_ctx *ctx)
 {
 {
   mbedtls_sha256_init(ctx);
   mbedtls_sha256_init(ctx);
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha256_starts(ctx, 0) == 0)
+#else
   if (mbedtls_sha256_starts_ret(ctx, 0) == 0)
   if (mbedtls_sha256_starts_ret(ctx, 0) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -900,7 +965,11 @@ static int
 __archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
 __archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
     size_t insize)
     size_t insize)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha256_update(ctx, indata, insize) == 0)
+#else
   if (mbedtls_sha256_update_ret(ctx, indata, insize) == 0)
   if (mbedtls_sha256_update_ret(ctx, indata, insize) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -909,7 +978,11 @@ __archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
 static int
 static int
 __archive_sha256final(archive_sha256_ctx *ctx, void *md)
 __archive_sha256final(archive_sha256_ctx *ctx, void *md)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha256_finish(ctx, md) == 0) {
+#else
   if (mbedtls_sha256_finish_ret(ctx, md) == 0) {
   if (mbedtls_sha256_finish_ret(ctx, md) == 0) {
+#endif
     mbedtls_sha256_free(ctx);
     mbedtls_sha256_free(ctx);
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   } else {
   } else {
@@ -973,31 +1046,6 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
   return (ARCHIVE_OK);
   return (ARCHIVE_OK);
 }
 }
 
 
-#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
-
-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
-__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  return (win_crypto_Update(ctx, indata, insize));
-}
-
-static int
-__archive_sha256final(archive_sha256_ctx *ctx, void *md)
-{
-  return (win_crypto_Final(md, 32, ctx));
-}
-
 #else
 #else
 
 
 static int
 static int
@@ -1124,13 +1172,42 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
   return (ARCHIVE_OK);
   return (ARCHIVE_OK);
 }
 }
 
 
+#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
+
+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
+__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
+    size_t insize)
+{
+  return (win_crypto_Update(ctx, indata, insize));
+}
+
+static int
+__archive_sha384final(archive_sha384_ctx *ctx, void *md)
+{
+  return (win_crypto_Final(md, 48, ctx));
+}
+
 #elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
 #elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
 
 
 static int
 static int
 __archive_sha384init(archive_sha384_ctx *ctx)
 __archive_sha384init(archive_sha384_ctx *ctx)
 {
 {
   mbedtls_sha512_init(ctx);
   mbedtls_sha512_init(ctx);
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha512_starts(ctx, 1) == 0)
+#else
   if (mbedtls_sha512_starts_ret(ctx, 1) == 0)
   if (mbedtls_sha512_starts_ret(ctx, 1) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -1140,7 +1217,11 @@ static int
 __archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
 __archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
     size_t insize)
     size_t insize)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha512_update(ctx, indata, insize) == 0)
+#else
   if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
   if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -1149,7 +1230,11 @@ __archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
 static int
 static int
 __archive_sha384final(archive_sha384_ctx *ctx, void *md)
 __archive_sha384final(archive_sha384_ctx *ctx, void *md)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha512_finish(ctx, md) == 0) {
+#else
   if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
   if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
+#endif
     mbedtls_sha512_free(ctx);
     mbedtls_sha512_free(ctx);
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   } else {
   } else {
@@ -1213,31 +1298,6 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
   return (ARCHIVE_OK);
   return (ARCHIVE_OK);
 }
 }
 
 
-#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
-
-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
-__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  return (win_crypto_Update(ctx, indata, insize));
-}
-
-static int
-__archive_sha384final(archive_sha384_ctx *ctx, void *md)
-{
-  return (win_crypto_Final(md, 48, ctx));
-}
-
 #else
 #else
 
 
 static int
 static int
@@ -1388,13 +1448,42 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
   return (ARCHIVE_OK);
   return (ARCHIVE_OK);
 }
 }
 
 
+#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
+
+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
+__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
+    size_t insize)
+{
+  return (win_crypto_Update(ctx, indata, insize));
+}
+
+static int
+__archive_sha512final(archive_sha512_ctx *ctx, void *md)
+{
+  return (win_crypto_Final(md, 64, ctx));
+}
+
 #elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
 #elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
 
 
 static int
 static int
 __archive_sha512init(archive_sha512_ctx *ctx)
 __archive_sha512init(archive_sha512_ctx *ctx)
 {
 {
   mbedtls_sha512_init(ctx);
   mbedtls_sha512_init(ctx);
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha512_starts(ctx, 0) == 0)
+#else
   if (mbedtls_sha512_starts_ret(ctx, 0) == 0)
   if (mbedtls_sha512_starts_ret(ctx, 0) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -1404,7 +1493,11 @@ static int
 __archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
 __archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
     size_t insize)
     size_t insize)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha512_update(ctx, indata, insize) == 0)
+#else
   if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
   if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
+#endif
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   else
   else
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
@@ -1413,7 +1506,11 @@ __archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
 static int
 static int
 __archive_sha512final(archive_sha512_ctx *ctx, void *md)
 __archive_sha512final(archive_sha512_ctx *ctx, void *md)
 {
 {
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha512_finish(ctx, md) == 0) {
+#else
   if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
   if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
+#endif
     mbedtls_sha512_free(ctx);
     mbedtls_sha512_free(ctx);
     return (ARCHIVE_OK);
     return (ARCHIVE_OK);
   } else {
   } else {
@@ -1477,31 +1574,6 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
   return (ARCHIVE_OK);
   return (ARCHIVE_OK);
 }
 }
 
 
-#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
-
-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
-__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
-    size_t insize)
-{
-  return (win_crypto_Update(ctx, indata, insize));
-}
-
-static int
-__archive_sha512final(archive_sha512_ctx *ctx, void *md)
-{
-  return (win_crypto_Final(md, 64, ctx));
-}
-
 #else
 #else
 
 
 static int
 static int
@@ -1536,11 +1608,12 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
  * 1. libc
  * 1. libc
  * 2. libc2
  * 2. libc2
  * 3. libc3
  * 3. libc3
- * 4. libSystem
- * 5. Nettle
- * 6. OpenSSL
- * 7. libmd
- * 8. Windows API
+ * 4. libmd
+ * 5. libSystem
+ * 6. Windows API
+ * 7. mbedTLS
+ * 8. Nettle
+ * 9. OpenSSL
  */
  */
 const struct archive_digest __archive_digest =
 const struct archive_digest __archive_digest =
 {
 {

+ 25 - 10
Utilities/cmlibarchive/libarchive/archive_digest_private.h

@@ -113,6 +113,7 @@
   defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
   defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
   defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
   defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
 #include <CommonCrypto/CommonDigest.h>
 #include <CommonCrypto/CommonDigest.h>
+#define	ARCHIVE_CRYPTO_CommonCrypto 1
 #endif
 #endif
 
 
 /* mbed TLS crypto headers */
 /* mbed TLS crypto headers */
@@ -167,6 +168,7 @@
 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
 /* don't use bcrypt when XP needs to be supported */
 /* don't use bcrypt when XP needs to be supported */
 #include <bcrypt.h>
 #include <bcrypt.h>
+#define	ARCHIVE_CRYPTO_CNG 1
 typedef struct {
 typedef struct {
   int   valid;
   int   valid;
   BCRYPT_ALG_HANDLE  hAlg;
   BCRYPT_ALG_HANDLE  hAlg;
@@ -175,6 +177,7 @@ typedef struct {
 #else
 #else
 #include <windows.h>
 #include <windows.h>
 #include <wincrypt.h>
 #include <wincrypt.h>
+#define	ARCHIVE_CRYPTO_WINCRYPT 1
 typedef struct {
 typedef struct {
   int   valid;
   int   valid;
   HCRYPTPROV  cryptProv;
   HCRYPTPROV  cryptProv;
@@ -190,14 +193,16 @@ typedef MD5_CTX archive_md5_ctx;
 typedef MD5_CTX archive_md5_ctx;
 typedef MD5_CTX archive_md5_ctx;
 #elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
 #elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
 typedef CC_MD5_CTX archive_md5_ctx;
 typedef CC_MD5_CTX archive_md5_ctx;
+#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
+typedef Digest_CTX archive_md5_ctx;
 #elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
 #elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_md5_context archive_md5_ctx;
 typedef mbedtls_md5_context archive_md5_ctx;
 #elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
 #elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct md5_ctx archive_md5_ctx;
 typedef struct md5_ctx archive_md5_ctx;
 #elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
 #elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
 typedef EVP_MD_CTX *archive_md5_ctx;
 typedef EVP_MD_CTX *archive_md5_ctx;
-#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
-typedef Digest_CTX archive_md5_ctx;
 #else
 #else
 typedef unsigned char archive_md5_ctx;
 typedef unsigned char archive_md5_ctx;
 #endif
 #endif
@@ -207,8 +212,10 @@ typedef RMD160_CTX archive_rmd160_ctx;
 #elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
 #elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
 typedef RIPEMD160_CTX archive_rmd160_ctx;
 typedef RIPEMD160_CTX archive_rmd160_ctx;
 #elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS)
 #elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_ripemd160_context archive_rmd160_ctx;
 typedef mbedtls_ripemd160_context archive_rmd160_ctx;
 #elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
 #elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct ripemd160_ctx archive_rmd160_ctx;
 typedef struct ripemd160_ctx archive_rmd160_ctx;
 #elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
 #elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
 typedef EVP_MD_CTX *archive_rmd160_ctx;
 typedef EVP_MD_CTX *archive_rmd160_ctx;
@@ -222,14 +229,16 @@ typedef SHA1_CTX archive_sha1_ctx;
 typedef SHA1_CTX archive_sha1_ctx;
 typedef SHA1_CTX archive_sha1_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
 #elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
 typedef CC_SHA1_CTX archive_sha1_ctx;
 typedef CC_SHA1_CTX archive_sha1_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
+typedef Digest_CTX archive_sha1_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
 #elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_sha1_context archive_sha1_ctx;
 typedef mbedtls_sha1_context archive_sha1_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
 #elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct sha1_ctx archive_sha1_ctx;
 typedef struct sha1_ctx archive_sha1_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
 #elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
 typedef EVP_MD_CTX *archive_sha1_ctx;
 typedef EVP_MD_CTX *archive_sha1_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
-typedef Digest_CTX archive_sha1_ctx;
 #else
 #else
 typedef unsigned char archive_sha1_ctx;
 typedef unsigned char archive_sha1_ctx;
 #endif
 #endif
@@ -244,14 +253,16 @@ typedef SHA2_CTX archive_sha256_ctx;
 typedef SHA256_CTX archive_sha256_ctx;
 typedef SHA256_CTX archive_sha256_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
 #elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
 typedef CC_SHA256_CTX archive_sha256_ctx;
 typedef CC_SHA256_CTX archive_sha256_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
+typedef Digest_CTX archive_sha256_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
 #elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_sha256_context archive_sha256_ctx;
 typedef mbedtls_sha256_context archive_sha256_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
 #elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct sha256_ctx archive_sha256_ctx;
 typedef struct sha256_ctx archive_sha256_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
 #elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
 typedef EVP_MD_CTX *archive_sha256_ctx;
 typedef EVP_MD_CTX *archive_sha256_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
-typedef Digest_CTX archive_sha256_ctx;
 #else
 #else
 typedef unsigned char archive_sha256_ctx;
 typedef unsigned char archive_sha256_ctx;
 #endif
 #endif
@@ -264,14 +275,16 @@ typedef SHA384_CTX archive_sha384_ctx;
 typedef SHA2_CTX archive_sha384_ctx;
 typedef SHA2_CTX archive_sha384_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
 #elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
 typedef CC_SHA512_CTX archive_sha384_ctx;
 typedef CC_SHA512_CTX archive_sha384_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
+typedef Digest_CTX archive_sha384_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
 #elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_sha512_context archive_sha384_ctx;
 typedef mbedtls_sha512_context archive_sha384_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
 #elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct sha384_ctx archive_sha384_ctx;
 typedef struct sha384_ctx archive_sha384_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
 #elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
 typedef EVP_MD_CTX *archive_sha384_ctx;
 typedef EVP_MD_CTX *archive_sha384_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
-typedef Digest_CTX archive_sha384_ctx;
 #else
 #else
 typedef unsigned char archive_sha384_ctx;
 typedef unsigned char archive_sha384_ctx;
 #endif
 #endif
@@ -286,14 +299,16 @@ typedef SHA2_CTX archive_sha512_ctx;
 typedef SHA512_CTX archive_sha512_ctx;
 typedef SHA512_CTX archive_sha512_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
 #elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
 typedef CC_SHA512_CTX archive_sha512_ctx;
 typedef CC_SHA512_CTX archive_sha512_ctx;
+#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
+typedef Digest_CTX archive_sha512_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
 #elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_sha512_context archive_sha512_ctx;
 typedef mbedtls_sha512_context archive_sha512_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
 #elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct sha512_ctx archive_sha512_ctx;
 typedef struct sha512_ctx archive_sha512_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
 #elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
 typedef EVP_MD_CTX *archive_sha512_ctx;
 typedef EVP_MD_CTX *archive_sha512_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
-typedef Digest_CTX archive_sha512_ctx;
 #else
 #else
 typedef unsigned char archive_sha512_ctx;
 typedef unsigned char archive_sha512_ctx;
 #endif
 #endif

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_disk_acl_darwin.c

@@ -195,7 +195,7 @@ add_trivial_nfs4_acl(struct archive_entry *entry)
 	} else if ((mode & 0010) || (mode & 0001))
 	} else if ((mode & 0010) || (mode & 0001))
 		tacl_entry[1].permset |= eperm;
 		tacl_entry[1].permset |= eperm;
 
 
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < sizeof(tacl_entry) / sizeof(tacl_entry[0]); i++) {
 		if (tacl_entry[i].permset != 0) {
 		if (tacl_entry[i].permset != 0) {
 			archive_entry_acl_add_entry(entry,
 			archive_entry_acl_add_entry(entry,
 			    tacl_entry[i].type, tacl_entry[i].permset,
 			    tacl_entry[i].type, tacl_entry[i].permset,

+ 2 - 2
Utilities/cmlibarchive/libarchive/archive_disk_acl_freebsd.c

@@ -262,7 +262,7 @@ translate_acl(struct archive_read_disk *a,
 			}
 			}
 			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
 			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
 				r = acl_get_flag_np(acl_flagset,
 				r = acl_get_flag_np(acl_flagset,
-				    acl_nfs4_flag_map[i].p_perm);
+				    (acl_flag_t)acl_nfs4_flag_map[i].p_perm);
 				if (r == -1) {
 				if (r == -1) {
 					archive_set_error(&a->archive, errno,
 					archive_set_error(&a->archive, errno,
 					    "Failed to check flag in a NFSv4 "
 					    "Failed to check flag in a NFSv4 "
@@ -517,7 +517,7 @@ set_acl(struct archive *a, int fd, const char *name,
 			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
 			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
 				if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
 				if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
 					if (acl_add_flag_np(acl_flagset,
 					if (acl_add_flag_np(acl_flagset,
-					    acl_nfs4_flag_map[i].p_perm) != 0) {
+					    (acl_flag_t)acl_nfs4_flag_map[i].p_perm) != 0) {
 						archive_set_error(a, errno,
 						archive_set_error(a, errno,
 						    "Failed to add flag to "
 						    "Failed to add flag to "
 						    "NFSv4 ACL flagset");
 						    "NFSv4 ACL flagset");

+ 32 - 22
Utilities/cmlibarchive/libarchive/archive_entry.c

@@ -275,7 +275,7 @@ archive_entry_new2(struct archive *a)
  * Functions for reading fields from an archive_entry.
  * Functions for reading fields from an archive_entry.
  */
  */
 
 
-time_t
+__LA_TIME_T
 archive_entry_atime(struct archive_entry *entry)
 archive_entry_atime(struct archive_entry *entry)
 {
 {
 	return (entry->ae_stat.aest_atime);
 	return (entry->ae_stat.aest_atime);
@@ -293,7 +293,7 @@ archive_entry_atime_is_set(struct archive_entry *entry)
 	return (entry->ae_set & AE_SET_ATIME);
 	return (entry->ae_set & AE_SET_ATIME);
 }
 }
 
 
-time_t
+__LA_TIME_T
 archive_entry_birthtime(struct archive_entry *entry)
 archive_entry_birthtime(struct archive_entry *entry)
 {
 {
 	return (entry->ae_stat.aest_birthtime);
 	return (entry->ae_stat.aest_birthtime);
@@ -311,7 +311,7 @@ archive_entry_birthtime_is_set(struct archive_entry *entry)
 	return (entry->ae_set & AE_SET_BIRTHTIME);
 	return (entry->ae_set & AE_SET_BIRTHTIME);
 }
 }
 
 
-time_t
+__LA_TIME_T
 archive_entry_ctime(struct archive_entry *entry)
 archive_entry_ctime(struct archive_entry *entry)
 {
 {
 	return (entry->ae_stat.aest_ctime);
 	return (entry->ae_stat.aest_ctime);
@@ -329,7 +329,7 @@ archive_entry_ctime_nsec(struct archive_entry *entry)
 	return (entry->ae_stat.aest_ctime_nsec);
 	return (entry->ae_stat.aest_ctime_nsec);
 }
 }
 
 
-dev_t
+__LA_DEV_T
 archive_entry_dev(struct archive_entry *entry)
 archive_entry_dev(struct archive_entry *entry)
 {
 {
 	if (entry->ae_stat.aest_dev_is_broken_down)
 	if (entry->ae_stat.aest_dev_is_broken_down)
@@ -345,7 +345,7 @@ archive_entry_dev_is_set(struct archive_entry *entry)
 	return (entry->ae_set & AE_SET_DEV);
 	return (entry->ae_set & AE_SET_DEV);
 }
 }
 
 
-dev_t
+__LA_DEV_T
 archive_entry_devmajor(struct archive_entry *entry)
 archive_entry_devmajor(struct archive_entry *entry)
 {
 {
 	if (entry->ae_stat.aest_dev_is_broken_down)
 	if (entry->ae_stat.aest_dev_is_broken_down)
@@ -354,7 +354,7 @@ archive_entry_devmajor(struct archive_entry *entry)
 		return major(entry->ae_stat.aest_dev);
 		return major(entry->ae_stat.aest_dev);
 }
 }
 
 
-dev_t
+__LA_DEV_T
 archive_entry_devminor(struct archive_entry *entry)
 archive_entry_devminor(struct archive_entry *entry)
 {
 {
 	if (entry->ae_stat.aest_dev_is_broken_down)
 	if (entry->ae_stat.aest_dev_is_broken_down)
@@ -568,7 +568,7 @@ archive_entry_mode(struct archive_entry *entry)
 	return (entry->acl.mode);
 	return (entry->acl.mode);
 }
 }
 
 
-time_t
+__LA_TIME_T
 archive_entry_mtime(struct archive_entry *entry)
 archive_entry_mtime(struct archive_entry *entry)
 {
 {
 	return (entry->ae_stat.aest_mtime);
 	return (entry->ae_stat.aest_mtime);
@@ -667,7 +667,7 @@ archive_entry_rdev_is_set(struct archive_entry *entry)
 	return (entry->ae_set & AE_SET_RDEV);
 	return (entry->ae_set & AE_SET_RDEV);
 }
 }
 
 
-dev_t
+__LA_DEV_T
 archive_entry_rdev(struct archive_entry *entry)
 archive_entry_rdev(struct archive_entry *entry)
 {
 {
 	if (archive_entry_rdev_is_set(entry)) {
 	if (archive_entry_rdev_is_set(entry)) {
@@ -681,7 +681,7 @@ archive_entry_rdev(struct archive_entry *entry)
 	}
 	}
 }
 }
 
 
-dev_t
+__LA_DEV_T
 archive_entry_rdevmajor(struct archive_entry *entry)
 archive_entry_rdevmajor(struct archive_entry *entry)
 {
 {
 	if (archive_entry_rdev_is_set(entry)) {
 	if (archive_entry_rdev_is_set(entry)) {
@@ -694,7 +694,7 @@ archive_entry_rdevmajor(struct archive_entry *entry)
 	}
 	}
 }
 }
 
 
-dev_t
+__LA_DEV_T
 archive_entry_rdevminor(struct archive_entry *entry)
 archive_entry_rdevminor(struct archive_entry *entry)
 {
 {
 	if (archive_entry_rdev_is_set(entry)) {
 	if (archive_entry_rdev_is_set(entry)) {
@@ -984,7 +984,9 @@ void
 archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
 archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
 {
 {
 	if (ino < 0) {
 	if (ino < 0) {
-		ino = 0;
+		entry->stat_valid = 0;
+		entry->ae_set &= ~AE_SET_INO;
+		return;
 	}
 	}
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
 	entry->ae_set |= AE_SET_INO;
 	entry->ae_set |= AE_SET_INO;
@@ -995,7 +997,9 @@ void
 archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
 archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
 {
 {
 	if (ino < 0) {
 	if (ino < 0) {
-		ino = 0;
+		entry->stat_valid = 0;
+		entry->ae_set &= ~AE_SET_INO;
+		return;
 	}
 	}
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
 	entry->ae_set |= AE_SET_INO;
 	entry->ae_set |= AE_SET_INO;
@@ -1088,7 +1092,7 @@ _archive_entry_copy_hardlink_l(struct archive_entry *entry,
 }
 }
 
 
 void
 void
-archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)
+archive_entry_set_atime(struct archive_entry *entry, __LA_TIME_T t, long ns)
 {
 {
 	FIX_NS(t, ns);
 	FIX_NS(t, ns);
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
@@ -1105,7 +1109,7 @@ archive_entry_unset_atime(struct archive_entry *entry)
 }
 }
 
 
 void
 void
-archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns)
+archive_entry_set_birthtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
 {
 {
 	FIX_NS(t, ns);
 	FIX_NS(t, ns);
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
@@ -1122,7 +1126,7 @@ archive_entry_unset_birthtime(struct archive_entry *entry)
 }
 }
 
 
 void
 void
-archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns)
+archive_entry_set_ctime(struct archive_entry *entry, __LA_TIME_T t, long ns)
 {
 {
 	FIX_NS(t, ns);
 	FIX_NS(t, ns);
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
@@ -1139,7 +1143,7 @@ archive_entry_unset_ctime(struct archive_entry *entry)
 }
 }
 
 
 void
 void
-archive_entry_set_dev(struct archive_entry *entry, dev_t d)
+archive_entry_set_dev(struct archive_entry *entry, __LA_DEV_T d)
 {
 {
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
 	entry->ae_set |= AE_SET_DEV;
 	entry->ae_set |= AE_SET_DEV;
@@ -1148,7 +1152,7 @@ archive_entry_set_dev(struct archive_entry *entry, dev_t d)
 }
 }
 
 
 void
 void
-archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
+archive_entry_set_devmajor(struct archive_entry *entry, __LA_DEV_T m)
 {
 {
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
 	entry->ae_set |= AE_SET_DEV;
 	entry->ae_set |= AE_SET_DEV;
@@ -1157,7 +1161,7 @@ archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
 }
 }
 
 
 void
 void
-archive_entry_set_devminor(struct archive_entry *entry, dev_t m)
+archive_entry_set_devminor(struct archive_entry *entry, __LA_DEV_T m)
 {
 {
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
 	entry->ae_set |= AE_SET_DEV;
 	entry->ae_set |= AE_SET_DEV;
@@ -1243,7 +1247,7 @@ archive_entry_set_mode(struct archive_entry *entry, mode_t m)
 }
 }
 
 
 void
 void
-archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns)
+archive_entry_set_mtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
 {
 {
 	FIX_NS(t, ns);
 	FIX_NS(t, ns);
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
@@ -1319,7 +1323,7 @@ archive_entry_set_perm(struct archive_entry *entry, mode_t p)
 }
 }
 
 
 void
 void
-archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
+archive_entry_set_rdev(struct archive_entry *entry, __LA_DEV_T m)
 {
 {
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
 	entry->ae_stat.aest_rdev = m;
 	entry->ae_stat.aest_rdev = m;
@@ -1330,7 +1334,7 @@ archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
 }
 }
 
 
 void
 void
-archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
+archive_entry_set_rdevmajor(struct archive_entry *entry, __LA_DEV_T m)
 {
 {
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
 	entry->ae_stat.aest_rdev_is_broken_down = 1;
 	entry->ae_stat.aest_rdev_is_broken_down = 1;
@@ -1340,7 +1344,7 @@ archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
 }
 }
 
 
 void
 void
-archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
+archive_entry_set_rdevminor(struct archive_entry *entry, __LA_DEV_T m)
 {
 {
 	entry->stat_valid = 0;
 	entry->stat_valid = 0;
 	entry->ae_stat.aest_rdev_is_broken_down = 1;
 	entry->ae_stat.aest_rdev_is_broken_down = 1;
@@ -1603,21 +1607,27 @@ archive_entry_set_digest(struct archive_entry *entry, int type,
 	switch (type) {
 	switch (type) {
 	case ARCHIVE_ENTRY_DIGEST_MD5:
 	case ARCHIVE_ENTRY_DIGEST_MD5:
 		copy_digest(entry, md5, digest);
 		copy_digest(entry, md5, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_MD5;
 		break;
 		break;
 	case ARCHIVE_ENTRY_DIGEST_RMD160:
 	case ARCHIVE_ENTRY_DIGEST_RMD160:
 		copy_digest(entry, rmd160, digest);
 		copy_digest(entry, rmd160, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_RMD160;
 		break;
 		break;
 	case ARCHIVE_ENTRY_DIGEST_SHA1:
 	case ARCHIVE_ENTRY_DIGEST_SHA1:
 		copy_digest(entry, sha1, digest);
 		copy_digest(entry, sha1, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_SHA1;
 		break;
 		break;
 	case ARCHIVE_ENTRY_DIGEST_SHA256:
 	case ARCHIVE_ENTRY_DIGEST_SHA256:
 		copy_digest(entry, sha256, digest);
 		copy_digest(entry, sha256, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_SHA256;
 		break;
 		break;
 	case ARCHIVE_ENTRY_DIGEST_SHA384:
 	case ARCHIVE_ENTRY_DIGEST_SHA384:
 		copy_digest(entry, sha384, digest);
 		copy_digest(entry, sha384, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_SHA384;
 		break;
 		break;
 	case ARCHIVE_ENTRY_DIGEST_SHA512:
 	case ARCHIVE_ENTRY_DIGEST_SHA512:
 		copy_digest(entry, sha512, digest);
 		copy_digest(entry, sha512, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_SHA512;
 		break;
 		break;
 	default:
 	default:
 		return ARCHIVE_WARN;
 		return ARCHIVE_WARN;

+ 56 - 25
Utilities/cmlibarchive/libarchive/archive_entry.h

@@ -28,7 +28,7 @@
 #define	ARCHIVE_ENTRY_H_INCLUDED
 #define	ARCHIVE_ENTRY_H_INCLUDED
 
 
 /* Note: Compiler will complain if this does not match archive.h! */
 /* Note: Compiler will complain if this does not match archive.h! */
-#define	ARCHIVE_VERSION_NUMBER 3007009
+#define	ARCHIVE_VERSION_NUMBER 3008001
 
 
 /*
 /*
  * Note: archive_entry.h is for use outside of libarchive; the
  * Note: archive_entry.h is for use outside of libarchive; the
@@ -40,8 +40,11 @@
 
 
 #include <sys/types.h>
 #include <sys/types.h>
 #include <stddef.h>  /* for wchar_t */
 #include <stddef.h>  /* for wchar_t */
-#include <stdint.h>
+#include <stdint.h>  /* for C99 int64_t, etc. */
+#if ARCHIVE_VERSION_NUMBER < 4000000
+/* time_t is slated to be removed from public includes in 4.0 */
 #include <time.h>
 #include <time.h>
+#endif
 
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #include <windows.h>
 #include <windows.h>
@@ -55,12 +58,15 @@
 #define __LA_INT64_T_DEFINED
 #define __LA_INT64_T_DEFINED
 # if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
 # if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
 typedef __int64 la_int64_t;
 typedef __int64 la_int64_t;
+typedef unsigned __int64 la_uint64_t;
 # else
 # else
 #include <unistd.h>
 #include <unistd.h>
 #  if defined(_SCO_DS) || defined(__osf__)
 #  if defined(_SCO_DS) || defined(__osf__)
 typedef long long la_int64_t;
 typedef long long la_int64_t;
+typedef unsigned long long la_uint64_t;
 #  else
 #  else
 typedef int64_t la_int64_t;
 typedef int64_t la_int64_t;
+typedef uint64_t la_uint64_t;
 #  endif
 #  endif
 # endif
 # endif
 #endif
 #endif
@@ -96,6 +102,30 @@ typedef ssize_t la_ssize_t;
 # define	__LA_MODE_T	mode_t
 # define	__LA_MODE_T	mode_t
 #endif
 #endif
 
 
+#if ARCHIVE_VERSION_NUMBER < 4000000
+/* Use the platform types for time_t */
+#define __LA_TIME_T time_t
+#else
+/* Use 64-bits integer types for time_t */
+#define __LA_TIME_T la_int64_t
+#endif
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+/* Use the platform types for dev_t */
+#define __LA_DEV_T dev_t
+#else
+/* Use 64-bits integer types for dev_t */
+#define __LA_DEV_T la_int64_t
+#endif
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+/* Libarchive 3.x used signed int64 for inode numbers */
+#define __LA_INO_T la_int64_t
+#else
+/* Switch to unsigned for libarchive 4.0 */
+#define __LA_INO_T la_uint64_t
+#endif
+
 /* Large file support for Android */
 /* Large file support for Android */
 #if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
 #if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
 #include "android_lf.h"
 #include "android_lf.h"
@@ -232,19 +262,19 @@ __LA_DECL struct archive_entry	*archive_entry_new2(struct archive *);
  * also return NULL when implicit character set conversions fail.
  * also return NULL when implicit character set conversions fail.
  * This is usually what you want.
  * This is usually what you want.
  */
  */
-__LA_DECL time_t	 archive_entry_atime(struct archive_entry *);
+__LA_DECL __LA_TIME_T	 archive_entry_atime(struct archive_entry *);
 __LA_DECL long		 archive_entry_atime_nsec(struct archive_entry *);
 __LA_DECL long		 archive_entry_atime_nsec(struct archive_entry *);
 __LA_DECL int		 archive_entry_atime_is_set(struct archive_entry *);
 __LA_DECL int		 archive_entry_atime_is_set(struct archive_entry *);
-__LA_DECL time_t	 archive_entry_birthtime(struct archive_entry *);
+__LA_DECL __LA_TIME_T	 archive_entry_birthtime(struct archive_entry *);
 __LA_DECL long		 archive_entry_birthtime_nsec(struct archive_entry *);
 __LA_DECL long		 archive_entry_birthtime_nsec(struct archive_entry *);
 __LA_DECL int		 archive_entry_birthtime_is_set(struct archive_entry *);
 __LA_DECL int		 archive_entry_birthtime_is_set(struct archive_entry *);
-__LA_DECL time_t	 archive_entry_ctime(struct archive_entry *);
+__LA_DECL __LA_TIME_T	 archive_entry_ctime(struct archive_entry *);
 __LA_DECL long		 archive_entry_ctime_nsec(struct archive_entry *);
 __LA_DECL long		 archive_entry_ctime_nsec(struct archive_entry *);
 __LA_DECL int		 archive_entry_ctime_is_set(struct archive_entry *);
 __LA_DECL int		 archive_entry_ctime_is_set(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_dev(struct archive_entry *);
+__LA_DECL __LA_DEV_T		 archive_entry_dev(struct archive_entry *);
 __LA_DECL int		 archive_entry_dev_is_set(struct archive_entry *);
 __LA_DECL int		 archive_entry_dev_is_set(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_devmajor(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_devminor(struct archive_entry *);
+__LA_DECL __LA_DEV_T		 archive_entry_devmajor(struct archive_entry *);
+__LA_DECL __LA_DEV_T		 archive_entry_devminor(struct archive_entry *);
 __LA_DECL __LA_MODE_T	 archive_entry_filetype(struct archive_entry *);
 __LA_DECL __LA_MODE_T	 archive_entry_filetype(struct archive_entry *);
 __LA_DECL int		 archive_entry_filetype_is_set(struct archive_entry *);
 __LA_DECL int		 archive_entry_filetype_is_set(struct archive_entry *);
 __LA_DECL void		 archive_entry_fflags(struct archive_entry *,
 __LA_DECL void		 archive_entry_fflags(struct archive_entry *,
@@ -261,8 +291,8 @@ __LA_DECL const char	*archive_entry_hardlink(struct archive_entry *);
 __LA_DECL const char	*archive_entry_hardlink_utf8(struct archive_entry *);
 __LA_DECL const char	*archive_entry_hardlink_utf8(struct archive_entry *);
 __LA_DECL const wchar_t	*archive_entry_hardlink_w(struct archive_entry *);
 __LA_DECL const wchar_t	*archive_entry_hardlink_w(struct archive_entry *);
 __LA_DECL int		 archive_entry_hardlink_is_set(struct archive_entry *);
 __LA_DECL int		 archive_entry_hardlink_is_set(struct archive_entry *);
-__LA_DECL la_int64_t	 archive_entry_ino(struct archive_entry *);
-__LA_DECL la_int64_t	 archive_entry_ino64(struct archive_entry *);
+__LA_DECL __LA_INO_T	 archive_entry_ino(struct archive_entry *);
+__LA_DECL __LA_INO_T	 archive_entry_ino64(struct archive_entry *);
 __LA_DECL int		 archive_entry_ino_is_set(struct archive_entry *);
 __LA_DECL int		 archive_entry_ino_is_set(struct archive_entry *);
 __LA_DECL __LA_MODE_T	 archive_entry_mode(struct archive_entry *);
 __LA_DECL __LA_MODE_T	 archive_entry_mode(struct archive_entry *);
 __LA_DECL time_t	 archive_entry_mtime(struct archive_entry *);
 __LA_DECL time_t	 archive_entry_mtime(struct archive_entry *);
@@ -275,9 +305,9 @@ __LA_DECL const wchar_t	*archive_entry_pathname_w(struct archive_entry *);
 __LA_DECL __LA_MODE_T	 archive_entry_perm(struct archive_entry *);
 __LA_DECL __LA_MODE_T	 archive_entry_perm(struct archive_entry *);
 __LA_DECL int		 archive_entry_perm_is_set(struct archive_entry *);
 __LA_DECL int		 archive_entry_perm_is_set(struct archive_entry *);
 __LA_DECL int		 archive_entry_rdev_is_set(struct archive_entry *);
 __LA_DECL int		 archive_entry_rdev_is_set(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_rdev(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_rdevmajor(struct archive_entry *);
-__LA_DECL dev_t		 archive_entry_rdevminor(struct archive_entry *);
+__LA_DECL __LA_DEV_T		 archive_entry_rdev(struct archive_entry *);
+__LA_DECL __LA_DEV_T		 archive_entry_rdevmajor(struct archive_entry *);
+__LA_DECL __LA_DEV_T		 archive_entry_rdevminor(struct archive_entry *);
 __LA_DECL const char	*archive_entry_sourcepath(struct archive_entry *);
 __LA_DECL const char	*archive_entry_sourcepath(struct archive_entry *);
 __LA_DECL const wchar_t	*archive_entry_sourcepath_w(struct archive_entry *);
 __LA_DECL const wchar_t	*archive_entry_sourcepath_w(struct archive_entry *);
 __LA_DECL la_int64_t	 archive_entry_size(struct archive_entry *);
 __LA_DECL la_int64_t	 archive_entry_size(struct archive_entry *);
@@ -306,18 +336,18 @@ __LA_DECL int archive_entry_is_encrypted(struct archive_entry *);
  * always copied.
  * always copied.
  */
  */
 
 
-__LA_DECL void	archive_entry_set_atime(struct archive_entry *, time_t, long);
+__LA_DECL void	archive_entry_set_atime(struct archive_entry *, __LA_TIME_T, long);
 __LA_DECL void  archive_entry_unset_atime(struct archive_entry *);
 __LA_DECL void  archive_entry_unset_atime(struct archive_entry *);
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #if defined(_WIN32) && !defined(__CYGWIN__)
 __LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, struct _BY_HANDLE_FILE_INFORMATION *);
 __LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, struct _BY_HANDLE_FILE_INFORMATION *);
 #endif
 #endif
-__LA_DECL void	archive_entry_set_birthtime(struct archive_entry *, time_t, long);
+__LA_DECL void	archive_entry_set_birthtime(struct archive_entry *, __LA_TIME_T, long);
 __LA_DECL void  archive_entry_unset_birthtime(struct archive_entry *);
 __LA_DECL void  archive_entry_unset_birthtime(struct archive_entry *);
-__LA_DECL void	archive_entry_set_ctime(struct archive_entry *, time_t, long);
+__LA_DECL void	archive_entry_set_ctime(struct archive_entry *, __LA_TIME_T, long);
 __LA_DECL void  archive_entry_unset_ctime(struct archive_entry *);
 __LA_DECL void  archive_entry_unset_ctime(struct archive_entry *);
-__LA_DECL void	archive_entry_set_dev(struct archive_entry *, dev_t);
-__LA_DECL void	archive_entry_set_devmajor(struct archive_entry *, dev_t);
-__LA_DECL void	archive_entry_set_devminor(struct archive_entry *, dev_t);
+__LA_DECL void	archive_entry_set_dev(struct archive_entry *, __LA_DEV_T);
+__LA_DECL void	archive_entry_set_devmajor(struct archive_entry *, __LA_DEV_T);
+__LA_DECL void	archive_entry_set_devminor(struct archive_entry *, __LA_DEV_T);
 __LA_DECL void	archive_entry_set_filetype(struct archive_entry *, unsigned int);
 __LA_DECL void	archive_entry_set_filetype(struct archive_entry *, unsigned int);
 __LA_DECL void	archive_entry_set_fflags(struct archive_entry *,
 __LA_DECL void	archive_entry_set_fflags(struct archive_entry *,
 	    unsigned long /* set */, unsigned long /* clear */);
 	    unsigned long /* set */, unsigned long /* clear */);
@@ -340,15 +370,15 @@ __LA_DECL void	archive_entry_set_hardlink_utf8(struct archive_entry *, const cha
 __LA_DECL void	archive_entry_copy_hardlink(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_copy_hardlink(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
 __LA_DECL void	archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
 __LA_DECL int	archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
 __LA_DECL int	archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
-__LA_DECL void	archive_entry_set_ino(struct archive_entry *, la_int64_t);
-__LA_DECL void	archive_entry_set_ino64(struct archive_entry *, la_int64_t);
+__LA_DECL void	archive_entry_set_ino(struct archive_entry *, __LA_INO_T);
+__LA_DECL void	archive_entry_set_ino64(struct archive_entry *, __LA_INO_T);
 __LA_DECL void	archive_entry_set_link(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_set_link(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_set_link_utf8(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_set_link_utf8(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_copy_link(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_copy_link(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_copy_link_w(struct archive_entry *, const wchar_t *);
 __LA_DECL void	archive_entry_copy_link_w(struct archive_entry *, const wchar_t *);
 __LA_DECL int	archive_entry_update_link_utf8(struct archive_entry *, const char *);
 __LA_DECL int	archive_entry_update_link_utf8(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_set_mode(struct archive_entry *, __LA_MODE_T);
 __LA_DECL void	archive_entry_set_mode(struct archive_entry *, __LA_MODE_T);
-__LA_DECL void	archive_entry_set_mtime(struct archive_entry *, time_t, long);
+__LA_DECL void	archive_entry_set_mtime(struct archive_entry *, __LA_TIME_T, long);
 __LA_DECL void  archive_entry_unset_mtime(struct archive_entry *);
 __LA_DECL void  archive_entry_unset_mtime(struct archive_entry *);
 __LA_DECL void	archive_entry_set_nlink(struct archive_entry *, unsigned int);
 __LA_DECL void	archive_entry_set_nlink(struct archive_entry *, unsigned int);
 __LA_DECL void	archive_entry_set_pathname(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_set_pathname(struct archive_entry *, const char *);
@@ -357,9 +387,9 @@ __LA_DECL void	archive_entry_copy_pathname(struct archive_entry *, const char *)
 __LA_DECL void	archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
 __LA_DECL void	archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
 __LA_DECL int	archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
 __LA_DECL int	archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_set_perm(struct archive_entry *, __LA_MODE_T);
 __LA_DECL void	archive_entry_set_perm(struct archive_entry *, __LA_MODE_T);
-__LA_DECL void	archive_entry_set_rdev(struct archive_entry *, dev_t);
-__LA_DECL void	archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
-__LA_DECL void	archive_entry_set_rdevminor(struct archive_entry *, dev_t);
+__LA_DECL void	archive_entry_set_rdev(struct archive_entry *, __LA_DEV_T);
+__LA_DECL void	archive_entry_set_rdevmajor(struct archive_entry *, __LA_DEV_T);
+__LA_DECL void	archive_entry_set_rdevminor(struct archive_entry *, __LA_DEV_T);
 __LA_DECL void	archive_entry_set_size(struct archive_entry *, la_int64_t);
 __LA_DECL void	archive_entry_set_size(struct archive_entry *, la_int64_t);
 __LA_DECL void	archive_entry_unset_size(struct archive_entry *);
 __LA_DECL void	archive_entry_unset_size(struct archive_entry *);
 __LA_DECL void	archive_entry_copy_sourcepath(struct archive_entry *, const char *);
 __LA_DECL void	archive_entry_copy_sourcepath(struct archive_entry *, const char *);
@@ -415,6 +445,7 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
 #define ARCHIVE_ENTRY_DIGEST_SHA512           0x00000006
 #define ARCHIVE_ENTRY_DIGEST_SHA512           0x00000006
 
 
 __LA_DECL const unsigned char * archive_entry_digest(struct archive_entry *, int /* type */);
 __LA_DECL const unsigned char * archive_entry_digest(struct archive_entry *, int /* type */);
+__LA_DECL int archive_entry_set_digest(struct archive_entry *, int, const unsigned char *);
 
 
 /*
 /*
  * ACL routines.  This used to simply store and return text-format ACL
  * ACL routines.  This used to simply store and return text-format ACL

+ 6 - 25
Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c

@@ -24,43 +24,24 @@
  */
  */
 
 
 #include "archive_platform.h"
 #include "archive_platform.h"
-
+#include "archive_time_private.h"
 #include "archive_private.h"
 #include "archive_private.h"
 #include "archive_entry.h"
 #include "archive_entry.h"
 
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #if defined(_WIN32) && !defined(__CYGWIN__)
 
 
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-
-__inline static void
-fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
-{
-	ULARGE_INTEGER utc;
-
-	utc.HighPart = filetime->dwHighDateTime;
-	utc.LowPart  = filetime->dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		*t = (time_t)(utc.QuadPart / 10000000);	/* milli seconds base */
-		*ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
-	} else {
-		*t = 0;
-		*ns = 0;
-	}
-}
-
 void
 void
 archive_entry_copy_bhfi(struct archive_entry *entry,
 archive_entry_copy_bhfi(struct archive_entry *entry,
 			BY_HANDLE_FILE_INFORMATION *bhfi)
 			BY_HANDLE_FILE_INFORMATION *bhfi)
 {
 {
-	time_t secs;
-	long nsecs;
+	int64_t secs;
+	uint32_t nsecs;
 
 
-	fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs);
+	ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastAccessTime), &secs, &nsecs);
 	archive_entry_set_atime(entry, secs, nsecs);
 	archive_entry_set_atime(entry, secs, nsecs);
-	fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
+	ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &secs, &nsecs);
 	archive_entry_set_mtime(entry, secs, nsecs);
 	archive_entry_set_mtime(entry, secs, nsecs);
-	fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs);
+	ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftCreationTime), &secs, &nsecs);
 	archive_entry_set_birthtime(entry, secs, nsecs);
 	archive_entry_set_birthtime(entry, secs, nsecs);
 	archive_entry_set_ctime(entry, secs, nsecs);
 	archive_entry_set_ctime(entry, secs, nsecs);
 	archive_entry_set_dev(entry, bhfi->dwVolumeSerialNumber);
 	archive_entry_set_dev(entry, bhfi->dwVolumeSerialNumber);

+ 8 - 0
Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c

@@ -280,6 +280,10 @@ find_entry(struct archive_entry_linkresolver *res,
 	dev_t			 dev;
 	dev_t			 dev;
 	int64_t			 ino;
 	int64_t			 ino;
 
 
+	if (!archive_entry_ino_is_set(entry) || !archive_entry_dev_is_set(entry)) {
+		return (NULL);
+	}
+
 	/* Free a held entry. */
 	/* Free a held entry. */
 	if (res->spare != NULL) {
 	if (res->spare != NULL) {
 		archive_entry_free(res->spare->canonical);
 		archive_entry_free(res->spare->canonical);
@@ -369,6 +373,10 @@ insert_entry(struct archive_entry_linkresolver *res,
 	struct links_entry *le;
 	struct links_entry *le;
 	size_t hash, bucket;
 	size_t hash, bucket;
 
 
+	if (!archive_entry_ino_is_set(entry) || !archive_entry_dev_is_set(entry)) {
+		return (NULL);
+	}
+
 	/* Add this entry to the links cache. */
 	/* Add this entry to the links cache. */
 	le = calloc(1, sizeof(struct links_entry));
 	le = calloc(1, sizeof(struct links_entry));
 	if (le == NULL)
 	if (le == NULL)

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_entry_locale.h

@@ -87,4 +87,4 @@ int _archive_entry_copy_symlink_l(struct archive_entry *,
 int _archive_entry_copy_uname_l(struct archive_entry *,
 int _archive_entry_copy_uname_l(struct archive_entry *,
     const char *, size_t, struct archive_string_conv *);
     const char *, size_t, struct archive_string_conv *);
 
 
-#endif /* ARCHIVE_ENTRY_LOCALE_H_INCLUDED */
+#endif /* !ARCHIVE_ENTRY_LOCALE_H_INCLUDED */

+ 8 - 5
Utilities/cmlibarchive/libarchive/archive_entry_private.h

@@ -174,6 +174,13 @@ struct archive_entry {
 	size_t mac_metadata_size;
 	size_t mac_metadata_size;
 
 
 	/* Digest support. */
 	/* Digest support. */
+#define AE_MSET_DIGEST_MD5	 1
+#define AE_MSET_DIGEST_RMD160	 2
+#define AE_MSET_DIGEST_SHA1	 4
+#define AE_MSET_DIGEST_SHA256	 8
+#define AE_MSET_DIGEST_SHA384	16
+#define AE_MSET_DIGEST_SHA512	32
+	uint_least32_t mset_digest;
 	struct ae_digest digest;
 	struct ae_digest digest;
 
 
 	/* ACL support. */
 	/* ACL support. */
@@ -195,8 +202,4 @@ struct archive_entry {
 	int ae_symlink_type;
 	int ae_symlink_type;
 };
 };
 
 
-int
-archive_entry_set_digest(struct archive_entry *entry, int type,
-    const unsigned char *digest);
-
-#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
+#endif /* !ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_hmac_private.h

@@ -116,4 +116,4 @@ struct archive_hmac {
 };
 };
 
 
 extern const struct archive_hmac __archive_hmac;
 extern const struct archive_hmac __archive_hmac;
-#endif /* ARCHIVE_HMAC_PRIVATE_H_INCLUDED */
+#endif /* !ARCHIVE_HMAC_PRIVATE_H_INCLUDED */

+ 35 - 63
Utilities/cmlibarchive/libarchive/archive_match.c

@@ -35,14 +35,17 @@
 #ifdef HAVE_STRING_H
 #ifdef HAVE_STRING_H
 #include <string.h>
 #include <string.h>
 #endif
 #endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
 
 
 #include "archive.h"
 #include "archive.h"
 #include "archive_private.h"
 #include "archive_private.h"
 #include "archive_entry.h"
 #include "archive_entry.h"
-#include "archive_getdate.h"
 #include "archive_pathmatch.h"
 #include "archive_pathmatch.h"
 #include "archive_rb.h"
 #include "archive_rb.h"
 #include "archive_string.h"
 #include "archive_string.h"
+#include "archive_time_private.h"
 
 
 struct match {
 struct match {
 	struct match		*next;
 	struct match		*next;
@@ -53,8 +56,7 @@ struct match {
 struct match_list {
 struct match_list {
 	struct match		*first;
 	struct match		*first;
 	struct match		**last;
 	struct match		**last;
-	int			 count;
-	int			 unmatched_count;
+	size_t			 unmatched_count;
 	struct match		*unmatched_next;
 	struct match		*unmatched_next;
 	int			 unmatched_eof;
 	int			 unmatched_eof;
 };
 };
@@ -73,7 +75,6 @@ struct match_file {
 struct entry_list {
 struct entry_list {
 	struct match_file	*first;
 	struct match_file	*first;
 	struct match_file	**last;
 	struct match_file	**last;
-	int			 count;
 };
 };
 
 
 struct id_array {
 struct id_array {
@@ -144,12 +145,15 @@ static int	add_pattern_mbs(struct archive_match *, struct match_list *,
 		    const char *);
 		    const char *);
 static int	add_pattern_wcs(struct archive_match *, struct match_list *,
 static int	add_pattern_wcs(struct archive_match *, struct match_list *,
 		    const wchar_t *);
 		    const wchar_t *);
+#if !defined(_WIN32) || defined(__CYGWIN__)
 static int	cmp_key_mbs(const struct archive_rb_node *, const void *);
 static int	cmp_key_mbs(const struct archive_rb_node *, const void *);
-static int	cmp_key_wcs(const struct archive_rb_node *, const void *);
 static int	cmp_node_mbs(const struct archive_rb_node *,
 static int	cmp_node_mbs(const struct archive_rb_node *,
 		    const struct archive_rb_node *);
 		    const struct archive_rb_node *);
+#else
+static int	cmp_key_wcs(const struct archive_rb_node *, const void *);
 static int	cmp_node_wcs(const struct archive_rb_node *,
 static int	cmp_node_wcs(const struct archive_rb_node *,
 		    const struct archive_rb_node *);
 		    const struct archive_rb_node *);
+#endif
 static void	entry_list_add(struct entry_list *, struct match_file *);
 static void	entry_list_add(struct entry_list *, struct match_file *);
 static void	entry_list_free(struct entry_list *);
 static void	entry_list_free(struct entry_list *);
 static void	entry_list_init(struct entry_list *);
 static void	entry_list_init(struct entry_list *);
@@ -187,14 +191,14 @@ static int	time_excluded(struct archive_match *,
 		    struct archive_entry *);
 		    struct archive_entry *);
 static int	validate_time_flag(struct archive *, int, const char *);
 static int	validate_time_flag(struct archive *, int, const char *);
 
 
-#define get_date __archive_get_date
+#define get_date archive_parse_date
 
 
-static const struct archive_rb_tree_ops rb_ops_mbs = {
+static const struct archive_rb_tree_ops rb_ops = {
+#if !defined(_WIN32) || defined(__CYGWIN__)
 	cmp_node_mbs, cmp_key_mbs
 	cmp_node_mbs, cmp_key_mbs
-};
-
-static const struct archive_rb_tree_ops rb_ops_wcs = {
+#else
 	cmp_node_wcs, cmp_key_wcs
 	cmp_node_wcs, cmp_key_wcs
+#endif
 };
 };
 
 
 /*
 /*
@@ -228,7 +232,7 @@ archive_match_new(void)
 	a->recursive_include = 1;
 	a->recursive_include = 1;
 	match_list_init(&(a->inclusions));
 	match_list_init(&(a->inclusions));
 	match_list_init(&(a->exclusions));
 	match_list_init(&(a->exclusions));
-	__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
+	__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops);
 	entry_list_init(&(a->exclusion_entry_list));
 	entry_list_init(&(a->exclusion_entry_list));
 	match_list_init(&(a->inclusion_unames));
 	match_list_init(&(a->inclusion_unames));
 	match_list_init(&(a->inclusion_gnames));
 	match_list_init(&(a->inclusion_gnames));
@@ -507,7 +511,9 @@ archive_match_path_unmatched_inclusions(struct archive *_a)
 	    ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions");
 	    ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions");
 	a = (struct archive_match *)_a;
 	a = (struct archive_match *)_a;
 
 
-	return (a->inclusions.unmatched_count);
+	if (a->inclusions.unmatched_count > (size_t)INT_MAX)
+		return INT_MAX;
+	return (int)(a->inclusions.unmatched_count);
 }
 }
 
 
 int
 int
@@ -650,7 +656,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
 						break;
 						break;
 					}
 					}
 				} else {
 				} else {
-			            	if (*b == 0x0d || *b == 0x0a) {
+					if (*b == 0x0d || *b == 0x0a) {
 						found_separator = 1;
 						found_separator = 1;
 						break;
 						break;
 					}
 					}
@@ -735,7 +741,7 @@ path_excluded(struct archive_match *a, int mbs, const void *pathname)
 		}
 		}
 	}
 	}
 
 
-	/* Exclusions take priority */
+	/* Exclusions take priority. */
 	for (match = a->exclusions.first; match != NULL;
 	for (match = a->exclusions.first; match != NULL;
 	    match = match->next){
 	    match = match->next){
 		r = match_path_exclusion(a, match, mbs, pathname);
 		r = match_path_exclusion(a, match, mbs, pathname);
@@ -834,7 +840,6 @@ match_list_init(struct match_list *list)
 {
 {
 	list->first = NULL;
 	list->first = NULL;
 	list->last = &(list->first);
 	list->last = &(list->first);
-	list->count = 0;
 }
 }
 
 
 static void
 static void
@@ -855,7 +860,6 @@ match_list_add(struct match_list *list, struct match *m)
 {
 {
 	*list->last = m;
 	*list->last = m;
 	list->last = &(m->next);
 	list->last = &(m->next);
-	list->count++;
 	list->unmatched_count++;
 	list->unmatched_count++;
 }
 }
 
 
@@ -1145,36 +1149,15 @@ set_timefilter_date_w(struct archive_match *a, int timetype,
 }
 }
 
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #if defined(_WIN32) && !defined(__CYGWIN__)
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
 static int
 static int
 set_timefilter_find_data(struct archive_match *a, int timetype,
 set_timefilter_find_data(struct archive_match *a, int timetype,
-    DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
-    DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
+    const FILETIME* ftLastWriteTime, const FILETIME* ftCreationTime)
 {
 {
-	ULARGE_INTEGER utc;
 	time_t ctime_sec, mtime_sec;
 	time_t ctime_sec, mtime_sec;
-	long ctime_ns, mtime_ns;
+	uint32_t ctime_ns, mtime_ns;
 
 
-	utc.HighPart = ftCreationTime_dwHighDateTime;
-	utc.LowPart = ftCreationTime_dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		ctime_sec = (time_t)(utc.QuadPart / 10000000);
-		ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
-	} else {
-		ctime_sec = 0;
-		ctime_ns = 0;
-	}
-	utc.HighPart = ftLastWriteTime_dwHighDateTime;
-	utc.LowPart = ftLastWriteTime_dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		mtime_sec = (time_t)(utc.QuadPart / 10000000);
-		mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
-	} else {
-		mtime_sec = 0;
-		mtime_ns = 0;
-	}
+	ntfs_to_unix(FILETIME_to_ntfs(ftLastWriteTime), &mtime_sec, &mtime_ns);
+	ntfs_to_unix(FILETIME_to_ntfs(ftCreationTime), &ctime_sec, &ctime_ns);
 	return set_timefilter(a, timetype,
 	return set_timefilter(a, timetype,
 			mtime_sec, mtime_ns, ctime_sec, ctime_ns);
 			mtime_sec, mtime_ns, ctime_sec, ctime_ns);
 }
 }
@@ -1199,9 +1182,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
 		return (ARCHIVE_FAILED);
 		return (ARCHIVE_FAILED);
 	}
 	}
 	FindClose(h);
 	FindClose(h);
-	return set_timefilter_find_data(a, timetype,
-	    d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
-	    d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
+	return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
 }
 }
 
 
 static int
 static int
@@ -1223,9 +1204,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
 		return (ARCHIVE_FAILED);
 		return (ARCHIVE_FAILED);
 	}
 	}
 	FindClose(h);
 	FindClose(h);
-	return set_timefilter_find_data(a, timetype,
-	    d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
-	    d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
+	return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
 }
 }
 
 
 #else /* _WIN32 && !__CYGWIN__ */
 #else /* _WIN32 && !__CYGWIN__ */
@@ -1300,6 +1279,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
 /*
 /*
  * Call back functions for archive_rb.
  * Call back functions for archive_rb.
  */
  */
+#if !defined(_WIN32) || defined(__CYGWIN__)
 static int
 static int
 cmp_node_mbs(const struct archive_rb_node *n1,
 cmp_node_mbs(const struct archive_rb_node *n1,
     const struct archive_rb_node *n2)
     const struct archive_rb_node *n2)
@@ -1328,7 +1308,7 @@ cmp_key_mbs(const struct archive_rb_node *n, const void *key)
 		return (-1);
 		return (-1);
 	return (strcmp(p, (const char *)key));
 	return (strcmp(p, (const char *)key));
 }
 }
-
+#else
 static int
 static int
 cmp_node_wcs(const struct archive_rb_node *n1,
 cmp_node_wcs(const struct archive_rb_node *n1,
     const struct archive_rb_node *n2)
     const struct archive_rb_node *n2)
@@ -1357,13 +1337,13 @@ cmp_key_wcs(const struct archive_rb_node *n, const void *key)
 		return (-1);
 		return (-1);
 	return (wcscmp(p, (const wchar_t *)key));
 	return (wcscmp(p, (const wchar_t *)key));
 }
 }
+#endif
 
 
 static void
 static void
 entry_list_init(struct entry_list *list)
 entry_list_init(struct entry_list *list)
 {
 {
 	list->first = NULL;
 	list->first = NULL;
 	list->last = &(list->first);
 	list->last = &(list->first);
-	list->count = 0;
 }
 }
 
 
 static void
 static void
@@ -1384,7 +1364,6 @@ entry_list_add(struct entry_list *list, struct match_file *file)
 {
 {
 	*list->last = file;
 	*list->last = file;
 	list->last = &(file->next);
 	list->last = &(file->next);
-	list->count++;
 }
 }
 
 
 static int
 static int
@@ -1407,9 +1386,7 @@ add_entry(struct archive_match *a, int flag,
 		return (ARCHIVE_FAILED);
 		return (ARCHIVE_FAILED);
 	}
 	}
 	archive_mstring_copy_wcs(&(f->pathname), pathname);
 	archive_mstring_copy_wcs(&(f->pathname), pathname);
-	a->exclusion_tree.rbt_ops = &rb_ops_wcs;
 #else
 #else
-	(void)rb_ops_wcs;
 	pathname = archive_entry_pathname(entry);
 	pathname = archive_entry_pathname(entry);
 	if (pathname == NULL) {
 	if (pathname == NULL) {
 		free(f);
 		free(f);
@@ -1417,7 +1394,6 @@ add_entry(struct archive_match *a, int flag,
 		return (ARCHIVE_FAILED);
 		return (ARCHIVE_FAILED);
 	}
 	}
 	archive_mstring_copy_mbs(&(f->pathname), pathname);
 	archive_mstring_copy_mbs(&(f->pathname), pathname);
-	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
 #endif
 #endif
 	f->flag = flag;
 	f->flag = flag;
 	f->mtime_sec = archive_entry_mtime(entry);
 	f->mtime_sec = archive_entry_mtime(entry);
@@ -1542,16 +1518,13 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
 	}
 	}
 
 
 	/* If there is no exclusion list, include the file. */
 	/* If there is no exclusion list, include the file. */
-	if (a->exclusion_entry_list.count == 0)
+	if (a->exclusion_entry_list.first == NULL)
 		return (0);
 		return (0);
 
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #if defined(_WIN32) && !defined(__CYGWIN__)
 	pathname = archive_entry_pathname_w(entry);
 	pathname = archive_entry_pathname_w(entry);
-	a->exclusion_tree.rbt_ops = &rb_ops_wcs;
 #else
 #else
-	(void)rb_ops_wcs;
 	pathname = archive_entry_pathname(entry);
 	pathname = archive_entry_pathname(entry);
-	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
 #endif
 #endif
 	if (pathname == NULL)
 	if (pathname == NULL)
 		return (0);
 		return (0);
@@ -1707,7 +1680,7 @@ archive_match_owner_excluded(struct archive *_a,
 static int
 static int
 add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
 add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
 {
 {
-	unsigned i;
+	size_t i;
 
 
 	if (ids->count + 1 >= ids->size) {
 	if (ids->count + 1 >= ids->size) {
 		void *p;
 		void *p;
@@ -1744,10 +1717,10 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
 static int
 static int
 match_owner_id(struct id_array *ids, int64_t id)
 match_owner_id(struct id_array *ids, int64_t id)
 {
 {
-	unsigned b, m, t;
+	size_t b, m, t;
 
 
 	t = 0;
 	t = 0;
-	b = (unsigned)ids->count;
+	b = ids->count;
 	while (t < b) {
 	while (t < b) {
 		m = (t + b)>>1;
 		m = (t + b)>>1;
 		if (ids->ids[m] == id)
 		if (ids->ids[m] == id)
@@ -1842,7 +1815,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
 			return (1);
 			return (1);
 	}
 	}
 
 
-	if (a->inclusion_unames.count) {
+	if (a->inclusion_unames.first != NULL) {
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #if defined(_WIN32) && !defined(__CYGWIN__)
 		r = match_owner_name_wcs(a, &(a->inclusion_unames),
 		r = match_owner_name_wcs(a, &(a->inclusion_unames),
 			archive_entry_uname_w(entry));
 			archive_entry_uname_w(entry));
@@ -1856,7 +1829,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
 			return (r);
 			return (r);
 	}
 	}
 
 
-	if (a->inclusion_gnames.count) {
+	if (a->inclusion_gnames.first != NULL) {
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #if defined(_WIN32) && !defined(__CYGWIN__)
 		r = match_owner_name_wcs(a, &(a->inclusion_gnames),
 		r = match_owner_name_wcs(a, &(a->inclusion_gnames),
 			archive_entry_gname_w(entry));
 			archive_entry_gname_w(entry));
@@ -1871,4 +1844,3 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
 	}
 	}
 	return (0);
 	return (0);
 }
 }
-

+ 2 - 2
Utilities/cmlibarchive/libarchive/archive_options.c

@@ -38,7 +38,7 @@ parse_option(const char **str,
 int
 int
 _archive_set_option(struct archive *a,
 _archive_set_option(struct archive *a,
     const char *m, const char *o, const char *v,
     const char *m, const char *o, const char *v,
-    int magic, const char *fn, option_handler use_option)
+    unsigned int magic, const char *fn, option_handler use_option)
 {
 {
 	const char *mp, *op, *vp;
 	const char *mp, *op, *vp;
 	int r;
 	int r;
@@ -97,7 +97,7 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons
 
 
 int
 int
 _archive_set_options(struct archive *a, const char *options,
 _archive_set_options(struct archive *a, const char *options,
-    int magic, const char *fn, option_handler use_option)
+    unsigned int magic, const char *fn, option_handler use_option)
 {
 {
 	int allok = 1, anyok = 0, ignore_mod_err = 0, r;
 	int allok = 1, anyok = 0, ignore_mod_err = 0, r;
 	char *data;
 	char *data;

+ 2 - 2
Utilities/cmlibarchive/libarchive/archive_options_private.h

@@ -35,11 +35,11 @@ typedef int (*option_handler)(struct archive *a,
 int
 int
 _archive_set_option(struct archive *a,
 _archive_set_option(struct archive *a,
     const char *mod, const char *opt, const char *val,
     const char *mod, const char *opt, const char *val,
-    int magic, const char *fn, option_handler use_option);
+    unsigned int magic, const char *fn, option_handler use_option);
 
 
 int
 int
 _archive_set_options(struct archive *a, const char *options,
 _archive_set_options(struct archive *a, const char *options,
-    int magic, const char *fn, option_handler use_option);
+    unsigned int magic, const char *fn, option_handler use_option);
 
 
 int
 int
 _archive_set_either_option(struct archive *a,
 _archive_set_either_option(struct archive *a,

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_pack_dev.h

@@ -46,4 +46,4 @@ pack_t	 pack_native;
 					 (((y) << 12) & 0xfff00000) | \
 					 (((y) << 12) & 0xfff00000) | \
 					 (((y) <<  0) & 0x000000ff)))
 					 (((y) <<  0) & 0x000000ff)))
 
 
-#endif	/* ARCHIVE_PACK_DEV_H */
+#endif	/* !ARCHIVE_PACK_DEV_H */

+ 57 - 10
Utilities/cmlibarchive/libarchive/archive_getdate.c → Utilities/cmlibarchive/libarchive/archive_parse_date.c

@@ -27,7 +27,7 @@
 **  This code is in the public domain and has no copyright.
 **  This code is in the public domain and has no copyright.
 */
 */
 
 
-#ifndef CM_GET_DATE
+#ifndef CM_PARSE_DATE
 #include "archive_platform.h"
 #include "archive_platform.h"
 #endif
 #endif
 
 
@@ -37,8 +37,7 @@
 #include <string.h>
 #include <string.h>
 #include <time.h>
 #include <time.h>
 
 
-#define __LIBARCHIVE_BUILD 1
-#include "archive_getdate.h"
+#include "archive.h"
 
 
 /* Basic time units. */
 /* Basic time units. */
 #define	EPOCH		1970
 #define	EPOCH		1970
@@ -822,6 +821,23 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
 		Timezone, DSTmaybe));
 		Timezone, DSTmaybe));
 }
 }
 
 
+/*
+ * Parses and consumes an unsigned number.
+ * Returns 1 if any number is parsed. Otherwise, *value is unchanged.
+ */
+static char
+consume_unsigned_number(const char **in, time_t *value)
+{
+	char c;
+	if (isdigit((unsigned char)(c = **in))) {
+		for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); )
+			*value = 10 * *value + c - '0';
+		(*in)--;
+		return 1;
+	}
+	return 0;
+}
+
 /*
 /*
  * Tokenizer.
  * Tokenizer.
  */
  */
@@ -863,7 +879,8 @@ nexttoken(const char **in, time_t *value)
 			    && i < sizeof(buff)-1) {
 			    && i < sizeof(buff)-1) {
 				if (*src != '.') {
 				if (*src != '.') {
 					if (isupper((unsigned char)*src))
 					if (isupper((unsigned char)*src))
-						buff[i++] = tolower((unsigned char)*src);
+						buff[i++] = (char)tolower(
+						    (unsigned char)*src);
 					else
 					else
 						buff[i++] = *src;
 						buff[i++] = *src;
 				}
 				}
@@ -897,10 +914,7 @@ nexttoken(const char **in, time_t *value)
 		 * Because '-' and '+' have other special meanings, I
 		 * Because '-' and '+' have other special meanings, I
 		 * don't deal with signed numbers here.
 		 * don't deal with signed numbers here.
 		 */
 		 */
-		if (isdigit((unsigned char)(c = **in))) {
-			for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); )
-				*value = 10 * *value + c - '0';
-			(*in)--;
+		if (consume_unsigned_number(in, value)) {
 			return (tUNUMBER);
 			return (tUNUMBER);
 		}
 		}
 
 
@@ -916,7 +930,7 @@ difftm (struct tm *a, struct tm *b)
 {
 {
 	int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
 	int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
 	int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
 	int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
-	int days = (
+	long days = (
 		/* difference in day of year */
 		/* difference in day of year */
 		a->tm_yday - b->tm_yday
 		a->tm_yday - b->tm_yday
 		/* + intervening leap days */
 		/* + intervening leap days */
@@ -931,6 +945,32 @@ difftm (struct tm *a, struct tm *b)
 	    + (a->tm_sec - b->tm_sec));
 	    + (a->tm_sec - b->tm_sec));
 }
 }
 
 
+/*
+ * Parses a Unix epoch timestamp (seconds).
+ * This supports a subset of what GNU tar accepts from black box testing,
+ * but covers common use cases.
+ */
+static time_t
+parse_unix_epoch(const char *p)
+{
+	time_t epoch;
+
+	/* may begin with + */
+	if (*p == '+') {
+		p++;
+	}
+
+	/* followed by some number */
+	if (!consume_unsigned_number(&p, &epoch))
+		return (time_t)-1;
+
+	/* ...and nothing else */
+	if (*p != '\0')
+		return (time_t)-1;
+
+	return epoch;
+}
+
 /*
 /*
  *
  *
  * The public function.
  * The public function.
@@ -938,7 +978,7 @@ difftm (struct tm *a, struct tm *b)
  * TODO: tokens[] array should be dynamically sized.
  * TODO: tokens[] array should be dynamically sized.
  */
  */
 time_t
 time_t
-__archive_get_date(time_t now, const char *p)
+archive_parse_date(time_t now, const char *p)
 {
 {
 	struct token	tokens[256];
 	struct token	tokens[256];
 	struct gdstate	_gds;
 	struct gdstate	_gds;
@@ -950,6 +990,13 @@ __archive_get_date(time_t now, const char *p)
 	time_t		tod;
 	time_t		tod;
 	long		tzone;
 	long		tzone;
 
 
+	/*
+	 * @-prefixed Unix epoch timestamps (seconds)
+	 * Skip the complex tokenizer - We do not want to accept strings like "@tenth"
+	 */
+	if (*p == '@')
+		return parse_unix_epoch(p + 1);
+
 	/* Clear out the parsed token array. */
 	/* Clear out the parsed token array. */
 	memset(tokens, 0, sizeof(tokens));
 	memset(tokens, 0, sizeof(tokens));
 	/* Initialize the parser state. */
 	/* Initialize the parser state. */

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_platform_acl.h

@@ -50,4 +50,4 @@
 #define ARCHIVE_ACL_SUPPORT     1
 #define ARCHIVE_ACL_SUPPORT     1
 #endif
 #endif
 
 
-#endif	/* ARCHIVE_PLATFORM_ACL_H_INCLUDED */
+#endif	/* !ARCHIVE_PLATFORM_ACL_H_INCLUDED */

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_platform_xattr.h

@@ -42,4 +42,4 @@
 #define ARCHIVE_XATTR_SUPPORT     1
 #define ARCHIVE_XATTR_SUPPORT     1
 #endif
 #endif
 
 
-#endif	/* ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
+#endif	/* !ARCHIVE_PLATFORM_XATTR_H_INCLUDED */

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_random_private.h

@@ -33,4 +33,4 @@
 /* Random number generator. */
 /* Random number generator. */
 int archive_random(void *buf, size_t nbytes);
 int archive_random(void *buf, size_t nbytes);
 
 
-#endif /* ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */
+#endif /* !ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_rb.h

@@ -110,4 +110,4 @@ struct archive_rb_node *
 	__archive_rb_tree_iterate(struct archive_rb_tree *,
 	__archive_rb_tree_iterate(struct archive_rb_tree *,
 	struct archive_rb_node *, const unsigned int);
 	struct archive_rb_node *, const unsigned int);
 
 
-#endif	/* ARCHIVE_RB_H_*/
+#endif	/* !ARCHIVE_RB_H_INCLUDED */

+ 0 - 6
Utilities/cmlibarchive/libarchive/archive_read.c

@@ -176,15 +176,9 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
 		return 0;
 		return 0;
 
 
 	if (self->archive->client.skipper != NULL) {
 	if (self->archive->client.skipper != NULL) {
-		/* Seek requests over 1GiB are broken down into
-		 * multiple seeks.  This avoids overflows when the
-		 * requests get passed through 32-bit arguments. */
-		int64_t skip_limit = (int64_t)1 << 30;
 		int64_t total = 0;
 		int64_t total = 0;
 		for (;;) {
 		for (;;) {
 			int64_t get, ask = request;
 			int64_t get, ask = request;
-			if (ask > skip_limit)
-				ask = skip_limit;
 			get = (self->archive->client.skipper)
 			get = (self->archive->client.skipper)
 				(&self->archive->archive, self->data, ask);
 				(&self->archive->archive, self->data, ask);
 			total += get;
 			total += get;

+ 5 - 4
Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c

@@ -280,7 +280,7 @@ tree_dir_next_posix(struct tree *t);
 #endif
 #endif
 
 
 /* Initiate/terminate a tree traversal. */
 /* Initiate/terminate a tree traversal. */
-static struct tree *tree_open(const char *, int, int);
+static struct tree *tree_open(const char *, char, int);
 static struct tree *tree_reopen(struct tree *, const char *, int);
 static struct tree *tree_reopen(struct tree *, const char *, int);
 static void tree_close(struct tree *);
 static void tree_close(struct tree *);
 static void tree_free(struct tree *);
 static void tree_free(struct tree *);
@@ -518,7 +518,7 @@ _archive_read_close(struct archive *_a)
 
 
 static void
 static void
 setup_symlink_mode(struct archive_read_disk *a, char symlink_mode,
 setup_symlink_mode(struct archive_read_disk *a, char symlink_mode,
-    int follow_symlinks)
+    char follow_symlinks)
 {
 {
 	a->symlink_mode = symlink_mode;
 	a->symlink_mode = symlink_mode;
 	a->follow_symlinks = follow_symlinks;
 	a->follow_symlinks = follow_symlinks;
@@ -786,7 +786,8 @@ _archive_read_data_block(struct archive *_a, const void **buff,
 	 */
 	 */
 	if (t->current_sparse->offset > t->entry_total) {
 	if (t->current_sparse->offset > t->entry_total) {
 		if (lseek(t->entry_fd,
 		if (lseek(t->entry_fd,
-		    (off_t)t->current_sparse->offset, SEEK_SET) < 0) {
+		    (off_t)t->current_sparse->offset, SEEK_SET) !=
+		    t->current_sparse->offset) {
 			archive_set_error(&a->archive, errno, "Seek error");
 			archive_set_error(&a->archive, errno, "Seek error");
 			r = ARCHIVE_FATAL;
 			r = ARCHIVE_FATAL;
 			a->archive.state = ARCHIVE_STATE_FATAL;
 			a->archive.state = ARCHIVE_STATE_FATAL;
@@ -2188,7 +2189,7 @@ tree_append(struct tree *t, const char *name, size_t name_length)
  * Open a directory tree for traversal.
  * Open a directory tree for traversal.
  */
  */
 static struct tree *
 static struct tree *
-tree_open(const char *path, int symlink_mode, int restore_time)
+tree_open(const char *path, char symlink_mode, int restore_time)
 {
 {
 	struct tree *t;
 	struct tree *t;
 
 

+ 4 - 3
Utilities/cmlibarchive/libarchive/archive_read_disk_private.h

@@ -52,10 +52,11 @@ struct archive_read_disk {
 
 
 	/*
 	/*
 	 * Since symlink interaction changes, we need to track whether
 	 * Since symlink interaction changes, we need to track whether
-	 * we're following symlinks for the current item.  'L' mode above
-	 * sets this true, 'P' sets it false, 'H' changes it as we traverse.
+	 * we're following symlinks for the current item, governed by the above
+	 * symlink_mode.  'L' sets this true, 'P' sets it false, 'H' changes it
+	 * as we traverse.
 	 */
 	 */
-	char	follow_symlinks;  /* Either 'L' or 'P'. */
+	char	follow_symlinks;  /* Either 0 or 1. */
 
 
 	/* Directory traversals. */
 	/* Directory traversals. */
 	struct tree *tree;
 	struct tree *tree;

+ 32 - 37
Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c

@@ -41,6 +41,7 @@
 #include "archive_entry.h"
 #include "archive_entry.h"
 #include "archive_private.h"
 #include "archive_private.h"
 #include "archive_read_disk_private.h"
 #include "archive_read_disk_private.h"
+#include "archive_time_private.h"
 
 
 #ifndef O_BINARY
 #ifndef O_BINARY
 #define O_BINARY	0
 #define O_BINARY	0
@@ -49,7 +50,7 @@
 /* Old SDKs do not provide IO_REPARSE_TAG_SYMLINK */
 /* Old SDKs do not provide IO_REPARSE_TAG_SYMLINK */
 #define	IO_REPARSE_TAG_SYMLINK 0xA000000CL
 #define	IO_REPARSE_TAG_SYMLINK 0xA000000CL
 #endif
 #endif
-/* To deal with absolute symlink isuues */
+/* To deal with absolute symlink issues */
 #define START_ABSOLUTE_SYMLINK_REPARSE L"\\??\\"
 #define START_ABSOLUTE_SYMLINK_REPARSE L"\\??\\"
 
 
 /*-
 /*-
@@ -602,7 +603,7 @@ _archive_read_close(struct archive *_a)
 
 
 static void
 static void
 setup_symlink_mode(struct archive_read_disk *a, char symlink_mode, 
 setup_symlink_mode(struct archive_read_disk *a, char symlink_mode, 
-    int follow_symlinks)
+    char follow_symlinks)
 {
 {
 	a->symlink_mode = symlink_mode;
 	a->symlink_mode = symlink_mode;
 	a->follow_symlinks = follow_symlinks;
 	a->follow_symlinks = follow_symlinks;
@@ -1651,7 +1652,7 @@ tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path,
 /*
 /*
  * Append a name to the current dir path.
  * Append a name to the current dir path.
  */
  */
-static void
+static int
 tree_append(struct tree *t, const wchar_t *name, size_t name_length)
 tree_append(struct tree *t, const wchar_t *name, size_t name_length)
 {
 {
 	size_t size_needed;
 	size_t size_needed;
@@ -1664,7 +1665,8 @@ tree_append(struct tree *t, const wchar_t *name, size_t name_length)
 
 
 	/* Resize pathname buffer as needed. */
 	/* Resize pathname buffer as needed. */
 	size_needed = name_length + t->dirname_length + 2;
 	size_needed = name_length + t->dirname_length + 2;
-	archive_wstring_ensure(&t->path, size_needed);
+	if (archive_wstring_ensure(&t->path, size_needed) == NULL)
+		return (TREE_ERROR_FATAL);
 	/* Add a separating '/' if it's needed. */
 	/* Add a separating '/' if it's needed. */
 	if (t->dirname_length > 0 &&
 	if (t->dirname_length > 0 &&
 	    t->path.s[archive_strlen(&t->path)-1] != L'/')
 	    t->path.s[archive_strlen(&t->path)-1] != L'/')
@@ -1676,13 +1678,15 @@ tree_append(struct tree *t, const wchar_t *name, size_t name_length)
 		t->full_path.s[t->full_path_dir_length] = L'\0';
 		t->full_path.s[t->full_path_dir_length] = L'\0';
 		t->full_path.length = t->full_path_dir_length;
 		t->full_path.length = t->full_path_dir_length;
 		size_needed = name_length + t->full_path_dir_length + 2;
 		size_needed = name_length + t->full_path_dir_length + 2;
-		archive_wstring_ensure(&t->full_path, size_needed);
+		if (archive_wstring_ensure(&t->full_path, size_needed) == NULL)
+			return (TREE_ERROR_FATAL);
 		/* Add a separating '\' if it's needed. */
 		/* Add a separating '\' if it's needed. */
 		if (t->full_path.s[archive_strlen(&t->full_path)-1] != L'\\')
 		if (t->full_path.s[archive_strlen(&t->full_path)-1] != L'\\')
 			archive_wstrappend_wchar(&t->full_path, L'\\');
 			archive_wstrappend_wchar(&t->full_path, L'\\');
 		archive_wstrncat(&t->full_path, name, name_length);
 		archive_wstrncat(&t->full_path, name, name_length);
 		t->restore_time.full_path = t->full_path.s;
 		t->restore_time.full_path = t->full_path.s;
 	}
 	}
+	return (0);
 }
 }
 
 
 /*
 /*
@@ -1696,7 +1700,10 @@ tree_open(const wchar_t *path, int symlink_mode, int restore_time)
 	t = calloc(1, sizeof(*t));
 	t = calloc(1, sizeof(*t));
 	archive_string_init(&(t->full_path));
 	archive_string_init(&(t->full_path));
 	archive_string_init(&t->path);
 	archive_string_init(&t->path);
-	archive_wstring_ensure(&t->path, 15);
+	if (archive_wstring_ensure(&t->path, 15) == NULL) {
+		free(t);
+		return (NULL);
+	}
 	t->initial_symlink_mode = symlink_mode;
 	t->initial_symlink_mode = symlink_mode;
 	return (tree_reopen(t, path, restore_time));
 	return (tree_reopen(t, path, restore_time));
 }
 }
@@ -1755,7 +1762,8 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time)
 		p = wcsrchr(base, L'/');
 		p = wcsrchr(base, L'/');
 		if (p != NULL) {
 		if (p != NULL) {
 			*p = L'\0';
 			*p = L'\0';
-			tree_append(t, base, p - base);
+			if (tree_append(t, base, p - base))
+				goto failed;
 			t->dirname_length = archive_strlen(&t->path);
 			t->dirname_length = archive_strlen(&t->path);
 			base = p + 1;
 			base = p + 1;
 		}
 		}
@@ -1891,8 +1899,10 @@ tree_next(struct tree *t)
 			}
 			}
 			/* Top stack item needs a regular visit. */
 			/* Top stack item needs a regular visit. */
 			t->current = t->stack;
 			t->current = t->stack;
-			tree_append(t, t->stack->name.s,
+			r = tree_append(t, t->stack->name.s,
 			    archive_strlen(&(t->stack->name)));
 			    archive_strlen(&(t->stack->name)));
+			if (r != 0)
+				return (r);
 			//t->dirname_length = t->path_length;
 			//t->dirname_length = t->path_length;
 			//tree_pop(t);
 			//tree_pop(t);
 			t->stack->flags &= ~needsFirstVisit;
 			t->stack->flags &= ~needsFirstVisit;
@@ -1900,8 +1910,10 @@ tree_next(struct tree *t)
 		} else if (t->stack->flags & needsDescent) {
 		} else if (t->stack->flags & needsDescent) {
 			/* Top stack item is dir to descend into. */
 			/* Top stack item is dir to descend into. */
 			t->current = t->stack;
 			t->current = t->stack;
-			tree_append(t, t->stack->name.s,
+			r = tree_append(t, t->stack->name.s,
 			    archive_strlen(&(t->stack->name)));
 			    archive_strlen(&(t->stack->name)));
+			if (r != 0)
+				return (r);
 			t->stack->flags &= ~needsDescent;
 			t->stack->flags &= ~needsDescent;
 			r = tree_descent(t);
 			r = tree_descent(t);
 			if (r != 0) {
 			if (r != 0) {
@@ -1944,9 +1956,10 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern)
 			struct archive_wstring pt;
 			struct archive_wstring pt;
 
 
 			archive_string_init(&pt);
 			archive_string_init(&pt);
-			archive_wstring_ensure(&pt,
+			if (archive_wstring_ensure(&pt,
 			    archive_strlen(&(t->full_path))
 			    archive_strlen(&(t->full_path))
-			      + 2 + wcslen(pattern));
+			      + 2 + wcslen(pattern)) == NULL)
+				return (TREE_ERROR_FATAL);
 			archive_wstring_copy(&pt, &(t->full_path));
 			archive_wstring_copy(&pt, &(t->full_path));
 			archive_wstrappend_wchar(&pt, L'\\');
 			archive_wstrappend_wchar(&pt, L'\\');
 			archive_wstrcat(&pt, pattern);
 			archive_wstrcat(&pt, pattern);
@@ -1978,45 +1991,27 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern)
 			continue;
 			continue;
 		if (name[0] == L'.' && name[1] == L'.' && name[2] == L'\0')
 		if (name[0] == L'.' && name[1] == L'.' && name[2] == L'\0')
 			continue;
 			continue;
-		tree_append(t, name, namelen);
+		r = tree_append(t, name, namelen);
+		if (r != 0)
+			return (r);
 		return (t->visit_type = TREE_REGULAR);
 		return (t->visit_type = TREE_REGULAR);
 	}
 	}
 }
 }
 
 
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-static void
-fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
-{
-	ULARGE_INTEGER utc;
-
-	utc.HighPart = filetime->dwHighDateTime;
-	utc.LowPart  = filetime->dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		/* milli seconds base */
-		*t = (time_t)(utc.QuadPart / 10000000);
-		/* nano seconds base */
-		*ns = (long)(utc.QuadPart % 10000000) * 100;
-	} else {
-		*t = 0;
-		*ns = 0;
-	}
-}
-
 static void
 static void
 entry_copy_bhfi(struct archive_entry *entry, const wchar_t *path,
 entry_copy_bhfi(struct archive_entry *entry, const wchar_t *path,
 	const WIN32_FIND_DATAW *findData,
 	const WIN32_FIND_DATAW *findData,
 	const BY_HANDLE_FILE_INFORMATION *bhfi)
 	const BY_HANDLE_FILE_INFORMATION *bhfi)
 {
 {
-	time_t secs;
-	long nsecs;
+	int64_t secs;
+	uint32_t nsecs;
 	mode_t mode;
 	mode_t mode;
 
 
-	fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs);
+	ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastAccessTime), &secs, &nsecs);
 	archive_entry_set_atime(entry, secs, nsecs);
 	archive_entry_set_atime(entry, secs, nsecs);
-	fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
+	ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &secs, &nsecs);
 	archive_entry_set_mtime(entry, secs, nsecs);
 	archive_entry_set_mtime(entry, secs, nsecs);
-	fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs);
+	ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftCreationTime), &secs, &nsecs);
 	archive_entry_set_birthtime(entry, secs, nsecs);
 	archive_entry_set_birthtime(entry, secs, nsecs);
 	archive_entry_set_ctime(entry, secs, nsecs);
 	archive_entry_set_ctime(entry, secs, nsecs);
 	archive_entry_set_dev(entry, bhfi_dev(bhfi));
 	archive_entry_set_dev(entry, bhfi_dev(bhfi));

+ 15 - 0
Utilities/cmlibarchive/libarchive/archive_read_format.3

@@ -37,8 +37,10 @@
 .Nm archive_read_support_format_lha ,
 .Nm archive_read_support_format_lha ,
 .Nm archive_read_support_format_mtree ,
 .Nm archive_read_support_format_mtree ,
 .Nm archive_read_support_format_rar ,
 .Nm archive_read_support_format_rar ,
+.Nm archive_read_support_format_rar5 ,
 .Nm archive_read_support_format_raw ,
 .Nm archive_read_support_format_raw ,
 .Nm archive_read_support_format_tar ,
 .Nm archive_read_support_format_tar ,
+.Nm archive_read_support_format_warc ,
 .Nm archive_read_support_format_xar ,
 .Nm archive_read_support_format_xar ,
 .Nm archive_read_support_format_zip
 .Nm archive_read_support_format_zip
 .Nd functions for reading streaming archives
 .Nd functions for reading streaming archives
@@ -70,10 +72,14 @@ Streaming Archive Library (libarchive, -larchive)
 .Ft int
 .Ft int
 .Fn archive_read_support_format_rar "struct archive *"
 .Fn archive_read_support_format_rar "struct archive *"
 .Ft int
 .Ft int
+.Fn archive_read_support_format_rar5 "struct archive *"
+.Ft int
 .Fn archive_read_support_format_raw "struct archive *"
 .Fn archive_read_support_format_raw "struct archive *"
 .Ft int
 .Ft int
 .Fn archive_read_support_format_tar "struct archive *"
 .Fn archive_read_support_format_tar "struct archive *"
 .Ft int
 .Ft int
+.Fn archive_read_support_format_warc "struct archive *"
+.Ft int
 .Fn archive_read_support_format_xar "struct archive *"
 .Fn archive_read_support_format_xar "struct archive *"
 .Ft int
 .Ft int
 .Fn archive_read_support_format_zip "struct archive *"
 .Fn archive_read_support_format_zip "struct archive *"
@@ -89,8 +95,10 @@ Streaming Archive Library (libarchive, -larchive)
 .Fn archive_read_support_format_lha ,
 .Fn archive_read_support_format_lha ,
 .Fn archive_read_support_format_mtree ,
 .Fn archive_read_support_format_mtree ,
 .Fn archive_read_support_format_rar ,
 .Fn archive_read_support_format_rar ,
+.Fn archive_read_support_format_rar5 ,
 .Fn archive_read_support_format_raw ,
 .Fn archive_read_support_format_raw ,
 .Fn archive_read_support_format_tar ,
 .Fn archive_read_support_format_tar ,
+.Fn archive_read_support_format_warc ,
 .Fn archive_read_support_format_xar ,
 .Fn archive_read_support_format_xar ,
 .Fn archive_read_support_format_zip
 .Fn archive_read_support_format_zip
 .Xc
 .Xc
@@ -100,6 +108,13 @@ For example,
 .Fn archive_read_support_format_tar
 .Fn archive_read_support_format_tar
 enables support for a variety of standard tar formats, old-style tar,
 enables support for a variety of standard tar formats, old-style tar,
 ustar, pax interchange format, and many common variants.
 ustar, pax interchange format, and many common variants.
+.Fn archive_read_support_format_zip
+enables support for both the streaming and the seeking zip readers,
+which can separately be enabled by respectively
+.Fn archive_read_support_format_zip_streamable
+and
+.Fn archive_read_support_format_zip_seekable
+.
 .It Fn archive_read_support_format_all
 .It Fn archive_read_support_format_all
 Enables support for all available formats except the
 Enables support for all available formats except the
 .Dq raw
 .Dq raw

+ 31 - 11
Utilities/cmlibarchive/libarchive/archive_read_open_fd.c

@@ -52,6 +52,7 @@
 struct read_fd_data {
 struct read_fd_data {
 	int	 fd;
 	int	 fd;
 	size_t	 block_size;
 	size_t	 block_size;
+	int64_t	 size;
 	char	 use_lseek;
 	char	 use_lseek;
 	void	*buffer;
 	void	*buffer;
 };
 };
@@ -95,6 +96,7 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
 	if (S_ISREG(st.st_mode)) {
 	if (S_ISREG(st.st_mode)) {
 		archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
 		archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
 		mine->use_lseek = 1;
 		mine->use_lseek = 1;
+		mine->size = st.st_size;
 	}
 	}
 #if defined(__CYGWIN__) || defined(_WIN32)
 #if defined(__CYGWIN__) || defined(_WIN32)
 	setmode(mine->fd, O_BINARY);
 	setmode(mine->fd, O_BINARY);
@@ -131,7 +133,7 @@ static int64_t
 file_skip(struct archive *a, void *client_data, int64_t request)
 file_skip(struct archive *a, void *client_data, int64_t request)
 {
 {
 	struct read_fd_data *mine = (struct read_fd_data *)client_data;
 	struct read_fd_data *mine = (struct read_fd_data *)client_data;
-	int64_t skip = request;
+	off_t skip = (off_t)request;
 	int64_t old_offset, new_offset;
 	int64_t old_offset, new_offset;
 	int skip_bits = sizeof(skip) * 8 - 1;  /* off_t is a signed type. */
 	int skip_bits = sizeof(skip) * 8 - 1;  /* off_t is a signed type. */
 
 
@@ -140,20 +142,25 @@ file_skip(struct archive *a, void *client_data, int64_t request)
 
 
 	/* Reduce a request that would overflow the 'skip' variable. */
 	/* Reduce a request that would overflow the 'skip' variable. */
 	if (sizeof(request) > sizeof(skip)) {
 	if (sizeof(request) > sizeof(skip)) {
-		int64_t max_skip =
+		const int64_t max_skip =
 		    (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
 		    (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
 		if (request > max_skip)
 		if (request > max_skip)
-			skip = max_skip;
+			skip = (off_t)max_skip;
 	}
 	}
 
 
-	/* Reduce request to the next smallest multiple of block_size */
-	request = (request / mine->block_size) * mine->block_size;
-	if (request == 0)
+	/* Reduce 'skip' to the next smallest multiple of block_size */
+	skip = (off_t)(((int64_t)skip / mine->block_size) * mine->block_size);
+	if (skip == 0)
 		return (0);
 		return (0);
 
 
-	if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) &&
-	    ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0))
-		return (new_offset - old_offset);
+	if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
+		if (old_offset >= mine->size ||
+		    skip > mine->size - old_offset) {
+			/* Do not seek past end of file. */
+			errno = ESPIPE;
+		} else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
+			return (new_offset - old_offset);
+	}
 
 
 	/* If seek failed once, it will probably fail again. */
 	/* If seek failed once, it will probably fail again. */
 	mine->use_lseek = 0;
 	mine->use_lseek = 0;
@@ -178,11 +185,24 @@ static int64_t
 file_seek(struct archive *a, void *client_data, int64_t request, int whence)
 file_seek(struct archive *a, void *client_data, int64_t request, int whence)
 {
 {
 	struct read_fd_data *mine = (struct read_fd_data *)client_data;
 	struct read_fd_data *mine = (struct read_fd_data *)client_data;
+	off_t seek = (off_t)request;
 	int64_t r;
 	int64_t r;
+	int seek_bits = sizeof(seek) * 8 - 1;  /* off_t is a signed type. */
 
 
 	/* We use off_t here because lseek() is declared that way. */
 	/* We use off_t here because lseek() is declared that way. */
-	/* See above for notes about when off_t is less than 64 bits. */
-	r = lseek(mine->fd, request, whence);
+
+	/* Reduce a request that would overflow the 'seek' variable. */
+	if (sizeof(request) > sizeof(seek)) {
+		const int64_t max_seek =
+		    (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
+		const int64_t min_seek = ~max_seek;
+		if (request > max_seek)
+			seek = (off_t)max_seek;
+		else if (request < min_seek)
+			seek = (off_t)min_seek;
+	}
+
+	r = lseek(mine->fd, seek, whence);
 	if (r >= 0)
 	if (r >= 0)
 		return r;
 		return r;
 
 

+ 47 - 23
Utilities/cmlibarchive/libarchive/archive_read_open_file.c

@@ -52,6 +52,7 @@
 struct read_FILE_data {
 struct read_FILE_data {
 	FILE    *f;
 	FILE    *f;
 	size_t	 block_size;
 	size_t	 block_size;
+	int64_t	 size;
 	void	*buffer;
 	void	*buffer;
 	char	 can_skip;
 	char	 can_skip;
 };
 };
@@ -91,6 +92,7 @@ archive_read_open_FILE(struct archive *a, FILE *f)
 		archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
 		archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
 		/* Enable the seek optimization only for regular files. */
 		/* Enable the seek optimization only for regular files. */
 		mine->can_skip = 1;
 		mine->can_skip = 1;
+		mine->size = st.st_size;
 	}
 	}
 
 
 #if defined(__CYGWIN__) || defined(_WIN32)
 #if defined(__CYGWIN__) || defined(_WIN32)
@@ -130,6 +132,7 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
 #else
 #else
 	long skip = (long)request;
 	long skip = (long)request;
 #endif
 #endif
+	int64_t old_offset, new_offset = -1;
 	int skip_bits = sizeof(skip) * 8 - 1;
 	int skip_bits = sizeof(skip) * 8 - 1;
 
 
 	(void)a; /* UNUSED */
 	(void)a; /* UNUSED */
@@ -145,7 +148,7 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
 
 
 	/* If request is too big for a long or an off_t, reduce it. */
 	/* If request is too big for a long or an off_t, reduce it. */
 	if (sizeof(request) > sizeof(skip)) {
 	if (sizeof(request) > sizeof(skip)) {
-		int64_t max_skip =
+		const int64_t max_skip =
 		    (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
 		    (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
 		if (request > max_skip)
 		if (request > max_skip)
 			skip = max_skip;
 			skip = max_skip;
@@ -153,19 +156,36 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
 
 
 #ifdef __ANDROID__
 #ifdef __ANDROID__
         /* fileno() isn't safe on all platforms ... see above. */
         /* fileno() isn't safe on all platforms ... see above. */
-	if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
+	old_offset = lseek(fileno(mine->f), 0, SEEK_CUR);
 #elif HAVE__FSEEKI64
 #elif HAVE__FSEEKI64
-	if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
+	old_offset = _ftelli64(mine->f);
 #elif HAVE_FSEEKO
 #elif HAVE_FSEEKO
-	if (fseeko(mine->f, skip, SEEK_CUR) != 0)
+	old_offset = ftello(mine->f);
 #else
 #else
-	if (fseek(mine->f, skip, SEEK_CUR) != 0)
+	old_offset = ftell(mine->f);
 #endif
 #endif
-	{
-		mine->can_skip = 0;
-		return (0);
+	if (old_offset >= 0) {
+		if (old_offset < mine->size &&
+		    skip <= mine->size - old_offset) {
+#ifdef __ANDROID__
+			new_offset = lseek(fileno(mine->f), skip, SEEK_CUR);
+#elif HAVE__FSEEKI64
+			if (_fseeki64(mine->f, skip, SEEK_CUR) == 0)
+				new_offset = _ftelli64(mine->f);
+#elif HAVE_FSEEKO
+			if (fseeko(mine->f, skip, SEEK_CUR) == 0)
+				new_offset = ftello(mine->f);
+#else
+			if (fseek(mine->f, skip, SEEK_CUR) == 0)
+				new_offset = ftell(mine->f);
+#endif
+			if (new_offset >= 0)
+				return (new_offset - old_offset);
+		}
 	}
 	}
-	return (request);
+
+	mine->can_skip = 0;
+	return (0);
 }
 }
 
 
 /*
 /*
@@ -176,39 +196,42 @@ FILE_seek(struct archive *a, void *client_data, int64_t request, int whence)
 {
 {
 	struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
 	struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
 #if HAVE__FSEEKI64
 #if HAVE__FSEEKI64
-	int64_t skip = request;
+	int64_t seek = request;
 #elif HAVE_FSEEKO
 #elif HAVE_FSEEKO
-	off_t skip = (off_t)request;
+	off_t seek = (off_t)request;
 #else
 #else
-	long skip = (long)request;
+	long seek = (long)request;
 #endif
 #endif
-	int skip_bits = sizeof(skip) * 8 - 1;
+	int seek_bits = sizeof(seek) * 8 - 1;
 	(void)a; /* UNUSED */
 	(void)a; /* UNUSED */
 
 
-	/* If request is too big for a long or an off_t, reduce it. */
-	if (sizeof(request) > sizeof(skip)) {
-		int64_t max_skip =
-		    (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
-		if (request > max_skip)
-			skip = max_skip;
+	/* Reduce a request that would overflow the 'seek' variable. */
+	if (sizeof(request) > sizeof(seek)) {
+		const int64_t max_seek =
+		    (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
+		const int64_t min_seek = ~max_seek;
+		if (request > max_seek)
+			seek = max_seek;
+		else if (request < min_seek)
+			seek = min_seek;
 	}
 	}
 
 
 #ifdef __ANDROID__
 #ifdef __ANDROID__
 	/* Newer Android versions have fseeko...to meditate. */
 	/* Newer Android versions have fseeko...to meditate. */
-	int64_t ret = lseek(fileno(mine->f), skip, whence);
+	int64_t ret = lseek(fileno(mine->f), seek, whence);
 	if (ret >= 0) {
 	if (ret >= 0) {
 		return ret;
 		return ret;
 	}
 	}
 #elif HAVE__FSEEKI64
 #elif HAVE__FSEEKI64
-	if (_fseeki64(mine->f, skip, whence) == 0) {
+	if (_fseeki64(mine->f, seek, whence) == 0) {
 		return _ftelli64(mine->f);
 		return _ftelli64(mine->f);
 	}
 	}
 #elif HAVE_FSEEKO
 #elif HAVE_FSEEKO
-	if (fseeko(mine->f, skip, whence) == 0) {
+	if (fseeko(mine->f, seek, whence) == 0) {
 		return ftello(mine->f);
 		return ftello(mine->f);
 	}
 	}
 #else
 #else
-	if (fseek(mine->f, skip, whence) == 0) {
+	if (fseek(mine->f, seek, whence) == 0) {
 		return ftell(mine->f);
 		return ftell(mine->f);
 	}
 	}
 #endif
 #endif
@@ -227,3 +250,4 @@ FILE_close(struct archive *a, void *client_data)
 	free(mine);
 	free(mine);
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 }
 }
+

+ 38 - 13
Utilities/cmlibarchive/libarchive/archive_read_open_filename.c

@@ -74,6 +74,7 @@ struct read_file_data {
 	size_t	 block_size;
 	size_t	 block_size;
 	void	*buffer;
 	void	*buffer;
 	mode_t	 st_mode;  /* Mode bits for opened file. */
 	mode_t	 st_mode;  /* Mode bits for opened file. */
+	int64_t	 size;
 	char	 use_lseek;
 	char	 use_lseek;
 	enum fnt_e { FNT_STDIN, FNT_MBS, FNT_WCS } filename_type;
 	enum fnt_e { FNT_STDIN, FNT_MBS, FNT_WCS } filename_type;
 	union {
 	union {
@@ -400,8 +401,10 @@ file_open(struct archive *a, void *client_data)
 	mine->st_mode = st.st_mode;
 	mine->st_mode = st.st_mode;
 
 
 	/* Disk-like inputs can use lseek(). */
 	/* Disk-like inputs can use lseek(). */
-	if (is_disk_like)
+	if (is_disk_like) {
 		mine->use_lseek = 1;
 		mine->use_lseek = 1;
+		mine->size = st.st_size;
+	}
 
 
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 fail:
 fail:
@@ -479,21 +482,30 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
 	struct read_file_data *mine = (struct read_file_data *)client_data;
 	struct read_file_data *mine = (struct read_file_data *)client_data;
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #if defined(_WIN32) && !defined(__CYGWIN__)
 	/* We use _lseeki64() on Windows. */
 	/* We use _lseeki64() on Windows. */
-	int64_t old_offset, new_offset;
+	int64_t old_offset, new_offset, skip = request;
 #else
 #else
-	off_t old_offset, new_offset;
+	off_t old_offset, new_offset, skip = (off_t)request;
 #endif
 #endif
+	int skip_bits = sizeof(skip) * 8 - 1;
 
 
 	/* We use off_t here because lseek() is declared that way. */
 	/* We use off_t here because lseek() is declared that way. */
 
 
-	/* TODO: Deal with case where off_t isn't 64 bits.
-	 * This shouldn't be a problem on Linux or other POSIX
-	 * systems, since the configuration logic for libarchive
-	 * tries to obtain a 64-bit off_t.
-	 */
-	if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
-	    (new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
-		return (new_offset - old_offset);
+	/* Reduce a request that would overflow the 'skip' variable. */
+	if (sizeof(request) > sizeof(skip)) {
+		const int64_t max_skip =
+		    (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
+		if (request > max_skip)
+			skip = max_skip;
+	}
+
+	if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
+		if (old_offset >= mine->size ||
+		    skip > mine->size - old_offset) {
+			/* Do not seek past end of file. */
+			errno = ESPIPE;
+		} else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
+			return (new_offset - old_offset);
+	}
 
 
 	/* If lseek() fails, don't bother trying again. */
 	/* If lseek() fails, don't bother trying again. */
 	mine->use_lseek = 0;
 	mine->use_lseek = 0;
@@ -540,11 +552,24 @@ static int64_t
 file_seek(struct archive *a, void *client_data, int64_t request, int whence)
 file_seek(struct archive *a, void *client_data, int64_t request, int whence)
 {
 {
 	struct read_file_data *mine = (struct read_file_data *)client_data;
 	struct read_file_data *mine = (struct read_file_data *)client_data;
+	off_t seek = (off_t)request;
 	int64_t r;
 	int64_t r;
+	int seek_bits = sizeof(seek) * 8 - 1;
 
 
 	/* We use off_t here because lseek() is declared that way. */
 	/* We use off_t here because lseek() is declared that way. */
-	/* See above for notes about when off_t is less than 64 bits. */
-	r = lseek(mine->fd, request, whence);
+
+	/* Reduce a request that would overflow the 'seek' variable. */
+	if (sizeof(request) > sizeof(seek)) {
+		const int64_t max_seek =
+		    (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
+		const int64_t min_seek = ~max_seek;
+		if (request > max_seek)
+			seek = (off_t)max_seek;
+		else if (request < min_seek)
+			seek = (off_t)min_seek;
+	}
+
+	r = lseek(mine->fd, seek, whence);
 	if (r >= 0)
 	if (r >= 0)
 		return r;
 		return r;
 
 

+ 2 - 1
Utilities/cmlibarchive/libarchive/archive_read_support_filter_compress.c

@@ -328,6 +328,7 @@ next_code(struct archive_read_filter *self)
 	static int debug_buff[1024];
 	static int debug_buff[1024];
 	static unsigned debug_index;
 	static unsigned debug_index;
 
 
+again:
 	code = newcode = getbits(self, state->bits);
 	code = newcode = getbits(self, state->bits);
 	if (code < 0)
 	if (code < 0)
 		return (code);
 		return (code);
@@ -360,7 +361,7 @@ next_code(struct archive_read_filter *self)
 		state->section_end_code = (1 << state->bits) - 1;
 		state->section_end_code = (1 << state->bits) - 1;
 		state->free_ent = 257;
 		state->free_ent = 257;
 		state->oldcode = -1;
 		state->oldcode = -1;
-		return (next_code(self));
+		goto again;
 	}
 	}
 
 
 	if (code > state->free_ent
 	if (code > state->free_ent

+ 255 - 47
Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c

@@ -57,6 +57,7 @@
 #include "archive_ppmd7_private.h"
 #include "archive_ppmd7_private.h"
 #include "archive_private.h"
 #include "archive_private.h"
 #include "archive_read_private.h"
 #include "archive_read_private.h"
+#include "archive_time_private.h"
 #include "archive_endian.h"
 #include "archive_endian.h"
 
 
 #ifndef HAVE_ZLIB_H
 #ifndef HAVE_ZLIB_H
@@ -66,7 +67,26 @@
 #define _7ZIP_SIGNATURE	"7z\xBC\xAF\x27\x1C"
 #define _7ZIP_SIGNATURE	"7z\xBC\xAF\x27\x1C"
 #define SFX_MIN_ADDR	0x27000
 #define SFX_MIN_ADDR	0x27000
 #define SFX_MAX_ADDR	0x60000
 #define SFX_MAX_ADDR	0x60000
+#define SFX_MAX_OFFSET	(SFX_MAX_ADDR - SFX_MIN_ADDR)
 
 
+/*
+ * PE format
+ */
+#define PE_DOS_HDR_LEN				0x40
+#define PE_DOS_HDR_ELFANEW_OFFSET	0x3c
+#define PE_COFF_HDR_LEN				0x18
+#define PE_COFF_HDR_SEC_CNT_OFFSET	0x6
+#define PE_COFF_HDR_OPT_SZ_OFFSET	0x14
+#define PE_SEC_HDR_LEN 				0x28
+#define PE_SEC_HDR_RAW_ADDR_OFFSET	0x14
+#define PE_SEC_HDR_RAW_SZ_OFFSET	0x10
+
+/*
+ * ELF format
+ */
+#define ELF_HDR_MIN_LEN 0x34
+#define ELF_HDR_EI_CLASS_OFFSET 0x04
+#define ELF_HDR_EI_DATA_OFFSET 0x05
 
 
 /*
 /*
  * Codec ID
  * Codec ID
@@ -90,6 +110,7 @@
 #define _7Z_ARM		0x03030501
 #define _7Z_ARM		0x03030501
 #define _7Z_ARMTHUMB	0x03030701
 #define _7Z_ARMTHUMB	0x03030701
 #define _7Z_ARM64	0xa
 #define _7Z_ARM64	0xa
+#define _7Z_RISCV	0xb
 #define _7Z_SPARC	0x03030805
 #define _7Z_SPARC	0x03030805
 
 
 #define _7Z_ZSTD	0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
 #define _7Z_ZSTD	0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
@@ -151,7 +172,6 @@ struct _7z_digests {
 	uint32_t	*digests;
 	uint32_t	*digests;
 };
 };
 
 
-
 struct _7z_folder {
 struct _7z_folder {
 	uint64_t		 numCoders;
 	uint64_t		 numCoders;
 	struct _7z_coder {
 	struct _7z_coder {
@@ -231,13 +251,13 @@ struct _7zip_entry {
 #define CRC32_IS_SET	(1<<3)
 #define CRC32_IS_SET	(1<<3)
 #define HAS_STREAM	(1<<4)
 #define HAS_STREAM	(1<<4)
 
 
-	time_t			 mtime;
-	time_t			 atime;
-	time_t			 ctime;
-	long			 mtime_ns;
-	long			 atime_ns;
-	long			 ctime_ns;
-	uint32_t		 mode;
+	int64_t			 mtime;
+	int64_t			 atime;
+	int64_t			 ctime;
+	uint32_t		 mtime_ns;
+	uint32_t		 atime_ns;
+	uint32_t		 ctime_ns;
+	__LA_MODE_T		 mode;
 	uint32_t		 attr;
 	uint32_t		 attr;
 };
 };
 
 
@@ -395,7 +415,6 @@ static int	decode_encoded_header_info(struct archive_read *,
 static int	decompress(struct archive_read *, struct _7zip *,
 static int	decompress(struct archive_read *, struct _7zip *,
 		    void *, size_t *, const void *, size_t *);
 		    void *, size_t *, const void *, size_t *);
 static ssize_t	extract_pack_stream(struct archive_read *, size_t);
 static ssize_t	extract_pack_stream(struct archive_read *, size_t);
-static void	fileTimeToUtc(uint64_t, time_t *, long *);
 static uint64_t folder_uncompressed_size(struct _7z_folder *);
 static uint64_t folder_uncompressed_size(struct _7z_folder *);
 static void	free_CodersInfo(struct _7z_coders_info *);
 static void	free_CodersInfo(struct _7z_coders_info *);
 static void	free_Digest(struct _7z_digests *);
 static void	free_Digest(struct _7z_digests *);
@@ -431,7 +450,9 @@ static ssize_t	read_stream(struct archive_read *, const void **, size_t,
 		    size_t);
 		    size_t);
 static int	seek_pack(struct archive_read *);
 static int	seek_pack(struct archive_read *);
 static int64_t	skip_stream(struct archive_read *, size_t);
 static int64_t	skip_stream(struct archive_read *, size_t);
-static int	skip_sfx(struct archive_read *, ssize_t);
+static int	skip_sfx(struct archive_read *, const ssize_t);
+static ssize_t	find_pe_overlay(struct archive_read *);
+static ssize_t	find_elf_data_sec(struct archive_read *);
 static int	slurp_central_directory(struct archive_read *, struct _7zip *,
 static int	slurp_central_directory(struct archive_read *, struct _7zip *,
 		    struct _7z_header_info *);
 		    struct _7z_header_info *);
 static int	setup_decode_folder(struct archive_read *, struct _7z_folder *,
 static int	setup_decode_folder(struct archive_read *, struct _7z_folder *,
@@ -531,15 +552,17 @@ archive_read_format_7zip_bid(struct archive_read *a, int best_bid)
 	 * It may a 7-Zip SFX archive file. If first two bytes are
 	 * It may a 7-Zip SFX archive file. If first two bytes are
 	 * 'M' and 'Z' available on Windows or first four bytes are
 	 * 'M' and 'Z' available on Windows or first four bytes are
 	 * "\x7F\x45LF" available on posix like system, seek the 7-Zip
 	 * "\x7F\x45LF" available on posix like system, seek the 7-Zip
-	 * signature. Although we will perform a seek when reading
-	 * a header, what we do not use __archive_read_seek() here is
-	 * due to a bidding performance.
+	 * signature. While find_pe_overlay can be performed without
+	 * performing a seek, find_elf_data_sec requires one,
+	 * thus a performance difference between the two is expected. 
 	 */
 	 */
 	if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
 	if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
-		ssize_t offset = SFX_MIN_ADDR;
+		const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) :
+						       find_elf_data_sec(a);
+		ssize_t offset = min_addr;
 		ssize_t window = 4096;
 		ssize_t window = 4096;
 		ssize_t bytes_avail;
 		ssize_t bytes_avail;
-		while (offset + window <= (SFX_MAX_ADDR)) {
+		while (offset + window <= (min_addr + SFX_MAX_OFFSET)) {
 			const char *buff = __archive_read_ahead(a,
 			const char *buff = __archive_read_ahead(a,
 					offset + window, &bytes_avail);
 					offset + window, &bytes_avail);
 			if (buff == NULL) {
 			if (buff == NULL) {
@@ -589,21 +612,14 @@ check_7zip_header_in_sfx(const char *p)
 }
 }
 
 
 static int
 static int
-skip_sfx(struct archive_read *a, ssize_t bytes_avail)
+skip_sfx(struct archive_read *a, const ssize_t min_addr)
 {
 {
 	const void *h;
 	const void *h;
 	const char *p, *q;
 	const char *p, *q;
 	size_t skip, offset;
 	size_t skip, offset;
 	ssize_t bytes, window;
 	ssize_t bytes, window;
 
 
-	/*
-	 * If bytes_avail > SFX_MIN_ADDR we do not have to call
-	 * __archive_read_seek() at this time since we have
-	 * already had enough data.
-	 */
-	if (bytes_avail > SFX_MIN_ADDR)
-		__archive_read_consume(a, SFX_MIN_ADDR);
-	else if (__archive_read_seek(a, SFX_MIN_ADDR, SEEK_SET) < 0)
+	if (__archive_read_seek(a, min_addr, SEEK_SET) < 0)
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 
 
 	offset = 0;
 	offset = 0;
@@ -636,7 +652,7 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail)
 				    (struct _7zip *)a->format->data;
 				    (struct _7zip *)a->format->data;
 				skip = p - (const char *)h;
 				skip = p - (const char *)h;
 				__archive_read_consume(a, skip);
 				__archive_read_consume(a, skip);
-				zip->seek_base = SFX_MIN_ADDR + offset + skip;
+				zip->seek_base = min_addr + offset + skip;
 				return (ARCHIVE_OK);
 				return (ARCHIVE_OK);
 			}
 			}
 			p += step;
 			p += step;
@@ -653,6 +669,207 @@ fatal:
 	return (ARCHIVE_FATAL);
 	return (ARCHIVE_FATAL);
 }
 }
 
 
+static ssize_t
+find_pe_overlay(struct archive_read *a)
+{
+	const char *h;
+	ssize_t bytes, max_offset, offset, sec_end;
+	ssize_t opt_hdr_sz, sec_cnt;
+
+	for (;;) {
+		/*
+		 * Read Dos header to find e_lfanew
+		 */
+		h = __archive_read_ahead(a, PE_DOS_HDR_LEN, &bytes);
+		if (h == NULL || h[0] != 'M' || h[1] != 'Z') {
+			break;
+		}
+		offset = archive_le32dec(h + PE_DOS_HDR_ELFANEW_OFFSET);
+
+		/*
+		 * Read COFF header to find opt header size and sec cnt
+		 */
+		if (bytes < offset + PE_COFF_HDR_LEN) {
+			h = __archive_read_ahead(a, offset + PE_COFF_HDR_LEN,
+			    &bytes);
+			if (h == NULL || h[offset] != 'P' ||
+			    h[offset + 1] != 'E') {
+				break;
+			}
+		}
+		sec_cnt = archive_le16dec(
+		    h + offset + PE_COFF_HDR_SEC_CNT_OFFSET);
+		opt_hdr_sz = archive_le16dec(
+		    h + offset + PE_COFF_HDR_OPT_SZ_OFFSET);
+
+		/*
+		 * Skip optional header
+		 */
+		if (opt_hdr_sz != 0) {
+			offset += PE_COFF_HDR_LEN + opt_hdr_sz;
+		} else {
+			break;
+		}
+
+		/*
+		 * Traverse sec table to find max raw offset (i.e., overlay)
+		 */
+		if (bytes < offset + sec_cnt * PE_SEC_HDR_LEN) {
+			h = __archive_read_ahead(a,
+			    offset + sec_cnt * PE_SEC_HDR_LEN, NULL);
+			if (h == NULL) {
+				break;
+			}
+		}
+		max_offset = offset;
+		while (sec_cnt > 0) {
+			sec_end = archive_le32dec(
+				      h + offset + PE_SEC_HDR_RAW_SZ_OFFSET) +
+			    archive_le32dec(
+				h + offset + PE_SEC_HDR_RAW_ADDR_OFFSET);
+			if (sec_end > max_offset) {
+				max_offset = sec_end;
+			}
+			offset += PE_SEC_HDR_LEN;
+			sec_cnt--;
+		}
+		return (max_offset);
+	}
+
+	/*
+	 * If encounter any weirdness, revert to old brute-force style search
+	 */
+	return (SFX_MIN_ADDR);
+}
+
+static ssize_t
+find_elf_data_sec(struct archive_read *a)
+{
+	const char *h;
+	char big_endian, format_64;
+	ssize_t bytes, min_addr = SFX_MIN_ADDR;
+	uint64_t e_shoff, strtab_offset, strtab_size;
+	uint16_t e_shentsize, e_shnum, e_shstrndx;
+	uint16_t (*dec16)(const void *);
+	uint32_t (*dec32)(const void *);
+	uint64_t (*dec64)(const void *);
+
+	for (;;) {
+		/*
+		 * Read Elf header to find bitness & endianness
+		 */
+		h = __archive_read_ahead(a, ELF_HDR_MIN_LEN, &bytes);
+		if (h == NULL || memcmp(h, "\x7F\x45LF", 4) != 0) {
+			break;
+		}
+		format_64 = h[ELF_HDR_EI_CLASS_OFFSET] == 0x2;
+		big_endian = h[ELF_HDR_EI_DATA_OFFSET] == 0x2;
+		if (big_endian) {
+			dec16 = &archive_be16dec;
+			dec32 = &archive_be32dec;
+			dec64 = &archive_be64dec;
+		} else {
+			dec16 = &archive_le16dec;
+			dec32 = &archive_le32dec;
+			dec64 = &archive_le64dec;
+		}
+
+		/*
+		 * Read section header table info
+		 */
+		if (format_64) {
+			e_shoff = (*dec64)(h + 0x28);
+			e_shentsize = (*dec16)(h + 0x3A);
+			e_shnum = (*dec16)(h + 0x3C);
+			e_shstrndx = (*dec16)(h + 0x3E);
+			if (e_shnum < e_shstrndx || e_shentsize < 0x28)
+				break;
+
+		} else {
+			e_shoff = (*dec32)(h + 0x20);
+			e_shentsize = (*dec16)(h + 0x2E);
+			e_shnum = (*dec16)(h + 0x30);
+			e_shstrndx = (*dec16)(h + 0x32);
+			if (e_shnum < e_shstrndx || e_shentsize < 0x18)
+				break;
+		}
+
+		/*
+		 * Reading the section table to find strtab section
+		 */
+		if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) {
+			break;
+		}
+		h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL);
+		if (h == NULL) {
+			break;
+		}
+		if (format_64) {
+			strtab_offset = (*dec64)(
+			    h + e_shstrndx * e_shentsize + 0x18);
+			strtab_size = (*dec64)(
+			    h + e_shstrndx * e_shentsize + 0x20);
+		} else {
+			strtab_offset = (*dec32)(
+			    h + e_shstrndx * e_shentsize + 0x10);
+			strtab_size = (*dec32)(
+			    h + e_shstrndx * e_shentsize + 0x14);
+		}
+
+		/*
+		 * Read the STRTAB section to find the .data offset
+		 */
+		if (__archive_read_seek(a, strtab_offset, SEEK_SET) < 0) {
+			break;
+		}
+		h = __archive_read_ahead(a, strtab_size, NULL);
+		if (h == NULL) {
+			break;
+		}
+		ssize_t data_sym_offset = -1;
+		for (size_t offset = 0; offset < strtab_size - 6; offset++) {
+			if (memcmp(h + offset, ".data\00", 6) == 0) {
+				data_sym_offset = offset;
+				break;
+			}
+		}
+		if (data_sym_offset == -1) {
+			break;
+		}
+
+		/*
+		 * Find the section with the .data name
+		 */
+		if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) {
+			break;
+		}
+		h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL);
+		if (h == NULL) {
+			break;
+		}
+		ssize_t sec_tbl_offset = 0, name_offset;
+		while (e_shnum > 0) {
+			name_offset = (*dec32)(h + sec_tbl_offset);
+			if (name_offset == data_sym_offset) {
+				if (format_64) {
+					min_addr = (*dec64)(
+					    h + sec_tbl_offset + 0x18);
+				} else {
+					min_addr = (*dec32)(
+					    h + sec_tbl_offset + 0x10);
+				}
+				break;
+			}
+			sec_tbl_offset += e_shentsize;
+			e_shnum--;
+		}
+		break;
+	}
+
+	__archive_read_seek(a, 0, SEEK_SET);
+	return (min_addr);
+}
+
 static int
 static int
 archive_read_format_7zip_read_header(struct archive_read *a,
 archive_read_format_7zip_read_header(struct archive_read *a,
 	struct archive_entry *entry)
 	struct archive_entry *entry)
@@ -1237,6 +1454,12 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
 				filters[fi].id = LZMA_FILTER_ARM64;
 				filters[fi].id = LZMA_FILTER_ARM64;
 				fi++;
 				fi++;
 				break;
 				break;
+#endif
+#ifdef LZMA_FILTER_RISCV
+			case _7Z_RISCV:
+				filters[fi].id = LZMA_FILTER_RISCV;
+				fi++;
+				break;
 #endif
 #endif
 			case _7Z_SPARC:
 			case _7Z_SPARC:
 				filters[fi].id = LZMA_FILTER_SPARC;
 				filters[fi].id = LZMA_FILTER_SPARC;
@@ -1410,6 +1633,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
 	case _7Z_ARM:
 	case _7Z_ARM:
 	case _7Z_ARMTHUMB:
 	case _7Z_ARMTHUMB:
 	case _7Z_ARM64:
 	case _7Z_ARM64:
+	case _7Z_RISCV:
 	case _7Z_SPARC:
 	case _7Z_SPARC:
 	case _7Z_DELTA:
 	case _7Z_DELTA:
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -2862,23 +3086,6 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
 	return (0);
 	return (0);
 }
 }
 
 
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-static void
-fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns)
-{
-
-	if (fileTime >= EPOC_TIME) {
-		fileTime -= EPOC_TIME;
-		/* milli seconds base */
-		*timep = (time_t)(fileTime / 10000000);
-		/* nano seconds base */
-		*ns = (long)(fileTime % 10000000) * 100;
-	} else {
-		*timep = 0;
-		*ns = 0;
-	}
-}
-
 static int
 static int
 read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
 read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
 {
 {
@@ -2921,19 +3128,19 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
 			goto failed;
 			goto failed;
 		switch (type) {
 		switch (type) {
 		case kCTime:
 		case kCTime:
-			fileTimeToUtc(archive_le64dec(p),
+			ntfs_to_unix(archive_le64dec(p),
 			    &(entries[i].ctime),
 			    &(entries[i].ctime),
 			    &(entries[i].ctime_ns));
 			    &(entries[i].ctime_ns));
 			entries[i].flg |= CTIME_IS_SET;
 			entries[i].flg |= CTIME_IS_SET;
 			break;
 			break;
 		case kATime:
 		case kATime:
-			fileTimeToUtc(archive_le64dec(p),
+			ntfs_to_unix(archive_le64dec(p),
 			    &(entries[i].atime),
 			    &(entries[i].atime),
 			    &(entries[i].atime_ns));
 			    &(entries[i].atime_ns));
 			entries[i].flg |= ATIME_IS_SET;
 			entries[i].flg |= ATIME_IS_SET;
 			break;
 			break;
 		case kMTime:
 		case kMTime:
-			fileTimeToUtc(archive_le64dec(p),
+			ntfs_to_unix(archive_le64dec(p),
 			    &(entries[i].mtime),
 			    &(entries[i].mtime),
 			    &(entries[i].mtime_ns));
 			    &(entries[i].mtime_ns));
 			entries[i].flg |= MTIME_IS_SET;
 			entries[i].flg |= MTIME_IS_SET;
@@ -3028,7 +3235,9 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
 
 
 	if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
 	if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
 		/* This is an executable ? Must be self-extracting... */
 		/* This is an executable ? Must be self-extracting... */
-		r = skip_sfx(a, bytes_avail);
+		const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) :
+						       find_elf_data_sec(a);
+		r = skip_sfx(a, min_addr);
 		if (r < ARCHIVE_WARN)
 		if (r < ARCHIVE_WARN)
 			return (r);
 			return (r);
 		if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL)
 		if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL)
@@ -4322,4 +4531,3 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
 
 
 	return ((ssize_t)outPos);
 	return ((ssize_t)outPos);
 }
 }
-

+ 6 - 1
Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c

@@ -363,7 +363,12 @@ archive_read_support_format_cab(struct archive *_a)
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
 	archive_string_init(&cab->ws);
 	archive_string_init(&cab->ws);
-	archive_wstring_ensure(&cab->ws, 256);
+	if (archive_wstring_ensure(&cab->ws, 256) == NULL) {
+		archive_set_error(&a->archive, ENOMEM,
+		    "Can't allocate memory");
+		free(cab);
+		return (ARCHIVE_FATAL);
+	}
 
 
 	r = __archive_read_register_format(a,
 	r = __archive_read_register_format(a,
 	    cab,
 	    cab,

+ 15 - 7
Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c

@@ -189,6 +189,7 @@ struct cpio {
 };
 };
 
 
 static int64_t	atol16(const char *, unsigned);
 static int64_t	atol16(const char *, unsigned);
+static uint64_t	atol16u(const char *, unsigned);
 static int64_t	atol8(const char *, unsigned);
 static int64_t	atol8(const char *, unsigned);
 static int	archive_read_format_cpio_bid(struct archive_read *, int);
 static int	archive_read_format_cpio_bid(struct archive_read *, int);
 static int	archive_read_format_cpio_options(struct archive_read *,
 static int	archive_read_format_cpio_options(struct archive_read *,
@@ -835,6 +836,7 @@ header_afiol(struct archive_read *a, struct cpio *cpio,
     struct archive_entry *entry, size_t *namelength, size_t *name_pad)
     struct archive_entry *entry, size_t *namelength, size_t *name_pad)
 {
 {
 	int64_t t;
 	int64_t t;
+	uint64_t u;
 	const void *h;
 	const void *h;
 	const char *header;
 	const char *header;
 
 
@@ -851,12 +853,12 @@ header_afiol(struct archive_read *a, struct cpio *cpio,
 
 
 	archive_entry_set_dev(entry, 
 	archive_entry_set_dev(entry, 
 		(dev_t)atol16(header + afiol_dev_offset, afiol_dev_size));
 		(dev_t)atol16(header + afiol_dev_offset, afiol_dev_size));
-	t = atol16(header + afiol_ino_offset, afiol_ino_size);
-	if (t < 0) {
-		archive_set_error(&a->archive, 0, "Nonsensical ino value");
-		return (ARCHIVE_FATAL);
-	}
-	archive_entry_set_ino(entry, t);
+	u = atol16u(header + afiol_ino_offset, afiol_ino_size);
+#if ARCHIVE_VERSION_NUMBER < 4000000
+	archive_entry_set_ino(entry, (int64_t)(u & INT64_MAX));
+#else
+	archive_entry_set_ino(entry, u);
+#endif
 	archive_entry_set_mode(entry,
 	archive_entry_set_mode(entry,
 		(mode_t)atol8(header + afiol_mode_offset, afiol_mode_size));
 		(mode_t)atol8(header + afiol_mode_offset, afiol_mode_size));
 	archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size));
 	archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size));
@@ -1030,6 +1032,12 @@ atol8(const char *p, unsigned char_cnt)
 
 
 static int64_t
 static int64_t
 atol16(const char *p, unsigned char_cnt)
 atol16(const char *p, unsigned char_cnt)
+{
+	return ((int64_t)atol16u(p, char_cnt));
+}
+
+static uint64_t
+atol16u(const char *p, unsigned char_cnt)
 {
 {
 	uint64_t l;
 	uint64_t l;
 	int digit;
 	int digit;
@@ -1048,7 +1056,7 @@ atol16(const char *p, unsigned char_cnt)
 		l <<= 4;
 		l <<= 4;
 		l |= digit;
 		l |= digit;
 	}
 	}
-	return ((int64_t)l);
+	return (l);
 }
 }
 
 
 static int
 static int

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c

@@ -2273,7 +2273,7 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
 				if (version == 1) {
 				if (version == 1) {
 					if (data_length >= 8)
 					if (data_length >= 8)
 						file->mode
 						file->mode
-						    = toi(data, 4);
+						    = (__LA_MODE_T)toi(data, 4);
 					if (data_length >= 16)
 					if (data_length >= 16)
 						file->nlinks
 						file->nlinks
 						    = toi(data + 8, 4);
 						    = toi(data + 8, 4);

+ 16 - 57
Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c

@@ -43,6 +43,7 @@
 #include "archive_entry_locale.h"
 #include "archive_entry_locale.h"
 #include "archive_private.h"
 #include "archive_private.h"
 #include "archive_read_private.h"
 #include "archive_read_private.h"
+#include "archive_time_private.h"
 #include "archive_endian.h"
 #include "archive_endian.h"
 
 
 
 
@@ -162,12 +163,12 @@ struct lha {
 #define ATIME_IS_SET		2
 #define ATIME_IS_SET		2
 #define UNIX_MODE_IS_SET	4
 #define UNIX_MODE_IS_SET	4
 #define CRC_IS_SET		8
 #define CRC_IS_SET		8
-	time_t			 birthtime;
-	long			 birthtime_tv_nsec;
-	time_t			 mtime;
-	long			 mtime_tv_nsec;
-	time_t			 atime;
-	long			 atime_tv_nsec;
+	int64_t			 birthtime;
+	uint32_t		 birthtime_tv_nsec;
+	int64_t			 mtime;
+	uint32_t		 mtime_tv_nsec;
+	int64_t			 atime;
+	uint32_t		 atime_tv_nsec;
 	mode_t			 mode;
 	mode_t			 mode;
 	int64_t			 uid;
 	int64_t			 uid;
 	int64_t			 gid;
 	int64_t			 gid;
@@ -230,8 +231,6 @@ static int	lha_read_file_extended_header(struct archive_read *,
 		    struct lha *, uint16_t *, int, uint64_t, size_t *);
 		    struct lha *, uint16_t *, int, uint64_t, size_t *);
 static size_t	lha_check_header_format(const void *);
 static size_t	lha_check_header_format(const void *);
 static int	lha_skip_sfx(struct archive_read *);
 static int	lha_skip_sfx(struct archive_read *);
-static time_t	lha_dos_time(const unsigned char *);
-static time_t	lha_win_time(uint64_t, long *);
 static unsigned char	lha_calcsum(unsigned char, const void *,
 static unsigned char	lha_calcsum(unsigned char, const void *,
 		    int, size_t);
 		    int, size_t);
 static int	lha_parse_linkname(struct archive_wstring *,
 static int	lha_parse_linkname(struct archive_wstring *,
@@ -819,7 +818,7 @@ lha_read_file_header_0(struct archive_read *a, struct lha *lha)
 	headersum = p[H0_HEADER_SUM_OFFSET];
 	headersum = p[H0_HEADER_SUM_OFFSET];
 	lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET);
 	lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET);
 	lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET);
 	lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET);
-	lha->mtime = lha_dos_time(p + H0_DOS_TIME_OFFSET);
+	lha->mtime = dos_to_unix(archive_le32dec(p + H0_DOS_TIME_OFFSET));
 	namelen = p[H0_NAME_LEN_OFFSET];
 	namelen = p[H0_NAME_LEN_OFFSET];
 	extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen;
 	extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen;
 	if ((namelen > 221 || extdsize < 0) && extdsize != -2) {
 	if ((namelen > 221 || extdsize < 0) && extdsize != -2) {
@@ -919,7 +918,7 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha)
 	/* Note: An extended header size is included in a compsize. */
 	/* Note: An extended header size is included in a compsize. */
 	lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET);
 	lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET);
 	lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET);
 	lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET);
-	lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET);
+	lha->mtime = dos_to_unix(archive_le32dec(p + H1_DOS_TIME_OFFSET));
 	namelen = p[H1_NAME_LEN_OFFSET];
 	namelen = p[H1_NAME_LEN_OFFSET];
 	/* Calculate a padding size. The result will be normally 0 only(?) */
 	/* Calculate a padding size. The result will be normally 0 only(?) */
 	padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen;
 	padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen;
@@ -1090,7 +1089,7 @@ lha_read_file_header_3(struct archive_read *a, struct lha *lha)
 
 
 	if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4)
 	if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4)
 		goto invalid;
 		goto invalid;
-	lha->header_size =archive_le32dec(p + H3_HEADER_SIZE_OFFSET);
+	lha->header_size = archive_le32dec(p + H3_HEADER_SIZE_OFFSET);
 	lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET);
 	lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET);
 	lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET);
 	lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET);
 	lha->mtime = archive_le32dec(p + H3_TIME_OFFSET);
 	lha->mtime = archive_le32dec(p + H3_TIME_OFFSET);
@@ -1326,16 +1325,16 @@ lha_read_file_extended_header(struct archive_read *a, struct lha *lha,
 			break;
 			break;
 		case EXT_TIMESTAMP:
 		case EXT_TIMESTAMP:
 			if (datasize == (sizeof(uint64_t) * 3)) {
 			if (datasize == (sizeof(uint64_t) * 3)) {
-				lha->birthtime = lha_win_time(
-				    archive_le64dec(extdheader),
+				ntfs_to_unix(archive_le64dec(extdheader),
+					&lha->birthtime,
 				    &lha->birthtime_tv_nsec);
 				    &lha->birthtime_tv_nsec);
 				extdheader += sizeof(uint64_t);
 				extdheader += sizeof(uint64_t);
-				lha->mtime = lha_win_time(
-				    archive_le64dec(extdheader),
+				ntfs_to_unix(archive_le64dec(extdheader),
+					&lha->mtime,
 				    &lha->mtime_tv_nsec);
 				    &lha->mtime_tv_nsec);
 				extdheader += sizeof(uint64_t);
 				extdheader += sizeof(uint64_t);
-				lha->atime = lha_win_time(
-				    archive_le64dec(extdheader),
+				ntfs_to_unix(archive_le64dec(extdheader),
+					&lha->atime,
 				    &lha->atime_tv_nsec);
 				    &lha->atime_tv_nsec);
 				lha->setflag |= BIRTHTIME_IS_SET |
 				lha->setflag |= BIRTHTIME_IS_SET |
 				    ATIME_IS_SET;
 				    ATIME_IS_SET;
@@ -1716,45 +1715,6 @@ lha_parse_linkname(struct archive_wstring *linkname,
 	return (0);
 	return (0);
 }
 }
 
 
-/* Convert an MSDOS-style date/time into Unix-style time. */
-static time_t
-lha_dos_time(const unsigned char *p)
-{
-	int msTime, msDate;
-	struct tm ts;
-
-	msTime = archive_le16dec(p);
-	msDate = archive_le16dec(p+2);
-
-	memset(&ts, 0, sizeof(ts));
-	ts.tm_year = ((msDate >> 9) & 0x7f) + 80;   /* Years since 1900. */
-	ts.tm_mon = ((msDate >> 5) & 0x0f) - 1;     /* Month number.     */
-	ts.tm_mday = msDate & 0x1f;		    /* Day of month.     */
-	ts.tm_hour = (msTime >> 11) & 0x1f;
-	ts.tm_min = (msTime >> 5) & 0x3f;
-	ts.tm_sec = (msTime << 1) & 0x3e;
-	ts.tm_isdst = -1;
-	return (mktime(&ts));
-}
-
-/* Convert an MS-Windows-style date/time into Unix-style time. */
-static time_t
-lha_win_time(uint64_t wintime, long *ns)
-{
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-
-	if (wintime >= EPOC_TIME) {
-		wintime -= EPOC_TIME;	/* 1970-01-01 00:00:00 (UTC) */
-		if (ns != NULL)
-			*ns = (long)(wintime % 10000000) * 100;
-		return (wintime / 10000000);
-	} else {
-		if (ns != NULL)
-			*ns = 0;
-		return (0);
-	}
-}
-
 static unsigned char
 static unsigned char
 lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size)
 lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size)
 {
 {
@@ -2917,4 +2877,3 @@ lzh_decode_huffman(struct huffman *hf, unsigned rbits)
 	/* This bit pattern needs to be found out at a huffman tree. */
 	/* This bit pattern needs to be found out at a huffman tree. */
 	return (lzh_decode_huffman_tree(hf, rbits, c));
 	return (lzh_decode_huffman_tree(hf, rbits, c));
 }
 }
-

+ 116 - 62
Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c

@@ -337,8 +337,8 @@ struct rar
   int found_first_header;
   int found_first_header;
   char has_endarc_header;
   char has_endarc_header;
   struct data_block_offsets *dbo;
   struct data_block_offsets *dbo;
-  unsigned int cursor;
-  unsigned int nodes;
+  size_t cursor;
+  size_t nodes;
   char filename_must_match;
   char filename_must_match;
 
 
   /* LZSS members */
   /* LZSS members */
@@ -453,7 +453,7 @@ static int read_filter(struct archive_read *, int64_t *);
 static int rar_decode_byte(struct archive_read*, uint8_t *);
 static int rar_decode_byte(struct archive_read*, uint8_t *);
 static int execute_filter(struct archive_read*, struct rar_filter *,
 static int execute_filter(struct archive_read*, struct rar_filter *,
                           struct rar_virtual_machine *, size_t);
                           struct rar_virtual_machine *, size_t);
-static int copy_from_lzss_window(struct archive_read *, void *, int64_t, int);
+static int copy_from_lzss_window(struct archive_read *, uint8_t *, int64_t, int);
 static inline void vm_write_32(struct rar_virtual_machine*, size_t, uint32_t);
 static inline void vm_write_32(struct rar_virtual_machine*, size_t, uint32_t);
 static inline uint32_t vm_read_32(struct rar_virtual_machine*, size_t);
 static inline uint32_t vm_read_32(struct rar_virtual_machine*, size_t);
 
 
@@ -743,11 +743,11 @@ archive_read_support_format_rar(struct archive *_a)
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
   }
   }
 
 
-	/*
-	 * Until enough data has been read, we cannot tell about
-	 * any encrypted entries yet.
-	 */
-	rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
+  /*
+   * Until enough data has been read, we cannot tell about
+   * any encrypted entries yet.
+   */
+  rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
 
 
   r = __archive_read_register_format(a,
   r = __archive_read_register_format(a,
                                      rar,
                                      rar,
@@ -770,21 +770,21 @@ archive_read_support_format_rar(struct archive *_a)
 static int
 static int
 archive_read_support_format_rar_capabilities(struct archive_read * a)
 archive_read_support_format_rar_capabilities(struct archive_read * a)
 {
 {
-	(void)a; /* UNUSED */
-	return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA
-			| ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
+  (void)a; /* UNUSED */
+  return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA
+    | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
 }
 }
 
 
 static int
 static int
 archive_read_format_rar_has_encrypted_entries(struct archive_read *_a)
 archive_read_format_rar_has_encrypted_entries(struct archive_read *_a)
 {
 {
-	if (_a && _a->format) {
-		struct rar * rar = (struct rar *)_a->format->data;
-		if (rar) {
-			return rar->has_encrypted_entries;
-		}
-	}
-	return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
+  if (_a && _a->format) {
+    struct rar * rar = (struct rar *)_a->format->data;
+    if (rar) {
+      return rar->has_encrypted_entries;
+    }
+  }
+  return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
 }
 }
 
 
 
 
@@ -795,7 +795,7 @@ archive_read_format_rar_bid(struct archive_read *a, int best_bid)
 
 
   /* If there's already a bid > 30, we'll never win. */
   /* If there's already a bid > 30, we'll never win. */
   if (best_bid > 30)
   if (best_bid > 30)
-	  return (-1);
+    return (-1);
 
 
   if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
   if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
     return (-1);
     return (-1);
@@ -867,7 +867,7 @@ skip_sfx(struct archive_read *a)
     }
     }
     skip = p - (const char *)h;
     skip = p - (const char *)h;
     __archive_read_consume(a, skip);
     __archive_read_consume(a, skip);
-	total += skip;
+    total += skip;
   }
   }
 fatal:
 fatal:
   archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
   archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@@ -912,7 +912,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
   const void *h;
   const void *h;
   const char *p;
   const char *p;
   struct rar *rar;
   struct rar *rar;
-  size_t skip;
+  int64_t skip;
   char head_type;
   char head_type;
   int ret;
   int ret;
   unsigned flags;
   unsigned flags;
@@ -932,7 +932,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
    * as well.
    * as well.
    */
    */
   if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
   if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
-	  rar->has_encrypted_entries = 0;
+    rar->has_encrypted_entries = 0;
   }
   }
 
 
   /* RAR files can be generated without EOF headers, so return ARCHIVE_EOF if
   /* RAR files can be generated without EOF headers, so return ARCHIVE_EOF if
@@ -955,8 +955,11 @@ archive_read_format_rar_read_header(struct archive_read *a,
   {
   {
     unsigned long crc32_val;
     unsigned long crc32_val;
 
 
-    if ((h = __archive_read_ahead(a, 7, NULL)) == NULL)
+    if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) {
+      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                        "Failed to read next header.");
       return (ARCHIVE_FATAL);
       return (ARCHIVE_FATAL);
+    }
     p = h;
     p = h;
 
 
     head_type = p[2];
     head_type = p[2];
@@ -974,7 +977,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
     case MAIN_HEAD:
     case MAIN_HEAD:
       rar->main_flags = archive_le16dec(p + 3);
       rar->main_flags = archive_le16dec(p + 3);
       skip = archive_le16dec(p + 5);
       skip = archive_le16dec(p + 5);
-      if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)) {
+      if ((size_t)skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)) {
         archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
         archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
           "Invalid header size");
           "Invalid header size");
         return (ARCHIVE_FATAL);
         return (ARCHIVE_FATAL);
@@ -986,7 +989,8 @@ archive_read_format_rar_read_header(struct archive_read *a,
       memcpy(rar->reserved2, p + 7 + sizeof(rar->reserved1),
       memcpy(rar->reserved2, p + 7 + sizeof(rar->reserved1),
              sizeof(rar->reserved2));
              sizeof(rar->reserved2));
       if (rar->main_flags & MHD_ENCRYPTVER) {
       if (rar->main_flags & MHD_ENCRYPTVER) {
-        if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)+1) {
+        if ((size_t)skip <
+            7 + sizeof(rar->reserved1) + sizeof(rar->reserved2) + 1) {
           archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
           archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
             "Invalid header size");
             "Invalid header size");
           return (ARCHIVE_FATAL);
           return (ARCHIVE_FATAL);
@@ -1055,28 +1059,30 @@ archive_read_format_rar_read_header(struct archive_read *a,
       /* Skim the entire header and compute the CRC. */
       /* Skim the entire header and compute the CRC. */
       crc32_val = 0;
       crc32_val = 0;
       while (skip > 0) {
       while (skip > 0) {
-	      size_t to_read = skip;
-	      if (to_read > 32 * 1024)
-		      to_read = 32 * 1024;
-	      if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
-		      archive_set_error(&a->archive,  ARCHIVE_ERRNO_FILE_FORMAT,
-			  "Bad RAR file");
-		      return (ARCHIVE_FATAL);
-	      }
-	      p = h;
-	      crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned int)to_read);
-	      __archive_read_consume(a, to_read);
-	      skip -= to_read;
+        unsigned to_read;
+        if (skip > 32 * 1024)
+          to_read = 32 * 1024;
+        else
+          to_read = (unsigned)skip;
+        if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
+          archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+            "Bad RAR file");
+          return (ARCHIVE_FATAL);
+        }
+        p = h;
+        crc32_val = crc32(crc32_val, (const unsigned char *)p, to_read);
+        __archive_read_consume(a, to_read);
+        skip -= to_read;
       }
       }
       if ((crc32_val & 0xffff) != crc32_expected) {
       if ((crc32_val & 0xffff) != crc32_expected) {
 #ifndef DONT_FAIL_ON_CRC_ERROR
 #ifndef DONT_FAIL_ON_CRC_ERROR
-	      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		  "Header CRC error");
-	      return (ARCHIVE_FATAL);
+        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+          "Header CRC error");
+        return (ARCHIVE_FATAL);
 #endif
 #endif
       }
       }
       if (head_type == ENDARC_HEAD)
       if (head_type == ENDARC_HEAD)
-	      return (ARCHIVE_EOF);
+        return (ARCHIVE_EOF);
       break;
       break;
 
 
     case NEWSUB_HEAD:
     case NEWSUB_HEAD:
@@ -1085,7 +1091,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
       break;
       break;
 
 
     default:
     default:
-      archive_set_error(&a->archive,  ARCHIVE_ERRNO_FILE_FORMAT,
+      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
                         "Bad RAR file");
                         "Bad RAR file");
       return (ARCHIVE_FATAL);
       return (ARCHIVE_FATAL);
     }
     }
@@ -1100,7 +1106,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
   int ret;
   int ret;
 
 
   if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
   if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
-	  rar->has_encrypted_entries = 0;
+    rar->has_encrypted_entries = 0;
   }
   }
 
 
   if (rar->bytes_unconsumed > 0) {
   if (rar->bytes_unconsumed > 0) {
@@ -1188,7 +1194,7 @@ archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset,
     int whence)
     int whence)
 {
 {
   int64_t client_offset, ret;
   int64_t client_offset, ret;
-  unsigned int i;
+  size_t i;
   struct rar *rar = (struct rar *)(a->format->data);
   struct rar *rar = (struct rar *)(a->format->data);
 
 
   if (rar->compression_method == COMPRESS_METHOD_STORE)
   if (rar->compression_method == COMPRESS_METHOD_STORE)
@@ -1435,7 +1441,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
   }
   }
 
 
   if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
   if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
+  {
+    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                      "Failed to read full header content.");
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
+  }
 
 
   /* File Header CRC check. */
   /* File Header CRC check. */
   crc32_computed = crc32(crc32_computed, h, (unsigned)(header_size - 7));
   crc32_computed = crc32(crc32_computed, h, (unsigned)(header_size - 7));
@@ -1462,8 +1472,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
 
 
   if (rar->file_flags & FHD_PASSWORD)
   if (rar->file_flags & FHD_PASSWORD)
   {
   {
-	archive_entry_set_is_data_encrypted(entry, 1);
-	rar->has_encrypted_entries = 1;
+    archive_entry_set_is_data_encrypted(entry, 1);
+    rar->has_encrypted_entries = 1;
     archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
     archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
                       "RAR encryption support unavailable.");
                       "RAR encryption support unavailable.");
     /* Since it is only the data part itself that is encrypted we can at least
     /* Since it is only the data part itself that is encrypted we can at least
@@ -1508,10 +1518,23 @@ read_header(struct archive_read *a, struct archive_entry *entry,
    */
    */
   if (head_type == NEWSUB_HEAD) {
   if (head_type == NEWSUB_HEAD) {
     size_t distance = p - (const char *)h;
     size_t distance = p - (const char *)h;
+    if (rar->packed_size > INT64_MAX - header_size) {
+      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                        "Extended header size too large.");
+      return (ARCHIVE_FATAL);
+    }
     header_size += rar->packed_size;
     header_size += rar->packed_size;
+    if ((uintmax_t)header_size > SIZE_MAX) {
+      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                        "Unable to read extended header data.");
+      return (ARCHIVE_FATAL);
+    }
     /* Make sure we have the extended data. */
     /* Make sure we have the extended data. */
-    if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
-        return (ARCHIVE_FATAL);
+    if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) {
+      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                        "Failed to read extended header data.");
+      return (ARCHIVE_FATAL);
+    }
     p = h;
     p = h;
     endp = p + header_size - 7;
     endp = p + header_size - 7;
     p += distance;
     p += distance;
@@ -1672,6 +1695,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
     !memcmp(rar->filename, rar->filename_save, filename_size + 1))
     !memcmp(rar->filename, rar->filename_save, filename_size + 1))
   {
   {
     __archive_read_consume(a, header_size - 7);
     __archive_read_consume(a, header_size - 7);
+    rar->br.avail_in = 0;
+    rar->br.next_in = NULL;
     rar->cursor++;
     rar->cursor++;
     if (rar->cursor >= rar->nodes)
     if (rar->cursor >= rar->nodes)
     {
     {
@@ -1691,6 +1716,12 @@ read_header(struct archive_read *a, struct archive_entry *entry,
     }
     }
     if (rar->dbo[rar->cursor].start_offset < 0)
     if (rar->dbo[rar->cursor].start_offset < 0)
     {
     {
+      if (rar->packed_size > INT64_MAX - a->filter->position)
+      {
+        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                          "Unable to store offsets.");
+        return (ARCHIVE_FATAL);
+      }
       rar->dbo[rar->cursor].start_offset = a->filter->position;
       rar->dbo[rar->cursor].start_offset = a->filter->position;
       rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset +
       rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset +
         rar->packed_size;
         rar->packed_size;
@@ -1747,6 +1778,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
   }
   }
 
 
   __archive_read_consume(a, header_size - 7);
   __archive_read_consume(a, header_size - 7);
+  if (rar->packed_size > INT64_MAX - a->filter->position) {
+    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                      "Unable to store offsets.");
+    return (ARCHIVE_FATAL);
+  }
   rar->dbo[0].start_offset = a->filter->position;
   rar->dbo[0].start_offset = a->filter->position;
   rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size;
   rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size;
 
 
@@ -1755,7 +1791,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
   case OS_MSDOS:
   case OS_MSDOS:
   case OS_OS2:
   case OS_OS2:
   case OS_WIN32:
   case OS_WIN32:
-    rar->mode = archive_le32dec(file_header.file_attr);
+    rar->mode = (__LA_MODE_T)archive_le32dec(file_header.file_attr);
     if (rar->mode & FILE_ATTRIBUTE_DIRECTORY)
     if (rar->mode & FILE_ATTRIBUTE_DIRECTORY)
       rar->mode = AE_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
       rar->mode = AE_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
     else
     else
@@ -1766,7 +1802,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
   case OS_UNIX:
   case OS_UNIX:
   case OS_MAC_OS:
   case OS_MAC_OS:
   case OS_BEOS:
   case OS_BEOS:
-    rar->mode = archive_le32dec(file_header.file_attr);
+    rar->mode = (__LA_MODE_T)archive_le32dec(file_header.file_attr);
     break;
     break;
 
 
   default:
   default:
@@ -1782,6 +1818,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
   rar->offset_outgoing = 0;
   rar->offset_outgoing = 0;
   rar->br.cache_avail = 0;
   rar->br.cache_avail = 0;
   rar->br.avail_in = 0;
   rar->br.avail_in = 0;
+  rar->br.next_in = NULL;
   rar->crc_calculated = 0;
   rar->crc_calculated = 0;
   rar->entry_eof = 0;
   rar->entry_eof = 0;
   rar->valid = 1;
   rar->valid = 1;
@@ -1943,8 +1980,18 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
   int ret = (ARCHIVE_OK);
   int ret = (ARCHIVE_OK);
 
 
   rar = (struct rar *)(a->format->data);
   rar = (struct rar *)(a->format->data);
+  if ((uintmax_t)rar->packed_size > SIZE_MAX)
+  {
+    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                      "Unable to read link.");
+    return (ARCHIVE_FATAL);
+  }
   if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
   if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
+  {
+    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                      "Failed to read link.");
     return (ARCHIVE_FATAL);
     return (ARCHIVE_FATAL);
+  }
   p = h;
   p = h;
 
 
   if (archive_entry_copy_symlink_l(entry,
   if (archive_entry_copy_symlink_l(entry,
@@ -2226,7 +2273,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
 
 
       ret = expand(a, &end);
       ret = expand(a, &end);
       if (ret != ARCHIVE_OK)
       if (ret != ARCHIVE_OK)
-	      return (ret);
+        return (ret);
 
 
       rar->bytes_uncopied = end - start;
       rar->bytes_uncopied = end - start;
       rar->filters.lastend = end;
       rar->filters.lastend = end;
@@ -2334,9 +2381,9 @@ parse_codes(struct archive_read *a)
       __archive_ppmd7_functions.Ppmd7_Construct(&rar->ppmd7_context);
       __archive_ppmd7_functions.Ppmd7_Construct(&rar->ppmd7_context);
 
 
       if (rar->dictionary_size == 0) {
       if (rar->dictionary_size == 0) {
-	      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
                           "Invalid zero dictionary size");
                           "Invalid zero dictionary size");
-	      return (ARCHIVE_FATAL);
+        return (ARCHIVE_FATAL);
       }
       }
 
 
       if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,
       if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,
@@ -2931,11 +2978,11 @@ expand(struct archive_read *a, int64_t *end)
     }
     }
 
 
     if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
     if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
-      return (ARCHIVE_FATAL);
+      goto bad_data;
 
 
     if (symbol < 256)
     if (symbol < 256)
     {
     {
-      lzss_emit_literal(rar, symbol);
+      lzss_emit_literal(rar, (uint8_t)symbol);
       continue;
       continue;
     }
     }
     else if (symbol == 256)
     else if (symbol == 256)
@@ -2958,14 +3005,14 @@ expand(struct archive_read *a, int64_t *end)
       else
       else
       {
       {
         if (parse_codes(a) != ARCHIVE_OK)
         if (parse_codes(a) != ARCHIVE_OK)
-          return (ARCHIVE_FATAL);
+          goto bad_data;
         continue;
         continue;
       }
       }
     }
     }
     else if(symbol==257)
     else if(symbol==257)
     {
     {
       if (!read_filter(a, end))
       if (!read_filter(a, end))
-          return (ARCHIVE_FATAL);
+          goto bad_data;
       continue;
       continue;
     }
     }
     else if(symbol==258)
     else if(symbol==258)
@@ -3050,7 +3097,7 @@ expand(struct archive_read *a, int64_t *end)
           {
           {
             if ((lowoffsetsymbol =
             if ((lowoffsetsymbol =
               read_next_symbol(a, &rar->lowoffsetcode)) < 0)
               read_next_symbol(a, &rar->lowoffsetcode)) < 0)
-              return (ARCHIVE_FATAL);
+              goto bad_data;
             if(lowoffsetsymbol == 16)
             if(lowoffsetsymbol == 16)
             {
             {
               rar->numlowoffsetrepeats = 15;
               rar->numlowoffsetrepeats = 15;
@@ -3098,7 +3145,7 @@ bad_data:
 }
 }
 
 
 static int
 static int
-copy_from_lzss_window(struct archive_read *a, void *buffer,
+copy_from_lzss_window(struct archive_read *a, uint8_t *buffer,
                       int64_t startpos, int length)
                       int64_t startpos, int length)
 {
 {
   int windowoffs, firstpart;
   int windowoffs, firstpart;
@@ -3113,7 +3160,7 @@ copy_from_lzss_window(struct archive_read *a, void *buffer,
   }
   }
   if (firstpart < length) {
   if (firstpart < length) {
     memcpy(buffer, &rar->lzss.window[windowoffs], firstpart);
     memcpy(buffer, &rar->lzss.window[windowoffs], firstpart);
-    memcpy(buffer, &rar->lzss.window[0], length - firstpart);
+    memcpy(buffer + firstpart, &rar->lzss.window[0], length - firstpart);
   } else {
   } else {
     memcpy(buffer, &rar->lzss.window[windowoffs], length);
     memcpy(buffer, &rar->lzss.window[windowoffs], length);
   }
   }
@@ -3182,8 +3229,12 @@ static const void *
 rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
 rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
 {
 {
   struct rar *rar = (struct rar *)(a->format->data);
   struct rar *rar = (struct rar *)(a->format->data);
-  const void *h = __archive_read_ahead(a, min, avail);
+  const void *h;
   int ret;
   int ret;
+
+again:
+  h = __archive_read_ahead(a, min, avail);
+
   if (avail)
   if (avail)
   {
   {
     if (a->archive.read_data_is_posix_read && *avail > (ssize_t)a->archive.read_data_requested)
     if (a->archive.read_data_is_posix_read && *avail > (ssize_t)a->archive.read_data_requested)
@@ -3205,7 +3256,7 @@ rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
       rar->filename_must_match = 0;
       rar->filename_must_match = 0;
       if (ret != (ARCHIVE_OK))
       if (ret != (ARCHIVE_OK))
         return NULL;
         return NULL;
-      return rar_read_ahead(a, min, avail);
+      goto again;
     }
     }
   }
   }
   return h;
   return h;
@@ -3269,6 +3320,9 @@ parse_filter(struct archive_read *a, const uint8_t *bytes, uint16_t length, uint
   else
   else
     blocklength = prog ? prog->oldfilterlength : 0;
     blocklength = prog ? prog->oldfilterlength : 0;
 
 
+  if (blocklength > rar->dictionary_size)
+    return 0;
+
   registers[3] = PROGRAM_SYSTEM_GLOBAL_ADDRESS;
   registers[3] = PROGRAM_SYSTEM_GLOBAL_ADDRESS;
   registers[4] = blocklength;
   registers[4] = blocklength;
   registers[5] = prog ? prog->usagecount : 0;
   registers[5] = prog ? prog->usagecount : 0;

+ 57 - 30
Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c

@@ -46,6 +46,7 @@
 #include "archive_entry_locale.h"
 #include "archive_entry_locale.h"
 #include "archive_ppmd7_private.h"
 #include "archive_ppmd7_private.h"
 #include "archive_entry_private.h"
 #include "archive_entry_private.h"
+#include "archive_time_private.h"
 
 
 #ifdef HAVE_BLAKE2_H
 #ifdef HAVE_BLAKE2_H
 #include <blake2.h>
 #include <blake2.h>
@@ -100,10 +101,12 @@ struct file_header {
 	uint8_t dir : 1;             /* Is this file entry a directory? */
 	uint8_t dir : 1;             /* Is this file entry a directory? */
 
 
 	/* Optional time fields. */
 	/* Optional time fields. */
-	uint64_t e_mtime;
-	uint64_t e_ctime;
-	uint64_t e_atime;
-	uint32_t e_unix_ns;
+	int64_t e_mtime;
+	int64_t e_ctime;
+	int64_t e_atime;
+	uint32_t e_mtime_ns;
+	uint32_t e_ctime_ns;
+	uint32_t e_atime_ns;
 
 
 	/* Optional hash fields. */
 	/* Optional hash fields. */
 	uint32_t stored_crc32;
 	uint32_t stored_crc32;
@@ -1101,22 +1104,22 @@ static int read_consume_bits(struct archive_read* a, struct rar5* rar,
 	return ARCHIVE_OK;
 	return ARCHIVE_OK;
 }
 }
 
 
-static int read_u32(struct archive_read* a, uint32_t* pvalue) {
+static char read_u32(struct archive_read* a, uint32_t* pvalue) {
 	const uint8_t* p;
 	const uint8_t* p;
 	if(!read_ahead(a, 4, &p))
 	if(!read_ahead(a, 4, &p))
 		return 0;
 		return 0;
 
 
 	*pvalue = archive_le32dec(p);
 	*pvalue = archive_le32dec(p);
-	return ARCHIVE_OK == consume(a, 4) ? 1 : 0;
+	return ARCHIVE_OK == consume(a, 4);
 }
 }
 
 
-static int read_u64(struct archive_read* a, uint64_t* pvalue) {
+static char read_u64(struct archive_read* a, uint64_t* pvalue) {
 	const uint8_t* p;
 	const uint8_t* p;
 	if(!read_ahead(a, 8, &p))
 	if(!read_ahead(a, 8, &p))
 		return 0;
 		return 0;
 
 
 	*pvalue = archive_le64dec(p);
 	*pvalue = archive_le64dec(p);
-	return ARCHIVE_OK == consume(a, 8) ? 1 : 0;
+	return ARCHIVE_OK == consume(a, 8);
 }
 }
 
 
 static int bid_standard(struct archive_read* a) {
 static int bid_standard(struct archive_read* a) {
@@ -1301,14 +1304,8 @@ static int parse_file_extra_hash(struct archive_read* a, struct rar5* rar,
 	return ARCHIVE_OK;
 	return ARCHIVE_OK;
 }
 }
 
 
-static uint64_t time_win_to_unix(uint64_t win_time) {
-	const size_t ns_in_sec = 10000000;
-	const uint64_t sec_to_unix = 11644473600LL;
-	return win_time / ns_in_sec - sec_to_unix;
-}
-
 static int parse_htime_item(struct archive_read* a, char unix_time,
 static int parse_htime_item(struct archive_read* a, char unix_time,
-    uint64_t* where, int64_t* extra_data_size)
+    int64_t* sec, uint32_t* nsec, int64_t* extra_data_size)
 {
 {
 	if(unix_time) {
 	if(unix_time) {
 		uint32_t time_val;
 		uint32_t time_val;
@@ -1316,13 +1313,13 @@ static int parse_htime_item(struct archive_read* a, char unix_time,
 			return ARCHIVE_EOF;
 			return ARCHIVE_EOF;
 
 
 		*extra_data_size -= 4;
 		*extra_data_size -= 4;
-		*where = (uint64_t) time_val;
+		*sec = (int64_t) time_val;
 	} else {
 	} else {
 		uint64_t windows_time;
 		uint64_t windows_time;
 		if(!read_u64(a, &windows_time))
 		if(!read_u64(a, &windows_time))
 			return ARCHIVE_EOF;
 			return ARCHIVE_EOF;
 
 
-		*where = time_win_to_unix(windows_time);
+		ntfs_to_unix(windows_time, sec, nsec);
 		*extra_data_size -= 8;
 		*extra_data_size -= 8;
 	}
 	}
 
 
@@ -1386,7 +1383,7 @@ static int parse_file_extra_version(struct archive_read* a,
 static int parse_file_extra_htime(struct archive_read* a,
 static int parse_file_extra_htime(struct archive_read* a,
     struct archive_entry* e, struct rar5* rar, int64_t* extra_data_size)
     struct archive_entry* e, struct rar5* rar, int64_t* extra_data_size)
 {
 {
-	char unix_time = 0;
+	char unix_time, has_unix_ns, has_mtime, has_ctime, has_atime;
 	size_t flags = 0;
 	size_t flags = 0;
 	size_t value_len;
 	size_t value_len;
 
 
@@ -1407,32 +1404,62 @@ static int parse_file_extra_htime(struct archive_read* a,
 	}
 	}
 
 
 	unix_time = flags & IS_UNIX;
 	unix_time = flags & IS_UNIX;
+	has_unix_ns = unix_time && (flags & HAS_UNIX_NS);
+	has_mtime = flags & HAS_MTIME;
+	has_atime = flags & HAS_ATIME;
+	has_ctime = flags & HAS_CTIME;
+	rar->file.e_atime_ns = rar->file.e_ctime_ns = rar->file.e_mtime_ns = 0;
 
 
-	if(flags & HAS_MTIME) {
+	if(has_mtime) {
 		parse_htime_item(a, unix_time, &rar->file.e_mtime,
 		parse_htime_item(a, unix_time, &rar->file.e_mtime,
-		    extra_data_size);
-		archive_entry_set_mtime(e, rar->file.e_mtime, 0);
+		    &rar->file.e_mtime_ns, extra_data_size);
 	}
 	}
 
 
-	if(flags & HAS_CTIME) {
+	if(has_ctime) {
 		parse_htime_item(a, unix_time, &rar->file.e_ctime,
 		parse_htime_item(a, unix_time, &rar->file.e_ctime,
-		    extra_data_size);
-		archive_entry_set_ctime(e, rar->file.e_ctime, 0);
+		    &rar->file.e_ctime_ns, extra_data_size);
 	}
 	}
 
 
-	if(flags & HAS_ATIME) {
+	if(has_atime) {
 		parse_htime_item(a, unix_time, &rar->file.e_atime,
 		parse_htime_item(a, unix_time, &rar->file.e_atime,
-		    extra_data_size);
-		archive_entry_set_atime(e, rar->file.e_atime, 0);
+		    &rar->file.e_atime_ns, extra_data_size);
 	}
 	}
 
 
-	if(flags & HAS_UNIX_NS) {
-		if(!read_u32(a, &rar->file.e_unix_ns))
+	if(has_mtime && has_unix_ns) {
+		if(!read_u32(a, &rar->file.e_mtime_ns))
 			return ARCHIVE_EOF;
 			return ARCHIVE_EOF;
 
 
 		*extra_data_size -= 4;
 		*extra_data_size -= 4;
 	}
 	}
 
 
+	if(has_ctime && has_unix_ns) {
+		if(!read_u32(a, &rar->file.e_ctime_ns))
+			return ARCHIVE_EOF;
+
+		*extra_data_size -= 4;
+	}
+
+	if(has_atime && has_unix_ns) {
+		if(!read_u32(a, &rar->file.e_atime_ns))
+			return ARCHIVE_EOF;
+
+		*extra_data_size -= 4;
+	}
+
+	/* The seconds and nanoseconds are either together, or separated in two
+	 * fields so we parse them, then set the archive_entry's times. */
+	if(has_mtime) {
+		archive_entry_set_mtime(e, rar->file.e_mtime, rar->file.e_mtime_ns);
+	}
+
+	if(has_ctime) {
+		archive_entry_set_ctime(e, rar->file.e_ctime, rar->file.e_ctime_ns);
+	}
+
+	if(has_atime) {
+		archive_entry_set_atime(e, rar->file.e_atime, rar->file.e_atime_ns);
+	}
+
 	return ARCHIVE_OK;
 	return ARCHIVE_OK;
 }
 }
 
 
@@ -3106,7 +3133,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
 		 *   can be stored in the output buffer directly.
 		 *   can be stored in the output buffer directly.
 		 *
 		 *
 		 * - Code 256 defines a new filter, which is later used to
 		 * - Code 256 defines a new filter, which is later used to
-		 *   ransform the data block accordingly to the filter type.
+		 *   transform the data block accordingly to the filter type.
 		 *   The data block needs to be fully uncompressed first.
 		 *   The data block needs to be fully uncompressed first.
 		 *
 		 *
 		 * - Code bigger than 257 and smaller than 262 define
 		 * - Code bigger than 257 and smaller than 262 define

+ 145 - 99
Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c

@@ -169,36 +169,36 @@ static int	gnu_add_sparse_entry(struct archive_read *, struct tar *,
 
 
 static void	gnu_clear_sparse_list(struct tar *);
 static void	gnu_clear_sparse_list(struct tar *);
 static int	gnu_sparse_old_read(struct archive_read *, struct tar *,
 static int	gnu_sparse_old_read(struct archive_read *, struct tar *,
-		    const struct archive_entry_header_gnutar *header, size_t *);
+		    const struct archive_entry_header_gnutar *header, int64_t *);
 static int	gnu_sparse_old_parse(struct archive_read *, struct tar *,
 static int	gnu_sparse_old_parse(struct archive_read *, struct tar *,
 		    const struct gnu_sparse *sparse, int length);
 		    const struct gnu_sparse *sparse, int length);
 static int	gnu_sparse_01_parse(struct archive_read *, struct tar *,
 static int	gnu_sparse_01_parse(struct archive_read *, struct tar *,
 		    const char *, size_t);
 		    const char *, size_t);
-static ssize_t	gnu_sparse_10_read(struct archive_read *, struct tar *,
-		    size_t *);
+static int64_t	gnu_sparse_10_read(struct archive_read *, struct tar *,
+		    int64_t *);
 static int	header_Solaris_ACL(struct archive_read *,  struct tar *,
 static int	header_Solaris_ACL(struct archive_read *,  struct tar *,
-		    struct archive_entry *, const void *, size_t *);
+		    struct archive_entry *, const void *, int64_t *);
 static int	header_common(struct archive_read *,  struct tar *,
 static int	header_common(struct archive_read *,  struct tar *,
 		    struct archive_entry *, const void *);
 		    struct archive_entry *, const void *);
 static int	header_old_tar(struct archive_read *, struct tar *,
 static int	header_old_tar(struct archive_read *, struct tar *,
 		    struct archive_entry *, const void *);
 		    struct archive_entry *, const void *);
 static int	header_pax_extension(struct archive_read *, struct tar *,
 static int	header_pax_extension(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *, size_t *);
+		    struct archive_entry *, const void *, int64_t *);
 static int	header_pax_global(struct archive_read *, struct tar *,
 static int	header_pax_global(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h, size_t *);
+		    struct archive_entry *, const void *h, int64_t *);
 static int	header_gnu_longlink(struct archive_read *, struct tar *,
 static int	header_gnu_longlink(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h, size_t *);
+		    struct archive_entry *, const void *h, int64_t *);
 static int	header_gnu_longname(struct archive_read *, struct tar *,
 static int	header_gnu_longname(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h, size_t *);
+		    struct archive_entry *, const void *h, int64_t *);
 static int	is_mac_metadata_entry(struct archive_entry *entry);
 static int	is_mac_metadata_entry(struct archive_entry *entry);
 static int	read_mac_metadata_blob(struct archive_read *,
 static int	read_mac_metadata_blob(struct archive_read *,
-		    struct archive_entry *, size_t *);
+		    struct archive_entry *, int64_t *);
 static int	header_volume(struct archive_read *, struct tar *,
 static int	header_volume(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h, size_t *);
+		    struct archive_entry *, const void *h, int64_t *);
 static int	header_ustar(struct archive_read *, struct tar *,
 static int	header_ustar(struct archive_read *, struct tar *,
 		    struct archive_entry *, const void *h);
 		    struct archive_entry *, const void *h);
 static int	header_gnutar(struct archive_read *, struct tar *,
 static int	header_gnutar(struct archive_read *, struct tar *,
-		    struct archive_entry *, const void *h, size_t *);
+		    struct archive_entry *, const void *h, int64_t *);
 static int	archive_read_format_tar_bid(struct archive_read *, int);
 static int	archive_read_format_tar_bid(struct archive_read *, int);
 static int	archive_read_format_tar_options(struct archive_read *,
 static int	archive_read_format_tar_options(struct archive_read *,
 		    const char *, const char *);
 		    const char *, const char *);
@@ -211,7 +211,7 @@ static int	archive_read_format_tar_read_header(struct archive_read *,
 static int	checksum(struct archive_read *, const void *);
 static int	checksum(struct archive_read *, const void *);
 static int 	pax_attribute(struct archive_read *, struct tar *,
 static int 	pax_attribute(struct archive_read *, struct tar *,
 		    struct archive_entry *, const char *key, size_t key_length,
 		    struct archive_entry *, const char *key, size_t key_length,
-		    size_t value_length, size_t *unconsumed);
+		    size_t value_length, int64_t *unconsumed);
 static int	pax_attribute_LIBARCHIVE_xattr(struct archive_entry *,
 static int	pax_attribute_LIBARCHIVE_xattr(struct archive_entry *,
 		    const char *, size_t, const char *, size_t);
 		    const char *, size_t, const char *, size_t);
 static int	pax_attribute_SCHILY_acl(struct archive_read *, struct tar *,
 static int	pax_attribute_SCHILY_acl(struct archive_read *, struct tar *,
@@ -220,20 +220,20 @@ static int	pax_attribute_SUN_holesdata(struct archive_read *, struct tar *,
 		    struct archive_entry *, const char *, size_t);
 		    struct archive_entry *, const char *, size_t);
 static void	pax_time(const char *, size_t, int64_t *sec, long *nanos);
 static void	pax_time(const char *, size_t, int64_t *sec, long *nanos);
 static ssize_t	readline(struct archive_read *, struct tar *, const char **,
 static ssize_t	readline(struct archive_read *, struct tar *, const char **,
-		    ssize_t limit, size_t *);
+		    ssize_t limit, int64_t *);
 static int	read_body_to_string(struct archive_read *, struct tar *,
 static int	read_body_to_string(struct archive_read *, struct tar *,
-		    struct archive_string *, const void *h, size_t *);
+		    struct archive_string *, const void *h, int64_t *);
 static int	read_bytes_to_string(struct archive_read *,
 static int	read_bytes_to_string(struct archive_read *,
-		    struct archive_string *, size_t, size_t *);
+		    struct archive_string *, size_t, int64_t *);
 static int64_t	tar_atol(const char *, size_t);
 static int64_t	tar_atol(const char *, size_t);
 static int64_t	tar_atol10(const char *, size_t);
 static int64_t	tar_atol10(const char *, size_t);
 static int64_t	tar_atol256(const char *, size_t);
 static int64_t	tar_atol256(const char *, size_t);
 static int64_t	tar_atol8(const char *, size_t);
 static int64_t	tar_atol8(const char *, size_t);
 static int	tar_read_header(struct archive_read *, struct tar *,
 static int	tar_read_header(struct archive_read *, struct tar *,
-		    struct archive_entry *, size_t *);
+		    struct archive_entry *, int64_t *);
 static int	tohex(int c);
 static int	tohex(int c);
 static char	*url_decode(const char *, size_t);
 static char	*url_decode(const char *, size_t);
-static void	tar_flush_unconsumed(struct archive_read *, size_t *);
+static void	tar_flush_unconsumed(struct archive_read *, int64_t *);
 
 
 /* Sanity limits:  These numbers should be low enough to
 /* Sanity limits:  These numbers should be low enough to
  * prevent a maliciously-crafted archive from forcing us to
  * prevent a maliciously-crafted archive from forcing us to
@@ -478,7 +478,7 @@ archive_read_format_tar_options(struct archive_read *a,
  * anything outstanding since we're going to do read_aheads
  * anything outstanding since we're going to do read_aheads
  */
  */
 static void
 static void
-tar_flush_unconsumed(struct archive_read *a, size_t *unconsumed)
+tar_flush_unconsumed(struct archive_read *a, int64_t *unconsumed)
 {
 {
 	if (*unconsumed) {
 	if (*unconsumed) {
 /*
 /*
@@ -526,7 +526,8 @@ archive_read_format_tar_read_header(struct archive_read *a,
 	const char *p;
 	const char *p;
 	const wchar_t *wp;
 	const wchar_t *wp;
 	int r;
 	int r;
-	size_t l, unconsumed = 0;
+	size_t l;
+	int64_t unconsumed = 0;
 
 
 	/* Assign default device/inode values. */
 	/* Assign default device/inode values. */
 	archive_entry_set_dev(entry, 1 + default_dev); /* Don't use zero. */
 	archive_entry_set_dev(entry, 1 + default_dev); /* Don't use zero. */
@@ -627,7 +628,10 @@ archive_read_format_tar_read_data(struct archive_read *a,
 		/* If we're at end of file, return EOF. */
 		/* If we're at end of file, return EOF. */
 		if (tar->sparse_list == NULL ||
 		if (tar->sparse_list == NULL ||
 		    tar->entry_bytes_remaining == 0) {
 		    tar->entry_bytes_remaining == 0) {
-			if (__archive_read_consume(a, tar->entry_padding) < 0)
+			int64_t request = tar->entry_bytes_remaining +
+			    tar->entry_padding;
+
+			if (__archive_read_consume(a, request) != request)
 				return (ARCHIVE_FATAL);
 				return (ARCHIVE_FATAL);
 			tar->entry_padding = 0;
 			tar->entry_padding = 0;
 			*buff = NULL;
 			*buff = NULL;
@@ -665,29 +669,15 @@ archive_read_format_tar_read_data(struct archive_read *a,
 static int
 static int
 archive_read_format_tar_skip(struct archive_read *a)
 archive_read_format_tar_skip(struct archive_read *a)
 {
 {
-	int64_t bytes_skipped;
 	int64_t request;
 	int64_t request;
-	struct sparse_block *p;
 	struct tar* tar;
 	struct tar* tar;
 
 
 	tar = (struct tar *)(a->format->data);
 	tar = (struct tar *)(a->format->data);
 
 
-	/* Do not consume the hole of a sparse file. */
-	request = 0;
-	for (p = tar->sparse_list; p != NULL; p = p->next) {
-		if (!p->hole) {
-			if (p->remaining >= INT64_MAX - request) {
-				return ARCHIVE_FATAL;
-			}
-			request += p->remaining;
-		}
-	}
-	if (request > tar->entry_bytes_remaining)
-		request = tar->entry_bytes_remaining;
-	request += tar->entry_padding + tar->entry_bytes_unconsumed;
+	request = tar->entry_bytes_remaining + tar->entry_padding +
+	    tar->entry_bytes_unconsumed;
 
 
-	bytes_skipped = __archive_read_consume(a, request);
-	if (bytes_skipped < 0)
+	if (__archive_read_consume(a, request) != request)
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 
 
 	tar->entry_bytes_remaining = 0;
 	tar->entry_bytes_remaining = 0;
@@ -700,13 +690,29 @@ archive_read_format_tar_skip(struct archive_read *a)
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 }
 }
 
 
+/*
+ * This function resets the accumulated state while reading
+ * a header.
+ */
+static void
+tar_reset_header_state(struct tar *tar)
+{
+	tar->pax_hdrcharset_utf8 = 1;
+	tar->sparse_gnu_attributes_seen = 0;
+	archive_string_empty(&(tar->entry_gname));
+	archive_string_empty(&(tar->entry_pathname));
+	archive_string_empty(&(tar->entry_pathname_override));
+	archive_string_empty(&(tar->entry_uname));
+	archive_string_empty(&tar->entry_linkpath);
+}
+
 /*
 /*
  * This function reads and interprets all of the headers associated
  * This function reads and interprets all of the headers associated
  * with a single entry.
  * with a single entry.
  */
  */
 static int
 static int
 tar_read_header(struct archive_read *a, struct tar *tar,
 tar_read_header(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, size_t *unconsumed)
+    struct archive_entry *entry, int64_t *unconsumed)
 {
 {
 	ssize_t bytes;
 	ssize_t bytes;
 	int err = ARCHIVE_OK, err2;
 	int err = ARCHIVE_OK, err2;
@@ -725,13 +731,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
 	static const int32_t seen_x_header = 32; /* Also X */
 	static const int32_t seen_x_header = 32; /* Also X */
 	static const int32_t seen_mac_metadata = 512;
 	static const int32_t seen_mac_metadata = 512;
 
 
-	tar->pax_hdrcharset_utf8 = 1;
-	tar->sparse_gnu_attributes_seen = 0;
-	archive_string_empty(&(tar->entry_gname));
-	archive_string_empty(&(tar->entry_pathname));
-	archive_string_empty(&(tar->entry_pathname_override));
-	archive_string_empty(&(tar->entry_uname));
-	archive_string_empty(&tar->entry_linkpath);
+	tar_reset_header_state(tar);
 
 
 	/* Ensure format is set. */
 	/* Ensure format is set. */
 	if (a->archive.archive_format_name == NULL) {
 	if (a->archive.archive_format_name == NULL) {
@@ -815,6 +815,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
 		switch(header->typeflag[0]) {
 		switch(header->typeflag[0]) {
 		case 'A': /* Solaris tar ACL */
 		case 'A': /* Solaris tar ACL */
 			if (seen_headers & seen_A_header) {
 			if (seen_headers & seen_A_header) {
+				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+						  "Redundant 'A' header");
 				return (ARCHIVE_FATAL);
 				return (ARCHIVE_FATAL);
 			}
 			}
 			seen_headers |= seen_A_header;
 			seen_headers |= seen_A_header;
@@ -824,6 +826,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
 			break;
 			break;
 		case 'g': /* POSIX-standard 'g' header. */
 		case 'g': /* POSIX-standard 'g' header. */
 			if (seen_headers & seen_g_header) {
 			if (seen_headers & seen_g_header) {
+				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+						  "Redundant 'g' header");
 				return (ARCHIVE_FATAL);
 				return (ARCHIVE_FATAL);
 			}
 			}
 			seen_headers |= seen_g_header;
 			seen_headers |= seen_g_header;
@@ -833,27 +837,41 @@ tar_read_header(struct archive_read *a, struct tar *tar,
 			break;
 			break;
 		case 'K': /* Long link name (GNU tar, others) */
 		case 'K': /* Long link name (GNU tar, others) */
 			if (seen_headers & seen_K_header) {
 			if (seen_headers & seen_K_header) {
-				return (ARCHIVE_FATAL);
+				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+						  "Damaged archive: Redundant 'K' headers may cause linknames to be incorrect");
+				err = err_combine(err, ARCHIVE_WARN);
 			}
 			}
 			seen_headers |= seen_K_header;
 			seen_headers |= seen_K_header;
+			a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
+			a->archive.archive_format_name = "GNU tar format";
 			err2 = header_gnu_longlink(a, tar, entry, h, unconsumed);
 			err2 = header_gnu_longlink(a, tar, entry, h, unconsumed);
 			break;
 			break;
 		case 'L': /* Long filename (GNU tar, others) */
 		case 'L': /* Long filename (GNU tar, others) */
 			if (seen_headers & seen_L_header) {
 			if (seen_headers & seen_L_header) {
-				return (ARCHIVE_FATAL);
+				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+						  "Damaged archive: Redundant 'L' headers may cause filenames to be incorrect");
+				err = err_combine(err, ARCHIVE_WARN);
 			}
 			}
 			seen_headers |= seen_L_header;
 			seen_headers |= seen_L_header;
+			a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
+			a->archive.archive_format_name = "GNU tar format";
 			err2 = header_gnu_longname(a, tar, entry, h, unconsumed);
 			err2 = header_gnu_longname(a, tar, entry, h, unconsumed);
 			break;
 			break;
 		case 'V': /* GNU volume header */
 		case 'V': /* GNU volume header */
 			if (seen_headers & seen_V_header) {
 			if (seen_headers & seen_V_header) {
-				return (ARCHIVE_FATAL);
+				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+						  "Redundant 'V' header");
+				err = err_combine(err, ARCHIVE_WARN);
 			}
 			}
 			seen_headers |= seen_V_header;
 			seen_headers |= seen_V_header;
+			a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
+			a->archive.archive_format_name = "GNU tar format";
 			err2 = header_volume(a, tar, entry, h, unconsumed);
 			err2 = header_volume(a, tar, entry, h, unconsumed);
 			break;
 			break;
 		case 'X': /* Used by SUN tar; same as 'x'. */
 		case 'X': /* Used by SUN tar; same as 'x'. */
 			if (seen_headers & seen_x_header) {
 			if (seen_headers & seen_x_header) {
+				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+						  "Redundant 'X'/'x' header");
 				return (ARCHIVE_FATAL);
 				return (ARCHIVE_FATAL);
 			}
 			}
 			seen_headers |= seen_x_header;
 			seen_headers |= seen_x_header;
@@ -864,6 +882,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
 			break;
 			break;
 		case 'x': /* POSIX-standard 'x' header. */
 		case 'x': /* POSIX-standard 'x' header. */
 			if (seen_headers & seen_x_header) {
 			if (seen_headers & seen_x_header) {
+				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+						  "Redundant 'x' header");
 				return (ARCHIVE_FATAL);
 				return (ARCHIVE_FATAL);
 			}
 			}
 			seen_headers |= seen_x_header;
 			seen_headers |= seen_x_header;
@@ -915,6 +935,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
 				err = err_combine(err, err2);
 				err = err_combine(err, err2);
 				/* Note: Other headers can appear again. */
 				/* Note: Other headers can appear again. */
 				seen_headers = seen_mac_metadata;
 				seen_headers = seen_mac_metadata;
+				tar_reset_header_state(tar);
 				break;
 				break;
 			}
 			}
 
 
@@ -1043,7 +1064,7 @@ archive_block_is_null(const char *p)
  */
  */
 static int
 static int
 header_Solaris_ACL(struct archive_read *a, struct tar *tar,
 header_Solaris_ACL(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
+    struct archive_entry *entry, const void *h, int64_t *unconsumed)
 {
 {
 	const struct archive_entry_header_ustar *header;
 	const struct archive_entry_header_ustar *header;
 	struct archive_string	 acl_text;
 	struct archive_string	 acl_text;
@@ -1097,8 +1118,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
 		break;
 		break;
 	default:
 	default:
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-		    "Malformed Solaris ACL attribute (unsupported type %"
-		    PRIo64 ")", type);
+		    "Malformed Solaris ACL attribute (unsupported type %llu)",
+		    (unsigned long long)type);
 		archive_string_free(&acl_text);
 		archive_string_free(&acl_text);
 		return (ARCHIVE_WARN);
 		return (ARCHIVE_WARN);
 	}
 	}
@@ -1149,7 +1170,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
  */
  */
 static int
 static int
 header_gnu_longlink(struct archive_read *a, struct tar *tar,
 header_gnu_longlink(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
+    struct archive_entry *entry, const void *h, int64_t *unconsumed)
 {
 {
 	int err;
 	int err;
 
 
@@ -1183,7 +1204,7 @@ set_conversion_failed_error(struct archive_read *a,
  */
  */
 static int
 static int
 header_gnu_longname(struct archive_read *a, struct tar *tar,
 header_gnu_longname(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
+    struct archive_entry *entry, const void *h, int64_t *unconsumed)
 {
 {
 	int err;
 	int err;
 	struct archive_string longname;
 	struct archive_string longname;
@@ -1204,7 +1225,7 @@ header_gnu_longname(struct archive_read *a, struct tar *tar,
  */
  */
 static int
 static int
 header_volume(struct archive_read *a, struct tar *tar,
 header_volume(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
+    struct archive_entry *entry, const void *h, int64_t *unconsumed)
 {
 {
 	const struct archive_entry_header_ustar *header;
 	const struct archive_entry_header_ustar *header;
 	int64_t size, to_consume;
 	int64_t size, to_consume;
@@ -1230,7 +1251,7 @@ header_volume(struct archive_read *a, struct tar *tar,
 static int
 static int
 read_bytes_to_string(struct archive_read *a,
 read_bytes_to_string(struct archive_read *a,
 		     struct archive_string *as, size_t size,
 		     struct archive_string *as, size_t size,
-		     size_t *unconsumed) {
+		     int64_t *unconsumed) {
 	const void *src;
 	const void *src;
 
 
 	/* Fail if we can't make our buffer big enough. */
 	/* Fail if we can't make our buffer big enough. */
@@ -1263,7 +1284,7 @@ read_bytes_to_string(struct archive_read *a,
  */
  */
 static int
 static int
 read_body_to_string(struct archive_read *a, struct tar *tar,
 read_body_to_string(struct archive_read *a, struct tar *tar,
-    struct archive_string *as, const void *h, size_t *unconsumed)
+    struct archive_string *as, const void *h, int64_t *unconsumed)
 {
 {
 	int64_t size;
 	int64_t size;
 	const struct archive_entry_header_ustar *header;
 	const struct archive_entry_header_ustar *header;
@@ -1272,18 +1293,21 @@ read_body_to_string(struct archive_read *a, struct tar *tar,
 	(void)tar; /* UNUSED */
 	(void)tar; /* UNUSED */
 	header = (const struct archive_entry_header_ustar *)h;
 	header = (const struct archive_entry_header_ustar *)h;
 	size  = tar_atol(header->size, sizeof(header->size));
 	size  = tar_atol(header->size, sizeof(header->size));
-	if (size > entry_limit) {
+	if (size < 0 || size > entry_limit) {
+		archive_set_error(&a->archive, EINVAL,
+		    "Special header has invalid size: %lld",
+		    (long long)size);
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
-	if ((size > (int64_t)pathname_limit) || (size < 0)) {
+	if (size > (int64_t)pathname_limit) {
 		archive_string_empty(as);
 		archive_string_empty(as);
 		int64_t to_consume = ((size + 511) & ~511);
 		int64_t to_consume = ((size + 511) & ~511);
 		if (to_consume != __archive_read_consume(a, to_consume)) {
 		if (to_consume != __archive_read_consume(a, to_consume)) {
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 		archive_set_error(&a->archive, EINVAL,
 		archive_set_error(&a->archive, EINVAL,
-		    "Special header too large: %d > 1MiB",
-		    (int)size);
+		    "Special header too large: %lld > 1MiB",
+		    (long long)size);
 		return (ARCHIVE_WARN);
 		return (ARCHIVE_WARN);
 	}
 	}
 	r = read_bytes_to_string(a, as, size, unconsumed);
 	r = read_bytes_to_string(a, as, size, unconsumed);
@@ -1654,7 +1678,7 @@ is_mac_metadata_entry(struct archive_entry *entry) {
  */
  */
 static int
 static int
 read_mac_metadata_blob(struct archive_read *a,
 read_mac_metadata_blob(struct archive_read *a,
-    struct archive_entry *entry, size_t *unconsumed)
+    struct archive_entry *entry, int64_t *unconsumed)
 {
 {
 	int64_t size;
 	int64_t size;
 	size_t msize;
 	size_t msize;
@@ -1711,7 +1735,7 @@ read_mac_metadata_blob(struct archive_read *a,
  */
  */
 static int
 static int
 header_pax_global(struct archive_read *a, struct tar *tar,
 header_pax_global(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
+    struct archive_entry *entry, const void *h, int64_t *unconsumed)
 {
 {
 	const struct archive_entry_header_ustar *header;
 	const struct archive_entry_header_ustar *header;
 	int64_t size, to_consume;
 	int64_t size, to_consume;
@@ -1722,7 +1746,10 @@ header_pax_global(struct archive_read *a, struct tar *tar,
 
 
 	header = (const struct archive_entry_header_ustar *)h;
 	header = (const struct archive_entry_header_ustar *)h;
 	size = tar_atol(header->size, sizeof(header->size));
 	size = tar_atol(header->size, sizeof(header->size));
-	if (size > entry_limit) {
+	if (size < 0 || size > entry_limit) {
+		archive_set_error(&a->archive, EINVAL,
+		    "Special header has invalid size: %lld",
+		    (long long)size);
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
 	to_consume = ((size + 511) & ~511);
 	to_consume = ((size + 511) & ~511);
@@ -1818,7 +1845,7 @@ header_ustar(struct archive_read *a, struct tar *tar,
 
 
 static int
 static int
 header_pax_extension(struct archive_read *a, struct tar *tar,
 header_pax_extension(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
+    struct archive_entry *entry, const void *h, int64_t *unconsumed)
 {
 {
 	/* Sanity checks: The largest `x` body I've ever heard of was
 	/* Sanity checks: The largest `x` body I've ever heard of was
 	 * a little over 4MB.  So I doubt there has ever been a
 	 * a little over 4MB.  So I doubt there has ever been a
@@ -1869,8 +1896,8 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 		archive_set_error(&a->archive, EINVAL,
 		archive_set_error(&a->archive, EINVAL,
-		    "Ignoring oversized pax extensions: %d > %d",
-		    (int)ext_size, (int)ext_size_limit);
+		    "Ignoring oversized pax extensions: %lld > %lld",
+		    (long long)ext_size, (long long)ext_size_limit);
 		return (ARCHIVE_WARN);
 		return (ARCHIVE_WARN);
 	}
 	}
 	tar_flush_unconsumed(a, unconsumed);
 	tar_flush_unconsumed(a, unconsumed);
@@ -1969,6 +1996,13 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
 		*unconsumed += p - attr_start;
 		*unconsumed += p - attr_start;
 		tar_flush_unconsumed(a, unconsumed);
 		tar_flush_unconsumed(a, unconsumed);
 
 
+		if (value_length == 0) {
+			archive_set_error(&a->archive, EINVAL,
+					  "Malformed pax attributes");
+			*unconsumed += ext_size + ext_padding;
+			return (ARCHIVE_WARN);
+		}
+
 		/* pax_attribute will consume value_length - 1 */
 		/* pax_attribute will consume value_length - 1 */
 		r = pax_attribute(a, tar, entry, attr_name.s, archive_strlen(&attr_name), value_length - 1, unconsumed);
 		r = pax_attribute(a, tar, entry, attr_name.s, archive_strlen(&attr_name), value_length - 1, unconsumed);
 		ext_size -= value_length - 1;
 		ext_size -= value_length - 1;
@@ -2179,8 +2213,9 @@ pax_attribute_SCHILY_acl(struct archive_read *a, struct tar *tar,
 	if (value_length > acl_limit) {
 	if (value_length > acl_limit) {
 		__archive_read_consume(a, value_length);
 		__archive_read_consume(a, value_length);
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-				  "Unreasonably large ACL: %d > %d",
-				  (int)value_length, (int)acl_limit);
+				  "Unreasonably large ACL: %llu > %llu",
+				  (unsigned long long)value_length,
+				  (unsigned long long)acl_limit);
 		return (ARCHIVE_WARN);
 		return (ARCHIVE_WARN);
 	}
 	}
 
 
@@ -2212,7 +2247,7 @@ pax_attribute_SCHILY_acl(struct archive_read *a, struct tar *tar,
 }
 }
 
 
 static int
 static int
-pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps, long *pn, size_t *unconsumed) {
+pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps, long *pn, int64_t *unconsumed) {
 	struct archive_string as;
 	struct archive_string as;
 	int r;
 	int r;
 
 
@@ -2227,12 +2262,16 @@ pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps
 	r = read_bytes_to_string(a, &as, value_length, unconsumed);
 	r = read_bytes_to_string(a, &as, value_length, unconsumed);
 	if (r < ARCHIVE_OK) {
 	if (r < ARCHIVE_OK) {
 		archive_string_free(&as);
 		archive_string_free(&as);
+		*ps = 0;
+		*pn = 0;
 		return (r);
 		return (r);
 	}
 	}
 
 
 	pax_time(as.s, archive_strlen(&as), ps, pn);
 	pax_time(as.s, archive_strlen(&as), ps, pn);
 	archive_string_free(&as);
 	archive_string_free(&as);
-	if (*ps < 0 || *ps == INT64_MAX) {
+	if (*ps == INT64_MIN) {
+		*ps = 0;
+		*pn = 0;
 		return (ARCHIVE_WARN);
 		return (ARCHIVE_WARN);
 	}
 	}
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
@@ -2241,7 +2280,7 @@ pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps
 static int
 static int
 pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *result) {
 pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *result) {
 	struct archive_string as;
 	struct archive_string as;
-	size_t unconsumed = 0;
+	int64_t unconsumed = 0;
 	int r;
 	int r;
 
 
 	if (value_length > 64) {
 	if (value_length > 64) {
@@ -2255,6 +2294,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *
 	tar_flush_unconsumed(a, &unconsumed);
 	tar_flush_unconsumed(a, &unconsumed);
 	if (r < ARCHIVE_OK) {
 	if (r < ARCHIVE_OK) {
 		archive_string_free(&as);
 		archive_string_free(&as);
+		*result = 0;
 		return (r);
 		return (r);
 	}
 	}
 
 
@@ -2281,7 +2321,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *
  */
  */
 static int
 static int
 pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *entry,
 pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *entry,
-	      const char *key, size_t key_length, size_t value_length, size_t *unconsumed)
+	      const char *key, size_t key_length, size_t value_length, int64_t *unconsumed)
 {
 {
 	int64_t t;
 	int64_t t;
 	long n;
 	long n;
@@ -2365,8 +2405,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
 					tar->sparse_gnu_minor = 1;
 					tar->sparse_gnu_minor = 1;
 					if (value_length > sparse_map_limit) {
 					if (value_length > sparse_map_limit) {
 						archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 						archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-								  "Unreasonably large sparse map: %d > %d",
-								  (int)value_length, (int)sparse_map_limit);
+								  "Unreasonably large sparse map: %llu > %llu",
+								  (unsigned long long)value_length,
+								  (unsigned long long)sparse_map_limit);
 						err = ARCHIVE_FAILED;
 						err = ARCHIVE_FAILED;
 					} else {
 					} else {
 						p = __archive_read_ahead(a, value_length, &bytes_read);
 						p = __archive_read_ahead(a, value_length, &bytes_read);
@@ -2473,8 +2514,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
 				} else {
 				} else {
 					archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 					archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 							  "symlink type is very long"
 							  "symlink type is very long"
-							  "(longest recognized value is 4 bytes, this is %d)",
-							  (int)value_length);
+							  "(longest recognized value is 4 bytes, this is %llu)",
+							  (unsigned long long)value_length);
 					err = ARCHIVE_WARN;
 					err = ARCHIVE_WARN;
 				}
 				}
 				__archive_read_consume(a, value_length);
 				__archive_read_consume(a, value_length);
@@ -2510,8 +2551,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
 			if (value_length > xattr_limit) {
 			if (value_length > xattr_limit) {
 				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 						  "Ignoring unreasonably large security.selinux attribute:"
 						  "Ignoring unreasonably large security.selinux attribute:"
-						  " %d > %d",
-						  (int)value_length, (int)xattr_limit);
+						  " %llu > %llu",
+						  (unsigned long long)value_length,
+						  (unsigned long long)xattr_limit);
 				/* TODO: Should this be FAILED instead? */
 				/* TODO: Should this be FAILED instead? */
 				err = ARCHIVE_WARN;
 				err = ARCHIVE_WARN;
 			} else {
 			} else {
@@ -2628,8 +2670,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
 					}
 					}
 				} else {
 				} else {
 					archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 					archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-							  "Unreasonably large xattr: %d > %d",
-							  (int)value_length, (int)xattr_limit);
+							  "Unreasonably large xattr: %llu > %llu",
+							  (unsigned long long)value_length,
+							  (unsigned long long)xattr_limit);
 					err = ARCHIVE_WARN;
 					err = ARCHIVE_WARN;
 				}
 				}
 				__archive_read_consume(a, value_length);
 				__archive_read_consume(a, value_length);
@@ -2659,8 +2702,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
 					}
 					}
 				} else {
 				} else {
 					archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 					archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-							  "Unreasonably large sparse map: %d > %d",
-							  (int)value_length, (int)sparse_map_limit);
+							  "Unreasonably large sparse map: %llu > %llu",
+							  (unsigned long long)value_length,
+							  (unsigned long long)sparse_map_limit);
 					err = ARCHIVE_FAILED;
 					err = ARCHIVE_FAILED;
 				}
 				}
 				__archive_read_consume(a, value_length);
 				__archive_read_consume(a, value_length);
@@ -2729,8 +2773,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
 				}
 				}
 			} else {
 			} else {
 				archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
 				archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-						  "hdrcharset attribute is unreasonably large (%d bytes)",
-						  (int)value_length);
+						  "hdrcharset attribute is unreasonably large (%llu bytes)",
+						  (unsigned long long)value_length);
 				err = ARCHIVE_WARN;
 				err = ARCHIVE_WARN;
 			}
 			}
 			__archive_read_consume(a, value_length);
 			__archive_read_consume(a, value_length);
@@ -2817,7 +2861,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
 
 
 
 
 /*
 /*
- * parse a decimal time value, which may include a fractional portion
+ * Parse a decimal time value, which may include a fractional portion
+ *
+ * Sets ps to INT64_MIN on error.
  */
  */
 static void
 static void
 pax_time(const char *p, size_t length, int64_t *ps, long *pn)
 pax_time(const char *p, size_t length, int64_t *ps, long *pn)
@@ -2833,6 +2879,7 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
 
 
 	if (length <= 0) {
 	if (length <= 0) {
 		*ps = 0;
 		*ps = 0;
+		*pn = 0;
 		return;
 		return;
 	}
 	}
 	s = 0;
 	s = 0;
@@ -2846,8 +2893,9 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
 		digit = *p - '0';
 		digit = *p - '0';
 		if (s > limit ||
 		if (s > limit ||
 		    (s == limit && digit > last_digit_limit)) {
 		    (s == limit && digit > last_digit_limit)) {
-			s = INT64_MAX;
-			break;
+			*ps = INT64_MIN;
+			*pn = 0;
+			return;
 		}
 		}
 		s = (s * 10) + digit;
 		s = (s * 10) + digit;
 		++p;
 		++p;
@@ -2878,7 +2926,7 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
  */
  */
 static int
 static int
 header_gnutar(struct archive_read *a, struct tar *tar,
 header_gnutar(struct archive_read *a, struct tar *tar,
-    struct archive_entry *entry, const void *h, size_t *unconsumed)
+    struct archive_entry *entry, const void *h, int64_t *unconsumed)
 {
 {
 	const struct archive_entry_header_gnutar *header;
 	const struct archive_entry_header_gnutar *header;
 	int64_t t;
 	int64_t t;
@@ -3029,7 +3077,7 @@ gnu_clear_sparse_list(struct tar *tar)
 
 
 static int
 static int
 gnu_sparse_old_read(struct archive_read *a, struct tar *tar,
 gnu_sparse_old_read(struct archive_read *a, struct tar *tar,
-    const struct archive_entry_header_gnutar *header, size_t *unconsumed)
+    const struct archive_entry_header_gnutar *header, int64_t *unconsumed)
 {
 {
 	ssize_t bytes_read;
 	ssize_t bytes_read;
 	const void *data;
 	const void *data;
@@ -3163,7 +3211,7 @@ gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p, size
  */
  */
 static int64_t
 static int64_t
 gnu_sparse_10_atol(struct archive_read *a, struct tar *tar,
 gnu_sparse_10_atol(struct archive_read *a, struct tar *tar,
-    int64_t *remaining, size_t *unconsumed)
+    int64_t *remaining, int64_t *unconsumed)
 {
 {
 	int64_t l, limit, last_digit_limit;
 	int64_t l, limit, last_digit_limit;
 	const char *p;
 	const char *p;
@@ -3208,12 +3256,10 @@ gnu_sparse_10_atol(struct archive_read *a, struct tar *tar,
  * Returns length (in bytes) of the sparse data description
  * Returns length (in bytes) of the sparse data description
  * that was read.
  * that was read.
  */
  */
-static ssize_t
-gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
+static int64_t
+gnu_sparse_10_read(struct archive_read *a, struct tar *tar, int64_t *unconsumed)
 {
 {
-	ssize_t bytes_read;
-	int entries;
-	int64_t offset, size, to_skip, remaining;
+	int64_t bytes_read, entries, offset, size, to_skip, remaining;
 
 
 	/* Clear out the existing sparse list. */
 	/* Clear out the existing sparse list. */
 	gnu_clear_sparse_list(tar);
 	gnu_clear_sparse_list(tar);
@@ -3221,7 +3267,7 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
 	remaining = tar->entry_bytes_remaining;
 	remaining = tar->entry_bytes_remaining;
 
 
 	/* Parse entries. */
 	/* Parse entries. */
-	entries = (int)gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
+	entries = gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
 	if (entries < 0)
 	if (entries < 0)
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	/* Parse the individual entries. */
 	/* Parse the individual entries. */
@@ -3239,14 +3285,14 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
 	}
 	}
 	/* Skip rest of block... */
 	/* Skip rest of block... */
 	tar_flush_unconsumed(a, unconsumed);
 	tar_flush_unconsumed(a, unconsumed);
-	bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining);
+	bytes_read = tar->entry_bytes_remaining - remaining;
 	to_skip = 0x1ff & -bytes_read;
 	to_skip = 0x1ff & -bytes_read;
 	/* Fail if tar->entry_bytes_remaing would get negative */
 	/* Fail if tar->entry_bytes_remaing would get negative */
 	if (to_skip > remaining)
 	if (to_skip > remaining)
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	if (to_skip != __archive_read_consume(a, to_skip))
 	if (to_skip != __archive_read_consume(a, to_skip))
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
-	return ((ssize_t)(bytes_read + to_skip));
+	return (bytes_read + to_skip);
 }
 }
 
 
 /*
 /*
@@ -3456,7 +3502,7 @@ tar_atol256(const char *_p, size_t char_cnt)
  */
  */
 static ssize_t
 static ssize_t
 readline(struct archive_read *a, struct tar *tar, const char **start,
 readline(struct archive_read *a, struct tar *tar, const char **start,
-    ssize_t limit, size_t *unconsumed)
+    ssize_t limit, int64_t *unconsumed)
 {
 {
 	ssize_t bytes_read;
 	ssize_t bytes_read;
 	ssize_t total_size = 0;
 	ssize_t total_size = 0;

+ 5 - 2
Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c

@@ -386,7 +386,8 @@ start_over:
 	case LAST_WT:
 	case LAST_WT:
 	default:
 	default:
 		/* consume the content and start over */
 		/* consume the content and start over */
-		_warc_skip(a);
+		if (_warc_skip(a) < 0)
+			return (ARCHIVE_FATAL);
 		goto start_over;
 		goto start_over;
 	}
 	}
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
@@ -439,7 +440,9 @@ _warc_skip(struct archive_read *a)
 {
 {
 	struct warc_s *w = a->format->data;
 	struct warc_s *w = a->format->data;
 
 
-	__archive_read_consume(a, w->cntlen + 4U/*\r\n\r\n separator*/);
+	if (__archive_read_consume(a, w->cntlen) < 0 ||
+	    __archive_read_consume(a, 4U/*\r\n\r\n separator*/) < 0)
+		return (ARCHIVE_FATAL);
 	w->cntlen = 0U;
 	w->cntlen = 0U;
 	w->cntoff = 0U;
 	w->cntoff = 0U;
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);

+ 336 - 7
Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c

@@ -36,6 +36,10 @@
 #include <bsdxml.h>
 #include <bsdxml.h>
 #elif HAVE_EXPAT_H
 #elif HAVE_EXPAT_H
 #include <cm3p/expat.h>
 #include <cm3p/expat.h>
+#elif HAVE_XMLLITE_H
+#include <objidl.h>
+#include <initguid.h>
+#include <xmllite.h>
 #endif
 #endif
 #ifdef HAVE_BZLIB_H
 #ifdef HAVE_BZLIB_H
 #include <cm3p/bzlib.h>
 #include <cm3p/bzlib.h>
@@ -56,12 +60,13 @@
 #include "archive_read_private.h"
 #include "archive_read_private.h"
 
 
 #if (!defined(HAVE_LIBXML_XMLREADER_H) && \
 #if (!defined(HAVE_LIBXML_XMLREADER_H) && \
-     !defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H)) ||\
+     !defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H) && \
+     !defined(HAVE_XMLLITE_H)) ||\
 	!defined(HAVE_ZLIB_H) || \
 	!defined(HAVE_ZLIB_H) || \
 	!defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
 	!defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
 /*
 /*
  * xar needs several external libraries.
  * xar needs several external libraries.
- *   o libxml2 or expat --- XML parser
+ *   o libxml2, expat or (Windows only) xmllite --- XML parser
  *   o openssl or MD5/SHA1 hash function
  *   o openssl or MD5/SHA1 hash function
  *   o zlib
  *   o zlib
  *   o bzlib2 (option)
  *   o bzlib2 (option)
@@ -438,6 +443,8 @@ static void	expat_start_cb(void *, const XML_Char *, const XML_Char **);
 static void	expat_end_cb(void *, const XML_Char *);
 static void	expat_end_cb(void *, const XML_Char *);
 static void	expat_data_cb(void *, const XML_Char *, int);
 static void	expat_data_cb(void *, const XML_Char *, int);
 static int	expat_read_toc(struct archive_read *);
 static int	expat_read_toc(struct archive_read *);
+#elif defined(HAVE_XMLLITE_H)
+static int	xmllite_read_toc(struct archive_read *);
 #endif
 #endif
 
 
 int
 int
@@ -589,6 +596,8 @@ read_toc(struct archive_read *a)
 	r = xml2_read_toc(a);
 	r = xml2_read_toc(a);
 #elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H)
 #elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H)
 	r = expat_read_toc(a);
 	r = expat_read_toc(a);
+#elif defined(HAVE_XMLLITE_H)
+	r = xmllite_read_toc(a);
 #endif
 #endif
 	if (r != ARCHIVE_OK)
 	if (r != ARCHIVE_OK)
 		return (r);
 		return (r);
@@ -1110,17 +1119,17 @@ atohex(unsigned char *b, size_t bsize, const char *p, size_t psize)
 	while (bsize && psize > 1) {
 	while (bsize && psize > 1) {
 		unsigned char x;
 		unsigned char x;
 
 
-		if (p[0] >= 'a' && p[0] <= 'z')
+		if (p[0] >= 'a' && p[0] <= 'f')
 			x = (p[0] - 'a' + 0x0a) << 4;
 			x = (p[0] - 'a' + 0x0a) << 4;
-		else if (p[0] >= 'A' && p[0] <= 'Z')
+		else if (p[0] >= 'A' && p[0] <= 'F')
 			x = (p[0] - 'A' + 0x0a) << 4;
 			x = (p[0] - 'A' + 0x0a) << 4;
 		else if (p[0] >= '0' && p[0] <= '9')
 		else if (p[0] >= '0' && p[0] <= '9')
 			x = (p[0] - '0') << 4;
 			x = (p[0] - '0') << 4;
 		else
 		else
 			return (-1);
 			return (-1);
-		if (p[1] >= 'a' && p[1] <= 'z')
+		if (p[1] >= 'a' && p[1] <= 'f')
 			x |= p[1] - 'a' + 0x0a;
 			x |= p[1] - 'a' + 0x0a;
-		else if (p[1] >= 'A' && p[1] <= 'Z')
+		else if (p[1] >= 'A' && p[1] <= 'F')
 			x |= p[1] - 'A' + 0x0a;
 			x |= p[1] - 'A' + 0x0a;
 		else if (p[1] >= '0' && p[1] <= '9')
 		else if (p[1] >= '0' && p[1] <= '9')
 			x |= p[1] - '0';
 			x |= p[1] - '0';
@@ -3333,6 +3342,326 @@ expat_read_toc(struct archive_read *a)
 	XML_ParserFree(parser);
 	XML_ParserFree(parser);
 	return (ud.state);
 	return (ud.state);
 }
 }
-#endif /* defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) */
+
+#elif defined(HAVE_XMLLITE_H)
+
+struct ArchiveStreamAdapter {
+	const ISequentialStreamVtbl *lpVtbl; /* see asaStaticVtable */
+	struct archive_read *a;
+};
+
+static HRESULT STDMETHODCALLTYPE
+asaQueryInterface(ISequentialStream *this, REFIID riid, void **ppv)
+{
+	if (!IsEqualIID(riid, &IID_ISequentialStream)) {
+		*ppv = NULL;
+		return E_NOINTERFACE;
+	}
+	*ppv = this;
+	return S_OK;
+}
+
+/*
+ * We can dispense with reference counting as we tightly manage the lifetime
+ * of an ArchiveStreamAdapter.
+ */
+static ULONG STDMETHODCALLTYPE
+asaAddRef(ISequentialStream *this)
+{
+	(void)this; /* UNUSED */
+	return ULONG_MAX;
+}
+
+static ULONG STDMETHODCALLTYPE
+asaRelease(ISequentialStream *this)
+{
+	(void)this; /* UNUSED */
+	return ULONG_MAX;
+}
+
+static HRESULT STDMETHODCALLTYPE
+asaRead(ISequentialStream *this, void *pv, ULONG cb, ULONG *pcbRead)
+{
+	struct ArchiveStreamAdapter *asa = (struct ArchiveStreamAdapter *)this;
+	struct archive_read *a;
+	struct xar *xar;
+	const void *d = pv;
+	size_t outbytes = cb;
+	size_t used = 0;
+	int r;
+
+	a = asa->a;
+	xar = (struct xar *)(a->format->data);
+
+	*pcbRead = 0;
+
+	if (xar->toc_remaining <= 0)
+		return cb != 0 ? S_FALSE : S_OK;
+
+	r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining);
+	if (r != ARCHIVE_OK)
+		return E_FAIL;
+	__archive_read_consume(a, used);
+	xar->toc_remaining -= used;
+	xar->offset += used;
+	xar->toc_total += outbytes;
+	PRINT_TOC(pv, outbytes);
+
+	*pcbRead = (ULONG)outbytes;
+	return outbytes < cb ? S_FALSE : S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE
+asaWrite(ISequentialStream *this, const void *pv, ULONG cb, ULONG *pcbWritten)
+{
+	(void)this; /* UNUSED */
+	(void)pv; /* UNUSED */
+	(void)cb; /* UNUSED */
+	if (!pcbWritten) return E_INVALIDARG;
+	*pcbWritten = 0;
+	return E_NOTIMPL;
+}
+
+static const ISequentialStreamVtbl asaStaticVtable = {
+	.QueryInterface = asaQueryInterface,
+	.AddRef = asaAddRef,
+	.Release = asaRelease,
+	.Read = asaRead,
+	.Write = asaWrite,
+};
+
+static int
+xmllite_create_stream_adapter(struct archive_read *a,
+    struct ArchiveStreamAdapter **pasa)
+{
+	struct ArchiveStreamAdapter *asa =
+	    calloc(1, sizeof(struct ArchiveStreamAdapter));
+	if (!asa) {
+		archive_set_error(&(a->archive), ENOMEM, "Out of memory");
+		return (ARCHIVE_FATAL);
+	}
+	asa->lpVtbl = &asaStaticVtable;
+	asa->a = a;
+	*pasa = asa;
+	return (ARCHIVE_OK);
+}
+
+typedef HRESULT(STDMETHODCALLTYPE *xmllite_wstr_func)(IXmlReader *, LPCWSTR *,
+    UINT *);
+
+/*
+ * Returns an narrow-char archive_string in *as after calling
+ * the wide-char COM API callee() on the XmlReader reader.
+ * Sets an appropriate error on the archive if it fails.
+ */
+static int
+xmllite_call_return_as(struct archive_read *a, struct archive_string *as,
+    IXmlReader *reader, xmllite_wstr_func callee)
+{
+	LPCWSTR wcs;
+	UINT wlen;
+
+	if (FAILED(callee(reader, &wcs, &wlen))) {
+		archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
+		    "Failed to read XML data");
+		return (ARCHIVE_FATAL);
+	}
+
+	archive_string_init(as);
+	if (archive_string_append_from_wcs(as, wcs, (size_t)wlen) < 0) {
+		archive_string_free(as);
+		archive_set_error(&(a->archive), ENOMEM, "Out of memory");
+		return (ARCHIVE_FATAL);
+	}
+
+	return (ARCHIVE_OK);
+}
+
+static char *
+xmllite_call_return_mbs(struct archive_read *a, IXmlReader *reader,
+    xmllite_wstr_func callee)
+{
+	char *ret;
+	struct archive_string as;
+
+	if (xmllite_call_return_as(a, &as, reader, callee) < 0) {
+		return NULL;
+	}
+
+	ret = strdup(as.s);
+	archive_string_free(&as);
+	if (ret == NULL) {
+		archive_set_error(&(a->archive), ENOMEM, "Out of memory");
+		return NULL;
+	}
+	return ret;
+}
+
+static int
+xmllite_xmlattr_setup(struct archive_read *a,
+    struct xmlattr_list *list, IXmlReader *reader)
+{
+	struct xmlattr *attr;
+	HRESULT hr;
+
+	list->first = NULL;
+	list->last = &(list->first);
+	hr = reader->lpVtbl->MoveToFirstAttribute(reader);
+	/* Contrary to other checks, we're not using SUCCEEDED/FAILED
+	 * because MoveToNextAttribute returns *S_FALSE* (success!)
+	 * when it runs out of attributes.
+	 */
+	while (hr == S_OK) {
+		/* Attributes implied as being default by the DTD are ignored */
+		if (reader->lpVtbl->IsDefault(reader))
+			continue;
+
+		attr = malloc(sizeof*(attr));
+		if (attr == NULL) {
+			archive_set_error(&(a->archive), ENOMEM,
+			    "Out of memory");
+			return (ARCHIVE_FATAL);
+		}
+
+		attr->name = xmllite_call_return_mbs(a, reader,
+		    reader->lpVtbl->GetLocalName);
+		if (attr->name == NULL) {
+			free(attr);
+			/* xmllite_call_return_mbs sets an appropriate error */
+			return (ARCHIVE_FATAL);
+		}
+
+		attr->value = xmllite_call_return_mbs(a, reader,
+		    reader->lpVtbl->GetValue);
+		if (attr->value == NULL) {
+			free(attr->name);
+			free(attr);
+			/* xmllite_call_return_mbs sets an appropriate error */
+			return (ARCHIVE_FATAL);
+		}
+
+		attr->next = NULL;
+		*list->last = attr;
+		list->last = &(attr->next);
+		hr = reader->lpVtbl->MoveToNextAttribute(reader);
+	}
+
+	if (FAILED(hr)) {
+		archive_set_error(&(a->archive), ARCHIVE_ERRNO_FILE_FORMAT,
+		    "Failed to parse XML document");
+		return (ARCHIVE_FAILED);
+	}
+
+	return (ARCHIVE_OK);
+}
+
+static int
+xmllite_read_toc(struct archive_read *a)
+{
+	struct ArchiveStreamAdapter *asa = NULL;
+	char *name;
+	struct archive_string as;
+	BOOL empty;
+	XmlNodeType type;
+	struct xmlattr_list list;
+	IXmlReader *reader = NULL;
+	int r = ARCHIVE_OK;
+
+	if ((r = xmllite_create_stream_adapter(a, &asa)) < 0) {
+		goto out;
+	}
+
+	if (FAILED(CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL))) {
+		r = ARCHIVE_FATAL;
+		goto out;
+	}
+
+	if (FAILED(reader->lpVtbl->SetInput(reader, (IUnknown *)asa))) {
+		archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
+		    "Failed to prepare XML stream");
+		r = ARCHIVE_FATAL;
+		goto out;
+	}
+
+	while (!reader->lpVtbl->IsEOF(reader)) {
+		if (FAILED(reader->lpVtbl->Read(reader, &type))) {
+			archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
+			    "Failed to read XML stream");
+			r = ARCHIVE_FATAL;
+			goto out;
+		}
+
+		switch (type) {
+		case XmlNodeType_Element:
+			empty = reader->lpVtbl->IsEmptyElement(reader);
+
+			name = xmllite_call_return_mbs(a, reader,
+			    reader->lpVtbl->GetLocalName);
+			if (name == NULL) {
+				/* xmllite_call_return_mbs sets an appropriate error */
+				r = ARCHIVE_FATAL;
+				goto out;
+			}
+
+			r = xmllite_xmlattr_setup(a, &list, reader);
+			if (r == ARCHIVE_OK) {
+				r = xml_start(a, name, &list);
+			}
+			xmlattr_cleanup(&list);
+			if (r == ARCHIVE_OK && empty) {
+				xml_end(a, name);
+			}
+
+			free(name);
+			if (r != ARCHIVE_OK) {
+				goto out;
+			}
+
+			break;
+		case XmlNodeType_EndElement:
+			name = xmllite_call_return_mbs(a, reader,
+			    reader->lpVtbl->GetLocalName);
+			if (name == NULL) {
+				/* xmllite_call_return_mbs sets an appropriate error */
+				r = ARCHIVE_FATAL;
+				goto out;
+			}
+
+			xml_end(a, name);
+			free(name);
+			break;
+		case XmlNodeType_Text:
+			r = xmllite_call_return_as(a, &as, reader,
+			    reader->lpVtbl->GetValue);
+			if (r != ARCHIVE_OK) {
+				/* xmllite_call_return_as sets an appropriate error */
+				goto out;
+			}
+
+			xml_data(a, as.s, (int)archive_strlen(&as));
+			archive_string_free(&as);
+
+		case XmlNodeType_None:
+		case XmlNodeType_Attribute:
+		case XmlNodeType_CDATA:
+		case XmlNodeType_ProcessingInstruction:
+		case XmlNodeType_Comment:
+		case XmlNodeType_DocumentType:
+		case XmlNodeType_Whitespace:
+		case XmlNodeType_XmlDeclaration:
+		default:
+			break;
+		}
+	}
+
+out:
+	if (reader)
+		reader->lpVtbl->Release(reader);
+
+	free(asa);
+
+	return r;
+}
+#endif /* defined(XMLLITE) */
 
 
 #endif /* Support xar format */
 #endif /* Support xar format */

+ 3 - 23
Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c

@@ -71,6 +71,7 @@
 #include "archive_private.h"
 #include "archive_private.h"
 #include "archive_rb.h"
 #include "archive_rb.h"
 #include "archive_read_private.h"
 #include "archive_read_private.h"
+#include "archive_time_private.h"
 #include "archive_ppmd8_private.h"
 #include "archive_ppmd8_private.h"
 
 
 #ifndef HAVE_ZLIB_H
 #ifndef HAVE_ZLIB_H
@@ -465,27 +466,6 @@ compression_name(const int compression)
 	return "??";
 	return "??";
 }
 }
 
 
-/* Convert an MSDOS-style date/time into Unix-style time. */
-static time_t
-zip_time(const char *p)
-{
-	int msTime, msDate;
-	struct tm ts;
-
-	msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]);
-	msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]);
-
-	memset(&ts, 0, sizeof(ts));
-	ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
-	ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
-	ts.tm_mday = msDate & 0x1f; /* Day of month. */
-	ts.tm_hour = (msTime >> 11) & 0x1f;
-	ts.tm_min = (msTime >> 5) & 0x3f;
-	ts.tm_sec = (msTime << 1) & 0x3e;
-	ts.tm_isdst = -1;
-	return mktime(&ts);
-}
-
 /*
 /*
  * The extra data is stored as a list of
  * The extra data is stored as a list of
  *	id1+size1+data1 + id2+size2+data2 ...
  *	id1+size1+data1 + id2+size2+data2 ...
@@ -978,7 +958,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
 	}
 	}
 	zip->init_decryption = (zip_entry->zip_flags & ZIP_ENCRYPTED);
 	zip->init_decryption = (zip_entry->zip_flags & ZIP_ENCRYPTED);
 	zip_entry->compression = (char)archive_le16dec(p + 8);
 	zip_entry->compression = (char)archive_le16dec(p + 8);
-	zip_entry->mtime = zip_time(p + 10);
+	zip_entry->mtime = dos_to_unix(archive_le32dec(p + 10));
 	zip_entry->crc32 = archive_le32dec(p + 14);
 	zip_entry->crc32 = archive_le32dec(p + 14);
 	if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
 	if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
 		zip_entry->decdat = p[11];
 		zip_entry->decdat = p[11];
@@ -3986,7 +3966,7 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
 			zip->has_encrypted_entries = 1;
 			zip->has_encrypted_entries = 1;
 		}
 		}
 		zip_entry->compression = (char)archive_le16dec(p + 10);
 		zip_entry->compression = (char)archive_le16dec(p + 10);
-		zip_entry->mtime = zip_time(p + 12);
+		zip_entry->mtime = dos_to_unix(archive_le32dec(p + 12));
 		zip_entry->crc32 = archive_le32dec(p + 16);
 		zip_entry->crc32 = archive_le32dec(p + 16);
 		if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
 		if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
 			zip_entry->decdat = p[13];
 			zip_entry->decdat = p[13];

+ 61 - 34
Utilities/cmlibarchive/libarchive/archive_string.c

@@ -472,7 +472,8 @@ static int
 archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
 archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
     const char *s, size_t length, struct archive_string_conv *sc)
     const char *s, size_t length, struct archive_string_conv *sc)
 {
 {
-	int count, ret = 0;
+	int ret = 0;
+	size_t count;
 	UINT from_cp;
 	UINT from_cp;
 
 
 	if (sc != NULL)
 	if (sc != NULL)
@@ -494,7 +495,7 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
 		ws = dest->s + dest->length;
 		ws = dest->s + dest->length;
 		mp = (const unsigned char *)s;
 		mp = (const unsigned char *)s;
 		count = 0;
 		count = 0;
-		while (count < (int)length && *mp) {
+		while (count < length && *mp) {
 			*ws++ = (wchar_t)*mp++;
 			*ws++ = (wchar_t)*mp++;
 			count++;
 			count++;
 		}
 		}
@@ -517,13 +518,13 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
 			 *  UTF-16BE/LE NFD ===> UTF-16 NFC
 			 *  UTF-16BE/LE NFD ===> UTF-16 NFC
 			 *  UTF-16BE/LE NFC ===> UTF-16 NFD
 			 *  UTF-16BE/LE NFC ===> UTF-16 NFD
 			 */
 			 */
-			count = (int)utf16nbytes(s, length);
+			count = utf16nbytes(s, length);
 		} else {
 		} else {
 			/*
 			/*
 			 *  UTF-8 NFD ===> UTF-16 NFC
 			 *  UTF-8 NFD ===> UTF-16 NFC
 			 *  UTF-8 NFC ===> UTF-16 NFD
 			 *  UTF-8 NFC ===> UTF-16 NFD
 			 */
 			 */
-			count = (int)mbsnbytes(s, length);
+			count = mbsnbytes(s, length);
 		}
 		}
 		u16.s = (char *)dest->s;
 		u16.s = (char *)dest->s;
 		u16.length = dest->length << 1;
 		u16.length = dest->length << 1;
@@ -538,7 +539,7 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
 		sc->flag = saved_flag;/* restore the saved flag. */
 		sc->flag = saved_flag;/* restore the saved flag. */
 		return (ret);
 		return (ret);
 	} else if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) {
 	} else if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) {
-		count = (int)utf16nbytes(s, length);
+		count = utf16nbytes(s, length);
 		count >>= 1; /* to be WCS length */
 		count >>= 1; /* to be WCS length */
 		/* Allocate memory for WCS. */
 		/* Allocate memory for WCS. */
 		if (NULL == archive_wstring_ensure(dest,
 		if (NULL == archive_wstring_ensure(dest,
@@ -547,14 +548,14 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
 		wmemcpy(dest->s + dest->length, (const wchar_t *)s, count);
 		wmemcpy(dest->s + dest->length, (const wchar_t *)s, count);
 		if ((sc->flag & SCONV_FROM_UTF16BE) && !IS_BIG_ENDIAN) {
 		if ((sc->flag & SCONV_FROM_UTF16BE) && !IS_BIG_ENDIAN) {
 			uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
 			uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
-			int b;
+			size_t b;
 			for (b = 0; b < count; b++) {
 			for (b = 0; b < count; b++) {
 				uint16_t val = archive_le16dec(u16+b);
 				uint16_t val = archive_le16dec(u16+b);
 				archive_be16enc(u16+b, val);
 				archive_be16enc(u16+b, val);
 			}
 			}
 		} else if ((sc->flag & SCONV_FROM_UTF16LE) && IS_BIG_ENDIAN) {
 		} else if ((sc->flag & SCONV_FROM_UTF16LE) && IS_BIG_ENDIAN) {
 			uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
 			uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
-			int b;
+			size_t b;
 			for (b = 0; b < count; b++) {
 			for (b = 0; b < count; b++) {
 				uint16_t val = archive_be16dec(u16+b);
 				uint16_t val = archive_be16dec(u16+b);
 				archive_le16enc(u16+b, val);
 				archive_le16enc(u16+b, val);
@@ -578,21 +579,28 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
 
 
 		buffsize = dest->length + length + 1;
 		buffsize = dest->length + length + 1;
 		do {
 		do {
+			int r;
+
+			/* MultiByteToWideChar is limited to int. */
+			if (length > (size_t)INT_MAX ||
+				(dest->buffer_length >> 1) > (size_t)INT_MAX)
+				return (-1);
 			/* Allocate memory for WCS. */
 			/* Allocate memory for WCS. */
 			if (NULL == archive_wstring_ensure(dest, buffsize))
 			if (NULL == archive_wstring_ensure(dest, buffsize))
 				return (-1);
 				return (-1);
 			/* Convert MBS to WCS. */
 			/* Convert MBS to WCS. */
-			count = MultiByteToWideChar(from_cp,
+			r = MultiByteToWideChar(from_cp,
 			    mbflag, s, (int)length, dest->s + dest->length,
 			    mbflag, s, (int)length, dest->s + dest->length,
 			    (int)(dest->buffer_length >> 1) -1);
 			    (int)(dest->buffer_length >> 1) -1);
-			if (count == 0 &&
+			if (r == 0 &&
 			    GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 			    GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 				/* Expand the WCS buffer. */
 				/* Expand the WCS buffer. */
 				buffsize = dest->buffer_length << 1;
 				buffsize = dest->buffer_length << 1;
 				continue;
 				continue;
 			}
 			}
-			if (count == 0 && length != 0)
+			if (r == 0 && length != 0)
 				ret = -1;
 				ret = -1;
+			count = (size_t)r;
 			break;
 			break;
 		} while (1);
 		} while (1);
 	}
 	}
@@ -701,9 +709,9 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
     const wchar_t *ws, size_t len, struct archive_string_conv *sc)
     const wchar_t *ws, size_t len, struct archive_string_conv *sc)
 {
 {
 	BOOL defchar_used, *dp;
 	BOOL defchar_used, *dp;
-	int count, ret = 0;
+	int ret = 0;
 	UINT to_cp;
 	UINT to_cp;
-	int wslen = (int)len;
+	size_t count, wslen = len;
 
 
 	if (sc != NULL)
 	if (sc != NULL)
 		to_cp = sc->to_cp;
 		to_cp = sc->to_cp;
@@ -742,13 +750,13 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
 		count = 0;
 		count = 0;
 		defchar_used = 0;
 		defchar_used = 0;
 		if (sc->flag & SCONV_TO_UTF16BE) {
 		if (sc->flag & SCONV_TO_UTF16BE) {
-			while (count < (int)len && *ws) {
+			while (count < len && *ws) {
 				archive_be16enc(u16+count, *ws);
 				archive_be16enc(u16+count, *ws);
 				ws++;
 				ws++;
 				count++;
 				count++;
 			}
 			}
 		} else {
 		} else {
-			while (count < (int)len && *ws) {
+			while (count < len && *ws) {
 				archive_le16enc(u16+count, *ws);
 				archive_le16enc(u16+count, *ws);
 				ws++;
 				ws++;
 				count++;
 				count++;
@@ -761,15 +769,21 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
 		    archive_string_ensure(as, as->length + len * 2 + 1))
 		    archive_string_ensure(as, as->length + len * 2 + 1))
 			return (-1);
 			return (-1);
 		do {
 		do {
+			int r;
+
 			defchar_used = 0;
 			defchar_used = 0;
 			if (to_cp == CP_UTF8 || sc == NULL)
 			if (to_cp == CP_UTF8 || sc == NULL)
 				dp = NULL;
 				dp = NULL;
 			else
 			else
 				dp = &defchar_used;
 				dp = &defchar_used;
-			count = WideCharToMultiByte(to_cp, 0, ws, wslen,
+			/* WideCharToMultiByte is limited to int. */
+			if (as->buffer_length - as->length - 1 > (size_t)INT_MAX ||
+				wslen > (size_t)INT_MAX)
+				return (-1);
+			r = WideCharToMultiByte(to_cp, 0, ws, (int)wslen,
 			    as->s + as->length,
 			    as->s + as->length,
-			    (int)as->buffer_length - (int)as->length - 1, NULL, dp);
-			if (count == 0 &&
+			    (int)(as->buffer_length - as->length - 1), NULL, dp);
+			if (r == 0 &&
 			    GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 			    GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 				/* Expand the MBS buffer and retry. */
 				/* Expand the MBS buffer and retry. */
 				if (NULL == archive_string_ensure(as,
 				if (NULL == archive_string_ensure(as,
@@ -777,8 +791,9 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
 					return (-1);
 					return (-1);
 				continue;
 				continue;
 			}
 			}
-			if (count == 0)
+			if (r == 0)
 				ret = -1;
 				ret = -1;
+			count = (size_t)r;
 			break;
 			break;
 		} while (1);
 		} while (1);
 	}
 	}
@@ -2054,7 +2069,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
 	char *outp;
 	char *outp;
 	size_t avail, bs;
 	size_t avail, bs;
 	int return_value = 0; /* success */
 	int return_value = 0; /* success */
-	int to_size, from_size;
+	size_t to_size, from_size;
 
 
 	if (sc->flag & SCONV_TO_UTF16)
 	if (sc->flag & SCONV_TO_UTF16)
 		to_size = 2;
 		to_size = 2;
@@ -2073,7 +2088,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
 	remaining = length;
 	remaining = length;
 	outp = as->s + as->length;
 	outp = as->s + as->length;
 	avail = as->buffer_length - as->length - to_size;
 	avail = as->buffer_length - as->length - to_size;
-	while (remaining >= (size_t)from_size) {
+	while (remaining >= from_size) {
 		size_t result = iconv(cd, &itp, &remaining, &outp, &avail);
 		size_t result = iconv(cd, &itp, &remaining, &outp, &avail);
 
 
 		if (result != (size_t)-1)
 		if (result != (size_t)-1)
@@ -2196,6 +2211,8 @@ invalid_mbs(const void *_p, size_t n, struct archive_string_conv *sc)
 	if (codepage != CP_UTF8)
 	if (codepage != CP_UTF8)
 		mbflag |= MB_PRECOMPOSED;
 		mbflag |= MB_PRECOMPOSED;
 
 
+	if (n > (size_t)INT_MAX)
+		return (-1); /* Invalid */
 	if (MultiByteToWideChar(codepage, mbflag, p, (int)n, NULL, 0) == 0)
 	if (MultiByteToWideChar(codepage, mbflag, p, (int)n, NULL, 0) == 0)
 		return (-1); /* Invalid */
 		return (-1); /* Invalid */
 	return (0); /* Okay */
 	return (0); /* Okay */
@@ -2349,7 +2366,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
 	cnt = utf8_count[ch];
 	cnt = utf8_count[ch];
 
 
 	/* Invalid sequence or there are not plenty bytes. */
 	/* Invalid sequence or there are not plenty bytes. */
-	if ((int)n < cnt) {
+	if (n < (size_t)cnt) {
 		cnt = (int)n;
 		cnt = (int)n;
 		for (i = 1; i < cnt; i++) {
 		for (i = 1; i < cnt; i++) {
 			if ((s[i] & 0xc0) != 0x80) {
 			if ((s[i] & 0xc0) != 0x80) {
@@ -2418,7 +2435,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
 			cnt = 6;
 			cnt = 6;
 		else
 		else
 			cnt = 1;
 			cnt = 1;
-		if ((int)n < cnt)
+		if (n < (size_t)cnt)
 			cnt = (int)n;
 			cnt = (int)n;
 		for (i = 1; i < cnt; i++) {
 		for (i = 1; i < cnt; i++) {
 			if ((s[i] & 0xc0) != 0x80) {
 			if ((s[i] & 0xc0) != 0x80) {
@@ -2634,7 +2651,7 @@ unicode_to_utf16be(char *p, size_t remaining, uint32_t uc)
 	} else {
 	} else {
 		if (remaining < 2)
 		if (remaining < 2)
 			return (0);
 			return (0);
-		archive_be16enc(utf16, uc);
+		archive_be16enc(utf16, (uint16_t)uc);
 		return (2);
 		return (2);
 	}
 	}
 }
 }
@@ -2656,7 +2673,7 @@ unicode_to_utf16le(char *p, size_t remaining, uint32_t uc)
 	} else {
 	} else {
 		if (remaining < 2)
 		if (remaining < 2)
 			return (0);
 			return (0);
-		archive_le16enc(utf16, uc);
+		archive_le16enc(utf16, (uint16_t)uc);
 		return (2);
 		return (2);
 	}
 	}
 }
 }
@@ -3521,10 +3538,9 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
 {
 {
 	struct archive_string tmp;
 	struct archive_string tmp;
 	const char *u16;
 	const char *u16;
-	int ll;
 	BOOL defchar;
 	BOOL defchar;
 	char *mbs;
 	char *mbs;
-	size_t mbs_size, b;
+	size_t mbs_size, b, ll;
 	int ret = 0;
 	int ret = 0;
 
 
 	bytes &= ~1;
 	bytes &= ~1;
@@ -3588,18 +3604,24 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
 	}
 	}
 
 
 	do {
 	do {
+		int r;
 		defchar = 0;
 		defchar = 0;
-		ll = WideCharToMultiByte(sc->to_cp, 0,
+		/* WideCharToMultiByte is limited to int. */
+		if (bytes > (size_t)INT_MAX || mbs_size > (size_t)INT_MAX)
+			return (-1);
+		r = WideCharToMultiByte(sc->to_cp, 0,
 		    (LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
 		    (LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
 			NULL, &defchar);
 			NULL, &defchar);
 		/* Exit loop if we succeeded */
 		/* Exit loop if we succeeded */
-		if (ll != 0 ||
+		if (r != 0 ||
 		    GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
 		    GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+			ll = (size_t)r;
 			break;
 			break;
 		}
 		}
 		/* Else expand buffer and loop to try again. */
 		/* Else expand buffer and loop to try again. */
-		ll = WideCharToMultiByte(sc->to_cp, 0,
+		r = WideCharToMultiByte(sc->to_cp, 0,
 		    (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
 		    (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
+		ll = (size_t)r;
 		if (archive_string_ensure(as, ll +1) == NULL)
 		if (archive_string_ensure(as, ll +1) == NULL)
 			return (-1);
 			return (-1);
 		mbs = as->s + as->length;
 		mbs = as->s + as->length;
@@ -3665,16 +3687,21 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
 		return (0);
 		return (0);
 	}
 	}
 	do {
 	do {
-		count = MultiByteToWideChar(sc->from_cp,
+		int r;
+		if (length > (size_t)INT_MAX || (avail >> 1) > (size_t)INT_MAX)
+			return (-1);
+		r = MultiByteToWideChar(sc->from_cp,
 		    MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
 		    MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
 		/* Exit loop if we succeeded */
 		/* Exit loop if we succeeded */
-		if (count != 0 ||
+		if (r != 0 ||
 		    GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
 		    GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+			count = (size_t)r;
 			break;
 			break;
 		}
 		}
 		/* Expand buffer and try again */
 		/* Expand buffer and try again */
-		count = MultiByteToWideChar(sc->from_cp,
+		r = MultiByteToWideChar(sc->from_cp,
 		    MB_PRECOMPOSED, s, (int)length, NULL, 0);
 		    MB_PRECOMPOSED, s, (int)length, NULL, 0);
+		count = (size_t)r;
 		if (archive_string_ensure(as16, (count +1) * 2)
 		if (archive_string_ensure(as16, (count +1) * 2)
 		    == NULL)
 		    == NULL)
 			return (-1);
 			return (-1);
@@ -3825,9 +3852,9 @@ best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p,
 			ret = -1;
 			ret = -1;
 		}
 		}
 		if (bigendian)
 		if (bigendian)
-			archive_be16enc(utf16, c);
+			archive_be16enc(utf16, (uint16_t)c);
 		else
 		else
-			archive_le16enc(utf16, c);
+			archive_le16enc(utf16, (uint16_t)c);
 		utf16 += 2;
 		utf16 += 2;
 	}
 	}
 	as16->length = utf16 - as16->s;
 	as16->length = utf16 - as16->s;

+ 1 - 2
Utilities/cmlibarchive/libarchive/archive_string_composition.h

@@ -2286,5 +2286,4 @@ static const struct unicode_decomposition_table u_decomposition_table[] = {
 	{ 0x110AB , 0x110A5 , 0x110BA },
 	{ 0x110AB , 0x110A5 , 0x110BA },
 };
 };
 
 
-#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */
-
+#endif /* !ARCHIVE_STRING_COMPOSITION_H_INCLUDED */

+ 10 - 1
Utilities/cmlibarchive/libarchive/archive_string_sprintf.c

@@ -116,8 +116,14 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
 
 
 		long_flag = '\0';
 		long_flag = '\0';
 		switch(*p) {
 		switch(*p) {
-		case 'j':
 		case 'l':
 		case 'l':
+			if (p[1] == 'l') {
+				long_flag = 'L';
+				p += 2;
+				break;
+			}
+			__LA_FALLTHROUGH;
+		case 'j':
 		case 'z':
 		case 'z':
 			long_flag = *p;
 			long_flag = *p;
 			p++;
 			p++;
@@ -136,6 +142,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
 			switch(long_flag) {
 			switch(long_flag) {
 			case 'j': s = va_arg(ap, intmax_t); break;
 			case 'j': s = va_arg(ap, intmax_t); break;
 			case 'l': s = va_arg(ap, long); break;
 			case 'l': s = va_arg(ap, long); break;
+			case 'L': s = va_arg(ap, long long); break;
 			case 'z': s = va_arg(ap, ssize_t); break;
 			case 'z': s = va_arg(ap, ssize_t); break;
 			default:  s = va_arg(ap, int); break;
 			default:  s = va_arg(ap, int); break;
 			}
 			}
@@ -144,6 +151,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
 		case 's':
 		case 's':
 			switch(long_flag) {
 			switch(long_flag) {
 			case 'l':
 			case 'l':
+			case 'L':
 				pw = va_arg(ap, wchar_t *);
 				pw = va_arg(ap, wchar_t *);
 				if (pw == NULL)
 				if (pw == NULL)
 					pw = L"(null)";
 					pw = L"(null)";
@@ -172,6 +180,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
 			switch(long_flag) {
 			switch(long_flag) {
 			case 'j': u = va_arg(ap, uintmax_t); break;
 			case 'j': u = va_arg(ap, uintmax_t); break;
 			case 'l': u = va_arg(ap, unsigned long); break;
 			case 'l': u = va_arg(ap, unsigned long); break;
+			case 'L': u = va_arg(ap, unsigned long long); break;
 			case 'z': u = va_arg(ap, size_t); break;
 			case 'z': u = va_arg(ap, size_t); break;
 			default:  u = va_arg(ap, unsigned int); break;
 			default:  u = va_arg(ap, unsigned int); break;
 			}
 			}

+ 163 - 0
Utilities/cmlibarchive/libarchive/archive_time.c

@@ -0,0 +1,163 @@
+/*-
+ * Copyright © 2025 ARJANEN Loïc Jean David
+ * 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 "archive_platform.h"
+#include "archive_private.h"
+#include "archive_time_private.h"
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NTFS_EPOC_TIME ARCHIVE_LITERAL_ULL(11644473600)
+#define NTFS_TICKS ARCHIVE_LITERAL_ULL(10000000)
+#define NTFS_EPOC_TICKS (NTFS_EPOC_TIME * NTFS_TICKS)
+#define DOS_MIN_TIME 0x00210000U
+#define DOS_MAX_TIME 0xff9fbf7dU
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <winnt.h>
+/* Windows FILETIME to NTFS time. */
+uint64_t
+FILETIME_to_ntfs(const FILETIME* filetime)
+{
+	ULARGE_INTEGER utc;
+	utc.HighPart = filetime->dwHighDateTime;
+	utc.LowPart  = filetime->dwLowDateTime;
+	return utc.QuadPart;
+}
+#endif
+
+/* Convert an MSDOS-style date/time into Unix-style time. */
+int64_t
+dos_to_unix(uint32_t dos_time)
+{
+	uint16_t msTime, msDate;
+	struct tm ts;
+	time_t t;
+
+	msTime = (0xFFFF & dos_time);
+	msDate = (dos_time >> 16);
+
+	memset(&ts, 0, sizeof(ts));
+	ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
+	ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
+	ts.tm_mday = msDate & 0x1f; /* Day of month. */
+	ts.tm_hour = (msTime >> 11) & 0x1f;
+	ts.tm_min = (msTime >> 5) & 0x3f;
+	ts.tm_sec = (msTime << 1) & 0x3e;
+	ts.tm_isdst = -1;
+	t = mktime(&ts);
+	return (int64_t)(t == (time_t)-1 ? INT32_MAX : t);
+}
+
+/* Convert into MSDOS-style date/time. */
+uint32_t
+unix_to_dos(int64_t unix_time)
+{
+	struct tm *t;
+	uint32_t dt;
+	time_t ut = unix_time;
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
+	struct tm tmbuf;
+#endif
+
+	if (sizeof(time_t) < sizeof(int64_t) && (int64_t)ut != unix_time) {
+		ut = (time_t)(unix_time > 0 ? INT32_MAX : INT32_MIN);
+	}
+
+#if defined(HAVE_LOCALTIME_S)
+	t = localtime_s(&tmbuf, &ut) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
+	t = localtime_r(&ut, &tmbuf);
+#else
+	t = localtime(&ut);
+#endif
+	dt = 0;
+	if (t != NULL && t->tm_year >= INT_MIN + 80) {
+		const int year = t->tm_year - 80;
+
+		if (year & ~0x7f) {
+			dt = year > 0 ? DOS_MAX_TIME : DOS_MIN_TIME;
+		}
+		else {
+			dt += (year & 0x7f) << 9;
+			dt += ((t->tm_mon + 1) & 0x0f) << 5;
+			dt += (t->tm_mday & 0x1f);
+			dt <<= 16;
+			dt += (t->tm_hour & 0x1f) << 11;
+			dt += (t->tm_min & 0x3f) << 5;
+			/* Only counting every 2 seconds. */
+			dt += (t->tm_sec & 0x3e) >> 1;
+		}
+	}
+	if (dt > DOS_MAX_TIME) {
+		dt = DOS_MAX_TIME;
+	}
+	else if (dt < DOS_MIN_TIME) {
+		dt = DOS_MIN_TIME;
+	}
+	return dt;
+}
+
+/* Convert NTFS time to Unix sec/nsec */
+void
+ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs)
+{
+	if (ntfs > INT64_MAX) {
+		ntfs -= NTFS_EPOC_TICKS;
+		*secs = ntfs / NTFS_TICKS;
+		*nsecs = 100 * (ntfs % NTFS_TICKS);
+	}
+	else {
+		lldiv_t tdiv;
+		int64_t value = (int64_t)ntfs - (int64_t)NTFS_EPOC_TICKS;
+
+		tdiv = lldiv(value, NTFS_TICKS);
+		*secs = tdiv.quot;
+		*nsecs = (uint32_t)(tdiv.rem * 100);
+	}
+}
+
+/* Convert Unix sec/nsec to NTFS time */
+uint64_t
+unix_to_ntfs(int64_t secs, uint32_t nsecs)
+{
+	uint64_t ntfs;
+
+	if (secs < -(int64_t)NTFS_EPOC_TIME)
+		return 0;
+
+	ntfs = secs + NTFS_EPOC_TIME;
+
+	if (ntfs > UINT64_MAX / NTFS_TICKS)
+		return UINT64_MAX;
+
+	ntfs *= NTFS_TICKS;
+
+	if (ntfs > UINT64_MAX - nsecs/100)
+		return UINT64_MAX;
+
+	return ntfs + nsecs/100;
+}

+ 18 - 8
Utilities/cmlibarchive/libarchive/archive_getdate.h → Utilities/cmlibarchive/libarchive/archive_time_private.h

@@ -1,5 +1,5 @@
 /*-
 /*-
- * Copyright (c) 2003-2015 Tim Kientzle
+ * Copyright © 2025 ARJANEN Loïc Jean David
  * All rights reserved.
  * All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without
@@ -22,16 +22,26 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  */
-
-#ifndef ARCHIVE_GETDATE_H_INCLUDED
-#define ARCHIVE_GETDATE_H_INCLUDED
+#ifndef ARCHIVE_TIME_PRIVATE_H_INCLUDED
+#define ARCHIVE_TIME_PRIVATE_H_INCLUDED
 
 
 #ifndef __LIBARCHIVE_BUILD
 #ifndef __LIBARCHIVE_BUILD
 #error This header is only to be used internally to libarchive.
 #error This header is only to be used internally to libarchive.
 #endif
 #endif
+#include <stdint.h>
 
 
-#include <time.h>
-
-time_t __archive_get_date(time_t now, const char *);
-
+/* NTFS time to Unix sec/nsec. */
+void ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs);
+/* DOS time to Unix sec. */
+int64_t dos_to_unix(uint32_t dos);
+/* Unix sec/nsec to NTFS time. */
+uint64_t unix_to_ntfs(int64_t secs, uint32_t nsecs);
+/* Unix sec to DOS time. */
+uint32_t unix_to_dos(int64_t secs);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <windef.h>
+#include <winbase.h>
+/* Windows FILETIME to NTFS time. */
+uint64_t FILETIME_to_ntfs(const FILETIME* filetime);
 #endif
 #endif
+#endif /* ARCHIVE_TIME_PRIVATE_H_INCLUDED */

+ 16 - 60
Utilities/cmlibarchive/libarchive/archive_util.c

@@ -77,7 +77,9 @@
 #define O_CLOEXEC	0
 #define O_CLOEXEC	0
 #endif
 #endif
 
 
-static int archive_utility_string_sort_helper(char **, unsigned int);
+#if ARCHIVE_VERSION_NUMBER < 4000000
+static int __LA_LIBC_CC archive_utility_string_sort_helper(const void *, const void *);
+#endif
 
 
 /* Generic initialization of 'struct archive' objects. */
 /* Generic initialization of 'struct archive' objects. */
 int
 int
@@ -629,74 +631,28 @@ __archive_ensure_cloexec_flag(int fd)
 #endif
 #endif
 }
 }
 
 
+#if ARCHIVE_VERSION_NUMBER < 4000000
 /*
 /*
- * Utility function to sort a group of strings using quicksort.
+ * Utility functions to sort a group of strings using quicksort.
  */
  */
 static int
 static int
-archive_utility_string_sort_helper(char **strings, unsigned int n)
+__LA_LIBC_CC
+archive_utility_string_sort_helper(const void *p1, const void *p2)
 {
 {
-	unsigned int i, lesser_count, greater_count;
-	char **lesser, **greater, **tmp, *pivot;
-	int retval1, retval2;
-
-	/* A list of 0 or 1 elements is already sorted */
-	if (n <= 1)
-		return (ARCHIVE_OK);
-
-	lesser_count = greater_count = 0;
-	lesser = greater = NULL;
-	pivot = strings[0];
-	for (i = 1; i < n; i++)
-	{
-		if (strcmp(strings[i], pivot) < 0)
-		{
-			lesser_count++;
-			tmp = realloc(lesser, lesser_count * sizeof(*tmp));
-			if (!tmp) {
-				free(greater);
-				free(lesser);
-				return (ARCHIVE_FATAL);
-			}
-			lesser = tmp;
-			lesser[lesser_count - 1] = strings[i];
-		}
-		else
-		{
-			greater_count++;
-			tmp = realloc(greater, greater_count * sizeof(*tmp));
-			if (!tmp) {
-				free(greater);
-				free(lesser);
-				return (ARCHIVE_FATAL);
-			}
-			greater = tmp;
-			greater[greater_count - 1] = strings[i];
-		}
-	}
+	const char * const * const s1 = p1;
+	const char * const * const s2 = p2;
 
 
-	/* quicksort(lesser) */
-	retval1 = archive_utility_string_sort_helper(lesser, lesser_count);
-	for (i = 0; i < lesser_count; i++)
-		strings[i] = lesser[i];
-	free(lesser);
-
-	/* pivot */
-	strings[lesser_count] = pivot;
-
-	/* quicksort(greater) */
-	retval2 = archive_utility_string_sort_helper(greater, greater_count);
-	for (i = 0; i < greater_count; i++)
-		strings[lesser_count + 1 + i] = greater[i];
-	free(greater);
-
-	return (retval1 < retval2) ? retval1 : retval2;
+	return strcmp(*s1, *s2);
 }
 }
 
 
 int
 int
 archive_utility_string_sort(char **strings)
 archive_utility_string_sort(char **strings)
 {
 {
-	  unsigned int size = 0;
-	  while (strings[size] != NULL)
+	size_t size = 0;
+	while (strings[size] != NULL)
 		size++;
 		size++;
-	  return archive_utility_string_sort_helper(strings, size);
+	qsort(strings, size, sizeof(char *),
+	      archive_utility_string_sort_helper);
+	return (ARCHIVE_OK);
 }
 }
+#endif

+ 397 - 8
Utilities/cmlibarchive/libarchive/archive_version_details.c

@@ -46,11 +46,125 @@
 #endif
 #endif
 #ifdef HAVE_ZSTD_H
 #ifdef HAVE_ZSTD_H
 #include <cm3p/zstd.h>
 #include <cm3p/zstd.h>
+#include <stdio.h>
+#endif
+#ifdef HAVE_LZO_LZOCONF_H
+#include <lzo/lzoconf.h>
+#endif
+#if HAVE_LIBXML_XMLVERSION_H
+#include <libxml/xmlversion.h>
+#elif HAVE_BSDXML_H
+#include <bsdxml.h>
+#elif HAVE_EXPAT_H
+#include <cm3p/expat.h>
+#endif
+#if HAVE_MBEDTLS_VERSION_H
+#include <mbedtls/version.h>
+#endif
+#if HAVE_NETTLE_VERSION_H
+#include <nettle/version.h>
+#include <stdio.h>
+#endif
+#if HAVE_OPENSSL_OPENSSLV_H
+#include <openssl/opensslv.h>
+#include <stdio.h>
+#endif
+#if HAVE_ICONV_H
+#include <iconv.h>
+#endif
+#if HAVE_PCRE_H
+#include <pcre.h>
+#endif
+#if HAVE_PCRE2_H
+#include <pcre2.h>
 #endif
 #endif
 
 
 #include "archive.h"
 #include "archive.h"
 #include "archive_private.h"
 #include "archive_private.h"
 #include "archive_string.h"
 #include "archive_string.h"
+#include "archive_cryptor_private.h"
+#include "archive_digest_private.h"
+
+static void
+archive_regex_version(struct archive_string* str)
+{
+#if HAVE_LIBPCREPOSIX && HAVE_PCRE_H
+	archive_strcat(str, " libpcre/");
+	archive_strcat(str, archive_libpcre_version());
+#elif HAVE_LIBPCRE2POSIX && HAVE_PCRE2_H
+	archive_strcat(str, " libpcre2/");
+	archive_strcat(str, archive_libpcre2_version());
+#else
+	(void)str; /* UNUSED */
+#endif
+}
+
+static void
+archive_xml_version(struct archive_string* str)
+{
+#if HAVE_LIBXML_XMLVERSION_H && HAVE_LIBXML2
+	archive_strcat(str, " libxml2/");
+	archive_strcat(str, archive_libxml2_version());
+#elif HAVE_BSDXML_H && HAVE_LIBBSDXML
+	archive_strcat(str, " bsdxml/");
+	archive_strcat(str, archive_libbsdxml_version());
+#elif HAVE_EXPAT_H && HAVE_LIBEXPAT
+	archive_strcat(str, " expat/");
+	archive_strcat(str, archive_libexpat_version());
+#else
+	(void)str; /* UNUSED */
+#endif
+}
+
+static void
+archive_libb2_version(struct archive_string* str)
+{
+	archive_strcat(str, " libb2/");
+#if HAVE_BLAKE2_H && HAVE_LIBB2
+#if defined(LIBB2_PKGCONFIG_VERSION)
+	archive_strcat(str, LIBB2_PKGCONFIG_VERSION);
+#else
+	archive_strcat(str, "system");
+#endif
+#else
+	archive_strcat(str, "bundled");
+#endif
+}
+
+static void
+archive_crypto_version(struct archive_string* str)
+{
+#if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto)
+	archive_strcat(str, " CommonCrypto/");
+	archive_strcat(str, archive_commoncrypto_version());
+#endif
+#if defined(ARCHIVE_CRYPTOR_USE_CNG)
+	archive_strcat(str, " cng/");
+	archive_strcat(str, archive_cng_version());
+#endif
+#if defined(ARCHIVE_CRYPTOR_USE_MBED)
+	archive_strcat(str, " mbedtls/");
+	archive_strcat(str, archive_mbedtls_version());
+#endif
+#if defined(ARCHIVE_CRYPTOR_USE_NETTLE)
+	archive_strcat(str, " nettle/");
+	archive_strcat(str, archive_nettle_version());
+#endif
+#if defined(ARCHIVE_CRYPTOR_USE_OPENSSL)
+	archive_strcat(str, " openssl/");
+	archive_strcat(str, archive_openssl_version());
+#endif
+#if defined(ARCHIVE_CRYPTOR_USE_LIBMD)
+	archive_strcat(str, " libmd/");
+	archive_strcat(str, archive_libmd_version());
+#endif
+#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT)
+	archive_strcat(str, " WinCrypt/");
+	archive_strcat(str, archive_wincrypt_version());
+#endif
+	// Just in case
+	(void)str; /* UNUSED */
+}
 
 
 const char *
 const char *
 archive_version_details(void)
 archive_version_details(void)
@@ -62,12 +176,17 @@ archive_version_details(void)
 	const char *bzlib = archive_bzlib_version();
 	const char *bzlib = archive_bzlib_version();
 	const char *liblz4 = archive_liblz4_version();
 	const char *liblz4 = archive_liblz4_version();
 	const char *libzstd = archive_libzstd_version();
 	const char *libzstd = archive_libzstd_version();
+	const char *liblzo = archive_liblzo2_version();
+	const char *libiconv = archive_libiconv_version();
+	const char *libacl = archive_libacl_version();
+	const char *librichacl = archive_librichacl_version();
+	const char *libattr = archive_libacl_version();
 
 
 	if (!init) {
 	if (!init) {
 		archive_string_init(&str);
 		archive_string_init(&str);
 
 
 		archive_strcat(&str, ARCHIVE_VERSION_STRING);
 		archive_strcat(&str, ARCHIVE_VERSION_STRING);
-		if (zlib != NULL) {
+		if (zlib) {
 			archive_strcat(&str, " zlib/");
 			archive_strcat(&str, " zlib/");
 			archive_strcat(&str, zlib);
 			archive_strcat(&str, zlib);
 		}
 		}
@@ -91,6 +210,30 @@ archive_version_details(void)
 			archive_strcat(&str, " libzstd/");
 			archive_strcat(&str, " libzstd/");
 			archive_strcat(&str, libzstd);
 			archive_strcat(&str, libzstd);
 		}
 		}
+		if (liblzo) {
+			archive_strcat(&str, " liblzo2/");
+			archive_strcat(&str, liblzo);
+		}
+		archive_xml_version(&str);
+		archive_regex_version(&str);
+		archive_crypto_version(&str);
+		archive_libb2_version(&str);
+		if (librichacl) {
+			archive_strcat(&str, " librichacl/");
+			archive_strcat(&str, librichacl);
+		}
+		if (libacl) {
+			archive_strcat(&str, " libacl/");
+			archive_strcat(&str, libacl);
+		}
+		if (libattr) {
+			archive_strcat(&str, " libattr/");
+			archive_strcat(&str, libattr);
+		}
+		if (libiconv) {
+			archive_strcat(&str, " libiconv/");
+			archive_strcat(&str, libiconv);
+		}
 	}
 	}
 	return str.s;
 	return str.s;
 }
 }
@@ -98,8 +241,8 @@ archive_version_details(void)
 const char *
 const char *
 archive_zlib_version(void)
 archive_zlib_version(void)
 {
 {
-#ifdef HAVE_ZLIB_H
-	return ZLIB_VERSION;
+#if HAVE_ZLIB_H && HAVE_LIBZ
+	return zlibVersion();
 #else
 #else
 	return NULL;
 	return NULL;
 #endif
 #endif
@@ -108,8 +251,8 @@ archive_zlib_version(void)
 const char *
 const char *
 archive_liblzma_version(void)
 archive_liblzma_version(void)
 {
 {
-#ifdef HAVE_LZMA_H
-	return LZMA_VERSION_STRING;
+#if HAVE_LZMA_H && HAVE_LIBLZMA
+	return lzma_version_string();
 #else
 #else
 	return NULL;
 	return NULL;
 #endif
 #endif
@@ -118,7 +261,7 @@ archive_liblzma_version(void)
 const char *
 const char *
 archive_bzlib_version(void)
 archive_bzlib_version(void)
 {
 {
-#ifdef HAVE_BZLIB_H
+#if HAVE_BZLIB_H && HAVE_LIBBZ2
 	return BZ2_bzlibVersion();
 	return BZ2_bzlibVersion();
 #else
 #else
 	return NULL;
 	return NULL;
@@ -128,12 +271,22 @@ archive_bzlib_version(void)
 const char *
 const char *
 archive_liblz4_version(void)
 archive_liblz4_version(void)
 {
 {
-#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
+#if HAVE_LZ4_H && HAVE_LIBLZ4
+#if LZ4_VERSION_NUMBER > 10705
+	return LZ4_versionString();
+#elif LZ4_VERSION_NUMBER > 10300
+	div_t major = div(LZ4_versionNumber(), 10000);
+	div_t minor = div(major.rem, 100);
+	static char lz4_version[9];
+	snprintf(lz4_version, 9, "%d.%d.%d", major.quot, minor.quot, minor.rem);
+	return lz4_version;
+#else
 #define str(s) #s
 #define str(s) #s
 #define NUMBER(x) str(x)
 #define NUMBER(x) str(x)
 	return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
 	return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
 #undef NUMBER
 #undef NUMBER
 #undef str
 #undef str
+#endif
 #else
 #else
 	return NULL;
 	return NULL;
 #endif
 #endif
@@ -143,7 +296,243 @@ const char *
 archive_libzstd_version(void)
 archive_libzstd_version(void)
 {
 {
 #if HAVE_ZSTD_H && HAVE_LIBZSTD
 #if HAVE_ZSTD_H && HAVE_LIBZSTD
-	return ZSTD_VERSION_STRING;
+#if ZSTD_VERSION_NUMBER > 10300
+	return ZSTD_versionString();
+#else
+	div_t major = div(ZSTD_versionNumber(), 10000);
+	div_t minor = div(major.rem, 100);
+	static char zstd_version[9];
+	snprintf(zstd_version, 9, "%d.%d.%d", major.quot, minor.quot, minor.rem);
+	return zstd_version;
+#endif
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_liblzo2_version(void)
+{
+#if HAVE_LZO_LZOCONF_H && HAVE_LIBLZO2
+	return LZO_VERSION_STRING;
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_libbsdxml_version(void)
+{
+#if HAVE_BSDXML_H && HAVE_LIBBSDXML
+	return XML_ExpatVersion();
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_libxml2_version(void)
+{
+#if HAVE_LIBXML_XMLREADER_H && HAVE_LIBXML2
+	return LIBXML_DOTTED_VERSION;
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_libexpat_version(void)
+{
+#if HAVE_EXPAT_H && HAVE_LIBEXPAT
+	return XML_ExpatVersion();
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_mbedtls_version(void)
+{
+#if defined(ARCHIVE_CRYPTOR_USE_MBED) || defined(ARCHIVE_CRYPTO_MBED)
+	static char mbed_version[9];
+	mbedtls_version_get_string(mbed_version);
+	return mbed_version;
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_nettle_version(void)
+{
+#if defined(ARCHIVE_CRYPTOR_USE_NETTLE) || defined(ARCHIVE_CRYPTO_NETTLE)
+	static char nettle_version[6];
+	snprintf(nettle_version, 6, "%d.%d", nettle_version_major(), nettle_version_minor());
+	return nettle_version;
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_openssl_version(void)
+{
+#if defined(ARCHIVE_CRYPTOR_USE_OPENSSL) || defined(ARCHIVE_CRYPTO_OPENSSL)
+#ifdef OPENSSL_VERSION_STR
+	return OPENSSL_VERSION_STR;
+#else
+#define OPENSSL_MAJOR (OPENSSL_VERSION_NUMBER >> 28)
+#define OPENSSL_MINOR ((OPENSSL_VERSION_NUMBER >> 20) & 0xFF)
+	static char openssl_version[6];
+	snprintf(openssl_version, 6, "%ld.%ld", OPENSSL_MAJOR, OPENSSL_MINOR);
+	return openssl_version;
+#undef OPENSSL_MAJOR
+#undef OPENSSL_MINOR
+#endif
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_libmd_version(void)
+{
+#if defined(ARCHIVE_CRYPTOR_USE_LIBMD) || defined(ARCHIVE_CRYPTO_LIBMD)
+	return "system";
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_commoncrypto_version(void)
+{
+#if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto) || defined(ARCHIVE_CRYPTO_CommonCrypto)
+	return "system";
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_cng_version(void)
+{
+#if defined(ARCHIVE_CRYPTOR_USE_CNG) || defined(ARCHIVE_CRYPTO_CNG)
+#ifdef BCRYPT_HASH_INTERFACE_MAJORVERSION_2
+	return "2.0";
+#else
+	return "1.0";
+#endif
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_wincrypt_version(void)
+{
+#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) || defined(ARCHIVE_CRYPTO_WINCRYPT)
+	HCRYPTPROV prov;
+	if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+		if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
+			return NULL;
+		if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
+			return NULL;
+	}
+	DWORD version, length = sizeof(version);
+	if (!CryptGetProvParam(prov, PP_VERSION, (BYTE *)&version, &length, 0)) {
+		return NULL;
+	} else {
+		char major = (version >> 8) & 0xFF;
+		char minor = version & 0xFF;
+		static char wincrypt_version[6];
+		snprintf(wincrypt_version, 6, "%hhd.%hhd", major, minor);
+		return wincrypt_version;
+	}
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_librichacl_version(void)
+{
+#if HAVE_LIBRICHACL
+#if defined(LIBRICHACL_PKGCONFIG_VERSION)
+	return LIBRICHACL_PKGCONFIG_VERSION;
+#else
+	return "system";
+#endif
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_libacl_version(void)
+{
+#if HAVE_LIBACL
+#if defined(LIBACL_PKGCONFIG_VERSION)
+	return LIBACL_PKGCONFIG_VERSION;
+#else
+	return "system";
+#endif
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_libattr_version(void)
+{
+#if HAVE_LIBATTR
+#if defined(LIBATTR_PKGCONFIG_VERSION)
+	return LIBATTR_PKGCONFIG_VERSION;
+#else
+	return "system";
+#endif
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_libiconv_version(void)
+{
+#if HAVE_LIBCHARSET && HAVE_ICONV_H
+	char major = _libiconv_version >> 8;
+	char minor = _libiconv_version & 0xFF;
+	static char charset_version[6];
+	snprintf(charset_version, 6, "%hhd.%hhd", major, minor);
+	return charset_version;
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_libpcre_version(void)
+{
+#if HAVE_LIBPCREPOSIX && HAVE_PCRE_H
+#define str(s) #s
+#define NUMBER(x) str(x)
+	return NUMBER(PCRE_MAJOR) "." NUMBER(PCRE_MINOR);
+#undef NUMBER
+#undef str
+#else
+	return NULL;
+#endif
+}
+
+const char *
+archive_libpcre2_version(void)
+{
+#if HAVE_LIBPCRE2POSIX && HAVE_PCRE2_H
+#define str(s) #s
+#define NUMBER(x) str(x)
+	return NUMBER(PCRE2_MAJOR) "." NUMBER(PCRE2_MINOR);
+#undef NUMBER
+#undef str
 #else
 #else
 	return NULL;
 	return NULL;
 #endif
 #endif

+ 4 - 31
Utilities/cmlibarchive/libarchive/archive_windows.c

@@ -47,6 +47,7 @@
 #include "archive_platform.h"
 #include "archive_platform.h"
 #include "archive_private.h"
 #include "archive_private.h"
 #include "archive_entry.h"
 #include "archive_entry.h"
+#include "archive_time_private.h"
 #include <ctype.h>
 #include <ctype.h>
 #include <errno.h>
 #include <errno.h>
 #include <stddef.h>
 #include <stddef.h>
@@ -61,8 +62,6 @@
 #include <windows.h>
 #include <windows.h>
 #include <share.h>
 #include <share.h>
 
 
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-
 #if defined(__LA_LSEEK_NEEDED)
 #if defined(__LA_LSEEK_NEEDED)
 static BOOL SetFilePointerEx_perso(HANDLE hFile,
 static BOOL SetFilePointerEx_perso(HANDLE hFile,
 				   LARGE_INTEGER liDistanceToMove,
 				   LARGE_INTEGER liDistanceToMove,
@@ -450,24 +449,6 @@ __la_read(int fd, void *buf, size_t nbytes)
 	return ((ssize_t)bytes_read);
 	return ((ssize_t)bytes_read);
 }
 }
 
 
-/* Convert Windows FILETIME to UTC */
-__inline static void
-fileTimeToUTC(const FILETIME *filetime, time_t *t, long *ns)
-{
-	ULARGE_INTEGER utc;
-
-	utc.HighPart = filetime->dwHighDateTime;
-	utc.LowPart  = filetime->dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		*t = (time_t)(utc.QuadPart / 10000000);	/* milli seconds base */
-		*ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
-	} else {
-		*t = 0;
-		*ns = 0;
-	}
-}
-
 /* Stat by handle
 /* Stat by handle
  * Windows' stat() does not accept the path added "\\?\" especially "?"
  * Windows' stat() does not accept the path added "\\?\" especially "?"
  * character.
  * character.
@@ -487,8 +468,6 @@ __hstat(HANDLE handle, struct ustat *st)
 	ULARGE_INTEGER ino64;
 	ULARGE_INTEGER ino64;
 	DWORD ftype;
 	DWORD ftype;
 	mode_t mode;
 	mode_t mode;
-	time_t t;
-	long ns;
 
 
 	switch (ftype = GetFileType(handle)) {
 	switch (ftype = GetFileType(handle)) {
 	case FILE_TYPE_UNKNOWN:
 	case FILE_TYPE_UNKNOWN:
@@ -544,15 +523,9 @@ __hstat(HANDLE handle, struct ustat *st)
 		mode |= S_IFREG;
 		mode |= S_IFREG;
 	st->st_mode = mode;
 	st->st_mode = mode;
 
 
-	fileTimeToUTC(&info.ftLastAccessTime, &t, &ns);
-	st->st_atime = t;
-	st->st_atime_nsec = ns;
-	fileTimeToUTC(&info.ftLastWriteTime, &t, &ns);
-	st->st_mtime = t;
-	st->st_mtime_nsec = ns;
-	fileTimeToUTC(&info.ftCreationTime, &t, &ns);
-	st->st_ctime = t;
-	st->st_ctime_nsec = ns;
+	ntfs_to_unix(FILETIME_to_ntfs(&info.ftLastAccessTime), &st->st_atime, &st->st_atime_nsec);
+	ntfs_to_unix(FILETIME_to_ntfs(&info.ftLastWriteTime), &st->st_mtime, &st->st_mtime_nsec);
+	ntfs_to_unix(FILETIME_to_ntfs(&info.ftCreationTime), &st->st_ctime, &st->st_ctime_nsec);
 	st->st_size =
 	st->st_size =
 	    ((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1))
 	    ((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1))
 		+ (int64_t)(info.nFileSizeLow);
 		+ (int64_t)(info.nFileSizeLow);

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_windows.h

@@ -321,4 +321,4 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
 # endif
 # endif
 #endif
 #endif
 
 
-#endif /* LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED */
+#endif /* !LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED */

+ 1 - 1
Utilities/cmlibarchive/libarchive/archive_write.c

@@ -283,7 +283,7 @@ __archive_write_filters_open(struct archive_write *a)
 }
 }
 
 
 /*
 /*
- * Close all filtes
+ * Close all filters
  */
  */
 static int
 static int
 __archive_write_filters_close(struct archive_write *a)
 __archive_write_filters_close(struct archive_write *a)

+ 18 - 1
Utilities/cmlibarchive/libarchive/archive_write_add_filter_gzip.c

@@ -58,6 +58,7 @@ archive_write_set_compression_gzip(struct archive *a)
 struct private_data {
 struct private_data {
 	int		 compression_level;
 	int		 compression_level;
 	int		 timestamp;
 	int		 timestamp;
+	char	*original_filename;
 #ifdef HAVE_ZLIB_H
 #ifdef HAVE_ZLIB_H
 	z_stream	 stream;
 	z_stream	 stream;
 	int64_t		 total_in;
 	int64_t		 total_in;
@@ -113,6 +114,8 @@ archive_write_add_filter_gzip(struct archive *_a)
 	f->free = &archive_compressor_gzip_free;
 	f->free = &archive_compressor_gzip_free;
 	f->code = ARCHIVE_FILTER_GZIP;
 	f->code = ARCHIVE_FILTER_GZIP;
 	f->name = "gzip";
 	f->name = "gzip";
+
+	data->original_filename = NULL;
 #ifdef HAVE_ZLIB_H
 #ifdef HAVE_ZLIB_H
 	data->compression_level = Z_DEFAULT_COMPRESSION;
 	data->compression_level = Z_DEFAULT_COMPRESSION;
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
@@ -140,6 +143,7 @@ archive_compressor_gzip_free(struct archive_write_filter *f)
 #else
 #else
 	__archive_write_program_free(data->pdata);
 	__archive_write_program_free(data->pdata);
 #endif
 #endif
+	free((void*)data->original_filename);
 	free(data);
 	free(data);
 	f->data = NULL;
 	f->data = NULL;
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
@@ -165,6 +169,13 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key,
 		data->timestamp = (value == NULL)?-1:1;
 		data->timestamp = (value == NULL)?-1:1;
 		return (ARCHIVE_OK);
 		return (ARCHIVE_OK);
 	}
 	}
+	if (strcmp(key, "original-filename") == 0) {
+		free((void*)data->original_filename);
+		data->original_filename = NULL;
+		if (value)
+			data->original_filename = strdup(value);
+		return (ARCHIVE_OK);
+	}
 
 
 	/* Note: The "warn" return is just to inform the options
 	/* Note: The "warn" return is just to inform the options
 	 * supervisor that we didn't handle it.  It will generate
 	 * supervisor that we didn't handle it.  It will generate
@@ -210,7 +221,7 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
 	data->compressed[0] = 0x1f; /* GZip signature bytes */
 	data->compressed[0] = 0x1f; /* GZip signature bytes */
 	data->compressed[1] = 0x8b;
 	data->compressed[1] = 0x8b;
 	data->compressed[2] = 0x08; /* "Deflate" compression */
 	data->compressed[2] = 0x08; /* "Deflate" compression */
-	data->compressed[3] = 0; /* No options */
+	data->compressed[3] = data->original_filename == NULL ? 0 : 0x8;
 	if (data->timestamp >= 0) {
 	if (data->timestamp >= 0) {
 		time_t t = time(NULL);
 		time_t t = time(NULL);
 		data->compressed[4] = (uint8_t)(t)&0xff;  /* Timestamp */
 		data->compressed[4] = (uint8_t)(t)&0xff;  /* Timestamp */
@@ -229,6 +240,12 @@ archive_compressor_gzip_open(struct archive_write_filter *f)
 	data->stream.next_out += 10;
 	data->stream.next_out += 10;
 	data->stream.avail_out -= 10;
 	data->stream.avail_out -= 10;
 
 
+	if (data->original_filename != NULL) {
+		strcpy((char*)data->compressed + 10, data->original_filename);
+		data->stream.next_out += strlen(data->original_filename) + 1;
+		data->stream.avail_out -= strlen(data->original_filename) + 1;
+	}
+
 	f->write = archive_compressor_gzip_write;
 	f->write = archive_compressor_gzip_write;
 
 
 	/* Initialize compression library. */
 	/* Initialize compression library. */

+ 37 - 39
Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c

@@ -60,6 +60,7 @@
 #include "archive_string.h"
 #include "archive_string.h"
 #include "archive_entry.h"
 #include "archive_entry.h"
 #include "archive_private.h"
 #include "archive_private.h"
+#include "archive_time_private.h"
 
 
 #ifndef O_BINARY
 #ifndef O_BINARY
 #define O_BINARY 0
 #define O_BINARY 0
@@ -407,7 +408,11 @@ permissive_name_w(struct archive_write_disk *a)
 		wn = _wcsdup(wnp);
 		wn = _wcsdup(wnp);
 		if (wn == NULL)
 		if (wn == NULL)
 			return (-1);
 			return (-1);
-		archive_wstring_ensure(&(a->_name_data), 4 + wcslen(wn) + 1);
+		if (archive_wstring_ensure(&(a->_name_data),
+			4 + wcslen(wn) + 1) == NULL) {
+			free(wn);
+			return (-1);
+		}
 		a->name = a->_name_data.s;
 		a->name = a->_name_data.s;
 		/* Prepend "\\?\" */
 		/* Prepend "\\?\" */
 		archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
 		archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
@@ -437,8 +442,11 @@ permissive_name_w(struct archive_write_disk *a)
 				wn = _wcsdup(wnp);
 				wn = _wcsdup(wnp);
 				if (wn == NULL)
 				if (wn == NULL)
 					return (-1);
 					return (-1);
-				archive_wstring_ensure(&(a->_name_data),
-					8 + wcslen(wn) + 1);
+				if (archive_wstring_ensure(&(a->_name_data),
+					8 + wcslen(wn) + 1) == NULL) {
+					free(wn);
+					return (-1);
+				}
 				a->name = a->_name_data.s;
 				a->name = a->_name_data.s;
 				/* Prepend "\\?\UNC\" */
 				/* Prepend "\\?\UNC\" */
 				archive_wstrncpy(&(a->_name_data),
 				archive_wstrncpy(&(a->_name_data),
@@ -470,10 +478,16 @@ permissive_name_w(struct archive_write_disk *a)
 	 */
 	 */
 	if (wnp[0] == L'\\') {
 	if (wnp[0] == L'\\') {
 		wn = _wcsdup(wnp);
 		wn = _wcsdup(wnp);
-		if (wn == NULL)
+		if (wn == NULL) {
+			free(wsp);
 			return (-1);
 			return (-1);
-		archive_wstring_ensure(&(a->_name_data),
-			4 + 2 + wcslen(wn) + 1);
+		}
+		if (archive_wstring_ensure(&(a->_name_data),
+			4 + 2 + wcslen(wn) + 1) == NULL) {
+			free(wsp);
+			free(wn);
+			return (-1);
+		}
 		a->name = a->_name_data.s;
 		a->name = a->_name_data.s;
 		/* Prepend "\\?\" and drive name. */
 		/* Prepend "\\?\" and drive name. */
 		archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
 		archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
@@ -485,9 +499,16 @@ permissive_name_w(struct archive_write_disk *a)
 	}
 	}
 
 
 	wn = _wcsdup(wnp);
 	wn = _wcsdup(wnp);
-	if (wn == NULL)
+	if (wn == NULL) {
+		free(wsp);
+		return (-1);
+	}
+	if (archive_wstring_ensure(&(a->_name_data),
+		4 + l + 1 + wcslen(wn) + 1) == NULL) {
+		free(wsp);
+		free(wn);
 		return (-1);
 		return (-1);
-	archive_wstring_ensure(&(a->_name_data), 4 + l + 1 + wcslen(wn) + 1);
+	}
 	a->name = a->_name_data.s;
 	a->name = a->_name_data.s;
 	/* Prepend "\\?\" and drive name if not already added. */
 	/* Prepend "\\?\" and drive name if not already added. */
 	if (l > 3 && wsp[0] == L'\\' && wsp[1] == L'\\' &&
 	if (l > 3 && wsp[0] == L'\\' && wsp[1] == L'\\' &&
@@ -637,7 +658,7 @@ la_CreateHardLinkW(wchar_t *linkname, wchar_t *target)
 }
 }
 
 
 /*
 /*
- * Create file or directory symolic link
+ * Create file or directory symbolic link
  *
  *
  * If linktype is AE_SYMLINK_TYPE_UNDEFINED (or unknown), guess linktype from
  * If linktype is AE_SYMLINK_TYPE_UNDEFINED (or unknown), guess linktype from
  * the link target
  * the link target
@@ -2605,10 +2626,6 @@ set_times(struct archive_write_disk *a,
     time_t mtime, long mtime_nanos,
     time_t mtime, long mtime_nanos,
     time_t ctime_sec, long ctime_nanos)
     time_t ctime_sec, long ctime_nanos)
 {
 {
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-#define WINTIME(sec, nsec) (((sec * 10000000LL) + EPOC_TIME)\
-	 + ((nsec)/100))
-
 	HANDLE hw = 0;
 	HANDLE hw = 0;
 	ULARGE_INTEGER wintm;
 	ULARGE_INTEGER wintm;
 	FILETIME *pfbtime;
 	FILETIME *pfbtime;
@@ -2646,17 +2663,17 @@ set_times(struct archive_write_disk *a,
 		h = hw;
 		h = hw;
 	}
 	}
 
 
-	wintm.QuadPart = WINTIME(atime, atime_nanos);
+	wintm.QuadPart = unix_to_ntfs(atime, atime_nanos);
 	fatime.dwLowDateTime = wintm.LowPart;
 	fatime.dwLowDateTime = wintm.LowPart;
 	fatime.dwHighDateTime = wintm.HighPart;
 	fatime.dwHighDateTime = wintm.HighPart;
-	wintm.QuadPart = WINTIME(mtime, mtime_nanos);
+	wintm.QuadPart = unix_to_ntfs(mtime, mtime_nanos);
 	fmtime.dwLowDateTime = wintm.LowPart;
 	fmtime.dwLowDateTime = wintm.LowPart;
 	fmtime.dwHighDateTime = wintm.HighPart;
 	fmtime.dwHighDateTime = wintm.HighPart;
 	/*
 	/*
 	 * SetFileTime() supports birthtime.
 	 * SetFileTime() supports birthtime.
 	 */
 	 */
 	if (birthtime > 0 || birthtime_nanos > 0) {
 	if (birthtime > 0 || birthtime_nanos > 0) {
-		wintm.QuadPart = WINTIME(birthtime, birthtime_nanos);
+		wintm.QuadPart = unix_to_ntfs(birthtime, birthtime_nanos);
 		fbtime.dwLowDateTime = wintm.LowPart;
 		fbtime.dwLowDateTime = wintm.LowPart;
 		fbtime.dwHighDateTime = wintm.HighPart;
 		fbtime.dwHighDateTime = wintm.HighPart;
 		pfbtime = &fbtime;
 		pfbtime = &fbtime;
@@ -2878,34 +2895,16 @@ set_xattrs(struct archive_write_disk *a)
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 }
 }
 
 
-static void
-fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
-{
-	ULARGE_INTEGER utc;
-
-	utc.HighPart = filetime->dwHighDateTime;
-	utc.LowPart  = filetime->dwLowDateTime;
-	if (utc.QuadPart >= EPOC_TIME) {
-		utc.QuadPart -= EPOC_TIME;
-		/* milli seconds base */
-		*t = (time_t)(utc.QuadPart / 10000000);
-		/* nano seconds base */
-		*ns = (long)(utc.QuadPart % 10000000) * 100;
-	} else {
-		*t = 0;
-		*ns = 0;
-	}
-}
 /*
 /*
  * Test if file on disk is older than entry.
  * Test if file on disk is older than entry.
  */
  */
 static int
 static int
 older(BY_HANDLE_FILE_INFORMATION *st, struct archive_entry *entry)
 older(BY_HANDLE_FILE_INFORMATION *st, struct archive_entry *entry)
 {
 {
-	time_t sec;
-	long nsec;
+	int64_t sec;
+	uint32_t nsec;
 
 
-	fileTimeToUtc(&st->ftLastWriteTime, &sec, &nsec);
+	ntfs_to_unix(FILETIME_to_ntfs(&st->ftLastWriteTime), &sec, &nsec);
 	/* First, test the seconds and return if we have a definite answer. */
 	/* First, test the seconds and return if we have a definite answer. */
 	/* Definitely older. */
 	/* Definitely older. */
 	if (sec < archive_entry_mtime(entry))
 	if (sec < archive_entry_mtime(entry))
@@ -2913,11 +2912,10 @@ older(BY_HANDLE_FILE_INFORMATION *st, struct archive_entry *entry)
 	/* Definitely younger. */
 	/* Definitely younger. */
 	if (sec > archive_entry_mtime(entry))
 	if (sec > archive_entry_mtime(entry))
 		return (0);
 		return (0);
-	if (nsec < archive_entry_mtime_nsec(entry))
+	if ((long)nsec < archive_entry_mtime_nsec(entry))
 		return (1);
 		return (1);
 	/* Same age or newer, so not older. */
 	/* Same age or newer, so not older. */
 	return (0);
 	return (0);
 }
 }
 
 
 #endif /* _WIN32 && !__CYGWIN__ */
 #endif /* _WIN32 && !__CYGWIN__ */
-

+ 263 - 35
Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c

@@ -28,7 +28,12 @@
 #ifdef HAVE_ERRNO_H
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #include <errno.h>
 #endif
 #endif
+#ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #ifdef HAVE_BZLIB_H
 #ifdef HAVE_BZLIB_H
 #include <cm3p/bzlib.h>
 #include <cm3p/bzlib.h>
 #endif
 #endif
@@ -38,6 +43,9 @@
 #ifdef HAVE_ZLIB_H
 #ifdef HAVE_ZLIB_H
 #include <cm3p/zlib.h>
 #include <cm3p/zlib.h>
 #endif
 #endif
+#ifdef HAVE_ZSTD_H
+#include <cm3p/zstd.h>
+#endif
 
 
 #include "archive.h"
 #include "archive.h"
 #ifndef HAVE_ZLIB_H
 #ifndef HAVE_ZLIB_H
@@ -50,6 +58,7 @@
 #include "archive_private.h"
 #include "archive_private.h"
 #include "archive_rb.h"
 #include "archive_rb.h"
 #include "archive_string.h"
 #include "archive_string.h"
+#include "archive_time_private.h"
 #include "archive_write_private.h"
 #include "archive_write_private.h"
 #include "archive_write_set_format_private.h"
 #include "archive_write_set_format_private.h"
 
 
@@ -63,6 +72,8 @@
 #define _7Z_BZIP2	0x040202
 #define _7Z_BZIP2	0x040202
 #define _7Z_PPMD	0x030401
 #define _7Z_PPMD	0x030401
 
 
+#define _7Z_ZSTD	0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
+
 /*
 /*
  * 7-Zip header property IDs.
  * 7-Zip header property IDs.
  */
  */
@@ -110,6 +121,9 @@
 // the attr field along with the unix permissions.
 // the attr field along with the unix permissions.
 #define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000
 #define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000
 
 
+// Many systems define min or MIN, but not all.
+#define sevenzipmin(a,b) ((a) < (b) ? (a) : (b))
+
 enum la_zaction {
 enum la_zaction {
 	ARCHIVE_Z_FINISH,
 	ARCHIVE_Z_FINISH,
 	ARCHIVE_Z_RUN
 	ARCHIVE_Z_RUN
@@ -209,7 +223,11 @@ struct _7zip {
 #define	ENCODED_CRC32	2
 #define	ENCODED_CRC32	2
 
 
 	unsigned		 opt_compression;
 	unsigned		 opt_compression;
+
 	int			 opt_compression_level;
 	int			 opt_compression_level;
+	int			 opt_zstd_compression_level; // This requires a different default value.
+
+	int			 opt_threads;
 
 
 	struct la_zstream	 stream;
 	struct la_zstream	 stream;
 	struct coder		 coder;
 	struct coder		 coder;
@@ -285,12 +303,19 @@ static int	compression_code_lzma(struct archive *,
 static int	compression_end_lzma(struct archive *, struct la_zstream *);
 static int	compression_end_lzma(struct archive *, struct la_zstream *);
 #endif
 #endif
 static int	compression_init_encoder_ppmd(struct archive *,
 static int	compression_init_encoder_ppmd(struct archive *,
-		    struct la_zstream *, unsigned, uint32_t);
+		    struct la_zstream *, uint8_t, uint32_t);
 static int	compression_code_ppmd(struct archive *,
 static int	compression_code_ppmd(struct archive *,
 		    struct la_zstream *, enum la_zaction);
 		    struct la_zstream *, enum la_zaction);
 static int	compression_end_ppmd(struct archive *, struct la_zstream *);
 static int	compression_end_ppmd(struct archive *, struct la_zstream *);
 static int	_7z_compression_init_encoder(struct archive_write *, unsigned,
 static int	_7z_compression_init_encoder(struct archive_write *, unsigned,
 		    int);
 		    int);
+static int	compression_init_encoder_zstd(struct archive *,
+		    struct la_zstream *, int, int);
+#if defined(HAVE_ZSTD_H)
+static int	compression_code_zstd(struct archive *,
+		    struct la_zstream *, enum la_zaction);
+static int	compression_end_zstd(struct archive *, struct la_zstream *);
+#endif
 static int	compression_code(struct archive *,
 static int	compression_code(struct archive *,
 		    struct la_zstream *, enum la_zaction);
 		    struct la_zstream *, enum la_zaction);
 static int	compression_end(struct archive *,
 static int	compression_end(struct archive *,
@@ -301,6 +326,21 @@ static int	make_header(struct archive_write *, uint64_t, uint64_t,
 static int	make_streamsInfo(struct archive_write *, uint64_t, uint64_t,
 static int	make_streamsInfo(struct archive_write *, uint64_t, uint64_t,
 		    	uint64_t, int, struct coder *, int, uint32_t);
 		    	uint64_t, int, struct coder *, int, uint32_t);
 
 
+static int
+string_to_number(const char *string, intmax_t *numberp)
+{
+	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);
+}
+
 int
 int
 archive_write_set_format_7zip(struct archive *_a)
 archive_write_set_format_7zip(struct archive *_a)
 {
 {
@@ -335,11 +375,24 @@ archive_write_set_format_7zip(struct archive *_a)
 	zip->opt_compression = _7Z_BZIP2;
 	zip->opt_compression = _7Z_BZIP2;
 #elif defined(HAVE_ZLIB_H)
 #elif defined(HAVE_ZLIB_H)
 	zip->opt_compression = _7Z_DEFLATE;
 	zip->opt_compression = _7Z_DEFLATE;
+#elif HAVE_ZSTD_H
+	zip->opt_compression = _7Z_ZSTD;
 #else
 #else
 	zip->opt_compression = _7Z_COPY;
 	zip->opt_compression = _7Z_COPY;
 #endif
 #endif
+
 	zip->opt_compression_level = 6;
 	zip->opt_compression_level = 6;
 
 
+#ifdef ZSTD_CLEVEL_DEFAULT
+	// Zstandard compression needs a different default
+	// value than other encoders.
+	zip->opt_zstd_compression_level = ZSTD_CLEVEL_DEFAULT;
+#else
+	zip->opt_zstd_compression_level = 3;
+#endif
+
+	zip->opt_threads = 1;
+
 	a->format_data = zip;
 	a->format_data = zip;
 
 
 	a->format_name = "7zip";
 	a->format_name = "7zip";
@@ -397,6 +450,13 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
 			zip->opt_compression = _7Z_LZMA2;
 			zip->opt_compression = _7Z_LZMA2;
 #else
 #else
 			name = "lzma2";
 			name = "lzma2";
+#endif
+		else if (strcmp(value, "zstd") == 0 ||
+		    strcmp(value, "ZSTD") == 0)
+#if HAVE_ZSTD_H
+			zip->opt_compression = _7Z_ZSTD;
+#else
+			name = "zstd";
 #endif
 #endif
 		else if (strcmp(value, "ppmd") == 0 ||
 		else if (strcmp(value, "ppmd") == 0 ||
 		    strcmp(value, "PPMD") == 0 ||
 		    strcmp(value, "PPMD") == 0 ||
@@ -420,16 +480,68 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
 		return (ARCHIVE_OK);
 		return (ARCHIVE_OK);
 	}
 	}
 	if (strcmp(key, "compression-level") == 0) {
 	if (strcmp(key, "compression-level") == 0) {
-		if (value == NULL ||
-		    !(value[0] >= '0' && value[0] <= '9') ||
-		    value[1] != '\0') {
-			archive_set_error(&(a->archive),
-			    ARCHIVE_ERRNO_MISC,
-			    "Illegal value `%s'",
-			    value);
+		if (value == NULL || *value == '\0') {
+			archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
+				"Invalid compression-level option value `%s'", value);
+			return (ARCHIVE_FAILED);
+		}
+
+		char *end = NULL;
+		long lvl = strtol(value, &end, 10);
+		if (end == NULL || *end != '\0') {
+			archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
+				"parsing compression-level option value failed `%s'", value);
+			return (ARCHIVE_FAILED);
+		}
+
+#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream && HAVE_ZSTD_minCLevel
+		int min_level = sevenzipmin(0, ZSTD_minCLevel());
+#else
+		const int min_level = 0;
+#endif
+
+#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream
+		int max_level = ZSTD_maxCLevel();
+#else
+		const int max_level = 9;
+#endif
+
+		if (lvl < min_level || lvl > max_level) {
+			archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
+				"compression-level option value `%ld' out of range", lvl);
 			return (ARCHIVE_FAILED);
 			return (ARCHIVE_FAILED);
 		}
 		}
-		zip->opt_compression_level = value[0] - '0';
+
+		// Note: we don't know here if this value is for zstd (negative to ~22),
+		// or zlib-style 0-9. If zstd is enabled but not in use, we will need to
+		// validate opt_compression_level before use.
+		zip->opt_compression_level = (int)lvl;
+
+		zip->opt_zstd_compression_level = (int)lvl;
+		return (ARCHIVE_OK);
+	}
+	if (strcmp(key, "threads") == 0) {
+		intmax_t threads;
+		if (string_to_number(value, &threads) != ARCHIVE_OK) {
+			return (ARCHIVE_WARN);
+		}
+		if (threads < 0) {
+			return (ARCHIVE_WARN);
+		}
+		if (threads == 0) {
+#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
+			threads = sysconf(_SC_NPROCESSORS_ONLN);
+#elif !defined(__CYGWIN__) && defined(_WIN32_WINNT) && \
+	_WIN32_WINNT >= 0x0601 /* _WIN32_WINNT_WIN7 */
+			DWORD winCores = GetActiveProcessorCount(
+				ALL_PROCESSOR_GROUPS);
+			threads = (intmax_t)winCores;
+#else
+			threads = 1;
+#endif
+		}
+
+		zip->opt_threads = (int)threads;
 		return (ARCHIVE_OK);
 		return (ARCHIVE_OK);
 	}
 	}
 
 
@@ -495,8 +607,20 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry)
 	 * Init compression.
 	 * Init compression.
 	 */
 	 */
 	if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) {
 	if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) {
-		r = _7z_compression_init_encoder(a, zip->opt_compression,
-			zip->opt_compression_level);
+
+		int level = zip->opt_compression_level;
+#if HAVE_ZSTD_H
+		if (zip->opt_compression == _7Z_ZSTD) {
+			level = zip->opt_zstd_compression_level;
+		} else if (level < 0 || level > 9) {
+			archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
+				"compression-level option value `%d' out of range 0-9", level);
+			file_free(file);
+			return (ARCHIVE_FATAL);
+		}
+#endif
+
+		r = _7z_compression_init_encoder(a, zip->opt_compression, level);
 		if (r < 0) {
 		if (r < 0) {
 			file_free(file);
 			file_free(file);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
@@ -785,8 +909,12 @@ _7z_close(struct archive_write *a)
 #else
 #else
 		header_compression = _7Z_COPY;
 		header_compression = _7Z_COPY;
 #endif
 #endif
-		r = _7z_compression_init_encoder(a, header_compression,
-		                                 zip->opt_compression_level);
+
+		int level = zip->opt_compression_level;
+		if (level < 0) level = 0;
+		else if (level > 9) level = 9;
+
+		r = _7z_compression_init_encoder(a, header_compression, level);
 		if (r < 0)
 		if (r < 0)
 			return (r);
 			return (r);
 		zip->crc32flg = PRECODE_CRC32;
 		zip->crc32flg = PRECODE_CRC32;
@@ -844,7 +972,7 @@ _7z_close(struct archive_write *a)
 		header_offset = header_size = 0;
 		header_offset = header_size = 0;
 		header_crc32 = 0;
 		header_crc32 = 0;
 	}
 	}
-	
+
 	length = zip->temp_offset;
 	length = zip->temp_offset;
 
 
 	/*
 	/*
@@ -1164,20 +1292,6 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 }
 }
 
 
-
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-static uint64_t
-utcToFiletime(time_t t, long ns)
-{
-	uint64_t fileTime;
-
-	fileTime = t;
-	fileTime *= 10000000;
-	fileTime += ns / 100;
-	fileTime += EPOC_TIME;
-	return (fileTime);
-}
-
 static int
 static int
 make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
 make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
 {
 {
@@ -1249,7 +1363,6 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
 	if (r < 0)
 	if (r < 0)
 		return (r);
 		return (r);
 
 
-
 	/*
 	/*
 	 * Make Times.
 	 * Make Times.
 	 */
 	 */
@@ -1257,7 +1370,7 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
 	for (;file != NULL; file = file->next) {
 	for (;file != NULL; file = file->next) {
 		if ((file->flg & flg) == 0)
 		if ((file->flg & flg) == 0)
 			continue;
 			continue;
-		archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
+		archive_le64enc(filetime, unix_to_ntfs(file->times[ti].time,
 			file->times[ti].time_ns));
 			file->times[ti].time_ns));
 		r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
 		r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
 		if (r < 0)
 		if (r < 0)
@@ -1504,7 +1617,7 @@ file_cmp_node(const struct archive_rb_node *n1,
 		return (memcmp(f1->utf16name, f2->utf16name, f1->name_len));
 		return (memcmp(f1->utf16name, f2->utf16name, f1->name_len));
 	return (f1->name_len > f2->name_len)?1:-1;
 	return (f1->name_len > f2->name_len)?1:-1;
 }
 }
-        
+
 static int
 static int
 file_cmp_key(const struct archive_rb_node *n, const void *key)
 file_cmp_key(const struct archive_rb_node *n, const void *key)
 {
 {
@@ -1646,7 +1759,8 @@ file_init_register_empty(struct _7zip *zip)
 }
 }
 
 
 #if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
 #if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
-	 !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
+	 !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) ||\
+	 !(HAVE_ZSTD_H && HAVE_ZSTD_compressStream)
 static int
 static int
 compression_unsupported_encoder(struct archive *a,
 compression_unsupported_encoder(struct archive *a,
     struct la_zstream *lastrm, const char *name)
     struct la_zstream *lastrm, const char *name)
@@ -2159,7 +2273,7 @@ ppmd_write(void *p, Byte b)
 
 
 static int
 static int
 compression_init_encoder_ppmd(struct archive *a,
 compression_init_encoder_ppmd(struct archive *a,
-    struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize)
+    struct la_zstream *lastrm, uint8_t maxOrder, uint32_t msize)
 {
 {
 	struct ppmd_stream *strm;
 	struct ppmd_stream *strm;
 	uint8_t *props;
 	uint8_t *props;
@@ -2279,6 +2393,117 @@ compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 }
 }
 
 
+#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream
+static int
+compression_init_encoder_zstd(struct archive *a, struct la_zstream *lastrm, int level, int threads)
+{
+	if (lastrm->valid)
+		compression_end(a, lastrm);
+
+	ZSTD_CStream *strm = ZSTD_createCStream();
+	if (strm == NULL) {
+		archive_set_error(a, ENOMEM,
+			"Can't allocate memory for zstd stream");
+		return (ARCHIVE_FATAL);
+	}
+
+	if (ZSTD_isError(ZSTD_initCStream(strm, level))) {
+		ZSTD_freeCStream(strm);
+		archive_set_error(a, ARCHIVE_ERRNO_MISC,
+			"Internal error initializing zstd compressor object");
+		return (ARCHIVE_FATAL);
+	}
+
+	ZSTD_CCtx_setParameter(strm, ZSTD_c_nbWorkers, threads);
+
+	// p7zip-zstd fails to unpack archives that don't have prop_size 5.
+	// 7-Zip-zstd fails to unpack archives that don't have prop_size 3 or 5.
+	// So let's use 5...
+	lastrm->prop_size = 5;
+	lastrm->props = calloc(5, 1);
+	if (lastrm->props == NULL) {
+		ZSTD_freeCStream(strm);
+		archive_set_error(a, ARCHIVE_ERRNO_MISC,
+			"Internal error initializing zstd compressor properties");
+		return (ARCHIVE_FATAL);
+	}
+
+	// Refer to the DProps struct in 7-Zip-zstd's ZstdDecoder.h:
+	// https://github.com/mcmilk/7-Zip-zstd/blob/79b2c78e9e7735ddf90147129b75cf2797ff6522/CPP/7zip/Compress/ZstdDecoder.h#L34S
+	lastrm->props[0] = ZSTD_VERSION_MAJOR;
+	lastrm->props[1] = ZSTD_VERSION_MINOR;
+	lastrm->props[2] = level;
+	// lastrm->props[3] and lastrm->props[4] are reserved. Leave them as 0.
+
+	lastrm->real_stream = strm;
+	lastrm->valid = 1;
+	lastrm->code = compression_code_zstd;
+	lastrm->end = compression_end_zstd;
+
+	return (ARCHIVE_OK);
+}
+
+static int
+compression_code_zstd(struct archive *a,
+    struct la_zstream *lastrm, enum la_zaction action)
+{
+	ZSTD_CStream *strm = (ZSTD_CStream *)lastrm->real_stream;
+
+	ZSTD_outBuffer out = { .dst = lastrm->next_out, .size = lastrm->avail_out, .pos = 0 };
+	ZSTD_inBuffer  in  = { .src = lastrm->next_in,  .size = lastrm->avail_in,  .pos = 0 };
+
+	size_t zret;
+
+	ZSTD_EndDirective mode = (action == ARCHIVE_Z_RUN) ? ZSTD_e_continue : ZSTD_e_end;
+
+	zret = ZSTD_compressStream2(strm, &out, &in, mode);
+	if (ZSTD_isError(zret)) {
+		archive_set_error(a, ARCHIVE_ERRNO_MISC,
+			"zstd compression failed, ZSTD_compressStream2 returned: %s",
+			ZSTD_getErrorName(zret));
+		return (ARCHIVE_FATAL);
+	}
+
+	lastrm->next_in += in.pos;
+	lastrm->avail_in -= in.pos;
+	lastrm->total_in += in.pos;
+
+	lastrm->next_out += out.pos;
+	lastrm->avail_out -= out.pos;
+	lastrm->total_out += out.pos;
+
+	if (action == ARCHIVE_Z_FINISH && zret == 0)
+		return (ARCHIVE_EOF); // All done.
+
+	return (ARCHIVE_OK); // More work to do.
+}
+
+static int
+compression_end_zstd(struct archive *a, struct la_zstream *lastrm)
+{
+	ZSTD_CStream *strm;
+
+	(void)a; /* UNUSED */
+	strm = (ZSTD_CStream *)lastrm->real_stream;
+	ZSTD_freeCStream(strm);
+	lastrm->valid = 0;
+	lastrm->real_stream = NULL;
+	return (ARCHIVE_OK);
+}
+
+#else
+
+static int
+compression_init_encoder_zstd(struct archive *a, struct la_zstream *lastrm, int level, int threads)
+{
+	(void) level; /* UNUSED */
+	(void) threads; /* UNUSED */
+	if (lastrm->valid)
+		compression_end(a, lastrm);
+	return (compression_unsupported_encoder(a, lastrm, "zstd"));
+}
+#endif
+
 /*
 /*
  * Universal compressor initializer.
  * Universal compressor initializer.
  */
  */
@@ -2316,6 +2541,11 @@ _7z_compression_init_encoder(struct archive_write *a, unsigned compression,
 		    &(a->archive), &(zip->stream),
 		    &(a->archive), &(zip->stream),
 		    PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE);
 		    PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE);
 		break;
 		break;
+	case _7Z_ZSTD:
+		r = compression_init_encoder_zstd(
+		    &(a->archive), &(zip->stream),
+		    compression_level, zip->opt_threads);
+		break;
 	case _7Z_COPY:
 	case _7Z_COPY:
 	default:
 	default:
 		r = compression_init_encoder_copy(
 		r = compression_init_encoder_copy(
@@ -2352,5 +2582,3 @@ compression_end(struct archive *a, struct la_zstream *lastrm)
 	}
 	}
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 }
 }
-
-

+ 8 - 8
Utilities/cmlibarchive/libarchive/archive_write_set_format_gnutar.c

@@ -153,7 +153,7 @@ static const char template_header[] = {
 static int      archive_write_gnutar_options(struct archive_write *,
 static int      archive_write_gnutar_options(struct archive_write *,
 		    const char *, const char *);
 		    const char *, const char *);
 static int	archive_format_gnutar_header(struct archive_write *, char h[512],
 static int	archive_format_gnutar_header(struct archive_write *, char h[512],
-		    struct archive_entry *, int tartype);
+		    struct archive_entry *, char tartype);
 static int      archive_write_gnutar_header(struct archive_write *,
 static int      archive_write_gnutar_header(struct archive_write *,
 		    struct archive_entry *entry);
 		    struct archive_entry *entry);
 static ssize_t	archive_write_gnutar_data(struct archive_write *a, const void *buff,
 static ssize_t	archive_write_gnutar_data(struct archive_write *a, const void *buff,
@@ -274,7 +274,7 @@ archive_write_gnutar_header(struct archive_write *a,
 {
 {
 	char buff[512];
 	char buff[512];
 	int r, ret, ret2 = ARCHIVE_OK;
 	int r, ret, ret2 = ARCHIVE_OK;
-	int tartype;
+	char tartype;
 	struct gnutar *gnutar;
 	struct gnutar *gnutar;
 	struct archive_string_conv *sconv;
 	struct archive_string_conv *sconv;
 	struct archive_entry *entry_main;
 	struct archive_entry *entry_main;
@@ -504,7 +504,7 @@ archive_write_gnutar_header(struct archive_write *a,
 		archive_entry_set_uname(temp, "root");
 		archive_entry_set_uname(temp, "root");
 		archive_entry_set_gname(temp, "wheel");
 		archive_entry_set_gname(temp, "wheel");
 
 
-		archive_entry_set_pathname(temp, "././@LongLink");
+		archive_entry_set_pathname(temp, "././@LongName");
 		archive_entry_set_size(temp, length);
 		archive_entry_set_size(temp, length);
 		ret = archive_format_gnutar_header(a, buff, temp, 'L');
 		ret = archive_format_gnutar_header(a, buff, temp, 'L');
 		archive_entry_free(temp);
 		archive_entry_free(temp);
@@ -562,7 +562,7 @@ exit_write_header:
 
 
 static int
 static int
 archive_format_gnutar_header(struct archive_write *a, char h[512],
 archive_format_gnutar_header(struct archive_write *a, char h[512],
-    struct archive_entry *entry, int tartype)
+    struct archive_entry *entry, char tartype)
 {
 {
 	unsigned int checksum;
 	unsigned int checksum;
 	int i, ret;
 	int i, ret;
@@ -640,7 +640,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
 	if (format_number(archive_entry_uid(entry), h + GNUTAR_uid_offset,
 	if (format_number(archive_entry_uid(entry), h + GNUTAR_uid_offset,
 		GNUTAR_uid_size, GNUTAR_uid_max_size)) {
 		GNUTAR_uid_size, GNUTAR_uid_max_size)) {
 		archive_set_error(&a->archive, ERANGE,
 		archive_set_error(&a->archive, ERANGE,
-		    "Numeric user ID %jd too large",
+		    "Numeric user ID %jd too large for gnutar format",
 		    (intmax_t)archive_entry_uid(entry));
 		    (intmax_t)archive_entry_uid(entry));
 		ret = ARCHIVE_FAILED;
 		ret = ARCHIVE_FAILED;
 	}
 	}
@@ -649,7 +649,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
 	if (format_number(archive_entry_gid(entry), h + GNUTAR_gid_offset,
 	if (format_number(archive_entry_gid(entry), h + GNUTAR_gid_offset,
 		GNUTAR_gid_size, GNUTAR_gid_max_size)) {
 		GNUTAR_gid_size, GNUTAR_gid_max_size)) {
 		archive_set_error(&a->archive, ERANGE,
 		archive_set_error(&a->archive, ERANGE,
-		    "Numeric group ID %jd too large",
+		    "Numeric group ID %jd too large for gnutar format",
 		    (intmax_t)archive_entry_gid(entry));
 		    (intmax_t)archive_entry_gid(entry));
 		ret = ARCHIVE_FAILED;
 		ret = ARCHIVE_FAILED;
 	}
 	}
@@ -672,7 +672,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
 		    h + GNUTAR_rdevmajor_offset,
 		    h + GNUTAR_rdevmajor_offset,
 			GNUTAR_rdevmajor_size)) {
 			GNUTAR_rdevmajor_size)) {
 			archive_set_error(&a->archive, ERANGE,
 			archive_set_error(&a->archive, ERANGE,
-			    "Major device number too large");
+			    "Major device number too large for gnutar format");
 			ret = ARCHIVE_FAILED;
 			ret = ARCHIVE_FAILED;
 		}
 		}
 
 
@@ -680,7 +680,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
 		    h + GNUTAR_rdevminor_offset,
 		    h + GNUTAR_rdevminor_offset,
 			GNUTAR_rdevminor_size)) {
 			GNUTAR_rdevminor_size)) {
 			archive_set_error(&a->archive, ERANGE,
 			archive_set_error(&a->archive, ERANGE,
-			    "Minor device number too large");
+			    "Minor device number too large for gnutar format");
 			ret = ARCHIVE_FAILED;
 			ret = ARCHIVE_FAILED;
 		}
 		}
 	}
 	}

+ 14 - 3
Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c

@@ -1171,7 +1171,12 @@ archive_write_set_format_iso9660(struct archive *_a)
 	iso9660->primary.rootent->parent = iso9660->primary.rootent;
 	iso9660->primary.rootent->parent = iso9660->primary.rootent;
 	iso9660->cur_dirent = iso9660->primary.rootent;
 	iso9660->cur_dirent = iso9660->primary.rootent;
 	archive_string_init(&(iso9660->cur_dirstr));
 	archive_string_init(&(iso9660->cur_dirstr));
-	archive_string_ensure(&(iso9660->cur_dirstr), 1);
+	if (archive_string_ensure(&(iso9660->cur_dirstr), 1) == NULL) {
+		free(iso9660);
+		archive_set_error(&a->archive, ENOMEM,
+		    "Can't allocate memory");
+		return (ARCHIVE_FATAL);
+	}
 	iso9660->cur_dirstr.s[0] = 0;
 	iso9660->cur_dirstr.s[0] = 0;
 	iso9660->sconv_to_utf16be = NULL;
 	iso9660->sconv_to_utf16be = NULL;
 	iso9660->sconv_from_utf16be = NULL;
 	iso9660->sconv_from_utf16be = NULL;
@@ -5670,9 +5675,15 @@ isoent_tree(struct archive_write *a, struct isoent **isoentpp)
 		 * inserted. */
 		 * inserted. */
 		iso9660->cur_dirent = dent;
 		iso9660->cur_dirent = dent;
 		archive_string_empty(&(iso9660->cur_dirstr));
 		archive_string_empty(&(iso9660->cur_dirstr));
-		archive_string_ensure(&(iso9660->cur_dirstr),
+		if (archive_string_ensure(&(iso9660->cur_dirstr),
 		    archive_strlen(&(dent->file->parentdir)) +
 		    archive_strlen(&(dent->file->parentdir)) +
-		    archive_strlen(&(dent->file->basename)) + 2);
+		    archive_strlen(&(dent->file->basename)) + 2) == NULL) {
+			archive_set_error(&a->archive, ENOMEM,
+			    "Can't allocate memory");
+			_isoent_free(isoent);
+			*isoentpp = NULL;
+			return (ARCHIVE_FATAL);
+		}
 		if (archive_strlen(&(dent->file->parentdir)) +
 		if (archive_strlen(&(dent->file->parentdir)) +
 		    archive_strlen(&(dent->file->basename)) == 0)
 		    archive_strlen(&(dent->file->basename)) == 0)
 			iso9660->cur_dirstr.s[0] = 0;
 			iso9660->cur_dirstr.s[0] = 0;

+ 98 - 15
Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c

@@ -82,6 +82,7 @@ struct dir_info {
 struct reg_info {
 struct reg_info {
 	int compute_sum;
 	int compute_sum;
 	uint32_t crc;
 	uint32_t crc;
+	uint_least32_t mset_digest;
 	struct ae_digest digest;
 	struct ae_digest digest;
 };
 };
 
 
@@ -862,6 +863,50 @@ mtree_entry_free(struct mtree_entry *me)
 	free(me);
 	free(me);
 }
 }
 
 
+static void
+mtree_copy_ae_digests(struct reg_info *reg, struct archive_entry *entry, int compute_sum)
+{
+	reg->compute_sum = compute_sum;
+	reg->mset_digest = entry->mset_digest;
+
+	if ((reg->compute_sum & F_MD5)
+		&& (reg->mset_digest & AE_MSET_DIGEST_MD5)) {
+
+		memcpy(&reg->digest.md5, entry->digest.md5,
+			sizeof(reg->digest.md5));
+	}
+	if ((reg->compute_sum & F_RMD160)
+		&& (reg->mset_digest & AE_MSET_DIGEST_RMD160)) {
+
+		memcpy(&reg->digest.rmd160, entry->digest.rmd160,
+			sizeof(reg->digest.rmd160));
+	}
+	if ((reg->compute_sum & F_SHA1)
+		&& (reg->mset_digest & AE_MSET_DIGEST_SHA1)) {
+
+		memcpy(&reg->digest.sha1, entry->digest.sha1,
+			sizeof(reg->digest.sha1));
+	}
+	if ((reg->compute_sum & F_SHA256)
+		&& (reg->mset_digest & AE_MSET_DIGEST_SHA256)) {
+
+		memcpy(&reg->digest.sha256, entry->digest.sha256,
+			sizeof(reg->digest.sha256));
+	}
+	if ((reg->compute_sum & F_SHA384)
+		&& (reg->mset_digest & AE_MSET_DIGEST_SHA384)) {
+
+		memcpy(&reg->digest.sha384, entry->digest.sha384,
+			sizeof(reg->digest.sha384));
+	}
+	if ((reg->compute_sum & F_SHA512)
+		&& (reg->mset_digest & AE_MSET_DIGEST_SHA512)) {
+
+		memcpy(&reg->digest.sha512, entry->digest.sha512,
+			sizeof(reg->digest.sha512));
+	}
+}
+
 static int
 static int
 archive_write_mtree_header(struct archive_write *a,
 archive_write_mtree_header(struct archive_write *a,
     struct archive_entry *entry)
     struct archive_entry *entry)
@@ -896,8 +941,12 @@ archive_write_mtree_header(struct archive_write *a,
 	/* If the current file is a regular file, we have to
 	/* If the current file is a regular file, we have to
 	 * compute the sum of its content.
 	 * compute the sum of its content.
 	 * Initialize a bunch of checksum context. */
 	 * Initialize a bunch of checksum context. */
-	if (mtree_entry->reg_info)
+	if (mtree_entry->reg_info) {
 		sum_init(mtree);
 		sum_init(mtree);
+		/* honor archive_entry_set_digest() calls. These values will be
+		 * overwritten if archive_write_mtree_data() is called */
+		mtree_copy_ae_digests(mtree_entry->reg_info, entry, mtree->compute_sum);
+	}
 
 
 	return (r2);
 	return (r2);
 }
 }
@@ -1516,28 +1565,46 @@ sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
 		mtree->crc_len += n;
 		mtree->crc_len += n;
 	}
 	}
 #ifdef ARCHIVE_HAS_MD5
 #ifdef ARCHIVE_HAS_MD5
-	if (mtree->compute_sum & F_MD5)
+	if (mtree->compute_sum & F_MD5) {
 		archive_md5_update(&mtree->md5ctx, buff, n);
 		archive_md5_update(&mtree->md5ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_MD5;
+	}
 #endif
 #endif
 #ifdef ARCHIVE_HAS_RMD160
 #ifdef ARCHIVE_HAS_RMD160
-	if (mtree->compute_sum & F_RMD160)
+	if (mtree->compute_sum & F_RMD160) {
 		archive_rmd160_update(&mtree->rmd160ctx, buff, n);
 		archive_rmd160_update(&mtree->rmd160ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_RMD160;
+	}
 #endif
 #endif
 #ifdef ARCHIVE_HAS_SHA1
 #ifdef ARCHIVE_HAS_SHA1
-	if (mtree->compute_sum & F_SHA1)
+	if (mtree->compute_sum & F_SHA1) {
 		archive_sha1_update(&mtree->sha1ctx, buff, n);
 		archive_sha1_update(&mtree->sha1ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_SHA1;
+	}
 #endif
 #endif
 #ifdef ARCHIVE_HAS_SHA256
 #ifdef ARCHIVE_HAS_SHA256
-	if (mtree->compute_sum & F_SHA256)
+	if (mtree->compute_sum & F_SHA256) {
 		archive_sha256_update(&mtree->sha256ctx, buff, n);
 		archive_sha256_update(&mtree->sha256ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_SHA256;
+	}
 #endif
 #endif
 #ifdef ARCHIVE_HAS_SHA384
 #ifdef ARCHIVE_HAS_SHA384
-	if (mtree->compute_sum & F_SHA384)
+	if (mtree->compute_sum & F_SHA384) {
 		archive_sha384_update(&mtree->sha384ctx, buff, n);
 		archive_sha384_update(&mtree->sha384ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_SHA384;
+	}
 #endif
 #endif
 #ifdef ARCHIVE_HAS_SHA512
 #ifdef ARCHIVE_HAS_SHA512
-	if (mtree->compute_sum & F_SHA512)
+	if (mtree->compute_sum & F_SHA512) {
 		archive_sha512_update(&mtree->sha512ctx, buff, n);
 		archive_sha512_update(&mtree->sha512ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_SHA512;
+	}
 #endif
 #endif
 }
 }
 
 
@@ -1553,27 +1620,39 @@ sum_final(struct mtree_writer *mtree, struct reg_info *reg)
 		reg->crc = ~mtree->crc;
 		reg->crc = ~mtree->crc;
 	}
 	}
 #ifdef ARCHIVE_HAS_MD5
 #ifdef ARCHIVE_HAS_MD5
-	if (mtree->compute_sum & F_MD5)
+	if ((mtree->compute_sum & F_MD5)
+		&& !(reg->mset_digest & AE_MSET_DIGEST_MD5))
+
 		archive_md5_final(&mtree->md5ctx, reg->digest.md5);
 		archive_md5_final(&mtree->md5ctx, reg->digest.md5);
 #endif
 #endif
 #ifdef ARCHIVE_HAS_RMD160
 #ifdef ARCHIVE_HAS_RMD160
-	if (mtree->compute_sum & F_RMD160)
+	if ((mtree->compute_sum & F_RMD160)
+		&& !(reg->mset_digest & AE_MSET_DIGEST_RMD160))
+
 		archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160);
 		archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160);
 #endif
 #endif
 #ifdef ARCHIVE_HAS_SHA1
 #ifdef ARCHIVE_HAS_SHA1
-	if (mtree->compute_sum & F_SHA1)
+	if ((mtree->compute_sum & F_SHA1)
+		&& !(reg->mset_digest & AE_MSET_DIGEST_SHA1))
+
 		archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1);
 		archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1);
 #endif
 #endif
 #ifdef ARCHIVE_HAS_SHA256
 #ifdef ARCHIVE_HAS_SHA256
-	if (mtree->compute_sum & F_SHA256)
+	if ((mtree->compute_sum & F_SHA256)
+		&& !(reg->mset_digest & AE_MSET_DIGEST_SHA256))
+
 		archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256);
 		archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256);
 #endif
 #endif
 #ifdef ARCHIVE_HAS_SHA384
 #ifdef ARCHIVE_HAS_SHA384
-	if (mtree->compute_sum & F_SHA384)
+	if ((mtree->compute_sum & F_SHA384)
+		&& !(reg->mset_digest & AE_MSET_DIGEST_SHA384))
+
 		archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384);
 		archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384);
 #endif
 #endif
 #ifdef ARCHIVE_HAS_SHA512
 #ifdef ARCHIVE_HAS_SHA512
-	if (mtree->compute_sum & F_SHA512)
+	if ((mtree->compute_sum & F_SHA512)
+		&& !(reg->mset_digest & AE_MSET_DIGEST_SHA512))
+
 		archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512);
 		archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512);
 #endif
 #endif
 	/* Save what types of sum are computed. */
 	/* Save what types of sum are computed. */
@@ -2130,9 +2209,13 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
 		 * inserted. */
 		 * inserted. */
 		mtree->cur_dirent = dent;
 		mtree->cur_dirent = dent;
 		archive_string_empty(&(mtree->cur_dirstr));
 		archive_string_empty(&(mtree->cur_dirstr));
-		archive_string_ensure(&(mtree->cur_dirstr),
+		if (archive_string_ensure(&(mtree->cur_dirstr),
 		    archive_strlen(&(dent->parentdir)) +
 		    archive_strlen(&(dent->parentdir)) +
-		    archive_strlen(&(dent->basename)) + 2);
+		    archive_strlen(&(dent->basename)) + 2) == NULL) {
+			archive_set_error(&a->archive, ENOMEM,
+			    "Can't allocate memory");
+			return (ARCHIVE_FATAL);
+		}
 		if (archive_strlen(&(dent->parentdir)) +
 		if (archive_strlen(&(dent->parentdir)) +
 		    archive_strlen(&(dent->basename)) == 0)
 		    archive_strlen(&(dent->basename)) == 0)
 			mtree->cur_dirstr.s[0] = 0;
 			mtree->cur_dirstr.s[0] = 0;

+ 3 - 3
Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c

@@ -1414,7 +1414,7 @@ archive_write_pax_header(struct archive_write *a,
 		struct archive_entry *pax_attr_entry;
 		struct archive_entry *pax_attr_entry;
 		time_t s;
 		time_t s;
 		int64_t uid, gid;
 		int64_t uid, gid;
-		int mode;
+		__LA_MODE_T mode;
 
 
 		pax_attr_entry = archive_entry_new2(&a->archive);
 		pax_attr_entry = archive_entry_new2(&a->archive);
 		p = entry_name.s;
 		p = entry_name.s;
@@ -1571,7 +1571,7 @@ build_ustar_entry_name(char *dest, const char *src, size_t src_length,
 	const char *filename, *filename_end;
 	const char *filename, *filename_end;
 	char *p;
 	char *p;
 	int need_slash = 0; /* Was there a trailing slash? */
 	int need_slash = 0; /* Was there a trailing slash? */
-	size_t suffix_length = 99;
+	size_t suffix_length = 98; /* 99 - 1 for trailing slash */
 	size_t insert_length;
 	size_t insert_length;
 
 
 	/* Length of additional dir element to be added. */
 	/* Length of additional dir element to be added. */
@@ -1623,7 +1623,7 @@ build_ustar_entry_name(char *dest, const char *src, size_t src_length,
 	/* Step 2: Locate the "prefix" section of the dirname, including
 	/* Step 2: Locate the "prefix" section of the dirname, including
 	 * trailing '/'. */
 	 * trailing '/'. */
 	prefix = src;
 	prefix = src;
-	prefix_end = prefix + 155;
+	prefix_end = prefix + 154 /* 155 - 1 for trailing / */;
 	if (prefix_end > filename)
 	if (prefix_end > filename)
 		prefix_end = filename;
 		prefix_end = filename;
 	while (prefix_end > prefix && *prefix_end != '/')
 	while (prefix_end > prefix && *prefix_end != '/')

+ 568 - 124
Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c

@@ -34,6 +34,14 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #if HAVE_LIBXML_XMLWRITER_H
 #if HAVE_LIBXML_XMLWRITER_H
 #include <libxml/xmlwriter.h>
 #include <libxml/xmlwriter.h>
+#if defined(LIBXML_VERSION) && LIBXML_VERSION >= 20703
+#define XAR_WRITER_HAS_XML
+#endif /* LIBXML_VERSION */
+#elif HAVE_XMLLITE_H
+#include <objidl.h>
+#include <initguid.h>
+#include <xmllite.h>
+#define XAR_WRITER_HAS_XML
 #endif
 #endif
 #ifdef HAVE_BZLIB_H
 #ifdef HAVE_BZLIB_H
 #include <cm3p/bzlib.h>
 #include <cm3p/bzlib.h>
@@ -70,13 +78,12 @@
  *
  *
  */
  */
 
 
-#if !(defined(HAVE_LIBXML_XMLWRITER_H) && defined(LIBXML_VERSION) &&\
-	LIBXML_VERSION >= 20703) ||\
+#if !defined(XAR_WRITER_HAS_XML) ||\
 	!defined(HAVE_ZLIB_H) || \
 	!defined(HAVE_ZLIB_H) || \
 	!defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
 	!defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
 /*
 /*
  * xar needs several external libraries.
  * xar needs several external libraries.
- *   o libxml2
+ *   o libxml2 or xmllite (on Windows)
  *   o openssl or MD5/SHA1 hash function
  *   o openssl or MD5/SHA1 hash function
  *   o zlib
  *   o zlib
  *   o bzlib2 (option)
  *   o bzlib2 (option)
@@ -94,9 +101,26 @@ archive_write_set_format_xar(struct archive *_a)
 
 
 #else	/* Support xar format */
 #else	/* Support xar format */
 
 
-/*#define DEBUG_PRINT_TOC		1 */
+struct xml_writer;
+static int xml_writer_create(struct xml_writer **pctx);
+static int xml_writer_start_document(struct xml_writer *ctx);
+static int xml_writer_end_document(struct xml_writer *ctx);
+static int xml_writer_set_indent(struct xml_writer *ctx, unsigned int indent);
+static int xml_writer_start_element(struct xml_writer *ctx,
+    const char *localName);
+static int xml_writer_write_attribute(struct xml_writer *ctx, const char *key,
+    const char *value);
+static int xml_writer_write_attributef(struct xml_writer *ctx, const char *key,
+    const char *format, ...);
+static int xml_writer_write_string(struct xml_writer *ctx, const char *string);
+static int xml_writer_write_base64(struct xml_writer* ctx,
+    const char *data, size_t start, size_t len);
+static int xml_writer_end_element(struct xml_writer *ctx);
+static int xml_writer_get_final_content_and_length(struct xml_writer *ctx,
+    const char **out, size_t *size);
+static int xml_writer_destroy(struct xml_writer *ctx);
 
 
-#define BAD_CAST_CONST (const xmlChar *)
+/*#define DEBUG_PRINT_TOC		1 */
 
 
 #define HEADER_MAGIC	0x78617221
 #define HEADER_MAGIC	0x78617221
 #define HEADER_SIZE	28
 #define HEADER_SIZE	28
@@ -807,50 +831,49 @@ xar_finish_entry(struct archive_write *a)
 }
 }
 
 
 static int
 static int
-xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer,
+xmlwrite_string_attr(struct archive_write *a, struct xml_writer *writer,
 	const char *key, const char *value,
 	const char *key, const char *value,
 	const char *attrkey, const char *attrvalue)
 	const char *attrkey, const char *attrvalue)
 {
 {
 	int r;
 	int r;
 
 
-	r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
+	r = xml_writer_start_element(writer, key);
 	if (r < 0) {
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartElement() failed: %d", r);
+		    "xml_writer_start_element() failed: %d", r);
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
 	if (attrkey != NULL && attrvalue != NULL) {
 	if (attrkey != NULL && attrvalue != NULL) {
-		r = xmlTextWriterWriteAttribute(writer,
-		    BAD_CAST_CONST(attrkey), BAD_CAST_CONST(attrvalue));
+		r = xml_writer_write_attribute(writer, attrkey, attrvalue);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
+			    "xml_writer_write_attribute() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 	}
 	}
 	if (value != NULL) {
 	if (value != NULL) {
-		r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
+		r = xml_writer_write_string(writer, value);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteString() failed: %d", r);
+			    "xml_writer_write_string() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 	}
 	}
-	r = xmlTextWriterEndElement(writer);
+	r = xml_writer_end_element(writer);
 	if (r < 0) {
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterEndElement() failed: %d", r);
+		    "xml_writer_end_element() failed: %d", r);
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 }
 }
 
 
 static int
 static int
-xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer,
+xmlwrite_string(struct archive_write *a, struct xml_writer *writer,
 	const char *key, const char *value)
 	const char *key, const char *value)
 {
 {
 	int r;
 	int r;
@@ -858,34 +881,34 @@ xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer,
 	if (value == NULL)
 	if (value == NULL)
 		return (ARCHIVE_OK);
 		return (ARCHIVE_OK);
 
 
-	r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
+	r = xml_writer_start_element(writer, key);
 	if (r < 0) {
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartElement() failed: %d", r);
+		    "xml_writer_start_element() failed: %d", r);
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
 	if (value != NULL) {
 	if (value != NULL) {
-		r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
+		r = xml_writer_write_string(writer, value);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteString() failed: %d", r);
+			    "xml_writer_write_string() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 	}
 	}
-	r = xmlTextWriterEndElement(writer);
+	r = xml_writer_end_element(writer);
 	if (r < 0) {
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterEndElement() failed: %d", r);
+		    "xml_writer_end_element() failed: %d", r);
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 }
 }
 
 
 static int
 static int
-xmlwrite_fstring(struct archive_write *a, xmlTextWriterPtr writer,
+xmlwrite_fstring(struct archive_write *a, struct xml_writer *writer,
 	const char *key, const char *fmt, ...)
 	const char *key, const char *fmt, ...)
 {
 {
 	struct xar *xar;
 	struct xar *xar;
@@ -900,7 +923,7 @@ xmlwrite_fstring(struct archive_write *a, xmlTextWriterPtr writer,
 }
 }
 
 
 static int
 static int
-xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
+xmlwrite_time(struct archive_write *a, struct xml_writer *writer,
 	const char *key, time_t t, int z)
 	const char *key, time_t t, int z)
 {
 {
 	char timestr[100];
 	char timestr[100];
@@ -922,7 +945,7 @@ xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
 }
 }
 
 
 static int
 static int
-xmlwrite_mode(struct archive_write *a, xmlTextWriterPtr writer,
+xmlwrite_mode(struct archive_write *a, struct xml_writer *writer,
 	const char *key, mode_t mode)
 	const char *key, mode_t mode)
 {
 {
 	char ms[5];
 	char ms[5];
@@ -937,7 +960,7 @@ xmlwrite_mode(struct archive_write *a, xmlTextWriterPtr writer,
 }
 }
 
 
 static int
 static int
-xmlwrite_sum(struct archive_write *a, xmlTextWriterPtr writer,
+xmlwrite_sum(struct archive_write *a, struct xml_writer *writer,
 	const char *key, struct chksumval *sum)
 	const char *key, struct chksumval *sum)
 {
 {
 	const char *algname;
 	const char *algname;
@@ -971,7 +994,7 @@ xmlwrite_sum(struct archive_write *a, xmlTextWriterPtr writer,
 }
 }
 
 
 static int
 static int
-xmlwrite_heap(struct archive_write *a, xmlTextWriterPtr writer,
+xmlwrite_heap(struct archive_write *a, struct xml_writer *writer,
 	struct heap_data *heap)
 	struct heap_data *heap)
 {
 {
 	const char *encname;
 	const char *encname;
@@ -1029,7 +1052,7 @@ xmlwrite_heap(struct archive_write *a, xmlTextWriterPtr writer,
  * Our implements records both <flags> and <ext2> if it's necessary.
  * Our implements records both <flags> and <ext2> if it's necessary.
  */
  */
 static int
 static int
-make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
+make_fflags_entry(struct archive_write *a, struct xml_writer *writer,
     const char *element, const char *fflags_text)
     const char *element, const char *fflags_text)
 {
 {
 	static const struct flagentry {
 	static const struct flagentry {
@@ -1119,11 +1142,11 @@ make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
 	} while (p != NULL);
 	} while (p != NULL);
 
 
 	if (n > 0) {
 	if (n > 0) {
-		r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(element));
+		r = xml_writer_start_element(writer, element);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 		for (i = 0; i < n; i++) {
 		for (i = 0; i < n; i++) {
@@ -1133,29 +1156,59 @@ make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
 				return (r);
 				return (r);
 		}
 		}
 
 
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 	}
 	}
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 }
 }
 
 
+/*
+ * This function determines whether a UTF-8 string contains
+ * only codepoints that are convertible to Latin-1. Strings
+ * beyond Latin-1 are stored base64-encoded in the XAR TOC.
+ */
 static int
 static int
-make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
+is_u8_zstring_latin1(const char *in)
+{
+	unsigned int c;
+	while (*in) {
+		c = *in++;
+		if (c < 0x80) continue;
+		/*
+		 * Filter out non-continuation, any continuation of 2-3
+		 * bytes, and any continuation of 1 byte whose high 3 bits
+		 * are non-zero. Recall, 1-byte continuations can store 11
+		 * bits whereas Latin-1 codepoints are only 8 bits wide.
+		 */
+		if ((c & 0xFC) != 0xC0)
+			return (0);
+		c = *in++;
+		/*
+		 * If we get any non-continuation byte (including 0x00!),
+		 * the string is not valid UTF-8.
+		 */
+		if ((c & 0xC0) != 0x80)
+			return (0); /* invalid unicode */
+	}
+	return (1);
+}
+
+static int
+make_file_entry(struct archive_write *a, struct xml_writer *writer,
     struct file *file)
     struct file *file)
 {
 {
 	struct xar *xar;
 	struct xar *xar;
 	const char *filetype, *filelink, *fflags;
 	const char *filetype, *filelink, *fflags;
 	struct archive_string linkto;
 	struct archive_string linkto;
 	struct heap_data *heap;
 	struct heap_data *heap;
-	unsigned char *tmp;
 	const char *p;
 	const char *p;
 	size_t len;
 	size_t len;
-	int r, r2, l, ll;
+	int r, r2;
 
 
 	xar = (struct xar *)a->format_data;
 	xar = (struct xar *)a->format_data;
 	r2 = ARCHIVE_OK;
 	r2 = ARCHIVE_OK;
@@ -1163,44 +1216,35 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 	/*
 	/*
 	 * Make a file name entry, "<name>".
 	 * Make a file name entry, "<name>".
 	 */
 	 */
-	l = ll = (int)archive_strlen(&(file->basename));
-	tmp = malloc(l);
-	if (tmp == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "Can't allocate memory");
-		return (ARCHIVE_FATAL);
-	}
-	r = UTF8Toisolat1(tmp, &l, BAD_CAST(file->basename.s), &ll);
-	free(tmp);
-	if (r < 0) {
-		r = xmlTextWriterStartElement(writer, BAD_CAST("name"));
+	if (!is_u8_zstring_latin1(file->basename.s)) {
+		r = xml_writer_start_element(writer, "name");
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
-		r = xmlTextWriterWriteAttribute(writer,
-		    BAD_CAST("enctype"), BAD_CAST("base64"));
+		r = xml_writer_write_attribute(writer,
+		    "enctype", "base64");
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
+			    "xml_writer_write_attribute() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
-		r = xmlTextWriterWriteBase64(writer, file->basename.s,
+		r = xml_writer_write_base64(writer, file->basename.s,
 		    0, (int)archive_strlen(&(file->basename)));
 		    0, (int)archive_strlen(&(file->basename)));
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteBase64() failed: %d", r);
+			    "xml_writer_write_base64() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 	} else {
 	} else {
@@ -1281,11 +1325,11 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 		break;
 		break;
 	case AE_IFCHR:
 	case AE_IFCHR:
 	case AE_IFBLK:
 	case AE_IFBLK:
-		r = xmlTextWriterStartElement(writer, BAD_CAST("device"));
+		r = xml_writer_start_element(writer, "device");
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 		r = xmlwrite_fstring(a, writer, "major",
 		r = xmlwrite_fstring(a, writer, "major",
@@ -1296,11 +1340,11 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 		    "%d", archive_entry_rdevminor(file->entry));
 		    "%d", archive_entry_rdevminor(file->entry));
 		if (r < 0)
 		if (r < 0)
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 		break;
 		break;
@@ -1436,19 +1480,19 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 
 
 		archive_entry_xattr_next(file->entry,
 		archive_entry_xattr_next(file->entry,
 		    &name, &value, &size);
 		    &name, &value, &size);
-		r = xmlTextWriterStartElement(writer, BAD_CAST("ea"));
+		r = xml_writer_start_element(writer, "ea");
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
-		r = xmlTextWriterWriteFormatAttribute(writer,
-		    BAD_CAST("id"), "%d", heap->id);
+		r = xml_writer_write_attributef(writer,
+		    "id", "%d", heap->id);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
+			    "xml_writer_write_attributef() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 		r = xmlwrite_heap(a, writer, heap);
 		r = xmlwrite_heap(a, writer, heap);
@@ -1458,11 +1502,11 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 		if (r < 0)
 		if (r < 0)
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 
 
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 	}
 	}
@@ -1471,11 +1515,11 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 	 * Make a file data entry, "<data>".
 	 * Make a file data entry, "<data>".
 	 */
 	 */
 	if (file->data.length > 0) {
 	if (file->data.length > 0) {
-		r = xmlTextWriterStartElement(writer, BAD_CAST("data"));
+		r = xml_writer_start_element(writer, "data");
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 
 
@@ -1483,21 +1527,21 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 		if (r < 0)
 		if (r < 0)
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 
 
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 	}
 	}
 
 
 	if (archive_strlen(&file->script) > 0) {
 	if (archive_strlen(&file->script) > 0) {
-		r = xmlTextWriterStartElement(writer, BAD_CAST("content"));
+		r = xml_writer_start_element(writer, "content");
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 
 
@@ -1510,11 +1554,11 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 		if (r < 0)
 		if (r < 0)
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 
 
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 	}
 	}
@@ -1530,8 +1574,9 @@ make_toc(struct archive_write *a)
 {
 {
 	struct xar *xar;
 	struct xar *xar;
 	struct file *np;
 	struct file *np;
-	xmlBufferPtr bp;
-	xmlTextWriterPtr writer;
+	struct xml_writer *writer;
+	const char* content;
+	size_t use;
 	int algsize;
 	int algsize;
 	int r, ret;
 	int r, ret;
 
 
@@ -1543,51 +1588,43 @@ make_toc(struct archive_write *a)
 	 * Initialize xml writer.
 	 * Initialize xml writer.
 	 */
 	 */
 	writer = NULL;
 	writer = NULL;
-	bp = xmlBufferCreate();
-	if (bp == NULL) {
-		archive_set_error(&a->archive, ENOMEM,
-		    "xmlBufferCreate() "
-		    "couldn't create xml buffer");
-		goto exit_toc;
-	}
-	writer = xmlNewTextWriterMemory(bp, 0);
-	if (writer == NULL) {
+	r = xml_writer_create(&writer);
+	if (r < 0) {
 		archive_set_error(&a->archive,
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlNewTextWriterMemory() "
-		    "couldn't create xml writer");
+		    "xml_writer_create() failed: %d", r);
 		goto exit_toc;
 		goto exit_toc;
 	}
 	}
-	r = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
+	r = xml_writer_set_indent(writer, 4);
 	if (r < 0) {
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartDocument() failed: %d", r);
+		    "xml_writer_set_indent() failed: %d", r);
 		goto exit_toc;
 		goto exit_toc;
 	}
 	}
-	r = xmlTextWriterSetIndent(writer, 4);
+	r = xml_writer_start_document(writer);
 	if (r < 0) {
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterSetIndent() failed: %d", r);
+		    "xml_writer_start_document() failed: %d", r);
 		goto exit_toc;
 		goto exit_toc;
 	}
 	}
 
 
 	/*
 	/*
 	 * Start recording TOC
 	 * Start recording TOC
 	 */
 	 */
-	r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
+	r = xml_writer_start_element(writer, "xar");
 	if (r < 0) {
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartElement() failed: %d", r);
+		    "xml_writer_start_element() failed: %d", r);
 		goto exit_toc;
 		goto exit_toc;
 	}
 	}
-	r = xmlTextWriterStartElement(writer, BAD_CAST("toc"));
+	r = xml_writer_start_element(writer, "toc");
 	if (r < 0) {
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartDocument() failed: %d", r);
+		    "xml_writer_start_element() failed: %d", r);
 		goto exit_toc;
 		goto exit_toc;
 	}
 	}
 
 
@@ -1606,19 +1643,19 @@ make_toc(struct archive_write *a)
 		/*
 		/*
 		 * Record TOC checksum
 		 * Record TOC checksum
 		 */
 		 */
-		r = xmlTextWriterStartElement(writer, BAD_CAST("checksum"));
+		r = xml_writer_start_element(writer, "checksum");
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			goto exit_toc;
 			goto exit_toc;
 		}
 		}
-		r = xmlTextWriterWriteAttribute(writer, BAD_CAST("style"),
-		    BAD_CAST_CONST(getalgname(xar->opt_toc_sumalg)));
+		r = xml_writer_write_attribute(writer, "style",
+		    getalgname(xar->opt_toc_sumalg));
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
+			    "xml_writer_write_attribute() failed: %d", r);
 			goto exit_toc;
 			goto exit_toc;
 		}
 		}
 
 
@@ -1636,11 +1673,11 @@ make_toc(struct archive_write *a)
 		if (r < 0)
 		if (r < 0)
 			goto exit_toc;
 			goto exit_toc;
 
 
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			goto exit_toc;
 			goto exit_toc;
 		}
 		}
 	}
 	}
@@ -1656,32 +1693,32 @@ make_toc(struct archive_write *a)
 		if (np->dir && np->children.first != NULL) {
 		if (np->dir && np->children.first != NULL) {
 			/* Enter to sub directories. */
 			/* Enter to sub directories. */
 			np = np->children.first;
 			np = np->children.first;
-			r = xmlTextWriterStartElement(writer,
-			    BAD_CAST("file"));
+			r = xml_writer_start_element(writer,
+			    "file");
 			if (r < 0) {
 			if (r < 0) {
 				archive_set_error(&a->archive,
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
 				    ARCHIVE_ERRNO_MISC,
-				    "xmlTextWriterStartElement() "
+				    "xml_writer_start_element() "
 				    "failed: %d", r);
 				    "failed: %d", r);
 				goto exit_toc;
 				goto exit_toc;
 			}
 			}
-			r = xmlTextWriterWriteFormatAttribute(
-			    writer, BAD_CAST("id"), "%d", np->id);
+			r = xml_writer_write_attributef(
+			    writer, "id", "%d", np->id);
 			if (r < 0) {
 			if (r < 0) {
 				archive_set_error(&a->archive,
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
 				    ARCHIVE_ERRNO_MISC,
-				    "xmlTextWriterWriteAttribute() "
+				    "xml_writer_write_attributef() "
 				    "failed: %d", r);
 				    "failed: %d", r);
 				goto exit_toc;
 				goto exit_toc;
 			}
 			}
 			continue;
 			continue;
 		}
 		}
 		while (np != np->parent) {
 		while (np != np->parent) {
-			r = xmlTextWriterEndElement(writer);
+			r = xml_writer_end_element(writer);
 			if (r < 0) {
 			if (r < 0) {
 				archive_set_error(&a->archive,
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
 				    ARCHIVE_ERRNO_MISC,
-				    "xmlTextWriterEndElement() "
+				    "xml_writer_end_element() "
 				    "failed: %d", r);
 				    "failed: %d", r);
 				goto exit_toc;
 				goto exit_toc;
 			}
 			}
@@ -1690,21 +1727,21 @@ make_toc(struct archive_write *a)
 				np = np->parent;
 				np = np->parent;
 			} else {
 			} else {
 				np = np->chnext;
 				np = np->chnext;
-				r = xmlTextWriterStartElement(writer,
-				    BAD_CAST("file"));
+				r = xml_writer_start_element(writer,
+				    "file");
 				if (r < 0) {
 				if (r < 0) {
 					archive_set_error(&a->archive,
 					archive_set_error(&a->archive,
 					    ARCHIVE_ERRNO_MISC,
 					    ARCHIVE_ERRNO_MISC,
-					    "xmlTextWriterStartElement() "
+					    "xml_writer_start_element() "
 					    "failed: %d", r);
 					    "failed: %d", r);
 					goto exit_toc;
 					goto exit_toc;
 				}
 				}
-				r = xmlTextWriterWriteFormatAttribute(
-				    writer, BAD_CAST("id"), "%d", np->id);
+				r = xml_writer_write_attributef(
+				    writer, "id", "%d", np->id);
 				if (r < 0) {
 				if (r < 0) {
 					archive_set_error(&a->archive,
 					archive_set_error(&a->archive,
 					    ARCHIVE_ERRNO_MISC,
 					    ARCHIVE_ERRNO_MISC,
-					    "xmlTextWriterWriteAttribute() "
+					    "xml_writer_write_attributef() "
 					    "failed: %d", r);
 					    "failed: %d", r);
 					goto exit_toc;
 					goto exit_toc;
 				}
 				}
@@ -1713,31 +1750,40 @@ make_toc(struct archive_write *a)
 		}
 		}
 	} while (np != np->parent);
 	} while (np != np->parent);
 
 
-	r = xmlTextWriterEndDocument(writer);
+	r = xml_writer_end_document(writer);
 	if (r < 0) {
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterEndDocument() failed: %d", r);
+		    "xml_writer_end_document() failed: %d", r);
 		goto exit_toc;
 		goto exit_toc;
 	}
 	}
+
+	r = xml_writer_get_final_content_and_length(writer, &content, &use);
+	if (r < 0) {
+		archive_set_error(&a->archive,
+		    ARCHIVE_ERRNO_MISC,
+		    "xml_writer_get_final_content_and_length() failed: %d", r);
+		goto exit_toc;
+	}
+
 #if DEBUG_PRINT_TOC
 #if DEBUG_PRINT_TOC
 	fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n",
 	fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n",
-	    strlen((const char *)bp->content), bp->content);
+	    (int)strlen(content), content);
 #endif
 #endif
 
 
 	/*
 	/*
 	 * Compress the TOC and calculate the sum of the TOC.
 	 * Compress the TOC and calculate the sum of the TOC.
 	 */
 	 */
 	xar->toc.temp_offset = xar->temp_offset;
 	xar->toc.temp_offset = xar->temp_offset;
-	xar->toc.size = bp->use;
+	xar->toc.size = (uint64_t)use;
 	checksum_init(&(xar->a_sumwrk), xar->opt_toc_sumalg);
 	checksum_init(&(xar->a_sumwrk), xar->opt_toc_sumalg);
 
 
 	r = compression_init_encoder_gzip(&(a->archive),
 	r = compression_init_encoder_gzip(&(a->archive),
 	    &(xar->stream), 6, 1);
 	    &(xar->stream), 6, 1);
 	if (r != ARCHIVE_OK)
 	if (r != ARCHIVE_OK)
 		goto exit_toc;
 		goto exit_toc;
-	xar->stream.next_in = bp->content;
-	xar->stream.avail_in = bp->use;
+	xar->stream.next_in = (const unsigned char *)content;
+	xar->stream.avail_in = use;
 	xar->stream.total_in = 0;
 	xar->stream.total_in = 0;
 	xar->stream.next_out = xar->wbuff;
 	xar->stream.next_out = xar->wbuff;
 	xar->stream.avail_out = sizeof(xar->wbuff);
 	xar->stream.avail_out = sizeof(xar->wbuff);
@@ -1768,9 +1814,7 @@ make_toc(struct archive_write *a)
 	ret = ARCHIVE_OK;
 	ret = ARCHIVE_OK;
 exit_toc:
 exit_toc:
 	if (writer)
 	if (writer)
-		xmlFreeTextWriter(writer);
-	if (bp)
-		xmlBufferFree(bp);
+		xml_writer_destroy(writer);
 
 
 	return (ret);
 	return (ret);
 }
 }
@@ -3251,4 +3295,404 @@ getalgname(enum sumalg sumalg)
 	}
 	}
 }
 }
 
 
+#if HAVE_LIBXML_XMLWRITER_H
+
+#define BAD_CAST_CONST (const xmlChar *)
+
+struct xml_writer {
+	xmlTextWriterPtr writer;
+	xmlBufferPtr bp;
+	unsigned int indent;
+};
+
+static int
+xml_writer_create(struct xml_writer **pctx)
+{
+	struct xml_writer *ctx = calloc(1, sizeof(struct xml_writer));
+	if (ctx == NULL) {
+		return (-1);
+	}
+
+	ctx->bp = xmlBufferCreate();
+	if (ctx->bp == NULL) {
+		free(ctx);
+		return (-1);
+	}
+
+	ctx->writer = xmlNewTextWriterMemory(ctx->bp, 0);
+	if (ctx->writer == NULL) {
+		xmlBufferFree(ctx->bp);
+		free(ctx);
+		return (-1);
+	}
+
+	*pctx = ctx;
+	return (0);
+}
+
+static int
+xml_writer_destroy(struct xml_writer *ctx)
+{
+	xmlFreeTextWriter(ctx->writer);
+	xmlBufferFree(ctx->bp);
+	free(ctx);
+	return (0);
+}
+
+static int
+xml_writer_start_document(struct xml_writer *ctx)
+{
+	int r;
+	r = xmlTextWriterStartDocument(ctx->writer, "1.0", "UTF-8", NULL);
+	if (r < 0) {
+		return (r);
+	}
+
+	r = xmlTextWriterSetIndent(ctx->writer, (int)ctx->indent);
+	return (r);
+}
+
+static int
+xml_writer_end_document(struct xml_writer *ctx)
+{
+	return (xmlTextWriterEndDocument(ctx->writer));
+}
+
+static int
+xml_writer_set_indent(struct xml_writer *ctx, unsigned int indent)
+{
+	/* libxml2 only lets you set the indent after starting the document */
+	ctx->indent = indent;
+	return (0);
+}
+
+static int
+xml_writer_start_element(struct xml_writer *ctx, const char *localName)
+{
+	return (xmlTextWriterStartElement(ctx->writer,
+	    BAD_CAST_CONST(localName)));
+}
+
+static int
+xml_writer_write_attribute(struct xml_writer *ctx,
+    const char *key, const char *value)
+{
+	return (xmlTextWriterWriteAttribute(ctx->writer,
+	    BAD_CAST_CONST(key), BAD_CAST_CONST(value)));
+}
+
+static int
+xml_writer_write_attributef(struct xml_writer *ctx,
+    const char *key, const char *format, ...)
+{
+	va_list ap;
+	int ret;
+	va_start(ap, format);
+	ret = xmlTextWriterWriteVFormatAttribute(ctx->writer,
+	    BAD_CAST_CONST(key), format, ap);
+	va_end(ap);
+	return (ret);
+}
+
+static int
+xml_writer_write_string(struct xml_writer *ctx, const char *string)
+{
+	return (xmlTextWriterWriteString(ctx->writer, BAD_CAST_CONST(string)));
+}
+
+static int
+xml_writer_write_base64(struct xml_writer* ctx,
+    const char *data, size_t start, size_t len)
+{
+	return (xmlTextWriterWriteBase64(ctx->writer, data,
+	    (int)start, (int)len));
+}
+
+static int
+xml_writer_end_element(struct xml_writer *ctx)
+{
+	return (xmlTextWriterEndElement(ctx->writer));
+}
+
+static int
+xml_writer_get_final_content_and_length(struct xml_writer *ctx,
+    const char **out, size_t *size)
+{
+	*out = (const char*)ctx->bp->content;
+	*size = (size_t)ctx->bp->use;
+	return (0);
+}
+
+#elif HAVE_XMLLITE_H
+
+struct xml_writer {
+	IXmlWriter *writer;
+	IStream *stream;
+	HGLOBAL global;
+};
+
+static int
+xml_writer_create(struct xml_writer **pctx)
+{
+	struct xml_writer *ctx;
+	HRESULT hr;
+
+	ctx = calloc(1, sizeof(struct xml_writer));
+	if (ctx == NULL) {
+		return (E_OUTOFMEMORY);
+	}
+
+	hr = CreateStreamOnHGlobal(NULL, TRUE, &ctx->stream);
+	if (FAILED(hr)) {
+		free(ctx);
+		return (hr);
+	}
+
+	hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&ctx->writer, NULL);
+	if (FAILED(hr)) {
+		ctx->stream->lpVtbl->Release(ctx->stream);
+		free(ctx);
+		return (hr);
+	}
+
+	hr = ctx->writer->lpVtbl->SetOutput(ctx->writer,
+	    (IUnknown *)ctx->stream);
+	if (FAILED(hr)) {
+		ctx->writer->lpVtbl->Release(ctx->writer);
+		ctx->stream->lpVtbl->Release(ctx->stream);
+		free(ctx);
+		return (hr);
+	}
+
+	*pctx = ctx;
+	return (S_OK);
+}
+
+static int
+xml_writer_destroy(struct xml_writer *ctx)
+{
+	if (ctx->global)
+		GlobalUnlock(ctx->global);
+	ctx->writer->lpVtbl->Release(ctx->writer); /* Destroys only writer */
+	ctx->stream->lpVtbl->Release(ctx->stream); /* Destroys stream, global */
+	free(ctx);
+	return (S_OK);
+}
+
+static int
+xml_writer_start_document(struct xml_writer *ctx)
+{
+	return ctx->writer->lpVtbl->WriteStartDocument(ctx->writer,
+	    XmlStandalone_Omit);
+}
+
+static int
+xml_writer_end_document(struct xml_writer *ctx)
+{
+	return ctx->writer->lpVtbl->WriteEndDocument(ctx->writer);
+}
+
+static int
+xml_writer_set_indent(struct xml_writer *ctx, unsigned int indent)
+{
+	/* Windows' xmllite does not support indent sizes; will always be 2 */
+	(void)indent;
+	return ctx->writer->lpVtbl->SetProperty(ctx->writer,
+	    XmlWriterProperty_Indent, (LONG_PTR)TRUE);
+}
+
+static int
+xml_writer_start_element(struct xml_writer *ctx, const char *localName)
+{
+	struct archive_wstring as;
+	HRESULT hr;
+	archive_string_init(&as);
+	if (archive_wstring_append_from_mbs(&as, localName,
+	    strlen(localName))) {
+		hr = E_OUTOFMEMORY;
+		goto exit_hr;
+	}
+	hr = ctx->writer->lpVtbl->WriteStartElement(ctx->writer, NULL,
+	    as.s, NULL);
+
+exit_hr:
+	archive_wstring_free(&as);
+	return hr;
+}
+
+static int
+xml_writer_write_attribute(struct xml_writer *ctx,
+    const char *key, const char *value)
+{
+	struct archive_wstring ask, asv;
+	HRESULT hr;
+	archive_string_init(&ask);
+	archive_string_init(&asv);
+	if (archive_wstring_append_from_mbs(&ask, key, strlen(key))) {
+		hr = E_OUTOFMEMORY;
+		goto exit_hr;
+	}
+	if (archive_wstring_append_from_mbs(&asv, value, strlen(value))) {
+		hr = E_OUTOFMEMORY;
+		goto exit_hr;
+	}
+	hr = ctx->writer->lpVtbl->WriteAttributeString(ctx->writer, NULL,
+	    ask.s, NULL, asv.s);
+
+exit_hr:
+	archive_wstring_free(&asv);
+	archive_wstring_free(&ask);
+	return hr;
+}
+
+static int
+xml_writer_write_attributef(struct xml_writer *ctx,
+    const char *key, const char *format, ...)
+{
+	struct archive_wstring ask, asv;
+	struct archive_string asf;
+	HRESULT hr;
+	va_list ap;
+
+	va_start(ap, format);
+	archive_string_init(&ask);
+	archive_string_init(&asv);
+	archive_string_init(&asf);
+
+	if (archive_wstring_append_from_mbs(&ask, key, strlen(key))) {
+		hr = E_OUTOFMEMORY;
+		goto exit_hr;
+	}
+
+	archive_string_vsprintf(&asf, format, ap);
+	if (archive_wstring_append_from_mbs(&asv, asf.s, asf.length)) {
+		hr = E_OUTOFMEMORY;
+		goto exit_hr;
+	}
+
+	hr = ctx->writer->lpVtbl->WriteAttributeString(ctx->writer, NULL,
+	    ask.s, NULL, asv.s);
+
+exit_hr:
+	archive_string_free(&asf);
+	archive_wstring_free(&asv);
+	archive_wstring_free(&ask);
+	va_end(ap);
+
+	return hr;
+}
+
+static int
+xml_writer_write_string(struct xml_writer *ctx, const char *string)
+{
+	struct archive_wstring as;
+	HRESULT hr;
+	archive_string_init(&as);
+	if (archive_wstring_append_from_mbs(&as, string, strlen(string))) {
+		hr = E_OUTOFMEMORY;
+		goto exit_hr;
+	}
+	hr = ctx->writer->lpVtbl->WriteString(ctx->writer, as.s);
+
+exit_hr:
+	archive_wstring_free(&as);
+	return hr;
+}
+
+static const wchar_t base64[] = {
+	L'A', L'B', L'C', L'D', L'E', L'F', L'G', L'H',
+	L'I', L'J', L'K', L'L', 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', L'a', L'b', L'c', L'd', L'e', L'f',
+	L'g', L'h', L'i', L'j', L'k', L'l', 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', L'0', L'1', L'2', L'3',
+	L'4', L'5', L'6', L'7', L'8', L'9', L'+', L'/'
+};
+
+static void
+la_b64_wencode(struct archive_wstring *as, const unsigned char *p, size_t len)
+{
+	int c;
+
+	for (; len >= 3; p += 3, len -= 3) {
+		c = p[0] >> 2;
+		archive_wstrappend_wchar(as, base64[c]);
+		c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4);
+		archive_wstrappend_wchar(as, base64[c]);
+		c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6);
+		archive_wstrappend_wchar(as, base64[c]);
+		c = p[2] & 0x3f;
+		archive_wstrappend_wchar(as, base64[c]);
+	}
+	if (len > 0) {
+		c = p[0] >> 2;
+		archive_wstrappend_wchar(as, base64[c]);
+		c = (p[0] & 0x03) << 4;
+		if (len == 1) {
+			archive_wstrappend_wchar(as, base64[c]);
+			archive_wstrappend_wchar(as, '=');
+			archive_wstrappend_wchar(as, '=');
+		} else {
+			c |= (p[1] & 0xf0) >> 4;
+			archive_wstrappend_wchar(as, base64[c]);
+			c = (p[1] & 0x0f) << 2;
+			archive_wstrappend_wchar(as, base64[c]);
+			archive_wstrappend_wchar(as, '=');
+		}
+	}
+}
+
+static int
+xml_writer_write_base64(struct xml_writer* ctx,
+    const char *data, size_t start, size_t len)
+{
+	struct archive_wstring as;
+	HRESULT hr;
+	archive_string_init(&as);
+	la_b64_wencode(&as, (const unsigned char *)data + start, len - start);
+	hr = ctx->writer->lpVtbl->WriteString(ctx->writer, as.s);
+	archive_wstring_free(&as);
+	return hr;
+}
+
+static int
+xml_writer_end_element(struct xml_writer *ctx)
+{
+	return ctx->writer->lpVtbl->WriteEndElement(ctx->writer);
+}
+
+static int
+xml_writer_get_final_content_and_length(struct xml_writer *ctx,
+    const char **out, size_t *size)
+{
+	HGLOBAL gbl;
+	HRESULT hr;
+
+	hr = ctx->writer->lpVtbl->Flush(ctx->writer);
+	if (FAILED(hr)) {
+		return (hr);
+	}
+
+	hr = GetHGlobalFromStream(ctx->stream, &gbl);
+	if (FAILED(hr)) {
+		return (hr);
+	}
+
+	*out = (const char *)GlobalLock(gbl);
+	if (*out == NULL) {
+		hr = HRESULT_FROM_WIN32(GetLastError());
+		return (hr);
+	}
+
+	/* GlobalUnlock is called in
+	 * xml_writer_destroy.
+	 */
+	*size = (size_t)GlobalSize(gbl);
+	ctx->global = gbl;
+	return (hr);
+}
+
+#endif /* HAVE_LIBXML_XMLWRITER_H */
+
 #endif /* Support xar format */
 #endif /* Support xar format */

File diff suppressed because it is too large
+ 735 - 54
Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c


+ 35 - 8
Utilities/cmlibarchive/libarchive/archive_write_set_options.3

@@ -263,7 +263,7 @@ decimal integer specifying log2 window size in bytes. Values from
 The value is interpreted as a decimal integer specifying the
 The value is interpreted as a decimal integer specifying the
 number of threads for multi-threaded zstd compression.
 number of threads for multi-threaded zstd compression.
 If set to 0, zstd will attempt to detect and use the number
 If set to 0, zstd will attempt to detect and use the number
-of physical CPU cores.
+of active physical CPU cores.
 .El
 .El
 .It Format 7zip
 .It Format 7zip
 .Bl -tag -compact -width indent
 .Bl -tag -compact -width indent
@@ -274,9 +274,10 @@ The value is one of
 .Dq deflate ,
 .Dq deflate ,
 .Dq bzip2 ,
 .Dq bzip2 ,
 .Dq lzma1 ,
 .Dq lzma1 ,
-.Dq lzma2
+.Dq lzma2 ,
+.Dq ppmd ,
 or
 or
-.Dq ppmd
+.Dq zstd
 to indicate how the following entries should be compressed.
 to indicate how the following entries should be compressed.
 The values
 The values
 .Dq store
 .Dq store
@@ -289,9 +290,16 @@ and other special entries.
 The value is interpreted as a decimal integer specifying the
 The value is interpreted as a decimal integer specifying the
 compression level.
 compression level.
 Values between 0 and 9 are supported, with the exception of bzip2
 Values between 0 and 9 are supported, with the exception of bzip2
-which only supports values between 1 and 9.
+which only supports values between 1 and 9, and zstd which may
+support negative values depending on the library version and
+commonly used values 1 through 22.
 The interpretation of the compression level depends on the chosen
 The interpretation of the compression level depends on the chosen
 compression method.
 compression method.
+.It Cm threads
+The value is interpreted as a decimal integer specifying the
+number of threads for multi-threaded compression (for compressors
+like zstd that support it). If set to 0, an attempt will be made
+to discover the number of CPU cores.
 .El
 .El
 .It Format bin
 .It Format bin
 .Bl -tag -compact -width indent
 .Bl -tag -compact -width indent
@@ -632,9 +640,13 @@ and
 .Bl -tag -compact -width indent
 .Bl -tag -compact -width indent
 .It Cm compression
 .It Cm compression
 The value is either
 The value is either
-.Dq store
+.Dq store ,
+.Dq deflate ,
+.Dq bzip2 ,
+.Dq lzma ,
+.Dq xz ,
 or
 or
-.Dq deflate
+.Dq zstd
 to indicate how the following entries should be compressed.
 to indicate how the following entries should be compressed.
 Note that this setting is ignored for directories, symbolic links,
 Note that this setting is ignored for directories, symbolic links,
 and other special entries.
 and other special entries.
@@ -645,8 +657,23 @@ Values between 0 and 9 are supported.
 A compression level of 0 switches the compression method to
 A compression level of 0 switches the compression method to
 .Dq store ,
 .Dq store ,
 other values will enable
 other values will enable
-.Dq deflate
-compression with the given level.
+.Dq deflate ,
+.Dq bzip2 ,
+.Dq lzma ,
+or
+.Dq zstd
+compression (in order of priority, depending on what libraries 
+are linked) with the given level.
+.It Cm threads
+The value is interpreted as a decimal integer specifying the
+number of threads to use for compression.
+It is supported only for
+.Dq xz
+or
+.Dq zstd
+compression and ignored for any other.
+A threads value of 0 is a special one requesting to detect and use as
+many threads as the number of active physical CPU cores.
 .It Cm encryption
 .It Cm encryption
 Enable encryption using traditional zip encryption.
 Enable encryption using traditional zip encryption.
 .It Cm encryption Ns = Ns Ar type
 .It Cm encryption Ns = Ns Ar type

+ 18 - 2
Utilities/cmlibarchive/libarchive/libarchive-formats.5

@@ -327,10 +327,26 @@ by the usual environment variables.
 Libarchive can read and write zip format archives that have
 Libarchive can read and write zip format archives that have
 uncompressed entries and entries compressed with the
 uncompressed entries and entries compressed with the
 .Dq deflate
 .Dq deflate
+,
+.Dq LZMA
+,
+.Dq XZ
+,
+.Dq BZIP2
+and
+.Dq ZSTD
+algorithms.
+Libarchive can also read, but not write, zip format archives that
+have entries compressed with the
+.Dq PPMd
 algorithm.
 algorithm.
 Other zip compression algorithms are not supported.
 Other zip compression algorithms are not supported.
-It can extract jar archives, archives that use Zip64 extensions and
-self-extracting zip archives.
+The extensions supported by libarchive are Zip64, Libarchive's
+extensions to better support streaming, PKZIP's traditional
+ZIP encryption, Info-ZIP's Unix extra fields, extra time, and
+Unicode path, as well as WinZIP's AES encryption.
+It can extract jar archives, __MACOSX resource forks extension
+for OS X, and self-extracting zip archives.
 Libarchive can use either of two different strategies for
 Libarchive can use either of two different strategies for
 reading Zip archives:
 reading Zip archives:
 a streaming strategy which is fast and can handle extremely
 a streaming strategy which is fast and can handle extremely

Some files were not shown because too many files changed in this diff