Răsfoiți Sursa

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 2 săptămâni în urmă
părinte
comite
cca334aa26
81 a modificat fișierele cu 4255 adăugiri și 1224 ștergeri
  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.h
 
-  cm_get_date.h
-  cm_get_date.c
+  cm_parse_date.h
+  cm_parse_date.c
   cm_utf8.h
   cm_utf8.c
   cm_codecvt.hxx

+ 1 - 0
Source/Modules/CMakeBuildUtilities.cmake

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

+ 2 - 2
Source/cmArchiveWrite.cxx

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

+ 3 - 3
Source/cmCTest.cxx

@@ -38,7 +38,7 @@
 #  include <unistd.h> // IWYU pragma: keep
 #endif
 
-#include "cm_get_date.h"
+#include "cm_parse_date.h"
 
 #include "cmCMakePresetsGraph.h"
 #include "cmCTestBuildAndTest.h"
@@ -214,7 +214,7 @@ struct tm* cmCTest::GetNightlyTime(std::string const& str, bool tomorrowtag)
   char buf[1024];
   std::snprintf(buf, sizeof(buf), "%d%02d%02d %s", lctime->tm_year + 1900,
                 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,
              "   Get the nightly start time: " << ntime << std::endl);
   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(),
            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) {
     this->Impl->StopTime = std::chrono::system_clock::time_point();
     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
 
 /** 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
 } /* extern "C" */

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

@@ -8,7 +8,7 @@ readonly name="LibArchive"
 readonly ownership="LibArchive Upstream <[email protected]>"
 readonly subtree="Utilities/cmlibarchive"
 readonly repo="https://github.com/libarchive/libarchive.git"
-readonly tag="v3.7.9"
+readonly tag="v3.8.1"
 readonly shortlog=false
 readonly paths="
   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.
 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
 # necessary but this shows you what value the variables initially have.
 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_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_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_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)
@@ -378,10 +384,12 @@ ENDMACRO (GENERATE_LIST_H)
 # Generate installation rules for man pages.
 #
 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)
 #
 # 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)
 ELSE(ENABLE_LIBB2)
   SET(LIBB2_FOUND FALSE) # Override cached value
+  UNSET(LIBB2_PKGCONFIG_VERSION CACHE)
 ENDIF(ENABLE_LIBB2)
 IF(LIBB2_FOUND)
   SET(HAVE_LIBB2 1)
@@ -614,8 +623,13 @@ IF(LIBB2_FOUND)
   SET(CMAKE_REQUIRED_INCLUDES ${LIBB2_INCLUDE_DIR})
   CHECK_FUNCTION_EXISTS(blake2sp_init HAVE_LIBB2)
   CMAKE_POP_CHECK_STATE()
+  pkg_check_modules(LIBB2 libb2)
+  IF(LIBB2_VERSION)
+    SET(LIBB2_PKGCONFIG_VERSION LIBB2_VERSION)
+  ENDIF(LIBB2_VERSION)
 ELSE(LIBB2_FOUND)
   SET(ARCHIVE_BLAKE2 TRUE)
+  UNSET(LIBB2_PKGCONFIG_VERSION CACHE)
 ENDIF(LIBB2_FOUND)
 #
 # Find LZ4
@@ -681,6 +695,7 @@ IF(ZSTD_FOUND)
   SET(CMAKE_REQUIRED_INCLUDES ${ZSTD_INCLUDE_DIR})
   CHECK_FUNCTION_EXISTS(ZSTD_decompressStream HAVE_LIBZSTD)
   CHECK_FUNCTION_EXISTS(ZSTD_compressStream HAVE_ZSTD_compressStream)
+  CHECK_FUNCTION_EXISTS(ZSTD_minCLevel HAVE_ZSTD_minCLevel)
   #
   # TODO: test for static library.
   #
@@ -690,7 +705,6 @@ ENDIF(ZSTD_FOUND)
 MARK_AS_ADVANCED(CLEAR ZSTD_INCLUDE_DIR)
 MARK_AS_ADVANCED(CLEAR ZSTD_LIBRARY)
 
-
 #
 # 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/md.h" HAVE_MBEDTLS_MD_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)
   MARK_AS_ADVANCED(CLEAR MBEDTLS_INCLUDE_DIRS)
   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/ripemd160.h" HAVE_NETTLE_RIPEMD160_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)
   MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR)
   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_INCLUDES ${OPENSSL_INCLUDE_DIR})
     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)
   ENDIF(OPENSSL_FOUND)
 ELSE()
@@ -1074,7 +1089,6 @@ main(int argc, char **argv)
         	"${OUTPUT}\n"
         	"Source file was:\n${SOURCE}\n")
 	ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
-
       ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
       ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO})
     ENDFOREACH(CRYPTO)
@@ -1168,6 +1182,7 @@ IF(ENABLE_ICONV)
       CHECK_ICONV("libiconv" "const")
       CHECK_ICONV("libiconv" "")
       IF (HAVE_ICONV)
+        SET(HAVE_LIBICONV 1)
         LIST(APPEND ADDITIONAL_LIBS ${LIBICONV_PATH})
       ENDIF(HAVE_ICONV)
     ENDIF(NOT HAVE_ICONV AND LIBICONV_PATH)
@@ -1211,6 +1226,7 @@ ELSE(ENABLE_ICONV)
   # (once enabled).
   UNSET(HAVE_LOCALE_CHARSET CACHE)
   UNSET(HAVE_ICONV CACHE)
+  UNSET(HAVE_LIBICONV CACHE)
   UNSET(HAVE_ICONV_libc_ CACHE)
   UNSET(HAVE_ICONV_libc_const CACHE)
   UNSET(HAVE_ICONV_libiconv_ CACHE)
@@ -1240,6 +1256,7 @@ IF(LIBXML2_FOUND)
   SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
   CHECK_INCLUDE_FILES("libxml/xmlreader.h" HAVE_LIBXML_XMLREADER_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.
   TRY_MACRO_FOR_LIBRARY(
     "${ICONV_INCLUDE_DIR};${LIBXML2_INCLUDE_DIR}"
@@ -1267,6 +1284,25 @@ ELSE(LIBXML2_FOUND)
     SET(HAVE_LIBEXPAT 1)
     LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H)
     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(LIBXML2_FOUND)
 
@@ -1757,11 +1793,16 @@ IF(ENABLE_XATTR)
   CHECK_LIBRARY_EXISTS(attr "setxattr" "" HAVE_LIBATTR)
   IF(HAVE_LIBATTR)
     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)
     IF(HAVE_LIBATTR_GNU)
       SET(CMAKE_REQUIRED_LIBRARIES "gnu")
     ENDIF()
+    UNSET(LIBATTR_PKGCONFIG_VERSION CACHE)
   ENDIF(HAVE_LIBATTR)
   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)
@@ -1879,6 +1920,12 @@ IF(ENABLE_ACL)
     SET(CMAKE_REQUIRED_LIBRARIES "acl")
     FIND_LIBRARY(ACL_LIBRARY NAMES acl)
     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)
 
   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")
     FIND_LIBRARY(RICHACL_LIBRARY NAMES richacl)
     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)
 
   CHECK_STRUCT_HAS_MEMBER("struct richace" e_type "sys/richacl.h"
@@ -2121,7 +2174,7 @@ ENDIF()
 #
 # 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 one's computer.
@@ -2133,7 +2186,7 @@ IF(WIN32 AND NOT CYGWIN)
             FILES_MATCHING PATTERN "*.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
 
 * 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
   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 ;).
 IF(ENABLE_INSTALL)
   INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/build/pkgconfig/libarchive.pc
-          DESTINATION "lib/pkgconfig")
+          DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
 ENDIF()

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

@@ -513,6 +513,9 @@
 /* Define to 1 if you have the `gcc' library (-lgcc). */
 #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). */
 #cmakedefine HAVE_LIBLZ4 1
 
@@ -549,6 +552,9 @@
 /* Define to 1 if you have the <libxml/xmlwriter.h> header file. */
 #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). */
 #cmakedefine HAVE_LIBZ 1
 
@@ -558,6 +564,9 @@
 /* Define to 1 if you have the ZSTD_compressStream function. */
 #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. */
 #cmakedefine HAVE_LIMITS_H 1
 
@@ -649,6 +658,9 @@
 /* Define to 1 if you have the <mbedtls/pkcs5.h> header file. */
 #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. */
 #cmakedefine HAVE_MBRTOWC 1
 
@@ -694,6 +706,9 @@
 /* Define to 1 if you have the <nettle/sha.h> header file. */
 #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. */
 #cmakedefine HAVE_NL_LANGINFO 1
 
@@ -703,6 +718,9 @@
 /* Define to 1 if you have the <openssl/evp.h> header file. */
 #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. */
 #cmakedefine HAVE_PATHS_H 1
 
@@ -922,7 +940,6 @@
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #cmakedefine HAVE_SYS_STAT_H 1
 
-
 /* Define to 1 if you have the <sys/sysmacros.h> header file. */
 #cmakedefine HAVE_SYS_SYSMACROS_H 1
 
@@ -1046,6 +1063,9 @@
 /* Define to 1 if you have a working FS_IOC_GETFLAGS */
 #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. */
 #cmakedefine HAVE_ZLIB_H 1
 
@@ -1103,6 +1123,15 @@
 /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
 #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.
  */

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

@@ -1,4 +1,12 @@
 #!/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
 #

+ 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_strmode.c
   archive_entry_xattr.c
-  archive_getdate.c
-  archive_getdate.h
   archive_hmac.c
   archive_hmac_private.h
   archive_match.c
@@ -49,6 +47,7 @@ SET(libarchive_SOURCES
   archive_options_private.h
   archive_pack_dev.h
   archive_pack_dev.c
+  archive_parse_date.c
   archive_pathmatch.c
   archive_pathmatch.h
   archive_platform.h
@@ -117,6 +116,8 @@ SET(libarchive_SOURCES
   archive_string.h
   archive_string_composition.h
   archive_string_sprintf.c
+  archive_time.c
+  archive_time_private.h
   archive_util.c
   archive_version_details.c
   archive_virtual.c
@@ -256,7 +257,7 @@ IF(BUILD_SHARED_LIBS)
   ADD_LIBRARY(archive SHARED ${libarchive_SOURCES} ${include_HEADERS})
   TARGET_INCLUDE_DIRECTORIES(archive PUBLIC .)
   TARGET_LINK_LIBRARIES(archive ${ADDITIONAL_LIBS})
-  SET_TARGET_PROPERTIES(archive PROPERTIES 
+  SET_TARGET_PROPERTIES(archive PROPERTIES
                         VERSION ${SOVERSION_FULL}
                         SOVERSION ${SOVERSION}
                         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)
 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)
   # How to install the libraries
   IF(BUILD_SHARED_LIBS)
     INSTALL(TARGETS archive
             RUNTIME DESTINATION bin
-            LIBRARY DESTINATION lib
-            ARCHIVE DESTINATION lib)
+            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
   ENDIF(BUILD_SHARED_LIBS)
   INSTALL(TARGETS archive_static
           RUNTIME DESTINATION bin
-          LIBRARY DESTINATION lib
-          ARCHIVE DESTINATION lib)
+          LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+          ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
   INSTALL_MAN(${libarchive_MANS})
   INSTALL(FILES ${include_HEADERS} DESTINATION include)
 ENDIF()

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

@@ -34,12 +34,15 @@
  * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
  */
 /* 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 <stddef.h>  /* for wchar_t */
 #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 */
+#endif
 
 /*
  * Note: archive.h is for use outside of libarchive; the configuration
@@ -63,12 +66,15 @@
 #define __LA_INT64_T_DEFINED
 # if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
 typedef __int64 la_int64_t;
+typedef unsigned __int64 la_uint64_t;
 # else
 # include <unistd.h>  /* ssize_t */
 #  if defined(_SCO_DS) || defined(__osf__)
 typedef long long la_int64_t;
+typedef unsigned long long la_uint64_t;
 #  else
 typedef int64_t la_int64_t;
+typedef uint64_t la_uint64_t;
 #  endif
 # endif
 #endif
@@ -94,6 +100,22 @@ typedef ssize_t la_ssize_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
+
 /* Large file support for Android */
 #if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
 #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.
  */
-#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
 __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_liblz4_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. */
 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_cpio(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_iso9660(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_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_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 */
 __LA_DECL int archive_write_open(struct archive *, void *,
 		     archive_open_callback *, archive_write_callback *,
@@ -1080,6 +1125,10 @@ __LA_DECL int		 archive_compression(struct archive *)
 				__LA_DEPRECATED;
 #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 const char	*archive_error_string(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 *);
 
 /* Utility functions */
+#if ARCHIVE_VERSION_NUMBER < 4000000
 /* Convenience function to sort a NULL terminated list of strings */
 __LA_DECL int archive_utility_string_sort(char **);
+#endif
 
 #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. */
 		for (n = fields; n < numfields; ++n)
 			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 */
 			continue;
 		}
@@ -1683,7 +1688,12 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text,
 		for (n = fields; n < numfields; ++n)
 			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 */
 			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 */,
     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);
 
 	/* Skip beginning space characters. */
-	while (*s != '\0' && *s == ' ')
+	while (*s == ' ')
 		s++;
 	/* Copy non-space characters. */
 	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
 #include <bcrypt.h>
+#define	ARCHIVE_CRYPTOR_USE_CNG 1
 
 /* Common in other bcrypt implementations, but missing from VS2008. */
 #ifndef BCRYPT_SUCCESS
@@ -86,6 +87,7 @@ typedef struct {
 #include <mbedtls/aes.h>
 #include <mbedtls/md.h>
 #include <mbedtls/pkcs5.h>
+#define	ARCHIVE_CRYPTOR_USE_MBED 1
 
 #define AES_MAX_KEY_SIZE 32
 #define AES_BLOCK_SIZE 16
@@ -105,6 +107,7 @@ typedef struct {
 #endif
 #include <nettle/aes.h>
 #include <nettle/version.h>
+#define	ARCHIVE_CRYPTOR_USE_NETTLE 1
 
 typedef struct {
 #if NETTLE_VERSION_MAJOR < 3
@@ -125,6 +128,7 @@ typedef struct {
 
 #elif defined(HAVE_LIBCRYPTO)
 #include "archive_openssl_evp_private.h"
+#define	ARCHIVE_CRYPTOR_USE_OPENSSL 1
 #define AES_BLOCK_SIZE	16
 #define AES_MAX_KEY_SIZE 32
 
@@ -140,6 +144,10 @@ typedef struct {
 
 #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_MAX_KEY_SIZE 32
 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
 #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)
 
 static int
 __archive_md5init(archive_md5_ctx *ctx)
 {
   mbedtls_md5_init(ctx);
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_md5_starts(ctx) == 0)
+#else
   if (mbedtls_md5_starts_ret(ctx) == 0)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -245,7 +274,11 @@ static int
 __archive_md5update(archive_md5_ctx *ctx, const void *indata,
     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)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -254,7 +287,11 @@ __archive_md5update(archive_md5_ctx *ctx, const void *indata,
 static int
 __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) {
+#endif
     mbedtls_md5_free(ctx);
     return (ARCHIVE_OK);
   } else {
@@ -322,31 +359,6 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
   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
 
 static int
@@ -431,7 +443,11 @@ static int
 __archive_ripemd160init(archive_rmd160_ctx *ctx)
 {
   mbedtls_ripemd160_init(ctx);
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_ripemd160_starts(ctx) == 0)
+#else
   if (mbedtls_ripemd160_starts_ret(ctx) == 0)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -441,7 +457,11 @@ static int
 __archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
     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)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -450,7 +470,11 @@ __archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
 static int
 __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) {
+#endif
     mbedtls_ripemd160_free(ctx);
     return (ARCHIVE_OK);
   } else {
@@ -616,13 +640,42 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
   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)
 
 static int
 __archive_sha1init(archive_sha1_ctx *ctx)
 {
   mbedtls_sha1_init(ctx);
+#if MBEDTLS_VERSION_NUMBER > 0x03000000
+  if (mbedtls_sha1_starts(ctx) == 0)
+#else
   if (mbedtls_sha1_starts_ret(ctx) == 0)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -632,7 +685,11 @@ static int
 __archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
     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)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -641,7 +698,11 @@ __archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
 static int
 __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) {
+#endif
     mbedtls_sha1_free(ctx);
     return (ARCHIVE_OK);
   } else {
@@ -709,31 +770,6 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
   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
 
 static int
@@ -884,13 +920,42 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
   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)
 
 static int
 __archive_sha256init(archive_sha256_ctx *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)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -900,7 +965,11 @@ static int
 __archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
     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)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -909,7 +978,11 @@ __archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
 static int
 __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) {
+#endif
     mbedtls_sha256_free(ctx);
     return (ARCHIVE_OK);
   } else {
@@ -973,31 +1046,6 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
   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
 
 static int
@@ -1124,13 +1172,42 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
   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)
 
 static int
 __archive_sha384init(archive_sha384_ctx *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)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -1140,7 +1217,11 @@ static int
 __archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
     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)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -1149,7 +1230,11 @@ __archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
 static int
 __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) {
+#endif
     mbedtls_sha512_free(ctx);
     return (ARCHIVE_OK);
   } else {
@@ -1213,31 +1298,6 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
   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
 
 static int
@@ -1388,13 +1448,42 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
   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)
 
 static int
 __archive_sha512init(archive_sha512_ctx *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)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -1404,7 +1493,11 @@ static int
 __archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
     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)
+#endif
     return (ARCHIVE_OK);
   else
     return (ARCHIVE_FATAL);
@@ -1413,7 +1506,11 @@ __archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
 static int
 __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) {
+#endif
     mbedtls_sha512_free(ctx);
     return (ARCHIVE_OK);
   } else {
@@ -1477,31 +1574,6 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
   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
 
 static int
@@ -1536,11 +1608,12 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
  * 1. libc
  * 2. libc2
  * 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 =
 {

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

@@ -113,6 +113,7 @@
   defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
   defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
 #include <CommonCrypto/CommonDigest.h>
+#define	ARCHIVE_CRYPTO_CommonCrypto 1
 #endif
 
 /* mbed TLS crypto headers */
@@ -167,6 +168,7 @@
 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
 /* don't use bcrypt when XP needs to be supported */
 #include <bcrypt.h>
+#define	ARCHIVE_CRYPTO_CNG 1
 typedef struct {
   int   valid;
   BCRYPT_ALG_HANDLE  hAlg;
@@ -175,6 +177,7 @@ typedef struct {
 #else
 #include <windows.h>
 #include <wincrypt.h>
+#define	ARCHIVE_CRYPTO_WINCRYPT 1
 typedef struct {
   int   valid;
   HCRYPTPROV  cryptProv;
@@ -190,14 +193,16 @@ typedef MD5_CTX archive_md5_ctx;
 typedef MD5_CTX archive_md5_ctx;
 #elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
 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)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_md5_context archive_md5_ctx;
 #elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct md5_ctx archive_md5_ctx;
 #elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
 typedef EVP_MD_CTX *archive_md5_ctx;
-#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
-typedef Digest_CTX archive_md5_ctx;
 #else
 typedef unsigned char archive_md5_ctx;
 #endif
@@ -207,8 +212,10 @@ typedef RMD160_CTX archive_rmd160_ctx;
 #elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
 typedef RIPEMD160_CTX archive_rmd160_ctx;
 #elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_ripemd160_context archive_rmd160_ctx;
 #elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct ripemd160_ctx archive_rmd160_ctx;
 #elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
 typedef EVP_MD_CTX *archive_rmd160_ctx;
@@ -222,14 +229,16 @@ typedef SHA1_CTX archive_sha1_ctx;
 typedef SHA1_CTX archive_sha1_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
 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)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_sha1_context archive_sha1_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct sha1_ctx archive_sha1_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
 typedef EVP_MD_CTX *archive_sha1_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
-typedef Digest_CTX archive_sha1_ctx;
 #else
 typedef unsigned char archive_sha1_ctx;
 #endif
@@ -244,14 +253,16 @@ typedef SHA2_CTX archive_sha256_ctx;
 typedef SHA256_CTX archive_sha256_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
 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)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_sha256_context archive_sha256_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct sha256_ctx archive_sha256_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
 typedef EVP_MD_CTX *archive_sha256_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
-typedef Digest_CTX archive_sha256_ctx;
 #else
 typedef unsigned char archive_sha256_ctx;
 #endif
@@ -264,14 +275,16 @@ typedef SHA384_CTX archive_sha384_ctx;
 typedef SHA2_CTX archive_sha384_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
 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)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_sha512_context archive_sha384_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct sha384_ctx archive_sha384_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
 typedef EVP_MD_CTX *archive_sha384_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
-typedef Digest_CTX archive_sha384_ctx;
 #else
 typedef unsigned char archive_sha384_ctx;
 #endif
@@ -286,14 +299,16 @@ typedef SHA2_CTX archive_sha512_ctx;
 typedef SHA512_CTX archive_sha512_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
 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)
+#define	ARCHIVE_CRYPTO_MBED 1
 typedef mbedtls_sha512_context archive_sha512_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
+#define	ARCHIVE_CRYPTO_NETTLE 1
 typedef struct sha512_ctx archive_sha512_ctx;
 #elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
 typedef EVP_MD_CTX *archive_sha512_ctx;
-#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
-typedef Digest_CTX archive_sha512_ctx;
 #else
 typedef unsigned char archive_sha512_ctx;
 #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))
 		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) {
 			archive_entry_acl_add_entry(entry,
 			    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) {
 				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) {
 					archive_set_error(&a->archive, errno,
 					    "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) {
 				if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
 					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,
 						    "Failed to add flag to "
 						    "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.
  */
 
-time_t
+__LA_TIME_T
 archive_entry_atime(struct archive_entry *entry)
 {
 	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);
 }
 
-time_t
+__LA_TIME_T
 archive_entry_birthtime(struct archive_entry *entry)
 {
 	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);
 }
 
-time_t
+__LA_TIME_T
 archive_entry_ctime(struct archive_entry *entry)
 {
 	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);
 }
 
-dev_t
+__LA_DEV_T
 archive_entry_dev(struct archive_entry *entry)
 {
 	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);
 }
 
-dev_t
+__LA_DEV_T
 archive_entry_devmajor(struct archive_entry *entry)
 {
 	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);
 }
 
-dev_t
+__LA_DEV_T
 archive_entry_devminor(struct archive_entry *entry)
 {
 	if (entry->ae_stat.aest_dev_is_broken_down)
@@ -568,7 +568,7 @@ archive_entry_mode(struct archive_entry *entry)
 	return (entry->acl.mode);
 }
 
-time_t
+__LA_TIME_T
 archive_entry_mtime(struct archive_entry *entry)
 {
 	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);
 }
 
-dev_t
+__LA_DEV_T
 archive_entry_rdev(struct archive_entry *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)
 {
 	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)
 {
 	if (archive_entry_rdev_is_set(entry)) {
@@ -984,7 +984,9 @@ void
 archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
 {
 	if (ino < 0) {
-		ino = 0;
+		entry->stat_valid = 0;
+		entry->ae_set &= ~AE_SET_INO;
+		return;
 	}
 	entry->stat_valid = 0;
 	entry->ae_set |= AE_SET_INO;
@@ -995,7 +997,9 @@ void
 archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
 {
 	if (ino < 0) {
-		ino = 0;
+		entry->stat_valid = 0;
+		entry->ae_set &= ~AE_SET_INO;
+		return;
 	}
 	entry->stat_valid = 0;
 	entry->ae_set |= AE_SET_INO;
@@ -1088,7 +1092,7 @@ _archive_entry_copy_hardlink_l(struct archive_entry *entry,
 }
 
 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);
 	entry->stat_valid = 0;
@@ -1105,7 +1109,7 @@ archive_entry_unset_atime(struct archive_entry *entry)
 }
 
 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);
 	entry->stat_valid = 0;
@@ -1122,7 +1126,7 @@ archive_entry_unset_birthtime(struct archive_entry *entry)
 }
 
 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);
 	entry->stat_valid = 0;
@@ -1139,7 +1143,7 @@ archive_entry_unset_ctime(struct archive_entry *entry)
 }
 
 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->ae_set |= AE_SET_DEV;
@@ -1148,7 +1152,7 @@ archive_entry_set_dev(struct archive_entry *entry, dev_t d)
 }
 
 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->ae_set |= AE_SET_DEV;
@@ -1157,7 +1161,7 @@ archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
 }
 
 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->ae_set |= AE_SET_DEV;
@@ -1243,7 +1247,7 @@ archive_entry_set_mode(struct archive_entry *entry, mode_t m)
 }
 
 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);
 	entry->stat_valid = 0;
@@ -1319,7 +1323,7 @@ archive_entry_set_perm(struct archive_entry *entry, mode_t p)
 }
 
 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->ae_stat.aest_rdev = m;
@@ -1330,7 +1334,7 @@ archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
 }
 
 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->ae_stat.aest_rdev_is_broken_down = 1;
@@ -1340,7 +1344,7 @@ archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
 }
 
 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->ae_stat.aest_rdev_is_broken_down = 1;
@@ -1603,21 +1607,27 @@ archive_entry_set_digest(struct archive_entry *entry, int type,
 	switch (type) {
 	case ARCHIVE_ENTRY_DIGEST_MD5:
 		copy_digest(entry, md5, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_MD5;
 		break;
 	case ARCHIVE_ENTRY_DIGEST_RMD160:
 		copy_digest(entry, rmd160, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_RMD160;
 		break;
 	case ARCHIVE_ENTRY_DIGEST_SHA1:
 		copy_digest(entry, sha1, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_SHA1;
 		break;
 	case ARCHIVE_ENTRY_DIGEST_SHA256:
 		copy_digest(entry, sha256, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_SHA256;
 		break;
 	case ARCHIVE_ENTRY_DIGEST_SHA384:
 		copy_digest(entry, sha384, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_SHA384;
 		break;
 	case ARCHIVE_ENTRY_DIGEST_SHA512:
 		copy_digest(entry, sha512, digest);
+		entry->mset_digest |= AE_MSET_DIGEST_SHA512;
 		break;
 	default:
 		return ARCHIVE_WARN;

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

@@ -28,7 +28,7 @@
 #define	ARCHIVE_ENTRY_H_INCLUDED
 
 /* 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
@@ -40,8 +40,11 @@
 
 #include <sys/types.h>
 #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>
+#endif
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #include <windows.h>
@@ -55,12 +58,15 @@
 #define __LA_INT64_T_DEFINED
 # if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
 typedef __int64 la_int64_t;
+typedef unsigned __int64 la_uint64_t;
 # else
 #include <unistd.h>
 #  if defined(_SCO_DS) || defined(__osf__)
 typedef long long la_int64_t;
+typedef unsigned long long la_uint64_t;
 #  else
 typedef int64_t la_int64_t;
+typedef uint64_t la_uint64_t;
 #  endif
 # endif
 #endif
@@ -96,6 +102,30 @@ typedef ssize_t la_ssize_t;
 # define	__LA_MODE_T	mode_t
 #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 */
 #if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
 #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.
  * 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 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 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 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 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 int		 archive_entry_filetype_is_set(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 wchar_t	*archive_entry_hardlink_w(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 __LA_MODE_T	 archive_entry_mode(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 int		 archive_entry_perm_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 wchar_t	*archive_entry_sourcepath_w(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.
  */
 
-__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 *);
 #if defined(_WIN32) && !defined(__CYGWIN__)
 __LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, struct _BY_HANDLE_FILE_INFORMATION *);
 #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_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_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_fflags(struct archive_entry *,
 	    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_w(struct archive_entry *, const wchar_t *);
 __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_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_w(struct archive_entry *, const wchar_t *);
 __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_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_set_nlink(struct archive_entry *, unsigned int);
 __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 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_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_unset_size(struct archive_entry *);
 __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
 
 __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

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

@@ -24,43 +24,24 @@
  */
 
 #include "archive_platform.h"
-
+#include "archive_time_private.h"
 #include "archive_private.h"
 #include "archive_entry.h"
 
 #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
 archive_entry_copy_bhfi(struct archive_entry *entry,
 			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);
-	fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
+	ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &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_ctime(entry, secs, nsecs);
 	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;
 	int64_t			 ino;
 
+	if (!archive_entry_ino_is_set(entry) || !archive_entry_dev_is_set(entry)) {
+		return (NULL);
+	}
+
 	/* Free a held entry. */
 	if (res->spare != NULL) {
 		archive_entry_free(res->spare->canonical);
@@ -369,6 +373,10 @@ insert_entry(struct archive_entry_linkresolver *res,
 	struct links_entry *le;
 	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. */
 	le = calloc(1, sizeof(struct links_entry));
 	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 *,
     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;
 
 	/* 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;
 
 	/* ACL support. */
@@ -195,8 +202,4 @@ struct archive_entry {
 	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;
-#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
 #include <string.h>
 #endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
 
 #include "archive.h"
 #include "archive_private.h"
 #include "archive_entry.h"
-#include "archive_getdate.h"
 #include "archive_pathmatch.h"
 #include "archive_rb.h"
 #include "archive_string.h"
+#include "archive_time_private.h"
 
 struct match {
 	struct match		*next;
@@ -53,8 +56,7 @@ struct match {
 struct match_list {
 	struct match		*first;
 	struct match		**last;
-	int			 count;
-	int			 unmatched_count;
+	size_t			 unmatched_count;
 	struct match		*unmatched_next;
 	int			 unmatched_eof;
 };
@@ -73,7 +75,6 @@ struct match_file {
 struct entry_list {
 	struct match_file	*first;
 	struct match_file	**last;
-	int			 count;
 };
 
 struct id_array {
@@ -144,12 +145,15 @@ static int	add_pattern_mbs(struct archive_match *, struct match_list *,
 		    const char *);
 static int	add_pattern_wcs(struct archive_match *, struct match_list *,
 		    const wchar_t *);
+#if !defined(_WIN32) || defined(__CYGWIN__)
 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 *,
 		    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 *,
 		    const struct archive_rb_node *);
+#endif
 static void	entry_list_add(struct entry_list *, struct match_file *);
 static void	entry_list_free(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 *);
 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
-};
-
-static const struct archive_rb_tree_ops rb_ops_wcs = {
+#else
 	cmp_node_wcs, cmp_key_wcs
+#endif
 };
 
 /*
@@ -228,7 +232,7 @@ archive_match_new(void)
 	a->recursive_include = 1;
 	match_list_init(&(a->inclusions));
 	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));
 	match_list_init(&(a->inclusion_unames));
 	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");
 	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
@@ -650,7 +656,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
 						break;
 					}
 				} else {
-			            	if (*b == 0x0d || *b == 0x0a) {
+					if (*b == 0x0d || *b == 0x0a) {
 						found_separator = 1;
 						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;
 	    match = match->next){
 		r = match_path_exclusion(a, match, mbs, pathname);
@@ -834,7 +840,6 @@ match_list_init(struct match_list *list)
 {
 	list->first = NULL;
 	list->last = &(list->first);
-	list->count = 0;
 }
 
 static void
@@ -855,7 +860,6 @@ match_list_add(struct match_list *list, struct match *m)
 {
 	*list->last = m;
 	list->last = &(m->next);
-	list->count++;
 	list->unmatched_count++;
 }
 
@@ -1145,36 +1149,15 @@ set_timefilter_date_w(struct archive_match *a, int timetype,
 }
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
 static int
 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;
-	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,
 			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);
 	}
 	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
@@ -1223,9 +1204,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
 		return (ARCHIVE_FAILED);
 	}
 	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__ */
@@ -1300,6 +1279,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
 /*
  * Call back functions for archive_rb.
  */
+#if !defined(_WIN32) || defined(__CYGWIN__)
 static int
 cmp_node_mbs(const struct archive_rb_node *n1,
     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 (strcmp(p, (const char *)key));
 }
-
+#else
 static int
 cmp_node_wcs(const struct archive_rb_node *n1,
     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 (wcscmp(p, (const wchar_t *)key));
 }
+#endif
 
 static void
 entry_list_init(struct entry_list *list)
 {
 	list->first = NULL;
 	list->last = &(list->first);
-	list->count = 0;
 }
 
 static void
@@ -1384,7 +1364,6 @@ entry_list_add(struct entry_list *list, struct match_file *file)
 {
 	*list->last = file;
 	list->last = &(file->next);
-	list->count++;
 }
 
 static int
@@ -1407,9 +1386,7 @@ add_entry(struct archive_match *a, int flag,
 		return (ARCHIVE_FAILED);
 	}
 	archive_mstring_copy_wcs(&(f->pathname), pathname);
-	a->exclusion_tree.rbt_ops = &rb_ops_wcs;
 #else
-	(void)rb_ops_wcs;
 	pathname = archive_entry_pathname(entry);
 	if (pathname == NULL) {
 		free(f);
@@ -1417,7 +1394,6 @@ add_entry(struct archive_match *a, int flag,
 		return (ARCHIVE_FAILED);
 	}
 	archive_mstring_copy_mbs(&(f->pathname), pathname);
-	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
 #endif
 	f->flag = flag;
 	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 (a->exclusion_entry_list.count == 0)
+	if (a->exclusion_entry_list.first == NULL)
 		return (0);
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 	pathname = archive_entry_pathname_w(entry);
-	a->exclusion_tree.rbt_ops = &rb_ops_wcs;
 #else
-	(void)rb_ops_wcs;
 	pathname = archive_entry_pathname(entry);
-	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
 #endif
 	if (pathname == NULL)
 		return (0);
@@ -1707,7 +1680,7 @@ archive_match_owner_excluded(struct archive *_a,
 static int
 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) {
 		void *p;
@@ -1744,10 +1717,10 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
 static int
 match_owner_id(struct id_array *ids, int64_t id)
 {
-	unsigned b, m, t;
+	size_t b, m, t;
 
 	t = 0;
-	b = (unsigned)ids->count;
+	b = ids->count;
 	while (t < b) {
 		m = (t + b)>>1;
 		if (ids->ids[m] == id)
@@ -1842,7 +1815,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
 			return (1);
 	}
 
-	if (a->inclusion_unames.count) {
+	if (a->inclusion_unames.first != NULL) {
 #if defined(_WIN32) && !defined(__CYGWIN__)
 		r = match_owner_name_wcs(a, &(a->inclusion_unames),
 			archive_entry_uname_w(entry));
@@ -1856,7 +1829,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
 			return (r);
 	}
 
-	if (a->inclusion_gnames.count) {
+	if (a->inclusion_gnames.first != NULL) {
 #if defined(_WIN32) && !defined(__CYGWIN__)
 		r = match_owner_name_wcs(a, &(a->inclusion_gnames),
 			archive_entry_gname_w(entry));
@@ -1871,4 +1844,3 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
 	}
 	return (0);
 }
-

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

@@ -38,7 +38,7 @@ parse_option(const char **str,
 int
 _archive_set_option(struct archive *a,
     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;
 	int r;
@@ -97,7 +97,7 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons
 
 int
 _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;
 	char *data;

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

@@ -35,11 +35,11 @@ typedef int (*option_handler)(struct archive *a,
 int
 _archive_set_option(struct archive *a,
     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
 _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
 _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) <<  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.
 */
 
-#ifndef CM_GET_DATE
+#ifndef CM_PARSE_DATE
 #include "archive_platform.h"
 #endif
 
@@ -37,8 +37,7 @@
 #include <string.h>
 #include <time.h>
 
-#define __LIBARCHIVE_BUILD 1
-#include "archive_getdate.h"
+#include "archive.h"
 
 /* Basic time units. */
 #define	EPOCH		1970
@@ -822,6 +821,23 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
 		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.
  */
@@ -863,7 +879,8 @@ nexttoken(const char **in, time_t *value)
 			    && i < sizeof(buff)-1) {
 				if (*src != '.') {
 					if (isupper((unsigned char)*src))
-						buff[i++] = tolower((unsigned char)*src);
+						buff[i++] = (char)tolower(
+						    (unsigned char)*src);
 					else
 						buff[i++] = *src;
 				}
@@ -897,10 +914,7 @@ nexttoken(const char **in, time_t *value)
 		 * Because '-' and '+' have other special meanings, I
 		 * 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);
 		}
 
@@ -916,7 +930,7 @@ difftm (struct tm *a, struct tm *b)
 {
 	int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
 	int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
-	int days = (
+	long days = (
 		/* difference in day of year */
 		a->tm_yday - b->tm_yday
 		/* + intervening leap days */
@@ -931,6 +945,32 @@ difftm (struct tm *a, struct tm *b)
 	    + (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.
@@ -938,7 +978,7 @@ difftm (struct tm *a, struct tm *b)
  * TODO: tokens[] array should be dynamically sized.
  */
 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 gdstate	_gds;
@@ -950,6 +990,13 @@ __archive_get_date(time_t now, const char *p)
 	time_t		tod;
 	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. */
 	memset(tokens, 0, sizeof(tokens));
 	/* Initialize the parser state. */

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

@@ -50,4 +50,4 @@
 #define ARCHIVE_ACL_SUPPORT     1
 #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
 #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. */
 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 *,
 	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;
 
 	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;
 		for (;;) {
 			int64_t get, ask = request;
-			if (ask > skip_limit)
-				ask = skip_limit;
 			get = (self->archive->client.skipper)
 				(&self->archive->archive, self->data, ask);
 			total += get;

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

@@ -280,7 +280,7 @@ tree_dir_next_posix(struct tree *t);
 #endif
 
 /* 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 void tree_close(struct tree *);
 static void tree_free(struct tree *);
@@ -518,7 +518,7 @@ _archive_read_close(struct archive *_a)
 
 static void
 setup_symlink_mode(struct archive_read_disk *a, char symlink_mode,
-    int follow_symlinks)
+    char follow_symlinks)
 {
 	a->symlink_mode = symlink_mode;
 	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 (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");
 			r = ARCHIVE_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.
  */
 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;
 

+ 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
-	 * 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. */
 	struct tree *tree;

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

@@ -41,6 +41,7 @@
 #include "archive_entry.h"
 #include "archive_private.h"
 #include "archive_read_disk_private.h"
+#include "archive_time_private.h"
 
 #ifndef O_BINARY
 #define O_BINARY	0
@@ -49,7 +50,7 @@
 /* Old SDKs do not provide IO_REPARSE_TAG_SYMLINK */
 #define	IO_REPARSE_TAG_SYMLINK 0xA000000CL
 #endif
-/* To deal with absolute symlink isuues */
+/* To deal with absolute symlink issues */
 #define START_ABSOLUTE_SYMLINK_REPARSE L"\\??\\"
 
 /*-
@@ -602,7 +603,7 @@ _archive_read_close(struct archive *_a)
 
 static void
 setup_symlink_mode(struct archive_read_disk *a, char symlink_mode, 
-    int follow_symlinks)
+    char follow_symlinks)
 {
 	a->symlink_mode = symlink_mode;
 	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.
  */
-static void
+static int
 tree_append(struct tree *t, const wchar_t *name, size_t name_length)
 {
 	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. */
 	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. */
 	if (t->dirname_length > 0 &&
 	    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.length = t->full_path_dir_length;
 		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. */
 		if (t->full_path.s[archive_strlen(&t->full_path)-1] != L'\\')
 			archive_wstrappend_wchar(&t->full_path, L'\\');
 		archive_wstrncat(&t->full_path, name, name_length);
 		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));
 	archive_string_init(&(t->full_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;
 	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'/');
 		if (p != NULL) {
 			*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);
 			base = p + 1;
 		}
@@ -1891,8 +1899,10 @@ tree_next(struct tree *t)
 			}
 			/* Top stack item needs a regular visit. */
 			t->current = t->stack;
-			tree_append(t, t->stack->name.s,
+			r = tree_append(t, t->stack->name.s,
 			    archive_strlen(&(t->stack->name)));
+			if (r != 0)
+				return (r);
 			//t->dirname_length = t->path_length;
 			//tree_pop(t);
 			t->stack->flags &= ~needsFirstVisit;
@@ -1900,8 +1910,10 @@ tree_next(struct tree *t)
 		} else if (t->stack->flags & needsDescent) {
 			/* Top stack item is dir to descend into. */
 			t->current = t->stack;
-			tree_append(t, t->stack->name.s,
+			r = tree_append(t, t->stack->name.s,
 			    archive_strlen(&(t->stack->name)));
+			if (r != 0)
+				return (r);
 			t->stack->flags &= ~needsDescent;
 			r = tree_descent(t);
 			if (r != 0) {
@@ -1944,9 +1956,10 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern)
 			struct archive_wstring pt;
 
 			archive_string_init(&pt);
-			archive_wstring_ensure(&pt,
+			if (archive_wstring_ensure(&pt,
 			    archive_strlen(&(t->full_path))
-			      + 2 + wcslen(pattern));
+			      + 2 + wcslen(pattern)) == NULL)
+				return (TREE_ERROR_FATAL);
 			archive_wstring_copy(&pt, &(t->full_path));
 			archive_wstrappend_wchar(&pt, L'\\');
 			archive_wstrcat(&pt, pattern);
@@ -1978,45 +1991,27 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern)
 			continue;
 		if (name[0] == L'.' && name[1] == L'.' && name[2] == L'\0')
 			continue;
-		tree_append(t, name, namelen);
+		r = tree_append(t, name, namelen);
+		if (r != 0)
+			return (r);
 		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
 entry_copy_bhfi(struct archive_entry *entry, const wchar_t *path,
 	const WIN32_FIND_DATAW *findData,
 	const BY_HANDLE_FILE_INFORMATION *bhfi)
 {
-	time_t secs;
-	long nsecs;
+	int64_t secs;
+	uint32_t nsecs;
 	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);
-	fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
+	ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &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_ctime(entry, secs, nsecs);
 	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_mtree ,
 .Nm archive_read_support_format_rar ,
+.Nm archive_read_support_format_rar5 ,
 .Nm archive_read_support_format_raw ,
 .Nm archive_read_support_format_tar ,
+.Nm archive_read_support_format_warc ,
 .Nm archive_read_support_format_xar ,
 .Nm archive_read_support_format_zip
 .Nd functions for reading streaming archives
@@ -70,10 +72,14 @@ Streaming Archive Library (libarchive, -larchive)
 .Ft int
 .Fn archive_read_support_format_rar "struct archive *"
 .Ft int
+.Fn archive_read_support_format_rar5 "struct archive *"
+.Ft int
 .Fn archive_read_support_format_raw "struct archive *"
 .Ft int
 .Fn archive_read_support_format_tar "struct archive *"
 .Ft int
+.Fn archive_read_support_format_warc "struct archive *"
+.Ft int
 .Fn archive_read_support_format_xar "struct archive *"
 .Ft int
 .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_mtree ,
 .Fn archive_read_support_format_rar ,
+.Fn archive_read_support_format_rar5 ,
 .Fn archive_read_support_format_raw ,
 .Fn archive_read_support_format_tar ,
+.Fn archive_read_support_format_warc ,
 .Fn archive_read_support_format_xar ,
 .Fn archive_read_support_format_zip
 .Xc
@@ -100,6 +108,13 @@ For example,
 .Fn archive_read_support_format_tar
 enables support for a variety of standard tar formats, old-style tar,
 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
 Enables support for all available formats except the
 .Dq raw

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

@@ -52,6 +52,7 @@
 struct read_fd_data {
 	int	 fd;
 	size_t	 block_size;
+	int64_t	 size;
 	char	 use_lseek;
 	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)) {
 		archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
 		mine->use_lseek = 1;
+		mine->size = st.st_size;
 	}
 #if defined(__CYGWIN__) || defined(_WIN32)
 	setmode(mine->fd, O_BINARY);
@@ -131,7 +133,7 @@ static int64_t
 file_skip(struct archive *a, void *client_data, int64_t request)
 {
 	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;
 	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. */
 	if (sizeof(request) > sizeof(skip)) {
-		int64_t max_skip =
+		const int64_t max_skip =
 		    (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
 		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);
 
-	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. */
 	mine->use_lseek = 0;
@@ -178,11 +185,24 @@ static int64_t
 file_seek(struct archive *a, void *client_data, int64_t request, int whence)
 {
 	struct read_fd_data *mine = (struct read_fd_data *)client_data;
+	off_t seek = (off_t)request;
 	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. */
-	/* 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)
 		return r;
 

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

@@ -52,6 +52,7 @@
 struct read_FILE_data {
 	FILE    *f;
 	size_t	 block_size;
+	int64_t	 size;
 	void	*buffer;
 	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);
 		/* Enable the seek optimization only for regular files. */
 		mine->can_skip = 1;
+		mine->size = st.st_size;
 	}
 
 #if defined(__CYGWIN__) || defined(_WIN32)
@@ -130,6 +132,7 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
 #else
 	long skip = (long)request;
 #endif
+	int64_t old_offset, new_offset = -1;
 	int skip_bits = sizeof(skip) * 8 - 1;
 
 	(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 (sizeof(request) > sizeof(skip)) {
-		int64_t max_skip =
+		const int64_t max_skip =
 		    (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
 		if (request > max_skip)
 			skip = max_skip;
@@ -153,19 +156,36 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
 
 #ifdef __ANDROID__
         /* fileno() isn't safe on all platforms ... see above. */
-	if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
+	old_offset = lseek(fileno(mine->f), 0, SEEK_CUR);
 #elif HAVE__FSEEKI64
-	if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
+	old_offset = _ftelli64(mine->f);
 #elif HAVE_FSEEKO
-	if (fseeko(mine->f, skip, SEEK_CUR) != 0)
+	old_offset = ftello(mine->f);
 #else
-	if (fseek(mine->f, skip, SEEK_CUR) != 0)
+	old_offset = ftell(mine->f);
 #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;
 #if HAVE__FSEEKI64
-	int64_t skip = request;
+	int64_t seek = request;
 #elif HAVE_FSEEKO
-	off_t skip = (off_t)request;
+	off_t seek = (off_t)request;
 #else
-	long skip = (long)request;
+	long seek = (long)request;
 #endif
-	int skip_bits = sizeof(skip) * 8 - 1;
+	int seek_bits = sizeof(seek) * 8 - 1;
 	(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__
 	/* 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) {
 		return ret;
 	}
 #elif HAVE__FSEEKI64
-	if (_fseeki64(mine->f, skip, whence) == 0) {
+	if (_fseeki64(mine->f, seek, whence) == 0) {
 		return _ftelli64(mine->f);
 	}
 #elif HAVE_FSEEKO
-	if (fseeko(mine->f, skip, whence) == 0) {
+	if (fseeko(mine->f, seek, whence) == 0) {
 		return ftello(mine->f);
 	}
 #else
-	if (fseek(mine->f, skip, whence) == 0) {
+	if (fseek(mine->f, seek, whence) == 0) {
 		return ftell(mine->f);
 	}
 #endif
@@ -227,3 +250,4 @@ FILE_close(struct archive *a, void *client_data)
 	free(mine);
 	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;
 	void	*buffer;
 	mode_t	 st_mode;  /* Mode bits for opened file. */
+	int64_t	 size;
 	char	 use_lseek;
 	enum fnt_e { FNT_STDIN, FNT_MBS, FNT_WCS } filename_type;
 	union {
@@ -400,8 +401,10 @@ file_open(struct archive *a, void *client_data)
 	mine->st_mode = st.st_mode;
 
 	/* Disk-like inputs can use lseek(). */
-	if (is_disk_like)
+	if (is_disk_like) {
 		mine->use_lseek = 1;
+		mine->size = st.st_size;
+	}
 
 	return (ARCHIVE_OK);
 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;
 #if defined(_WIN32) && !defined(__CYGWIN__)
 	/* We use _lseeki64() on Windows. */
-	int64_t old_offset, new_offset;
+	int64_t old_offset, new_offset, skip = request;
 #else
-	off_t old_offset, new_offset;
+	off_t old_offset, new_offset, skip = (off_t)request;
 #endif
+	int skip_bits = sizeof(skip) * 8 - 1;
 
 	/* 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. */
 	mine->use_lseek = 0;
@@ -540,11 +552,24 @@ static int64_t
 file_seek(struct archive *a, void *client_data, int64_t request, int whence)
 {
 	struct read_file_data *mine = (struct read_file_data *)client_data;
+	off_t seek = (off_t)request;
 	int64_t r;
+	int seek_bits = sizeof(seek) * 8 - 1;
 
 	/* 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)
 		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 unsigned debug_index;
 
+again:
 	code = newcode = getbits(self, state->bits);
 	if (code < 0)
 		return (code);
@@ -360,7 +361,7 @@ next_code(struct archive_read_filter *self)
 		state->section_end_code = (1 << state->bits) - 1;
 		state->free_ent = 257;
 		state->oldcode = -1;
-		return (next_code(self));
+		goto again;
 	}
 
 	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_private.h"
 #include "archive_read_private.h"
+#include "archive_time_private.h"
 #include "archive_endian.h"
 
 #ifndef HAVE_ZLIB_H
@@ -66,7 +67,26 @@
 #define _7ZIP_SIGNATURE	"7z\xBC\xAF\x27\x1C"
 #define SFX_MIN_ADDR	0x27000
 #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
@@ -90,6 +110,7 @@
 #define _7Z_ARM		0x03030501
 #define _7Z_ARMTHUMB	0x03030701
 #define _7Z_ARM64	0xa
+#define _7Z_RISCV	0xb
 #define _7Z_SPARC	0x03030805
 
 #define _7Z_ZSTD	0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
@@ -151,7 +172,6 @@ struct _7z_digests {
 	uint32_t	*digests;
 };
 
-
 struct _7z_folder {
 	uint64_t		 numCoders;
 	struct _7z_coder {
@@ -231,13 +251,13 @@ struct _7zip_entry {
 #define CRC32_IS_SET	(1<<3)
 #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;
 };
 
@@ -395,7 +415,6 @@ static int	decode_encoded_header_info(struct archive_read *,
 static int	decompress(struct archive_read *, struct _7zip *,
 		    void *, size_t *, const void *, 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 void	free_CodersInfo(struct _7z_coders_info *);
 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);
 static int	seek_pack(struct archive_read *);
 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 *,
 		    struct _7z_header_info *);
 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
 	 * 'M' and 'Z' available on Windows or first four bytes are
 	 * "\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) {
-		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 bytes_avail;
-		while (offset + window <= (SFX_MAX_ADDR)) {
+		while (offset + window <= (min_addr + SFX_MAX_OFFSET)) {
 			const char *buff = __archive_read_ahead(a,
 					offset + window, &bytes_avail);
 			if (buff == NULL) {
@@ -589,21 +612,14 @@ check_7zip_header_in_sfx(const char *p)
 }
 
 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 char *p, *q;
 	size_t skip, offset;
 	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);
 
 	offset = 0;
@@ -636,7 +652,7 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail)
 				    (struct _7zip *)a->format->data;
 				skip = p - (const char *)h;
 				__archive_read_consume(a, skip);
-				zip->seek_base = SFX_MIN_ADDR + offset + skip;
+				zip->seek_base = min_addr + offset + skip;
 				return (ARCHIVE_OK);
 			}
 			p += step;
@@ -653,6 +669,207 @@ 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
 archive_read_format_7zip_read_header(struct archive_read *a,
 	struct archive_entry *entry)
@@ -1237,6 +1454,12 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
 				filters[fi].id = LZMA_FILTER_ARM64;
 				fi++;
 				break;
+#endif
+#ifdef LZMA_FILTER_RISCV
+			case _7Z_RISCV:
+				filters[fi].id = LZMA_FILTER_RISCV;
+				fi++;
+				break;
 #endif
 			case _7Z_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_ARMTHUMB:
 	case _7Z_ARM64:
+	case _7Z_RISCV:
 	case _7Z_SPARC:
 	case _7Z_DELTA:
 		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);
 }
 
-#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
 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;
 		switch (type) {
 		case kCTime:
-			fileTimeToUtc(archive_le64dec(p),
+			ntfs_to_unix(archive_le64dec(p),
 			    &(entries[i].ctime),
 			    &(entries[i].ctime_ns));
 			entries[i].flg |= CTIME_IS_SET;
 			break;
 		case kATime:
-			fileTimeToUtc(archive_le64dec(p),
+			ntfs_to_unix(archive_le64dec(p),
 			    &(entries[i].atime),
 			    &(entries[i].atime_ns));
 			entries[i].flg |= ATIME_IS_SET;
 			break;
 		case kMTime:
-			fileTimeToUtc(archive_le64dec(p),
+			ntfs_to_unix(archive_le64dec(p),
 			    &(entries[i].mtime),
 			    &(entries[i].mtime_ns));
 			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) {
 		/* 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)
 			return (r);
 		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);
 }
-

+ 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);
 	}
 	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,
 	    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 uint64_t	atol16u(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_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)
 {
 	int64_t t;
+	uint64_t u;
 	const void *h;
 	const char *header;
 
@@ -851,12 +853,12 @@ header_afiol(struct archive_read *a, struct cpio *cpio,
 
 	archive_entry_set_dev(entry, 
 		(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,
 		(mode_t)atol8(header + afiol_mode_offset, afiol_mode_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
 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;
 	int digit;
@@ -1048,7 +1056,7 @@ atol16(const char *p, unsigned char_cnt)
 		l <<= 4;
 		l |= digit;
 	}
-	return ((int64_t)l);
+	return (l);
 }
 
 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 (data_length >= 8)
 						file->mode
-						    = toi(data, 4);
+						    = (__LA_MODE_T)toi(data, 4);
 					if (data_length >= 16)
 						file->nlinks
 						    = 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_private.h"
 #include "archive_read_private.h"
+#include "archive_time_private.h"
 #include "archive_endian.h"
 
 
@@ -162,12 +163,12 @@ struct lha {
 #define ATIME_IS_SET		2
 #define UNIX_MODE_IS_SET	4
 #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;
 	int64_t			 uid;
 	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 *);
 static size_t	lha_check_header_format(const void *);
 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 *,
 		    int, size_t);
 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];
 	lha->compsize = archive_le32dec(p + H0_COMP_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];
 	extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen;
 	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. */
 	lha->compsize = archive_le32dec(p + H1_COMP_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];
 	/* Calculate a padding size. The result will be normally 0 only(?) */
 	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)
 		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->origsize = archive_le32dec(p + H3_ORIG_SIZE_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;
 		case EXT_TIMESTAMP:
 			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);
 				extdheader += sizeof(uint64_t);
-				lha->mtime = lha_win_time(
-				    archive_le64dec(extdheader),
+				ntfs_to_unix(archive_le64dec(extdheader),
+					&lha->mtime,
 				    &lha->mtime_tv_nsec);
 				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->setflag |= BIRTHTIME_IS_SET |
 				    ATIME_IS_SET;
@@ -1716,45 +1715,6 @@ lha_parse_linkname(struct archive_wstring *linkname,
 	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
 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. */
 	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;
   char has_endarc_header;
   struct data_block_offsets *dbo;
-  unsigned int cursor;
-  unsigned int nodes;
+  size_t cursor;
+  size_t nodes;
   char filename_must_match;
 
   /* 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 execute_filter(struct archive_read*, struct rar_filter *,
                           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 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);
   }
 
-	/*
-	 * 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,
                                      rar,
@@ -770,21 +770,21 @@ archive_read_support_format_rar(struct archive *_a)
 static int
 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
 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 (best_bid > 30)
-	  return (-1);
+    return (-1);
 
   if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
     return (-1);
@@ -867,7 +867,7 @@ skip_sfx(struct archive_read *a)
     }
     skip = p - (const char *)h;
     __archive_read_consume(a, skip);
-	total += skip;
+    total += skip;
   }
 fatal:
   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 char *p;
   struct rar *rar;
-  size_t skip;
+  int64_t skip;
   char head_type;
   int ret;
   unsigned flags;
@@ -932,7 +932,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
    * as well.
    */
   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
@@ -955,8 +955,11 @@ archive_read_format_rar_read_header(struct archive_read *a,
   {
     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);
+    }
     p = h;
 
     head_type = p[2];
@@ -974,7 +977,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
     case MAIN_HEAD:
       rar->main_flags = archive_le16dec(p + 3);
       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,
           "Invalid header size");
         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),
              sizeof(rar->reserved2));
       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,
             "Invalid header size");
           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. */
       crc32_val = 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) {
 #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
       }
       if (head_type == ENDARC_HEAD)
-	      return (ARCHIVE_EOF);
+        return (ARCHIVE_EOF);
       break;
 
     case NEWSUB_HEAD:
@@ -1085,7 +1091,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
       break;
 
     default:
-      archive_set_error(&a->archive,  ARCHIVE_ERRNO_FILE_FORMAT,
+      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
                         "Bad RAR file");
       return (ARCHIVE_FATAL);
     }
@@ -1100,7 +1106,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
   int ret;
 
   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) {
@@ -1188,7 +1194,7 @@ archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset,
     int whence)
 {
   int64_t client_offset, ret;
-  unsigned int i;
+  size_t i;
   struct rar *rar = (struct rar *)(a->format->data);
 
   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)
+  {
+    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                      "Failed to read full header content.");
     return (ARCHIVE_FATAL);
+  }
 
   /* File Header CRC check. */
   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)
   {
-	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,
                       "RAR encryption support unavailable.");
     /* 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) {
     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;
+    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. */
-    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;
     endp = p + header_size - 7;
     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))
   {
     __archive_read_consume(a, header_size - 7);
+    rar->br.avail_in = 0;
+    rar->br.next_in = NULL;
     rar->cursor++;
     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->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].end_offset = rar->dbo[rar->cursor].start_offset +
         rar->packed_size;
@@ -1747,6 +1778,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
   }
 
   __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].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_OS2:
   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)
       rar->mode = AE_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
     else
@@ -1766,7 +1802,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
   case OS_UNIX:
   case OS_MAC_OS:
   case OS_BEOS:
-    rar->mode = archive_le32dec(file_header.file_attr);
+    rar->mode = (__LA_MODE_T)archive_le32dec(file_header.file_attr);
     break;
 
   default:
@@ -1782,6 +1818,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
   rar->offset_outgoing = 0;
   rar->br.cache_avail = 0;
   rar->br.avail_in = 0;
+  rar->br.next_in = NULL;
   rar->crc_calculated = 0;
   rar->entry_eof = 0;
   rar->valid = 1;
@@ -1943,8 +1980,18 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
   int ret = (ARCHIVE_OK);
 
   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)
+  {
+    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+                      "Failed to read link.");
     return (ARCHIVE_FATAL);
+  }
   p = h;
 
   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);
       if (ret != ARCHIVE_OK)
-	      return (ret);
+        return (ret);
 
       rar->bytes_uncopied = end - start;
       rar->filters.lastend = end;
@@ -2334,9 +2381,9 @@ parse_codes(struct archive_read *a)
       __archive_ppmd7_functions.Ppmd7_Construct(&rar->ppmd7_context);
 
       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");
-	      return (ARCHIVE_FATAL);
+        return (ARCHIVE_FATAL);
       }
 
       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)
-      return (ARCHIVE_FATAL);
+      goto bad_data;
 
     if (symbol < 256)
     {
-      lzss_emit_literal(rar, symbol);
+      lzss_emit_literal(rar, (uint8_t)symbol);
       continue;
     }
     else if (symbol == 256)
@@ -2958,14 +3005,14 @@ expand(struct archive_read *a, int64_t *end)
       else
       {
         if (parse_codes(a) != ARCHIVE_OK)
-          return (ARCHIVE_FATAL);
+          goto bad_data;
         continue;
       }
     }
     else if(symbol==257)
     {
       if (!read_filter(a, end))
-          return (ARCHIVE_FATAL);
+          goto bad_data;
       continue;
     }
     else if(symbol==258)
@@ -3050,7 +3097,7 @@ expand(struct archive_read *a, int64_t *end)
           {
             if ((lowoffsetsymbol =
               read_next_symbol(a, &rar->lowoffsetcode)) < 0)
-              return (ARCHIVE_FATAL);
+              goto bad_data;
             if(lowoffsetsymbol == 16)
             {
               rar->numlowoffsetrepeats = 15;
@@ -3098,7 +3145,7 @@ bad_data:
 }
 
 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)
 {
   int windowoffs, firstpart;
@@ -3113,7 +3160,7 @@ copy_from_lzss_window(struct archive_read *a, void *buffer,
   }
   if (firstpart < length) {
     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 {
     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)
 {
   struct rar *rar = (struct rar *)(a->format->data);
-  const void *h = __archive_read_ahead(a, min, avail);
+  const void *h;
   int ret;
+
+again:
+  h = __archive_read_ahead(a, min, avail);
+
   if (avail)
   {
     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;
       if (ret != (ARCHIVE_OK))
         return NULL;
-      return rar_read_ahead(a, min, avail);
+      goto again;
     }
   }
   return h;
@@ -3269,6 +3320,9 @@ parse_filter(struct archive_read *a, const uint8_t *bytes, uint16_t length, uint
   else
     blocklength = prog ? prog->oldfilterlength : 0;
 
+  if (blocklength > rar->dictionary_size)
+    return 0;
+
   registers[3] = PROGRAM_SYSTEM_GLOBAL_ADDRESS;
   registers[4] = blocklength;
   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_ppmd7_private.h"
 #include "archive_entry_private.h"
+#include "archive_time_private.h"
 
 #ifdef HAVE_BLAKE2_H
 #include <blake2.h>
@@ -100,10 +101,12 @@ struct file_header {
 	uint8_t dir : 1;             /* Is this file entry a directory? */
 
 	/* 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. */
 	uint32_t stored_crc32;
@@ -1101,22 +1104,22 @@ static int read_consume_bits(struct archive_read* a, struct rar5* rar,
 	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;
 	if(!read_ahead(a, 4, &p))
 		return 0;
 
 	*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;
 	if(!read_ahead(a, 8, &p))
 		return 0;
 
 	*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) {
@@ -1301,14 +1304,8 @@ static int parse_file_extra_hash(struct archive_read* a, struct rar5* rar,
 	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,
-    uint64_t* where, int64_t* extra_data_size)
+    int64_t* sec, uint32_t* nsec, int64_t* extra_data_size)
 {
 	if(unix_time) {
 		uint32_t time_val;
@@ -1316,13 +1313,13 @@ static int parse_htime_item(struct archive_read* a, char unix_time,
 			return ARCHIVE_EOF;
 
 		*extra_data_size -= 4;
-		*where = (uint64_t) time_val;
+		*sec = (int64_t) time_val;
 	} else {
 		uint64_t windows_time;
 		if(!read_u64(a, &windows_time))
 			return ARCHIVE_EOF;
 
-		*where = time_win_to_unix(windows_time);
+		ntfs_to_unix(windows_time, sec, nsec);
 		*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,
     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 value_len;
 
@@ -1407,32 +1404,62 @@ static int parse_file_extra_htime(struct archive_read* a,
 	}
 
 	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,
-		    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,
-		    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,
-		    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;
 
 		*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;
 }
 
@@ -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.
 		 *
 		 * - 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.
 		 *
 		 * - 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 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 *,
 		    const struct gnu_sparse *sparse, int length);
 static int	gnu_sparse_01_parse(struct archive_read *, struct tar *,
 		    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 *,
-		    struct archive_entry *, const void *, size_t *);
+		    struct archive_entry *, const void *, int64_t *);
 static int	header_common(struct archive_read *,  struct tar *,
 		    struct archive_entry *, const void *);
 static int	header_old_tar(struct archive_read *, struct tar *,
 		    struct archive_entry *, const void *);
 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 *,
-		    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 *,
-		    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 *,
-		    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	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 *,
-		    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 *,
 		    struct archive_entry *, const void *h);
 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_options(struct archive_read *,
 		    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 	pax_attribute(struct archive_read *, struct tar *,
 		    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 *,
 		    const char *, size_t, const char *, size_t);
 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);
 static void	pax_time(const char *, size_t, int64_t *sec, long *nanos);
 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 *,
-		    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 *,
-		    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_atol10(const char *, size_t);
 static int64_t	tar_atol256(const char *, size_t);
 static int64_t	tar_atol8(const char *, size_t);
 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 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
  * 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
  */
 static void
-tar_flush_unconsumed(struct archive_read *a, size_t *unconsumed)
+tar_flush_unconsumed(struct archive_read *a, int64_t *unconsumed)
 {
 	if (*unconsumed) {
 /*
@@ -526,7 +526,8 @@ archive_read_format_tar_read_header(struct archive_read *a,
 	const char *p;
 	const wchar_t *wp;
 	int r;
-	size_t l, unconsumed = 0;
+	size_t l;
+	int64_t unconsumed = 0;
 
 	/* Assign default device/inode values. */
 	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 (tar->sparse_list == NULL ||
 		    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);
 			tar->entry_padding = 0;
 			*buff = NULL;
@@ -665,29 +669,15 @@ archive_read_format_tar_read_data(struct archive_read *a,
 static int
 archive_read_format_tar_skip(struct archive_read *a)
 {
-	int64_t bytes_skipped;
 	int64_t request;
-	struct sparse_block *p;
 	struct tar* tar;
 
 	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);
 
 	tar->entry_bytes_remaining = 0;
@@ -700,13 +690,29 @@ archive_read_format_tar_skip(struct archive_read *a)
 	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
  * with a single entry.
  */
 static int
 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;
 	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_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. */
 	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]) {
 		case 'A': /* Solaris tar ACL */
 			if (seen_headers & seen_A_header) {
+				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+						  "Redundant 'A' header");
 				return (ARCHIVE_FATAL);
 			}
 			seen_headers |= seen_A_header;
@@ -824,6 +826,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
 			break;
 		case 'g': /* POSIX-standard 'g' header. */
 			if (seen_headers & seen_g_header) {
+				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+						  "Redundant 'g' header");
 				return (ARCHIVE_FATAL);
 			}
 			seen_headers |= seen_g_header;
@@ -833,27 +837,41 @@ tar_read_header(struct archive_read *a, struct tar *tar,
 			break;
 		case 'K': /* Long link name (GNU tar, others) */
 			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;
+			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);
 			break;
 		case 'L': /* Long filename (GNU tar, others) */
 			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;
+			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);
 			break;
 		case 'V': /* GNU volume 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;
+			a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
+			a->archive.archive_format_name = "GNU tar format";
 			err2 = header_volume(a, tar, entry, h, unconsumed);
 			break;
 		case 'X': /* Used by SUN tar; same as 'x'. */
 			if (seen_headers & seen_x_header) {
+				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+						  "Redundant 'X'/'x' header");
 				return (ARCHIVE_FATAL);
 			}
 			seen_headers |= seen_x_header;
@@ -864,6 +882,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
 			break;
 		case 'x': /* POSIX-standard 'x' header. */
 			if (seen_headers & seen_x_header) {
+				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+						  "Redundant 'x' header");
 				return (ARCHIVE_FATAL);
 			}
 			seen_headers |= seen_x_header;
@@ -915,6 +935,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
 				err = err_combine(err, err2);
 				/* Note: Other headers can appear again. */
 				seen_headers = seen_mac_metadata;
+				tar_reset_header_state(tar);
 				break;
 			}
 
@@ -1043,7 +1064,7 @@ archive_block_is_null(const char *p)
  */
 static int
 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;
 	struct archive_string	 acl_text;
@@ -1097,8 +1118,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
 		break;
 	default:
 		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);
 		return (ARCHIVE_WARN);
 	}
@@ -1149,7 +1170,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
  */
 static int
 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;
 
@@ -1183,7 +1204,7 @@ set_conversion_failed_error(struct archive_read *a,
  */
 static int
 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;
 	struct archive_string longname;
@@ -1204,7 +1225,7 @@ header_gnu_longname(struct archive_read *a, struct tar *tar,
  */
 static int
 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;
 	int64_t size, to_consume;
@@ -1230,7 +1251,7 @@ header_volume(struct archive_read *a, struct tar *tar,
 static int
 read_bytes_to_string(struct archive_read *a,
 		     struct archive_string *as, size_t size,
-		     size_t *unconsumed) {
+		     int64_t *unconsumed) {
 	const void *src;
 
 	/* Fail if we can't make our buffer big enough. */
@@ -1263,7 +1284,7 @@ read_bytes_to_string(struct archive_read *a,
  */
 static int
 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;
 	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 */
 	header = (const struct archive_entry_header_ustar *)h;
 	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);
 	}
-	if ((size > (int64_t)pathname_limit) || (size < 0)) {
+	if (size > (int64_t)pathname_limit) {
 		archive_string_empty(as);
 		int64_t to_consume = ((size + 511) & ~511);
 		if (to_consume != __archive_read_consume(a, to_consume)) {
 			return (ARCHIVE_FATAL);
 		}
 		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);
 	}
 	r = read_bytes_to_string(a, as, size, unconsumed);
@@ -1654,7 +1678,7 @@ is_mac_metadata_entry(struct archive_entry *entry) {
  */
 static int
 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;
 	size_t msize;
@@ -1711,7 +1735,7 @@ read_mac_metadata_blob(struct archive_read *a,
  */
 static int
 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;
 	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;
 	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);
 	}
 	to_consume = ((size + 511) & ~511);
@@ -1818,7 +1845,7 @@ header_ustar(struct archive_read *a, struct tar *tar,
 
 static int
 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
 	 * 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);
 		}
 		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);
 	}
 	tar_flush_unconsumed(a, unconsumed);
@@ -1969,6 +1996,13 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
 		*unconsumed += p - attr_start;
 		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 */
 		r = pax_attribute(a, tar, entry, attr_name.s, archive_strlen(&attr_name), value_length - 1, unconsumed);
 		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) {
 		__archive_read_consume(a, value_length);
 		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);
 	}
 
@@ -2212,7 +2247,7 @@ pax_attribute_SCHILY_acl(struct archive_read *a, struct tar *tar,
 }
 
 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;
 	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);
 	if (r < ARCHIVE_OK) {
 		archive_string_free(&as);
+		*ps = 0;
+		*pn = 0;
 		return (r);
 	}
 
 	pax_time(as.s, archive_strlen(&as), ps, pn);
 	archive_string_free(&as);
-	if (*ps < 0 || *ps == INT64_MAX) {
+	if (*ps == INT64_MIN) {
+		*ps = 0;
+		*pn = 0;
 		return (ARCHIVE_WARN);
 	}
 	return (ARCHIVE_OK);
@@ -2241,7 +2280,7 @@ pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps
 static int
 pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *result) {
 	struct archive_string as;
-	size_t unconsumed = 0;
+	int64_t unconsumed = 0;
 	int r;
 
 	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);
 	if (r < ARCHIVE_OK) {
 		archive_string_free(&as);
+		*result = 0;
 		return (r);
 	}
 
@@ -2281,7 +2321,7 @@ pax_attribute_read_number(struct archive_read *a, size_t value_length, int64_t *
  */
 static int
 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;
 	long n;
@@ -2365,8 +2405,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
 					tar->sparse_gnu_minor = 1;
 					if (value_length > sparse_map_limit) {
 						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;
 					} else {
 						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 {
 					archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 							  "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;
 				}
 				__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) {
 				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 						  "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? */
 				err = ARCHIVE_WARN;
 			} else {
@@ -2628,8 +2670,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
 					}
 				} else {
 					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;
 				}
 				__archive_read_consume(a, value_length);
@@ -2659,8 +2702,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
 					}
 				} else {
 					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;
 				}
 				__archive_read_consume(a, value_length);
@@ -2729,8 +2773,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent
 				}
 			} else {
 				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;
 			}
 			__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
 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) {
 		*ps = 0;
+		*pn = 0;
 		return;
 	}
 	s = 0;
@@ -2846,8 +2893,9 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
 		digit = *p - '0';
 		if (s > limit ||
 		    (s == limit && digit > last_digit_limit)) {
-			s = INT64_MAX;
-			break;
+			*ps = INT64_MIN;
+			*pn = 0;
+			return;
 		}
 		s = (s * 10) + digit;
 		++p;
@@ -2878,7 +2926,7 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
  */
 static int
 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;
 	int64_t t;
@@ -3029,7 +3077,7 @@ gnu_clear_sparse_list(struct tar *tar)
 
 static int
 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;
 	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
 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;
 	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
  * 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. */
 	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;
 
 	/* Parse entries. */
-	entries = (int)gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
+	entries = gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
 	if (entries < 0)
 		return (ARCHIVE_FATAL);
 	/* 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... */
 	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;
 	/* Fail if tar->entry_bytes_remaing would get negative */
 	if (to_skip > remaining)
 		return (ARCHIVE_FATAL);
 	if (to_skip != __archive_read_consume(a, to_skip))
 		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
 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 total_size = 0;

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

@@ -386,7 +386,8 @@ start_over:
 	case LAST_WT:
 	default:
 		/* consume the content and start over */
-		_warc_skip(a);
+		if (_warc_skip(a) < 0)
+			return (ARCHIVE_FATAL);
 		goto start_over;
 	}
 	return (ARCHIVE_OK);
@@ -439,7 +440,9 @@ _warc_skip(struct archive_read *a)
 {
 	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->cntoff = 0U;
 	return (ARCHIVE_OK);

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

@@ -36,6 +36,10 @@
 #include <bsdxml.h>
 #elif HAVE_EXPAT_H
 #include <cm3p/expat.h>
+#elif HAVE_XMLLITE_H
+#include <objidl.h>
+#include <initguid.h>
+#include <xmllite.h>
 #endif
 #ifdef HAVE_BZLIB_H
 #include <cm3p/bzlib.h>
@@ -56,12 +60,13 @@
 #include "archive_read_private.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(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
 /*
  * 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 zlib
  *   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_data_cb(void *, const XML_Char *, int);
 static int	expat_read_toc(struct archive_read *);
+#elif defined(HAVE_XMLLITE_H)
+static int	xmllite_read_toc(struct archive_read *);
 #endif
 
 int
@@ -589,6 +596,8 @@ read_toc(struct archive_read *a)
 	r = xml2_read_toc(a);
 #elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H)
 	r = expat_read_toc(a);
+#elif defined(HAVE_XMLLITE_H)
+	r = xmllite_read_toc(a);
 #endif
 	if (r != ARCHIVE_OK)
 		return (r);
@@ -1110,17 +1119,17 @@ atohex(unsigned char *b, size_t bsize, const char *p, size_t psize)
 	while (bsize && psize > 1) {
 		unsigned char x;
 
-		if (p[0] >= 'a' && p[0] <= 'z')
+		if (p[0] >= 'a' && p[0] <= 'f')
 			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;
 		else if (p[0] >= '0' && p[0] <= '9')
 			x = (p[0] - '0') << 4;
 		else
 			return (-1);
-		if (p[1] >= 'a' && p[1] <= 'z')
+		if (p[1] >= 'a' && p[1] <= 'f')
 			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;
 		else if (p[1] >= '0' && p[1] <= '9')
 			x |= p[1] - '0';
@@ -3333,6 +3342,326 @@ expat_read_toc(struct archive_read *a)
 	XML_ParserFree(parser);
 	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 */

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

@@ -71,6 +71,7 @@
 #include "archive_private.h"
 #include "archive_rb.h"
 #include "archive_read_private.h"
+#include "archive_time_private.h"
 #include "archive_ppmd8_private.h"
 
 #ifndef HAVE_ZLIB_H
@@ -465,27 +466,6 @@ compression_name(const int compression)
 	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
  *	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_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);
 	if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
 		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_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);
 		if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
 			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,
     const char *s, size_t length, struct archive_string_conv *sc)
 {
-	int count, ret = 0;
+	int ret = 0;
+	size_t count;
 	UINT from_cp;
 
 	if (sc != NULL)
@@ -494,7 +495,7 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
 		ws = dest->s + dest->length;
 		mp = (const unsigned char *)s;
 		count = 0;
-		while (count < (int)length && *mp) {
+		while (count < length && *mp) {
 			*ws++ = (wchar_t)*mp++;
 			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 NFC ===> UTF-16 NFD
 			 */
-			count = (int)utf16nbytes(s, length);
+			count = utf16nbytes(s, length);
 		} else {
 			/*
 			 *  UTF-8 NFD ===> UTF-16 NFC
 			 *  UTF-8 NFC ===> UTF-16 NFD
 			 */
-			count = (int)mbsnbytes(s, length);
+			count = mbsnbytes(s, length);
 		}
 		u16.s = (char *)dest->s;
 		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. */
 		return (ret);
 	} else if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) {
-		count = (int)utf16nbytes(s, length);
+		count = utf16nbytes(s, length);
 		count >>= 1; /* to be WCS length */
 		/* Allocate memory for WCS. */
 		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);
 		if ((sc->flag & SCONV_FROM_UTF16BE) && !IS_BIG_ENDIAN) {
 			uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
-			int b;
+			size_t b;
 			for (b = 0; b < count; b++) {
 				uint16_t val = archive_le16dec(u16+b);
 				archive_be16enc(u16+b, val);
 			}
 		} else if ((sc->flag & SCONV_FROM_UTF16LE) && IS_BIG_ENDIAN) {
 			uint16_t *u16 = (uint16_t *)(dest->s + dest->length);
-			int b;
+			size_t b;
 			for (b = 0; b < count; b++) {
 				uint16_t val = archive_be16dec(u16+b);
 				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;
 		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. */
 			if (NULL == archive_wstring_ensure(dest, buffsize))
 				return (-1);
 			/* Convert MBS to WCS. */
-			count = MultiByteToWideChar(from_cp,
+			r = MultiByteToWideChar(from_cp,
 			    mbflag, s, (int)length, dest->s + dest->length,
 			    (int)(dest->buffer_length >> 1) -1);
-			if (count == 0 &&
+			if (r == 0 &&
 			    GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
 				/* Expand the WCS buffer. */
 				buffsize = dest->buffer_length << 1;
 				continue;
 			}
-			if (count == 0 && length != 0)
+			if (r == 0 && length != 0)
 				ret = -1;
+			count = (size_t)r;
 			break;
 		} 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)
 {
 	BOOL defchar_used, *dp;
-	int count, ret = 0;
+	int ret = 0;
 	UINT to_cp;
-	int wslen = (int)len;
+	size_t count, wslen = len;
 
 	if (sc != NULL)
 		to_cp = sc->to_cp;
@@ -742,13 +750,13 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
 		count = 0;
 		defchar_used = 0;
 		if (sc->flag & SCONV_TO_UTF16BE) {
-			while (count < (int)len && *ws) {
+			while (count < len && *ws) {
 				archive_be16enc(u16+count, *ws);
 				ws++;
 				count++;
 			}
 		} else {
-			while (count < (int)len && *ws) {
+			while (count < len && *ws) {
 				archive_le16enc(u16+count, *ws);
 				ws++;
 				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))
 			return (-1);
 		do {
+			int r;
+
 			defchar_used = 0;
 			if (to_cp == CP_UTF8 || sc == NULL)
 				dp = NULL;
 			else
 				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,
-			    (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) {
 				/* Expand the MBS buffer and retry. */
 				if (NULL == archive_string_ensure(as,
@@ -777,8 +791,9 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
 					return (-1);
 				continue;
 			}
-			if (count == 0)
+			if (r == 0)
 				ret = -1;
+			count = (size_t)r;
 			break;
 		} while (1);
 	}
@@ -2054,7 +2069,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
 	char *outp;
 	size_t avail, bs;
 	int return_value = 0; /* success */
-	int to_size, from_size;
+	size_t to_size, from_size;
 
 	if (sc->flag & SCONV_TO_UTF16)
 		to_size = 2;
@@ -2073,7 +2088,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
 	remaining = length;
 	outp = as->s + as->length;
 	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);
 
 		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)
 		mbflag |= MB_PRECOMPOSED;
 
+	if (n > (size_t)INT_MAX)
+		return (-1); /* Invalid */
 	if (MultiByteToWideChar(codepage, mbflag, p, (int)n, NULL, 0) == 0)
 		return (-1); /* Invalid */
 	return (0); /* Okay */
@@ -2349,7 +2366,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
 	cnt = utf8_count[ch];
 
 	/* Invalid sequence or there are not plenty bytes. */
-	if ((int)n < cnt) {
+	if (n < (size_t)cnt) {
 		cnt = (int)n;
 		for (i = 1; i < cnt; i++) {
 			if ((s[i] & 0xc0) != 0x80) {
@@ -2418,7 +2435,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
 			cnt = 6;
 		else
 			cnt = 1;
-		if ((int)n < cnt)
+		if (n < (size_t)cnt)
 			cnt = (int)n;
 		for (i = 1; i < cnt; i++) {
 			if ((s[i] & 0xc0) != 0x80) {
@@ -2634,7 +2651,7 @@ unicode_to_utf16be(char *p, size_t remaining, uint32_t uc)
 	} else {
 		if (remaining < 2)
 			return (0);
-		archive_be16enc(utf16, uc);
+		archive_be16enc(utf16, (uint16_t)uc);
 		return (2);
 	}
 }
@@ -2656,7 +2673,7 @@ unicode_to_utf16le(char *p, size_t remaining, uint32_t uc)
 	} else {
 		if (remaining < 2)
 			return (0);
-		archive_le16enc(utf16, uc);
+		archive_le16enc(utf16, (uint16_t)uc);
 		return (2);
 	}
 }
@@ -3521,10 +3538,9 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
 {
 	struct archive_string tmp;
 	const char *u16;
-	int ll;
 	BOOL defchar;
 	char *mbs;
-	size_t mbs_size, b;
+	size_t mbs_size, b, ll;
 	int ret = 0;
 
 	bytes &= ~1;
@@ -3588,18 +3604,24 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
 	}
 
 	do {
+		int r;
 		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,
 			NULL, &defchar);
 		/* Exit loop if we succeeded */
-		if (ll != 0 ||
+		if (r != 0 ||
 		    GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+			ll = (size_t)r;
 			break;
 		}
 		/* 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);
+		ll = (size_t)r;
 		if (archive_string_ensure(as, ll +1) == NULL)
 			return (-1);
 		mbs = as->s + as->length;
@@ -3665,16 +3687,21 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
 		return (0);
 	}
 	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);
 		/* Exit loop if we succeeded */
-		if (count != 0 ||
+		if (r != 0 ||
 		    GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+			count = (size_t)r;
 			break;
 		}
 		/* Expand buffer and try again */
-		count = MultiByteToWideChar(sc->from_cp,
+		r = MultiByteToWideChar(sc->from_cp,
 		    MB_PRECOMPOSED, s, (int)length, NULL, 0);
+		count = (size_t)r;
 		if (archive_string_ensure(as16, (count +1) * 2)
 		    == NULL)
 			return (-1);
@@ -3825,9 +3852,9 @@ best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p,
 			ret = -1;
 		}
 		if (bigendian)
-			archive_be16enc(utf16, c);
+			archive_be16enc(utf16, (uint16_t)c);
 		else
-			archive_le16enc(utf16, c);
+			archive_le16enc(utf16, (uint16_t)c);
 		utf16 += 2;
 	}
 	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 },
 };
 
-#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';
 		switch(*p) {
-		case 'j':
 		case 'l':
+			if (p[1] == 'l') {
+				long_flag = 'L';
+				p += 2;
+				break;
+			}
+			__LA_FALLTHROUGH;
+		case 'j':
 		case 'z':
 			long_flag = *p;
 			p++;
@@ -136,6 +142,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
 			switch(long_flag) {
 			case 'j': s = va_arg(ap, intmax_t); 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;
 			default:  s = va_arg(ap, int); break;
 			}
@@ -144,6 +151,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
 		case 's':
 			switch(long_flag) {
 			case 'l':
+			case 'L':
 				pw = va_arg(ap, wchar_t *);
 				if (pw == NULL)
 					pw = L"(null)";
@@ -172,6 +180,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
 			switch(long_flag) {
 			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 long); break;
 			case 'z': u = va_arg(ap, size_t); 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.
  *
  * 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
  * 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
 #error This header is only to be used internally to libarchive.
 #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 /* ARCHIVE_TIME_PRIVATE_H_INCLUDED */

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

@@ -77,7 +77,9 @@
 #define O_CLOEXEC	0
 #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. */
 int
@@ -629,74 +631,28 @@ __archive_ensure_cloexec_flag(int fd)
 #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
-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
 archive_utility_string_sort(char **strings)
 {
-	  unsigned int size = 0;
-	  while (strings[size] != NULL)
+	size_t size = 0;
+	while (strings[size] != NULL)
 		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
 #ifdef HAVE_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
 
 #include "archive.h"
 #include "archive_private.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 *
 archive_version_details(void)
@@ -62,12 +176,17 @@ archive_version_details(void)
 	const char *bzlib = archive_bzlib_version();
 	const char *liblz4 = archive_liblz4_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) {
 		archive_string_init(&str);
 
 		archive_strcat(&str, ARCHIVE_VERSION_STRING);
-		if (zlib != NULL) {
+		if (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);
 		}
+		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;
 }
@@ -98,8 +241,8 @@ archive_version_details(void)
 const char *
 archive_zlib_version(void)
 {
-#ifdef HAVE_ZLIB_H
-	return ZLIB_VERSION;
+#if HAVE_ZLIB_H && HAVE_LIBZ
+	return zlibVersion();
 #else
 	return NULL;
 #endif
@@ -108,8 +251,8 @@ archive_zlib_version(void)
 const char *
 archive_liblzma_version(void)
 {
-#ifdef HAVE_LZMA_H
-	return LZMA_VERSION_STRING;
+#if HAVE_LZMA_H && HAVE_LIBLZMA
+	return lzma_version_string();
 #else
 	return NULL;
 #endif
@@ -118,7 +261,7 @@ archive_liblzma_version(void)
 const char *
 archive_bzlib_version(void)
 {
-#ifdef HAVE_BZLIB_H
+#if HAVE_BZLIB_H && HAVE_LIBBZ2
 	return BZ2_bzlibVersion();
 #else
 	return NULL;
@@ -128,12 +271,22 @@ archive_bzlib_version(void)
 const char *
 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 NUMBER(x) str(x)
 	return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
 #undef NUMBER
 #undef str
+#endif
 #else
 	return NULL;
 #endif
@@ -143,7 +296,243 @@ const char *
 archive_libzstd_version(void)
 {
 #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
 	return NULL;
 #endif

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

@@ -47,6 +47,7 @@
 #include "archive_platform.h"
 #include "archive_private.h"
 #include "archive_entry.h"
+#include "archive_time_private.h"
 #include <ctype.h>
 #include <errno.h>
 #include <stddef.h>
@@ -61,8 +62,6 @@
 #include <windows.h>
 #include <share.h>
 
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-
 #if defined(__LA_LSEEK_NEEDED)
 static BOOL SetFilePointerEx_perso(HANDLE hFile,
 				   LARGE_INTEGER liDistanceToMove,
@@ -450,24 +449,6 @@ __la_read(int fd, void *buf, size_t nbytes)
 	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
  * Windows' stat() does not accept the path added "\\?\" especially "?"
  * character.
@@ -487,8 +468,6 @@ __hstat(HANDLE handle, struct ustat *st)
 	ULARGE_INTEGER ino64;
 	DWORD ftype;
 	mode_t mode;
-	time_t t;
-	long ns;
 
 	switch (ftype = GetFileType(handle)) {
 	case FILE_TYPE_UNKNOWN:
@@ -544,15 +523,9 @@ __hstat(HANDLE handle, struct ustat *st)
 		mode |= S_IFREG;
 	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 =
 	    ((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1))
 		+ (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 /* 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
 __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 {
 	int		 compression_level;
 	int		 timestamp;
+	char	*original_filename;
 #ifdef HAVE_ZLIB_H
 	z_stream	 stream;
 	int64_t		 total_in;
@@ -113,6 +114,8 @@ archive_write_add_filter_gzip(struct archive *_a)
 	f->free = &archive_compressor_gzip_free;
 	f->code = ARCHIVE_FILTER_GZIP;
 	f->name = "gzip";
+
+	data->original_filename = NULL;
 #ifdef HAVE_ZLIB_H
 	data->compression_level = Z_DEFAULT_COMPRESSION;
 	return (ARCHIVE_OK);
@@ -140,6 +143,7 @@ archive_compressor_gzip_free(struct archive_write_filter *f)
 #else
 	__archive_write_program_free(data->pdata);
 #endif
+	free((void*)data->original_filename);
 	free(data);
 	f->data = NULL;
 	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;
 		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
 	 * 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[1] = 0x8b;
 	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) {
 		time_t t = time(NULL);
 		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.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;
 
 	/* Initialize compression library. */

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

@@ -60,6 +60,7 @@
 #include "archive_string.h"
 #include "archive_entry.h"
 #include "archive_private.h"
+#include "archive_time_private.h"
 
 #ifndef O_BINARY
 #define O_BINARY 0
@@ -407,7 +408,11 @@ permissive_name_w(struct archive_write_disk *a)
 		wn = _wcsdup(wnp);
 		if (wn == NULL)
 			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;
 		/* Prepend "\\?\" */
 		archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
@@ -437,8 +442,11 @@ permissive_name_w(struct archive_write_disk *a)
 				wn = _wcsdup(wnp);
 				if (wn == NULL)
 					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;
 				/* Prepend "\\?\UNC\" */
 				archive_wstrncpy(&(a->_name_data),
@@ -470,10 +478,16 @@ permissive_name_w(struct archive_write_disk *a)
 	 */
 	if (wnp[0] == L'\\') {
 		wn = _wcsdup(wnp);
-		if (wn == NULL)
+		if (wn == NULL) {
+			free(wsp);
 			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;
 		/* Prepend "\\?\" and drive name. */
 		archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
@@ -485,9 +499,16 @@ permissive_name_w(struct archive_write_disk *a)
 	}
 
 	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);
-	archive_wstring_ensure(&(a->_name_data), 4 + l + 1 + wcslen(wn) + 1);
+	}
 	a->name = a->_name_data.s;
 	/* Prepend "\\?\" and drive name if not already added. */
 	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
  * the link target
@@ -2605,10 +2626,6 @@ set_times(struct archive_write_disk *a,
     time_t mtime, long mtime_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;
 	ULARGE_INTEGER wintm;
 	FILETIME *pfbtime;
@@ -2646,17 +2663,17 @@ set_times(struct archive_write_disk *a,
 		h = hw;
 	}
 
-	wintm.QuadPart = WINTIME(atime, atime_nanos);
+	wintm.QuadPart = unix_to_ntfs(atime, atime_nanos);
 	fatime.dwLowDateTime = wintm.LowPart;
 	fatime.dwHighDateTime = wintm.HighPart;
-	wintm.QuadPart = WINTIME(mtime, mtime_nanos);
+	wintm.QuadPart = unix_to_ntfs(mtime, mtime_nanos);
 	fmtime.dwLowDateTime = wintm.LowPart;
 	fmtime.dwHighDateTime = wintm.HighPart;
 	/*
 	 * SetFileTime() supports birthtime.
 	 */
 	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.dwHighDateTime = wintm.HighPart;
 		pfbtime = &fbtime;
@@ -2878,34 +2895,16 @@ set_xattrs(struct archive_write_disk *a)
 	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.
  */
 static int
 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. */
 	/* Definitely older. */
 	if (sec < archive_entry_mtime(entry))
@@ -2913,11 +2912,10 @@ older(BY_HANDLE_FILE_INFORMATION *st, struct archive_entry *entry)
 	/* Definitely younger. */
 	if (sec > archive_entry_mtime(entry))
 		return (0);
-	if (nsec < archive_entry_mtime_nsec(entry))
+	if ((long)nsec < archive_entry_mtime_nsec(entry))
 		return (1);
 	/* Same age or newer, so not older. */
 	return (0);
 }
 
 #endif /* _WIN32 && !__CYGWIN__ */
-

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

@@ -28,7 +28,12 @@
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
+#ifdef HAVE_STDLIB_H
 #include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #ifdef HAVE_BZLIB_H
 #include <cm3p/bzlib.h>
 #endif
@@ -38,6 +43,9 @@
 #ifdef HAVE_ZLIB_H
 #include <cm3p/zlib.h>
 #endif
+#ifdef HAVE_ZSTD_H
+#include <cm3p/zstd.h>
+#endif
 
 #include "archive.h"
 #ifndef HAVE_ZLIB_H
@@ -50,6 +58,7 @@
 #include "archive_private.h"
 #include "archive_rb.h"
 #include "archive_string.h"
+#include "archive_time_private.h"
 #include "archive_write_private.h"
 #include "archive_write_set_format_private.h"
 
@@ -63,6 +72,8 @@
 #define _7Z_BZIP2	0x040202
 #define _7Z_PPMD	0x030401
 
+#define _7Z_ZSTD	0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
+
 /*
  * 7-Zip header property IDs.
  */
@@ -110,6 +121,9 @@
 // the attr field along with the unix permissions.
 #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 {
 	ARCHIVE_Z_FINISH,
 	ARCHIVE_Z_RUN
@@ -209,7 +223,11 @@ struct _7zip {
 #define	ENCODED_CRC32	2
 
 	unsigned		 opt_compression;
+
 	int			 opt_compression_level;
+	int			 opt_zstd_compression_level; // This requires a different default value.
+
+	int			 opt_threads;
 
 	struct la_zstream	 stream;
 	struct coder		 coder;
@@ -285,12 +303,19 @@ static int	compression_code_lzma(struct archive *,
 static int	compression_end_lzma(struct archive *, struct la_zstream *);
 #endif
 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 *,
 		    struct la_zstream *, enum la_zaction);
 static int	compression_end_ppmd(struct archive *, struct la_zstream *);
 static int	_7z_compression_init_encoder(struct archive_write *, unsigned,
 		    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 *,
 		    struct la_zstream *, enum la_zaction);
 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,
 		    	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
 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;
 #elif defined(HAVE_ZLIB_H)
 	zip->opt_compression = _7Z_DEFLATE;
+#elif HAVE_ZSTD_H
+	zip->opt_compression = _7Z_ZSTD;
 #else
 	zip->opt_compression = _7Z_COPY;
 #endif
+
 	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_name = "7zip";
@@ -397,6 +450,13 @@ _7z_options(struct archive_write *a, const char *key, const char *value)
 			zip->opt_compression = _7Z_LZMA2;
 #else
 			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
 		else if (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);
 	}
 	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);
 		}
-		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);
 	}
 
@@ -495,8 +607,20 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry)
 	 * Init compression.
 	 */
 	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) {
 			file_free(file);
 			return (ARCHIVE_FATAL);
@@ -785,8 +909,12 @@ _7z_close(struct archive_write *a)
 #else
 		header_compression = _7Z_COPY;
 #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)
 			return (r);
 		zip->crc32flg = PRECODE_CRC32;
@@ -844,7 +972,7 @@ _7z_close(struct archive_write *a)
 		header_offset = header_size = 0;
 		header_crc32 = 0;
 	}
-	
+
 	length = zip->temp_offset;
 
 	/*
@@ -1164,20 +1292,6 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
 	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
 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)
 		return (r);
 
-
 	/*
 	 * 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) {
 		if ((file->flg & flg) == 0)
 			continue;
-		archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
+		archive_le64enc(filetime, unix_to_ntfs(file->times[ti].time,
 			file->times[ti].time_ns));
 		r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
 		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 (f1->name_len > f2->name_len)?1:-1;
 }
-        
+
 static int
 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) ||\
-	 !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
+	 !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) ||\
+	 !(HAVE_ZSTD_H && HAVE_ZSTD_compressStream)
 static int
 compression_unsupported_encoder(struct archive *a,
     struct la_zstream *lastrm, const char *name)
@@ -2159,7 +2273,7 @@ ppmd_write(void *p, Byte b)
 
 static int
 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;
 	uint8_t *props;
@@ -2279,6 +2393,117 @@ compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
 	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.
  */
@@ -2316,6 +2541,11 @@ _7z_compression_init_encoder(struct archive_write *a, unsigned compression,
 		    &(a->archive), &(zip->stream),
 		    PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE);
 		break;
+	case _7Z_ZSTD:
+		r = compression_init_encoder_zstd(
+		    &(a->archive), &(zip->stream),
+		    compression_level, zip->opt_threads);
+		break;
 	case _7Z_COPY:
 	default:
 		r = compression_init_encoder_copy(
@@ -2352,5 +2582,3 @@ compression_end(struct archive *a, struct la_zstream *lastrm)
 	}
 	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 *,
 		    const char *, const char *);
 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 *,
 		    struct archive_entry *entry);
 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];
 	int r, ret, ret2 = ARCHIVE_OK;
-	int tartype;
+	char tartype;
 	struct gnutar *gnutar;
 	struct archive_string_conv *sconv;
 	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_gname(temp, "wheel");
 
-		archive_entry_set_pathname(temp, "././@LongLink");
+		archive_entry_set_pathname(temp, "././@LongName");
 		archive_entry_set_size(temp, length);
 		ret = archive_format_gnutar_header(a, buff, temp, 'L');
 		archive_entry_free(temp);
@@ -562,7 +562,7 @@ exit_write_header:
 
 static int
 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;
 	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,
 		GNUTAR_uid_size, GNUTAR_uid_max_size)) {
 		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));
 		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,
 		GNUTAR_gid_size, GNUTAR_gid_max_size)) {
 		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));
 		ret = ARCHIVE_FAILED;
 	}
@@ -672,7 +672,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
 		    h + GNUTAR_rdevmajor_offset,
 			GNUTAR_rdevmajor_size)) {
 			archive_set_error(&a->archive, ERANGE,
-			    "Major device number too large");
+			    "Major device number too large for gnutar format");
 			ret = ARCHIVE_FAILED;
 		}
 
@@ -680,7 +680,7 @@ archive_format_gnutar_header(struct archive_write *a, char h[512],
 		    h + GNUTAR_rdevminor_offset,
 			GNUTAR_rdevminor_size)) {
 			archive_set_error(&a->archive, ERANGE,
-			    "Minor device number too large");
+			    "Minor device number too large for gnutar format");
 			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->cur_dirent = iso9660->primary.rootent;
 	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->sconv_to_utf16be = NULL;
 	iso9660->sconv_from_utf16be = NULL;
@@ -5670,9 +5675,15 @@ isoent_tree(struct archive_write *a, struct isoent **isoentpp)
 		 * inserted. */
 		iso9660->cur_dirent = dent;
 		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->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)) +
 		    archive_strlen(&(dent->file->basename)) == 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 {
 	int compute_sum;
 	uint32_t crc;
+	uint_least32_t mset_digest;
 	struct ae_digest digest;
 };
 
@@ -862,6 +863,50 @@ mtree_entry_free(struct mtree_entry *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
 archive_write_mtree_header(struct archive_write *a,
     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
 	 * compute the sum of its content.
 	 * Initialize a bunch of checksum context. */
-	if (mtree_entry->reg_info)
+	if (mtree_entry->reg_info) {
 		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);
 }
@@ -1516,28 +1565,46 @@ sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
 		mtree->crc_len += n;
 	}
 #ifdef ARCHIVE_HAS_MD5
-	if (mtree->compute_sum & F_MD5)
+	if (mtree->compute_sum & F_MD5) {
 		archive_md5_update(&mtree->md5ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_MD5;
+	}
 #endif
 #ifdef ARCHIVE_HAS_RMD160
-	if (mtree->compute_sum & F_RMD160)
+	if (mtree->compute_sum & F_RMD160) {
 		archive_rmd160_update(&mtree->rmd160ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_RMD160;
+	}
 #endif
 #ifdef ARCHIVE_HAS_SHA1
-	if (mtree->compute_sum & F_SHA1)
+	if (mtree->compute_sum & F_SHA1) {
 		archive_sha1_update(&mtree->sha1ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_SHA1;
+	}
 #endif
 #ifdef ARCHIVE_HAS_SHA256
-	if (mtree->compute_sum & F_SHA256)
+	if (mtree->compute_sum & F_SHA256) {
 		archive_sha256_update(&mtree->sha256ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_SHA256;
+	}
 #endif
 #ifdef ARCHIVE_HAS_SHA384
-	if (mtree->compute_sum & F_SHA384)
+	if (mtree->compute_sum & F_SHA384) {
 		archive_sha384_update(&mtree->sha384ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_SHA384;
+	}
 #endif
 #ifdef ARCHIVE_HAS_SHA512
-	if (mtree->compute_sum & F_SHA512)
+	if (mtree->compute_sum & F_SHA512) {
 		archive_sha512_update(&mtree->sha512ctx, buff, n);
+		mtree->mtree_entry->reg_info->mset_digest &=
+			~AE_MSET_DIGEST_SHA512;
+	}
 #endif
 }
 
@@ -1553,27 +1620,39 @@ sum_final(struct mtree_writer *mtree, struct reg_info *reg)
 		reg->crc = ~mtree->crc;
 	}
 #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);
 #endif
 #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);
 #endif
 #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);
 #endif
 #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);
 #endif
 #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);
 #endif
 #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);
 #endif
 	/* Save what types of sum are computed. */
@@ -2130,9 +2209,13 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
 		 * inserted. */
 		mtree->cur_dirent = dent;
 		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->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)) +
 		    archive_strlen(&(dent->basename)) == 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;
 		time_t s;
 		int64_t uid, gid;
-		int mode;
+		__LA_MODE_T mode;
 
 		pax_attr_entry = archive_entry_new2(&a->archive);
 		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;
 	char *p;
 	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;
 
 	/* 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
 	 * trailing '/'. */
 	prefix = src;
-	prefix_end = prefix + 155;
+	prefix_end = prefix + 154 /* 155 - 1 for trailing / */;
 	if (prefix_end > filename)
 		prefix_end = filename;
 	while (prefix_end > prefix && *prefix_end != '/')

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

@@ -34,6 +34,14 @@
 #include <stdlib.h>
 #if HAVE_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
 #ifdef HAVE_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(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
 /*
  * xar needs several external libraries.
- *   o libxml2
+ *   o libxml2 or xmllite (on Windows)
  *   o openssl or MD5/SHA1 hash function
  *   o zlib
  *   o bzlib2 (option)
@@ -94,9 +101,26 @@ archive_write_set_format_xar(struct archive *_a)
 
 #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_SIZE	28
@@ -807,50 +831,49 @@ xar_finish_entry(struct archive_write *a)
 }
 
 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 *attrkey, const char *attrvalue)
 {
 	int r;
 
-	r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
+	r = xml_writer_start_element(writer, key);
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartElement() failed: %d", r);
+		    "xml_writer_start_element() failed: %d", r);
 		return (ARCHIVE_FATAL);
 	}
 	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) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
+			    "xml_writer_write_attribute() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 	}
 	if (value != NULL) {
-		r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
+		r = xml_writer_write_string(writer, value);
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteString() failed: %d", r);
+			    "xml_writer_write_string() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 	}
-	r = xmlTextWriterEndElement(writer);
+	r = xml_writer_end_element(writer);
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterEndElement() failed: %d", r);
+		    "xml_writer_end_element() failed: %d", r);
 		return (ARCHIVE_FATAL);
 	}
 	return (ARCHIVE_OK);
 }
 
 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)
 {
 	int r;
@@ -858,34 +881,34 @@ xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer,
 	if (value == NULL)
 		return (ARCHIVE_OK);
 
-	r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key));
+	r = xml_writer_start_element(writer, key);
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartElement() failed: %d", r);
+		    "xml_writer_start_element() failed: %d", r);
 		return (ARCHIVE_FATAL);
 	}
 	if (value != NULL) {
-		r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value));
+		r = xml_writer_write_string(writer, value);
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteString() failed: %d", r);
+			    "xml_writer_write_string() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 	}
-	r = xmlTextWriterEndElement(writer);
+	r = xml_writer_end_element(writer);
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterEndElement() failed: %d", r);
+		    "xml_writer_end_element() failed: %d", r);
 		return (ARCHIVE_FATAL);
 	}
 	return (ARCHIVE_OK);
 }
 
 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, ...)
 {
 	struct xar *xar;
@@ -900,7 +923,7 @@ xmlwrite_fstring(struct archive_write *a, xmlTextWriterPtr writer,
 }
 
 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)
 {
 	char timestr[100];
@@ -922,7 +945,7 @@ xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
 }
 
 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)
 {
 	char ms[5];
@@ -937,7 +960,7 @@ xmlwrite_mode(struct archive_write *a, xmlTextWriterPtr writer,
 }
 
 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 *algname;
@@ -971,7 +994,7 @@ xmlwrite_sum(struct archive_write *a, xmlTextWriterPtr writer,
 }
 
 static int
-xmlwrite_heap(struct archive_write *a, xmlTextWriterPtr writer,
+xmlwrite_heap(struct archive_write *a, struct xml_writer *writer,
 	struct heap_data *heap)
 {
 	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.
  */
 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)
 {
 	static const struct flagentry {
@@ -1119,11 +1142,11 @@ make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
 	} while (p != NULL);
 
 	if (n > 0) {
-		r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(element));
+		r = xml_writer_start_element(writer, element);
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 		for (i = 0; i < n; i++) {
@@ -1133,29 +1156,59 @@ make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer,
 				return (r);
 		}
 
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 	}
 	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
-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 xar *xar;
 	const char *filetype, *filelink, *fflags;
 	struct archive_string linkto;
 	struct heap_data *heap;
-	unsigned char *tmp;
 	const char *p;
 	size_t len;
-	int r, r2, l, ll;
+	int r, r2;
 
 	xar = (struct xar *)a->format_data;
 	r2 = ARCHIVE_OK;
@@ -1163,44 +1216,35 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 	/*
 	 * 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) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
-		r = xmlTextWriterWriteAttribute(writer,
-		    BAD_CAST("enctype"), BAD_CAST("base64"));
+		r = xml_writer_write_attribute(writer,
+		    "enctype", "base64");
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
+			    "xml_writer_write_attribute() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
-		r = xmlTextWriterWriteBase64(writer, file->basename.s,
+		r = xml_writer_write_base64(writer, file->basename.s,
 		    0, (int)archive_strlen(&(file->basename)));
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteBase64() failed: %d", r);
+			    "xml_writer_write_base64() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 	} else {
@@ -1281,11 +1325,11 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 		break;
 	case AE_IFCHR:
 	case AE_IFBLK:
-		r = xmlTextWriterStartElement(writer, BAD_CAST("device"));
+		r = xml_writer_start_element(writer, "device");
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 		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));
 		if (r < 0)
 			return (ARCHIVE_FATAL);
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 		break;
@@ -1436,19 +1480,19 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 
 		archive_entry_xattr_next(file->entry,
 		    &name, &value, &size);
-		r = xmlTextWriterStartElement(writer, BAD_CAST("ea"));
+		r = xml_writer_start_element(writer, "ea");
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			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) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
+			    "xml_writer_write_attributef() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 		r = xmlwrite_heap(a, writer, heap);
@@ -1458,11 +1502,11 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 		if (r < 0)
 			return (ARCHIVE_FATAL);
 
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 	}
@@ -1471,11 +1515,11 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 	 * Make a file data entry, "<data>".
 	 */
 	if (file->data.length > 0) {
-		r = xmlTextWriterStartElement(writer, BAD_CAST("data"));
+		r = xml_writer_start_element(writer, "data");
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 
@@ -1483,21 +1527,21 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 		if (r < 0)
 			return (ARCHIVE_FATAL);
 
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 	}
 
 	if (archive_strlen(&file->script) > 0) {
-		r = xmlTextWriterStartElement(writer, BAD_CAST("content"));
+		r = xml_writer_start_element(writer, "content");
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 
@@ -1510,11 +1554,11 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
 		if (r < 0)
 			return (ARCHIVE_FATAL);
 
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			return (ARCHIVE_FATAL);
 		}
 	}
@@ -1530,8 +1574,9 @@ make_toc(struct archive_write *a)
 {
 	struct xar *xar;
 	struct file *np;
-	xmlBufferPtr bp;
-	xmlTextWriterPtr writer;
+	struct xml_writer *writer;
+	const char* content;
+	size_t use;
 	int algsize;
 	int r, ret;
 
@@ -1543,51 +1588,43 @@ make_toc(struct archive_write *a)
 	 * Initialize xml writer.
 	 */
 	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_ERRNO_MISC,
-		    "xmlNewTextWriterMemory() "
-		    "couldn't create xml writer");
+		    "xml_writer_create() failed: %d", r);
 		goto exit_toc;
 	}
-	r = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL);
+	r = xml_writer_set_indent(writer, 4);
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartDocument() failed: %d", r);
+		    "xml_writer_set_indent() failed: %d", r);
 		goto exit_toc;
 	}
-	r = xmlTextWriterSetIndent(writer, 4);
+	r = xml_writer_start_document(writer);
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterSetIndent() failed: %d", r);
+		    "xml_writer_start_document() failed: %d", r);
 		goto exit_toc;
 	}
 
 	/*
 	 * Start recording TOC
 	 */
-	r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
+	r = xml_writer_start_element(writer, "xar");
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartElement() failed: %d", r);
+		    "xml_writer_start_element() failed: %d", r);
 		goto exit_toc;
 	}
-	r = xmlTextWriterStartElement(writer, BAD_CAST("toc"));
+	r = xml_writer_start_element(writer, "toc");
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterStartDocument() failed: %d", r);
+		    "xml_writer_start_element() failed: %d", r);
 		goto exit_toc;
 	}
 
@@ -1606,19 +1643,19 @@ make_toc(struct archive_write *a)
 		/*
 		 * Record TOC checksum
 		 */
-		r = xmlTextWriterStartElement(writer, BAD_CAST("checksum"));
+		r = xml_writer_start_element(writer, "checksum");
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterStartElement() failed: %d", r);
+			    "xml_writer_start_element() failed: %d", r);
 			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) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterWriteAttribute() failed: %d", r);
+			    "xml_writer_write_attribute() failed: %d", r);
 			goto exit_toc;
 		}
 
@@ -1636,11 +1673,11 @@ make_toc(struct archive_write *a)
 		if (r < 0)
 			goto exit_toc;
 
-		r = xmlTextWriterEndElement(writer);
+		r = xml_writer_end_element(writer);
 		if (r < 0) {
 			archive_set_error(&a->archive,
 			    ARCHIVE_ERRNO_MISC,
-			    "xmlTextWriterEndElement() failed: %d", r);
+			    "xml_writer_end_element() failed: %d", r);
 			goto exit_toc;
 		}
 	}
@@ -1656,32 +1693,32 @@ make_toc(struct archive_write *a)
 		if (np->dir && np->children.first != NULL) {
 			/* Enter to sub directories. */
 			np = np->children.first;
-			r = xmlTextWriterStartElement(writer,
-			    BAD_CAST("file"));
+			r = xml_writer_start_element(writer,
+			    "file");
 			if (r < 0) {
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
-				    "xmlTextWriterStartElement() "
+				    "xml_writer_start_element() "
 				    "failed: %d", r);
 				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) {
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
-				    "xmlTextWriterWriteAttribute() "
+				    "xml_writer_write_attributef() "
 				    "failed: %d", r);
 				goto exit_toc;
 			}
 			continue;
 		}
 		while (np != np->parent) {
-			r = xmlTextWriterEndElement(writer);
+			r = xml_writer_end_element(writer);
 			if (r < 0) {
 				archive_set_error(&a->archive,
 				    ARCHIVE_ERRNO_MISC,
-				    "xmlTextWriterEndElement() "
+				    "xml_writer_end_element() "
 				    "failed: %d", r);
 				goto exit_toc;
 			}
@@ -1690,21 +1727,21 @@ make_toc(struct archive_write *a)
 				np = np->parent;
 			} else {
 				np = np->chnext;
-				r = xmlTextWriterStartElement(writer,
-				    BAD_CAST("file"));
+				r = xml_writer_start_element(writer,
+				    "file");
 				if (r < 0) {
 					archive_set_error(&a->archive,
 					    ARCHIVE_ERRNO_MISC,
-					    "xmlTextWriterStartElement() "
+					    "xml_writer_start_element() "
 					    "failed: %d", r);
 					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) {
 					archive_set_error(&a->archive,
 					    ARCHIVE_ERRNO_MISC,
-					    "xmlTextWriterWriteAttribute() "
+					    "xml_writer_write_attributef() "
 					    "failed: %d", r);
 					goto exit_toc;
 				}
@@ -1713,31 +1750,40 @@ make_toc(struct archive_write *a)
 		}
 	} while (np != np->parent);
 
-	r = xmlTextWriterEndDocument(writer);
+	r = xml_writer_end_document(writer);
 	if (r < 0) {
 		archive_set_error(&a->archive,
 		    ARCHIVE_ERRNO_MISC,
-		    "xmlTextWriterEndDocument() failed: %d", r);
+		    "xml_writer_end_document() failed: %d", r);
 		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
 	fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n",
-	    strlen((const char *)bp->content), bp->content);
+	    (int)strlen(content), content);
 #endif
 
 	/*
 	 * Compress the TOC and calculate the sum of the TOC.
 	 */
 	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);
 
 	r = compression_init_encoder_gzip(&(a->archive),
 	    &(xar->stream), 6, 1);
 	if (r != ARCHIVE_OK)
 		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.next_out = xar->wbuff;
 	xar->stream.avail_out = sizeof(xar->wbuff);
@@ -1768,9 +1814,7 @@ make_toc(struct archive_write *a)
 	ret = ARCHIVE_OK;
 exit_toc:
 	if (writer)
-		xmlFreeTextWriter(writer);
-	if (bp)
-		xmlBufferFree(bp);
+		xml_writer_destroy(writer);
 
 	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 */

Fișier diff suprimat deoarece este prea mare
+ 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
 number of threads for multi-threaded zstd compression.
 If set to 0, zstd will attempt to detect and use the number
-of physical CPU cores.
+of active physical CPU cores.
 .El
 .It Format 7zip
 .Bl -tag -compact -width indent
@@ -274,9 +274,10 @@ The value is one of
 .Dq deflate ,
 .Dq bzip2 ,
 .Dq lzma1 ,
-.Dq lzma2
+.Dq lzma2 ,
+.Dq ppmd ,
 or
-.Dq ppmd
+.Dq zstd
 to indicate how the following entries should be compressed.
 The values
 .Dq store
@@ -289,9 +290,16 @@ and other special entries.
 The value is interpreted as a decimal integer specifying the
 compression level.
 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
 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
 .It Format bin
 .Bl -tag -compact -width indent
@@ -632,9 +640,13 @@ and
 .Bl -tag -compact -width indent
 .It Cm compression
 The value is either
-.Dq store
+.Dq store ,
+.Dq deflate ,
+.Dq bzip2 ,
+.Dq lzma ,
+.Dq xz ,
 or
-.Dq deflate
+.Dq zstd
 to indicate how the following entries should be compressed.
 Note that this setting is ignored for directories, symbolic links,
 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
 .Dq store ,
 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
 Enable encryption using traditional zip encryption.
 .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
 uncompressed entries and entries compressed with the
 .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.
 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
 reading Zip archives:
 a streaming strategy which is fast and can handle extremely

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff