[Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-578-g013e7ec
Brad King
brad.king at kitware.com
Mon Feb 27 09:03:51 EST 2017
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".
The branch, next has been updated
via 013e7ec9100fe5fd850a4c4f89d34359d12f6dd9 (commit)
via 29528cc33e929b3c034b1491842ddaf91b3855cf (commit)
via 62d0e22325d36e5f9d61ccfbef0d68cfe1935f1b (commit)
via 059aa805c9c0cb34c92eb69abf66febc40ab62db (commit)
via 5fee76606b7a1f252e75e95c3d8303777459938d (commit)
via adcade6088a8bbe19002ac88f724d25ac95597c5 (commit)
via da915157b0ac1194e5290ca92695fc0afc073e1b (commit)
via 160ebe58b53d542f44f2aac6b69d4cf02ec40c15 (commit)
from cb2ea6642dced14a1f0e0929ea8a9073cdf7f9b8 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=013e7ec9100fe5fd850a4c4f89d34359d12f6dd9
commit 013e7ec9100fe5fd850a4c4f89d34359d12f6dd9
Merge: cb2ea66 29528cc
Author: Brad King <brad.king at kitware.com>
AuthorDate: Mon Feb 27 09:03:49 2017 -0500
Commit: CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Mon Feb 27 09:03:49 2017 -0500
Merge topic 'update-libarchive' into next
29528cc3 libarchive: Remove liblzma from introspection tests
62d0e223 Merge branch 'upstream-LibArchive' into update-libarchive
059aa805 LibArchive 2017-02-25 (d6b1bb9f)
5fee7660 libarchive: Update script to get 3.3.1
adcade60 CMake Nightly Date Stamp
da915157 CMake Nightly Date Stamp
160ebe58 CMake Nightly Date Stamp
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=29528cc33e929b3c034b1491842ddaf91b3855cf
commit 29528cc33e929b3c034b1491842ddaf91b3855cf
Author: Brad King <brad.king at kitware.com>
AuthorDate: Mon Feb 27 08:53:08 2017 -0500
Commit: Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 27 08:53:08 2017 -0500
libarchive: Remove liblzma from introspection tests
This was added upstream but does not make sense in CMake because we
may replace the library with a logical target name that will not
work inside a `try_compile`.
diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt
index f4a34ab..bfe6b13 100644
--- a/Utilities/cmlibarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/CMakeLists.txt
@@ -295,8 +295,6 @@ ENDIF()
IF(LIBLZMA_FOUND)
SET(HAVE_LIBLZMA 1)
SET(HAVE_LZMA_H 1)
- SET(CMAKE_REQUIRED_INCLUDES ${LIBLZMA_INCLUDE_DIR})
- SET(CMAKE_REQUIRED_LIBRARIES ${LIBLZMA_LIBRARIES})
INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS})
LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES})
IF(CMAKE_USE_SYSTEM_LIBLZMA)
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=62d0e22325d36e5f9d61ccfbef0d68cfe1935f1b
commit 62d0e22325d36e5f9d61ccfbef0d68cfe1935f1b
Merge: 5fee766 059aa80
Author: Brad King <brad.king at kitware.com>
AuthorDate: Mon Feb 27 08:51:36 2017 -0500
Commit: Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 27 08:51:36 2017 -0500
Merge branch 'upstream-LibArchive' into update-libarchive
* upstream-LibArchive:
LibArchive 2017-02-25 (d6b1bb9f)
diff --cc Utilities/cmlibarchive/CMakeLists.txt
index 56811b6,0000000..f4a34ab
mode 100644,000000..100644
--- a/Utilities/cmlibarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/CMakeLists.txt
@@@ -1,1447 -1,0 +1,1454 @@@
+PROJECT(libarchive C)
+#
+SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake")
+if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libarchive_BINARY_DIR}/bin)
+endif()
+
+# On MacOS, prefer MacPorts libraries to system libraries.
+# I haven't come up with a compelling argument for this to be conditional.
+list(APPEND CMAKE_PREFIX_PATH /opt/local)
+# Enable @rpath in the install name.
+# detail in "cmake --help-policy CMP0042"
+SET(CMAKE_MACOSX_RPATH ON)
+
+#
+# Version - read from 'version' file.
+#
+FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/build/version _version)
+STRING(REGEX REPLACE
- "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]?$" "\\1" _major ${_version})
++ "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]*$" "\\1" _major ${_version})
+STRING(REGEX REPLACE
- "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]?$" "\\1" _minor ${_version})
++ "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]*$" "\\1" _minor ${_version})
+STRING(REGEX REPLACE
- "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]?$" "\\1" _revision ${_version})
++ "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]*$" "\\1" _revision ${_version})
+STRING(REGEX REPLACE
- "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]?)$" "\\1" _quality ${_version})
++ "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]*)$" "\\1" _quality ${_version})
+SET(_version_number ${_major}${_minor}${_revision})
+STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_minor ${_minor})
+STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_revision ${_revision})
+#
+SET(VERSION "${_major}.${_trimmed_minor}.${_trimmed_revision}${_quality}")
+SET(BSDCPIO_VERSION_STRING "${VERSION}")
+SET(BSDTAR_VERSION_STRING "${VERSION}")
+SET(BSDCAT_VERSION_STRING "${VERSION}")
+SET(LIBARCHIVE_VERSION_NUMBER "${_version_number}")
+SET(LIBARCHIVE_VERSION_STRING "${VERSION}")
+
+# INTERFACE_VERSION increments with every release
+# libarchive 2.7 == interface version 9 = 2 + 7
+# libarchive 2.8 == interface version 10 = 2 + 8
+# libarchive 2.9 == interface version 11 = 2 + 9
+# libarchive 3.0 == interface version 12
+# libarchive 3.1 == interface version 13
+math(EXPR INTERFACE_VERSION "13 + ${_minor}")
+
+# Set SOVERSION == Interface version
+# ?? Should there be more here ??
+SET(SOVERSION "${INTERFACE_VERSION}")
+
+# Enalbe CMAKE_PUSH_CHECK_STATE() and CMAKE_POP_CHECK_STATE() macros
+# saving and restoring the state of the variables.
+INCLUDE(${CMake_SOURCE_DIR}/Modules/CMakePushCheckState.cmake)
+
+# 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)
+SET(CMAKE_REQUIRED_INCLUDES)
+SET(CMAKE_REQUIRED_LIBRARIES)
+SET(CMAKE_REQUIRED_FLAGS)
+
+# Disable warnings to avoid changing 3rd party code.
+IF(CMAKE_C_COMPILER_ID MATCHES
+ "^(GNU|Clang|AppleClang|XL|VisualAge|SunPro|MIPSpro|HP|Intel)$")
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
+ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
+ENDIF()
+
+# Enable CTest/CDash support
+include(CTest)
+
+OPTION(ENABLE_NETTLE "Enable use of Nettle" ON)
+OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
+OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF)
+OPTION(ENABLE_LZMA "Enable the use of the system LZMA library if found" ON)
+
+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_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON)
+OPTION(ENABLE_LibGCC "Enable the use of the system LibGCC library if found" ON)
+# CNG is used for encrypt/decrypt Zip archives on Windows.
+OPTION(ENABLE_CNG "Enable the use of CNG(Crypto Next Generation)" ON)
+
+OPTION(ENABLE_XATTR "Enable extended attribute support" ON)
+OPTION(ENABLE_ACL "Enable ACL support" ON)
+OPTION(ENABLE_ICONV "Enable iconv support" ON)
+
+IF(WIN32)
+ #ELSEIF(WINDOWS_VERSION STREQUAL "WINXP")
+ SET(NTDDI_VERSION 0x05010000)
+ SET(_WIN32_WINNT 0x0501)
+ SET(WINVER 0x0501)
+ENDIF(WIN32)
+
+set(HAVE_PTHREAD_H 0) # no threads in CMake
+
+IF("${CMAKE_C_PLATFORM_ID}" MATCHES "^(HP-UX)$")
+ ADD_DEFINITIONS(-D_XOPEN_SOURCE=500) # Ask wchar.h for mbstate_t
+ENDIF()
+
+#
+INCLUDE(CheckCSourceCompiles)
+INCLUDE(CheckCSourceRuns)
+INCLUDE(CheckFileOffsetBits)
+INCLUDE(CheckFuncs)
+INCLUDE(CheckHeaderDirent)
+INCLUDE(CheckIncludeFile)
+INCLUDE(CheckIncludeFiles)
+INCLUDE(CheckLibraryExists)
+INCLUDE(CheckStructHasMember)
+INCLUDE(CheckSymbolExists)
+INCLUDE(CheckTypeExists)
+INCLUDE(CheckTypeSize)
+
+#
+# Generate list.h
+#
+MACRO (GENERATE_LIST_H _listfile _cmlist __list_sources)
+ SET(_argv ${ARGV})
+ # Remove _listfile and _cmlist from _argv
+ LIST(REMOVE_AT _argv 0 1)
+ IF (NOT EXISTS "${_listfile}" OR
+ ${_cmlist} IS_NEWER_THAN "${_listfile}")
+
+ MESSAGE(STATUS "Generating ${_listfile}")
+ FILE(WRITE ${_listfile} "")
+ FOREACH (testfile ${_argv})
+ IF (testfile MATCHES "^test_[^/]+[.]c$")
+ FILE(STRINGS ${testfile} testvar REGEX "^DEFINE_TEST")
+ FOREACH (deftest ${testvar})
+ FILE(APPEND ${_listfile} "${deftest}\n")
+ ENDFOREACH (deftest)
+ ENDIF (testfile MATCHES "^test_[^/]+[.]c$")
+ ENDFOREACH (testfile)
+
+ ENDIF (NOT EXISTS "${_listfile}" OR
+ ${_cmlist} IS_NEWER_THAN "${_listfile}")
+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)
+ENDMACRO (INSTALL_MAN __mans)
+#
+# Find out what macro is needed to use libraries on Windows.
+#
+MACRO (TRY_MACRO_FOR_LIBRARY INCLUDES LIBRARIES
+ TRY_TYPE SAMPLE_SOURCE MACRO_LIST)
+ IF(WIN32 AND NOT CYGWIN)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ SET(CMAKE_REQUIRED_INCLUDES ${INCLUDES})
+ SET(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES})
+ FOREACH(VAR ${MACRO_LIST})
+ # Clear ${VAR} from CACHE If the libraries which ${VAR} was
+ # checked with are changed.
+ SET(VAR_WITH_LIB "${VAR}_WITH_LIB")
+ GET_PROPERTY(PREV_VAR_WITH_LIB VARIABLE PROPERTY ${VAR_WITH_LIB})
+ IF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}")
+ UNSET(${VAR} CACHE)
+ ENDIF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}")
+ # Check if the library can be used with the macro.
+ IF("${TRY_TYPE}" MATCHES "COMPILES")
+ CHECK_C_SOURCE_COMPILES("${SAMPLE_SOURCE}" ${VAR})
+ ELSEIF("${TRY_TYPE}" MATCHES "RUNS")
+ CHECK_C_SOURCE_RUNS("${SAMPLE_SOURCE}" ${VAR})
+ ELSE("${TRY_TYPE}" MATCHES "COMPILES")
+ MESSAGE(FATAL_ERROR "UNKNOWN KEYWORD \"${TRY_TYPE}\" FOR TRY_TYPE")
+ ENDIF("${TRY_TYPE}" MATCHES "COMPILES")
+ # Save the libraries which ${VAR} is checked with.
+ SET(${VAR_WITH_LIB} "${LIBRARIES}" CACHE INTERNAL
+ "Macro ${VAR} is checked with")
+ ENDFOREACH(VAR)
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+ ENDIF(WIN32 AND NOT CYGWIN)
+ENDMACRO (TRY_MACRO_FOR_LIBRARY)
+#
+# Check compress/decompress libraries
+#
+IF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN)
+ # GnuWin32 is only for Win32, not Win64.
+ SET(__GNUWIN32PATH "C:/Program Files/GnuWin32")
+ENDIF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN)
+IF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}")
+ # You have to add a path availabel DLL file into PATH environment variable.
+ # Maybe DLL path is "C:/Program Files/GnuWin32/bin".
+ # The zlib and the bzip2 Setup program have installed programs and DLLs into
+ # "C:/Program Files/GnuWin32" by default.
+ # This is convenience setting for Windows.
+ SET(CMAKE_PREFIX_PATH ${__GNUWIN32PATH} $(CMAKE_PREFIX_PATH))
+ #
+ # If you didn't use Setup program or installed into nonstandard path,
+ # cmake cannot find out your zlib or bzip2 libraries and include files,
+ # you should execute cmake with -DCMAKE_PREFIX_PATH option.
+ # e.g.
+ # cmake -DCMAKE_PREFIX_PATH=<your-GnuWin32-path> <path-to-source>
+ #
+ # If compiling error occurred in zconf.h, You may need patch to zconf.h.
+ #--- zconf.h.orig 2005-07-21 00:40:26.000000000
+ #+++ zconf.h 2009-01-19 11:39:10.093750000
+ #@@ -286,7 +286,7 @@
+ #
+ # #if 1 /* HAVE_UNISTD_H -- this line is updated by ./configure */
+ # # include <sys/types.h> /* for off_t */
+ #-# include <unistd.h> /* for SEEK_* and off_t */
+ #+# include <stdio.h> /* for SEEK_* and off_t */
+ # # ifdef VMS
+ # # include <unixio.h> /* for off_t */
+ # # endif
+ENDIF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}")
+
+SET(ADDITIONAL_LIBS "")
+#
+# Find ZLIB
+#
+IF(ENABLE_ZLIB)
+ FIND_PACKAGE(ZLIB)
+ELSE()
+ SET(ZLIB_FOUND FALSE) # Override cached value
+ENDIF()
+IF(ZLIB_FOUND)
+ SET(HAVE_LIBZ 1)
+ SET(HAVE_ZLIB_H 1)
+ INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${ZLIB_LIBRARIES})
+ IF(WIN32 AND NOT CYGWIN)
+ #
+ # Test if ZLIB_WINAPI macro is needed to use.
+ #
+ TRY_MACRO_FOR_LIBRARY(
+ "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}"
+ RUNS
+ "#include <zlib.h>\nint main() {uLong f = zlibCompileFlags(); return (f&(1U<<10))?0:-1; }"
+ ZLIB_WINAPI)
+ IF(ZLIB_WINAPI)
+ ADD_DEFINITIONS(-DZLIB_WINAPI)
+ ELSE(ZLIB_WINAPI)
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}"
+ COMPILES
+ "#include <zlib.h>\nint main() {return zlibVersion()?1:0; }"
+ "ZLIB_DLL;WITHOUT_ZLIB_DLL")
+ IF(ZLIB_DLL)
+ ADD_DEFINITIONS(-DZLIB_DLL)
+ ENDIF(ZLIB_DLL)
+ ENDIF(ZLIB_WINAPI)
+ ENDIF(WIN32 AND NOT CYGWIN)
+ELSE(ZLIB_FOUND)
+ MESSAGE(FATAL_ERROR "CMake requires zlib to be available to libarchive")
+ENDIF(ZLIB_FOUND)
+#
+# Find BZip2
+#
+IF(ENABLE_BZip2)
+ FIND_PACKAGE(BZip2)
+ELSE()
+ SET(BZIP2_FOUND FALSE) # Override cached value
+ENDIF()
+IF(BZIP2_FOUND)
+ SET(HAVE_LIBBZ2 1)
+ SET(HAVE_BZLIB_H 1)
+ INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${BZIP2_LIBRARIES})
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${BZIP2_INCLUDE_DIR}" "${BZIP2_LIBRARIES}"
+ COMPILES
+ "#include <bzlib.h>\nint main() {return BZ2_bzlibVersion()?1:0; }"
+ "USE_BZIP2_DLL;USE_BZIP2_STATIC")
+ IF(USE_BZIP2_DLL)
+ ADD_DEFINITIONS(-DUSE_BZIP2_DLL)
+ ELSEIF(USE_BZIP2_STATIC)
+ ADD_DEFINITIONS(-DUSE_BZIP2_STATIC)
+ ENDIF(USE_BZIP2_DLL)
+ENDIF(BZIP2_FOUND)
+MARK_AS_ADVANCED(CLEAR BZIP2_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES)
+
+
+#
+# Find LZMA
+#
+IF(ENABLE_LZMA)
+ FIND_PACKAGE(LibLZMA)
+ELSE()
+ SET(LIBZMA_FOUND FALSE) # Override cached value
+ENDIF()
+
+IF(LIBLZMA_FOUND)
+ SET(HAVE_LIBLZMA 1)
+ SET(HAVE_LZMA_H 1)
++ SET(CMAKE_REQUIRED_INCLUDES ${LIBLZMA_INCLUDE_DIR})
++ SET(CMAKE_REQUIRED_LIBRARIES ${LIBLZMA_LIBRARIES})
+ INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS})
+ LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES})
+ IF(CMAKE_USE_SYSTEM_LIBLZMA)
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${LIBLZMA_INCLUDE_DIRS}" "${LIBLZMA_LIBRARIES}"
+ COMPILES
+ "#include <lzma.h>\nint main() {return (int)lzma_version_number(); }"
+ "WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC")
+ IF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC)
+ ADD_DEFINITIONS(-DLZMA_API_STATIC)
+ ENDIF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC)
+ ELSE()
+ ADD_DEFINITIONS(-DLZMA_API_STATIC)
+ ENDIF()
+ELSE(LIBLZMA_FOUND)
+# LZMA not found and will not be used.
+ENDIF(LIBLZMA_FOUND)
+IF(0) # CMake does not need LZO2 support in libarchive
+#
+# Find LZO2
+#
+IF(ENABLE_LZO)
+ IF (LZO2_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(LZO2_FIND_QUIETLY TRUE)
+ ENDIF (LZO2_INCLUDE_DIR)
+
+ FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h)
+ FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2)
+ INCLUDE(FindPackageHandleStandardArgs)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
+ELSE(ENABLE_LZO)
+ SET(LIBZMA_FOUND FALSE) # Override cached value
+ENDIF(ENABLE_LZO)
+IF(LZO2_FOUND)
+ SET(HAVE_LIBLZO2 1)
+ SET(HAVE_LZO_LZOCONF_H 1)
+ SET(HAVE_LZO_LZO1X_H 1)
+ INCLUDE_DIRECTORIES(${LZO2_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${LZO2_LIBRARY})
+ #
+ # TODO: test for static library.
+ #
+ENDIF(LZO2_FOUND)
+MARK_AS_ADVANCED(CLEAR LZO2_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR LZO2_LIBRARY)
+ENDIF()
+IF(0) # CMake does not need LZ4 support in libarchive
+#
+# Find LZ4
+#
+IF (LZ4_INCLUDE_DIR)
+ # Already in cache, be silent
+ SET(LZ4_FIND_QUIETLY TRUE)
+ENDIF (LZ4_INCLUDE_DIR)
+
+FIND_PATH(LZ4_INCLUDE_DIR lz4.h)
+FIND_LIBRARY(LZ4_LIBRARY NAMES lz4 liblz4)
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR)
+IF(LZ4_FOUND)
+ SET(HAVE_LIBLZ4 1)
+ SET(HAVE_LZ4_H 1)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ SET(CMAKE_REQUIRED_INCLUDES ${LZ4_INCLUDE_DIR})
+ CHECK_INCLUDE_FILES("lz4hc.h" HAVE_LZ4HC_H)
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+ INCLUDE_DIRECTORIES(${LZ4_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${LZ4_LIBRARY})
+ #
+ # TODO: test for static library.
+ #
+ENDIF(LZ4_FOUND)
+MARK_AS_ADVANCED(CLEAR LZ4_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR LZ4_LIBRARY)
+ENDIF()
+
+#
+# Check headers
+#
+CHECK_HEADER_DIRENT()
+
+SET(INCLUDES "")
+MACRO (LA_CHECK_INCLUDE_FILE header var)
+ CHECK_INCLUDE_FILES("${INCLUDES};${header}" ${var})
+ IF (${var})
+ SET(INCLUDES ${INCLUDES} ${header})
+ ENDIF (${var})
+ENDMACRO (LA_CHECK_INCLUDE_FILE)
+
+# Some FreeBSD headers assume sys/types.h was already included.
+LA_CHECK_INCLUDE_FILE("sys/types.h" HAVE_SYS_TYPES_H)
+
+# Alphabetize the rest unless there's a compelling reason
+IF(ENABLE_ACL)
+ LA_CHECK_INCLUDE_FILE("acl/libacl.h" HAVE_ACL_LIBACL_H)
+ELSE(ENABLE_ACL)
+ SET(HAVE_ACL_LIBACL_H FALSE)
+ENDIF(ENABLE_ACL)
+LA_CHECK_INCLUDE_FILE("ctype.h" HAVE_CTYPE_H)
+LA_CHECK_INCLUDE_FILE("copyfile.h" HAVE_COPYFILE_H)
+LA_CHECK_INCLUDE_FILE("direct.h" HAVE_DIRECT_H)
+LA_CHECK_INCLUDE_FILE("dlfcn.h" HAVE_DLFCN_H)
+LA_CHECK_INCLUDE_FILE("errno.h" HAVE_ERRNO_H)
+LA_CHECK_INCLUDE_FILE("ext2fs/ext2_fs.h" HAVE_EXT2FS_EXT2_FS_H)
+
+CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
+#include <ext2fs/ext2_fs.h>
+int main(void) { return EXT2_IOC_GETFLAGS; }" HAVE_WORKING_EXT2_IOC_GETFLAGS)
+
+LA_CHECK_INCLUDE_FILE("fcntl.h" HAVE_FCNTL_H)
+LA_CHECK_INCLUDE_FILE("grp.h" HAVE_GRP_H)
+LA_CHECK_INCLUDE_FILE("inttypes.h" HAVE_INTTYPES_H)
+LA_CHECK_INCLUDE_FILE("io.h" HAVE_IO_H)
+LA_CHECK_INCLUDE_FILE("langinfo.h" HAVE_LANGINFO_H)
+LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H)
+LA_CHECK_INCLUDE_FILE("linux/types.h" HAVE_LINUX_TYPES_H)
+LA_CHECK_INCLUDE_FILE("linux/fiemap.h" HAVE_LINUX_FIEMAP_H)
+LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H)
++
++CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
++#include <linux/fs.h>
++int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS)
++
+LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H)
+LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H)
+LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H)
+LA_CHECK_INCLUDE_FILE("paths.h" HAVE_PATHS_H)
+LA_CHECK_INCLUDE_FILE("poll.h" HAVE_POLL_H)
+LA_CHECK_INCLUDE_FILE("process.h" HAVE_PROCESS_H)
+LA_CHECK_INCLUDE_FILE("pthread.h" HAVE_PTHREAD_H)
+LA_CHECK_INCLUDE_FILE("pwd.h" HAVE_PWD_H)
+LA_CHECK_INCLUDE_FILE("readpassphrase.h" HAVE_READPASSPHRASE_H)
+LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H)
+LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H)
+LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H)
+LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H)
+LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H)
+LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H)
+LA_CHECK_INCLUDE_FILE("string.h" HAVE_STRING_H)
+LA_CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H)
+LA_CHECK_INCLUDE_FILE("sys/acl.h" HAVE_SYS_ACL_H)
+LA_CHECK_INCLUDE_FILE("sys/cdefs.h" HAVE_SYS_CDEFS_H)
+LA_CHECK_INCLUDE_FILE("sys/ioctl.h" HAVE_SYS_IOCTL_H)
+LA_CHECK_INCLUDE_FILE("sys/mkdev.h" HAVE_SYS_MKDEV_H)
+LA_CHECK_INCLUDE_FILE("sys/mount.h" HAVE_SYS_MOUNT_H)
+LA_CHECK_INCLUDE_FILE("sys/param.h" HAVE_SYS_PARAM_H)
+LA_CHECK_INCLUDE_FILE("sys/poll.h" HAVE_SYS_POLL_H)
+LA_CHECK_INCLUDE_FILE("sys/select.h" HAVE_SYS_SELECT_H)
+LA_CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H)
+LA_CHECK_INCLUDE_FILE("sys/statfs.h" HAVE_SYS_STATFS_H)
+LA_CHECK_INCLUDE_FILE("sys/statvfs.h" HAVE_SYS_STATVFS_H)
+LA_CHECK_INCLUDE_FILE("sys/time.h" HAVE_SYS_TIME_H)
+LA_CHECK_INCLUDE_FILE("sys/utime.h" HAVE_SYS_UTIME_H)
+LA_CHECK_INCLUDE_FILE("sys/utsname.h" HAVE_SYS_UTSNAME_H)
+LA_CHECK_INCLUDE_FILE("sys/vfs.h" HAVE_SYS_VFS_H)
+LA_CHECK_INCLUDE_FILE("sys/wait.h" HAVE_SYS_WAIT_H)
+LA_CHECK_INCLUDE_FILE("time.h" HAVE_TIME_H)
+LA_CHECK_INCLUDE_FILE("unistd.h" HAVE_UNISTD_H)
+LA_CHECK_INCLUDE_FILE("utime.h" HAVE_UTIME_H)
+LA_CHECK_INCLUDE_FILE("wchar.h" HAVE_WCHAR_H)
+LA_CHECK_INCLUDE_FILE("wctype.h" HAVE_WCTYPE_H)
+LA_CHECK_INCLUDE_FILE("windows.h" HAVE_WINDOWS_H)
+IF(ENABLE_CNG)
+ LA_CHECK_INCLUDE_FILE("Bcrypt.h" HAVE_BCRYPT_H)
+ELSE(ENABLE_CNG)
+ UNSET(HAVE_BCRYPT_H CACHE)
+ENDIF(ENABLE_CNG)
+# Following files need windows.h, so we should test it after windows.h test.
+LA_CHECK_INCLUDE_FILE("wincrypt.h" HAVE_WINCRYPT_H)
+LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H)
+
+#
+# Check whether use of __EXTENSIONS__ is safe.
+# We need some macro such as _GNU_SOURCE to use extension functions.
+#
+SET(_INCLUDE_FILES)
+FOREACH (it ${_HEADER})
+ SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
+ENDFOREACH (it)
+
+CHECK_C_SOURCE_COMPILES(
+ "#define __EXTENSIONS__ 1
+ ${_INCLUDE_FILES}
+ int main() { return 0;}"
+ SAFE_TO_DEFINE_EXTENSIONS)
+
+#
+# Find Nettle
+#
+IF(ENABLE_NETTLE)
+ FIND_PACKAGE(Nettle)
+ IF(NETTLE_FOUND)
+ SET(HAVE_LIBNETTLE 1)
+ LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARIES})
+ INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR})
+
+ LIST(APPEND CMAKE_REQUIRED_INCLUDES ${NETTLE_INCLUDE_DIR})
+ LA_CHECK_INCLUDE_FILE("nettle/aes.h" HAVE_NETTLE_AES_H)
+ LA_CHECK_INCLUDE_FILE("nettle/hmac.h" HAVE_NETTLE_HMAC_H)
+ LA_CHECK_INCLUDE_FILE("nettle/md5.h" HAVE_NETTLE_MD5_H)
+ LA_CHECK_INCLUDE_FILE("nettle/pbkdf2.h" HAVE_NETTLE_PBKDF2_H)
+ LA_CHECK_INCLUDE_FILE("nettle/ripemd160.h" HAVE_NETTLE_RIPEMD160_H)
+ LA_CHECK_INCLUDE_FILE("nettle/sha.h" HAVE_NETTLE_SHA_H)
+
+ ENDIF(NETTLE_FOUND)
+ MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR)
+ MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES)
+ENDIF(ENABLE_NETTLE)
+
+#
+# Find OpenSSL
+# (Except on Mac, where OpenSSL is deprecated.)
+#
+IF(ENABLE_OPENSSL AND NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
+ FIND_PACKAGE(OpenSSL)
+ IF(OPENSSL_FOUND)
+ SET(HAVE_LIBCRYPTO 1)
+ INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
+ ENDIF(OPENSSL_FOUND)
+ELSE()
+ SET(OPENSSL_FOUND FALSE) # Override cached value
+ENDIF()
+
+# FreeBSD libmd
+IF(NOT OPENSSL_FOUND)
+ CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND)
+ IF(LIBMD_FOUND)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ SET(CMAKE_REQUIRED_LIBRARIES "md")
+ FIND_LIBRARY(LIBMD_LIBRARY NAMES md)
+ LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY})
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+ ENDIF(LIBMD_FOUND)
+ENDIF(NOT OPENSSL_FOUND)
+
+#
+# How to prove that CRYPTO functions, which have several names on various
+# platforms, just see if archive_digest.c can compile and link against
+# required libraries.
+#
+MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
+ FOREACH(ALGORITHM ${ALGORITHMS})
+ IF(NOT ARCHIVE_CRYPTO_${ALGORITHM})
+ STRING(TOLOWER "${ALGORITHM}" lower_algorithm)
+ STRING(TOUPPER "${ALGORITHM}" algorithm)
+ IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND)
+ SET(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} FALSE)
+ ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NOT NETTLE_FOUND)
+ SET(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} FALSE)
+ ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND)
+
+ IF(NOT DEFINED ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
+ # Probe the local implementation for whether this
+ # crypto implementation is available on this platform.
+ SET(TRY_CRYPTO_REQUIRED_INCLUDES
+ "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp")
+ SET(TRY_CRYPTO_REQUIRED_LIBS)
+ IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
+ SET(TRY_CRYPTO_REQUIRED_INCLUDES
+ "${TRY_CRYPTO_REQUIRED_INCLUDES};${OPENSSL_INCLUDE_DIR}")
+ SET(TRY_CRYPTO_REQUIRED_LIBS
+ "-DLINK_LIBRARIES:STRING=${OPENSSL_LIBRARIES}")
+ ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NETTLE_FOUND)
+ SET(TRY_CRYPTO_REQUIRED_INCLUDES
+ "${TRY_CRYPTO_REQUIRED_INCLUDES};${NETTLE_INCLUDE_DIR}")
+ SET(TRY_CRYPTO_REQUIRED_LIBS
+ "-DLINK_LIBRARIES:STRING=${NETTLE_LIBRARY}")
+ ELSEIF("${IMPLEMENTATION}" MATCHES "^LIBMD$" AND LIBMD_FOUND)
+ SET(TRY_CRYPTO_REQUIRED_LIBS
+ "-DLINK_LIBRARIES:STRING=${LIBMD_LIBRARY}")
+ ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
+
+ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h)
+ FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h"
+ CONFDEFS_H)
+ FILE(READ "${CMAKE_CURRENT_SOURCE_DIR}/libarchive/archive_digest.c"
+ ARCHIVE_CRYPTO_C)
+
+ SET(SOURCE "${CONFDEFS_H}
+
+#define ARCHIVE_${algorithm}_COMPILE_TEST
+#define ARCHIVE_CRYPTO_${algorithm}_${IMPLEMENTATION}
+#define PLATFORM_CONFIG_H \"check_crypto_md.h\"
+
+${ARCHIVE_CRYPTO_C}
+
+int
+main(int argc, char **argv)
+{
+ archive_${lower_algorithm}_ctx ctx;
+ archive_${lower_algorithm}_init(&ctx);
+ archive_${lower_algorithm}_update(&ctx, *argv, argc);
+ archive_${lower_algorithm}_final(&ctx, NULL);
+ return 0;
+}
+")
+
+ FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.h" "")
+ FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c" "${SOURCE}")
+ MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}")
+
+ TRY_COMPILE(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c
+ CMAKE_FLAGS
+ "${TRY_CRYPTO_REQUIRED_LIBS}"
+ "${TRY_CRYPTO_REQUIRED_INCLUDES}"
+ OUTPUT_VARIABLE OUTPUT)
+
+ # Inform user whether or not we found it; if not, log why we didn't.
+ IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
+ MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- found")
+ SET(ARCHIVE_CRYPTO_${ALGORITHM} 1)
+ ELSE (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
+ MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- not found")
+ FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} failed with the following output:\n"
+ "${OUTPUT}\n"
+ "Source file was:\n${SOURCE}\n")
+ ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
+ ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
+
+ # Add appropriate libs/includes depending on whether the implementation
+ # was found on this platform.
+ IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
+ IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
+ INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_LIBRARIES})
+ LIST(REMOVE_DUPLICATES ADDITIONAL_LIBS)
+ ENDIF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
+ ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
+ ENDIF(NOT ARCHIVE_CRYPTO_${ALGORITHM})
+ ENDFOREACH(ALGORITHM ${ALGORITHMS})
+ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
+
+#
+# CRYPTO functions on Windows is defined at archive_windows.c, thus we do not
+# need the test what the functions can be mapped to archive_{crypto name}_init,
+# archive_{crypto name}_update and archive_{crypto name}_final.
+# The functions on Windows use CALG_{crypto name} macro to create a crypt object
+# and then we need to know what CALG_{crypto name} macros is available to show
+# ARCHIVE_CRYPTO_{crypto name}_WIN macros because Windows 2000 and earlier version
+# of Windows XP do not support SHA256, SHA384 and SHA512.
+#
+MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
+ IF(WIN32 AND NOT CYGWIN)
+ FOREACH(CRYPTO ${CRYPTO_LIST})
+ IF(NOT ARCHIVE_CRYPTO_${CRYPTO})
+ IF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
+ STRING(TOUPPER "${CRYPTO}" crypto)
+ SET(ALGID "")
+ IF ("${CRYPTO}" MATCHES "^MD5$")
+ SET(ALGID "CALG_MD5")
+ ENDIF ("${CRYPTO}" MATCHES "^MD5$")
+ IF ("${CRYPTO}" MATCHES "^SHA1$")
+ SET(ALGID "CALG_SHA1")
+ ENDIF ("${CRYPTO}" MATCHES "^SHA1$")
+ IF ("${CRYPTO}" MATCHES "^SHA256$")
+ SET(ALGID "CALG_SHA_256")
+ ENDIF ("${CRYPTO}" MATCHES "^SHA256$")
+ IF ("${CRYPTO}" MATCHES "^SHA384$")
+ SET(ALGID "CALG_SHA_384")
+ ENDIF ("${CRYPTO}" MATCHES "^SHA384$")
+ IF ("${CRYPTO}" MATCHES "^SHA512$")
+ SET(ALGID "CALG_SHA_512")
+ ENDIF ("${CRYPTO}" MATCHES "^SHA512$")
+
+ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h)
+ FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h"
+ CONFDEFS_H)
+
+ SET(SOURCE "${CONFDEFS_H}
+
+#define ${crypto}_COMPILE_TEST
+#include <windows.h>
+#include <wincrypt.h>
+
+int
+main(int argc, char **argv)
+{
+ return ${ALGID};
+}
+")
+ SET(SOURCE_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_win.c")
+
+ FILE(WRITE "${SOURCE_FILE}" "${SOURCE}")
+ MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN")
+
+ TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN
+ ${CMAKE_BINARY_DIR}
+ ${SOURCE_FILE}
+ CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive"
+ OUTPUT_VARIABLE OUTPUT)
+
+ IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
+ MESSAGE(STATUS
+ "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- found")
+ SET(ARCHIVE_CRYPTO_${CRYPTO} 1)
+ ELSE (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
+ MESSAGE(STATUS
+ "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- not found")
+ FILE(APPEND
+ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN failed with the following output:\n"
+ "${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)
+ ENDIF(WIN32 AND NOT CYGWIN)
+ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
+
+#
+# Find iconv
+# POSIX defines the second arg as const char **
+# and requires it to be in libc. But we can accept
+# a non-const argument here and can support iconv()
+# being in libiconv.
+#
+MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
+ IF(NOT HAVE_ICONV)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ IF (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR
+ CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ #
+ # During checking iconv proto type, we should use -Werror to avoid the
+ # success of iconv detection with a warnig which success is a miss
+ # detection. So this needs for all build mode(even it's a release mode).
+ #
+ SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")
+ ENDIF ()
+ IF (CMAKE_C_COMPILER_ID STREQUAL "XL")
+ SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -qhalt=w -qflag=w:w")
+ ENDIF ()
+ IF (MSVC)
+ # NOTE: /WX option is the same as gcc's -Werror option.
+ SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX")
+ ENDIF (MSVC)
+ #
+ CHECK_C_SOURCE_COMPILES(
+ "#include <stdlib.h>
+ #include <iconv.h>
+ int main() {
+ ${TRY_ICONV_CONST} char *ccp;
+ iconv_t cd = iconv_open(\"\", \"\");
+ iconv(cd, &ccp, (size_t *)0, (char **)0, (size_t *)0);
+ iconv_close(cd);
+ return 0;
+ }"
+ HAVE_ICONV_${LIB}_${TRY_ICONV_CONST})
+ IF(HAVE_ICONV_${LIB}_${TRY_ICONV_CONST})
+ SET(HAVE_ICONV true)
+ SET(ICONV_CONST ${TRY_ICONV_CONST})
+ ENDIF(HAVE_ICONV_${LIB}_${TRY_ICONV_CONST})
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+ ENDIF(NOT HAVE_ICONV)
+ENDMACRO(CHECK_ICONV TRY_ICONV_CONST)
+
+IF(ENABLE_ICONV)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
+ MARK_AS_ADVANCED(ICONV_INCLUDE_DIR)
+ IF(ICONV_INCLUDE_DIR)
+ #SET(INCLUDES ${INCLUDES} "iconv.h")
+ SET(HAVE_ICONV_H 1)
+ INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR})
+ SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
+ CHECK_ICONV("libc" "const")
+ CHECK_ICONV("libc" "")
+
+ # If iconv isn't in libc and we have a libiconv, try that.
+ FIND_LIBRARY(LIBICONV_PATH NAMES iconv libiconv)
+ IF(NOT HAVE_ICONV AND LIBICONV_PATH)
+ LIST(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH})
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${ICONV_INCLUDE_DIR}" "${LIBICONV_PATH}"
+ COMPILES
+ "#include <iconv.h>\nint main() {return iconv_close((iconv_t)0);}"
+ "WITHOUT_LIBICONV_STATIC;LIBICONV_STATIC")
+ IF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC)
+ ADD_DEFINITIONS(-DLIBICONV_STATIC)
+ ENDIF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC)
+ #
+ # Set up CMAKE_REQUIRED_* for CHECK_ICONV
+ #
+ SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
+ SET(CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH})
+ IF(LIBICONV_STATIC)
+ # LIBICONV_STATIC is necessary for the success of CHECK_ICONV
+ # on Windows.
+ SET(CMAKE_REQUIRED_DEFINITIONS "-DLIBICONV_STATIC")
+ ELSE(LIBICONV_STATIC)
+ SET(CMAKE_REQUIRED_DEFINITIONS)
+ ENDIF(LIBICONV_STATIC)
+ CHECK_ICONV("libiconv" "const")
+ CHECK_ICONV("libiconv" "")
+ IF (HAVE_ICONV)
+ LIST(APPEND ADDITIONAL_LIBS ${LIBICONV_PATH})
+ ENDIF(HAVE_ICONV)
+ ENDIF(NOT HAVE_ICONV AND LIBICONV_PATH)
+ ENDIF(ICONV_INCLUDE_DIR)
+ #
+ # Find locale_charset() for libiconv.
+ #
+ IF(LIBICONV_PATH)
+ SET(CMAKE_REQUIRED_DEFINITIONS)
+ SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
+ SET(CMAKE_REQUIRED_LIBRARIES)
+ CHECK_INCLUDE_FILES("localcharset.h" HAVE_LOCALCHARSET_H)
+ FIND_LIBRARY(LIBCHARSET_PATH NAMES charset libcharset)
+ IF(LIBCHARSET_PATH)
+ SET(CMAKE_REQUIRED_LIBRARIES ${LIBCHARSET_PATH})
+ IF(WIN32 AND NOT CYGWIN)
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${ICONV_INCLUDE_DIR}" "${LIBCHARSET_PATH}"
+ COMPILES
+ "#include <localcharset.h>\nint main() {return locale_charset()?1:0;}"
+ "WITHOUT_LIBCHARSET_STATIC;LIBCHARSET_STATIC")
+ IF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC)
+ ADD_DEFINITIONS(-DLIBCHARSET_STATIC)
+ ENDIF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC)
+ IF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC)
+ SET(HAVE_LOCALE_CHARSET ON CACHE INTERNAL
+ "Have function locale_charset")
+ ENDIF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC)
+ ELSE(WIN32 AND NOT CYGWIN)
+ CHECK_FUNCTION_EXISTS_GLIBC(locale_charset HAVE_LOCALE_CHARSET)
+ ENDIF(WIN32 AND NOT CYGWIN)
+ IF(HAVE_LOCALE_CHARSET)
+ LIST(APPEND ADDITIONAL_LIBS ${LIBCHARSET_PATH})
+ ENDIF(HAVE_LOCALE_CHARSET)
+ ENDIF(LIBCHARSET_PATH)
+ ENDIF(LIBICONV_PATH)
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+ELSE(ENABLE_ICONV)
+ # Make sure ICONV variables are not in CACHE after ENABLE_ICONV disabled
+ # (once enabled).
+ UNSET(HAVE_LOCALE_CHARSET CACHE)
+ UNSET(HAVE_ICONV CACHE)
+ UNSET(HAVE_ICONV_libc_ CACHE)
+ UNSET(HAVE_ICONV_libc_const CACHE)
+ UNSET(HAVE_ICONV_libiconv_ CACHE)
+ UNSET(HAVE_ICONV_libiconv_const CACHE)
+ UNSET(ICONV_INCLUDE_DIR CACHE)
+ UNSET(LIBICONV_PATH CACHE)
+ UNSET(LIBICONV_DLL CACHE)
+ UNSET(LIBICONV_STATIC CACHE)
+ UNSET(LIBCHARSET_DLL CACHE)
+ UNSET(LIBCHARSET_STATIC CACHE)
+ENDIF(ENABLE_ICONV)
+
+IF(0) # CMake does not need XML support in libarchive
+#
+# Find Libxml2
+#
+IF(ENABLE_LIBXML2)
+ FIND_PACKAGE(LibXml2)
+ELSE()
+ SET(LIBXML2_FOUND FALSE)
+ENDIF()
+IF(LIBXML2_FOUND)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${LIBXML2_LIBRARIES})
+ SET(HAVE_LIBXML2 1)
+ # libxml2's include files use iconv.h
+ 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)
+ # Test if a macro is needed for the library.
+ TRY_MACRO_FOR_LIBRARY(
+ "${ICONV_INCLUDE_DIR};${LIBXML2_INCLUDE_DIR}"
+ "ws2_32.lib;${ZLIB_LIBRARIES};${LIBICONV_PATH};${LIBXML2_LIBRARIES}"
+ COMPILES
+ "#include <stddef.h>\n#include <libxml/xmlreader.h>\nint main() {return xmlTextReaderRead((xmlTextReaderPtr)(void *)0);}"
+ "WITHOUT_LIBXML_STATIC;LIBXML_STATIC")
+ IF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC)
+ ADD_DEFINITIONS(-DLIBXML_STATIC)
+ ENDIF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC)
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+ELSE(LIBXML2_FOUND)
+ #
+ # Find Expat
+ #
+ IF(ENABLE_EXPAT)
+ FIND_PACKAGE(EXPAT)
+ ELSE()
+ SET(EXPAT_FOUND FALSE)
+ ENDIF()
+ IF(EXPAT_FOUND)
+ CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+ INCLUDE_DIRECTORIES(${EXPAT_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${EXPAT_LIBRARIES})
+ SET(HAVE_LIBEXPAT 1)
+ LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H)
+ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+ ENDIF(EXPAT_FOUND)
+ENDIF(LIBXML2_FOUND)
+MARK_AS_ADVANCED(CLEAR LIBXML2_INCLUDE_DIR)
+MARK_AS_ADVANCED(CLEAR LIBXML2_LIBRARIES)
+ENDIF()
+
+#
+# Check functions
+#
+CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
+IF (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR
+ CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ #
+ # During checking functions, we should use -fno-builtin to avoid the
+ # failure of function detection which failure is an error "conflicting
+ # types for built-in function" caused by using -Werror option.
+ #
+ SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-builtin")
+ENDIF ()
+CHECK_SYMBOL_EXISTS(_CrtSetReportMode "crtdbg.h" HAVE__CrtSetReportMode)
+CHECK_FUNCTION_EXISTS_GLIBC(arc4random_buf HAVE_ARC4RANDOM_BUF)
+CHECK_FUNCTION_EXISTS_GLIBC(chflags HAVE_CHFLAGS)
+CHECK_FUNCTION_EXISTS_GLIBC(chown HAVE_CHOWN)
+CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT)
+CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R)
+CHECK_FUNCTION_EXISTS_GLIBC(dirfd HAVE_DIRFD)
+CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR)
+CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS)
+CHECK_FUNCTION_EXISTS_GLIBC(fchmod HAVE_FCHMOD)
+CHECK_FUNCTION_EXISTS_GLIBC(fchown HAVE_FCHOWN)
+CHECK_FUNCTION_EXISTS_GLIBC(fcntl HAVE_FCNTL)
+CHECK_FUNCTION_EXISTS_GLIBC(fdopendir HAVE_FDOPENDIR)
+CHECK_FUNCTION_EXISTS_GLIBC(fork HAVE_FORK)
+CHECK_FUNCTION_EXISTS_GLIBC(fstat HAVE_FSTAT)
+CHECK_FUNCTION_EXISTS_GLIBC(fstatat HAVE_FSTATAT)
+CHECK_FUNCTION_EXISTS_GLIBC(fstatfs HAVE_FSTATFS)
+CHECK_FUNCTION_EXISTS_GLIBC(fstatvfs HAVE_FSTATVFS)
+CHECK_FUNCTION_EXISTS_GLIBC(ftruncate HAVE_FTRUNCATE)
+CHECK_FUNCTION_EXISTS_GLIBC(futimens HAVE_FUTIMENS)
+CHECK_FUNCTION_EXISTS_GLIBC(futimes HAVE_FUTIMES)
+CHECK_FUNCTION_EXISTS_GLIBC(futimesat HAVE_FUTIMESAT)
+CHECK_FUNCTION_EXISTS_GLIBC(geteuid HAVE_GETEUID)
+CHECK_FUNCTION_EXISTS_GLIBC(getgrgid_r HAVE_GETGRGID_R)
+CHECK_FUNCTION_EXISTS_GLIBC(getgrnam_r HAVE_GETGRNAM_R)
+CHECK_FUNCTION_EXISTS_GLIBC(getpwnam_r HAVE_GETPWNAM_R)
+CHECK_FUNCTION_EXISTS_GLIBC(getpwuid_r HAVE_GETPWUID_R)
+CHECK_FUNCTION_EXISTS_GLIBC(getpid HAVE_GETPID)
+CHECK_FUNCTION_EXISTS_GLIBC(getvfsbyname HAVE_GETVFSBYNAME)
+CHECK_FUNCTION_EXISTS_GLIBC(gmtime_r HAVE_GMTIME_R)
+CHECK_FUNCTION_EXISTS_GLIBC(lchflags HAVE_LCHFLAGS)
+CHECK_FUNCTION_EXISTS_GLIBC(lchmod HAVE_LCHMOD)
+CHECK_FUNCTION_EXISTS_GLIBC(lchown HAVE_LCHOWN)
+CHECK_FUNCTION_EXISTS_GLIBC(link HAVE_LINK)
+CHECK_FUNCTION_EXISTS_GLIBC(localtime_r HAVE_LOCALTIME_R)
+CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT)
+CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES)
+CHECK_FUNCTION_EXISTS_GLIBC(mbrtowc HAVE_MBRTOWC)
+CHECK_FUNCTION_EXISTS_GLIBC(memmove HAVE_MEMMOVE)
+CHECK_FUNCTION_EXISTS_GLIBC(mkdir HAVE_MKDIR)
+CHECK_FUNCTION_EXISTS_GLIBC(mkfifo HAVE_MKFIFO)
+CHECK_FUNCTION_EXISTS_GLIBC(mknod HAVE_MKNOD)
+CHECK_FUNCTION_EXISTS_GLIBC(mkstemp HAVE_MKSTEMP)
+CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO)
+CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT)
+CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE)
+CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL)
+CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP)
+CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK)
+CHECK_FUNCTION_EXISTS_GLIBC(readpassphrase HAVE_READPASSPHRASE)
+CHECK_FUNCTION_EXISTS_GLIBC(select HAVE_SELECT)
+CHECK_FUNCTION_EXISTS_GLIBC(setenv HAVE_SETENV)
+CHECK_FUNCTION_EXISTS_GLIBC(setlocale HAVE_SETLOCALE)
+CHECK_FUNCTION_EXISTS_GLIBC(sigaction HAVE_SIGACTION)
+CHECK_FUNCTION_EXISTS_GLIBC(statfs HAVE_STATFS)
+CHECK_FUNCTION_EXISTS_GLIBC(statvfs HAVE_STATVFS)
+CHECK_FUNCTION_EXISTS_GLIBC(strchr HAVE_STRCHR)
+CHECK_FUNCTION_EXISTS_GLIBC(strdup HAVE_STRDUP)
+CHECK_FUNCTION_EXISTS_GLIBC(strerror HAVE_STRERROR)
+CHECK_FUNCTION_EXISTS_GLIBC(strncpy_s HAVE_STRNCPY_S)
+CHECK_FUNCTION_EXISTS_GLIBC(strrchr HAVE_STRRCHR)
+CHECK_FUNCTION_EXISTS_GLIBC(symlink HAVE_SYMLINK)
+CHECK_FUNCTION_EXISTS_GLIBC(timegm HAVE_TIMEGM)
+CHECK_FUNCTION_EXISTS_GLIBC(tzset HAVE_TZSET)
+CHECK_FUNCTION_EXISTS_GLIBC(unsetenv HAVE_UNSETENV)
+CHECK_FUNCTION_EXISTS_GLIBC(utime HAVE_UTIME)
+CHECK_FUNCTION_EXISTS_GLIBC(utimes HAVE_UTIMES)
+CHECK_FUNCTION_EXISTS_GLIBC(utimensat HAVE_UTIMENSAT)
+CHECK_FUNCTION_EXISTS_GLIBC(vfork HAVE_VFORK)
+CHECK_FUNCTION_EXISTS_GLIBC(wcrtomb HAVE_WCRTOMB)
+CHECK_FUNCTION_EXISTS_GLIBC(wcscmp HAVE_WCSCMP)
+CHECK_FUNCTION_EXISTS_GLIBC(wcscpy HAVE_WCSCPY)
+CHECK_FUNCTION_EXISTS_GLIBC(wcslen HAVE_WCSLEN)
+CHECK_FUNCTION_EXISTS_GLIBC(wctomb HAVE_WCTOMB)
+CHECK_FUNCTION_EXISTS_GLIBC(_ctime64_s HAVE__CTIME64_S)
+CHECK_FUNCTION_EXISTS_GLIBC(_fseeki64 HAVE__FSEEKI64)
+CHECK_FUNCTION_EXISTS_GLIBC(_get_timezone HAVE__GET_TIMEZONE)
+CHECK_FUNCTION_EXISTS_GLIBC(_localtime64_s HAVE__LOCALTIME64_S)
+CHECK_FUNCTION_EXISTS_GLIBC(_mkgmtime64 HAVE__MKGMTIME64)
+
+SET(CMAKE_REQUIRED_LIBRARIES "")
+CHECK_FUNCTION_EXISTS(cygwin_conv_path HAVE_CYGWIN_CONV_PATH)
+CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO)
+CHECK_FUNCTION_EXISTS(strerror_r HAVE_STRERROR_R)
+CHECK_FUNCTION_EXISTS(strftime HAVE_STRFTIME)
+CHECK_FUNCTION_EXISTS(vprintf HAVE_VPRINTF)
+CHECK_FUNCTION_EXISTS(wmemcmp HAVE_WMEMCMP)
+CHECK_FUNCTION_EXISTS(wmemcpy HAVE_WMEMCPY)
+CHECK_FUNCTION_EXISTS(wmemmove HAVE_WMEMMOVE)
+
+CMAKE_POP_CHECK_STATE() # Restore the state of the variables
+
+CHECK_C_SOURCE_COMPILES(
+ "#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct vfsconf v; return sizeof(v);}"
+ HAVE_STRUCT_VFSCONF)
+
+CHECK_C_SOURCE_COMPILES(
+ "#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct xvfsconf v; return sizeof(v);}"
+ HAVE_STRUCT_XVFSCONF)
+
+# Make sure we have the POSIX version of readdir_r, not the
+# older 2-argument version.
+CHECK_C_SOURCE_COMPILES(
+ "#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}"
+ HAVE_READDIR_R)
+
+
+# Only detect readlinkat() if we also have AT_FDCWD in unistd.h.
+# NOTE: linux requires fcntl.h for AT_FDCWD.
+CHECK_C_SOURCE_COMPILES(
+ "#include <fcntl.h>\n#include <unistd.h>\nint main() {char buf[10]; return readlinkat(AT_FDCWD, \"\", buf, 0);}"
+ HAVE_READLINKAT)
+
+
+# To verify major(), we need to both include the header
+# of interest and verify that the result can be linked.
+# CHECK_FUNCTION_EXISTS doesn't accept a header argument,
+# CHECK_SYMBOL_EXISTS doesn't test linkage.
+CHECK_C_SOURCE_COMPILES(
+ "#include <sys/mkdev.h>\nint main() { return major(256); }"
+ MAJOR_IN_MKDEV)
+CHECK_C_SOURCE_COMPILES(
+ "#include <sys/sysmacros.h>\nint main() { return major(256); }"
+ MAJOR_IN_SYSMACROS)
+
+CHECK_C_SOURCE_COMPILES(
+ "#include <lzma.h>\n#if LZMA_VERSION < 50020000\n#error unsupported\n#endif\nint main(void){lzma_stream_encoder_mt(0, 0); return 0;}"
+ HAVE_LZMA_STREAM_ENCODER_MT)
+
+IF(HAVE_STRERROR_R)
+ SET(HAVE_DECL_STRERROR_R 1)
+ENDIF(HAVE_STRERROR_R)
+
+#
+# Check defines
+#
+SET(headers "limits.h")
+IF(HAVE_STDINT_H)
+ LIST(APPEND headers "stdint.h")
+ENDIF(HAVE_STDINT_H)
+IF(HAVE_INTTYPES_H)
+ LIST(APPEND headers "inttypes.h")
+ENDIF(HAVE_INTTYPES_H)
+CHECK_SYMBOL_EXISTS(EFTYPE "errno.h" HAVE_EFTYPE)
+CHECK_SYMBOL_EXISTS(EILSEQ "errno.h" HAVE_EILSEQ)
+CHECK_SYMBOL_EXISTS(D_MD_ORDER "langinfo.h" HAVE_D_MD_ORDER)
+CHECK_SYMBOL_EXISTS(INT32_MAX "${headers}" HAVE_DECL_INT32_MAX)
+CHECK_SYMBOL_EXISTS(INT32_MIN "${headers}" HAVE_DECL_INT32_MIN)
+CHECK_SYMBOL_EXISTS(INT64_MAX "${headers}" HAVE_DECL_INT64_MAX)
+CHECK_SYMBOL_EXISTS(INT64_MIN "${headers}" HAVE_DECL_INT64_MIN)
+CHECK_SYMBOL_EXISTS(INTMAX_MAX "${headers}" HAVE_DECL_INTMAX_MAX)
+CHECK_SYMBOL_EXISTS(INTMAX_MIN "${headers}" HAVE_DECL_INTMAX_MIN)
+CHECK_SYMBOL_EXISTS(UINT32_MAX "${headers}" HAVE_DECL_UINT32_MAX)
+CHECK_SYMBOL_EXISTS(UINT64_MAX "${headers}" HAVE_DECL_UINT64_MAX)
+CHECK_SYMBOL_EXISTS(UINTMAX_MAX "${headers}" HAVE_DECL_UINTMAX_MAX)
+CHECK_SYMBOL_EXISTS(SIZE_MAX "${headers}" HAVE_DECL_SIZE_MAX)
+CHECK_SYMBOL_EXISTS(SSIZE_MAX "limits.h" HAVE_DECL_SSIZE_MAX)
+
+#
+# Check struct members
+#
+# Check for tm_gmtoff in struct tm
+CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff
+ "time.h" HAVE_STRUCT_TM_TM_GMTOFF)
+CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff
+ "time.h" HAVE_STRUCT_TM___TM_GMTOFF)
+
+# Check for f_namemax in struct statfs
+CHECK_STRUCT_HAS_MEMBER("struct statfs" f_namemax
+ "sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_NAMEMAX)
+
+# Check for birthtime in struct stat
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIME)
+
+# Check for high-resolution timestamps in struct stat
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtimespec.tv_nsec
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_n
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_N)
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_umtime
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_UMTIME)
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_usec
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_USEC)
+# Check for block size support in struct stat
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_blksize
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BLKSIZE)
+# Check for st_flags in struct stat (BSD fflags)
+CHECK_STRUCT_HAS_MEMBER("struct stat" st_flags
+ "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_FLAGS)
+
+IF(HAVE_SYS_STATVFS_H)
+ CHECK_STRUCT_HAS_MEMBER("struct statvfs" f_iosize
+ "sys/types.h;sys/statvfs.h" HAVE_STRUCT_STATVFS_F_IOSIZE)
+ENDIF()
+
+#
+#
+CHECK_STRUCT_HAS_MEMBER("struct tm" tm_sec
+ "sys/types.h;sys/time.h;time.h" TIME_WITH_SYS_TIME)
+
+#
+# Check for integer types
+#
+#
+CHECK_TYPE_SIZE("short" SIZE_OF_SHORT)
+CHECK_TYPE_SIZE("int" SIZE_OF_INT)
+CHECK_TYPE_SIZE("long" SIZE_OF_LONG)
+CHECK_TYPE_SIZE("long long" SIZE_OF_LONG_LONG)
+
+CHECK_TYPE_SIZE("unsigned short" SIZE_OF_UNSIGNED_SHORT)
+CHECK_TYPE_SIZE("unsigned" SIZE_OF_UNSIGNED)
+CHECK_TYPE_SIZE("unsigned long" SIZE_OF_UNSIGNED_LONG)
+CHECK_TYPE_SIZE("unsigned long long" SIZE_OF_UNSIGNED_LONG_LONG)
+
+CHECK_TYPE_SIZE("__int64" __INT64)
+CHECK_TYPE_SIZE("unsigned __int64" UNSIGNED___INT64)
+
+CHECK_TYPE_SIZE(int16_t INT16_T)
+CHECK_TYPE_SIZE(int32_t INT32_T)
+CHECK_TYPE_SIZE(int64_t INT64_T)
+CHECK_TYPE_SIZE(intmax_t INTMAX_T)
+CHECK_TYPE_SIZE(uint8_t UINT8_T)
+CHECK_TYPE_SIZE(uint16_t UINT16_T)
+CHECK_TYPE_SIZE(uint32_t UINT32_T)
+CHECK_TYPE_SIZE(uint64_t UINT64_T)
+CHECK_TYPE_SIZE(uintmax_t UINTMAX_T)
+
+CHECK_TYPE_SIZE(dev_t DEV_T)
+IF(NOT HAVE_DEV_T)
+ IF(MSVC)
+ SET(dev_t "unsigned int")
+ ENDIF(MSVC)
+ENDIF(NOT HAVE_DEV_T)
+#
+CHECK_TYPE_SIZE(gid_t GID_T)
+IF(NOT HAVE_GID_T)
+ IF(WIN32)
+ SET(gid_t "short")
+ ELSE(WIN32)
+ SET(gid_t "unsigned int")
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_GID_T)
+#
+CHECK_TYPE_SIZE(id_t ID_T)
+IF(NOT HAVE_ID_T)
+ IF(WIN32)
+ SET(id_t "short")
+ ELSE(WIN32)
+ SET(id_t "unsigned int")
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_ID_T)
+#
+CHECK_TYPE_SIZE(mode_t MODE_T)
+IF(NOT HAVE_MODE_T)
+ IF(WIN32)
+ SET(mode_t "unsigned short")
+ ELSE(WIN32)
+ SET(mode_t "int")
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_MODE_T)
+#
+CHECK_TYPE_SIZE(off_t OFF_T)
+IF(NOT HAVE_OFF_T)
+ SET(off_t "__int64")
+ENDIF(NOT HAVE_OFF_T)
+#
+CHECK_TYPE_SIZE(size_t SIZE_T)
+IF(NOT HAVE_SIZE_T)
+ IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(size_t "uint64_t")
+ ELSE("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(size_t "uint32_t")
+ ENDIF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ENDIF(NOT HAVE_SIZE_T)
+#
+CHECK_TYPE_SIZE(ssize_t SSIZE_T)
+IF(NOT HAVE_SSIZE_T)
+ IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(ssize_t "int64_t")
+ ELSE("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(ssize_t "long")
+ ENDIF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ENDIF(NOT HAVE_SSIZE_T)
+#
+CHECK_TYPE_SIZE(uid_t UID_T)
+IF(NOT HAVE_UID_T)
+ IF(WIN32)
+ SET(uid_t "short")
+ ELSE(WIN32)
+ SET(uid_t "unsigned int")
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_UID_T)
+#
+CHECK_TYPE_SIZE(pid_t PID_T)
+IF(NOT HAVE_PID_T)
+ IF(WIN32)
+ SET(pid_t "int")
+ ELSE(WIN32)
+ MESSAGE(FATAL_ERROR "pid_t doesn't exist on this platform?")
+ ENDIF(WIN32)
+ENDIF(NOT HAVE_PID_T)
+#
+CHECK_TYPE_SIZE(intptr_t INTPTR_T)
+IF(NOT HAVE_INTPTR_T)
+ IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(intptr_t "int64_t")
+ ELSE()
+ SET(intptr_t "int32_t")
+ ENDIF()
+ENDIF(NOT HAVE_INTPTR_T)
+#
+CHECK_TYPE_SIZE(uintptr_t UINTPTR_T)
+IF(NOT HAVE_UINTPTR_T)
+ IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ SET(uintptr_t "uint64_t")
+ ELSE()
+ SET(uintptr_t "uint32_t")
+ ENDIF()
+ENDIF(NOT HAVE_UINTPTR_T)
+#
+CHECK_TYPE_SIZE(wchar_t SIZEOF_WCHAR_T)
+IF(HAVE_SIZEOF_WCHAR_T)
+ SET(HAVE_WCHAR_T 1)
+ENDIF(HAVE_SIZEOF_WCHAR_T)
+#
+# Check if _FILE_OFFSET_BITS macro needed for large files
+#
+CHECK_FILE_OFFSET_BITS()
+
+#
+# Check for Extended Attribute libraries, headers, and functions
+#
+IF(ENABLE_XATTR)
+ LA_CHECK_INCLUDE_FILE(attr/xattr.h HAVE_ATTR_XATTR_H)
+ LA_CHECK_INCLUDE_FILE(sys/xattr.h HAVE_SYS_XATTR_H)
+ LA_CHECK_INCLUDE_FILE(sys/extattr.h HAVE_SYS_EXTATTR_H)
+ CHECK_LIBRARY_EXISTS(attr "setxattr" "" HAVE_LIBATTR)
+ IF(HAVE_LIBATTR)
+ SET(CMAKE_REQUIRED_LIBRARIES "attr")
+ ENDIF(HAVE_LIBATTR)
+ CHECK_SYMBOL_EXISTS(EXTATTR_NAMESPACE_USER "sys/types.h;sys/extattr.h" HAVE_DECL_EXTATTR_NAMESPACE_USER)
+ CHECK_FUNCTION_EXISTS_GLIBC(extattr_get_file HAVE_EXTATTR_GET_FILE)
+ CHECK_FUNCTION_EXISTS_GLIBC(extattr_list_file HAVE_EXTATTR_LIST_FILE)
+ CHECK_FUNCTION_EXISTS_GLIBC(extattr_set_fd HAVE_EXTATTR_SET_FD)
+ CHECK_FUNCTION_EXISTS_GLIBC(extattr_set_file HAVE_EXTATTR_SET_FILE)
+ CHECK_FUNCTION_EXISTS_GLIBC(fgetxattr HAVE_FGETXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(flistxattr HAVE_FLISTXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(fsetxattr HAVE_FSETXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(getxattr HAVE_GETXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(lgetxattr HAVE_LGETXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(listxattr HAVE_LISTXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(llistxattr HAVE_LLISTXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(lsetxattr HAVE_LSETXATTR)
+ CHECK_FUNCTION_EXISTS_GLIBC(fgetea HAVE_FGETEA)
+ CHECK_FUNCTION_EXISTS_GLIBC(flistea HAVE_FLISTEA)
+ CHECK_FUNCTION_EXISTS_GLIBC(fsetea HAVE_FSETEA)
+ CHECK_FUNCTION_EXISTS_GLIBC(getea HAVE_GETEA)
+ CHECK_FUNCTION_EXISTS_GLIBC(lgetea HAVE_LGETEA)
+ CHECK_FUNCTION_EXISTS_GLIBC(listea HAVE_LISTEA)
+ CHECK_FUNCTION_EXISTS_GLIBC(llistea HAVE_LLISTEA)
+ CHECK_FUNCTION_EXISTS_GLIBC(lsetea HAVE_LSETEA)
+ELSE(ENABLE_XATTR)
+ SET(HAVE_ATTR_LIB FALSE)
+ SET(HAVE_ATTR_XATTR_H FALSE)
+ SET(HAVE_DECL_EXTATTR_NAMESPACE_USER FALSE)
+ SET(HAVE_EXTATTR_GET_FILE FALSE)
+ SET(HAVE_EXTATTR_LIST_FILE FALSE)
+ SET(HAVE_EXTATTR_SET_FD FALSE)
+ SET(HAVE_EXTATTR_SET_FILE FALSE)
+ SET(HAVE_FGETEA FALSE)
+ SET(HAVE_FGETXATTR FALSE)
+ SET(HAVE_FLISTEA FALSE)
+ SET(HAVE_FLISTXATTR FALSE)
+ SET(HAVE_FSETEA FALSE)
+ SET(HAVE_FSETXATTR FALSE)
+ SET(HAVE_GETEA FALSE)
+ SET(HAVE_GETXATTR FALSE)
+ SET(HAVE_LGETEA FALSE)
+ SET(HAVE_LGETXATTR FALSE)
+ SET(HAVE_LISTEA FALSE)
+ SET(HAVE_LISTXATTR FALSE)
+ SET(HAVE_LLISTEA FALSE)
+ SET(HAVE_LLISTXATTR FALSE)
+ SET(HAVE_LSETEA FALSE)
+ SET(HAVE_LSETXATTR FALSE)
+ SET(HAVE_SYS_EXTATTR_H FALSE)
+ SET(HAVE_SYS_XATTR_H FALSE)
+ENDIF(ENABLE_XATTR)
+
+#
+# Check for ACL libraries, headers, and functions
+#
+# The ACL support in libarchive is written against the POSIX1e draft,
+# which was never officially approved and varies quite a bit across
+# platforms. Worse, some systems have completely non-POSIX acl functions,
+# which makes the following checks rather more complex than I would like.
+#
+IF(ENABLE_ACL)
+ CHECK_LIBRARY_EXISTS(acl "acl_get_file" "" HAVE_LIBACL)
+ IF(HAVE_LIBACL)
+ SET(CMAKE_REQUIRED_LIBRARIES "acl")
+ FIND_LIBRARY(ACL_LIBRARY NAMES acl)
+ LIST(APPEND ADDITIONAL_LIBS ${ACL_LIBRARY})
+ ENDIF(HAVE_LIBACL)
+ #
+ CHECK_FUNCTION_EXISTS_GLIBC(acl_create_entry HAVE_ACL_CREATE_ENTRY)
+ CHECK_FUNCTION_EXISTS_GLIBC(acl_init HAVE_ACL_INIT)
+ CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd HAVE_ACL_SET_FD)
+ CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd_np HAVE_ACL_SET_FD_NP)
+ CHECK_FUNCTION_EXISTS_GLIBC(acl_set_file HAVE_ACL_SET_FILE)
+ CHECK_TYPE_EXISTS(acl_permset_t "${INCLUDES}" HAVE_ACL_PERMSET_T)
+
+ # The "acl_get_perm()" function was omitted from the POSIX draft.
+ # (It's a pretty obvious oversight; otherwise, there's no way to
+ # test for specific permissions in a permset.) Linux uses the obvious
+ # name, FreeBSD adds _np to mark it as "non-Posix extension."
+ # Test for both as a double-check that we really have POSIX-style ACL support.
+ CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP)
+ CHECK_FUNCTION_EXISTS(acl_get_perm HAVE_ACL_GET_PERM)
+ CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP)
+ CHECK_FUNCTION_EXISTS(acl_get_link HAVE_ACL_GET_LINK)
+ CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP)
+ CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP)
+ CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP)
+ CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "${INCLUDES}" HAVE_ACL_TYPE_NFS4)
+
+ # MacOS has an acl.h that isn't POSIX. It can be detected by
+ # checking for ACL_USER
+ CHECK_SYMBOL_EXISTS(ACL_USER "${INCLUDES}" HAVE_ACL_USER)
+ CHECK_C_SOURCE_COMPILES("#include <sys/types.h>
+#include <sys/acl.h>
+int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED)
+
+ # Solaris and derivates ACLs
+ CHECK_LIBRARY_EXISTS(sec "acl_get" "" HAVE_LIBSEC)
+ IF(HAVE_LIBSEC)
+ SET(CMAKE_REQUIRED_LIBRARIES "sec")
+ FIND_LIBRARY(SEC_LIBRARY NAMES sec)
+ LIST(APPEND ADDITIONAL_LIBS ${SEC_LIBRARY})
+ ENDIF(HAVE_LIBSEC)
+ #
+ CHECK_TYPE_EXISTS(aclent_t "${INCLUDES}" HAVE_ACLENT_T)
+ CHECK_TYPE_EXISTS(ace_t "${INCLUDES}" HAVE_ACE_T)
+ CHECK_FUNCTION_EXISTS(acl_get HAVE_FACL_GET)
+ CHECK_FUNCTION_EXISTS(facl_get HAVE_FACL_GET)
+ CHECK_FUNCTION_EXISTS(acl_set HAVE_FACL_SET)
+ CHECK_FUNCTION_EXISTS(facl_set HAVE_FACL_SET)
+ELSE(ENABLE_ACL)
+ # If someone runs cmake, then disables ACL support, we need
+ # to forcibly override the cached values for these.
+ SET(HAVE_ACL_CREATE_ENTRY FALSE)
+ SET(HAVE_ACL_GET_LINK FALSE)
+ SET(HAVE_ACL_GET_LINK_NP FALSE)
+ SET(HAVE_ACL_GET_PERM FALSE)
+ SET(HAVE_ACL_GET_PERM_NP FALSE)
+ SET(HAVE_ACL_INIT FALSE)
+ SET(HAVE_ACL_LIB FALSE)
+ SET(HAVE_ACL_PERMSET_T FALSE)
+ SET(HAVE_ACL_SET_FD FALSE)
+ SET(HAVE_ACL_SET_FD_NP FALSE)
+ SET(HAVE_ACL_SET_FILE FALSE)
+ SET(HAVE_ACL_TYPE_NFS4 FALSE)
+ SET(HAVE_ACL_USER FALSE)
+ SET(HAVE_ACL_TYPE_EXTENDED FALSE)
+ SET(HAVE_ACL_GET FALSE)
+ SET(HAVE_ACLENT_T FALSE)
+ SET(HAVE_ACE_T FALSE)
+ SET(HAVE_FACL_GET FALSE)
+ SET(HAVE_ACL_SET FALSE)
+ SET(HAVE_FACL_SET FALSE)
+ENDIF(ENABLE_ACL)
+
+#
+# Check MD5/RMD160/SHA support
+# NOTE: Crypto checks must be run last before generating config.h
+#
+CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" LIBC)
+CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC2)
+CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC3)
+CHECK_CRYPTO("MD5;SHA1;SHA256;SHA384;SHA512" LIBSYSTEM)
+CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" NETTLE)
+CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" OPENSSL)
+
+# Libmd has to be probed after OpenSSL.
+CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA512" LIBMD)
+
+CHECK_CRYPTO_WIN("MD5;SHA1;SHA256;SHA384;SHA512")
+
+# Generate "config.h" from "build/cmake/config.h.in"
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
+ ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
+ADD_DEFINITIONS(-DHAVE_CONFIG_H)
+
+#
+# Register installation of PDF documents.
+#
+IF(WIN32 AND NOT CYGWIN)
+ #
+ # On Windows platform, It's better that we install PDF documents
+ # on one's computer.
+ # These PDF documents are available in the release package.
+ #
+ IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf)
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf
+ DESTINATION share/man
+ FILES_MATCHING PATTERN "*.pdf"
+ )
+ ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf)
+ENDIF(WIN32 AND NOT CYGWIN)
+#
+#
+#
+INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/libarchive)
+#
+IF(MSVC)
+ ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
+ENDIF(MSVC)
+
+# We need CoreServices on Mac OS.
+IF(APPLE)
+ LIST(APPEND ADDITIONAL_LIBS "-framework CoreServices")
+ENDIF(APPLE)
+
+add_subdirectory(libarchive)
+
+install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmlibarchive)
diff --cc Utilities/cmlibarchive/build/cmake/config.h.in
index fc248b3,0000000..55e04b9
mode 100644,000000..100644
--- a/Utilities/cmlibarchive/build/cmake/config.h.in
+++ b/Utilities/cmlibarchive/build/cmake/config.h.in
@@@ -1,1242 -1,0 +1,1245 @@@
+/* config.h. Generated from build/cmake/config.h.in by cmake configure */
+#if defined(__osf__)
+# define _OSF_SOURCE
+#endif
+
+/*
+ * Ensure we have C99-style int64_t, etc, all defined.
+ */
+
+/* First, we need to know if the system has already defined them. */
+#cmakedefine HAVE_INT16_T
+#cmakedefine HAVE_INT32_T
+#cmakedefine HAVE_INT64_T
+#cmakedefine HAVE_INTMAX_T
+
+#cmakedefine HAVE_UINT8_T
+#cmakedefine HAVE_UINT16_T
+#cmakedefine HAVE_UINT32_T
+#cmakedefine HAVE_UINT64_T
+#cmakedefine HAVE_UINTMAX_T
+
+/* We might have the types we want under other spellings. */
+#cmakedefine HAVE___INT64
+#cmakedefine HAVE_U_INT64_T
+#cmakedefine HAVE_UNSIGNED___INT64
+
+/* The sizes of various standard integer types. */
+ at SIZE_OF_SHORT_CODE@
+ at SIZE_OF_INT_CODE@
+ at SIZE_OF_LONG_CODE@
+ at SIZE_OF_LONG_LONG_CODE@
+ at SIZE_OF_UNSIGNED_SHORT_CODE@
+ at SIZE_OF_UNSIGNED_CODE@
+ at SIZE_OF_UNSIGNED_LONG_CODE@
+ at SIZE_OF_UNSIGNED_LONG_LONG_CODE@
+
+/*
+ * If we lack int64_t, define it to the first of __int64, int, long, and long long
+ * that exists and is the right size.
+ */
+#if !defined(HAVE_INT64_T) && defined(HAVE___INT64)
+typedef __int64 int64_t;
+#define HAVE_INT64_T
+#endif
+
+#if !defined(HAVE_INT64_T) && SIZE_OF_INT == 8
+typedef int int64_t;
+#define HAVE_INT64_T
+#endif
+
+#if !defined(HAVE_INT64_T) && SIZE_OF_LONG == 8
+typedef long int64_t;
+#define HAVE_INT64_T
+#endif
+
+#if !defined(HAVE_INT64_T) && SIZE_OF_LONG_LONG == 8
+typedef long long int64_t;
+#define HAVE_INT64_T
+#endif
+
+#if !defined(HAVE_INT64_T)
+#error No 64-bit integer type was found.
+#endif
+
+/*
+ * Similarly for int32_t
+ */
+#if !defined(HAVE_INT32_T) && SIZE_OF_INT == 4
+typedef int int32_t;
+#define HAVE_INT32_T
+#endif
+
+#if !defined(HAVE_INT32_T) && SIZE_OF_LONG == 4
+typedef long int32_t;
+#define HAVE_INT32_T
+#endif
+
+#if !defined(HAVE_INT32_T)
+#error No 32-bit integer type was found.
+#endif
+
+/*
+ * Similarly for int16_t
+ */
+#if !defined(HAVE_INT16_T) && SIZE_OF_INT == 2
+typedef int int16_t;
+#define HAVE_INT16_T
+#endif
+
+#if !defined(HAVE_INT16_T) && SIZE_OF_SHORT == 2
+typedef short int16_t;
+#define HAVE_INT16_T
+#endif
+
+#if !defined(HAVE_INT16_T)
+#error No 16-bit integer type was found.
+#endif
+
+/*
+ * Similarly for uint64_t
+ */
+#if !defined(HAVE_UINT64_T) && defined(HAVE_UNSIGNED___INT64)
+typedef unsigned __int64 uint64_t;
+#define HAVE_UINT64_T
+#endif
+
+#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED == 8
+typedef unsigned uint64_t;
+#define HAVE_UINT64_T
+#endif
+
+#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED_LONG == 8
+typedef unsigned long uint64_t;
+#define HAVE_UINT64_T
+#endif
+
+#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED_LONG_LONG == 8
+typedef unsigned long long uint64_t;
+#define HAVE_UINT64_T
+#endif
+
+#if !defined(HAVE_UINT64_T)
+#error No 64-bit unsigned integer type was found.
+#endif
+
+
+/*
+ * Similarly for uint32_t
+ */
+#if !defined(HAVE_UINT32_T) && SIZE_OF_UNSIGNED == 4
+typedef unsigned uint32_t;
+#define HAVE_UINT32_T
+#endif
+
+#if !defined(HAVE_UINT32_T) && SIZE_OF_UNSIGNED_LONG == 4
+typedef unsigned long uint32_t;
+#define HAVE_UINT32_T
+#endif
+
+#if !defined(HAVE_UINT32_T)
+#error No 32-bit unsigned integer type was found.
+#endif
+
+/*
+ * Similarly for uint16_t
+ */
+#if !defined(HAVE_UINT16_T) && SIZE_OF_UNSIGNED == 2
+typedef unsigned uint16_t;
+#define HAVE_UINT16_T
+#endif
+
+#if !defined(HAVE_UINT16_T) && SIZE_OF_UNSIGNED_SHORT == 2
+typedef unsigned short uint16_t;
+#define HAVE_UINT16_T
+#endif
+
+#if !defined(HAVE_UINT16_T)
+#error No 16-bit unsigned integer type was found.
+#endif
+
+/*
+ * Similarly for uint8_t
+ */
+#if !defined(HAVE_UINT8_T)
+typedef unsigned char uint8_t;
+#define HAVE_UINT8_T
+#endif
+
+#if !defined(HAVE_UINT16_T)
+#error No 8-bit unsigned integer type was found.
+#endif
+
+/* Define intmax_t and uintmax_t if they are not already defined. */
+#if !defined(HAVE_INTMAX_T)
+typedef int64_t intmax_t;
+#endif
+
+#if !defined(HAVE_UINTMAX_T)
+typedef uint64_t uintmax_t;
+#endif
+
+/* Define ZLIB_WINAPI if zlib was built on Visual Studio. */
+#cmakedefine ZLIB_WINAPI 1
+
+/* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */
+#cmakedefine ARCHIVE_CRYPTO_MD5_LIBC 1
+
+/* MD5 via ARCHIVE_CRYPTO_MD5_LIBSYSTEM supported. */
+#cmakedefine ARCHIVE_CRYPTO_MD5_LIBSYSTEM 1
+
+/* MD5 via ARCHIVE_CRYPTO_MD5_NETTLE supported. */
+#cmakedefine ARCHIVE_CRYPTO_MD5_NETTLE 1
+
+/* MD5 via ARCHIVE_CRYPTO_MD5_OPENSSL supported. */
+#cmakedefine ARCHIVE_CRYPTO_MD5_OPENSSL 1
+
+/* MD5 via ARCHIVE_CRYPTO_MD5_WIN supported. */
+#cmakedefine ARCHIVE_CRYPTO_MD5_WIN 1
+
+/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBC supported. */
+#cmakedefine ARCHIVE_CRYPTO_RMD160_LIBC 1
+
+/* RMD160 via ARCHIVE_CRYPTO_RMD160_NETTLE supported. */
+#cmakedefine ARCHIVE_CRYPTO_RMD160_NETTLE 1
+
+/* RMD160 via ARCHIVE_CRYPTO_RMD160_OPENSSL supported. */
+#cmakedefine ARCHIVE_CRYPTO_RMD160_OPENSSL 1
+
+/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBC supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA1_LIBC 1
+
+/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBSYSTEM supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA1_LIBSYSTEM 1
+
+/* SHA1 via ARCHIVE_CRYPTO_SHA1_NETTLE supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA1_NETTLE 1
+
+/* SHA1 via ARCHIVE_CRYPTO_SHA1_OPENSSL supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA1_OPENSSL 1
+
+/* SHA1 via ARCHIVE_CRYPTO_SHA1_WIN supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA1_WIN 1
+
+/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC 1
+
+/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC2 supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC2 1
+
+/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC3 supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC3 1
+
+/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBSYSTEM supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBSYSTEM 1
+
+/* SHA256 via ARCHIVE_CRYPTO_SHA256_NETTLE supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA256_NETTLE 1
+
+/* SHA256 via ARCHIVE_CRYPTO_SHA256_OPENSSL supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA256_OPENSSL 1
+
+/* SHA256 via ARCHIVE_CRYPTO_SHA256_WIN supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA256_WIN 1
+
+/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC 1
+
+/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC2 supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC2 1
+
+/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC3 supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC3 1
+
+/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBSYSTEM supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBSYSTEM 1
+
+/* SHA384 via ARCHIVE_CRYPTO_SHA384_NETTLE supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA384_NETTLE 1
+
+/* SHA384 via ARCHIVE_CRYPTO_SHA384_OPENSSL supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA384_OPENSSL 1
+
+/* SHA384 via ARCHIVE_CRYPTO_SHA384_WIN supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA384_WIN 1
+
+/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC 1
+
+/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC2 supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC2 1
+
+/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC3 supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC3 1
+
+/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBSYSTEM supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBSYSTEM 1
+
+/* SHA512 via ARCHIVE_CRYPTO_SHA512_NETTLE supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA512_NETTLE 1
+
+/* SHA512 via ARCHIVE_CRYPTO_SHA512_OPENSSL supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA512_OPENSSL 1
+
+/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */
+#cmakedefine ARCHIVE_CRYPTO_SHA512_WIN 1
+
+/* Version number of bsdcpio */
+#cmakedefine BSDCPIO_VERSION_STRING "${BSDCPIO_VERSION_STRING}"
+
+/* Version number of bsdtar */
+#cmakedefine BSDTAR_VERSION_STRING "${BSDTAR_VERSION_STRING}"
+
+/* Version number of bsdcat */
+#cmakedefine BSDCAT_VERSION_STRING "${BSDCAT_VERSION_STRING}"
+
+/* Define to 1 if you have the `acl_create_entry' function. */
+#cmakedefine HAVE_ACL_CREATE_ENTRY 1
+
+/* Define to 1 if you have the `acl_get_fd_np' function. */
+#cmakedefine HAVE_ACL_GET_FD_NP 1
+
+/* Define to 1 if you have the `acl_get_link' function. */
+#cmakedefine HAVE_ACL_GET_LINK 1
+
+/* Define to 1 if you have the `acl_get_link_np' function. */
+#cmakedefine HAVE_ACL_GET_LINK_NP 1
+
+/* Define to 1 if you have the `acl_get_perm' function. */
+#cmakedefine HAVE_ACL_GET_PERM 1
+
+/* Define to 1 if you have the `acl_get_perm_np' function. */
+#cmakedefine HAVE_ACL_GET_PERM_NP 1
+
+/* Define to 1 if you have the `acl_init' function. */
+#cmakedefine HAVE_ACL_INIT 1
+
+/* Define to 1 if you have the <acl/libacl.h> header file. */
+#cmakedefine HAVE_ACL_LIBACL_H 1
+
+/* Define to 1 if the system has the type `acl_permset_t'. */
+#cmakedefine HAVE_ACL_PERMSET_T 1
+
+/* Define to 1 if you have the `acl_set_fd' function. */
+#cmakedefine HAVE_ACL_SET_FD 1
+
+/* Define to 1 if you have the `acl_set_fd_np' function. */
+#cmakedefine HAVE_ACL_SET_FD_NP 1
+
+/* Define to 1 if you have the `acl_set_file' function. */
+#cmakedefine HAVE_ACL_SET_FILE 1
+
+/* True for FreeBSD with NFSv4 ACL support */
+#cmakedefine HAVE_ACL_TYPE_NFS4 1
+
+/* True for MacOS ACL support */
+#cmakedefine HAVE_ACL_TYPE_EXTENDED 1
+
+/* True for systems with POSIX ACL support */
+#cmakedefine HAVE_ACL_USER 1
+
+/* Define to 1 if you have the `arc4random_buf' function. */
+#cmakedefine HAVE_ARC4RANDOM_BUF 1
+
+/* Define to 1 if you have the <attr/xattr.h> header file. */
+#cmakedefine HAVE_ATTR_XATTR_H 1
+
+/* Define to 1 if you have the <Bcrypt.h> header file. */
+#cmakedefine HAVE_BCRYPT_H 1
+
+/* Define to 1 if you have the <bsdxml.h> header file. */
+#cmakedefine HAVE_BSDXML_H 1
+
+/* Define to 1 if you have the <bzlib.h> header file. */
+#cmakedefine HAVE_BZLIB_H 1
+
+/* Define to 1 if you have the `chflags' function. */
+#cmakedefine HAVE_CHFLAGS 1
+
+/* Define to 1 if you have the `chown' function. */
+#cmakedefine HAVE_CHOWN 1
+
+/* Define to 1 if you have the `chroot' function. */
+#cmakedefine HAVE_CHROOT 1
+
+/* Define to 1 if you have the <copyfile.h> header file. */
+#cmakedefine HAVE_COPYFILE_H 1
+
+/* Define to 1 if you have the `ctime_r' function. */
+#cmakedefine HAVE_CTIME_R 1
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#cmakedefine HAVE_CTYPE_H 1
+
+/* Define to 1 if you have the `cygwin_conv_path' function. */
+#cmakedefine HAVE_CYGWIN_CONV_PATH 1
+
+/* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_INT32_MAX 1
+
+/* Define to 1 if you have the declaration of `INT32_MIN', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_INT32_MIN 1
+
+/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_INT64_MAX 1
+
+/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_INT64_MIN 1
+
+/* Define to 1 if you have the declaration of `INTMAX_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_INTMAX_MAX 1
+
+/* Define to 1 if you have the declaration of `INTMAX_MIN', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_INTMAX_MIN 1
+
+/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_SIZE_MAX 1
+
+/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_SSIZE_MAX 1
+
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_STRERROR_R 1
+
+/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_UINT32_MAX 1
+
+/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_UINT64_MAX 1
+
+/* Define to 1 if you have the declaration of `UINTMAX_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_UINTMAX_MAX 1
+
+/* Define to 1 if you have the <direct.h> header file. */
+#cmakedefine HAVE_DIRECT_H 1
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#cmakedefine HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the `dirfd' function. */
+#cmakedefine HAVE_DIRFD 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#cmakedefine HAVE_DLFCN_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#cmakedefine HAVE_DOPRNT 1
+
+/* Define to 1 if nl_langinfo supports D_MD_ORDER */
+#cmakedefine HAVE_D_MD_ORDER 1
+
+/* A possible errno value for invalid file format errors */
+#cmakedefine HAVE_EFTYPE 1
+
+/* A possible errno value for invalid file format errors */
+#cmakedefine HAVE_EILSEQ 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#cmakedefine HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <expat.h> header file. */
+#cmakedefine HAVE_EXPAT_H 1
+
+/* Define to 1 if you have the <ext2fs/ext2_fs.h> header file. */
+#cmakedefine HAVE_EXT2FS_EXT2_FS_H 1
+
+/* Define to 1 if you have the `extattr_get_file' function. */
+#cmakedefine HAVE_EXTATTR_GET_FILE 1
+
+/* Define to 1 if you have the `extattr_list_file' function. */
+#cmakedefine HAVE_EXTATTR_LIST_FILE 1
+
+/* Define to 1 if you have the `extattr_set_fd' function. */
+#cmakedefine HAVE_EXTATTR_SET_FD 1
+
+/* Define to 1 if you have the `extattr_set_file' function. */
+#cmakedefine HAVE_EXTATTR_SET_FILE 1
+
+/* Define to 1 if EXTATTR_NAMESPACE_USER is defined in sys/extattr.h. */
+#cmakedefine HAVE_DECL_EXTATTR_NAMESPACE_USER 1
+
+/* Define to 1 if you have the `fchdir' function. */
+#cmakedefine HAVE_FCHDIR 1
+
+/* Define to 1 if you have the `fchflags' function. */
+#cmakedefine HAVE_FCHFLAGS 1
+
+/* Define to 1 if you have the `fchmod' function. */
+#cmakedefine HAVE_FCHMOD 1
+
+/* Define to 1 if you have the `fchown' function. */
+#cmakedefine HAVE_FCHOWN 1
+
+/* Define to 1 if you have the `fcntl' function. */
+#cmakedefine HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#cmakedefine HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fdopendir' function. */
+#cmakedefine HAVE_FDOPENDIR 1
+
+/* Define to 1 if you have the `fgetea' function. */
+#cmakedefine HAVE_FGETEA 1
+
+/* Define to 1 if you have the `fgetxattr' function. */
+#cmakedefine HAVE_FGETXATTR 1
+
+/* Define to 1 if you have the `flistea' function. */
+#cmakedefine HAVE_FLISTEA 1
+
+/* Define to 1 if you have the `flistxattr' function. */
+#cmakedefine HAVE_FLISTXATTR 1
+
+/* Define to 1 if you have the `fork' function. */
+#cmakedefine HAVE_FORK 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#cmakedefine HAVE_FSEEKO 1
+
+/* Define to 1 if you have the `fsetea' function. */
+#cmakedefine HAVE_FSETEA 1
+
+/* Define to 1 if you have the `fsetxattr' function. */
+#cmakedefine HAVE_FSETXATTR 1
+
+/* Define to 1 if you have the `fstat' function. */
+#cmakedefine HAVE_FSTAT 1
+
+/* Define to 1 if you have the `fstatat' function. */
+#cmakedefine HAVE_FSTATAT 1
+
+/* Define to 1 if you have the `fstatfs' function. */
+#cmakedefine HAVE_FSTATFS 1
+
+/* Define to 1 if you have the `fstatvfs' function. */
+#cmakedefine HAVE_FSTATVFS 1
+
+/* Define to 1 if you have the `ftruncate' function. */
+#cmakedefine HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the `futimens' function. */
+#cmakedefine HAVE_FUTIMENS 1
+
+/* Define to 1 if you have the `futimes' function. */
+#cmakedefine HAVE_FUTIMES 1
+
+/* Define to 1 if you have the `futimesat' function. */
+#cmakedefine HAVE_FUTIMESAT 1
+
+/* Define to 1 if you have the `getea' function. */
+#cmakedefine HAVE_GETEA 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#cmakedefine HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getgrgid_r' function. */
+#cmakedefine HAVE_GETGRGID_R 1
+
+/* Define to 1 if you have the `getgrnam_r' function. */
+#cmakedefine HAVE_GETGRNAM_R 1
+
+/* Define to 1 if you have the `getpid' function. */
+#cmakedefine HAVE_GETPID 1
+
+/* Define to 1 if you have the `getpwnam_r' function. */
+#cmakedefine HAVE_GETPWNAM_R 1
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+#cmakedefine HAVE_GETPWUID_R 1
+
+/* Define to 1 if you have the `getvfsbyname' function. */
+#cmakedefine HAVE_GETVFSBYNAME 1
+
+/* Define to 1 if you have the `getxattr' function. */
+#cmakedefine HAVE_GETXATTR 1
+
+/* Define to 1 if you have the `gmtime_r' function. */
+#cmakedefine HAVE_GMTIME_R 1
+
+/* Define to 1 if you have the <grp.h> header file. */
+#cmakedefine HAVE_GRP_H 1
+
+/* Define to 1 if you have the `iconv' function. */
+#cmakedefine HAVE_ICONV 1
+
+/* Define to 1 if you have the <iconv.h> header file. */
+#cmakedefine HAVE_ICONV_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#cmakedefine HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+#cmakedefine HAVE_IO_H 1
+
+/* Define to 1 if you have the <langinfo.h> header file. */
+#cmakedefine HAVE_LANGINFO_H 1
+
+/* Define to 1 if you have the `lchflags' function. */
+#cmakedefine HAVE_LCHFLAGS 1
+
+/* Define to 1 if you have the `lchmod' function. */
+#cmakedefine HAVE_LCHMOD 1
+
+/* Define to 1 if you have the `lchown' function. */
+#cmakedefine HAVE_LCHOWN 1
+
+/* Define to 1 if you have the `lgetea' function. */
+#cmakedefine HAVE_LGETEA 1
+
+/* Define to 1 if you have the `lgetxattr' function. */
+#cmakedefine HAVE_LGETXATTR 1
+
+/* Define to 1 if you have the `acl' library (-lacl). */
+#cmakedefine HAVE_LIBACL 1
+
+/* Define to 1 if you have the `attr' library (-lattr). */
+#cmakedefine HAVE_LIBATTR 1
+
+/* Define to 1 if you have the `bsdxml' library (-lbsdxml). */
+#cmakedefine HAVE_LIBBSDXML 1
+
+/* Define to 1 if you have the `bz2' library (-lbz2). */
+#cmakedefine HAVE_LIBBZ2 1
+
+/* Define to 1 if you have the `charset' library (-lcharset). */
+#cmakedefine HAVE_LIBCHARSET 1
+
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+#cmakedefine HAVE_LIBCRYPTO 1
+
+/* Define to 1 if you have the `expat' library (-lexpat). */
+#cmakedefine HAVE_LIBEXPAT 1
+
+/* Define to 1 if you have the `gcc' library (-lgcc). */
+#cmakedefine HAVE_LIBGCC 1
+
+/* Define to 1 if you have the `lz4' library (-llz4). */
+#cmakedefine HAVE_LIBLZ4 1
+
+/* Define to 1 if you have the `lzma' library (-llzma). */
+#cmakedefine HAVE_LIBLZMA 1
+
+/* Define to 1 if you have the `lzmadec' library (-llzmadec). */
+#cmakedefine HAVE_LIBLZMADEC 1
+
+/* Define to 1 if you have the `lzo2' library (-llzo2). */
+#cmakedefine HAVE_LIBLZO2 1
+
+/* Define to 1 if you have the `nettle' library (-lnettle). */
+#cmakedefine HAVE_LIBNETTLE 1
+
+/* Define to 1 if you have the `pcre' library (-lpcre). */
+#cmakedefine HAVE_LIBPCRE 1
+
+/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */
+#cmakedefine HAVE_LIBPCREPOSIX 1
+
+/* Define to 1 if you have the `xml2' library (-lxml2). */
+#cmakedefine HAVE_LIBXML2 1
+
+/* Define to 1 if you have the <libxml/xmlreader.h> header file. */
+#cmakedefine HAVE_LIBXML_XMLREADER_H 1
+
+/* 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 `z' library (-lz). */
+#cmakedefine HAVE_LIBZ 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#cmakedefine HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the `link' function. */
+#cmakedefine HAVE_LINK 1
+
+/* Define to 1 if you have the <linux/types.h> header file. */
+#cmakedefine HAVE_LINUX_TYPES_H 1
+
+/* Define to 1 if you have the <linux/fiemap.h> header file. */
+#cmakedefine HAVE_LINUX_FIEMAP_H 1
+
+/* Define to 1 if you have the <linux/fs.h> header file. */
+#cmakedefine HAVE_LINUX_FS_H 1
+
+/* Define to 1 if you have the <linux/magic.h> header file. */
+#cmakedefine HAVE_LINUX_MAGIC_H 1
+
+/* Define to 1 if you have the <linux/types.h> header file. */
+#cmakedefine HAVE_LINUX_TYPES_H 1
+
+/* Define to 1 if you have the `listea' function. */
+#cmakedefine HAVE_LISTEA 1
+
+/* Define to 1 if you have the `listxattr' function. */
+#cmakedefine HAVE_LISTXATTR 1
+
+/* Define to 1 if you have the `llistea' function. */
+#cmakedefine HAVE_LLISTEA 1
+
+/* Define to 1 if you have the `llistxattr' function. */
+#cmakedefine HAVE_LLISTXATTR 1
+
+/* Define to 1 if you have the <localcharset.h> header file. */
+#cmakedefine HAVE_LOCALCHARSET_H 1
+
+/* Define to 1 if you have the `locale_charset' function. */
+#cmakedefine HAVE_LOCALE_CHARSET 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#cmakedefine HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `localtime_r' function. */
+#cmakedefine HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the system has the type `long long int'. */
+#cmakedefine HAVE_LONG_LONG_INT 1
+
+/* Define to 1 if you have the `lsetea' function. */
+#cmakedefine HAVE_LSETEA 1
+
+/* Define to 1 if you have the `lsetxattr' function. */
+#cmakedefine HAVE_LSETXATTR 1
+
+/* Define to 1 if you have the `lstat' function. */
+#cmakedefine HAVE_LSTAT 1
+
+/* Define to 1 if `lstat' has the bug that it succeeds when given the
+ zero-length file name argument. */
+#cmakedefine HAVE_LSTAT_EMPTY_STRING_BUG 1
+
+/* Define to 1 if you have the `lutimes' function. */
+#cmakedefine HAVE_LUTIMES 1
+
+/* Define to 1 if you have the <lz4hc.h> header file. */
+#cmakedefine HAVE_LZ4HC_H 1
+
+/* Define to 1 if you have the <lz4.h> header file. */
+#cmakedefine HAVE_LZ4_H 1
+
+/* Define to 1 if you have the <lzmadec.h> header file. */
+#cmakedefine HAVE_LZMADEC_H 1
+
+/* Define to 1 if you have the <lzma.h> header file. */
+#cmakedefine HAVE_LZMA_H 1
+
+/* Define to 1 if you have a working `lzma_stream_encoder_mt' function. */
+#cmakedefine HAVE_LZMA_STREAM_ENCODER_MT 1
+
+/* Define to 1 if you have the <lzo/lzo1x.h> header file. */
+#cmakedefine HAVE_LZO_LZO1X_H 1
+
+/* Define to 1 if you have the <lzo/lzoconf.h> header file. */
+#cmakedefine HAVE_LZO_LZOCONF_H 1
+
+/* Define to 1 if you have the `mbrtowc' function. */
+#cmakedefine HAVE_MBRTOWC 1
+
+/* Define to 1 if you have the `memmove' function. */
+#cmakedefine HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#cmakedefine HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mkdir' function. */
+#cmakedefine HAVE_MKDIR 1
+
+/* Define to 1 if you have the `mkfifo' function. */
+#cmakedefine HAVE_MKFIFO 1
+
+/* Define to 1 if you have the `mknod' function. */
+#cmakedefine HAVE_MKNOD 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#cmakedefine HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#cmakedefine HAVE_NDIR_H 1
+
+/* Define to 1 if you have the <nettle/aes.h> header file. */
+#cmakedefine HAVE_NETTLE_AES_H 1
+
+/* Define to 1 if you have the <nettle/hmac.h> header file. */
+#cmakedefine HAVE_NETTLE_HMAC_H 1
+
+/* Define to 1 if you have the <nettle/md5.h> header file. */
+#cmakedefine HAVE_NETTLE_MD5_H 1
+
+/* Define to 1 if you have the <nettle/pbkdf2.h> header file. */
+#cmakedefine HAVE_NETTLE_PBKDF2_H 1
+
+/* Define to 1 if you have the <nettle/ripemd160.h> header file. */
+#cmakedefine HAVE_NETTLE_RIPEMD160_H 1
+
+/* 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 `nl_langinfo' function. */
+#cmakedefine HAVE_NL_LANGINFO 1
+
+/* Define to 1 if you have the `openat' function. */
+#cmakedefine HAVE_OPENAT 1
+
+/* Define to 1 if you have the <paths.h> header file. */
+#cmakedefine HAVE_PATHS_H 1
+
+/* Define to 1 if you have the <pcreposix.h> header file. */
+#cmakedefine HAVE_PCREPOSIX_H 1
+
+/* Define to 1 if you have the `pipe' function. */
+#cmakedefine HAVE_PIPE 1
+
+/* Define to 1 if you have the `PKCS5_PBKDF2_HMAC_SHA1' function. */
+#cmakedefine HAVE_PKCS5_PBKDF2_HMAC_SHA1 1
+
+/* Define to 1 if you have the `poll' function. */
+#cmakedefine HAVE_POLL 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#cmakedefine HAVE_POLL_H 1
+
+/* Define to 1 if you have the `posix_spawnp' function. */
+#cmakedefine HAVE_POSIX_SPAWNP 1
+
+/* Define to 1 if you have the <process.h> header file. */
+#cmakedefine HAVE_PROCESS_H 1
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#cmakedefine HAVE_PTHREAD_H 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#cmakedefine HAVE_PWD_H 1
+
+/* Define to 1 if you have the `readdir_r' function. */
+#cmakedefine HAVE_READDIR_R 1
+
+/* Define to 1 if you have the `readlink' function. */
+#cmakedefine HAVE_READLINK 1
+
+/* Define to 1 if you have the `readlinkat' function. */
+#cmakedefine HAVE_READLINKAT 1
+
+/* Define to 1 if you have the `readpassphrase' function. */
+#cmakedefine HAVE_READPASSPHRASE 1
+
+/* Define to 1 if you have the <readpassphrase.h> header file. */
+#cmakedefine HAVE_READPASSPHRASE_H 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+#cmakedefine HAVE_REGEX_H 1
+
+/* Define to 1 if you have the `select' function. */
+#cmakedefine HAVE_SELECT 1
+
+/* Define to 1 if you have the `setenv' function. */
+#cmakedefine HAVE_SETENV 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#cmakedefine HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `sigaction' function. */
+#cmakedefine HAVE_SIGACTION 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#cmakedefine HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the <spawn.h> header file. */
+#cmakedefine HAVE_SPAWN_H 1
+
+/* Define to 1 if you have the `statfs' function. */
+#cmakedefine HAVE_STATFS 1
+
+/* Define to 1 if you have the `statvfs' function. */
+#cmakedefine HAVE_STATVFS 1
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+ zero-length file name argument. */
+#cmakedefine HAVE_STAT_EMPTY_STRING_BUG 1
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#cmakedefine HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strchr' function. */
+#cmakedefine HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strdup' function. */
+#cmakedefine HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#cmakedefine HAVE_STRERROR 1
+
+/* Define to 1 if you have the `strerror_r' function. */
+#cmakedefine HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the `strftime' function. */
+#cmakedefine HAVE_STRFTIME 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#cmakedefine HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#cmakedefine HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strrchr' function. */
+#cmakedefine HAVE_STRRCHR 1
+
+/* Define to 1 if `f_namemax' is a member of `struct statfs'. */
+#cmakedefine HAVE_STRUCT_STATFS_F_NAMEMAX 1
+
+/* Define to 1 if `f_iosize' is a member of `struct statvfs'. */
+#cmakedefine HAVE_STRUCT_STATVFS_F_IOSIZE 1
+
+/* Define to 1 if `st_birthtime' is a member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIME 1
+
+/* Define to 1 if `st_birthtimespec.tv_nsec' is a member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1
+
+/* Define to 1 if `st_blksize' is a member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_BLKSIZE 1
+
+/* Define to 1 if `st_flags' is a member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_FLAGS 1
+
+/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
+
+/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_MTIME_N 1
+
+/* Define to 1 if `st_mtime_usec' is a member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_MTIME_USEC 1
+
+/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
+
+/* Define to 1 if `st_umtime' is a member of `struct stat'. */
+#cmakedefine HAVE_STRUCT_STAT_ST_UMTIME 1
+
+/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */
+#cmakedefine HAVE_STRUCT_TM_TM_GMTOFF 1
+
+/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */
+#cmakedefine HAVE_STRUCT_TM___TM_GMTOFF 1
+
+/* Define to 1 if you have `struct vfsconf'. */
+#cmakedefine HAVE_STRUCT_VFSCONF 1
+
+/* Define to 1 if you have `struct xvfsconf'. */
+#cmakedefine HAVE_STRUCT_XVFSCONF 1
+
+/* Define to 1 if you have the `symlink' function. */
+#cmakedefine HAVE_SYMLINK 1
+
+/* Define to 1 if you have the <sys/acl.h> header file. */
+#cmakedefine HAVE_SYS_ACL_H 1
+
+/* Define to 1 if you have the <sys/cdefs.h> header file. */
+#cmakedefine HAVE_SYS_CDEFS_H 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+#cmakedefine HAVE_SYS_DIR_H 1
+
+/* Define to 1 if you have the <sys/ea.h> header file. */
+#cmakedefine HAVE_SYS_EA_H 1
+
+/* Define to 1 if you have the <sys/extattr.h> header file. */
+#cmakedefine HAVE_SYS_EXTATTR_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#cmakedefine HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/mkdev.h> header file. */
+#cmakedefine HAVE_SYS_MKDEV_H 1
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#cmakedefine HAVE_SYS_MOUNT_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+#cmakedefine HAVE_SYS_NDIR_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#cmakedefine HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#cmakedefine HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#cmakedefine HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/statfs.h> header file. */
+#cmakedefine HAVE_SYS_STATFS_H 1
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#cmakedefine HAVE_SYS_STATVFS_H 1
+
+/* 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/time.h> header file. */
+#cmakedefine HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#cmakedefine HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/utime.h> header file. */
+#cmakedefine HAVE_SYS_UTIME_H 1
+
+/* Define to 1 if you have the <sys/utsname.h> header file. */
+#cmakedefine HAVE_SYS_UTSNAME_H 1
+
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+#cmakedefine HAVE_SYS_VFS_H 1
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#cmakedefine HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+#cmakedefine HAVE_SYS_XATTR_H 1
+
+/* Define to 1 if you have the `timegm' function. */
+#cmakedefine HAVE_TIMEGM 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#cmakedefine HAVE_TIME_H 1
+
+/* Define to 1 if you have the `tzset' function. */
+#cmakedefine HAVE_TZSET 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#cmakedefine HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `unsetenv' function. */
+#cmakedefine HAVE_UNSETENV 1
+
+/* Define to 1 if the system has the type `unsigned long long'. */
+#cmakedefine HAVE_UNSIGNED_LONG_LONG 1
+
+/* Define to 1 if the system has the type `unsigned long long int'. */
+#cmakedefine HAVE_UNSIGNED_LONG_LONG_INT 1
+
+/* Define to 1 if you have the `utime' function. */
+#cmakedefine HAVE_UTIME 1
+
+/* Define to 1 if you have the `utimensat' function. */
+#cmakedefine HAVE_UTIMENSAT 1
+
+/* Define to 1 if you have the `utimes' function. */
+#cmakedefine HAVE_UTIMES 1
+
+/* Define to 1 if you have the <utime.h> header file. */
+#cmakedefine HAVE_UTIME_H 1
+
+/* Define to 1 if you have the `vfork' function. */
+#cmakedefine HAVE_VFORK 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#cmakedefine HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#cmakedefine HAVE_WCHAR_H 1
+
+/* Define to 1 if the system has the type `wchar_t'. */
+#cmakedefine HAVE_WCHAR_T 1
+
+/* Define to 1 if you have the `wcrtomb' function. */
+#cmakedefine HAVE_WCRTOMB 1
+
+/* Define to 1 if you have the `wcscmp' function. */
+#cmakedefine HAVE_WCSCMP 1
+
+/* Define to 1 if you have the `wcscpy' function. */
+#cmakedefine HAVE_WCSCPY 1
+
+/* Define to 1 if you have the `wcslen' function. */
+#cmakedefine HAVE_WCSLEN 1
+
+/* Define to 1 if you have the `wctomb' function. */
+#cmakedefine HAVE_WCTOMB 1
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#cmakedefine HAVE_WCTYPE_H 1
+
+/* Define to 1 if you have the <wincrypt.h> header file. */
+#cmakedefine HAVE_WINCRYPT_H 1
+
+/* Define to 1 if you have the <windows.h> header file. */
+#cmakedefine HAVE_WINDOWS_H 1
+
+/* Define to 1 if you have the <winioctl.h> header file. */
+#cmakedefine HAVE_WINIOCTL_H 1
+
+/* Define to 1 if you have _CrtSetReportMode in <crtdbg.h> */
+#cmakedefine HAVE__CrtSetReportMode 1
+
+/* Define to 1 if you have the `wmemcmp' function. */
+#cmakedefine HAVE_WMEMCMP 1
+
+/* Define to 1 if you have the `wmemcpy' function. */
+#cmakedefine HAVE_WMEMCPY 1
+
+/* Define to 1 if you have the `wmemmove' function. */
+#cmakedefine HAVE_WMEMMOVE 1
+
+/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */
+#cmakedefine HAVE_WORKING_EXT2_IOC_GETFLAGS 1
+
++/* 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 <zlib.h> header file. */
+#cmakedefine HAVE_ZLIB_H 1
+
+/* Define to 1 if you have the `_ctime64_s' function. */
+#cmakedefine HAVE__CTIME64_S 1
+
+/* Define to 1 if you have the `_fseeki64' function. */
+#cmakedefine HAVE__FSEEKI64 1
+
+/* Define to 1 if you have the `_get_timezone' function. */
+#cmakedefine HAVE__GET_TIMEZONE 1
+
+/* Define to 1 if you have the `_localtime64_s' function. */
+#cmakedefine HAVE__LOCALTIME64_S 1
+
+/* Define to 1 if you have the `_mkgmtime64' function. */
+#cmakedefine HAVE__MKGMTIME64 1
+
+/* Define as const if the declaration of iconv() needs const. */
+#define ICONV_CONST ${ICONV_CONST}
+
+/* Version number of libarchive as a single integer */
+#cmakedefine LIBARCHIVE_VERSION_NUMBER "${LIBARCHIVE_VERSION_NUMBER}"
+
+/* Version number of libarchive */
+#cmakedefine LIBARCHIVE_VERSION_STRING "${LIBARCHIVE_VERSION_STRING}"
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+ slash. */
+#cmakedefine LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
+ */
+#cmakedefine MAJOR_IN_MKDEV 1
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in
+ <sysmacros.h>. */
+#cmakedefine MAJOR_IN_SYSMACROS 1
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#cmakedefine NO_MINUS_C_MINUS_O 1
+
+/* The size of `wchar_t', as computed by sizeof. */
+#cmakedefine SIZEOF_WCHAR_T ${SIZEOF_WCHAR_T}
+
+/* Define to 1 if strerror_r returns char *. */
+#cmakedefine STRERROR_R_CHAR_P 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#cmakedefine TIME_WITH_SYS_TIME 1
+
+/*
+ * Some platform requires a macro to use extension functions.
+ */
+#cmakedefine SAFE_TO_DEFINE_EXTENSIONS 1
+#ifdef SAFE_TO_DEFINE_EXTENSIONS
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+#endif /* SAFE_TO_DEFINE_EXTENSIONS */
+
+/* Version number of package */
+#cmakedefine VERSION "${VERSION}"
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#cmakedefine _LARGEFILE_SOURCE 1
+
+/* Define for large files, on AIX-style hosts. */
+#cmakedefine _LARGE_FILES ${_LARGE_FILES}
+
+/* Define to control Windows SDK version */
+#ifndef NTDDI_VERSION
+#cmakedefine NTDDI_VERSION ${NTDDI_VERSION}
+#endif // NTDDI_VERSION
+
+#ifndef _WIN32_WINNT
+#cmakedefine _WIN32_WINNT ${_WIN32_WINNT}
+#endif // _WIN32_WINNT
+
+#ifndef WINVER
+#cmakedefine WINVER ${WINVER}
+#endif // WINVER
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#cmakedefine const ${const}
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#cmakedefine gid_t ${gid_t}
+
+/* Define to `unsigned long' if <sys/types.h> does not define. */
+#cmakedefine id_t ${id_t}
+
+/* Define to `int' if <sys/types.h> does not define. */
+#cmakedefine mode_t ${mode_t}
+
+/* Define to `long long' if <sys/types.h> does not define. */
+#cmakedefine off_t ${off_t}
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#cmakedefine pid_t ${pid_t}
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#cmakedefine size_t ${size_t}
+
+/* Define to `int' if <sys/types.h> does not define. */
+#cmakedefine ssize_t ${ssize_t}
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#cmakedefine uid_t ${uid_t}
+
+/* Define to `int' if <sys/types.h> does not define. */
+#cmakedefine intptr_t ${intptr_t}
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#cmakedefine uintptr_t ${uintptr_t}
diff --cc Utilities/cmlibarchive/libarchive/archive.h
index 040f151,0000000..cfb5c48
mode 100644,000000..100644
--- a/Utilities/cmlibarchive/libarchive/archive.h
+++ b/Utilities/cmlibarchive/libarchive/archive.h
@@@ -1,1180 -1,0 +1,1184 @@@
+/*-
+ * Copyright (c) 2003-2010 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.50 2008/05/26 17:00:22 kientzle Exp $
+ */
+
+#ifndef ARCHIVE_H_INCLUDED
+#define ARCHIVE_H_INCLUDED
+
+/*
+ * The version number is expressed as a single integer that makes it
+ * easy to compare versions at build time: for version a.b.c, the
+ * version number is printf("%d%03d%03d",a,b,c). For example, if you
+ * know your application requires version 2.12.108 or later, you can
+ * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
+ */
+/* Note: Compiler will complain if this does not match archive_entry.h! */
- #define ARCHIVE_VERSION_NUMBER 3003000
++#define ARCHIVE_VERSION_NUMBER 3003001
+
+#include <sys/stat.h>
+#include <stddef.h> /* for wchar_t */
+#include <stdio.h> /* For FILE * */
+#include <time.h> /* For time_t */
+
+/*
+ * Note: archive.h is for use outside of libarchive; the configuration
+ * headers (config.h, archive_platform.h, etc.) are purely internal.
+ * Do NOT use HAVE_XXX configuration macros to control the behavior of
+ * this header! If you must conditionalize, use predefined compiler and/or
+ * platform macros.
+ */
+#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560
+# include <stdint.h>
+#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS) && !defined(__osf__)
+# include <inttypes.h>
+#endif
+
+/* Get appropriate definitions of 64-bit integer */
+#if !defined(__LA_INT64_T_DEFINED)
+/* Older code relied on the __LA_INT64_T macro; after 4.0 we'll switch to the typedef exclusively. */
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_INT64_T la_int64_t
+# endif
+#define __LA_INT64_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+typedef __int64 la_int64_t;
+# else
+# include <unistd.h> /* ssize_t */
+# if defined(_SCO_DS) || defined(__osf__)
+typedef long long la_int64_t;
+# else
+typedef int64_t la_int64_t;
+# endif
+# endif
+#endif
+
+/* The la_ssize_t should match the type used in 'struct stat' */
+#if !defined(__LA_SSIZE_T_DEFINED)
+/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_SSIZE_T la_ssize_t
+# endif
+#define __LA_SSIZE_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
+typedef ssize_t la_ssize_t;
+# elif defined(_WIN64)
+typedef __int64 la_ssize_t;
+# else
+typedef long la_ssize_t;
+# endif
+# else
+# include <unistd.h> /* ssize_t */
+typedef ssize_t la_ssize_t;
+# endif
+#endif
+
+/* Large file support for Android */
+#ifdef __ANDROID__
+#include "android_lf.h"
+#endif
+
+/*
+ * On Windows, define LIBARCHIVE_STATIC if you're building or using a
+ * .lib. The default here assumes you're building a DLL. Only
+ * libarchive source should ever define __LIBARCHIVE_BUILD.
+ */
+#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC)
+# ifdef __LIBARCHIVE_BUILD
+# ifdef __GNUC__
+# define __LA_DECL __attribute__((dllexport)) extern
+# else
+# define __LA_DECL __declspec(dllexport)
+# endif
+# else
+# ifdef __GNUC__
+# define __LA_DECL
+# else
+# define __LA_DECL __declspec(dllimport)
+# endif
+# endif
+#else
+/* Static libraries or non-Windows needs no special declaration. */
+# define __LA_DECL
+#endif
+
+#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__MINGW32__)
+#define __LA_PRINTF(fmtarg, firstvararg) \
+ __attribute__((__format__ (__printf__, fmtarg, firstvararg)))
+#else
+#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */
+#endif
+
+/* CMake uses some deprecated APIs to build with old libarchive versions. */
+#define __LA_DEPRECATED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The version number is provided as both a macro and a function.
+ * The macro identifies the installed header; the function identifies
+ * the library version (which may not be the same if you're using a
+ * dynamically-linked version of the library). Of course, if the
+ * header and library are very different, you should expect some
+ * strangeness. Don't do that.
+ */
+__LA_DECL int archive_version_number(void);
+
+/*
+ * Textual name/version of the library, useful for version displays.
+ */
- #define ARCHIVE_VERSION_ONLY_STRING "3.3.0"
++#define ARCHIVE_VERSION_ONLY_STRING "3.3.1"
+#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
+__LA_DECL const char * archive_version_string(void);
+
+/*
+ * Detailed textual name/version of the library and its dependencies.
+ * This has the form:
+ * "libarchive x.y.z zlib/a.b.c liblzma/d.e.f ... etc ..."
+ * the list of libraries described here will vary depending on how
+ * libarchive was compiled.
+ */
+__LA_DECL const char * archive_version_details(void);
+
+/*
+ * Returns NULL if libarchive was compiled without the associated library.
+ * Otherwise, returns the version number that libarchive was compiled
+ * against.
+ */
+__LA_DECL const char * archive_zlib_version(void);
+__LA_DECL const char * archive_liblzma_version(void);
+__LA_DECL const char * archive_bzlib_version(void);
+__LA_DECL const char * archive_liblz4_version(void);
+
+/* Declare our basic types. */
+struct archive;
+struct archive_entry;
+
+/*
+ * Error codes: Use archive_errno() and archive_error_string()
+ * to retrieve details. Unless specified otherwise, all functions
+ * that return 'int' use these codes.
+ */
+#define ARCHIVE_EOF 1 /* Found end of archive. */
+#define ARCHIVE_OK 0 /* Operation was successful. */
+#define ARCHIVE_RETRY (-10) /* Retry might succeed. */
+#define ARCHIVE_WARN (-20) /* Partial success. */
+/* For example, if write_header "fails", then you can't push data. */
+#define ARCHIVE_FAILED (-25) /* Current operation cannot complete. */
+/* But if write_header is "fatal," then this archive is dead and useless. */
+#define ARCHIVE_FATAL (-30) /* No more operations are possible. */
+
+/*
+ * As far as possible, archive_errno returns standard platform errno codes.
+ * Of course, the details vary by platform, so the actual definitions
+ * here are stored in "archive_platform.h". The symbols are listed here
+ * for reference; as a rule, clients should not need to know the exact
+ * platform-dependent error code.
+ */
+/* Unrecognized or invalid file format. */
+/* #define ARCHIVE_ERRNO_FILE_FORMAT */
+/* Illegal usage of the library. */
+/* #define ARCHIVE_ERRNO_PROGRAMMER_ERROR */
+/* Unknown or unclassified error. */
+/* #define ARCHIVE_ERRNO_MISC */
+
+/*
+ * Callbacks are invoked to automatically read/skip/write/open/close the
+ * archive. You can provide your own for complex tasks (like breaking
+ * archives across multiple tapes) or use standard ones built into the
+ * library.
+ */
+
+/* Returns pointer and size of next block of data from archive. */
+typedef la_ssize_t archive_read_callback(struct archive *,
+ void *_client_data, const void **_buffer);
+
+/* Skips at most request bytes from archive and returns the skipped amount.
+ * This may skip fewer bytes than requested; it may even skip zero bytes.
+ * If you do skip fewer bytes than requested, libarchive will invoke your
+ * read callback and discard data as necessary to make up the full skip.
+ */
+typedef la_int64_t archive_skip_callback(struct archive *,
+ void *_client_data, la_int64_t request);
+
+/* Seeks to specified location in the file and returns the position.
+ * Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h.
+ * Return ARCHIVE_FATAL if the seek fails for any reason.
+ */
+typedef la_int64_t archive_seek_callback(struct archive *,
+ void *_client_data, la_int64_t offset, int whence);
+
+/* Returns size actually written, zero on EOF, -1 on error. */
+typedef la_ssize_t archive_write_callback(struct archive *,
+ void *_client_data,
+ const void *_buffer, size_t _length);
+
+typedef int archive_open_callback(struct archive *, void *_client_data);
+
+typedef int archive_close_callback(struct archive *, void *_client_data);
+
+/* Switches from one client data object to the next/prev client data object.
+ * This is useful for reading from different data blocks such as a set of files
+ * that make up one large file.
+ */
+typedef int archive_switch_callback(struct archive *, void *_client_data1,
+ void *_client_data2);
+
+/*
+ * Returns a passphrase used for encryption or decryption, NULL on nothing
+ * to do and give it up.
+ */
+typedef const char *archive_passphrase_callback(struct archive *,
+ void *_client_data);
+
+/*
+ * Codes to identify various stream filters.
+ */
+#define ARCHIVE_FILTER_NONE 0
+#define ARCHIVE_FILTER_GZIP 1
+#define ARCHIVE_FILTER_BZIP2 2
+#define ARCHIVE_FILTER_COMPRESS 3
+#define ARCHIVE_FILTER_PROGRAM 4
+#define ARCHIVE_FILTER_LZMA 5
+#define ARCHIVE_FILTER_XZ 6
+#define ARCHIVE_FILTER_UU 7
+#define ARCHIVE_FILTER_RPM 8
+#define ARCHIVE_FILTER_LZIP 9
+#define ARCHIVE_FILTER_LRZIP 10
+#define ARCHIVE_FILTER_LZOP 11
+#define ARCHIVE_FILTER_GRZIP 12
+#define ARCHIVE_FILTER_LZ4 13
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
+#define ARCHIVE_COMPRESSION_GZIP ARCHIVE_FILTER_GZIP
+#define ARCHIVE_COMPRESSION_BZIP2 ARCHIVE_FILTER_BZIP2
+#define ARCHIVE_COMPRESSION_COMPRESS ARCHIVE_FILTER_COMPRESS
+#define ARCHIVE_COMPRESSION_PROGRAM ARCHIVE_FILTER_PROGRAM
+#define ARCHIVE_COMPRESSION_LZMA ARCHIVE_FILTER_LZMA
+#define ARCHIVE_COMPRESSION_XZ ARCHIVE_FILTER_XZ
+#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU
+#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM
+#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP
+#define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP
+#endif
+
+/*
+ * Codes returned by archive_format.
+ *
+ * Top 16 bits identifies the format family (e.g., "tar"); lower
+ * 16 bits indicate the variant. This is updated by read_next_header.
+ * Note that the lower 16 bits will often vary from entry to entry.
+ * In some cases, this variation occurs as libarchive learns more about
+ * the archive (for example, later entries might utilize extensions that
+ * weren't necessary earlier in the archive; in this case, libarchive
+ * will change the format code to indicate the extended format that
+ * was used). In other cases, it's because different tools have
+ * modified the archive and so different parts of the archive
+ * actually have slightly different formats. (Both tar and cpio store
+ * format codes in each entry, so it is quite possible for each
+ * entry to be in a different format.)
+ */
+#define ARCHIVE_FORMAT_BASE_MASK 0xff0000
+#define ARCHIVE_FORMAT_CPIO 0x10000
+#define ARCHIVE_FORMAT_CPIO_POSIX (ARCHIVE_FORMAT_CPIO | 1)
+#define ARCHIVE_FORMAT_CPIO_BIN_LE (ARCHIVE_FORMAT_CPIO | 2)
+#define ARCHIVE_FORMAT_CPIO_BIN_BE (ARCHIVE_FORMAT_CPIO | 3)
+#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4)
+#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5)
+#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6)
+#define ARCHIVE_FORMAT_SHAR 0x20000
+#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1)
+#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2)
+#define ARCHIVE_FORMAT_TAR 0x30000
+#define ARCHIVE_FORMAT_TAR_USTAR (ARCHIVE_FORMAT_TAR | 1)
+#define ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE (ARCHIVE_FORMAT_TAR | 2)
+#define ARCHIVE_FORMAT_TAR_PAX_RESTRICTED (ARCHIVE_FORMAT_TAR | 3)
+#define ARCHIVE_FORMAT_TAR_GNUTAR (ARCHIVE_FORMAT_TAR | 4)
+#define ARCHIVE_FORMAT_ISO9660 0x40000
+#define ARCHIVE_FORMAT_ISO9660_ROCKRIDGE (ARCHIVE_FORMAT_ISO9660 | 1)
+#define ARCHIVE_FORMAT_ZIP 0x50000
+#define ARCHIVE_FORMAT_EMPTY 0x60000
+#define ARCHIVE_FORMAT_AR 0x70000
+#define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1)
+#define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2)
+#define ARCHIVE_FORMAT_MTREE 0x80000
+#define ARCHIVE_FORMAT_RAW 0x90000
+#define ARCHIVE_FORMAT_XAR 0xA0000
+#define ARCHIVE_FORMAT_LHA 0xB0000
+#define ARCHIVE_FORMAT_CAB 0xC0000
+#define ARCHIVE_FORMAT_RAR 0xD0000
+#define ARCHIVE_FORMAT_7ZIP 0xE0000
+#define ARCHIVE_FORMAT_WARC 0xF0000
+
+/*
+ * Codes returned by archive_read_format_capabilities().
+ *
+ * This list can be extended with values between 0 and 0xffff.
+ * The original purpose of this list was to let different archive
+ * format readers expose their general capabilities in terms of
+ * encryption.
+ */
+#define ARCHIVE_READ_FORMAT_CAPS_NONE (0) /* no special capabilities */
+#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA (1<<0) /* reader can detect encrypted data */
+#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA (1<<1) /* reader can detect encryptable metadata (pathname, mtime, etc.) */
+
+/*
+ * Codes returned by archive_read_has_encrypted_entries().
+ *
+ * In case the archive does not support encryption detection at all
+ * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. If the reader
+ * for some other reason (e.g. not enough bytes read) cannot say if
+ * there are encrypted entries, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW
+ * is returned.
+ */
+#define ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED -2
+#define ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW -1
+
+/*-
+ * Basic outline for reading an archive:
+ * 1) Ask archive_read_new for an archive reader object.
+ * 2) Update any global properties as appropriate.
+ * In particular, you'll certainly want to call appropriate
+ * archive_read_support_XXX functions.
+ * 3) Call archive_read_open_XXX to open the archive
+ * 4) Repeatedly call archive_read_next_header to get information about
+ * successive archive entries. Call archive_read_data to extract
+ * data for entries of interest.
+ * 5) Call archive_read_free to end processing.
+ */
+__LA_DECL struct archive *archive_read_new(void);
+
+/*
+ * The archive_read_support_XXX calls enable auto-detect for this
+ * archive handle. They also link in the necessary support code.
+ * For example, if you don't want bzlib linked in, don't invoke
+ * support_compression_bzip2(). The "all" functions provide the
+ * obvious shorthand.
+ */
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+__LA_DECL int archive_read_support_compression_all(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_bzip2(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_compress(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_gzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_lzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_lzma(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_none(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_program(struct archive *,
+ const char *command) __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_program_signature
+ (struct archive *, const char *,
+ const void * /* match */, size_t) __LA_DEPRECATED;
+
+__LA_DECL int archive_read_support_compression_rpm(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_uu(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_read_support_compression_xz(struct archive *)
+ __LA_DEPRECATED;
+#endif
+
+__LA_DECL int archive_read_support_filter_all(struct archive *);
+__LA_DECL int archive_read_support_filter_bzip2(struct archive *);
+__LA_DECL int archive_read_support_filter_compress(struct archive *);
+__LA_DECL int archive_read_support_filter_gzip(struct archive *);
+__LA_DECL int archive_read_support_filter_grzip(struct archive *);
+__LA_DECL int archive_read_support_filter_lrzip(struct archive *);
+__LA_DECL int archive_read_support_filter_lz4(struct archive *);
+__LA_DECL int archive_read_support_filter_lzip(struct archive *);
+__LA_DECL int archive_read_support_filter_lzma(struct archive *);
+__LA_DECL int archive_read_support_filter_lzop(struct archive *);
+__LA_DECL int archive_read_support_filter_none(struct archive *);
+__LA_DECL int archive_read_support_filter_program(struct archive *,
+ const char *command);
+__LA_DECL int archive_read_support_filter_program_signature
+ (struct archive *, const char * /* cmd */,
+ const void * /* match */, size_t);
+__LA_DECL int archive_read_support_filter_rpm(struct archive *);
+__LA_DECL int archive_read_support_filter_uu(struct archive *);
+__LA_DECL int archive_read_support_filter_xz(struct archive *);
+
+__LA_DECL int archive_read_support_format_7zip(struct archive *);
+__LA_DECL int archive_read_support_format_all(struct archive *);
+__LA_DECL int archive_read_support_format_ar(struct archive *);
+__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 *);
+__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 *);
+__LA_DECL int archive_read_support_format_mtree(struct archive *);
+__LA_DECL int archive_read_support_format_rar(struct archive *);
+__LA_DECL int archive_read_support_format_raw(struct archive *);
+__LA_DECL int archive_read_support_format_tar(struct archive *);
+__LA_DECL int archive_read_support_format_warc(struct archive *);
+__LA_DECL int archive_read_support_format_xar(struct archive *);
+/* archive_read_support_format_zip() enables both streamable and seekable
+ * zip readers. */
+__LA_DECL int archive_read_support_format_zip(struct archive *);
+/* Reads Zip archives as stream from beginning to end. Doesn't
+ * correctly handle SFX ZIP files or ZIP archives that have been modified
+ * in-place. */
+__LA_DECL int archive_read_support_format_zip_streamable(struct archive *);
+/* Reads starting from central directory; requires seekable input. */
+__LA_DECL int archive_read_support_format_zip_seekable(struct archive *);
+
+/* Functions to manually set the format and filters to be used. This is
+ * useful to bypass the bidding process when the format and filters to use
+ * is known in advance.
+ */
+__LA_DECL int archive_read_set_format(struct archive *, int);
+__LA_DECL int archive_read_append_filter(struct archive *, int);
+__LA_DECL int archive_read_append_filter_program(struct archive *,
+ const char *);
+__LA_DECL int archive_read_append_filter_program_signature
+ (struct archive *, const char *, const void * /* match */, size_t);
+
+/* Set various callbacks. */
+__LA_DECL int archive_read_set_open_callback(struct archive *,
+ archive_open_callback *);
+__LA_DECL int archive_read_set_read_callback(struct archive *,
+ archive_read_callback *);
+__LA_DECL int archive_read_set_seek_callback(struct archive *,
+ archive_seek_callback *);
+__LA_DECL int archive_read_set_skip_callback(struct archive *,
+ archive_skip_callback *);
+__LA_DECL int archive_read_set_close_callback(struct archive *,
+ archive_close_callback *);
+/* Callback used to switch between one data object to the next */
+__LA_DECL int archive_read_set_switch_callback(struct archive *,
+ archive_switch_callback *);
+
+/* This sets the first data object. */
+__LA_DECL int archive_read_set_callback_data(struct archive *, void *);
+/* This sets data object at specified index */
+__LA_DECL int archive_read_set_callback_data2(struct archive *, void *,
+ unsigned int);
+/* This adds a data object at the specified index. */
+__LA_DECL int archive_read_add_callback_data(struct archive *, void *,
+ unsigned int);
+/* This appends a data object to the end of list */
+__LA_DECL int archive_read_append_callback_data(struct archive *, void *);
+/* This prepends a data object to the beginning of list */
+__LA_DECL int archive_read_prepend_callback_data(struct archive *, void *);
+
+/* Opening freezes the callbacks. */
+__LA_DECL int archive_read_open1(struct archive *);
+
+/* Convenience wrappers around the above. */
+__LA_DECL int archive_read_open(struct archive *, void *_client_data,
+ archive_open_callback *, archive_read_callback *,
+ archive_close_callback *);
+__LA_DECL int archive_read_open2(struct archive *, void *_client_data,
+ archive_open_callback *, archive_read_callback *,
+ archive_skip_callback *, archive_close_callback *);
+
+/*
+ * A variety of shortcuts that invoke archive_read_open() with
+ * canned callbacks suitable for common situations. The ones that
+ * accept a block size handle tape blocking correctly.
+ */
+/* Use this if you know the filename. Note: NULL indicates stdin. */
+__LA_DECL int archive_read_open_filename(struct archive *,
+ const char *_filename, size_t _block_size);
+/* Use this for reading multivolume files by filenames.
+ * NOTE: Must be NULL terminated. Sorting is NOT done. */
+__LA_DECL int archive_read_open_filenames(struct archive *,
+ const char **_filenames, size_t _block_size);
+__LA_DECL int archive_read_open_filename_w(struct archive *,
+ const wchar_t *_filename, size_t _block_size);
+/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */
+__LA_DECL int archive_read_open_file(struct archive *,
+ const char *_filename, size_t _block_size) __LA_DEPRECATED;
+/* Read an archive that's stored in memory. */
+__LA_DECL int archive_read_open_memory(struct archive *,
+ const void * buff, size_t size);
+/* A more involved version that is only used for internal testing. */
+__LA_DECL int archive_read_open_memory2(struct archive *a, const void *buff,
+ size_t size, size_t read_size);
+/* Read an archive that's already open, using the file descriptor. */
+__LA_DECL int archive_read_open_fd(struct archive *, int _fd,
+ size_t _block_size);
+/* Read an archive that's already open, using a FILE *. */
+/* Note: DO NOT use this with tape drives. */
+__LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file);
+
+/* Parses and returns next entry header. */
+__LA_DECL int archive_read_next_header(struct archive *,
+ struct archive_entry **);
+
+/* Parses and returns next entry header using the archive_entry passed in */
+__LA_DECL int archive_read_next_header2(struct archive *,
+ struct archive_entry *);
+
+/*
+ * Retrieve the byte offset in UNCOMPRESSED data where last-read
+ * header started.
+ */
+__LA_DECL la_int64_t archive_read_header_position(struct archive *);
+
+/*
+ * Returns 1 if the archive contains at least one encrypted entry.
+ * If the archive format not support encryption at all
+ * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
+ * If for any other reason (e.g. not enough data read so far)
+ * we cannot say whether there are encrypted entries, then
+ * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
+ * In general, this function will return values below zero when the
+ * reader is uncertain or totally incapable of encryption support.
+ * When this function returns 0 you can be sure that the reader
+ * supports encryption detection but no encrypted entries have
+ * been found yet.
+ *
+ * NOTE: If the metadata/header of an archive is also encrypted, you
+ * cannot rely on the number of encrypted entries. That is why this
+ * function does not return the number of encrypted entries but#
+ * just shows that there are some.
+ */
+__LA_DECL int archive_read_has_encrypted_entries(struct archive *);
+
+/*
+ * Returns a bitmask of capabilities that are supported by the archive format reader.
+ * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
+ */
+__LA_DECL int archive_read_format_capabilities(struct archive *);
+
+/* Read data from the body of an entry. Similar to read(2). */
+__LA_DECL la_ssize_t archive_read_data(struct archive *,
+ void *, size_t);
+
+/* Seek within the body of an entry. Similar to lseek(2). */
+__LA_DECL la_int64_t archive_seek_data(struct archive *, la_int64_t, int);
+
+/*
+ * A zero-copy version of archive_read_data that also exposes the file offset
+ * of each returned block. Note that the client has no way to specify
+ * the desired size of the block. The API does guarantee that offsets will
+ * be strictly increasing and that returned blocks will not overlap.
+ */
+__LA_DECL int archive_read_data_block(struct archive *a,
+ const void **buff, size_t *size, la_int64_t *offset);
+
+/*-
+ * Some convenience functions that are built on archive_read_data:
+ * 'skip': skips entire entry
+ * 'into_buffer': writes data into memory buffer that you provide
+ * 'into_fd': writes data to specified filedes
+ */
+__LA_DECL int archive_read_data_skip(struct archive *);
+__LA_DECL int archive_read_data_into_fd(struct archive *, int fd);
+
+/*
+ * Set read options.
+ */
+/* Apply option to the format only. */
+__LA_DECL int archive_read_set_format_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
+/* Apply option to the filter only. */
+__LA_DECL int archive_read_set_filter_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
+/* Apply option to both the format and the filter. */
+__LA_DECL int archive_read_set_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
+/* Apply option string to both the format and the filter. */
+__LA_DECL int archive_read_set_options(struct archive *_a,
+ const char *opts);
+
+/*
+ * Add a decryption passphrase.
+ */
+__LA_DECL int archive_read_add_passphrase(struct archive *, const char *);
+__LA_DECL int archive_read_set_passphrase_callback(struct archive *,
+ void *client_data, archive_passphrase_callback *);
+
+
+/*-
+ * Convenience function to recreate the current entry (whose header
+ * has just been read) on disk.
+ *
+ * This does quite a bit more than just copy data to disk. It also:
+ * - Creates intermediate directories as required.
+ * - Manages directory permissions: non-writable directories will
+ * be initially created with write permission enabled; when the
+ * archive is closed, dir permissions are edited to the values specified
+ * in the archive.
+ * - Checks hardlinks: hardlinks will not be extracted unless the
+ * linked-to file was also extracted within the same session. (TODO)
+ */
+
+/* The "flags" argument selects optional behavior, 'OR' the flags you want. */
+
+/* Default: Do not try to set owner/group. */
+#define ARCHIVE_EXTRACT_OWNER (0x0001)
+/* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */
+#define ARCHIVE_EXTRACT_PERM (0x0002)
+/* Default: Do not restore mtime/atime. */
+#define ARCHIVE_EXTRACT_TIME (0x0004)
+/* Default: Replace existing files. */
+#define ARCHIVE_EXTRACT_NO_OVERWRITE (0x0008)
+/* Default: Try create first, unlink only if create fails with EEXIST. */
+#define ARCHIVE_EXTRACT_UNLINK (0x0010)
+/* Default: Do not restore ACLs. */
+#define ARCHIVE_EXTRACT_ACL (0x0020)
+/* Default: Do not restore fflags. */
+#define ARCHIVE_EXTRACT_FFLAGS (0x0040)
+/* Default: Do not restore xattrs. */
+#define ARCHIVE_EXTRACT_XATTR (0x0080)
+/* Default: Do not try to guard against extracts redirected by symlinks. */
+/* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */
+#define ARCHIVE_EXTRACT_SECURE_SYMLINKS (0x0100)
+/* Default: Do not reject entries with '..' as path elements. */
+#define ARCHIVE_EXTRACT_SECURE_NODOTDOT (0x0200)
+/* Default: Create parent directories as needed. */
+#define ARCHIVE_EXTRACT_NO_AUTODIR (0x0400)
+/* Default: Overwrite files, even if one on disk is newer. */
+#define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (0x0800)
+/* Detect blocks of 0 and write holes instead. */
+#define ARCHIVE_EXTRACT_SPARSE (0x1000)
+/* Default: Do not restore Mac extended metadata. */
+/* This has no effect except on Mac OS. */
+#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000)
+/* Default: Use HFS+ compression if it was compressed. */
+/* This has no effect except on Mac OS v10.6 or later. */
+#define ARCHIVE_EXTRACT_NO_HFS_COMPRESSION (0x4000)
+/* Default: Do not use HFS+ compression if it was not compressed. */
+/* This has no effect except on Mac OS v10.6 or later. */
+#define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000)
+/* Default: Do not reject entries with absolute paths */
+#define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000)
+/* Default: Do not clear no-change flags when unlinking object */
+#define ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS (0x20000)
+
+__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
+ int flags);
+__LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *,
+ struct archive * /* dest */);
+__LA_DECL void archive_read_extract_set_progress_callback(struct archive *,
+ void (*_progress_func)(void *), void *_user_data);
+
+/* Record the dev/ino of a file that will not be written. This is
+ * generally set to the dev/ino of the archive being read. */
+__LA_DECL void archive_read_extract_set_skip_file(struct archive *,
+ la_int64_t, la_int64_t);
+
+/* Close the file and release most resources. */
+__LA_DECL int archive_read_close(struct archive *);
+/* Release all resources and destroy the object. */
+/* Note that archive_read_free will call archive_read_close for you. */
+__LA_DECL int archive_read_free(struct archive *);
+#if ARCHIVE_VERSION_NUMBER < 4000000
+/* Synonym for archive_read_free() for backwards compatibility. */
+__LA_DECL int archive_read_finish(struct archive *) __LA_DEPRECATED;
+#endif
+
+/*-
+ * To create an archive:
+ * 1) Ask archive_write_new for an archive writer object.
+ * 2) Set any global properties. In particular, you should set
+ * the compression and format to use.
+ * 3) Call archive_write_open to open the file (most people
+ * will use archive_write_open_file or archive_write_open_fd,
+ * which provide convenient canned I/O callbacks for you).
+ * 4) For each entry:
+ * - construct an appropriate struct archive_entry structure
+ * - archive_write_header to write the header
+ * - archive_write_data to write the entry data
+ * 5) archive_write_close to close the output
+ * 6) archive_write_free to cleanup the writer and release resources
+ */
+__LA_DECL struct archive *archive_write_new(void);
+__LA_DECL int archive_write_set_bytes_per_block(struct archive *,
+ int bytes_per_block);
+__LA_DECL int archive_write_get_bytes_per_block(struct archive *);
+/* XXX This is badly misnamed; suggestions appreciated. XXX */
+__LA_DECL int archive_write_set_bytes_in_last_block(struct archive *,
+ int bytes_in_last_block);
+__LA_DECL int archive_write_get_bytes_in_last_block(struct archive *);
+
+/* The dev/ino of a file that won't be archived. This is used
+ * to avoid recursively adding an archive to itself. */
+__LA_DECL int archive_write_set_skip_file(struct archive *,
+ la_int64_t, la_int64_t);
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+__LA_DECL int archive_write_set_compression_bzip2(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_compress(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_gzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_lzip(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_lzma(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_none(struct archive *)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_program(struct archive *,
+ const char *cmd) __LA_DEPRECATED;
+__LA_DECL int archive_write_set_compression_xz(struct archive *)
+ __LA_DEPRECATED;
+#endif
+
+/* A convenience function to set the filter based on the code. */
+__LA_DECL int archive_write_add_filter(struct archive *, int filter_code);
+__LA_DECL int archive_write_add_filter_by_name(struct archive *,
+ const char *name);
+__LA_DECL int archive_write_add_filter_b64encode(struct archive *);
+__LA_DECL int archive_write_add_filter_bzip2(struct archive *);
+__LA_DECL int archive_write_add_filter_compress(struct archive *);
+__LA_DECL int archive_write_add_filter_grzip(struct archive *);
+__LA_DECL int archive_write_add_filter_gzip(struct archive *);
+__LA_DECL int archive_write_add_filter_lrzip(struct archive *);
+__LA_DECL int archive_write_add_filter_lz4(struct archive *);
+__LA_DECL int archive_write_add_filter_lzip(struct archive *);
+__LA_DECL int archive_write_add_filter_lzma(struct archive *);
+__LA_DECL int archive_write_add_filter_lzop(struct archive *);
+__LA_DECL int archive_write_add_filter_none(struct archive *);
+__LA_DECL int archive_write_add_filter_program(struct archive *,
+ const char *cmd);
+__LA_DECL int archive_write_add_filter_uuencode(struct archive *);
+__LA_DECL int archive_write_add_filter_xz(struct archive *);
+
+
+/* A convenience function to set the format based on the code or name. */
+__LA_DECL int archive_write_set_format(struct archive *, int format_code);
+__LA_DECL int archive_write_set_format_by_name(struct archive *,
+ const char *name);
+/* To minimize link pollution, use one or more of the following. */
+__LA_DECL int archive_write_set_format_7zip(struct archive *);
+__LA_DECL int archive_write_set_format_ar_bsd(struct archive *);
+__LA_DECL int archive_write_set_format_ar_svr4(struct archive *);
+__LA_DECL int archive_write_set_format_cpio(struct archive *);
+__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
+__LA_DECL int archive_write_set_format_gnutar(struct archive *);
+__LA_DECL int archive_write_set_format_iso9660(struct archive *);
+__LA_DECL int archive_write_set_format_mtree(struct archive *);
+__LA_DECL int archive_write_set_format_mtree_classic(struct archive *);
+/* TODO: int archive_write_set_format_old_tar(struct archive *); */
+__LA_DECL int archive_write_set_format_pax(struct archive *);
+__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
+__LA_DECL int archive_write_set_format_raw(struct archive *);
+__LA_DECL int archive_write_set_format_shar(struct archive *);
+__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
+__LA_DECL int archive_write_set_format_ustar(struct archive *);
+__LA_DECL int archive_write_set_format_v7tar(struct archive *);
+__LA_DECL int archive_write_set_format_warc(struct archive *);
+__LA_DECL int archive_write_set_format_xar(struct archive *);
+__LA_DECL int archive_write_set_format_zip(struct archive *);
+__LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const char *filename);
+__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_open(struct archive *, void *,
+ archive_open_callback *, archive_write_callback *,
+ archive_close_callback *);
+__LA_DECL int archive_write_open_fd(struct archive *, int _fd);
+__LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
+__LA_DECL int archive_write_open_filename_w(struct archive *,
+ const wchar_t *_file);
+/* A deprecated synonym for archive_write_open_filename() */
+__LA_DECL int archive_write_open_file(struct archive *, const char *_file)
+ __LA_DEPRECATED;
+__LA_DECL int archive_write_open_FILE(struct archive *, FILE *);
+/* _buffSize is the size of the buffer, _used refers to a variable that
+ * will be updated after each write into the buffer. */
+__LA_DECL int archive_write_open_memory(struct archive *,
+ void *_buffer, size_t _buffSize, size_t *_used);
+
+/*
+ * Note that the library will truncate writes beyond the size provided
+ * to archive_write_header or pad if the provided data is short.
+ */
+__LA_DECL int archive_write_header(struct archive *,
+ struct archive_entry *);
+__LA_DECL la_ssize_t archive_write_data(struct archive *,
+ const void *, size_t);
+
+/* This interface is currently only available for archive_write_disk handles. */
+__LA_DECL la_ssize_t archive_write_data_block(struct archive *,
+ const void *, size_t, la_int64_t);
+
+__LA_DECL int archive_write_finish_entry(struct archive *);
+__LA_DECL int archive_write_close(struct archive *);
+/* Marks the archive as FATAL so that a subsequent free() operation
+ * won't try to close() cleanly. Provides a fast abort capability
+ * when the client discovers that things have gone wrong. */
+__LA_DECL int archive_write_fail(struct archive *);
+/* This can fail if the archive wasn't already closed, in which case
+ * archive_write_free() will implicitly call archive_write_close(). */
+__LA_DECL int archive_write_free(struct archive *);
+#if ARCHIVE_VERSION_NUMBER < 4000000
+/* Synonym for archive_write_free() for backwards compatibility. */
+__LA_DECL int archive_write_finish(struct archive *) __LA_DEPRECATED;
+#endif
+
+/*
+ * Set write options.
+ */
+/* Apply option to the format only. */
+__LA_DECL int archive_write_set_format_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
+/* Apply option to the filter only. */
+__LA_DECL int archive_write_set_filter_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
+/* Apply option to both the format and the filter. */
+__LA_DECL int archive_write_set_option(struct archive *_a,
+ const char *m, const char *o,
+ const char *v);
+/* Apply option string to both the format and the filter. */
+__LA_DECL int archive_write_set_options(struct archive *_a,
+ const char *opts);
+
+/*
+ * Set a encryption passphrase.
+ */
+__LA_DECL int archive_write_set_passphrase(struct archive *_a, const char *p);
+__LA_DECL int archive_write_set_passphrase_callback(struct archive *,
+ void *client_data, archive_passphrase_callback *);
+
+/*-
+ * ARCHIVE_WRITE_DISK API
+ *
+ * To create objects on disk:
+ * 1) Ask archive_write_disk_new for a new archive_write_disk object.
+ * 2) Set any global properties. In particular, you probably
+ * want to set the options.
+ * 3) For each entry:
+ * - construct an appropriate struct archive_entry structure
+ * - archive_write_header to create the file/dir/etc on disk
+ * - archive_write_data to write the entry data
+ * 4) archive_write_free to cleanup the writer and release resources
+ *
+ * In particular, you can use this in conjunction with archive_read()
+ * to pull entries out of an archive and create them on disk.
+ */
+__LA_DECL struct archive *archive_write_disk_new(void);
+/* This file will not be overwritten. */
+__LA_DECL int archive_write_disk_set_skip_file(struct archive *,
+ la_int64_t, la_int64_t);
+/* Set flags to control how the next item gets created.
+ * This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */
+__LA_DECL int archive_write_disk_set_options(struct archive *,
+ int flags);
+/*
+ * The lookup functions are given uname/uid (or gname/gid) pairs and
+ * return a uid (gid) suitable for this system. These are used for
+ * restoring ownership and for setting ACLs. The default functions
+ * are naive, they just return the uid/gid. These are small, so reasonable
+ * for applications that don't need to preserve ownership; they
+ * are probably also appropriate for applications that are doing
+ * same-system backup and restore.
+ */
+/*
+ * The "standard" lookup functions use common system calls to lookup
+ * the uname/gname, falling back to the uid/gid if the names can't be
+ * found. They cache lookups and are reasonably fast, but can be very
+ * large, so they are not used unless you ask for them. In
+ * particular, these match the specifications of POSIX "pax" and old
+ * POSIX "tar".
+ */
+__LA_DECL int archive_write_disk_set_standard_lookup(struct archive *);
+/*
+ * If neither the default (naive) nor the standard (big) functions suit
+ * your needs, you can write your own and register them. Be sure to
+ * include a cleanup function if you have allocated private data.
+ */
+__LA_DECL int archive_write_disk_set_group_lookup(struct archive *,
+ void * /* private_data */,
+ la_int64_t (*)(void *, const char *, la_int64_t),
+ void (* /* cleanup */)(void *));
+__LA_DECL int archive_write_disk_set_user_lookup(struct archive *,
+ void * /* private_data */,
+ la_int64_t (*)(void *, const char *, la_int64_t),
+ void (* /* cleanup */)(void *));
+__LA_DECL la_int64_t archive_write_disk_gid(struct archive *, const char *, la_int64_t);
+__LA_DECL la_int64_t archive_write_disk_uid(struct archive *, const char *, la_int64_t);
+
+/*
+ * ARCHIVE_READ_DISK API
+ *
+ * This is still evolving and somewhat experimental.
+ */
+__LA_DECL struct archive *archive_read_disk_new(void);
+/* The names for symlink modes here correspond to an old BSD
+ * command-line argument convention: -L, -P, -H */
+/* Follow all symlinks. */
+__LA_DECL int archive_read_disk_set_symlink_logical(struct archive *);
+/* Follow no symlinks. */
+__LA_DECL int archive_read_disk_set_symlink_physical(struct archive *);
+/* Follow symlink initially, then not. */
+__LA_DECL int archive_read_disk_set_symlink_hybrid(struct archive *);
+/* TODO: Handle Linux stat32/stat64 ugliness. <sigh> */
+__LA_DECL int archive_read_disk_entry_from_file(struct archive *,
+ struct archive_entry *, int /* fd */, const struct stat *);
+/* Look up gname for gid or uname for uid. */
+/* Default implementations are very, very stupid. */
+__LA_DECL const char *archive_read_disk_gname(struct archive *, la_int64_t);
+__LA_DECL const char *archive_read_disk_uname(struct archive *, la_int64_t);
+/* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the
+ * results for performance. */
+__LA_DECL int archive_read_disk_set_standard_lookup(struct archive *);
+/* You can install your own lookups if you like. */
+__LA_DECL int archive_read_disk_set_gname_lookup(struct archive *,
+ void * /* private_data */,
+ const char *(* /* lookup_fn */)(void *, la_int64_t),
+ void (* /* cleanup_fn */)(void *));
+__LA_DECL int archive_read_disk_set_uname_lookup(struct archive *,
+ void * /* private_data */,
+ const char *(* /* lookup_fn */)(void *, la_int64_t),
+ void (* /* cleanup_fn */)(void *));
+/* Start traversal. */
+__LA_DECL int archive_read_disk_open(struct archive *, const char *);
+__LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *);
+/*
+ * Request that current entry be visited. If you invoke it on every
+ * directory, you'll get a physical traversal. This is ignored if the
+ * current entry isn't a directory or a link to a directory. So, if
+ * you invoke this on every returned path, you'll get a full logical
+ * traversal.
+ */
+__LA_DECL int archive_read_disk_descend(struct archive *);
+__LA_DECL int archive_read_disk_can_descend(struct archive *);
+__LA_DECL int archive_read_disk_current_filesystem(struct archive *);
+__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *);
+__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *);
+/* Request that the access time of the entry visited by traversal be restored. */
+__LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
+/*
+ * Set behavior. The "flags" argument selects optional behavior.
+ */
+/* Request that the access time of the entry visited by traversal be restored.
+ * This is the same as archive_read_disk_set_atime_restored. */
+#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001)
+/* Default: Do not skip an entry which has nodump flags. */
+#define ARCHIVE_READDISK_HONOR_NODUMP (0x0002)
+/* Default: Skip a mac resource fork file whose prefix is "._" because of
+ * using copyfile. */
+#define ARCHIVE_READDISK_MAC_COPYFILE (0x0004)
+/* Default: Traverse mount points. */
+#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008)
+/* Default: Xattrs are read from disk. */
+#define ARCHIVE_READDISK_NO_XATTR (0x0010)
++/* Default: ACLs are read from disk. */
++#define ARCHIVE_READDISK_NO_ACL (0x0020)
++/* Default: File flags are read from disk. */
++#define ARCHIVE_READDISK_NO_FFLAGS (0x0040)
+
+__LA_DECL int archive_read_disk_set_behavior(struct archive *,
+ int flags);
+
+/*
+ * Set archive_match object that will be used in archive_read_disk to
+ * know whether an entry should be skipped. The callback function
+ * _excluded_func will be invoked when an entry is skipped by the result
+ * of archive_match.
+ */
+__LA_DECL int archive_read_disk_set_matching(struct archive *,
+ struct archive *_matching, void (*_excluded_func)
+ (struct archive *, void *, struct archive_entry *),
+ void *_client_data);
+__LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *,
+ int (*_metadata_filter_func)(struct archive *, void *,
+ struct archive_entry *), void *_client_data);
+
+/* Simplified cleanup interface;
+ * This calls archive_read_free() or archive_write_free() as needed. */
+__LA_DECL int archive_free(struct archive *);
+
+/*
+ * Accessor functions to read/set various information in
+ * the struct archive object:
+ */
+
+/* Number of filters in the current filter pipeline. */
+/* Filter #0 is the one closest to the format, -1 is a synonym for the
+ * last filter, which is always the pseudo-filter that wraps the
+ * client callbacks. */
+__LA_DECL int archive_filter_count(struct archive *);
+__LA_DECL la_int64_t archive_filter_bytes(struct archive *, int);
+__LA_DECL int archive_filter_code(struct archive *, int);
+__LA_DECL const char * archive_filter_name(struct archive *, int);
+
+#if ARCHIVE_VERSION_NUMBER < 4000000
+/* These don't properly handle multiple filters, so are deprecated and
+ * will eventually be removed. */
+/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */
+__LA_DECL la_int64_t archive_position_compressed(struct archive *)
+ __LA_DEPRECATED;
+/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */
+__LA_DECL la_int64_t archive_position_uncompressed(struct archive *)
+ __LA_DEPRECATED;
+/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */
+__LA_DECL const char *archive_compression_name(struct archive *)
+ __LA_DEPRECATED;
+/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */
+__LA_DECL int archive_compression(struct archive *)
+ __LA_DEPRECATED;
+#endif
+
+__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 *);
+__LA_DECL int archive_format(struct archive *);
+__LA_DECL void archive_clear_error(struct archive *);
+__LA_DECL void archive_set_error(struct archive *, int _err,
+ const char *fmt, ...) __LA_PRINTF(3, 4);
+__LA_DECL void archive_copy_error(struct archive *dest,
+ struct archive *src);
+__LA_DECL int archive_file_count(struct archive *);
+
+/*
+ * ARCHIVE_MATCH API
+ */
+__LA_DECL struct archive *archive_match_new(void);
+__LA_DECL int archive_match_free(struct archive *);
+
+/*
+ * Test if archive_entry is excluded.
+ * This is a convenience function. This is the same as calling all
+ * archive_match_path_excluded, archive_match_time_excluded
+ * and archive_match_owner_excluded.
+ */
+__LA_DECL int archive_match_excluded(struct archive *,
+ struct archive_entry *);
+
+/*
+ * Test if pathname is excluded. The conditions are set by following functions.
+ */
+__LA_DECL int archive_match_path_excluded(struct archive *,
+ struct archive_entry *);
+/* Add exclusion pathname pattern. */
+__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *);
+__LA_DECL int archive_match_exclude_pattern_w(struct archive *,
+ const wchar_t *);
+/* Add exclusion pathname pattern from file. */
+__LA_DECL int archive_match_exclude_pattern_from_file(struct archive *,
+ const char *, int _nullSeparator);
+__LA_DECL int archive_match_exclude_pattern_from_file_w(struct archive *,
+ const wchar_t *, int _nullSeparator);
+/* Add inclusion pathname pattern. */
+__LA_DECL int archive_match_include_pattern(struct archive *, const char *);
+__LA_DECL int archive_match_include_pattern_w(struct archive *,
+ const wchar_t *);
+/* Add inclusion pathname pattern from file. */
+__LA_DECL int archive_match_include_pattern_from_file(struct archive *,
+ const char *, int _nullSeparator);
+__LA_DECL int archive_match_include_pattern_from_file_w(struct archive *,
+ const wchar_t *, int _nullSeparator);
+/*
+ * How to get statistic information for inclusion patterns.
+ */
+/* Return the amount number of unmatched inclusion patterns. */
+__LA_DECL int archive_match_path_unmatched_inclusions(struct archive *);
+/* Return the pattern of unmatched inclusion with ARCHIVE_OK.
+ * Return ARCHIVE_EOF if there is no inclusion pattern. */
+__LA_DECL int archive_match_path_unmatched_inclusions_next(
+ struct archive *, const char **);
+__LA_DECL int archive_match_path_unmatched_inclusions_next_w(
+ struct archive *, const wchar_t **);
+
+/*
+ * Test if a file is excluded by its time stamp.
+ * The conditions are set by following functions.
+ */
+__LA_DECL int archive_match_time_excluded(struct archive *,
+ struct archive_entry *);
+
+/*
+ * Flags to tell a matching type of time stamps. These are used for
+ * following functions.
+ */
+/* Time flag: mtime to be tested. */
+#define ARCHIVE_MATCH_MTIME (0x0100)
+/* Time flag: ctime to be tested. */
+#define ARCHIVE_MATCH_CTIME (0x0200)
+/* Comparison flag: Match the time if it is newer than. */
+#define ARCHIVE_MATCH_NEWER (0x0001)
+/* Comparison flag: Match the time if it is older than. */
+#define ARCHIVE_MATCH_OLDER (0x0002)
+/* Comparison flag: Match the time if it is equal to. */
+#define ARCHIVE_MATCH_EQUAL (0x0010)
+/* Set inclusion time. */
+__LA_DECL int archive_match_include_time(struct archive *, int _flag,
+ time_t _sec, long _nsec);
+/* Set inclusion time by a date string. */
+__LA_DECL int archive_match_include_date(struct archive *, int _flag,
+ const char *_datestr);
+__LA_DECL int archive_match_include_date_w(struct archive *, int _flag,
+ const wchar_t *_datestr);
+/* Set inclusion time by a particular file. */
+__LA_DECL int archive_match_include_file_time(struct archive *,
+ int _flag, const char *_pathname);
+__LA_DECL int archive_match_include_file_time_w(struct archive *,
+ int _flag, const wchar_t *_pathname);
+/* Add exclusion entry. */
+__LA_DECL int archive_match_exclude_entry(struct archive *,
+ int _flag, struct archive_entry *);
+
+/*
+ * Test if a file is excluded by its uid ,gid, uname or gname.
+ * The conditions are set by following functions.
+ */
+__LA_DECL int archive_match_owner_excluded(struct archive *,
+ struct archive_entry *);
+/* Add inclusion uid, gid, uname and gname. */
+__LA_DECL int archive_match_include_uid(struct archive *, la_int64_t);
+__LA_DECL int archive_match_include_gid(struct archive *, la_int64_t);
+__LA_DECL int archive_match_include_uname(struct archive *, const char *);
+__LA_DECL int archive_match_include_uname_w(struct archive *,
+ const wchar_t *);
+__LA_DECL int archive_match_include_gname(struct archive *, const char *);
+__LA_DECL int archive_match_include_gname_w(struct archive *,
+ const wchar_t *);
+
+/* Utility functions */
+/* Convenience function to sort a NULL terminated list of strings */
+__LA_DECL int archive_utility_string_sort(char **);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* These are meaningless outside of this header. */
+#undef __LA_DECL
+
+#endif /* !ARCHIVE_H_INCLUDED */
diff --cc Utilities/cmlibarchive/libarchive/archive_entry.h
index c331117,0000000..6e0225b
mode 100644,000000..100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.h
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.h
@@@ -1,699 -1,0 +1,699 @@@
+/*-
+ * Copyright (c) 2003-2008 Tim Kientzle
+ * Copyright (c) 2016 Martin Matuska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $
+ */
+
+#ifndef ARCHIVE_ENTRY_H_INCLUDED
+#define ARCHIVE_ENTRY_H_INCLUDED
+
+/* Note: Compiler will complain if this does not match archive.h! */
- #define ARCHIVE_VERSION_NUMBER 3003000
++#define ARCHIVE_VERSION_NUMBER 3003001
+
+/*
+ * Note: archive_entry.h is for use outside of libarchive; the
+ * configuration headers (config.h, archive_platform.h, etc.) are
+ * purely internal. Do NOT use HAVE_XXX configuration macros to
+ * control the behavior of this header! If you must conditionalize,
+ * use predefined compiler and/or platform macros.
+ */
+
+#include <sys/types.h>
+#include <stddef.h> /* for wchar_t */
+#include <time.h>
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <windows.h>
+#endif
+
+/* Get a suitable 64-bit integer type. */
+#if !defined(__LA_INT64_T_DEFINED)
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_INT64_T la_int64_t
+# endif
+#define __LA_INT64_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+typedef __int64 la_int64_t;
+# else
+#include <unistd.h>
+# if defined(_SCO_DS) || defined(__osf__)
+typedef long long la_int64_t;
+# else
+typedef int64_t la_int64_t;
+# endif
+# endif
+#endif
+
+/* The la_ssize_t should match the type used in 'struct stat' */
+#if !defined(__LA_SSIZE_T_DEFINED)
+/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_SSIZE_T la_ssize_t
+# endif
+#define __LA_SSIZE_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
+typedef ssize_t la_ssize_t;
+# elif defined(_WIN64)
+typedef __int64 la_ssize_t;
+# else
+typedef long la_ssize_t;
+# endif
+# else
+# include <unistd.h> /* ssize_t */
+typedef ssize_t la_ssize_t;
+# endif
+#endif
+
+/* Get a suitable definition for mode_t */
+#if ARCHIVE_VERSION_NUMBER >= 3999000
+/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */
+# define __LA_MODE_T int
+#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) && !defined(__WATCOMC__)
+# define __LA_MODE_T unsigned short
+#else
+# define __LA_MODE_T mode_t
+#endif
+
+/* Large file support for Android */
+#ifdef __ANDROID__
+#include "android_lf.h"
+#endif
+
+/*
+ * On Windows, define LIBARCHIVE_STATIC if you're building or using a
+ * .lib. The default here assumes you're building a DLL. Only
+ * libarchive source should ever define __LIBARCHIVE_BUILD.
+ */
+#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC)
+# ifdef __LIBARCHIVE_BUILD
+# ifdef __GNUC__
+# define __LA_DECL __attribute__((dllexport)) extern
+# else
+# define __LA_DECL __declspec(dllexport)
+# endif
+# else
+# ifdef __GNUC__
+# define __LA_DECL
+# else
+# define __LA_DECL __declspec(dllimport)
+# endif
+# endif
+#else
+/* Static libraries on all platforms and shared libraries on non-Windows. */
+# define __LA_DECL
+#endif
+
+/* CMake uses some deprecated APIs to build with old libarchive versions. */
+#define __LA_DEPRECATED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Description of an archive entry.
+ *
+ * You can think of this as "struct stat" with some text fields added in.
+ *
+ * TODO: Add "comment", "charset", and possibly other entries that are
+ * supported by "pax interchange" format. However, GNU, ustar, cpio,
+ * and other variants don't support these features, so they're not an
+ * excruciatingly high priority right now.
+ *
+ * TODO: "pax interchange" format allows essentially arbitrary
+ * key/value attributes to be attached to any entry. Supporting
+ * such extensions may make this library useful for special
+ * applications (e.g., a package manager could attach special
+ * package-management attributes to each entry).
+ */
+struct archive;
+struct archive_entry;
+
+/*
+ * File-type constants. These are returned from archive_entry_filetype()
+ * and passed to archive_entry_set_filetype().
+ *
+ * These values match S_XXX defines on every platform I've checked,
+ * including Windows, AIX, Linux, Solaris, and BSD. They're
+ * (re)defined here because platforms generally don't define the ones
+ * they don't support. For example, Windows doesn't define S_IFLNK or
+ * S_IFBLK. Instead of having a mass of conditional logic and system
+ * checks to define any S_XXX values that aren't supported locally,
+ * I've just defined a new set of such constants so that
+ * libarchive-based applications can manipulate and identify archive
+ * entries properly even if the hosting platform can't store them on
+ * disk.
+ *
+ * These values are also used directly within some portable formats,
+ * such as cpio. If you find a platform that varies from these, the
+ * correct solution is to leave these alone and translate from these
+ * portable values to platform-native values when entries are read from
+ * or written to disk.
+ */
+/*
+ * In libarchive 4.0, we can drop the casts here.
+ * They're needed to work around Borland C's broken mode_t.
+ */
+#define AE_IFMT ((__LA_MODE_T)0170000)
+#define AE_IFREG ((__LA_MODE_T)0100000)
+#define AE_IFLNK ((__LA_MODE_T)0120000)
+#define AE_IFSOCK ((__LA_MODE_T)0140000)
+#define AE_IFCHR ((__LA_MODE_T)0020000)
+#define AE_IFBLK ((__LA_MODE_T)0060000)
+#define AE_IFDIR ((__LA_MODE_T)0040000)
+#define AE_IFIFO ((__LA_MODE_T)0010000)
+
+/*
+ * Basic object manipulation
+ */
+
+__LA_DECL struct archive_entry *archive_entry_clear(struct archive_entry *);
+/* The 'clone' function does a deep copy; all of the strings are copied too. */
+__LA_DECL struct archive_entry *archive_entry_clone(struct archive_entry *);
+__LA_DECL void archive_entry_free(struct archive_entry *);
+__LA_DECL struct archive_entry *archive_entry_new(void);
+
+/*
+ * This form of archive_entry_new2() will pull character-set
+ * conversion information from the specified archive handle. The
+ * older archive_entry_new(void) form is equivalent to calling
+ * archive_entry_new2(NULL) and will result in the use of an internal
+ * default character-set conversion.
+ */
+__LA_DECL struct archive_entry *archive_entry_new2(struct archive *);
+
+/*
+ * Retrieve fields from an archive_entry.
+ *
+ * There are a number of implicit conversions among these fields. For
+ * example, if a regular string field is set and you read the _w wide
+ * character field, the entry will implicitly convert narrow-to-wide
+ * using the current locale. Similarly, dev values are automatically
+ * updated when you write devmajor or devminor and vice versa.
+ *
+ * In addition, fields can be "set" or "unset." Unset string fields
+ * return NULL, non-string fields have _is_set() functions to test
+ * whether they've been set. You can "unset" a string field by
+ * assigning NULL; non-string fields have _unset() functions to
+ * unset them.
+ *
+ * Note: There is one ambiguity in the above; string fields will
+ * 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 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 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 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 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_MODE_T archive_entry_filetype(struct archive_entry *);
+__LA_DECL void archive_entry_fflags(struct archive_entry *,
+ unsigned long * /* set */,
+ unsigned long * /* clear */);
+__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *);
+__LA_DECL la_int64_t archive_entry_gid(struct archive_entry *);
+__LA_DECL const char *archive_entry_gname(struct archive_entry *);
+__LA_DECL const char *archive_entry_gname_utf8(struct archive_entry *);
+__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *);
+__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 la_int64_t archive_entry_ino(struct archive_entry *);
+__LA_DECL la_int64_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 *);
+__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *);
+__LA_DECL int archive_entry_mtime_is_set(struct archive_entry *);
+__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *);
+__LA_DECL const char *archive_entry_pathname(struct archive_entry *);
+__LA_DECL const char *archive_entry_pathname_utf8(struct archive_entry *);
+__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 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 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 *);
+__LA_DECL int archive_entry_size_is_set(struct archive_entry *);
+__LA_DECL const char *archive_entry_strmode(struct archive_entry *);
+__LA_DECL const char *archive_entry_symlink(struct archive_entry *);
+__LA_DECL const char *archive_entry_symlink_utf8(struct archive_entry *);
+__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *);
+__LA_DECL la_int64_t archive_entry_uid(struct archive_entry *);
+__LA_DECL const char *archive_entry_uname(struct archive_entry *);
+__LA_DECL const char *archive_entry_uname_utf8(struct archive_entry *);
+__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *);
+__LA_DECL int archive_entry_is_data_encrypted(struct archive_entry *);
+__LA_DECL int archive_entry_is_metadata_encrypted(struct archive_entry *);
+__LA_DECL int archive_entry_is_encrypted(struct archive_entry *);
+
+/*
+ * Set fields in an archive_entry.
+ *
+ * Note: Before libarchive 2.4, there were 'set' and 'copy' versions
+ * of the string setters. 'copy' copied the actual string, 'set' just
+ * stored the pointer. In libarchive 2.4 and later, strings are
+ * always copied.
+ */
+
+__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long);
+__LA_DECL void archive_entry_unset_atime(struct archive_entry *);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, struct _BY_HANDLE_FILE_INFORMATION *);
+#endif
+__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long);
+__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *);
+__LA_DECL void archive_entry_set_ctime(struct archive_entry *, 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_filetype(struct archive_entry *, unsigned int);
+__LA_DECL void archive_entry_set_fflags(struct archive_entry *,
+ unsigned long /* set */, unsigned long /* clear */);
+/* Returns pointer to start of first invalid token, or NULL if none. */
+/* Note that all recognized tokens are processed, regardless. */
+__LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *,
+ const char *);
+__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *,
+ const wchar_t *);
+__LA_DECL void archive_entry_set_gid(struct archive_entry *, la_int64_t);
+__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_gname_utf8(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *);
+__LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_hardlink_utf8(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
+__LA_DECL 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_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_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 *);
+__LA_DECL void archive_entry_set_pathname_utf8(struct archive_entry *, const char *);
+__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_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 *);
+__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *);
+__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_symlink_utf8(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);
+__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_uid(struct archive_entry *, la_int64_t);
+__LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_uname_utf8(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *);
+__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *);
+__LA_DECL void archive_entry_set_is_data_encrypted(struct archive_entry *, char is_encrypted);
+__LA_DECL void archive_entry_set_is_metadata_encrypted(struct archive_entry *, char is_encrypted);
+/*
+ * Routines to bulk copy fields to/from a platform-native "struct
+ * stat." Libarchive used to just store a struct stat inside of each
+ * archive_entry object, but this created issues when trying to
+ * manipulate archives on systems different than the ones they were
+ * created on.
+ *
+ * TODO: On Linux and other LFS systems, provide both stat32 and
+ * stat64 versions of these functions and all of the macro glue so
+ * that archive_entry_stat is magically defined to
+ * archive_entry_stat32 or archive_entry_stat64 as appropriate.
+ */
+__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *);
+__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *);
+
+/*
+ * Storage for Mac OS-specific AppleDouble metadata information.
+ * Apple-format tar files store a separate binary blob containing
+ * encoded metadata with ACL, extended attributes, etc.
+ * This provides a place to store that blob.
+ */
+
+__LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *);
+__LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t);
+
+/*
+ * ACL routines. This used to simply store and return text-format ACL
+ * strings, but that proved insufficient for a number of reasons:
+ * = clients need control over uname/uid and gname/gid mappings
+ * = there are many different ACL text formats
+ * = would like to be able to read/convert archives containing ACLs
+ * on platforms that lack ACL libraries
+ *
+ * This last point, in particular, forces me to implement a reasonably
+ * complete set of ACL support routines.
+ */
+
+/*
+ * Permission bits.
+ */
+#define ARCHIVE_ENTRY_ACL_EXECUTE 0x00000001
+#define ARCHIVE_ENTRY_ACL_WRITE 0x00000002
+#define ARCHIVE_ENTRY_ACL_READ 0x00000004
+#define ARCHIVE_ENTRY_ACL_READ_DATA 0x00000008
+#define ARCHIVE_ENTRY_ACL_LIST_DIRECTORY 0x00000008
+#define ARCHIVE_ENTRY_ACL_WRITE_DATA 0x00000010
+#define ARCHIVE_ENTRY_ACL_ADD_FILE 0x00000010
+#define ARCHIVE_ENTRY_ACL_APPEND_DATA 0x00000020
+#define ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY 0x00000020
+#define ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS 0x00000040
+#define ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS 0x00000080
+#define ARCHIVE_ENTRY_ACL_DELETE_CHILD 0x00000100
+#define ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES 0x00000200
+#define ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES 0x00000400
+#define ARCHIVE_ENTRY_ACL_DELETE 0x00000800
+#define ARCHIVE_ENTRY_ACL_READ_ACL 0x00001000
+#define ARCHIVE_ENTRY_ACL_WRITE_ACL 0x00002000
+#define ARCHIVE_ENTRY_ACL_WRITE_OWNER 0x00004000
+#define ARCHIVE_ENTRY_ACL_SYNCHRONIZE 0x00008000
+
+#define ARCHIVE_ENTRY_ACL_PERMS_POSIX1E \
+ (ARCHIVE_ENTRY_ACL_EXECUTE \
+ | ARCHIVE_ENTRY_ACL_WRITE \
+ | ARCHIVE_ENTRY_ACL_READ)
+
+#define ARCHIVE_ENTRY_ACL_PERMS_NFS4 \
+ (ARCHIVE_ENTRY_ACL_EXECUTE \
+ | ARCHIVE_ENTRY_ACL_READ_DATA \
+ | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY \
+ | ARCHIVE_ENTRY_ACL_WRITE_DATA \
+ | ARCHIVE_ENTRY_ACL_ADD_FILE \
+ | ARCHIVE_ENTRY_ACL_APPEND_DATA \
+ | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY \
+ | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS \
+ | ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS \
+ | ARCHIVE_ENTRY_ACL_DELETE_CHILD \
+ | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES \
+ | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES \
+ | ARCHIVE_ENTRY_ACL_DELETE \
+ | ARCHIVE_ENTRY_ACL_READ_ACL \
+ | ARCHIVE_ENTRY_ACL_WRITE_ACL \
+ | ARCHIVE_ENTRY_ACL_WRITE_OWNER \
+ | ARCHIVE_ENTRY_ACL_SYNCHRONIZE)
+
+/*
+ * Inheritance values (NFS4 ACLs only); included in permset.
+ */
+#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000
+#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000
+#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000
+#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000
+#define ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY 0x10000000
+#define ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS 0x20000000
+#define ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS 0x40000000
+
+#define ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4 \
+ (ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT \
+ | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT \
+ | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \
+ | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \
+ | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \
+ | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \
+ | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED)
+
+/* We need to be able to specify combinations of these. */
+#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */
+#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */
+#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */
+#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \
+ | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
+#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \
+ | ARCHIVE_ENTRY_ACL_TYPE_DENY \
+ | ARCHIVE_ENTRY_ACL_TYPE_AUDIT \
+ | ARCHIVE_ENTRY_ACL_TYPE_ALARM)
+
+/* Tag values mimic POSIX.1e */
+#define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */
+#define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */
+#define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */
+#define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */
+#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access (POSIX.1e only) */
+#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public (POSIX.1e only) */
+#define ARCHIVE_ENTRY_ACL_EVERYONE 10107 /* Everyone (NFS4 only) */
+
+/*
+ * Set the ACL by clearing it and adding entries one at a time.
+ * Unlike the POSIX.1e ACL routines, you must specify the type
+ * (access/default) for each entry. Internally, the ACL data is just
+ * a soup of entries. API calls here allow you to retrieve just the
+ * entries of interest. This design (which goes against the spirit of
+ * POSIX.1e) is useful for handling archive formats that combine
+ * default and access information in a single ACL list.
+ */
+__LA_DECL void archive_entry_acl_clear(struct archive_entry *);
+__LA_DECL int archive_entry_acl_add_entry(struct archive_entry *,
+ int /* type */, int /* permset */, int /* tag */,
+ int /* qual */, const char * /* name */);
+__LA_DECL int archive_entry_acl_add_entry_w(struct archive_entry *,
+ int /* type */, int /* permset */, int /* tag */,
+ int /* qual */, const wchar_t * /* name */);
+
+/*
+ * To retrieve the ACL, first "reset", then repeatedly ask for the
+ * "next" entry. The want_type parameter allows you to request only
+ * certain types of entries.
+ */
+__LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */);
+__LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */,
+ int * /* type */, int * /* permset */, int * /* tag */,
+ int * /* qual */, const char ** /* name */);
+__LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type */,
+ int * /* type */, int * /* permset */, int * /* tag */,
+ int * /* qual */, const wchar_t ** /* name */);
+
+/*
+ * Construct a text-format ACL. The flags argument is a bitmask that
+ * can include any of the following:
+ *
+ * Flags only for archive entries with POSIX.1e ACL:
+ * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries.
+ * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries.
+ * ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each
+ * default ACL entry.
+ * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and
+ * "mask" entries.
+ *
+ * Flags only for archive entries with NFSv4 ACL:
+ * ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for
+ * unset permissions and flags in NFSv4 ACL permission and flag fields
+ *
+ * Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL:
+ * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
+ * each ACL entry.
+ * ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma
+ * instead of newline.
+ */
+#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001
+#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002
+#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004
+#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008
+#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010
+
+__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *,
+ la_ssize_t * /* len */, int /* flags */);
+__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *,
+ la_ssize_t * /* len */, int /* flags */);
+__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *,
+ const wchar_t * /* wtext */, int /* type */);
+__LA_DECL int archive_entry_acl_from_text(struct archive_entry *,
+ const char * /* text */, int /* type */);
+
+/* Deprecated constants */
+#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
+#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
+
+/* Deprecated functions */
+__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *,
+ int /* flags */) __LA_DEPRECATED;
+__LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
+ int /* flags */) __LA_DEPRECATED;
+
+/* Return bitmask of ACL types in an archive entry */
+__LA_DECL int archive_entry_acl_types(struct archive_entry *);
+
+/* Return a count of entries matching 'want_type' */
+__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */);
+
+/* Return an opaque ACL object. */
+/* There's not yet anything clients can actually do with this... */
+struct archive_acl;
+__LA_DECL struct archive_acl *archive_entry_acl(struct archive_entry *);
+
+/*
+ * extended attributes
+ */
+
+__LA_DECL void archive_entry_xattr_clear(struct archive_entry *);
+__LA_DECL void archive_entry_xattr_add_entry(struct archive_entry *,
+ const char * /* name */, const void * /* value */,
+ size_t /* size */);
+
+/*
+ * To retrieve the xattr list, first "reset", then repeatedly ask for the
+ * "next" entry.
+ */
+
+__LA_DECL int archive_entry_xattr_count(struct archive_entry *);
+__LA_DECL int archive_entry_xattr_reset(struct archive_entry *);
+__LA_DECL int archive_entry_xattr_next(struct archive_entry *,
+ const char ** /* name */, const void ** /* value */, size_t *);
+
+/*
+ * sparse
+ */
+
+__LA_DECL void archive_entry_sparse_clear(struct archive_entry *);
+__LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *,
+ la_int64_t /* offset */, la_int64_t /* length */);
+
+/*
+ * To retrieve the xattr list, first "reset", then repeatedly ask for the
+ * "next" entry.
+ */
+
+__LA_DECL int archive_entry_sparse_count(struct archive_entry *);
+__LA_DECL int archive_entry_sparse_reset(struct archive_entry *);
+__LA_DECL int archive_entry_sparse_next(struct archive_entry *,
+ la_int64_t * /* offset */, la_int64_t * /* length */);
+
+/*
+ * Utility to match up hardlinks.
+ *
+ * The 'struct archive_entry_linkresolver' is a cache of archive entries
+ * for files with multiple links. Here's how to use it:
+ * 1. Create a lookup object with archive_entry_linkresolver_new()
+ * 2. Tell it the archive format you're using.
+ * 3. Hand each archive_entry to archive_entry_linkify().
+ * That function will return 0, 1, or 2 entries that should
+ * be written.
+ * 4. Call archive_entry_linkify(resolver, NULL) until
+ * no more entries are returned.
+ * 5. Call archive_entry_linkresolver_free(resolver) to free resources.
+ *
+ * The entries returned have their hardlink and size fields updated
+ * appropriately. If an entry is passed in that does not refer to
+ * a file with multiple links, it is returned unchanged. The intention
+ * is that you should be able to simply filter all entries through
+ * this machine.
+ *
+ * To make things more efficient, be sure that each entry has a valid
+ * nlinks value. The hardlink cache uses this to track when all links
+ * have been found. If the nlinks value is zero, it will keep every
+ * name in the cache indefinitely, which can use a lot of memory.
+ *
+ * Note that archive_entry_size() is reset to zero if the file
+ * body should not be written to the archive. Pay attention!
+ */
+struct archive_entry_linkresolver;
+
+/*
+ * There are three different strategies for marking hardlinks.
+ * The descriptions below name them after the best-known
+ * formats that rely on each strategy:
+ *
+ * "Old cpio" is the simplest, it always returns any entry unmodified.
+ * As far as I know, only cpio formats use this. Old cpio archives
+ * store every link with the full body; the onus is on the dearchiver
+ * to detect and properly link the files as they are restored.
+ * "tar" is also pretty simple; it caches a copy the first time it sees
+ * any link. Subsequent appearances are modified to be hardlink
+ * references to the first one without any body. Used by all tar
+ * formats, although the newest tar formats permit the "old cpio" strategy
+ * as well. This strategy is very simple for the dearchiver,
+ * and reasonably straightforward for the archiver.
+ * "new cpio" is trickier. It stores the body only with the last
+ * occurrence. The complication is that we might not
+ * see every link to a particular file in a single session, so
+ * there's no easy way to know when we've seen the last occurrence.
+ * The solution here is to queue one link until we see the next.
+ * At the end of the session, you can enumerate any remaining
+ * entries by calling archive_entry_linkify(NULL) and store those
+ * bodies. If you have a file with three links l1, l2, and l3,
+ * you'll get the following behavior if you see all three links:
+ * linkify(l1) => NULL (the resolver stores l1 internally)
+ * linkify(l2) => l1 (resolver stores l2, you write l1)
+ * linkify(l3) => l2, l3 (all links seen, you can write both).
+ * If you only see l1 and l2, you'll get this behavior:
+ * linkify(l1) => NULL
+ * linkify(l2) => l1
+ * linkify(NULL) => l2 (at end, you retrieve remaining links)
+ * As the name suggests, this strategy is used by newer cpio variants.
+ * It's noticeably more complex for the archiver, slightly more complex
+ * for the dearchiver than the tar strategy, but makes it straightforward
+ * to restore a file using any link by simply continuing to scan until
+ * you see a link that is stored with a body. In contrast, the tar
+ * strategy requires you to rescan the archive from the beginning to
+ * correctly extract an arbitrary link.
+ */
+
+__LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void);
+__LA_DECL void archive_entry_linkresolver_set_strategy(
+ struct archive_entry_linkresolver *, int /* format_code */);
+__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *);
+__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *,
+ struct archive_entry **, struct archive_entry **);
+__LA_DECL struct archive_entry *archive_entry_partial_links(
+ struct archive_entry_linkresolver *res, unsigned int *links);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* This is meaningless outside of this header. */
+#undef __LA_DECL
+
+#endif /* !ARCHIVE_ENTRY_H_INCLUDED */
diff --cc Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
index 53629ac,0000000..a5f3067
mode 100644,000000..100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
@@@ -1,4206 -1,0 +1,4243 @@@
+/*-
+ * Copyright (c) 2003-2010 Tim Kientzle
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#if !defined(_WIN32) || defined(__CYGWIN__)
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_ACL_H
+#include <sys/acl.h>
+#endif
+#ifdef HAVE_SYS_EXTATTR_H
+#include <sys/extattr.h>
+#endif
+#if defined(HAVE_SYS_XATTR_H)
+#include <sys/xattr.h>
+#elif defined(HAVE_ATTR_XATTR_H)
+#include <attr/xattr.h>
+#endif
+#ifdef HAVE_SYS_EA_H
+#include <sys/ea.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_UTIME_H
+#include <sys/utime.h>
+#endif
+#ifdef HAVE_COPYFILE_H
+#include <copyfile.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+#ifdef HAVE_LINUX_FS_H
+#include <linux/fs.h> /* for Linux file flags */
+#endif
+/*
+ * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
+ * As the include guards don't agree, the order of include is important.
+ */
+#ifdef HAVE_LINUX_EXT2_FS_H
+#include <linux/ext2_fs.h> /* for Linux file flags */
+#endif
+#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
+#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+#ifdef F_GETTIMES /* Tru64 specific */
+#include <sys/fcntl1.h>
+#endif
+
+/*
+ * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared.
+ *
+ * It assumes that the input is an integer type of no more than 64 bits.
+ * If the number is less than zero, t must be a signed type, so it fits in
+ * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t
+ * without loss. But it could be a large unsigned value, so we have to clip it
+ * to INT64_MAX.*
+ */
+#define to_int64_time(t) \
+ ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t))
+
+#if __APPLE__
+#include <TargetConditionals.h>
+#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H
+#include <quarantine.h>
+#define HAVE_QUARANTINE 1
+#endif
+#endif
+
+#ifdef HAVE_ZLIB_H
+#include <cm_zlib.h>
+#endif
+
+/* TODO: Support Mac OS 'quarantine' feature. This is really just a
+ * standard tag to mark files that have been downloaded as "tainted".
+ * On Mac OS, we should mark the extracted files as tainted if the
+ * archive being read was tainted. Windows has a similar feature; we
+ * should investigate ways to support this generically. */
+
+#include "archive.h"
+#include "archive_acl_private.h"
+#include "archive_string.h"
+#include "archive_endian.h"
+#include "archive_entry.h"
+#include "archive_private.h"
+#include "archive_write_disk_private.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+/* Ignore non-int O_NOFOLLOW constant. */
+/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */
+#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
+#undef O_NOFOLLOW
+#endif
+
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW 0
+#endif
+
+struct fixup_entry {
+ struct fixup_entry *next;
+ struct archive_acl acl;
+ mode_t mode;
+ int64_t atime;
+ int64_t birthtime;
+ int64_t mtime;
+ int64_t ctime;
+ unsigned long atime_nanos;
+ unsigned long birthtime_nanos;
+ unsigned long mtime_nanos;
+ unsigned long ctime_nanos;
+ unsigned long fflags_set;
+ size_t mac_metadata_size;
+ void *mac_metadata;
+ int fixup; /* bitmask of what needs fixing */
+ char *name;
+};
+
+/*
+ * We use a bitmask to track which operations remain to be done for
+ * this file. In particular, this helps us avoid unnecessary
+ * operations when it's possible to take care of one step as a
+ * side-effect of another. For example, mkdir() can specify the mode
+ * for the newly-created object but symlink() cannot. This means we
+ * can skip chmod() if mkdir() succeeded, but we must explicitly
+ * chmod() if we're trying to create a directory that already exists
+ * (mkdir() failed) or if we're restoring a symlink. Similarly, we
+ * need to verify UID/GID before trying to restore SUID/SGID bits;
+ * that verification can occur explicitly through a stat() call or
+ * implicitly because of a successful chown() call.
+ */
+#define TODO_MODE_FORCE 0x40000000
+#define TODO_MODE_BASE 0x20000000
+#define TODO_SUID 0x10000000
+#define TODO_SUID_CHECK 0x08000000
+#define TODO_SGID 0x04000000
+#define TODO_SGID_CHECK 0x02000000
+#define TODO_APPLEDOUBLE 0x01000000
+#define TODO_MODE (TODO_MODE_BASE|TODO_SUID|TODO_SGID)
+#define TODO_TIMES ARCHIVE_EXTRACT_TIME
+#define TODO_OWNER ARCHIVE_EXTRACT_OWNER
+#define TODO_FFLAGS ARCHIVE_EXTRACT_FFLAGS
+#define TODO_ACLS ARCHIVE_EXTRACT_ACL
+#define TODO_XATTR ARCHIVE_EXTRACT_XATTR
+#define TODO_MAC_METADATA ARCHIVE_EXTRACT_MAC_METADATA
+#define TODO_HFS_COMPRESSION ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED
+
+struct archive_write_disk {
+ struct archive archive;
+
+ mode_t user_umask;
+ struct fixup_entry *fixup_list;
+ struct fixup_entry *current_fixup;
+ int64_t user_uid;
+ int skip_file_set;
+ int64_t skip_file_dev;
+ int64_t skip_file_ino;
+ time_t start_time;
+
+ int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid);
+ void (*cleanup_gid)(void *private);
+ void *lookup_gid_data;
+ int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid);
+ void (*cleanup_uid)(void *private);
+ void *lookup_uid_data;
+
+ /*
+ * Full path of last file to satisfy symlink checks.
+ */
+ struct archive_string path_safe;
+
+ /*
+ * Cached stat data from disk for the current entry.
+ * If this is valid, pst points to st. Otherwise,
+ * pst is null.
+ */
+ struct stat st;
+ struct stat *pst;
+
+ /* Information about the object being restored right now. */
+ struct archive_entry *entry; /* Entry being extracted. */
+ char *name; /* Name of entry, possibly edited. */
+ struct archive_string _name_data; /* backing store for 'name' */
+ /* Tasks remaining for this object. */
+ int todo;
+ /* Tasks deferred until end-of-archive. */
+ int deferred;
+ /* Options requested by the client. */
+ int flags;
+ /* Handle for the file we're restoring. */
+ int fd;
+ /* Current offset for writing data to the file. */
+ int64_t offset;
+ /* Last offset actually written to disk. */
+ int64_t fd_offset;
+ /* Total bytes actually written to files. */
+ int64_t total_bytes_written;
+ /* Maximum size of file, -1 if unknown. */
+ int64_t filesize;
+ /* Dir we were in before this restore; only for deep paths. */
+ int restore_pwd;
+ /* Mode we should use for this entry; affected by _PERM and umask. */
+ mode_t mode;
+ /* UID/GID to use in restoring this entry. */
+ int64_t uid;
+ int64_t gid;
+ /*
+ * HFS+ Compression.
+ */
+ /* Xattr "com.apple.decmpfs". */
+ uint32_t decmpfs_attr_size;
+ unsigned char *decmpfs_header_p;
+ /* ResourceFork set options used for fsetxattr. */
+ int rsrc_xattr_options;
+ /* Xattr "com.apple.ResourceFork". */
+ unsigned char *resource_fork;
+ size_t resource_fork_allocated_size;
+ unsigned int decmpfs_block_count;
+ uint32_t *decmpfs_block_info;
+ /* Buffer for compressed data. */
+ unsigned char *compressed_buffer;
+ size_t compressed_buffer_size;
+ size_t compressed_buffer_remaining;
+ /* The offset of the ResourceFork where compressed data will
+ * be placed. */
+ uint32_t compressed_rsrc_position;
+ uint32_t compressed_rsrc_position_v;
+ /* Buffer for uncompressed data. */
+ char *uncompressed_buffer;
+ size_t block_remaining_bytes;
+ size_t file_remaining_bytes;
+#ifdef HAVE_ZLIB_H
+ z_stream stream;
+ int stream_valid;
+ int decmpfs_compression_level;
+#endif
+};
+
+/*
+ * Default mode for dirs created automatically (will be modified by umask).
+ * Note that POSIX specifies 0777 for implicitly-created dirs, "modified
+ * by the process' file creation mask."
+ */
+#define DEFAULT_DIR_MODE 0777
+/*
+ * Dir modes are restored in two steps: During the extraction, the permissions
+ * in the archive are modified to match the following limits. During
+ * the post-extract fixup pass, the permissions from the archive are
+ * applied.
+ */
+#define MINIMUM_DIR_MODE 0700
+#define MAXIMUM_DIR_MODE 0775
+
+/*
+ * Maximum uncompressed size of a decmpfs block.
+ */
+#define MAX_DECMPFS_BLOCK_SIZE (64 * 1024)
+/*
+ * HFS+ compression type.
+ */
+#define CMP_XATTR 3/* Compressed data in xattr. */
+#define CMP_RESOURCE_FORK 4/* Compressed data in resource fork. */
+/*
+ * HFS+ compression resource fork.
+ */
+#define RSRC_H_SIZE 260 /* Base size of Resource fork header. */
+#define RSRC_F_SIZE 50 /* Size of Resource fork footer. */
+/* Size to write compressed data to resource fork. */
+#define COMPRESSED_W_SIZE (64 * 1024)
+/* decmpfs definitions. */
+#define MAX_DECMPFS_XATTR_SIZE 3802
+#ifndef DECMPFS_XATTR_NAME
+#define DECMPFS_XATTR_NAME "com.apple.decmpfs"
+#endif
+#define DECMPFS_MAGIC 0x636d7066
+#define DECMPFS_COMPRESSION_MAGIC 0
+#define DECMPFS_COMPRESSION_TYPE 4
+#define DECMPFS_UNCOMPRESSED_SIZE 8
+#define DECMPFS_HEADER_SIZE 16
+
+#define HFS_BLOCKS(s) ((s) >> 12)
+
+static void fsobj_error(int *, struct archive_string *, int, const char *,
+ const char *);
+static int check_symlinks_fsobj(char *, int *, struct archive_string *,
+ int);
+static int check_symlinks(struct archive_write_disk *);
+static int create_filesystem_object(struct archive_write_disk *);
+static struct fixup_entry *current_fixup(struct archive_write_disk *,
+ const char *pathname);
+#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
+static void edit_deep_directories(struct archive_write_disk *ad);
+#endif
+static int cleanup_pathname_fsobj(char *, int *, struct archive_string *,
+ int);
+static int cleanup_pathname(struct archive_write_disk *);
+static int create_dir(struct archive_write_disk *, char *);
+static int create_parent_dir(struct archive_write_disk *, char *);
+static ssize_t hfs_write_data_block(struct archive_write_disk *,
+ const char *, size_t);
+static int fixup_appledouble(struct archive_write_disk *, const char *);
+static int older(struct stat *, struct archive_entry *);
+static int restore_entry(struct archive_write_disk *);
+static int set_mac_metadata(struct archive_write_disk *, const char *,
+ const void *, size_t);
+static int set_xattrs(struct archive_write_disk *);
+static int clear_nochange_fflags(struct archive_write_disk *);
+static int set_fflags(struct archive_write_disk *);
+static int set_fflags_platform(struct archive_write_disk *, int fd,
+ const char *name, mode_t mode,
+ unsigned long fflags_set, unsigned long fflags_clear);
+static int set_ownership(struct archive_write_disk *);
+static int set_mode(struct archive_write_disk *, int mode);
+static int set_time(int, int, const char *, time_t, long, time_t, long);
+static int set_times(struct archive_write_disk *, int, int, const char *,
+ time_t, long, time_t, long, time_t, long, time_t, long);
+static int set_times_from_entry(struct archive_write_disk *);
+static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
+static ssize_t write_data_block(struct archive_write_disk *,
+ const char *, size_t);
+
+static struct archive_vtable *archive_write_disk_vtable(void);
+
+static int _archive_write_disk_close(struct archive *);
+static int _archive_write_disk_free(struct archive *);
+static int _archive_write_disk_header(struct archive *,
+ struct archive_entry *);
+static int64_t _archive_write_disk_filter_bytes(struct archive *, int);
+static int _archive_write_disk_finish_entry(struct archive *);
+static ssize_t _archive_write_disk_data(struct archive *, const void *,
+ size_t);
+static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
+ size_t, int64_t);
+
+static int
+lazy_stat(struct archive_write_disk *a)
+{
+ if (a->pst != NULL) {
+ /* Already have stat() data available. */
+ return (ARCHIVE_OK);
+ }
+#ifdef HAVE_FSTAT
+ if (a->fd >= 0 && fstat(a->fd, &a->st) == 0) {
+ a->pst = &a->st;
+ return (ARCHIVE_OK);
+ }
+#endif
+ /*
+ * XXX At this point, symlinks should not be hit, otherwise
+ * XXX a race occurred. Do we want to check explicitly for that?
+ */
+ if (lstat(a->name, &a->st) == 0) {
+ a->pst = &a->st;
+ return (ARCHIVE_OK);
+ }
+ archive_set_error(&a->archive, errno, "Couldn't stat file");
+ return (ARCHIVE_WARN);
+}
+
+static struct archive_vtable *
+archive_write_disk_vtable(void)
+{
+ static struct archive_vtable av;
+ static int inited = 0;
+
+ if (!inited) {
+ av.archive_close = _archive_write_disk_close;
+ av.archive_filter_bytes = _archive_write_disk_filter_bytes;
+ av.archive_free = _archive_write_disk_free;
+ av.archive_write_header = _archive_write_disk_header;
+ av.archive_write_finish_entry
+ = _archive_write_disk_finish_entry;
+ av.archive_write_data = _archive_write_disk_data;
+ av.archive_write_data_block = _archive_write_disk_data_block;
+ inited = 1;
+ }
+ return (&av);
+}
+
+static int64_t
+_archive_write_disk_filter_bytes(struct archive *_a, int n)
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ (void)n; /* UNUSED */
+ if (n == -1 || n == 0)
+ return (a->total_bytes_written);
+ return (-1);
+}
+
+
+int
+archive_write_disk_set_options(struct archive *_a, int flags)
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+
+ a->flags = flags;
+ return (ARCHIVE_OK);
+}
+
+
+/*
+ * Extract this entry to disk.
+ *
+ * TODO: Validate hardlinks. According to the standards, we're
+ * supposed to check each extracted hardlink and squawk if it refers
+ * to a file that we didn't restore. I'm not entirely convinced this
+ * is a good idea, but more importantly: Is there any way to validate
+ * hardlinks without keeping a complete list of filenames from the
+ * entire archive?? Ugh.
+ *
+ */
+static int
+_archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ struct fixup_entry *fe;
+ int ret, r;
+
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
+ "archive_write_disk_header");
+ archive_clear_error(&a->archive);
+ if (a->archive.state & ARCHIVE_STATE_DATA) {
+ r = _archive_write_disk_finish_entry(&a->archive);
+ if (r == ARCHIVE_FATAL)
+ return (r);
+ }
+
+ /* Set up for this particular entry. */
+ a->pst = NULL;
+ a->current_fixup = NULL;
+ a->deferred = 0;
+ if (a->entry) {
+ archive_entry_free(a->entry);
+ a->entry = NULL;
+ }
+ a->entry = archive_entry_clone(entry);
+ a->fd = -1;
+ a->fd_offset = 0;
+ a->offset = 0;
+ a->restore_pwd = -1;
+ a->uid = a->user_uid;
+ a->mode = archive_entry_mode(a->entry);
+ if (archive_entry_size_is_set(a->entry))
+ a->filesize = archive_entry_size(a->entry);
+ else
+ a->filesize = -1;
+ archive_strcpy(&(a->_name_data), archive_entry_pathname(a->entry));
+ a->name = a->_name_data.s;
+ archive_clear_error(&a->archive);
+
+ /*
+ * Clean up the requested path. This is necessary for correct
+ * dir restores; the dir restore logic otherwise gets messed
+ * up by nonsense like "dir/.".
+ */
+ ret = cleanup_pathname(a);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+
+ /*
+ * Query the umask so we get predictable mode settings.
+ * This gets done on every call to _write_header in case the
+ * user edits their umask during the extraction for some
+ * reason.
+ */
+ umask(a->user_umask = umask(0));
+
+ /* Figure out what we need to do for this entry. */
+ a->todo = TODO_MODE_BASE;
+ if (a->flags & ARCHIVE_EXTRACT_PERM) {
+ a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */
+ /*
+ * SGID requires an extra "check" step because we
+ * cannot easily predict the GID that the system will
+ * assign. (Different systems assign GIDs to files
+ * based on a variety of criteria, including process
+ * credentials and the gid of the enclosing
+ * directory.) We can only restore the SGID bit if
+ * the file has the right GID, and we only know the
+ * GID if we either set it (see set_ownership) or if
+ * we've actually called stat() on the file after it
+ * was restored. Since there are several places at
+ * which we might verify the GID, we need a TODO bit
+ * to keep track.
+ */
+ if (a->mode & S_ISGID)
+ a->todo |= TODO_SGID | TODO_SGID_CHECK;
+ /*
+ * Verifying the SUID is simpler, but can still be
+ * done in multiple ways, hence the separate "check" bit.
+ */
+ if (a->mode & S_ISUID)
+ a->todo |= TODO_SUID | TODO_SUID_CHECK;
+ } else {
+ /*
+ * User didn't request full permissions, so don't
+ * restore SUID, SGID bits and obey umask.
+ */
+ a->mode &= ~S_ISUID;
+ a->mode &= ~S_ISGID;
+ a->mode &= ~S_ISVTX;
+ a->mode &= ~a->user_umask;
+ }
+ if (a->flags & ARCHIVE_EXTRACT_OWNER)
+ a->todo |= TODO_OWNER;
+ if (a->flags & ARCHIVE_EXTRACT_TIME)
+ a->todo |= TODO_TIMES;
+ if (a->flags & ARCHIVE_EXTRACT_ACL) {
+ if (archive_entry_filetype(a->entry) == AE_IFDIR)
+ a->deferred |= TODO_ACLS;
+ else
+ a->todo |= TODO_ACLS;
+ }
+ if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) {
+ if (archive_entry_filetype(a->entry) == AE_IFDIR)
+ a->deferred |= TODO_MAC_METADATA;
+ else
+ a->todo |= TODO_MAC_METADATA;
+ }
+#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
+ if ((a->flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) == 0) {
+ unsigned long set, clear;
+ archive_entry_fflags(a->entry, &set, &clear);
+ if ((set & ~clear) & UF_COMPRESSED) {
+ a->todo |= TODO_HFS_COMPRESSION;
+ a->decmpfs_block_count = (unsigned)-1;
+ }
+ }
+ if ((a->flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) != 0 &&
+ (a->mode & AE_IFMT) == AE_IFREG && a->filesize > 0) {
+ a->todo |= TODO_HFS_COMPRESSION;
+ a->decmpfs_block_count = (unsigned)-1;
+ }
+ {
+ const char *p;
+
+ /* Check if the current file name is a type of the
+ * resource fork file. */
+ p = strrchr(a->name, '/');
+ if (p == NULL)
+ p = a->name;
+ else
+ p++;
+ if (p[0] == '.' && p[1] == '_') {
+ /* Do not compress "._XXX" files. */
+ a->todo &= ~TODO_HFS_COMPRESSION;
+ if (a->filesize > 0)
+ a->todo |= TODO_APPLEDOUBLE;
+ }
+ }
+#endif
+
+ if (a->flags & ARCHIVE_EXTRACT_XATTR)
+ a->todo |= TODO_XATTR;
+ if (a->flags & ARCHIVE_EXTRACT_FFLAGS)
+ a->todo |= TODO_FFLAGS;
+ if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) {
+ ret = check_symlinks(a);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+ }
+#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
+ /* If path exceeds PATH_MAX, shorten the path. */
+ edit_deep_directories(a);
+#endif
+
+ ret = restore_entry(a);
+
+#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
+ /*
+ * Check if the filesystem the file is restoring on supports
+ * HFS+ Compression. If not, cancel HFS+ Compression.
+ */
+ if (a->todo | TODO_HFS_COMPRESSION) {
+ /*
+ * NOTE: UF_COMPRESSED is ignored even if the filesystem
+ * supports HFS+ Compression because the file should
+ * have at least an extended attribute "com.apple.decmpfs"
+ * before the flag is set to indicate that the file have
+ * been compressed. If the filesystem does not support
+ * HFS+ Compression the system call will fail.
+ */
+ if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0)
+ a->todo &= ~TODO_HFS_COMPRESSION;
+ }
+#endif
+
+ /*
+ * TODO: There are rumours that some extended attributes must
+ * be restored before file data is written. If this is true,
+ * then we either need to write all extended attributes both
+ * before and after restoring the data, or find some rule for
+ * determining which must go first and which last. Due to the
+ * many ways people are using xattrs, this may prove to be an
+ * intractable problem.
+ */
+
+#ifdef HAVE_FCHDIR
+ /* If we changed directory above, restore it here. */
+ if (a->restore_pwd >= 0) {
+ r = fchdir(a->restore_pwd);
+ if (r != 0) {
+ archive_set_error(&a->archive, errno,
+ "chdir() failure");
+ ret = ARCHIVE_FATAL;
+ }
+ close(a->restore_pwd);
+ a->restore_pwd = -1;
+ }
+#endif
+
+ /*
+ * Fixup uses the unedited pathname from archive_entry_pathname(),
+ * because it is relative to the base dir and the edited path
+ * might be relative to some intermediate dir as a result of the
+ * deep restore logic.
+ */
+ if (a->deferred & TODO_MODE) {
+ fe = current_fixup(a, archive_entry_pathname(entry));
+ if (fe == NULL)
+ return (ARCHIVE_FATAL);
+ fe->fixup |= TODO_MODE_BASE;
+ fe->mode = a->mode;
+ }
+
+ if ((a->deferred & TODO_TIMES)
+ && (archive_entry_mtime_is_set(entry)
+ || archive_entry_atime_is_set(entry))) {
+ fe = current_fixup(a, archive_entry_pathname(entry));
+ if (fe == NULL)
+ return (ARCHIVE_FATAL);
+ fe->mode = a->mode;
+ fe->fixup |= TODO_TIMES;
+ if (archive_entry_atime_is_set(entry)) {
+ fe->atime = archive_entry_atime(entry);
+ fe->atime_nanos = archive_entry_atime_nsec(entry);
+ } else {
+ /* If atime is unset, use start time. */
+ fe->atime = a->start_time;
+ fe->atime_nanos = 0;
+ }
+ if (archive_entry_mtime_is_set(entry)) {
+ fe->mtime = archive_entry_mtime(entry);
+ fe->mtime_nanos = archive_entry_mtime_nsec(entry);
+ } else {
+ /* If mtime is unset, use start time. */
+ fe->mtime = a->start_time;
+ fe->mtime_nanos = 0;
+ }
+ if (archive_entry_birthtime_is_set(entry)) {
+ fe->birthtime = archive_entry_birthtime(entry);
+ fe->birthtime_nanos = archive_entry_birthtime_nsec(
+ entry);
+ } else {
+ /* If birthtime is unset, use mtime. */
+ fe->birthtime = fe->mtime;
+ fe->birthtime_nanos = fe->mtime_nanos;
+ }
+ }
+
+ if (a->deferred & TODO_ACLS) {
+ fe = current_fixup(a, archive_entry_pathname(entry));
+ if (fe == NULL)
+ return (ARCHIVE_FATAL);
+ fe->fixup |= TODO_ACLS;
+ archive_acl_copy(&fe->acl, archive_entry_acl(entry));
+ }
+
+ if (a->deferred & TODO_MAC_METADATA) {
+ const void *metadata;
+ size_t metadata_size;
+ metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
+ if (metadata != NULL && metadata_size > 0) {
+ fe = current_fixup(a, archive_entry_pathname(entry));
+ if (fe == NULL)
+ return (ARCHIVE_FATAL);
+ fe->mac_metadata = malloc(metadata_size);
+ if (fe->mac_metadata != NULL) {
+ memcpy(fe->mac_metadata, metadata,
+ metadata_size);
+ fe->mac_metadata_size = metadata_size;
+ fe->fixup |= TODO_MAC_METADATA;
+ }
+ }
+ }
+
+ if (a->deferred & TODO_FFLAGS) {
+ fe = current_fixup(a, archive_entry_pathname(entry));
+ if (fe == NULL)
+ return (ARCHIVE_FATAL);
+ fe->fixup |= TODO_FFLAGS;
+ /* TODO: Complete this.. defer fflags from below. */
+ }
+
+ /* We've created the object and are ready to pour data into it. */
+ if (ret >= ARCHIVE_WARN)
+ a->archive.state = ARCHIVE_STATE_DATA;
+ /*
+ * If it's not open, tell our client not to try writing.
+ * In particular, dirs, links, etc, don't get written to.
+ */
+ if (a->fd < 0) {
+ archive_entry_set_size(entry, 0);
+ a->filesize = 0;
+ }
+
+ return (ret);
+}
+
+int
+archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i)
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file");
+ a->skip_file_set = 1;
+ a->skip_file_dev = d;
+ a->skip_file_ino = i;
+ return (ARCHIVE_OK);
+}
+
+static ssize_t
+write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
+{
+ uint64_t start_size = size;
+ ssize_t bytes_written = 0;
+ ssize_t block_size = 0, bytes_to_write;
+
+ if (size == 0)
+ return (ARCHIVE_OK);
+
+ if (a->filesize == 0 || a->fd < 0) {
+ archive_set_error(&a->archive, 0,
+ "Attempt to write to an empty file");
+ return (ARCHIVE_WARN);
+ }
+
+ if (a->flags & ARCHIVE_EXTRACT_SPARSE) {
+#if HAVE_STRUCT_STAT_ST_BLKSIZE
+ int r;
+ if ((r = lazy_stat(a)) != ARCHIVE_OK)
+ return (r);
+ block_size = a->pst->st_blksize;
+#else
+ /* XXX TODO XXX Is there a more appropriate choice here ? */
+ /* This needn't match the filesystem allocation size. */
+ block_size = 16*1024;
+#endif
+ }
+
+ /* If this write would run beyond the file size, truncate it. */
+ if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize)
+ start_size = size = (size_t)(a->filesize - a->offset);
+
+ /* Write the data. */
+ while (size > 0) {
+ if (block_size == 0) {
+ bytes_to_write = size;
+ } else {
+ /* We're sparsifying the file. */
+ const char *p, *end;
+ int64_t block_end;
+
+ /* Skip leading zero bytes. */
+ for (p = buff, end = buff + size; p < end; ++p) {
+ if (*p != '\0')
+ break;
+ }
+ a->offset += p - buff;
+ size -= p - buff;
+ buff = p;
+ if (size == 0)
+ break;
+
+ /* Calculate next block boundary after offset. */
+ block_end
+ = (a->offset / block_size + 1) * block_size;
+
+ /* If the adjusted write would cross block boundary,
+ * truncate it to the block boundary. */
+ bytes_to_write = size;
+ if (a->offset + bytes_to_write > block_end)
+ bytes_to_write = block_end - a->offset;
+ }
+ /* Seek if necessary to the specified offset. */
+ if (a->offset != a->fd_offset) {
+ if (lseek(a->fd, a->offset, SEEK_SET) < 0) {
+ archive_set_error(&a->archive, errno,
+ "Seek failed");
+ return (ARCHIVE_FATAL);
+ }
+ a->fd_offset = a->offset;
+ }
+ bytes_written = write(a->fd, buff, bytes_to_write);
+ if (bytes_written < 0) {
+ archive_set_error(&a->archive, errno, "Write failed");
+ return (ARCHIVE_WARN);
+ }
+ buff += bytes_written;
+ size -= bytes_written;
+ a->total_bytes_written += bytes_written;
+ a->offset += bytes_written;
+ a->fd_offset = a->offset;
+ }
+ return (start_size - size);
+}
+
+#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\
+ && defined(HAVE_ZLIB_H)
+
+/*
+ * Set UF_COMPRESSED file flag.
+ * This have to be called after hfs_write_decmpfs() because if the
+ * file does not have "com.apple.decmpfs" xattr the flag is ignored.
+ */
+static int
+hfs_set_compressed_fflag(struct archive_write_disk *a)
+{
+ int r;
+
+ if ((r = lazy_stat(a)) != ARCHIVE_OK)
+ return (r);
+
+ a->st.st_flags |= UF_COMPRESSED;
+ if (fchflags(a->fd, a->st.st_flags) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to set UF_COMPRESSED file flag");
+ return (ARCHIVE_WARN);
+ }
+ return (ARCHIVE_OK);
+}
+
+/*
+ * HFS+ Compression decmpfs
+ *
+ * +------------------------------+ +0
+ * | Magic(LE 4 bytes) |
+ * +------------------------------+
+ * | Type(LE 4 bytes) |
+ * +------------------------------+
+ * | Uncompressed size(LE 8 bytes)|
+ * +------------------------------+ +16
+ * | |
+ * | Compressed data |
+ * | (Placed only if Type == 3) |
+ * | |
+ * +------------------------------+ +3802 = MAX_DECMPFS_XATTR_SIZE
+ *
+ * Type is 3: decmpfs has compressed data.
+ * Type is 4: Resource Fork has compressed data.
+ */
+/*
+ * Write "com.apple.decmpfs"
+ */
+static int
+hfs_write_decmpfs(struct archive_write_disk *a)
+{
+ int r;
+ uint32_t compression_type;
+
+ r = fsetxattr(a->fd, DECMPFS_XATTR_NAME, a->decmpfs_header_p,
+ a->decmpfs_attr_size, 0, 0);
+ if (r < 0) {
+ archive_set_error(&a->archive, errno,
+ "Cannot restore xattr:%s", DECMPFS_XATTR_NAME);
+ compression_type = archive_le32dec(
+ &a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE]);
+ if (compression_type == CMP_RESOURCE_FORK)
+ fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME,
+ XATTR_SHOWCOMPRESSION);
+ return (ARCHIVE_WARN);
+ }
+ return (ARCHIVE_OK);
+}
+
+/*
+ * HFS+ Compression Resource Fork
+ *
+ * +-----------------------------+
+ * | Header(260 bytes) |
+ * +-----------------------------+
+ * | Block count(LE 4 bytes) |
+ * +-----------------------------+ --+
+ * +-- | Offset (LE 4 bytes) | |
+ * | | [distance from Block count] | | Block 0
+ * | +-----------------------------+ |
+ * | | Compressed size(LE 4 bytes) | |
+ * | +-----------------------------+ --+
+ * | | |
+ * | | .................. |
+ * | | |
+ * | +-----------------------------+ --+
+ * | | Offset (LE 4 bytes) | |
+ * | +-----------------------------+ | Block (Block count -1)
+ * | | Compressed size(LE 4 bytes) | |
+ * +-> +-----------------------------+ --+
+ * | Compressed data(n bytes) | Block 0
+ * +-----------------------------+
+ * | |
+ * | .................. |
+ * | |
+ * +-----------------------------+
+ * | Compressed data(n bytes) | Block (Block count -1)
+ * +-----------------------------+
+ * | Footer(50 bytes) |
+ * +-----------------------------+
+ *
+ */
+/*
+ * Write the header of "com.apple.ResourceFork"
+ */
+static int
+hfs_write_resource_fork(struct archive_write_disk *a, unsigned char *buff,
+ size_t bytes, uint32_t position)
+{
+ int ret;
+
+ ret = fsetxattr(a->fd, XATTR_RESOURCEFORK_NAME, buff, bytes,
+ position, a->rsrc_xattr_options);
+ if (ret < 0) {
+ archive_set_error(&a->archive, errno,
+ "Cannot restore xattr: %s at %u pos %u bytes",
+ XATTR_RESOURCEFORK_NAME,
+ (unsigned)position,
+ (unsigned)bytes);
+ return (ARCHIVE_WARN);
+ }
+ a->rsrc_xattr_options &= ~XATTR_CREATE;
+ return (ARCHIVE_OK);
+}
+
+static int
+hfs_write_compressed_data(struct archive_write_disk *a, size_t bytes_compressed)
+{
+ int ret;
+
+ ret = hfs_write_resource_fork(a, a->compressed_buffer,
+ bytes_compressed, a->compressed_rsrc_position);
+ if (ret == ARCHIVE_OK)
+ a->compressed_rsrc_position += bytes_compressed;
+ return (ret);
+}
+
+static int
+hfs_write_resource_fork_header(struct archive_write_disk *a)
+{
+ unsigned char *buff;
+ uint32_t rsrc_bytes;
+ uint32_t rsrc_header_bytes;
+
+ /*
+ * Write resource fork header + block info.
+ */
+ buff = a->resource_fork;
+ rsrc_bytes = a->compressed_rsrc_position - RSRC_F_SIZE;
+ rsrc_header_bytes =
+ RSRC_H_SIZE + /* Header base size. */
+ 4 + /* Block count. */
+ (a->decmpfs_block_count * 8);/* Block info */
+ archive_be32enc(buff, 0x100);
+ archive_be32enc(buff + 4, rsrc_bytes);
+ archive_be32enc(buff + 8, rsrc_bytes - 256);
+ archive_be32enc(buff + 12, 0x32);
+ memset(buff + 16, 0, 240);
+ archive_be32enc(buff + 256, rsrc_bytes - 260);
+ return hfs_write_resource_fork(a, buff, rsrc_header_bytes, 0);
+}
+
+static size_t
+hfs_set_resource_fork_footer(unsigned char *buff, size_t buff_size)
+{
+ static const char rsrc_footer[RSRC_F_SIZE] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c', 'm',
+ 'p', 'f', 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+ };
+ if (buff_size < sizeof(rsrc_footer))
+ return (0);
+ memcpy(buff, rsrc_footer, sizeof(rsrc_footer));
+ return (sizeof(rsrc_footer));
+}
+
+static int
+hfs_reset_compressor(struct archive_write_disk *a)
+{
+ int ret;
+
+ if (a->stream_valid)
+ ret = deflateReset(&a->stream);
+ else
+ ret = deflateInit(&a->stream, a->decmpfs_compression_level);
+
+ if (ret != Z_OK) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Failed to initialize compressor");
+ return (ARCHIVE_FATAL);
+ } else
+ a->stream_valid = 1;
+
+ return (ARCHIVE_OK);
+}
+
+static int
+hfs_decompress(struct archive_write_disk *a)
+{
+ uint32_t *block_info;
+ unsigned int block_count;
+ uint32_t data_pos, data_size;
+ ssize_t r;
+ ssize_t bytes_written, bytes_to_write;
+ unsigned char *b;
+
+ block_info = (uint32_t *)(a->resource_fork + RSRC_H_SIZE);
+ block_count = archive_le32dec(block_info++);
+ while (block_count--) {
+ data_pos = RSRC_H_SIZE + archive_le32dec(block_info++);
+ data_size = archive_le32dec(block_info++);
+ r = fgetxattr(a->fd, XATTR_RESOURCEFORK_NAME,
+ a->compressed_buffer, data_size, data_pos, 0);
+ if (r != data_size) {
+ archive_set_error(&a->archive,
+ (r < 0)?errno:ARCHIVE_ERRNO_MISC,
+ "Failed to read resource fork");
+ return (ARCHIVE_WARN);
+ }
+ if (a->compressed_buffer[0] == 0xff) {
+ bytes_to_write = data_size -1;
+ b = a->compressed_buffer + 1;
+ } else {
+ uLong dest_len = MAX_DECMPFS_BLOCK_SIZE;
+ int zr;
+
+ zr = uncompress((Bytef *)a->uncompressed_buffer,
+ &dest_len, a->compressed_buffer, data_size);
+ if (zr != Z_OK) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Failed to decompress resource fork");
+ return (ARCHIVE_WARN);
+ }
+ bytes_to_write = dest_len;
+ b = (unsigned char *)a->uncompressed_buffer;
+ }
+ do {
+ bytes_written = write(a->fd, b, bytes_to_write);
+ if (bytes_written < 0) {
+ archive_set_error(&a->archive, errno,
+ "Write failed");
+ return (ARCHIVE_WARN);
+ }
+ bytes_to_write -= bytes_written;
+ b += bytes_written;
+ } while (bytes_to_write > 0);
+ }
+ r = fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, 0);
+ if (r == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to remove resource fork");
+ return (ARCHIVE_WARN);
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
+hfs_drive_compressor(struct archive_write_disk *a, const char *buff,
+ size_t size)
+{
+ unsigned char *buffer_compressed;
+ size_t bytes_compressed;
+ size_t bytes_used;
+ int ret;
+
+ ret = hfs_reset_compressor(a);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+
+ if (a->compressed_buffer == NULL) {
+ size_t block_size;
+
+ block_size = COMPRESSED_W_SIZE + RSRC_F_SIZE +
+ + compressBound(MAX_DECMPFS_BLOCK_SIZE);
+ a->compressed_buffer = malloc(block_size);
+ if (a->compressed_buffer == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for Resource Fork");
+ return (ARCHIVE_FATAL);
+ }
+ a->compressed_buffer_size = block_size;
+ a->compressed_buffer_remaining = block_size;
+ }
+
+ buffer_compressed = a->compressed_buffer +
+ a->compressed_buffer_size - a->compressed_buffer_remaining;
+ a->stream.next_in = (Bytef *)(uintptr_t)(const void *)buff;
+ a->stream.avail_in = size;
+ a->stream.next_out = buffer_compressed;
+ a->stream.avail_out = a->compressed_buffer_remaining;
+ do {
+ ret = deflate(&a->stream, Z_FINISH);
+ switch (ret) {
+ case Z_OK:
+ case Z_STREAM_END:
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Failed to compress data");
+ return (ARCHIVE_FAILED);
+ }
+ } while (ret == Z_OK);
+ bytes_compressed = a->compressed_buffer_remaining - a->stream.avail_out;
+
+ /*
+ * If the compressed size is larger than the original size,
+ * throw away compressed data, use uncompressed data instead.
+ */
+ if (bytes_compressed > size) {
+ buffer_compressed[0] = 0xFF;/* uncompressed marker. */
+ memcpy(buffer_compressed + 1, buff, size);
+ bytes_compressed = size + 1;
+ }
+ a->compressed_buffer_remaining -= bytes_compressed;
+
+ /*
+ * If the compressed size is smaller than MAX_DECMPFS_XATTR_SIZE
+ * and the block count in the file is only one, store compressed
+ * data to decmpfs xattr instead of the resource fork.
+ */
+ if (a->decmpfs_block_count == 1 &&
+ (a->decmpfs_attr_size + bytes_compressed)
+ <= MAX_DECMPFS_XATTR_SIZE) {
+ archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE],
+ CMP_XATTR);
+ memcpy(a->decmpfs_header_p + DECMPFS_HEADER_SIZE,
+ buffer_compressed, bytes_compressed);
+ a->decmpfs_attr_size += bytes_compressed;
+ a->compressed_buffer_remaining = a->compressed_buffer_size;
+ /*
+ * Finish HFS+ Compression.
+ * - Write the decmpfs xattr.
+ * - Set the UF_COMPRESSED file flag.
+ */
+ ret = hfs_write_decmpfs(a);
+ if (ret == ARCHIVE_OK)
+ ret = hfs_set_compressed_fflag(a);
+ return (ret);
+ }
+
+ /* Update block info. */
+ archive_le32enc(a->decmpfs_block_info++,
+ a->compressed_rsrc_position_v - RSRC_H_SIZE);
+ archive_le32enc(a->decmpfs_block_info++, bytes_compressed);
+ a->compressed_rsrc_position_v += bytes_compressed;
+
+ /*
+ * Write the compressed data to the resource fork.
+ */
+ bytes_used = a->compressed_buffer_size - a->compressed_buffer_remaining;
+ while (bytes_used >= COMPRESSED_W_SIZE) {
+ ret = hfs_write_compressed_data(a, COMPRESSED_W_SIZE);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+ bytes_used -= COMPRESSED_W_SIZE;
+ if (bytes_used > COMPRESSED_W_SIZE)
+ memmove(a->compressed_buffer,
+ a->compressed_buffer + COMPRESSED_W_SIZE,
+ bytes_used);
+ else
+ memcpy(a->compressed_buffer,
+ a->compressed_buffer + COMPRESSED_W_SIZE,
+ bytes_used);
+ }
+ a->compressed_buffer_remaining = a->compressed_buffer_size - bytes_used;
+
+ /*
+ * If the current block is the last block, write the remaining
+ * compressed data and the resource fork footer.
+ */
+ if (a->file_remaining_bytes == 0) {
+ size_t rsrc_size;
+ int64_t bk;
+
+ /* Append the resource footer. */
+ rsrc_size = hfs_set_resource_fork_footer(
+ a->compressed_buffer + bytes_used,
+ a->compressed_buffer_remaining);
+ ret = hfs_write_compressed_data(a, bytes_used + rsrc_size);
+ a->compressed_buffer_remaining = a->compressed_buffer_size;
+
+ /* If the compressed size is not enough smaller than
+ * the uncompressed size. cancel HFS+ compression.
+ * TODO: study a behavior of ditto utility and improve
+ * the condition to fall back into no HFS+ compression. */
+ bk = HFS_BLOCKS(a->compressed_rsrc_position);
+ bk += bk >> 7;
+ if (bk > HFS_BLOCKS(a->filesize))
+ return hfs_decompress(a);
+ /*
+ * Write the resourcefork header.
+ */
+ if (ret == ARCHIVE_OK)
+ ret = hfs_write_resource_fork_header(a);
+ /*
+ * Finish HFS+ Compression.
+ * - Write the decmpfs xattr.
+ * - Set the UF_COMPRESSED file flag.
+ */
+ if (ret == ARCHIVE_OK)
+ ret = hfs_write_decmpfs(a);
+ if (ret == ARCHIVE_OK)
+ ret = hfs_set_compressed_fflag(a);
+ }
+ return (ret);
+}
+
+static ssize_t
+hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff,
+ size_t size)
+{
+ const char *buffer_to_write;
+ size_t bytes_to_write;
+ int ret;
+
+ if (a->decmpfs_block_count == (unsigned)-1) {
+ void *new_block;
+ size_t new_size;
+ unsigned int block_count;
+
+ if (a->decmpfs_header_p == NULL) {
+ new_block = malloc(MAX_DECMPFS_XATTR_SIZE
+ + sizeof(uint32_t));
+ if (new_block == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for decmpfs");
+ return (ARCHIVE_FATAL);
+ }
+ a->decmpfs_header_p = new_block;
+ }
+ a->decmpfs_attr_size = DECMPFS_HEADER_SIZE;
+ archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_MAGIC],
+ DECMPFS_MAGIC);
+ archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE],
+ CMP_RESOURCE_FORK);
+ archive_le64enc(&a->decmpfs_header_p[DECMPFS_UNCOMPRESSED_SIZE],
+ a->filesize);
+
+ /* Calculate a block count of the file. */
+ block_count =
+ (a->filesize + MAX_DECMPFS_BLOCK_SIZE -1) /
+ MAX_DECMPFS_BLOCK_SIZE;
+ /*
+ * Allocate buffer for resource fork.
+ * Set up related pointers;
+ */
+ new_size =
+ RSRC_H_SIZE + /* header */
+ 4 + /* Block count */
+ (block_count * sizeof(uint32_t) * 2) +
+ RSRC_F_SIZE; /* footer */
+ if (new_size > a->resource_fork_allocated_size) {
+ new_block = realloc(a->resource_fork, new_size);
+ if (new_block == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for ResourceFork");
+ return (ARCHIVE_FATAL);
+ }
+ a->resource_fork_allocated_size = new_size;
+ a->resource_fork = new_block;
+ }
+
+ /* Allocate uncompressed buffer */
+ if (a->uncompressed_buffer == NULL) {
+ new_block = malloc(MAX_DECMPFS_BLOCK_SIZE);
+ if (new_block == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for decmpfs");
+ return (ARCHIVE_FATAL);
+ }
+ a->uncompressed_buffer = new_block;
+ }
+ a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE;
+ a->file_remaining_bytes = a->filesize;
+ a->compressed_buffer_remaining = a->compressed_buffer_size;
+
+ /*
+ * Set up a resource fork.
+ */
+ a->rsrc_xattr_options = XATTR_CREATE;
+ /* Get the position where we are going to set a bunch
+ * of block info. */
+ a->decmpfs_block_info =
+ (uint32_t *)(a->resource_fork + RSRC_H_SIZE);
+ /* Set the block count to the resource fork. */
+ archive_le32enc(a->decmpfs_block_info++, block_count);
+ /* Get the position where we are going to set compressed
+ * data. */
+ a->compressed_rsrc_position =
+ RSRC_H_SIZE + 4 + (block_count * 8);
+ a->compressed_rsrc_position_v = a->compressed_rsrc_position;
+ a->decmpfs_block_count = block_count;
+ }
+
+ /* Ignore redundant bytes. */
+ if (a->file_remaining_bytes == 0)
+ return ((ssize_t)size);
+
+ /* Do not overrun a block size. */
+ if (size > a->block_remaining_bytes)
+ bytes_to_write = a->block_remaining_bytes;
+ else
+ bytes_to_write = size;
+ /* Do not overrun the file size. */
+ if (bytes_to_write > a->file_remaining_bytes)
+ bytes_to_write = a->file_remaining_bytes;
+
+ /* For efficiency, if a copy length is full of the uncompressed
+ * buffer size, do not copy writing data to it. */
+ if (bytes_to_write == MAX_DECMPFS_BLOCK_SIZE)
+ buffer_to_write = buff;
+ else {
+ memcpy(a->uncompressed_buffer +
+ MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes,
+ buff, bytes_to_write);
+ buffer_to_write = a->uncompressed_buffer;
+ }
+ a->block_remaining_bytes -= bytes_to_write;
+ a->file_remaining_bytes -= bytes_to_write;
+
+ if (a->block_remaining_bytes == 0 || a->file_remaining_bytes == 0) {
+ ret = hfs_drive_compressor(a, buffer_to_write,
+ MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes);
+ if (ret < 0)
+ return (ret);
+ a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE;
+ }
+ /* Ignore redundant bytes. */
+ if (a->file_remaining_bytes == 0)
+ return ((ssize_t)size);
+ return (bytes_to_write);
+}
+
+static ssize_t
+hfs_write_data_block(struct archive_write_disk *a, const char *buff,
+ size_t size)
+{
+ uint64_t start_size = size;
+ ssize_t bytes_written = 0;
+ ssize_t bytes_to_write;
+
+ if (size == 0)
+ return (ARCHIVE_OK);
+
+ if (a->filesize == 0 || a->fd < 0) {
+ archive_set_error(&a->archive, 0,
+ "Attempt to write to an empty file");
+ return (ARCHIVE_WARN);
+ }
+
+ /* If this write would run beyond the file size, truncate it. */
+ if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize)
+ start_size = size = (size_t)(a->filesize - a->offset);
+
+ /* Write the data. */
+ while (size > 0) {
+ bytes_to_write = size;
+ /* Seek if necessary to the specified offset. */
+ if (a->offset < a->fd_offset) {
+ /* Can't support backward move. */
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Seek failed");
+ return (ARCHIVE_FATAL);
+ } else if (a->offset > a->fd_offset) {
+ int64_t skip = a->offset - a->fd_offset;
+ char nullblock[1024];
+
+ memset(nullblock, 0, sizeof(nullblock));
+ while (skip > 0) {
+ if (skip > (int64_t)sizeof(nullblock))
+ bytes_written = hfs_write_decmpfs_block(
+ a, nullblock, sizeof(nullblock));
+ else
+ bytes_written = hfs_write_decmpfs_block(
+ a, nullblock, skip);
+ if (bytes_written < 0) {
+ archive_set_error(&a->archive, errno,
+ "Write failed");
+ return (ARCHIVE_WARN);
+ }
+ skip -= bytes_written;
+ }
+
+ a->fd_offset = a->offset;
+ }
+ bytes_written =
+ hfs_write_decmpfs_block(a, buff, bytes_to_write);
+ if (bytes_written < 0)
+ return (bytes_written);
+ buff += bytes_written;
+ size -= bytes_written;
+ a->total_bytes_written += bytes_written;
+ a->offset += bytes_written;
+ a->fd_offset = a->offset;
+ }
+ return (start_size - size);
+}
+#else
+static ssize_t
+hfs_write_data_block(struct archive_write_disk *a, const char *buff,
+ size_t size)
+{
+ return (write_data_block(a, buff, size));
+}
+#endif
+
+static ssize_t
+_archive_write_disk_data_block(struct archive *_a,
+ const void *buff, size_t size, int64_t offset)
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ ssize_t r;
+
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_DATA, "archive_write_data_block");
+
+ a->offset = offset;
+ if (a->todo & TODO_HFS_COMPRESSION)
+ r = hfs_write_data_block(a, buff, size);
+ else
+ r = write_data_block(a, buff, size);
+ if (r < ARCHIVE_OK)
+ return (r);
+ if ((size_t)r < size) {
+ archive_set_error(&a->archive, 0,
+ "Too much data: Truncating file at %ju bytes",
+ (uintmax_t)a->filesize);
+ return (ARCHIVE_WARN);
+ }
+#if ARCHIVE_VERSION_NUMBER < 3999000
+ return (ARCHIVE_OK);
+#else
+ return (size);
+#endif
+}
+
+static ssize_t
+_archive_write_disk_data(struct archive *_a, const void *buff, size_t size)
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_DATA, "archive_write_data");
+
+ if (a->todo & TODO_HFS_COMPRESSION)
+ return (hfs_write_data_block(a, buff, size));
+ return (write_data_block(a, buff, size));
+}
+
+static int
+_archive_write_disk_finish_entry(struct archive *_a)
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ int ret = ARCHIVE_OK;
+
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
+ "archive_write_finish_entry");
+ if (a->archive.state & ARCHIVE_STATE_HEADER)
+ return (ARCHIVE_OK);
+ archive_clear_error(&a->archive);
+
+ /* Pad or truncate file to the right size. */
+ if (a->fd < 0) {
+ /* There's no file. */
+ } else if (a->filesize < 0) {
+ /* File size is unknown, so we can't set the size. */
+ } else if (a->fd_offset == a->filesize) {
+ /* Last write ended at exactly the filesize; we're done. */
+ /* Hopefully, this is the common case. */
+#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H)
+ } else if (a->todo & TODO_HFS_COMPRESSION) {
+ char null_d[1024];
+ ssize_t r;
+
+ if (a->file_remaining_bytes)
+ memset(null_d, 0, sizeof(null_d));
+ while (a->file_remaining_bytes) {
+ if (a->file_remaining_bytes > sizeof(null_d))
+ r = hfs_write_data_block(
+ a, null_d, sizeof(null_d));
+ else
+ r = hfs_write_data_block(
+ a, null_d, a->file_remaining_bytes);
+ if (r < 0)
+ return ((int)r);
+ }
+#endif
+ } else {
+#if HAVE_FTRUNCATE
+ if (ftruncate(a->fd, a->filesize) == -1 &&
+ a->filesize == 0) {
+ archive_set_error(&a->archive, errno,
+ "File size could not be restored");
+ return (ARCHIVE_FAILED);
+ }
+#endif
+ /*
+ * Not all platforms implement the XSI option to
+ * extend files via ftruncate. Stat() the file again
+ * to see what happened.
+ */
+ a->pst = NULL;
+ if ((ret = lazy_stat(a)) != ARCHIVE_OK)
+ return (ret);
+ /* We can use lseek()/write() to extend the file if
+ * ftruncate didn't work or isn't available. */
+ if (a->st.st_size < a->filesize) {
+ const char nul = '\0';
+ if (lseek(a->fd, a->filesize - 1, SEEK_SET) < 0) {
+ archive_set_error(&a->archive, errno,
+ "Seek failed");
+ return (ARCHIVE_FATAL);
+ }
+ if (write(a->fd, &nul, 1) < 0) {
+ archive_set_error(&a->archive, errno,
+ "Write to restore size failed");
+ return (ARCHIVE_FATAL);
+ }
+ a->pst = NULL;
+ }
+ }
+
+ /* Restore metadata. */
+
+ /*
+ * This is specific to Mac OS X.
+ * If the current file is an AppleDouble file, it should be
+ * linked with the data fork file and remove it.
+ */
+ if (a->todo & TODO_APPLEDOUBLE) {
+ int r2 = fixup_appledouble(a, a->name);
+ if (r2 == ARCHIVE_EOF) {
+ /* The current file has been successfully linked
+ * with the data fork file and removed. So there
+ * is nothing to do on the current file. */
+ goto finish_metadata;
+ }
+ if (r2 < ret) ret = r2;
+ }
+
+ /*
+ * Look up the "real" UID only if we're going to need it.
+ * TODO: the TODO_SGID condition can be dropped here, can't it?
+ */
+ if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) {
+ a->uid = archive_write_disk_uid(&a->archive,
+ archive_entry_uname(a->entry),
+ archive_entry_uid(a->entry));
+ }
+ /* Look up the "real" GID only if we're going to need it. */
+ /* TODO: the TODO_SUID condition can be dropped here, can't it? */
+ if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) {
+ a->gid = archive_write_disk_gid(&a->archive,
+ archive_entry_gname(a->entry),
+ archive_entry_gid(a->entry));
+ }
+
+ /*
+ * Restore ownership before set_mode tries to restore suid/sgid
+ * bits. If we set the owner, we know what it is and can skip
+ * a stat() call to examine the ownership of the file on disk.
+ */
+ if (a->todo & TODO_OWNER) {
+ int r2 = set_ownership(a);
+ if (r2 < ret) ret = r2;
+ }
+
+ /*
+ * set_mode must precede ACLs on systems such as Solaris and
+ * FreeBSD where setting the mode implicitly clears extended ACLs
+ */
+ if (a->todo & TODO_MODE) {
+ int r2 = set_mode(a, a->mode);
+ if (r2 < ret) ret = r2;
+ }
+
+ /*
+ * Security-related extended attributes (such as
+ * security.capability on Linux) have to be restored last,
+ * since they're implicitly removed by other file changes.
+ */
+ if (a->todo & TODO_XATTR) {
+ int r2 = set_xattrs(a);
+ if (r2 < ret) ret = r2;
+ }
+
+ /*
+ * Some flags prevent file modification; they must be restored after
+ * file contents are written.
+ */
+ if (a->todo & TODO_FFLAGS) {
+ int r2 = set_fflags(a);
+ if (r2 < ret) ret = r2;
+ }
+
+ /*
+ * Time must follow most other metadata;
+ * otherwise atime will get changed.
+ */
+ if (a->todo & TODO_TIMES) {
+ int r2 = set_times_from_entry(a);
+ if (r2 < ret) ret = r2;
+ }
+
+ /*
+ * Mac extended metadata includes ACLs.
+ */
+ if (a->todo & TODO_MAC_METADATA) {
+ const void *metadata;
+ size_t metadata_size;
+ metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
+ if (metadata != NULL && metadata_size > 0) {
+ int r2 = set_mac_metadata(a, archive_entry_pathname(
+ a->entry), metadata, metadata_size);
+ if (r2 < ret) ret = r2;
+ }
+ }
+
+ /*
+ * ACLs must be restored after timestamps because there are
+ * ACLs that prevent attribute changes (including time).
+ */
+ if (a->todo & TODO_ACLS) {
+ int r2;
+#ifdef HAVE_DARWIN_ACL
+ /*
+ * On Mac OS, platform ACLs are stored also in mac_metadata by
+ * the operating system. If mac_metadata is present it takes
+ * precedence and we skip extracting libarchive NFSv4 ACLs
+ */
+ const void *metadata;
+ size_t metadata_size;
+ metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
- if (metadata == NULL || metadata_size == 0) {
++ if ((a->todo & TODO_MAC_METADATA) == 0 ||
++ metadata == NULL || metadata_size == 0) {
+#endif
+ r2 = archive_write_disk_set_acls(&a->archive, a->fd,
+ archive_entry_pathname(a->entry),
+ archive_entry_acl(a->entry));
+ if (r2 < ret) ret = r2;
+#ifdef HAVE_DARWIN_ACL
+ }
+#endif
+ }
+
+finish_metadata:
+ /* If there's an fd, we can close it now. */
+ if (a->fd >= 0) {
+ close(a->fd);
+ a->fd = -1;
+ }
+ /* If there's an entry, we can release it now. */
+ if (a->entry) {
+ archive_entry_free(a->entry);
+ a->entry = NULL;
+ }
+ a->archive.state = ARCHIVE_STATE_HEADER;
+ return (ret);
+}
+
+int
+archive_write_disk_set_group_lookup(struct archive *_a,
+ void *private_data,
+ int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid),
+ void (*cleanup_gid)(void *private))
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup");
+
+ if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL)
+ (a->cleanup_gid)(a->lookup_gid_data);
+
+ a->lookup_gid = lookup_gid;
+ a->cleanup_gid = cleanup_gid;
+ a->lookup_gid_data = private_data;
+ return (ARCHIVE_OK);
+}
+
+int
+archive_write_disk_set_user_lookup(struct archive *_a,
+ void *private_data,
+ int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid),
+ void (*cleanup_uid)(void *private))
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup");
+
+ if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL)
+ (a->cleanup_uid)(a->lookup_uid_data);
+
+ a->lookup_uid = lookup_uid;
+ a->cleanup_uid = cleanup_uid;
+ a->lookup_uid_data = private_data;
+ return (ARCHIVE_OK);
+}
+
+int64_t
+archive_write_disk_gid(struct archive *_a, const char *name, int64_t id)
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_ANY, "archive_write_disk_gid");
+ if (a->lookup_gid)
+ return (a->lookup_gid)(a->lookup_gid_data, name, id);
+ return (id);
+}
+
+int64_t
+archive_write_disk_uid(struct archive *_a, const char *name, int64_t id)
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_ANY, "archive_write_disk_uid");
+ if (a->lookup_uid)
+ return (a->lookup_uid)(a->lookup_uid_data, name, id);
+ return (id);
+}
+
+/*
+ * Create a new archive_write_disk object and initialize it with global state.
+ */
+struct archive *
+archive_write_disk_new(void)
+{
+ struct archive_write_disk *a;
+
+ a = (struct archive_write_disk *)calloc(1, sizeof(*a));
+ if (a == NULL)
+ return (NULL);
+ a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
+ /* We're ready to write a header immediately. */
+ a->archive.state = ARCHIVE_STATE_HEADER;
+ a->archive.vtable = archive_write_disk_vtable();
+ a->start_time = time(NULL);
+ /* Query and restore the umask. */
+ umask(a->user_umask = umask(0));
+#ifdef HAVE_GETEUID
+ a->user_uid = geteuid();
+#endif /* HAVE_GETEUID */
+ if (archive_string_ensure(&a->path_safe, 512) == NULL) {
+ free(a);
+ return (NULL);
+ }
+#ifdef HAVE_ZLIB_H
+ a->decmpfs_compression_level = 5;
+#endif
+ return (&a->archive);
+}
+
+
+/*
+ * If pathname is longer than PATH_MAX, chdir to a suitable
+ * intermediate dir and edit the path down to a shorter suffix. Note
+ * that this routine never returns an error; if the chdir() attempt
+ * fails for any reason, we just go ahead with the long pathname. The
+ * object creation is likely to fail, but any error will get handled
+ * at that time.
+ */
+#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
+static void
+edit_deep_directories(struct archive_write_disk *a)
+{
+ int ret;
+ char *tail = a->name;
+
+ /* If path is short, avoid the open() below. */
+ if (strlen(tail) < PATH_MAX)
+ return;
+
+ /* Try to record our starting dir. */
+ a->restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(a->restore_pwd);
+ if (a->restore_pwd < 0)
+ return;
+
+ /* As long as the path is too long... */
+ while (strlen(tail) >= PATH_MAX) {
+ /* Locate a dir prefix shorter than PATH_MAX. */
+ tail += PATH_MAX - 8;
+ while (tail > a->name && *tail != '/')
+ tail--;
+ /* Exit if we find a too-long path component. */
+ if (tail <= a->name)
+ return;
+ /* Create the intermediate dir and chdir to it. */
+ *tail = '\0'; /* Terminate dir portion */
+ ret = create_dir(a, a->name);
+ if (ret == ARCHIVE_OK && chdir(a->name) != 0)
+ ret = ARCHIVE_FAILED;
+ *tail = '/'; /* Restore the / we removed. */
+ if (ret != ARCHIVE_OK)
+ return;
+ tail++;
+ /* The chdir() succeeded; we've now shortened the path. */
+ a->name = tail;
+ }
+ return;
+}
+#endif
+
+/*
+ * The main restore function.
+ */
+static int
+restore_entry(struct archive_write_disk *a)
+{
+ int ret = ARCHIVE_OK, en;
+
+ if (a->flags & ARCHIVE_EXTRACT_UNLINK && !S_ISDIR(a->mode)) {
+ /*
+ * TODO: Fix this. Apparently, there are platforms
+ * that still allow root to hose the entire filesystem
+ * by unlinking a dir. The S_ISDIR() test above
+ * prevents us from using unlink() here if the new
+ * object is a dir, but that doesn't mean the old
+ * object isn't a dir.
+ */
+ if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
+ (void)clear_nochange_fflags(a);
+ if (unlink(a->name) == 0) {
+ /* We removed it, reset cached stat. */
+ a->pst = NULL;
+ } else if (errno == ENOENT) {
+ /* File didn't exist, that's just as good. */
+ } else if (rmdir(a->name) == 0) {
+ /* It was a dir, but now it's gone. */
+ a->pst = NULL;
+ } else {
+ /* We tried, but couldn't get rid of it. */
+ archive_set_error(&a->archive, errno,
+ "Could not unlink");
+ return(ARCHIVE_FAILED);
+ }
+ }
+
+ /* Try creating it first; if this fails, we'll try to recover. */
+ en = create_filesystem_object(a);
+
+ if ((en == ENOTDIR || en == ENOENT)
+ && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) {
+ /* If the parent dir doesn't exist, try creating it. */
+ create_parent_dir(a, a->name);
+ /* Now try to create the object again. */
+ en = create_filesystem_object(a);
+ }
+
+ if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) {
+ archive_set_error(&a->archive, en,
+ "Hard-link target '%s' does not exist.",
+ archive_entry_hardlink(a->entry));
+ return (ARCHIVE_FAILED);
+ }
+
+ if ((en == EISDIR || en == EEXIST)
+ && (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
+ /* If we're not overwriting, we're done. */
+ archive_entry_unset_size(a->entry);
+ return (ARCHIVE_OK);
+ }
+
+ /*
+ * Some platforms return EISDIR if you call
+ * open(O_WRONLY | O_EXCL | O_CREAT) on a directory, some
+ * return EEXIST. POSIX is ambiguous, requiring EISDIR
+ * for open(O_WRONLY) on a dir and EEXIST for open(O_EXCL | O_CREAT)
+ * on an existing item.
+ */
+ if (en == EISDIR) {
+ /* A dir is in the way of a non-dir, rmdir it. */
+ if (rmdir(a->name) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't remove already-existing dir");
+ return (ARCHIVE_FAILED);
+ }
+ a->pst = NULL;
+ /* Try again. */
+ en = create_filesystem_object(a);
+ } else if (en == EEXIST) {
+ /*
+ * We know something is in the way, but we don't know what;
+ * we need to find out before we go any further.
+ */
+ int r = 0;
+ /*
+ * The SECURE_SYMLINKS logic has already removed a
+ * symlink to a dir if the client wants that. So
+ * follow the symlink if we're creating a dir.
+ */
+ if (S_ISDIR(a->mode))
+ r = stat(a->name, &a->st);
+ /*
+ * If it's not a dir (or it's a broken symlink),
+ * then don't follow it.
+ */
+ if (r != 0 || !S_ISDIR(a->mode))
+ r = lstat(a->name, &a->st);
+ if (r != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't stat existing object");
+ return (ARCHIVE_FAILED);
+ }
+
+ /*
+ * NO_OVERWRITE_NEWER doesn't apply to directories.
+ */
+ if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER)
+ && !S_ISDIR(a->st.st_mode)) {
+ if (!older(&(a->st), a->entry)) {
+ archive_entry_unset_size(a->entry);
+ return (ARCHIVE_OK);
+ }
+ }
+
+ /* If it's our archive, we're done. */
+ if (a->skip_file_set &&
+ a->st.st_dev == (dev_t)a->skip_file_dev &&
+ a->st.st_ino == (ino_t)a->skip_file_ino) {
+ archive_set_error(&a->archive, 0,
+ "Refusing to overwrite archive");
+ return (ARCHIVE_FAILED);
+ }
+
+ if (!S_ISDIR(a->st.st_mode)) {
+ /* A non-dir is in the way, unlink it. */
+ if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
+ (void)clear_nochange_fflags(a);
+ if (unlink(a->name) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't unlink already-existing object");
+ return (ARCHIVE_FAILED);
+ }
+ a->pst = NULL;
+ /* Try again. */
+ en = create_filesystem_object(a);
+ } else if (!S_ISDIR(a->mode)) {
+ /* A dir is in the way of a non-dir, rmdir it. */
+ if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
+ (void)clear_nochange_fflags(a);
+ if (rmdir(a->name) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't replace existing directory with non-directory");
+ return (ARCHIVE_FAILED);
+ }
+ /* Try again. */
+ en = create_filesystem_object(a);
+ } else {
+ /*
+ * There's a dir in the way of a dir. Don't
+ * waste time with rmdir()/mkdir(), just fix
+ * up the permissions on the existing dir.
+ * Note that we don't change perms on existing
+ * dirs unless _EXTRACT_PERM is specified.
+ */
+ if ((a->mode != a->st.st_mode)
+ && (a->todo & TODO_MODE_FORCE))
+ a->deferred |= (a->todo & TODO_MODE);
+ /* Ownership doesn't need deferred fixup. */
+ en = 0; /* Forget the EEXIST. */
+ }
+ }
+
+ if (en) {
+ /* Everything failed; give up here. */
+ if ((&a->archive)->error == NULL)
+ archive_set_error(&a->archive, en, "Can't create '%s'",
+ a->name);
+ return (ARCHIVE_FAILED);
+ }
+
+ a->pst = NULL; /* Cached stat data no longer valid. */
+ return (ret);
+}
+
+/*
+ * Returns 0 if creation succeeds, or else returns errno value from
+ * the failed system call. Note: This function should only ever perform
+ * a single system call.
+ */
+static int
+create_filesystem_object(struct archive_write_disk *a)
+{
+ /* Create the entry. */
+ const char *linkname;
+ mode_t final_mode, mode;
+ int r;
+ /* these for check_symlinks_fsobj */
+ char *linkname_copy; /* non-const copy of linkname */
+ struct stat st;
+ struct archive_string error_string;
+ int error_number;
+
+ /* We identify hard/symlinks according to the link names. */
+ /* Since link(2) and symlink(2) don't handle modes, we're done here. */
+ linkname = archive_entry_hardlink(a->entry);
+ if (linkname != NULL) {
+#if !HAVE_LINK
+ return (EPERM);
+#else
+ archive_string_init(&error_string);
+ linkname_copy = strdup(linkname);
+ if (linkname_copy == NULL) {
+ return (EPERM);
+ }
+ /*
+ * TODO: consider using the cleaned-up path as the link
+ * target?
+ */
+ r = cleanup_pathname_fsobj(linkname_copy, &error_number,
+ &error_string, a->flags);
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ free(linkname_copy);
+ archive_string_free(&error_string);
+ /*
+ * EPERM is more appropriate than error_number for our
+ * callers
+ */
+ return (EPERM);
+ }
+ r = check_symlinks_fsobj(linkname_copy, &error_number,
+ &error_string, a->flags);
+ if (r != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ free(linkname_copy);
+ archive_string_free(&error_string);
+ /*
+ * EPERM is more appropriate than error_number for our
+ * callers
+ */
+ return (EPERM);
+ }
+ free(linkname_copy);
+ archive_string_free(&error_string);
+ r = link(linkname, a->name) ? errno : 0;
+ /*
+ * New cpio and pax formats allow hardlink entries
+ * to carry data, so we may have to open the file
+ * for hardlink entries.
+ *
+ * If the hardlink was successfully created and
+ * the archive doesn't have carry data for it,
+ * consider it to be non-authoritative for meta data.
+ * This is consistent with GNU tar and BSD pax.
+ * If the hardlink does carry data, let the last
+ * archive entry decide ownership.
+ */
+ if (r == 0 && a->filesize <= 0) {
+ a->todo = 0;
+ a->deferred = 0;
+ } else if (r == 0 && a->filesize > 0) {
+#ifdef HAVE_LSTAT
+ r = lstat(a->name, &st);
+#else
+ r = stat(a->name, &st);
+#endif
+ if (r != 0)
+ r = errno;
+ else if ((st.st_mode & AE_IFMT) == AE_IFREG) {
+ a->fd = open(a->name, O_WRONLY | O_TRUNC |
+ O_BINARY | O_CLOEXEC | O_NOFOLLOW);
+ __archive_ensure_cloexec_flag(a->fd);
+ if (a->fd < 0)
+ r = errno;
+ }
+ }
+ return (r);
+#endif
+ }
+ linkname = archive_entry_symlink(a->entry);
+ if (linkname != NULL) {
+#if HAVE_SYMLINK
+ return symlink(linkname, a->name) ? errno : 0;
+#else
+ return (EPERM);
+#endif
+ }
+
+ /*
+ * The remaining system calls all set permissions, so let's
+ * try to take advantage of that to avoid an extra chmod()
+ * call. (Recall that umask is set to zero right now!)
+ */
+
+ /* Mode we want for the final restored object (w/o file type bits). */
+ final_mode = a->mode & 07777;
+ /*
+ * The mode that will actually be restored in this step. Note
+ * that SUID, SGID, etc, require additional work to ensure
+ * security, so we never restore them at this point.
+ */
+ mode = final_mode & 0777 & ~a->user_umask;
+
+ switch (a->mode & AE_IFMT) {
+ default:
+ /* POSIX requires that we fall through here. */
+ /* FALLTHROUGH */
+ case AE_IFREG:
+ a->fd = open(a->name,
+ O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, mode);
+ __archive_ensure_cloexec_flag(a->fd);
+ r = (a->fd < 0);
+ break;
+ case AE_IFCHR:
+#ifdef HAVE_MKNOD
+ /* Note: we use AE_IFCHR for the case label, and
+ * S_IFCHR for the mknod() call. This is correct. */
+ r = mknod(a->name, mode | S_IFCHR,
+ archive_entry_rdev(a->entry));
+ break;
+#else
+ /* TODO: Find a better way to warn about our inability
+ * to restore a char device node. */
+ return (EINVAL);
+#endif /* HAVE_MKNOD */
+ case AE_IFBLK:
+#ifdef HAVE_MKNOD
+ r = mknod(a->name, mode | S_IFBLK,
+ archive_entry_rdev(a->entry));
+ break;
+#else
+ /* TODO: Find a better way to warn about our inability
+ * to restore a block device node. */
+ return (EINVAL);
+#endif /* HAVE_MKNOD */
+ case AE_IFDIR:
+ mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE;
+ r = mkdir(a->name, mode);
+ if (r == 0) {
+ /* Defer setting dir times. */
+ a->deferred |= (a->todo & TODO_TIMES);
+ a->todo &= ~TODO_TIMES;
+ /* Never use an immediate chmod(). */
+ /* We can't avoid the chmod() entirely if EXTRACT_PERM
+ * because of SysV SGID inheritance. */
+ if ((mode != final_mode)
+ || (a->flags & ARCHIVE_EXTRACT_PERM))
+ a->deferred |= (a->todo & TODO_MODE);
+ a->todo &= ~TODO_MODE;
+ }
+ break;
+ case AE_IFIFO:
+#ifdef HAVE_MKFIFO
+ r = mkfifo(a->name, mode);
+ break;
+#else
+ /* TODO: Find a better way to warn about our inability
+ * to restore a fifo. */
+ return (EINVAL);
+#endif /* HAVE_MKFIFO */
+ }
+
+ /* All the system calls above set errno on failure. */
+ if (r)
+ return (errno);
+
+ /* If we managed to set the final mode, we've avoided a chmod(). */
+ if (mode == final_mode)
+ a->todo &= ~TODO_MODE;
+ return (0);
+}
+
+/*
+ * Cleanup function for archive_extract. Mostly, this involves processing
+ * the fixup list, which is used to address a number of problems:
+ * * Dir permissions might prevent us from restoring a file in that
+ * dir, so we restore the dir with minimum 0700 permissions first,
+ * then correct the mode at the end.
+ * * Similarly, the act of restoring a file touches the directory
+ * and changes the timestamp on the dir, so we have to touch-up dir
+ * timestamps at the end as well.
+ * * Some file flags can interfere with the restore by, for example,
+ * preventing the creation of hardlinks to those files.
+ * * Mac OS extended metadata includes ACLs, so must be deferred on dirs.
+ *
+ * Note that tar/cpio do not require that archives be in a particular
+ * order; there is no way to know when the last file has been restored
+ * within a directory, so there's no way to optimize the memory usage
+ * here by fixing up the directory any earlier than the
+ * end-of-archive.
+ *
+ * XXX TODO: Directory ACLs should be restored here, for the same
+ * reason we set directory perms here. XXX
+ */
+static int
+_archive_write_disk_close(struct archive *_a)
+{
+ struct archive_write_disk *a = (struct archive_write_disk *)_a;
+ struct fixup_entry *next, *p;
+ int ret;
+
+ archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
+ "archive_write_disk_close");
+ ret = _archive_write_disk_finish_entry(&a->archive);
+
+ /* Sort dir list so directories are fixed up in depth-first order. */
+ p = sort_dir_list(a->fixup_list);
+
+ while (p != NULL) {
+ a->pst = NULL; /* Mark stat cache as out-of-date. */
+ if (p->fixup & TODO_TIMES) {
+ set_times(a, -1, p->mode, p->name,
+ p->atime, p->atime_nanos,
+ p->birthtime, p->birthtime_nanos,
+ p->mtime, p->mtime_nanos,
+ p->ctime, p->ctime_nanos);
+ }
+ if (p->fixup & TODO_MODE_BASE)
+ chmod(p->name, p->mode);
+ if (p->fixup & TODO_ACLS)
+#ifdef HAVE_DARWIN_ACL
- if (p->mac_metadata == NULL ||
++ if ((p->fixup & TODO_MAC_METADATA) == 0 ||
++ p->mac_metadata == NULL ||
+ p->mac_metadata_size == 0)
+#endif
+ archive_write_disk_set_acls(&a->archive,
+ -1, p->name, &p->acl);
+ if (p->fixup & TODO_FFLAGS)
+ set_fflags_platform(a, -1, p->name,
+ p->mode, p->fflags_set, 0);
+ if (p->fixup & TODO_MAC_METADATA)
+ set_mac_metadata(a, p->name, p->mac_metadata,
+ p->mac_metadata_size);
+ next = p->next;
+ archive_acl_clear(&p->acl);
+ free(p->mac_metadata);
+ free(p->name);
+ free(p);
+ p = next;
+ }
+ a->fixup_list = NULL;
+ return (ret);
+}
+
+static int
+_archive_write_disk_free(struct archive *_a)
+{
+ struct archive_write_disk *a;
+ int ret;
+ if (_a == NULL)
+ return (ARCHIVE_OK);
+ archive_check_magic(_a, ARCHIVE_WRITE_DISK_MAGIC,
+ ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free");
+ a = (struct archive_write_disk *)_a;
+ ret = _archive_write_disk_close(&a->archive);
+ archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL);
+ archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL);
+ if (a->entry)
+ archive_entry_free(a->entry);
+ archive_string_free(&a->_name_data);
+ archive_string_free(&a->archive.error_string);
+ archive_string_free(&a->path_safe);
+ a->archive.magic = 0;
+ __archive_clean(&a->archive);
+ free(a->decmpfs_header_p);
+ free(a->resource_fork);
+ free(a->compressed_buffer);
+ free(a->uncompressed_buffer);
+#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\
+ && defined(HAVE_ZLIB_H)
+ if (a->stream_valid) {
+ switch (deflateEnd(&a->stream)) {
+ case Z_OK:
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Failed to clean up compressor");
+ ret = ARCHIVE_FATAL;
+ break;
+ }
+ }
+#endif
+ free(a);
+ return (ret);
+}
+
+/*
+ * Simple O(n log n) merge sort to order the fixup list. In
+ * particular, we want to restore dir timestamps depth-first.
+ */
+static struct fixup_entry *
+sort_dir_list(struct fixup_entry *p)
+{
+ struct fixup_entry *a, *b, *t;
+
+ if (p == NULL)
+ return (NULL);
+ /* A one-item list is already sorted. */
+ if (p->next == NULL)
+ return (p);
+
+ /* Step 1: split the list. */
+ t = p;
+ a = p->next->next;
+ while (a != NULL) {
+ /* Step a twice, t once. */
+ a = a->next;
+ if (a != NULL)
+ a = a->next;
+ t = t->next;
+ }
+ /* Now, t is at the mid-point, so break the list here. */
+ b = t->next;
+ t->next = NULL;
+ a = p;
+
+ /* Step 2: Recursively sort the two sub-lists. */
+ a = sort_dir_list(a);
+ b = sort_dir_list(b);
+
+ /* Step 3: Merge the returned lists. */
+ /* Pick the first element for the merged list. */
+ if (strcmp(a->name, b->name) > 0) {
+ t = p = a;
+ a = a->next;
+ } else {
+ t = p = b;
+ b = b->next;
+ }
+
+ /* Always put the later element on the list first. */
+ while (a != NULL && b != NULL) {
+ if (strcmp(a->name, b->name) > 0) {
+ t->next = a;
+ a = a->next;
+ } else {
+ t->next = b;
+ b = b->next;
+ }
+ t = t->next;
+ }
+
+ /* Only one list is non-empty, so just splice it on. */
+ if (a != NULL)
+ t->next = a;
+ if (b != NULL)
+ t->next = b;
+
+ return (p);
+}
+
+/*
+ * Returns a new, initialized fixup entry.
+ *
+ * TODO: Reduce the memory requirements for this list by using a tree
+ * structure rather than a simple list of names.
+ */
+static struct fixup_entry *
+new_fixup(struct archive_write_disk *a, const char *pathname)
+{
+ struct fixup_entry *fe;
+
+ fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry));
+ if (fe == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for a fixup");
+ return (NULL);
+ }
+ fe->next = a->fixup_list;
+ a->fixup_list = fe;
+ fe->fixup = 0;
+ fe->name = strdup(pathname);
+ return (fe);
+}
+
+/*
+ * Returns a fixup structure for the current entry.
+ */
+static struct fixup_entry *
+current_fixup(struct archive_write_disk *a, const char *pathname)
+{
+ if (a->current_fixup == NULL)
+ a->current_fixup = new_fixup(a, pathname);
+ return (a->current_fixup);
+}
+
+/* Error helper for new *_fsobj functions */
+static void
+fsobj_error(int *a_eno, struct archive_string *a_estr,
+ int err, const char *errstr, const char *path)
+{
+ if (a_eno)
+ *a_eno = err;
+ if (a_estr)
+ archive_string_sprintf(a_estr, errstr, path);
+}
+
+/*
+ * TODO: Someday, integrate this with the deep dir support; they both
+ * scan the path and both can be optimized by comparing against other
+ * recent paths.
+ */
+/* TODO: Extend this to support symlinks on Windows Vista and later. */
+
+/*
+ * Checks the given path to see if any elements along it are symlinks. Returns
+ * ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
+ */
+static int
+check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
+ int flags)
+{
+#if !defined(HAVE_LSTAT)
+ /* Platform doesn't have lstat, so we can't look for symlinks. */
+ (void)path; /* UNUSED */
+ (void)error_number; /* UNUSED */
+ (void)error_string; /* UNUSED */
+ (void)flags; /* UNUSED */
+ return (ARCHIVE_OK);
+#else
+ int res = ARCHIVE_OK;
+ char *tail;
+ char *head;
+ int last;
+ char c;
+ int r;
+ struct stat st;
+ int restore_pwd;
+
+ /* Nothing to do here if name is empty */
+ if(path[0] == '\0')
+ return (ARCHIVE_OK);
+
+ /*
+ * Guard against symlink tricks. Reject any archive entry whose
+ * destination would be altered by a symlink.
+ *
+ * Walk the filename in chunks separated by '/'. For each segment:
+ * - if it doesn't exist, continue
+ * - if it's symlink, abort or remove it
+ * - if it's a directory and it's not the last chunk, cd into it
+ * As we go:
+ * head points to the current (relative) path
+ * tail points to the temporary \0 terminating the segment we're
+ * currently examining
+ * c holds what used to be in *tail
+ * last is 1 if this is the last tail
+ */
+ restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(restore_pwd);
+ if (restore_pwd < 0)
+ return (ARCHIVE_FATAL);
+ head = path;
+ tail = path;
+ last = 0;
+ /* TODO: reintroduce a safe cache here? */
+ /* Skip the root directory if the path is absolute. */
+ if(tail == path && tail[0] == '/')
+ ++tail;
+ /* Keep going until we've checked the entire name.
+ * head, tail, path all alias the same string, which is
+ * temporarily zeroed at tail, so be careful restoring the
+ * stashed (c=tail[0]) for error messages.
+ * Exiting the loop with break is okay; continue is not.
+ */
+ while (!last) {
+ /*
+ * Skip the separator we just consumed, plus any adjacent ones
+ */
+ while (*tail == '/')
+ ++tail;
+ /* Skip the next path element. */
+ while (*tail != '\0' && *tail != '/')
+ ++tail;
+ /* is this the last path component? */
+ last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0');
+ /* temporarily truncate the string here */
+ c = tail[0];
+ tail[0] = '\0';
+ /* Check that we haven't hit a symlink. */
+ r = lstat(head, &st);
+ if (r != 0) {
+ tail[0] = c;
+ /* We've hit a dir that doesn't exist; stop now. */
+ if (errno == ENOENT) {
+ break;
+ } else {
+ /*
+ * Treat any other error as fatal - best to be
+ * paranoid here.
+ * Note: This effectively disables deep
+ * directory support when security checks are
+ * enabled. Otherwise, very long pathnames that
+ * trigger an error here could evade the
+ * sandbox.
+ * TODO: We could do better, but it would
+ * probably require merging the symlink checks
+ * with the deep-directory editing.
+ */
+ fsobj_error(a_eno, a_estr, errno,
+ "Could not stat %s", path);
+ res = ARCHIVE_FAILED;
+ break;
+ }
+ } else if (S_ISDIR(st.st_mode)) {
+ if (!last) {
+ if (chdir(head) != 0) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, errno,
+ "Could not chdir %s", path);
+ res = (ARCHIVE_FATAL);
+ break;
+ }
+ /* Our view is now from inside this dir: */
+ head = tail + 1;
+ }
+ } else if (S_ISLNK(st.st_mode)) {
+ if (last) {
+ /*
+ * Last element is symlink; remove it
+ * so we can overwrite it with the
+ * item being extracted.
+ */
+ if (unlink(head)) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, errno,
+ "Could not remove symlink %s",
+ path);
+ res = ARCHIVE_FAILED;
+ break;
+ }
+ /*
+ * Even if we did remove it, a warning
+ * is in order. The warning is silly,
+ * though, if we're just replacing one
+ * symlink with another symlink.
+ */
+ tail[0] = c;
+ /*
+ * FIXME: not sure how important this is to
+ * restore
+ */
+ /*
+ if (!S_ISLNK(path)) {
+ fsobj_error(a_eno, a_estr, 0,
+ "Removing symlink %s", path);
+ }
+ */
+ /* Symlink gone. No more problem! */
+ res = ARCHIVE_OK;
+ break;
+ } else if (flags & ARCHIVE_EXTRACT_UNLINK) {
+ /* User asked us to remove problems. */
+ if (unlink(head) != 0) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, 0,
+ "Cannot remove intervening "
+ "symlink %s", path);
+ res = ARCHIVE_FAILED;
+ break;
+ }
+ tail[0] = c;
+ } else if ((flags &
+ ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) {
+ /*
+ * We are not the last element and we want to
+ * follow symlinks if they are a directory.
+ *
+ * This is needed to extract hardlinks over
+ * symlinks.
+ */
+ r = stat(head, &st);
+ if (r != 0) {
+ tail[0] = c;
+ if (errno == ENOENT) {
+ break;
+ } else {
+ fsobj_error(a_eno, a_estr,
+ errno,
+ "Could not stat %s", path);
+ res = (ARCHIVE_FAILED);
+ break;
+ }
+ } else if (S_ISDIR(st.st_mode)) {
+ if (chdir(head) != 0) {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr,
+ errno,
+ "Could not chdir %s", path);
+ res = (ARCHIVE_FATAL);
+ break;
+ }
+ /*
+ * Our view is now from inside
+ * this dir:
+ */
+ head = tail + 1;
+ } else {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, 0,
+ "Cannot extract through "
+ "symlink %s", path);
+ res = ARCHIVE_FAILED;
+ break;
+ }
+ } else {
+ tail[0] = c;
+ fsobj_error(a_eno, a_estr, 0,
+ "Cannot extract through symlink %s", path);
+ res = ARCHIVE_FAILED;
+ break;
+ }
+ }
+ /* be sure to always maintain this */
+ tail[0] = c;
+ if (tail[0] != '\0')
+ tail++; /* Advance to the next segment. */
+ }
+ /* Catches loop exits via break */
+ tail[0] = c;
+#ifdef HAVE_FCHDIR
+ /* If we changed directory above, restore it here. */
+ if (restore_pwd >= 0) {
+ r = fchdir(restore_pwd);
+ if (r != 0) {
+ fsobj_error(a_eno, a_estr, errno,
+ "chdir() failure", "");
+ }
+ close(restore_pwd);
+ restore_pwd = -1;
+ if (r != 0) {
+ res = (ARCHIVE_FATAL);
+ }
+ }
+#endif
+ /* TODO: reintroduce a safe cache here? */
+ return res;
+#endif
+}
+
+/*
+ * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise
+ * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED}
+ */
+static int
+check_symlinks(struct archive_write_disk *a)
+{
+ struct archive_string error_string;
+ int error_number;
+ int rc;
+ archive_string_init(&error_string);
+ rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
+ a->flags);
+ if (rc != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ }
+ archive_string_free(&error_string);
+ a->pst = NULL; /* to be safe */
+ return rc;
+}
+
+
+#if defined(__CYGWIN__)
+/*
+ * 1. Convert a path separator from '\' to '/' .
+ * We shouldn't check multibyte character directly because some
+ * character-set have been using the '\' character for a part of
+ * its multibyte character code.
+ * 2. Replace unusable characters in Windows with underscore('_').
+ * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx
+ */
+static void
+cleanup_pathname_win(char *path)
+{
+ wchar_t wc;
+ char *p;
+ size_t alen, l;
+ int mb, complete, utf8;
+
+ alen = 0;
+ mb = 0;
+ complete = 1;
+ utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0;
+ for (p = path; *p != '\0'; p++) {
+ ++alen;
+ if (*p == '\\') {
+ /* If previous byte is smaller than 128,
+ * this is not second byte of multibyte characters,
+ * so we can replace '\' with '/'. */
+ if (utf8 || !mb)
+ *p = '/';
+ else
+ complete = 0;/* uncompleted. */
+ } else if (*(unsigned char *)p > 127)
+ mb = 1;
+ else
+ mb = 0;
+ /* Rewrite the path name if its next character is unusable. */
+ if (*p == ':' || *p == '*' || *p == '?' || *p == '"' ||
+ *p == '<' || *p == '>' || *p == '|')
+ *p = '_';
+ }
+ if (complete)
+ return;
+
+ /*
+ * Convert path separator in wide-character.
+ */
+ p = path;
+ while (*p != '\0' && alen) {
+ l = mbtowc(&wc, p, alen);
+ if (l == (size_t)-1) {
+ while (*p != '\0') {
+ if (*p == '\\')
+ *p = '/';
+ ++p;
+ }
+ break;
+ }
+ if (l == 1 && wc == L'\\')
+ *p = '/';
+ p += l;
+ alen -= l;
+ }
+}
+#endif
+
+/*
+ * Canonicalize the pathname. In particular, this strips duplicate
+ * '/' characters, '.' elements, and trailing '/'. It also raises an
+ * error for an empty path, a trailing '..', (if _SECURE_NODOTDOT is
+ * set) any '..' in the path or (if ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
+ * is set) if the path is absolute.
+ */
+static int
+cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
+ int flags)
+{
+ char *dest, *src;
+ char separator = '\0';
+
+ dest = src = path;
+ if (*src == '\0') {
+ fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
+ "Invalid empty ", "pathname");
+ return (ARCHIVE_FAILED);
+ }
+
+#if defined(__CYGWIN__)
+ cleanup_pathname_win(path);
+#endif
+ /* Skip leading '/'. */
+ if (*src == '/') {
+ if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
+ fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
+ "Path is ", "absolute");
+ return (ARCHIVE_FAILED);
+ }
+
+ separator = *src++;
+ }
+
+ /* Scan the pathname one element at a time. */
+ for (;;) {
+ /* src points to first char after '/' */
+ if (src[0] == '\0') {
+ break;
+ } else if (src[0] == '/') {
+ /* Found '//', ignore second one. */
+ src++;
+ continue;
+ } else if (src[0] == '.') {
+ if (src[1] == '\0') {
+ /* Ignore trailing '.' */
+ break;
+ } else if (src[1] == '/') {
+ /* Skip './'. */
+ src += 2;
+ continue;
+ } else if (src[1] == '.') {
+ if (src[2] == '/' || src[2] == '\0') {
+ /* Conditionally warn about '..' */
+ if (flags
+ & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
+ fsobj_error(a_eno, a_estr,
+ ARCHIVE_ERRNO_MISC,
+ "Path contains ", "'..'");
+ return (ARCHIVE_FAILED);
+ }
+ }
+ /*
+ * Note: Under no circumstances do we
+ * remove '..' elements. In
+ * particular, restoring
+ * '/foo/../bar/' should create the
+ * 'foo' dir as a side-effect.
+ */
+ }
+ }
+
+ /* Copy current element, including leading '/'. */
+ if (separator)
+ *dest++ = '/';
+ while (*src != '\0' && *src != '/') {
+ *dest++ = *src++;
+ }
+
+ if (*src == '\0')
+ break;
+
+ /* Skip '/' separator. */
+ separator = *src++;
+ }
+ /*
+ * We've just copied zero or more path elements, not including the
+ * final '/'.
+ */
+ if (dest == path) {
+ /*
+ * Nothing got copied. The path must have been something
+ * like '.' or '/' or './' or '/././././/./'.
+ */
+ if (separator)
+ *dest++ = '/';
+ else
+ *dest++ = '.';
+ }
+ /* Terminate the result. */
+ *dest = '\0';
+ return (ARCHIVE_OK);
+}
+
+static int
+cleanup_pathname(struct archive_write_disk *a)
+{
+ struct archive_string error_string;
+ int error_number;
+ int rc;
+ archive_string_init(&error_string);
+ rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string,
+ a->flags);
+ if (rc != ARCHIVE_OK) {
+ archive_set_error(&a->archive, error_number, "%s",
+ error_string.s);
+ }
+ archive_string_free(&error_string);
+ return rc;
+}
+
+/*
+ * Create the parent directory of the specified path, assuming path
+ * is already in mutable storage.
+ */
+static int
+create_parent_dir(struct archive_write_disk *a, char *path)
+{
+ char *slash;
+ int r;
+
+ /* Remove tail element to obtain parent name. */
+ slash = strrchr(path, '/');
+ if (slash == NULL)
+ return (ARCHIVE_OK);
+ *slash = '\0';
+ r = create_dir(a, path);
+ *slash = '/';
+ return (r);
+}
+
+/*
+ * Create the specified dir, recursing to create parents as necessary.
+ *
+ * Returns ARCHIVE_OK if the path exists when we're done here.
+ * Otherwise, returns ARCHIVE_FAILED.
+ * Assumes path is in mutable storage; path is unchanged on exit.
+ */
+static int
+create_dir(struct archive_write_disk *a, char *path)
+{
+ struct stat st;
+ struct fixup_entry *le;
+ char *slash, *base;
+ mode_t mode_final, mode;
+ int r;
+
+ /* Check for special names and just skip them. */
+ slash = strrchr(path, '/');
+ if (slash == NULL)
+ base = path;
+ else
+ base = slash + 1;
+
+ if (base[0] == '\0' ||
+ (base[0] == '.' && base[1] == '\0') ||
+ (base[0] == '.' && base[1] == '.' && base[2] == '\0')) {
+ /* Don't bother trying to create null path, '.', or '..'. */
+ if (slash != NULL) {
+ *slash = '\0';
+ r = create_dir(a, path);
+ *slash = '/';
+ return (r);
+ }
+ return (ARCHIVE_OK);
+ }
+
+ /*
+ * Yes, this should be stat() and not lstat(). Using lstat()
+ * here loses the ability to extract through symlinks. Also note
+ * that this should not use the a->st cache.
+ */
+ if (stat(path, &st) == 0) {
+ if (S_ISDIR(st.st_mode))
+ return (ARCHIVE_OK);
+ if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
+ archive_set_error(&a->archive, EEXIST,
+ "Can't create directory '%s'", path);
+ return (ARCHIVE_FAILED);
+ }
+ if (unlink(path) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't create directory '%s': "
+ "Conflicting file cannot be removed",
+ path);
+ return (ARCHIVE_FAILED);
+ }
+ } else if (errno != ENOENT && errno != ENOTDIR) {
+ /* Stat failed? */
+ archive_set_error(&a->archive, errno,
+ "Can't test directory '%s'", path);
+ return (ARCHIVE_FAILED);
+ } else if (slash != NULL) {
+ *slash = '\0';
+ r = create_dir(a, path);
+ *slash = '/';
+ if (r != ARCHIVE_OK)
+ return (r);
+ }
+
+ /*
+ * Mode we want for the final restored directory. Per POSIX,
+ * implicitly-created dirs must be created obeying the umask.
+ * There's no mention whether this is different for privileged
+ * restores (which the rest of this code handles by pretending
+ * umask=0). I've chosen here to always obey the user's umask for
+ * implicit dirs, even if _EXTRACT_PERM was specified.
+ */
+ mode_final = DEFAULT_DIR_MODE & ~a->user_umask;
+ /* Mode we want on disk during the restore process. */
+ mode = mode_final;
+ mode |= MINIMUM_DIR_MODE;
+ mode &= MAXIMUM_DIR_MODE;
+ if (mkdir(path, mode) == 0) {
+ if (mode != mode_final) {
+ le = new_fixup(a, path);
+ if (le == NULL)
+ return (ARCHIVE_FATAL);
+ le->fixup |=TODO_MODE_BASE;
+ le->mode = mode_final;
+ }
+ return (ARCHIVE_OK);
+ }
+
+ /*
+ * Without the following check, a/b/../b/c/d fails at the
+ * second visit to 'b', so 'd' can't be created. Note that we
+ * don't add it to the fixup list here, as it's already been
+ * added.
+ */
+ if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
+ return (ARCHIVE_OK);
+
+ archive_set_error(&a->archive, errno, "Failed to create dir '%s'",
+ path);
+ return (ARCHIVE_FAILED);
+}
+
+/*
+ * Note: Although we can skip setting the user id if the desired user
+ * id matches the current user, we cannot skip setting the group, as
+ * many systems set the gid based on the containing directory. So
+ * we have to perform a chown syscall if we want to set the SGID
+ * bit. (The alternative is to stat() and then possibly chown(); it's
+ * more efficient to skip the stat() and just always chown().) Note
+ * that a successful chown() here clears the TODO_SGID_CHECK bit, which
+ * allows set_mode to skip the stat() check for the GID.
+ */
+static int
+set_ownership(struct archive_write_disk *a)
+{
+#ifndef __CYGWIN__
+/* unfortunately, on win32 there is no 'root' user with uid 0,
+ so we just have to try the chown and see if it works */
+
+ /* If we know we can't change it, don't bother trying. */
+ if (a->user_uid != 0 && a->user_uid != a->uid) {
+ archive_set_error(&a->archive, errno,
+ "Can't set UID=%jd", (intmax_t)a->uid);
+ return (ARCHIVE_WARN);
+ }
+#endif
+
+#ifdef HAVE_FCHOWN
+ /* If we have an fd, we can avoid a race. */
+ if (a->fd >= 0 && fchown(a->fd, a->uid, a->gid) == 0) {
+ /* We've set owner and know uid/gid are correct. */
+ a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
+ return (ARCHIVE_OK);
+ }
+#endif
+
+ /* We prefer lchown() but will use chown() if that's all we have. */
+ /* Of course, if we have neither, this will always fail. */
+#ifdef HAVE_LCHOWN
+ if (lchown(a->name, a->uid, a->gid) == 0) {
+ /* We've set owner and know uid/gid are correct. */
+ a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
+ return (ARCHIVE_OK);
+ }
+#elif HAVE_CHOWN
+ if (!S_ISLNK(a->mode) && chown(a->name, a->uid, a->gid) == 0) {
+ /* We've set owner and know uid/gid are correct. */
+ a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK);
+ return (ARCHIVE_OK);
+ }
+#endif
+
+ archive_set_error(&a->archive, errno,
+ "Can't set user=%jd/group=%jd for %s",
+ (intmax_t)a->uid, (intmax_t)a->gid, a->name);
+ return (ARCHIVE_WARN);
+}
+
+/*
+ * Note: Returns 0 on success, non-zero on failure.
+ */
+static int
+set_time(int fd, int mode, const char *name,
+ time_t atime, long atime_nsec,
+ time_t mtime, long mtime_nsec)
+{
+ /* Select the best implementation for this platform. */
+#if defined(HAVE_UTIMENSAT) && defined(HAVE_FUTIMENS)
+ /*
+ * utimensat() and futimens() are defined in
+ * POSIX.1-2008. They support ns resolution and setting times
+ * on fds and symlinks.
+ */
+ struct timespec ts[2];
+ (void)mode; /* UNUSED */
+ ts[0].tv_sec = atime;
+ ts[0].tv_nsec = atime_nsec;
+ ts[1].tv_sec = mtime;
+ ts[1].tv_nsec = mtime_nsec;
+ if (fd >= 0)
+ return futimens(fd, ts);
+ return utimensat(AT_FDCWD, name, ts, AT_SYMLINK_NOFOLLOW);
+
+#elif HAVE_UTIMES
+ /*
+ * The utimes()-family functions support µs-resolution and
+ * setting times fds and symlinks. utimes() is documented as
+ * LEGACY by POSIX, futimes() and lutimes() are not described
+ * in POSIX.
+ */
+ struct timeval times[2];
+
+ times[0].tv_sec = atime;
+ times[0].tv_usec = atime_nsec / 1000;
+ times[1].tv_sec = mtime;
+ times[1].tv_usec = mtime_nsec / 1000;
+
+#ifdef HAVE_FUTIMES
+ if (fd >= 0)
+ return (futimes(fd, times));
+#else
+ (void)fd; /* UNUSED */
+#endif
+#ifdef HAVE_LUTIMES
+ (void)mode; /* UNUSED */
+ return (lutimes(name, times));
+#else
+ if (S_ISLNK(mode))
+ return (0);
+ return (utimes(name, times));
+#endif
+
+#elif defined(HAVE_UTIME)
+ /*
+ * utime() is POSIX-standard but only supports 1s resolution and
+ * does not support fds or symlinks.
+ */
+ struct utimbuf times;
+ (void)fd; /* UNUSED */
+ (void)name; /* UNUSED */
+ (void)atime_nsec; /* UNUSED */
+ (void)mtime_nsec; /* UNUSED */
+ times.actime = atime;
+ times.modtime = mtime;
+ if (S_ISLNK(mode))
+ return (ARCHIVE_OK);
+ return (utime(name, ×));
+
+#else
+ /*
+ * We don't know how to set the time on this platform.
+ */
+ (void)fd; /* UNUSED */
+ (void)mode; /* UNUSED */
+ (void)name; /* UNUSED */
+ (void)atime_nsec; /* UNUSED */
+ (void)mtime_nsec; /* UNUSED */
+ return (ARCHIVE_WARN);
+#endif
+}
+
+#ifdef F_SETTIMES
+static int
+set_time_tru64(int fd, int mode, const char *name,
+ time_t atime, long atime_nsec,
+ time_t mtime, long mtime_nsec,
+ time_t ctime, long ctime_nsec)
+{
+ struct attr_timbuf tstamp;
+ tstamp.atime.tv_sec = atime;
+ tstamp.mtime.tv_sec = mtime;
+ tstamp.ctime.tv_sec = ctime;
+#if defined (__hpux) && defined (__ia64)
+ tstamp.atime.tv_nsec = atime_nsec;
+ tstamp.mtime.tv_nsec = mtime_nsec;
+ tstamp.ctime.tv_nsec = ctime_nsec;
+#else
+ tstamp.atime.tv_usec = atime_nsec / 1000;
+ tstamp.mtime.tv_usec = mtime_nsec / 1000;
+ tstamp.ctime.tv_usec = ctime_nsec / 1000;
+#endif
+ return (fcntl(fd,F_SETTIMES,&tstamp));
+}
+#endif /* F_SETTIMES */
+
+static int
+set_times(struct archive_write_disk *a,
+ int fd, int mode, const char *name,
+ time_t atime, long atime_nanos,
+ time_t birthtime, long birthtime_nanos,
+ time_t mtime, long mtime_nanos,
+ time_t cctime, long ctime_nanos)
+{
+ /* Note: set_time doesn't use libarchive return conventions!
+ * It uses syscall conventions. So 0 here instead of ARCHIVE_OK. */
+ int r1 = 0, r2 = 0;
+
+#ifdef F_SETTIMES
+ /*
+ * on Tru64 try own fcntl first which can restore even the
+ * ctime, fall back to default code path below if it fails
+ * or if we are not running as root
+ */
+ if (a->user_uid == 0 &&
+ set_time_tru64(fd, mode, name,
+ atime, atime_nanos, mtime,
+ mtime_nanos, cctime, ctime_nanos) == 0) {
+ return (ARCHIVE_OK);
+ }
+#else /* Tru64 */
+ (void)cctime; /* UNUSED */
+ (void)ctime_nanos; /* UNUSED */
+#endif /* Tru64 */
+
+#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
+ /*
+ * If you have struct stat.st_birthtime, we assume BSD
+ * birthtime semantics, in which {f,l,}utimes() updates
+ * birthtime to earliest mtime. So we set the time twice,
+ * first using the birthtime, then using the mtime. If
+ * birthtime == mtime, this isn't necessary, so we skip it.
+ * If birthtime > mtime, then this won't work, so we skip it.
+ */
+ if (birthtime < mtime
+ || (birthtime == mtime && birthtime_nanos < mtime_nanos))
+ r1 = set_time(fd, mode, name,
+ atime, atime_nanos,
+ birthtime, birthtime_nanos);
+#else
+ (void)birthtime; /* UNUSED */
+ (void)birthtime_nanos; /* UNUSED */
+#endif
+ r2 = set_time(fd, mode, name,
+ atime, atime_nanos,
+ mtime, mtime_nanos);
+ if (r1 != 0 || r2 != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't restore time");
+ return (ARCHIVE_WARN);
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
+set_times_from_entry(struct archive_write_disk *a)
+{
+ time_t atime, birthtime, mtime, cctime;
+ long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec;
+
+ /* Suitable defaults. */
+ atime = birthtime = mtime = cctime = a->start_time;
+ atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0;
+
+ /* If no time was provided, we're done. */
+ if (!archive_entry_atime_is_set(a->entry)
+#if HAVE_STRUCT_STAT_ST_BIRTHTIME
+ && !archive_entry_birthtime_is_set(a->entry)
+#endif
+ && !archive_entry_mtime_is_set(a->entry))
+ return (ARCHIVE_OK);
+
+ if (archive_entry_atime_is_set(a->entry)) {
+ atime = archive_entry_atime(a->entry);
+ atime_nsec = archive_entry_atime_nsec(a->entry);
+ }
+ if (archive_entry_birthtime_is_set(a->entry)) {
+ birthtime = archive_entry_birthtime(a->entry);
+ birthtime_nsec = archive_entry_birthtime_nsec(a->entry);
+ }
+ if (archive_entry_mtime_is_set(a->entry)) {
+ mtime = archive_entry_mtime(a->entry);
+ mtime_nsec = archive_entry_mtime_nsec(a->entry);
+ }
+ if (archive_entry_ctime_is_set(a->entry)) {
+ cctime = archive_entry_ctime(a->entry);
+ ctime_nsec = archive_entry_ctime_nsec(a->entry);
+ }
+
+ return set_times(a, a->fd, a->mode, a->name,
+ atime, atime_nsec,
+ birthtime, birthtime_nsec,
+ mtime, mtime_nsec,
+ cctime, ctime_nsec);
+}
+
+static int
+set_mode(struct archive_write_disk *a, int mode)
+{
+ int r = ARCHIVE_OK;
+ mode &= 07777; /* Strip off file type bits. */
+
+ if (a->todo & TODO_SGID_CHECK) {
+ /*
+ * If we don't know the GID is right, we must stat()
+ * to verify it. We can't just check the GID of this
+ * process, since systems sometimes set GID from
+ * the enclosing dir or based on ACLs.
+ */
+ if ((r = lazy_stat(a)) != ARCHIVE_OK)
+ return (r);
+ if (a->pst->st_gid != a->gid) {
+ mode &= ~ S_ISGID;
+ if (a->flags & ARCHIVE_EXTRACT_OWNER) {
+ /*
+ * This is only an error if you
+ * requested owner restore. If you
+ * didn't, we'll try to restore
+ * sgid/suid, but won't consider it a
+ * problem if we can't.
+ */
+ archive_set_error(&a->archive, -1,
+ "Can't restore SGID bit");
+ r = ARCHIVE_WARN;
+ }
+ }
+ /* While we're here, double-check the UID. */
+ if (a->pst->st_uid != a->uid
+ && (a->todo & TODO_SUID)) {
+ mode &= ~ S_ISUID;
+ if (a->flags & ARCHIVE_EXTRACT_OWNER) {
+ archive_set_error(&a->archive, -1,
+ "Can't restore SUID bit");
+ r = ARCHIVE_WARN;
+ }
+ }
+ a->todo &= ~TODO_SGID_CHECK;
+ a->todo &= ~TODO_SUID_CHECK;
+ } else if (a->todo & TODO_SUID_CHECK) {
+ /*
+ * If we don't know the UID is right, we can just check
+ * the user, since all systems set the file UID from
+ * the process UID.
+ */
+ if (a->user_uid != a->uid) {
+ mode &= ~ S_ISUID;
+ if (a->flags & ARCHIVE_EXTRACT_OWNER) {
+ archive_set_error(&a->archive, -1,
+ "Can't make file SUID");
+ r = ARCHIVE_WARN;
+ }
+ }
+ a->todo &= ~TODO_SUID_CHECK;
+ }
+
+ if (S_ISLNK(a->mode)) {
+#ifdef HAVE_LCHMOD
+ /*
+ * If this is a symlink, use lchmod(). If the
+ * platform doesn't support lchmod(), just skip it. A
+ * platform that doesn't provide a way to set
+ * permissions on symlinks probably ignores
+ * permissions on symlinks, so a failure here has no
+ * impact.
+ */
+ if (lchmod(a->name, mode) != 0) {
+ switch (errno) {
+ case ENOTSUP:
+ case ENOSYS:
+#if ENOTSUP != EOPNOTSUPP
+ case EOPNOTSUPP:
+#endif
+ /*
+ * if lchmod is defined but the platform
+ * doesn't support it, silently ignore
+ * error
+ */
+ break;
+ default:
+ archive_set_error(&a->archive, errno,
+ "Can't set permissions to 0%o", (int)mode);
+ r = ARCHIVE_WARN;
+ }
+ }
+#endif
+ } else if (!S_ISDIR(a->mode)) {
+ /*
+ * If it's not a symlink and not a dir, then use
+ * fchmod() or chmod(), depending on whether we have
+ * an fd. Dirs get their perms set during the
+ * post-extract fixup, which is handled elsewhere.
+ */
+#ifdef HAVE_FCHMOD
+ if (a->fd >= 0) {
+ if (fchmod(a->fd, mode) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't set permissions to 0%o", (int)mode);
+ r = ARCHIVE_WARN;
+ }
+ } else
+#endif
+ /* If this platform lacks fchmod(), then
+ * we'll just use chmod(). */
+ if (chmod(a->name, mode) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't set permissions to 0%o", (int)mode);
+ r = ARCHIVE_WARN;
+ }
+ }
+ return (r);
+}
+
+static int
+set_fflags(struct archive_write_disk *a)
+{
+ struct fixup_entry *le;
+ unsigned long set, clear;
+ int r;
+ int critical_flags;
+ mode_t mode = archive_entry_mode(a->entry);
+
+ /*
+ * Make 'critical_flags' hold all file flags that can't be
+ * immediately restored. For example, on BSD systems,
+ * SF_IMMUTABLE prevents hardlinks from being created, so
+ * should not be set until after any hardlinks are created. To
+ * preserve some semblance of portability, this uses #ifdef
+ * extensively. Ugly, but it works.
+ *
+ * Yes, Virginia, this does create a security race. It's mitigated
+ * somewhat by the practice of creating dirs 0700 until the extract
+ * is done, but it would be nice if we could do more than that.
+ * People restoring critical file systems should be wary of
+ * other programs that might try to muck with files as they're
+ * being restored.
+ */
+ /* Hopefully, the compiler will optimize this mess into a constant. */
+ critical_flags = 0;
+#ifdef SF_IMMUTABLE
+ critical_flags |= SF_IMMUTABLE;
+#endif
+#ifdef UF_IMMUTABLE
+ critical_flags |= UF_IMMUTABLE;
+#endif
+#ifdef SF_APPEND
+ critical_flags |= SF_APPEND;
+#endif
+#ifdef UF_APPEND
+ critical_flags |= UF_APPEND;
+#endif
- #ifdef EXT2_APPEND_FL
++#if defined(FS_APPEND_FL)
++ critical_flags |= FS_APPEND_FL;
++#elif defined(EXT2_APPEND_FL)
+ critical_flags |= EXT2_APPEND_FL;
+#endif
- #ifdef EXT2_IMMUTABLE_FL
++#if defined(FS_IMMUTABLE_FL)
++ critical_flags |= FS_IMMUTABLE_FL;
++#elif defined(EXT2_IMMUTABLE_FL)
+ critical_flags |= EXT2_IMMUTABLE_FL;
+#endif
++#ifdef FS_JOURNAL_DATA_FL
++ critical_flags |= FS_JOURNAL_DATA_FL;
++#endif
+
+ if (a->todo & TODO_FFLAGS) {
+ archive_entry_fflags(a->entry, &set, &clear);
+
+ /*
+ * The first test encourages the compiler to eliminate
+ * all of this if it's not necessary.
+ */
+ if ((critical_flags != 0) && (set & critical_flags)) {
+ le = current_fixup(a, a->name);
+ if (le == NULL)
+ return (ARCHIVE_FATAL);
+ le->fixup |= TODO_FFLAGS;
+ le->fflags_set = set;
+ /* Store the mode if it's not already there. */
+ if ((le->fixup & TODO_MODE) == 0)
+ le->mode = mode;
+ } else {
+ r = set_fflags_platform(a, a->fd,
+ a->name, mode, set, clear);
+ if (r != ARCHIVE_OK)
+ return (r);
+ }
+ }
+ return (ARCHIVE_OK);
+}
+
+static int
+clear_nochange_fflags(struct archive_write_disk *a)
+{
+ int nochange_flags;
+ mode_t mode = archive_entry_mode(a->entry);
+
+ /* Hopefully, the compiler will optimize this mess into a constant. */
+ nochange_flags = 0;
+#ifdef SF_IMMUTABLE
+ nochange_flags |= SF_IMMUTABLE;
+#endif
+#ifdef UF_IMMUTABLE
+ nochange_flags |= UF_IMMUTABLE;
+#endif
+#ifdef SF_APPEND
+ nochange_flags |= SF_APPEND;
+#endif
+#ifdef UF_APPEND
+ nochange_flags |= UF_APPEND;
+#endif
+#ifdef EXT2_APPEND_FL
+ nochange_flags |= EXT2_APPEND_FL;
+#endif
+#ifdef EXT2_IMMUTABLE_FL
+ nochange_flags |= EXT2_IMMUTABLE_FL;
+#endif
+
+ return (set_fflags_platform(a, a->fd, a->name, mode, 0,
+ nochange_flags));
+}
+
+
+#if ( defined(HAVE_LCHFLAGS) || defined(HAVE_CHFLAGS) || defined(HAVE_FCHFLAGS) ) && defined(HAVE_STRUCT_STAT_ST_FLAGS)
+/*
+ * BSD reads flags using stat() and sets them with one of {f,l,}chflags()
+ */
+static int
+set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
+ mode_t mode, unsigned long set, unsigned long clear)
+{
+ int r;
+
+ (void)mode; /* UNUSED */
+ if (set == 0 && clear == 0)
+ return (ARCHIVE_OK);
+
+ /*
+ * XXX Is the stat here really necessary? Or can I just use
+ * the 'set' flags directly? In particular, I'm not sure
+ * about the correct approach if we're overwriting an existing
+ * file that already has flags on it. XXX
+ */
+ if ((r = lazy_stat(a)) != ARCHIVE_OK)
+ return (r);
+
+ a->st.st_flags &= ~clear;
+ a->st.st_flags |= set;
+#ifdef HAVE_FCHFLAGS
+ /* If platform has fchflags() and we were given an fd, use it. */
+ if (fd >= 0 && fchflags(fd, a->st.st_flags) == 0)
+ return (ARCHIVE_OK);
+#endif
+ /*
+ * If we can't use the fd to set the flags, we'll use the
+ * pathname to set flags. We prefer lchflags() but will use
+ * chflags() if we must.
+ */
+#ifdef HAVE_LCHFLAGS
+ if (lchflags(name, a->st.st_flags) == 0)
+ return (ARCHIVE_OK);
+#elif defined(HAVE_CHFLAGS)
+ if (S_ISLNK(a->st.st_mode)) {
+ archive_set_error(&a->archive, errno,
+ "Can't set file flags on symlink.");
+ return (ARCHIVE_WARN);
+ }
+ if (chflags(name, a->st.st_flags) == 0)
+ return (ARCHIVE_OK);
+#endif
+ archive_set_error(&a->archive, errno,
+ "Failed to set file flags");
+ return (ARCHIVE_WARN);
+}
+
- #elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
++#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \
++ defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
++ (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \
++ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
+/*
+ * Linux uses ioctl() to read and write file flags.
+ */
+static int
+set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
+ mode_t mode, unsigned long set, unsigned long clear)
+{
+ int ret;
+ int myfd = fd;
+ int newflags, oldflags;
+ int sf_mask = 0;
+
- if (set == 0 && clear == 0)
++ if (set == 0 && clear == 0)
+ return (ARCHIVE_OK);
+ /* Only regular files and dirs can have flags. */
+ if (!S_ISREG(mode) && !S_ISDIR(mode))
+ return (ARCHIVE_OK);
+
+ /* If we weren't given an fd, open it ourselves. */
+ if (myfd < 0) {
+ myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(myfd);
+ }
+ if (myfd < 0)
+ return (ARCHIVE_OK);
+
+ /*
+ * Linux has no define for the flags that are only settable by
+ * the root user. This code may seem a little complex, but
+ * there seem to be some Linux systems that lack these
+ * defines. (?) The code below degrades reasonably gracefully
+ * if sf_mask is incomplete.
+ */
- #ifdef EXT2_IMMUTABLE_FL
++#if defined(FS_IMMUTABLE_FL)
++ sf_mask |= FS_IMMUTABLE_FL;
++#elif defined(EXT2_IMMUTABLE_FL)
+ sf_mask |= EXT2_IMMUTABLE_FL;
+#endif
- #ifdef EXT2_APPEND_FL
++#if defined(FS_APPEND_FL)
++ sf_mask |= FS_APPEND_FL;
++#elif defined(EXT2_APPEND_FL)
+ sf_mask |= EXT2_APPEND_FL;
+#endif
++#if defined(FS_JOURNAL_DATA_FL)
++ sf_mask |= FS_JOURNAL_DATA_FL;
++#endif
+ /*
+ * XXX As above, this would be way simpler if we didn't have
+ * to read the current flags from disk. XXX
+ */
+ ret = ARCHIVE_OK;
+
+ /* Read the current file flags. */
- if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) < 0)
++ if (ioctl(myfd,
++#ifdef FS_IOC_GETFLAGS
++ FS_IOC_GETFLAGS,
++#else
++ EXT2_IOC_GETFLAGS,
++#endif
++ &oldflags) < 0)
+ goto fail;
+
+ /* Try setting the flags as given. */
+ newflags = (oldflags & ~clear) | set;
- if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
++ if (ioctl(myfd,
++#ifdef FS_IOC_SETFLAGS
++ FS_IOC_SETFLAGS,
++#else
++ EXT2_IOC_SETFLAGS,
++#endif
++ &newflags) >= 0)
+ goto cleanup;
+ if (errno != EPERM)
+ goto fail;
+
+ /* If we couldn't set all the flags, try again with a subset. */
+ newflags &= ~sf_mask;
+ oldflags &= sf_mask;
+ newflags |= oldflags;
- if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
++ if (ioctl(myfd,
++#ifdef FS_IOC_SETFLAGS
++ FS_IOC_SETFLAGS,
++#else
++ EXT2_IOC_SETFLAGS,
++#endif
++ &newflags) >= 0)
+ goto cleanup;
+
+ /* We couldn't set the flags, so report the failure. */
+fail:
+ archive_set_error(&a->archive, errno,
+ "Failed to set file flags");
+ ret = ARCHIVE_WARN;
+cleanup:
+ if (fd < 0)
+ close(myfd);
+ return (ret);
+}
+
+#else
+
+/*
+ * Of course, some systems have neither BSD chflags() nor Linux' flags
+ * support through ioctl().
+ */
+static int
+set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
+ mode_t mode, unsigned long set, unsigned long clear)
+{
+ (void)a; /* UNUSED */
+ (void)fd; /* UNUSED */
+ (void)name; /* UNUSED */
+ (void)mode; /* UNUSED */
+ (void)set; /* UNUSED */
+ (void)clear; /* UNUSED */
+ return (ARCHIVE_OK);
+}
+
+#endif /* __linux */
+
+#ifndef HAVE_COPYFILE_H
+/* Default is to simply drop Mac extended metadata. */
+static int
+set_mac_metadata(struct archive_write_disk *a, const char *pathname,
+ const void *metadata, size_t metadata_size)
+{
+ (void)a; /* UNUSED */
+ (void)pathname; /* UNUSED */
+ (void)metadata; /* UNUSED */
+ (void)metadata_size; /* UNUSED */
+ return (ARCHIVE_OK);
+}
+
+static int
+fixup_appledouble(struct archive_write_disk *a, const char *pathname)
+{
+ (void)a; /* UNUSED */
+ (void)pathname; /* UNUSED */
+ return (ARCHIVE_OK);
+}
+#else
+
+/*
+ * On Mac OS, we use copyfile() to unpack the metadata and
+ * apply it to the target file.
+ */
+
+#if defined(HAVE_SYS_XATTR_H)
+static int
+copy_xattrs(struct archive_write_disk *a, int tmpfd, int dffd)
+{
+ ssize_t xattr_size;
+ char *xattr_names = NULL, *xattr_val = NULL;
+ int ret = ARCHIVE_OK, xattr_i;
+
+ xattr_size = flistxattr(tmpfd, NULL, 0, 0);
+ if (xattr_size == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to read metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ goto exit_xattr;
+ }
+ xattr_names = malloc(xattr_size);
+ if (xattr_names == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate memory for metadata(xattr)");
+ ret = ARCHIVE_FATAL;
+ goto exit_xattr;
+ }
+ xattr_size = flistxattr(tmpfd, xattr_names, xattr_size, 0);
+ if (xattr_size == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to read metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ goto exit_xattr;
+ }
+ for (xattr_i = 0; xattr_i < xattr_size;
+ xattr_i += strlen(xattr_names + xattr_i) + 1) {
+ char *xattr_val_saved;
+ ssize_t s;
+ int f;
+
+ s = fgetxattr(tmpfd, xattr_names + xattr_i, NULL, 0, 0, 0);
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ goto exit_xattr;
+ }
+ xattr_val_saved = xattr_val;
+ xattr_val = realloc(xattr_val, s);
+ if (xattr_val == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Failed to get metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ free(xattr_val_saved);
+ goto exit_xattr;
+ }
+ s = fgetxattr(tmpfd, xattr_names + xattr_i, xattr_val, s, 0, 0);
+ if (s == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ goto exit_xattr;
+ }
+ f = fsetxattr(dffd, xattr_names + xattr_i, xattr_val, s, 0, 0);
+ if (f == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get metadata(xattr)");
+ ret = ARCHIVE_WARN;
+ goto exit_xattr;
+ }
+ }
+exit_xattr:
+ free(xattr_names);
+ free(xattr_val);
+ return (ret);
+}
+#endif
+
+static int
+copy_acls(struct archive_write_disk *a, int tmpfd, int dffd)
+{
+#ifndef HAVE_SYS_ACL_H
+ return 0;
+#else
+ acl_t acl, dfacl = NULL;
+ int acl_r, ret = ARCHIVE_OK;
+
+ acl = acl_get_fd(tmpfd);
+ if (acl == NULL) {
+ if (errno == ENOENT)
+ /* There are not any ACLs. */
+ return (ret);
+ archive_set_error(&a->archive, errno,
+ "Failed to get metadata(acl)");
+ ret = ARCHIVE_WARN;
+ goto exit_acl;
+ }
+ dfacl = acl_dup(acl);
+ acl_r = acl_set_fd(dffd, dfacl);
+ if (acl_r == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to get metadata(acl)");
+ ret = ARCHIVE_WARN;
+ goto exit_acl;
+ }
+exit_acl:
+ if (acl)
+ acl_free(acl);
+ if (dfacl)
+ acl_free(dfacl);
+ return (ret);
+#endif
+}
+
+static int
+create_tempdatafork(struct archive_write_disk *a, const char *pathname)
+{
+ struct archive_string tmpdatafork;
+ int tmpfd;
+
+ archive_string_init(&tmpdatafork);
+ archive_strcpy(&tmpdatafork, "tar.md.XXXXXX");
+ tmpfd = mkstemp(tmpdatafork.s);
+ if (tmpfd < 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to mkstemp");
+ archive_string_free(&tmpdatafork);
+ return (-1);
+ }
+ if (copyfile(pathname, tmpdatafork.s, 0,
+ COPYFILE_UNPACK | COPYFILE_NOFOLLOW
+ | COPYFILE_ACL | COPYFILE_XATTR) < 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to restore metadata");
+ close(tmpfd);
+ tmpfd = -1;
+ }
+ unlink(tmpdatafork.s);
+ archive_string_free(&tmpdatafork);
+ return (tmpfd);
+}
+
+static int
+copy_metadata(struct archive_write_disk *a, const char *metadata,
+ const char *datafork, int datafork_compressed)
+{
+ int ret = ARCHIVE_OK;
+
+ if (datafork_compressed) {
+ int dffd, tmpfd;
+
+ tmpfd = create_tempdatafork(a, metadata);
+ if (tmpfd == -1)
+ return (ARCHIVE_WARN);
+
+ /*
+ * Do not open the data fork compressed by HFS+ compression
+ * with at least a writing mode(O_RDWR or O_WRONLY). it
+ * makes the data fork uncompressed.
+ */
+ dffd = open(datafork, 0);
+ if (dffd == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to open the data fork for metadata");
+ close(tmpfd);
+ return (ARCHIVE_WARN);
+ }
+
+#if defined(HAVE_SYS_XATTR_H)
+ ret = copy_xattrs(a, tmpfd, dffd);
+ if (ret == ARCHIVE_OK)
+#endif
+ ret = copy_acls(a, tmpfd, dffd);
+ close(tmpfd);
+ close(dffd);
+ } else {
+ if (copyfile(metadata, datafork, 0,
+ COPYFILE_UNPACK | COPYFILE_NOFOLLOW
+ | COPYFILE_ACL | COPYFILE_XATTR) < 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to restore metadata");
+ ret = ARCHIVE_WARN;
+ }
+ }
+ return (ret);
+}
+
+static int
+set_mac_metadata(struct archive_write_disk *a, const char *pathname,
+ const void *metadata, size_t metadata_size)
+{
+ struct archive_string tmp;
+ ssize_t written;
+ int fd;
+ int ret = ARCHIVE_OK;
+
+ /* This would be simpler if copyfile() could just accept the
+ * metadata as a block of memory; then we could sidestep this
+ * silly dance of writing the data to disk just so that
+ * copyfile() can read it back in again. */
+ archive_string_init(&tmp);
+ archive_strcpy(&tmp, pathname);
+ archive_strcat(&tmp, ".XXXXXX");
+ fd = mkstemp(tmp.s);
+
+ if (fd < 0) {
+ archive_set_error(&a->archive, errno,
+ "Failed to restore metadata");
+ archive_string_free(&tmp);
+ return (ARCHIVE_WARN);
+ }
+ written = write(fd, metadata, metadata_size);
+ close(fd);
+ if ((size_t)written != metadata_size) {
+ archive_set_error(&a->archive, errno,
+ "Failed to restore metadata");
+ ret = ARCHIVE_WARN;
+ } else {
+ int compressed;
+
+#if defined(UF_COMPRESSED)
+ if ((a->todo & TODO_HFS_COMPRESSION) != 0 &&
+ (ret = lazy_stat(a)) == ARCHIVE_OK)
+ compressed = a->st.st_flags & UF_COMPRESSED;
+ else
+#endif
+ compressed = 0;
+ ret = copy_metadata(a, tmp.s, pathname, compressed);
+ }
+ unlink(tmp.s);
+ archive_string_free(&tmp);
+ return (ret);
+}
+
+static int
+fixup_appledouble(struct archive_write_disk *a, const char *pathname)
+{
+ char buff[8];
+ struct stat st;
+ const char *p;
+ struct archive_string datafork;
+ int fd = -1, ret = ARCHIVE_OK;
+
+ archive_string_init(&datafork);
+ /* Check if the current file name is a type of the resource
+ * fork file. */
+ p = strrchr(pathname, '/');
+ if (p == NULL)
+ p = pathname;
+ else
+ p++;
+ if (p[0] != '.' || p[1] != '_')
+ goto skip_appledouble;
+
+ /*
+ * Check if the data fork file exists.
+ *
+ * TODO: Check if this write disk object has handled it.
+ */
+ archive_strncpy(&datafork, pathname, p - pathname);
+ archive_strcat(&datafork, p + 2);
+ if (lstat(datafork.s, &st) == -1 ||
+ (st.st_mode & AE_IFMT) != AE_IFREG)
+ goto skip_appledouble;
+
+ /*
+ * Check if the file is in the AppleDouble form.
+ */
+ fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC);
+ __archive_ensure_cloexec_flag(fd);
+ if (fd == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to open a restoring file");
+ ret = ARCHIVE_WARN;
+ goto skip_appledouble;
+ }
+ if (read(fd, buff, 8) == -1) {
+ archive_set_error(&a->archive, errno,
+ "Failed to read a restoring file");
+ close(fd);
+ ret = ARCHIVE_WARN;
+ goto skip_appledouble;
+ }
+ close(fd);
+ /* Check AppleDouble Magic Code. */
+ if (archive_be32dec(buff) != 0x00051607)
+ goto skip_appledouble;
+ /* Check AppleDouble Version. */
+ if (archive_be32dec(buff+4) != 0x00020000)
+ goto skip_appledouble;
+
+ ret = copy_metadata(a, pathname, datafork.s,
+#if defined(UF_COMPRESSED)
+ st.st_flags & UF_COMPRESSED);
+#else
+ 0);
+#endif
+ if (ret == ARCHIVE_OK) {
+ unlink(pathname);
+ ret = ARCHIVE_EOF;
+ }
+skip_appledouble:
+ archive_string_free(&datafork);
+ return (ret);
+}
+#endif
+
+#if HAVE_LSETXATTR || HAVE_LSETEA
+/*
+ * Restore extended attributes - Linux and AIX implementations:
+ * AIX' ea interface is syntaxwise identical to the Linux xattr interface.
+ */
+static int
+set_xattrs(struct archive_write_disk *a)
+{
+ struct archive_entry *entry = a->entry;
+ static int warning_done = 0;
+ int ret = ARCHIVE_OK;
+ int i = archive_entry_xattr_reset(entry);
+
+ while (i--) {
+ const char *name;
+ const void *value;
+ size_t size;
+ archive_entry_xattr_next(entry, &name, &value, &size);
+ if (name != NULL &&
+ strncmp(name, "xfsroot.", 8) != 0 &&
+ strncmp(name, "system.", 7) != 0) {
+ int e;
+#if HAVE_FSETXATTR
+ if (a->fd >= 0)
+ e = fsetxattr(a->fd, name, value, size, 0);
+ else
+#elif HAVE_FSETEA
+ if (a->fd >= 0)
+ e = fsetea(a->fd, name, value, size, 0);
+ else
+#endif
+ {
+#if HAVE_LSETXATTR
+ e = lsetxattr(archive_entry_pathname(entry),
+ name, value, size, 0);
+#elif HAVE_LSETEA
+ e = lsetea(archive_entry_pathname(entry),
+ name, value, size, 0);
+#endif
+ }
+ if (e == -1) {
+ if (errno == ENOTSUP || errno == ENOSYS) {
+ if (!warning_done) {
+ warning_done = 1;
+ archive_set_error(&a->archive,
+ errno,
+ "Cannot restore extended "
+ "attributes on this file "
+ "system");
+ }
+ } else
+ archive_set_error(&a->archive, errno,
+ "Failed to set extended attribute");
+ ret = ARCHIVE_WARN;
+ }
+ } else {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Invalid extended attribute encountered");
+ ret = ARCHIVE_WARN;
+ }
+ }
+ return (ret);
+}
+#elif HAVE_EXTATTR_SET_FILE && HAVE_DECL_EXTATTR_NAMESPACE_USER
+/*
+ * Restore extended attributes - FreeBSD implementation
+ */
+static int
+set_xattrs(struct archive_write_disk *a)
+{
+ struct archive_entry *entry = a->entry;
+ static int warning_done = 0;
+ int ret = ARCHIVE_OK;
+ int i = archive_entry_xattr_reset(entry);
+
+ while (i--) {
+ const char *name;
+ const void *value;
+ size_t size;
+ archive_entry_xattr_next(entry, &name, &value, &size);
+ if (name != NULL) {
+ int e;
+ int namespace;
+
+ if (strncmp(name, "user.", 5) == 0) {
+ /* "user." attributes go to user namespace */
+ name += 5;
+ namespace = EXTATTR_NAMESPACE_USER;
+ } else {
+ /* Warn about other extended attributes. */
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Can't restore extended attribute ``%s''",
+ name);
+ ret = ARCHIVE_WARN;
+ continue;
+ }
+ errno = 0;
+#if HAVE_EXTATTR_SET_FD
+ if (a->fd >= 0)
+ e = extattr_set_fd(a->fd, namespace, name,
+ value, size);
+ else
+#endif
+ /* TODO: should we use extattr_set_link() instead? */
+ {
+ e = extattr_set_file(
+ archive_entry_pathname(entry), namespace,
+ name, value, size);
+ }
+ if (e != (int)size) {
+ if (errno == ENOTSUP || errno == ENOSYS) {
+ if (!warning_done) {
+ warning_done = 1;
+ archive_set_error(&a->archive,
+ errno,
+ "Cannot restore extended "
+ "attributes on this file "
+ "system");
+ }
+ } else {
+ archive_set_error(&a->archive, errno,
+ "Failed to set extended attribute");
+ }
+
+ ret = ARCHIVE_WARN;
+ }
+ }
+ }
+ return (ret);
+}
+#else
+/*
+ * Restore extended attributes - stub implementation for unsupported systems
+ */
+static int
+set_xattrs(struct archive_write_disk *a)
+{
+ static int warning_done = 0;
+
+ /* If there aren't any extended attributes, then it's okay not
+ * to extract them, otherwise, issue a single warning. */
+ if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) {
+ warning_done = 1;
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Cannot restore extended attributes on this system");
+ return (ARCHIVE_WARN);
+ }
+ /* Warning was already emitted; suppress further warnings. */
+ return (ARCHIVE_OK);
+}
+#endif
+
+/*
+ * Test if file on disk is older than entry.
+ */
+static int
+older(struct stat *st, struct archive_entry *entry)
+{
+ /* First, test the seconds and return if we have a definite answer. */
+ /* Definitely older. */
+ if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry)))
+ return (1);
+ /* Definitely younger. */
+ if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry)))
+ return (0);
+ /* If this platform supports fractional seconds, try those. */
+#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
+ /* Definitely older. */
+ if (st->st_mtimespec.tv_nsec < archive_entry_mtime_nsec(entry))
+ return (1);
+#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+ /* Definitely older. */
+ if (st->st_mtim.tv_nsec < archive_entry_mtime_nsec(entry))
+ return (1);
+#elif HAVE_STRUCT_STAT_ST_MTIME_N
+ /* older. */
+ if (st->st_mtime_n < archive_entry_mtime_nsec(entry))
+ return (1);
+#elif HAVE_STRUCT_STAT_ST_UMTIME
+ /* older. */
+ if (st->st_umtime * 1000 < archive_entry_mtime_nsec(entry))
+ return (1);
+#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
+ /* older. */
+ if (st->st_mtime_usec * 1000 < archive_entry_mtime_nsec(entry))
+ return (1);
+#else
+ /* This system doesn't have high-res timestamps. */
+#endif
+ /* Same age or newer, so not older. */
+ return (0);
+}
+
+#endif /* !_WIN32 || __CYGWIN__ */
+
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=059aa805c9c0cb34c92eb69abf66febc40ab62db
commit 059aa805c9c0cb34c92eb69abf66febc40ab62db
Author: LibArchive Upstream <libarchive-discuss at googlegroups.com>
AuthorDate: Sat Feb 25 11:31:44 2017 -0800
Commit: Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 27 08:47:35 2017 -0500
LibArchive 2017-02-25 (d6b1bb9f)
Code extracted from:
https://github.com/libarchive/libarchive.git
at commit d6b1bb9f7ea7bc153b7356e8e345c9e48005821a (v3.3.1).
diff --git a/CMakeLists.txt b/CMakeLists.txt
index eb36b5b..1ca9d8f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,7 +15,7 @@ endif()
# RelWithDebInfo : Release build with Debug Info
# MinSizeRel : Release Min Size build
IF(NOT CMAKE_BUILD_TYPE)
- SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE)
+ SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
# Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the
# value type is "UNINITIALIZED".
@@ -44,13 +44,13 @@ SET(CMAKE_MACOSX_RPATH ON)
#
FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/build/version _version)
STRING(REGEX REPLACE
- "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]?$" "\\1" _major ${_version})
+ "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]*$" "\\1" _major ${_version})
STRING(REGEX REPLACE
- "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]?$" "\\1" _minor ${_version})
+ "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]*$" "\\1" _minor ${_version})
STRING(REGEX REPLACE
- "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]?$" "\\1" _revision ${_version})
+ "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]*$" "\\1" _revision ${_version})
STRING(REGEX REPLACE
- "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]?)$" "\\1" _quality ${_version})
+ "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]*)$" "\\1" _quality ${_version})
SET(_version_number ${_major}${_minor}${_revision})
STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_minor ${_minor})
STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_revision ${_revision})
@@ -462,6 +462,8 @@ ENDIF()
IF(LIBLZMA_FOUND)
SET(HAVE_LIBLZMA 1)
SET(HAVE_LZMA_H 1)
+ SET(CMAKE_REQUIRED_INCLUDES ${LIBLZMA_INCLUDE_DIR})
+ SET(CMAKE_REQUIRED_LIBRARIES ${LIBLZMA_LIBRARIES})
INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS})
LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES})
# Test if a macro is needed for the library.
@@ -570,6 +572,11 @@ LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H)
LA_CHECK_INCLUDE_FILE("linux/types.h" HAVE_LINUX_TYPES_H)
LA_CHECK_INCLUDE_FILE("linux/fiemap.h" HAVE_LINUX_FIEMAP_H)
LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H)
+
+CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
+#include <linux/fs.h>
+int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS)
+
LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H)
LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H)
LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H)
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index ec64d99..923a78e 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -1099,6 +1099,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */
#cmakedefine HAVE_WORKING_EXT2_IOC_GETFLAGS 1
+/* 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 <zlib.h> header file. */
#cmakedefine HAVE_ZLIB_H 1
diff --git a/build/version b/build/version
index a000b30..ef83457 100644
--- a/build/version
+++ b/build/version
@@ -1 +1 @@
-3003000
+3003001
diff --git a/libarchive/archive.h b/libarchive/archive.h
index cd27c90..d400735 100644
--- a/libarchive/archive.h
+++ b/libarchive/archive.h
@@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3003000
+#define ARCHIVE_VERSION_NUMBER 3003001
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.3.0"
+#define ARCHIVE_VERSION_ONLY_STRING "3.3.1"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -1001,6 +1001,10 @@ __LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008)
/* Default: Xattrs are read from disk. */
#define ARCHIVE_READDISK_NO_XATTR (0x0010)
+/* Default: ACLs are read from disk. */
+#define ARCHIVE_READDISK_NO_ACL (0x0020)
+/* Default: File flags are read from disk. */
+#define ARCHIVE_READDISK_NO_FFLAGS (0x0040)
__LA_DECL int archive_read_disk_set_behavior(struct archive *,
int flags);
diff --git a/libarchive/archive_digest_private.h b/libarchive/archive_digest_private.h
index b58ffb3..b4fd6ca 100644
--- a/libarchive/archive_digest_private.h
+++ b/libarchive/archive_digest_private.h
@@ -143,6 +143,7 @@
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
defined(ARCHIVE_CRYPTO_SHA512_WIN)
+#include <windows.h>
#include <wincrypt.h>
typedef struct {
int valid;
diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c
index d4f061b..10eff11 100644
--- a/libarchive/archive_entry.c
+++ b/libarchive/archive_entry.c
@@ -1649,7 +1649,10 @@ static struct flag {
{ "nosappnd", L"nosappnd", SF_APPEND, 0 },
{ "nosappend", L"nosappend", SF_APPEND, 0 },
#endif
-#ifdef EXT2_APPEND_FL /* 'a' */
+#if defined(FS_APPEND_FL) /* 'a' */
+ { "nosappnd", L"nosappnd", FS_APPEND_FL, 0 },
+ { "nosappend", L"nosappend", FS_APPEND_FL, 0 },
+#elif defined(EXT2_APPEND_FL) /* 'a' */
{ "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0 },
{ "nosappend", L"nosappend", EXT2_APPEND_FL, 0 },
#endif
@@ -1662,7 +1665,11 @@ static struct flag {
{ "noschange", L"noschange", SF_IMMUTABLE, 0 },
{ "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0 },
#endif
-#ifdef EXT2_IMMUTABLE_FL /* 'i' */
+#if defined(FS_IMMUTABLE_FL) /* 'i' */
+ { "noschg", L"noschg", FS_IMMUTABLE_FL, 0 },
+ { "noschange", L"noschange", FS_IMMUTABLE_FL, 0 },
+ { "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0 },
+#elif defined(EXT2_IMMUTABLE_FL) /* 'i' */
{ "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0 },
{ "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0 },
{ "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0 },
@@ -1686,7 +1693,9 @@ static struct flag {
#ifdef UF_NODUMP
{ "nodump", L"nodump", 0, UF_NODUMP},
#endif
-#ifdef EXT2_NODUMP_FL /* 'd' */
+#if defined(FS_NODUMP_FL) /* 'd' */
+ { "nodump", L"nodump", 0, FS_NODUMP_FL},
+#elif defined(EXT2_NODUMP_FL) /* 'd' */
{ "nodump", L"nodump", 0, EXT2_NODUMP_FL},
#endif
#ifdef UF_OPAQUE
@@ -1699,65 +1708,124 @@ static struct flag {
#ifdef UF_COMPRESSED
{ "nocompressed",L"nocompressed", UF_COMPRESSED, 0 },
#endif
-#ifdef EXT2_UNRM_FL
+#if defined(FS_UNRM_FL)
+ { "nouunlink", L"nouunlink", FS_UNRM_FL, 0},
+#elif defined(EXT2_UNRM_FL)
{ "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0},
#endif
-#ifdef EXT2_BTREE_FL
+#if defined(FS_BTREE_FL)
+ { "nobtree", L"nobtree", FS_BTREE_FL, 0 },
+#elif defined(EXT2_BTREE_FL)
{ "nobtree", L"nobtree", EXT2_BTREE_FL, 0 },
#endif
-#ifdef EXT2_ECOMPR_FL
+#if defined(FS_ECOMPR_FL)
+ { "nocomperr", L"nocomperr", FS_ECOMPR_FL, 0 },
+#elif defined(EXT2_ECOMPR_FL)
{ "nocomperr", L"nocomperr", EXT2_ECOMPR_FL, 0 },
#endif
-#ifdef EXT2_COMPR_FL /* 'c' */
+#if defined(FS_COMPR_FL) /* 'c' */
+ { "nocompress", L"nocompress", FS_COMPR_FL, 0 },
+#elif defined(EXT2_COMPR_FL) /* 'c' */
{ "nocompress", L"nocompress", EXT2_COMPR_FL, 0 },
#endif
-#ifdef EXT2_NOATIME_FL /* 'A' */
+#if defined(FS_NOATIME_FL) /* 'A' */
+ { "noatime", L"noatime", 0, FS_NOATIME_FL},
+#elif defined(EXT2_NOATIME_FL) /* 'A' */
{ "noatime", L"noatime", 0, EXT2_NOATIME_FL},
#endif
-#ifdef EXT2_DIRTY_FL
+#if defined(FS_DIRTY_FL)
+ { "nocompdirty",L"nocompdirty", FS_DIRTY_FL, 0},
+#elif defined(EXT2_DIRTY_FL)
{ "nocompdirty",L"nocompdirty", EXT2_DIRTY_FL, 0},
#endif
-#ifdef EXT2_COMPRBLK_FL
-#ifdef EXT2_NOCOMPR_FL
+#if defined(FS_COMPRBLK_FL)
+#if defined(FS_NOCOMPR_FL)
+ { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, FS_NOCOMPR_FL},
+#else
+ { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, 0},
+#endif
+#elif defined(EXT2_COMPRBLK_FL)
+#if defined(EXT2_NOCOMPR_FL)
{ "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL},
#else
{ "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, 0},
#endif
#endif
-#ifdef EXT2_DIRSYNC_FL
+#if defined(FS_DIRSYNC_FL)
+ { "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0},
+#elif defined(EXT2_DIRSYNC_FL)
{ "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0},
#endif
-#ifdef EXT2_INDEX_FL
+#if defined(FS_INDEX_FL)
+ { "nohashidx", L"nohashidx", FS_INDEX_FL, 0},
+#elif defined(EXT2_INDEX_FL)
{ "nohashidx", L"nohashidx", EXT2_INDEX_FL, 0},
#endif
-#ifdef EXT2_IMAGIC_FL
+#if defined(FS_IMAGIC_FL)
+ { "noimagic", L"noimagic", FS_IMAGIC_FL, 0},
+#elif defined(EXT2_IMAGIC_FL)
{ "noimagic", L"noimagic", EXT2_IMAGIC_FL, 0},
#endif
-#ifdef EXT3_JOURNAL_DATA_FL
+#if defined(FS_JOURNAL_DATA_FL)
+ { "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0},
+#elif defined(EXT3_JOURNAL_DATA_FL)
{ "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0},
#endif
-#ifdef EXT2_SECRM_FL
+#if defined(FS_SECRM_FL)
+ { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0},
+#elif defined(EXT2_SECRM_FL)
{ "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0},
#endif
-#ifdef EXT2_SYNC_FL
+#if defined(FS_SYNC_FL)
+ { "nosync", L"nosync", FS_SYNC_FL, 0},
+#elif defined(EXT2_SYNC_FL)
{ "nosync", L"nosync", EXT2_SYNC_FL, 0},
#endif
-#ifdef EXT2_NOTAIL_FL
+#if defined(FS_NOTAIL_FL)
+ { "notail", L"notail", 0, FS_NOTAIL_FL},
+#elif defined(EXT2_NOTAIL_FL)
{ "notail", L"notail", 0, EXT2_NOTAIL_FL},
#endif
-#ifdef EXT2_TOPDIR_FL
+#if defined(FS_TOPDIR_FL)
+ { "notopdir", L"notopdir", FS_TOPDIR_FL, 0},
+#elif defined(EXT2_TOPDIR_FL)
{ "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0},
#endif
-#ifdef EXT2_RESERVED_FL
+#ifdef FS_ENCRYPT_FL
+ { "noencrypt", L"noencrypt", FS_ENCRYPT_FL, 0},
+#endif
+#ifdef FS_HUGE_FILE_FL
+ { "nohugefile", L"nohugefile", FS_HUGE_FILE_FL, 0},
+#endif
+#ifdef FS_EXTENT_FL
+ { "noextent", L"noextent", FS_EXTENT_FL, 0},
+#endif
+#ifdef FS_EA_INODE_FL
+ { "noeainode", L"noeainode", FS_EA_INODE_FL, 0},
+#endif
+#ifdef FS_EOFBLOCKS_FL
+ { "noeofblocks",L"noeofblocks", FS_EOFBLOCKS_FL, 0},
+#endif
+#ifdef FS_NOCOW_FL
+ { "nocow", L"nocow", FS_NOCOW_FL, 0},
+#endif
+#ifdef FS_INLINE_DATA_FL
+ { "noinlinedata",L"noinlinedata", FS_INLINE_DATA_FL, 0},
+#endif
+#ifdef FS_PROJINHERIT_FL
+ { "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0},
+#endif
+#if defined(FS_RESERVED_FL)
+ { "noreserved", L"noreserved", FS_RESERVED_FL, 0},
+#elif defined(EXT2_RESERVED_FL)
{ "noreserved", L"noreserved", EXT2_RESERVED_FL, 0},
#endif
-
{ NULL, NULL, 0, 0 }
};
diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h
index 2dd557a..7645f0c 100644
--- a/libarchive/archive_entry.h
+++ b/libarchive/archive_entry.h
@@ -30,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3003000
+#define ARCHIVE_VERSION_NUMBER 3003001
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -66,6 +66,27 @@ typedef int64_t la_int64_t;
# endif
#endif
+/* The la_ssize_t should match the type used in 'struct stat' */
+#if !defined(__LA_SSIZE_T_DEFINED)
+/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
+# if ARCHIVE_VERSION_NUMBER < 4000000
+#define __LA_SSIZE_T la_ssize_t
+# endif
+#define __LA_SSIZE_T_DEFINED
+# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
+# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
+typedef ssize_t la_ssize_t;
+# elif defined(_WIN64)
+typedef __int64 la_ssize_t;
+# else
+typedef long la_ssize_t;
+# endif
+# else
+# include <unistd.h> /* ssize_t */
+typedef ssize_t la_ssize_t;
+# endif
+#endif
+
/* Get a suitable definition for mode_t */
#if ARCHIVE_VERSION_NUMBER >= 3999000
/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */
@@ -526,9 +547,9 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type
#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010
__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *,
- ssize_t * /* len */, int /* flags */);
+ la_ssize_t * /* len */, int /* flags */);
__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *,
- ssize_t * /* len */, int /* flags */);
+ la_ssize_t * /* len */, int /* flags */);
__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *,
const wchar_t * /* wtext */, int /* type */);
__LA_DECL int archive_entry_acl_from_text(struct archive_entry *,
diff --git a/libarchive/archive_hmac.c b/libarchive/archive_hmac.c
index 1e0ae28..f299655 100644
--- a/libarchive/archive_hmac.c
+++ b/libarchive/archive_hmac.c
@@ -76,6 +76,10 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+#ifndef BCRYPT_HASH_REUSABLE_FLAG
+# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020
+#endif
+
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
{
diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c
index 591a212..b2f1d17 100644
--- a/libarchive/archive_read_disk_entry_from_file.c
+++ b/libarchive/archive_read_disk_entry_from_file.c
@@ -203,15 +203,17 @@ archive_read_disk_entry_from_file(struct archive *_a,
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
/* On FreeBSD, we get flags for free with the stat. */
/* TODO: Does this belong in copy_stat()? */
- if (st->st_flags != 0)
+ if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0)
archive_entry_set_fflags(entry, st->st_flags, 0);
#endif
-#if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
/* Linux requires an extra ioctl to pull the flags. Although
* this is an extra step, it has a nice side-effect: We get an
* open file descriptor which we can use in the subsequent lookups. */
- if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
+ if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 &&
+ (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
if (fd < 0) {
if (a->tree != NULL)
fd = a->open_on_current_dir(a->tree, path,
@@ -223,7 +225,13 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
if (fd >= 0) {
int stflags;
- r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
+ r = ioctl(fd,
+#if defined(FS_IOC_GETFLAGS)
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &stflags);
if (r == 0 && stflags != 0)
archive_entry_set_fflags(entry, stflags, 0);
}
@@ -269,13 +277,15 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
#endif /* HAVE_READLINK || HAVE_READLINKAT */
- r = setup_acls(a, entry, &fd);
- if (!a->suppress_xattr) {
+ r = 0;
+ if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0)
+ r = setup_acls(a, entry, &fd);
+ if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) {
r1 = setup_xattrs(a, entry, &fd);
if (r1 < r)
r = r1;
}
- if (a->enable_copyfile) {
+ if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
r1 = setup_mac_metadata(a, entry, &fd);
if (r1 < r)
r = r1;
diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c
index b893704..6961ae6 100644
--- a/libarchive/archive_read_disk_posix.c
+++ b/libarchive/archive_read_disk_posix.c
@@ -465,8 +465,7 @@ archive_read_disk_new(void)
a->entry = archive_entry_new2(&a->archive);
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
- a->enable_copyfile = 1;
- a->traverse_mount_points = 1;
+ a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
a->open_on_current_dir = open_on_current_dir;
a->tree_current_dir_fd = tree_current_dir_fd;
a->tree_enter_working_dir = tree_enter_working_dir;
@@ -563,25 +562,19 @@ archive_read_disk_set_symlink_hybrid(struct archive *_a)
int
archive_read_disk_set_atime_restored(struct archive *_a)
{
-#ifndef HAVE_UTIMES
- static int warning_done = 0;
-#endif
struct archive_read_disk *a = (struct archive_read_disk *)_a;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
#ifdef HAVE_UTIMES
- a->restore_time = 1;
+ a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
if (a->tree != NULL)
a->tree->flags |= needsRestoreTimes;
return (ARCHIVE_OK);
#else
- if (warning_done)
- /* Warning was already emitted; suppress further warnings. */
- return (ARCHIVE_OK);
-
+ /* Display warning and unset flag */
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore access time on this system");
- warning_done = 1;
+ a->flags &= ~ARCHIVE_READDISK_RESTORE_ATIME;
return (ARCHIVE_WARN);
#endif
}
@@ -595,29 +588,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags)
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
+ a->flags = flags;
+
if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
r = archive_read_disk_set_atime_restored(_a);
else {
- a->restore_time = 0;
if (a->tree != NULL)
a->tree->flags &= ~needsRestoreTimes;
}
- if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
- a->honor_nodump = 1;
- else
- a->honor_nodump = 0;
- if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
- a->enable_copyfile = 1;
- else
- a->enable_copyfile = 0;
- if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
- a->traverse_mount_points = 0;
- else
- a->traverse_mount_points = 1;
- if (flags & ARCHIVE_READDISK_NO_XATTR)
- a->suppress_xattr = 1;
- else
- a->suppress_xattr = 0;
return (r);
}
@@ -918,7 +896,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
} while (lst == NULL);
#ifdef __APPLE__
- if (a->enable_copyfile) {
+ if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
/* If we're using copyfile(), ignore "._XXX" files. */
const char *bname = strrchr(tree_current_path(t), '/');
if (bname == NULL)
@@ -989,7 +967,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
}
if (t->initial_filesystem_id == -1)
t->initial_filesystem_id = t->current_filesystem_id;
- if (!a->traverse_mount_points) {
+ if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
if (t->initial_filesystem_id != t->current_filesystem_id)
descend = 0;
}
@@ -999,12 +977,14 @@ next_entry(struct archive_read_disk *a, struct tree *t,
* Honor nodump flag.
* If the file is marked with nodump flag, do not return this entry.
*/
- if (a->honor_nodump) {
+ if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) {
#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
if (st->st_flags & UF_NODUMP)
return (ARCHIVE_RETRY);
-#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\
- defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \
+ defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \
+ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
int stflags;
@@ -1013,9 +993,18 @@ next_entry(struct archive_read_disk *a, struct tree *t,
O_RDONLY | O_NONBLOCK | O_CLOEXEC);
__archive_ensure_cloexec_flag(t->entry_fd);
if (t->entry_fd >= 0) {
- r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS,
+ r = ioctl(t->entry_fd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
&stflags);
+#ifdef FS_NODUMP_FL
+ if (r == 0 && (stflags & FS_NODUMP_FL) != 0)
+#else
if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0)
+#endif
return (ARCHIVE_RETRY);
}
}
@@ -1340,10 +1329,11 @@ _archive_read_disk_open(struct archive *_a, const char *pathname)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (a->tree != NULL)
- a->tree = tree_reopen(a->tree, pathname, a->restore_time);
+ a->tree = tree_reopen(a->tree, pathname,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
else
a->tree = tree_open(pathname, a->symlink_mode,
- a->restore_time);
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
if (a->tree == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
@@ -2132,7 +2122,7 @@ tree_open(const char *path, int symlink_mode, int restore_time)
static struct tree *
tree_reopen(struct tree *t, const char *path, int restore_time)
{
- t->flags = (restore_time)?needsRestoreTimes:0;
+ t->flags = (restore_time != 0)?needsRestoreTimes:0;
t->flags |= onInitialDir;
t->visit_type = 0;
t->tree_errno = 0;
diff --git a/libarchive/archive_read_disk_private.h b/libarchive/archive_read_disk_private.h
index 2569321..b5a8328 100644
--- a/libarchive/archive_read_disk_private.h
+++ b/libarchive/archive_read_disk_private.h
@@ -63,16 +63,8 @@ struct archive_read_disk {
int (*tree_current_dir_fd)(struct tree*);
int (*tree_enter_working_dir)(struct tree*);
- /* Set 1 if users request to restore atime . */
- int restore_time;
- /* Set 1 if users request to honor nodump flag . */
- int honor_nodump;
- /* Set 1 if users request to enable mac copyfile. */
- int enable_copyfile;
- /* Set 1 if users request to traverse mount points. */
- int traverse_mount_points;
- /* Set 1 if users want to suppress xattr information. */
- int suppress_xattr;
+ /* Bitfield with ARCHIVE_READDISK_* tunables */
+ int flags;
const char * (*lookup_gname)(void *private, int64_t gid);
void (*cleanup_gname)(void *private);
diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c
index 27b75e3..3b90330 100644
--- a/libarchive/archive_read_disk_windows.c
+++ b/libarchive/archive_read_disk_windows.c
@@ -398,8 +398,7 @@ archive_read_disk_new(void)
a->entry = archive_entry_new2(&a->archive);
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
- a->enable_copyfile = 1;
- a->traverse_mount_points = 1;
+ a->flags = ARCHIVE_READDISK_MAC_COPYFILE;
return (&a->archive);
}
@@ -495,7 +494,7 @@ archive_read_disk_set_atime_restored(struct archive *_a)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime");
- a->restore_time = 1;
+ a->flags |= ARCHIVE_READDISK_RESTORE_ATIME;
if (a->tree != NULL)
a->tree->flags |= needsRestoreTimes;
return (ARCHIVE_OK);
@@ -510,25 +509,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags)
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
+ a->flags = flags;
+
if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
r = archive_read_disk_set_atime_restored(_a);
else {
- a->restore_time = 0;
if (a->tree != NULL)
a->tree->flags &= ~needsRestoreTimes;
}
- if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
- a->honor_nodump = 1;
- else
- a->honor_nodump = 0;
- if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
- a->enable_copyfile = 1;
- else
- a->enable_copyfile = 0;
- if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
- a->traverse_mount_points = 0;
- else
- a->traverse_mount_points = 1;
return (r);
}
@@ -852,7 +840,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
}
if (t->initial_filesystem_id == -1)
t->initial_filesystem_id = t->current_filesystem_id;
- if (!a->traverse_mount_points) {
+ if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) {
if (t->initial_filesystem_id != t->current_filesystem_id)
return (ARCHIVE_RETRY);
}
@@ -1219,9 +1207,11 @@ _archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
if (a->tree != NULL)
- a->tree = tree_reopen(a->tree, pathname, a->restore_time);
+ a->tree = tree_reopen(a->tree, pathname,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
else
- a->tree = tree_open(pathname, a->symlink_mode, a->restore_time);
+ a->tree = tree_open(pathname, a->symlink_mode,
+ a->flags & ARCHIVE_READDISK_RESTORE_ATIME);
if (a->tree == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate directory traversal data");
@@ -1519,7 +1509,7 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time)
struct archive_wstring ws;
wchar_t *pathname, *p, *base;
- t->flags = (restore_time)?needsRestoreTimes:0;
+ t->flags = (restore_time != 0)?needsRestoreTimes:0;
t->visit_type = 0;
t->tree_errno = 0;
t->full_path_dir_length = 0;
diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c
index 5e22438..b162465 100644
--- a/libarchive/archive_read_support_format_warc.c
+++ b/libarchive/archive_read_support_format_warc.c
@@ -543,7 +543,7 @@ xstrpisotime(const char *s, char **endptr)
/* as a courtesy to our callers, and since this is a non-standard
* routine, we skip leading whitespace */
- while (isblank((unsigned char)*s))
+ while (*s == ' ' || *s == '\t')
++s;
/* read year */
@@ -589,6 +589,7 @@ static unsigned int
_warc_rdver(const char *buf, size_t bsz)
{
static const char magic[] = "WARC/";
+ const char *c;
unsigned int ver = 0U;
unsigned int end = 0U;
@@ -615,11 +616,12 @@ _warc_rdver(const char *buf, size_t bsz)
* WARC below version 0.12 has a space-separated header
* WARC 0.12 and above terminates the version with a CRLF
*/
+ c = buf + 3U + end;
if (ver >= 1200U) {
- if (memcmp(buf + 3U + end, "\r\n", 2U) != 0)
+ if (memcmp(c, "\r\n", 2U) != 0)
ver = 0U;
} else if (ver < 1200U) {
- if (!isblank(*(buf + 3U + end)))
+ if (*c != ' ' && *c != '\t')
ver = 0U;
}
}
@@ -643,7 +645,7 @@ _warc_rdtyp(const char *buf, size_t bsz)
}
/* overread whitespace */
- while (val < eol && isblank((unsigned char)*val))
+ while (val < eol && (*val == ' ' || *val == '\t'))
++val;
if (val + 8U == eol) {
@@ -673,7 +675,7 @@ _warc_rduri(const char *buf, size_t bsz)
return res;
}
- while (val < eol && isblank((unsigned char)*val))
+ while (val < eol && (*val == ' ' || *val == '\t'))
++val;
/* overread URL designators */
@@ -731,7 +733,7 @@ _warc_rdlen(const char *buf, size_t bsz)
}
/* skip leading whitespace */
- while (val < eol && isblank(*val))
+ while (val < eol && (*val == ' ' || *val == '\t'))
val++;
/* there must be at least one digit */
if (!isdigit(*val))
diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
index 20450ba..5a01e84 100644
--- a/libarchive/archive_write_disk_posix.c
+++ b/libarchive/archive_write_disk_posix.c
@@ -1712,7 +1712,8 @@ _archive_write_disk_finish_entry(struct archive *_a)
const void *metadata;
size_t metadata_size;
metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
- if (metadata == NULL || metadata_size == 0) {
+ if ((a->todo & TODO_MAC_METADATA) == 0 ||
+ metadata == NULL || metadata_size == 0) {
#endif
r2 = archive_write_disk_set_acls(&a->archive, a->fd,
archive_entry_pathname(a->entry),
@@ -2293,7 +2294,8 @@ _archive_write_disk_close(struct archive *_a)
chmod(p->name, p->mode);
if (p->fixup & TODO_ACLS)
#ifdef HAVE_DARWIN_ACL
- if (p->mac_metadata == NULL ||
+ if ((p->fixup & TODO_MAC_METADATA) == 0 ||
+ p->mac_metadata == NULL ||
p->mac_metadata_size == 0)
#endif
archive_write_disk_set_acls(&a->archive,
@@ -3465,12 +3467,19 @@ set_fflags(struct archive_write_disk *a)
#ifdef UF_APPEND
critical_flags |= UF_APPEND;
#endif
-#ifdef EXT2_APPEND_FL
+#if defined(FS_APPEND_FL)
+ critical_flags |= FS_APPEND_FL;
+#elif defined(EXT2_APPEND_FL)
critical_flags |= EXT2_APPEND_FL;
#endif
-#ifdef EXT2_IMMUTABLE_FL
+#if defined(FS_IMMUTABLE_FL)
+ critical_flags |= FS_IMMUTABLE_FL;
+#elif defined(EXT2_IMMUTABLE_FL)
critical_flags |= EXT2_IMMUTABLE_FL;
#endif
+#ifdef FS_JOURNAL_DATA_FL
+ critical_flags |= FS_JOURNAL_DATA_FL;
+#endif
if (a->todo & TODO_FFLAGS) {
archive_entry_fflags(a->entry, &set, &clear);
@@ -3582,7 +3591,10 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
return (ARCHIVE_WARN);
}
-#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
+#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \
+ defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
+ (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \
+ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
/*
* Linux uses ioctl() to read and write file flags.
*/
@@ -3595,7 +3607,7 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
int newflags, oldflags;
int sf_mask = 0;
- if (set == 0 && clear == 0)
+ if (set == 0 && clear == 0)
return (ARCHIVE_OK);
/* Only regular files and dirs can have flags. */
if (!S_ISREG(mode) && !S_ISDIR(mode))
@@ -3616,12 +3628,19 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
* defines. (?) The code below degrades reasonably gracefully
* if sf_mask is incomplete.
*/
-#ifdef EXT2_IMMUTABLE_FL
+#if defined(FS_IMMUTABLE_FL)
+ sf_mask |= FS_IMMUTABLE_FL;
+#elif defined(EXT2_IMMUTABLE_FL)
sf_mask |= EXT2_IMMUTABLE_FL;
#endif
-#ifdef EXT2_APPEND_FL
+#if defined(FS_APPEND_FL)
+ sf_mask |= FS_APPEND_FL;
+#elif defined(EXT2_APPEND_FL)
sf_mask |= EXT2_APPEND_FL;
#endif
+#if defined(FS_JOURNAL_DATA_FL)
+ sf_mask |= FS_JOURNAL_DATA_FL;
+#endif
/*
* XXX As above, this would be way simpler if we didn't have
* to read the current flags from disk. XXX
@@ -3629,12 +3648,24 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
ret = ARCHIVE_OK;
/* Read the current file flags. */
- if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) < 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_GETFLAGS
+ FS_IOC_GETFLAGS,
+#else
+ EXT2_IOC_GETFLAGS,
+#endif
+ &oldflags) < 0)
goto fail;
/* Try setting the flags as given. */
newflags = (oldflags & ~clear) | set;
- if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_SETFLAGS
+ FS_IOC_SETFLAGS,
+#else
+ EXT2_IOC_SETFLAGS,
+#endif
+ &newflags) >= 0)
goto cleanup;
if (errno != EPERM)
goto fail;
@@ -3643,7 +3674,13 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
newflags &= ~sf_mask;
oldflags &= sf_mask;
newflags |= oldflags;
- if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+ if (ioctl(myfd,
+#ifdef FS_IOC_SETFLAGS
+ FS_IOC_SETFLAGS,
+#else
+ EXT2_IOC_SETFLAGS,
+#endif
+ &newflags) >= 0)
goto cleanup;
/* We couldn't set the flags, so report the failure. */
diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c
index 4e91097..c0ca435 100644
--- a/libarchive/archive_write_set_format_iso9660.c
+++ b/libarchive/archive_write_set_format_iso9660.c
@@ -4074,8 +4074,10 @@ write_information_block(struct archive_write *a)
memset(info.s, 0, info_size);
opt = 0;
#if defined(HAVE__CTIME64_S)
- __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
- _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
+ {
+ __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
+ _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
+ }
#elif defined(HAVE_CTIME_R)
ctime_r(&(iso9660->birth_time), buf);
#else
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5fee76606b7a1f252e75e95c3d8303777459938d
commit 5fee76606b7a1f252e75e95c3d8303777459938d
Author: Brad King <brad.king at kitware.com>
AuthorDate: Mon Feb 27 08:47:11 2017 -0500
Commit: Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 27 08:47:11 2017 -0500
libarchive: Update script to get 3.3.1
diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash
index 6c4eeb0..41c6a66 100755
--- a/Utilities/Scripts/update-libarchive.bash
+++ b/Utilities/Scripts/update-libarchive.bash
@@ -8,7 +8,7 @@ readonly name="LibArchive"
readonly ownership="LibArchive Upstream <libarchive-discuss at googlegroups.com>"
readonly subtree="Utilities/cmlibarchive"
readonly repo="https://github.com/libarchive/libarchive.git"
-readonly tag="v3.3.0"
+readonly tag="v3.3.1"
readonly shortlog=false
readonly paths="
CMakeLists.txt
-----------------------------------------------------------------------
Summary of changes:
Source/CMakeVersion.cmake | 2 +-
Utilities/Scripts/update-libarchive.bash | 2 +-
Utilities/cmlibarchive/CMakeLists.txt | 13 ++-
Utilities/cmlibarchive/build/cmake/config.h.in | 3 +
Utilities/cmlibarchive/build/version | 2 +-
Utilities/cmlibarchive/libarchive/archive.h | 8 +-
.../libarchive/archive_digest_private.h | 1 +
Utilities/cmlibarchive/libarchive/archive_entry.c | 110 ++++++++++++++++----
Utilities/cmlibarchive/libarchive/archive_entry.h | 2 +-
Utilities/cmlibarchive/libarchive/archive_hmac.c | 4 +
.../libarchive/archive_read_disk_entry_from_file.c | 24 +++--
.../libarchive/archive_read_disk_posix.c | 64 +++++-------
.../libarchive/archive_read_disk_private.h | 12 +--
.../libarchive/archive_read_disk_windows.c | 30 ++----
.../libarchive/archive_read_support_format_warc.c | 18 ++--
.../libarchive/archive_write_disk_posix.c | 59 +++++++++--
16 files changed, 228 insertions(+), 126 deletions(-)
hooks/post-receive
--
CMake
More information about the Cmake-commits
mailing list