mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-06 06:10:04 -05:00
LibArchive 2025-06-01 (9525f90c)
Code extracted from:
https://github.com/libarchive/libarchive.git
at commit 9525f90ca4bd14c7b335e2f8c84a4607b0af6bdf (v3.8.1).
This commit is contained in:
committed by
Brad King
parent
73f3c99bfb
commit
bb6def24fe
+62
-11
@@ -94,6 +94,9 @@ set(MACHO_CURRENT_VERSION "${MACHO_COMPATIBILITY_VERSION}.${_revision}")
|
||||
# saving and restoring the state of the variables.
|
||||
INCLUDE(CMakePushCheckState)
|
||||
|
||||
# Enable the pkg-config helpers.
|
||||
INCLUDE(FindPkgConfig)
|
||||
|
||||
# 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)
|
||||
@@ -225,6 +228,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)
|
||||
@@ -353,10 +357,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.
|
||||
@@ -581,6 +587,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)
|
||||
@@ -593,8 +600,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
|
||||
@@ -657,6 +669,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.
|
||||
#
|
||||
@@ -665,7 +678,6 @@ ENDIF(ZSTD_FOUND)
|
||||
MARK_AS_ADVANCED(CLEAR ZSTD_INCLUDE_DIR)
|
||||
MARK_AS_ADVANCED(CLEAR ZSTD_LIBRARY)
|
||||
|
||||
|
||||
#
|
||||
# Check headers
|
||||
#
|
||||
@@ -796,7 +808,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)
|
||||
@@ -819,7 +831,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)
|
||||
@@ -838,6 +850,7 @@ IF(ENABLE_OPENSSL AND NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
SET(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
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()
|
||||
@@ -1045,7 +1058,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)
|
||||
@@ -1138,6 +1150,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)
|
||||
@@ -1181,6 +1194,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)
|
||||
@@ -1210,6 +1224,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}"
|
||||
@@ -1237,6 +1252,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)
|
||||
MARK_AS_ADVANCED(CLEAR LIBXML2_INCLUDE_DIR)
|
||||
@@ -1790,11 +1824,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)
|
||||
@@ -1912,6 +1951,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)
|
||||
@@ -2051,6 +2096,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"
|
||||
@@ -2150,7 +2201,7 @@ INCLUDE(CreatePkgConfigFile)
|
||||
#
|
||||
# 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.
|
||||
@@ -2162,7 +2213,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)
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -729,6 +729,9 @@ typedef uint64_t uintmax_t;
|
||||
/* 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
|
||||
|
||||
@@ -765,6 +768,9 @@ typedef uint64_t uintmax_t;
|
||||
/* 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
|
||||
|
||||
@@ -774,6 +780,9 @@ typedef uint64_t uintmax_t;
|
||||
/* 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
|
||||
|
||||
@@ -865,6 +874,9 @@ typedef uint64_t uintmax_t;
|
||||
/* 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
|
||||
|
||||
@@ -910,6 +922,9 @@ typedef uint64_t uintmax_t;
|
||||
/* 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
|
||||
|
||||
@@ -919,6 +934,9 @@ typedef uint64_t uintmax_t;
|
||||
/* 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
|
||||
|
||||
@@ -1141,7 +1159,6 @@ typedef uint64_t uintmax_t;
|
||||
/* 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
|
||||
|
||||
@@ -1265,6 +1282,9 @@ typedef uint64_t uintmax_t;
|
||||
/* 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
|
||||
|
||||
@@ -1322,6 +1342,15 @@ typedef uint64_t uintmax_t;
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
@@ -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
@@ -1 +1 @@
|
||||
3007009
|
||||
3008001
|
||||
|
||||
@@ -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
|
||||
@@ -247,7 +248,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}
|
||||
@@ -265,18 +266,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
@@ -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"
|
||||
@@ -155,7 +177,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);
|
||||
|
||||
@@ -178,6 +200,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;
|
||||
@@ -449,6 +488,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 *);
|
||||
@@ -828,6 +869,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 *,
|
||||
@@ -1083,6 +1128,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 *);
|
||||
@@ -1201,8 +1250,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
|
||||
}
|
||||
|
||||
@@ -1185,8 +1185,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;
|
||||
}
|
||||
@@ -1676,7 +1681,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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 != ' ') {
|
||||
|
||||
@@ -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
@@ -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 =
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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"
|
||||
@@ -236,19 +266,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 *,
|
||||
@@ -265,8 +295,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 *);
|
||||
@@ -279,9 +309,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 *);
|
||||
@@ -310,18 +340,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 *, 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 */);
|
||||
@@ -344,15 +374,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 *);
|
||||
@@ -361,9 +391,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 *);
|
||||
@@ -419,6 +449,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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
+37
-65
@@ -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)
|
||||
@@ -1316,7 +1296,7 @@ cmp_node_mbs(const struct archive_rb_node *n1,
|
||||
return (-1);
|
||||
return (strcmp(p1, p2));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmp_key_mbs(const struct archive_rb_node *n, const void *key)
|
||||
{
|
||||
@@ -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)
|
||||
@@ -1345,7 +1325,7 @@ cmp_node_wcs(const struct archive_rb_node *n1,
|
||||
return (-1);
|
||||
return (wcscmp(p1, p2));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmp_key_wcs(const struct archive_rb_node *n, const void *key)
|
||||
{
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -46,4 +46,4 @@ pack_t pack_native;
|
||||
(((y) << 12) & 0xfff00000) | \
|
||||
(((y) << 0) & 0x000000ff)))
|
||||
|
||||
#endif /* ARCHIVE_PACK_DEV_H */
|
||||
#endif /* !ARCHIVE_PACK_DEV_H */
|
||||
|
||||
@@ -35,8 +35,7 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define __LIBARCHIVE_BUILD 1
|
||||
#include "archive_getdate.h"
|
||||
#include "archive.h"
|
||||
|
||||
/* Basic time units. */
|
||||
#define EPOCH 1970
|
||||
@@ -820,6 +819,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.
|
||||
*/
|
||||
@@ -861,7 +877,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;
|
||||
}
|
||||
@@ -895,10 +912,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);
|
||||
}
|
||||
|
||||
@@ -914,7 +928,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 */
|
||||
@@ -929,6 +943,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.
|
||||
@@ -936,7 +976,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;
|
||||
@@ -948,6 +988,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. */
|
||||
@@ -50,4 +50,4 @@
|
||||
#define ARCHIVE_ACL_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#endif /* ARCHIVE_PLATFORM_ACL_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_PLATFORM_ACL_H_INCLUDED */
|
||||
|
||||
@@ -42,4 +42,4 @@
|
||||
#define ARCHIVE_XATTR_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#endif /* ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -276,7 +276,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 *);
|
||||
@@ -514,7 +514,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;
|
||||
@@ -778,7 +778,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;
|
||||
@@ -2180,7 +2181,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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -53,6 +53,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
|
||||
@@ -62,7 +63,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
|
||||
@@ -86,6 +106,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 */
|
||||
@@ -147,7 +168,6 @@ struct _7z_digests {
|
||||
uint32_t *digests;
|
||||
};
|
||||
|
||||
|
||||
struct _7z_folder {
|
||||
uint64_t numCoders;
|
||||
struct _7z_coder {
|
||||
@@ -227,13 +247,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;
|
||||
};
|
||||
|
||||
@@ -391,7 +411,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 *);
|
||||
@@ -427,7 +446,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 *,
|
||||
@@ -527,15 +548,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) {
|
||||
@@ -585,21 +608,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;
|
||||
@@ -632,7 +648,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;
|
||||
@@ -649,6 +665,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)
|
||||
@@ -1230,6 +1447,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;
|
||||
@@ -1403,6 +1626,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,
|
||||
@@ -2852,23 +3076,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)
|
||||
{
|
||||
@@ -2911,19 +3118,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;
|
||||
@@ -3018,7 +3225,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)
|
||||
@@ -4312,4 +4521,3 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
|
||||
|
||||
return ((ssize_t)outPos);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -335,8 +335,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 */
|
||||
@@ -451,7 +451,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);
|
||||
|
||||
@@ -741,11 +741,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,
|
||||
@@ -768,21 +768,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -793,7 +793,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);
|
||||
@@ -865,7 +865,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,
|
||||
@@ -910,7 +910,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;
|
||||
@@ -930,7 +930,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
|
||||
@@ -953,8 +953,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];
|
||||
@@ -972,7 +975,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);
|
||||
@@ -984,7 +987,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);
|
||||
@@ -1053,28 +1057,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:
|
||||
@@ -1083,7 +1089,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);
|
||||
}
|
||||
@@ -1098,7 +1104,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) {
|
||||
@@ -1186,7 +1192,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)
|
||||
@@ -1433,7 +1439,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));
|
||||
@@ -1460,8 +1470,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
|
||||
@@ -1506,10 +1516,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;
|
||||
@@ -1670,6 +1693,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)
|
||||
{
|
||||
@@ -1689,6 +1714,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;
|
||||
@@ -1745,6 +1776,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;
|
||||
|
||||
@@ -1753,7 +1789,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
|
||||
@@ -1764,7 +1800,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:
|
||||
@@ -1780,6 +1816,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;
|
||||
@@ -1941,8 +1978,18 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
|
||||
int ret = (ARCHIVE_OK);
|
||||
|
||||
rar = (struct rar *)(a->format->data);
|
||||
if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
|
||||
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,
|
||||
@@ -2224,7 +2271,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;
|
||||
@@ -2332,9 +2379,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,
|
||||
@@ -2929,11 +2976,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)
|
||||
@@ -2956,14 +3003,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)
|
||||
@@ -3048,7 +3095,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;
|
||||
@@ -3096,7 +3143,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;
|
||||
@@ -3111,7 +3158,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);
|
||||
}
|
||||
@@ -3180,8 +3227,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)
|
||||
@@ -3203,7 +3254,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;
|
||||
@@ -3266,6 +3317,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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -3095,7 +3122,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
|
||||
|
||||
@@ -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;
|
||||
@@ -2178,8 +2212,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);
|
||||
}
|
||||
|
||||
@@ -2211,7 +2246,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;
|
||||
|
||||
@@ -2226,12 +2261,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);
|
||||
@@ -2240,7 +2279,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) {
|
||||
@@ -2254,6 +2293,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);
|
||||
}
|
||||
|
||||
@@ -2280,7 +2320,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;
|
||||
@@ -2364,8 +2404,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);
|
||||
@@ -2472,8 +2513,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);
|
||||
@@ -2509,8 +2550,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 {
|
||||
@@ -2627,8 +2669,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);
|
||||
@@ -2658,8 +2701,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);
|
||||
@@ -2728,8 +2772,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);
|
||||
@@ -2816,7 +2860,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)
|
||||
@@ -2832,6 +2878,7 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn)
|
||||
|
||||
if (length <= 0) {
|
||||
*ps = 0;
|
||||
*pn = 0;
|
||||
return;
|
||||
}
|
||||
s = 0;
|
||||
@@ -2845,8 +2892,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;
|
||||
@@ -2877,7 +2925,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;
|
||||
@@ -3028,7 +3076,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;
|
||||
@@ -3162,7 +3210,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;
|
||||
@@ -3207,12 +3255,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);
|
||||
@@ -3220,7 +3266,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. */
|
||||
@@ -3238,14 +3284,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3455,7 +3501,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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
#include <bsdxml.h>
|
||||
#elif HAVE_EXPAT_H
|
||||
#include <expat.h>
|
||||
#elif HAVE_XMLLITE_H
|
||||
#include <objidl.h>
|
||||
#include <initguid.h>
|
||||
#include <xmllite.h>
|
||||
#endif
|
||||
#ifdef HAVE_BZLIB_H
|
||||
#include <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 */
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
const char * const * const s1 = p1;
|
||||
const char * const * const s2 = p2;
|
||||
|
||||
/* 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];
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -46,11 +46,125 @@
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD_H
|
||||
#include <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 <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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -315,4 +315,4 @@ typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED */
|
||||
#endif /* !LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
archive_wstring_ensure(&(a->_name_data), 4 + l + 1 + wcslen(wn) + 1);
|
||||
}
|
||||
if (archive_wstring_ensure(&(a->_name_data),
|
||||
4 + l + 1 + wcslen(wn) + 1) == NULL) {
|
||||
free(wsp);
|
||||
free(wn);
|
||||
return (-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__ */
|
||||
|
||||
|
||||
@@ -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 <bzlib.h>
|
||||
#endif
|
||||
@@ -38,6 +43,9 @@
|
||||
#ifdef HAVE_ZLIB_H
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD_H
|
||||
#include <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);
|
||||
}
|
||||
zip->opt_compression_level = value[0] - '0';
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1167,7 +1167,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;
|
||||
@@ -5666,9 +5671,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;
|
||||
|
||||
@@ -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(®->digest.md5, entry->digest.md5,
|
||||
sizeof(reg->digest.md5));
|
||||
}
|
||||
if ((reg->compute_sum & F_RMD160)
|
||||
&& (reg->mset_digest & AE_MSET_DIGEST_RMD160)) {
|
||||
|
||||
memcpy(®->digest.rmd160, entry->digest.rmd160,
|
||||
sizeof(reg->digest.rmd160));
|
||||
}
|
||||
if ((reg->compute_sum & F_SHA1)
|
||||
&& (reg->mset_digest & AE_MSET_DIGEST_SHA1)) {
|
||||
|
||||
memcpy(®->digest.sha1, entry->digest.sha1,
|
||||
sizeof(reg->digest.sha1));
|
||||
}
|
||||
if ((reg->compute_sum & F_SHA256)
|
||||
&& (reg->mset_digest & AE_MSET_DIGEST_SHA256)) {
|
||||
|
||||
memcpy(®->digest.sha256, entry->digest.sha256,
|
||||
sizeof(reg->digest.sha256));
|
||||
}
|
||||
if ((reg->compute_sum & F_SHA384)
|
||||
&& (reg->mset_digest & AE_MSET_DIGEST_SHA384)) {
|
||||
|
||||
memcpy(®->digest.sha384, entry->digest.sha384,
|
||||
sizeof(reg->digest.sha384));
|
||||
}
|
||||
if ((reg->compute_sum & F_SHA512)
|
||||
&& (reg->mset_digest & AE_MSET_DIGEST_SHA512)) {
|
||||
|
||||
memcpy(®->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;
|
||||
|
||||
@@ -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 != '/')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user