libarchive 3.1.2-218-g00f4bd83 (reduced)

Extract upstream libarchive using the following shell code.

url=git://github.com/libarchive/libarchive.git &&
v=3.1.2-218-g00f4bd83 &&
r=00f4bd83 &&
paths="
  CMakeLists.txt
  COPYING
  CTestConfig.cmake
  build/cmake
  build/pkgconfig
  build/utils
  build/version
  libarchive/*.*
" &&
mkdir libarchive-$v-g$r-reduced &&
git clone $url libarchive-git &&
date=$(cd libarchive-git && git log -n 1 --format='%cd' $r) &&
(cd libarchive-git && git archive --format=tar $r -- $paths) |
(cd libarchive-$v-g$r-reduced && tar xv) &&
fromdos libarchive-$v-g$r-reduced/build/cmake/Find*.cmake &&
echo "g$r date: $date"
This commit is contained in:
LibArchive Upstream 2014-03-17 20:43:07 -07:00 committed by Brad King
parent 35df7c8ba8
commit 64713ae3ff
58 changed files with 4184 additions and 2250 deletions

View File

@ -59,7 +59,7 @@ SET(LIBARCHIVE_VERSION_NUMBER "${_version_number}")
SET(LIBARCHIVE_VERSION_STRING "${VERSION}") SET(LIBARCHIVE_VERSION_STRING "${VERSION}")
# INTERFACE_VERSION increments with every release # INTERFACE_VERSION increments with every release
# libarchive 2.7 == interface version 9 = 2 + 7 # libarchive 2.7 == interface version 9 = 2 + 7
# libarchive 2.8 == interface version 10 = 2 + 8 # libarchive 2.8 == interface version 10 = 2 + 8
# libarchive 2.9 == interface version 11 = 2 + 9 # libarchive 2.9 == interface version 11 = 2 + 9
# libarchive 3.0 == interface version 12 # libarchive 3.0 == interface version 12
@ -97,6 +97,20 @@ IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wmissing-prototypes") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wmissing-prototypes")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wcast-qual") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wcast-qual")
ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$") 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 -Wextra -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 (MSVC) IF (MSVC)
################################################################# #################################################################
# Set compile flags for debug build. # Set compile flags for debug build.
@ -143,6 +157,13 @@ include(CTest)
OPTION(ENABLE_NETTLE "Enable use of Nettle" ON) OPTION(ENABLE_NETTLE "Enable use of Nettle" ON)
OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON) OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
OPTION(ENABLE_LZMA "Enable the use of the system found LZMA library if found" ON)
OPTION(ENABLE_ZLIB "Enable the use of the system found ZLIB library if found" ON)
OPTION(ENABLE_BZip2 "Enable the use of the system found BZip2 library if found" ON)
OPTION(ENABLE_EXPAT "Enable the use of the system found EXPAT library if found" ON)
OPTION(ENABLE_PCREPOSIX "Enable the use of the system found PCREPOSIX library if found" ON)
OPTION(ENABLE_LibGCC "Enable the use of the system found LibGCC library if found" ON)
OPTION(ENABLE_TAR "Enable tar building" ON) OPTION(ENABLE_TAR "Enable tar building" ON)
OPTION(ENABLE_TAR_SHARED "Enable dynamic build of tar" FALSE) OPTION(ENABLE_TAR_SHARED "Enable dynamic build of tar" FALSE)
OPTION(ENABLE_CPIO "Enable cpio building" ON) OPTION(ENABLE_CPIO "Enable cpio building" ON)
@ -151,10 +172,16 @@ OPTION(ENABLE_XATTR "Enable extended attribute support" ON)
OPTION(ENABLE_ACL "Enable ACL support" ON) OPTION(ENABLE_ACL "Enable ACL support" ON)
OPTION(ENABLE_ICONV "Enable iconv support" ON) OPTION(ENABLE_ICONV "Enable iconv support" ON)
OPTION(ENABLE_TEST "Enable unit and regression tests" 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)
SET(POSIX_REGEX_LIB "AUTO" CACHE STRING "Choose what library should provide POSIX regular expression support") 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(ENABLE_SAFESEH "AUTO" CACHE STRING "Enable use of /SAFESEH linker flag (MSVC only)")
SET(WINDOWS_VERSION "" CACHE STRING "Set Windows version to use (Windows only)") SET(WINDOWS_VERSION "" CACHE STRING "Set Windows version to use (Windows only)")
IF(ENABLE_COVERAGE)
include(LibarchiveCodeCoverage)
ENDIF(ENABLE_COVERAGE)
IF(ENABLE_TEST) IF(ENABLE_TEST)
ENABLE_TESTING() ENABLE_TESTING()
ENDIF(ENABLE_TEST) ENDIF(ENABLE_TEST)
@ -184,12 +211,12 @@ IF(MSVC)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH") SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH")
SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH") SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH")
SET(CMAKE_REQUIRED_LINKER_FLAGS "/SAFESEH") SET(ENV{LDFLAGS} "$ENV{LDFLAGS} /SAFESEH")
ELSEIF(ENABLE_SAFESEH STREQUAL "NO") ELSEIF(ENABLE_SAFESEH STREQUAL "NO")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH: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_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO") SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
SET(CMAKE_REQUIRED_LINKER_FLAGS "/SAFESEH:NO") SET(ENV{LDFLAGS} "$ENV{LDFLAGS} /SAFESEH:NO")
ENDIF(ENABLE_SAFESEH STREQUAL "YES") ENDIF(ENABLE_SAFESEH STREQUAL "YES")
ENDIF(MSVC) ENDIF(MSVC)
@ -198,8 +225,8 @@ IF("${CMAKE_C_PLATFORM_ID}" MATCHES "^(HP-UX)$")
ENDIF() ENDIF()
# #
INCLUDE(LibarchiveCheckCSourceCompiles) INCLUDE(CheckCSourceCompiles)
INCLUDE(LibarchiveCheckCSourceRuns) INCLUDE(CheckCSourceRuns)
INCLUDE(CheckFileOffsetBits) INCLUDE(CheckFileOffsetBits)
INCLUDE(CheckFuncs) INCLUDE(CheckFuncs)
INCLUDE(CheckHeaderDirent) INCLUDE(CheckHeaderDirent)
@ -263,9 +290,9 @@ MACRO (TRY_MACRO_FOR_LIBRARY INCLUDES LIBRARIES
ENDIF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}") ENDIF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}")
# Check if the library can be used with the macro. # Check if the library can be used with the macro.
IF("${TRY_TYPE}" MATCHES "COMPILES") IF("${TRY_TYPE}" MATCHES "COMPILES")
LIBARCHIVE_CHECK_C_SOURCE_COMPILES("${SAMPLE_SOURCE}" ${VAR}) CHECK_C_SOURCE_COMPILES("${SAMPLE_SOURCE}" ${VAR})
ELSEIF("${TRY_TYPE}" MATCHES "RUNS") ELSEIF("${TRY_TYPE}" MATCHES "RUNS")
LIBARCHIVE_CHECK_C_SOURCE_RUNS("${SAMPLE_SOURCE}" ${VAR}) CHECK_C_SOURCE_RUNS("${SAMPLE_SOURCE}" ${VAR})
ELSE("${TRY_TYPE}" MATCHES "COMPILES") ELSE("${TRY_TYPE}" MATCHES "COMPILES")
MESSAGE(FATAL_ERROR "UNKNOWN KEYWORD \"${TRY_TYPE}\" FOR TRY_TYPE") MESSAGE(FATAL_ERROR "UNKNOWN KEYWORD \"${TRY_TYPE}\" FOR TRY_TYPE")
ENDIF("${TRY_TYPE}" MATCHES "COMPILES") ENDIF("${TRY_TYPE}" MATCHES "COMPILES")
@ -301,7 +328,7 @@ IF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}")
#--- zconf.h.orig 2005-07-21 00:40:26.000000000 #--- zconf.h.orig 2005-07-21 00:40:26.000000000
#+++ zconf.h 2009-01-19 11:39:10.093750000 #+++ zconf.h 2009-01-19 11:39:10.093750000
#@@ -286,7 +286,7 @@ #@@ -286,7 +286,7 @@
# #
# #if 1 /* HAVE_UNISTD_H -- this line is updated by ./configure */ # #if 1 /* HAVE_UNISTD_H -- this line is updated by ./configure */
# # include <sys/types.h> /* for off_t */ # # include <sys/types.h> /* for off_t */
#-# include <unistd.h> /* for SEEK_* and off_t */ #-# include <unistd.h> /* for SEEK_* and off_t */
@ -315,7 +342,11 @@ SET(ADDITIONAL_LIBS "")
# #
# Find ZLIB # Find ZLIB
# #
FIND_PACKAGE(ZLIB) IF(ENABLE_ZLIB)
FIND_PACKAGE(ZLIB)
ELSE()
SET(ZLIB_FOUND FALSE) # Override cached value
ENDIF()
IF(ZLIB_FOUND) IF(ZLIB_FOUND)
SET(HAVE_LIBZ 1) SET(HAVE_LIBZ 1)
SET(HAVE_ZLIB_H 1) SET(HAVE_ZLIB_H 1)
@ -350,7 +381,11 @@ MARK_AS_ADVANCED(CLEAR ZLIB_LIBRARY)
# #
# Find BZip2 # Find BZip2
# #
FIND_PACKAGE(BZip2) IF(ENABLE_BZip2)
FIND_PACKAGE(BZip2)
ELSE()
SET(BZIP2_FOUND FALSE) # Override cached value
ENDIF()
IF(BZIP2_FOUND) IF(BZIP2_FOUND)
SET(HAVE_LIBBZ2 1) SET(HAVE_LIBBZ2 1)
SET(HAVE_BZLIB_H 1) SET(HAVE_BZLIB_H 1)
@ -370,10 +405,18 @@ IF(BZIP2_FOUND)
ENDIF(BZIP2_FOUND) ENDIF(BZIP2_FOUND)
MARK_AS_ADVANCED(CLEAR BZIP2_INCLUDE_DIR) MARK_AS_ADVANCED(CLEAR BZIP2_INCLUDE_DIR)
MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES) MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES)
# #
# Find LZMA # Find LZMA
# #
FIND_PACKAGE(LZMA) IF(ENABLE_LZMA)
FIND_PACKAGE(LZMA)
ELSE()
SET(LZMA_FOUND FALSE) # Override cached value
SET(LZMADEC_FOUND FALSE) # Override cached value
ENDIF()
IF(LZMA_FOUND) IF(LZMA_FOUND)
SET(HAVE_LIBLZMA 1) SET(HAVE_LIBLZMA 1)
SET(HAVE_LZMA_H 1) SET(HAVE_LZMA_H 1)
@ -393,6 +436,8 @@ ELSEIF(LZMADEC_FOUND)
SET(HAVE_LZMADEC_H 1) SET(HAVE_LZMADEC_H 1)
INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES}) LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES})
ELSE(LZMA_FOUND)
# LZMA not found and will not be used.
ENDIF(LZMA_FOUND) ENDIF(LZMA_FOUND)
# #
# Find LZO2 # Find LZO2
@ -444,7 +489,7 @@ LA_CHECK_INCLUDE_FILE("dlfcn.h" HAVE_DLFCN_H)
LA_CHECK_INCLUDE_FILE("errno.h" HAVE_ERRNO_H) LA_CHECK_INCLUDE_FILE("errno.h" HAVE_ERRNO_H)
LA_CHECK_INCLUDE_FILE("ext2fs/ext2_fs.h" HAVE_EXT2FS_EXT2_FS_H) LA_CHECK_INCLUDE_FILE("ext2fs/ext2_fs.h" HAVE_EXT2FS_EXT2_FS_H)
LIBARCHIVE_CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h> CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
#include <ext2fs/ext2_fs.h> #include <ext2fs/ext2_fs.h>
int main(void) { return EXT2_IOC_GETFLAGS; }" HAVE_WORKING_EXT2_IOC_GETFLAGS) int main(void) { return EXT2_IOC_GETFLAGS; }" HAVE_WORKING_EXT2_IOC_GETFLAGS)
@ -507,7 +552,7 @@ FOREACH (it ${_HEADER})
SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n") SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
ENDFOREACH (it) ENDFOREACH (it)
LIBARCHIVE_CHECK_C_SOURCE_COMPILES( CHECK_C_SOURCE_COMPILES(
"#define __EXTENSIONS__ 1 "#define __EXTENSIONS__ 1
${_INCLUDE_FILES} ${_INCLUDE_FILES}
int main() { return 0;}" int main() { return 0;}"
@ -619,16 +664,10 @@ main(int argc, char **argv)
FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c" "${SOURCE}") FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c" "${SOURCE}")
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}") MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}")
IF(CMAKE_REQUIRED_LINKER_FLAGS)
SET(CHECK_CRYPTO_ADD_LINKER_FLAGS
"-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
ELSE(CMAKE_REQUIRED_LINKER_FLAGS)
SET(CHECK_CRYPTO_ADD_LINKER_FLAGS)
ENDIF(CMAKE_REQUIRED_LINKER_FLAGS)
TRY_COMPILE(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} TRY_COMPILE(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}
${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c
CMAKE_FLAGS ${CHECK_CRYPTO_ADD_LINKER_FLAGS} CMAKE_FLAGS
"${TRY_CRYPTO_REQUIRED_LIBS}" "${TRY_CRYPTO_REQUIRED_LIBS}"
"${TRY_CRYPTO_REQUIRED_INCLUDES}" "${TRY_CRYPTO_REQUIRED_INCLUDES}"
OUTPUT_VARIABLE OUTPUT) OUTPUT_VARIABLE OUTPUT)
@ -713,16 +752,10 @@ main(int argc, char **argv)
FILE(WRITE "${SOURCE_FILE}" "${SOURCE}") FILE(WRITE "${SOURCE_FILE}" "${SOURCE}")
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN") MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN")
IF(CMAKE_REQUIRED_LINKER_FLAGS)
SET(CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS
"-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
ELSE(CMAKE_REQUIRED_LINKER_FLAGS)
SET(CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS)
ENDIF(CMAKE_REQUIRED_LINKER_FLAGS)
TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN
${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}
${SOURCE_FILE} ${SOURCE_FILE}
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive" ${CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS} CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive"
OUTPUT_VARIABLE OUTPUT) OUTPUT_VARIABLE OUTPUT)
IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN) IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
@ -768,7 +801,7 @@ MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX") SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX")
ENDIF (MSVC) ENDIF (MSVC)
# #
LIBARCHIVE_CHECK_C_SOURCE_COMPILES( CHECK_C_SOURCE_COMPILES(
"#include <stdlib.h> "#include <stdlib.h>
#include <iconv.h> #include <iconv.h>
int main() { int main() {
@ -883,8 +916,8 @@ ENDIF(ENABLE_ICONV)
# #
# Find Libxml2 # Find Libxml2
#
FIND_PACKAGE(LibXml2) FIND_PACKAGE(LibXml2)
#
IF(LIBXML2_FOUND) IF(LIBXML2_FOUND)
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
@ -979,8 +1012,16 @@ IF(NOT FOUND_POSIX_REGEX_LIB AND POSIX_REGEX_LIB MATCHES "^(AUTO|LIBPCREPOSIX)$"
# #
# If requested, try finding library for PCREPOSIX # If requested, try finding library for PCREPOSIX
# #
FIND_PACKAGE(LibGCC) IF(ENABLE_LibGCC)
FIND_PACKAGE(PCREPOSIX) 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) IF(PCREPOSIX_FOUND)
INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${PCREPOSIX_LIBRARIES}) LIST(APPEND ADDITIONAL_LIBS ${PCREPOSIX_LIBRARIES})
@ -1131,14 +1172,14 @@ CMAKE_POP_CHECK_STATE() # Restore the state of the variables
# Make sure we have the POSIX version of readdir_r, not the # Make sure we have the POSIX version of readdir_r, not the
# older 2-argument version. # older 2-argument version.
LIBARCHIVE_CHECK_C_SOURCE_COMPILES( CHECK_C_SOURCE_COMPILES(
"#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}" "#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}"
HAVE_READDIR_R) HAVE_READDIR_R)
# Only detect readlinkat() if we also have AT_FDCWD in unistd.h. # Only detect readlinkat() if we also have AT_FDCWD in unistd.h.
# NOTE: linux requires fcntl.h for AT_FDCWD. # NOTE: linux requires fcntl.h for AT_FDCWD.
LIBARCHIVE_CHECK_C_SOURCE_COMPILES( CHECK_C_SOURCE_COMPILES(
"#include <fcntl.h>\n#include <unistd.h>\nint main() {char buf[10]; return readlinkat(AT_FDCWD, \"\", buf, 0);}" "#include <fcntl.h>\n#include <unistd.h>\nint main() {char buf[10]; return readlinkat(AT_FDCWD, \"\", buf, 0);}"
HAVE_READLINKAT) HAVE_READLINKAT)
@ -1147,10 +1188,10 @@ LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
# of interest and verify that the result can be linked. # of interest and verify that the result can be linked.
# CHECK_FUNCTION_EXISTS doesn't accept a header argument, # CHECK_FUNCTION_EXISTS doesn't accept a header argument,
# CHECK_SYMBOL_EXISTS doesn't test linkage. # CHECK_SYMBOL_EXISTS doesn't test linkage.
LIBARCHIVE_CHECK_C_SOURCE_COMPILES( CHECK_C_SOURCE_COMPILES(
"#include <sys/mkdev.h>\nint main() { return major(256); }" "#include <sys/mkdev.h>\nint main() { return major(256); }"
MAJOR_IN_MKDEV) MAJOR_IN_MKDEV)
LIBARCHIVE_CHECK_C_SOURCE_COMPILES( CHECK_C_SOURCE_COMPILES(
"#include <sys/sysmacros.h>\nint main() { return major(256); }" "#include <sys/sysmacros.h>\nint main() { return major(256); }"
MAJOR_IN_SYSMACROS) MAJOR_IN_SYSMACROS)
@ -1242,13 +1283,13 @@ CHECK_TYPE_SIZE("unsigned long long" SIZE_OF_UNSIGNED_LONG_LONG)
CHECK_TYPE_SIZE("__int64" __INT64) CHECK_TYPE_SIZE("__int64" __INT64)
CHECK_TYPE_SIZE("unsigned __int64" UNSIGNED___INT64) CHECK_TYPE_SIZE("unsigned __int64" UNSIGNED___INT64)
CHECK_TYPE_SIZE(int16_t INT16_T) CHECK_TYPE_SIZE(int16_t INT16_T)
CHECK_TYPE_SIZE(int32_t INT32_T) CHECK_TYPE_SIZE(int32_t INT32_T)
CHECK_TYPE_SIZE(int64_t INT64_T) CHECK_TYPE_SIZE(int64_t INT64_T)
CHECK_TYPE_SIZE(intmax_t INTMAX_T) CHECK_TYPE_SIZE(intmax_t INTMAX_T)
CHECK_TYPE_SIZE(uint8_t UINT8_T) CHECK_TYPE_SIZE(uint8_t UINT8_T)
CHECK_TYPE_SIZE(uint16_t UINT16_T) CHECK_TYPE_SIZE(uint16_t UINT16_T)
CHECK_TYPE_SIZE(uint32_t UINT32_T) CHECK_TYPE_SIZE(uint32_t UINT32_T)
CHECK_TYPE_SIZE(uint64_t UINT64_T) CHECK_TYPE_SIZE(uint64_t UINT64_T)
CHECK_TYPE_SIZE(uintmax_t UINTMAX_T) CHECK_TYPE_SIZE(uintmax_t UINTMAX_T)
@ -1491,6 +1532,9 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
ADD_DEFINITIONS(-DHAVE_CONFIG_H) ADD_DEFINITIONS(-DHAVE_CONFIG_H)
# Handle generation of the libarchive.pc file for pkg-config
INCLUDE(CreatePkgConfigFile)
# #
# Register installation of PDF documents. # Register installation of PDF documents.
# #

View File

@ -0,0 +1,31 @@
# - Generate a libarchive.pc like autotools for pkg-config
#
# Set the required variables (we use the same input file as autotools)
SET(prefix ${CMAKE_INSTALL_PREFIX})
SET(exec_prefix \${prefix})
SET(libdir \${exec_prefix}/lib)
SET(includedir \${prefix}/include)
# Now, this is not particularly pretty, nor is it terribly accurate...
# Loop over all our additional libs
FOREACH(mylib ${ADDITIONAL_LIBS})
# Extract the filename from the absolute path
GET_FILENAME_COMPONENT(mylib_name ${mylib} NAME_WE)
# Strip the lib prefix
STRING(REGEX REPLACE "^lib" "" mylib_name ${mylib_name})
# Append it to our LIBS string
SET(LIBS "${LIBS} -l${mylib_name}")
ENDFOREACH()
# libxml2 is easier, since it's already using pkg-config
FOREACH(mylib ${PC_LIBXML_STATIC_LDFLAGS})
SET(LIBS "${LIBS} ${mylib}")
ENDFOREACH()
# FIXME: The order of the libraries doesn't take dependencies into account,
# thus there's a good chance it'll make some binutils versions unhappy...
# This only affects Libs.private (looked up for static builds) though.
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc.in
${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc
@ONLY)
# And install it, of course ;).
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc
DESTINATION "lib/pkgconfig")

View File

@ -1,106 +0,0 @@
# - Check if given C source compiles and links into an executable
# CHECK_C_SOURCE_COMPILES(<code> <var> [FAIL_REGEX <fail-regex>])
# <code> - source code to try to compile, must define 'main'
# <var> - variable to store whether the source code compiled
# <fail-regex> - fail if test output matches this regex
# The following variables may be set before calling this macro to
# modify the way the check is run:
#
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_INCLUDES = list of include directories
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
#=============================================================================
# Copyright 2005-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
#
# Extra arguments added by libarchive
# CMAKE_REQUIRED_LINKER_FLAGS = string of linker command line flags
#
include(CMakeExpandImportedTargets)
macro(LIBARCHIVE_CHECK_C_SOURCE_COMPILES SOURCE VAR)
if("${VAR}" MATCHES "^${VAR}$")
set(_FAIL_REGEX)
set(_key)
foreach(arg ${ARGN})
if("${arg}" MATCHES "^(FAIL_REGEX)$")
set(_key "${arg}")
elseif(_key)
list(APPEND _${_key} "${arg}")
else()
message(FATAL_ERROR "Unknown argument:\n ${arg}\n")
endif()
endforeach()
set(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
if(CMAKE_REQUIRED_LIBRARIES)
# this one translates potentially used imported library targets to their files on disk
CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}")
set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}")
else()
set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES)
endif()
if(CMAKE_REQUIRED_INCLUDES)
set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
else()
set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES)
endif()
if(CMAKE_REQUIRED_LINKER_FLAGS)
set(CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS
"-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
else()
set(CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS)
endif()
file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c"
"${SOURCE}\n")
message(STATUS "Performing Test ${VAR}")
try_compile(${VAR}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} ${CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS}
"${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}"
"${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
foreach(_regex ${_FAIL_REGEX})
if("${OUTPUT}" MATCHES "${_regex}")
set(${VAR} 0)
endif()
endforeach()
if(${VAR})
set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
message(STATUS "Performing Test ${VAR} - Success")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SOURCE}\n")
else()
message(STATUS "Performing Test ${VAR} - Failed")
set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SOURCE}\n")
endif()
endif()
endmacro()

View File

@ -1,102 +0,0 @@
# - Check if the given C source code compiles and runs.
# CHECK_C_SOURCE_RUNS(<code> <var>)
# <code> - source code to try to compile
# <var> - variable to store the result
# (1 for success, empty for failure)
# The following variables may be set before calling this macro to
# modify the way the check is run:
#
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_INCLUDES = list of include directories
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
#=============================================================================
# Copyright 2006-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
#
# Extra arguments added by libarchive
# CMAKE_REQUIRED_LINKER_FLAGS = string of linker command line flags
#
include(CMakeExpandImportedTargets)
macro(LIBARCHIVE_CHECK_C_SOURCE_RUNS SOURCE VAR)
if("${VAR}" MATCHES "^${VAR}$")
set(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
if(CMAKE_REQUIRED_LIBRARIES)
# this one translates potentially used imported library targets to their files on disk
CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}")
set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}")
else()
set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES)
endif()
if(CMAKE_REQUIRED_INCLUDES)
set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
else()
set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES)
endif()
if(CMAKE_REQUIRED_LINKER_FLAGS)
set(CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS
"-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
else()
set(CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS)
endif()
file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c"
"${SOURCE}\n")
message(STATUS "Performing Test ${VAR}")
try_run(${VAR}_EXITCODE ${VAR}_COMPILED
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} ${CHECK_C_SOURCE_COMPILES_ADD_LINKER_FLAGS}
-DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
"${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}"
"${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}"
COMPILE_OUTPUT_VARIABLE OUTPUT)
# if it did not compile make the return value fail code of 1
if(NOT ${VAR}_COMPILED)
set(${VAR}_EXITCODE 1)
endif()
# if the return value was 0 then it worked
if("${${VAR}_EXITCODE}" EQUAL 0)
set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
message(STATUS "Performing Test ${VAR} - Success")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n"
"${OUTPUT}\n"
"Return value: ${${VAR}}\n"
"Source file was:\n${SOURCE}\n")
else()
if(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN")
set(${VAR} "${${VAR}_EXITCODE}")
else()
set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
endif()
message(STATUS "Performing Test ${VAR} - Failed")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
"${OUTPUT}\n"
"Return value: ${${VAR}_EXITCODE}\n"
"Source file was:\n${SOURCE}\n")
endif()
endif()
endmacro()

View File

@ -0,0 +1,68 @@
#################################################################
# Adds a build target called "coverage" for code coverage.
#
# This compiles the code using special GCC flags, run the tests,
# and then generates a nice HTML output. This new "coverage" make
# target will only be available if you build using GCC in Debug
# mode. If any of the required programs (lcov and genhtml) were
# not found, a FATAL_ERROR message is printed.
#
# If not already done, this code will set ENABLE_TEST to ON.
#
# To build the code coverage and open it in your browser do this:
#
# mkdir debug
# cd debug
# cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_COVERAGE=ON ..
# make -j4
# make coverage
# xdg-open coverage/index.html
#################################################################
# Find programs we need
FIND_PROGRAM(LCOV_EXECUTABLE lcov DOC "Full path to lcov executable")
FIND_PROGRAM(GENHTML_EXECUTABLE genhtml DOC "Full path to genhtml executable")
MARK_AS_ADVANCED(LCOV_EXECUTABLE GENHTML_EXECUTABLE)
# Check, compiler, build types and programs are available
IF(NOT CMAKE_COMPILER_IS_GNUCC)
MESSAGE(FATAL_ERROR "Coverage can only be built on GCC")
ELSEIF(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
MESSAGE(FATAL_ERROR "Coverage can only be built in Debug mode")
ELSEIF(NOT LCOV_EXECUTABLE)
MESSAGE(FATAL_ERROR "lcov executable not found")
ELSEIF(NOT GENHTML_EXECUTABLE)
MESSAGE(FATAL_ERROR "genhtml executable not found")
ENDIF(NOT CMAKE_COMPILER_IS_GNUCC)
# Enable testing if not already done
SET(ENABLE_TEST ON)
#################################################################
# Set special compiler and linker flags for test coverage
#################################################################
# 0. Enable debug: -g
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
# 1. Disable optimizations: -O0
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
# 2. Enable all kind of warnings:
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W")
# 3. Enable special coverage flag (HINT: --coverage is a synonym for -fprofile-arcs -ftest-coverage)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
#################################################################
ADD_CUSTOM_TARGET(coverage
COMMAND ${CMAKE_COMMAND} -E echo "Beginning test coverage. Output is written to coverage.log."
COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-1/5: Reset all execution counts to zero"
COMMAND ${LCOV_EXECUTABLE} --directory . --zerocounters > coverage.log 2>&1
COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-2/5: Run testrunner"
COMMAND ${CMAKE_CTEST_COMMAND} >> coverage.log 2>&1
COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-3/5: Collect coverage data"
COMMAND ${LCOV_EXECUTABLE} --capture --directory . --output-file "./coverage.info" >> coverage.log 2>&1
COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-4/5: Generate HTML from coverage data"
COMMAND ${GENHTML_EXECUTABLE} "coverage.info" --title="libarchive-${LIBARCHIVE_VERSION_STRING}" --show-details --legend --output-directory "./coverage" >> coverage.log 2>&1
COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-5/5: Open test coverage HTML output in browser: xdg-open ./coverage/index.html"
COMMENT "Runs testrunner and generates coverage output (formats: .info and .html)")

View File

@ -1106,8 +1106,13 @@ typedef uint64_t uintmax_t;
#cmakedefine _LARGE_FILES ${_LARGE_FILES} #cmakedefine _LARGE_FILES ${_LARGE_FILES}
/* Define for Windows to use Windows 2000+ APIs. */ /* Define for Windows to use Windows 2000+ APIs. */
#ifndef _WIN32_WINNT
#cmakedefine _WIN32_WINNT ${_WIN32_WINNT} #cmakedefine _WIN32_WINNT ${_WIN32_WINNT}
#endif // _WIN32_WINNT
#ifndef WINVER
#cmakedefine WINVER ${WINVER} #cmakedefine WINVER ${WINVER}
#endif // WINVER
/* Define to empty if `const' does not conform to ANSI C. */ /* Define to empty if `const' does not conform to ANSI C. */
#cmakedefine const ${const} #cmakedefine const ${const}

View File

@ -35,6 +35,8 @@ SET(libarchive_SOURCES
archive_match.c archive_match.c
archive_options.c archive_options.c
archive_options_private.h archive_options_private.h
archive_pack_dev.h
archive_pack_dev.c
archive_pathmatch.c archive_pathmatch.c
archive_pathmatch.h archive_pathmatch.h
archive_platform.h archive_platform.h
@ -125,6 +127,7 @@ SET(libarchive_SOURCES
archive_write_set_format_iso9660.c archive_write_set_format_iso9660.c
archive_write_set_format_mtree.c archive_write_set_format_mtree.c
archive_write_set_format_pax.c archive_write_set_format_pax.c
archive_write_set_format_raw.c
archive_write_set_format_shar.c archive_write_set_format_shar.c
archive_write_set_format_ustar.c archive_write_set_format_ustar.c
archive_write_set_format_v7tar.c archive_write_set_format_v7tar.c

View File

@ -47,7 +47,7 @@
/* Get appropriate definitions of standard POSIX-style types. */ /* Get appropriate definitions of standard POSIX-style types. */
/* These should match the types used in 'struct stat' */ /* These should match the types used in 'struct stat' */
#if defined(_WIN32) && !defined(__CYGWIN__) #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
# define __LA_INT64_T __int64 # define __LA_INT64_T __int64
# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) # if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
# define __LA_SSIZE_T ssize_t # define __LA_SSIZE_T ssize_t
@ -133,6 +133,11 @@ __LA_DECL int archive_version_number(void);
#define ARCHIVE_VERSION_STRING "libarchive 3.1.2" #define ARCHIVE_VERSION_STRING "libarchive 3.1.2"
__LA_DECL const char * archive_version_string(void); __LA_DECL const char * archive_version_string(void);
/*
* Detailed textual name/version of the library and its dependencies.
*/
__LA_DECL const char * archive_version_details(void);
/* Declare our basic types. */ /* Declare our basic types. */
struct archive; struct archive;
struct archive_entry; struct archive_entry;
@ -285,6 +290,30 @@ typedef int archive_switch_callback(struct archive *, void *_client_data1,
#define ARCHIVE_FORMAT_RAR 0xD0000 #define ARCHIVE_FORMAT_RAR 0xD0000
#define ARCHIVE_FORMAT_7ZIP 0xE0000 #define ARCHIVE_FORMAT_7ZIP 0xE0000
/*
* Codes returned by archive_read_format_capabilities().
*
* This list can be extended with values between 0 and 0xffff.
* The original purpose of this list was to let different archive
* format readers expose their general capabilities in terms of
* encryption.
*/
#define ARCHIVE_READ_FORMAT_CAPS_NONE (0) /* no special capabilities */
#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA (1<<0) /* reader can detect encrypted data */
#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA (1<<1) /* reader can detect encryptable metadata (pathname, mtime, etc.) */
/*
* Codes returned by archive_read_has_encrypted_entries().
*
* In case the archive does not support encryption detection at all
* ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. If the reader
* for some other reason (e.g. not enough bytes read) cannot say if
* there are encrypted entries, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW
* is returned.
*/
#define ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED -2
#define ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW -1
/*- /*-
* Basic outline for reading an archive: * Basic outline for reading an archive:
* 1) Ask archive_read_new for an archive reader object. * 1) Ask archive_read_new for an archive reader object.
@ -370,7 +399,15 @@ __LA_DECL int archive_read_support_format_rar(struct archive *);
__LA_DECL int archive_read_support_format_raw(struct archive *); __LA_DECL int archive_read_support_format_raw(struct archive *);
__LA_DECL int archive_read_support_format_tar(struct archive *); __LA_DECL int archive_read_support_format_tar(struct archive *);
__LA_DECL int archive_read_support_format_xar(struct archive *); __LA_DECL int archive_read_support_format_xar(struct archive *);
/* archive_read_support_format_zip() enables both streamable and seekable
* zip readers. */
__LA_DECL int archive_read_support_format_zip(struct archive *); __LA_DECL int archive_read_support_format_zip(struct archive *);
/* Reads Zip archives as stream from beginning to end. Doesn't
* correctly handle SFX ZIP files or ZIP archives that have been modified
* in-place. */
__LA_DECL int archive_read_support_format_zip_streamable(struct archive *);
/* Reads starting from central directory; requires seekable input. */
__LA_DECL int archive_read_support_format_zip_seekable(struct archive *);
/* Functions to manually set the format and filters to be used. This is /* Functions to manually set the format and filters to be used. This is
* useful to bypass the bidding process when the format and filters to use * useful to bypass the bidding process when the format and filters to use
@ -466,6 +503,32 @@ __LA_DECL int archive_read_next_header2(struct archive *,
*/ */
__LA_DECL __LA_INT64_T archive_read_header_position(struct archive *); __LA_DECL __LA_INT64_T archive_read_header_position(struct archive *);
/*
* Returns 1 if the archive contains at least one encrypted entry.
* If the archive format not support encryption at all
* ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
* If for any other reason (e.g. not enough data read so far)
* we cannot say whether there are encrypted entries, then
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
* In general, this function will return values below zero when the
* reader is uncertain or totally uncapable of encryption support.
* When this function returns 0 you can be sure that the reader
* supports encryption detection but no encrypted entries have
* been found yet.
*
* NOTE: If the metadata/header of an archive is also encrypted, you
* cannot rely on the number of encrypted entries. That is why this
* function does not return the number of encrypted entries but#
* just shows that there are some.
*/
__LA_DECL int archive_read_has_encrypted_entries(struct archive *);
/*
* Returns a bitmask of capabilities that are supported by the archive format reader.
* If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
*/
__LA_DECL int archive_read_format_capabilities(struct archive *);
/* Read data from the body of an entry. Similar to read(2). */ /* Read data from the body of an entry. Similar to read(2). */
__LA_DECL __LA_SSIZE_T archive_read_data(struct archive *, __LA_DECL __LA_SSIZE_T archive_read_data(struct archive *,
void *, size_t); void *, size_t);
@ -670,6 +733,7 @@ __LA_DECL int archive_write_set_format_mtree_classic(struct archive *);
/* TODO: int archive_write_set_format_old_tar(struct archive *); */ /* TODO: int archive_write_set_format_old_tar(struct archive *); */
__LA_DECL int archive_write_set_format_pax(struct archive *); __LA_DECL int archive_write_set_format_pax(struct archive *);
__LA_DECL int archive_write_set_format_pax_restricted(struct archive *); __LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
__LA_DECL int archive_write_set_format_raw(struct archive *);
__LA_DECL int archive_write_set_format_shar(struct archive *); __LA_DECL int archive_write_set_format_shar(struct archive *);
__LA_DECL int archive_write_set_format_shar_dump(struct archive *); __LA_DECL int archive_write_set_format_shar_dump(struct archive *);
__LA_DECL int archive_write_set_format_ustar(struct archive *); __LA_DECL int archive_write_set_format_ustar(struct archive *);
@ -879,6 +943,10 @@ __LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *,
int (*_metadata_filter_func)(struct archive *, void *, int (*_metadata_filter_func)(struct archive *, void *,
struct archive_entry *), void *_client_data); struct archive_entry *), void *_client_data);
/* Simplified cleanup interface;
* This calls archive_read_free() or archive_write_free() as needed. */
__LA_DECL int archive_free(struct archive *);
/* /*
* Accessor functions to read/set various information in * Accessor functions to read/set various information in
* the struct archive object: * the struct archive object:
@ -1025,6 +1093,10 @@ __LA_DECL int archive_match_include_gname(struct archive *, const char *);
__LA_DECL int archive_match_include_gname_w(struct archive *, __LA_DECL int archive_match_include_gname_w(struct archive *,
const wchar_t *); const wchar_t *);
/* Utility functions */
/* Convenience function to sort a NULL terminated list of strings */
__LA_DECL int archive_utility_string_sort(char **);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -58,7 +58,13 @@ archive_be16dec(const void *pp)
{ {
unsigned char const *p = (unsigned char const *)pp; unsigned char const *p = (unsigned char const *)pp;
return ((p[0] << 8) | p[1]); /* Store into unsigned temporaries before left shifting, to avoid
promotion to signed int and then left shifting into the sign bit,
which is undefined behaviour. */
unsigned int p1 = p[1];
unsigned int p0 = p[0];
return ((p0 << 8) | p1);
} }
static inline uint32_t static inline uint32_t
@ -66,7 +72,15 @@ archive_be32dec(const void *pp)
{ {
unsigned char const *p = (unsigned char const *)pp; unsigned char const *p = (unsigned char const *)pp;
return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); /* Store into unsigned temporaries before left shifting, to avoid
promotion to signed int and then left shifting into the sign bit,
which is undefined behaviour. */
unsigned int p3 = p[3];
unsigned int p2 = p[2];
unsigned int p1 = p[1];
unsigned int p0 = p[0];
return ((p0 << 24) | (p1 << 16) | (p2 << 8) | p3);
} }
static inline uint64_t static inline uint64_t
@ -82,7 +96,13 @@ archive_le16dec(const void *pp)
{ {
unsigned char const *p = (unsigned char const *)pp; unsigned char const *p = (unsigned char const *)pp;
return ((p[1] << 8) | p[0]); /* Store into unsigned temporaries before left shifting, to avoid
promotion to signed int and then left shifting into the sign bit,
which is undefined behaviour. */
unsigned int p1 = p[1];
unsigned int p0 = p[0];
return ((p1 << 8) | p0);
} }
static inline uint32_t static inline uint32_t
@ -90,7 +110,15 @@ archive_le32dec(const void *pp)
{ {
unsigned char const *p = (unsigned char const *)pp; unsigned char const *p = (unsigned char const *)pp;
return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); /* Store into unsigned temporaries before left shifting, to avoid
promotion to signed int and then left shifting into the sign bit,
which is undefined behaviour. */
unsigned int p3 = p[3];
unsigned int p2 = p[2];
unsigned int p1 = p[1];
unsigned int p0 = p[0];
return ((p3 << 24) | (p2 << 16) | (p1 << 8) | p0);
} }
static inline uint64_t static inline uint64_t

View File

@ -201,6 +201,9 @@ archive_entry_clone(struct archive_entry *entry)
entry2->ae_set = entry->ae_set; entry2->ae_set = entry->ae_set;
archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname); archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
/* Copy encryption status */
entry2->encryption = entry->encryption;
/* Copy ACL data over. */ /* Copy ACL data over. */
archive_acl_copy(&entry2->acl, &entry->acl); archive_acl_copy(&entry2->acl, &entry->acl);
@ -695,6 +698,24 @@ _archive_entry_uname_l(struct archive_entry *entry,
return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, 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. * Functions to set archive_entry properties.
*/ */
@ -1216,6 +1237,26 @@ archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
return (0); 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 int
_archive_entry_copy_uname_l(struct archive_entry *entry, _archive_entry_copy_uname_l(struct archive_entry *entry,
const char *name, size_t len, struct archive_string_conv *sc) const char *name, size_t len, struct archive_string_conv *sc)

View File

@ -43,12 +43,8 @@
#include <stddef.h> /* for wchar_t */ #include <stddef.h> /* for wchar_t */
#include <time.h> #include <time.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#endif
/* Get a suitable 64-bit integer type. */ /* Get a suitable 64-bit integer type. */
#if defined(_WIN32) && !defined(__CYGWIN__) #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
# define __LA_INT64_T __int64 # define __LA_INT64_T __int64
#else #else
#include <unistd.h> #include <unistd.h>
@ -63,7 +59,7 @@
#if ARCHIVE_VERSION_NUMBER >= 3999000 #if ARCHIVE_VERSION_NUMBER >= 3999000
/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ /* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */
# define __LA_MODE_T int # define __LA_MODE_T int
#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) #elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) && !defined(__WATCOMC__)
# define __LA_MODE_T unsigned short # define __LA_MODE_T unsigned short
#else #else
# define __LA_MODE_T mode_t # define __LA_MODE_T mode_t
@ -235,6 +231,9 @@ __LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *);
__LA_DECL __LA_INT64_T archive_entry_uid(struct archive_entry *); __LA_DECL __LA_INT64_T archive_entry_uid(struct archive_entry *);
__LA_DECL const char *archive_entry_uname(struct archive_entry *); __LA_DECL const char *archive_entry_uname(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *); __LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *);
__LA_DECL int archive_entry_is_data_encrypted(struct archive_entry *);
__LA_DECL int archive_entry_is_metadata_encrypted(struct archive_entry *);
__LA_DECL int archive_entry_is_encrypted(struct archive_entry *);
/* /*
* Set fields in an archive_entry. * Set fields in an archive_entry.
@ -306,6 +305,8 @@ __LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *); __LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *); __LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *); __LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_is_data_encrypted(struct archive_entry *, char is_encrypted);
__LA_DECL void archive_entry_set_is_metadata_encrypted(struct archive_entry *, char is_encrypted);
/* /*
* Routines to bulk copy fields to/from a platform-native "struct * Routines to bulk copy fields to/from a platform-native "struct
* stat." Libarchive used to just store a struct stat inside of each * stat." Libarchive used to just store a struct stat inside of each

View File

@ -154,6 +154,11 @@ struct archive_entry {
/* Not used within libarchive; useful for some clients. */ /* Not used within libarchive; useful for some clients. */
struct archive_mstring ae_sourcepath; /* Path this entry is sourced from. */ struct archive_mstring ae_sourcepath; /* Path this entry is sourced from. */
#define AE_ENCRYPTION_NONE 0
#define AE_ENCRYPTION_DATA 1
#define AE_ENCRYPTION_METADATA 2
char encryption;
void *mac_metadata; void *mac_metadata;
size_t mac_metadata_size; size_t mac_metadata_size;

View File

@ -58,7 +58,7 @@ archive_entry_sparse_add_entry(struct archive_entry *entry,
if (offset < 0 || length < 0) if (offset < 0 || length < 0)
/* Invalid value */ /* Invalid value */
return; return;
if (offset + length < 0 || if (offset > INT64_MAX - length ||
offset + length > archive_entry_size(entry)) offset + length > archive_entry_size(entry))
/* A value of "length" parameter is too large. */ /* A value of "length" parameter is too large. */
return; return;

View File

@ -369,8 +369,8 @@ relunitphrase(struct gdstate *gds)
&& gds->tokenp[1].token == tSEC_UNIT) { && gds->tokenp[1].token == tSEC_UNIT) {
/* "1 day" */ /* "1 day" */
gds->HaveRel++; gds->HaveRel++;
gds->RelSeconds += gds->tokenp[1].value * gds->tokenp[2].value; gds->RelSeconds += gds->tokenp[0].value * gds->tokenp[1].value;
gds->tokenp += 3; gds->tokenp += 2;
return 1; return 1;
} }
if (gds->tokenp[0].token == '-' if (gds->tokenp[0].token == '-'
@ -403,7 +403,7 @@ relunitphrase(struct gdstate *gds)
/* "now", "tomorrow" */ /* "now", "tomorrow" */
gds->HaveRel++; gds->HaveRel++;
gds->RelSeconds += gds->tokenp[0].value; gds->RelSeconds += gds->tokenp[0].value;
++gds->tokenp; gds->tokenp += 1;
return 1; return 1;
} }
if (gds->tokenp[0].token == tMONTH_UNIT) { if (gds->tokenp[0].token == tMONTH_UNIT) {
@ -1022,10 +1022,11 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
time_t d; time_t d;
time_t now = time(NULL);
while (*++argv != NULL) { while (*++argv != NULL) {
(void)printf("Input: %s\n", *argv); (void)printf("Input: %s\n", *argv);
d = get_date(*argv); d = get_date(now, *argv);
if (d == -1) if (d == -1)
(void)printf("Bad format - couldn't convert.\n"); (void)printf("Bad format - couldn't convert.\n");
else else

View File

@ -1152,7 +1152,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
{ {
/* NOTE: stat() on Windows cannot handle nano seconds. */ /* NOTE: stat() on Windows cannot handle nano seconds. */
HANDLE h; HANDLE h;
WIN32_FIND_DATA d; WIN32_FIND_DATAA d;
if (path == NULL || *path == '\0') { if (path == NULL || *path == '\0') {
archive_set_error(&(a->archive), EINVAL, "pathname is empty"); archive_set_error(&(a->archive), EINVAL, "pathname is empty");

View File

@ -0,0 +1,329 @@
/* $NetBSD: pack_dev.c,v 1.12 2013/06/14 16:28:20 tsutsui Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Charles M. Hannum.
*
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/* Originally from NetBSD's mknod(8) source. */
#include "archive_platform.h"
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
#if !defined(lint)
__RCSID("$NetBSD$");
#endif /* not lint */
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "archive_pack_dev.h"
static pack_t pack_netbsd;
static pack_t pack_freebsd;
static pack_t pack_8_8;
static pack_t pack_12_20;
static pack_t pack_14_18;
static pack_t pack_8_24;
static pack_t pack_bsdos;
static int compare_format(const void *, const void *);
static const char iMajorError[] = "invalid major number";
static const char iMinorError[] = "invalid minor number";
static const char tooManyFields[] = "too many fields for format";
/* This is blatantly stolen from libarchive/archive_entry.c,
* in an attempt to get this to play nice on MinGW... */
#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. <sigh> */
#include <sys/netmgr.h>
#define apd_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min))
#elif defined makedev
/* There's a "makedev" macro. */
#define apd_makedev(maj, min) makedev((maj), (min))
#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__))
/* Windows. <sigh> */
#define apd_makedev(maj, min) mkdev((maj), (min))
#else
/* There's a "makedev" function. */
#define apd_makedev(maj, min) makedev((maj), (min))
#endif
/* exported */
dev_t
pack_native(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = apd_makedev(numbers[0], numbers[1]);
if ((u_long)major(dev) != numbers[0])
*error = iMajorError;
else if ((u_long)minor(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
static dev_t
pack_netbsd(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_netbsd(numbers[0], numbers[1]);
if ((u_long)major_netbsd(dev) != numbers[0])
*error = iMajorError;
else if ((u_long)minor_netbsd(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0))
#define makedev_freebsd(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \
(((y) << 0) & 0xffff00ff)))
static dev_t
pack_freebsd(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_freebsd(numbers[0], numbers[1]);
if ((u_long)major_freebsd(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_freebsd(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
#define makedev_8_8(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \
(((y) << 0) & 0x000000ff)))
static dev_t
pack_8_8(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_8_8(numbers[0], numbers[1]);
if ((u_long)major_8_8(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_8_8(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20))
#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0))
#define makedev_12_20(x,y) ((dev_t)((((x) << 20) & 0xfff00000) | \
(((y) << 0) & 0x000fffff)))
static dev_t
pack_12_20(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_12_20(numbers[0], numbers[1]);
if ((u_long)major_12_20(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_12_20(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18))
#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0))
#define makedev_14_18(x,y) ((dev_t)((((x) << 18) & 0xfffc0000) | \
(((y) << 0) & 0x0003ffff)))
static dev_t
pack_14_18(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_14_18(numbers[0], numbers[1]);
if ((u_long)major_14_18(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_14_18(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24))
#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0))
#define makedev_8_24(x,y) ((dev_t)((((x) << 24) & 0xff000000) | \
(((y) << 0) & 0x00ffffff)))
static dev_t
pack_8_24(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_8_24(numbers[0], numbers[1]);
if ((u_long)major_8_24(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_8_24(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20))
#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8))
#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
#define makedev_12_12_8(x,y,z) ((dev_t)((((x) << 20) & 0xfff00000) | \
(((y) << 8) & 0x000fff00) | \
(((z) << 0) & 0x000000ff)))
static dev_t
pack_bsdos(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_12_20(numbers[0], numbers[1]);
if ((u_long)major_12_20(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_12_20(dev) != numbers[1])
*error = iMinorError;
} else if (n == 3) {
dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
if ((u_long)major_12_12_8(dev) != numbers[0])
*error = iMajorError;
if ((u_long)unit_12_12_8(dev) != numbers[1])
*error = "invalid unit number";
if ((u_long)subunit_12_12_8(dev) != numbers[2])
*error = "invalid subunit number";
} else
*error = tooManyFields;
return (dev);
}
/* list of formats and pack functions */
/* this list must be sorted lexically */
static struct format {
const char *name;
pack_t *pack;
} formats[] = {
{"386bsd", pack_8_8},
{"4bsd", pack_8_8},
{"bsdos", pack_bsdos},
{"freebsd", pack_freebsd},
{"hpux", pack_8_24},
{"isc", pack_8_8},
{"linux", pack_8_8},
{"native", pack_native},
{"netbsd", pack_netbsd},
{"osf1", pack_12_20},
{"sco", pack_8_8},
{"solaris", pack_14_18},
{"sunos", pack_8_8},
{"svr3", pack_8_8},
{"svr4", pack_14_18},
{"ultrix", pack_8_8},
};
static int
compare_format(const void *key, const void *element)
{
const char *name;
const struct format *format;
name = key;
format = element;
return (strcmp(name, format->name));
}
pack_t *
pack_find(const char *name)
{
struct format *format;
format = bsearch(name, formats,
sizeof(formats)/sizeof(formats[0]),
sizeof(formats[0]), compare_format);
if (format == 0)
return (NULL);
return (format->pack);
}

View File

@ -0,0 +1,50 @@
/* $NetBSD: pack_dev.h,v 1.8 2013/06/14 16:28:20 tsutsui Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Charles M. Hannum.
*
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/* Originally from NetBSD's mknod(8) source. */
#ifndef _PACK_DEV_H
#define _PACK_DEV_H
typedef dev_t pack_t(int, u_long [], const char **);
typedef unsigned long u_long;
pack_t *pack_find(const char *);
pack_t pack_native;
#define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8)))
#define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \
(((x) & 0x000000ff) >> 0)))
#define makedev_netbsd(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \
(((y) << 12) & 0xfff00000) | \
(((y) << 0) & 0x000000ff)))
#endif /* _PACK_DEV_H */

View File

@ -66,15 +66,18 @@
* headers as required. * headers as required.
*/ */
/* Get a real definition for __FBSDID if we can */ /* Get a real definition for __FBSDID or __RCSID if we can */
#if HAVE_SYS_CDEFS_H #if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
#endif #endif
/* If not, define it so as to avoid dangling semicolons. */ /* If not, define them so as to avoid dangling semicolons. */
#ifndef __FBSDID #ifndef __FBSDID
#define __FBSDID(a) struct _undefined_hack #define __FBSDID(a) struct _undefined_hack
#endif #endif
#ifndef __RCSID
#define __RCSID(a) struct _undefined_hack
#endif
/* Try to get standard C99-style integer type definitions. */ /* Try to get standard C99-style integer type definitions. */
#if HAVE_INTTYPES_H #if HAVE_INTTYPES_H

View File

@ -746,6 +746,59 @@ archive_read_header_position(struct archive *_a)
return (a->header_position); return (a->header_position);
} }
/*
* Returns 1 if the archive contains at least one encrypted entry.
* If the archive format not support encryption at all
* ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
* If for any other reason (e.g. not enough data read so far)
* we cannot say whether there are encrypted entries, then
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
* In general, this function will return values below zero when the
* reader is uncertain or totally uncapable of encryption support.
* When this function returns 0 you can be sure that the reader
* supports encryption detection but no encrypted entries have
* been found yet.
*
* NOTE: If the metadata/header of an archive is also encrypted, you
* cannot rely on the number of encrypted entries. That is why this
* function does not return the number of encrypted entries but#
* just shows that there are some.
*/
int
archive_read_has_encrypted_entries(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
int format_supports_encryption = archive_read_format_capabilities(_a)
& (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
if (!_a || !format_supports_encryption) {
/* Format in general doesn't support encryption */
return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED;
}
/* A reader potentially has read enough data now. */
if (a->format && a->format->has_encrypted_entries) {
return (a->format->has_encrypted_entries)(a);
}
/* For any other reason we cannot say how many entries are there. */
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
}
/*
* Returns a bitmask of capabilities that are supported by the archive format reader.
* If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
*/
int
archive_read_format_capabilities(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
if (a && a->format && a->format->format_capabilties) {
return (a->format->format_capabilties)(a);
}
return ARCHIVE_READ_FORMAT_CAPS_NONE;
}
/* /*
* Read data from an archive entry, using a read(2)-style interface. * Read data from an archive entry, using a read(2)-style interface.
* This is a convenience routine that just calls * This is a convenience routine that just calls
@ -1094,7 +1147,9 @@ __archive_read_register_format(struct archive_read *a,
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *), int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *), int (*read_data_skip)(struct archive_read *),
int64_t (*seek_data)(struct archive_read *, int64_t, int), int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *)) int (*cleanup)(struct archive_read *),
int (*format_capabilities)(struct archive_read *),
int (*has_encrypted_entries)(struct archive_read *))
{ {
int i, number_slots; int i, number_slots;
@ -1117,6 +1172,8 @@ __archive_read_register_format(struct archive_read *a,
a->formats[i].cleanup = cleanup; a->formats[i].cleanup = cleanup;
a->formats[i].data = format_data; a->formats[i].data = format_data;
a->formats[i].name = name; a->formats[i].name = name;
a->formats[i].format_capabilties = format_capabilities;
a->formats[i].has_encrypted_entries = has_encrypted_entries;
return (ARCHIVE_OK); return (ARCHIVE_OK);
} }
} }
@ -1557,10 +1614,9 @@ __archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
client->dataset[++cursor].begin_position = r; client->dataset[++cursor].begin_position = r;
} }
offset -= client->dataset[cursor].begin_position; offset -= client->dataset[cursor].begin_position;
if (offset < 0) if (offset < 0
offset = 0; || offset > client->dataset[cursor].total_size)
else if (offset > client->dataset[cursor].total_size - 1) return ARCHIVE_FATAL;
offset = client->dataset[cursor].total_size - 1;
if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0) if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0)
return r; return r;
break; break;

View File

@ -399,7 +399,7 @@ setup_mac_metadata(struct archive_read_disk *a,
#endif #endif
#if defined(HAVE_POSIX_ACL) && defined(ACL_TYPE_NFS4) #ifdef HAVE_POSIX_ACL
static int translate_acl(struct archive_read_disk *a, static int translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int archive_entry_acl_type); struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
@ -419,6 +419,7 @@ setup_acls(struct archive_read_disk *a,
archive_entry_acl_clear(entry); archive_entry_acl_clear(entry);
#ifdef ACL_TYPE_NFS4
/* Try NFS4 ACL first. */ /* Try NFS4 ACL first. */
if (*fd >= 0) if (*fd >= 0)
acl = acl_get_fd(*fd); acl = acl_get_fd(*fd);
@ -447,6 +448,7 @@ setup_acls(struct archive_read_disk *a,
acl_free(acl); acl_free(acl);
return (ARCHIVE_OK); return (ARCHIVE_OK);
} }
#endif
/* Retrieve access ACL from file. */ /* Retrieve access ACL from file. */
if (*fd >= 0) if (*fd >= 0)
@ -492,6 +494,7 @@ static struct {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ}, {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
#ifdef ACL_TYPE_NFS4
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
@ -508,8 +511,10 @@ static struct {
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
}; };
#ifdef ACL_TYPE_NFS4
static struct { static struct {
int archive_inherit; int archive_inherit;
int platform_inherit; int platform_inherit;
@ -519,21 +524,25 @@ static struct {
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY} {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
}; };
#endif
static int static int
translate_acl(struct archive_read_disk *a, translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int default_entry_acl_type) struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
{ {
acl_tag_t acl_tag; acl_tag_t acl_tag;
#ifdef ACL_TYPE_NFS4
acl_entry_type_t acl_type; acl_entry_type_t acl_type;
acl_flagset_t acl_flagset; acl_flagset_t acl_flagset;
int brand, r;
#endif
acl_entry_t acl_entry; acl_entry_t acl_entry;
acl_permset_t acl_permset; acl_permset_t acl_permset;
int brand, i, r, entry_acl_type; int i, entry_acl_type;
int s, ae_id, ae_tag, ae_perm; int s, ae_id, ae_tag, ae_perm;
const char *ae_name; const char *ae_name;
#ifdef ACL_TYPE_NFS4
// FreeBSD "brands" ACLs as POSIX.1e or NFSv4 // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
// Make sure the "brand" on this ACL is consistent // Make sure the "brand" on this ACL is consistent
// with the default_entry_acl_type bits provided. // with the default_entry_acl_type bits provided.
@ -560,6 +569,7 @@ translate_acl(struct archive_read_disk *a,
return ARCHIVE_FAILED; return ARCHIVE_FAILED;
break; break;
} }
#endif
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
@ -592,9 +602,11 @@ translate_acl(struct archive_read_disk *a,
case ACL_OTHER: case ACL_OTHER:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER; ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
break; break;
#ifdef ACL_TYPE_NFS4
case ACL_EVERYONE: case ACL_EVERYONE:
ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
break; break;
#endif
default: default:
/* Skip types that libarchive can't support. */ /* Skip types that libarchive can't support. */
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
@ -605,6 +617,7 @@ translate_acl(struct archive_read_disk *a,
// XXX acl_get_entry_type_np on FreeBSD returns EINVAL for // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
// non-NFSv4 ACLs // non-NFSv4 ACLs
entry_acl_type = default_entry_acl_type; entry_acl_type = default_entry_acl_type;
#ifdef ACL_TYPE_NFS4
r = acl_get_entry_type_np(acl_entry, &acl_type); r = acl_get_entry_type_np(acl_entry, &acl_type);
if (r == 0) { if (r == 0) {
switch (acl_type) { switch (acl_type) {
@ -634,9 +647,10 @@ translate_acl(struct archive_read_disk *a,
ae_perm |= acl_inherit_map[i].archive_inherit; ae_perm |= acl_inherit_map[i].archive_inherit;
} }
#endif
acl_get_permset(acl_entry, &acl_permset); acl_get_permset(acl_entry, &acl_permset);
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
/* /*
* acl_get_perm() is spelled differently on different * acl_get_perm() is spelled differently on different
* platforms; see above. * platforms; see above.

View File

@ -1973,7 +1973,7 @@ tree_dup(int fd)
static volatile int can_dupfd_cloexec = 1; static volatile int can_dupfd_cloexec = 1;
if (can_dupfd_cloexec) { if (can_dupfd_cloexec) {
new_fd = fcntl(fd, F_DUPFD_CLOEXEC); new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
if (new_fd != -1) if (new_fd != -1)
return (new_fd); return (new_fd);
/* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC, /* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC,

View File

@ -929,7 +929,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
else else
flags |= FILE_FLAG_SEQUENTIAL_SCAN; flags |= FILE_FLAG_SEQUENTIAL_SCAN;
t->entry_fh = CreateFileW(tree_current_access_path(t), t->entry_fh = CreateFileW(tree_current_access_path(t),
GENERIC_READ, 0, NULL, OPEN_EXISTING, flags, NULL); GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, flags, NULL);
if (t->entry_fh == INVALID_HANDLE_VALUE) { if (t->entry_fh == INVALID_HANDLE_VALUE) {
archive_set_error(&a->archive, errno, archive_set_error(&a->archive, errno,
"Couldn't open %ls", tree_current_path(a->tree)); "Couldn't open %ls", tree_current_path(a->tree));
@ -1886,7 +1886,7 @@ tree_current_file_information(struct tree *t, BY_HANDLE_FILE_INFORMATION *st,
if (sim_lstat && tree_current_is_physical_link(t)) if (sim_lstat && tree_current_is_physical_link(t))
flag |= FILE_FLAG_OPEN_REPARSE_POINT; flag |= FILE_FLAG_OPEN_REPARSE_POINT;
h = CreateFileW(tree_current_access_path(t), 0, 0, NULL, h = CreateFileW(tree_current_access_path(t), 0, FILE_SHARE_READ, NULL,
OPEN_EXISTING, flag, NULL); OPEN_EXISTING, flag, NULL);
if (h == INVALID_HANDLE_VALUE) { if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError()); la_dosmaperr(GetLastError());
@ -2115,7 +2115,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
} else } else
desiredAccess = GENERIC_READ; desiredAccess = GENERIC_READ;
h = CreateFileW(path, desiredAccess, 0, NULL, h = CreateFileW(path, desiredAccess, FILE_SHARE_READ, NULL,
OPEN_EXISTING, flag, NULL); OPEN_EXISTING, flag, NULL);
if (h == INVALID_HANDLE_VALUE) { if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError()); la_dosmaperr(GetLastError());
@ -2162,7 +2162,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
if (fd >= 0) { if (fd >= 0) {
h = (HANDLE)_get_osfhandle(fd); h = (HANDLE)_get_osfhandle(fd);
} else { } else {
h = CreateFileW(path, GENERIC_READ, 0, NULL, h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) { if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError()); la_dosmaperr(GetLastError());

View File

@ -103,7 +103,9 @@ int
archive_read_open_filename(struct archive *a, const char *filename, archive_read_open_filename(struct archive *a, const char *filename,
size_t block_size) size_t block_size)
{ {
const char *filenames[2] = { filename, NULL }; const char *filenames[2];
filenames[0] = filename;
filenames[1] = NULL;
return archive_read_open_filenames(a, filenames, block_size); return archive_read_open_filenames(a, filenames, block_size);
} }

View File

@ -207,6 +207,8 @@ struct archive_read {
int (*read_data_skip)(struct archive_read *); int (*read_data_skip)(struct archive_read *);
int64_t (*seek_data)(struct archive_read *, int64_t, int); int64_t (*seek_data)(struct archive_read *, int64_t, int);
int (*cleanup)(struct archive_read *); int (*cleanup)(struct archive_read *);
int (*format_capabilties)(struct archive_read *);
int (*has_encrypted_entries)(struct archive_read *);
} formats[16]; } formats[16];
struct archive_format_descriptor *format; /* Active format. */ struct archive_format_descriptor *format; /* Active format. */
@ -218,15 +220,17 @@ struct archive_read {
}; };
int __archive_read_register_format(struct archive_read *a, int __archive_read_register_format(struct archive_read *a,
void *format_data, void *format_data,
const char *name, const char *name,
int (*bid)(struct archive_read *, int), int (*bid)(struct archive_read *, int),
int (*options)(struct archive_read *, const char *, const char *), int (*options)(struct archive_read *, const char *, const char *),
int (*read_header)(struct archive_read *, struct archive_entry *), int (*read_header)(struct archive_read *, struct archive_entry *),
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *), int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *), int (*read_data_skip)(struct archive_read *),
int64_t (*seek_data)(struct archive_read *, int64_t, int), int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *)); int (*cleanup)(struct archive_read *),
int (*format_capabilities)(struct archive_read *),
int (*has_encrypted_entries)(struct archive_read *));
int __archive_read_get_bidder(struct archive_read *a, int __archive_read_get_bidder(struct archive_read *a,
struct archive_read_filter_bidder **bidder); struct archive_read_filter_bidder **bidder);

View File

@ -193,6 +193,28 @@ Defaults to enabled, use
.Cm !rockridge .Cm !rockridge
to disable. to disable.
.El .El
.It Format tar
.Bl -tag -compact -width indent
.It Cm compat-2x
Libarchive 2.x incorrectly encoded Unicode filenames on
some platforms.
This option mimics the libarchive 2.x filename handling
so that such archives can be read correctly.
.It Cm hdrcharset
The value is used as a character set name that will be
used when translating filenames.
.It Cm mac-ext
Support Mac OS metadata extension that records data in special
files beginning with a period and underscore.
Defaults to enabled on Mac OS, disabled on other platforms.
Use
.Cm !mac-ext
to disable.
.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.
.El
.El .El
.\" .\"
.Sh ERRORS .Sh ERRORS

View File

@ -78,7 +78,7 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
struct archive_read *a = (struct archive_read *)_a; struct archive_read *a = (struct archive_read *)_a;
struct archive_format_descriptor *format; struct archive_format_descriptor *format;
size_t i; size_t i;
int r, rv = ARCHIVE_WARN; int r, rv = ARCHIVE_WARN, matched_modules = 0;
for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) { for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) {
format = &a->formats[i]; format = &a->formats[i];
@ -86,8 +86,11 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
format->name == NULL) format->name == NULL)
/* This format does not support option. */ /* This format does not support option. */
continue; continue;
if (m != NULL && strcmp(format->name, m) != 0) if (m != NULL) {
continue; if (strcmp(format->name, m) != 0)
continue;
++matched_modules;
}
a->format = format; a->format = format;
r = format->options(a, o, v); r = format->options(a, o, v);
@ -96,16 +99,13 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
if (r == ARCHIVE_FATAL) if (r == ARCHIVE_FATAL)
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
if (m != NULL)
return (r);
if (r == ARCHIVE_OK) if (r == ARCHIVE_OK)
rv = ARCHIVE_OK; rv = ARCHIVE_OK;
} }
/* If the format name didn't match, return a special code for /* If the format name didn't match, return a special code for
* _archive_set_option[s]. */ * _archive_set_option[s]. */
if (rv == ARCHIVE_WARN && m != NULL) if (m != NULL && matched_modules == 0)
rv = ARCHIVE_WARN - 1; return ARCHIVE_WARN - 1;
return (rv); return (rv);
} }
@ -116,7 +116,7 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o,
struct archive_read *a = (struct archive_read *)_a; struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter *filter; struct archive_read_filter *filter;
struct archive_read_filter_bidder *bidder; struct archive_read_filter_bidder *bidder;
int r, rv = ARCHIVE_WARN; int r, rv = ARCHIVE_WARN, matched_modules = 0;
for (filter = a->filter; filter != NULL; filter = filter->upstream) { for (filter = a->filter; filter != NULL; filter = filter->upstream) {
bidder = filter->bidder; bidder = filter->bidder;
@ -125,24 +125,24 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o,
if (bidder->options == NULL) if (bidder->options == NULL)
/* This bidder does not support option */ /* This bidder does not support option */
continue; continue;
if (m != NULL && strcmp(filter->name, m) != 0) if (m != NULL) {
continue; if (strcmp(filter->name, m) != 0)
continue;
++matched_modules;
}
r = bidder->options(bidder, o, v); r = bidder->options(bidder, o, v);
if (r == ARCHIVE_FATAL) if (r == ARCHIVE_FATAL)
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
if (m != NULL)
return (r);
if (r == ARCHIVE_OK) if (r == ARCHIVE_OK)
rv = ARCHIVE_OK; rv = ARCHIVE_OK;
} }
/* If the filter name didn't match, return a special code for /* If the filter name didn't match, return a special code for
* _archive_set_option[s]. */ * _archive_set_option[s]. */
if (rv == ARCHIVE_WARN && m != NULL) if (m != NULL && matched_modules == 0)
rv = ARCHIVE_WARN - 1; return ARCHIVE_WARN - 1;
return (rv); return (rv);
} }

View File

@ -242,10 +242,11 @@ consume_header(struct archive_read_filter *self)
if (version >= 0x940) { if (version >= 0x940) {
unsigned level = *p++; unsigned level = *p++;
if (method == 1 && level == 0) level = 3; unsigned default_level[] = {0, 3, 1, 9};
if (method == 2 && level == 0) level = 1; if (level == 0)
if (method == 3 && level == 0) level = 9; /* Method is 1..3 here due to check above. */
if (level < 1 && level > 9) { level = default_level[method];
else if (level > 9) {
archive_set_error(&self->archive->archive, archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC, "Invalid level"); ARCHIVE_ERRNO_MISC, "Invalid level");
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);

View File

@ -601,7 +601,7 @@ lzip_init(struct archive_read_filter *self)
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
ret = lzma_raw_decoder(&(state->stream), filters); ret = lzma_raw_decoder(&(state->stream), filters);
#if LZMA_VERSION < 50000030 #if LZMA_VERSION < 50010000
free(filters[0].options); free(filters[0].options);
#endif #endif
if (ret != LZMA_OK) { if (ret != LZMA_OK) {

View File

@ -69,7 +69,11 @@ __FBSDID("$FreeBSD$");
#define _7Z_BZ2 0x040202 #define _7Z_BZ2 0x040202
#define _7Z_PPMD 0x030401 #define _7Z_PPMD 0x030401
#define _7Z_DELTA 0x03 #define _7Z_DELTA 0x03
#define _7Z_CRYPTO 0x06F10701 #define _7Z_CRYPTO_MAIN_ZIP 0x06F10101 /* Main Zip crypto algo */
#define _7Z_CRYPTO_RAR_29 0x06F10303 /* Rar29 AES-128 + (modified SHA-1) */
#define _7Z_CRYPTO_AES_256_SHA_256 0x06F10701 /* AES-256 + SHA-256 */
#define _7Z_X86 0x03030103 #define _7Z_X86 0x03030103
#define _7Z_X86_BCJ2 0x0303011B #define _7Z_X86_BCJ2 0x0303011B
#define _7Z_POWERPC 0x03030205 #define _7Z_POWERPC 0x03030205
@ -322,8 +326,13 @@ struct _7zip {
struct archive_string_conv *sconv; struct archive_string_conv *sconv;
char format_name[64]; char format_name[64];
/* Custom value that is non-zero if this archive contains encrypted entries. */
int has_encrypted_entries;
}; };
static int archive_read_format_7zip_has_encrypted_entries(struct archive_read *);
static int archive_read_support_format_7zip_capabilities(struct archive_read *a);
static int archive_read_format_7zip_bid(struct archive_read *, int); static int archive_read_format_7zip_bid(struct archive_read *, int);
static int archive_read_format_7zip_cleanup(struct archive_read *); static int archive_read_format_7zip_cleanup(struct archive_read *);
static int archive_read_format_7zip_read_data(struct archive_read *, static int archive_read_format_7zip_read_data(struct archive_read *,
@ -401,6 +410,13 @@ archive_read_support_format_7zip(struct archive *_a)
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
/*
* Until enough data has been read, we cannot tell about
* any encrypted entries yet.
*/
zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
r = __archive_read_register_format(a, r = __archive_read_register_format(a,
zip, zip,
"7zip", "7zip",
@ -410,13 +426,36 @@ archive_read_support_format_7zip(struct archive *_a)
archive_read_format_7zip_read_data, archive_read_format_7zip_read_data,
archive_read_format_7zip_read_data_skip, archive_read_format_7zip_read_data_skip,
NULL, NULL,
archive_read_format_7zip_cleanup); archive_read_format_7zip_cleanup,
archive_read_support_format_7zip_capabilities,
archive_read_format_7zip_has_encrypted_entries);
if (r != ARCHIVE_OK) if (r != ARCHIVE_OK)
free(zip); free(zip);
return (ARCHIVE_OK); return (ARCHIVE_OK);
} }
static int
archive_read_support_format_7zip_capabilities(struct archive_read * a)
{
(void)a; /* UNUSED */
return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA |
ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
}
static int
archive_read_format_7zip_has_encrypted_entries(struct archive_read *_a)
{
if (_a && _a->format) {
struct _7zip * zip = (struct _7zip *)_a->format->data;
if (zip) {
return zip->has_encrypted_entries;
}
}
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
}
static int static int
archive_read_format_7zip_bid(struct archive_read *a, int best_bid) archive_read_format_7zip_bid(struct archive_read *a, int best_bid)
{ {
@ -476,7 +515,7 @@ check_7zip_header_in_sfx(const char *p)
switch ((unsigned char)p[5]) { switch ((unsigned char)p[5]) {
case 0x1C: case 0x1C:
if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0) if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0)
return (6); return (6);
/* /*
* Test the CRC because its extraction code has 7-Zip * Test the CRC because its extraction code has 7-Zip
* Magic Code, so we should do this in order not to * Magic Code, so we should do this in order not to
@ -484,15 +523,15 @@ check_7zip_header_in_sfx(const char *p)
*/ */
if (crc32(0, (const unsigned char *)p + 12, 20) if (crc32(0, (const unsigned char *)p + 12, 20)
!= archive_le32dec(p + 8)) != archive_le32dec(p + 8))
return (6); return (6);
/* Hit the header! */ /* Hit the header! */
return (0); return (0);
case 0x37: return (5); case 0x37: return (5);
case 0x7A: return (4); case 0x7A: return (4);
case 0xBC: return (3); case 0xBC: return (3);
case 0xAF: return (2); case 0xAF: return (2);
case 0x27: return (1); case 0x27: return (1);
default: return (6); default: return (6);
} }
} }
@ -568,6 +607,19 @@ archive_read_format_7zip_read_header(struct archive_read *a,
struct _7zip *zip = (struct _7zip *)a->format->data; struct _7zip *zip = (struct _7zip *)a->format->data;
struct _7zip_entry *zip_entry; struct _7zip_entry *zip_entry;
int r, ret = ARCHIVE_OK; int r, ret = ARCHIVE_OK;
struct _7z_folder *folder = 0;
uint64_t fidx = 0;
/*
* It should be sufficient to call archive_read_next_header() for
* a reader to determine if an entry is encrypted or not. If the
* encryption of an entry is only detectable when calling
* archive_read_data(), so be it. We'll do the same check there
* as well.
*/
if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
zip->has_encrypted_entries = 0;
}
a->archive.archive_format = ARCHIVE_FORMAT_7ZIP; a->archive.archive_format = ARCHIVE_FORMAT_7ZIP;
if (a->archive.archive_format_name == NULL) if (a->archive.archive_format_name == NULL)
@ -604,6 +656,32 @@ archive_read_format_7zip_read_header(struct archive_read *a,
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
/* Figure out if the entry is encrypted by looking at the folder
that is associated to the current 7zip entry. If the folder
has a coder with a _7Z_CRYPTO codec then the folder is encrypted.
Hence the entry must also be encrypted. */
if (zip_entry && zip_entry->folderIndex < zip->si.ci.numFolders) {
folder = &(zip->si.ci.folders[zip_entry->folderIndex]);
for (fidx=0; folder && fidx<folder->numCoders; fidx++) {
switch(folder->coders[fidx].codec) {
case _7Z_CRYPTO_MAIN_ZIP:
case _7Z_CRYPTO_RAR_29:
case _7Z_CRYPTO_AES_256_SHA_256: {
archive_entry_set_is_data_encrypted(entry, 1);
zip->has_encrypted_entries = 1;
break;
}
}
}
}
/* Now that we've checked for encryption, if there were still no
* encrypted entries found we can say for sure that there are none.
*/
if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
zip->has_encrypted_entries = 0;
}
if (archive_entry_copy_pathname_l(entry, if (archive_entry_copy_pathname_l(entry,
(const char *)zip_entry->utf16name, (const char *)zip_entry->utf16name,
zip_entry->name_len, zip->sconv) != 0) { zip_entry->name_len, zip->sconv) != 0) {
@ -707,6 +785,10 @@ archive_read_format_7zip_read_data(struct archive_read *a,
zip = (struct _7zip *)(a->format->data); zip = (struct _7zip *)(a->format->data);
if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
zip->has_encrypted_entries = 0;
}
if (zip->pack_stream_bytes_unconsumed) if (zip->pack_stream_bytes_unconsumed)
read_consume(a); read_consume(a);
@ -969,7 +1051,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
{ {
lzma_options_delta delta_opt; lzma_options_delta delta_opt;
lzma_filter filters[LZMA_FILTERS_MAX]; lzma_filter filters[LZMA_FILTERS_MAX];
#if LZMA_VERSION < 50000030 #if LZMA_VERSION < 50010000
lzma_filter *ff; lzma_filter *ff;
#endif #endif
int fi = 0; int fi = 0;
@ -994,7 +1076,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
* for BCJ+LZMA. If we were able to tell the uncompressed * for BCJ+LZMA. If we were able to tell the uncompressed
* size to liblzma when using lzma_raw_decoder() liblzma * size to liblzma when using lzma_raw_decoder() liblzma
* could correctly deal with BCJ+LZMA. But unfortunately * could correctly deal with BCJ+LZMA. But unfortunately
* there is no way to do that. * there is no way to do that.
* Discussion about this can be found at XZ Utils forum. * Discussion about this can be found at XZ Utils forum.
*/ */
if (coder2 != NULL) { if (coder2 != NULL) {
@ -1056,7 +1138,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
else else
filters[fi].id = LZMA_FILTER_LZMA1; filters[fi].id = LZMA_FILTER_LZMA1;
filters[fi].options = NULL; filters[fi].options = NULL;
#if LZMA_VERSION < 50000030 #if LZMA_VERSION < 50010000
ff = &filters[fi]; ff = &filters[fi];
#endif #endif
r = lzma_properties_decode(&filters[fi], NULL, r = lzma_properties_decode(&filters[fi], NULL,
@ -1070,7 +1152,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
filters[fi].id = LZMA_VLI_UNKNOWN; filters[fi].id = LZMA_VLI_UNKNOWN;
filters[fi].options = NULL; filters[fi].options = NULL;
r = lzma_raw_decoder(&(zip->lzstream), filters); r = lzma_raw_decoder(&(zip->lzstream), filters);
#if LZMA_VERSION < 50000030 #if LZMA_VERSION < 50010000
free(ff->options); free(ff->options);
#endif #endif
if (r != LZMA_OK) { if (r != LZMA_OK) {
@ -1203,6 +1285,17 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unexpected codec ID: %lX", zip->codec); "Unexpected codec ID: %lX", zip->codec);
return (ARCHIVE_FAILED); return (ARCHIVE_FAILED);
case _7Z_CRYPTO_MAIN_ZIP:
case _7Z_CRYPTO_RAR_29:
case _7Z_CRYPTO_AES_256_SHA_256:
if (a->entry) {
archive_entry_set_is_metadata_encrypted(a->entry, 1);
archive_entry_set_is_data_encrypted(a->entry, 1);
zip->has_encrypted_entries = 1;
}
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Crypto codec not supported yet (ID: 0x%lX)", zip->codec);
return (ARCHIVE_FAILED);
default: default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unknown codec ID: %lX", zip->codec); "Unknown codec ID: %lX", zip->codec);
@ -1426,7 +1519,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
do { do {
int sym; int sym;
sym = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( sym = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
&(zip->ppmd7_context), &(zip->range_dec.p)); &(zip->ppmd7_context), &(zip->range_dec.p));
if (sym < 0) { if (sym < 0) {
@ -2755,6 +2848,7 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
zip->header_crc32 = 0; zip->header_crc32 = 0;
zip->header_is_encoded = 0; zip->header_is_encoded = 0;
zip->header_is_being_read = 1; zip->header_is_being_read = 1;
zip->has_encrypted_entries = 0;
check_header_crc = 1; check_header_crc = 1;
if ((p = header_bytes(a, 1)) == NULL) { if ((p = header_bytes(a, 1)) == NULL) {
@ -3170,7 +3264,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
return (r); return (r);
/* /*
* Skip the bytes we alrady has skipped in skip_stream(). * Skip the bytes we alrady has skipped in skip_stream().
*/ */
while (skip_bytes) { while (skip_bytes) {
ssize_t skipped; ssize_t skipped;
@ -3235,16 +3329,36 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
* Check coder types. * Check coder types.
*/ */
for (i = 0; i < folder->numCoders; i++) { for (i = 0; i < folder->numCoders; i++) {
if (folder->coders[i].codec == _7Z_CRYPTO) { switch(folder->coders[i].codec) {
archive_set_error(&(a->archive), case _7Z_CRYPTO_MAIN_ZIP:
ARCHIVE_ERRNO_MISC, case _7Z_CRYPTO_RAR_29:
"The %s is encrypted, " case _7Z_CRYPTO_AES_256_SHA_256: {
"but currently not supported", cname); /* For entry that is associated with this folder, mark
return (ARCHIVE_FATAL); it as encrypted (data+metadata). */
zip->has_encrypted_entries = 1;
if (a->entry) {
archive_entry_set_is_data_encrypted(a->entry, 1);
archive_entry_set_is_metadata_encrypted(a->entry, 1);
}
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
"The %s is encrypted, "
"but currently not supported", cname);
return (ARCHIVE_FATAL);
}
case _7Z_X86_BCJ2: {
found_bcj2++;
break;
}
} }
if (folder->coders[i].codec == _7Z_X86_BCJ2)
found_bcj2++;
} }
/* Now that we've checked for encryption, if there were still no
* encrypted entries found we can say for sure that there are none.
*/
if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
zip->has_encrypted_entries = 0;
}
if ((folder->numCoders > 2 && !found_bcj2) || found_bcj2 > 1) { if ((folder->numCoders > 2 && !found_bcj2) || found_bcj2 > 1) {
archive_set_error(&(a->archive), archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC, ARCHIVE_ERRNO_MISC,

View File

@ -122,7 +122,9 @@ archive_read_support_format_ar(struct archive *_a)
archive_read_format_ar_read_data, archive_read_format_ar_read_data,
archive_read_format_ar_skip, archive_read_format_ar_skip,
NULL, NULL,
archive_read_format_ar_cleanup); archive_read_format_ar_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK) { if (r != ARCHIVE_OK) {
free(ar); free(ar);

View File

@ -383,7 +383,9 @@ archive_read_support_format_cab(struct archive *_a)
archive_read_format_cab_read_data, archive_read_format_cab_read_data,
archive_read_format_cab_read_data_skip, archive_read_format_cab_read_data_skip,
NULL, NULL,
archive_read_format_cab_cleanup); archive_read_format_cab_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK) if (r != ARCHIVE_OK)
free(cab); free(cab);

View File

@ -243,7 +243,9 @@ archive_read_support_format_cpio(struct archive *_a)
archive_read_format_cpio_read_data, archive_read_format_cpio_read_data,
archive_read_format_cpio_skip, archive_read_format_cpio_skip,
NULL, NULL,
archive_read_format_cpio_cleanup); archive_read_format_cpio_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK) if (r != ARCHIVE_OK)
free(cpio); free(cpio);

View File

@ -54,6 +54,8 @@ archive_read_support_format_empty(struct archive *_a)
archive_read_format_empty_read_data, archive_read_format_empty_read_data,
NULL, NULL,
NULL, NULL,
NULL,
NULL,
NULL); NULL);
return (r); return (r);

View File

@ -478,7 +478,9 @@ archive_read_support_format_iso9660(struct archive *_a)
archive_read_format_iso9660_read_data, archive_read_format_iso9660_read_data,
archive_read_format_iso9660_read_data_skip, archive_read_format_iso9660_read_data_skip,
NULL, NULL,
archive_read_format_iso9660_cleanup); archive_read_format_iso9660_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK) { if (r != ARCHIVE_OK) {
free(iso9660); free(iso9660);

View File

@ -320,7 +320,9 @@ archive_read_support_format_lha(struct archive *_a)
archive_read_format_lha_read_data, archive_read_format_lha_read_data,
archive_read_format_lha_read_data_skip, archive_read_format_lha_read_data_skip,
NULL, NULL,
archive_read_format_lha_cleanup); archive_read_format_lha_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK) if (r != ARCHIVE_OK)
free(lha); free(lha);

View File

@ -51,6 +51,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#include "archive_private.h" #include "archive_private.h"
#include "archive_read_private.h" #include "archive_read_private.h"
#include "archive_string.h" #include "archive_string.h"
#include "archive_pack_dev.h"
#ifndef O_BINARY #ifndef O_BINARY
#define O_BINARY 0 #define O_BINARY 0
@ -103,6 +104,7 @@ struct mtree {
struct archive_entry_linkresolver *resolver; struct archive_entry_linkresolver *resolver;
int64_t cur_size; int64_t cur_size;
char checkfs;
}; };
static int bid_keycmp(const char *, const char *, ssize_t); static int bid_keycmp(const char *, const char *, ssize_t);
@ -173,6 +175,29 @@ get_time_t_min(void)
#endif #endif
} }
static int
archive_read_format_mtree_options(struct archive_read *a,
const char *key, const char *val)
{
struct mtree *mtree;
mtree = (struct mtree *)(a->format->data);
if (strcmp(key, "checkfs") == 0) {
/* Allows to read information missing from the mtree from the file system */
if (val == NULL || val[0] == 0) {
mtree->checkfs = 0;
} else {
mtree->checkfs = 1;
}
return (ARCHIVE_OK);
}
/* Note: The "warn" return is just to inform the options
* supervisor that we didn't handle it. It will generate
* a suitable error if no one used this option. */
return (ARCHIVE_WARN);
}
static void static void
free_options(struct mtree_option *head) free_options(struct mtree_option *head)
{ {
@ -205,7 +230,7 @@ archive_read_support_format_mtree(struct archive *_a)
mtree->fd = -1; mtree->fd = -1;
r = __archive_read_register_format(a, mtree, "mtree", r = __archive_read_register_format(a, mtree, "mtree",
mtree_bid, NULL, read_header, read_data, skip, NULL, cleanup); mtree_bid, archive_read_format_mtree_options, read_header, read_data, skip, NULL, cleanup, NULL, NULL);
if (r != ARCHIVE_OK) if (r != ARCHIVE_OK)
free(mtree); free(mtree);
@ -367,7 +392,7 @@ bid_keyword(const char *p, ssize_t len)
"gid", "gname", NULL "gid", "gname", NULL
}; };
static const char *keys_il[] = { static const char *keys_il[] = {
"ignore", "link", NULL "ignore", "inode", "link", NULL
}; };
static const char *keys_m[] = { static const char *keys_m[] = {
"md5", "md5digest", "mode", NULL "md5", "md5digest", "mode", NULL
@ -376,7 +401,7 @@ bid_keyword(const char *p, ssize_t len)
"nlink", "nochange", "optional", NULL "nlink", "nochange", "optional", NULL
}; };
static const char *keys_r[] = { static const char *keys_r[] = {
"rmd160", "rmd160digest", NULL "resdevice", "rmd160", "rmd160digest", NULL
}; };
static const char *keys_s[] = { static const char *keys_s[] = {
"sha1", "sha1digest", "sha1", "sha1digest",
@ -1103,162 +1128,164 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
mtree->current_dir.length = n; mtree->current_dir.length = n;
} }
/* if (mtree->checkfs) {
* Try to open and stat the file to get the real size /*
* and other file info. It would be nice to avoid * Try to open and stat the file to get the real size
* this here so that getting a listing of an mtree * and other file info. It would be nice to avoid
* wouldn't require opening every referenced contents * this here so that getting a listing of an mtree
* file. But then we wouldn't know the actual * wouldn't require opening every referenced contents
* contents size, so I don't see a really viable way * file. But then we wouldn't know the actual
* around this. (Also, we may want to someday pull * contents size, so I don't see a really viable way
* other unspecified info from the contents file on * around this. (Also, we may want to someday pull
* disk.) * other unspecified info from the contents file on
*/ * disk.)
mtree->fd = -1; */
if (archive_strlen(&mtree->contents_name) > 0) mtree->fd = -1;
path = mtree->contents_name.s; if (archive_strlen(&mtree->contents_name) > 0)
else path = mtree->contents_name.s;
path = archive_entry_pathname(entry); else
path = archive_entry_pathname(entry);
if (archive_entry_filetype(entry) == AE_IFREG || if (archive_entry_filetype(entry) == AE_IFREG ||
archive_entry_filetype(entry) == AE_IFDIR) { archive_entry_filetype(entry) == AE_IFDIR) {
mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC); mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
__archive_ensure_cloexec_flag(mtree->fd); __archive_ensure_cloexec_flag(mtree->fd);
if (mtree->fd == -1 && if (mtree->fd == -1 &&
(errno != ENOENT || (errno != ENOENT ||
archive_strlen(&mtree->contents_name) > 0)) { archive_strlen(&mtree->contents_name) > 0)) {
archive_set_error(&a->archive, errno, archive_set_error(&a->archive, errno,
"Can't open %s", path); "Can't open %s", path);
r = ARCHIVE_WARN;
}
}
st = &st_storage;
if (mtree->fd >= 0) {
if (fstat(mtree->fd, st) == -1) {
archive_set_error(&a->archive, errno,
"Could not fstat %s", path);
r = ARCHIVE_WARN;
/* If we can't stat it, don't keep it open. */
close(mtree->fd);
mtree->fd = -1;
st = NULL;
}
} else if (lstat(path, st) == -1) {
st = NULL;
}
/*
* Check for a mismatch between the type in the specification and
* the type of the contents object on disk.
*/
if (st != NULL) {
if (
((st->st_mode & S_IFMT) == S_IFREG &&
archive_entry_filetype(entry) == AE_IFREG)
#ifdef S_IFLNK
|| ((st->st_mode & S_IFMT) == S_IFLNK &&
archive_entry_filetype(entry) == AE_IFLNK)
#endif
#ifdef S_IFSOCK
|| ((st->st_mode & S_IFSOCK) == S_IFSOCK &&
archive_entry_filetype(entry) == AE_IFSOCK)
#endif
#ifdef S_IFCHR
|| ((st->st_mode & S_IFMT) == S_IFCHR &&
archive_entry_filetype(entry) == AE_IFCHR)
#endif
#ifdef S_IFBLK
|| ((st->st_mode & S_IFMT) == S_IFBLK &&
archive_entry_filetype(entry) == AE_IFBLK)
#endif
|| ((st->st_mode & S_IFMT) == S_IFDIR &&
archive_entry_filetype(entry) == AE_IFDIR)
#ifdef S_IFIFO
|| ((st->st_mode & S_IFMT) == S_IFIFO &&
archive_entry_filetype(entry) == AE_IFIFO)
#endif
) {
/* Types match. */
} else {
/* Types don't match; bail out gracefully. */
if (mtree->fd >= 0)
close(mtree->fd);
mtree->fd = -1;
if (parsed_kws & MTREE_HAS_OPTIONAL) {
/* It's not an error for an optional entry
to not match disk. */
*use_next = 1;
} else if (r == ARCHIVE_OK) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"mtree specification has different type for %s",
archive_entry_pathname(entry));
r = ARCHIVE_WARN; r = ARCHIVE_WARN;
} }
return r;
} }
}
/* st = &st_storage;
* If there is a contents file on disk, pick some of the metadata if (mtree->fd >= 0) {
* from that file. For most of these, we only set it from the contents if (fstat(mtree->fd, st) == -1) {
* if it wasn't already parsed from the specification. archive_set_error(&a->archive, errno,
*/ "Could not fstat %s", path);
if (st != NULL) { r = ARCHIVE_WARN;
if (((parsed_kws & MTREE_HAS_DEVICE) == 0 || /* If we can't stat it, don't keep it open. */
(parsed_kws & MTREE_HAS_NOCHANGE) != 0) && close(mtree->fd);
(archive_entry_filetype(entry) == AE_IFCHR || mtree->fd = -1;
archive_entry_filetype(entry) == AE_IFBLK)) st = NULL;
archive_entry_set_rdev(entry, st->st_rdev); }
if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0 || } else if (lstat(path, st) == -1) {
(parsed_kws & MTREE_HAS_NOCHANGE) != 0) st = NULL;
archive_entry_set_gid(entry, st->st_gid);
if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_uid(entry, st->st_uid);
if ((parsed_kws & MTREE_HAS_MTIME) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0) {
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtimespec.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtim.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIME_N
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtime_n);
#elif HAVE_STRUCT_STAT_ST_UMTIME
archive_entry_set_mtime(entry, st->st_mtime,
st->st_umtime*1000);
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtime_usec*1000);
#else
archive_entry_set_mtime(entry, st->st_mtime, 0);
#endif
} }
if ((parsed_kws & MTREE_HAS_NLINK) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_nlink(entry, st->st_nlink);
if ((parsed_kws & MTREE_HAS_PERM) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_perm(entry, st->st_mode);
if ((parsed_kws & MTREE_HAS_SIZE) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_size(entry, st->st_size);
archive_entry_set_ino(entry, st->st_ino);
archive_entry_set_dev(entry, st->st_dev);
archive_entry_linkify(mtree->resolver, &entry, &sparse_entry);
} else if (parsed_kws & MTREE_HAS_OPTIONAL) {
/* /*
* Couldn't open the entry, stat it or the on-disk type * Check for a mismatch between the type in the specification and
* didn't match. If this entry is optional, just ignore it * the type of the contents object on disk.
* and read the next header entry.
*/ */
*use_next = 1; if (st != NULL) {
return ARCHIVE_OK; if (
((st->st_mode & S_IFMT) == S_IFREG &&
archive_entry_filetype(entry) == AE_IFREG)
#ifdef S_IFLNK
|| ((st->st_mode & S_IFMT) == S_IFLNK &&
archive_entry_filetype(entry) == AE_IFLNK)
#endif
#ifdef S_IFSOCK
|| ((st->st_mode & S_IFSOCK) == S_IFSOCK &&
archive_entry_filetype(entry) == AE_IFSOCK)
#endif
#ifdef S_IFCHR
|| ((st->st_mode & S_IFMT) == S_IFCHR &&
archive_entry_filetype(entry) == AE_IFCHR)
#endif
#ifdef S_IFBLK
|| ((st->st_mode & S_IFMT) == S_IFBLK &&
archive_entry_filetype(entry) == AE_IFBLK)
#endif
|| ((st->st_mode & S_IFMT) == S_IFDIR &&
archive_entry_filetype(entry) == AE_IFDIR)
#ifdef S_IFIFO
|| ((st->st_mode & S_IFMT) == S_IFIFO &&
archive_entry_filetype(entry) == AE_IFIFO)
#endif
) {
/* Types match. */
} else {
/* Types don't match; bail out gracefully. */
if (mtree->fd >= 0)
close(mtree->fd);
mtree->fd = -1;
if (parsed_kws & MTREE_HAS_OPTIONAL) {
/* It's not an error for an optional entry
to not match disk. */
*use_next = 1;
} else if (r == ARCHIVE_OK) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"mtree specification has different type for %s",
archive_entry_pathname(entry));
r = ARCHIVE_WARN;
}
return r;
}
}
/*
* If there is a contents file on disk, pick some of the metadata
* from that file. For most of these, we only set it from the contents
* if it wasn't already parsed from the specification.
*/
if (st != NULL) {
if (((parsed_kws & MTREE_HAS_DEVICE) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0) &&
(archive_entry_filetype(entry) == AE_IFCHR ||
archive_entry_filetype(entry) == AE_IFBLK))
archive_entry_set_rdev(entry, st->st_rdev);
if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_gid(entry, st->st_gid);
if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_uid(entry, st->st_uid);
if ((parsed_kws & MTREE_HAS_MTIME) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0) {
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtimespec.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtim.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIME_N
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtime_n);
#elif HAVE_STRUCT_STAT_ST_UMTIME
archive_entry_set_mtime(entry, st->st_mtime,
st->st_umtime*1000);
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtime_usec*1000);
#else
archive_entry_set_mtime(entry, st->st_mtime, 0);
#endif
}
if ((parsed_kws & MTREE_HAS_NLINK) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_nlink(entry, st->st_nlink);
if ((parsed_kws & MTREE_HAS_PERM) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_perm(entry, st->st_mode);
if ((parsed_kws & MTREE_HAS_SIZE) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_size(entry, st->st_size);
archive_entry_set_ino(entry, st->st_ino);
archive_entry_set_dev(entry, st->st_dev);
archive_entry_linkify(mtree->resolver, &entry, &sparse_entry);
} else if (parsed_kws & MTREE_HAS_OPTIONAL) {
/*
* Couldn't open the entry, stat it or the on-disk type
* didn't match. If this entry is optional, just ignore it
* and read the next header entry.
*/
*use_next = 1;
return ARCHIVE_OK;
}
} }
mtree->cur_size = archive_entry_size(entry); mtree->cur_size = archive_entry_size(entry);
@ -1292,33 +1319,82 @@ parse_line(struct archive_read *a, struct archive_entry *entry,
/* /*
* Device entries have one of the following forms: * Device entries have one of the following forms:
* raw dev_t * - raw dev_t
* format,major,minor[,subdevice] * - format,major,minor[,subdevice]
* * When parsing succeeded, `pdev' will contain the appropriate dev_t value.
* Just use major and minor, no translation etc is done
* between formats.
*/ */
static int
parse_device(struct archive *a, struct archive_entry *entry, char *val)
{
char *comma1, *comma2;
comma1 = strchr(val, ','); /* strsep() is not in C90, but strcspn() is. */
if (comma1 == NULL) { /* Taken from http://unixpapa.com/incnote/string.html */
archive_entry_set_dev(entry, (dev_t)mtree_atol10(&val)); static char *
return (ARCHIVE_OK); la_strsep(char **sp, char *sep)
{
char *p, *s;
if (sp == NULL || *sp == NULL || **sp == '\0')
return(NULL);
s = *sp;
p = s + strcspn(s, sep);
if (*p != '\0')
*p++ = '\0';
*sp = p;
return(s);
}
static int
parse_device(dev_t *pdev, struct archive *a, char *val)
{
#define MAX_PACK_ARGS 3
unsigned long numbers[MAX_PACK_ARGS];
char *p, *dev;
int argc;
pack_t *pack;
dev_t result;
const char *error = NULL;
memset(pdev, 0, sizeof(*pdev));
if ((dev = strchr(val, ',')) != NULL) {
/*
* Device's major/minor are given in a specified format.
* Decode and pack it accordingly.
*/
*dev++ = '\0';
if ((pack = pack_find(val)) == NULL) {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"Unknown format `%s'", val);
return ARCHIVE_WARN;
}
argc = 0;
while ((p = la_strsep(&dev, ",")) != NULL) {
if (*p == '\0') {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"Missing number");
return ARCHIVE_WARN;
}
numbers[argc++] = mtree_atol(&p);
if (argc > MAX_PACK_ARGS) {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"Too many arguments");
return ARCHIVE_WARN;
}
}
if (argc < 2) {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"Not enough arguments");
return ARCHIVE_WARN;
}
result = (*pack)(argc, numbers, &error);
if (error != NULL) {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"%s", error);
return ARCHIVE_WARN;
}
} else {
/* file system raw value. */
result = (dev_t)mtree_atol(&val);
} }
++comma1; *pdev = result;
comma2 = strchr(comma1, ','); return ARCHIVE_OK;
if (comma2 == NULL) { #undef MAX_PACK_ARGS
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed device attribute");
return (ARCHIVE_WARN);
}
++comma2;
archive_entry_set_rdevmajor(entry, (dev_t)mtree_atol(&comma1));
archive_entry_set_rdevminor(entry, (dev_t)mtree_atol(&comma2));
return (ARCHIVE_OK);
} }
/* /*
@ -1374,8 +1450,16 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
break; break;
case 'd': case 'd':
if (strcmp(key, "device") == 0) { if (strcmp(key, "device") == 0) {
/* stat(2) st_rdev field, e.g. the major/minor IDs
* of a char/block special file */
int r;
dev_t dev;
*parsed_kws |= MTREE_HAS_DEVICE; *parsed_kws |= MTREE_HAS_DEVICE;
return parse_device(&a->archive, entry, val); r = parse_device(&dev, &a->archive, val);
if (r == ARCHIVE_OK)
archive_entry_set_rdev(entry, dev);
return r;
} }
case 'f': case 'f':
if (strcmp(key, "flags") == 0) { if (strcmp(key, "flags") == 0) {
@ -1394,6 +1478,11 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_copy_gname(entry, val); archive_entry_copy_gname(entry, val);
break; break;
} }
case 'i':
if (strcmp(key, "inode") == 0) {
archive_entry_set_ino(entry, mtree_atol10(&val));
break;
}
case 'l': case 'l':
if (strcmp(key, "link") == 0) { if (strcmp(key, "link") == 0) {
archive_entry_copy_symlink(entry, val); archive_entry_copy_symlink(entry, val);
@ -1423,6 +1512,17 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
break; break;
} }
case 'r': case 'r':
if (strcmp(key, "resdevice") == 0) {
/* stat(2) st_dev field, e.g. the device ID where the
* inode resides */
int r;
dev_t dev;
r = parse_device(&dev, &a->archive, val);
if (r == ARCHIVE_OK)
archive_entry_set_dev(entry, dev);
return r;
}
if (strcmp(key, "rmd160") == 0 || if (strcmp(key, "rmd160") == 0 ||
strcmp(key, "rmd160digest") == 0) strcmp(key, "rmd160digest") == 0)
break; break;

View File

@ -304,8 +304,15 @@ struct rar
ssize_t avail_in; ssize_t avail_in;
const unsigned char *next_in; const unsigned char *next_in;
} br; } br;
/*
* Custom field to denote that this archive contains encrypted entries
*/
int has_encrypted_entries;
}; };
static int archive_read_support_format_rar_capabilities(struct archive_read *);
static int archive_read_format_rar_has_encrypted_entries(struct archive_read *);
static int archive_read_format_rar_bid(struct archive_read *, int); static int archive_read_format_rar_bid(struct archive_read *, int);
static int archive_read_format_rar_options(struct archive_read *, static int archive_read_format_rar_options(struct archive_read *,
const char *, const char *); const char *, const char *);
@ -646,6 +653,12 @@ archive_read_support_format_rar(struct archive *_a)
} }
memset(rar, 0, sizeof(*rar)); memset(rar, 0, sizeof(*rar));
/*
* Until enough data has been read, we cannot tell about
* any encrypted entries yet.
*/
rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
r = __archive_read_register_format(a, r = __archive_read_register_format(a,
rar, rar,
"rar", "rar",
@ -655,13 +668,36 @@ archive_read_support_format_rar(struct archive *_a)
archive_read_format_rar_read_data, archive_read_format_rar_read_data,
archive_read_format_rar_read_data_skip, archive_read_format_rar_read_data_skip,
archive_read_format_rar_seek_data, archive_read_format_rar_seek_data,
archive_read_format_rar_cleanup); archive_read_format_rar_cleanup,
archive_read_support_format_rar_capabilities,
archive_read_format_rar_has_encrypted_entries);
if (r != ARCHIVE_OK) if (r != ARCHIVE_OK)
free(rar); free(rar);
return (r); return (r);
} }
static int
archive_read_support_format_rar_capabilities(struct archive_read * a)
{
(void)a; /* UNUSED */
return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA
| ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
}
static int
archive_read_format_rar_has_encrypted_entries(struct archive_read *_a)
{
if (_a && _a->format) {
struct rar * rar = (struct rar *)_a->format->data;
if (rar) {
return rar->has_encrypted_entries;
}
}
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
}
static int static int
archive_read_format_rar_bid(struct archive_read *a, int best_bid) archive_read_format_rar_bid(struct archive_read *a, int best_bid)
{ {
@ -755,7 +791,7 @@ archive_read_format_rar_options(struct archive_read *a,
{ {
struct rar *rar; struct rar *rar;
int ret = ARCHIVE_FAILED; int ret = ARCHIVE_FAILED;
rar = (struct rar *)(a->format->data); rar = (struct rar *)(a->format->data);
if (strcmp(key, "hdrcharset") == 0) { if (strcmp(key, "hdrcharset") == 0) {
if (val == NULL || val[0] == 0) if (val == NULL || val[0] == 0)
@ -797,6 +833,17 @@ archive_read_format_rar_read_header(struct archive_read *a,
rar = (struct rar *)(a->format->data); rar = (struct rar *)(a->format->data);
/*
* It should be sufficient to call archive_read_next_header() for
* a reader to determine if an entry is encrypted or not. If the
* encryption of an entry is only detectable when calling
* archive_read_data(), so be it. We'll do the same check there
* as well.
*/
if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
rar->has_encrypted_entries = 0;
}
/* RAR files can be generated without EOF headers, so return ARCHIVE_EOF if /* RAR files can be generated without EOF headers, so return ARCHIVE_EOF if
* this fails. * this fails.
*/ */
@ -857,9 +904,14 @@ archive_read_format_rar_read_header(struct archive_read *a,
sizeof(rar->reserved2)); sizeof(rar->reserved2));
} }
/* Main header is password encrytped, so we cannot read any
file names or any other info about files from the header. */
if (rar->main_flags & MHD_PASSWORD) if (rar->main_flags & MHD_PASSWORD)
{ {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_entry_set_is_metadata_encrypted(entry, 1);
archive_entry_set_is_data_encrypted(entry, 1);
rar->has_encrypted_entries = 1;
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"RAR encryption support unavailable."); "RAR encryption support unavailable.");
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
} }
@ -938,6 +990,10 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
struct rar *rar = (struct rar *)(a->format->data); struct rar *rar = (struct rar *)(a->format->data);
int ret; int ret;
if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
rar->has_encrypted_entries = 0;
}
if (rar->bytes_unconsumed > 0) { if (rar->bytes_unconsumed > 0) {
/* Consume as much as the decompressor actually used. */ /* Consume as much as the decompressor actually used. */
__archive_read_consume(a, rar->bytes_unconsumed); __archive_read_consume(a, rar->bytes_unconsumed);
@ -957,7 +1013,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
{ {
case COMPRESS_METHOD_STORE: case COMPRESS_METHOD_STORE:
ret = read_data_stored(a, buff, size, offset); ret = read_data_stored(a, buff, size, offset);
break; break;
case COMPRESS_METHOD_FASTEST: case COMPRESS_METHOD_FASTEST:
case COMPRESS_METHOD_FAST: case COMPRESS_METHOD_FAST:
@ -967,13 +1023,13 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
ret = read_data_compressed(a, buff, size, offset); ret = read_data_compressed(a, buff, size, offset);
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN)
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc); __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
break; break;
default: default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unsupported compression method for RAR file."); "Unsupported compression method for RAR file.");
ret = ARCHIVE_FATAL; ret = ARCHIVE_FATAL;
break; break;
} }
return (ret); return (ret);
} }
@ -1290,9 +1346,14 @@ read_header(struct archive_read *a, struct archive_entry *entry,
if (rar->file_flags & FHD_PASSWORD) if (rar->file_flags & FHD_PASSWORD)
{ {
archive_entry_set_is_data_encrypted(entry, 1);
rar->has_encrypted_entries = 1;
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"RAR encryption support unavailable."); "RAR encryption support unavailable.");
return (ARCHIVE_FATAL); /* Since it is only the data part itself that is encrypted we can at least
extract information about the currently processed entry and don't need
to return ARCHIVE_FATAL here. */
/*return (ARCHIVE_FATAL);*/
} }
if (rar->file_flags & FHD_LARGE) if (rar->file_flags & FHD_LARGE)
@ -1377,7 +1438,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
flagbyte = *(p + offset++); flagbyte = *(p + offset++);
flagbits = 8; flagbits = 8;
} }
flagbits -= 2; flagbits -= 2;
switch((flagbyte >> flagbits) & 3) switch((flagbyte >> flagbits) & 3)
{ {
@ -2611,7 +2672,7 @@ expand(struct archive_read *a, int64_t end)
if ((symbol = read_next_symbol(a, &rar->maincode)) < 0) if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
rar->output_last_match = 0; rar->output_last_match = 0;
if (symbol < 256) if (symbol < 256)
{ {
lzss_emit_literal(rar, symbol); lzss_emit_literal(rar, symbol);

View File

@ -78,7 +78,9 @@ archive_read_support_format_raw(struct archive *_a)
archive_read_format_raw_read_data, archive_read_format_raw_read_data,
archive_read_format_raw_read_data_skip, archive_read_format_raw_read_data_skip,
NULL, NULL,
archive_read_format_raw_cleanup); archive_read_format_raw_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK) if (r != ARCHIVE_OK)
free(info); free(info);
return (r); return (r);

View File

@ -151,6 +151,8 @@ struct tar {
struct archive_string_conv *sconv_default; struct archive_string_conv *sconv_default;
int init_default_conversion; int init_default_conversion;
int compat_2x; int compat_2x;
int process_mac_extensions;
int read_concatenated_archives;
}; };
static int archive_block_is_null(const char *p); static int archive_block_is_null(const char *p);
@ -241,6 +243,10 @@ archive_read_support_format_tar(struct archive *_a)
ARCHIVE_STATE_NEW, "archive_read_support_format_tar"); ARCHIVE_STATE_NEW, "archive_read_support_format_tar");
tar = (struct tar *)calloc(1, sizeof(*tar)); tar = (struct tar *)calloc(1, sizeof(*tar));
#ifdef HAVE_COPYFILE_H
/* Set this by default on Mac OS. */
tar->process_mac_extensions = 1;
#endif
if (tar == NULL) { if (tar == NULL) {
archive_set_error(&a->archive, ENOMEM, archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data"); "Can't allocate tar data");
@ -254,7 +260,9 @@ archive_read_support_format_tar(struct archive *_a)
archive_read_format_tar_read_data, archive_read_format_tar_read_data,
archive_read_format_tar_skip, archive_read_format_tar_skip,
NULL, NULL,
archive_read_format_tar_cleanup); archive_read_format_tar_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK) if (r != ARCHIVE_OK)
free(tar); free(tar);
@ -368,7 +376,7 @@ archive_read_format_tar_options(struct archive_read *a,
tar = (struct tar *)(a->format->data); tar = (struct tar *)(a->format->data);
if (strcmp(key, "compat-2x") == 0) { if (strcmp(key, "compat-2x") == 0) {
/* Handle UTF-8 filnames as libarchive 2.x */ /* Handle UTF-8 filnames as libarchive 2.x */
tar->compat_2x = (val != NULL)?1:0; tar->compat_2x = (val != NULL && val[0] != 0);
tar->init_default_conversion = tar->compat_2x; tar->init_default_conversion = tar->compat_2x;
return (ARCHIVE_OK); return (ARCHIVE_OK);
} else if (strcmp(key, "hdrcharset") == 0) { } else if (strcmp(key, "hdrcharset") == 0) {
@ -385,6 +393,12 @@ archive_read_format_tar_options(struct archive_read *a,
ret = ARCHIVE_FATAL; ret = ARCHIVE_FATAL;
} }
return (ret); return (ret);
} else if (strcmp(key, "mac-ext") == 0) {
tar->process_mac_extensions = (val != NULL && val[0] != 0);
return (ARCHIVE_OK);
} else if (strcmp(key, "read_concatenated_archives") == 0) {
tar->read_concatenated_archives = (val != NULL && val[0] != 0);
return (ARCHIVE_OK);
} }
/* Note: The "warn" return is just to inform the options /* Note: The "warn" return is just to inform the options
@ -397,7 +411,7 @@ archive_read_format_tar_options(struct archive_read *a,
* how much unconsumed data we have floating around, and to consume * how much unconsumed data we have floating around, and to consume
* anything outstanding since we're going to do read_aheads * anything outstanding since we're going to do read_aheads
*/ */
static void static void
tar_flush_unconsumed(struct archive_read *a, size_t *unconsumed) tar_flush_unconsumed(struct archive_read *a, size_t *unconsumed)
{ {
if (*unconsumed) { if (*unconsumed) {
@ -590,7 +604,7 @@ archive_read_format_tar_skip(struct archive_read *a)
tar = (struct tar *)(a->format->data); tar = (struct tar *)(a->format->data);
bytes_skipped = __archive_read_consume(a, bytes_skipped = __archive_read_consume(a,
tar->entry_bytes_remaining + tar->entry_padding + tar->entry_bytes_remaining + tar->entry_padding +
tar->entry_bytes_unconsumed); tar->entry_bytes_unconsumed);
if (bytes_skipped < 0) if (bytes_skipped < 0)
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
@ -619,36 +633,50 @@ tar_read_header(struct archive_read *a, struct tar *tar,
const struct archive_entry_header_ustar *header; const struct archive_entry_header_ustar *header;
const struct archive_entry_header_gnutar *gnuheader; const struct archive_entry_header_gnutar *gnuheader;
tar_flush_unconsumed(a, unconsumed); /* Loop until we find a workable header record. */
for (;;) {
/* Read 512-byte header record */
h = __archive_read_ahead(a, 512, &bytes);
if (bytes < 0)
return ((int)bytes);
if (bytes == 0) { /* EOF at a block boundary. */
/* Some writers do omit the block of nulls. <sigh> */
return (ARCHIVE_EOF);
}
if (bytes < 512) { /* Short block at EOF; this is bad. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated tar archive");
return (ARCHIVE_FATAL);
}
*unconsumed = 512;
/* Check for end-of-archive mark. */
if (h[0] == 0 && archive_block_is_null(h)) {
/* Try to consume a second all-null record, as well. */
tar_flush_unconsumed(a, unconsumed); tar_flush_unconsumed(a, unconsumed);
h = __archive_read_ahead(a, 512, NULL);
if (h != NULL) /* Read 512-byte header record */
__archive_read_consume(a, 512); h = __archive_read_ahead(a, 512, &bytes);
archive_clear_error(&a->archive); if (bytes < 0)
return ((int)bytes);
if (bytes == 0) { /* EOF at a block boundary. */
/* Some writers do omit the block of nulls. <sigh> */
return (ARCHIVE_EOF);
}
if (bytes < 512) { /* Short block at EOF; this is bad. */
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated tar archive");
return (ARCHIVE_FATAL);
}
*unconsumed = 512;
/* Header is workable if it's not an end-of-archive mark. */
if (h[0] != 0 || !archive_block_is_null(h))
break;
/* Ensure format is set for archives with only null blocks. */
if (a->archive.archive_format_name == NULL) { if (a->archive.archive_format_name == NULL) {
a->archive.archive_format = ARCHIVE_FORMAT_TAR; a->archive.archive_format = ARCHIVE_FORMAT_TAR;
a->archive.archive_format_name = "tar"; a->archive.archive_format_name = "tar";
} }
return (ARCHIVE_EOF);
if (!tar->read_concatenated_archives) {
/* Try to consume a second all-null record, as well. */
tar_flush_unconsumed(a, unconsumed);
h = __archive_read_ahead(a, 512, NULL);
if (h != NULL && h[0] == 0 && archive_block_is_null(h))
__archive_read_consume(a, 512);
archive_clear_error(&a->archive);
return (ARCHIVE_EOF);
}
/*
* We're reading concatenated archives, ignore this block and
* loop to get the next.
*/
} }
/* /*
@ -683,6 +711,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
a->archive.archive_format_name = "POSIX pax interchange format"; a->archive.archive_format_name = "POSIX pax interchange format";
err = header_pax_global(a, tar, entry, h, unconsumed); err = header_pax_global(a, tar, entry, h, unconsumed);
if (err == ARCHIVE_EOF)
return (err);
break; break;
case 'K': /* Long link name (GNU tar, others) */ case 'K': /* Long link name (GNU tar, others) */
err = header_longlink(a, tar, entry, h, unconsumed); err = header_longlink(a, tar, entry, h, unconsumed);
@ -735,9 +765,9 @@ tar_read_header(struct archive_read *a, struct tar *tar,
* extensions for both the AppleDouble extension entry and the * extensions for both the AppleDouble extension entry and the
* regular entry. * regular entry.
*/ */
/* TODO: Should this be disabled on non-Mac platforms? */
if ((err == ARCHIVE_WARN || err == ARCHIVE_OK) && if ((err == ARCHIVE_WARN || err == ARCHIVE_OK) &&
tar->header_recursion_depth == 0) { tar->header_recursion_depth == 0 &&
tar->process_mac_extensions) {
int err2 = read_mac_metadata_blob(a, tar, entry, h, unconsumed); int err2 = read_mac_metadata_blob(a, tar, entry, h, unconsumed);
if (err2 < err) if (err2 < err)
err = err2; err = err2;
@ -780,12 +810,20 @@ checksum(struct archive_read *a, const void *h)
{ {
const unsigned char *bytes; const unsigned char *bytes;
const struct archive_entry_header_ustar *header; const struct archive_entry_header_ustar *header;
int check, i, sum; int check, sum;
size_t i;
(void)a; /* UNUSED */ (void)a; /* UNUSED */
bytes = (const unsigned char *)h; bytes = (const unsigned char *)h;
header = (const struct archive_entry_header_ustar *)h; header = (const struct archive_entry_header_ustar *)h;
/* Checksum field must hold an octal number */
for (i = 0; i < sizeof(header->checksum); ++i) {
char c = header->checksum[i];
if (c != ' ' && c != '\0' && (c < '0' || c > '7'))
return 0;
}
/* /*
* Test the checksum. Note that POSIX specifies _unsigned_ * Test the checksum. Note that POSIX specifies _unsigned_
* bytes for this calculation. * bytes for this calculation.
@ -1277,7 +1315,7 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
if (wp[0] == '/' && wp[1] != L'\0') if (wp[0] == '/' && wp[1] != L'\0')
wname = wp + 1; wname = wp + 1;
} }
/* /*
* If last path element starts with "._", then * If last path element starts with "._", then
* this is a Mac extension. * this is a Mac extension.
*/ */
@ -1292,7 +1330,7 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
if (p[0] == '/' && p[1] != '\0') if (p[0] == '/' && p[1] != '\0')
name = p + 1; name = p + 1;
} }
/* /*
* If last path element starts with "._", then * If last path element starts with "._", then
* this is a Mac extension. * this is a Mac extension.
*/ */
@ -2412,9 +2450,10 @@ tar_atol(const char *p, size_t char_cnt)
static int64_t static int64_t
tar_atol_base_n(const char *p, size_t char_cnt, int base) tar_atol_base_n(const char *p, size_t char_cnt, int base)
{ {
int64_t l, limit, last_digit_limit; int64_t l, maxval, limit, last_digit_limit;
int digit, sign; int digit, sign;
maxval = INT64_MAX;
limit = INT64_MAX / base; limit = INT64_MAX / base;
last_digit_limit = INT64_MAX % base; last_digit_limit = INT64_MAX % base;
@ -2431,6 +2470,10 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
sign = -1; sign = -1;
p++; p++;
char_cnt--; char_cnt--;
maxval = INT64_MIN;
limit = -(INT64_MIN / base);
last_digit_limit = INT64_MIN % base;
} }
l = 0; l = 0;
@ -2438,8 +2481,7 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
digit = *p - '0'; digit = *p - '0';
while (digit >= 0 && digit < base && char_cnt != 0) { while (digit >= 0 && digit < base && char_cnt != 0) {
if (l>limit || (l == limit && digit > last_digit_limit)) { if (l>limit || (l == limit && digit > last_digit_limit)) {
l = INT64_MAX; /* Truncate on overflow. */ return maxval; /* Truncate on overflow. */
break;
} }
l = (l * base) + digit; l = (l * base) + digit;
digit = *++p - '0'; digit = *++p - '0';
@ -2462,36 +2504,56 @@ tar_atol10(const char *p, size_t char_cnt)
} }
/* /*
* Parse a base-256 integer. This is just a straight signed binary * Parse a base-256 integer. This is just a variable-length
* value in big-endian order, except that the high-order bit is * twos-complement signed binary value in big-endian order, except
* ignored. * that the high-order bit is ignored. The values here can be up to
* 12 bytes, so we need to be careful about overflowing 64-bit
* (8-byte) integers.
*
* This code unashamedly assumes that the local machine uses 8-bit
* bytes and twos-complement arithmetic.
*/ */
static int64_t static int64_t
tar_atol256(const char *_p, size_t char_cnt) tar_atol256(const char *_p, size_t char_cnt)
{ {
int64_t l, upper_limit, lower_limit; uint64_t l;
const unsigned char *p = (const unsigned char *)_p; const unsigned char *p = (const unsigned char *)_p;
unsigned char c, neg;
upper_limit = INT64_MAX / 256; /* Extend 7-bit 2s-comp to 8-bit 2s-comp, decide sign. */
lower_limit = INT64_MIN / 256; c = *p;
if (c & 0x40) {
/* Pad with 1 or 0 bits, depending on sign. */ neg = 0xff;
if ((0x40 & *p) == 0x40) c |= 0x80;
l = (int64_t)-1; l = ~ARCHIVE_LITERAL_ULL(0);
else } else {
neg = 0;
c &= 0x7f;
l = 0; l = 0;
l = (l << 6) | (0x3f & *p++);
while (--char_cnt > 0) {
if (l > upper_limit) {
l = INT64_MAX; /* Truncate on overflow */
break;
} else if (l < lower_limit) {
l = INT64_MIN;
break;
}
l = (l << 8) | (0xff & (int64_t)*p++);
} }
return (l);
/* If more than 8 bytes, check that we can ignore
* high-order bits without overflow. */
while (char_cnt > sizeof(int64_t)) {
--char_cnt;
if (c != neg)
return neg ? INT64_MIN : INT64_MAX;
c = *++p;
}
/* c is first byte that fits; if sign mismatch, return overflow */
if ((c ^ neg) & 0x80) {
return neg ? INT64_MIN : INT64_MAX;
}
/* Accumulate remaining bytes. */
while (--char_cnt > 0) {
l = (l << 8) | c;
c = *++p;
}
l = (l << 8) | c;
/* Return signed twos-complement value. */
return (int64_t)(l);
} }
/* /*

View File

@ -468,7 +468,9 @@ archive_read_support_format_xar(struct archive *_a)
xar_read_data, xar_read_data,
xar_read_data_skip, xar_read_data_skip,
NULL, NULL,
xar_cleanup); xar_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK) if (r != ARCHIVE_OK)
free(xar); free(xar);
return (r); return (r);
@ -967,10 +969,14 @@ move_reading_point(struct archive_read *a, uint64_t offset)
return ((int)step); return ((int)step);
xar->offset += step; xar->offset += step;
} else { } else {
archive_set_error(&(a->archive), int64_t pos = __archive_read_seek(a, offset, SEEK_SET);
ARCHIVE_ERRNO_MISC, if (pos == ARCHIVE_FAILED) {
"Cannot seek."); archive_set_error(&(a->archive),
return (ARCHIVE_FAILED); ARCHIVE_ERRNO_MISC,
"Cannot seek.");
return (ARCHIVE_FAILED);
}
xar->offset = pos;
} }
} }
return (ARCHIVE_OK); return (ARCHIVE_OK);

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,15 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1
#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__) #if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__)
#include <wincrypt.h> #include <wincrypt.h>
#endif #endif
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
#ifdef HAVE_LZMA_H
#include <lzma.h>
#endif
#ifdef HAVE_BZLIB_H
#include <bzlib.h>
#endif
#include "archive.h" #include "archive.h"
#include "archive_private.h" #include "archive_private.h"
@ -54,6 +63,8 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1
#define O_CLOEXEC 0 #define O_CLOEXEC 0
#endif #endif
static int archive_utility_string_sort_helper(char **, unsigned int);
/* Generic initialization of 'struct archive' objects. */ /* Generic initialization of 'struct archive' objects. */
int int
__archive_clean(struct archive *a) __archive_clean(struct archive *a)
@ -74,6 +85,38 @@ archive_version_string(void)
return (ARCHIVE_VERSION_STRING); return (ARCHIVE_VERSION_STRING);
} }
const char *
archive_version_details(void)
{
static struct archive_string str;
static int init = 0;
if (!init) {
archive_string_init(&str);
archive_strcat(&str, ARCHIVE_VERSION_STRING);
#ifdef HAVE_ZLIB_H
archive_strcat(&str, " zlib/");
archive_strcat(&str, ZLIB_VERSION);
#endif
#ifdef HAVE_LZMA_H
archive_strcat(&str, " liblzma/");
archive_strcat(&str, LZMA_VERSION_STRING);
#endif
#ifdef HAVE_BZLIB_H
{
const char *p = BZ2_bzlibVersion();
const char *sep = strchr(p, ',');
if (sep == NULL)
sep = p + strlen(p);
archive_strcat(&str, " bz2lib/");
archive_strncat(&str, p, sep - p);
}
#endif
}
return str.s;
}
int int
archive_errno(struct archive *a) archive_errno(struct archive *a)
{ {
@ -499,3 +542,69 @@ __archive_ensure_cloexec_flag(int fd)
} }
#endif #endif
} }
/*
* Utility function to sort a group of strings using quicksort.
*/
static int
archive_utility_string_sort_helper(char **strings, unsigned int n)
{
unsigned int i, lesser_count, greater_count;
char **lesser, **greater, **tmp, *pivot;
int retval1, retval2;
/* A list of 0 or 1 elements is already sorted */
if (n <= 1)
return (ARCHIVE_OK);
lesser_count = greater_count = 0;
lesser = greater = NULL;
pivot = strings[0];
for (i = 1; i < n; i++)
{
if (strcmp(strings[i], pivot) < 0)
{
lesser_count++;
tmp = (char **)realloc(lesser, lesser_count * sizeof(char *));
if (!tmp)
return (ARCHIVE_FATAL);
lesser = tmp;
lesser[lesser_count - 1] = strings[i];
}
else
{
greater_count++;
tmp = (char **)realloc(greater, greater_count * sizeof(char *));
if (!tmp)
return (ARCHIVE_FATAL);
greater = tmp;
greater[greater_count - 1] = strings[i];
}
}
/* quicksort(lesser) */
retval1 = archive_utility_string_sort_helper(lesser, lesser_count);
for (i = 0; i < lesser_count; i++)
strings[i] = lesser[i];
free(lesser);
/* pivot */
strings[lesser_count] = pivot;
/* quicksort(greater) */
retval2 = archive_utility_string_sort_helper(greater, greater_count);
for (i = 0; i < greater_count; i++)
strings[lesser_count + 1 + i] = greater[i];
free(greater);
return (retval1 < retval2) ? retval1 : retval2;
}
int
archive_utility_string_sort(char **strings)
{
unsigned int size = 0;
while (strings[size] != NULL)
size++;
return archive_utility_string_sort_helper(strings, size);
}

View File

@ -54,6 +54,14 @@ archive_filter_bytes(struct archive *a, int n)
return ((a->vtable->archive_filter_bytes)(a, n)); return ((a->vtable->archive_filter_bytes)(a, n));
} }
int
archive_free(struct archive *a)
{
if (a == NULL)
return (ARCHIVE_OK);
return ((a->vtable->archive_free)(a));
}
int int
archive_write_close(struct archive *a) archive_write_close(struct archive *a)
{ {
@ -76,9 +84,7 @@ archive_write_fail(struct archive *a)
int int
archive_write_free(struct archive *a) archive_write_free(struct archive *a)
{ {
if (a == NULL) return archive_free(a);
return (ARCHIVE_OK);
return ((a->vtable->archive_free)(a));
} }
#if ARCHIVE_VERSION_NUMBER < 4000000 #if ARCHIVE_VERSION_NUMBER < 4000000
@ -93,9 +99,7 @@ archive_write_finish(struct archive *a)
int int
archive_read_free(struct archive *a) archive_read_free(struct archive *a)
{ {
if (a == NULL) return archive_free(a);
return (ARCHIVE_OK);
return ((a->vtable->archive_free)(a));
} }
#if ARCHIVE_VERSION_NUMBER < 4000000 #if ARCHIVE_VERSION_NUMBER < 4000000

View File

@ -301,7 +301,7 @@ __la_open(const char *path, int flags, ...)
ws = NULL; ws = NULL;
if ((flags & ~O_BINARY) == O_RDONLY) { if ((flags & ~O_BINARY) == O_RDONLY) {
/* /*
* When we open a directory, _open function returns * When we open a directory, _open function returns
* "Permission denied" error. * "Permission denied" error.
*/ */
attr = GetFileAttributesA(path); attr = GetFileAttributesA(path);
@ -515,9 +515,9 @@ __hstat(HANDLE handle, struct ustat *st)
else else
mode |= S_IFREG; mode |= S_IFREG;
st->st_mode = mode; st->st_mode = mode;
fileTimeToUTC(&info.ftLastAccessTime, &t, &ns); fileTimeToUTC(&info.ftLastAccessTime, &t, &ns);
st->st_atime = t; st->st_atime = t;
st->st_atime_nsec = ns; st->st_atime_nsec = ns;
fileTimeToUTC(&info.ftLastWriteTime, &t, &ns); fileTimeToUTC(&info.ftLastWriteTime, &t, &ns);
st->st_mtime = t; st->st_mtime = t;
@ -525,7 +525,7 @@ __hstat(HANDLE handle, struct ustat *st)
fileTimeToUTC(&info.ftCreationTime, &t, &ns); fileTimeToUTC(&info.ftCreationTime, &t, &ns);
st->st_ctime = t; st->st_ctime = t;
st->st_ctime_nsec = ns; st->st_ctime_nsec = ns;
st->st_size = st->st_size =
((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1)) ((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1))
+ (int64_t)(info.nFileSizeLow); + (int64_t)(info.nFileSizeLow);
#ifdef SIMULATE_WIN_STAT #ifdef SIMULATE_WIN_STAT
@ -599,7 +599,7 @@ __la_stat(const char *path, struct stat *st)
struct ustat u; struct ustat u;
int ret; int ret;
handle = la_CreateFile(path, 0, 0, NULL, OPEN_EXISTING, handle = la_CreateFile(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_BACKUP_SEMANTICS,
NULL); NULL);
if (handle == INVALID_HANDLE_VALUE) { if (handle == INVALID_HANDLE_VALUE) {

View File

@ -89,7 +89,7 @@
/* Alias the Windows _function to the POSIX equivalent. */ /* Alias the Windows _function to the POSIX equivalent. */
#define close _close #define close _close
#define fcntl(fd, cmd, flg) /* No operation. */ #define fcntl(fd, cmd, flg) /* No operation. */
#ifndef fileno #ifndef fileno
#define fileno _fileno #define fileno _fileno
#endif #endif
@ -109,13 +109,14 @@
#define lstat __la_stat #define lstat __la_stat
#define open __la_open #define open __la_open
#define read __la_read #define read __la_read
#if !defined(__BORLANDC__) #if !defined(__BORLANDC__) && !defined(__WATCOMC__)
#define setmode _setmode #define setmode _setmode
#endif #endif
#ifdef stat #ifdef stat
#undef stat #undef stat
#endif #endif
#define stat(path,stref) __la_stat(path,stref) #define stat(path,stref) __la_stat(path,stref)
#if !defined(__WATCOMC__)
#if !defined(__BORLANDC__) #if !defined(__BORLANDC__)
#define strdup _strdup #define strdup _strdup
#endif #endif
@ -123,9 +124,12 @@
#if !defined(__BORLANDC__) #if !defined(__BORLANDC__)
#define umask _umask #define umask _umask
#endif #endif
#endif
#define waitpid __la_waitpid #define waitpid __la_waitpid
#define write __la_write #define write __la_write
#if !defined(__WATCOMC__)
#ifndef O_RDONLY #ifndef O_RDONLY
#define O_RDONLY _O_RDONLY #define O_RDONLY _O_RDONLY
#define O_WRONLY _O_WRONLY #define O_WRONLY _O_WRONLY
@ -203,7 +207,7 @@
#define _S_IXGRP (_S_IXUSR >> 3) /* read permission, group */ #define _S_IXGRP (_S_IXUSR >> 3) /* read permission, group */
#define _S_IWGRP (_S_IWUSR >> 3) /* write permission, group */ #define _S_IWGRP (_S_IWUSR >> 3) /* write permission, group */
#define _S_IRGRP (_S_IRUSR >> 3) /* execute/search permission, group */ #define _S_IRGRP (_S_IRUSR >> 3) /* execute/search permission, group */
#define _S_IRWXO (_S_IRWXG >> 3) #define _S_IRWXO (_S_IRWXG >> 3)
#define _S_IXOTH (_S_IXGRP >> 3) /* read permission, other */ #define _S_IXOTH (_S_IXGRP >> 3) /* read permission, other */
#define _S_IWOTH (_S_IWGRP >> 3) /* write permission, other */ #define _S_IWOTH (_S_IWGRP >> 3) /* write permission, other */
#define _S_IROTH (_S_IRGRP >> 3) /* execute/search permission, other */ #define _S_IROTH (_S_IRGRP >> 3) /* execute/search permission, other */
@ -223,6 +227,8 @@
#define S_IWOTH _S_IWOTH #define S_IWOTH _S_IWOTH
#define S_IROTH _S_IROTH #define S_IROTH _S_IROTH
#endif
#define F_DUPFD 0 /* Duplicate file descriptor. */ #define F_DUPFD 0 /* Duplicate file descriptor. */
#define F_GETFD 1 /* Get file descriptor flags. */ #define F_GETFD 1 /* Get file descriptor flags. */
#define F_SETFD 2 /* Set file descriptor flags. */ #define F_SETFD 2 /* Set file descriptor flags. */

View File

@ -503,8 +503,9 @@ _archive_write_close(struct archive *_a)
archive_clear_error(&a->archive); archive_clear_error(&a->archive);
/* Finish the last entry. */ /* Finish the last entry if a finish callback is specified */
if (a->archive.state == ARCHIVE_STATE_DATA) if (a->archive.state == ARCHIVE_STATE_DATA
&& a->format_finish_entry != NULL)
r = ((a->format_finish_entry)(a)); r = ((a->format_finish_entry)(a));
/* Finish off the archive. */ /* Finish off the archive. */
@ -638,6 +639,9 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
/* Format and write header. */ /* Format and write header. */
r2 = ((a->format_write_header)(a, entry)); r2 = ((a->format_write_header)(a, entry));
if (r2 == ARCHIVE_FAILED) {
return (ARCHIVE_FAILED);
}
if (r2 == ARCHIVE_FATAL) { if (r2 == ARCHIVE_FATAL) {
a->archive.state = ARCHIVE_STATE_FATAL; a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL); return (ARCHIVE_FATAL);
@ -658,7 +662,8 @@ _archive_write_finish_entry(struct archive *_a)
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
"archive_write_finish_entry"); "archive_write_finish_entry");
if (a->archive.state & ARCHIVE_STATE_DATA) if (a->archive.state & ARCHIVE_STATE_DATA
&& a->format_finish_entry != NULL)
ret = (a->format_finish_entry)(a); ret = (a->format_finish_entry)(a);
a->archive.state = ARCHIVE_STATE_HEADER; a->archive.state = ARCHIVE_STATE_HEADER;
return (ret); return (ret);
@ -671,8 +676,13 @@ static ssize_t
_archive_write_data(struct archive *_a, const void *buff, size_t s) _archive_write_data(struct archive *_a, const void *buff, size_t s)
{ {
struct archive_write *a = (struct archive_write *)_a; struct archive_write *a = (struct archive_write *)_a;
const size_t max_write = INT_MAX;
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC, archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_DATA, "archive_write_data"); ARCHIVE_STATE_DATA, "archive_write_data");
/* In particular, this catches attempts to pass negative values. */
if (s > max_write)
s = max_write;
archive_clear_error(&a->archive); archive_clear_error(&a->archive);
return ((a->format_write_data)(a, buff, s)); return ((a->format_write_data)(a, buff, s));
} }

View File

@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$");
struct write_lrzip { struct write_lrzip {
struct archive_write_program_data *pdata; struct archive_write_program_data *pdata;
int compression_level; int compression_level;
enum { lzma = 0, bzip2, gzip, lzo, zpaq } compression; enum { lzma = 0, bzip2, gzip, lzo, none, zpaq } compression;
}; };
static int archive_write_lrzip_open(struct archive_write_filter *); static int archive_write_lrzip_open(struct archive_write_filter *);
@ -107,6 +107,8 @@ archive_write_lrzip_options(struct archive_write_filter *f, const char *key,
data->compression = gzip; data->compression = gzip;
else if (strcmp(value, "lzo") == 0) else if (strcmp(value, "lzo") == 0)
data->compression = lzo; data->compression = lzo;
else if (strcmp(value, "none") == 0)
data->compression = none;
else if (strcmp(value, "zpaq") == 0) else if (strcmp(value, "zpaq") == 0)
data->compression = zpaq; data->compression = zpaq;
else else
@ -148,6 +150,9 @@ archive_write_lrzip_open(struct archive_write_filter *f)
case lzo: case lzo:
archive_strcat(&as, " -l"); archive_strcat(&as, " -l");
break; break;
case none:
archive_strcat(&as, " -n");
break;
case zpaq: case zpaq:
archive_strcat(&as, " -z"); archive_strcat(&as, " -z");
break; break;

View File

@ -43,7 +43,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0
#include "archive_acl_private.h" #include "archive_acl_private.h"
#include "archive_write_disk_private.h" #include "archive_write_disk_private.h"
#if !defined(HAVE_POSIX_ACL) || !defined(ACL_TYPE_NFS4) #ifndef HAVE_POSIX_ACL
/* Default empty function body to satisfy mainline code. */ /* Default empty function body to satisfy mainline code. */
int int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name, archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
@ -79,10 +79,12 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT, ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
return (ret); return (ret);
#ifdef ACL_TYPE_NFS4
} else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) { } else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) {
ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4, ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
return (ret); return (ret);
#endif
} else } else
return ARCHIVE_OK; return ARCHIVE_OK;
} }
@ -94,6 +96,7 @@ static struct {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ}, {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
#ifdef ACL_TYPE_NFS4
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
@ -110,8 +113,10 @@ static struct {
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
}; };
#ifdef ACL_TYPE_NFS4
static struct { static struct {
int archive_inherit; int archive_inherit;
int platform_inherit; int platform_inherit;
@ -121,6 +126,7 @@ static struct {
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY} {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
}; };
#endif
static int static int
set_acl(struct archive *a, int fd, const char *name, set_acl(struct archive *a, int fd, const char *name,
@ -130,7 +136,9 @@ set_acl(struct archive *a, int fd, const char *name,
acl_t acl; acl_t acl;
acl_entry_t acl_entry; acl_entry_t acl_entry;
acl_permset_t acl_permset; acl_permset_t acl_permset;
#ifdef ACL_TYPE_NFS4
acl_flagset_t acl_flagset; acl_flagset_t acl_flagset;
#endif
int ret; int ret;
int ae_type, ae_permset, ae_tag, ae_id; int ae_type, ae_permset, ae_tag, ae_id;
uid_t ae_uid; uid_t ae_uid;
@ -171,14 +179,17 @@ set_acl(struct archive *a, int fd, const char *name,
case ARCHIVE_ENTRY_ACL_OTHER: case ARCHIVE_ENTRY_ACL_OTHER:
acl_set_tag_type(acl_entry, ACL_OTHER); acl_set_tag_type(acl_entry, ACL_OTHER);
break; break;
#ifdef ACL_TYPE_NFS4
case ARCHIVE_ENTRY_ACL_EVERYONE: case ARCHIVE_ENTRY_ACL_EVERYONE:
acl_set_tag_type(acl_entry, ACL_EVERYONE); acl_set_tag_type(acl_entry, ACL_EVERYONE);
break; break;
#endif
default: default:
/* XXX */ /* XXX */
break; break;
} }
#ifdef ACL_TYPE_NFS4
switch (ae_type) { switch (ae_type) {
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW); acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
@ -200,6 +211,7 @@ set_acl(struct archive *a, int fd, const char *name,
// XXX error handling here. // XXX error handling here.
break; break;
} }
#endif
acl_get_permset(acl_entry, &acl_permset); acl_get_permset(acl_entry, &acl_permset);
acl_clear_perms(acl_permset); acl_clear_perms(acl_permset);
@ -210,6 +222,7 @@ set_acl(struct archive *a, int fd, const char *name,
acl_perm_map[i].platform_perm); acl_perm_map[i].platform_perm);
} }
#ifdef ACL_TYPE_NFS4
acl_get_flagset_np(acl_entry, &acl_flagset); acl_get_flagset_np(acl_entry, &acl_flagset);
acl_clear_flags_np(acl_flagset); acl_clear_flags_np(acl_flagset);
for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
@ -217,6 +230,7 @@ set_acl(struct archive *a, int fd, const char *name,
acl_add_flag_np(acl_flagset, acl_add_flag_np(acl_flagset,
acl_inherit_map[i].platform_inherit); acl_inherit_map[i].platform_inherit);
} }
#endif
} }
/* Try restoring the ACL through 'fd' if we can. */ /* Try restoring the ACL through 'fd' if we can. */

View File

@ -525,7 +525,7 @@ la_GetFunctionKernel32(const char *name)
static int set; static int set;
if (!set) { if (!set) {
set = 1; set = 1;
lib = LoadLibrary("kernel32.dll"); lib = LoadLibrary(TEXT("kernel32.dll"));
} }
if (lib == NULL) { if (lib == NULL) {
fprintf(stderr, "Can't load kernel32.dll?!\n"); fprintf(stderr, "Can't load kernel32.dll?!\n");

View File

@ -24,13 +24,14 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd February 2, 2012 .Dd February 14, 2013
.Dt ARCHIVE_WRITE_FORMAT 3 .Dt ARCHIVE_WRITE_FORMAT 3
.Os .Os
.Sh NAME .Sh NAME
.Nm archive_write_set_format_cpio , .Nm archive_write_set_format_cpio ,
.Nm archive_write_set_format_pax , .Nm archive_write_set_format_pax ,
.Nm archive_write_set_format_pax_restricted , .Nm archive_write_set_format_pax_restricted ,
.Nm archive_write_set_format_raw ,
.Nm archive_write_set_format_shar , .Nm archive_write_set_format_shar ,
.Nm archive_write_set_format_shar_dump , .Nm archive_write_set_format_shar_dump ,
.Nm archive_write_set_format_ustar .Nm archive_write_set_format_ustar
@ -46,6 +47,8 @@ Streaming Archive Library (libarchive, -larchive)
.Ft int .Ft int
.Fn archive_write_set_format_pax_restricted "struct archive *" .Fn archive_write_set_format_pax_restricted "struct archive *"
.Ft int .Ft int
.Fn archive_write_set_format_raw "struct archive *"
.Ft int
.Fn archive_write_set_format_shar "struct archive *" .Fn archive_write_set_format_shar "struct archive *"
.Ft int .Ft int
.Fn archive_write_set_format_shar_dump "struct archive *" .Fn archive_write_set_format_shar_dump "struct archive *"

View File

@ -47,6 +47,7 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
{ ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, archive_write_set_format_cpio_newc }, { ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, archive_write_set_format_cpio_newc },
{ ARCHIVE_FORMAT_ISO9660, archive_write_set_format_iso9660 }, { ARCHIVE_FORMAT_ISO9660, archive_write_set_format_iso9660 },
{ ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree }, { ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree },
{ ARCHIVE_FORMAT_RAW, archive_write_set_format_raw },
{ ARCHIVE_FORMAT_SHAR, archive_write_set_format_shar }, { ARCHIVE_FORMAT_SHAR, archive_write_set_format_shar },
{ ARCHIVE_FORMAT_SHAR_BASE, archive_write_set_format_shar }, { ARCHIVE_FORMAT_SHAR_BASE, archive_write_set_format_shar },
{ ARCHIVE_FORMAT_SHAR_DUMP, archive_write_set_format_shar_dump }, { ARCHIVE_FORMAT_SHAR_DUMP, archive_write_set_format_shar_dump },
@ -57,7 +58,7 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
archive_write_set_format_pax_restricted }, archive_write_set_format_pax_restricted },
{ ARCHIVE_FORMAT_TAR_USTAR, archive_write_set_format_ustar }, { ARCHIVE_FORMAT_TAR_USTAR, archive_write_set_format_ustar },
{ ARCHIVE_FORMAT_XAR, archive_write_set_format_xar }, { ARCHIVE_FORMAT_XAR, archive_write_set_format_xar },
{ ARCHIVE_FORMAT_ZIP, archive_write_set_format_zip }, { ARCHIVE_FORMAT_ZIP, archive_write_set_format_zip },
{ 0, NULL } { 0, NULL }
}; };

View File

@ -63,6 +63,7 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
{ "pax", archive_write_set_format_pax }, { "pax", archive_write_set_format_pax },
{ "paxr", archive_write_set_format_pax_restricted }, { "paxr", archive_write_set_format_pax_restricted },
{ "posix", archive_write_set_format_pax }, { "posix", archive_write_set_format_pax },
{ "raw", archive_write_set_format_raw },
{ "rpax", archive_write_set_format_pax_restricted }, { "rpax", archive_write_set_format_pax_restricted },
{ "shar", archive_write_set_format_shar }, { "shar", archive_write_set_format_shar },
{ "shardump", archive_write_set_format_shar_dump }, { "shardump", archive_write_set_format_shar_dump },

View File

@ -128,6 +128,9 @@ struct mtree_entry {
unsigned long fflags_clear; unsigned long fflags_clear;
dev_t rdevmajor; dev_t rdevmajor;
dev_t rdevminor; dev_t rdevminor;
dev_t devmajor;
dev_t devminor;
int64_t ino;
}; };
struct mtree_writer { struct mtree_writer {
@ -210,6 +213,9 @@ struct mtree_writer {
#define F_SHA256 0x00800000 /* SHA-256 digest */ #define F_SHA256 0x00800000 /* SHA-256 digest */
#define F_SHA384 0x01000000 /* SHA-384 digest */ #define F_SHA384 0x01000000 /* SHA-384 digest */
#define F_SHA512 0x02000000 /* SHA-512 digest */ #define F_SHA512 0x02000000 /* SHA-512 digest */
#define F_INO 0x04000000 /* inode number */
#define F_RESDEV 0x08000000 /* device ID on which the
* entry resides */
/* Options */ /* Options */
int dironly; /* If it is set, ignore all files except int dironly; /* If it is set, ignore all files except
@ -823,8 +829,11 @@ mtree_entry_new(struct archive_write *a, struct archive_entry *entry,
archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear); archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear);
me->mtime = archive_entry_mtime(entry); me->mtime = archive_entry_mtime(entry);
me->mtime_nsec = archive_entry_mtime_nsec(entry); me->mtime_nsec = archive_entry_mtime_nsec(entry);
me->rdevmajor = archive_entry_rdevmajor(entry); me->rdevmajor = archive_entry_rdevmajor(entry);
me->rdevminor = archive_entry_rdevminor(entry); me->rdevminor = archive_entry_rdevminor(entry);
me->devmajor = archive_entry_devmajor(entry);
me->devminor = archive_entry_devminor(entry);
me->ino = archive_entry_ino(entry);
me->size = archive_entry_size(entry); me->size = archive_entry_size(entry);
if (me->filetype == AE_IFDIR) { if (me->filetype == AE_IFDIR) {
me->dir_info = calloc(1, sizeof(*me->dir_info)); me->dir_info = calloc(1, sizeof(*me->dir_info));
@ -882,7 +891,7 @@ archive_write_mtree_header(struct archive_write *a,
mtree->first = 0; mtree->first = 0;
archive_strcat(&mtree->buf, "#mtree\n"); archive_strcat(&mtree->buf, "#mtree\n");
if ((mtree->keys & SET_KEYS) == 0) if ((mtree->keys & SET_KEYS) == 0)
mtree->output_global_set = 0;/* Disalbed. */ mtree->output_global_set = 0;/* Disabled. */
} }
mtree->entry_bytes_remaining = archive_entry_size(entry); mtree->entry_bytes_remaining = archive_entry_size(entry);
@ -983,6 +992,15 @@ write_mtree_entry(struct archive_write *a, struct mtree_entry *me)
if ((keys & F_UID) != 0) if ((keys & F_UID) != 0)
archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid); archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid);
if ((keys & F_INO) != 0)
archive_string_sprintf(str, " inode=%jd", (intmax_t)me->ino);
if ((keys & F_RESDEV) != 0) {
archive_string_sprintf(str,
" resdevice=native,%ju,%ju",
(uintmax_t)me->devmajor,
(uintmax_t)me->devminor);
}
switch (me->filetype) { switch (me->filetype) {
case AE_IFLNK: case AE_IFLNK:
if ((keys & F_TYPE) != 0) if ((keys & F_TYPE) != 0)
@ -1117,7 +1135,7 @@ write_mtree_entry_tree(struct archive_write *a)
} else { } else {
/* Whenever output_global_set is enabled /* Whenever output_global_set is enabled
* output global value(/set keywords) * output global value(/set keywords)
* even if the directory entry is not allowd * even if the directory entry is not allowed
* to be written because the global values * to be written because the global values
* can be used for the children. */ * can be used for the children. */
if (mtree->output_global_set) if (mtree->output_global_set)
@ -1296,6 +1314,8 @@ archive_write_mtree_options(struct archive_write *a, const char *key,
if (strcmp(key, "indent") == 0) { if (strcmp(key, "indent") == 0) {
mtree->indent = (value != NULL)? 1: 0; mtree->indent = (value != NULL)? 1: 0;
return (ARCHIVE_OK); return (ARCHIVE_OK);
} else if (strcmp(key, "inode") == 0) {
keybit = F_INO;
} }
break; break;
case 'l': case 'l':
@ -1314,7 +1334,9 @@ archive_write_mtree_options(struct archive_write *a, const char *key,
keybit = F_NLINK; keybit = F_NLINK;
break; break;
case 'r': case 'r':
if (strcmp(key, "ripemd160digest") == 0 || if (strcmp(key, "resdevice") == 0) {
keybit = F_RESDEV;
} else if (strcmp(key, "ripemd160digest") == 0 ||
strcmp(key, "rmd160") == 0 || strcmp(key, "rmd160") == 0 ||
strcmp(key, "rmd160digest") == 0) strcmp(key, "rmd160digest") == 0)
keybit = F_RMD160; keybit = F_RMD160;
@ -1855,9 +1877,9 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
return (ret); return (ret);
} }
/* Make a basename from dirname and slash */ /* Make a basename from file->parentdir.s and slash */
*slash = '\0'; *slash = '\0';
file->parentdir.length = slash - dirname; file->parentdir.length = slash - file->parentdir.s;
archive_strcpy(&(file->basename), slash + 1); archive_strcpy(&(file->basename), slash + 1);
return (ret); return (ret);
} }
@ -2198,6 +2220,9 @@ mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np,
np->mtime_nsec = file->mtime_nsec; np->mtime_nsec = file->mtime_nsec;
np->rdevmajor = file->rdevmajor; np->rdevmajor = file->rdevmajor;
np->rdevminor = file->rdevminor; np->rdevminor = file->rdevminor;
np->devmajor = file->devmajor;
np->devminor = file->devminor;
np->ino = file->ino;
return (ARCHIVE_WARN); return (ARCHIVE_WARN);
} }

View File

@ -0,0 +1,125 @@
/*-
* Copyright (c) 2013 Marek Kubica
* 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"
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include "archive_entry.h"
#include "archive_write_private.h"
static ssize_t archive_write_raw_data(struct archive_write *,
const void *buff, size_t s);
static int archive_write_raw_free(struct archive_write *);
static int archive_write_raw_header(struct archive_write *,
struct archive_entry *);
struct raw {
int entries_written;
};
/*
* Set output format to 'raw' format.
*/
int
archive_write_set_format_raw(struct archive *_a)
{
struct archive_write *a = (struct archive_write *)_a;
struct raw *raw;
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_set_format_raw");
/* If someone else was already registered, unregister them. */
if (a->format_free != NULL)
(a->format_free)(a);
raw = (struct raw *)calloc(1, sizeof(*raw));
if (raw == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't allocate raw data");
return (ARCHIVE_FATAL);
}
raw->entries_written = 0;
a->format_data = raw;
a->format_name = "raw";
/* no options exist for this format */
a->format_options = NULL;
a->format_write_header = archive_write_raw_header;
a->format_write_data = archive_write_raw_data;
a->format_finish_entry = NULL;
/* nothing needs to be done on closing */
a->format_close = NULL;
a->format_free = archive_write_raw_free;
a->archive.archive_format = ARCHIVE_FORMAT_RAW;
a->archive.archive_format_name = "RAW";
return (ARCHIVE_OK);
}
static int
archive_write_raw_header(struct archive_write *a, struct archive_entry *entry)
{
struct raw *raw = (struct raw *)a->format_data;
if (archive_entry_filetype(entry) != AE_IFREG) {
archive_set_error(&a->archive, ERANGE,
"Raw format only supports filetype AE_IFREG");
return (ARCHIVE_FATAL);
}
if (raw->entries_written > 0) {
archive_set_error(&a->archive, ERANGE,
"Raw format only supports one entry per archive");
return (ARCHIVE_FATAL);
}
raw->entries_written++;
return (ARCHIVE_OK);
}
static ssize_t
archive_write_raw_data(struct archive_write *a, const void *buff, size_t s)
{
int ret;
ret = __archive_write_output(a, buff, s);
if (ret >= 0)
return (s);
else
return (ret);
}
static int
archive_write_raw_free(struct archive_write *a)
{
struct raw *raw;
raw = (struct raw *)a->format_data;
free(raw);
a->format_data = NULL;
return (ARCHIVE_OK);
}

View File

@ -548,6 +548,7 @@ archive_write_shar_finish_entry(struct archive_write *a)
archive_strcat(&shar->work, ":"); archive_strcat(&shar->work, ":");
shar_quote(&shar->work, g, 1); shar_quote(&shar->work, g, 1);
} }
archive_strcat(&shar->work, " ");
shar_quote(&shar->work, shar_quote(&shar->work,
archive_entry_pathname(shar->entry), 1); archive_entry_pathname(shar->entry), 1);
archive_strcat(&shar->work, "\n"); archive_strcat(&shar->work, "\n");

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,7 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout)
{ {
HANDLE childStdout[2], childStdin[2],childStderr; HANDLE childStdout[2], childStdin[2],childStderr;
SECURITY_ATTRIBUTES secAtts; SECURITY_ATTRIBUTES secAtts;
STARTUPINFO staInfo; STARTUPINFOA staInfo;
PROCESS_INFORMATION childInfo; PROCESS_INFORMATION childInfo;
struct archive_string cmdline; struct archive_string cmdline;
struct archive_string fullpath; struct archive_string fullpath;

View File

@ -28,7 +28,7 @@
.\" From: @(#)mtree.8 8.2 (Berkeley) 12/11/93 .\" From: @(#)mtree.8 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd May 6, 2008 .Dd September 4, 2013
.Dt MTREE 5 .Dt MTREE 5
.Os .Os
.Sh NAME .Sh NAME
@ -134,6 +134,52 @@ The checksum of the file using the default algorithm specified by
the the
.Xr cksum 1 .Xr cksum 1
utility. utility.
.It Cm device
The device number for
.Sy block
or
.Sy char
file types.
The value must be one of the following forms:
.Pp
.Bl -tag -width 4n
.It Ar format , Ns Ar major , Ns Ar minor Ns Bo , Ns Ar subunit Bc
A device with
.Ar major , minor
and optional
.Ar subunit
fields.
Their meaning is specified by the operating's system
.Ar format .
See below for valid formats.
.It Ar number
Opaque number (as stored on the file system).
.El
.Pp
The following values for
.Ar format
are recognized:
.Sy native ,
.Sy 386bsd ,
.Sy 4bsd ,
.Sy bsdos ,
.Sy freebsd ,
.Sy hpux ,
.Sy isc ,
.Sy linux ,
.Sy netbsd ,
.Sy osf1 ,
.Sy sco ,
.Sy solaris ,
.Sy sunos ,
.Sy svr3 ,
.Sy svr4 ,
and
.Sy ultrix .
.Pp
See
.Xr mknod 8
for more details.
.It Cm contents .It Cm contents
The full pathname of a file that holds the contents of this file. The full pathname of a file that holds the contents of this file.
.It Cm flags .It Cm flags
@ -150,6 +196,8 @@ The file group as a numeric value.
The file group as a symbolic name. The file group as a symbolic name.
.It Cm ignore .It Cm ignore
Ignore any file hierarchy below this file. Ignore any file hierarchy below this file.
.It Cm inode
The inode number.
.It Cm link .It Cm link
The target of the symbolic link when type=link. The target of the symbolic link when type=link.
.It Cm md5 .It Cm md5
@ -164,6 +212,16 @@ value.
The number of hard links the file is expected to have. The number of hard links the file is expected to have.
.It Cm nochange .It Cm nochange
Make sure this file or directory exists but otherwise ignore all attributes. Make sure this file or directory exists but otherwise ignore all attributes.
.It Cm optional
The file is optional; do not complain about the file if it is not in
the file hierarchy.
.It Cm resdevice
The
.Dq resident
device number of the file, e.g. the ID of the device that
contains the file.
Its format is the same as the one for
.Cm device .
.It Cm ripemd160digest .It Cm ripemd160digest
The The
.Tn RIPEMD160 .Tn RIPEMD160
@ -192,6 +250,24 @@ message digest of the file.
.It Cm sha256digest .It Cm sha256digest
A synonym for A synonym for
.Cm sha256 . .Cm sha256 .
.It Cm sha384
The
.Tn FIPS
180-2
.Pq Dq Tn SHA-384
message digest of the file.
.It Cm sha384digest
A synonym for
.Cm sha384 .
.It Cm sha512
The
.Tn FIPS
180-2
.Pq Dq Tn SHA-512
message digest of the file.
.It Cm sha512digest
A synonym for
.Cm sha512 .
.It Cm size .It Cm size
The size, in bytes, of the file. The size, in bytes, of the file.
.It Cm time .It Cm time