Index: vendor/libarchive/dist/CMakeLists.txt =================================================================== --- vendor/libarchive/dist/CMakeLists.txt (revision 315874) +++ vendor/libarchive/dist/CMakeLists.txt (revision 315875) @@ -1,1865 +1,1913 @@ # CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12 FATAL_ERROR) # 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() # # Set the Build type for make based generators. # You can choose following types: # Debug : Debug build # Release : Release build # 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) ENDIF(NOT CMAKE_BUILD_TYPE) # Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the # value type is "UNINITIALIZED". GET_PROPERTY(cached_type CACHE CMAKE_BUILD_TYPE PROPERTY TYPE) IF("${cached_type}" STREQUAL "UNINITIALIZED") SET(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "Build Type" FORCE) ENDIF("${cached_type}" STREQUAL "UNINITIALIZED") # Check the Build Type. IF(NOT "${CMAKE_BUILD_TYPE}" MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)\$") MESSAGE(FATAL_ERROR "Unknown keyword for CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\n" "Acceptable keywords: Debug,Release,RelWithDebInfo,MinSizeRel") ENDIF(NOT "${CMAKE_BUILD_TYPE}" MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)\$") # 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}) STRING(REGEX REPLACE "^[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}) STRING(REGEX REPLACE "^[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(CMakePushCheckState) # 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) # Especially for early development, we want to be a little # aggressive about diagnosing build problems; this can get # relaxed somewhat in final shipping versions. IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$") SET(CMAKE_REQUIRED_FLAGS "-Wall -Wformat -Wformat-security") ################################################################# # Set compile flags for all build types. SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wformat -Wformat-security") ################################################################# # Set compile flags for debug build. # This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug" SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Werror") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wextra") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wunused") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wshadow") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wmissing-prototypes") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wcast-qual") ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$") IF (CMAKE_C_COMPILER_ID MATCHES "^Clang$") SET(CMAKE_REQUIRED_FLAGS "-Wall -Wformat -Wformat-security") ################################################################# # Set compile flags for all build types. SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wformat -Wformat-security") ################################################################# # Set compile flags for debug build. # This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug" SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Werror") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wextra") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wunused") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wshadow") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wmissing-prototypes") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wcast-qual") ENDIF (CMAKE_C_COMPILER_ID MATCHES "^Clang$") IF (CMAKE_C_COMPILER_ID MATCHES "^XL$") SET(CMAKE_C_COMPILER "xlc_r") SET(CMAKE_REQUIRED_FLAGS "-qflag=e:e -qformat=sec") ################################################################# # Set compile flags for all build types. SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -qflag=e:e -qformat=sec") ################################################################# # Set compile flags for debug build. # This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug" SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -qhalt=w") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -qflag=w:w") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -qinfo=pro:use") ENDIF(CMAKE_C_COMPILER_ID MATCHES "^XL$") IF (MSVC) ################################################################# # Set compile flags for debug build. # This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug" # Enable level 4 C4061: The enumerate has no associated handler in a switch # statement. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4061") # Enable level 4 C4254: A larger bit field was assigned to a smaller bit # field. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4254") # Enable level 4 C4295: An array was initialized but the last character in # the array is not a null; accessing the array may # produce unexpected results. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4295") # Enable level 4 C4296: An unsigned variable was used in a comparison # operation with zero. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4296") # Enable level 4 C4389: An operation involved signed and unsigned variables. # This could result in a loss of data. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4389") # Enable level 4 C4505: The given function is local and not referenced in # the body of the module; therefore, the function is # dead code. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4505") # Enable level 4 C4514: The optimizer removed an inline function that is not # called. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4514") # Enable level 4 C4702: Unreachable code. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4702") # Enable level 4 C4706: The test value in a conditional expression was the # result of an assignment. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4706") # /WX option is the same as gcc's -Werror option. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /WX") # /Oi option enables built-in functions. SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Oi") ################################################################# # Set compile flags for release build. SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oi") ENDIF (MSVC) # 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_TAR "Enable tar building" ON) OPTION(ENABLE_TAR_SHARED "Enable dynamic build of tar" FALSE) OPTION(ENABLE_CPIO "Enable cpio building" ON) OPTION(ENABLE_CPIO_SHARED "Enable dynamic build of cpio" FALSE) OPTION(ENABLE_CAT "Enable cat building" ON) OPTION(ENABLE_CAT_SHARED "Enable dynamic build of cat" FALSE) OPTION(ENABLE_XATTR "Enable extended attribute support" ON) OPTION(ENABLE_ACL "Enable ACL support" ON) OPTION(ENABLE_ICONV "Enable iconv support" ON) OPTION(ENABLE_TEST "Enable unit and regression tests" ON) OPTION(ENABLE_COVERAGE "Enable code coverage (GCC only, automatically sets ENABLE_TEST to ON)" FALSE) OPTION(ENABLE_INSTALL "Enable installing of libraries" ON) SET(POSIX_REGEX_LIB "AUTO" CACHE STRING "Choose what library should provide POSIX regular expression support") SET(ENABLE_SAFESEH "AUTO" CACHE STRING "Enable use of /SAFESEH linker flag (MSVC only)") SET(WINDOWS_VERSION "WIN7" CACHE STRING "Set Windows version to use (Windows only)") IF(ENABLE_COVERAGE) include(LibarchiveCodeCoverage) ENDIF(ENABLE_COVERAGE) IF(ENABLE_TEST) ENABLE_TESTING() ENDIF(ENABLE_TEST) IF(WIN32) IF(WINDOWS_VERSION STREQUAL "WIN8") SET(NTDDI_VERSION 0x06020000) SET(_WIN32_WINNT 0x0602) SET(WINVER 0x0602) ELSEIF(WINDOWS_VERSION STREQUAL "WIN7") SET(NTDDI_VERSION 0x06010000) SET(_WIN32_WINNT 0x0601) SET(WINVER 0x0601) ELSEIF(WINDOWS_VERSION STREQUAL "WS08") SET(NTDDI_VERSION 0x06000100) SET(_WIN32_WINNT 0x0600) SET(WINVER 0x0600) ELSEIF(WINDOWS_VERSION STREQUAL "VISTA") SET(NTDDI_VERSION 0x06000000) SET(_WIN32_WINNT 0x0600) SET(WINVER 0x0600) ELSEIF(WINDOWS_VERSION STREQUAL "WS03") SET(NTDDI_VERSION 0x05020000) SET(_WIN32_WINNT 0x0502) SET(WINVER 0x0502) ELSEIF(WINDOWS_VERSION STREQUAL "WINXP") SET(NTDDI_VERSION 0x05010000) SET(_WIN32_WINNT 0x0501) SET(WINVER 0x0501) ELSE(WINDOWS_VERSION STREQUAL "WIN8") # Default to Windows Server 2003 API if we don't recognize the specifier SET(NTDDI_VERSION 0x05020000) SET(_WIN32_WINNT 0x0502) SET(WINVER 0x0502) ENDIF(WINDOWS_VERSION STREQUAL "WIN8") ENDIF(WIN32) IF(MSVC) IF(ENABLE_SAFESEH STREQUAL "YES") SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH") SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH") SET(ENV{LDFLAGS} "$ENV{LDFLAGS} /SAFESEH") ELSEIF(ENABLE_SAFESEH STREQUAL "NO") SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO") SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO") SET(ENV{LDFLAGS} "$ENV{LDFLAGS} /SAFESEH:NO") ENDIF(ENABLE_SAFESEH STREQUAL "YES") ENDIF(MSVC) 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= # # 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 /* for off_t */ #-# include /* for SEEK_* and off_t */ #+# include /* for SEEK_* and off_t */ # # ifdef VMS # # include /* 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 \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 \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) ENDIF(ZLIB_FOUND) MARK_AS_ADVANCED(CLEAR ZLIB_INCLUDE_DIR) MARK_AS_ADVANCED(CLEAR ZLIB_LIBRARY) # # 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 \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}) # Test if a macro is needed for the library. TRY_MACRO_FOR_LIBRARY( "${LIBLZMA_INCLUDE_DIRS}" "${LIBLZMA_LIBRARIES}" COMPILES "#include \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(LIBLZMA_FOUND) # LZMA not found and will not be used. ENDIF(LIBLZMA_FOUND) # # 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) # # 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) # # 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 LA_CHECK_INCLUDE_FILE("acl/libacl.h" HAVE_ACL_LIBACL_H) +LA_CHECK_INCLUDE_FILE("attr/xattr.h" HAVE_ATTR_XATTR_H) 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 #include 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 #include 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("membership.h" HAVE_MEMBERSHIP_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/extattr.h" HAVE_SYS_EXTATTR_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/richacl.h" HAVE_SYS_RICHACL_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("sys/xattr.h" HAVE_SYS_XATTR_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) IF(HAVE_BCRYPT_H) LIST(APPEND ADDITIONAL_LIBS "Bcrypt") ENDIF(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}) LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_CRYPTO_LIBRARY}) 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 #include 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 MATCHES "^GNU$" OR CMAKE_C_COMPILER_ID MATCHES "^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 (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR CMAKE_C_COMPILER_ID MATCHES "^Clang$") IF (CMAKE_C_COMPILER_ID MATCHES "^XL$") SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -qhalt=w -qflag=w:w") ENDIF (CMAKE_C_COMPILER_ID MATCHES "^XL$") 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 #include 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) 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 \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 \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) # # 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 \n#include \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) # # POSIX Regular Expression support # IF(POSIX_REGEX_LIB MATCHES "^(AUTO|LIBC|LIBREGEX)$") # # If PCREPOSIX is not found or not requested, try using regex # from libc or libregex # FIND_PATH(REGEX_INCLUDE_DIR regex.h) IF(REGEX_INCLUDE_DIR) CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBC) # # If libc does not provide regex, find libregex. # IF(NOT HAVE_REGCOMP_LIBC) CMAKE_PUSH_CHECK_STATE() # Save the state of the variables FIND_LIBRARY(REGEX_LIBRARY regex) IF(REGEX_LIBRARY) SET(CMAKE_REQUIRED_LIBRARIES ${REGEX_LIBRARY}) CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBREGEX) IF(HAVE_REGCOMP_LIBREGEX) LIST(APPEND ADDITIONAL_LIBS ${REGEX_LIBRARY}) # # If regex.h is not found, retry looking for regex.h at # REGEX_INCLUDE_DIR # IF(NOT HAVE_REGEX_H) UNSET(HAVE_REGEX_H CACHE) INCLUDE_DIRECTORIES(${REGEX_INCLUDE_DIR}) SET(CMAKE_REQUIRED_INCLUDES ${REGEX_INCLUDE_DIR}) LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H) ENDIF(NOT HAVE_REGEX_H) # Test if a macro is needed for the library. TRY_MACRO_FOR_LIBRARY( "${REGEX_INCLUDE_DIR}" "${REGEX_LIBRARY}" COMPILES "#include \n#include \nint main() {regex_t r;return regcomp(&r, \"\", 0);}" "USE_REGEX_DLL;USE_REGEX_STATIC") IF(USE_REGEX_DLL) ADD_DEFINITIONS(-DUSE_REGEX_DLL) ELSEIF(USE_REGEX_STATIC) ADD_DEFINITIONS(-DUSE_REGEX_STATIC) ENDIF(USE_REGEX_DLL) ENDIF(HAVE_REGCOMP_LIBREGEX) ENDIF(REGEX_LIBRARY) CMAKE_POP_CHECK_STATE() # Restore the state of the variables ENDIF(NOT HAVE_REGCOMP_LIBC) ENDIF(REGEX_INCLUDE_DIR) IF(HAVE_REGCOMP_LIBC OR HAVE_REGCOMP_LIBREGEX) SET(FOUND_POSIX_REGEX_LIB 1) ENDIF(HAVE_REGCOMP_LIBC OR HAVE_REGCOMP_LIBREGEX) ENDIF(POSIX_REGEX_LIB MATCHES "^(AUTO|LIBC|LIBREGEX)$") IF(NOT FOUND_POSIX_REGEX_LIB AND POSIX_REGEX_LIB MATCHES "^(AUTO|LIBPCREPOSIX)$") # # If requested, try finding library for PCREPOSIX # IF(ENABLE_LibGCC) FIND_PACKAGE(LibGCC) ELSE() SET(LIBGCC_FOUND FALSE) # Override cached value ENDIF() IF(ENABLE_PCREPOSIX) FIND_PACKAGE(PCREPOSIX) ELSE() SET(PCREPOSIX_FOUND FALSE) # Override cached value ENDIF() IF(PCREPOSIX_FOUND) INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIR}) LIST(APPEND ADDITIONAL_LIBS ${PCREPOSIX_LIBRARIES}) # Test if a macro is needed for the library. TRY_MACRO_FOR_LIBRARY( "${PCRE_INCLUDE_DIR}" "${PCREPOSIX_LIBRARIES}" COMPILES "#include \nint main() {regex_t r;return regcomp(&r, \"\", 0);}" "WITHOUT_PCRE_STATIC;PCRE_STATIC") IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) ADD_DEFINITIONS(-DPCRE_STATIC) ELSEIF(NOT WITHOUT_PCRE_STATIC AND NOT PCRE_STATIC AND PCRE_FOUND) # Determine if pcre static libraries are to be used. LIST(APPEND ADDITIONAL_LIBS ${PCRE_LIBRARIES}) SET(TMP_LIBRARIES ${PCREPOSIX_LIBRARIES} ${PCRE_LIBRARIES}) MESSAGE(STATUS "trying again with -lpcre included") TRY_MACRO_FOR_LIBRARY( "${PCRE_INCLUDE_DIR}" "${TMP_LIBRARIES}" COMPILES "#include \nint main() {regex_t r;return regcomp(&r, \"\", 0);}" "WITHOUT_PCRE_STATIC;PCRE_STATIC") IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) ADD_DEFINITIONS(-DPCRE_STATIC) ELSEIF(NOT WITHOUT_PCRE_STATIC AND NOT PCRE_STATIC AND MSVC AND LIBGCC_FOUND) # When doing a Visual Studio build using pcre static libraries # built using the mingw toolchain, -lgcc is needed to resolve # ___chkstk_ms. MESSAGE(STATUS "Visual Studio build detected, trying again with -lgcc included") LIST(APPEND ADDITIONAL_LIBS ${LIBGCC_LIBRARIES}) SET(TMP_LIBRARIES ${PCREPOSIX_LIBRARIES} ${PCRE_LIBRARIES} ${LIBGCC_LIBRARIES}) TRY_MACRO_FOR_LIBRARY( "${PCRE_INCLUDE_DIR}" "${TMP_LIBRARIES}" COMPILES "#include \nint main() {regex_t r;return regcomp(&r, \"\", 0);}" "WITHOUT_PCRE_STATIC;PCRE_STATIC") IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) ADD_DEFINITIONS(-DPCRE_STATIC) ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC) ENDIF(PCREPOSIX_FOUND) MARK_AS_ADVANCED(CLEAR PCRE_INCLUDE_DIR) MARK_AS_ADVANCED(CLEAR PCREPOSIX_LIBRARIES) MARK_AS_ADVANCED(CLEAR PCRE_LIBRARIES) MARK_AS_ADVANCED(CLEAR LIBGCC_LIBRARIES) ENDIF(NOT FOUND_POSIX_REGEX_LIB AND POSIX_REGEX_LIB MATCHES "^(AUTO|LIBPCREPOSIX)$") # # Check functions # CMAKE_PUSH_CHECK_STATE() # Save the state of the variables IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR CMAKE_C_COMPILER_ID MATCHES "^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 (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR CMAKE_C_COMPILER_ID MATCHES "^Clang$") 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 \n#include \nint main(void) { struct vfsconf v; return sizeof(v);}" HAVE_STRUCT_VFSCONF) CHECK_C_SOURCE_COMPILES( "#include \n#include \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 \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 \n#include \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 \nint main() { return major(256); }" MAJOR_IN_MKDEV) CHECK_C_SOURCE_COMPILES( "#include \nint main() { return major(256); }" MAJOR_IN_SYSMACROS) CHECK_C_SOURCE_COMPILES( "#include \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) + CHECK_SYMBOL_EXISTS(XATTR_NOFOLLOW "sys/xattr.h" HAVE_DECL_XATTR_NOFOLLOW) + IF(HAVE_SYS_XATTR_H AND HAVE_DECL_XATTR_NOFOLLOW) + CHECK_FUNCTION_EXISTS(fgetxattr HAVE_FGETXATTR) + CHECK_FUNCTION_EXISTS(flistxattr HAVE_FLISTXATTR) + CHECK_FUNCTION_EXISTS(fsetxattr HAVE_FSETXATTR) + CHECK_FUNCTION_EXISTS(getxattr HAVE_GETXATTR) + CHECK_FUNCTION_EXISTS(listxattr HAVE_LISTXATTR) + CHECK_FUNCTION_EXISTS(setxattr HAVE_SETXATTR) + IF(HAVE_FGETXATTR AND + HAVE_FLISTXATTR AND + HAVE_FSETXATTR AND + HAVE_GETXATTR AND + HAVE_LISTXATTR AND + HAVE_SETXATTR) + SET(ARCHIVE_XATTR_DARWIN TRUE) + ENDIF() + ELSEIF(HAVE_SYS_EXTATTR_H AND HAVE_DECL_EXTATTR_NAMESPACE_USER) + # FreeBSD xattr support + CHECK_FUNCTION_EXISTS(extattr_get_fd HAVE_EXTATTR_GET_FD) + CHECK_FUNCTION_EXISTS(extattr_get_file HAVE_EXTATTR_GET_FILE) + CHECK_FUNCTION_EXISTS(extattr_get_link HAVE_EXTATTR_GET_LINK) + CHECK_FUNCTION_EXISTS(extattr_list_fd HAVE_EXTATTR_LIST_FD) + CHECK_FUNCTION_EXISTS(extattr_list_file HAVE_EXTATTR_LIST_FILE) + CHECK_FUNCTION_EXISTS(extattr_list_link HAVE_EXTATTR_LIST_LINK) + CHECK_FUNCTION_EXISTS(extattr_set_fd HAVE_EXTATTR_SET_FD) + CHECK_FUNCTION_EXISTS(extattr_set_link HAVE_EXTATTR_SET_LINK) + IF(HAVE_EXTATTR_GET_FD AND + HAVE_EXTATTR_GET_FILE AND + HAVE_EXTATTR_GET_LINK AND + HAVE_EXTATTR_LIST_FD AND + HAVE_EXTATTR_LIST_FILE AND + HAVE_EXTATTR_LIST_LINK AND + HAVE_EXTATTR_SET_FD AND + HAVE_EXTATTR_SET_LINK) + SET(ARCHIVE_XATTR_FREEBSD TRUE) + ENDIF() + ELSEIF(HAVE_SYS_XATTR_H OR HAVE_ATTR_XATTR_H) + # Linux xattr support + 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) + IF(HAVE_FGETXATTR AND + HAVE_FLISTXATTR AND + HAVE_FSETXATTR AND + HAVE_GETXATTR AND + HAVE_LGETXATTR AND + HAVE_LISTXATTR AND + HAVE_LLISTXATTR AND + HAVE_LSETXATTR) + SET(ARCHIVE_XATTR_LINUX TRUE) + ENDIF() + ELSEIF(HAVE_SYS_EA_H) + # AIX xattr support + CHECK_FUNCTION_EXISTS(fgetea HAVE_FGETEA) + CHECK_FUNCTION_EXISTS(flistea HAVE_FLISTEA) + CHECK_FUNCTION_EXISTS(fsetea HAVE_FSETEA) + CHECK_FUNCTION_EXISTS(getea HAVE_GETEA) + CHECK_FUNCTION_EXISTS(lgetea HAVE_LGETEA) + CHECK_FUNCTION_EXISTS(listea HAVE_LISTEA) + CHECK_FUNCTION_EXISTS(llistea HAVE_LLISTEA) + CHECK_FUNCTION_EXISTS(lsetea HAVE_LSETEA) + IF(HAVE_FGETEA AND + HAVE_FLISTEA AND + HAVE_FSETEA AND + HAVE_GETEA AND + HAVE_LGETEA AND + HAVE_LISTEA AND + HAVE_LLISTEA AND + HAVE_LSETEA) + SET(ARCHIVE_XATTR_AIX TRUE) + ENDIF() + ENDIF() + + IF(ARCHIVE_XATTR_DARWIN) + MESSAGE(STATUS "Extended attributes support: Darwin") + ELSEIF(ARCHIVE_XATTR_FREEBSD) + MESSAGE(STATUS "Extended attributes support: FreeBSD") + ELSEIF(ARCHIVE_XATTR_LINUX) + MESSAGE(STATUS "Extended attributes support: Linux") + ELSEIF(ARCHIVE_XATTR_AIX) + MESSAGE(STATUS "Extended attributes support: AIX") + ELSE() + MESSAGE(STATUS "Extended attributes support: none") + ENDIF() 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) + SET(ARCHIVE_XATTR_DARWIN FALSE) + SET(ARCHIVE_XATTR_FREEBSD FALSE) + SET(ARCHIVE_XATTR_LINUX FALSE) + SET(ARCHIVE_XATTR_AIX 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) # Solaris and derivates ACLs CHECK_FUNCTION_EXISTS(acl HAVE_ACL) CHECK_FUNCTION_EXISTS(facl HAVE_FACL) # Libacl 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_TYPE_EXISTS(acl_t "sys/types.h;sys/acl.h" HAVE_ACL_T) CHECK_TYPE_EXISTS(acl_entry_t "sys/types.h;sys/acl.h" HAVE_ACL_ENTRY_T) CHECK_TYPE_EXISTS(acl_permset_t "sys/types.h;sys/acl.h" HAVE_ACL_PERMSET_T) CHECK_TYPE_EXISTS(acl_tag_t "sys/types.h;sys/acl.h" HAVE_ACL_TAG_T) IF(HAVE_ACL AND HAVE_FACL) CHECK_TYPE_EXISTS(aclent_t "sys/acl.h" HAVE_ACLENT_T) IF(HAVE_ACLENT_T) CHECK_SYMBOL_EXISTS(GETACL "sys/acl.h" HAVE_DECL_GETACL) CHECK_SYMBOL_EXISTS(GETACLCNT "sys/acl.h" HAVE_DECL_GETACLCNT) CHECK_SYMBOL_EXISTS(SETACL "sys/acl.h" HAVE_DECL_SETACL) IF(HAVE_DECL_GETACL AND HAVE_DECL_GETACLCNT AND HAVE_DECL_SETACL) SET(ARCHIVE_ACL_SUNOS TRUE) ENDIF() CHECK_TYPE_EXISTS(ace_t "sys/acl.h" HAVE_ACE_T) IF(HAVE_ACE_T) CHECK_SYMBOL_EXISTS(ACE_GETACL "sys/acl.h" HAVE_DECL_ACE_GETACL) CHECK_SYMBOL_EXISTS(ACE_GETACLCNT "sys/acl.h" HAVE_DECL_ACE_GETACLCNT) CHECK_SYMBOL_EXISTS(ACE_SETACL "sys/acl.h" HAVE_DECL_ACE_SETACL) IF(HAVE_DECL_ACE_GETACL AND HAVE_DECL_ACE_GETACLCNT AND HAVE_DECL_ACE_SETACL) SET(ARCHIVE_ACL_SUNOS_NFS4 TRUE) ENDIF() ENDIF(HAVE_ACE_T) ENDIF(HAVE_ACLENT_T) ENDIF(HAVE_ACL AND HAVE_FACL) IF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND HAVE_ACL_TAG_T) CHECK_FUNCTION_EXISTS_GLIBC(acl_add_perm HAVE_ACL_ADD_PERM) CHECK_FUNCTION_EXISTS_GLIBC(acl_clear_perms HAVE_ACL_CLEAR_PERMS) CHECK_FUNCTION_EXISTS_GLIBC(acl_create_entry HAVE_ACL_CREATE_ENTRY) CHECK_FUNCTION_EXISTS_GLIBC(acl_delete_def_file HAVE_ACL_DELETE_DEF_FILE) CHECK_FUNCTION_EXISTS_GLIBC(acl_free HAVE_ACL_FREE) CHECK_FUNCTION_EXISTS_GLIBC(acl_get_entry HAVE_ACL_GET_ENTRY) CHECK_FUNCTION_EXISTS_GLIBC(acl_get_fd HAVE_ACL_GET_FD) CHECK_FUNCTION_EXISTS_GLIBC(acl_get_file HAVE_ACL_GET_FILE) CHECK_FUNCTION_EXISTS_GLIBC(acl_get_permset HAVE_ACL_GET_PERMSET) CHECK_FUNCTION_EXISTS_GLIBC(acl_get_qualifier HAVE_ACL_GET_QUALIFIER) CHECK_FUNCTION_EXISTS_GLIBC(acl_get_tag_type HAVE_ACL_GET_TAG_TYPE) 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_file HAVE_ACL_SET_FILE) CHECK_FUNCTION_EXISTS_GLIBC(acl_set_qualifier HAVE_ACL_SET_QUALIFIER) CHECK_FUNCTION_EXISTS_GLIBC(acl_set_tag_type HAVE_ACL_SET_TAG_TYPE) IF(HAVE_ACL_ADD_PERM AND HAVE_ACL_CLEAR_PERMS AND HAVE_ACL_CREATE_ENTRY AND HAVE_ACL_DELETE_DEF_FILE AND HAVE_ACL_FREE AND HAVE_ACL_GET_ENTRY AND HAVE_ACL_GET_FD AND HAVE_ACL_GET_FILE AND HAVE_ACL_GET_PERMSET AND HAVE_ACL_GET_QUALIFIER AND HAVE_ACL_GET_TAG_TYPE AND HAVE_ACL_INIT AND HAVE_ACL_SET_FD AND HAVE_ACL_SET_FILE AND HAVE_ACL_SET_QUALIFIER AND HAVE_ACL_SET_TAG_TYPE) SET(HAVE_POSIX_ACL_FUNCS 1) ENDIF() CHECK_FUNCTION_EXISTS_GLIBC(acl_get_perm HAVE_ACL_GET_PERM) IF(HAVE_POSIX_ACL_FUNCS AND HAVE_ACL_LIBACL_H AND HAVE_LIBACL AND HAVE_ACL_GET_PERM) SET(ARCHIVE_ACL_LIBACL TRUE) ELSE() CHECK_FUNCTION_EXISTS(acl_add_flag_np HAVE_ACL_ADD_FLAG_NP) CHECK_FUNCTION_EXISTS(acl_clear_flags_np HAVE_ACL_CLEAR_FLAGS_NP) CHECK_FUNCTION_EXISTS(acl_get_brand_np HAVE_ACL_GET_BRAND_NP) CHECK_FUNCTION_EXISTS(acl_get_entry_type_np HAVE_ACL_GET_ENTRY_TYPE_NP) CHECK_FUNCTION_EXISTS(acl_get_flag_np HAVE_ACL_GET_FLAG_NP) CHECK_FUNCTION_EXISTS(acl_get_flagset_np HAVE_ACL_GET_FLAGSET_NP) CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP) CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP) CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP) CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP) CHECK_FUNCTION_EXISTS(acl_set_entry_type_np HAVE_ACL_SET_ENTRY_TYPE_NP) CHECK_FUNCTION_EXISTS(acl_set_fd_np HAVE_ACL_SET_FD_NP) CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP) CHECK_FUNCTION_EXISTS(mbr_gid_to_uuid HAVE_MBR_GID_TO_UUID) CHECK_FUNCTION_EXISTS(mbr_uid_to_uuid HAVE_MBR_UID_TO_UUID) CHECK_FUNCTION_EXISTS(mbr_uuid_to_id HAVE_MBR_UUID_TO_ID) CHECK_C_SOURCE_COMPILES("#include #include int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_DECL_ACL_TYPE_EXTENDED) CHECK_C_SOURCE_COMPILES("#include #include int main(void) { return ACL_SYNCHRONIZE; }" HAVE_DECL_ACL_SYNCHRONIZE) CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "sys/acl.h" HAVE_DECL_ACL_TYPE_NFS4) CHECK_SYMBOL_EXISTS(ACL_USER "sys/acl.h" HAVE_DECL_ACL_USER) IF(HAVE_POSIX_ACL_FUNCS AND HAVE_ACL_GET_FD_NP AND HAVE_ACL_GET_PERM_NP AND NOT HAVE_ACL_GET_PERM AND HAVE_ACL_SET_FD_NP) IF(HAVE_DECL_ACL_USER) SET(ARCHIVE_ACL_FREEBSD TRUE) IF(HAVE_DECL_ACL_TYPE_NFS4 AND HAVE_ACL_ADD_FLAG_NP AND HAVE_ACL_CLEAR_FLAGS_NP AND HAVE_ACL_GET_BRAND_NP AND HAVE_ACL_GET_ENTRY_TYPE_NP AND HAVE_ACL_GET_FLAGSET_NP AND HAVE_ACL_SET_ENTRY_TYPE_NP) SET(ARCHIVE_ACL_FREEBSD_NFS4 TRUE) ENDIF() ELSEIF(HAVE_DECL_ACL_TYPE_EXTENDED AND HAVE_MEMBERSHIP_H AND HAVE_ACL_ADD_FLAG_NP AND HAVE_ACL_CLEAR_FLAGS_NP AND HAVE_ACL_GET_FLAGSET_NP AND HAVE_ACL_GET_LINK_NP AND HAVE_ACL_SET_LINK_NP AND HAVE_MBR_UID_TO_UUID AND HAVE_MBR_GID_TO_UUID AND HAVE_MBR_UUID_TO_ID) SET(ARCHIVE_ACL_DARWIN TRUE) ENDIF() ENDIF() ENDIF() ENDIF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND HAVE_ACL_TAG_T) # Richacl CHECK_LIBRARY_EXISTS(richacl "richacl_get_file" "" HAVE_LIBRICHACL) IF(HAVE_LIBRICHACL) SET(CMAKE_REQUIRED_LIBRARIES "richacl") FIND_LIBRARY(RICHACL_LIBRARY NAMES richacl) LIST(APPEND ADDITIONAL_LIBS ${RICHACL_LIBRARY}) ENDIF(HAVE_LIBRICHACL) CHECK_STRUCT_HAS_MEMBER("struct richace" e_type "sys/richacl.h" HAVE_STRUCT_RICHACE) CHECK_STRUCT_HAS_MEMBER("struct richacl" a_flags "sys/richacl.h" HAVE_STRUCT_RICHACL) IF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE) CHECK_FUNCTION_EXISTS_GLIBC(richacl_alloc HAVE_RICHACL_ALLOC) CHECK_FUNCTION_EXISTS_GLIBC(richacl_equiv_mode HAVE_RICHACL_EQUIV_MODE) CHECK_FUNCTION_EXISTS_GLIBC(richacl_free HAVE_RICHACL_FREE) CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_fd HAVE_RICHACL_GET_FD) CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_file HAVE_RICHACL_GET_FILE) CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_fd HAVE_RICHACL_SET_FD) CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_file HAVE_RICHACL_SET_FILE) IF(HAVE_RICHACL_ALLOC AND HAVE_RICHACL_EQUIV_MODE AND HAVE_RICHACL_FREE AND HAVE_RICHACL_GET_FD AND HAVE_RICHACL_GET_FILE AND HAVE_RICHACL_SET_FD AND HAVE_RICHACL_SET_FILE) SET(ARCHIVE_ACL_LIBRICHACL TRUE) ENDIF() ENDIF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE) IF(ARCHIVE_ACL_DARWIN) MESSAGE(STATUS "ACL support: Darwin (limited NFSv4)") ELSEIF(ARCHIVE_ACL_FREEBSD_NFS4) MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e and NFSv4)") ELSEIF(ARCHIVE_ACL_FREEBSD) MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e)") ELSEIF(ARCHIVE_ACL_LIBACL OR ARCHIVE_ACL_LIBRICHACL) IF(ARCHIVE_ACL_LIBACL AND ARCHIVE_ACL_LIBRICHACL) MESSAGE(STATUS "ACL support: libacl (POSIX.1e) + librichacl (NFSv4)") ELSEIF(ARCHIVE_ACL_LIBRICHACL) MESSAGE(STATUS "ACL support: librichacl (NFSv4)") ELSE() MESSAGE(STATUS "ACL support: libacl (POSIX.1e)") ENDIF() ELSEIF(ARCHIVE_ACL_SUNOS_NFS4) MESSAGE(STATUS "ACL support: Solaris (POSIX.1e and NFSv4)") ELSEIF(ARCHIVE_ACL_SUNOS) MESSAGE(STATUS "ACL support: Solaris (POSIX.1e)") ELSE() MESSAGE(STATUS "ACL support: none") ENDIF() ELSE(ENABLE_ACL) # If someone runs cmake, then disables ACL support, we need # to forcibly override the cached values for these. SET(ARCHIVE_ACL_DARWIN FALSE) SET(ARCHIVE_ACL_FREEBSD FALSE) SET(ARCHIVE_ACL_FREEBSD_NFS4 FALSE) SET(ARCHIVE_ACL_LIBACL FALSE) SET(ARCHIVE_ACL_SUNOS FALSE) SET(ARCHIVE_ACL_SUNOS_NFS4 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) # Handle generation of the libarchive.pc file for pkg-config INCLUDE(CreatePkgConfigFile) # # 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) IF(ENABLE_TEST) ADD_CUSTOM_TARGET(run_all_tests) ENDIF(ENABLE_TEST) add_subdirectory(libarchive) add_subdirectory(cat) add_subdirectory(tar) add_subdirectory(cpio) Index: vendor/libarchive/dist/Makefile.am =================================================================== --- vendor/libarchive/dist/Makefile.am (revision 315874) +++ vendor/libarchive/dist/Makefile.am (revision 315875) @@ -1,1315 +1,1318 @@ ## Process this file with automake to produce Makefile.in AUTOMAKE_OPTIONS= foreign subdir-objects ACLOCAL_AMFLAGS = -I build/autoconf # # What to build and install # lib_LTLIBRARIES= libarchive.la noinst_LTLIBRARIES= libarchive_fe.la bin_PROGRAMS= $(bsdtar_programs) $(bsdcpio_programs) $(bsdcat_programs) man_MANS= $(libarchive_man_MANS) $(bsdtar_man_MANS) $(bsdcpio_man_MANS) $(bsdcat_man_MANS) BUILT_SOURCES= libarchive/test/list.h tar/test/list.h cpio/test/list.h cat/test/list.h # # What to test: We always test libarchive, test bsdtar and bsdcpio only # if we built them. # check_PROGRAMS= libarchive_test $(bsdtar_test_programs) $(bsdcpio_test_programs) $(bsdcat_test_programs) TESTS= libarchive_test $(bsdtar_test_programs) $(bsdcpio_test_programs) $(bsdcat_test_programs) TESTS_ENVIRONMENT= $(libarchive_TESTS_ENVIRONMENT) $(bsdtar_TESTS_ENVIRONMENT) $(bsdcpio_TESTS_ENVIRONMENT) $(bsdcat_TESTS_ENVIRONMENT) # Always build and test both bsdtar and bsdcpio as part of 'distcheck' DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio # The next line is commented out by default in shipping libarchive releases. # It is uncommented by default in trunk. DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g AM_CFLAGS=$(DEV_CFLAGS) PLATFORMCPPFLAGS = @PLATFORMCPPFLAGS@ AM_CPPFLAGS=$(PLATFORMCPPFLAGS) # # What to include in the distribution # EXTRA_DIST= \ CMakeLists.txt \ README.md \ build/autogen.sh \ build/bump-version.sh \ build/clean.sh \ build/cmake \ build/version \ contrib \ doc \ examples \ $(libarchive_EXTRA_DIST) \ $(libarchive_test_EXTRA_DIST) \ $(bsdtar_EXTRA_DIST) \ $(bsdtar_test_EXTRA_DIST) \ $(bsdcpio_EXTRA_DIST) \ $(bsdcpio_test_EXTRA_DIST) \ $(bsdcat_EXTRA_DIST) \ $(bsdcat_test_EXTRA_DIST) # a) Clean out some unneeded files and directories # b) Collect all documentation and format it for distribution. dist-hook: rm -rf `find $(distdir) -name CVS -type d` rm -rf `find $(distdir) -name .svn -type d` rm -f `find $(distdir) -name '*~'` rm -f `find $(distdir) -name '*.out'` rm -f `find $(distdir) -name '*.core'` -rm -f $(distdir)/*/Makefile $(distdir)/*/*/Makefile cd $(distdir)/doc && /bin/sh update.sh # # Extra rules for cleanup # DISTCLEANFILES= \ libarchive/test/list.h \ tar/test/list.h \ cpio/test/list.h \ cat/test/list.h distclean-local: -rm -rf .ref -rm -rf autom4te.cache/ -rm -f *~ -[ -f libarchive/Makefile ] && cd libarchive && make clean -[ -f libarchive/test/Makefile ] && cd libarchive/test && make clean -[ -f tar/Makefile ] && cd tar && make clean -[ -f tar/test/Makefile ] && cd tar/test && make clean -[ -f cpio/Makefile ] && cd cpio && make clean -[ -f cpio/test/Makefile ] && cd cpio/test && make clean -[ -f cat/Makefile ] && cd cat && make clean -[ -f cpio/test/Makefile ] && cd cat/test && make clean # # Libarchive headers, source, etc. # # include_HEADERS= libarchive/archive.h libarchive/archive_entry.h libarchive_la_SOURCES= \ libarchive/archive_acl.c \ libarchive/archive_acl_private.h \ libarchive/archive_check_magic.c \ libarchive/archive_cmdline.c \ libarchive/archive_cmdline_private.h \ libarchive/archive_crc32.h \ libarchive/archive_cryptor.c \ libarchive/archive_cryptor_private.h \ libarchive/archive_digest.c \ libarchive/archive_digest_private.h \ libarchive/archive_endian.h \ libarchive/archive_entry.c \ libarchive/archive_entry.h \ libarchive/archive_entry_copy_stat.c \ libarchive/archive_entry_link_resolver.c \ libarchive/archive_entry_locale.h \ libarchive/archive_entry_private.h \ libarchive/archive_entry_sparse.c \ libarchive/archive_entry_stat.c \ libarchive/archive_entry_strmode.c \ libarchive/archive_entry_xattr.c \ libarchive/archive_getdate.c \ libarchive/archive_getdate.h \ libarchive/archive_hmac.c \ libarchive/archive_hmac_private.h \ libarchive/archive_match.c \ libarchive/archive_openssl_evp_private.h \ libarchive/archive_openssl_hmac_private.h \ libarchive/archive_options.c \ libarchive/archive_options_private.h \ libarchive/archive_pack_dev.h \ libarchive/archive_pack_dev.c \ libarchive/archive_pathmatch.c \ libarchive/archive_pathmatch.h \ libarchive/archive_platform.h \ libarchive/archive_platform_acl.h \ + libarchive/archive_platform_xattr.h \ libarchive/archive_ppmd_private.h \ libarchive/archive_ppmd7.c \ libarchive/archive_ppmd7_private.h \ libarchive/archive_private.h \ libarchive/archive_random.c \ libarchive/archive_random_private.h \ libarchive/archive_rb.c \ libarchive/archive_rb.h \ libarchive/archive_read.c \ libarchive/archive_read_add_passphrase.c \ libarchive/archive_read_append_filter.c \ libarchive/archive_read_data_into_fd.c \ libarchive/archive_read_disk_entry_from_file.c \ libarchive/archive_read_disk_posix.c \ libarchive/archive_read_disk_private.h \ libarchive/archive_read_disk_set_standard_lookup.c \ libarchive/archive_read_extract.c \ libarchive/archive_read_extract2.c \ libarchive/archive_read_open_fd.c \ libarchive/archive_read_open_file.c \ libarchive/archive_read_open_filename.c \ libarchive/archive_read_open_memory.c \ libarchive/archive_read_private.h \ libarchive/archive_read_set_format.c \ libarchive/archive_read_set_options.c \ libarchive/archive_read_support_filter_all.c \ libarchive/archive_read_support_filter_bzip2.c \ libarchive/archive_read_support_filter_compress.c \ libarchive/archive_read_support_filter_grzip.c \ libarchive/archive_read_support_filter_gzip.c \ libarchive/archive_read_support_filter_lrzip.c \ libarchive/archive_read_support_filter_lz4.c \ libarchive/archive_read_support_filter_lzop.c \ libarchive/archive_read_support_filter_none.c \ libarchive/archive_read_support_filter_program.c \ libarchive/archive_read_support_filter_rpm.c \ libarchive/archive_read_support_filter_uu.c \ libarchive/archive_read_support_filter_xz.c \ libarchive/archive_read_support_format_7zip.c \ libarchive/archive_read_support_format_all.c \ libarchive/archive_read_support_format_ar.c \ libarchive/archive_read_support_format_by_code.c \ libarchive/archive_read_support_format_cab.c \ libarchive/archive_read_support_format_cpio.c \ libarchive/archive_read_support_format_empty.c \ libarchive/archive_read_support_format_iso9660.c \ libarchive/archive_read_support_format_lha.c \ libarchive/archive_read_support_format_mtree.c \ libarchive/archive_read_support_format_rar.c \ libarchive/archive_read_support_format_raw.c \ libarchive/archive_read_support_format_tar.c \ libarchive/archive_read_support_format_warc.c \ libarchive/archive_read_support_format_xar.c \ libarchive/archive_read_support_format_zip.c \ libarchive/archive_string.c \ libarchive/archive_string.h \ libarchive/archive_string_composition.h \ libarchive/archive_string_sprintf.c \ libarchive/archive_util.c \ libarchive/archive_version_details.c \ libarchive/archive_virtual.c \ libarchive/archive_write.c \ libarchive/archive_write_disk_posix.c \ libarchive/archive_write_disk_private.h \ libarchive/archive_write_disk_set_standard_lookup.c \ libarchive/archive_write_open_fd.c \ libarchive/archive_write_open_file.c \ libarchive/archive_write_open_filename.c \ libarchive/archive_write_open_memory.c \ libarchive/archive_write_private.h \ libarchive/archive_write_add_filter.c \ libarchive/archive_write_add_filter_b64encode.c \ libarchive/archive_write_add_filter_by_name.c \ libarchive/archive_write_add_filter_bzip2.c \ libarchive/archive_write_add_filter_compress.c \ libarchive/archive_write_add_filter_grzip.c \ libarchive/archive_write_add_filter_gzip.c \ libarchive/archive_write_add_filter_lrzip.c \ libarchive/archive_write_add_filter_lz4.c \ libarchive/archive_write_add_filter_lzop.c \ libarchive/archive_write_add_filter_none.c \ libarchive/archive_write_add_filter_program.c \ libarchive/archive_write_add_filter_uuencode.c \ libarchive/archive_write_add_filter_xz.c \ libarchive/archive_write_set_format.c \ libarchive/archive_write_set_format_7zip.c \ libarchive/archive_write_set_format_ar.c \ libarchive/archive_write_set_format_by_name.c \ libarchive/archive_write_set_format_cpio.c \ libarchive/archive_write_set_format_cpio_newc.c \ libarchive/archive_write_set_format_filter_by_ext.c \ libarchive/archive_write_set_format_iso9660.c \ libarchive/archive_write_set_format_mtree.c \ libarchive/archive_write_set_format_pax.c \ libarchive/archive_write_set_format_raw.c \ libarchive/archive_write_set_format_shar.c \ libarchive/archive_write_set_format_ustar.c \ libarchive/archive_write_set_format_v7tar.c \ libarchive/archive_write_set_format_gnutar.c \ libarchive/archive_write_set_format_warc.c \ libarchive/archive_write_set_format_xar.c \ libarchive/archive_write_set_format_zip.c \ libarchive/archive_write_set_options.c \ libarchive/archive_write_set_passphrase.c \ libarchive/archive_xxhash.h \ libarchive/config_freebsd.h \ libarchive/filter_fork_posix.c \ libarchive/filter_fork.h \ libarchive/xxhash.c if INC_WINDOWS_FILES libarchive_la_SOURCES+= \ libarchive/archive_entry_copy_bhfi.c \ libarchive/archive_read_disk_windows.c \ libarchive/archive_windows.h \ libarchive/archive_windows.c \ libarchive/archive_write_disk_windows.c \ libarchive/filter_fork_windows.c endif if INC_LINUX_ACL libarchive_la_SOURCES+= \ libarchive/archive_acl_maps.h \ libarchive/archive_acl_maps_linux.c \ libarchive/archive_read_disk_acl_linux.c \ libarchive/archive_write_disk_acl_linux.c else if INC_SUNOS_ACL libarchive_la_SOURCES+= \ libarchive/archive_acl_maps.h \ libarchive/archive_acl_maps_sunos.c \ libarchive/archive_read_disk_acl_sunos.c \ libarchive/archive_write_disk_acl_sunos.c else if INC_DARWIN_ACL libarchive_la_SOURCES+= \ libarchive/archive_acl_maps.h \ libarchive/archive_acl_maps_darwin.c \ libarchive/archive_read_disk_acl_darwin.c \ libarchive/archive_write_disk_acl_darwin.c else if INC_FREEBSD_ACL libarchive_la_SOURCES+= \ libarchive/archive_acl_maps.h \ libarchive/archive_acl_maps_freebsd.c \ libarchive/archive_read_disk_acl_freebsd.c \ libarchive/archive_write_disk_acl_freebsd.c endif endif endif endif # -no-undefined marks that libarchive doesn't rely on symbols # defined in the application. This is mandatory for cygwin. libarchive_la_LDFLAGS= -no-undefined -version-info $(ARCHIVE_LIBTOOL_VERSION) libarchive_la_LIBADD= $(LTLIBICONV) # Manpages to install libarchive_man_MANS= \ libarchive/archive_entry.3 \ libarchive/archive_entry_acl.3 \ libarchive/archive_entry_linkify.3 \ libarchive/archive_entry_paths.3 \ libarchive/archive_entry_perms.3 \ libarchive/archive_entry_stat.3 \ libarchive/archive_entry_time.3 \ libarchive/archive_read.3 \ libarchive/archive_read_add_passphrase.3 \ libarchive/archive_read_data.3 \ libarchive/archive_read_disk.3 \ libarchive/archive_read_extract.3 \ libarchive/archive_read_filter.3 \ libarchive/archive_read_format.3 \ libarchive/archive_read_free.3 \ libarchive/archive_read_header.3 \ libarchive/archive_read_new.3 \ libarchive/archive_read_open.3 \ libarchive/archive_read_set_options.3 \ libarchive/archive_util.3 \ libarchive/archive_write.3 \ libarchive/archive_write_blocksize.3 \ libarchive/archive_write_data.3 \ libarchive/archive_write_disk.3 \ libarchive/archive_write_filter.3 \ libarchive/archive_write_finish_entry.3 \ libarchive/archive_write_format.3 \ libarchive/archive_write_free.3 \ libarchive/archive_write_header.3 \ libarchive/archive_write_new.3 \ libarchive/archive_write_open.3 \ libarchive/archive_write_set_options.3 \ libarchive/archive_write_set_passphrase.3 \ libarchive/cpio.5 \ libarchive/libarchive.3 \ libarchive/libarchive_changes.3 \ libarchive/libarchive_internals.3 \ libarchive/libarchive-formats.5 \ libarchive/mtree.5 \ libarchive/tar.5 # Additional libarchive files to include in the distribution libarchive_EXTRA_DIST= \ libarchive/archive_windows.c \ libarchive/archive_windows.h \ libarchive/filter_fork_windows.c \ libarchive/CMakeLists.txt \ $(libarchive_man_MANS) # pkgconfig pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = build/pkgconfig/libarchive.pc # Sources needed by all test programs test_utils_SOURCES= \ test_utils/test_utils.c \ test_utils/test_utils.h \ test_utils/test_main.c \ test_utils/test_common.h # # # libarchive_test program # # libarchive_test_SOURCES= \ $(libarchive_la_SOURCES) \ $(test_utils_SOURCES) \ libarchive/test/read_open_memory.c \ libarchive/test/test.h \ libarchive/test/test_acl_nfs4.c \ libarchive/test/test_acl_pax.c \ libarchive/test/test_acl_platform_nfs4.c \ libarchive/test/test_acl_platform_posix1e.c \ libarchive/test/test_acl_posix1e.c \ libarchive/test/test_acl_text.c \ libarchive/test/test_archive_api_feature.c \ libarchive/test/test_archive_clear_error.c \ libarchive/test/test_archive_cmdline.c \ libarchive/test/test_archive_digest.c \ libarchive/test/test_archive_getdate.c \ libarchive/test/test_archive_match_owner.c \ libarchive/test/test_archive_match_path.c \ libarchive/test/test_archive_match_time.c \ libarchive/test/test_archive_pathmatch.c \ libarchive/test/test_archive_read_add_passphrase.c \ libarchive/test/test_archive_read_close_twice.c \ libarchive/test/test_archive_read_close_twice_open_fd.c \ libarchive/test/test_archive_read_close_twice_open_filename.c \ libarchive/test/test_archive_read_multiple_data_objects.c \ libarchive/test/test_archive_read_next_header_empty.c \ libarchive/test/test_archive_read_next_header_raw.c \ libarchive/test/test_archive_read_open2.c \ libarchive/test/test_archive_read_set_filter_option.c \ libarchive/test/test_archive_read_set_format_option.c \ libarchive/test/test_archive_read_set_option.c \ libarchive/test/test_archive_read_set_options.c \ libarchive/test/test_archive_read_support.c \ libarchive/test/test_archive_set_error.c \ libarchive/test/test_archive_string.c \ libarchive/test/test_archive_string_conversion.c \ libarchive/test/test_archive_write_add_filter_by_name.c \ libarchive/test/test_archive_write_set_filter_option.c \ libarchive/test/test_archive_write_set_format_by_name.c \ libarchive/test/test_archive_write_set_format_filter_by_ext.c \ libarchive/test/test_archive_write_set_format_option.c \ libarchive/test/test_archive_write_set_option.c \ libarchive/test/test_archive_write_set_options.c \ libarchive/test/test_archive_write_set_passphrase.c \ libarchive/test/test_bad_fd.c \ libarchive/test/test_compat_bzip2.c \ libarchive/test/test_compat_cpio.c \ libarchive/test/test_compat_gtar.c \ libarchive/test/test_compat_gzip.c \ libarchive/test/test_compat_lz4.c \ libarchive/test/test_compat_lzip.c \ libarchive/test/test_compat_lzma.c \ libarchive/test/test_compat_lzop.c \ libarchive/test/test_compat_mac.c \ libarchive/test/test_compat_pax_libarchive_2x.c \ libarchive/test/test_compat_perl_archive_tar.c \ libarchive/test/test_compat_plexus_archiver_tar.c \ libarchive/test/test_compat_solaris_tar_acl.c \ libarchive/test/test_compat_solaris_pax_sparse.c \ libarchive/test/test_compat_star_acl.c \ libarchive/test/test_compat_tar_hardlink.c \ libarchive/test/test_compat_uudecode.c \ libarchive/test/test_compat_uudecode_large.c \ libarchive/test/test_compat_xz.c \ libarchive/test/test_compat_zip.c \ libarchive/test/test_empty_write.c \ libarchive/test/test_entry.c \ libarchive/test/test_entry_strmode.c \ libarchive/test/test_extattr_freebsd.c \ libarchive/test/test_filter_count.c \ libarchive/test/test_fuzz.c \ libarchive/test/test_gnutar_filename_encoding.c \ libarchive/test/test_link_resolver.c \ libarchive/test/test_open_failure.c \ libarchive/test/test_open_fd.c \ libarchive/test/test_open_file.c \ libarchive/test/test_open_filename.c \ libarchive/test/test_pax_filename_encoding.c \ libarchive/test/test_read_data_large.c \ libarchive/test/test_read_disk.c \ libarchive/test/test_read_disk_directory_traversals.c \ libarchive/test/test_read_disk_entry_from_file.c \ libarchive/test/test_read_extract.c \ libarchive/test/test_read_file_nonexistent.c \ libarchive/test/test_read_filter_compress.c \ libarchive/test/test_read_filter_grzip.c \ libarchive/test/test_read_filter_lrzip.c \ libarchive/test/test_read_filter_lzop.c \ libarchive/test/test_read_filter_lzop_multiple_parts.c \ libarchive/test/test_read_filter_program.c \ libarchive/test/test_read_filter_program_signature.c \ libarchive/test/test_read_filter_uudecode.c \ libarchive/test/test_read_format_7zip.c \ libarchive/test/test_read_format_7zip_encryption_data.c \ libarchive/test/test_read_format_7zip_encryption_partially.c \ libarchive/test/test_read_format_7zip_encryption_header.c \ libarchive/test/test_read_format_7zip_malformed.c \ libarchive/test/test_read_format_ar.c \ libarchive/test/test_read_format_cab.c \ libarchive/test/test_read_format_cab_filename.c \ libarchive/test/test_read_format_cpio_afio.c \ libarchive/test/test_read_format_cpio_bin.c \ libarchive/test/test_read_format_cpio_bin_Z.c \ libarchive/test/test_read_format_cpio_bin_be.c \ libarchive/test/test_read_format_cpio_bin_bz2.c \ libarchive/test/test_read_format_cpio_bin_gz.c \ libarchive/test/test_read_format_cpio_bin_le.c \ libarchive/test/test_read_format_cpio_bin_lzip.c \ libarchive/test/test_read_format_cpio_bin_lzma.c \ libarchive/test/test_read_format_cpio_bin_xz.c \ libarchive/test/test_read_format_cpio_filename.c \ libarchive/test/test_read_format_cpio_odc.c \ libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c \ libarchive/test/test_read_format_cpio_svr4_gzip.c \ libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c \ libarchive/test/test_read_format_cpio_svr4c_Z.c \ libarchive/test/test_read_format_empty.c \ libarchive/test/test_read_format_gtar_filename.c \ libarchive/test/test_read_format_gtar_gz.c \ libarchive/test/test_read_format_gtar_lzma.c \ libarchive/test/test_read_format_gtar_sparse.c \ libarchive/test/test_read_format_gtar_sparse_skip_entry.c \ libarchive/test/test_read_format_iso_Z.c \ libarchive/test/test_read_format_iso_multi_extent.c \ libarchive/test/test_read_format_iso_xorriso.c \ libarchive/test/test_read_format_isojoliet_bz2.c \ libarchive/test/test_read_format_isojoliet_long.c \ libarchive/test/test_read_format_isojoliet_rr.c \ libarchive/test/test_read_format_isojoliet_versioned.c \ libarchive/test/test_read_format_isorr_bz2.c \ libarchive/test/test_read_format_isorr_ce.c \ libarchive/test/test_read_format_isorr_new_bz2.c \ libarchive/test/test_read_format_isorr_rr_moved.c \ libarchive/test/test_read_format_isozisofs_bz2.c \ libarchive/test/test_read_format_lha.c \ libarchive/test/test_read_format_lha_bugfix_0.c \ libarchive/test/test_read_format_lha_filename.c \ libarchive/test/test_read_format_mtree.c \ libarchive/test/test_read_format_mtree_crash747.c \ libarchive/test/test_read_format_pax_bz2.c \ libarchive/test/test_read_format_rar.c \ libarchive/test/test_read_format_rar_encryption_data.c \ libarchive/test/test_read_format_rar_encryption_partially.c \ libarchive/test/test_read_format_rar_encryption_header.c \ libarchive/test/test_read_format_rar_invalid1.c \ libarchive/test/test_read_format_raw.c \ libarchive/test/test_read_format_tar.c \ libarchive/test/test_read_format_tar_concatenated.c \ libarchive/test/test_read_format_tar_empty_pax.c \ libarchive/test/test_read_format_tar_empty_filename.c \ libarchive/test/test_read_format_tar_filename.c \ libarchive/test/test_read_format_tbz.c \ libarchive/test/test_read_format_tgz.c \ libarchive/test/test_read_format_tlz.c \ libarchive/test/test_read_format_txz.c \ libarchive/test/test_read_format_tz.c \ libarchive/test/test_read_format_ustar_filename.c \ libarchive/test/test_read_format_warc.c \ libarchive/test/test_read_format_xar.c \ libarchive/test/test_read_format_zip.c \ libarchive/test/test_read_format_zip_comment_stored.c \ libarchive/test/test_read_format_zip_encryption_data.c \ libarchive/test/test_read_format_zip_encryption_partially.c \ libarchive/test/test_read_format_zip_encryption_header.c \ libarchive/test/test_read_format_zip_filename.c \ libarchive/test/test_read_format_zip_high_compression.c \ libarchive/test/test_read_format_zip_jar.c \ libarchive/test/test_read_format_zip_mac_metadata.c \ libarchive/test/test_read_format_zip_malformed.c \ libarchive/test/test_read_format_zip_msdos.c \ libarchive/test/test_read_format_zip_nested.c \ libarchive/test/test_read_format_zip_nofiletype.c \ libarchive/test/test_read_format_zip_padded.c \ libarchive/test/test_read_format_zip_sfx.c \ libarchive/test/test_read_format_zip_traditional_encryption_data.c \ libarchive/test/test_read_format_zip_winzip_aes.c \ libarchive/test/test_read_format_zip_winzip_aes_large.c \ libarchive/test/test_read_format_zip_zip64.c \ libarchive/test/test_read_large.c \ libarchive/test/test_read_pax_schily_xattr.c \ libarchive/test/test_read_pax_truncated.c \ libarchive/test/test_read_position.c \ libarchive/test/test_read_set_format.c \ libarchive/test/test_read_too_many_filters.c \ libarchive/test/test_read_truncated.c \ libarchive/test/test_read_truncated_filter.c \ libarchive/test/test_sparse_basic.c \ libarchive/test/test_tar_filenames.c \ libarchive/test/test_tar_large.c \ libarchive/test/test_ustar_filenames.c \ libarchive/test/test_ustar_filename_encoding.c \ libarchive/test/test_warn_missing_hardlink_target.c \ libarchive/test/test_write_disk.c \ libarchive/test/test_write_disk_appledouble.c \ libarchive/test/test_write_disk_failures.c \ libarchive/test/test_write_disk_hardlink.c \ libarchive/test/test_write_disk_hfs_compression.c \ libarchive/test/test_write_disk_lookup.c \ libarchive/test/test_write_disk_mac_metadata.c \ libarchive/test/test_write_disk_no_hfs_compression.c \ libarchive/test/test_write_disk_perms.c \ libarchive/test/test_write_disk_secure.c \ libarchive/test/test_write_disk_secure744.c \ libarchive/test/test_write_disk_secure745.c \ libarchive/test/test_write_disk_secure746.c \ libarchive/test/test_write_disk_sparse.c \ libarchive/test/test_write_disk_symlink.c \ libarchive/test/test_write_disk_times.c \ libarchive/test/test_write_filter_b64encode.c \ libarchive/test/test_write_filter_bzip2.c \ libarchive/test/test_write_filter_compress.c \ libarchive/test/test_write_filter_gzip.c \ libarchive/test/test_write_filter_gzip_timestamp.c \ libarchive/test/test_write_filter_lrzip.c \ libarchive/test/test_write_filter_lz4.c \ libarchive/test/test_write_filter_lzip.c \ libarchive/test/test_write_filter_lzma.c \ libarchive/test/test_write_filter_lzop.c \ libarchive/test/test_write_filter_program.c \ libarchive/test/test_write_filter_uuencode.c \ libarchive/test/test_write_filter_xz.c \ libarchive/test/test_write_format_7zip.c \ libarchive/test/test_write_format_7zip_empty.c \ libarchive/test/test_write_format_7zip_large.c \ libarchive/test/test_write_format_ar.c \ libarchive/test/test_write_format_cpio.c \ libarchive/test/test_write_format_cpio_empty.c \ libarchive/test/test_write_format_cpio_newc.c \ libarchive/test/test_write_format_cpio_odc.c \ libarchive/test/test_write_format_gnutar.c \ libarchive/test/test_write_format_gnutar_filenames.c \ libarchive/test/test_write_format_iso9660.c \ libarchive/test/test_write_format_iso9660_boot.c \ libarchive/test/test_write_format_iso9660_empty.c \ libarchive/test/test_write_format_iso9660_filename.c \ libarchive/test/test_write_format_iso9660_zisofs.c \ libarchive/test/test_write_format_mtree.c \ libarchive/test/test_write_format_mtree_absolute_path.c \ libarchive/test/test_write_format_mtree_classic.c \ libarchive/test/test_write_format_mtree_classic_indent.c\ libarchive/test/test_write_format_mtree_fflags.c \ libarchive/test/test_write_format_mtree_no_separator.c \ libarchive/test/test_write_format_mtree_quoted_filename.c\ libarchive/test/test_write_format_pax.c \ libarchive/test/test_write_format_raw.c \ libarchive/test/test_write_format_raw_b64.c \ libarchive/test/test_write_format_shar_empty.c \ libarchive/test/test_write_format_tar.c \ libarchive/test/test_write_format_tar_empty.c \ libarchive/test/test_write_format_tar_sparse.c \ libarchive/test/test_write_format_tar_ustar.c \ libarchive/test/test_write_format_tar_v7tar.c \ libarchive/test/test_write_format_warc.c \ libarchive/test/test_write_format_warc_empty.c \ libarchive/test/test_write_format_xar.c \ libarchive/test/test_write_format_xar_empty.c \ libarchive/test/test_write_format_zip.c \ libarchive/test/test_write_format_zip_compression_store.c \ libarchive/test/test_write_format_zip_empty.c \ libarchive/test/test_write_format_zip_empty_zip64.c \ libarchive/test/test_write_format_zip_file.c \ libarchive/test/test_write_format_zip_file_zip64.c \ libarchive/test/test_write_format_zip_large.c \ libarchive/test/test_write_format_zip_zip64.c \ libarchive/test/test_write_open_memory.c \ libarchive/test/test_write_read_format_zip.c \ + libarchive/test/test_xattr_platform.c \ libarchive/test/test_zip_filename_encoding.c libarchive_test_CPPFLAGS= \ -I$(top_srcdir)/libarchive \ -I$(top_srcdir)/libarchive/test \ -I$(top_srcdir)/test_utils \ -I$(top_builddir)/libarchive/test \ -DLIBARCHIVE_STATIC $(PLATFORMCPPFLAGS) libarchive_test_LDADD= $(LTLIBICONV) # The "list.h" file just lists all of the tests defined in all of the sources. # Building it automatically provides a sanity-check on libarchive_test_SOURCES # above. libarchive/test/list.h: Makefile $(MKDIR_P) libarchive/test cat $(top_srcdir)/libarchive/test/test_*.c | grep '^DEFINE_TEST' > libarchive/test/list.h libarchive_TESTS_ENVIRONMENT= LIBARCHIVE_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/libarchive/test LRZIP=NOCONFIG libarchive_test_EXTRA_DIST=\ libarchive/test/list.h \ libarchive/test/test_acl_pax_posix1e.tar.uu \ libarchive/test/test_acl_pax_nfs4.tar.uu \ libarchive/test/test_archive_string_conversion.txt.Z.uu \ libarchive/test/test_compat_bzip2_1.tbz.uu \ libarchive/test/test_compat_bzip2_2.tbz.uu \ libarchive/test/test_compat_cpio_1.cpio.uu \ libarchive/test/test_compat_gtar_1.tar.uu \ libarchive/test/test_compat_gtar_2.tar.uu \ libarchive/test/test_compat_gzip_1.tgz.uu \ libarchive/test/test_compat_gzip_2.tgz.uu \ libarchive/test/test_compat_lz4_1.tar.lz4.uu \ libarchive/test/test_compat_lz4_2.tar.lz4.uu \ libarchive/test/test_compat_lz4_3.tar.lz4.uu \ libarchive/test/test_compat_lz4_B4.tar.lz4.uu \ libarchive/test/test_compat_lz4_B4BD.tar.lz4.uu \ libarchive/test/test_compat_lz4_B4BDBX.tar.lz4.uu \ libarchive/test/test_compat_lz4_B5.tar.lz4.uu \ libarchive/test/test_compat_lz4_B5BD.tar.lz4.uu \ libarchive/test/test_compat_lz4_B6.tar.lz4.uu \ libarchive/test/test_compat_lz4_B6BD.tar.lz4.uu \ libarchive/test/test_compat_lz4_B7.tar.lz4.uu \ libarchive/test/test_compat_lz4_B7BD.tar.lz4.uu \ libarchive/test/test_compat_lzip_1.tlz.uu \ libarchive/test/test_compat_lzip_2.tlz.uu \ libarchive/test/test_compat_lzma_1.tlz.uu \ libarchive/test/test_compat_lzma_2.tlz.uu \ libarchive/test/test_compat_lzma_3.tlz.uu \ libarchive/test/test_compat_lzop_1.tar.lzo.uu \ libarchive/test/test_compat_lzop_2.tar.lzo.uu \ libarchive/test/test_compat_lzop_3.tar.lzo.uu \ libarchive/test/test_compat_mac-1.tar.Z.uu \ libarchive/test/test_compat_mac-2.tar.Z.uu \ libarchive/test/test_compat_pax_libarchive_2x.tar.Z.uu \ libarchive/test/test_compat_perl_archive_tar.tar.uu \ libarchive/test/test_compat_plexus_archiver_tar.tar.uu \ libarchive/test/test_compat_solaris_pax_sparse_1.pax.Z.uu \ libarchive/test/test_compat_solaris_pax_sparse_2.pax.Z.uu \ libarchive/test/test_compat_solaris_tar_acl.tar.uu \ libarchive/test/test_compat_star_acl_nfs4.tar.uu \ libarchive/test/test_compat_star_acl_posix1e.tar.uu \ libarchive/test/test_compat_tar_hardlink_1.tar.uu \ libarchive/test/test_compat_uudecode_large.tar.Z.uu \ libarchive/test/test_compat_xz_1.txz.uu \ libarchive/test/test_compat_zip_1.zip.uu \ libarchive/test/test_compat_zip_2.zip.uu \ libarchive/test/test_compat_zip_3.zip.uu \ libarchive/test/test_compat_zip_4.zip.uu \ libarchive/test/test_compat_zip_5.zip.uu \ libarchive/test/test_compat_zip_6.zip.uu \ libarchive/test/test_compat_zip_7.xps.uu \ libarchive/test/test_fuzz.cab.uu \ libarchive/test/test_fuzz.lzh.uu \ libarchive/test/test_fuzz_1.iso.Z.uu \ libarchive/test/test_pax_filename_encoding.tar.uu \ libarchive/test/test_rar_multivolume_multiple_files.part1.rar.uu \ libarchive/test/test_rar_multivolume_multiple_files.part2.rar.uu \ libarchive/test/test_rar_multivolume_multiple_files.part3.rar.uu \ libarchive/test/test_rar_multivolume_multiple_files.part4.rar.uu \ libarchive/test/test_rar_multivolume_multiple_files.part5.rar.uu \ libarchive/test/test_rar_multivolume_multiple_files.part6.rar.uu \ libarchive/test/test_rar_multivolume_single_file.part1.rar.uu \ libarchive/test/test_rar_multivolume_single_file.part2.rar.uu \ libarchive/test/test_rar_multivolume_single_file.part3.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part01.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part02.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part03.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part04.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part05.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part06.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part07.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part08.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part09.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part10.rar.uu \ libarchive/test/test_read_filter_grzip.tar.grz.uu \ libarchive/test/test_read_filter_lrzip.tar.lrz.uu \ libarchive/test/test_read_filter_lzop.tar.lzo.uu \ libarchive/test/test_read_filter_lzop_multiple_parts.tar.lzo.uu \ libarchive/test/test_read_format_mtree_crash747.mtree.bz2.uu \ libarchive/test/test_read_format_7zip_bcj2_bzip2.7z.uu \ libarchive/test/test_read_format_7zip_bcj2_copy_1.7z.uu \ libarchive/test/test_read_format_7zip_bcj2_copy_2.7z.uu \ libarchive/test/test_read_format_7zip_bcj2_copy_lzma.7z.uu \ libarchive/test/test_read_format_7zip_bcj2_deflate.7z.uu \ libarchive/test/test_read_format_7zip_bcj2_lzma1_1.7z.uu \ libarchive/test/test_read_format_7zip_bcj2_lzma1_2.7z.uu \ libarchive/test/test_read_format_7zip_bcj2_lzma2_1.7z.uu \ libarchive/test/test_read_format_7zip_bcj2_lzma2_2.7z.uu \ libarchive/test/test_read_format_7zip_bcj_bzip2.7z.uu \ libarchive/test/test_read_format_7zip_bcj_copy.7z.uu \ libarchive/test/test_read_format_7zip_bcj_deflate.7z.uu \ libarchive/test/test_read_format_7zip_bcj_lzma1.7z.uu \ libarchive/test/test_read_format_7zip_bcj_lzma2.7z.uu \ libarchive/test/test_read_format_7zip_bzip2.7z.uu \ libarchive/test/test_read_format_7zip_copy.7z.uu \ libarchive/test/test_read_format_7zip_copy_2.7z.uu \ libarchive/test/test_read_format_7zip_deflate.7z.uu \ libarchive/test/test_read_format_7zip_delta_lzma1.7z.uu \ libarchive/test/test_read_format_7zip_delta_lzma2.7z.uu \ libarchive/test/test_read_format_7zip_empty_archive.7z.uu \ libarchive/test/test_read_format_7zip_empty_file.7z.uu \ libarchive/test/test_read_format_7zip_encryption.7z.uu \ libarchive/test/test_read_format_7zip_encryption_header.7z.uu \ libarchive/test/test_read_format_7zip_encryption_partially.7z.uu \ libarchive/test/test_read_format_7zip_lzma1.7z.uu \ libarchive/test/test_read_format_7zip_lzma1_2.7z.uu \ libarchive/test/test_read_format_7zip_lzma1_lzma2.7z.uu \ libarchive/test/test_read_format_7zip_lzma2.7z.uu \ libarchive/test/test_read_format_7zip_malformed.7z.uu \ libarchive/test/test_read_format_7zip_malformed2.7z.uu \ libarchive/test/test_read_format_7zip_ppmd.7z.uu \ libarchive/test/test_read_format_7zip_symbolic_name.7z.uu \ libarchive/test/test_read_format_ar.ar.uu \ libarchive/test/test_read_format_cab_1.cab.uu \ libarchive/test/test_read_format_cab_2.cab.uu \ libarchive/test/test_read_format_cab_3.cab.uu \ libarchive/test/test_read_format_cab_filename_cp932.cab.uu \ libarchive/test/test_read_format_cpio_bin_be.cpio.uu \ libarchive/test/test_read_format_cpio_bin_le.cpio.uu \ libarchive/test/test_read_format_cpio_filename_cp866.cpio.uu \ libarchive/test/test_read_format_cpio_filename_eucjp.cpio.uu \ libarchive/test/test_read_format_cpio_filename_koi8r.cpio.uu \ libarchive/test/test_read_format_cpio_filename_utf8_jp.cpio.uu \ libarchive/test/test_read_format_cpio_filename_utf8_ru.cpio.uu \ libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.rpm.uu \ libarchive/test/test_read_format_cpio_svr4_gzip_rpm.rpm.uu \ libarchive/test/test_read_format_gtar_filename_cp866.tar.Z.uu \ libarchive/test/test_read_format_gtar_filename_eucjp.tar.Z.uu \ libarchive/test/test_read_format_gtar_filename_koi8r.tar.Z.uu \ libarchive/test/test_read_format_gtar_sparse_1_13.tar.uu \ libarchive/test/test_read_format_gtar_sparse_1_17.tar.uu \ libarchive/test/test_read_format_gtar_sparse_1_17_posix00.tar.uu \ libarchive/test/test_read_format_gtar_sparse_1_17_posix01.tar.uu \ libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tar.uu \ libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu \ libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu \ libarchive/test/test_read_format_iso.iso.Z.uu \ libarchive/test/test_read_format_iso_2.iso.Z.uu \ libarchive/test/test_read_format_iso_joliet.iso.Z.uu \ libarchive/test/test_read_format_iso_joliet_by_nero.iso.Z.uu \ libarchive/test/test_read_format_iso_joliet_long.iso.Z.uu \ libarchive/test/test_read_format_iso_joliet_rockridge.iso.Z.uu \ libarchive/test/test_read_format_iso_multi_extent.iso.Z.uu \ libarchive/test/test_read_format_iso_rockridge.iso.Z.uu \ libarchive/test/test_read_format_iso_rockridge_ce.iso.Z.uu \ libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu \ libarchive/test/test_read_format_iso_rockridge_rr_moved.iso.Z.uu \ libarchive/test/test_read_format_iso_xorriso.iso.Z.uu \ libarchive/test/test_read_format_iso_zisofs.iso.Z.uu \ libarchive/test/test_read_format_lha_bugfix_0.lzh.uu \ libarchive/test/test_read_format_lha_filename_cp932.lzh.uu \ libarchive/test/test_read_format_lha_header0.lzh.uu \ libarchive/test/test_read_format_lha_header1.lzh.uu \ libarchive/test/test_read_format_lha_header2.lzh.uu \ libarchive/test/test_read_format_lha_header3.lzh.uu \ libarchive/test/test_read_format_lha_lh0.lzh.uu \ libarchive/test/test_read_format_lha_lh6.lzh.uu \ libarchive/test/test_read_format_lha_lh7.lzh.uu \ libarchive/test/test_read_format_lha_withjunk.lzh.uu \ libarchive/test/test_read_format_mtree.mtree.uu \ libarchive/test/test_read_format_mtree_nomagic.mtree.uu \ libarchive/test/test_read_format_mtree_nomagic2.mtree.uu \ libarchive/test/test_read_format_mtree_nomagic3.mtree.uu \ libarchive/test/test_read_format_rar.rar.uu \ libarchive/test/test_read_format_rar_binary_data.rar.uu \ libarchive/test/test_read_format_rar_compress_best.rar.uu \ libarchive/test/test_read_format_rar_compress_normal.rar.uu \ libarchive/test/test_read_format_rar_encryption_data.rar.uu \ libarchive/test/test_read_format_rar_encryption_header.rar.uu \ libarchive/test/test_read_format_rar_encryption_partially.rar.uu \ libarchive/test/test_read_format_rar_invalid1.rar.uu \ libarchive/test/test_read_format_rar_multi_lzss_blocks.rar.uu \ libarchive/test/test_read_format_rar_multivolume.part0001.rar.uu \ libarchive/test/test_read_format_rar_multivolume.part0002.rar.uu \ libarchive/test/test_read_format_rar_multivolume.part0003.rar.uu \ libarchive/test/test_read_format_rar_multivolume.part0004.rar.uu \ libarchive/test/test_read_format_rar_noeof.rar.uu \ libarchive/test/test_read_format_rar_ppmd_lzss_conversion.rar.uu \ libarchive/test/test_read_format_rar_sfx.exe.uu \ libarchive/test/test_read_format_rar_subblock.rar.uu \ libarchive/test/test_read_format_rar_unicode.rar.uu \ libarchive/test/test_read_format_rar_windows.rar.uu \ libarchive/test/test_read_format_raw.bufr.uu \ libarchive/test/test_read_format_raw.data.Z.uu \ libarchive/test/test_read_format_raw.data.uu \ libarchive/test/test_read_format_tar_concatenated.tar.uu \ libarchive/test/test_read_format_tar_empty_filename.tar.uu \ libarchive/test/test_read_format_tar_empty_pax.tar.Z.uu \ libarchive/test/test_read_format_tar_filename_koi8r.tar.Z.uu \ libarchive/test/test_read_format_ustar_filename_cp866.tar.Z.uu \ libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu \ libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \ libarchive/test/test_read_format_warc.warc.uu \ libarchive/test/test_read_format_zip.zip.uu \ libarchive/test/test_read_format_zip_comment_stored_1.zip.uu \ libarchive/test/test_read_format_zip_comment_stored_2.zip.uu \ libarchive/test/test_read_format_zip_encryption_data.zip.uu \ libarchive/test/test_read_format_zip_encryption_header.zip.uu \ libarchive/test/test_read_format_zip_encryption_partially.zip.uu \ libarchive/test/test_read_format_zip_filename_cp866.zip.uu \ libarchive/test/test_read_format_zip_filename_cp932.zip.uu \ libarchive/test/test_read_format_zip_filename_koi8r.zip.uu \ libarchive/test/test_read_format_zip_filename_utf8_jp.zip.uu \ libarchive/test/test_read_format_zip_filename_utf8_ru.zip.uu \ libarchive/test/test_read_format_zip_filename_utf8_ru2.zip.uu \ libarchive/test/test_read_format_zip_high_compression.zip.uu \ libarchive/test/test_read_format_zip_length_at_end.zip.uu \ libarchive/test/test_read_format_zip_jar.jar.uu \ libarchive/test/test_read_format_zip_mac_metadata.zip.uu \ libarchive/test/test_read_format_zip_malformed1.zip.uu \ libarchive/test/test_read_format_zip_msdos.zip.uu \ libarchive/test/test_read_format_zip_nested.zip.uu \ libarchive/test/test_read_format_zip_nofiletype.zip.uu \ libarchive/test/test_read_format_zip_padded1.zip.uu \ libarchive/test/test_read_format_zip_padded2.zip.uu \ libarchive/test/test_read_format_zip_padded3.zip.uu \ libarchive/test/test_read_format_zip_sfx.uu \ libarchive/test/test_read_format_zip_symlink.zip.uu \ libarchive/test/test_read_format_zip_traditional_encryption_data.zip.uu \ libarchive/test/test_read_format_zip_ux.zip.uu \ libarchive/test/test_read_format_zip_winzip_aes128.zip.uu \ libarchive/test/test_read_format_zip_winzip_aes256.zip.uu \ libarchive/test/test_read_format_zip_winzip_aes256_large.zip.uu \ libarchive/test/test_read_format_zip_winzip_aes256_stored.zip.uu \ libarchive/test/test_read_format_zip_zip64a.zip.uu \ libarchive/test/test_read_format_zip_zip64b.zip.uu \ libarchive/test/test_read_large_splitted_rar_aa.uu \ libarchive/test/test_read_large_splitted_rar_ab.uu \ libarchive/test/test_read_large_splitted_rar_ac.uu \ libarchive/test/test_read_large_splitted_rar_ad.uu \ libarchive/test/test_read_large_splitted_rar_ae.uu \ libarchive/test/test_read_pax_schily_xattr.tar.uu \ libarchive/test/test_read_splitted_rar_aa.uu \ libarchive/test/test_read_splitted_rar_ab.uu \ libarchive/test/test_read_splitted_rar_ac.uu \ libarchive/test/test_read_splitted_rar_ad.uu \ libarchive/test/test_read_too_many_filters.gz.uu \ libarchive/test/test_splitted_rar_seek_support_aa.uu \ libarchive/test/test_splitted_rar_seek_support_ab.uu \ libarchive/test/test_splitted_rar_seek_support_ac.uu \ libarchive/test/test_write_disk_appledouble.cpio.gz.uu \ libarchive/test/test_write_disk_hfs_compression.tgz.uu \ libarchive/test/test_write_disk_mac_metadata.tar.gz.uu \ libarchive/test/test_write_disk_no_hfs_compression.tgz.uu \ libarchive/test/CMakeLists.txt \ libarchive/test/README # # Common code for libarchive frontends (cpio, tar) # libarchive_fe_la_SOURCES= \ libarchive_fe/err.c \ libarchive_fe/err.h \ libarchive_fe/lafe_platform.h \ libarchive_fe/line_reader.c \ libarchive_fe/line_reader.h \ libarchive_fe/passphrase.c \ libarchive_fe/passphrase.h libarchive_fe_la_CPPFLAGS= -I$(top_srcdir)/libarchive # # # bsdtar source, docs, etc. # # bsdtar_SOURCES= \ tar/bsdtar.c \ tar/bsdtar.h \ tar/bsdtar_platform.h \ tar/cmdline.c \ tar/creation_set.c \ tar/read.c \ tar/subst.c \ tar/util.c \ tar/write.c if INC_WINDOWS_FILES bsdtar_SOURCES+= \ tar/bsdtar_windows.h \ tar/bsdtar_windows.c endif bsdtar_DEPENDENCIES= libarchive.la libarchive_fe.la if STATIC_BSDTAR bsdtar_ldstatic= -static bsdtar_ccstatic= -DLIBARCHIVE_STATIC else bsdtar_ldstatic= bsdtar_ccstatic= endif bsdtar_LDADD= libarchive.la libarchive_fe.la $(LTLIBICONV) bsdtar_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdtar_ccstatic) $(PLATFORMCPPFLAGS) bsdtar_LDFLAGS= $(bsdtar_ldstatic) bsdtar_EXTRA_DIST= \ tar/bsdtar.1 \ tar/bsdtar_windows.h \ tar/bsdtar_windows.c \ tar/CMakeLists.txt \ tar/config_freebsd.h if BUILD_BSDTAR bsdtar_man_MANS= tar/bsdtar.1 bsdtar_programs= bsdtar else bsdtar_man_MANS= bsdtar_programs= endif # # bsdtar_test # bsdtar_test_SOURCES= \ $(test_utils_SOURCES) \ tar/test/test.h \ tar/test/test_0.c \ tar/test/test_basic.c \ tar/test/test_copy.c \ tar/test/test_empty_mtree.c \ tar/test/test_extract_tar_Z.c \ tar/test/test_extract_tar_bz2.c \ tar/test/test_extract_tar_grz.c \ tar/test/test_extract_tar_gz.c \ tar/test/test_extract_tar_lrz.c \ tar/test/test_extract_tar_lz.c \ tar/test/test_extract_tar_lz4.c \ tar/test/test_extract_tar_lzma.c \ tar/test/test_extract_tar_lzo.c \ tar/test/test_extract_tar_xz.c \ tar/test/test_format_newc.c \ tar/test/test_help.c \ tar/test/test_leading_slash.c \ tar/test/test_missing_file.c \ tar/test/test_option_C_upper.c \ tar/test/test_option_H_upper.c \ tar/test/test_option_L_upper.c \ tar/test/test_option_O_upper.c \ tar/test/test_option_T_upper.c \ tar/test/test_option_U_upper.c \ tar/test/test_option_X_upper.c \ tar/test/test_option_acls.c \ tar/test/test_option_a.c \ tar/test/test_option_b.c \ tar/test/test_option_b64encode.c \ tar/test/test_option_exclude.c \ tar/test/test_option_fflags.c \ tar/test/test_option_gid_gname.c \ tar/test/test_option_grzip.c \ tar/test/test_option_j.c \ tar/test/test_option_k.c \ tar/test/test_option_keep_newer_files.c \ tar/test/test_option_lrzip.c \ tar/test/test_option_lz4.c \ tar/test/test_option_lzma.c \ tar/test/test_option_lzop.c \ tar/test/test_option_n.c \ tar/test/test_option_newer_than.c \ tar/test/test_option_nodump.c \ tar/test/test_option_older_than.c \ tar/test/test_option_passphrase.c \ tar/test/test_option_q.c \ tar/test/test_option_r.c \ tar/test/test_option_s.c \ tar/test/test_option_uid_uname.c \ tar/test/test_option_uuencode.c \ + tar/test/test_option_xattrs.c \ tar/test/test_option_xz.c \ tar/test/test_option_z.c \ tar/test/test_patterns.c \ tar/test/test_print_longpath.c \ tar/test/test_stdio.c \ tar/test/test_strip_components.c \ tar/test/test_symlink_dir.c \ tar/test/test_version.c \ tar/test/test_windows.c bsdtar_test_CPPFLAGS=\ -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \ -I$(top_srcdir)/test_utils \ -I$(top_srcdir)/tar -I$(top_srcdir)/tar/test \ -I$(top_builddir)/tar/test \ $(PLATFORMCPPFLAGS) tar/test/list.h: Makefile $(MKDIR_P) tar/test cat $(top_srcdir)/tar/test/test_*.c | grep '^DEFINE_TEST' > tar/test/list.h if BUILD_BSDTAR bsdtar_test_programs= bsdtar_test bsdtar_TESTS_ENVIRONMENT= BSDTAR=`cd $(top_builddir);/bin/pwd`/bsdtar$(EXEEXT) BSDTAR_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/tar/test else bsdtar_test_programs= bsdtar_TESTS_ENVIRONMENT= endif bsdtar_test_EXTRA_DIST= \ tar/test/list.h \ tar/test/test_extract.tar.Z.uu \ tar/test/test_extract.tar.bz2.uu \ tar/test/test_extract.tar.grz.uu \ tar/test/test_extract.tar.gz.uu \ tar/test/test_extract.tar.lrz.uu \ tar/test/test_extract.tar.lz.uu \ tar/test/test_extract.tar.lz4.uu \ tar/test/test_extract.tar.lzma.uu \ tar/test/test_extract.tar.lzo.uu \ tar/test/test_extract.tar.xz.uu \ tar/test/test_leading_slash.tar.uu \ tar/test/test_option_keep_newer_files.tar.Z.uu \ tar/test/test_option_passphrase.zip.uu \ tar/test/test_option_s.tar.Z.uu \ tar/test/test_patterns_2.tar.uu \ tar/test/test_patterns_3.tar.uu \ tar/test/test_patterns_4.tar.uu \ tar/test/test_print_longpath.tar.Z.uu \ tar/test/CMakeLists.txt # # # bsdcpio source, docs, etc. # # bsdcpio_SOURCES= \ cpio/cmdline.c \ cpio/cpio.c \ cpio/cpio.h \ cpio/cpio_platform.h if INC_WINDOWS_FILES bsdcpio_SOURCES+= \ cpio/cpio_windows.h \ cpio/cpio_windows.c endif bsdcpio_DEPENDENCIES = libarchive.la libarchive_fe.la if STATIC_BSDCPIO bsdcpio_ldstatic= -static bsdcpio_ccstatic= -DLIBARCHIVE_STATIC else bsdcpio_ldstatic= bsdcpio_ccstatic= endif bsdcpio_LDADD= libarchive_fe.la libarchive.la $(LTLIBICONV) bsdcpio_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdcpio_ccstatic) $(PLATFORMCPPFLAGS) bsdcpio_LDFLAGS= $(bsdcpio_ldstatic) bsdcpio_EXTRA_DIST= \ cpio/bsdcpio.1 \ cpio/cpio_windows.h \ cpio/cpio_windows.c \ cpio/CMakeLists.txt \ cpio/config_freebsd.h if BUILD_BSDCPIO # Manpages to install bsdcpio_man_MANS= cpio/bsdcpio.1 bsdcpio_programs= bsdcpio else bsdcpio_man_MANS= bsdcpio_programs= endif # # bsdcpio_test # bsdcpio_test_SOURCES= \ $(test_utils_SOURCES) \ cpio/cmdline.c \ cpio/test/test.h \ cpio/test/test_0.c \ cpio/test/test_basic.c \ cpio/test/test_cmdline.c \ cpio/test/test_extract_cpio_Z.c \ cpio/test/test_extract_cpio_bz2.c \ cpio/test/test_extract_cpio_grz.c \ cpio/test/test_extract_cpio_gz.c \ cpio/test/test_extract_cpio_lrz.c \ cpio/test/test_extract_cpio_lz.c \ cpio/test/test_extract_cpio_lz4.c \ cpio/test/test_extract_cpio_lzma.c \ cpio/test/test_extract_cpio_lzo.c \ cpio/test/test_extract_cpio_xz.c \ cpio/test/test_format_newc.c \ cpio/test/test_gcpio_compat.c \ cpio/test/test_missing_file.c \ cpio/test/test_option_0.c \ cpio/test/test_option_B_upper.c \ cpio/test/test_option_C_upper.c \ cpio/test/test_option_J_upper.c \ cpio/test/test_option_L_upper.c \ cpio/test/test_option_Z_upper.c \ cpio/test/test_option_a.c \ cpio/test/test_option_b64encode.c \ cpio/test/test_option_c.c \ cpio/test/test_option_d.c \ cpio/test/test_option_f.c \ cpio/test/test_option_grzip.c \ cpio/test/test_option_help.c \ cpio/test/test_option_l.c \ cpio/test/test_option_lrzip.c \ cpio/test/test_option_lz4.c \ cpio/test/test_option_lzma.c \ cpio/test/test_option_lzop.c \ cpio/test/test_option_m.c \ cpio/test/test_option_passphrase.c \ cpio/test/test_option_t.c \ cpio/test/test_option_u.c \ cpio/test/test_option_uuencode.c \ cpio/test/test_option_version.c \ cpio/test/test_option_xz.c \ cpio/test/test_option_y.c \ cpio/test/test_option_z.c \ cpio/test/test_owner_parse.c \ cpio/test/test_passthrough_dotdot.c \ cpio/test/test_passthrough_reverse.c bsdcpio_test_CPPFLAGS= \ -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \ -I$(top_srcdir)/test_utils \ -I$(top_srcdir)/cpio -I$(top_srcdir)/cpio/test \ -I$(top_builddir)/cpio/test \ $(PLATFORMCPPFLAGS) bsdcpio_test_LDADD=libarchive_fe.la cpio/test/list.h: Makefile $(MKDIR_P) cpio/test cat $(top_srcdir)/cpio/test/test_*.c | grep '^DEFINE_TEST' > cpio/test/list.h if BUILD_BSDCPIO bsdcpio_test_programs= bsdcpio_test bsdcpio_TESTS_ENVIRONMENT= BSDCPIO=`cd $(top_builddir);/bin/pwd`/bsdcpio$(EXEEXT) BSDCPIO_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/cpio/test else bsdcpio_test_programs= bsdcpio_TESTS_ENVIRONMENT= endif bsdcpio_test_EXTRA_DIST= \ cpio/test/list.h \ cpio/test/test_extract.cpio.Z.uu \ cpio/test/test_extract.cpio.bz2.uu \ cpio/test/test_extract.cpio.grz.uu \ cpio/test/test_extract.cpio.gz.uu \ cpio/test/test_extract.cpio.lrz.uu \ cpio/test/test_extract.cpio.lz.uu \ cpio/test/test_extract.cpio.lz4.uu \ cpio/test/test_extract.cpio.lzma.uu \ cpio/test/test_extract.cpio.lzo.uu \ cpio/test/test_extract.cpio.xz.uu \ cpio/test/test_gcpio_compat_ref.bin.uu \ cpio/test/test_gcpio_compat_ref.crc.uu \ cpio/test/test_gcpio_compat_ref.newc.uu \ cpio/test/test_gcpio_compat_ref.ustar.uu \ cpio/test/test_gcpio_compat_ref_nosym.bin.uu \ cpio/test/test_gcpio_compat_ref_nosym.crc.uu \ cpio/test/test_gcpio_compat_ref_nosym.newc.uu \ cpio/test/test_gcpio_compat_ref_nosym.ustar.uu \ cpio/test/test_option_f.cpio.uu \ cpio/test/test_option_m.cpio.uu \ cpio/test/test_option_passphrase.zip.uu \ cpio/test/test_option_t.cpio.uu \ cpio/test/test_option_t.stdout.uu \ cpio/test/test_option_tv.stdout.uu \ cpio/test/CMakeLists.txt # # # bsdcat source, docs, etc. # # bsdcat_SOURCES= \ cat/bsdcat.c \ cat/bsdcat.h \ cat/bsdcat_platform.h \ cat/cmdline.c if INC_WINDOWS_FILES bsdcat_SOURCES+= endif bsdcat_DEPENDENCIES = libarchive.la libarchive_fe.la if STATIC_BSDCAT bsdcat_ldstatic= -static bsdcat_ccstatic= -DLIBARCHIVE_STATIC else bsdcat_ldstatic= bsdcat_ccstatic= endif bsdcat_LDADD= libarchive_fe.la libarchive.la $(LTLIBICONV) bsdcat_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdcat_ccstatic) $(PLATFORMCPPFLAGS) bsdcat_LDFLAGS= $(bsdcat_ldstatic) bsdcat_EXTRA_DIST= \ cat/bsdcat.1 \ cat/CMakeLists.txt if BUILD_BSDCAT # Manpages to install bsdcat_man_MANS= cat/bsdcat.1 bsdcat_programs= bsdcat else bsdcat_man_MANS= bsdcat_programs= endif # # bsdcat_test # bsdcat_test_SOURCES= \ $(test_utils_SOURCES) \ cat/test/test.h \ cat/test/test_0.c \ cat/test/test_empty_gz.c \ cat/test/test_empty_lz4.c \ cat/test/test_empty_xz.c \ cat/test/test_error.c \ cat/test/test_error_mixed.c \ cat/test/test_expand_Z.c \ cat/test/test_expand_bz2.c \ cat/test/test_expand_gz.c \ cat/test/test_expand_lz4.c \ cat/test/test_expand_mixed.c \ cat/test/test_expand_plain.c \ cat/test/test_expand_xz.c \ cat/test/test_help.c \ cat/test/test_version.c bsdcat_test_CPPFLAGS= \ -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \ -I$(top_srcdir)/test_utils \ -I$(top_srcdir)/cat -I$(top_srcdir)/cat/test \ -I$(top_builddir)/cat/test \ $(PLATFORMCPPFLAGS) bsdcat_test_LDADD=libarchive_fe.la cat/test/list.h: Makefile cat $(top_srcdir)/cat/test/test_*.c | grep '^DEFINE_TEST' > cat/test/list.h if BUILD_BSDCAT bsdcat_test_programs= bsdcat_test bsdcat_TESTS_ENVIRONMENT= BSDCAT=`cd $(top_builddir);/bin/pwd`/bsdcat$(EXEEXT) BSDCAT_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/cat/test else bsdcat_test_programs= bsdcat_TESTS_ENVIRONMENT= endif bsdcat_test_EXTRA_DIST= \ cat/test/list.h \ cat/test/test_empty.gz.uu \ cat/test/test_empty.lz4.uu \ cat/test/test_empty.xz.uu \ cat/test/test_expand.Z.uu \ cat/test/test_expand.bz2.uu \ cat/test/test_expand.gz.uu \ cat/test/test_expand.lz4.uu \ cat/test/test_expand.plain.uu \ cat/test/test_expand.xz.uu \ cat/test/CMakeLists.txt Index: vendor/libarchive/dist/build/cmake/config.h.in =================================================================== --- vendor/libarchive/dist/build/cmake/config.h.in (revision 315874) +++ vendor/libarchive/dist/build/cmake/config.h.in (revision 315875) @@ -1,1297 +1,1313 @@ /* config.h. Generated from build/cmake/config.h.in by cmake configure */ /* * 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. */ @SIZE_OF_SHORT_CODE@ @SIZE_OF_INT_CODE@ @SIZE_OF_LONG_CODE@ @SIZE_OF_LONG_LONG_CODE@ @SIZE_OF_UNSIGNED_SHORT_CODE@ @SIZE_OF_UNSIGNED_CODE@ @SIZE_OF_UNSIGNED_LONG_CODE@ @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 /* Darwin ACL support */ #cmakedefine ARCHIVE_ACL_DARWIN 1 /* FreeBSD ACL support */ #cmakedefine ARCHIVE_ACL_FREEBSD 1 /* FreeBSD NFSv4 ACL support */ #cmakedefine ARCHIVE_ACL_FREEBSD_NFS4 1 /* Linux POSIX.1e ACL support via libacl */ #cmakedefine ARCHIVE_ACL_LIBACL 1 /* Linux NFSv4 ACL support via librichacl */ #cmakedefine ARCHIVE_ACL_LIBRICHACL 1 /* Solaris ACL support */ #cmakedefine ARCHIVE_ACL_SUNOS 1 /* Solaris NFSv4 ACL support */ #cmakedefine ARCHIVE_ACL_SUNOS_NFS4 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 +/* AIX xattr support */ +#cmakedefine ARCHIVE_XATTR_AIX 1 + +/* Darwin xattr support */ +#cmakedefine ARCHIVE_XATTR_DARWIN 1 + +/* FreeBSD xattr support */ +#cmakedefine ARCHIVE_XATTR_FREEBSD 1 + +/* Linux xattr support */ +#cmakedefine ARCHIVE_XATTR_LINUX 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 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 /* Define to 1 if you have the `arc4random_buf' function. */ #cmakedefine HAVE_ARC4RANDOM_BUF 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ATTR_XATTR_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_BCRYPT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_BSDXML_H 1 /* Define to 1 if you have the 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 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 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 `ACE_GETACL', and to 0 if you don't. */ #cmakedefine HAVE_DECL_ACE_GETACL 1 /* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you don't. */ #cmakedefine HAVE_DECL_ACE_GETACLCNT 1 /* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you don't. */ #cmakedefine HAVE_DECL_ACE_SETACL 1 /* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if you don't. */ #cmakedefine HAVE_DECL_ACL_SYNCHRONIZE 1 /* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if you don't. */ #cmakedefine HAVE_DECL_ACL_TYPE_EXTENDED 1 /* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you don't. */ #cmakedefine HAVE_DECL_ACL_TYPE_NFS4 1 /* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you don't. */ #cmakedefine HAVE_DECL_ACL_USER 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 `SETACL', and to 0 if you don't. */ #cmakedefine HAVE_DECL_SETACL 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 declaration of `XATTR_NOFOLLOW', and to 0 if + you don't. */ +#cmakedefine HAVE_DECL_XATTR_NOFOLLOW 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_DIRECT_H 1 /* Define to 1 if you have the 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 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 header file. */ #cmakedefine HAVE_ERRNO_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_EXPAT_H 1 /* Define to 1 if you have the 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 declaration of `GETACL', and to 0 if you don't. */ #cmakedefine HAVE_DECL_GETACL 1 /* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you don't. */ #cmakedefine HAVE_DECL_GETACLCNT 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 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 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 header file. */ #cmakedefine HAVE_ICONV_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_INTTYPES_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_IO_H 1 /* Define to 1 if you have the 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 header file. */ #cmakedefine HAVE_LIBXML_XMLREADER_H 1 /* Define to 1 if you have the 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 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 header file. */ #cmakedefine HAVE_LINUX_FIEMAP_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LINUX_FS_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LINUX_MAGIC_H 1 /* Define to 1 if you have the 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 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 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 header file. */ #cmakedefine HAVE_LZ4HC_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LZ4_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LZMADEC_H 1 /* Define to 1 if you have the 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 header file. */ #cmakedefine HAVE_LZO_LZO1X_H 1 /* Define to 1 if you have the 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 header file. */ #cmakedefine HAVE_MEMBERSHIP_H 1 /* Define to 1 if you have the `memmove' function. */ #cmakedefine HAVE_MEMMOVE 1 /* Define to 1 if you have the 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 header file, and it defines `DIR'. */ #cmakedefine HAVE_NDIR_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETTLE_AES_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETTLE_HMAC_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETTLE_MD5_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETTLE_PBKDF2_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETTLE_RIPEMD160_H 1 /* Define to 1 if you have the 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 header file. */ #cmakedefine HAVE_PATHS_H 1 /* Define to 1 if you have the 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 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 header file. */ #cmakedefine HAVE_PROCESS_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_PTHREAD_H 1 /* Define to 1 if you have the 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 header file. */ #cmakedefine HAVE_READPASSPHRASE_H 1 /* Define to 1 if you have the 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 header file. */ #cmakedefine HAVE_SIGNAL_H 1 /* Define to 1 if you have the 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 header file. */ #cmakedefine HAVE_STDARG_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDINT_H 1 /* Define to 1 if you have the 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 header file. */ #cmakedefine HAVE_STRINGS_H 1 /* Define to 1 if you have the 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 header file. */ #cmakedefine HAVE_SYS_ACL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_CDEFS_H 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ #cmakedefine HAVE_SYS_DIR_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_EA_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_EXTATTR_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_IOCTL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_MKDEV_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_MOUNT_H 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ #cmakedefine HAVE_SYS_NDIR_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_POLL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_RICHACL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_SELECT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_STATFS_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_STATVFS_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_UTIME_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_UTSNAME_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_VFS_H 1 /* Define to 1 if you have that is POSIX.1 compatible. */ #cmakedefine HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the 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 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 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 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 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 header file. */ #cmakedefine HAVE_WCTYPE_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_WINCRYPT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_WINDOWS_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_WINIOCTL_H 1 /* Define to 1 if you have _CrtSetReportMode in */ #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 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 . */ #cmakedefine MAJOR_IN_MKDEV 1 /* Define to 1 if `major', `minor', and `makedev' are declared in . */ #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 and . */ #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 doesn't define. */ #cmakedefine gid_t ${gid_t} /* Define to `unsigned long' if does not define. */ #cmakedefine id_t ${id_t} /* Define to `int' if does not define. */ #cmakedefine mode_t ${mode_t} /* Define to `long long' if does not define. */ #cmakedefine off_t ${off_t} /* Define to `int' if doesn't define. */ #cmakedefine pid_t ${pid_t} /* Define to `unsigned int' if does not define. */ #cmakedefine size_t ${size_t} /* Define to `int' if does not define. */ #cmakedefine ssize_t ${ssize_t} /* Define to `int' if doesn't define. */ #cmakedefine uid_t ${uid_t} /* Define to `int' if does not define. */ #cmakedefine intptr_t ${intptr_t} /* Define to `unsigned int' if does not define. */ #cmakedefine uintptr_t ${uintptr_t} Index: vendor/libarchive/dist/configure.ac =================================================================== --- vendor/libarchive/dist/configure.ac (revision 315874) +++ vendor/libarchive/dist/configure.ac (revision 315875) @@ -1,1087 +1,1177 @@ dnl Process this file with autoconf to produce a configure script. dnl First, define all of the version numbers up front. dnl In particular, this allows the version macro to be used in AC_INIT dnl These first two version numbers are updated automatically on each release. m4_define([LIBARCHIVE_VERSION_S],[3.3.2dev]) m4_define([LIBARCHIVE_VERSION_N],[3003002]) dnl bsdtar and bsdcpio versioning tracks libarchive m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S()) m4_define([BSDCPIO_VERSION_S],LIBARCHIVE_VERSION_S()) m4_define([BSDCAT_VERSION_S],LIBARCHIVE_VERSION_S()) AC_PREREQ([2.69]) # # Now starts the "real" configure script. # AC_INIT([libarchive],[LIBARCHIVE_VERSION_S()],[libarchive-discuss@googlegroups.com]) # Make sure the srcdir contains "libarchive" directory AC_CONFIG_SRCDIR([libarchive]) # Use auxiliary subscripts from this subdirectory (cleans up root) AC_CONFIG_AUX_DIR([build/autoconf]) # M4 scripts AC_CONFIG_MACRO_DIR([build/autoconf]) # Must follow AC_CONFIG macros above... AM_INIT_AUTOMAKE() AM_MAINTAINER_MODE([enable]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) # Libtool's "interface version" can be computed from the libarchive version. # Libtool interface version bumps on any API change, so increments # whenever libarchive minor version does. ARCHIVE_MINOR=$(( (LIBARCHIVE_VERSION_N() / 1000) % 1000 )) # Libarchive 2.7 == libtool interface 9 = 2 + 7 # Libarchive 2.8 == libtool interface 10 = 2 + 8 # Libarchive 2.9 == libtool interface 11 = 2 + 8 # Libarchive 3.0 == libtool interface 12 # Libarchive 3.1 == libtool interface 13 ARCHIVE_INTERFACE=`echo $((13 + ${ARCHIVE_MINOR}))` # Libarchive revision is bumped on any source change === libtool revision ARCHIVE_REVISION=$(( LIBARCHIVE_VERSION_N() % 1000 )) # Libarchive minor is bumped on any interface addition === libtool age ARCHIVE_LIBTOOL_VERSION=$ARCHIVE_INTERFACE:$ARCHIVE_REVISION:$ARCHIVE_MINOR # Stick the version numbers into config.h AC_DEFINE([LIBARCHIVE_VERSION_STRING],"LIBARCHIVE_VERSION_S()", [Version number of libarchive]) AC_DEFINE_UNQUOTED([LIBARCHIVE_VERSION_NUMBER],"LIBARCHIVE_VERSION_N()", [Version number of libarchive as a single integer]) AC_DEFINE([BSDCPIO_VERSION_STRING],"BSDCPIO_VERSION_S()", [Version number of bsdcpio]) AC_DEFINE([BSDTAR_VERSION_STRING],"BSDTAR_VERSION_S()", [Version number of bsdtar]) AC_DEFINE([BSDCAT_VERSION_STRING],"BSDTAR_VERSION_S()", [Version number of bsdcat]) # The shell variables here must be the same as the AC_SUBST() variables # below, but the shell variable names apparently cannot be the same as # the m4 macro names above. Why? Ask autoconf. BSDCPIO_VERSION_STRING=BSDCPIO_VERSION_S() BSDTAR_VERSION_STRING=BSDTAR_VERSION_S() BSDCAT_VERSION_STRING=BSDCAT_VERSION_S() LIBARCHIVE_VERSION_STRING=LIBARCHIVE_VERSION_S() LIBARCHIVE_VERSION_NUMBER=LIBARCHIVE_VERSION_N() # Substitute the above version numbers into the various files below. # Yes, I believe this is the fourth time we define what are essentially # the same symbols. Why? Ask autoconf. AC_SUBST(ARCHIVE_LIBTOOL_VERSION) AC_SUBST(BSDCPIO_VERSION_STRING) AC_SUBST(BSDTAR_VERSION_STRING) AC_SUBST(BSDCAT_VERSION_STRING) AC_SUBST(LIBARCHIVE_VERSION_STRING) AC_SUBST(LIBARCHIVE_VERSION_NUMBER) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([build/pkgconfig/libarchive.pc]) # Check for host type AC_CANONICAL_HOST dnl Compilation on mingw and Cygwin needs special Makefile rules inc_windows_files=no inc_cygwin_files=no case "$host_os" in *mingw* ) inc_windows_files=yes ;; *cygwin* | *msys*) inc_cygwin_files=yes ;; esac AM_CONDITIONAL([INC_WINDOWS_FILES], [test $inc_windows_files = yes]) AM_CONDITIONAL([INC_CYGWIN_FILES], [test $inc_cygwin_files = yes]) dnl Defines that are required for specific platforms (e.g. -D_POSIX_SOURCE, etc) PLATFORMCPPFLAGS= case "$host_os" in *mingw* ) PLATFORMCPPFLAGS=-D__USE_MINGW_ANSI_STDIO ;; esac AC_SUBST(PLATFORMCPPFLAGS) # Checks for programs. AC_PROG_CC AM_PROG_CC_C_O AC_USE_SYSTEM_EXTENSIONS AC_LIBTOOL_WIN32_DLL AC_PROG_LIBTOOL AC_CHECK_TOOL([STRIP],[strip]) AC_PROG_MKDIR_P # # Options for building bsdtar. # # Default is to build bsdtar, but allow people to override that. # AC_ARG_ENABLE([bsdtar], [AS_HELP_STRING([--enable-bsdtar], [enable build of bsdtar (default)]) AS_HELP_STRING([--enable-bsdtar=static], [force static build of bsdtar]) AS_HELP_STRING([--enable-bsdtar=shared], [force dynamic build of bsdtar]) AS_HELP_STRING([--disable-bsdtar], [disable build of bsdtar])], [], [enable_bsdtar=yes]) case "$enable_bsdtar" in yes) if test "$enable_static" = "no"; then static_bsdtar=no else static_bsdtar=yes fi build_bsdtar=yes ;; dynamic|shared) if test "$enable_shared" = "no"; then AC_MSG_FAILURE([Shared linking of bsdtar requires shared libarchive]) fi build_bsdtar=yes static_bsdtar=no ;; static) build_bsdtar=yes static_bsdtar=yes ;; no) build_bsdtar=no static_bsdtar=no ;; *) AC_MSG_FAILURE([Unsupported value for --enable-bsdtar]) ;; esac AM_CONDITIONAL([BUILD_BSDTAR], [ test "$build_bsdtar" = yes ]) AM_CONDITIONAL([STATIC_BSDTAR], [ test "$static_bsdtar" = yes ]) # # Options for building bsdcat. # # Default is to build bsdcat, but allow people to override that. # AC_ARG_ENABLE([bsdcat], [AS_HELP_STRING([--enable-bsdcat], [enable build of bsdcat (default)]) AS_HELP_STRING([--enable-bsdcat=static], [force static build of bsdcat]) AS_HELP_STRING([--enable-bsdcat=shared], [force dynamic build of bsdcat]) AS_HELP_STRING([--disable-bsdcat], [disable build of bsdcat])], [], [enable_bsdcat=yes]) case "$enable_bsdcat" in yes) if test "$enable_static" = "no"; then static_bsdcat=no else static_bsdcat=yes fi build_bsdcat=yes ;; dynamic|shared) if test "$enable_shared" = "no"; then AC_MSG_FAILURE([Shared linking of bsdcat requires shared libarchive]) fi build_bsdcat=yes static_bsdcat=no ;; static) build_bsdcat=yes static_bsdcat=yes ;; no) build_bsdcat=no static_bsdcat=no ;; *) AC_MSG_FAILURE([Unsupported value for --enable-bsdcat]) ;; esac AM_CONDITIONAL([BUILD_BSDCAT], [ test "$build_bsdcat" = yes ]) AM_CONDITIONAL([STATIC_BSDCAT], [ test "$static_bsdcat" = yes ]) # # Options for building bsdcpio. # # Default is not to build bsdcpio, but that can be overridden. # AC_ARG_ENABLE([bsdcpio], [AS_HELP_STRING([--enable-bsdcpio], [enable build of bsdcpio (default)]) AS_HELP_STRING([--enable-bsdcpio=static], [static build of bsdcpio]) AS_HELP_STRING([--enable-bsdcpio=shared], [dynamic build of bsdcpio]) AS_HELP_STRING([--disable-bsdcpio], [disable build of bsdcpio])], [], [enable_bsdcpio=yes]) case "$enable_bsdcpio" in yes) if test "$enable_static" = "no"; then static_bsdcpio=no else static_bsdcpio=yes fi build_bsdcpio=yes ;; dynamic|shared) if test "$enabled_shared" = "no"; then AC_MSG_FAILURE([Shared linking of bsdcpio requires shared libarchive]) fi build_bsdcpio=yes ;; static) build_bsdcpio=yes static_bsdcpio=yes ;; no) build_bsdcpio=no static_bsdcpio=no ;; *) AC_MSG_FAILURE([Unsupported value for --enable-bsdcpio]) ;; esac AM_CONDITIONAL([BUILD_BSDCPIO], [ test "$build_bsdcpio" = yes ]) AM_CONDITIONAL([STATIC_BSDCPIO], [ test "$static_bsdcpio" = yes ]) # Set up defines needed before including any headers case $host in *mingw* | *cygwin* | *msys* ) AC_DEFINE([_WIN32_WINNT], 0x0502, [Define to '0x0502' for Windows Server 2003 APIs.]) AC_DEFINE([WINVER], 0x0502, [Define to '0x0502' for Windows Server 2003 APIs.]) AC_DEFINE([NTDDI_VERSION], 0x05020000, [Define to '0x05020000' for Windows Server 2003 APIs.]) ;; esac # Checks for header files. AC_HEADER_DIRENT AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS([acl/libacl.h]) +AC_CHECK_HEADERS([acl/libacl.h attr/xattr.h]) AC_CHECK_HEADERS([copyfile.h ctype.h]) AC_CHECK_HEADERS([errno.h ext2fs/ext2_fs.h fcntl.h grp.h]) AC_CACHE_CHECK([whether EXT2_IOC_GETFLAGS is usable], [ac_cv_have_decl_EXT2_IOC_GETFLAGS], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include @%:@include ], [int x = EXT2_IOC_GETFLAGS])], [AS_VAR_SET([ac_cv_have_decl_EXT2_IOC_GETFLAGS], [yes])], [AS_VAR_SET([ac_cv_have_decl_EXT2_IOC_GETFLAGS], [no])])]) AS_VAR_IF([ac_cv_have_decl_EXT2_IOC_GETFLAGS], [yes], [AC_DEFINE_UNQUOTED([HAVE_WORKING_EXT2_IOC_GETFLAGS], [1], [Define to 1 if you have a working EXT2_IOC_GETFLAGS])]) AC_CHECK_HEADERS([inttypes.h io.h langinfo.h limits.h]) AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h linux/magic.h linux/types.h]) AC_CACHE_CHECK([whether FS_IOC_GETFLAGS is usable], [ac_cv_have_decl_FS_IOC_GETFLAGS], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include @%:@include ], [int x = FS_IOC_GETFLAGS])], [AS_VAR_SET([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes])], [AS_VAR_SET([ac_cv_have_decl_FS_IOC_GETFLAGS], [no])])]) AS_VAR_IF([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes], [AC_DEFINE_UNQUOTED([HAVE_WORKING_FS_IOC_GETFLAGS], [1], [Define to 1 if you have a working FS_IOC_GETFLAGS])]) AC_CHECK_HEADERS([locale.h membership.h paths.h poll.h pthread.h pwd.h]) AC_CHECK_HEADERS([readpassphrase.h signal.h spawn.h]) AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.h]) -AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/extattr.h]) +AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/ea.h sys/extattr.h]) AC_CHECK_HEADERS([sys/ioctl.h sys/mkdev.h sys/mount.h]) AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/richacl.h]) AC_CHECK_HEADERS([sys/select.h sys/statfs.h sys/statvfs.h]) -AC_CHECK_HEADERS([sys/time.h sys/utime.h sys/utsname.h sys/vfs.h]) +AC_CHECK_HEADERS([sys/time.h sys/utime.h sys/utsname.h sys/vfs.h sys/xattr.h]) AC_CHECK_HEADERS([time.h unistd.h utime.h wchar.h wctype.h]) AC_CHECK_HEADERS([windows.h]) # check windows.h first; the other headers require it. AC_CHECK_HEADERS([wincrypt.h winioctl.h],[],[], [[#ifdef HAVE_WINDOWS_H # include #endif ]]) # Checks for libraries. AC_ARG_WITH([zlib], AS_HELP_STRING([--without-zlib], [Don't build support for gzip through zlib])) if test "x$with_zlib" != "xno"; then AC_CHECK_HEADERS([zlib.h]) AC_CHECK_LIB(z,inflate) fi AC_ARG_WITH([bz2lib], AS_HELP_STRING([--without-bz2lib], [Don't build support for bzip2 through bz2lib])) if test "x$with_bz2lib" != "xno"; then AC_CHECK_HEADERS([bzlib.h]) case "$host_os" in *mingw* | *cygwin* | *msys*) dnl AC_CHECK_LIB cannot be used on the Windows port of libbz2, therefore dnl use AC_LINK_IFELSE. AC_MSG_CHECKING([for BZ2_bzDecompressInit in -lbz2]) old_LIBS="$LIBS" LIBS="-lbz2 $LIBS" AC_LINK_IFELSE( [AC_LANG_SOURCE(#include int main() { return BZ2_bzDecompressInit(NULL, 0, 0); })], [ac_cv_lib_bz2_BZ2_bzDecompressInit=yes], [ac_cv_lib_bz2_BZ2_bzDecompressInit=no]) LIBS="$old_LIBS" AC_MSG_RESULT($ac_cv_lib_bz2_BZ2_bzDecompressInit) if test "x$ac_cv_lib_bz2_BZ2_bzDecompressInit" = xyes; then AC_DEFINE([HAVE_LIBBZ2], [1], [Define to 1 if you have the `bz2' library (-lbz2).]) LIBS="-lbz2 $LIBS" fi ;; *) AC_CHECK_LIB(bz2,BZ2_bzDecompressInit) ;; esac fi AC_ARG_WITH([iconv], AS_HELP_STRING([--without-iconv], [Don't try to link against iconv])) if test "x$with_iconv" != "xno"; then AM_ICONV AC_CHECK_HEADERS([iconv.h],[],[],[#include ]) if test "x$am_cv_func_iconv" = "xyes"; then AC_CHECK_HEADERS([localcharset.h]) am_save_LIBS="$LIBS" LIBS="${LIBS} ${LIBICONV}" AC_CHECK_FUNCS([locale_charset]) LIBS="${am_save_LIBS}" if test "x$ac_cv_func_locale_charset" != "xyes"; then # If locale_charset() is not in libiconv, we have to find libcharset. AC_CHECK_LIB(charset,locale_charset) fi fi fi AC_ARG_WITH([lz4], AS_HELP_STRING([--without-lz4], [Don't build support for lz4 through liblz4])) if test "x$with_lz4" != "xno"; then AC_CHECK_HEADERS([lz4.h lz4hc.h]) AC_CHECK_LIB(lz4,LZ4_decompress_safe) fi AC_ARG_WITH([lzma], AS_HELP_STRING([--without-lzma], [Don't build support for xz through lzma])) if test "x$with_lzma" != "xno"; then AC_CHECK_HEADERS([lzma.h]) AC_CHECK_LIB(lzma,lzma_stream_decoder) # Some pre-release (but widely distributed) versions of liblzma # included a disabled version of lzma_stream_encoder_mt that # fools a naive AC_CHECK_LIB or AC_CHECK_FUNC, so we need # to do something more complex here: AC_CACHE_CHECK( [whether we have multithread support in lzma], ac_cv_lzma_has_mt, [AC_LINK_IFELSE([ AC_LANG_PROGRAM([[#include ] [#if LZMA_VERSION < 50020000] [#error unsupported] [#endif]], [[lzma_stream_encoder_mt(0, 0);]])], [ac_cv_lzma_has_mt=yes], [ac_cv_lzma_has_mt=no])]) if test "x$ac_cv_lzma_has_mt" != xno; then AC_DEFINE([HAVE_LZMA_STREAM_ENCODER_MT], [1], [Define to 1 if you have the `lzma_stream_encoder_mt' function.]) fi fi AC_ARG_WITH([lzo2], AS_HELP_STRING([--with-lzo2], [Build with LZO support from liblzo2])) if test "x$with_lzo2" = "xyes"; then AC_CHECK_HEADERS([lzo/lzoconf.h lzo/lzo1x.h]) AC_CHECK_LIB(lzo2,lzo1x_decompress_safe) fi AC_ARG_WITH([cng], AS_HELP_STRING([--without-cng], [Don't build support of CNG(Crypto Next Generation)])) AC_ARG_WITH([nettle], AS_HELP_STRING([--without-nettle], [Don't build with crypto support from Nettle])) AC_ARG_WITH([openssl], AS_HELP_STRING([--without-openssl], [Don't build support for mtree and xar hashes through openssl])) case "$host_os" in *darwin* ) with_openssl=no ;; esac AC_ARG_WITH([xml2], AS_HELP_STRING([--without-xml2], [Don't build support for xar through libxml2])) AC_ARG_WITH([expat], AS_HELP_STRING([--without-expat], [Don't build support for xar through expat])) if test "x$with_xml2" != "xno"; then PKG_PROG_PKG_CONFIG PKG_CHECK_MODULES(LIBXML2_PC, [libxml-2.0], [ CPPFLAGS="${CPPFLAGS} ${LIBXML2_PC_CFLAGS}" LIBS="${LIBS} ${LIBXML2_PC_LIBS}" AC_CHECK_LIB(xml2,xmlInitParser,[true],AC_MSG_FAILURE(Missing xml2 library)) ], [ AC_CHECK_LIB(xml2,xmlInitParser) ]) AC_CHECK_HEADERS([libxml/xmlreader.h libxml/xmlwriter.h]) fi if test "x$ac_cv_header_libxml_xmlreader_h" != "xyes"; then if test "x$with_expat" != "xno"; then AC_CHECK_HEADERS([expat.h]) AC_CHECK_LIB(expat,XML_ParserCreate) fi fi AC_ARG_ENABLE([posix-regex-lib], [AS_HELP_STRING([--enable-posix-regex-lib], [choose what library to use for POSIX regular expression support (default: auto)]) AS_HELP_STRING([--enable-posix-regex-lib=libc], [use libc POSIX regular expression support]) AS_HELP_STRING([--enable-posix-regex-lib=libregex], [use libregex POSIX regular expression support]) AS_HELP_STRING([--enable-posix-regex-lib=libpcreposix], [use libpcreposix POSIX regular expression support]) AS_HELP_STRING([--disable-posix-regex-lib], [don't enable POSIX regular expression support])], [], [enable_posix_regex_lib=auto]) posix_regex_lib_found= if test "$enable_posix_regex_lib" = "auto" || test "$enable_posix_regex_lib" = "libc" || test "$enable_posix_regex_lib" = "libregex"; then AC_CHECK_HEADERS([regex.h]) if test "x$ac_cv_header_regex_h" != "xno"; then AC_CHECK_FUNC(regcomp) if test "x$ac_cv_func_regcomp" = xyes; then posix_regex_lib_found=1 else AC_CHECK_LIB(regex,regcomp) if test "x$ac_cv_lib_regex_regcomp" = xyes; then posix_regex_lib_found=1 fi fi fi fi if test -z $posix_regex_lib_found && (test "$enable_posix_regex_lib" = "auto" || test "$enable_posix_regex_lib" = "libpcreposix"); then AC_CHECK_HEADERS([pcreposix.h]) AC_CHECK_LIB(pcreposix,regcomp) if test "x$ac_cv_lib_pcreposix_regcomp" != xyes; then AC_MSG_NOTICE(trying libpcreposix check again with libpcre) unset ac_cv_lib_pcreposix_regcomp AC_CHECK_LIB(pcre,pcre_exec) AC_CHECK_LIB(pcreposix,regcomp) if test "x$ac_cv_lib_pcre_pcre_exec" = xyes && test "x$ac_cv_lib_pcreposix_regcomp" = xyes; then AC_MSG_CHECKING(if PCRE_STATIC needs to be defined) AC_LINK_IFELSE( [AC_LANG_SOURCE(#include int main() { return regcomp(NULL, NULL, 0); })], [without_pcre_static=yes], [without_pcre_static=no]) AC_LINK_IFELSE( [AC_LANG_SOURCE(#define PCRE_STATIC #include int main() { return regcomp(NULL, NULL, 0); })], [with_pcre_static=yes], [with_pcre_static=no]) if test "x$without_pcre_static" != xyes && test "x$with_pcre_static" = xyes; then AC_MSG_RESULT(yes) AC_DEFINE([PCRE_STATIC], [1], [Define to 1 if PCRE_STATIC needs to be defined.]) elif test "x$without_pcre_static" = xyes || test "x$with_pcre_static" = xyes; then AC_MSG_RESULT(no) fi posix_regex_lib_found=1 fi else posix_regex_lib_found=1 fi fi # TODO: Give the user the option of using a pre-existing system # libarchive. This will define HAVE_LIBARCHIVE which will cause # bsdtar_platform.h to use #include <...> for the libarchive headers. # Need to include Makefile.am magic to link against system # -larchive in that case. #AC_CHECK_LIB(archive,archive_version) # Checks for supported compiler flags AX_APPEND_COMPILE_FLAGS([-Wall -Wformat -Wformat-security]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST # la_TYPE_UID_T defaults to "int", which is incorrect for MinGW # and MSVC. Use a customized version. la_TYPE_UID_T AC_TYPE_MODE_T # AC_TYPE_OFF_T defaults to "long", which limits us to 4GB files on # most systems... default to "long long" instead. AC_CHECK_TYPE(off_t, [long long]) AC_TYPE_SIZE_T AC_CHECK_TYPE(id_t, [unsigned long]) AC_CHECK_TYPE(uintptr_t, [unsigned int]) # Check for tm_gmtoff in struct tm AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.__tm_gmtoff],,, [ #include ]) # Check for f_namemax in struct statfs AC_CHECK_MEMBERS([struct statfs.f_namemax],,, [ #include #include ]) # Check for f_iosize in struct statvfs AC_CHECK_MEMBERS([struct statvfs.f_iosize],,, [ #include ]) # Check for birthtime in struct stat AC_CHECK_MEMBERS([struct stat.st_birthtime]) # Check for high-resolution timestamps in struct stat AC_CHECK_MEMBERS([struct stat.st_birthtimespec.tv_nsec]) AC_CHECK_MEMBERS([struct stat.st_mtimespec.tv_nsec]) AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec]) AC_CHECK_MEMBERS([struct stat.st_mtime_n]) # AIX AC_CHECK_MEMBERS([struct stat.st_umtime]) # Tru64 AC_CHECK_MEMBERS([struct stat.st_mtime_usec]) # Hurd # Check for block size support in struct stat AC_CHECK_MEMBERS([struct stat.st_blksize]) # Check for st_flags in struct stat (BSD fflags) AC_CHECK_MEMBERS([struct stat.st_flags]) # If you have uintmax_t, we assume printf supports %ju # If you have unsigned long long, we assume printf supports %llu # TODO: Check for %ju and %llu support directly. AC_CHECK_TYPES([uintmax_t, unsigned long long]) # We use C99-style integer types # Declare them if the local platform doesn't already do so. AC_TYPE_INTMAX_T AC_TYPE_UINTMAX_T AC_TYPE_INT64_T AC_TYPE_UINT64_T AC_TYPE_INT32_T AC_TYPE_UINT32_T AC_TYPE_INT16_T AC_TYPE_UINT16_T AC_TYPE_UINT8_T AC_CHECK_DECLS([SIZE_MAX, INT32_MAX, INT32_MIN]) AC_CHECK_DECLS([INT64_MAX, INT64_MIN, UINT64_MAX, UINT32_MAX]) AC_CHECK_DECLS([INTMAX_MAX, INTMAX_MIN, UINTMAX_MAX]) AC_CHECK_DECL([SSIZE_MAX], [AC_DEFINE(HAVE_DECL_SSIZE_MAX, 1, [Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you don't.])], [], [#include ]) AC_CHECK_DECL([EFTYPE], [AC_DEFINE(HAVE_EFTYPE, 1, [A possible errno value for invalid file format errors])], [], [#include ]) AC_CHECK_DECL([EILSEQ], [AC_DEFINE(HAVE_EILSEQ, 1, [A possible errno value for invalid file format errors])], [], [#include ]) AC_CHECK_TYPE([wchar_t], [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_[]wchar_t), 1, [Define to 1 if the system has the type `wchar_t'.])dnl AC_CHECK_SIZEOF([wchar_t])], []) AC_HEADER_TIME # Checks for library functions. AC_PROG_GCC_TRADITIONAL AC_HEADER_MAJOR AC_FUNC_FSEEKO AC_FUNC_MEMCMP AC_FUNC_LSTAT AC_FUNC_STAT AC_FUNC_STRERROR_R AC_FUNC_STRFTIME AC_FUNC_VPRINTF # check for: # CreateHardLinkA(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES) # To avoid necessity for including windows.h or special forward declaration # workarounds, we use 'void *' for 'struct SECURITY_ATTRIBUTES *' AC_CHECK_STDCALL_FUNC([CreateHardLinkA],[const char *, const char *, void *]) AC_CHECK_FUNCS([arc4random_buf chflags chown chroot ctime_r dirfd]) AC_CHECK_FUNCS([fchdir fchflags fchmod fchown fcntl fdopendir fork]) AC_CHECK_FUNCS([fstat fstatat fstatfs fstatvfs ftruncate]) AC_CHECK_FUNCS([futimens futimes futimesat]) AC_CHECK_FUNCS([geteuid getpid getgrgid_r getgrnam_r]) AC_CHECK_FUNCS([getpwnam_r getpwuid_r getvfsbyname gmtime_r]) AC_CHECK_FUNCS([lchflags lchmod lchown link localtime_r lstat lutimes]) AC_CHECK_FUNCS([mbrtowc memmove memset]) AC_CHECK_FUNCS([mkdir mkfifo mknod mkstemp]) AC_CHECK_FUNCS([nl_langinfo openat pipe poll posix_spawnp readlink readlinkat]) AC_CHECK_FUNCS([readpassphrase]) AC_CHECK_FUNCS([select setenv setlocale sigaction statfs statvfs]) AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strrchr symlink timegm]) AC_CHECK_FUNCS([tzset unsetenv utime utimensat utimes vfork]) AC_CHECK_FUNCS([wcrtomb wcscmp wcscpy wcslen wctomb wmemcmp wmemcpy wmemmove]) AC_CHECK_FUNCS([_ctime64_s _fseeki64]) AC_CHECK_FUNCS([_get_timezone _localtime64_s _mkgmtime64]) # detects cygwin-1.7, as opposed to older versions AC_CHECK_FUNCS([cygwin_conv_path]) # DragonFly uses vfsconf, FreeBSD xvfsconf. AC_CHECK_TYPES(struct vfsconf,,, [#if HAVE_SYS_TYPES_H #include #endif #include ]) AC_CHECK_TYPES(struct xvfsconf,,, [#if HAVE_SYS_TYPES_H #include #endif #include ]) # There are several variants of readdir_r around; we only # accept the POSIX-compliant version. AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include ]], [[DIR *dir; struct dirent e, *r; return(readdir_r(dir, &e, &r));]])], [AC_DEFINE(HAVE_READDIR_R,1,[Define to 1 if you have a POSIX compatible readdir_r])] ) # FreeBSD's nl_langinfo supports an option to specify whether the # current locale uses month/day or day/month ordering. It makes the # output a little prettier... AC_CHECK_DECL([D_MD_ORDER], [AC_DEFINE(HAVE_D_MD_ORDER, 1, [Define to 1 if nl_langinfo supports D_MD_ORDER])], [], [#if HAVE_LANGINFO_H #include #endif ]) # Check for dirent.d_namlen field explicitly # (This is a bit more straightforward than, if not quite as portable as, # the recipe given by the autoconf maintainers.) AC_CHECK_MEMBER(struct dirent.d_namlen,,, [#if HAVE_DIRENT_H #include #endif ]) # Check for Extended Attributes support AC_ARG_ENABLE([xattr], AS_HELP_STRING([--disable-xattr], [Disable Extended Attributes support (default: check)])) if test "x$enable_xattr" != "xno"; then - AC_CHECK_HEADERS([attr/xattr.h]) - AC_CHECK_HEADERS([sys/xattr.h sys/ea.h]) - AC_SEARCH_LIBS([setxattr], [attr]) - AC_CHECK_FUNCS([extattr_get_file extattr_list_file]) - AC_CHECK_FUNCS([extattr_set_fd extattr_set_file]) - AC_CHECK_FUNCS([fgetxattr flistxattr fsetxattr getxattr]) - AC_CHECK_FUNCS([lgetxattr listxattr llistxattr lsetxattr]) - AC_CHECK_FUNCS([fgetea flistea fsetea getea]) - AC_CHECK_FUNCS([lgetea listea llistea lsetea]) - AC_CHECK_DECLS([EXTATTR_NAMESPACE_USER], [], [], [#include + AC_SEARCH_LIBS([setxattr], [attr]) + AC_CHECK_DECLS([EXTATTR_NAMESPACE_USER], [], [], [#include #include ]) + AC_CHECK_DECLS([XATTR_NOFOLLOW], [], [], [#include +]) + if test "x$ac_cv_header_sys_xattr_h" = "xyes" \ + -a "x$ac_cv_have_decl_XATTR_NOFOLLOW" = "xyes"; then + # Darwin extended attributes support + AC_CACHE_VAL([ac_cv_archive_xattr_darwin], + [AC_CHECK_FUNCS(fgetxattr \ + flistxattr \ + fsetxattr \ + getxattr \ + listxattr \ + setxattr, + [ac_cv_archive_xattr_darwin=yes], + [ac_cv_archive_xattr_darwin=no], + [#include +]) + ] + ) + elif test "x$ac_cv_header_sys_extattr_h" = "xyes" \ + -a "x$ac_cv_have_decl_EXTATTR_NAMESPACE_USER" = "xyes"; then + # FreeBSD extended attributes support + AC_CACHE_VAL([ac_cv_archive_xattr_freebsd], + [AC_CHECK_FUNCS(extattr_get_fd \ + extattr_get_file \ + extattr_get_link \ + extattr_list_fd \ + extattr_list_file \ + extattr_list_link \ + extattr_set_fd \ + extattr_set_link, + [ac_cv_archive_xattr_freebsd=yes], + [ac_cv_archive_xattr_freebsd=no], + [#include +#include +]) + ] + ) + elif test "x$ac_cv_header_sys_xattr_h" = "xyes" \ + -o "x$ac_cv_header_attr_xattr_h" = "xyes"; then + # Linux extended attributes support + AC_CACHE_VAL([ac_cv_archive_xattr_linux], + [AC_CHECK_FUNCS(fgetxattr \ + flistxattr \ + fsetxattr \ + getxattr \ + lgetxattr \ + listxattr \ + llistxattr \ + lsetxattr, + [ac_cv_archive_xattr_linux=yes], + [ac_cv_archive_xattr_linux=no], + [#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_XATTR_H +#include +#endif +#if HAVE_ATTR_XATTR_H +#include +#endif +]) + ] + ) + elif test "x$ac_cv_header_sys_ea_h" = "xyes"; then + # AIX extended attributes support + AC_CACHE_VAL([ac_cv_archive_xattr_aix], + [AC_CHECK_FUNCS(fgetea \ + flistea \ + fsetea \ + getea \ + lgetea \ + listea \ + llistea \ + lsetea, + [ac_cv_archive_xattr_aix=yes], + [ac_cv_archive_xattr_aix=no], + [#include +]) + ] + ) + fi + + AC_MSG_CHECKING([for extended attributes support]) + if test "x$ac_cv_archive_xattr_linux" = "xyes"; then + AC_DEFINE([ARCHIVE_XATTR_LINUX], [1], [Linux xattr support]) + AC_MSG_RESULT([Linux]) + elif test "x$ac_cv_archive_xattr_darwin" = "xyes"; then + AC_DEFINE([ARCHIVE_XATTR_DARWIN], [1], [Darwin xattr support]) + AC_MSG_RESULT([Darwin]) + elif test "x$ac_cv_archive_xattr_freebsd" = "xyes"; then + AC_DEFINE([ARCHIVE_XATTR_FREEBSD], [1], [FreeBSD xattr support]) + AC_MSG_RESULT([FreeBSD]) + elif test "x$ac_cv_archive_xattr_aix" = "xyes"; then + AC_DEFINE([ARCHIVE_XATTR_AIX], [1], [AIX xattr support]) + AC_MSG_RESULT([AIX]) + else + AC_MSG_RESULT([none]) + fi fi # Check for ACL support # # 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. # AC_ARG_ENABLE([acl], AS_HELP_STRING([--disable-acl], [Disable ACL support (default: check)])) if test "x$enable_acl" != "xno"; then # Libacl AC_CHECK_LIB([acl], [acl_get_file]) AC_CHECK_TYPES([acl_t, acl_entry_t, acl_permset_t, acl_tag_t], [], [], [ #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_ACL_H #include #endif ]) AC_CHECK_LIB([richacl], [richacl_get_file]) AC_CHECK_TYPES([[struct richace], [struct richacl]], [], [], [ #if HAVE_SYS_RICHACL_H #include #endif ]) # Solaris and derivates ACLs AC_CHECK_FUNCS(acl facl) if test "x$ac_cv_lib_richacl_richacl_get_file" = "xyes" \ -a "x$ac_cv_type_struct_richace" = "xyes" \ -a "x$ac_cv_type_struct_richacl" = "xyes"; then AC_CACHE_VAL([ac_cv_archive_acl_librichacl], [AC_CHECK_FUNCS(richacl_alloc \ richacl_equiv_mode \ richacl_free \ richacl_get_fd \ richacl_get_file \ richacl_set_fd \ richacl_set_file, [ac_cv_archive_acl_librichacl=yes], [ac_cv_archive_acl_librichacl=no], [#include ])]) fi if test "x$ac_cv_func_acl" = "xyes" \ -a "x$ac_cv_func_facl" = "xyes"; then AC_CHECK_TYPES([aclent_t], [], [], [[#include ]]) if test "x$ac_cv_type_aclent_t" = "xyes"; then AC_CACHE_VAL([ac_cv_archive_acl_sunos], [AC_CHECK_DECLS([GETACL, SETACL, GETACLCNT], [ac_cv_archive_acl_sunos=yes], [ac_cv_archive_acl_sunos=no], [#include ])]) AC_CHECK_TYPES([ace_t], [], [], [[#include ]]) if test "x$ac_cv_type_ace_t" = "xyes"; then AC_CACHE_VAL([ac_cv_archive_acl_sunos_nfs4], [AC_CHECK_DECLS([ACE_GETACL, ACE_SETACL, ACE_GETACLCNT], [ac_cv_archive_acl_sunos_nfs4=yes], [ac_cv_archive_acl_sonos_nfs4=no], [#include ])]) fi fi elif test "x$ac_cv_type_acl_t" = "xyes" \ -a "x$ac_cv_type_acl_entry_t" = "xyes" \ -a "x$ac_cv_type_acl_permset_t" = "xyes" \ -a "x$ac_cv_type_acl_tag_t" = "xyes"; then # POSIX.1e ACL functions AC_CACHE_VAL([ac_cv_posix_acl_funcs], [AC_CHECK_FUNCS(acl_add_perm \ acl_clear_perms \ acl_create_entry \ acl_delete_def_file \ acl_free \ acl_get_entry \ acl_get_fd \ acl_get_file \ acl_get_permset \ acl_get_qualifier \ acl_get_tag_type \ acl_init \ acl_set_fd \ acl_set_file \ acl_set_qualifier \ acl_set_tag_type, [ac_cv_posix_acl_funcs=yes], [ac_cv_posix_acl_funcs=no], [#if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_ACL_H #include #endif ]) ]) AC_CHECK_FUNCS(acl_get_perm) if test "x$ac_cv_posix_acl_funcs" = "xyes" \ -a "x$ac_cv_header_acl_libacl_h" = "xyes" \ -a "x$ac_cv_lib_acl_acl_get_file" = "xyes" \ -a "x$ac_cv_func_acl_get_perm"; then AC_CACHE_VAL([ac_cv_archive_acl_libacl], [ac_cv_archive_acl_libacl=yes]) AC_DEFINE([ARCHIVE_ACL_LIBACL], [1], [POSIX.1e ACL support via libacl]) else # FreeBSD/Darwin AC_CHECK_FUNCS(acl_add_flag_np \ acl_clear_flags_np \ acl_get_brand_np \ acl_get_entry_type_np \ acl_get_flag_np \ acl_get_flagset_np \ acl_get_fd_np \ acl_get_link_np \ acl_get_perm_np \ acl_is_trivial_np \ acl_set_entry_type_np \ acl_set_fd_np \ acl_set_link_np,,, [#include #include ]) AC_CHECK_FUNCS(mbr_uid_to_uuid \ mbr_uuid_to_id \ mbr_gid_to_uuid,,, [#include ]) AC_CHECK_DECLS([ACL_TYPE_EXTENDED, ACL_TYPE_NFS4, ACL_USER, ACL_SYNCHRONIZE], [], [], [#include #include ]) if test "x$ac_cv_posix_acl_funcs" = "xyes" \ -a "x$ac_cv_func_acl_get_fd_np" = "xyes" \ -a "x$ac_cv_func_acl_get_perm" != "xyes" \ -a "x$ac_cv_func_acl_get_perm_np" = "xyes" \ -a "x$ac_cv_func_acl_set_fd_np" = "xyes"; then if test "x$ac_cv_have_decl_ACL_USER" = "xyes"; then AC_CACHE_VAL([ac_cv_archive_acl_freebsd], [ac_cv_archive_acl_freebsd=yes]) if test "x$ac_cv_have_decl_ACL_TYPE_NFS4" = "xyes" \ -a "x$ac_cv_func_acl_add_flag_np" = "xyes" \ -a "x$ac_cv_func_acl_get_brand_np" = "xyes" \ -a "x$ac_cv_func_acl_get_entry_type_np" = "xyes" \ -a "x$ac_cv_func_acl_get_flagset_np" = "xyes" \ -a "x$ac_cv_func_acl_set_entry_type_np" = "xyes"; then AC_CACHE_VAL([ac_cv_archive_acl_freebsd_nfs4], [ac_cv_archive_acl_freebsd_nfs4=yes]) fi elif test "x$ac_cv_have_decl_ACL_TYPE_EXTENDED" = "xyes" \ -a "x$ac_cv_func_acl_add_flag_np" = "xyes" \ -a "x$ac_cv_func_acl_get_flagset_np" = "xyes" \ -a "x$ac_cv_func_acl_get_link_np" = "xyes" \ -a "x$ac_cv_func_acl_set_link_np" = "xyes" \ -a "x$ac_cv_func_mbr_uid_to_uuid" = "xyes" \ -a "x$ac_cv_func_mbr_uuid_to_id" = "xyes" \ -a "x$ac_cv_func_mbr_gid_to_uuid" = "xyes"; then AC_CACHE_VAL([ac_cv_archive_acl_darwin], [ac_cv_archive_acl_darwin=yes]) fi fi fi fi AC_MSG_CHECKING([for ACL support]) if test "x$ac_cv_archive_acl_libacl" = "xyes" \ -a "x$ac_cv_archive_acl_librichacl" = "xyes"; then AC_MSG_RESULT([libacl (POSIX.1e) + librichacl (NFSv4)]) AC_DEFINE([ARCHIVE_ACL_LIBACL], [1], [Linux POSIX.1e ACL support via libacl]) AC_DEFINE([ARCHIVE_ACL_LIBRICHACL], [1], [Linux NFSv4 ACL support via librichacl]) elif test "x$ac_cv_archive_acl_libacl" = "xyes"; then AC_MSG_RESULT([libacl (POSIX.1e)]) AC_DEFINE([ARCHIVE_ACL_LIBACL], [1], [Linux POSIX.1e ACL support via libacl]) elif test "x$ac_cv_archive_acl_librichacl" = "xyes"; then AC_MSG_RESULT([librichacl (NFSv4)]) AC_DEFINE([ARCHIVE_ACL_LIBRICHACL], [1], [Linux NFSv4 ACL support via librichacl]) elif test "x$ac_cv_archive_acl_darwin" = "xyes"; then AC_DEFINE([ARCHIVE_ACL_DARWIN], [1], [Darwin ACL support]) AC_MSG_RESULT([Darwin (limited NFSv4)]) elif test "x$ac_cv_archive_acl_sunos" = "xyes"; then AC_DEFINE([ARCHIVE_ACL_SUNOS], [1], [Solaris ACL support]) if test "x$ac_cv_archive_acl_sunos_nfs4" = "xyes"; then AC_DEFINE([ARCHIVE_ACL_SUNOS_NFS4], [1], [Solaris NFSv4 ACL support]) AC_MSG_RESULT([Solaris (POSIX.1e and NFSv4)]) else AC_MSG_RESULT([Solaris (POSIX.1e)]) fi elif test "x$ac_cv_archive_acl_freebsd" = "xyes"; then AC_DEFINE([ARCHIVE_ACL_FREEBSD], [1], [FreeBSD ACL support]) if test "x$ac_cv_archive_acl_freebsd_nfs4" = "xyes"; then AC_DEFINE([ARCHIVE_ACL_FREEBSD_NFS4], [1], [FreeBSD NFSv4 ACL support]) AC_MSG_RESULT([FreeBSD (POSIX.1e and NFSv4)]) else AC_MSG_RESULT([FreeBSD (POSIX.1e)]) fi else AC_MSG_RESULT([none]) fi fi AM_CONDITIONAL([INC_LINUX_ACL], [test "x$ac_cv_archive_acl_libacl" = "xyes" \ -o "x$ac_cv_archive_acl_librichacl" = "xyes"]) AM_CONDITIONAL([INC_SUNOS_ACL], [test "x$ac_cv_archive_acl_sunos" = "xyes"]) AM_CONDITIONAL([INC_DARWIN_ACL], [test "x$ac_cv_archive_acl_darwin" = "xyes"]) AM_CONDITIONAL([INC_FREEBSD_ACL], [test "x$ac_cv_archive_acl_freebsd" = "xyes"]) # Additional requirements AC_SYS_LARGEFILE dnl NOTE: Crypto checks must run last. AC_DEFUN([CRYPTO_CHECK], [ if test "$found_$1" != yes; then saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I. -I$srcdir -I$srcdir/libarchive" touch "check_crypto_md.h" AC_MSG_CHECKING([support for ARCHIVE_CRYPTO_$1_$2]) AC_LINK_IFELSE([AC_LANG_SOURCE([ #define ARCHIVE_$1_COMPILE_TEST #define ARCHIVE_CRYPTO_$1_$2 #define PLATFORM_CONFIG_H "check_crypto_md.h" $(cat "$srcdir/libarchive/archive_digest.c") int main(int argc, char **argv) { archive_$3_ctx ctx; archive_$3_init(&ctx); archive_$3_update(&ctx, *argv, argc); archive_$3_final(&ctx, NULL); return 0; } ])], [ AC_MSG_RESULT([yes]) found_$1=yes found_$2=yes AC_DEFINE(ARCHIVE_CRYPTO_$1_$2, 1, [ $1 via ARCHIVE_CRYPTO_$1_$2 supported.]) ], [ AC_MSG_RESULT([no])]) CPPFLAGS="$saved_CPPFLAGS" rm "check_crypto_md.h" fi ]) AC_DEFUN([CRYPTO_CHECK_WIN], [ if test "$found_$1" != yes; then AC_MSG_CHECKING([support for ARCHIVE_CRYPTO_$1_WIN]) AC_LINK_IFELSE([AC_LANG_SOURCE([ #define ARCHIVE_$1_COMPILE_TEST #include #include int main(int argc, char **argv) { (void)argc; (void)argv; return ($2); } ])], [ AC_MSG_RESULT([yes]) found_$1=yes found_WIN=yes AC_DEFINE(ARCHIVE_CRYPTO_$1_WIN, 1, [ $1 via ARCHIVE_CRYPTO_$1_WIN supported.]) ], [ AC_MSG_RESULT([no])]) fi ]) case "$host_os" in *mingw* | *cygwin* | *msys*) ;; *) CRYPTO_CHECK(MD5, LIBC, md5) CRYPTO_CHECK(MD5, LIBSYSTEM, md5) CRYPTO_CHECK(RMD160, LIBC, rmd160) CRYPTO_CHECK(SHA1, LIBC, sha1) CRYPTO_CHECK(SHA1, LIBSYSTEM, sha1) CRYPTO_CHECK(SHA256, LIBC, sha256) CRYPTO_CHECK(SHA256, LIBC2, sha256) CRYPTO_CHECK(SHA256, LIBC3, sha256) CRYPTO_CHECK(SHA256, LIBSYSTEM, sha256) CRYPTO_CHECK(SHA384, LIBC, sha384) CRYPTO_CHECK(SHA384, LIBC2, sha384) CRYPTO_CHECK(SHA384, LIBC3, sha384) CRYPTO_CHECK(SHA384, LIBSYSTEM, sha384) CRYPTO_CHECK(SHA512, LIBC, sha512) CRYPTO_CHECK(SHA512, LIBC2, sha512) CRYPTO_CHECK(SHA512, LIBC3, sha512) CRYPTO_CHECK(SHA512, LIBSYSTEM, sha512) ;; esac if test "x$with_cng" != "xno"; then AC_CHECK_HEADERS([bcrypt.h],[ LIBS="$LIBS -lbcrypt" ],[], [[#ifdef HAVE_WINDOWS_H # include #endif ]]) fi if test "x$with_nettle" != "xno"; then AC_CHECK_HEADERS([nettle/md5.h nettle/ripemd160.h nettle/sha.h]) AC_CHECK_HEADERS([nettle/pbkdf2.h nettle/aes.h nettle/hmac.h]) saved_LIBS=$LIBS AC_CHECK_LIB(nettle,nettle_sha1_init) CRYPTO_CHECK(MD5, NETTLE, md5) CRYPTO_CHECK(RMD160, NETTLE, rmd160) CRYPTO_CHECK(SHA1, NETTLE, sha1) CRYPTO_CHECK(SHA256, NETTLE, sha256) CRYPTO_CHECK(SHA384, NETTLE, sha384) CRYPTO_CHECK(SHA512, NETTLE, sha512) if test "x$found_NETTLE" != "xyes"; then LIBS=$saved_LIBS fi fi if test "x$with_openssl" != "xno"; then AC_CHECK_HEADERS([openssl/evp.h]) saved_LIBS=$LIBS case "$host_os" in *mingw* | *cygwin* | *msys*) case "$host_cpu" in x86_64) AC_CHECK_LIB(eay64,OPENSSL_config) if test "x$ac_cv_lib_eay64_main" != "xyes"; then AC_CHECK_LIB(eay32,OPENSSL_config) fi ;; *) AC_CHECK_LIB(eay32,OPENSSL_config) ;; esac ;; *) AC_CHECK_LIB(crypto,OPENSSL_config) ;; esac CRYPTO_CHECK(MD5, OPENSSL, md5) CRYPTO_CHECK(RMD160, OPENSSL, rmd160) CRYPTO_CHECK(SHA1, OPENSSL, sha1) CRYPTO_CHECK(SHA256, OPENSSL, sha256) CRYPTO_CHECK(SHA384, OPENSSL, sha384) CRYPTO_CHECK(SHA512, OPENSSL, sha512) if test "x$found_OPENSSL" != "xyes"; then LIBS=$saved_LIBS else AC_CHECK_FUNCS([PKCS5_PBKDF2_HMAC_SHA1]) fi AC_CHECK_LIB(crypto,EVP_CIPHER_CTX_init) fi # Probe libmd AFTER OpenSSL/libcrypto. # The two are incompatible and OpenSSL is more complete. AC_CHECK_HEADERS([md5.h ripemd.h sha.h sha256.h sha512.h]) saved_LIBS=$LIBS AC_CHECK_LIB(md,MD5Init) CRYPTO_CHECK(MD5, LIBMD, md5) CRYPTO_CHECK(RMD160, LIBMD, rmd160) CRYPTO_CHECK(SHA1, LIBMD, sha1) CRYPTO_CHECK(SHA256, LIBMD, sha256) CRYPTO_CHECK(SHA512, LIBMD, sha512) if test "x$found_LIBMD" != "xyes"; then LIBS=$saved_LIBS fi case "$host_os" in *mingw* | *cygwin* | *msys*) CRYPTO_CHECK_WIN(MD5, CALG_MD5) CRYPTO_CHECK_WIN(SHA1, CALG_SHA1) CRYPTO_CHECK_WIN(SHA256, CALG_SHA_256) CRYPTO_CHECK_WIN(SHA384, CALG_SHA_384) CRYPTO_CHECK_WIN(SHA512, CALG_SHA_512) ;; esac # Ensure test directories are present if building out-of-tree AC_CONFIG_COMMANDS([mkdirs], [mkdir -p libarchive/test tar/test cat/test cpio/test]) AC_OUTPUT Index: vendor/libarchive/dist/libarchive/CMakeLists.txt =================================================================== --- vendor/libarchive/dist/libarchive/CMakeLists.txt (revision 315874) +++ vendor/libarchive/dist/libarchive/CMakeLists.txt (revision 315875) @@ -1,262 +1,263 @@ ############################################ # # How to build libarchive # ############################################ # Public headers SET(include_HEADERS archive.h archive_entry.h ) # Sources and private headers SET(libarchive_SOURCES archive_acl.c archive_acl_private.h archive_check_magic.c archive_cmdline.c archive_cmdline_private.h archive_crc32.h archive_cryptor.c archive_cryptor_private.h archive_digest.c archive_digest_private.h archive_endian.h archive_entry.c archive_entry.h archive_entry_copy_stat.c archive_entry_link_resolver.c archive_entry_locale.h archive_entry_private.h archive_entry_sparse.c archive_entry_stat.c archive_entry_strmode.c archive_entry_xattr.c archive_getdate.c archive_getdate.h archive_hmac.c archive_hmac_private.h archive_match.c archive_openssl_evp_private.h archive_openssl_hmac_private.h archive_options.c archive_options_private.h archive_pack_dev.h archive_pack_dev.c archive_pathmatch.c archive_pathmatch.h archive_platform.h archive_platform_acl.h + archive_platform_xattr.h archive_ppmd_private.h archive_ppmd7.c archive_ppmd7_private.h archive_private.h archive_random.c archive_random_private.h archive_rb.c archive_rb.h archive_read.c archive_read_add_passphrase.c archive_read_append_filter.c archive_read_data_into_fd.c archive_read_disk_entry_from_file.c archive_read_disk_posix.c archive_read_disk_private.h archive_read_disk_set_standard_lookup.c archive_read_extract.c archive_read_extract2.c archive_read_open_fd.c archive_read_open_file.c archive_read_open_filename.c archive_read_open_memory.c archive_read_private.h archive_read_set_format.c archive_read_set_options.c archive_read_support_filter_all.c archive_read_support_filter_bzip2.c archive_read_support_filter_compress.c archive_read_support_filter_gzip.c archive_read_support_filter_grzip.c archive_read_support_filter_lrzip.c archive_read_support_filter_lz4.c archive_read_support_filter_lzop.c archive_read_support_filter_none.c archive_read_support_filter_program.c archive_read_support_filter_rpm.c archive_read_support_filter_uu.c archive_read_support_filter_xz.c archive_read_support_format_7zip.c archive_read_support_format_all.c archive_read_support_format_ar.c archive_read_support_format_by_code.c archive_read_support_format_cab.c archive_read_support_format_cpio.c archive_read_support_format_empty.c archive_read_support_format_iso9660.c archive_read_support_format_lha.c archive_read_support_format_mtree.c archive_read_support_format_rar.c archive_read_support_format_raw.c archive_read_support_format_tar.c archive_read_support_format_warc.c archive_read_support_format_xar.c archive_read_support_format_zip.c archive_string.c archive_string.h archive_string_composition.h archive_string_sprintf.c archive_util.c archive_version_details.c archive_virtual.c archive_write.c archive_write_disk_posix.c archive_write_disk_private.h archive_write_disk_set_standard_lookup.c archive_write_private.h archive_write_open_fd.c archive_write_open_file.c archive_write_open_filename.c archive_write_open_memory.c archive_write_add_filter.c archive_write_add_filter_b64encode.c archive_write_add_filter_by_name.c archive_write_add_filter_bzip2.c archive_write_add_filter_compress.c archive_write_add_filter_grzip.c archive_write_add_filter_gzip.c archive_write_add_filter_lrzip.c archive_write_add_filter_lz4.c archive_write_add_filter_lzop.c archive_write_add_filter_none.c archive_write_add_filter_program.c archive_write_add_filter_uuencode.c archive_write_add_filter_xz.c archive_write_set_format.c archive_write_set_format_7zip.c archive_write_set_format_ar.c archive_write_set_format_by_name.c archive_write_set_format_cpio.c archive_write_set_format_cpio_newc.c archive_write_set_format_filter_by_ext.c archive_write_set_format_gnutar.c archive_write_set_format_iso9660.c archive_write_set_format_mtree.c archive_write_set_format_pax.c archive_write_set_format_raw.c archive_write_set_format_shar.c archive_write_set_format_ustar.c archive_write_set_format_v7tar.c archive_write_set_format_warc.c archive_write_set_format_xar.c archive_write_set_format_zip.c archive_write_set_options.c archive_write_set_passphrase.c archive_xxhash.h filter_fork_posix.c filter_fork.h xxhash.c ) # Man pages SET(libarchive_MANS archive_entry.3 archive_entry_acl.3 archive_entry_linkify.3 archive_entry_paths.3 archive_entry_perms.3 archive_entry_stat.3 archive_entry_time.3 archive_read.3 archive_read_add_passphrase.3 archive_read_data.3 archive_read_disk.3 archive_read_extract.3 archive_read_filter.3 archive_read_format.3 archive_read_free.3 archive_read_header.3 archive_read_new.3 archive_read_open.3 archive_read_set_options.3 archive_util.3 archive_write.3 archive_write_blocksize.3 archive_write_data.3 archive_write_disk.3 archive_write_filter.3 archive_write_finish_entry.3 archive_write_format.3 archive_write_free.3 archive_write_header.3 archive_write_new.3 archive_write_open.3 archive_write_set_options.3 archive_write_set_passphrase.3 cpio.5 libarchive.3 libarchive_changes.3 libarchive_internals.3 libarchive-formats.5 mtree.5 tar.5 ) IF(WIN32 AND NOT CYGWIN) LIST(APPEND libarchive_SOURCES archive_entry_copy_bhfi.c) LIST(APPEND libarchive_SOURCES archive_read_disk_windows.c) LIST(APPEND libarchive_SOURCES archive_windows.c) LIST(APPEND libarchive_SOURCES archive_windows.h) LIST(APPEND libarchive_SOURCES archive_write_disk_windows.c) LIST(APPEND libarchive_SOURCES filter_fork_windows.c) ENDIF(WIN32 AND NOT CYGWIN) IF(ARCHIVE_ACL_DARWIN) LIST(APPEND libarchive_SOURCES archive_acl_maps.h) LIST(APPEND libarchive_SOURCES archive_acl_maps_darwin.c) LIST(APPEND libarchive_SOURCES archive_read_disk_acl_darwin.c) LIST(APPEND libarchive_SOURCES archive_write_disk_acl_darwin.c) ELSEIF(ARCHIVE_ACL_FREEBSD) LIST(APPEND libarchive_SOURCES archive_acl_maps.h) LIST(APPEND libarchive_SOURCES archive_acl_maps_freebsd.c) LIST(APPEND libarchive_SOURCES archive_read_disk_acl_freebsd.c) LIST(APPEND libarchive_SOURCES archive_write_disk_acl_freebsd.c) ELSEIF(ARCHIVE_ACL_LIBACL) LIST(APPEND libarchive_SOURCES archive_acl_maps.h) LIST(APPEND libarchive_SOURCES archive_acl_maps_linux.c) LIST(APPEND libarchive_SOURCES archive_read_disk_acl_linux.c) LIST(APPEND libarchive_SOURCES archive_write_disk_acl_linux.c) ELSEIF(ARCHIVE_ACL_SUNOS) LIST(APPEND libarchive_SOURCES archive_acl_maps.h) LIST(APPEND libarchive_SOURCES archive_acl_maps_sunos.c) LIST(APPEND libarchive_SOURCES archive_read_disk_acl_sunos.c) LIST(APPEND libarchive_SOURCES archive_write_disk_acl_sunos.c) ENDIF() # Libarchive is a shared library ADD_LIBRARY(archive SHARED ${libarchive_SOURCES} ${include_HEADERS}) TARGET_LINK_LIBRARIES(archive ${ADDITIONAL_LIBS}) SET_TARGET_PROPERTIES(archive PROPERTIES SOVERSION ${SOVERSION}) # archive_static is a static library ADD_LIBRARY(archive_static STATIC ${libarchive_SOURCES} ${include_HEADERS}) TARGET_LINK_LIBRARIES(archive_static ${ADDITIONAL_LIBS}) SET_TARGET_PROPERTIES(archive_static PROPERTIES COMPILE_DEFINITIONS LIBARCHIVE_STATIC) # On Posix systems, libarchive.so and libarchive.a can co-exist. IF(NOT WIN32 OR CYGWIN) SET_TARGET_PROPERTIES(archive_static PROPERTIES OUTPUT_NAME archive) ENDIF(NOT WIN32 OR CYGWIN) IF(ENABLE_INSTALL) # How to install the libraries INSTALL(TARGETS archive archive_static RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) INSTALL_MAN(${libarchive_MANS}) INSTALL(FILES ${include_HEADERS} DESTINATION include) ENDIF() add_subdirectory(test) Index: vendor/libarchive/dist/libarchive/archive_entry.c =================================================================== --- vendor/libarchive/dist/libarchive/archive_entry.c (revision 315874) +++ vendor/libarchive/dist/libarchive/archive_entry.c (revision 315875) @@ -1,2035 +1,2038 @@ /*- * Copyright (c) 2003-2007 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. */ #include "archive_platform.h" __FBSDID("$FreeBSD: head/lib/libarchive/archive_entry.c 201096 2009-12-28 02:41:27Z kientzle $"); #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #if MAJOR_IN_MKDEV #include #define HAVE_MAJOR #elif MAJOR_IN_SYSMACROS #include #define HAVE_MAJOR #endif #ifdef HAVE_ERRNO_H #include #endif #ifdef HAVE_LIMITS_H #include #endif #ifdef HAVE_LINUX_FS_H #include /* 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 /* for Linux file flags */ #endif #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) #include /* for Linux file flags */ #endif #include #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_WCHAR_H #include #endif #include "archive.h" #include "archive_acl_private.h" #include "archive_entry.h" #include "archive_entry_locale.h" #include "archive_private.h" #include "archive_entry_private.h" #if !defined(HAVE_MAJOR) && !defined(major) /* Replacement for major/minor/makedev. */ #define major(x) ((int)(0x00ff & ((x) >> 8))) #define minor(x) ((int)(0xffff00ff & (x))) #define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min))) #endif /* Play games to come up with a suitable makedev() definition. */ #ifdef __QNXNTO__ /* QNX. */ #include #define ae_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min)) #elif defined makedev /* There's a "makedev" macro. */ #define ae_makedev(maj, min) makedev((maj), (min)) #elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__)) /* Windows. */ #define ae_makedev(maj, min) mkdev((maj), (min)) #else /* There's a "makedev" function. */ #define ae_makedev(maj, min) makedev((maj), (min)) #endif /* * This adjustment is needed to support the following idiom for adding * 1000ns to the stored time: * archive_entry_set_atime(archive_entry_atime(), * archive_entry_atime_nsec() + 1000) * The additional if() here compensates for ambiguity in the C standard, * which permits two possible interpretations of a % b when a is negative. */ #define FIX_NS(t,ns) \ do { \ t += ns / 1000000000; \ ns %= 1000000000; \ if (ns < 0) { --t; ns += 1000000000; } \ } while (0) static char * ae_fflagstostr(unsigned long bitset, unsigned long bitclear); static const wchar_t *ae_wcstofflags(const wchar_t *stringp, unsigned long *setp, unsigned long *clrp); static const char *ae_strtofflags(const char *stringp, unsigned long *setp, unsigned long *clrp); #ifndef HAVE_WCSCPY static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2) { wchar_t *dest = s1; while ((*s1 = *s2) != L'\0') ++s1, ++s2; return dest; } #endif #ifndef HAVE_WCSLEN static size_t wcslen(const wchar_t *s) { const wchar_t *p = s; while (*p != L'\0') ++p; return p - s; } #endif #ifndef HAVE_WMEMCMP /* Good enough for simple equality testing, but not for sorting. */ #define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t)) #endif /**************************************************************************** * * Public Interface * ****************************************************************************/ struct archive_entry * archive_entry_clear(struct archive_entry *entry) { if (entry == NULL) return (NULL); archive_mstring_clean(&entry->ae_fflags_text); archive_mstring_clean(&entry->ae_gname); archive_mstring_clean(&entry->ae_hardlink); archive_mstring_clean(&entry->ae_pathname); archive_mstring_clean(&entry->ae_sourcepath); archive_mstring_clean(&entry->ae_symlink); archive_mstring_clean(&entry->ae_uname); archive_entry_copy_mac_metadata(entry, NULL, 0); archive_acl_clear(&entry->acl); archive_entry_xattr_clear(entry); archive_entry_sparse_clear(entry); free(entry->stat); memset(entry, 0, sizeof(*entry)); return entry; } struct archive_entry * archive_entry_clone(struct archive_entry *entry) { struct archive_entry *entry2; struct ae_xattr *xp; struct ae_sparse *sp; size_t s; const void *p; /* Allocate new structure and copy over all of the fields. */ /* TODO: Should we copy the archive over? Or require a new archive * as an argument? */ entry2 = archive_entry_new2(entry->archive); if (entry2 == NULL) return (NULL); entry2->ae_stat = entry->ae_stat; entry2->ae_fflags_set = entry->ae_fflags_set; entry2->ae_fflags_clear = entry->ae_fflags_clear; /* TODO: XXX If clone can have a different archive, what do we do here if * character sets are different? XXX */ archive_mstring_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text); archive_mstring_copy(&entry2->ae_gname, &entry->ae_gname); archive_mstring_copy(&entry2->ae_hardlink, &entry->ae_hardlink); archive_mstring_copy(&entry2->ae_pathname, &entry->ae_pathname); archive_mstring_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath); archive_mstring_copy(&entry2->ae_symlink, &entry->ae_symlink); entry2->ae_set = entry->ae_set; archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname); /* Copy encryption status */ entry2->encryption = entry->encryption; /* Copy ACL data over. */ archive_acl_copy(&entry2->acl, &entry->acl); /* Copy Mac OS metadata. */ p = archive_entry_mac_metadata(entry, &s); archive_entry_copy_mac_metadata(entry2, p, s); /* Copy xattr data over. */ xp = entry->xattr_head; while (xp != NULL) { archive_entry_xattr_add_entry(entry2, xp->name, xp->value, xp->size); xp = xp->next; } /* Copy sparse data over. */ sp = entry->sparse_head; while (sp != NULL) { archive_entry_sparse_add_entry(entry2, sp->offset, sp->length); sp = sp->next; } return (entry2); } void archive_entry_free(struct archive_entry *entry) { archive_entry_clear(entry); free(entry); } struct archive_entry * archive_entry_new(void) { return archive_entry_new2(NULL); } struct archive_entry * archive_entry_new2(struct archive *a) { struct archive_entry *entry; entry = (struct archive_entry *)calloc(1, sizeof(*entry)); if (entry == NULL) return (NULL); entry->archive = a; return (entry); } /* * Functions for reading fields from an archive_entry. */ time_t archive_entry_atime(struct archive_entry *entry) { return (entry->ae_stat.aest_atime); } long archive_entry_atime_nsec(struct archive_entry *entry) { return (entry->ae_stat.aest_atime_nsec); } int archive_entry_atime_is_set(struct archive_entry *entry) { return (entry->ae_set & AE_SET_ATIME); } time_t archive_entry_birthtime(struct archive_entry *entry) { return (entry->ae_stat.aest_birthtime); } long archive_entry_birthtime_nsec(struct archive_entry *entry) { return (entry->ae_stat.aest_birthtime_nsec); } int archive_entry_birthtime_is_set(struct archive_entry *entry) { return (entry->ae_set & AE_SET_BIRTHTIME); } time_t archive_entry_ctime(struct archive_entry *entry) { return (entry->ae_stat.aest_ctime); } int archive_entry_ctime_is_set(struct archive_entry *entry) { return (entry->ae_set & AE_SET_CTIME); } long archive_entry_ctime_nsec(struct archive_entry *entry) { return (entry->ae_stat.aest_ctime_nsec); } dev_t archive_entry_dev(struct archive_entry *entry) { if (entry->ae_stat.aest_dev_is_broken_down) return ae_makedev(entry->ae_stat.aest_devmajor, entry->ae_stat.aest_devminor); else return (entry->ae_stat.aest_dev); } int archive_entry_dev_is_set(struct archive_entry *entry) { return (entry->ae_set & AE_SET_DEV); } dev_t archive_entry_devmajor(struct archive_entry *entry) { if (entry->ae_stat.aest_dev_is_broken_down) return (entry->ae_stat.aest_devmajor); else return major(entry->ae_stat.aest_dev); } dev_t archive_entry_devminor(struct archive_entry *entry) { if (entry->ae_stat.aest_dev_is_broken_down) return (entry->ae_stat.aest_devminor); else return minor(entry->ae_stat.aest_dev); } mode_t archive_entry_filetype(struct archive_entry *entry) { return (AE_IFMT & entry->acl.mode); } void archive_entry_fflags(struct archive_entry *entry, unsigned long *set, unsigned long *clear) { *set = entry->ae_fflags_set; *clear = entry->ae_fflags_clear; } /* * Note: if text was provided, this just returns that text. If you * really need the text to be rebuilt in a canonical form, set the * text, ask for the bitmaps, then set the bitmaps. (Setting the * bitmaps clears any stored text.) This design is deliberate: if * we're editing archives, we don't want to discard flags just because * they aren't supported on the current system. The bitmap<->text * conversions are platform-specific (see below). */ const char * archive_entry_fflags_text(struct archive_entry *entry) { const char *f; char *p; if (archive_mstring_get_mbs(entry->archive, &entry->ae_fflags_text, &f) == 0) { if (f != NULL) return (f); } else if (errno == ENOMEM) __archive_errx(1, "No memory"); if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0) return (NULL); p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear); if (p == NULL) return (NULL); archive_mstring_copy_mbs(&entry->ae_fflags_text, p); free(p); if (archive_mstring_get_mbs(entry->archive, &entry->ae_fflags_text, &f) == 0) return (f); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } la_int64_t archive_entry_gid(struct archive_entry *entry) { return (entry->ae_stat.aest_gid); } const char * archive_entry_gname(struct archive_entry *entry) { const char *p; if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } const char * archive_entry_gname_utf8(struct archive_entry *entry) { const char *p; if (archive_mstring_get_utf8(entry->archive, &entry->ae_gname, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } const wchar_t * archive_entry_gname_w(struct archive_entry *entry) { const wchar_t *p; if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } int _archive_entry_gname_l(struct archive_entry *entry, const char **p, size_t *len, struct archive_string_conv *sc) { return (archive_mstring_get_mbs_l(&entry->ae_gname, p, len, sc)); } const char * archive_entry_hardlink(struct archive_entry *entry) { const char *p; if ((entry->ae_set & AE_SET_HARDLINK) == 0) return (NULL); if (archive_mstring_get_mbs( entry->archive, &entry->ae_hardlink, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } const char * archive_entry_hardlink_utf8(struct archive_entry *entry) { const char *p; if ((entry->ae_set & AE_SET_HARDLINK) == 0) return (NULL); if (archive_mstring_get_utf8( entry->archive, &entry->ae_hardlink, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } const wchar_t * archive_entry_hardlink_w(struct archive_entry *entry) { const wchar_t *p; if ((entry->ae_set & AE_SET_HARDLINK) == 0) return (NULL); if (archive_mstring_get_wcs( entry->archive, &entry->ae_hardlink, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } int _archive_entry_hardlink_l(struct archive_entry *entry, const char **p, size_t *len, struct archive_string_conv *sc) { if ((entry->ae_set & AE_SET_HARDLINK) == 0) { *p = NULL; *len = 0; return (0); } return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc)); } la_int64_t archive_entry_ino(struct archive_entry *entry) { return (entry->ae_stat.aest_ino); } int archive_entry_ino_is_set(struct archive_entry *entry) { return (entry->ae_set & AE_SET_INO); } la_int64_t archive_entry_ino64(struct archive_entry *entry) { return (entry->ae_stat.aest_ino); } mode_t archive_entry_mode(struct archive_entry *entry) { return (entry->acl.mode); } time_t archive_entry_mtime(struct archive_entry *entry) { return (entry->ae_stat.aest_mtime); } long archive_entry_mtime_nsec(struct archive_entry *entry) { return (entry->ae_stat.aest_mtime_nsec); } int archive_entry_mtime_is_set(struct archive_entry *entry) { return (entry->ae_set & AE_SET_MTIME); } unsigned int archive_entry_nlink(struct archive_entry *entry) { return (entry->ae_stat.aest_nlink); } const char * archive_entry_pathname(struct archive_entry *entry) { const char *p; if (archive_mstring_get_mbs( entry->archive, &entry->ae_pathname, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } const char * archive_entry_pathname_utf8(struct archive_entry *entry) { const char *p; if (archive_mstring_get_utf8( entry->archive, &entry->ae_pathname, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } const wchar_t * archive_entry_pathname_w(struct archive_entry *entry) { const wchar_t *p; if (archive_mstring_get_wcs( entry->archive, &entry->ae_pathname, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } int _archive_entry_pathname_l(struct archive_entry *entry, const char **p, size_t *len, struct archive_string_conv *sc) { return (archive_mstring_get_mbs_l(&entry->ae_pathname, p, len, sc)); } mode_t archive_entry_perm(struct archive_entry *entry) { return (~AE_IFMT & entry->acl.mode); } dev_t archive_entry_rdev(struct archive_entry *entry) { if (entry->ae_stat.aest_rdev_is_broken_down) return ae_makedev(entry->ae_stat.aest_rdevmajor, entry->ae_stat.aest_rdevminor); else return (entry->ae_stat.aest_rdev); } dev_t archive_entry_rdevmajor(struct archive_entry *entry) { if (entry->ae_stat.aest_rdev_is_broken_down) return (entry->ae_stat.aest_rdevmajor); else return major(entry->ae_stat.aest_rdev); } dev_t archive_entry_rdevminor(struct archive_entry *entry) { if (entry->ae_stat.aest_rdev_is_broken_down) return (entry->ae_stat.aest_rdevminor); else return minor(entry->ae_stat.aest_rdev); } la_int64_t archive_entry_size(struct archive_entry *entry) { return (entry->ae_stat.aest_size); } int archive_entry_size_is_set(struct archive_entry *entry) { return (entry->ae_set & AE_SET_SIZE); } const char * archive_entry_sourcepath(struct archive_entry *entry) { const char *p; if (archive_mstring_get_mbs( entry->archive, &entry->ae_sourcepath, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } const wchar_t * archive_entry_sourcepath_w(struct archive_entry *entry) { const wchar_t *p; if (archive_mstring_get_wcs( entry->archive, &entry->ae_sourcepath, &p) == 0) return (p); return (NULL); } const char * archive_entry_symlink(struct archive_entry *entry) { const char *p; if ((entry->ae_set & AE_SET_SYMLINK) == 0) return (NULL); if (archive_mstring_get_mbs( entry->archive, &entry->ae_symlink, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } const char * archive_entry_symlink_utf8(struct archive_entry *entry) { const char *p; if ((entry->ae_set & AE_SET_SYMLINK) == 0) return (NULL); if (archive_mstring_get_utf8( entry->archive, &entry->ae_symlink, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } const wchar_t * archive_entry_symlink_w(struct archive_entry *entry) { const wchar_t *p; if ((entry->ae_set & AE_SET_SYMLINK) == 0) return (NULL); if (archive_mstring_get_wcs( entry->archive, &entry->ae_symlink, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } int _archive_entry_symlink_l(struct archive_entry *entry, const char **p, size_t *len, struct archive_string_conv *sc) { if ((entry->ae_set & AE_SET_SYMLINK) == 0) { *p = NULL; *len = 0; return (0); } return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc)); } la_int64_t archive_entry_uid(struct archive_entry *entry) { return (entry->ae_stat.aest_uid); } const char * archive_entry_uname(struct archive_entry *entry) { const char *p; if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } const char * archive_entry_uname_utf8(struct archive_entry *entry) { const char *p; if (archive_mstring_get_utf8(entry->archive, &entry->ae_uname, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } const wchar_t * archive_entry_uname_w(struct archive_entry *entry) { const wchar_t *p; if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); } int _archive_entry_uname_l(struct archive_entry *entry, const char **p, size_t *len, struct archive_string_conv *sc) { return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc)); } int archive_entry_is_data_encrypted(struct archive_entry *entry) { return ((entry->encryption & AE_ENCRYPTION_DATA) == AE_ENCRYPTION_DATA); } int archive_entry_is_metadata_encrypted(struct archive_entry *entry) { return ((entry->encryption & AE_ENCRYPTION_METADATA) == AE_ENCRYPTION_METADATA); } int archive_entry_is_encrypted(struct archive_entry *entry) { return (entry->encryption & (AE_ENCRYPTION_DATA|AE_ENCRYPTION_METADATA)); } /* * Functions to set archive_entry properties. */ void archive_entry_set_filetype(struct archive_entry *entry, unsigned int type) { entry->stat_valid = 0; entry->acl.mode &= ~AE_IFMT; entry->acl.mode |= AE_IFMT & type; } void archive_entry_set_fflags(struct archive_entry *entry, unsigned long set, unsigned long clear) { archive_mstring_clean(&entry->ae_fflags_text); entry->ae_fflags_set = set; entry->ae_fflags_clear = clear; } const char * archive_entry_copy_fflags_text(struct archive_entry *entry, const char *flags) { archive_mstring_copy_mbs(&entry->ae_fflags_text, flags); return (ae_strtofflags(flags, &entry->ae_fflags_set, &entry->ae_fflags_clear)); } const wchar_t * archive_entry_copy_fflags_text_w(struct archive_entry *entry, const wchar_t *flags) { archive_mstring_copy_wcs(&entry->ae_fflags_text, flags); return (ae_wcstofflags(flags, &entry->ae_fflags_set, &entry->ae_fflags_clear)); } void archive_entry_set_gid(struct archive_entry *entry, la_int64_t g) { entry->stat_valid = 0; entry->ae_stat.aest_gid = g; } void archive_entry_set_gname(struct archive_entry *entry, const char *name) { archive_mstring_copy_mbs(&entry->ae_gname, name); } void archive_entry_set_gname_utf8(struct archive_entry *entry, const char *name) { archive_mstring_copy_utf8(&entry->ae_gname, name); } void archive_entry_copy_gname(struct archive_entry *entry, const char *name) { archive_mstring_copy_mbs(&entry->ae_gname, name); } void archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name) { archive_mstring_copy_wcs(&entry->ae_gname, name); } int archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name) { if (archive_mstring_update_utf8(entry->archive, &entry->ae_gname, name) == 0) return (1); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (0); } int _archive_entry_copy_gname_l(struct archive_entry *entry, const char *name, size_t len, struct archive_string_conv *sc) { return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc)); } void archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino) { entry->stat_valid = 0; entry->ae_set |= AE_SET_INO; entry->ae_stat.aest_ino = ino; } void archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino) { entry->stat_valid = 0; entry->ae_set |= AE_SET_INO; entry->ae_stat.aest_ino = ino; } void archive_entry_set_hardlink(struct archive_entry *entry, const char *target) { archive_mstring_copy_mbs(&entry->ae_hardlink, target); if (target != NULL) entry->ae_set |= AE_SET_HARDLINK; else entry->ae_set &= ~AE_SET_HARDLINK; } void archive_entry_set_hardlink_utf8(struct archive_entry *entry, const char *target) { archive_mstring_copy_utf8(&entry->ae_hardlink, target); if (target != NULL) entry->ae_set |= AE_SET_HARDLINK; else entry->ae_set &= ~AE_SET_HARDLINK; } void archive_entry_copy_hardlink(struct archive_entry *entry, const char *target) { archive_mstring_copy_mbs(&entry->ae_hardlink, target); if (target != NULL) entry->ae_set |= AE_SET_HARDLINK; else entry->ae_set &= ~AE_SET_HARDLINK; } void archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target) { archive_mstring_copy_wcs(&entry->ae_hardlink, target); if (target != NULL) entry->ae_set |= AE_SET_HARDLINK; else entry->ae_set &= ~AE_SET_HARDLINK; } int archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target) { if (target != NULL) entry->ae_set |= AE_SET_HARDLINK; else entry->ae_set &= ~AE_SET_HARDLINK; if (archive_mstring_update_utf8(entry->archive, &entry->ae_hardlink, target) == 0) return (1); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (0); } int _archive_entry_copy_hardlink_l(struct archive_entry *entry, const char *target, size_t len, struct archive_string_conv *sc) { int r; r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink, target, len, sc); if (target != NULL && r == 0) entry->ae_set |= AE_SET_HARDLINK; else entry->ae_set &= ~AE_SET_HARDLINK; return (r); } void archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns) { FIX_NS(t, ns); entry->stat_valid = 0; entry->ae_set |= AE_SET_ATIME; entry->ae_stat.aest_atime = t; entry->ae_stat.aest_atime_nsec = ns; } void archive_entry_unset_atime(struct archive_entry *entry) { archive_entry_set_atime(entry, 0, 0); entry->ae_set &= ~AE_SET_ATIME; } void archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns) { FIX_NS(t, ns); entry->stat_valid = 0; entry->ae_set |= AE_SET_BIRTHTIME; entry->ae_stat.aest_birthtime = t; entry->ae_stat.aest_birthtime_nsec = ns; } void archive_entry_unset_birthtime(struct archive_entry *entry) { archive_entry_set_birthtime(entry, 0, 0); entry->ae_set &= ~AE_SET_BIRTHTIME; } void archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns) { FIX_NS(t, ns); entry->stat_valid = 0; entry->ae_set |= AE_SET_CTIME; entry->ae_stat.aest_ctime = t; entry->ae_stat.aest_ctime_nsec = ns; } void archive_entry_unset_ctime(struct archive_entry *entry) { archive_entry_set_ctime(entry, 0, 0); entry->ae_set &= ~AE_SET_CTIME; } void archive_entry_set_dev(struct archive_entry *entry, dev_t d) { entry->stat_valid = 0; entry->ae_set |= AE_SET_DEV; entry->ae_stat.aest_dev_is_broken_down = 0; entry->ae_stat.aest_dev = d; } void archive_entry_set_devmajor(struct archive_entry *entry, dev_t m) { entry->stat_valid = 0; entry->ae_set |= AE_SET_DEV; entry->ae_stat.aest_dev_is_broken_down = 1; entry->ae_stat.aest_devmajor = m; } void archive_entry_set_devminor(struct archive_entry *entry, dev_t m) { entry->stat_valid = 0; entry->ae_set |= AE_SET_DEV; entry->ae_stat.aest_dev_is_broken_down = 1; entry->ae_stat.aest_devminor = m; } /* Set symlink if symlink is already set, else set hardlink. */ void archive_entry_set_link(struct archive_entry *entry, const char *target) { if (entry->ae_set & AE_SET_SYMLINK) archive_mstring_copy_mbs(&entry->ae_symlink, target); else archive_mstring_copy_mbs(&entry->ae_hardlink, target); } void archive_entry_set_link_utf8(struct archive_entry *entry, const char *target) { if (entry->ae_set & AE_SET_SYMLINK) archive_mstring_copy_utf8(&entry->ae_symlink, target); else archive_mstring_copy_utf8(&entry->ae_hardlink, target); } /* Set symlink if symlink is already set, else set hardlink. */ void archive_entry_copy_link(struct archive_entry *entry, const char *target) { if (entry->ae_set & AE_SET_SYMLINK) archive_mstring_copy_mbs(&entry->ae_symlink, target); else archive_mstring_copy_mbs(&entry->ae_hardlink, target); } /* Set symlink if symlink is already set, else set hardlink. */ void archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target) { if (entry->ae_set & AE_SET_SYMLINK) archive_mstring_copy_wcs(&entry->ae_symlink, target); else archive_mstring_copy_wcs(&entry->ae_hardlink, target); } int archive_entry_update_link_utf8(struct archive_entry *entry, const char *target) { int r; if (entry->ae_set & AE_SET_SYMLINK) r = archive_mstring_update_utf8(entry->archive, &entry->ae_symlink, target); else r = archive_mstring_update_utf8(entry->archive, &entry->ae_hardlink, target); if (r == 0) return (1); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (0); } int _archive_entry_copy_link_l(struct archive_entry *entry, const char *target, size_t len, struct archive_string_conv *sc) { int r; if (entry->ae_set & AE_SET_SYMLINK) r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink, target, len, sc); else r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink, target, len, sc); return (r); } void archive_entry_set_mode(struct archive_entry *entry, mode_t m) { entry->stat_valid = 0; entry->acl.mode = m; } void archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns) { FIX_NS(t, ns); entry->stat_valid = 0; entry->ae_set |= AE_SET_MTIME; entry->ae_stat.aest_mtime = t; entry->ae_stat.aest_mtime_nsec = ns; } void archive_entry_unset_mtime(struct archive_entry *entry) { archive_entry_set_mtime(entry, 0, 0); entry->ae_set &= ~AE_SET_MTIME; } void archive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink) { entry->stat_valid = 0; entry->ae_stat.aest_nlink = nlink; } void archive_entry_set_pathname(struct archive_entry *entry, const char *name) { archive_mstring_copy_mbs(&entry->ae_pathname, name); } void archive_entry_set_pathname_utf8(struct archive_entry *entry, const char *name) { archive_mstring_copy_utf8(&entry->ae_pathname, name); } void archive_entry_copy_pathname(struct archive_entry *entry, const char *name) { archive_mstring_copy_mbs(&entry->ae_pathname, name); } void archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name) { archive_mstring_copy_wcs(&entry->ae_pathname, name); } int archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name) { if (archive_mstring_update_utf8(entry->archive, &entry->ae_pathname, name) == 0) return (1); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (0); } int _archive_entry_copy_pathname_l(struct archive_entry *entry, const char *name, size_t len, struct archive_string_conv *sc) { return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname, name, len, sc)); } void archive_entry_set_perm(struct archive_entry *entry, mode_t p) { entry->stat_valid = 0; entry->acl.mode &= AE_IFMT; entry->acl.mode |= ~AE_IFMT & p; } void archive_entry_set_rdev(struct archive_entry *entry, dev_t m) { entry->stat_valid = 0; entry->ae_stat.aest_rdev = m; entry->ae_stat.aest_rdev_is_broken_down = 0; } void archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m) { entry->stat_valid = 0; entry->ae_stat.aest_rdev_is_broken_down = 1; entry->ae_stat.aest_rdevmajor = m; } void archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m) { entry->stat_valid = 0; entry->ae_stat.aest_rdev_is_broken_down = 1; entry->ae_stat.aest_rdevminor = m; } void archive_entry_set_size(struct archive_entry *entry, la_int64_t s) { entry->stat_valid = 0; entry->ae_stat.aest_size = s; entry->ae_set |= AE_SET_SIZE; } void archive_entry_unset_size(struct archive_entry *entry) { archive_entry_set_size(entry, 0); entry->ae_set &= ~AE_SET_SIZE; } void archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path) { archive_mstring_copy_mbs(&entry->ae_sourcepath, path); } void archive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path) { archive_mstring_copy_wcs(&entry->ae_sourcepath, path); } void archive_entry_set_symlink(struct archive_entry *entry, const char *linkname) { archive_mstring_copy_mbs(&entry->ae_symlink, linkname); if (linkname != NULL) entry->ae_set |= AE_SET_SYMLINK; else entry->ae_set &= ~AE_SET_SYMLINK; } void archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname) { archive_mstring_copy_utf8(&entry->ae_symlink, linkname); if (linkname != NULL) entry->ae_set |= AE_SET_SYMLINK; else entry->ae_set &= ~AE_SET_SYMLINK; } void archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname) { archive_mstring_copy_mbs(&entry->ae_symlink, linkname); if (linkname != NULL) entry->ae_set |= AE_SET_SYMLINK; else entry->ae_set &= ~AE_SET_SYMLINK; } void archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname) { archive_mstring_copy_wcs(&entry->ae_symlink, linkname); if (linkname != NULL) entry->ae_set |= AE_SET_SYMLINK; else entry->ae_set &= ~AE_SET_SYMLINK; } int archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname) { if (linkname != NULL) entry->ae_set |= AE_SET_SYMLINK; else entry->ae_set &= ~AE_SET_SYMLINK; if (archive_mstring_update_utf8(entry->archive, &entry->ae_symlink, linkname) == 0) return (1); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (0); } int _archive_entry_copy_symlink_l(struct archive_entry *entry, const char *linkname, size_t len, struct archive_string_conv *sc) { int r; r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink, linkname, len, sc); if (linkname != NULL && r == 0) entry->ae_set |= AE_SET_SYMLINK; else entry->ae_set &= ~AE_SET_SYMLINK; return (r); } void archive_entry_set_uid(struct archive_entry *entry, la_int64_t u) { entry->stat_valid = 0; entry->ae_stat.aest_uid = u; } void archive_entry_set_uname(struct archive_entry *entry, const char *name) { archive_mstring_copy_mbs(&entry->ae_uname, name); } void archive_entry_set_uname_utf8(struct archive_entry *entry, const char *name) { archive_mstring_copy_utf8(&entry->ae_uname, name); } void archive_entry_copy_uname(struct archive_entry *entry, const char *name) { archive_mstring_copy_mbs(&entry->ae_uname, name); } void archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name) { archive_mstring_copy_wcs(&entry->ae_uname, name); } int archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name) { if (archive_mstring_update_utf8(entry->archive, &entry->ae_uname, name) == 0) return (1); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (0); } void archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted) { if (is_encrypted) { entry->encryption |= AE_ENCRYPTION_DATA; } else { entry->encryption &= ~AE_ENCRYPTION_DATA; } } void archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted) { if (is_encrypted) { entry->encryption |= AE_ENCRYPTION_METADATA; } else { entry->encryption &= ~AE_ENCRYPTION_METADATA; } } int _archive_entry_copy_uname_l(struct archive_entry *entry, const char *name, size_t len, struct archive_string_conv *sc) { return (archive_mstring_copy_mbs_len_l(&entry->ae_uname, name, len, sc)); } const void * archive_entry_mac_metadata(struct archive_entry *entry, size_t *s) { *s = entry->mac_metadata_size; return entry->mac_metadata; } void archive_entry_copy_mac_metadata(struct archive_entry *entry, const void *p, size_t s) { free(entry->mac_metadata); if (p == NULL || s == 0) { entry->mac_metadata = NULL; entry->mac_metadata_size = 0; } else { entry->mac_metadata_size = s; entry->mac_metadata = malloc(s); if (entry->mac_metadata == NULL) abort(); memcpy(entry->mac_metadata, p, s); } } /* * ACL management. The following would, of course, be a lot simpler * if: 1) the last draft of POSIX.1e were a really thorough and * complete standard that addressed the needs of ACL archiving and 2) * everyone followed it faithfully. Alas, neither is true, so the * following is a lot more complex than might seem necessary to the * uninitiated. */ struct archive_acl * archive_entry_acl(struct archive_entry *entry) { return &entry->acl; } void archive_entry_acl_clear(struct archive_entry *entry) { archive_acl_clear(&entry->acl); } /* * Add a single ACL entry to the internal list of ACL data. */ int archive_entry_acl_add_entry(struct archive_entry *entry, int type, int permset, int tag, int id, const char *name) { return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name); } /* * As above, but with a wide-character name. */ int archive_entry_acl_add_entry_w(struct archive_entry *entry, int type, int permset, int tag, int id, const wchar_t *name) { return archive_acl_add_entry_w_len(&entry->acl, type, permset, tag, id, name, wcslen(name)); } /* * Return a bitmask of ACL types in an archive entry ACL list */ int archive_entry_acl_types(struct archive_entry *entry) { return (archive_acl_types(&entry->acl)); } /* * Return a count of entries matching "want_type". */ int archive_entry_acl_count(struct archive_entry *entry, int want_type) { return archive_acl_count(&entry->acl, want_type); } /* * Prepare for reading entries from the ACL data. Returns a count * of entries matching "want_type", or zero if there are no * non-extended ACL entries of that type. */ int archive_entry_acl_reset(struct archive_entry *entry, int want_type) { return archive_acl_reset(&entry->acl, want_type); } /* * Return the next ACL entry in the list. Fake entries for the * standard permissions and include them in the returned list. */ int archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type, int *permset, int *tag, int *id, const char **name) { int r; r = archive_acl_next(entry->archive, &entry->acl, want_type, type, permset, tag, id, name); if (r == ARCHIVE_FATAL && errno == ENOMEM) __archive_errx(1, "No memory"); return (r); } /* * Generate a text version of the ACL. The flags parameter controls * the style of the generated ACL. */ wchar_t * archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len, int flags) { return (archive_acl_to_text_w(&entry->acl, len, flags, entry->archive)); } char * archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len, int flags) { return (archive_acl_to_text_l(&entry->acl, len, flags, NULL)); } char * _archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len, int flags, struct archive_string_conv *sc) { return (archive_acl_to_text_l(&entry->acl, len, flags, sc)); } /* * ACL text parser. */ int archive_entry_acl_from_text_w(struct archive_entry *entry, const wchar_t *wtext, int type) { return (archive_acl_from_text_w(&entry->acl, wtext, type)); } int archive_entry_acl_from_text(struct archive_entry *entry, const char *text, int type) { return (archive_acl_from_text_l(&entry->acl, text, type, NULL)); } int _archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text, int type, struct archive_string_conv *sc) { return (archive_acl_from_text_l(&entry->acl, text, type, sc)); } /* Deprecated */ static int archive_entry_acl_text_compat(int *flags) { if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0) return (1); /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */ if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) *flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID; /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */ if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) *flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; *flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA; return (0); } /* Deprecated */ const wchar_t * archive_entry_acl_text_w(struct archive_entry *entry, int flags) { if (entry->acl.acl_text_w != NULL) { free(entry->acl.acl_text_w); entry->acl.acl_text_w = NULL; } if (archive_entry_acl_text_compat(&flags) == 0) entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl, NULL, flags, entry->archive); return (entry->acl.acl_text_w); } /* Deprecated */ const char * archive_entry_acl_text(struct archive_entry *entry, int flags) { if (entry->acl.acl_text != NULL) { free(entry->acl.acl_text); entry->acl.acl_text = NULL; } if (archive_entry_acl_text_compat(&flags) == 0) entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL, flags, NULL); return (entry->acl.acl_text); } /* Deprecated */ int _archive_entry_acl_text_l(struct archive_entry *entry, int flags, const char **acl_text, size_t *len, struct archive_string_conv *sc) { if (entry->acl.acl_text != NULL) { free(entry->acl.acl_text); entry->acl.acl_text = NULL; } if (archive_entry_acl_text_compat(&flags) == 0) entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, (ssize_t *)len, flags, sc); *acl_text = entry->acl.acl_text; return (0); } /* * Following code is modified from UC Berkeley sources, and * is subject to the following copyright notice. */ /*- * Copyright (c) 1993 * The Regents of the University of California. 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ static struct flag { const char *name; const wchar_t *wname; unsigned long set; unsigned long clear; } flags[] = { /* Preferred (shorter) names per flag first, all prefixed by "no" */ #ifdef SF_APPEND { "nosappnd", L"nosappnd", SF_APPEND, 0 }, { "nosappend", L"nosappend", SF_APPEND, 0 }, #endif #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 #ifdef SF_ARCHIVED { "noarch", L"noarch", SF_ARCHIVED, 0 }, { "noarchived", L"noarchived", SF_ARCHIVED, 0 }, #endif #ifdef SF_IMMUTABLE { "noschg", L"noschg", SF_IMMUTABLE, 0 }, { "noschange", L"noschange", SF_IMMUTABLE, 0 }, { "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0 }, #endif #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 }, #endif #ifdef SF_NOUNLINK { "nosunlnk", L"nosunlnk", SF_NOUNLINK, 0 }, { "nosunlink", L"nosunlink", SF_NOUNLINK, 0 }, #endif #ifdef SF_SNAPSHOT { "nosnapshot", L"nosnapshot", SF_SNAPSHOT, 0 }, #endif #ifdef UF_APPEND { "nouappnd", L"nouappnd", UF_APPEND, 0 }, { "nouappend", L"nouappend", UF_APPEND, 0 }, #endif #ifdef UF_IMMUTABLE { "nouchg", L"nouchg", UF_IMMUTABLE, 0 }, { "nouchange", L"nouchange", UF_IMMUTABLE, 0 }, { "nouimmutable", L"nouimmutable", UF_IMMUTABLE, 0 }, #endif #ifdef UF_NODUMP { "nodump", L"nodump", 0, UF_NODUMP}, #endif #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 { "noopaque", L"noopaque", UF_OPAQUE, 0 }, #endif #ifdef UF_NOUNLINK { "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0 }, { "nouunlink", L"nouunlink", UF_NOUNLINK, 0 }, #endif #ifdef UF_COMPRESSED { "nocompressed",L"nocompressed", UF_COMPRESSED, 0 }, #endif +#ifdef UF_HIDDEN + { "nohidden", L"nohidden", UF_HIDDEN, 0 }, +#endif #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 #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 #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 #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 #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 #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 #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 #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 #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 #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 #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 #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 #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 #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 #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 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 } }; /* * fflagstostr -- * Convert file flags to a comma-separated string. If no flags * are set, return the empty string. */ static char * ae_fflagstostr(unsigned long bitset, unsigned long bitclear) { char *string, *dp; const char *sp; unsigned long bits; struct flag *flag; size_t length; bits = bitset | bitclear; length = 0; for (flag = flags; flag->name != NULL; flag++) if (bits & (flag->set | flag->clear)) { length += strlen(flag->name) + 1; bits &= ~(flag->set | flag->clear); } if (length == 0) return (NULL); string = (char *)malloc(length); if (string == NULL) return (NULL); dp = string; for (flag = flags; flag->name != NULL; flag++) { if (bitset & flag->set || bitclear & flag->clear) { sp = flag->name + 2; } else if (bitset & flag->clear || bitclear & flag->set) { sp = flag->name; } else continue; bitset &= ~(flag->set | flag->clear); bitclear &= ~(flag->set | flag->clear); if (dp > string) *dp++ = ','; while ((*dp++ = *sp++) != '\0') ; dp--; } *dp = '\0'; return (string); } /* * strtofflags -- * Take string of arguments and return file flags. This * version works a little differently than strtofflags(3). * In particular, it always tests every token, skipping any * unrecognized tokens. It returns a pointer to the first * unrecognized token, or NULL if every token was recognized. * This version is also const-correct and does not modify the * provided string. */ static const char * ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp) { const char *start, *end; struct flag *flag; unsigned long set, clear; const char *failed; set = clear = 0; start = s; failed = NULL; /* Find start of first token. */ while (*start == '\t' || *start == ' ' || *start == ',') start++; while (*start != '\0') { size_t length; /* Locate end of token. */ end = start; while (*end != '\0' && *end != '\t' && *end != ' ' && *end != ',') end++; length = end - start; for (flag = flags; flag->name != NULL; flag++) { size_t flag_length = strlen(flag->name); if (length == flag_length && memcmp(start, flag->name, length) == 0) { /* Matched "noXXXX", so reverse the sense. */ clear |= flag->set; set |= flag->clear; break; } else if (length == flag_length - 2 && memcmp(start, flag->name + 2, length) == 0) { /* Matched "XXXX", so don't reverse. */ set |= flag->set; clear |= flag->clear; break; } } /* Ignore unknown flag names. */ if (flag->name == NULL && failed == NULL) failed = start; /* Find start of next token. */ start = end; while (*start == '\t' || *start == ' ' || *start == ',') start++; } if (setp) *setp = set; if (clrp) *clrp = clear; /* Return location of first failure. */ return (failed); } /* * wcstofflags -- * Take string of arguments and return file flags. This * version works a little differently than strtofflags(3). * In particular, it always tests every token, skipping any * unrecognized tokens. It returns a pointer to the first * unrecognized token, or NULL if every token was recognized. * This version is also const-correct and does not modify the * provided string. */ static const wchar_t * ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp) { const wchar_t *start, *end; struct flag *flag; unsigned long set, clear; const wchar_t *failed; set = clear = 0; start = s; failed = NULL; /* Find start of first token. */ while (*start == L'\t' || *start == L' ' || *start == L',') start++; while (*start != L'\0') { size_t length; /* Locate end of token. */ end = start; while (*end != L'\0' && *end != L'\t' && *end != L' ' && *end != L',') end++; length = end - start; for (flag = flags; flag->wname != NULL; flag++) { size_t flag_length = wcslen(flag->wname); if (length == flag_length && wmemcmp(start, flag->wname, length) == 0) { /* Matched "noXXXX", so reverse the sense. */ clear |= flag->set; set |= flag->clear; break; } else if (length == flag_length - 2 && wmemcmp(start, flag->wname + 2, length) == 0) { /* Matched "XXXX", so don't reverse. */ set |= flag->set; clear |= flag->clear; break; } } /* Ignore unknown flag names. */ if (flag->wname == NULL && failed == NULL) failed = start; /* Find start of next token. */ start = end; while (*start == L'\t' || *start == L' ' || *start == L',') start++; } if (setp) *setp = set; if (clrp) *clrp = clear; /* Return location of first failure. */ return (failed); } #ifdef TEST #include int main(int argc, char **argv) { struct archive_entry *entry = archive_entry_new(); unsigned long set, clear; const wchar_t *remainder; remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,"); archive_entry_fflags(entry, &set, &clear); wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder); wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry)); return (0); } #endif Index: vendor/libarchive/dist/libarchive/archive_platform_xattr.h =================================================================== --- vendor/libarchive/dist/libarchive/archive_platform_xattr.h (nonexistent) +++ vendor/libarchive/dist/libarchive/archive_platform_xattr.h (revision 315875) @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2017 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$ + */ + +/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */ + +#ifndef ARCHIVE_PLATFORM_XATTR_H_INCLUDED +#define ARCHIVE_PLATFORM_XATTR_H_INCLUDED + +/* + * Determine if we support extended attributes + */ +#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_FREEBSD || \ + ARCHIVE_XATTR_AIX +#define ARCHIVE_XATTR_SUPPORT 1 +#endif + +#endif /* ARCHIVE_PLATFORM_XATTR_H_INCLUDED */ Property changes on: vendor/libarchive/dist/libarchive/archive_platform_xattr.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/libarchive/dist/libarchive/archive_read_disk_entry_from_file.c =================================================================== --- vendor/libarchive/dist/libarchive/archive_read_disk_entry_from_file.c (revision 315874) +++ vendor/libarchive/dist/libarchive/archive_read_disk_entry_from_file.c (revision 315875) @@ -1,989 +1,1028 @@ /*- * Copyright (c) 2003-2009 Tim Kientzle * Copyright (c) 2010-2012 Michihiro NAKAJIMA * 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. */ #include "archive_platform.h" __FBSDID("$FreeBSD"); /* This is the tree-walking code for POSIX systems. */ #if !defined(_WIN32) || defined(__CYGWIN__) #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_EXTATTR_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #if defined(HAVE_SYS_XATTR_H) #include #elif defined(HAVE_ATTR_XATTR_H) #include #endif #ifdef HAVE_SYS_EA_H #include #endif #ifdef HAVE_COPYFILE_H #include #endif #ifdef HAVE_ERRNO_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #ifdef HAVE_LIMITS_H #include #endif #ifdef HAVE_LINUX_TYPES_H #include #endif #ifdef HAVE_LINUX_FIEMAP_H #include #endif #ifdef HAVE_LINUX_FS_H #include #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 /* for Linux file flags */ #endif #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) #include /* Linux file flags, broken on Cygwin */ #endif #ifdef HAVE_PATHS_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include "archive.h" #include "archive_entry.h" #include "archive_private.h" #include "archive_read_disk_private.h" #ifndef O_CLOEXEC #define O_CLOEXEC 0 #endif static int setup_mac_metadata(struct archive_read_disk *, struct archive_entry *, int *fd); static int setup_xattrs(struct archive_read_disk *, struct archive_entry *, int *fd); static int setup_sparse(struct archive_read_disk *, struct archive_entry *, int *fd); #if defined(HAVE_LINUX_FIEMAP_H) static int setup_sparse_fiemap(struct archive_read_disk *, struct archive_entry *, int *fd); #endif #if !ARCHIVE_ACL_SUPPORT int archive_read_disk_entry_setup_acls(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { (void)a; /* UNUSED */ (void)entry; /* UNUSED */ (void)fd; /* UNUSED */ return (ARCHIVE_OK); } #endif /* * Enter working directory and return working pathname of archive_entry. * If a pointer to an integer is provided and its value is below zero * open a file descriptor on this pahtname. */ const char * archive_read_disk_entry_setup_path(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { const char *path; path = archive_entry_sourcepath(entry); if (path == NULL || (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0)) path = archive_entry_pathname(entry); if (path == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Couldn't determine path"); } else if (fd != NULL && *fd < 0 && a->tree != NULL && (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK)) { *fd = a->open_on_current_dir(a->tree, path, O_RDONLY | O_NONBLOCK); } return (path); } int archive_read_disk_entry_from_file(struct archive *_a, struct archive_entry *entry, int fd, const struct stat *st) { struct archive_read_disk *a = (struct archive_read_disk *)_a; const char *path, *name; struct stat s; int initial_fd = fd; int r, r1; archive_clear_error(_a); path = archive_entry_sourcepath(entry); if (path == NULL) path = archive_entry_pathname(entry); if (a->tree == NULL) { if (st == NULL) { #if HAVE_FSTAT if (fd >= 0) { if (fstat(fd, &s) != 0) { archive_set_error(&a->archive, errno, "Can't fstat"); return (ARCHIVE_FAILED); } } else #endif #if HAVE_LSTAT if (!a->follow_symlinks) { if (lstat(path, &s) != 0) { archive_set_error(&a->archive, errno, "Can't lstat %s", path); return (ARCHIVE_FAILED); } } else #endif if (stat(path, &s) != 0) { archive_set_error(&a->archive, errno, "Can't stat %s", path); return (ARCHIVE_FAILED); } st = &s; } archive_entry_copy_stat(entry, st); } /* Lookup uname/gname */ name = archive_read_disk_uname(_a, archive_entry_uid(entry)); if (name != NULL) archive_entry_copy_uname(entry, name); name = archive_read_disk_gname(_a, archive_entry_gid(entry)); if (name != NULL) archive_entry_copy_gname(entry, name); #ifdef HAVE_STRUCT_STAT_ST_FLAGS /* On FreeBSD, we get flags for free with the stat. */ /* TODO: Does this belong in copy_stat()? */ if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0) archive_entry_set_fflags(entry, st->st_flags, 0); #endif #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 ((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, O_RDONLY | O_NONBLOCK | O_CLOEXEC); else fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); __archive_ensure_cloexec_flag(fd); } if (fd >= 0) { int 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); } } #endif #if defined(HAVE_READLINK) || defined(HAVE_READLINKAT) if (S_ISLNK(st->st_mode)) { size_t linkbuffer_len = st->st_size + 1; char *linkbuffer; int lnklen; linkbuffer = malloc(linkbuffer_len); if (linkbuffer == NULL) { archive_set_error(&a->archive, ENOMEM, "Couldn't read link data"); return (ARCHIVE_FAILED); } if (a->tree != NULL) { #ifdef HAVE_READLINKAT lnklen = readlinkat(a->tree_current_dir_fd(a->tree), path, linkbuffer, linkbuffer_len); #else if (a->tree_enter_working_dir(a->tree) != 0) { archive_set_error(&a->archive, errno, "Couldn't read link data"); free(linkbuffer); return (ARCHIVE_FAILED); } lnklen = readlink(path, linkbuffer, linkbuffer_len); #endif /* HAVE_READLINKAT */ } else lnklen = readlink(path, linkbuffer, linkbuffer_len); if (lnklen < 0) { archive_set_error(&a->archive, errno, "Couldn't read link data"); free(linkbuffer); return (ARCHIVE_FAILED); } linkbuffer[lnklen] = 0; archive_entry_set_symlink(entry, linkbuffer); free(linkbuffer); } #endif /* HAVE_READLINK || HAVE_READLINKAT */ r = 0; if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0) r = archive_read_disk_entry_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->flags & ARCHIVE_READDISK_MAC_COPYFILE) { r1 = setup_mac_metadata(a, entry, &fd); if (r1 < r) r = r1; } r1 = setup_sparse(a, entry, &fd); if (r1 < r) r = r1; /* If we opened the file earlier in this function, close it. */ if (initial_fd != fd) close(fd); return (r); } #if defined(__APPLE__) && defined(HAVE_COPYFILE_H) /* * The Mac OS "copyfile()" API copies the extended metadata for a * file into a separate file in AppleDouble format (see RFC 1740). * * Mac OS tar and cpio implementations store this extended * metadata as a separate entry just before the regular entry * with a "._" prefix added to the filename. * * Note that this is currently done unconditionally; the tar program has * an option to discard this information before the archive is written. * * TODO: If there's a failure, report it and return ARCHIVE_WARN. */ static int setup_mac_metadata(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { int tempfd = -1; int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR; struct stat copyfile_stat; int ret = ARCHIVE_OK; void *buff = NULL; int have_attrs; const char *name, *tempdir; struct archive_string tempfile; (void)fd; /* UNUSED */ name = archive_read_disk_entry_setup_path(a, entry, NULL); if (name == NULL) return (ARCHIVE_WARN); /* Short-circuit if there's nothing to do. */ have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK); if (have_attrs == -1) { archive_set_error(&a->archive, errno, "Could not check extended attributes"); return (ARCHIVE_WARN); } if (have_attrs == 0) return (ARCHIVE_OK); tempdir = NULL; if (issetugid() == 0) tempdir = getenv("TMPDIR"); if (tempdir == NULL) tempdir = _PATH_TMP; archive_string_init(&tempfile); archive_strcpy(&tempfile, tempdir); archive_strcat(&tempfile, "tar.md.XXXXXX"); tempfd = mkstemp(tempfile.s); if (tempfd < 0) { archive_set_error(&a->archive, errno, "Could not open extended attribute file"); ret = ARCHIVE_WARN; goto cleanup; } __archive_ensure_cloexec_flag(tempfd); /* XXX I wish copyfile() could pack directly to a memory * buffer; that would avoid the temp file here. For that * matter, it would be nice if fcopyfile() actually worked, * that would reduce the many open/close races here. */ if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) { archive_set_error(&a->archive, errno, "Could not pack extended attributes"); ret = ARCHIVE_WARN; goto cleanup; } if (fstat(tempfd, ©file_stat)) { archive_set_error(&a->archive, errno, "Could not check size of extended attributes"); ret = ARCHIVE_WARN; goto cleanup; } buff = malloc(copyfile_stat.st_size); if (buff == NULL) { archive_set_error(&a->archive, errno, "Could not allocate memory for extended attributes"); ret = ARCHIVE_WARN; goto cleanup; } if (copyfile_stat.st_size != read(tempfd, buff, copyfile_stat.st_size)) { archive_set_error(&a->archive, errno, "Could not read extended attributes into memory"); ret = ARCHIVE_WARN; goto cleanup; } archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size); cleanup: if (tempfd >= 0) { close(tempfd); unlink(tempfile.s); } archive_string_free(&tempfile); free(buff); return (ret); } #else /* * Stub implementation for non-Mac systems. */ static int setup_mac_metadata(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { (void)a; /* UNUSED */ (void)entry; /* UNUSED */ (void)fd; /* UNUSED */ return (ARCHIVE_OK); } #endif -#if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \ - HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \ - (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA) +#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX /* - * Linux and AIX extended attribute support. + * Linux, Darwin and AIX extended attribute support. * * TODO: By using a stack-allocated buffer for the first * call to getxattr(), we might be able to avoid the second * call entirely. We only need the second call if the * stack-allocated buffer is too small. But a modest buffer * of 1024 bytes or so will often be big enough. Same applies * to listxattr(). */ static int setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, const char *name, int fd, const char *accpath) { ssize_t size; void *value = NULL; -#if HAVE_FGETXATTR - if (fd >= 0) + + if (fd >= 0) { +#if ARCHIVE_XATTR_LINUX size = fgetxattr(fd, name, NULL, 0); - else if (!a->follow_symlinks) - size = lgetxattr(accpath, name, NULL, 0); - else - size = getxattr(accpath, name, NULL, 0); -#elif HAVE_FGETEA - if (fd >= 0) +#elif ARCHIVE_XATTR_DARWIN + size = fgetxattr(fd, name, NULL, 0, 0, 0); +#elif ARCHIVE_XATTR_AIX size = fgetea(fd, name, NULL, 0); - else if (!a->follow_symlinks) +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + size = lgetxattr(accpath, name, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, NULL, 0, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX size = lgetea(accpath, name, NULL, 0); - else +#endif + } else { +#if ARCHIVE_XATTR_LINUX + size = getxattr(accpath, name, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, NULL, 0, 0, 0); +#elif ARCHIVE_XATTR_AIX size = getea(accpath, name, NULL, 0); #endif + } if (size == -1) { archive_set_error(&a->archive, errno, "Couldn't query extended attribute"); return (ARCHIVE_WARN); } if (size > 0 && (value = malloc(size)) == NULL) { archive_set_error(&a->archive, errno, "Out of memory"); return (ARCHIVE_FATAL); } -#if HAVE_FGETXATTR - if (fd >= 0) + + if (fd >= 0) { +#if ARCHIVE_XATTR_LINUX size = fgetxattr(fd, name, value, size); - else if (!a->follow_symlinks) - size = lgetxattr(accpath, name, value, size); - else - size = getxattr(accpath, name, value, size); -#elif HAVE_FGETEA - if (fd >= 0) +#elif ARCHIVE_XATTR_DARWIN + size = fgetxattr(fd, name, value, size, 0, 0); +#elif ARCHIVE_XATTR_AIX size = fgetea(fd, name, value, size); - else if (!a->follow_symlinks) +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + size = lgetxattr(accpath, name, value, size); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, value, size, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX size = lgetea(accpath, name, value, size); - else +#endif + } else { +#if ARCHIVE_XATTR_LINUX + size = getxattr(accpath, name, value, size); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, value, size, 0, 0); +#elif ARCHIVE_XATTR_AIX size = getea(accpath, name, value, size); #endif + } if (size == -1) { archive_set_error(&a->archive, errno, "Couldn't read extended attribute"); return (ARCHIVE_WARN); } archive_entry_xattr_add_entry(entry, name, value, size); free(value); return (ARCHIVE_OK); } static int setup_xattrs(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { char *list, *p; const char *path; ssize_t list_size; path = NULL; if (*fd < 0) { path = archive_read_disk_entry_setup_path(a, entry, fd); if (path == NULL) return (ARCHIVE_WARN); } -#if HAVE_FLISTXATTR - if (*fd >= 0) + if (*fd >= 0) { +#if ARCHIVE_XATTR_LINUX list_size = flistxattr(*fd, NULL, 0); - else if (!a->follow_symlinks) - list_size = llistxattr(path, NULL, 0); - else - list_size = listxattr(path, NULL, 0); -#elif HAVE_FLISTEA - if (*fd >= 0) +#elif ARCHIVE_XATTR_DARWIN + list_size = flistxattr(*fd, NULL, 0, 0); +#elif ARCHIVE_XATTR_AIX list_size = flistea(*fd, NULL, 0); - else if (!a->follow_symlinks) +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + list_size = llistxattr(path, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, NULL, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX list_size = llistea(path, NULL, 0); - else +#endif + } else { +#if ARCHIVE_XATTR_LINUX + list_size = listxattr(path, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, NULL, 0, 0); +#elif ARCHIVE_XATTR_AIX list_size = listea(path, NULL, 0); #endif + } if (list_size == -1) { if (errno == ENOTSUP || errno == ENOSYS) return (ARCHIVE_OK); archive_set_error(&a->archive, errno, "Couldn't list extended attributes"); return (ARCHIVE_WARN); } if (list_size == 0) return (ARCHIVE_OK); if ((list = malloc(list_size)) == NULL) { archive_set_error(&a->archive, errno, "Out of memory"); return (ARCHIVE_FATAL); } -#if HAVE_FLISTXATTR - if (*fd >= 0) + if (*fd >= 0) { +#if ARCHIVE_XATTR_LINUX list_size = flistxattr(*fd, list, list_size); - else if (!a->follow_symlinks) - list_size = llistxattr(path, list, list_size); - else - list_size = listxattr(path, list, list_size); -#elif HAVE_FLISTEA - if (*fd >= 0) +#elif ARCHIVE_XATTR_DARWIN + list_size = flistxattr(*fd, list, list_size, 0); +#elif ARCHIVE_XATTR_AIX list_size = flistea(*fd, list, list_size); - else if (!a->follow_symlinks) +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + list_size = llistxattr(path, list, list_size); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, list, list_size, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX list_size = llistea(path, list, list_size); - else +#endif + } else { +#if ARCHIVE_XATTR_LINUX + list_size = listxattr(path, list, list_size); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, list, list_size, 0); +#elif ARCHIVE_XATTR_AIX list_size = listea(path, list, list_size); #endif + } if (list_size == -1) { archive_set_error(&a->archive, errno, "Couldn't retrieve extended attributes"); free(list); return (ARCHIVE_WARN); } for (p = list; (p - list) < list_size; p += strlen(p) + 1) { if (strncmp(p, "system.", 7) == 0 || strncmp(p, "xfsroot.", 8) == 0) continue; setup_xattr(a, entry, p, *fd, path); } free(list); return (ARCHIVE_OK); } -#elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE && \ - HAVE_DECL_EXTATTR_NAMESPACE_USER +#elif ARCHIVE_XATTR_FREEBSD /* * FreeBSD extattr interface. */ /* TODO: Implement this. Follow the Linux model above, but * with FreeBSD-specific system calls, of course. Be careful * to not include the system extattrs that hold ACLs; we handle * those separately. */ static int setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, int namespace, const char *name, const char *fullname, int fd, const char *path); static int setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, int namespace, const char *name, const char *fullname, int fd, const char *accpath) { ssize_t size; void *value = NULL; if (fd >= 0) size = extattr_get_fd(fd, namespace, name, NULL, 0); else if (!a->follow_symlinks) size = extattr_get_link(accpath, namespace, name, NULL, 0); else size = extattr_get_file(accpath, namespace, name, NULL, 0); if (size == -1) { archive_set_error(&a->archive, errno, "Couldn't query extended attribute"); return (ARCHIVE_WARN); } if (size > 0 && (value = malloc(size)) == NULL) { archive_set_error(&a->archive, errno, "Out of memory"); return (ARCHIVE_FATAL); } if (fd >= 0) size = extattr_get_fd(fd, namespace, name, value, size); else if (!a->follow_symlinks) size = extattr_get_link(accpath, namespace, name, value, size); else size = extattr_get_file(accpath, namespace, name, value, size); if (size == -1) { free(value); archive_set_error(&a->archive, errno, "Couldn't read extended attribute"); return (ARCHIVE_WARN); } archive_entry_xattr_add_entry(entry, fullname, value, size); free(value); return (ARCHIVE_OK); } static int setup_xattrs(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { char buff[512]; char *list, *p; ssize_t list_size; const char *path; int namespace = EXTATTR_NAMESPACE_USER; path = NULL; if (*fd < 0) { path = archive_read_disk_entry_setup_path(a, entry, fd); if (path == NULL) return (ARCHIVE_WARN); } if (*fd >= 0) list_size = extattr_list_fd(*fd, namespace, NULL, 0); else if (!a->follow_symlinks) list_size = extattr_list_link(path, namespace, NULL, 0); else list_size = extattr_list_file(path, namespace, NULL, 0); if (list_size == -1 && errno == EOPNOTSUPP) return (ARCHIVE_OK); if (list_size == -1) { archive_set_error(&a->archive, errno, "Couldn't list extended attributes"); return (ARCHIVE_WARN); } if (list_size == 0) return (ARCHIVE_OK); if ((list = malloc(list_size)) == NULL) { archive_set_error(&a->archive, errno, "Out of memory"); return (ARCHIVE_FATAL); } if (*fd >= 0) list_size = extattr_list_fd(*fd, namespace, list, list_size); else if (!a->follow_symlinks) list_size = extattr_list_link(path, namespace, list, list_size); else list_size = extattr_list_file(path, namespace, list, list_size); if (list_size == -1) { archive_set_error(&a->archive, errno, "Couldn't retrieve extended attributes"); free(list); return (ARCHIVE_WARN); } p = list; while ((p - list) < list_size) { size_t len = 255 & (int)*p; char *name; strcpy(buff, "user."); name = buff + strlen(buff); memcpy(name, p + 1, len); name[len] = '\0'; setup_xattr(a, entry, namespace, name, buff, *fd, path); p += 1 + len; } free(list); return (ARCHIVE_OK); } #else /* * Generic (stub) extended attribute support. */ static int setup_xattrs(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { (void)a; /* UNUSED */ (void)entry; /* UNUSED */ (void)fd; /* UNUSED */ return (ARCHIVE_OK); } #endif #if defined(HAVE_LINUX_FIEMAP_H) /* * Linux FIEMAP sparse interface. * * The FIEMAP ioctl returns an "extent" for each physical allocation * on disk. We need to process those to generate a more compact list * of logical file blocks. We also need to be very careful to use * FIEMAP_FLAG_SYNC here, since there are reports that Linux sometimes * does not report allocations for newly-written data that hasn't * been synced to disk. * * It's important to return a minimal sparse file list because we want * to not trigger sparse file extensions if we don't have to, since * not all readers support them. */ static int setup_sparse_fiemap(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { char buff[4096]; struct fiemap *fm; struct fiemap_extent *fe; int64_t size; int count, do_fiemap, iters; int exit_sts = ARCHIVE_OK; const char *path; if (archive_entry_filetype(entry) != AE_IFREG || archive_entry_size(entry) <= 0 || archive_entry_hardlink(entry) != NULL) return (ARCHIVE_OK); if (*fd < 0) { path = archive_read_disk_entry_setup_path(a, entry, NULL); if (path == NULL) return (ARCHIVE_FAILED); if (a->tree != NULL) *fd = a->open_on_current_dir(a->tree, path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); else *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); if (*fd < 0) { archive_set_error(&a->archive, errno, "Can't open `%s'", path); return (ARCHIVE_FAILED); } __archive_ensure_cloexec_flag(*fd); } /* Initialize buffer to avoid the error valgrind complains about. */ memset(buff, 0, sizeof(buff)); count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe); fm = (struct fiemap *)buff; fm->fm_start = 0; fm->fm_length = ~0ULL;; fm->fm_flags = FIEMAP_FLAG_SYNC; fm->fm_extent_count = count; do_fiemap = 1; size = archive_entry_size(entry); for (iters = 0; ; ++iters) { int i, r; r = ioctl(*fd, FS_IOC_FIEMAP, fm); if (r < 0) { /* When something error happens, it is better we * should return ARCHIVE_OK because an earlier * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */ goto exit_setup_sparse_fiemap; } if (fm->fm_mapped_extents == 0) { if (iters == 0) { /* Fully sparse file; insert a zero-length "data" entry */ archive_entry_sparse_add_entry(entry, 0, 0); } break; } fe = fm->fm_extents; for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) { if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) { /* The fe_length of the last block does not * adjust itself to its size files. */ int64_t length = fe->fe_length; if (fe->fe_logical + length > (uint64_t)size) length -= fe->fe_logical + length - size; if (fe->fe_logical == 0 && length == size) { /* This is not sparse. */ do_fiemap = 0; break; } if (length > 0) archive_entry_sparse_add_entry(entry, fe->fe_logical, length); } if (fe->fe_flags & FIEMAP_EXTENT_LAST) do_fiemap = 0; } if (do_fiemap) { fe = fm->fm_extents + fm->fm_mapped_extents -1; fm->fm_start = fe->fe_logical + fe->fe_length; } else break; } exit_setup_sparse_fiemap: return (exit_sts); } #if !defined(SEEK_HOLE) || !defined(SEEK_DATA) static int setup_sparse(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { return setup_sparse_fiemap(a, entry, fd); } #endif #endif /* defined(HAVE_LINUX_FIEMAP_H) */ #if defined(SEEK_HOLE) && defined(SEEK_DATA) /* * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris) */ static int setup_sparse(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { int64_t size; off_t initial_off; off_t off_s, off_e; int exit_sts = ARCHIVE_OK; int check_fully_sparse = 0; const char *path; if (archive_entry_filetype(entry) != AE_IFREG || archive_entry_size(entry) <= 0 || archive_entry_hardlink(entry) != NULL) return (ARCHIVE_OK); /* Does filesystem support the reporting of hole ? */ if (*fd < 0) { path = archive_read_disk_entry_setup_path(a, entry, fd); if (path == NULL) return (ARCHIVE_FAILED); } if (*fd >= 0) { #ifdef _PC_MIN_HOLE_SIZE if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0) return (ARCHIVE_OK); #endif initial_off = lseek(*fd, 0, SEEK_CUR); if (initial_off != 0) lseek(*fd, 0, SEEK_SET); } else { #ifdef _PC_MIN_HOLE_SIZE if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0) return (ARCHIVE_OK); #endif *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); if (*fd < 0) { archive_set_error(&a->archive, errno, "Can't open `%s'", path); return (ARCHIVE_FAILED); } __archive_ensure_cloexec_flag(*fd); initial_off = 0; } #ifndef _PC_MIN_HOLE_SIZE /* Check if the underlying filesystem supports seek hole */ off_s = lseek(*fd, 0, SEEK_HOLE); if (off_s < 0) #if defined(HAVE_LINUX_FIEMAP_H) return setup_sparse_fiemap(a, entry, fd); #else goto exit_setup_sparse; #endif else if (off_s > 0) lseek(*fd, 0, SEEK_SET); #endif off_s = 0; size = archive_entry_size(entry); while (off_s < size) { off_s = lseek(*fd, off_s, SEEK_DATA); if (off_s == (off_t)-1) { if (errno == ENXIO) { /* no more hole */ if (archive_entry_sparse_count(entry) == 0) { /* Potentially a fully-sparse file. */ check_fully_sparse = 1; } break; } archive_set_error(&a->archive, errno, "lseek(SEEK_HOLE) failed"); exit_sts = ARCHIVE_FAILED; goto exit_setup_sparse; } off_e = lseek(*fd, off_s, SEEK_HOLE); if (off_e == (off_t)-1) { if (errno == ENXIO) { off_e = lseek(*fd, 0, SEEK_END); if (off_e != (off_t)-1) break;/* no more data */ } archive_set_error(&a->archive, errno, "lseek(SEEK_DATA) failed"); exit_sts = ARCHIVE_FAILED; goto exit_setup_sparse; } if (off_s == 0 && off_e == size) break;/* This is not sparse. */ archive_entry_sparse_add_entry(entry, off_s, off_e - off_s); off_s = off_e; } if (check_fully_sparse) { if (lseek(*fd, 0, SEEK_HOLE) == 0 && lseek(*fd, 0, SEEK_END) == size) { /* Fully sparse file; insert a zero-length "data" entry */ archive_entry_sparse_add_entry(entry, 0, 0); } } exit_setup_sparse: lseek(*fd, initial_off, SEEK_SET); return (exit_sts); } #elif !defined(HAVE_LINUX_FIEMAP_H) /* * Generic (stub) sparse support. */ static int setup_sparse(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { (void)a; /* UNUSED */ (void)entry; /* UNUSED */ (void)fd; /* UNUSED */ return (ARCHIVE_OK); } #endif #endif /* !defined(_WIN32) || defined(__CYGWIN__) */ Index: vendor/libarchive/dist/libarchive/archive_write_disk_posix.c =================================================================== --- vendor/libarchive/dist/libarchive/archive_write_disk_posix.c (revision 315874) +++ vendor/libarchive/dist/libarchive/archive_write_disk_posix.c (revision 315875) @@ -1,4283 +1,4295 @@ /*- * 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 #endif #ifdef HAVE_SYS_ACL_H #include #endif #ifdef HAVE_SYS_EXTATTR_H #include #endif -#if defined(HAVE_SYS_XATTR_H) +#if HAVE_SYS_XATTR_H #include -#elif defined(HAVE_ATTR_XATTR_H) +#elif HAVE_ATTR_XATTR_H #include #endif #ifdef HAVE_SYS_EA_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_UTIME_H #include #endif #ifdef HAVE_COPYFILE_H #include #endif #ifdef HAVE_ERRNO_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #ifdef HAVE_GRP_H #include #endif #ifdef HAVE_LANGINFO_H #include #endif #ifdef HAVE_LINUX_FS_H #include /* 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 /* for Linux file flags */ #endif #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) #include /* Linux file flags, broken on Cygwin */ #endif #ifdef HAVE_LIMITS_H #include #endif #ifdef HAVE_PWD_H #include #endif #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_UTIME_H #include #endif #ifdef F_GETTIMES /* Tru64 specific */ #include #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 #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H #include #define HAVE_QUARANTINE 1 #endif #endif #ifdef HAVE_ZLIB_H #include #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_ACL_DARWIN /* * On MacOS, platform ACLs get stored in mac_metadata, too. * If we intend to extract mac_metadata and it is present * we skip extracting libarchive NFSv4 ACLs. */ size_t metadata_size; if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 || archive_entry_mac_metadata(a->entry, &metadata_size) == NULL || metadata_size == 0) #endif #if ARCHIVE_ACL_LIBRICHACL /* * RichACLs are stored in an extended attribute. * If we intend to extract extended attributes and have this * attribute we skip extracting libarchive NFSv4 ACLs. */ short extract_acls = 1; if (a->flags & ARCHIVE_EXTRACT_XATTR && ( archive_entry_acl_types(a->entry) & ARCHIVE_ENTRY_ACL_TYPE_NFS4)) { const char *attr_name; const void *attr_value; size_t attr_size; int i = archive_entry_xattr_reset(a->entry); while (i--) { archive_entry_xattr_next(a->entry, &attr_name, &attr_value, &attr_size); if (attr_name != NULL && attr_value != NULL && attr_size > 0 && strcmp(attr_name, "trusted.richacl") == 0) { extract_acls = 0; break; } } } if (extract_acls) #endif #if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL { #endif if (archive_entry_filetype(a->entry) == AE_IFDIR) a->deferred |= TODO_ACLS; else a->todo |= TODO_ACLS; #if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL } #endif } 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) + if (a->flags & ARCHIVE_EXTRACT_XATTR) { +#if ARCHIVE_XATTR_DARWIN + /* + * On MacOS, extended attributes get stored in mac_metadata, + * too. If we intend to extract mac_metadata and it is present + * we skip extracting extended attributes. + */ + size_t metadata_size; + + if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 || + archive_entry_mac_metadata(a->entry, + &metadata_size) == NULL || metadata_size == 0) +#endif 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; r2 = archive_write_disk_set_acls(&a->archive, a->fd, archive_entry_pathname(a->entry), archive_entry_acl(a->entry), archive_entry_mode(a->entry)); if (r2 < ret) ret = r2; } 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) archive_write_disk_set_acls(&a->archive, -1, p->name, &p->acl, p->mode); 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, "%s%s", 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 ", 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 ", 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 ", 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 ", 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 ", 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 ", 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 ", 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 ", path); res = ARCHIVE_FAILED; break; } } else { tail[0] = c; fsobj_error(a_eno, a_estr, 0, "Cannot extract through symlink ", 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 #if defined(FS_APPEND_FL) critical_flags |= FS_APPEND_FL; #elif defined(EXT2_APPEND_FL) critical_flags |= EXT2_APPEND_FL; #endif #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(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) 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. */ #if defined(FS_IMMUTABLE_FL) sf_mask |= FS_IMMUTABLE_FL; #elif defined(EXT2_IMMUTABLE_FL) sf_mask |= EXT2_IMMUTABLE_FL; #endif #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, #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, #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, #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 +#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX /* - * Restore extended attributes - Linux and AIX implementations: + * Restore extended attributes - Linux, Darwin 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) + if (a->fd >= 0) { +#if ARCHIVE_XATTR_LINUX e = fsetxattr(a->fd, name, value, size, 0); - else -#elif HAVE_FSETEA - if (a->fd >= 0) +#elif ARCHIVE_XATTR_DARWIN + e = fsetxattr(a->fd, name, value, size, 0, 0); +#elif ARCHIVE_XATTR_AIX e = fsetea(a->fd, name, value, size, 0); - else #endif - { -#if HAVE_LSETXATTR + } else { +#if ARCHIVE_XATTR_LINUX e = lsetxattr(archive_entry_pathname(entry), name, value, size, 0); -#elif HAVE_LSETEA +#elif ARCHIVE_XATTR_DARWIN + e = setxattr(archive_entry_pathname(entry), + name, value, size, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX 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 +#elif ARCHIVE_XATTR_FREEBSD /* * 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) + + 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( + } else { + e = extattr_set_link( 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); } #ifndef ARCHIVE_ACL_SUPPORT int archive_write_disk_set_acls(struct archive *a, int fd, const char *name, struct archive_acl *abstract_acl, __LA_MODE_T mode) { (void)a; /* UNUSED */ (void)fd; /* UNUSED */ (void)name; /* UNUSED */ (void)abstract_acl; /* UNUSED */ (void)mode; /* UNUSED */ return (ARCHIVE_OK); } #endif #endif /* !_WIN32 || __CYGWIN__ */ Index: vendor/libarchive/dist/libarchive/config_freebsd.h =================================================================== --- vendor/libarchive/dist/libarchive/config_freebsd.h (revision 315874) +++ vendor/libarchive/dist/libarchive/config_freebsd.h (revision 315875) @@ -1,162 +1,259 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ -/* FreeBSD 5.0 and later have ACL and extattr support. */ +#include + +/* FreeBSD 5.0 and later has ACL and extattr support. */ #if __FreeBSD__ > 4 -#define HAVE_ACL_CREATE_ENTRY 1 -#define HAVE_ACL_GET_FD_NP 1 -#define HAVE_ACL_GET_LINK_NP 1 -#define HAVE_ACL_GET_PERM_NP 1 -#define HAVE_ACL_INIT 1 -#define HAVE_ACL_SET_FD 1 -#define HAVE_ACL_SET_FD_NP 1 -#define HAVE_ACL_SET_FILE 1 -#define HAVE_ACL_USER 1 -#define HAVE_EXTATTR_GET_FILE 1 -#define HAVE_EXTATTR_LIST_FILE 1 -#define HAVE_EXTATTR_SET_FD 1 -#define HAVE_EXTATTR_SET_FILE 1 -#define HAVE_STRUCT_XVFSCONF 1 -#define HAVE_SYS_ACL_H 1 -#define HAVE_SYS_EXTATTR_H 1 -#endif +#define ARCHIVE_ACL_FREEBSD 1 +#define HAVE_ACL_GET_PERM_NP 1 +#define HAVE_ARC4RANDOM_BUF 1 +#define HAVE_EXTATTR_GET_FILE 1 +#define HAVE_EXTATTR_LIST_FILE 1 +#define HAVE_EXTATTR_SET_FD 1 +#define HAVE_EXTATTR_SET_FILE 1 +#define HAVE_STRUCT_XVFSCONF 1 +#define HAVE_SYS_ACL_H 1 +#define HAVE_SYS_EXTATTR_H 1 +#if __FreeBSD__ > 7 +/* FreeBSD 8.0 and later has NFSv4 ACL support */ +#define ARCHIVE_ACL_FREEBSD_NFS4 1 +#define HAVE_ACL_GET_LINK_NP 1 +#define HAVE_ACL_IS_TRIVIAL_NP 1 +#define HAVE_ACL_SET_LINK_NP 1 +#endif /* __FreeBSD__ > 7 */ +#endif /* __FreeBSD__ > 4 */ #ifdef WITH_OPENSSL -#define HAVE_OPENSSL_MD5_H 1 -#define HAVE_OPENSSL_RIPEMD_H 1 -#define HAVE_OPENSSL_SHA_H 1 -#define HAVE_SHA384 1 -#define HAVE_SHA512 1 +#define HAVE_LIBCRYPTO 1 +#define HAVE_OPENSSL_EVP_H 1 +#define HAVE_OPENSSL_MD5_H 1 +#define HAVE_OPENSSL_RIPEMD_H 1 +#define HAVE_OPENSSL_SHA_H 1 +#define HAVE_OPENSSL_SHA256_INIT 1 +#define HAVE_OPENSSL_SHA384_INIT 1 +#define HAVE_OPENSSL_SHA512_INIT 1 +#define HAVE_PKCS5_PBKDF2_HMAC_SHA1 1 +#define HAVE_SHA256 1 +#define HAVE_SHA384 1 +#define HAVE_SHA512 1 +#else +#define HAVE_LIBMD 1 +#define HAVE_MD5_H 1 +#define HAVE_MD5INIT 1 +#define HAVE_RIPEMD_H 1 +#define HAVE_SHA_H 1 +#define HAVE_SHA1 1 +#define HAVE_SHA1_INIT 1 +#define HAVE_SHA256 1 +#define HAVE_SHA256_H 1 +#define HAVE_SHA256_INIT 1 +#define HAVE_SHA512 1 +#define HAVE_SHA512_H 1 +#define HAVE_SHA512_INIT 1 #endif -#define HAVE_BSDXML_H 1 -#define HAVE_BZLIB_H 1 -#define HAVE_CHFLAGS 1 -#define HAVE_CHOWN 1 -#define HAVE_DECL_INT64_MAX 1 -#define HAVE_DECL_INT64_MIN 1 -#define HAVE_DECL_SIZE_MAX 1 -#define HAVE_DECL_SSIZE_MAX 1 -#define HAVE_DECL_STRERROR_R 1 -#define HAVE_DECL_UINT32_MAX 1 -#define HAVE_DECL_UINT64_MAX 1 -#define HAVE_DIRENT_H 1 -#define HAVE_EFTYPE 1 -#define HAVE_EILSEQ 1 -#define HAVE_ERRNO_H 1 -#define HAVE_FCHDIR 1 -#define HAVE_FCHFLAGS 1 -#define HAVE_FCHMOD 1 -#define HAVE_FCHOWN 1 -#define HAVE_FCNTL 1 -#define HAVE_FCNTL_H 1 -#define HAVE_FSEEKO 1 -#define HAVE_FSTAT 1 -#define HAVE_FTRUNCATE 1 -#define HAVE_FUTIMES 1 -#define HAVE_GETEUID 1 -#define HAVE_GETGRGID_R 1 -#define HAVE_GETPID 1 -#define HAVE_GETPWUID_R 1 -#define HAVE_GRP_H 1 -#define HAVE_INTTYPES_H 1 -#define HAVE_LCHFLAGS 1 -#define HAVE_LCHMOD 1 -#define HAVE_LCHOWN 1 -#define HAVE_LIMITS_H 1 -#define HAVE_LINK 1 -#define HAVE_LSTAT 1 -#define HAVE_LUTIMES 1 -#define HAVE_MALLOC 1 -#define HAVE_MD5 1 -#define HAVE_MD5_H 1 -#define HAVE_MEMMOVE 1 -#define HAVE_MKDIR 1 -#define HAVE_MKFIFO 1 -#define HAVE_MKNOD 1 -#define HAVE_PIPE 1 -#define HAVE_POLL 1 -#define HAVE_POLL_H 1 -#define HAVE_PWD_H 1 -#define HAVE_READLINK 1 -#define HAVE_RMD160 1 -#define HAVE_SELECT 1 -#define HAVE_SETENV 1 -#define HAVE_SHA_H 1 -#define HAVE_SHA1 1 -#define HAVE_SHA256 1 -#define HAVE_SHA256_H 1 -#define HAVE_SIGNAL_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_STDLIB_H 1 -#define HAVE_STRCHR 1 -#define HAVE_STRDUP 1 -#define HAVE_STRERROR 1 -#define HAVE_STRERROR_R 1 -#define HAVE_STRINGS_H 1 -#define HAVE_STRING_H 1 -#define HAVE_STRRCHR 1 -#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 -#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1 -#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1 -#define HAVE_STRUCT_STAT_ST_FLAGS 1 -#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 -#define HAVE_STRUCT_TM_TM_GMTOFF 1 -#define HAVE_SYMLINK 1 -#define HAVE_SYS_CDEFS_H 1 -#define HAVE_SYS_IOCTL_H 1 -#define HAVE_SYS_MOUNT_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_SELECT_H 1 -#define HAVE_SYS_STAT_H 1 -#define HAVE_SYS_TIME_H 1 -#define HAVE_SYS_TYPES_H 1 -#undef HAVE_SYS_UTIME_H -#define HAVE_SYS_UTSNAME_H 1 -#define HAVE_SYS_WAIT_H 1 -#define HAVE_TIMEGM 1 -#define HAVE_TZSET 1 -#define HAVE_UNISTD_H 1 -#define HAVE_UNSETENV 1 -#define HAVE_UTIME 1 -#define HAVE_UTIMES 1 -#define HAVE_UTIME_H 1 -#define HAVE_VFORK 1 -#define HAVE_WCHAR_H 1 -#define HAVE_WCSCPY 1 -#define HAVE_WCSLEN 1 -#define HAVE_WCTOMB 1 -#define HAVE_WMEMCMP 1 -#define HAVE_WMEMCPY 1 -#define HAVE_ZLIB_H 1 -#define TIME_WITH_SYS_TIME 1 +#define HAVE_BSDXML_H 1 +#define HAVE_BZLIB_H 1 +#define HAVE_CHFLAGS 1 +#define HAVE_CHOWN 1 +#define HAVE_CHROOT 1 +#define HAVE_CTIME_R 1 +#define HAVE_CTYPE_H 1 +#define HAVE_DECL_EXTATTR_NAMESPACE_USER 1 +#define HAVE_DECL_INT32_MAX 1 +#define HAVE_DECL_INT32_MIN 1 +#define HAVE_DECL_INT64_MAX 1 +#define HAVE_DECL_INT64_MIN 1 +#define HAVE_DECL_INTMAX_MAX 1 +#define HAVE_DECL_INTMAX_MIN 1 +#define HAVE_DECL_SIZE_MAX 1 +#define HAVE_DECL_SSIZE_MAX 1 +#define HAVE_DECL_STRERROR_R 1 +#define HAVE_DECL_UINT32_MAX 1 +#define HAVE_DECL_UINT64_MAX 1 +#define HAVE_DECL_UINTMAX_MAX 1 +#define HAVE_DIRENT_H 1 +#define HAVE_DLFCN_H 1 +#define HAVE_D_MD_ORDER 1 +#define HAVE_EFTYPE 1 +#define HAVE_EILSEQ 1 +#define HAVE_ERRNO_H 1 +#define HAVE_FCHDIR 1 +#define HAVE_FCHFLAGS 1 +#define HAVE_FCHMOD 1 +#define HAVE_FCHOWN 1 +#define HAVE_FCNTL 1 +#define HAVE_FCNTL_H 1 +#define HAVE_FDOPENDIR 1 +#define HAVE_FORK 1 +#define HAVE_FSEEKO 1 +#define HAVE_FSTAT 1 +#define HAVE_FSTATAT 1 +#define HAVE_FSTATFS 1 +#define HAVE_FSTATVFS 1 +#define HAVE_FTRUNCATE 1 +#define HAVE_FUTIMES 1 +#define HAVE_FUTIMESAT 1 +#define HAVE_GETEUID 1 +#define HAVE_GETGRGID_R 1 +#define HAVE_GETGRNAM_R 1 +#define HAVE_GETPID 1 +#define HAVE_GETPWNAM_R 1 +#define HAVE_GETPWUID_R 1 +#define HAVE_GETVFSBYNAME 1 +#define HAVE_GMTIME_R 1 +#define HAVE_GRP_H 1 +#define HAVE_INTMAX_T 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_LANGINFO_H 1 +#define HAVE_LCHFLAGS 1 +#define HAVE_LCHMOD 1 +#define HAVE_LCHOWN 1 +#define HAVE_LIBZ 1 +#define HAVE_LIMITS_H 1 +#define HAVE_LINK 1 +#define HAVE_LOCALE_H 1 +#define HAVE_LOCALTIME_R 1 +#define HAVE_LONG_LONG_INT 1 +#define HAVE_LSTAT 1 +#define HAVE_LUTIMES 1 +#define HAVE_MBRTOWC 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMORY_H 1 +#define HAVE_MEMSET 1 +#define HAVE_MKDIR 1 +#define HAVE_MKFIFO 1 +#define HAVE_MKNOD 1 +#define HAVE_MKSTEMP 1 +#define HAVE_NL_LANGINFO 1 +#define HAVE_OPENAT 1 +#define HAVE_PATHS_H 1 +#define HAVE_PIPE 1 +#define HAVE_POLL 1 +#define HAVE_POLL_H 1 +#define HAVE_POSIX_SPAWNP 1 +#define HAVE_PTHREAD_H 1 +#define HAVE_PWD_H 1 +#define HAVE_READDIR_R 1 +#define HAVE_READLINK 1 +#define HAVE_READLINKAT 1 +#define HAVE_READPASSPHRASE 1 +#define HAVE_READPASSPHRASE_H 1 +#define HAVE_REGEX_H 1 +#define HAVE_SELECT 1 +#define HAVE_SETENV 1 +#define HAVE_SETLOCALE 1 +#define HAVE_SIGACTION 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_SPAWN_H 1 +#define HAVE_STATFS 1 +#define HAVE_STATVFS 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRCHR 1 +#define HAVE_STRDUP 1 +#define HAVE_STRERROR 1 +#define HAVE_STRERROR_R 1 +#define HAVE_STRFTIME 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRUCT_STATFS_F_NAMEMAX 1 +#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1 +#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1 +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 +#define HAVE_STRUCT_STAT_ST_FLAGS 1 +#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 +#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1 +#define HAVE_STRUCT_TM_TM_GMTOFF 1 +#define HAVE_SYMLINK 1 +#define HAVE_SYS_CDEFS_H 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_SYS_MOUNT_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_POLL_H 1 +#define HAVE_SYS_SELECT_H 1 +#define HAVE_SYS_STATVFS_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_SYS_UTSNAME_H 1 +#define HAVE_SYS_WAIT_H 1 +#define HAVE_TIMEGM 1 +#define HAVE_TIME_H 1 +#define HAVE_TZSET 1 +#define HAVE_UINTMAX_T 1 +#define HAVE_UNISTD_H 1 +#define HAVE_UNSETENV 1 +#define HAVE_UNSIGNED_LONG_LONG 1 +#define HAVE_UNSIGNED_LONG_LONG_INT 1 +#define HAVE_UTIME 1 +#define HAVE_UTIMES 1 +#define HAVE_UTIME_H 1 +#define HAVE_VFORK 1 +#define HAVE_VPRINTF 1 +#define HAVE_WCHAR_H 1 +#define HAVE_WCHAR_T 1 +#define HAVE_WCRTOMB 1 +#define HAVE_WCSCMP 1 +#define HAVE_WCSCPY 1 +#define HAVE_WCSLEN 1 +#define HAVE_WCTOMB 1 +#define HAVE_WCTYPE_H 1 +#define HAVE_WMEMCMP 1 +#define HAVE_WMEMCPY 1 +#define HAVE_WMEMMOVE 1 +#define HAVE_ZLIB_H 1 +#define TIME_WITH_SYS_TIME 1 +#if __FreeBSD_version >= 1100056 +#define HAVE_FUTIMENS 1 +#define HAVE_UTIMENSAT 1 +#endif + /* FreeBSD 4 and earlier lack intmax_t/uintmax_t */ #if __FreeBSD__ < 5 -#define intmax_t int64_t -#define uintmax_t uint64_t +#define intmax_t int64_t +#define uintmax_t uint64_t +#endif + +/* FreeBSD defines for archive_hash.h */ +#ifdef WITH_OPENSSL +#define ARCHIVE_CRYPTO_MD5_OPENSSL 1 +#define ARCHIVE_CRYPTO_RMD160_OPENSSL 1 +#define ARCHIVE_CRYPTO_SHA1_OPENSSL +#define ARCHIVE_CRYPTO_SHA256_OPENSSL 1 +#define ARCHIVE_CRYPTO_SHA384_OPENSSL 1 +#define ARCHIVE_CRYPTO_SHA512_OPENSSL 1 +#else +#define ARCHIVE_CRYPTO_MD5_LIBMD 1 +#define ARCHIVE_CRYPTO_SHA1_LIBMD 1 +#define ARCHIVE_CRYPTO_SHA256_LIBMD 1 +#define ARCHIVE_CRYPTO_SHA512_LIBMD 1 #endif Index: vendor/libarchive/dist/libarchive/test/CMakeLists.txt =================================================================== --- vendor/libarchive/dist/libarchive/test/CMakeLists.txt (revision 315874) +++ vendor/libarchive/dist/libarchive/test/CMakeLists.txt (revision 315875) @@ -1,313 +1,314 @@ ############################################ # # How to build libarchive_test # ############################################ IF(ENABLE_TEST) SET(libarchive_test_SOURCES ../../test_utils/test_utils.c ../../test_utils/test_main.c read_open_memory.c test.h test_acl_nfs4.c test_acl_pax.c test_acl_platform_nfs4.c test_acl_platform_posix1e.c test_acl_posix1e.c test_acl_text.c test_archive_api_feature.c test_archive_clear_error.c test_archive_cmdline.c test_archive_digest.c test_archive_getdate.c test_archive_match_owner.c test_archive_match_path.c test_archive_match_time.c test_archive_pathmatch.c test_archive_read_add_passphrase.c test_archive_read_close_twice.c test_archive_read_close_twice_open_fd.c test_archive_read_close_twice_open_filename.c test_archive_read_multiple_data_objects.c test_archive_read_next_header_empty.c test_archive_read_next_header_raw.c test_archive_read_open2.c test_archive_read_set_filter_option.c test_archive_read_set_format_option.c test_archive_read_set_option.c test_archive_read_set_options.c test_archive_read_support.c test_archive_set_error.c test_archive_string.c test_archive_string_conversion.c test_archive_write_add_filter_by_name.c test_archive_write_set_filter_option.c test_archive_write_set_format_by_name.c test_archive_write_set_format_filter_by_ext.c test_archive_write_set_format_option.c test_archive_write_set_option.c test_archive_write_set_options.c test_archive_write_set_passphrase.c test_bad_fd.c test_compat_bzip2.c test_compat_cpio.c test_compat_gtar.c test_compat_gzip.c test_compat_lz4.c test_compat_lzip.c test_compat_lzma.c test_compat_lzop.c test_compat_mac.c test_compat_pax_libarchive_2x.c test_compat_perl_archive_tar.c test_compat_plexus_archiver_tar.c test_compat_solaris_pax_sparse.c test_compat_solaris_tar_acl.c test_compat_star_acl.c test_compat_tar_hardlink.c test_compat_uudecode.c test_compat_uudecode_large.c test_compat_xz.c test_compat_zip.c test_empty_write.c test_entry.c test_entry_strmode.c test_extattr_freebsd.c test_filter_count.c test_fuzz.c test_gnutar_filename_encoding.c test_link_resolver.c test_open_failure.c test_open_fd.c test_open_file.c test_open_filename.c test_pax_filename_encoding.c test_read_data_large.c test_read_disk.c test_read_disk_directory_traversals.c test_read_disk_entry_from_file.c test_read_extract.c test_read_file_nonexistent.c test_read_filter_compress.c test_read_filter_grzip.c test_read_filter_lrzip.c test_read_filter_lzop.c test_read_filter_lzop_multiple_parts.c test_read_filter_program.c test_read_filter_program_signature.c test_read_filter_uudecode.c test_read_format_7zip.c test_read_format_7zip_encryption_data.c test_read_format_7zip_encryption_header.c test_read_format_7zip_encryption_partially.c test_read_format_7zip_malformed.c test_read_format_ar.c test_read_format_cab.c test_read_format_cab_filename.c test_read_format_cpio_afio.c test_read_format_cpio_bin.c test_read_format_cpio_bin_Z.c test_read_format_cpio_bin_be.c test_read_format_cpio_bin_bz2.c test_read_format_cpio_bin_gz.c test_read_format_cpio_bin_le.c test_read_format_cpio_bin_lzip.c test_read_format_cpio_bin_lzma.c test_read_format_cpio_bin_xz.c test_read_format_cpio_filename.c test_read_format_cpio_odc.c test_read_format_cpio_svr4_bzip2_rpm.c test_read_format_cpio_svr4_gzip.c test_read_format_cpio_svr4_gzip_rpm.c test_read_format_cpio_svr4c_Z.c test_read_format_empty.c test_read_format_gtar_filename.c test_read_format_gtar_gz.c test_read_format_gtar_lzma.c test_read_format_gtar_sparse.c test_read_format_gtar_sparse_skip_entry.c test_read_format_iso_Z.c test_read_format_iso_multi_extent.c test_read_format_iso_xorriso.c test_read_format_isojoliet_bz2.c test_read_format_isojoliet_long.c test_read_format_isojoliet_rr.c test_read_format_isojoliet_versioned.c test_read_format_isorr_bz2.c test_read_format_isorr_ce.c test_read_format_isorr_new_bz2.c test_read_format_isorr_rr_moved.c test_read_format_isozisofs_bz2.c test_read_format_lha.c test_read_format_lha_bugfix_0.c test_read_format_lha_filename.c test_read_format_mtree.c test_read_format_mtree_crash747.c test_read_format_pax_bz2.c test_read_format_rar.c test_read_format_rar_encryption_data.c test_read_format_rar_encryption_header.c test_read_format_rar_encryption_partially.c test_read_format_rar_invalid1.c test_read_format_raw.c test_read_format_tar.c test_read_format_tar_concatenated.c test_read_format_tar_empty_filename.c test_read_format_tar_empty_pax.c test_read_format_tar_filename.c test_read_format_tbz.c test_read_format_tgz.c test_read_format_tlz.c test_read_format_txz.c test_read_format_tz.c test_read_format_ustar_filename.c test_read_format_warc.c test_read_format_xar.c test_read_format_zip.c test_read_format_zip_comment_stored.c test_read_format_zip_encryption_data.c test_read_format_zip_encryption_header.c test_read_format_zip_encryption_partially.c test_read_format_zip_filename.c test_read_format_zip_high_compression.c test_read_format_zip_jar.c test_read_format_zip_mac_metadata.c test_read_format_zip_malformed.c test_read_format_zip_msdos.c test_read_format_zip_nested.c test_read_format_zip_nofiletype.c test_read_format_zip_padded.c test_read_format_zip_sfx.c test_read_format_zip_traditional_encryption_data.c test_read_format_zip_winzip_aes.c test_read_format_zip_winzip_aes_large.c test_read_format_zip_zip64.c test_read_large.c test_read_pax_schily_xattr.c test_read_pax_truncated.c test_read_position.c test_read_set_format.c test_read_too_many_filters.c test_read_truncated.c test_read_truncated_filter.c test_sparse_basic.c test_tar_filenames.c test_tar_large.c test_ustar_filename_encoding.c test_ustar_filenames.c test_warn_missing_hardlink_target.c test_write_disk.c test_write_disk_appledouble.c test_write_disk_failures.c test_write_disk_hardlink.c test_write_disk_hfs_compression.c test_write_disk_lookup.c test_write_disk_mac_metadata.c test_write_disk_no_hfs_compression.c test_write_disk_perms.c test_write_disk_secure.c test_write_disk_secure744.c test_write_disk_secure745.c test_write_disk_secure746.c test_write_disk_sparse.c test_write_disk_symlink.c test_write_disk_times.c test_write_filter_b64encode.c test_write_filter_bzip2.c test_write_filter_compress.c test_write_filter_gzip.c test_write_filter_gzip_timestamp.c test_write_filter_lrzip.c test_write_filter_lz4.c test_write_filter_lzip.c test_write_filter_lzma.c test_write_filter_lzop.c test_write_filter_program.c test_write_filter_uuencode.c test_write_filter_xz.c test_write_format_7zip.c test_write_format_7zip_empty.c test_write_format_7zip_large.c test_write_format_ar.c test_write_format_cpio.c test_write_format_cpio_empty.c test_write_format_cpio_newc.c test_write_format_cpio_odc.c test_write_format_gnutar.c test_write_format_gnutar_filenames.c test_write_format_iso9660.c test_write_format_iso9660_boot.c test_write_format_iso9660_empty.c test_write_format_iso9660_filename.c test_write_format_iso9660_zisofs.c test_write_format_mtree.c test_write_format_mtree_absolute_path.c test_write_format_mtree_classic.c test_write_format_mtree_classic_indent.c test_write_format_mtree_fflags.c test_write_format_mtree_no_separator.c test_write_format_mtree_quoted_filename.c test_write_format_pax.c test_write_format_raw.c test_write_format_raw_b64.c test_write_format_shar_empty.c test_write_format_tar.c test_write_format_tar_empty.c test_write_format_tar_sparse.c test_write_format_tar_ustar.c test_write_format_tar_v7tar.c test_write_format_warc.c test_write_format_warc_empty.c test_write_format_xar.c test_write_format_xar_empty.c test_write_format_zip.c test_write_format_zip_compression_store.c test_write_format_zip_empty.c test_write_format_zip_empty_zip64.c test_write_format_zip_file.c test_write_format_zip_file_zip64.c test_write_format_zip_large.c test_write_format_zip_zip64.c test_write_open_memory.c test_write_read_format_zip.c + test_xattr_platform.c test_zip_filename_encoding.c ) # # Register target # ADD_EXECUTABLE(libarchive_test ${libarchive_test_SOURCES}) TARGET_LINK_LIBRARIES(libarchive_test archive_static ${ADDITIONAL_LIBS}) SET_PROPERTY(TARGET libarchive_test PROPERTY COMPILE_DEFINITIONS LIBARCHIVE_STATIC LIST_H) # # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. # GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h ${CMAKE_CURRENT_LIST_FILE} ${libarchive_test_SOURCES}) SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}) # list.h has a line DEFINE_TEST(testname) for every # test. We can use that to define the tests for cmake by # defining a DEFINE_TEST macro and reading list.h in. MACRO (DEFINE_TEST _testname) ADD_TEST( NAME libarchive_${_testname} COMMAND libarchive_test -vv -r ${CMAKE_CURRENT_SOURCE_DIR} ${_testname}) ENDMACRO (DEFINE_TEST _testname) INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/libarchive/test) # Experimental new test handling ADD_CUSTOM_TARGET(run_libarchive_test COMMAND libarchive_test -r ${CMAKE_CURRENT_SOURCE_DIR} -vv) ADD_DEPENDENCIES(run_all_tests run_libarchive_test) ENDIF(ENABLE_TEST) Index: vendor/libarchive/dist/libarchive/test/test_xattr_platform.c =================================================================== --- vendor/libarchive/dist/libarchive/test/test_xattr_platform.c (nonexistent) +++ vendor/libarchive/dist/libarchive/test/test_xattr_platform.c (revision 315875) @@ -0,0 +1,102 @@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2017 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. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_xattr_platform) +{ +#if !ARCHIVE_XATTR_SUPPORT + skipping("Extended attributes are not supported on this platform"); +#else /* ARCHIVE_XATTR_SUPPORT */ + struct archive *a; + struct archive_entry *ae; + const char *name; + const void *value; + size_t size, insize; + int e, r; + const char *attrname = "user.libarchive.test"; + const char *readval = "readval"; + const char *writeval = "writeval"; + + assertMakeFile("readtest", 0644, "a"); + + if (!setXattr("readtest", attrname, readval, strlen(readval) + 1)) { + skipping("Extended attributes are not supported on this " + "filesystem"); + return; + } + + /* Read test */ + assert(NULL != (a = archive_read_disk_new())); + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "readtest"); + assertEqualInt(ARCHIVE_OK, + archive_read_disk_entry_from_file(a, ae, -1, NULL)); + e = archive_entry_xattr_reset(ae); + assert(e > 0); + + r = 0; + while (archive_entry_xattr_next(ae, &name, &value, + &size) == ARCHIVE_OK) { + if (name != NULL && value != NULL && size > 0 && + strcmp(name, attrname) == 0) { + failure("Attribute value does not match"); + assertEqualString((const char *)value, readval); + r = 1; + break; + } + } + failure("Attribute not found: %s", attrname); + assertEqualInt(r, 1); + + archive_entry_free(ae); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + assert(NULL != (a = archive_write_disk_new())); + archive_write_disk_set_options(a, ARCHIVE_EXTRACT_TIME | + ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_XATTR); + + /* Write test */ + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "writetest"); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_perm(ae, 0654); + archive_entry_set_mtime(ae, 123456, 7890); + archive_entry_set_size(ae, 0); + archive_entry_xattr_add_entry(ae, attrname, writeval, + strlen(writeval) + 1); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + value = getXattr("writetest", attrname, &insize); + if (assertEqualInt(insize, strlen(writeval) + 1) != 0) + assertEqualMem(value, writeval, insize); +#endif +} Property changes on: vendor/libarchive/dist/libarchive/test/test_xattr_platform.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/libarchive/dist/tar/bsdtar.1 =================================================================== --- vendor/libarchive/dist/tar/bsdtar.1 (revision 315874) +++ vendor/libarchive/dist/tar/bsdtar.1 (revision 315875) @@ -1,1242 +1,1242 @@ .\" Copyright (c) 2003-2007 Tim Kientzle .\" Copyright (c) 2017 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 AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd February 25, 2017 .Dt TAR 1 .Os .Sh NAME .Nm tar .Nd manipulate tape archives .Sh SYNOPSIS .Nm .Op Ar bundled-flags Ao args Ac .Op Ao Ar file Ac | Ao Ar pattern Ac ... .Nm .Brq Fl c .Op Ar options .Op Ar files | Ar directories .Nm .Brq Fl r | Fl u .Fl f Ar archive-file .Op Ar options .Op Ar files | Ar directories .Nm .Brq Fl t | Fl x .Op Ar options .Op Ar patterns .Sh DESCRIPTION .Nm creates and manipulates streaming archive files. This implementation can extract from tar, pax, cpio, zip, jar, ar, xar, rpm, 7-zip, and ISO 9660 cdrom images and can create tar, pax, cpio, ar, zip, 7-zip, and shar archives. .Pp The first synopsis form shows a .Dq bundled option word. This usage is provided for compatibility with historical implementations. See COMPATIBILITY below for details. .Pp The other synopsis forms show the preferred usage. The first option to .Nm is a mode indicator from the following list: .Bl -tag -compact -width indent .It Fl c Create a new archive containing the specified items. The long option form is .Fl Fl create . .It Fl r Like .Fl c , but new entries are appended to the archive. Note that this only works on uncompressed archives stored in regular files. The .Fl f option is required. The long option form is .Fl Fl append . .It Fl t List archive contents to stdout. The long option form is .Fl Fl list . .It Fl u Like .Fl r , but new entries are added only if they have a modification date newer than the corresponding entry in the archive. Note that this only works on uncompressed archives stored in regular files. The .Fl f option is required. The long form is .Fl Fl update . .It Fl x Extract to disk from the archive. If a file with the same name appears more than once in the archive, each copy will be extracted, with later copies overwriting (replacing) earlier copies. The long option form is .Fl Fl extract . .El .Pp In .Fl c , .Fl r , or .Fl u mode, each specified file or directory is added to the archive in the order specified on the command line. By default, the contents of each directory are also archived. .Pp In extract or list mode, the entire command line is read and parsed before the archive is opened. The pathnames or patterns on the command line indicate which items in the archive should be processed. Patterns are shell-style globbing patterns as documented in .Xr tcsh 1 . .Sh OPTIONS Unless specifically stated otherwise, options are applicable in all operating modes. .Bl -tag -width indent .It Cm @ Ns Pa archive (c and r modes only) The specified archive is opened and the entries in it will be appended to the current archive. As a simple example, .Dl Nm Fl c Fl f Pa - Pa newfile Cm @ Ns Pa original.tar writes a new archive to standard output containing a file .Pa newfile and all of the entries from .Pa original.tar . In contrast, .Dl Nm Fl c Fl f Pa - Pa newfile Pa original.tar creates a new archive with only two entries. Similarly, .Dl Nm Fl czf Pa - Fl Fl format Cm pax Cm @ Ns Pa - reads an archive from standard input (whose format will be determined automatically) and converts it into a gzip-compressed pax-format archive on stdout. In this way, .Nm can be used to convert archives from one format to another. .It Fl a , Fl Fl auto-compress (c mode only) Use the archive suffix to decide a set of the format and the compressions. As a simple example, .Dl Nm Fl a Fl cf Pa archive.tgz source.c source.h creates a new archive with restricted pax format and gzip compression, .Dl Nm Fl a Fl cf Pa archive.tar.bz2.uu source.c source.h creates a new archive with restricted pax format and bzip2 compression and uuencode compression, .Dl Nm Fl a Fl cf Pa archive.zip source.c source.h creates a new archive with zip format, .Dl Nm Fl a Fl jcf Pa archive.tgz source.c source.h ignores the .Dq -j option, and creates a new archive with restricted pax format and gzip compression, .Dl Nm Fl a Fl jcf Pa archive.xxx source.c source.h if it is unknown suffix or no suffix, creates a new archive with restricted pax format and bzip2 compression. .It Fl Fl acls (c, r, u, x modes only) Archive or extract POSIX.1e or NFSv4 ACLs. This is the reverse of .Fl Fl no-acls -and the default behavior in c, r, and u modes (except Mac OS X) or if +and the default behavior in c, r, and u modes (except on Mac OS X) or if .Nm is run in x mode as root. On Mac OS X this option translates extended ACLs to NFSv4 ACLs. To store extended ACLs the .Fl Fl mac-metadata option is preferred. .It Fl B , Fl Fl read-full-blocks Ignored for compatibility with other .Xr tar 1 implementations. .It Fl b Ar blocksize , Fl Fl block-size Ar blocksize Specify the block size, in 512-byte records, for tape drive I/O. As a rule, this argument is only needed when reading from or writing to tape drives, and usually not even then as the default block size of 20 records (10240 bytes) is very common. .It Fl C Ar directory , Fl Fl cd Ar directory , Fl Fl directory Ar directory In c and r mode, this changes the directory before adding the following files. In x mode, change directories after opening the archive but before extracting entries from the archive. .It Fl Fl chroot (x mode only) .Fn chroot to the current directory after processing any .Fl C options and before extracting any files. .It Fl Fl clear-nochange-fflags (x mode only) Before removing file system objects to replace them, clear platform-specific file flags that might prevent removal. .It Fl Fl exclude Ar pattern Do not process files or directories that match the specified pattern. Note that exclusions take precedence over patterns or filenames specified on the command line. .It Fl Fl fflags (c, r, u, x modes only) Archive or extract file flags. This is the reverse of .Fl Fl no-fflags and the default behavior in c, r, and u modes or if .Nm is run in x mode as root. .It Fl Fl format Ar format (c, r, u mode only) Use the specified format for the created archive. Supported formats include .Dq cpio , .Dq pax , .Dq shar , and .Dq ustar . Other formats may also be supported; see .Xr libarchive-formats 5 for more information about currently-supported formats. In r and u modes, when extending an existing archive, the format specified here must be compatible with the format of the existing archive on disk. .It Fl f Ar file , Fl Fl file Ar file Read the archive from or write the archive to the specified file. The filename can be .Pa - for standard input or standard output. The default varies by system; on .Fx , the default is .Pa /dev/sa0 ; on Linux, the default is .Pa /dev/st0 . .It Fl Fl gid Ar id Use the provided group id number. On extract, this overrides the group id in the archive; the group name in the archive will be ignored. On create, this overrides the group id read from disk; if .Fl Fl gname is not also specified, the group name will be set to match the group id. .It Fl Fl gname Ar name Use the provided group name. On extract, this overrides the group name in the archive; if the provided group name does not exist on the system, the group id (from the archive or from the .Fl Fl gid option) will be used instead. On create, this sets the group name that will be stored in the archive; the name will not be verified against the system group database. .It Fl H (c and r modes only) Symbolic links named on the command line will be followed; the target of the link will be archived, not the link itself. .It Fl h (c and r modes only) Synonym for .Fl L . .It Fl I Synonym for .Fl T . .It Fl Fl help Show usage. .It Fl Fl hfsCompression (x mode only) Mac OS X specific (v10.6 or later). Compress extracted regular files with HFS+ compression. .It Fl Fl ignore-zeros An alias of .Fl Fl options Cm read_concatenated_archives for compatibility with GNU tar. .It Fl Fl include Ar pattern Process only files or directories that match the specified pattern. Note that exclusions specified with .Fl Fl exclude take precedence over inclusions. If no inclusions are explicitly specified, all entries are processed by default. The .Fl Fl include option is especially useful when filtering archives. For example, the command .Dl Nm Fl c Fl f Pa new.tar Fl Fl include='*foo*' Cm @ Ns Pa old.tgz creates a new archive .Pa new.tar containing only the entries from .Pa old.tgz containing the string .Sq foo . .It Fl J , Fl Fl xz (c mode only) Compress the resulting archive with .Xr xz 1 . In extract or list modes, this option is ignored. Note that, unlike other .Nm tar implementations, this implementation recognizes XZ compression automatically when reading archives. .It Fl j , Fl Fl bzip , Fl Fl bzip2 , Fl Fl bunzip2 (c mode only) Compress the resulting archive with .Xr bzip2 1 . In extract or list modes, this option is ignored. Note that, unlike other .Nm tar implementations, this implementation recognizes bzip2 compression automatically when reading archives. .It Fl k , Fl Fl keep-old-files (x mode only) Do not overwrite existing files. In particular, if a file appears more than once in an archive, later copies will not overwrite earlier copies. .It Fl Fl keep-newer-files (x mode only) Do not overwrite existing files that are newer than the versions appearing in the archive being extracted. .It Fl L , Fl Fl dereference (c and r modes only) All symbolic links will be followed. Normally, symbolic links are archived as such. With this option, the target of the link will be archived instead. .It Fl l , Fl Fl check-links (c and r modes only) Issue a warning message unless all links to each file are archived. .It Fl Fl lrzip (c mode only) Compress the resulting archive with .Xr lrzip 1 . In extract or list modes, this option is ignored. .It Fl Fl lz4 (c mode only) Compress the archive with lz4-compatible compression before writing it. In input mode, this option is ignored; lz4 compression is recognized automatically on input. .It Fl Fl lzma (c mode only) Compress the resulting archive with the original LZMA algorithm. Use of this option is discouraged and new archives should be created with .Fl Fl xz instead. Note that, unlike other .Nm tar implementations, this implementation recognizes LZMA compression automatically when reading archives. .It Fl Fl lzop (c mode only) Compress the resulting archive with .Xr lzop 1 . In extract or list modes, this option is ignored. .It Fl m , Fl Fl modification-time (x mode only) Do not extract modification time. By default, the modification time is set to the time stored in the archive. .It Fl Fl mac-metadata (c, r, u and x mode only) Mac OS X specific. Archive or extract extended ACLs and extended attributes using .Xr copyfile 3 in AppleDouble format. This is the reverse of .Fl Fl no-mac-metadata . and the default behavior in c, r, and u modes or if .Nm is run in x mode as root. .It Fl n , Fl Fl norecurse , Fl Fl no-recursion (c, r, u modes only) Do not recursively archive the contents of directories. .It Fl Fl newer Ar date (c, r, u modes only) Only include files and directories newer than the specified date. This compares ctime entries. .It Fl Fl newer-mtime Ar date (c, r, u modes only) Like .Fl Fl newer , except it compares mtime entries instead of ctime entries. .It Fl Fl newer-than Pa file (c, r, u modes only) Only include files and directories newer than the specified file. This compares ctime entries. .It Fl Fl newer-mtime-than Pa file (c, r, u modes only) Like .Fl Fl newer-than , except it compares mtime entries instead of ctime entries. .It Fl Fl nodump (c and r modes only) Honor the nodump file flag by skipping this file. .It Fl Fl nopreserveHFSCompression (x mode only) -Mac OS X specific(v10.6 or later). Do not compress extracted regular files +Mac OS X specific (v10.6 or later). Do not compress extracted regular files which were compressed with HFS+ compression before archived. By default, compress the regular files again with HFS+ compression. .It Fl Fl null (use with .Fl I or .Fl T ) Filenames or patterns are separated by null characters, not by newlines. This is often used to read filenames output by the .Fl print0 option to .Xr find 1 . .It Fl Fl no-acls (c, r, u, x modes only) Do not archive or extract POSIX.1e or NFSv4 ACLs. This is the reverse of .Fl Fl acls and the default behavior if .Nm -is run as non-root in x mode (on Mac OS X also in c, r and u modes). +is run as non-root in x mode (on Mac OS X as any user in c, r, u and x modes). .It Fl Fl no-fflags (c, r, u, x modes only) Do not archive or extract file flags. This is the reverse of .Fl Fl fflags and the default behavior if .Nm is run as non-root in x mode. .It Fl Fl no-mac-metadata (x mode only) Mac OS X specific. Do not archive or extract ACLs and extended attributes using .Xr copyfile 3 in AppleDouble format. This is the reverse of .Fl Fl mac-metadata . and the default behavior if .Nm is run as non-root in x mode. .It Fl n , Fl Fl norecurse , Fl Fl no-recursion .It Fl Fl no-same-owner (x mode only) Do not extract owner and group IDs. This is the reverse of .Fl Fl same-owner and the default behavior if .Nm is run as non-root. .It Fl Fl no-same-permissions (x mode only) Do not extract full permissions (SGID, SUID, sticky bit, ACLs, extended attributes or extended file flags). This is the reverse of .Fl p and the default behavior if .Nm is run as non-root. .It Fl Fl no-xattrs (c, r, u, x modes only) Do not archive or extract extended attributes. This is the reverse of .Fl Fl xattrs and the default behavior if .Nm is run as non-root in x mode. .It Fl Fl numeric-owner This is equivalent to .Fl Fl uname .Qq .Fl Fl gname .Qq . On extract, it causes user and group names in the archive to be ignored in favor of the numeric user and group ids. On create, it causes user and group names to not be stored in the archive. .It Fl O , Fl Fl to-stdout (x, t modes only) In extract (-x) mode, files will be written to standard out rather than being extracted to disk. In list (-t) mode, the file listing will be written to stderr rather than the usual stdout. .It Fl o (x mode) Use the user and group of the user running the program rather than those specified in the archive. Note that this has no significance unless .Fl p is specified, and the program is being run by the root user. In this case, the file modes and flags from the archive will be restored, but ACLs or owner information in the archive will be discarded. .It Fl o (c, r, u mode) A synonym for .Fl Fl format Ar ustar .It Fl Fl older Ar date (c, r, u modes only) Only include files and directories older than the specified date. This compares ctime entries. .It Fl Fl older-mtime Ar date (c, r, u modes only) Like .Fl Fl older , except it compares mtime entries instead of ctime entries. .It Fl Fl older-than Pa file (c, r, u modes only) Only include files and directories older than the specified file. This compares ctime entries. .It Fl Fl older-mtime-than Pa file (c, r, u modes only) Like .Fl Fl older-than , except it compares mtime entries instead of ctime entries. .It Fl Fl one-file-system (c, r, and u modes) Do not cross mount points. .It Fl Fl options Ar options Select optional behaviors for particular modules. The argument is a text string containing comma-separated keywords and values. These are passed to the modules that handle particular formats to control how those formats will behave. Each option has one of the following forms: .Bl -tag -compact -width indent .It Ar key=value The key will be set to the specified value in every module that supports it. Modules that do not support this key will ignore it. .It Ar key The key will be enabled in every module that supports it. This is equivalent to .Ar key Ns Cm =1 . .It Ar !key The key will be disabled in every module that supports it. .It Ar module:key=value , Ar module:key , Ar module:!key As above, but the corresponding key and value will be provided only to modules whose name matches .Ar module . .El The currently supported modules and keys are: .Bl -tag -compact -width indent .It Cm iso9660:joliet Support Joliet extensions. This is enabled by default, use .Cm !joliet or .Cm iso9660:!joliet to disable. .It Cm iso9660:rockridge Support Rock Ridge extensions. This is enabled by default, use .Cm !rockridge or .Cm iso9660:!rockridge to disable. .It Cm gzip:compression-level A decimal integer from 1 to 9 specifying the gzip compression level. .It Cm gzip:timestamp Store timestamp. This is enabled by default, use .Cm !timestamp or .Cm gzip:!timestamp to disable. .It Cm lrzip:compression Ns = Ns Ar type Use .Ar type as compression method. Supported values are bzip2, gzip, lzo (ultra fast), and zpaq (best, extremely slow). .It Cm lrzip:compression-level A decimal integer from 1 to 9 specifying the lrzip compression level. .It Cm lz4:compression-level A decimal integer from 1 to 9 specifying the lzop compression level. .It Cm lz4:stream-checksum Enable stream checksum. This is by default, use .Cm lz4:!stream-checksum to disable. .It Cm lz4:block-checksum Enable block checksum (Disabled by default). .It Cm lz4:block-size A decimal integer from 4 to 7 specifying the lz4 compression block size (7 is set by default). .It Cm lz4:block-dependence Use the previous block of the block being compressed for a compression dictionary to improve compression ratio. .It Cm lzop:compression-level A decimal integer from 1 to 9 specifying the lzop compression level. .It Cm xz:compression-level A decimal integer from 0 to 9 specifying the xz compression level. .It Cm mtree: Ns Ar keyword The mtree writer module allows you to specify which mtree keywords will be included in the output. Supported keywords include: .Cm cksum , Cm device , Cm flags , Cm gid , Cm gname , Cm indent , .Cm link , Cm md5 , Cm mode , Cm nlink , Cm rmd160 , Cm sha1 , Cm sha256 , .Cm sha384 , Cm sha512 , Cm size , Cm time , Cm uid , Cm uname . The default is equivalent to: .Dq device, flags, gid, gname, link, mode, nlink, size, time, type, uid, uname . .It Cm mtree:all Enables all of the above keywords. You can also use .Cm mtree:!all to disable all keywords. .It Cm mtree:use-set Enable generation of .Cm /set lines in the output. .It Cm mtree:indent Produce human-readable output by indenting options and splitting lines to fit into 80 columns. .It Cm zip:compression Ns = Ns Ar type Use .Ar type as compression method. Supported values are store (uncompressed) and deflate (gzip algorithm). .It Cm zip:encryption Enable encryption using traditional zip encryption. .It Cm zip:encryption Ns = Ns Ar type Use .Ar type as encryption type. Supported values are zipcrypt (traditional zip encryption), aes128 (WinZip AES-128 encryption) and aes256 (WinZip AES-256 encryption). .It Cm read_concatenated_archives Ignore zeroed blocks in the archive, which occurs when multiple tar archives have been concatenated together. Without this option, only the contents of the first concatenated archive would be read. This option is comparable to the .Fl i , Fl Fl ignore-zeros option of GNU tar. .El If a provided option is not supported by any module, that is a fatal error. .It Fl P , Fl Fl absolute-paths Preserve pathnames. By default, absolute pathnames (those that begin with a / character) have the leading slash removed both when creating archives and extracting from them. Also, .Nm will refuse to extract archive entries whose pathnames contain .Pa .. or whose target directory would be altered by a symlink. This option suppresses these behaviors. .It Fl p , Fl Fl insecure , Fl Fl preserve-permissions (x mode only) Preserve file permissions. Attempt to restore the full permissions, including owner, file modes, ACLs, extended attributes and extended file flags, if available, for each item extracted from the archive. This is te reverse of .Fl Fl no-same-permissions and the default if .Nm is being run by root and can be partially overridden by also specifying .Fl Fl no-acls , .Fl Fl no-fflags , .Fl Fl no-mac-metadata or .Fl Fl no-xattrs . .It Fl Fl passphrase Ar passphrase The .Pa passphrase is used to extract or create an encrypted archive. Currently, zip is the only supported format that supports encryption. You shouldn't use this option unless you realize how insecure use of this option is. .It Fl Fl posix (c, r, u mode only) Synonym for .Fl Fl format Ar pax .It Fl q , Fl Fl fast-read (x and t mode only) Extract or list only the first archive entry that matches each pattern or filename operand. Exit as soon as each specified pattern or filename has been matched. By default, the archive is always read to the very end, since there can be multiple entries with the same name and, by convention, later entries overwrite earlier entries. This option is provided as a performance optimization. .It Fl S (x mode only) Extract files as sparse files. For every block on disk, check first if it contains only NULL bytes and seek over it otherwise. This works similar to the conv=sparse option of dd. .It Fl s Ar pattern Modify file or archive member names according to .Pa pattern . The pattern has the format .Ar /old/new/ Ns Op ghHprRsS where .Ar old is a basic regular expression, .Ar new is the replacement string of the matched part, and the optional trailing letters modify how the replacement is handled. If .Ar old is not matched, the pattern is skipped. Within .Ar new , ~ is substituted with the match, \e1 to \e9 with the content of the corresponding captured group. The optional trailing g specifies that matching should continue after the matched part and stop on the first unmatched pattern. The optional trailing s specifies that the pattern applies to the value of symbolic links. The optional trailing p specifies that after a successful substitution the original path name and the new path name should be printed to standard error. Optional trailing H, R, or S characters suppress substitutions for hardlink targets, regular filenames, or symlink targets, respectively. Optional trailing h, r, or s characters enable substitutions for hardlink targets, regular filenames, or symlink targets, respectively. The default is .Ar hrs which applies substitutions to all names. In particular, it is never necessary to specify h, r, or s. .It Fl Fl same-owner (x mode only) Extract owner and group IDs. This is the reverse of .Fl Fl no-same-owner and the default behavior if .Nm is run as root. .It Fl Fl strip-components Ar count Remove the specified number of leading path elements. Pathnames with fewer elements will be silently skipped. Note that the pathname is edited after checking inclusion/exclusion patterns but before security checks. .It Fl T Ar filename , Fl Fl files-from Ar filename In x or t mode, .Nm will read the list of names to be extracted from .Pa filename . In c mode, .Nm will read names to be archived from .Pa filename . The special name .Dq -C on a line by itself will cause the current directory to be changed to the directory specified on the following line. Names are terminated by newlines unless .Fl Fl null is specified. Note that .Fl Fl null also disables the special handling of lines containing .Dq -C . Note: If you are generating lists of files using .Xr find 1 , you probably want to use .Fl n as well. .It Fl Fl totals (c, r, u modes only) After archiving all files, print a summary to stderr. .It Fl U , Fl Fl unlink , Fl Fl unlink-first (x mode only) Unlink files before creating them. This can be a minor performance optimization if most files already exist, but can make things slower if most files do not already exist. This flag also causes .Nm to remove intervening directory symlinks instead of reporting an error. See the SECURITY section below for more details. .It Fl Fl uid Ar id Use the provided user id number and ignore the user name from the archive. On create, if .Fl Fl uname is not also specified, the user name will be set to match the user id. .It Fl Fl uname Ar name Use the provided user name. On extract, this overrides the user name in the archive; if the provided user name does not exist on the system, it will be ignored and the user id (from the archive or from the .Fl Fl uid option) will be used instead. On create, this sets the user name that will be stored in the archive; the name is not verified against the system user database. .It Fl Fl use-compress-program Ar program Pipe the input (in x or t mode) or the output (in c mode) through .Pa program instead of using the builtin compression support. .It Fl v , Fl Fl verbose Produce verbose output. In create and extract modes, .Nm will list each file name as it is read from or written to the archive. In list mode, .Nm will produce output similar to that of .Xr ls 1 . An additional .Fl v option will also provide ls-like details in create and extract mode. .It Fl Fl version Print version of .Nm and .Nm libarchive , and exit. .It Fl w , Fl Fl confirmation , Fl Fl interactive Ask for confirmation for every action. .It Fl X Ar filename , Fl Fl exclude-from Ar filename Read a list of exclusion patterns from the specified file. See .Fl Fl exclude for more information about the handling of exclusions. .It Fl Fl xattrs (c, r, u, x modes only) Archive or extract extended attributes. This is the reverse of .Fl Fl no-xattrs and the default behavior in c, r, and u modes or if .Nm is run in x mode as root. .It Fl y (c mode only) Compress the resulting archive with .Xr bzip2 1 . In extract or list modes, this option is ignored. Note that, unlike other .Nm tar implementations, this implementation recognizes bzip2 compression automatically when reading archives. .It Fl Z , Fl Fl compress , Fl Fl uncompress (c mode only) Compress the resulting archive with .Xr compress 1 . In extract or list modes, this option is ignored. Note that, unlike other .Nm tar implementations, this implementation recognizes compress compression automatically when reading archives. .It Fl z , Fl Fl gunzip , Fl Fl gzip (c mode only) Compress the resulting archive with .Xr gzip 1 . In extract or list modes, this option is ignored. Note that, unlike other .Nm tar implementations, this implementation recognizes gzip compression automatically when reading archives. .El .Sh ENVIRONMENT The following environment variables affect the execution of .Nm : .Bl -tag -width ".Ev BLOCKSIZE" .It Ev TAR_READER_OPTIONS The default options for format readers and compression readers. The .Fl Fl options option overrides this. .It Ev TAR_WRITER_OPTIONS The default options for format writers and compression writers. The .Fl Fl options option overrides this. .It Ev LANG The locale to use. See .Xr environ 7 for more information. .It Ev TAPE The default device. The .Fl f option overrides this. Please see the description of the .Fl f option above for more details. .It Ev TZ The timezone to use when displaying dates. See .Xr environ 7 for more information. .El .Sh EXIT STATUS .Ex -std .Sh EXAMPLES The following creates a new archive called .Ar file.tar.gz that contains two files .Ar source.c and .Ar source.h : .Dl Nm Fl czf Pa file.tar.gz Pa source.c Pa source.h .Pp To view a detailed table of contents for this archive: .Dl Nm Fl tvf Pa file.tar.gz .Pp To extract all entries from the archive on the default tape drive: .Dl Nm Fl x .Pp To examine the contents of an ISO 9660 cdrom image: .Dl Nm Fl tf Pa image.iso .Pp To move file hierarchies, invoke .Nm as .Dl Nm Fl cf Pa - Fl C Pa srcdir\ . | Nm Fl xpf Pa - Fl C Pa destdir or more traditionally .Dl cd srcdir \&; Nm Fl cf Pa -\ . | ( cd destdir \&; Nm Fl xpf Pa - ) .Pp In create mode, the list of files and directories to be archived can also include directory change instructions of the form .Cm -C Ns Pa foo/baz and archive inclusions of the form .Cm @ Ns Pa archive-file . For example, the command line .Dl Nm Fl c Fl f Pa new.tar Pa foo1 Cm @ Ns Pa old.tgz Cm -C Ns Pa /tmp Pa foo2 will create a new archive .Pa new.tar . .Nm will read the file .Pa foo1 from the current directory and add it to the output archive. It will then read each entry from .Pa old.tgz and add those entries to the output archive. Finally, it will switch to the .Pa /tmp directory and add .Pa foo2 to the output archive. .Pp An input file in .Xr mtree 5 format can be used to create an output archive with arbitrary ownership, permissions, or names that differ from existing data on disk: .Pp .Bd -literal -offset indent $ cat input.mtree #mtree usr/bin uid=0 gid=0 mode=0755 type=dir usr/bin/ls uid=0 gid=0 mode=0755 type=file content=myls $ tar -cvf output.tar @input.mtree .Ed .Pp The .Fl Fl newer and .Fl Fl newer-mtime switches accept a variety of common date and time specifications, including .Dq 12 Mar 2005 7:14:29pm , .Dq 2005-03-12 19:14 , .Dq 5 minutes ago , and .Dq 19:14 PST May 1 . .Pp The .Fl Fl options argument can be used to control various details of archive generation or reading. For example, you can generate mtree output which only contains .Cm type , Cm time , and .Cm uid keywords: .Dl Nm Fl cf Pa file.tar Fl Fl format=mtree Fl Fl options='!all,type,time,uid' Pa dir or you can set the compression level used by gzip or xz compression: .Dl Nm Fl czf Pa file.tar Fl Fl options='compression-level=9' . For more details, see the explanation of the .Fn archive_read_set_options and .Fn archive_write_set_options API calls that are described in .Xr archive_read 3 and .Xr archive_write 3 . .Sh COMPATIBILITY The bundled-arguments format is supported for compatibility with historic implementations. It consists of an initial word (with no leading - character) in which each character indicates an option. Arguments follow as separate words. The order of the arguments must match the order of the corresponding characters in the bundled command word. For example, .Dl Nm Cm tbf 32 Pa file.tar specifies three flags .Cm t , .Cm b , and .Cm f . The .Cm b and .Cm f flags both require arguments, so there must be two additional items on the command line. The .Ar 32 is the argument to the .Cm b flag, and .Ar file.tar is the argument to the .Cm f flag. .Pp The mode options c, r, t, u, and x and the options b, f, l, m, o, v, and w comply with SUSv2. .Pp For maximum portability, scripts that invoke .Nm tar should use the bundled-argument format above, should limit themselves to the .Cm c , .Cm t , and .Cm x modes, and the .Cm b , .Cm f , .Cm m , .Cm v , and .Cm w options. .Pp Additional long options are provided to improve compatibility with other tar implementations. .Sh SECURITY Certain security issues are common to many archiving programs, including .Nm . In particular, carefully-crafted archives can request that .Nm extract files to locations outside of the target directory. This can potentially be used to cause unwitting users to overwrite files they did not intend to overwrite. If the archive is being extracted by the superuser, any file on the system can potentially be overwritten. There are three ways this can happen. Although .Nm has mechanisms to protect against each one, savvy users should be aware of the implications: .Bl -bullet -width indent .It Archive entries can have absolute pathnames. By default, .Nm removes the leading .Pa / character from filenames before restoring them to guard against this problem. .It Archive entries can have pathnames that include .Pa .. components. By default, .Nm will not extract files containing .Pa .. components in their pathname. .It Archive entries can exploit symbolic links to restore files to other directories. An archive can restore a symbolic link to another directory, then use that link to restore a file into that directory. To guard against this, .Nm checks each extracted path for symlinks. If the final path element is a symlink, it will be removed and replaced with the archive entry. If .Fl U is specified, any intermediate symlink will also be unconditionally removed. If neither .Fl U nor .Fl P is specified, .Nm will refuse to extract the entry. .El To protect yourself, you should be wary of any archives that come from untrusted sources. You should examine the contents of an archive with .Dl Nm Fl tf Pa filename before extraction. You should use the .Fl k option to ensure that .Nm will not overwrite any existing files or the .Fl U option to remove any pre-existing files. You should generally not extract archives while running with super-user privileges. Note that the .Fl P option to .Nm disables the security checks above and allows you to extract an archive while preserving any absolute pathnames, .Pa .. components, or symlinks to other directories. .Sh SEE ALSO .Xr bzip2 1 , .Xr compress 1 , .Xr cpio 1 , .Xr gzip 1 , .Xr mt 1 , .Xr pax 1 , .Xr shar 1 , .Xr xz 1 , .Xr libarchive 3 , .Xr libarchive-formats 5 , .Xr tar 5 .Sh STANDARDS There is no current POSIX standard for the tar command; it appeared in .St -p1003.1-96 but was dropped from .St -p1003.1-2001 . The options supported by this implementation were developed by surveying a number of existing tar implementations as well as the old POSIX specification for tar and the current POSIX specification for pax. .Pp The ustar and pax interchange file formats are defined by .St -p1003.1-2001 for the pax command. .Sh HISTORY A .Nm tar command appeared in Seventh Edition Unix, which was released in January, 1979. There have been numerous other implementations, many of which extended the file format. John Gilmore's .Nm pdtar public-domain implementation (circa November, 1987) was quite influential, and formed the basis of GNU tar. GNU tar was included as the standard system tar in .Fx beginning with .Fx 1.0 . .Pp This is a complete re-implementation based on the .Xr libarchive 3 library. It was first released with .Fx 5.4 in May, 2005. .Sh BUGS This program follows .St -p1003.1-96 for the definition of the .Fl l option. Note that GNU tar prior to version 1.15 treated .Fl l as a synonym for the .Fl Fl one-file-system option. .Pp The .Fl C Pa dir option may differ from historic implementations. .Pp All archive output is written in correctly-sized blocks, even if the output is being compressed. Whether or not the last output block is padded to a full block size varies depending on the format and the output device. For tar and cpio formats, the last block of output is padded to a full block size if the output is being written to standard output or to a character or block device such as a tape drive. If the output is being written to a regular file, the last block will not be padded. Many compressors, including .Xr gzip 1 and .Xr bzip2 1 , complain about the null padding when decompressing an archive created by .Nm , although they still extract it correctly. .Pp The compression and decompression is implemented internally, so there may be insignificant differences between the compressed output generated by .Dl Nm Fl czf Pa - file and that generated by .Dl Nm Fl cf Pa - file | Nm gzip .Pp The default should be to read and write archives to the standard I/O paths, but tradition (and POSIX) dictates otherwise. .Pp The .Cm r and .Cm u modes require that the archive be uncompressed and located in a regular file on disk. Other archives can be modified using .Cm c mode with the .Pa @archive-file extension. .Pp To archive a file called .Pa @foo or .Pa -foo you must specify it as .Pa ./@foo or .Pa ./-foo , respectively. .Pp In create mode, a leading .Pa ./ is always removed. A leading .Pa / is stripped unless the .Fl P option is specified. .Pp There needs to be better support for file selection on both create and extract. .Pp There is not yet any support for multi-volume archives. .Pp Converting between dissimilar archive formats (such as tar and cpio) using the .Cm @ Ns Pa - convention can cause hard link information to be lost. (This is a consequence of the incompatible ways that different archive formats store hardlink information.) Index: vendor/libarchive/dist/tar/test/CMakeLists.txt =================================================================== --- vendor/libarchive/dist/tar/test/CMakeLists.txt (revision 315874) +++ vendor/libarchive/dist/tar/test/CMakeLists.txt (revision 315875) @@ -1,121 +1,122 @@ ############################################ # # How to build bsdtar_test # ############################################ IF(ENABLE_TAR AND ENABLE_TEST) SET(bsdtar_test_SOURCES ../../test_utils/test_utils.c ../../test_utils/test_main.c test.h test_0.c test_basic.c test_copy.c test_empty_mtree.c test_extract_tar_Z.c test_extract_tar_bz2.c test_extract_tar_grz.c test_extract_tar_gz.c test_extract_tar_lrz.c test_extract_tar_lz.c test_extract_tar_lz4.c test_extract_tar_lzma.c test_extract_tar_lzo.c test_extract_tar_xz.c test_format_newc.c test_help.c test_leading_slash.c test_missing_file.c test_option_C_upper.c test_option_H_upper.c test_option_L_upper.c test_option_O_upper.c test_option_T_upper.c test_option_U_upper.c test_option_X_upper.c test_option_a.c test_option_acls.c test_option_b.c test_option_b64encode.c test_option_exclude.c test_option_fflags.c test_option_gid_gname.c test_option_grzip.c test_option_j.c test_option_k.c test_option_keep_newer_files.c test_option_lrzip.c test_option_lz4.c test_option_lzma.c test_option_lzop.c test_option_n.c test_option_newer_than.c test_option_nodump.c test_option_older_than.c test_option_passphrase.c test_option_q.c test_option_r.c test_option_s.c test_option_uid_uname.c test_option_uuencode.c + test_option_xattrs.c test_option_xz.c test_option_z.c test_patterns.c test_print_longpath.c test_stdio.c test_strip_components.c test_symlink_dir.c test_version.c test_windows.c ) # # Register target # ADD_EXECUTABLE(bsdtar_test ${bsdtar_test_SOURCES}) IF(ENABLE_ACL) SET(TEST_ACL_LIBS "") IF(HAVE_LIBACL) LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY}) ENDIF(HAVE_LIBACL) IF(HAVE_LIBRICHACL) LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY}) ENDIF(HAVE_LIBRICHACL) TARGET_LINK_LIBRARIES(bsdtar_test ${TEST_ACL_LIBS}) ENDIF(ENABLE_ACL) SET_PROPERTY(TARGET bsdtar_test PROPERTY COMPILE_DEFINITIONS LIST_H) # # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. # GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h ${CMAKE_CURRENT_LIST_FILE} ${bsdtar_test_SOURCES}) SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}) # list.h has a line DEFINE_TEST(testname) for every # test. We can use that to define the tests for cmake by # defining a DEFINE_TEST macro and reading list.h in. MACRO (DEFINE_TEST _testname) ADD_TEST( NAME bsdtar_${_testname} COMMAND bsdtar_test -vv -p $ -r ${CMAKE_CURRENT_SOURCE_DIR} ${_testname}) ENDMACRO (DEFINE_TEST _testname) INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/tar/test) # Experimental new test handling ADD_CUSTOM_TARGET(run_bsdtar_test COMMAND bsdtar_test -p $ -r ${CMAKE_CURRENT_SOURCE_DIR} -vv) ADD_DEPENDENCIES(run_bsdtar_test bsdtar) ADD_DEPENDENCIES(run_all_tests run_bsdtar_test) ENDIF(ENABLE_TAR AND ENABLE_TEST) Index: vendor/libarchive/dist/tar/test/test_option_acls.c =================================================================== --- vendor/libarchive/dist/tar/test/test_option_acls.c (revision 315874) +++ vendor/libarchive/dist/tar/test/test_option_acls.c (revision 315875) @@ -1,469 +1,508 @@ /*- * Copyright (c) 2017 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. */ #include "test.h" __FBSDID("$FreeBSD$"); -#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL +#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBACL static const acl_perm_t acl_perms[] = { -#if HAVE_DARWIN_ACL +#if ARCHIVE_ACL_DARWIN ACL_READ_DATA, ACL_LIST_DIRECTORY, ACL_WRITE_DATA, ACL_ADD_FILE, ACL_EXECUTE, ACL_SEARCH, ACL_DELETE, ACL_APPEND_DATA, ACL_ADD_SUBDIRECTORY, ACL_DELETE_CHILD, ACL_READ_ATTRIBUTES, ACL_WRITE_ATTRIBUTES, ACL_READ_EXTATTRIBUTES, ACL_WRITE_EXTATTRIBUTES, ACL_READ_SECURITY, ACL_WRITE_SECURITY, ACL_CHANGE_OWNER, ACL_SYNCHRONIZE -#else /* !HAVE_DARWIN_ACL */ +#else /* !ARCHIVE_ACL_DARWIN */ ACL_EXECUTE, ACL_WRITE, ACL_READ, -#if HAVE_FREEBSD_NFS4_ACL +#if ARCHIVE_ACL_FREEBSD_NFS4 ACL_READ_DATA, ACL_LIST_DIRECTORY, ACL_WRITE_DATA, ACL_ADD_FILE, ACL_APPEND_DATA, ACL_ADD_SUBDIRECTORY, ACL_READ_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS, ACL_DELETE_CHILD, ACL_READ_ATTRIBUTES, ACL_WRITE_ATTRIBUTES, ACL_DELETE, ACL_READ_ACL, ACL_WRITE_ACL, ACL_WRITE_OWNER, ACL_SYNCHRONIZE -#endif /* HAVE_FREEBSD_NFS4_ACL */ -#endif /* !HAVE_DARWIN_ACL */ +#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */ +#endif /* !ARCHIVE_ACL_DARWIN */ }; -#if HAVE_DARWIN_ACL || HAVE_FREEBSD_NFS4_ACL +#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD_NFS4 static const acl_flag_t acl_flags[] = { -#if HAVE_DARWIN_ACL +#if ARCHIVE_ACL_DARWIN ACL_ENTRY_INHERITED, ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_LIMIT_INHERIT, ACL_ENTRY_ONLY_INHERIT -#else /* HAVE_FREEBSD_NFS4_ACL */ +#else /* ARCHIVE_ACL_FREEBSD_NFS4 */ ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_INHERITED -#endif /* HAVE_FREEBSD_NFS4_ACL */ +#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */ }; -#endif /* HAVE_DARWIN_ACL || HAVE_FREEBSD_NFS4_ACL */ +#endif /* ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD_NFS4 */ /* * Compare two ACL entries on FreeBSD or on Mac OS X */ static int compare_acl_entry(acl_entry_t ae_a, acl_entry_t ae_b, int is_nfs4) { acl_tag_t tag_a, tag_b; acl_permset_t permset_a, permset_b; int perm_a, perm_b, perm_start, perm_end; void *qual_a, *qual_b; -#if HAVE_FREEBSD_NFS4_ACL +#if ARCHIVE_ACL_FREEBSD_NFS4 acl_entry_type_t type_a, type_b; #endif -#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL +#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN acl_flagset_t flagset_a, flagset_b; int flag_a, flag_b; #endif int i, r; /* Compare ACL tag */ r = acl_get_tag_type(ae_a, &tag_a); failure("acl_get_tag_type() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) return (-1); r = acl_get_tag_type(ae_b, &tag_b); failure("acl_get_tag_type() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) return (-1); if (tag_a != tag_b) return (0); /* Compare ACL qualifier */ -#if HAVE_DARWIN_ACL +#if ARCHIVE_ACL_DARWIN if (tag_a == ACL_EXTENDED_ALLOW || tag_b == ACL_EXTENDED_DENY) #else if (tag_a == ACL_USER || tag_a == ACL_GROUP) #endif { qual_a = acl_get_qualifier(ae_a); failure("acl_get_qualifier() error: %s", strerror(errno)); if (assert(qual_a != NULL) == 0) return (-1); qual_b = acl_get_qualifier(ae_b); failure("acl_get_qualifier() error: %s", strerror(errno)); if (assert(qual_b != NULL) == 0) { acl_free(qual_a); return (-1); } -#if HAVE_DARWIN_ACL +#if ARCHIVE_ACL_DARWIN if (memcmp(((guid_t *)qual_a)->g_guid, ((guid_t *)qual_b)->g_guid, KAUTH_GUID_SIZE) != 0) #else if ((tag_a == ACL_USER && (*(uid_t *)qual_a != *(uid_t *)qual_b)) || (tag_a == ACL_GROUP && (*(gid_t *)qual_a != *(gid_t *)qual_b))) #endif { acl_free(qual_a); acl_free(qual_b); return (0); } acl_free(qual_a); acl_free(qual_b); } -#if HAVE_FREEBSD_NFS4_ACL +#if ARCHIVE_ACL_FREEBSD_NFS4 if (is_nfs4) { /* Compare NFS4 ACL type */ r = acl_get_entry_type_np(ae_a, &type_a); failure("acl_get_entry_type_np() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) return (-1); r = acl_get_entry_type_np(ae_b, &type_b); failure("acl_get_entry_type_np() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) return (-1); if (type_a != type_b) return (0); } #endif /* Compare ACL perms */ r = acl_get_permset(ae_a, &permset_a); failure("acl_get_permset() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) return (-1); r = acl_get_permset(ae_b, &permset_b); failure("acl_get_permset() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) return (-1); perm_start = 0; perm_end = (int)(sizeof(acl_perms) / sizeof(acl_perms[0])); -#if HAVE_FREEBSD_NFS4_ACL +#if ARCHIVE_ACL_FREEBSD_NFS4 if (is_nfs4) perm_start = 3; else perm_end = 3; #endif /* Cycle through all perms and compare their value */ for (i = perm_start; i < perm_end; i++) { -#if HAVE_LIBACL +#if ARCHIVE_ACL_LIBACL perm_a = acl_get_perm(permset_a, acl_perms[i]); perm_b = acl_get_perm(permset_b, acl_perms[i]); #else perm_a = acl_get_perm_np(permset_a, acl_perms[i]); perm_b = acl_get_perm_np(permset_b, acl_perms[i]); #endif if (perm_a == -1 || perm_b == -1) return (-1); if (perm_a != perm_b) return (0); } -#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL +#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN if (is_nfs4) { r = acl_get_flagset_np(ae_a, &flagset_a); failure("acl_get_flagset_np() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) return (-1); r = acl_get_flagset_np(ae_b, &flagset_b); failure("acl_get_flagset_np() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) return (-1); /* Cycle through all flags and compare their status */ for (i = 0; i < (int)(sizeof(acl_flags) / sizeof(acl_flags[0])); i++) { flag_a = acl_get_flag_np(flagset_a, acl_flags[i]); flag_b = acl_get_flag_np(flagset_b, acl_flags[i]); if (flag_a == -1 || flag_b == -1) return (-1); if (flag_a != flag_b) return (0); } } -#else /* HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL*/ +#else /* ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_DARWIN */ (void)is_nfs4; /* UNUSED */ #endif return (1); } -#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */ +#endif /* ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBACL */ -#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL +#if ARCHIVE_ACL_SUPPORT /* * Clear default ACLs or inheritance flags */ static void clear_inheritance_flags(const char *path, int type) { switch (type) { case ARCHIVE_TEST_ACL_TYPE_POSIX1E: -#if HAVE_POSIX_ACL +#if ARCHIVE_ACL_POSIX1E +#if !ARCHIVE_ACL_SUNOS acl_delete_def_file(path); #else /* Solaris */ setTestAcl(path); #endif +#endif /* ARCHIVE_ACL_POSIX1E */ break; case ARCHIVE_TEST_ACL_TYPE_NFS4: -#if HAVE_NFS4_ACL +#if ARCHIVE_ACL_NFS4 setTestAcl(path); #endif break; default: (void)path; /* UNUSED */ break; } } static int compare_acls(const char *path_a, const char *path_b) { int ret = 1; int is_nfs4 = 0; -#if HAVE_SUN_ACL +#if ARCHIVE_ACL_SUNOS void *acl_a, *acl_b; int aclcnt_a, aclcnt_b; aclent_t *aclent_a, *aclent_b; ace_t *ace_a, *ace_b; int e; -#else +#elif ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL acl_t acl_a, acl_b; acl_entry_t aclent_a, aclent_b; int a, b, r; #endif +#if ARCHIVE_ACL_LIBRICHACL + struct richacl *richacl_a, *richacl_b; + richacl_a = NULL; + richacl_b = NULL; +#endif + +#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL || \ + ARCHIVE_ACL_SUNOS acl_a = NULL; acl_b = NULL; -#if HAVE_SUN_ACL +#endif +#if ARCHIVE_ACL_SUNOS acl_a = sunacl_get(GETACL, &aclcnt_a, 0, path_a); if (acl_a == NULL) { -#if HAVE_SUN_NFS4_ACL +#if ARCHIVE_ACL_SUNOS_NFS4 is_nfs4 = 1; acl_a = sunacl_get(ACE_GETACL, &aclcnt_a, 0, path_a); #endif failure("acl_get() error: %s", strerror(errno)); if (assert(acl_a != NULL) == 0) return (-1); -#if HAVE_SUN_NFS4_ACL +#if ARCHIVE_ACL_SUNOS_NFS4 acl_b = sunacl_get(ACE_GETACL, &aclcnt_b, 0, path_b); #endif } else acl_b = sunacl_get(GETACL, &aclcnt_b, 0, path_b); if (acl_b == NULL && (errno == ENOSYS || errno == ENOTSUP)) { free(acl_a); return (0); } failure("acl_get() error: %s", strerror(errno)); if (assert(acl_b != NULL) == 0) { free(acl_a); return (-1); } if (aclcnt_a != aclcnt_b) { ret = 0; goto exit_free; } for (e = 0; e < aclcnt_a; e++) { if (!is_nfs4) { aclent_a = &((aclent_t *)acl_a)[e]; aclent_b = &((aclent_t *)acl_b)[e]; if (aclent_a->a_type != aclent_b->a_type || aclent_a->a_id != aclent_b->a_id || aclent_a->a_perm != aclent_b->a_perm) { ret = 0; goto exit_free; } } -#if HAVE_SUN_NFS4_ACL +#if ARCHIVE_ACL_SUNOS_NFS4 else { ace_a = &((ace_t *)acl_a)[e]; ace_b = &((ace_t *)acl_b)[e]; if (ace_a->a_who != ace_b->a_who || ace_a->a_access_mask != ace_b->a_access_mask || ace_a->a_flags != ace_b->a_flags || ace_a->a_type != ace_b->a_type) { ret = 0; goto exit_free; } } #endif } -#else /* !HAVE_SUN_ACL */ -#if HAVE_DARWIN_ACL +#else /* !ARCHIVE_ACL_SUNOS */ +#if ARCHIVE_ACL_LIBRICHACL + richacl_a = richacl_get_file(path_a); +#if !ARCHIVE_ACL_LIBACL + if (richacl_a == NULL && + (errno == ENODATA || errno == ENOTSUP || errno == ENOSYS)) + return (0); + failure("richacl_get_file() error: %s (%s)", path_a, strerror(errno)); + if (assert(richacl_a != NULL) == 0) + return (-1); +#endif + if (richacl_a != NULL) { + richacl_b = richacl_get_file(path_b); + if (richacl_b == NULL && + (errno == ENODATA || errno == ENOTSUP || errno == ENOSYS)) + return (0); + failure("richacl_get_file() error: %s (%s)", path_b, + strerror(errno)); + if (assert(richacl_b != NULL) == 0) { + richacl_free(richacl_a); + return (-1); + } + if (richacl_compare(richacl_a, richacl_b) == 0) + ret = 0; + richacl_free(richacl_a); + richacl_free(richacl_b); + return (ret); + } +#endif /* ARCHIVE_ACL_LIBRICHACL */ +#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL +#if ARCHIVE_ACL_DARWIN is_nfs4 = 1; acl_a = acl_get_file(path_a, ACL_TYPE_EXTENDED); -#elif HAVE_FREEBSD_NFS4_ACL +#elif ARCHIVE_ACL_FREEBSD_NFS4 acl_a = acl_get_file(path_a, ACL_TYPE_NFS4); if (acl_a != NULL) is_nfs4 = 1; #endif -#if !HAVE_DARWIN_ACL if (acl_a == NULL) acl_a = acl_get_file(path_a, ACL_TYPE_ACCESS); -#endif failure("acl_get_file() error: %s (%s)", path_a, strerror(errno)); if (assert(acl_a != NULL) == 0) return (-1); -#if HAVE_DARWIN_ACL +#if ARCHIVE_ACL_DARWIN acl_b = acl_get_file(path_b, ACL_TYPE_EXTENDED); -#elif HAVE_FREEBSD_NFS4_ACL +#elif ARCHIVE_ACL_FREEBSD_NFS4 acl_b = acl_get_file(path_b, ACL_TYPE_NFS4); #endif -#if !HAVE_DARWIN_ACL +#if !ARCHIVE_ACL_DARWIN if (acl_b == NULL) { -#if HAVE_FREEBSD_NFS4_ACL +#if ARCHIVE_ACL_FREEBSD_NFS4 if (is_nfs4) { acl_free(acl_a); return (0); } #endif acl_b = acl_get_file(path_b, ACL_TYPE_ACCESS); } failure("acl_get_file() error: %s (%s)", path_b, strerror(errno)); if (assert(acl_b != NULL) == 0) { acl_free(acl_a); return (-1); } #endif a = acl_get_entry(acl_a, ACL_FIRST_ENTRY, &aclent_a); if (a == -1) { ret = 0; goto exit_free; } b = acl_get_entry(acl_b, ACL_FIRST_ENTRY, &aclent_b); if (b == -1) { ret = 0; goto exit_free; } -#if HAVE_DARWIN_ACL +#if ARCHIVE_ACL_DARWIN while (a == 0 && b == 0) #else /* FreeBSD, Linux */ while (a == 1 && b == 1) #endif { r = compare_acl_entry(aclent_a, aclent_b, is_nfs4); if (r != 1) { ret = r; goto exit_free; } a = acl_get_entry(acl_a, ACL_NEXT_ENTRY, &aclent_a); b = acl_get_entry(acl_b, ACL_NEXT_ENTRY, &aclent_b); } /* Entry count must match */ if (a != b) ret = 0; -#endif /* !HAVE_SUN_ACL */ +#endif /* ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL */ +#endif /* !ARCHIVE_ACL_SUNOS */ exit_free: -#if HAVE_SUN_ACL +#if ARCHIVE_ACL_SUNOS free(acl_a); free(acl_b); #else acl_free(acl_a); acl_free(acl_b); #endif return (ret); } -#endif /* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */ +#endif /* ARCHIVE_ACL_SUPPORT */ DEFINE_TEST(test_option_acls) { -#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_POSIX_ACL +#if !ARCHIVE_ACL_SUPPORT skipping("ACLs are not supported on this platform"); -#else /* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */ +#else /* ARCHIVE_ACL_SUPPORT */ int acltype, r; assertMakeFile("f", 0644, "a"); acltype = setTestAcl("f"); if (acltype == 0) { skipping("Can't write ACLs on the filesystem"); return; } /* Archive it with acls */ r = systemf("%s -c --no-mac-metadata --acls -f acls.tar f >acls.out 2>acls.err", testprog); assertEqualInt(r, 0); /* Archive it without acls */ r = systemf("%s -c --no-mac-metadata --no-acls -f noacls.tar f >noacls.out 2>noacls.err", testprog); assertEqualInt(r, 0); /* Extract acls with acls */ assertMakeDir("acls_acls", 0755); clear_inheritance_flags("acls_acls", acltype); r = systemf("%s -x -C acls_acls --no-same-permissions --acls -f acls.tar >acls_acls.out 2>acls_acls.err", testprog); assertEqualInt(r, 0); r = compare_acls("f", "acls_acls/f"); assertEqualInt(r, 1); /* Extractl acls without acls */ assertMakeDir("acls_noacls", 0755); clear_inheritance_flags("acls_noacls", acltype); r = systemf("%s -x -C acls_noacls -p --no-acls -f acls.tar >acls_noacls.out 2>acls_noacls.err", testprog); assertEqualInt(r, 0); r = compare_acls("f", "acls_noacls/f"); assertEqualInt(r, 0); /* Extract noacls with acls flag */ assertMakeDir("noacls_acls", 0755); clear_inheritance_flags("noacls_acls", acltype); r = systemf("%s -x -C noacls_acls --no-same-permissions --acls -f noacls.tar >noacls_acls.out 2>noacls_acls.err", testprog); assertEqualInt(r, 0); r = compare_acls("f", "noacls_acls/f"); assertEqualInt(r, 0); /* Extract noacls with noacls */ assertMakeDir("noacls_noacls", 0755); clear_inheritance_flags("noacls_noacls", acltype); r = systemf("%s -x -C noacls_noacls -p --no-acls -f noacls.tar >noacls_noacls.out 2>noacls_noacls.err", testprog); assertEqualInt(r, 0); r = compare_acls("f", "noacls_noacls/f"); assertEqualInt(r, 0); -#endif /* HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_POSIX_ACL */ +#endif /* ARCHIVE_ACL_SUPPORT */ } Index: vendor/libarchive/dist/tar/test/test_option_xattrs.c =================================================================== --- vendor/libarchive/dist/tar/test/test_option_xattrs.c (nonexistent) +++ vendor/libarchive/dist/tar/test/test_option_xattrs.c (revision 315875) @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2017 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. + */ +#include "test.h" +__FBSDID("$FreeBSD$"); + +DEFINE_TEST(test_option_xattrs) +{ +#if !ARCHIVE_XATTR_SUPPORT + skipping("Extended atributes are not supported on this platform"); +#else /* ARCHIVE_XATTR_SUPPORT */ + + const char *testattr = "user.libarchive.test"; + const char *testval = "testval"; + const void *readval; + size_t size; + int r; + + /* Create a file. */ + assertMakeFile("f", 0644, "a"); + + if (!setXattr("f", "user.libarchive.test", testval, + strlen(testval) + 1)) { + skipping("Can't set user extended attributes on this " + "filesystem"); + return; + } + + /* Archive with xattrs */ + r = systemf("%s -c --no-mac-metadata --xattrs -f xattrs.tar f >xattrs.out 2>xattrs.err", testprog); + assertEqualInt(r, 0); + + /* Archive without xattrs */ + r = systemf("%s -c --no-mac-metadata --no-xattrs -f noxattrs.tar f >noxattrs.out 2>noxattrs.err", testprog); + assertEqualInt(r, 0); + + /* Extract xattrs with xattrs */ + assertMakeDir("xattrs_xattrs", 0755); + r = systemf("%s -x -C xattrs_xattrs --no-same-permissions --xattrs -f xattrs.tar >xattrs_xattrs.out 2>xattrs_xattrs.err", testprog); + assertEqualInt(r, 0); + readval = getXattr("xattrs_xattrs/f", testattr, &size); + if(assertEqualInt(size, strlen(testval) + 1) != 0) + assertEqualMem(readval, testval, size); + + /* Extract xattrs without xattrs */ + assertMakeDir("xattrs_noxattrs", 0755); + r = systemf("%s -x -C xattrs_noxattrs -p --no-xattrs -f xattrs.tar >xattrs_noxattrs.out 2>xattrs_noxattrs.err", testprog); + assertEqualInt(r, 0); + readval = getXattr("xattrs_noxattrs/f", testattr, &size); + assert(readval == NULL); + + /* Extract noxattrs with xattrs */ + assertMakeDir("noxattrs_xattrs", 0755); + r = systemf("%s -x -C noxattrs_xattrs --no-same-permissions --xattrs -f noxattrs.tar >noxattrs_xattrs.out 2>noxattrs_xattrs.err", testprog); + assertEqualInt(r, 0); + readval = getXattr("noxattrs_xattrs/f", testattr, &size); + assert(readval == NULL); + + /* Extract noxattrs with noxattrs */ + assertMakeDir("noxattrs_noxattrs", 0755); + r = systemf("%s -x -C noxattrs_noxattrs -p --no-xattrs -f noxattrs.tar >noxattrs_noxattrs.out 2>noxattrs_noxattrs.err", testprog); + assertEqualInt(r, 0); + readval = getXattr("noxattrs_noxattrs/f", testattr, &size); + assert(readval == NULL); +#endif /* ARCHIVE_XATTR_SUPPORT */ +} Property changes on: vendor/libarchive/dist/tar/test/test_option_xattrs.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/libarchive/dist/test_utils/test_common.h =================================================================== --- vendor/libarchive/dist/test_utils/test_common.h (revision 315874) +++ vendor/libarchive/dist/test_utils/test_common.h (revision 315875) @@ -1,435 +1,445 @@ /* * Copyright (c) 2003-2017 Tim Kientzle * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef TEST_COMMON_H #define TEST_COMMON_H /* * The goal of this file (and the matching test.c) is to * simplify the very repetitive test-*.c test programs. */ #if defined(HAVE_CONFIG_H) /* Most POSIX platforms use the 'configure' script to build config.h */ #include "config.h" #elif defined(__FreeBSD__) /* Building as part of FreeBSD system requires a pre-built config.h. */ #include "config_freebsd.h" #elif defined(_WIN32) && !defined(__CYGWIN__) /* Win32 can't run the 'configure' script. */ #include "config_windows.h" #else /* Warn if the library hasn't been (automatically or manually) configured. */ #error Oops: No config.h and no pre-built configuration in test.h. #endif #include /* Windows requires this before sys/stat.h */ #include #if HAVE_DIRENT_H #include #endif #ifdef HAVE_DIRECT_H #include #define dirent direct #endif #include #include #ifdef HAVE_IO_H #include #endif #ifdef HAVE_STDINT_H #include #endif #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #ifdef HAVE_ACL_LIBACL_H #include #endif #ifdef HAVE_SYS_ACL_H #include #endif +#ifdef HAVE_SYS_RICHACL_H +#include +#endif #ifdef HAVE_WINDOWS_H #include #endif /* * System-specific tweaks. We really want to minimize these * as much as possible, since they make it harder to understand * the mainline code. */ /* Windows (including Visual Studio and MinGW but not Cygwin) */ #if defined(_WIN32) && !defined(__CYGWIN__) #if !defined(__BORLANDC__) #undef chdir #define chdir _chdir #define strdup _strdup #endif #endif /* Visual Studio */ #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf sprintf_s #endif #if defined(__BORLANDC__) #pragma warn -8068 /* Constant out of range in comparison. */ #endif /* Haiku OS and QNX */ #if defined(__HAIKU__) || defined(__QNXNTO__) /* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */ #include #endif /* Get a real definition for __FBSDID if we can */ #if HAVE_SYS_CDEFS_H #include #endif /* If not, define it so as to avoid dangling semicolons. */ #ifndef __FBSDID #define __FBSDID(a) struct _undefined_hack #endif #ifndef O_BINARY #define O_BINARY 0 #endif #include "archive_platform_acl.h" #define ARCHIVE_TEST_ACL_TYPE_POSIX1E 1 #define ARCHIVE_TEST_ACL_TYPE_NFS4 2 +#include "archive_platform_xattr.h" /* * Redefine DEFINE_TEST for use in defining the test functions. */ #undef DEFINE_TEST #define DEFINE_TEST(name) void name(void); void name(void) /* An implementation of the standard assert() macro */ #define assert(e) assertion_assert(__FILE__, __LINE__, (e), #e, NULL) /* chdir() and error if it fails */ #define assertChdir(path) \ assertion_chdir(__FILE__, __LINE__, path) /* Assert two files have the same file flags */ #define assertEqualFflags(patha, pathb) \ assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 0) /* Assert two integers are the same. Reports value of each one if not. */ #define assertEqualInt(v1,v2) \ assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) /* Assert two strings are the same. Reports value of each one if not. */ #define assertEqualString(v1,v2) \ assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 0) #define assertEqualUTF8String(v1,v2) \ assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL, 1) /* As above, but v1 and v2 are wchar_t * */ #define assertEqualWString(v1,v2) \ assertion_equal_wstring(__FILE__, __LINE__, (v1), #v1, (v2), #v2, NULL) /* As above, but raw blocks of bytes. */ #define assertEqualMem(v1, v2, l) \ assertion_equal_mem(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (l), #l, NULL) /* Assert that memory is full of a specified byte */ #define assertMemoryFilledWith(v1, l, b) \ assertion_memory_filled_with(__FILE__, __LINE__, (v1), #v1, (l), #l, (b), #b, NULL) /* Assert two files are the same. */ #define assertEqualFile(f1, f2) \ assertion_equal_file(__FILE__, __LINE__, (f1), (f2)) /* Assert that a file is empty. */ #define assertEmptyFile(pathname) \ assertion_empty_file(__FILE__, __LINE__, (pathname)) /* Assert that a file is not empty. */ #define assertNonEmptyFile(pathname) \ assertion_non_empty_file(__FILE__, __LINE__, (pathname)) #define assertFileAtime(pathname, sec, nsec) \ assertion_file_atime(__FILE__, __LINE__, pathname, sec, nsec) #define assertFileAtimeRecent(pathname) \ assertion_file_atime_recent(__FILE__, __LINE__, pathname) #define assertFileBirthtime(pathname, sec, nsec) \ assertion_file_birthtime(__FILE__, __LINE__, pathname, sec, nsec) #define assertFileBirthtimeRecent(pathname) \ assertion_file_birthtime_recent(__FILE__, __LINE__, pathname) /* Assert that a file exists; supports printf-style arguments. */ #define assertFileExists(pathname) \ assertion_file_exists(__FILE__, __LINE__, pathname) /* Assert that a file exists. */ #define assertFileNotExists(pathname) \ assertion_file_not_exists(__FILE__, __LINE__, pathname) /* Assert that file contents match a string. */ #define assertFileContents(data, data_size, pathname) \ assertion_file_contents(__FILE__, __LINE__, data, data_size, pathname) /* Verify that a file does not contain invalid strings */ #define assertFileContainsNoInvalidStrings(pathname, strings) \ assertion_file_contains_no_invalid_strings(__FILE__, __LINE__, pathname, strings) #define assertFileMtime(pathname, sec, nsec) \ assertion_file_mtime(__FILE__, __LINE__, pathname, sec, nsec) #define assertFileMtimeRecent(pathname) \ assertion_file_mtime_recent(__FILE__, __LINE__, pathname) #define assertFileNLinks(pathname, nlinks) \ assertion_file_nlinks(__FILE__, __LINE__, pathname, nlinks) #define assertFileSize(pathname, size) \ assertion_file_size(__FILE__, __LINE__, pathname, size) #define assertFileMode(pathname, mode) \ assertion_file_mode(__FILE__, __LINE__, pathname, mode) #define assertTextFileContents(text, pathname) \ assertion_text_file_contents(__FILE__, __LINE__, text, pathname) #define assertFileContainsLinesAnyOrder(pathname, lines) \ assertion_file_contains_lines_any_order(__FILE__, __LINE__, pathname, lines) #define assertIsDir(pathname, mode) \ assertion_is_dir(__FILE__, __LINE__, pathname, mode) #define assertIsHardlink(path1, path2) \ assertion_is_hardlink(__FILE__, __LINE__, path1, path2) #define assertIsNotHardlink(path1, path2) \ assertion_is_not_hardlink(__FILE__, __LINE__, path1, path2) #define assertIsReg(pathname, mode) \ assertion_is_reg(__FILE__, __LINE__, pathname, mode) #define assertIsSymlink(pathname, contents) \ assertion_is_symlink(__FILE__, __LINE__, pathname, contents) /* Create a directory, report error if it fails. */ #define assertMakeDir(dirname, mode) \ assertion_make_dir(__FILE__, __LINE__, dirname, mode) #define assertMakeFile(path, mode, contents) \ assertion_make_file(__FILE__, __LINE__, path, mode, -1, contents) #define assertMakeBinFile(path, mode, csize, contents) \ assertion_make_file(__FILE__, __LINE__, path, mode, csize, contents) #define assertMakeHardlink(newfile, oldfile) \ assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile) #define assertMakeSymlink(newfile, linkto) \ assertion_make_symlink(__FILE__, __LINE__, newfile, linkto) #define assertSetNodump(path) \ assertion_set_nodump(__FILE__, __LINE__, path) #define assertUmask(mask) \ assertion_umask(__FILE__, __LINE__, mask) /* Assert that two files have unequal file flags */ #define assertUnequalFflags(patha, pathb) \ assertion_compare_fflags(__FILE__, __LINE__, patha, pathb, 1) #define assertUtimes(pathname, atime, atime_nsec, mtime, mtime_nsec) \ assertion_utimes(__FILE__, __LINE__, pathname, atime, atime_nsec, mtime, mtime_nsec) #ifndef PROGRAM #define assertEntrySetAcls(entry, acls, count) \ assertion_entry_set_acls(__FILE__, __LINE__, entry, acls, count) #define assertEntryCompareAcls(entry, acls, count, type, mode) \ assertion_entry_compare_acls(__FILE__, __LINE__, entry, acls, count, type, mode) #endif /* * This would be simple with C99 variadic macros, but I don't want to * require that. Instead, I insert a function call before each * skipping() call to pass the file and line information down. Crude, * but effective. */ #define skipping \ skipping_setup(__FILE__, __LINE__);test_skipping /* Function declarations. These are defined in test_utility.c. */ void failure(const char *fmt, ...); int assertion_assert(const char *, int, int, const char *, void *); int assertion_chdir(const char *, int, const char *); int assertion_compare_fflags(const char *, int, const char *, const char *, int); int assertion_empty_file(const char *, int, const char *); int assertion_equal_file(const char *, int, const char *, const char *); int assertion_equal_int(const char *, int, long long, const char *, long long, const char *, void *); int assertion_equal_mem(const char *, int, const void *, const char *, const void *, const char *, size_t, const char *, void *); int assertion_memory_filled_with(const char *, int, const void *, const char *, size_t, const char *, char, const char *, void *); int assertion_equal_string(const char *, int, const char *v1, const char *, const char *v2, const char *, void *, int); int assertion_equal_wstring(const char *, int, const wchar_t *v1, const char *, const wchar_t *v2, const char *, void *); int assertion_file_atime(const char *, int, const char *, long, long); int assertion_file_atime_recent(const char *, int, const char *); int assertion_file_birthtime(const char *, int, const char *, long, long); int assertion_file_birthtime_recent(const char *, int, const char *); int assertion_file_contains_lines_any_order(const char *, int, const char *, const char **); int assertion_file_contains_no_invalid_strings(const char *, int, const char *, const char **); int assertion_file_contents(const char *, int, const void *, int, const char *); int assertion_file_exists(const char *, int, const char *); int assertion_file_mode(const char *, int, const char *, int); int assertion_file_mtime(const char *, int, const char *, long, long); int assertion_file_mtime_recent(const char *, int, const char *); int assertion_file_nlinks(const char *, int, const char *, int); int assertion_file_not_exists(const char *, int, const char *); int assertion_file_size(const char *, int, const char *, long); int assertion_is_dir(const char *, int, const char *, int); int assertion_is_hardlink(const char *, int, const char *, const char *); int assertion_is_not_hardlink(const char *, int, const char *, const char *); int assertion_is_reg(const char *, int, const char *, int); int assertion_is_symlink(const char *, int, const char *, const char *); int assertion_make_dir(const char *, int, const char *, int); int assertion_make_file(const char *, int, const char *, int, int, const void *); int assertion_make_hardlink(const char *, int, const char *newpath, const char *); int assertion_make_symlink(const char *, int, const char *newpath, const char *); int assertion_non_empty_file(const char *, int, const char *); int assertion_set_nodump(const char *, int, const char *); int assertion_text_file_contents(const char *, int, const char *buff, const char *f); int assertion_umask(const char *, int, int); int assertion_utimes(const char *, int, const char *, long, long, long, long ); int assertion_version(const char*, int, const char *, const char *); void skipping_setup(const char *, int); void test_skipping(const char *fmt, ...); /* Like sprintf, then system() */ int systemf(const char * fmt, ...); /* Delay until time() returns a value after this. */ void sleepUntilAfter(time_t); /* Return true if this platform can create symlinks. */ int canSymlink(void); /* Return true if this platform can run the "bzip2" program. */ int canBzip2(void); /* Return true if this platform can run the "grzip" program. */ int canGrzip(void); /* Return true if this platform can run the "gzip" program. */ int canGzip(void); /* Return true if this platform can run the specified command. */ int canRunCommand(const char *); /* Return true if this platform can run the "lrzip" program. */ int canLrzip(void); /* Return true if this platform can run the "lz4" program. */ int canLz4(void); /* Return true if this platform can run the "lzip" program. */ int canLzip(void); /* Return true if this platform can run the "lzma" program. */ int canLzma(void); /* Return true if this platform can run the "lzop" program. */ int canLzop(void); /* Return true if this platform can run the "xz" program. */ int canXz(void); /* Return true if this filesystem can handle nodump flags. */ int canNodump(void); /* Set test ACLs */ int setTestAcl(const char *path); + +/* Get extended attribute */ +const void *getXattr(const char *, const char *, size_t *); + +/* Set extended attribute */ +int setXattr(const char *, const char *, const void *, size_t); /* Return true if the file has large i-node number(>0xffffffff). */ int is_LargeInode(const char *); #if ARCHIVE_ACL_SUNOS /* Fetch ACLs on Solaris using acl() or facl() */ void *sunacl_get(int cmd, int *aclcnt, int fd, const char *path); #endif /* Suck file into string allocated via malloc(). Call free() when done. */ /* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */ char *slurpfile(size_t *, const char *fmt, ...); /* Dump block of bytes to a file. */ void dumpfile(const char *filename, void *, size_t); /* Extracts named reference file to the current directory. */ void extract_reference_file(const char *); /* Copies named reference file to the current directory. */ void copy_reference_file(const char *); /* Extracts a list of files to the current directory. * List must be NULL terminated. */ void extract_reference_files(const char **); /* Subtract umask from mode */ mode_t umasked(mode_t expected_mode); /* Path to working directory for current test */ extern const char *testworkdir; #ifndef PROGRAM /* * Special interfaces for libarchive test harness. */ #include "archive.h" #include "archive_entry.h" /* ACL structure */ struct archive_test_acl_t { int type; /* Type of ACL */ int permset; /* Permissions for this class of users. */ int tag; /* Owner, User, Owning group, group, other, etc. */ int qual; /* GID or UID of user/group, depending on tag. */ const char *name; /* Name of user/group, depending on tag. */ }; /* Set ACLs */ int assertion_entry_set_acls(const char *, int, struct archive_entry *, struct archive_test_acl_t *, int); /* Compare ACLs */ int assertion_entry_compare_acls(const char *, int, struct archive_entry *, struct archive_test_acl_t *, int, int, int); /* Special customized read-from-memory interface. */ int read_open_memory(struct archive *, const void *, size_t, size_t); /* _minimal version exercises a slightly different set of libarchive APIs. */ int read_open_memory_minimal(struct archive *, const void *, size_t, size_t); /* _seek version produces a seekable file. */ int read_open_memory_seek(struct archive *, const void *, size_t, size_t); /* Versions of above that accept an archive argument for additional info. */ #define assertA(e) assertion_assert(__FILE__, __LINE__, (e), #e, (a)) #define assertEqualIntA(a,v1,v2) \ assertion_equal_int(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a)) #define assertEqualStringA(a,v1,v2) \ assertion_equal_string(__FILE__, __LINE__, (v1), #v1, (v2), #v2, (a), 0) #else /* defined(PROGRAM) */ /* * Special interfaces for program test harness. */ /* Pathname of exe to be tested. */ extern const char *testprogfile; /* Name of exe to use in printf-formatted command strings. */ /* On Windows, this includes leading/trailing quotes. */ extern const char *testprog; void assertVersion(const char *prog, const char *base); #endif /* defined(PROGRAM) */ #ifdef USE_DMALLOC #include #endif #endif /* TEST_COMMON_H */ Index: vendor/libarchive/dist/test_utils/test_main.c =================================================================== --- vendor/libarchive/dist/test_utils/test_main.c (revision 315874) +++ vendor/libarchive/dist/test_utils/test_main.c (revision 315875) @@ -1,3744 +1,3832 @@ /* * Copyright (c) 2003-2009 Tim Kientzle * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test.h" #include "test_utils.h" #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #include #ifdef HAVE_ICONV_H #include #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 /* for Linux file flags */ #endif #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) #include /* Linux file flags, broken on Cygwin */ #endif #ifdef HAVE_LINUX_FS_H #include #endif #include #include #ifdef HAVE_SIGNAL_H #include #endif #include #include #ifdef HAVE_SIGNAL_H #endif #ifdef HAVE_ACL_LIBACL_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_ACL_H #include #endif +#ifdef HAVE_SYS_EA_H +#include +#endif +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif +#if HAVE_SYS_XATTR_H +#include +#elif HAVE_ATTR_XATTR_H +#include +#endif #ifdef HAVE_SYS_RICHACL_H #include #endif #if HAVE_MEMBERSHIP_H #include #endif /* * * Windows support routines * * Note: Configuration is a tricky issue. Using HAVE_* feature macros * in the test harness is dangerous because they cover up * configuration errors. The classic example of this is omitting a * configure check. If libarchive and libarchive_test both look for * the same feature macro, such errors are hard to detect. Platform * macros (e.g., _WIN32 or __GNUC__) are a little better, but can * easily lead to very messy code. It's best to limit yourself * to only the most generic programming techniques in the test harness * and thus avoid conditionals altogether. Where that's not possible, * try to minimize conditionals by grouping platform-specific tests in * one place (e.g., test_acl_freebsd) or by adding new assert() * functions (e.g., assertMakeHardlink()) to cover up platform * differences. Platform-specific coding in libarchive_test is often * a symptom that some capability is missing from libarchive itself. */ #if defined(_WIN32) && !defined(__CYGWIN__) #include #include #include #ifndef F_OK #define F_OK (0) #endif #ifndef S_ISDIR #define S_ISDIR(m) ((m) & _S_IFDIR) #endif #ifndef S_ISREG #define S_ISREG(m) ((m) & _S_IFREG) #endif #if !defined(__BORLANDC__) #define access _access #undef chdir #define chdir _chdir #endif #ifndef fileno #define fileno _fileno #endif /*#define fstat _fstat64*/ #if !defined(__BORLANDC__) #define getcwd _getcwd #endif #define lstat stat /*#define lstat _stat64*/ /*#define stat _stat64*/ #define rmdir _rmdir #if !defined(__BORLANDC__) #define strdup _strdup #define umask _umask #endif #define int64_t __int64 #endif #if defined(HAVE__CrtSetReportMode) # include #endif mode_t umasked(mode_t expected_mode) { mode_t mode = umask(0); umask(mode); return expected_mode & ~mode; } /* Path to working directory for current test */ const char *testworkdir; #ifdef PROGRAM /* Pathname of exe to be tested. */ const char *testprogfile; /* Name of exe to use in printf-formatted command strings. */ /* On Windows, this includes leading/trailing quotes. */ const char *testprog; #endif #if defined(_WIN32) && !defined(__CYGWIN__) static void *GetFunctionKernel32(const char *); static int my_CreateSymbolicLinkA(const char *, const char *, int); static int my_CreateHardLinkA(const char *, const char *); static int my_GetFileInformationByName(const char *, BY_HANDLE_FILE_INFORMATION *); static void * GetFunctionKernel32(const char *name) { static HINSTANCE lib; static int set; if (!set) { set = 1; lib = LoadLibrary("kernel32.dll"); } if (lib == NULL) { fprintf(stderr, "Can't load kernel32.dll?!\n"); exit(1); } return (void *)GetProcAddress(lib, name); } static int my_CreateSymbolicLinkA(const char *linkname, const char *target, int flags) { static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, DWORD); static int set; if (!set) { set = 1; f = GetFunctionKernel32("CreateSymbolicLinkA"); } return f == NULL ? 0 : (*f)(linkname, target, flags); } static int my_CreateHardLinkA(const char *linkname, const char *target) { static BOOLEAN (WINAPI *f)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES); static int set; if (!set) { set = 1; f = GetFunctionKernel32("CreateHardLinkA"); } return f == NULL ? 0 : (*f)(linkname, target, NULL); } static int my_GetFileInformationByName(const char *path, BY_HANDLE_FILE_INFORMATION *bhfi) { HANDLE h; int r; memset(bhfi, 0, sizeof(*bhfi)); h = CreateFile(path, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (h == INVALID_HANDLE_VALUE) return (0); r = GetFileInformationByHandle(h, bhfi); CloseHandle(h); return (r); } #endif #if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__) static void invalid_parameter_handler(const wchar_t * expression, const wchar_t * function, const wchar_t * file, unsigned int line, uintptr_t pReserved) { /* nop */ // Silence unused-parameter compiler warnings. (void)expression; (void)function; (void)file; (void)line; (void)pReserved; } #endif /* * * OPTIONS FLAGS * */ /* Enable core dump on failure. */ static int dump_on_failure = 0; /* Default is to remove temp dirs and log data for successful tests. */ static int keep_temp_files = 0; /* Default is to run the specified tests once and report errors. */ static int until_failure = 0; /* Default is to just report pass/fail for each test. */ static int verbosity = 0; #define VERBOSITY_SUMMARY_ONLY -1 /* -q */ #define VERBOSITY_PASSFAIL 0 /* Default */ #define VERBOSITY_LIGHT_REPORT 1 /* -v */ #define VERBOSITY_FULL 2 /* -vv */ /* A few places generate even more output for verbosity > VERBOSITY_FULL, * mostly for debugging the test harness itself. */ /* Cumulative count of assertion failures. */ static int failures = 0; /* Cumulative count of reported skips. */ static int skips = 0; /* Cumulative count of assertions checked. */ static int assertions = 0; /* Directory where uuencoded reference files can be found. */ static const char *refdir; /* * Report log information selectively to console and/or disk log. */ static int log_console = 0; static FILE *logfile; static void vlogprintf(const char *fmt, va_list ap) { #ifdef va_copy va_list lfap; va_copy(lfap, ap); #endif if (log_console) vfprintf(stdout, fmt, ap); if (logfile != NULL) #ifdef va_copy vfprintf(logfile, fmt, lfap); va_end(lfap); #else vfprintf(logfile, fmt, ap); #endif } static void logprintf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vlogprintf(fmt, ap); va_end(ap); } /* Set up a message to display only if next assertion fails. */ static char msgbuff[4096]; static const char *msg, *nextmsg; void failure(const char *fmt, ...) { va_list ap; if (fmt == NULL) { nextmsg = NULL; } else { va_start(ap, fmt); vsprintf(msgbuff, fmt, ap); va_end(ap); nextmsg = msgbuff; } } /* * Copy arguments into file-local variables. * This was added to permit vararg assert() functions without needing * variadic wrapper macros. Turns out that the vararg capability is almost * never used, so almost all of the vararg assertions can be simplified * by removing the vararg capability and reworking the wrapper macro to * pass __FILE__, __LINE__ directly into the function instead of using * this hook. I suspect this machinery is used so rarely that we * would be better off just removing it entirely. That would simplify * the code here noticeably. */ static const char *skipping_filename; static int skipping_line; void skipping_setup(const char *filename, int line) { skipping_filename = filename; skipping_line = line; } /* Called at the beginning of each assert() function. */ static void assertion_count(const char *file, int line) { (void)file; /* UNUSED */ (void)line; /* UNUSED */ ++assertions; /* Proper handling of "failure()" message. */ msg = nextmsg; nextmsg = NULL; /* Uncomment to print file:line after every assertion. * Verbose, but occasionally useful in tracking down crashes. */ /* printf("Checked %s:%d\n", file, line); */ } /* * For each test source file, we remember how many times each * assertion was reported. Cleared before each new test, * used by test_summarize(). */ static struct line { int count; int skip; } failed_lines[10000]; const char *failed_filename; /* Count this failure, setup up log destination and handle initial report. */ static void failure_start(const char *filename, int line, const char *fmt, ...) { va_list ap; /* Record another failure for this line. */ ++failures; failed_filename = filename; failed_lines[line].count++; /* Determine whether to log header to console. */ switch (verbosity) { case VERBOSITY_LIGHT_REPORT: log_console = (failed_lines[line].count < 2); break; default: log_console = (verbosity >= VERBOSITY_FULL); } /* Log file:line header for this failure */ va_start(ap, fmt); #if _MSC_VER logprintf("%s(%d): ", filename, line); #else logprintf("%s:%d: ", filename, line); #endif vlogprintf(fmt, ap); va_end(ap); logprintf("\n"); if (msg != NULL && msg[0] != '\0') { logprintf(" Description: %s\n", msg); msg = NULL; } /* Determine whether to log details to console. */ if (verbosity == VERBOSITY_LIGHT_REPORT) log_console = 0; } /* Complete reporting of failed tests. */ /* * The 'extra' hook here is used by libarchive to include libarchive * error messages with assertion failures. It could also be used * to add strerror() output, for example. Just define the EXTRA_DUMP() * macro appropriately. */ static void failure_finish(void *extra) { (void)extra; /* UNUSED (maybe) */ #ifdef EXTRA_DUMP if (extra != NULL) { logprintf(" errno: %d\n", EXTRA_ERRNO(extra)); logprintf(" detail: %s\n", EXTRA_DUMP(extra)); } #endif if (dump_on_failure) { fprintf(stderr, " *** forcing core dump so failure can be debugged ***\n"); abort(); } } /* Inform user that we're skipping some checks. */ void test_skipping(const char *fmt, ...) { char buff[1024]; va_list ap; va_start(ap, fmt); vsprintf(buff, fmt, ap); va_end(ap); /* Use failure() message if set. */ msg = nextmsg; nextmsg = NULL; /* failure_start() isn't quite right, but is awfully convenient. */ failure_start(skipping_filename, skipping_line, "SKIPPING: %s", buff); --failures; /* Undo failures++ in failure_start() */ /* Don't failure_finish() here. */ /* Mark as skip, so doesn't count as failed test. */ failed_lines[skipping_line].skip = 1; ++skips; } /* * * ASSERTIONS * */ /* Generic assert() just displays the failed condition. */ int assertion_assert(const char *file, int line, int value, const char *condition, void *extra) { assertion_count(file, line); if (!value) { failure_start(file, line, "Assertion failed: %s", condition); failure_finish(extra); } return (value); } /* chdir() and report any errors */ int assertion_chdir(const char *file, int line, const char *pathname) { assertion_count(file, line); if (chdir(pathname) == 0) return (1); failure_start(file, line, "chdir(\"%s\")", pathname); failure_finish(NULL); return (0); } /* Verify two integers are equal. */ int assertion_equal_int(const char *file, int line, long long v1, const char *e1, long long v2, const char *e2, void *extra) { assertion_count(file, line); if (v1 == v2) return (1); failure_start(file, line, "%s != %s", e1, e2); logprintf(" %s=%lld (0x%llx, 0%llo)\n", e1, v1, v1, v1); logprintf(" %s=%lld (0x%llx, 0%llo)\n", e2, v2, v2, v2); failure_finish(extra); return (0); } /* * Utility to convert a single UTF-8 sequence. */ static int _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) { static const char utf8_count[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 00 - 0F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 10 - 1F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20 - 2F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30 - 3F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40 - 4F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 50 - 5F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60 - 6F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 70 - 7F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 80 - 8F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 90 - 9F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* A0 - AF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* B0 - BF */ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* C0 - CF */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,/* D0 - DF */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,/* E0 - EF */ 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */ }; int ch; int cnt; uint32_t wc; *pwc = 0; /* Sanity check. */ if (n == 0) return (0); /* * Decode 1-4 bytes depending on the value of the first byte. */ ch = (unsigned char)*s; if (ch == 0) return (0); /* Standard: return 0 for end-of-string. */ cnt = utf8_count[ch]; /* Invalid sequence or there are not plenty bytes. */ if (n < (size_t)cnt) return (-1); /* Make a Unicode code point from a single UTF-8 sequence. */ switch (cnt) { case 1: /* 1 byte sequence. */ *pwc = ch & 0x7f; return (cnt); case 2: /* 2 bytes sequence. */ if ((s[1] & 0xc0) != 0x80) return (-1); *pwc = ((ch & 0x1f) << 6) | (s[1] & 0x3f); return (cnt); case 3: /* 3 bytes sequence. */ if ((s[1] & 0xc0) != 0x80) return (-1); if ((s[2] & 0xc0) != 0x80) return (-1); wc = ((ch & 0x0f) << 12) | ((s[1] & 0x3f) << 6) | (s[2] & 0x3f); if (wc < 0x800) return (-1);/* Overlong sequence. */ break; case 4: /* 4 bytes sequence. */ if (n < 4) return (-1); if ((s[1] & 0xc0) != 0x80) return (-1); if ((s[2] & 0xc0) != 0x80) return (-1); if ((s[3] & 0xc0) != 0x80) return (-1); wc = ((ch & 0x07) << 18) | ((s[1] & 0x3f) << 12) | ((s[2] & 0x3f) << 6) | (s[3] & 0x3f); if (wc < 0x10000) return (-1);/* Overlong sequence. */ break; default: return (-1); } /* The code point larger than 0x10FFFF is not legal * Unicode values. */ if (wc > 0x10FFFF) return (-1); /* Correctly gets a Unicode, returns used bytes. */ *pwc = wc; return (cnt); } static void strdump(const char *e, const char *p, int ewidth, int utf8) { const char *q = p; logprintf(" %*s = ", ewidth, e); if (p == NULL) { logprintf("NULL\n"); return; } logprintf("\""); while (*p != '\0') { unsigned int c = 0xff & *p++; switch (c) { case '\a': logprintf("\\a"); break; case '\b': logprintf("\\b"); break; case '\n': logprintf("\\n"); break; case '\r': logprintf("\\r"); break; default: if (c >= 32 && c < 127) logprintf("%c", c); else logprintf("\\x%02X", c); } } logprintf("\""); logprintf(" (length %d)", q == NULL ? -1 : (int)strlen(q)); /* * If the current string is UTF-8, dump its code points. */ if (utf8) { size_t len; uint32_t uc; int n; int cnt = 0; p = q; len = strlen(p); logprintf(" ["); while ((n = _utf8_to_unicode(&uc, p, len)) > 0) { if (p != q) logprintf(" "); logprintf("%04X", uc); p += n; len -= n; cnt++; } logprintf("]"); logprintf(" (count %d", cnt); if (n < 0) { logprintf(",unknown %d bytes", len); } logprintf(")"); } logprintf("\n"); } /* Verify two strings are equal, dump them if not. */ int assertion_equal_string(const char *file, int line, const char *v1, const char *e1, const char *v2, const char *e2, void *extra, int utf8) { int l1, l2; assertion_count(file, line); if (v1 == v2 || (v1 != NULL && v2 != NULL && strcmp(v1, v2) == 0)) return (1); failure_start(file, line, "%s != %s", e1, e2); l1 = (int)strlen(e1); l2 = (int)strlen(e2); if (l1 < l2) l1 = l2; strdump(e1, v1, l1, utf8); strdump(e2, v2, l1, utf8); failure_finish(extra); return (0); } static void wcsdump(const char *e, const wchar_t *w) { logprintf(" %s = ", e); if (w == NULL) { logprintf("(null)"); return; } logprintf("\""); while (*w != L'\0') { unsigned int c = *w++; if (c >= 32 && c < 127) logprintf("%c", c); else if (c < 256) logprintf("\\x%02X", c); else if (c < 0x10000) logprintf("\\u%04X", c); else logprintf("\\U%08X", c); } logprintf("\"\n"); } #ifndef HAVE_WCSCMP static int wcscmp(const wchar_t *s1, const wchar_t *s2) { while (*s1 == *s2++) { if (*s1++ == L'\0') return 0; } if (*s1 > *--s2) return 1; else return -1; } #endif /* Verify that two wide strings are equal, dump them if not. */ int assertion_equal_wstring(const char *file, int line, const wchar_t *v1, const char *e1, const wchar_t *v2, const char *e2, void *extra) { assertion_count(file, line); if (v1 == v2) return (1); if (v1 != NULL && v2 != NULL && wcscmp(v1, v2) == 0) return (1); failure_start(file, line, "%s != %s", e1, e2); wcsdump(e1, v1); wcsdump(e2, v2); failure_finish(extra); return (0); } /* * Pretty standard hexdump routine. As a bonus, if ref != NULL, then * any bytes in p that differ from ref will be highlighted with '_' * before and after the hex value. */ static void hexdump(const char *p, const char *ref, size_t l, size_t offset) { size_t i, j; char sep; if (p == NULL) { logprintf("(null)\n"); return; } for(i=0; i < l; i+=16) { logprintf("%04x", (unsigned)(i + offset)); sep = ' '; for (j = 0; j < 16 && i + j < l; j++) { if (ref != NULL && p[i + j] != ref[i + j]) sep = '_'; logprintf("%c%02x", sep, 0xff & (int)p[i+j]); if (ref != NULL && p[i + j] == ref[i + j]) sep = ' '; } for (; j < 16; j++) { logprintf("%c ", sep); sep = ' '; } logprintf("%c", sep); for (j=0; j < 16 && i + j < l; j++) { int c = p[i + j]; if (c >= ' ' && c <= 126) logprintf("%c", c); else logprintf("."); } logprintf("\n"); } } /* Verify that two blocks of memory are the same, display the first * block of differences if they're not. */ int assertion_equal_mem(const char *file, int line, const void *_v1, const char *e1, const void *_v2, const char *e2, size_t l, const char *ld, void *extra) { const char *v1 = (const char *)_v1; const char *v2 = (const char *)_v2; size_t offset; assertion_count(file, line); if (v1 == v2 || (v1 != NULL && v2 != NULL && memcmp(v1, v2, l) == 0)) return (1); if (v1 == NULL || v2 == NULL) return (0); failure_start(file, line, "%s != %s", e1, e2); logprintf(" size %s = %d\n", ld, (int)l); /* Dump 48 bytes (3 lines) so that the first difference is * in the second line. */ offset = 0; while (l > 64 && memcmp(v1, v2, 32) == 0) { /* Two lines agree, so step forward one line. */ v1 += 16; v2 += 16; l -= 16; offset += 16; } logprintf(" Dump of %s\n", e1); hexdump(v1, v2, l < 128 ? l : 128, offset); logprintf(" Dump of %s\n", e2); hexdump(v2, v1, l < 128 ? l : 128, offset); logprintf("\n"); failure_finish(extra); return (0); } /* Verify that a block of memory is filled with the specified byte. */ int assertion_memory_filled_with(const char *file, int line, const void *_v1, const char *vd, size_t l, const char *ld, char b, const char *bd, void *extra) { const char *v1 = (const char *)_v1; size_t c = 0; size_t i; (void)ld; /* UNUSED */ assertion_count(file, line); for (i = 0; i < l; ++i) { if (v1[i] == b) { ++c; } } if (c == l) return (1); failure_start(file, line, "%s (size %d) not filled with %s", vd, (int)l, bd); logprintf(" Only %d bytes were correct\n", (int)c); failure_finish(extra); return (0); } /* Verify that the named file exists and is empty. */ int assertion_empty_file(const char *filename, int line, const char *f1) { char buff[1024]; struct stat st; ssize_t s; FILE *f; assertion_count(filename, line); if (stat(f1, &st) != 0) { failure_start(filename, line, "Stat failed: %s", f1); failure_finish(NULL); return (0); } if (st.st_size == 0) return (1); failure_start(filename, line, "File should be empty: %s", f1); logprintf(" File size: %d\n", (int)st.st_size); logprintf(" Contents:\n"); f = fopen(f1, "rb"); if (f == NULL) { logprintf(" Unable to open %s\n", f1); } else { s = ((off_t)sizeof(buff) < st.st_size) ? (ssize_t)sizeof(buff) : (ssize_t)st.st_size; s = fread(buff, 1, s, f); hexdump(buff, NULL, s, 0); fclose(f); } failure_finish(NULL); return (0); } /* Verify that the named file exists and is not empty. */ int assertion_non_empty_file(const char *filename, int line, const char *f1) { struct stat st; assertion_count(filename, line); if (stat(f1, &st) != 0) { failure_start(filename, line, "Stat failed: %s", f1); failure_finish(NULL); return (0); } if (st.st_size == 0) { failure_start(filename, line, "File empty: %s", f1); failure_finish(NULL); return (0); } return (1); } /* Verify that two files have the same contents. */ /* TODO: hexdump the first bytes that actually differ. */ int assertion_equal_file(const char *filename, int line, const char *fn1, const char *fn2) { char buff1[1024]; char buff2[1024]; FILE *f1, *f2; int n1, n2; assertion_count(filename, line); f1 = fopen(fn1, "rb"); f2 = fopen(fn2, "rb"); if (f1 == NULL || f2 == NULL) { if (f1) fclose(f1); if (f2) fclose(f2); return (0); } for (;;) { n1 = (int)fread(buff1, 1, sizeof(buff1), f1); n2 = (int)fread(buff2, 1, sizeof(buff2), f2); if (n1 != n2) break; if (n1 == 0 && n2 == 0) { fclose(f1); fclose(f2); return (1); } if (memcmp(buff1, buff2, n1) != 0) break; } fclose(f1); fclose(f2); failure_start(filename, line, "Files not identical"); logprintf(" file1=\"%s\"\n", fn1); logprintf(" file2=\"%s\"\n", fn2); failure_finish(NULL); return (0); } /* Verify that the named file does exist. */ int assertion_file_exists(const char *filename, int line, const char *f) { assertion_count(filename, line); #if defined(_WIN32) && !defined(__CYGWIN__) if (!_access(f, 0)) return (1); #else if (!access(f, F_OK)) return (1); #endif failure_start(filename, line, "File should exist: %s", f); failure_finish(NULL); return (0); } /* Verify that the named file doesn't exist. */ int assertion_file_not_exists(const char *filename, int line, const char *f) { assertion_count(filename, line); #if defined(_WIN32) && !defined(__CYGWIN__) if (_access(f, 0)) return (1); #else if (access(f, F_OK)) return (1); #endif failure_start(filename, line, "File should not exist: %s", f); failure_finish(NULL); return (0); } /* Compare the contents of a file to a block of memory. */ int assertion_file_contents(const char *filename, int line, const void *buff, int s, const char *fn) { char *contents; FILE *f; int n; assertion_count(filename, line); f = fopen(fn, "rb"); if (f == NULL) { failure_start(filename, line, "File should exist: %s", fn); failure_finish(NULL); return (0); } contents = malloc(s * 2); n = (int)fread(contents, 1, s * 2, f); fclose(f); if (n == s && memcmp(buff, contents, s) == 0) { free(contents); return (1); } failure_start(filename, line, "File contents don't match"); logprintf(" file=\"%s\"\n", fn); if (n > 0) hexdump(contents, buff, n > 512 ? 512 : n, 0); else { logprintf(" File empty, contents should be:\n"); hexdump(buff, NULL, s > 512 ? 512 : s, 0); } failure_finish(NULL); free(contents); return (0); } /* Check the contents of a text file, being tolerant of line endings. */ int assertion_text_file_contents(const char *filename, int line, const char *buff, const char *fn) { char *contents; const char *btxt, *ftxt; FILE *f; int n, s; assertion_count(filename, line); f = fopen(fn, "r"); if (f == NULL) { failure_start(filename, line, "File doesn't exist: %s", fn); failure_finish(NULL); return (0); } s = (int)strlen(buff); contents = malloc(s * 2 + 128); n = (int)fread(contents, 1, s * 2 + 128 - 1, f); if (n >= 0) contents[n] = '\0'; fclose(f); /* Compare texts. */ btxt = buff; ftxt = (const char *)contents; while (*btxt != '\0' && *ftxt != '\0') { if (*btxt == *ftxt) { ++btxt; ++ftxt; continue; } if (btxt[0] == '\n' && ftxt[0] == '\r' && ftxt[1] == '\n') { /* Pass over different new line characters. */ ++btxt; ftxt += 2; continue; } break; } if (*btxt == '\0' && *ftxt == '\0') { free(contents); return (1); } failure_start(filename, line, "Contents don't match"); logprintf(" file=\"%s\"\n", fn); if (n > 0) { hexdump(contents, buff, n, 0); logprintf(" expected\n", fn); hexdump(buff, contents, s, 0); } else { logprintf(" File empty, contents should be:\n"); hexdump(buff, NULL, s, 0); } failure_finish(NULL); free(contents); return (0); } /* Verify that a text file contains the specified lines, regardless of order */ /* This could be more efficient if we sorted both sets of lines, etc, but * since this is used only for testing and only ever deals with a dozen or so * lines at a time, this relatively crude approach is just fine. */ int assertion_file_contains_lines_any_order(const char *file, int line, const char *pathname, const char *lines[]) { char *buff; size_t buff_size; size_t expected_count, actual_count, i, j; char **expected = NULL; char *p, **actual = NULL; char c; int expected_failure = 0, actual_failure = 0; assertion_count(file, line); buff = slurpfile(&buff_size, "%s", pathname); if (buff == NULL) { failure_start(pathname, line, "Can't read file: %s", pathname); failure_finish(NULL); return (0); } /* Make a copy of the provided lines and count up the expected * file size. */ for (i = 0; lines[i] != NULL; ++i) { } expected_count = i; if (expected_count) { expected = malloc(sizeof(char *) * expected_count); if (expected == NULL) { failure_start(pathname, line, "Can't allocate memory"); failure_finish(NULL); free(expected); return (0); } for (i = 0; lines[i] != NULL; ++i) { expected[i] = strdup(lines[i]); } } /* Break the file into lines */ actual_count = 0; for (c = '\0', p = buff; p < buff + buff_size; ++p) { if (*p == '\x0d' || *p == '\x0a') *p = '\0'; if (c == '\0' && *p != '\0') ++actual_count; c = *p; } if (actual_count) { actual = calloc(sizeof(char *), actual_count); if (actual == NULL) { failure_start(pathname, line, "Can't allocate memory"); failure_finish(NULL); free(expected); return (0); } for (j = 0, p = buff; p < buff + buff_size; p += 1 + strlen(p)) { if (*p != '\0') { actual[j] = p; ++j; } } } /* Erase matching lines from both lists */ for (i = 0; i < expected_count; ++i) { if (expected[i] == NULL) continue; for (j = 0; j < actual_count; ++j) { if (actual[j] == NULL) continue; if (strcmp(expected[i], actual[j]) == 0) { free(expected[i]); expected[i] = NULL; actual[j] = NULL; break; } } } /* If there's anything left, it's a failure */ for (i = 0; i < expected_count; ++i) { if (expected[i] != NULL) ++expected_failure; } for (j = 0; j < actual_count; ++j) { if (actual[j] != NULL) ++actual_failure; } if (expected_failure == 0 && actual_failure == 0) { free(buff); free(expected); free(actual); return (1); } failure_start(file, line, "File doesn't match: %s", pathname); for (i = 0; i < expected_count; ++i) { if (expected[i] != NULL) { logprintf(" Expected but not present: %s\n", expected[i]); free(expected[i]); } } for (j = 0; j < actual_count; ++j) { if (actual[j] != NULL) logprintf(" Present but not expected: %s\n", actual[j]); } failure_finish(NULL); free(buff); free(expected); free(actual); return (0); } /* Verify that a text file does not contains the specified strings */ int assertion_file_contains_no_invalid_strings(const char *file, int line, const char *pathname, const char *strings[]) { char *buff; int i; buff = slurpfile(NULL, "%s", pathname); if (buff == NULL) { failure_start(file, line, "Can't read file: %s", pathname); failure_finish(NULL); return (0); } for (i = 0; strings[i] != NULL; ++i) { if (strstr(buff, strings[i]) != NULL) { failure_start(file, line, "Invalid string in %s: %s", pathname, strings[i]); failure_finish(NULL); free(buff); return(0); } } free(buff); return (0); } /* Test that two paths point to the same file. */ /* As a side-effect, asserts that both files exist. */ static int is_hardlink(const char *file, int line, const char *path1, const char *path2) { #if defined(_WIN32) && !defined(__CYGWIN__) BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2; int r; assertion_count(file, line); r = my_GetFileInformationByName(path1, &bhfi1); if (r == 0) { failure_start(file, line, "File %s can't be inspected?", path1); failure_finish(NULL); return (0); } r = my_GetFileInformationByName(path2, &bhfi2); if (r == 0) { failure_start(file, line, "File %s can't be inspected?", path2); failure_finish(NULL); return (0); } return (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber && bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow); #else struct stat st1, st2; int r; assertion_count(file, line); r = lstat(path1, &st1); if (r != 0) { failure_start(file, line, "File should exist: %s", path1); failure_finish(NULL); return (0); } r = lstat(path2, &st2); if (r != 0) { failure_start(file, line, "File should exist: %s", path2); failure_finish(NULL); return (0); } return (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev); #endif } int assertion_is_hardlink(const char *file, int line, const char *path1, const char *path2) { if (is_hardlink(file, line, path1, path2)) return (1); failure_start(file, line, "Files %s and %s are not hardlinked", path1, path2); failure_finish(NULL); return (0); } int assertion_is_not_hardlink(const char *file, int line, const char *path1, const char *path2) { if (!is_hardlink(file, line, path1, path2)) return (1); failure_start(file, line, "Files %s and %s should not be hardlinked", path1, path2); failure_finish(NULL); return (0); } /* Verify a/b/mtime of 'pathname'. */ /* If 'recent', verify that it's within last 10 seconds. */ static int assertion_file_time(const char *file, int line, const char *pathname, long t, long nsec, char type, int recent) { long long filet, filet_nsec; int r; #if defined(_WIN32) && !defined(__CYGWIN__) #define EPOC_TIME (116444736000000000ULL) FILETIME fxtime, fbirthtime, fatime, fmtime; ULARGE_INTEGER wintm; HANDLE h; fxtime.dwLowDateTime = 0; fxtime.dwHighDateTime = 0; assertion_count(file, line); /* Note: FILE_FLAG_BACKUP_SEMANTICS applies to open * a directory file. If not, CreateFile() will fail when * the pathname is a directory. */ h = CreateFile(pathname, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (h == INVALID_HANDLE_VALUE) { failure_start(file, line, "Can't access %s\n", pathname); failure_finish(NULL); return (0); } r = GetFileTime(h, &fbirthtime, &fatime, &fmtime); switch (type) { case 'a': fxtime = fatime; break; case 'b': fxtime = fbirthtime; break; case 'm': fxtime = fmtime; break; } CloseHandle(h); if (r == 0) { failure_start(file, line, "Can't GetFileTime %s\n", pathname); failure_finish(NULL); return (0); } wintm.LowPart = fxtime.dwLowDateTime; wintm.HighPart = fxtime.dwHighDateTime; filet = (wintm.QuadPart - EPOC_TIME) / 10000000; filet_nsec = ((wintm.QuadPart - EPOC_TIME) % 10000000) * 100; nsec = (nsec / 100) * 100; /* Round the request */ #else struct stat st; assertion_count(file, line); r = lstat(pathname, &st); if (r != 0) { failure_start(file, line, "Can't stat %s\n", pathname); failure_finish(NULL); return (0); } switch (type) { case 'a': filet = st.st_atime; break; case 'm': filet = st.st_mtime; break; case 'b': filet = 0; break; default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type); exit(1); } #if defined(__FreeBSD__) switch (type) { case 'a': filet_nsec = st.st_atimespec.tv_nsec; break; case 'b': filet = st.st_birthtime; /* FreeBSD filesystems that don't support birthtime * (e.g., UFS1) always return -1 here. */ if (filet == -1) { return (1); } filet_nsec = st.st_birthtimespec.tv_nsec; break; case 'm': filet_nsec = st.st_mtimespec.tv_nsec; break; default: fprintf(stderr, "INTERNAL: Bad type %c for file time", type); exit(1); } /* FreeBSD generally only stores to microsecond res, so round. */ filet_nsec = (filet_nsec / 1000) * 1000; nsec = (nsec / 1000) * 1000; #else filet_nsec = nsec = 0; /* Generic POSIX only has whole seconds. */ if (type == 'b') return (1); /* Generic POSIX doesn't have birthtime */ #if defined(__HAIKU__) if (type == 'a') return (1); /* Haiku doesn't have atime. */ #endif #endif #endif if (recent) { /* Check that requested time is up-to-date. */ time_t now = time(NULL); if (filet < now - 10 || filet > now + 1) { failure_start(file, line, "File %s has %ctime %lld, %lld seconds ago\n", pathname, type, filet, now - filet); failure_finish(NULL); return (0); } } else if (filet != t || filet_nsec != nsec) { failure_start(file, line, "File %s has %ctime %lld.%09lld, expected %lld.%09lld", pathname, type, filet, filet_nsec, t, nsec); failure_finish(NULL); return (0); } return (1); } /* Verify atime of 'pathname'. */ int assertion_file_atime(const char *file, int line, const char *pathname, long t, long nsec) { return assertion_file_time(file, line, pathname, t, nsec, 'a', 0); } /* Verify atime of 'pathname' is up-to-date. */ int assertion_file_atime_recent(const char *file, int line, const char *pathname) { return assertion_file_time(file, line, pathname, 0, 0, 'a', 1); } /* Verify birthtime of 'pathname'. */ int assertion_file_birthtime(const char *file, int line, const char *pathname, long t, long nsec) { return assertion_file_time(file, line, pathname, t, nsec, 'b', 0); } /* Verify birthtime of 'pathname' is up-to-date. */ int assertion_file_birthtime_recent(const char *file, int line, const char *pathname) { return assertion_file_time(file, line, pathname, 0, 0, 'b', 1); } /* Verify mode of 'pathname'. */ int assertion_file_mode(const char *file, int line, const char *pathname, int expected_mode) { int mode; int r; assertion_count(file, line); #if defined(_WIN32) && !defined(__CYGWIN__) failure_start(file, line, "assertFileMode not yet implemented for Windows"); (void)mode; /* UNUSED */ (void)r; /* UNUSED */ (void)pathname; /* UNUSED */ (void)expected_mode; /* UNUSED */ #else { struct stat st; r = lstat(pathname, &st); mode = (int)(st.st_mode & 0777); } if (r == 0 && mode == expected_mode) return (1); failure_start(file, line, "File %s has mode %o, expected %o", pathname, mode, expected_mode); #endif failure_finish(NULL); return (0); } /* Verify mtime of 'pathname'. */ int assertion_file_mtime(const char *file, int line, const char *pathname, long t, long nsec) { return assertion_file_time(file, line, pathname, t, nsec, 'm', 0); } /* Verify mtime of 'pathname' is up-to-date. */ int assertion_file_mtime_recent(const char *file, int line, const char *pathname) { return assertion_file_time(file, line, pathname, 0, 0, 'm', 1); } /* Verify number of links to 'pathname'. */ int assertion_file_nlinks(const char *file, int line, const char *pathname, int nlinks) { #if defined(_WIN32) && !defined(__CYGWIN__) BY_HANDLE_FILE_INFORMATION bhfi; int r; assertion_count(file, line); r = my_GetFileInformationByName(pathname, &bhfi); if (r != 0 && bhfi.nNumberOfLinks == (DWORD)nlinks) return (1); failure_start(file, line, "File %s has %d links, expected %d", pathname, bhfi.nNumberOfLinks, nlinks); failure_finish(NULL); return (0); #else struct stat st; int r; assertion_count(file, line); r = lstat(pathname, &st); if (r == 0 && (int)st.st_nlink == nlinks) return (1); failure_start(file, line, "File %s has %d links, expected %d", pathname, st.st_nlink, nlinks); failure_finish(NULL); return (0); #endif } /* Verify size of 'pathname'. */ int assertion_file_size(const char *file, int line, const char *pathname, long size) { int64_t filesize; int r; assertion_count(file, line); #if defined(_WIN32) && !defined(__CYGWIN__) { BY_HANDLE_FILE_INFORMATION bhfi; r = !my_GetFileInformationByName(pathname, &bhfi); filesize = ((int64_t)bhfi.nFileSizeHigh << 32) + bhfi.nFileSizeLow; } #else { struct stat st; r = lstat(pathname, &st); filesize = st.st_size; } #endif if (r == 0 && filesize == size) return (1); failure_start(file, line, "File %s has size %ld, expected %ld", pathname, (long)filesize, (long)size); failure_finish(NULL); return (0); } /* Assert that 'pathname' is a dir. If mode >= 0, verify that too. */ int assertion_is_dir(const char *file, int line, const char *pathname, int mode) { struct stat st; int r; #if defined(_WIN32) && !defined(__CYGWIN__) (void)mode; /* UNUSED */ #endif assertion_count(file, line); r = lstat(pathname, &st); if (r != 0) { failure_start(file, line, "Dir should exist: %s", pathname); failure_finish(NULL); return (0); } if (!S_ISDIR(st.st_mode)) { failure_start(file, line, "%s is not a dir", pathname); failure_finish(NULL); return (0); } #if !defined(_WIN32) || defined(__CYGWIN__) /* Windows doesn't handle permissions the same way as POSIX, * so just ignore the mode tests. */ /* TODO: Can we do better here? */ if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) { failure_start(file, line, "Dir %s has wrong mode", pathname); logprintf(" Expected: 0%3o\n", mode); logprintf(" Found: 0%3o\n", st.st_mode & 07777); failure_finish(NULL); return (0); } #endif return (1); } /* Verify that 'pathname' is a regular file. If 'mode' is >= 0, * verify that too. */ int assertion_is_reg(const char *file, int line, const char *pathname, int mode) { struct stat st; int r; #if defined(_WIN32) && !defined(__CYGWIN__) (void)mode; /* UNUSED */ #endif assertion_count(file, line); r = lstat(pathname, &st); if (r != 0 || !S_ISREG(st.st_mode)) { failure_start(file, line, "File should exist: %s", pathname); failure_finish(NULL); return (0); } #if !defined(_WIN32) || defined(__CYGWIN__) /* Windows doesn't handle permissions the same way as POSIX, * so just ignore the mode tests. */ /* TODO: Can we do better here? */ if (mode >= 0 && (mode_t)mode != (st.st_mode & 07777)) { failure_start(file, line, "File %s has wrong mode", pathname); logprintf(" Expected: 0%3o\n", mode); logprintf(" Found: 0%3o\n", st.st_mode & 07777); failure_finish(NULL); return (0); } #endif return (1); } /* Check whether 'pathname' is a symbolic link. If 'contents' is * non-NULL, verify that the symlink has those contents. */ static int is_symlink(const char *file, int line, const char *pathname, const char *contents) { #if defined(_WIN32) && !defined(__CYGWIN__) (void)pathname; /* UNUSED */ (void)contents; /* UNUSED */ assertion_count(file, line); /* Windows sort-of has real symlinks, but they're only usable * by privileged users and are crippled even then, so there's * really not much point in bothering with this. */ return (0); #else char buff[300]; struct stat st; ssize_t linklen; int r; assertion_count(file, line); r = lstat(pathname, &st); if (r != 0) { failure_start(file, line, "Symlink should exist: %s", pathname); failure_finish(NULL); return (0); } if (!S_ISLNK(st.st_mode)) return (0); if (contents == NULL) return (1); linklen = readlink(pathname, buff, sizeof(buff)); if (linklen < 0) { failure_start(file, line, "Can't read symlink %s", pathname); failure_finish(NULL); return (0); } buff[linklen] = '\0'; if (strcmp(buff, contents) != 0) return (0); return (1); #endif } /* Assert that path is a symlink that (optionally) contains contents. */ int assertion_is_symlink(const char *file, int line, const char *path, const char *contents) { if (is_symlink(file, line, path, contents)) return (1); if (contents) failure_start(file, line, "File %s is not a symlink to %s", path, contents); else failure_start(file, line, "File %s is not a symlink", path); failure_finish(NULL); return (0); } /* Create a directory and report any errors. */ int assertion_make_dir(const char *file, int line, const char *dirname, int mode) { assertion_count(file, line); #if defined(_WIN32) && !defined(__CYGWIN__) (void)mode; /* UNUSED */ if (0 == _mkdir(dirname)) return (1); #else if (0 == mkdir(dirname, mode)) { if (0 == chmod(dirname, mode)) { assertion_file_mode(file, line, dirname, mode); return (1); } } #endif failure_start(file, line, "Could not create directory %s", dirname); failure_finish(NULL); return(0); } /* Create a file with the specified contents and report any failures. */ int assertion_make_file(const char *file, int line, const char *path, int mode, int csize, const void *contents) { #if defined(_WIN32) && !defined(__CYGWIN__) /* TODO: Rework this to set file mode as well. */ FILE *f; (void)mode; /* UNUSED */ assertion_count(file, line); f = fopen(path, "wb"); if (f == NULL) { failure_start(file, line, "Could not create file %s", path); failure_finish(NULL); return (0); } if (contents != NULL) { size_t wsize; if (csize < 0) wsize = strlen(contents); else wsize = (size_t)csize; if (wsize != fwrite(contents, 1, wsize, f)) { fclose(f); failure_start(file, line, "Could not write file %s", path); failure_finish(NULL); return (0); } } fclose(f); return (1); #else int fd; assertion_count(file, line); fd = open(path, O_CREAT | O_WRONLY, mode >= 0 ? mode : 0644); if (fd < 0) { failure_start(file, line, "Could not create %s", path); failure_finish(NULL); return (0); } if (0 != chmod(path, mode)) { failure_start(file, line, "Could not chmod %s", path); failure_finish(NULL); close(fd); return (0); } if (contents != NULL) { ssize_t wsize; if (csize < 0) wsize = (ssize_t)strlen(contents); else wsize = (ssize_t)csize; if (wsize != write(fd, contents, wsize)) { close(fd); failure_start(file, line, "Could not write to %s", path); failure_finish(NULL); close(fd); return (0); } } close(fd); assertion_file_mode(file, line, path, mode); return (1); #endif } /* Create a hardlink and report any failures. */ int assertion_make_hardlink(const char *file, int line, const char *newpath, const char *linkto) { int succeeded; assertion_count(file, line); #if defined(_WIN32) && !defined(__CYGWIN__) succeeded = my_CreateHardLinkA(newpath, linkto); #elif HAVE_LINK succeeded = !link(linkto, newpath); #else succeeded = 0; #endif if (succeeded) return (1); failure_start(file, line, "Could not create hardlink"); logprintf(" New link: %s\n", newpath); logprintf(" Old name: %s\n", linkto); failure_finish(NULL); return(0); } /* Create a symlink and report any failures. */ int assertion_make_symlink(const char *file, int line, const char *newpath, const char *linkto) { #if defined(_WIN32) && !defined(__CYGWIN__) int targetIsDir = 0; /* TODO: Fix this */ assertion_count(file, line); if (my_CreateSymbolicLinkA(newpath, linkto, targetIsDir)) return (1); #elif HAVE_SYMLINK assertion_count(file, line); if (0 == symlink(linkto, newpath)) return (1); #endif failure_start(file, line, "Could not create symlink"); logprintf(" New link: %s\n", newpath); logprintf(" Old name: %s\n", linkto); failure_finish(NULL); return(0); } /* Set umask, report failures. */ int assertion_umask(const char *file, int line, int mask) { assertion_count(file, line); (void)file; /* UNUSED */ (void)line; /* UNUSED */ umask(mask); return (1); } /* Set times, report failures. */ int assertion_utimes(const char *file, int line, const char *pathname, long at, long at_nsec, long mt, long mt_nsec) { int r; #if defined(_WIN32) && !defined(__CYGWIN__) #define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\ + (((nsec)/1000)*10)) HANDLE h; ULARGE_INTEGER wintm; FILETIME fatime, fmtime; FILETIME *pat, *pmt; assertion_count(file, line); h = CreateFileA(pathname,GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (h == INVALID_HANDLE_VALUE) { failure_start(file, line, "Can't access %s\n", pathname); failure_finish(NULL); return (0); } if (at > 0 || at_nsec > 0) { wintm.QuadPart = WINTIME(at, at_nsec); fatime.dwLowDateTime = wintm.LowPart; fatime.dwHighDateTime = wintm.HighPart; pat = &fatime; } else pat = NULL; if (mt > 0 || mt_nsec > 0) { wintm.QuadPart = WINTIME(mt, mt_nsec); fmtime.dwLowDateTime = wintm.LowPart; fmtime.dwHighDateTime = wintm.HighPart; pmt = &fmtime; } else pmt = NULL; if (pat != NULL || pmt != NULL) r = SetFileTime(h, NULL, pat, pmt); else r = 1; CloseHandle(h); if (r == 0) { failure_start(file, line, "Can't SetFileTime %s\n", pathname); failure_finish(NULL); return (0); } return (1); #else /* defined(_WIN32) && !defined(__CYGWIN__) */ struct stat st; struct timeval times[2]; #if !defined(__FreeBSD__) mt_nsec = at_nsec = 0; /* Generic POSIX only has whole seconds. */ #endif if (mt == 0 && mt_nsec == 0 && at == 0 && at_nsec == 0) return (1); r = lstat(pathname, &st); if (r < 0) { failure_start(file, line, "Can't stat %s\n", pathname); failure_finish(NULL); return (0); } if (mt == 0 && mt_nsec == 0) { mt = st.st_mtime; #if defined(__FreeBSD__) mt_nsec = st.st_mtimespec.tv_nsec; /* FreeBSD generally only stores to microsecond res, so round. */ mt_nsec = (mt_nsec / 1000) * 1000; #endif } if (at == 0 && at_nsec == 0) { at = st.st_atime; #if defined(__FreeBSD__) at_nsec = st.st_atimespec.tv_nsec; /* FreeBSD generally only stores to microsecond res, so round. */ at_nsec = (at_nsec / 1000) * 1000; #endif } times[1].tv_sec = mt; times[1].tv_usec = mt_nsec / 1000; times[0].tv_sec = at; times[0].tv_usec = at_nsec / 1000; #ifdef HAVE_LUTIMES r = lutimes(pathname, times); #else r = utimes(pathname, times); #endif if (r < 0) { failure_start(file, line, "Can't utimes %s\n", pathname); failure_finish(NULL); return (0); } return (1); #endif /* defined(_WIN32) && !defined(__CYGWIN__) */ } /* Compare file flags */ int assertion_compare_fflags(const char *file, int line, const char *patha, const char *pathb, int nomatch) { #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) struct stat sa, sb; assertion_count(file, line); if (stat(patha, &sa) < 0) return (0); if (stat(pathb, &sb) < 0) return (0); if (!nomatch && sa.st_flags != sb.st_flags) { failure_start(file, line, "File flags should be identical: " "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb, sb.st_flags); failure_finish(NULL); return (0); } if (nomatch && sa.st_flags == sb.st_flags) { failure_start(file, line, "File flags should be different: " "%s=%#010x %s=%#010x", patha, sa.st_flags, pathb, sb.st_flags); failure_finish(NULL); return (0); } #elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) && \ defined(FS_NODUMP_FL)) || \ (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \ && defined(EXT2_NODUMP_FL)) int fd, r, flagsa, flagsb; assertion_count(file, line); fd = open(patha, O_RDONLY | O_NONBLOCK); if (fd < 0) { failure_start(file, line, "Can't open %s\n", patha); failure_finish(NULL); return (0); } r = ioctl(fd, #ifdef FS_IOC_GETFLAGS FS_IOC_GETFLAGS, #else EXT2_IOC_GETFLAGS, #endif &flagsa); close(fd); if (r < 0) { failure_start(file, line, "Can't get flags %s\n", patha); failure_finish(NULL); return (0); } fd = open(pathb, O_RDONLY | O_NONBLOCK); if (fd < 0) { failure_start(file, line, "Can't open %s\n", pathb); failure_finish(NULL); return (0); } r = ioctl(fd, #ifdef FS_IOC_GETFLAGS FS_IOC_GETFLAGS, #else EXT2_IOC_GETFLAGS, #endif &flagsb); close(fd); if (r < 0) { failure_start(file, line, "Can't get flags %s\n", pathb); failure_finish(NULL); return (0); } if (!nomatch && flagsa != flagsb) { failure_start(file, line, "File flags should be identical: " "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb); failure_finish(NULL); return (0); } if (nomatch && flagsa == flagsb) { failure_start(file, line, "File flags should be different: " "%s=%#010x %s=%#010x", patha, flagsa, pathb, flagsb); failure_finish(NULL); return (0); } #else (void)patha; /* UNUSED */ (void)pathb; /* UNUSED */ (void)nomatch; /* UNUSED */ assertion_count(file, line); #endif return (1); } /* Set nodump, report failures. */ int assertion_set_nodump(const char *file, int line, const char *pathname) { #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) int r; assertion_count(file, line); r = chflags(pathname, UF_NODUMP); if (r < 0) { failure_start(file, line, "Can't set nodump %s\n", pathname); failure_finish(NULL); return (0); } #elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) && \ defined(FS_NODUMP_FL)) || \ (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \ && defined(EXT2_NODUMP_FL)) int fd, r, flags; assertion_count(file, line); fd = open(pathname, O_RDONLY | O_NONBLOCK); if (fd < 0) { failure_start(file, line, "Can't open %s\n", pathname); failure_finish(NULL); return (0); } r = ioctl(fd, #ifdef FS_IOC_GETFLAGS FS_IOC_GETFLAGS, #else EXT2_IOC_GETFLAGS, #endif &flags); if (r < 0) { failure_start(file, line, "Can't get flags %s\n", pathname); failure_finish(NULL); return (0); } #ifdef FS_NODUMP_FL flags |= FS_NODUMP_FL; #else flags |= EXT2_NODUMP_FL; #endif r = ioctl(fd, #ifdef FS_IOC_SETFLAGS FS_IOC_SETFLAGS, #else EXT2_IOC_SETFLAGS, #endif &flags); if (r < 0) { failure_start(file, line, "Can't set nodump %s\n", pathname); failure_finish(NULL); return (0); } close(fd); #else (void)pathname; /* UNUSED */ assertion_count(file, line); #endif return (1); } #ifdef PROGRAM static void assert_version_id(char **qq, size_t *ss) { char *q = *qq; size_t s = *ss; /* Version number is a series of digits and periods. */ while (s > 0 && (*q == '.' || (*q >= '0' && *q <= '9'))) { ++q; --s; } if (q[0] == 'd' && q[1] == 'e' && q[2] == 'v') { q += 3; s -= 3; } /* Skip a single trailing a,b,c, or d. */ if (*q == 'a' || *q == 'b' || *q == 'c' || *q == 'd') ++q; /* Version number terminated by space. */ failure("No space after version: ``%s''", q); assert(s > 1); failure("No space after version: ``%s''", q); assert(*q == ' '); ++q; --s; *qq = q; *ss = s; } /* * Check program version */ void assertVersion(const char *prog, const char *base) { int r; char *p, *q; size_t s; unsigned int prog_len = strlen(base); r = systemf("%s --version >version.stdout 2>version.stderr", prog); if (r != 0) r = systemf("%s -W version >version.stdout 2>version.stderr", prog); failure("Unable to run either %s --version or %s -W version", prog, prog); if (!assert(r == 0)) return; /* --version should generate nothing to stdout. */ assertEmptyFile("version.stderr"); /* Verify format of version message. */ q = p = slurpfile(&s, "version.stdout"); /* Version message should start with name of program, then space. */ assert(s > prog_len + 1); failure("Version must start with '%s': ``%s''", base, p); if (!assertEqualMem(q, base, prog_len)) { free(p); return; } q += prog_len; s -= prog_len; assert(*q == ' '); q++; s--; assert_version_id(&q, &s); /* Separator. */ failure("No `-' between program name and versions: ``%s''", p); assertEqualMem(q, "- ", 2); q += 2; s -= 2; failure("Not long enough for libarchive version: ``%s''", p); assert(s > 11); failure("Libarchive version must start with `libarchive': ``%s''", p); assertEqualMem(q, "libarchive ", 11); q += 11; s -= 11; assert_version_id(&q, &s); /* Skip arbitrary third-party version numbers. */ while (s > 0 && (*q == ' ' || *q == '-' || *q == '/' || *q == '.' || isalnum(*q))) { ++q; --s; } /* All terminated by end-of-line. */ assert(s >= 1); /* Skip an optional CR character (e.g., Windows) */ failure("Version output must end with \\n or \\r\\n"); if (*q == '\r') { ++q; --s; } assertEqualMem(q, "\n", 1); free(p); } #endif /* PROGRAM */ /* * * UTILITIES for use by tests. * */ /* * Check whether platform supports symlinks. This is intended * for tests to use in deciding whether to bother testing symlink * support; if the platform doesn't support symlinks, there's no point * in checking whether the program being tested can create them. * * Note that the first time this test is called, we actually go out to * disk to create and verify a symlink. This is necessary because * symlink support is actually a property of a particular filesystem * and can thus vary between directories on a single system. After * the first call, this returns the cached result from memory, so it's * safe to call it as often as you wish. */ int canSymlink(void) { /* Remember the test result */ static int value = 0, tested = 0; if (tested) return (value); ++tested; assertion_make_file(__FILE__, __LINE__, "canSymlink.0", 0644, 1, "a"); /* Note: Cygwin has its own symlink() emulation that does not * use the Win32 CreateSymbolicLink() function. */ #if defined(_WIN32) && !defined(__CYGWIN__) value = my_CreateSymbolicLinkA("canSymlink.1", "canSymlink.0", 0) && is_symlink(__FILE__, __LINE__, "canSymlink.1", "canSymlink.0"); #elif HAVE_SYMLINK value = (0 == symlink("canSymlink.0", "canSymlink.1")) && is_symlink(__FILE__, __LINE__, "canSymlink.1","canSymlink.0"); #endif return (value); } /* Platform-dependent options for hiding the output of a subcommand. */ #if defined(_WIN32) && !defined(__CYGWIN__) static const char *redirectArgs = ">NUL 2>NUL"; /* Win32 cmd.exe */ #else static const char *redirectArgs = ">/dev/null 2>/dev/null"; /* POSIX 'sh' */ #endif /* * Can this platform run the bzip2 program? */ int canBzip2(void) { static int tested = 0, value = 0; if (!tested) { tested = 1; if (systemf("bzip2 -d -V %s", redirectArgs) == 0) value = 1; } return (value); } /* * Can this platform run the grzip program? */ int canGrzip(void) { static int tested = 0, value = 0; if (!tested) { tested = 1; if (systemf("grzip -V %s", redirectArgs) == 0) value = 1; } return (value); } /* * Can this platform run the gzip program? */ int canGzip(void) { static int tested = 0, value = 0; if (!tested) { tested = 1; if (systemf("gzip -V %s", redirectArgs) == 0) value = 1; } return (value); } /* * Can this platform run the lrzip program? */ int canRunCommand(const char *cmd) { static int tested = 0, value = 0; if (!tested) { tested = 1; if (systemf("%s %s", cmd, redirectArgs) == 0) value = 1; } return (value); } int canLrzip(void) { static int tested = 0, value = 0; if (!tested) { tested = 1; if (systemf("lrzip -V %s", redirectArgs) == 0) value = 1; } return (value); } /* * Can this platform run the lz4 program? */ int canLz4(void) { static int tested = 0, value = 0; if (!tested) { tested = 1; if (systemf("lz4 -V %s", redirectArgs) == 0) value = 1; } return (value); } /* * Can this platform run the lzip program? */ int canLzip(void) { static int tested = 0, value = 0; if (!tested) { tested = 1; if (systemf("lzip -V %s", redirectArgs) == 0) value = 1; } return (value); } /* * Can this platform run the lzma program? */ int canLzma(void) { static int tested = 0, value = 0; if (!tested) { tested = 1; if (systemf("lzma -V %s", redirectArgs) == 0) value = 1; } return (value); } /* * Can this platform run the lzop program? */ int canLzop(void) { static int tested = 0, value = 0; if (!tested) { tested = 1; if (systemf("lzop -V %s", redirectArgs) == 0) value = 1; } return (value); } /* * Can this platform run the xz program? */ int canXz(void) { static int tested = 0, value = 0; if (!tested) { tested = 1; if (systemf("xz -V %s", redirectArgs) == 0) value = 1; } return (value); } /* * Can this filesystem handle nodump flags. */ int canNodump(void) { #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) const char *path = "cannodumptest"; struct stat sb; assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL); if (chflags(path, UF_NODUMP) < 0) return (0); if (stat(path, &sb) < 0) return (0); if (sb.st_flags & UF_NODUMP) return (1); #elif (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS) \ && defined(FS_NODUMP_FL)) || \ (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) \ && defined(EXT2_NODUMP_FL)) const char *path = "cannodumptest"; int fd, r, flags; assertion_make_file(__FILE__, __LINE__, path, 0644, 0, NULL); fd = open(path, O_RDONLY | O_NONBLOCK); if (fd < 0) return (0); r = ioctl(fd, #ifdef FS_IOC_GETFLAGS FS_IOC_GETFLAGS, #else EXT2_IOC_GETFLAGS, #endif &flags); if (r < 0) return (0); #ifdef FS_NODUMP_FL flags |= FS_NODUMP_FL; #else flags |= EXT2_NODUMP_FL; #endif r = ioctl(fd, #ifdef FS_IOC_SETFLAGS FS_IOC_SETFLAGS, #else EXT2_IOC_SETFLAGS, #endif &flags); if (r < 0) return (0); close(fd); fd = open(path, O_RDONLY | O_NONBLOCK); if (fd < 0) return (0); r = ioctl(fd, #ifdef FS_IOC_GETFLAGS FS_IOC_GETFLAGS, #else EXT2_IOC_GETFLAGS, #endif &flags); if (r < 0) return (0); close(fd); #ifdef FS_NODUMP_FL if (flags & FS_NODUMP_FL) #else if (flags & EXT2_NODUMP_FL) #endif return (1); #endif + return (0); +} + +/* Get extended attribute from a path */ +const void * +getXattr(const char *path, const char *name, size_t *sizep) +{ + void *value = NULL; +#if ARCHIVE_XATTR_SUPPORT + ssize_t size; +#if ARCHIVE_XATTR_LINUX + size = lgetxattr(path, name, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(path, name, NULL, 0, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX + size = lgetea(path, name, NULL, 0); +#elif ARCHIVE_XATTR_FREEBSD + size = extattr_get_link(path, EXTATTR_NAMESPACE_USER, name + 5, + NULL, 0); +#endif + + if (size >= 0) { + value = malloc(size); +#if ARCHIVE_XATTR_LINUX + size = lgetxattr(path, name, value, size); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(path, name, value, size, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX + size = lgetea(path, name, value, size); +#elif ARCHIVE_XATTR_FREEBSD + size = extattr_get_link(path, EXTATTR_NAMESPACE_USER, name + 5, + value, size); +#endif + if (size < 0) { + free(value); + value = NULL; + } + } + if (size < 0) + *sizep = 0; + else + *sizep = (size_t)size; +#else /* !ARCHIVE_XATTR_SUPPORT */ + (void)path; /* UNUSED */ + (void)name; /* UNUSED */ + *sizep = 0; +#endif /* !ARCHIVE_XATTR_SUPPORT */ + return (value); +} + +/* + * Set extended attribute on a path + * Returns 0 on error, 1 on success + */ +int +setXattr(const char *path, const char *name, const void *value, size_t size) +{ +#if ARCHIVE_XATTR_SUPPORT +#if ARCHIVE_XATTR_LINUX + if (lsetxattr(path, name, value, size, 0) == 0) +#elif ARCHIVE_XATTR_DARWIN + if (setxattr(path, name, value, size, 0, XATTR_NOFOLLOW) == 0) +#elif ARCHIVE_XATTR_AIX + if (lsetea(path, name, value, size, 0) == 0) +#elif ARCHIVE_XATTR_FREEBSD + if (extattr_set_link(path, EXTATTR_NAMESPACE_USER, name + 5, value, + size) > -1) +#else + if (0) +#endif + return (1); +#else /* !ARCHIVE_XATTR_SUPPORT */ + (void)path; /* UNUSED */ + (void)name; /* UNUSED */ + (void)value; /* UNUSED */ + (void)size; /* UNUSED */ +#endif /* !ARCHIVE_XATTR_SUPPORT */ return (0); } #if ARCHIVE_ACL_SUNOS /* Fetch ACLs on Solaris using acl() or facl() */ void * sunacl_get(int cmd, int *aclcnt, int fd, const char *path) { int cnt, cntcmd; size_t size; void *aclp; if (cmd == GETACL) { cntcmd = GETACLCNT; size = sizeof(aclent_t); } #if ARCHIVE_ACL_SUNOS_NFS4 else if (cmd == ACE_GETACL) { cntcmd = ACE_GETACLCNT; size = sizeof(ace_t); } #endif else { errno = EINVAL; *aclcnt = -1; return (NULL); } aclp = NULL; cnt = -2; while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) { if (path != NULL) cnt = acl(path, cntcmd, 0, NULL); else cnt = facl(fd, cntcmd, 0, NULL); if (cnt > 0) { if (aclp == NULL) aclp = malloc(cnt * size); else aclp = realloc(NULL, cnt * size); if (aclp != NULL) { if (path != NULL) cnt = acl(path, cmd, cnt, aclp); else cnt = facl(fd, cmd, cnt, aclp); } } else { if (aclp != NULL) { free(aclp); aclp = NULL; } break; } } *aclcnt = cnt; return (aclp); } #endif /* ARCHIVE_ACL_SUNOS */ /* * Set test ACLs on a path * Return values: * 0: error setting ACLs * ARCHIVE_TEST_ACL_TYPE_POSIX1E: POSIX.1E ACLs have been set * ARCHIVE_TEST_ACL_TYPE_NFS4: NFSv4 or extended ACLs have been set */ int setTestAcl(const char *path) { #if ARCHIVE_ACL_SUPPORT int r = 1; #if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN acl_t acl; #endif #if ARCHIVE_ACL_LIBRICHACL struct richacl *richacl; #endif #if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD const char *acltext_posix1e = "user:1:rw-," "group:15:r-x," "user::rwx," "group::rwx," "other::r-x," "mask::rwx"; #elif ARCHIVE_ACL_SUNOS /* Solaris POSIX.1e */ aclent_t aclp_posix1e[] = { { USER_OBJ, -1, 4 | 2 | 1 }, { USER, 1, 4 | 2 }, { GROUP_OBJ, -1, 4 | 2 | 1 }, { GROUP, 15, 4 | 1 }, { CLASS_OBJ, -1, 4 | 2 | 1 }, { OTHER_OBJ, -1, 4 | 2 | 1 } }; #endif #if ARCHIVE_ACL_FREEBSD /* FreeBSD NFS4 */ const char *acltext_nfs4 = "user:1:rwpaRcs::allow:1," "group:15:rxaRcs::allow:15," "owner@:rwpxaARWcCos::allow," "group@:rwpxaRcs::allow," "everyone@:rxaRcs::allow"; #elif ARCHIVE_ACL_LIBRICHACL const char *acltext_nfs4 = "owner:rwpxaARWcCoS::mask," "group:rwpxaRcS::mask," "other:rxaRcS::mask," "user:1:rwpaRcS::allow," "group:15:rxaRcS::allow," "owner@:rwpxaARWcCoS::allow," "group@:rwpxaRcS::allow," "everyone@:rxaRcS::allow"; #elif ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFS4 */ ace_t aclp_nfs4[] = { { 1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE, 0, ACE_ACCESS_ALLOWED_ACE_TYPE }, { 15, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE, ACE_IDENTIFIER_GROUP, ACE_ACCESS_ALLOWED_ACE_TYPE }, { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_WRITE_ATTRIBUTES | ACE_READ_NAMED_ATTRS | ACE_WRITE_NAMED_ATTRS | ACE_READ_ACL | ACE_WRITE_ACL | ACE_WRITE_OWNER | ACE_SYNCHRONIZE, ACE_OWNER, ACE_ACCESS_ALLOWED_ACE_TYPE }, { -1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE, ACE_GROUP | ACE_IDENTIFIER_GROUP, ACE_ACCESS_ALLOWED_ACE_TYPE }, { -1, ACE_READ_DATA | ACE_EXECUTE | ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | ACE_READ_ACL | ACE_SYNCHRONIZE, ACE_EVERYONE, ACE_ACCESS_ALLOWED_ACE_TYPE } }; #elif ARCHIVE_ACL_DARWIN /* Mac OS X */ acl_entry_t aclent; acl_permset_t permset; const uid_t uid = 1; uuid_t uuid; int i; const acl_perm_t acl_perms[] = { ACL_READ_DATA, ACL_WRITE_DATA, ACL_APPEND_DATA, ACL_EXECUTE, ACL_READ_ATTRIBUTES, ACL_READ_EXTATTRIBUTES, ACL_READ_SECURITY, #if HAVE_DECL_ACL_SYNCHRONIZE ACL_SYNCHRONIZE #endif }; #endif /* ARCHIVE_ACL_DARWIN */ #if ARCHIVE_ACL_FREEBSD acl = acl_from_text(acltext_nfs4); failure("acl_from_text() error: %s", strerror(errno)); if (assert(acl != NULL) == 0) return (0); #elif ARCHIVE_ACL_LIBRICHACL richacl = richacl_from_text(acltext_nfs4, NULL, NULL); failure("richacl_from_text() error: %s", strerror(errno)); if (assert(richacl != NULL) == 0) return (0); #elif ARCHIVE_ACL_DARWIN acl = acl_init(1); failure("acl_init() error: %s", strerror(errno)); if (assert(acl != NULL) == 0) return (0); r = acl_create_entry(&acl, &aclent); failure("acl_create_entry() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) goto testacl_free; r = acl_set_tag_type(aclent, ACL_EXTENDED_ALLOW); failure("acl_set_tag_type() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) goto testacl_free; r = acl_get_permset(aclent, &permset); failure("acl_get_permset() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) goto testacl_free; for (i = 0; i < (int)(sizeof(acl_perms) / sizeof(acl_perms[0])); i++) { r = acl_add_perm(permset, acl_perms[i]); failure("acl_add_perm() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) goto testacl_free; } r = acl_set_permset(aclent, permset); failure("acl_set_permset() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) goto testacl_free; r = mbr_uid_to_uuid(uid, uuid); failure("mbr_uid_to_uuid() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) goto testacl_free; r = acl_set_qualifier(aclent, uuid); failure("acl_set_qualifier() error: %s", strerror(errno)); if (assertEqualInt(r, 0) == 0) goto testacl_free; #endif /* ARCHIVE_ACL_DARWIN */ #if ARCHIVE_ACL_NFS4 #if ARCHIVE_ACL_FREEBSD r = acl_set_file(path, ACL_TYPE_NFS4, acl); acl_free(acl); #elif ARCHIVE_ACL_LIBRICHACL r = richacl_set_file(path, richacl); richacl_free(richacl); #elif ARCHIVE_ACL_SUNOS_NFS4 r = acl(path, ACE_SETACL, (int)(sizeof(aclp_nfs4)/sizeof(aclp_nfs4[0])), aclp_nfs4); #elif ARCHIVE_ACL_DARWIN r = acl_set_file(path, ACL_TYPE_EXTENDED, acl); acl_free(acl); #endif if (r == 0) return (ARCHIVE_TEST_ACL_TYPE_NFS4); #endif /* ARCHIVE_ACL_NFS4 */ #if ARCHIVE_ACL_POSIX1E #if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL acl = acl_from_text(acltext_posix1e); failure("acl_from_text() error: %s", strerror(errno)); if (assert(acl != NULL) == 0) return (0); r = acl_set_file(path, ACL_TYPE_ACCESS, acl); acl_free(acl); #elif ARCHIVE_ACL_SUNOS r = acl(path, SETACL, (int)(sizeof(aclp_posix1e)/sizeof(aclp_posix1e[0])), aclp_posix1e); #endif if (r == 0) return (ARCHIVE_TEST_ACL_TYPE_POSIX1E); else return (0); #endif /* ARCHIVE_ACL_POSIX1E */ #if ARCHIVE_ACL_DARWIN testacl_free: acl_free(acl); #endif #endif /* ARCHIVE_ACL_SUPPORT */ (void)path; /* UNUSED */ return (0); } /* * Sleep as needed; useful for verifying disk timestamp changes by * ensuring that the wall-clock time has actually changed before we * go back to re-read something from disk. */ void sleepUntilAfter(time_t t) { while (t >= time(NULL)) #if defined(_WIN32) && !defined(__CYGWIN__) Sleep(500); #else sleep(1); #endif } /* * Call standard system() call, but build up the command line using * sprintf() conventions. */ int systemf(const char *fmt, ...) { char buff[8192]; va_list ap; int r; va_start(ap, fmt); vsprintf(buff, fmt, ap); if (verbosity > VERBOSITY_FULL) logprintf("Cmd: %s\n", buff); r = system(buff); va_end(ap); return (r); } /* * Slurp a file into memory for ease of comparison and testing. * Returns size of file in 'sizep' if non-NULL, null-terminates * data in memory for ease of use. */ char * slurpfile(size_t * sizep, const char *fmt, ...) { char filename[8192]; struct stat st; va_list ap; char *p; ssize_t bytes_read; FILE *f; int r; va_start(ap, fmt); vsprintf(filename, fmt, ap); va_end(ap); f = fopen(filename, "rb"); if (f == NULL) { /* Note: No error; non-existent file is okay here. */ return (NULL); } r = fstat(fileno(f), &st); if (r != 0) { logprintf("Can't stat file %s\n", filename); fclose(f); return (NULL); } p = malloc((size_t)st.st_size + 1); if (p == NULL) { logprintf("Can't allocate %ld bytes of memory to read file %s\n", (long int)st.st_size, filename); fclose(f); return (NULL); } bytes_read = fread(p, 1, (size_t)st.st_size, f); if (bytes_read < st.st_size) { logprintf("Can't read file %s\n", filename); fclose(f); free(p); return (NULL); } p[st.st_size] = '\0'; if (sizep != NULL) *sizep = (size_t)st.st_size; fclose(f); return (p); } /* * Slurp a file into memory for ease of comparison and testing. * Returns size of file in 'sizep' if non-NULL, null-terminates * data in memory for ease of use. */ void dumpfile(const char *filename, void *data, size_t len) { ssize_t bytes_written; FILE *f; f = fopen(filename, "wb"); if (f == NULL) { logprintf("Can't open file %s for writing\n", filename); return; } bytes_written = fwrite(data, 1, len, f); if (bytes_written < (ssize_t)len) logprintf("Can't write file %s\n", filename); fclose(f); } /* Read a uuencoded file from the reference directory, decode, and * write the result into the current directory. */ #define VALID_UUDECODE(c) (c >= 32 && c <= 96) #define UUDECODE(c) (((c) - 0x20) & 0x3f) void extract_reference_file(const char *name) { char buff[1024]; FILE *in, *out; sprintf(buff, "%s/%s.uu", refdir, name); in = fopen(buff, "r"); failure("Couldn't open reference file %s", buff); assert(in != NULL); if (in == NULL) return; /* Read up to and including the 'begin' line. */ for (;;) { if (fgets(buff, sizeof(buff), in) == NULL) { /* TODO: This is a failure. */ return; } if (memcmp(buff, "begin ", 6) == 0) break; } /* Now, decode the rest and write it. */ out = fopen(name, "wb"); while (fgets(buff, sizeof(buff), in) != NULL) { char *p = buff; int bytes; if (memcmp(buff, "end", 3) == 0) break; bytes = UUDECODE(*p++); while (bytes > 0) { int n = 0; /* Write out 1-3 bytes from that. */ if (bytes > 0) { assert(VALID_UUDECODE(p[0])); assert(VALID_UUDECODE(p[1])); n = UUDECODE(*p++) << 18; n |= UUDECODE(*p++) << 12; fputc(n >> 16, out); --bytes; } if (bytes > 0) { assert(VALID_UUDECODE(p[0])); n |= UUDECODE(*p++) << 6; fputc((n >> 8) & 0xFF, out); --bytes; } if (bytes > 0) { assert(VALID_UUDECODE(p[0])); n |= UUDECODE(*p++); fputc(n & 0xFF, out); --bytes; } } } fclose(out); fclose(in); } void copy_reference_file(const char *name) { char buff[1024]; FILE *in, *out; size_t rbytes; sprintf(buff, "%s/%s", refdir, name); in = fopen(buff, "rb"); failure("Couldn't open reference file %s", buff); assert(in != NULL); if (in == NULL) return; /* Now, decode the rest and write it. */ /* Not a lot of error checking here; the input better be right. */ out = fopen(name, "wb"); while ((rbytes = fread(buff, 1, sizeof(buff), in)) > 0) { if (fwrite(buff, 1, rbytes, out) != rbytes) { logprintf("Error: fwrite\n"); break; } } fclose(out); fclose(in); } int is_LargeInode(const char *file) { #if defined(_WIN32) && !defined(__CYGWIN__) BY_HANDLE_FILE_INFORMATION bhfi; int r; r = my_GetFileInformationByName(file, &bhfi); if (r != 0) return (0); return (bhfi.nFileIndexHigh & 0x0000FFFFUL); #else struct stat st; int64_t ino; if (stat(file, &st) < 0) return (0); ino = (int64_t)st.st_ino; return (ino > 0xffffffff); #endif } void extract_reference_files(const char **names) { while (names && *names) extract_reference_file(*names++); } #ifndef PROGRAM /* Set ACLs */ int assertion_entry_set_acls(const char *file, int line, struct archive_entry *ae, struct archive_test_acl_t *acls, int n) { int i, r, ret; assertion_count(file, line); ret = 0; archive_entry_acl_clear(ae); for (i = 0; i < n; i++) { r = archive_entry_acl_add_entry(ae, acls[i].type, acls[i].permset, acls[i].tag, acls[i].qual, acls[i].name); if (r != 0) { ret = 1; failure_start(file, line, "type=%#010x, ", "permset=%#010x, tag=%d, qual=%d name=%s", acls[i].type, acls[i].permset, acls[i].tag, acls[i].qual, acls[i].name); failure_finish(NULL); } } return (ret); } static int archive_test_acl_match(struct archive_test_acl_t *acl, int type, int permset, int tag, int qual, const char *name) { if (type != acl->type) return (0); if (permset != acl->permset) return (0); if (tag != acl->tag) return (0); if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) return (1); if (tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (1); if (tag == ARCHIVE_ENTRY_ACL_EVERYONE) return (1); if (tag == ARCHIVE_ENTRY_ACL_OTHER) return (1); if (qual != acl->qual) return (0); if (name == NULL) { if (acl->name == NULL || acl->name[0] == '\0') return (1); return (0); } if (acl->name == NULL) { if (name[0] == '\0') return (1); return (0); } return (0 == strcmp(name, acl->name)); } /* Compare ACLs */ int assertion_entry_compare_acls(const char *file, int line, struct archive_entry *ae, struct archive_test_acl_t *acls, int cnt, int want_type, int mode) { int *marker; int i, r, n, ret; int type, permset, tag, qual; int matched; const char *name; assertion_count(file, line); ret = 0; n = 0; marker = malloc(sizeof(marker[0]) * cnt); for (i = 0; i < cnt; i++) { if ((acls[i].type & want_type) != 0) { marker[n] = i; n++; } } if (n == 0) { failure_start(file, line, "No ACL's to compare, type mask: %d", want_type); return (1); } while (0 == (r = archive_entry_acl_next(ae, want_type, &type, &permset, &tag, &qual, &name))) { for (i = 0, matched = 0; i < n && !matched; i++) { if (archive_test_acl_match(&acls[marker[i]], type, permset, tag, qual, name)) { /* We found a match; remove it. */ marker[i] = marker[n - 1]; n--; matched = 1; } } if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS && tag == ARCHIVE_ENTRY_ACL_USER_OBJ) { if (!matched) { failure_start(file, line, "No match for " "user_obj perm"); failure_finish(NULL); ret = 1; } if ((permset << 6) != (mode & 0700)) { failure_start(file, line, "USER_OBJ permset " "(%02o) != user mode (%02o)", permset, 07 & (mode >> 6)); failure_finish(NULL); ret = 1; } } else if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS && tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ) { if (!matched) { failure_start(file, line, "No match for " "group_obj perm"); failure_finish(NULL); ret = 1; } if ((permset << 3) != (mode & 0070)) { failure_start(file, line, "GROUP_OBJ permset " "(%02o) != group mode (%02o)", permset, 07 & (mode >> 3)); failure_finish(NULL); ret = 1; } } else if (type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS && tag == ARCHIVE_ENTRY_ACL_OTHER) { if (!matched) { failure_start(file, line, "No match for " "other perm"); failure_finish(NULL); ret = 1; } if ((permset << 0) != (mode & 0007)) { failure_start(file, line, "OTHER permset " "(%02o) != other mode (%02o)", permset, mode & 07); failure_finish(NULL); ret = 1; } } else if (matched != 1) { failure_start(file, line, "Could not find match for " "ACL (type=%#010x,permset=%#010x,tag=%d,qual=%d," "name=``%s'')", type, permset, tag, qual, name); failure_finish(NULL); ret = 1; } } if (r != ARCHIVE_EOF) { failure_start(file, line, "Should not exit before EOF"); failure_finish(NULL); ret = 1; } if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0 && (mode_t)(mode & 0777) != (archive_entry_mode(ae) & 0777)) { failure_start(file, line, "Mode (%02o) and entry mode (%02o) " "mismatch", mode, archive_entry_mode(ae)); failure_finish(NULL); ret = 1; } if (n != 0) { failure_start(file, line, "Could not find match for ACL " "(type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s'')", acls[marker[0]].type, acls[marker[0]].permset, acls[marker[0]].tag, acls[marker[0]].qual, acls[marker[0]].name); failure_finish(NULL); ret = 1; /* Number of ACLs not matched should == 0 */ } free(marker); return (ret); } #endif /* !defined(PROGRAM) */ /* * * TEST management * */ /* * "list.h" is simply created by "grep DEFINE_TEST test_*.c"; it has * a line like * DEFINE_TEST(test_function) * for each test. */ /* Use "list.h" to declare all of the test functions. */ #undef DEFINE_TEST #define DEFINE_TEST(name) void name(void); #include "list.h" /* Use "list.h" to create a list of all tests (functions and names). */ #undef DEFINE_TEST #define DEFINE_TEST(n) { n, #n, 0 }, struct test_list_t tests[] = { #include "list.h" }; /* * Summarize repeated failures in the just-completed test. */ static void test_summarize(int failed, int skips_num) { unsigned int i; switch (verbosity) { case VERBOSITY_SUMMARY_ONLY: printf(failed ? "E" : "."); fflush(stdout); break; case VERBOSITY_PASSFAIL: printf(failed ? "FAIL\n" : skips_num ? "ok (S)\n" : "ok\n"); break; } log_console = (verbosity == VERBOSITY_LIGHT_REPORT); for (i = 0; i < sizeof(failed_lines)/sizeof(failed_lines[0]); i++) { if (failed_lines[i].count > 1 && !failed_lines[i].skip) logprintf("%s:%d: Summary: Failed %d times\n", failed_filename, i, failed_lines[i].count); } /* Clear the failure history for the next file. */ failed_filename = NULL; memset(failed_lines, 0, sizeof(failed_lines)); } /* * Actually run a single test, with appropriate setup and cleanup. */ static int test_run(int i, const char *tmpdir) { char workdir[1024]; char logfilename[64]; int failures_before = failures; int skips_before = skips; int oldumask; switch (verbosity) { case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */ break; case VERBOSITY_PASSFAIL: /* rest of line will include ok/FAIL marker */ printf("%3d: %-64s", i, tests[i].name); fflush(stdout); break; default: /* Title of test, details will follow */ printf("%3d: %s\n", i, tests[i].name); } /* Chdir to the top-level work directory. */ if (!assertChdir(tmpdir)) { fprintf(stderr, "ERROR: Can't chdir to top work dir %s\n", tmpdir); exit(1); } /* Create a log file for this test. */ sprintf(logfilename, "%s.log", tests[i].name); logfile = fopen(logfilename, "w"); fprintf(logfile, "%s\n\n", tests[i].name); /* Chdir() to a work dir for this specific test. */ snprintf(workdir, sizeof(workdir), "%s/%s", tmpdir, tests[i].name); testworkdir = workdir; if (!assertMakeDir(testworkdir, 0755) || !assertChdir(testworkdir)) { fprintf(stderr, "ERROR: Can't chdir to work dir %s\n", testworkdir); exit(1); } /* Explicitly reset the locale before each test. */ setlocale(LC_ALL, "C"); /* Record the umask before we run the test. */ umask(oldumask = umask(0)); /* * Run the actual test. */ (*tests[i].func)(); /* * Clean up and report afterwards. */ testworkdir = NULL; /* Restore umask */ umask(oldumask); /* Reset locale. */ setlocale(LC_ALL, "C"); /* Reset directory. */ if (!assertChdir(tmpdir)) { fprintf(stderr, "ERROR: Couldn't chdir to temp dir %s\n", tmpdir); exit(1); } /* Report per-test summaries. */ tests[i].failures = failures - failures_before; test_summarize(tests[i].failures, skips - skips_before); /* Close the per-test log file. */ fclose(logfile); logfile = NULL; /* If there were no failures, we can remove the work dir and logfile. */ if (tests[i].failures == 0) { if (!keep_temp_files && assertChdir(tmpdir)) { #if defined(_WIN32) && !defined(__CYGWIN__) /* Make sure not to leave empty directories. * Sometimes a processing of closing files used by tests * is not done, then rmdir will be failed and it will * leave a empty test directory. So we should wait a few * seconds and retry rmdir. */ int r, t; for (t = 0; t < 10; t++) { if (t > 0) Sleep(1000); r = systemf("rmdir /S /Q %s", tests[i].name); if (r == 0) break; } systemf("del %s", logfilename); #else systemf("rm -rf %s", tests[i].name); systemf("rm %s", logfilename); #endif } } /* Return appropriate status. */ return (tests[i].failures); } /* * * * MAIN and support routines. * * */ static void usage(const char *program) { static const int limit = sizeof(tests) / sizeof(tests[0]); int i; printf("Usage: %s [options] ...\n", program); printf("Default is to run all tests.\n"); printf("Otherwise, specify the numbers of the tests you wish to run.\n"); printf("Options:\n"); printf(" -d Dump core after any failure, for debugging.\n"); printf(" -k Keep all temp files.\n"); printf(" Default: temp files for successful tests deleted.\n"); #ifdef PROGRAM printf(" -p Path to executable to be tested.\n"); printf(" Default: path taken from " ENVBASE " environment variable.\n"); #endif printf(" -q Quiet.\n"); printf(" -r Path to dir containing reference files.\n"); printf(" Default: Current directory.\n"); printf(" -u Keep running specifies tests until one fails.\n"); printf(" -v Verbose.\n"); printf("Available tests:\n"); for (i = 0; i < limit; i++) printf(" %d: %s\n", i, tests[i].name); exit(1); } static char * get_refdir(const char *d) { size_t tried_size, buff_size; char *buff, *tried, *pwd = NULL, *p = NULL; #ifdef PATH_MAX buff_size = PATH_MAX; #else buff_size = 8192; #endif buff = calloc(buff_size, 1); if (buff == NULL) { fprintf(stderr, "Unable to allocate memory\n"); exit(1); } /* Allocate a buffer to hold the various directories we checked. */ tried_size = buff_size * 2; tried = calloc(tried_size, 1); if (tried == NULL) { fprintf(stderr, "Unable to allocate memory\n"); exit(1); } /* If a dir was specified, try that */ if (d != NULL) { pwd = NULL; snprintf(buff, buff_size, "%s", d); p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); if (p != NULL) goto success; strncat(tried, buff, tried_size - strlen(tried) - 1); strncat(tried, "\n", tried_size - strlen(tried) - 1); goto failure; } /* Get the current dir. */ #ifdef PATH_MAX pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */ #else pwd = getcwd(NULL, 0); #endif while (pwd[strlen(pwd) - 1] == '\n') pwd[strlen(pwd) - 1] = '\0'; /* Look for a known file. */ snprintf(buff, buff_size, "%s", pwd); p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); if (p != NULL) goto success; strncat(tried, buff, tried_size - strlen(tried) - 1); strncat(tried, "\n", tried_size - strlen(tried) - 1); snprintf(buff, buff_size, "%s/test", pwd); p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); if (p != NULL) goto success; strncat(tried, buff, tried_size - strlen(tried) - 1); strncat(tried, "\n", tried_size - strlen(tried) - 1); #if defined(LIBRARY) snprintf(buff, buff_size, "%s/%s/test", pwd, LIBRARY); #else snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM); #endif p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); if (p != NULL) goto success; strncat(tried, buff, tried_size - strlen(tried) - 1); strncat(tried, "\n", tried_size - strlen(tried) - 1); #if defined(PROGRAM_ALIAS) snprintf(buff, buff_size, "%s/%s/test", pwd, PROGRAM_ALIAS); p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); if (p != NULL) goto success; strncat(tried, buff, tried_size - strlen(tried) - 1); strncat(tried, "\n", tried_size - strlen(tried) - 1); #endif if (memcmp(pwd, "/usr/obj", 8) == 0) { snprintf(buff, buff_size, "%s", pwd + 8); p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); if (p != NULL) goto success; strncat(tried, buff, tried_size - strlen(tried) - 1); strncat(tried, "\n", tried_size - strlen(tried) - 1); snprintf(buff, buff_size, "%s/test", pwd + 8); p = slurpfile(NULL, "%s/%s", buff, KNOWNREF); if (p != NULL) goto success; strncat(tried, buff, tried_size - strlen(tried) - 1); strncat(tried, "\n", tried_size - strlen(tried) - 1); } failure: printf("Unable to locate known reference file %s\n", KNOWNREF); printf(" Checked following directories:\n%s\n", tried); printf("Use -r option to specify full path to reference directory\n"); #if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG) DebugBreak(); #endif exit(1); success: free(p); free(pwd); free(tried); /* Copy result into a fresh buffer to reduce memory usage. */ p = strdup(buff); free(buff); return p; } int main(int argc, char **argv) { static const int limit = sizeof(tests) / sizeof(tests[0]); int test_set[sizeof(tests) / sizeof(tests[0])]; int i = 0, j = 0, tests_run = 0, tests_failed = 0, option; time_t now; char *refdir_alloc = NULL; const char *progname; char **saved_argv; const char *tmp, *option_arg, *p; char tmpdir[256], *pwd, *testprogdir, *tmp2 = NULL, *vlevel = NULL; char tmpdir_timestamp[256]; (void)argc; /* UNUSED */ /* Get the current dir. */ #ifdef PATH_MAX pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */ #else pwd = getcwd(NULL, 0); #endif while (pwd[strlen(pwd) - 1] == '\n') pwd[strlen(pwd) - 1] = '\0'; #if defined(HAVE__CrtSetReportMode) && !defined(__WATCOMC__) /* To stop to run the default invalid parameter handler. */ _set_invalid_parameter_handler(invalid_parameter_handler); /* Disable annoying assertion message box. */ _CrtSetReportMode(_CRT_ASSERT, 0); #endif /* * Name of this program, used to build root of our temp directory * tree. */ progname = p = argv[0]; if ((testprogdir = (char *)malloc(strlen(progname) + 1)) == NULL) { fprintf(stderr, "ERROR: Out of memory."); exit(1); } strcpy(testprogdir, progname); while (*p != '\0') { /* Support \ or / dir separators for Windows compat. */ if (*p == '/' || *p == '\\') { progname = p + 1; i = j; } ++p; j++; } testprogdir[i] = '\0'; #if defined(_WIN32) && !defined(__CYGWIN__) if (testprogdir[0] != '/' && testprogdir[0] != '\\' && !(((testprogdir[0] >= 'a' && testprogdir[0] <= 'z') || (testprogdir[0] >= 'A' && testprogdir[0] <= 'Z')) && testprogdir[1] == ':' && (testprogdir[2] == '/' || testprogdir[2] == '\\'))) #else if (testprogdir[0] != '/') #endif { /* Fixup path for relative directories. */ if ((testprogdir = (char *)realloc(testprogdir, strlen(pwd) + 1 + strlen(testprogdir) + 1)) == NULL) { fprintf(stderr, "ERROR: Out of memory."); exit(1); } memmove(testprogdir + strlen(pwd) + 1, testprogdir, strlen(testprogdir) + 1); memcpy(testprogdir, pwd, strlen(pwd)); testprogdir[strlen(pwd)] = '/'; } #ifdef PROGRAM /* Get the target program from environment, if available. */ testprogfile = getenv(ENVBASE); #endif if (getenv("TMPDIR") != NULL) tmp = getenv("TMPDIR"); else if (getenv("TMP") != NULL) tmp = getenv("TMP"); else if (getenv("TEMP") != NULL) tmp = getenv("TEMP"); else if (getenv("TEMPDIR") != NULL) tmp = getenv("TEMPDIR"); else tmp = "/tmp"; /* Allow -d to be controlled through the environment. */ if (getenv(ENVBASE "_DEBUG") != NULL) dump_on_failure = 1; /* Allow -v to be controlled through the environment. */ if (getenv("_VERBOSITY_LEVEL") != NULL) { vlevel = getenv("_VERBOSITY_LEVEL"); verbosity = atoi(vlevel); if (verbosity < VERBOSITY_SUMMARY_ONLY || verbosity > VERBOSITY_FULL) { /* Unsupported verbosity levels are silently ignored */ vlevel = NULL; verbosity = VERBOSITY_PASSFAIL; } } /* Get the directory holding test files from environment. */ refdir = getenv(ENVBASE "_TEST_FILES"); /* * Parse options, without using getopt(), which isn't available * on all platforms. */ ++argv; /* Skip program name */ while (*argv != NULL) { if (**argv != '-') break; p = *argv++; ++p; /* Skip '-' */ while (*p != '\0') { option = *p++; option_arg = NULL; /* If 'opt' takes an argument, parse that. */ if (option == 'p' || option == 'r') { if (*p != '\0') option_arg = p; else if (*argv == NULL) { fprintf(stderr, "Option -%c requires argument.\n", option); usage(progname); } else option_arg = *argv++; p = ""; /* End of this option word. */ } /* Now, handle the option. */ switch (option) { case 'd': dump_on_failure = 1; break; case 'k': keep_temp_files = 1; break; case 'p': #ifdef PROGRAM testprogfile = option_arg; #else fprintf(stderr, "-p option not permitted\n"); usage(progname); #endif break; case 'q': if (!vlevel) verbosity--; break; case 'r': refdir = option_arg; break; case 'u': until_failure++; break; case 'v': if (!vlevel) verbosity++; break; default: fprintf(stderr, "Unrecognized option '%c'\n", option); usage(progname); } } } /* * Sanity-check that our options make sense. */ #ifdef PROGRAM if (testprogfile == NULL) { if ((tmp2 = (char *)malloc(strlen(testprogdir) + 1 + strlen(PROGRAM) + 1)) == NULL) { fprintf(stderr, "ERROR: Out of memory."); exit(1); } strcpy(tmp2, testprogdir); strcat(tmp2, "/"); strcat(tmp2, PROGRAM); testprogfile = tmp2; } { char *testprg; #if defined(_WIN32) && !defined(__CYGWIN__) /* Command.com sometimes rejects '/' separators. */ testprg = strdup(testprogfile); for (i = 0; testprg[i] != '\0'; i++) { if (testprg[i] == '/') testprg[i] = '\\'; } testprogfile = testprg; #endif /* Quote the name that gets put into shell command lines. */ testprg = malloc(strlen(testprogfile) + 3); strcpy(testprg, "\""); strcat(testprg, testprogfile); strcat(testprg, "\""); testprog = testprg; } #endif #if !defined(_WIN32) && defined(SIGPIPE) { /* Ignore SIGPIPE signals */ struct sigaction sa; sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGPIPE, &sa, NULL); } #endif /* * Create a temp directory for the following tests. * Include the time the tests started as part of the name, * to make it easier to track the results of multiple tests. */ now = time(NULL); for (i = 0; ; i++) { strftime(tmpdir_timestamp, sizeof(tmpdir_timestamp), "%Y-%m-%dT%H.%M.%S", localtime(&now)); sprintf(tmpdir, "%s/%s.%s-%03d", tmp, progname, tmpdir_timestamp, i); if (assertMakeDir(tmpdir,0755)) break; if (i >= 999) { fprintf(stderr, "ERROR: Unable to create temp directory %s\n", tmpdir); exit(1); } } /* * If the user didn't specify a directory for locating * reference files, try to find the reference files in * the "usual places." */ refdir = refdir_alloc = get_refdir(refdir); /* * Banner with basic information. */ printf("\n"); printf("If tests fail or crash, details will be in:\n"); printf(" %s\n", tmpdir); printf("\n"); if (verbosity > VERBOSITY_SUMMARY_ONLY) { printf("Reference files will be read from: %s\n", refdir); #ifdef PROGRAM printf("Running tests on: %s\n", testprog); #endif printf("Exercising: "); fflush(stdout); printf("%s\n", EXTRA_VERSION); } else { printf("Running "); fflush(stdout); } /* * Run some or all of the individual tests. */ saved_argv = argv; do { argv = saved_argv; do { int test_num; test_num = get_test_set(test_set, limit, *argv, tests); if (test_num < 0) { printf("*** INVALID Test %s\n", *argv); free(refdir_alloc); free(testprogdir); usage(progname); return (1); } for (i = 0; i < test_num; i++) { tests_run++; if (test_run(test_set[i], tmpdir)) { tests_failed++; if (until_failure) goto finish; } } if (*argv != NULL) argv++; } while (*argv != NULL); } while (until_failure); finish: /* Must be freed after all tests run */ free(tmp2); free(testprogdir); free(pwd); /* * Report summary statistics. */ if (verbosity > VERBOSITY_SUMMARY_ONLY) { printf("\n"); printf("Totals:\n"); printf(" Tests run: %8d\n", tests_run); printf(" Tests failed: %8d\n", tests_failed); printf(" Assertions checked:%8d\n", assertions); printf(" Assertions failed: %8d\n", failures); printf(" Skips reported: %8d\n", skips); } if (failures) { printf("\n"); printf("Failing tests:\n"); for (i = 0; i < limit; ++i) { if (tests[i].failures) printf(" %d: %s (%d failures)\n", i, tests[i].name, tests[i].failures); } printf("\n"); printf("Details for failing tests: %s\n", tmpdir); printf("\n"); } else { if (verbosity == VERBOSITY_SUMMARY_ONLY) printf("\n"); printf("%d tests passed, no failures\n", tests_run); } free(refdir_alloc); /* If the final tmpdir is empty, we can remove it. */ /* This should be the usual case when all tests succeed. */ assertChdir(".."); rmdir(tmpdir); return (tests_failed ? 1 : 0); }