libarchive 3.1.2 (reduced)

Extract upstream libarchive using the following shell code.

url=git://github.com/libarchive/libarchive.git &&
v=3.1.2 &&
r=19f23e19 &&
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 2013-02-09 12:17:57 -05:00 committed by Brad King
parent 4f4fe6e50b
commit 35df7c8ba8
154 changed files with 18795 additions and 4199 deletions

View File

@ -1,13 +1,36 @@
#
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.6 FATAL_ERROR)
#
PROJECT(libarchive C)
#
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake")
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libarchive_BINARY_DIR}/bin)
endif()
SET(CMAKE_BUILD_TYPE "Release")
#
# Set the Build type for make based generators.
# You can choose following types:
# Debug : Debug build
# Release : Release build
# RelWithDebInfo : Release build with Debug Info
# MinSizeRel : Release Min Size build
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
# Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the
# value type is "UNINITIALIZED".
GET_PROPERTY(cached_type CACHE CMAKE_BUILD_TYPE PROPERTY TYPE)
IF("${cached_type}" STREQUAL "UNINITIALIZED")
SET(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "Build Type" FORCE)
ENDIF("${cached_type}" STREQUAL "UNINITIALIZED")
# Check the Build Type.
IF(NOT "${CMAKE_BUILD_TYPE}"
MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)\$")
MESSAGE(FATAL_ERROR
"Unknown keyword for CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\n"
"Acceptable keywords: Debug,Release,RelWithDebInfo,MinSizeRel")
ENDIF(NOT "${CMAKE_BUILD_TYPE}"
MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)\$")
# On MacOS, prefer MacPorts libraries to system libraries.
# I haven't come up with a compelling argument for this to be conditional.
@ -40,20 +63,80 @@ SET(LIBARCHIVE_VERSION_STRING "${VERSION}")
# libarchive 2.8 == interface version 10 = 2 + 8
# libarchive 2.9 == interface version 11 = 2 + 9
# libarchive 3.0 == interface version 12
# libarchive 3.x == interface version 12 + x
math(EXPR INTERFACE_VERSION "12 + ${_minor}")
# libarchive 3.1 == interface version 13
math(EXPR INTERFACE_VERSION "13 + ${_minor}")
# Set SOVERSION == Interface version
# ?? Should there be more here ??
SET(SOVERSION "${INTERFACE_VERSION}")
# Enalbe CMAKE_PUSH_CHECK_STATE() and CMAKE_POP_CHECK_STATE() macros
# saving and restoring the state of the variables.
INCLUDE(CMakePushCheckState)
# Initialize the state of the variables. This initialization is not
# necessary but this shows you what value the variables initially have.
SET(CMAKE_REQUIRED_DEFINITIONS)
SET(CMAKE_REQUIRED_INCLUDES)
SET(CMAKE_REQUIRED_LIBRARIES)
SET(CMAKE_REQUIRED_FLAGS)
# Especially for early development, we want to be a little
# aggressive about diagnosing build problems; this can get
# relaxed somewhat in final shipping versions.
IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
ADD_DEFINITIONS(-Wall)
SET(CMAKE_REQUIRED_FLAGS "-Wall")
SET(CMAKE_REQUIRED_FLAGS "-Wall -Wformat -Wformat-security")
#################################################################
# Set compile flags for all build types.
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wformat -Wformat-security")
#################################################################
# Set compile flags for debug build.
# This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug"
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Werror -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 "^GNU$")
IF (MSVC)
#################################################################
# Set compile flags for debug build.
# This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug"
# Enable level 4 C4061: The enumerate has no associated handler in a switch
# statement.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4061")
# Enable level 4 C4254: A larger bit field was assigned to a smaller bit
# field.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4254")
# Enable level 4 C4295: An array was initialized but the last character in
# the array is not a null; accessing the array may
# produce unexpected results.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4295")
# Enable level 4 C4296: An unsigned variable was used in a comparison
# operation with zero.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4296")
# Enable level 4 C4389: An operation involved signed and unsigned variables.
# This could result in a loss of data.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4389")
# Enable level 4 C4505: The given function is local and not referenced in
# the body of the module; therefore, the function is
# dead code.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4505")
# Enable level 4 C4514: The optimizer removed an inline function that is not
# called.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4514")
# Enable level 4 C4702: Unreachable code.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4702")
# Enable level 4 C4706: The test value in a conditional expression was the
# result of an assignment.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4706")
# /WX option is the same as gcc's -Werror option.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /WX")
# /Oi option enables built-in functions.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Oi")
#################################################################
# Set compile flags for release build.
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oi")
ENDIF (MSVC)
# Enable CTest/CDash support
include(CTest)
@ -68,19 +151,55 @@ OPTION(ENABLE_XATTR "Enable extended attribute support" ON)
OPTION(ENABLE_ACL "Enable ACL support" ON)
OPTION(ENABLE_ICONV "Enable iconv support" ON)
OPTION(ENABLE_TEST "Enable unit and regression tests" ON)
SET(POSIX_REGEX_LIB "AUTO" CACHE STRING "Choose what library should provide POSIX regular expression support")
SET(ENABLE_SAFESEH "AUTO" CACHE STRING "Enable use of /SAFESEH linker flag (MSVC only)")
SET(WINDOWS_VERSION "" CACHE STRING "Set Windows version to use (Windows only)")
IF(ENABLE_TEST)
ENABLE_TESTING()
ENDIF(ENABLE_TEST)
IF(WIN32)
SET(_WIN32_WINNT 0x0500 CACHE INTERNAL "Setting _WIN32_WINNT to 0x0500 for Windows 2000 APIs")
SET(WINVER 0x0500 CACHE INTERNAL "Setting WINVER to 0x0500 for Windows 2000 APIs")
IF(WINDOWS_VERSION STREQUAL "WIN8")
SET(WINVER 0x0602)
ELSEIF(WINDOWS_VERSION STREQUAL "WIN7")
SET(WINVER 0x0601)
ELSEIF(WINDOWS_VERSION STREQUAL "WS08")
SET(WINVER 0x0600)
ELSEIF(WINDOWS_VERSION STREQUAL "VISTA")
SET(WINVER 0x0600)
ELSEIF(WINDOWS_VERSION STREQUAL "WS03")
SET(WINVER 0x0502)
ELSEIF(WINDOWS_VERSION STREQUAL "WINXP")
SET(WINVER 0x0501)
ELSE(WINDOWS_VERSION STREQUAL "WIN8")
# The default is to use Windows 2000 API.
SET(WINVER 0x0500)
ENDIF(WINDOWS_VERSION STREQUAL "WIN8")
SET(_WIN32_WINNT ${WINVER})
ENDIF(WIN32)
IF(MSVC)
IF(ENABLE_SAFESEH STREQUAL "YES")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH")
SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH")
SET(CMAKE_REQUIRED_LINKER_FLAGS "/SAFESEH")
ELSEIF(ENABLE_SAFESEH STREQUAL "NO")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
SET(CMAKE_REQUIRED_LINKER_FLAGS "/SAFESEH:NO")
ENDIF(ENABLE_SAFESEH STREQUAL "YES")
ENDIF(MSVC)
IF("${CMAKE_C_PLATFORM_ID}" MATCHES "^(HP-UX)$")
ADD_DEFINITIONS(-D_XOPEN_SOURCE=500) # Ask wchar.h for mbstate_t
ENDIF()
#
INCLUDE(CheckCSourceCompiles)
INCLUDE(CheckCSourceRuns)
INCLUDE(LibarchiveCheckCSourceCompiles)
INCLUDE(LibarchiveCheckCSourceRuns)
INCLUDE(CheckFileOffsetBits)
INCLUDE(CheckFuncs)
INCLUDE(CheckHeaderDirent)
@ -125,7 +244,38 @@ MACRO (INSTALL_MAN __mans)
INSTALL(FILES ${_man} DESTINATION "share/man/man${_mansect}")
ENDFOREACH (_man)
ENDMACRO (INSTALL_MAN __mans)
#
# Find out what macro is needed to use libraries on Windows.
#
MACRO (TRY_MACRO_FOR_LIBRARY INCLUDES LIBRARIES
TRY_TYPE SAMPLE_SOURCE MACRO_LIST)
IF(WIN32 AND NOT CYGWIN)
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
SET(CMAKE_REQUIRED_INCLUDES ${INCLUDES})
SET(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES})
FOREACH(VAR ${MACRO_LIST})
# Clear ${VAR} from CACHE If the libraries which ${VAR} was
# checked with are changed.
SET(VAR_WITH_LIB "${VAR}_WITH_LIB")
GET_PROPERTY(PREV_VAR_WITH_LIB VARIABLE PROPERTY ${VAR_WITH_LIB})
IF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}")
UNSET(${VAR} CACHE)
ENDIF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}")
# Check if the library can be used with the macro.
IF("${TRY_TYPE}" MATCHES "COMPILES")
LIBARCHIVE_CHECK_C_SOURCE_COMPILES("${SAMPLE_SOURCE}" ${VAR})
ELSEIF("${TRY_TYPE}" MATCHES "RUNS")
LIBARCHIVE_CHECK_C_SOURCE_RUNS("${SAMPLE_SOURCE}" ${VAR})
ELSE("${TRY_TYPE}" MATCHES "COMPILES")
MESSAGE(FATAL_ERROR "UNKNOWN KEYWORD \"${TRY_TYPE}\" FOR TRY_TYPE")
ENDIF("${TRY_TYPE}" MATCHES "COMPILES")
# Save the libraries which ${VAR} is checked with.
SET(${VAR_WITH_LIB} "${LIBRARIES}" CACHE INTERNAL
"Macro ${VAR} is checked with")
ENDFOREACH(VAR)
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
ENDIF(WIN32 AND NOT CYGWIN)
ENDMACRO (TRY_MACRO_FOR_LIBRARY)
#
# Check compress/decompress libraries
#
@ -172,11 +322,27 @@ IF(ZLIB_FOUND)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${ZLIB_LIBRARIES})
IF(WIN32 AND NOT CYGWIN)
SET(CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIR})
SET(CMAKE_REQUIRED_LIBRARIES ${ZLIB_LIBRARIES})
CHECK_C_SOURCE_Runs(
"#ifndef ZLIB_WINAPI\n#define ZLIB_WINAPI\n#endif\n#include <zlib.h>\nint main() {uLong f = zlibCompileFlags(); return (f&(1U<<10))?0:-1; }"
#
# Test if ZLIB_WINAPI macro is needed to use.
#
TRY_MACRO_FOR_LIBRARY(
"${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}"
RUNS
"#include <zlib.h>\nint main() {uLong f = zlibCompileFlags(); return (f&(1U<<10))?0:-1; }"
ZLIB_WINAPI)
IF(ZLIB_WINAPI)
ADD_DEFINITIONS(-DZLIB_WINAPI)
ELSE(ZLIB_WINAPI)
# Test if a macro is needed for the library.
TRY_MACRO_FOR_LIBRARY(
"${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}"
COMPILES
"#include <zlib.h>\nint main() {return zlibVersion()?1:0; }"
"ZLIB_DLL;WITHOUT_ZLIB_DLL")
IF(ZLIB_DLL)
ADD_DEFINITIONS(-DZLIB_DLL)
ENDIF(ZLIB_DLL)
ENDIF(ZLIB_WINAPI)
ENDIF(WIN32 AND NOT CYGWIN)
ENDIF(ZLIB_FOUND)
MARK_AS_ADVANCED(CLEAR ZLIB_INCLUDE_DIR)
@ -190,9 +356,20 @@ IF(BZIP2_FOUND)
SET(HAVE_BZLIB_H 1)
INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${BZIP2_LIBRARIES})
# Test if a macro is needed for the library.
TRY_MACRO_FOR_LIBRARY(
"${BZIP2_INCLUDE_DIR}" "${BZIP2_LIBRARIES}"
COMPILES
"#include <bzlib.h>\nint main() {return BZ2_bzlibVersion()?1:0; }"
"USE_BZIP2_DLL;USE_BZIP2_STATIC")
IF(USE_BZIP2_DLL)
ADD_DEFINITIONS(-DUSE_BZIP2_DLL)
ELSEIF(USE_BZIP2_STATIC)
ADD_DEFINITIONS(-DUSE_BZIP2_STATIC)
ENDIF(USE_BZIP2_DLL)
ENDIF(BZIP2_FOUND)
MARK_AS_ADVANCED(CLEAR BZIP2_INCLUDE_DIR)
MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARY)
MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES)
#
# Find LZMA
#
@ -202,12 +379,45 @@ IF(LZMA_FOUND)
SET(HAVE_LZMA_H 1)
INCLUDE_DIRECTORIES(${LZMA_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${LZMA_LIBRARIES})
# Test if a macro is needed for the library.
TRY_MACRO_FOR_LIBRARY(
"${LZMA_INCLUDE_DIR}" "${LZMA_LIBRARIES}"
COMPILES
"#include <lzma.h>\nint main() {return (int)lzma_version_number(); }"
"WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC")
IF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC)
ADD_DEFINITIONS(-DLZMA_API_STATIC)
ENDIF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC)
ELSEIF(LZMADEC_FOUND)
SET(HAVE_LIBLZMADEC 1)
SET(HAVE_LZMADEC_H 1)
INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES})
ENDIF(LZMA_FOUND)
#
# Find LZO2
#
IF (LZO2_INCLUDE_DIR)
# Already in cache, be silent
SET(LZO2_FIND_QUIETLY TRUE)
ENDIF (LZO2_INCLUDE_DIR)
FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h)
FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
IF(LZO2_FOUND)
SET(HAVE_LIBLZO2 1)
SET(HAVE_LZO_LZOCONF_H 1)
SET(HAVE_LZO_LZO1X_H 1)
INCLUDE_DIRECTORIES(${LZO2_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${LZO2_LIBRARY})
#
# TODO: test for static library.
#
ENDIF(LZO2_FOUND)
MARK_AS_ADVANCED(CLEAR LZO2_INCLUDE_DIR)
MARK_AS_ADVANCED(CLEAR LZO2_LIBRARY)
#
# Check headers
@ -234,7 +444,7 @@ LA_CHECK_INCLUDE_FILE("dlfcn.h" HAVE_DLFCN_H)
LA_CHECK_INCLUDE_FILE("errno.h" HAVE_ERRNO_H)
LA_CHECK_INCLUDE_FILE("ext2fs/ext2_fs.h" HAVE_EXT2FS_EXT2_FS_H)
CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
LIBARCHIVE_CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
#include <ext2fs/ext2_fs.h>
int main(void) { return EXT2_IOC_GETFLAGS; }" HAVE_WORKING_EXT2_IOC_GETFLAGS)
@ -244,6 +454,7 @@ LA_CHECK_INCLUDE_FILE("inttypes.h" HAVE_INTTYPES_H)
LA_CHECK_INCLUDE_FILE("io.h" HAVE_IO_H)
LA_CHECK_INCLUDE_FILE("langinfo.h" HAVE_LANGINFO_H)
LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H)
LA_CHECK_INCLUDE_FILE("linux/types.h" HAVE_LINUX_TYPES_H)
LA_CHECK_INCLUDE_FILE("linux/fiemap.h" HAVE_LINUX_FIEMAP_H)
LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H)
LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H)
@ -255,6 +466,7 @@ LA_CHECK_INCLUDE_FILE("process.h" HAVE_PROCESS_H)
LA_CHECK_INCLUDE_FILE("pwd.h" HAVE_PWD_H)
LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H)
LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H)
LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H)
LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H)
LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H)
LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H)
@ -295,7 +507,7 @@ FOREACH (it ${_HEADER})
SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
ENDFOREACH (it)
CHECK_C_SOURCE_COMPILES(
LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#define __EXTENSIONS__ 1
${_INCLUDE_FILES}
int main() { return 0;}"
@ -305,14 +517,17 @@ CHECK_C_SOURCE_COMPILES(
# Find Nettle
#
IF(ENABLE_NETTLE)
CHECK_LIBRARY_EXISTS(nettle "nettle_sha1_digest" "" NETTLE_FOUND)
FIND_PACKAGE(Nettle)
IF(NETTLE_FOUND)
SET(CMAKE_REQUIRED_LIBRARIES "nettle")
FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle)
LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARY})
ELSE(NETTLE_FOUND)
SET(ENABLE_NETTLE OFF)
SET(HAVE_LIBNETTLE 1)
SET(HAVE_NETTLE_MD5_H 1)
SET(HAVE_NETTLE_RIPEMD160_H 1)
SET(HAVE_NETTLE_SHA_H 1)
INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARIES})
ENDIF(NETTLE_FOUND)
MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR)
MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES)
ENDIF(ENABLE_NETTLE)
#
@ -326,12 +541,16 @@ ELSE()
ENDIF()
# FreeBSD libmd
IF(NOT OPENSSL_FOUND)
CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND)
IF(LIBMD_FOUND)
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
SET(CMAKE_REQUIRED_LIBRARIES "md")
FIND_LIBRARY(LIBMD_LIBRARY NAMES md)
LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY})
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
ENDIF(LIBMD_FOUND)
ENDIF(NOT OPENSSL_FOUND)
#
# How to prove that CRYPTO functions, which have several names on various
@ -339,13 +558,8 @@ ENDIF(LIBMD_FOUND)
# required libraries.
#
MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
IF(HAVE_SYS_TYPES_H)
SET(CRYPTO_HEADER_CONFIG "#define HAVE_SYS_TYPES_H 1\n")
ELSE(HAVE_SYS_TYPES_H)
SET(CRYPTO_HEADER_CONFIG "")
ENDIF(HAVE_SYS_TYPES_H)
FOREACH(ALGORITHM ${ALGORITHMS})
IF(NOT ARCHIVE_CRYPTO_${ALGORITHM})
STRING(TOLOWER "${ALGORITHM}" lower_algorithm)
STRING(TOUPPER "${ALGORITHM}" algorithm)
IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND)
@ -358,7 +572,7 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
# Probe the local implementation for whether this
# crypto implementation is available on this platform.
SET(TRY_CRYPTO_REQUIRED_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp")
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp")
SET(TRY_CRYPTO_REQUIRED_LIBS)
IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
SET(TRY_CRYPTO_REQUIRED_INCLUDES
@ -366,6 +580,8 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
SET(TRY_CRYPTO_REQUIRED_LIBS
"-DLINK_LIBRARIES:STRING=${OPENSSL_LIBRARIES}")
ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NETTLE_FOUND)
SET(TRY_CRYPTO_REQUIRED_INCLUDES
"${TRY_CRYPTO_REQUIRED_INCLUDES};${NETTLE_INCLUDE_DIR}")
SET(TRY_CRYPTO_REQUIRED_LIBS
"-DLINK_LIBRARIES:STRING=${NETTLE_LIBRARY}")
ELSEIF("${IMPLEMENTATION}" MATCHES "^LIBMD$" AND LIBMD_FOUND)
@ -373,10 +589,15 @@ MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
"-DLINK_LIBRARIES:STRING=${LIBMD_LIBRARY}")
ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h)
FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h"
CONFDEFS_H)
FILE(READ "${CMAKE_CURRENT_SOURCE_DIR}/libarchive/archive_crypto.c"
ARCHIVE_CRYPTO_C)
SET(SOURCE "
SET(SOURCE "${CONFDEFS_H}
#define ARCHIVE_${algorithm}_COMPILE_TEST
#define ARCHIVE_CRYPTO_${algorithm}_${IMPLEMENTATION}
#define PLATFORM_CONFIG_H \"check_crypto_md.h\"
@ -386,10 +607,10 @@ ${ARCHIVE_CRYPTO_C}
int
main(int argc, char **argv)
{
archive_${lower_crypto}_ctx ctx;
archive_${lower_crypto}_init(&ctx);
archive_${lower_crypto}_update(&ctx, *argv, argc);
archive_${lower_crypto}_final(&ctx, NULL);
archive_${lower_algorithm}_ctx ctx;
archive_${lower_algorithm}_init(&ctx);
archive_${lower_algorithm}_update(&ctx, *argv, argc);
archive_${lower_algorithm}_final(&ctx, NULL);
return 0;
}
")
@ -398,10 +619,16 @@ main(int argc, char **argv)
FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c" "${SOURCE}")
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}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c
CMAKE_FLAGS
CMAKE_FLAGS ${CHECK_CRYPTO_ADD_LINKER_FLAGS}
"${TRY_CRYPTO_REQUIRED_LIBS}"
"${TRY_CRYPTO_REQUIRED_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
@ -409,6 +636,7 @@ main(int argc, char **argv)
# Inform user whether or not we found it; if not, log why we didn't.
IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- found")
SET(ARCHIVE_CRYPTO_${ALGORITHM} 1)
ELSE (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- not found")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
@ -427,6 +655,7 @@ main(int argc, char **argv)
LIST(REMOVE_DUPLICATES ADDITIONAL_LIBS)
ENDIF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND)
ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION})
ENDIF(NOT ARCHIVE_CRYPTO_${ALGORITHM})
ENDFOREACH(ALGORITHM ${ALGORITHMS})
ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
@ -442,6 +671,7 @@ ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
IF(WIN32 AND NOT CYGWIN)
FOREACH(CRYPTO ${CRYPTO_LIST})
IF(NOT ARCHIVE_CRYPTO_${CRYPTO})
IF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
STRING(TOUPPER "${CRYPTO}" crypto)
SET(ALGID "")
@ -461,9 +691,14 @@ MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
SET(ALGID "CALG_SHA_512")
ENDIF ("${CRYPTO}" MATCHES "^SHA512$")
SET(SOURCE "#define ${crypto}_COMPILE_TEST
#define _WIN32_WINNT ${_WIN32_WINNT}
#define WINVER ${WINVER}
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h)
FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h"
CONFDEFS_H)
SET(SOURCE "${CONFDEFS_H}
#define ${crypto}_COMPILE_TEST
#include <windows.h>
#include <wincrypt.h>
@ -478,15 +713,22 @@ main(int argc, char **argv)
FILE(WRITE "${SOURCE_FILE}" "${SOURCE}")
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
${CMAKE_BINARY_DIR}
${SOURCE_FILE}
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_CURRENT_SOURCE_DIR}/libarchive"
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive" ${CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS}
OUTPUT_VARIABLE OUTPUT)
IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
MESSAGE(STATUS
"Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- found")
SET(ARCHIVE_CRYPTO_${CRYPTO} 1)
ELSE (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
MESSAGE(STATUS
"Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- not found")
@ -498,6 +740,7 @@ main(int argc, char **argv)
ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO})
ENDFOREACH(CRYPTO)
ENDIF(WIN32 AND NOT CYGWIN)
ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
@ -511,7 +754,21 @@ ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
#
MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
IF(NOT HAVE_ICONV)
CHECK_C_SOURCE_COMPILES(
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
#
# During checking iconv proto type, we should use -Werror to avoid the
# success of iconv detection with a warnig which success is a miss
# detection. So this needs for all build mode(even it's a release mode).
#
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")
ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
IF (MSVC)
# NOTE: /WX option is the same as gcc's -Werror option.
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX")
ENDIF (MSVC)
#
LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#include <stdlib.h>
#include <iconv.h>
int main() {
@ -526,10 +783,12 @@ MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
SET(HAVE_ICONV true)
SET(ICONV_CONST ${TRY_ICONV_CONST})
ENDIF(HAVE_ICONV_${LIB}_${TRY_ICONV_CONST})
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
ENDIF(NOT HAVE_ICONV)
ENDMACRO(CHECK_ICONV TRY_ICONV_CONST)
IF(ENABLE_ICONV)
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
IF(ICONV_INCLUDE_DIR)
#SET(INCLUDES ${INCLUDES} "iconv.h")
@ -540,9 +799,30 @@ IF(ENABLE_ICONV)
CHECK_ICONV("libc" "")
# If iconv isn't in libc and we have a libiconv, try that.
FIND_LIBRARY(LIBICONV_PATH iconv)
FIND_LIBRARY(LIBICONV_PATH NAMES iconv libiconv)
IF(NOT HAVE_ICONV AND LIBICONV_PATH)
LIST(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH})
# Test if a macro is needed for the library.
TRY_MACRO_FOR_LIBRARY(
"${ICONV_INCLUDE_DIR}" "${LIBICONV_PATH}"
COMPILES
"#include <iconv.h>\nint main() {return iconv_close((iconv_t)0);}"
"WITHOUT_LIBICONV_STATIC;LIBICONV_STATIC")
IF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC)
ADD_DEFINITIONS(-DLIBICONV_STATIC)
ENDIF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC)
#
# Set up CMAKE_REQUIRED_* for CHECK_ICONV
#
SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
SET(CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH})
IF(LIBICONV_STATIC)
# LIBICONV_STATIC is necessary for the success of CHECK_ICONV
# on Windows.
SET(CMAKE_REQUIRED_DEFINITIONS "-DLIBICONV_STATIC")
ELSE(LIBICONV_STATIC)
SET(CMAKE_REQUIRED_DEFINITIONS)
ENDIF(LIBICONV_STATIC)
CHECK_ICONV("libiconv" "const")
CHECK_ICONV("libiconv" "")
IF (HAVE_ICONV)
@ -554,19 +834,36 @@ IF(ENABLE_ICONV)
# Find locale_charset() for libiconv.
#
IF(LIBICONV_PATH)
SET(CMAKE_REQUIRED_DEFINITIONS)
SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
SET(CMAKE_REQUIRED_LIBRARIES)
CHECK_INCLUDE_FILES("localcharset.h" HAVE_LOCALCHARSET_H)
CHECK_FUNCTION_EXISTS_GLIBC(locale_charset HAVE_LOCALE_CHARSET)
IF(NOT HAVE_LOCALE_CHARSET)
FIND_LIBRARY(LIBCHARSET_PATH charset)
FIND_LIBRARY(LIBCHARSET_PATH NAMES charset libcharset)
IF(LIBCHARSET_PATH)
SET(CMAKE_REQUIRED_LIBRARIES ${LIBCHARSET_PATH})
IF(WIN32 AND NOT CYGWIN)
# Test if a macro is needed for the library.
TRY_MACRO_FOR_LIBRARY(
"${ICONV_INCLUDE_DIR}" "${LIBCHARSET_PATH}"
COMPILES
"#include <localcharset.h>\nint main() {return locale_charset()?1:0;}"
"WITHOUT_LIBCHARSET_STATIC;LIBCHARSET_STATIC")
IF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC)
ADD_DEFINITIONS(-DLIBCHARSET_STATIC)
ENDIF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC)
IF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC)
SET(HAVE_LOCALE_CHARSET ON CACHE INTERNAL
"Have function locale_charset")
ENDIF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC)
ELSE(WIN32 AND NOT CYGWIN)
CHECK_FUNCTION_EXISTS_GLIBC(locale_charset HAVE_LOCALE_CHARSET)
ENDIF(WIN32 AND NOT CYGWIN)
IF(HAVE_LOCALE_CHARSET)
LIST(APPEND ADDITIONAL_LIBS ${LIBCHARSET_PATH})
ENDIF(HAVE_LOCALE_CHARSET)
ENDIF(LIBCHARSET_PATH)
ENDIF(NOT HAVE_LOCALE_CHARSET)
ENDIF(LIBICONV_PATH)
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
ELSE(ENABLE_ICONV)
# Make sure ICONV variables are not in CACHE after ENABLE_ICONV disabled
# (once enabled).
@ -578,6 +875,10 @@ ELSE(ENABLE_ICONV)
UNSET(HAVE_ICONV_libiconv_const CACHE)
UNSET(ICONV_INCLUDE_DIR CACHE)
UNSET(LIBICONV_PATH CACHE)
UNSET(LIBICONV_DLL CACHE)
UNSET(LIBICONV_STATIC CACHE)
UNSET(LIBCHARSET_DLL CACHE)
UNSET(LIBCHARSET_STATIC CACHE)
ENDIF(ENABLE_ICONV)
#
@ -585,6 +886,7 @@ ENDIF(ENABLE_ICONV)
#
FIND_PACKAGE(LibXml2)
IF(LIBXML2_FOUND)
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${LIBXML2_LIBRARIES})
SET(HAVE_LIBXML2 1)
@ -592,30 +894,150 @@ IF(LIBXML2_FOUND)
SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
CHECK_INCLUDE_FILES("libxml/xmlreader.h" HAVE_LIBXML_XMLREADER_H)
CHECK_INCLUDE_FILES("libxml/xmlwriter.h" HAVE_LIBXML_XMLWRITER_H)
SET(CMAKE_REQUIRED_INCLUDES "")
# Test if a macro is needed for the library.
TRY_MACRO_FOR_LIBRARY(
"${ICONV_INCLUDE_DIR};${LIBXML2_INCLUDE_DIR}"
"ws2_32.lib;${ZLIB_LIBRARIES};${LIBICONV_PATH};${LIBXML2_LIBRARIES}"
COMPILES
"#include <stddef.h>\n#include <libxml/xmlreader.h>\nint main() {return xmlTextReaderRead((xmlTextReaderPtr)(void *)0);}"
"WITHOUT_LIBXML_STATIC;LIBXML_STATIC")
IF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC)
ADD_DEFINITIONS(-DLIBXML_STATIC)
ENDIF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC)
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
ELSE(LIBXML2_FOUND)
#
# Find Expat
#
FIND_PACKAGE(EXPAT)
IF(EXPAT_FOUND)
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
INCLUDE_DIRECTORIES(${EXPAT_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${EXPAT_LIBRARIES})
SET(HAVE_LIBEXPAT 1)
LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H)
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
ENDIF(EXPAT_FOUND)
ENDIF(LIBXML2_FOUND)
MARK_AS_ADVANCED(CLEAR LIBXML2_INCLUDE_DIR)
MARK_AS_ADVANCED(CLEAR LIBXML2_LIBRARIES)
#
# POSIX Regular Expression support
#
IF(POSIX_REGEX_LIB MATCHES "^(AUTO|LIBC|LIBREGEX)$")
#
# If PCREPOSIX is not found or not requested, try using regex
# from libc or libregex
#
FIND_PATH(REGEX_INCLUDE_DIR regex.h)
IF(REGEX_INCLUDE_DIR)
CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBC)
#
# If libc does not provide regex, find libregex.
#
IF(NOT HAVE_REGCOMP_LIBC)
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
FIND_LIBRARY(REGEX_LIBRARY regex)
IF(REGEX_LIBRARY)
SET(CMAKE_REQUIRED_LIBRARIES ${REGEX_LIBRARY})
CHECK_FUNCTION_EXISTS_GLIBC(regcomp HAVE_REGCOMP_LIBREGEX)
IF(HAVE_REGCOMP_LIBREGEX)
LIST(APPEND ADDITIONAL_LIBS ${REGEX_LIBRARY})
#
# If regex.h is not found, retry looking for regex.h at
# REGEX_INCLUDE_DIR
#
IF(NOT HAVE_REGEX_H)
UNSET(HAVE_REGEX_H CACHE)
INCLUDE_DIRECTORIES(${REGEX_INCLUDE_DIR})
SET(CMAKE_REQUIRED_INCLUDES ${REGEX_INCLUDE_DIR})
LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H)
ENDIF(NOT HAVE_REGEX_H)
# Test if a macro is needed for the library.
TRY_MACRO_FOR_LIBRARY(
"${REGEX_INCLUDE_DIR}" "${REGEX_LIBRARY}"
COMPILES
"#include <stddef.h>\n#include <regex.h>\nint main() {regex_t r;return regcomp(&r, \"\", 0);}"
"USE_REGEX_DLL;USE_REGEX_STATIC")
IF(USE_REGEX_DLL)
ADD_DEFINITIONS(-DUSE_REGEX_DLL)
ELSEIF(USE_REGEX_STATIC)
ADD_DEFINITIONS(-DUSE_REGEX_STATIC)
ENDIF(USE_REGEX_DLL)
ENDIF(HAVE_REGCOMP_LIBREGEX)
ENDIF(REGEX_LIBRARY)
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
ENDIF(NOT HAVE_REGCOMP_LIBC)
ENDIF(REGEX_INCLUDE_DIR)
IF(HAVE_REGCOMP_LIBC OR HAVE_REGCOMP_LIBREGEX)
SET(FOUND_POSIX_REGEX_LIB 1)
ENDIF(HAVE_REGCOMP_LIBC OR HAVE_REGCOMP_LIBREGEX)
ENDIF(POSIX_REGEX_LIB MATCHES "^(AUTO|LIBC|LIBREGEX)$")
IF(NOT FOUND_POSIX_REGEX_LIB AND POSIX_REGEX_LIB MATCHES "^(AUTO|LIBPCREPOSIX)$")
#
# If requested, try finding library for PCREPOSIX
#
FIND_PACKAGE(LibGCC)
FIND_PACKAGE(PCREPOSIX)
IF(PCREPOSIX_FOUND)
INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${PCREPOSIX_LIBRARIES})
# Test if a macro is needed for the library.
TRY_MACRO_FOR_LIBRARY(
"${PCRE_INCLUDE_DIR}" "${PCREPOSIX_LIBRARIES}"
COMPILES
"#include <pcreposix.h>\nint main() {regex_t r;return regcomp(&r, \"\", 0);}"
"WITHOUT_PCRE_STATIC;PCRE_STATIC")
IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
ADD_DEFINITIONS(-DPCRE_STATIC)
ELSEIF(NOT WITHOUT_PCRE_STATIC AND NOT PCRE_STATIC AND PCRE_FOUND)
# Determine if pcre static libraries are to be used.
LIST(APPEND ADDITIONAL_LIBS ${PCRE_LIBRARIES})
SET(TMP_LIBRARIES ${PCREPOSIX_LIBRARIES} ${PCRE_LIBRARIES})
MESSAGE(STATUS "trying again with -lpcre included")
TRY_MACRO_FOR_LIBRARY(
"${PCRE_INCLUDE_DIR}" "${TMP_LIBRARIES}"
COMPILES
"#include <pcreposix.h>\nint main() {regex_t r;return regcomp(&r, \"\", 0);}"
"WITHOUT_PCRE_STATIC;PCRE_STATIC")
IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
ADD_DEFINITIONS(-DPCRE_STATIC)
ELSEIF(NOT WITHOUT_PCRE_STATIC AND NOT PCRE_STATIC AND MSVC AND LIBGCC_FOUND)
# When doing a Visual Studio build using pcre static libraries
# built using the mingw toolchain, -lgcc is needed to resolve
# ___chkstk_ms.
MESSAGE(STATUS "Visual Studio build detected, trying again with -lgcc included")
LIST(APPEND ADDITIONAL_LIBS ${LIBGCC_LIBRARIES})
SET(TMP_LIBRARIES ${PCREPOSIX_LIBRARIES} ${PCRE_LIBRARIES} ${LIBGCC_LIBRARIES})
TRY_MACRO_FOR_LIBRARY(
"${PCRE_INCLUDE_DIR}" "${TMP_LIBRARIES}"
COMPILES
"#include <pcreposix.h>\nint main() {regex_t r;return regcomp(&r, \"\", 0);}"
"WITHOUT_PCRE_STATIC;PCRE_STATIC")
IF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
ADD_DEFINITIONS(-DPCRE_STATIC)
ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
ENDIF(NOT WITHOUT_PCRE_STATIC AND PCRE_STATIC)
ENDIF(PCREPOSIX_FOUND)
MARK_AS_ADVANCED(CLEAR PCRE_INCLUDE_DIR)
MARK_AS_ADVANCED(CLEAR PCREPOSIX_LIBRARIES)
MARK_AS_ADVANCED(CLEAR PCRE_LIBRARIES)
MARK_AS_ADVANCED(CLEAR LIBGCC_LIBRARIES)
ENDIF(NOT FOUND_POSIX_REGEX_LIB AND POSIX_REGEX_LIB MATCHES "^(AUTO|LIBPCREPOSIX)$")
#
# Check functions
#
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
#
# During checking functions, we should use -fno-builtin to avoid the
# failure of function detection which failure is an error "conflicting
# types for built-in function" caused by using -Werror option.
#
SET(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-builtin")
ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
CHECK_SYMBOL_EXISTS(_CrtSetReportMode "crtdbg.h" HAVE__CrtSetReportMode)
@ -623,6 +1045,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(chflags HAVE_CHFLAGS)
CHECK_FUNCTION_EXISTS_GLIBC(chown HAVE_CHOWN)
CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT)
CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R)
CHECK_FUNCTION_EXISTS_GLIBC(dirfd HAVE_DIRFD)
CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR)
CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS)
CHECK_FUNCTION_EXISTS_GLIBC(fchmod HAVE_FCHMOD)
@ -654,7 +1077,6 @@ CHECK_FUNCTION_EXISTS_GLIBC(localtime_r HAVE_LOCALTIME_R)
CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT)
CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES)
CHECK_FUNCTION_EXISTS_GLIBC(mbrtowc HAVE_MBRTOWC)
CHECK_FUNCTION_EXISTS_GLIBC(mbsnrtowcs HAVE_MBSNRTOWCS)
CHECK_FUNCTION_EXISTS_GLIBC(memmove HAVE_MEMMOVE)
CHECK_FUNCTION_EXISTS_GLIBC(mkdir HAVE_MKDIR)
CHECK_FUNCTION_EXISTS_GLIBC(mkfifo HAVE_MKFIFO)
@ -664,6 +1086,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO)
CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT)
CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE)
CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL)
CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP)
CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK)
CHECK_FUNCTION_EXISTS_GLIBC(select HAVE_SELECT)
CHECK_FUNCTION_EXISTS_GLIBC(setenv HAVE_SETENV)
@ -688,7 +1111,6 @@ CHECK_FUNCTION_EXISTS_GLIBC(wcrtomb HAVE_WCRTOMB)
CHECK_FUNCTION_EXISTS_GLIBC(wcscmp HAVE_WCSCMP)
CHECK_FUNCTION_EXISTS_GLIBC(wcscpy HAVE_WCSCPY)
CHECK_FUNCTION_EXISTS_GLIBC(wcslen HAVE_WCSLEN)
CHECK_FUNCTION_EXISTS_GLIBC(wcsnrtombs HAVE_WCSNRTOMBS)
CHECK_FUNCTION_EXISTS_GLIBC(wctomb HAVE_WCTOMB)
CHECK_FUNCTION_EXISTS_GLIBC(_ctime64_s HAVE__CTIME64_S)
CHECK_FUNCTION_EXISTS_GLIBC(_fseeki64 HAVE__FSEEKI64)
@ -705,21 +1127,18 @@ CHECK_FUNCTION_EXISTS(vprintf HAVE_VPRINTF)
CHECK_FUNCTION_EXISTS(wmemcmp HAVE_WMEMCMP)
CHECK_FUNCTION_EXISTS(wmemcpy HAVE_WMEMCPY)
# Restore CMAKE_REQUIRED_FLAGS
IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
SET(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS})
ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$")
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
# Make sure we have the POSIX version of readdir_r, not the
# older 2-argument version.
CHECK_C_SOURCE_COMPILES(
LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}"
HAVE_READDIR_R)
# Only detect readlinkat() if we also have AT_FDCWD in unistd.h.
# NOTE: linux requires fcntl.h for AT_FDCWD.
CHECK_C_SOURCE_COMPILES(
LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#include <fcntl.h>\n#include <unistd.h>\nint main() {char buf[10]; return readlinkat(AT_FDCWD, \"\", buf, 0);}"
HAVE_READLINKAT)
@ -728,10 +1147,10 @@ CHECK_C_SOURCE_COMPILES(
# of interest and verify that the result can be linked.
# CHECK_FUNCTION_EXISTS doesn't accept a header argument,
# CHECK_SYMBOL_EXISTS doesn't test linkage.
CHECK_C_SOURCE_COMPILES(
LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#include <sys/mkdev.h>\nint main() { return major(256); }"
MAJOR_IN_MKDEV)
CHECK_C_SOURCE_COMPILES(
LIBARCHIVE_CHECK_C_SOURCE_COMPILES(
"#include <sys/sysmacros.h>\nint main() { return major(256); }"
MAJOR_IN_SYSMACROS)
@ -795,6 +1214,12 @@ CHECK_STRUCT_MEMBER("struct stat" st_blksize
# Check for st_flags in struct stat (BSD fflags)
CHECK_STRUCT_MEMBER("struct stat" st_flags
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_FLAGS)
IF(HAVE_SYS_STATVFS_H)
CHECK_STRUCT_MEMBER("struct statvfs" f_iosize
"sys/types.h;sys/statvfs.h" HAVE_STRUCT_STATVFS_F_IOSIZE)
ENDIF()
#
#
CHECK_STRUCT_MEMBER("struct tm" tm_sec
@ -1021,6 +1446,8 @@ IF(ENABLE_ACL)
CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP)
CHECK_FUNCTION_EXISTS(acl_get_link HAVE_ACL_GET_LINK)
CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP)
CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP)
CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP)
# MacOS has an acl.h that isn't POSIX. It can be detected by
# checking for ACL_USER
@ -1089,11 +1516,6 @@ IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
ENDIF(MSVC)
# We need CoreServices on Mac OS.
IF(APPLE)
LIST(APPEND ADDITIONAL_LIBS "-framework CoreServices")
ENDIF(APPLE)
IF(ENABLE_TEST)
ADD_CUSTOM_TARGET(run_all_tests)
ENDIF(ENABLE_TEST)

View File

@ -19,7 +19,7 @@ GET_FILENAME_COMPONENT(_selfdir_CheckFileOffsetBits
MACRO (CHECK_FILE_OFFSET_BITS)
IF(NOT DEFINED _FILE_OFFSET_BITS)
MESSAGE(STATUS "Cheking _FILE_OFFSET_BITS for large files")
MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files")
TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64
${CMAKE_CURRENT_BINARY_DIR}
${_selfdir_CheckFileOffsetBits}/CheckFileOffsetBits.c
@ -33,10 +33,10 @@ MACRO (CHECK_FILE_OFFSET_BITS)
IF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
SET(_FILE_OFFSET_BITS 64 CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
MESSAGE(STATUS "Cheking _FILE_OFFSET_BITS for large files - needed")
MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - needed")
ELSE(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
SET(_FILE_OFFSET_BITS "" CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
MESSAGE(STATUS "Cheking _FILE_OFFSET_BITS for large files - not needed")
MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - not needed")
ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
ENDIF(NOT DEFINED _FILE_OFFSET_BITS)

View File

@ -0,0 +1,22 @@
# - Find libgcc
# Find the libgcc library.
#
# LIBGCC_LIBRARIES - List of libraries when using libgcc
# LIBGCC_FOUND - True if libgcc found.
IF (LIBGCC_LIBRARY)
# Already in cache, be silent
SET(LIBGCC_FIND_QUIETLY TRUE)
ENDIF (LIBGCC_LIBRARY)
FIND_LIBRARY(LIBGCC_LIBRARY NAMES gcc libgcc)
# handle the QUIETLY and REQUIRED arguments and set LIBGCC_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBGCC DEFAULT_MSG LIBGCC_LIBRARY)
IF(LIBGCC_FOUND)
SET(LIBGCC_LIBRARIES ${LIBGCC_LIBRARY})
SET(HAVE_LIBGCC 1)
ENDIF(LIBGCC_FOUND)

View File

@ -0,0 +1,23 @@
# - Find Nettle
# Find the Nettle include directory and library
#
# NETTLE_INCLUDE_DIR - where to find <nettle/sha.h>, etc.
# NETTLE_LIBRARIES - List of libraries when using libnettle.
# NETTLE_FOUND - True if libnettle found.
IF (NETTLE_INCLUDE_DIR)
# Already in cache, be silent
SET(NETTLE_FIND_QUIETLY TRUE)
ENDIF (NETTLE_INCLUDE_DIR)
FIND_PATH(NETTLE_INCLUDE_DIR nettle/md5.h nettle/ripemd160.h nettle/sha.h)
FIND_LIBRARY(NETTLE_LIBRARY NAMES nettle libnettle)
# handle the QUIETLY and REQUIRED arguments and set NETTLE_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(NETTLE DEFAULT_MSG NETTLE_LIBRARY NETTLE_INCLUDE_DIR)
IF(NETTLE_FOUND)
SET(NETTLE_LIBRARIES ${NETTLE_LIBRARY})
ENDIF(NETTLE_FOUND)

View File

@ -0,0 +1,34 @@
# - Find pcreposix
# Find the native PCRE and PCREPOSIX include and libraries
#
# PCRE_INCLUDE_DIR - where to find pcreposix.h, etc.
# PCREPOSIX_LIBRARIES - List of libraries when using libpcreposix.
# PCRE_LIBRARIES - List of libraries when using libpcre.
# PCREPOSIX_FOUND - True if libpcreposix found.
# PCRE_FOUND - True if libpcre found.
IF (PCRE_INCLUDE_DIR)
# Already in cache, be silent
SET(PCRE_FIND_QUIETLY TRUE)
ENDIF (PCRE_INCLUDE_DIR)
FIND_PATH(PCRE_INCLUDE_DIR pcreposix.h)
FIND_LIBRARY(PCREPOSIX_LIBRARY NAMES pcreposix libpcreposix)
FIND_LIBRARY(PCRE_LIBRARY NAMES pcre libpcre)
# handle the QUIETLY and REQUIRED arguments and set PCREPOSIX_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCREPOSIX DEFAULT_MSG PCREPOSIX_LIBRARY PCRE_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG PCRE_LIBRARY)
IF(PCREPOSIX_FOUND)
SET(PCREPOSIX_LIBRARIES ${PCREPOSIX_LIBRARY})
SET(HAVE_LIBPCREPOSIX 1)
SET(HAVE_PCREPOSIX_H 1)
ENDIF(PCREPOSIX_FOUND)
IF(PCRE_FOUND)
SET(PCRE_LIBRARIES ${PCRE_LIBRARY})
SET(HAVE_LIBPCRE 1)
ENDIF(PCRE_FOUND)

View File

@ -0,0 +1,106 @@
# - 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

@ -0,0 +1,102 @@
# - 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

@ -390,6 +390,9 @@ typedef uint64_t uintmax_t;
*/
#cmakedefine HAVE_DIRENT_H 1
/* Define to 1 if you have the `dirfd' function. */
#cmakedefine HAVE_DIRFD 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H 1
@ -576,12 +579,27 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `expat' library (-lexpat). */
#cmakedefine HAVE_LIBEXPAT 1
/* Define to 1 if you have the `gcc' library (-lgcc). */
#cmakedefine HAVE_LIBGCC 1
/* Define to 1 if you have the `lzma' library (-llzma). */
#cmakedefine HAVE_LIBLZMA 1
/* Define to 1 if you have the `lzmadec' library (-llzmadec). */
#cmakedefine HAVE_LIBLZMADEC 1
/* Define to 1 if you have the `lzo2' library (-llzo2). */
#cmakedefine HAVE_LIBLZO2 1
/* Define to 1 if you have the `nettle' library (-lnettle). */
#cmakedefine HAVE_LIBNETTLE 1
/* Define to 1 if you have the `pcre' library (-lpcre). */
#cmakedefine HAVE_LIBPCRE 1
/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */
#cmakedefine HAVE_LIBPCREPOSIX 1
/* Define to 1 if you have the `xml2' library (-lxml2). */
#cmakedefine HAVE_LIBXML2 1
@ -609,6 +627,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <linux/magic.h> header file. */
#cmakedefine HAVE_LINUX_MAGIC_H 1
/* Define to 1 if you have the <linux/types.h> header file. */
#cmakedefine HAVE_LINUX_TYPES_H 1
/* Define to 1 if you have the `listea' function. */
#cmakedefine HAVE_LISTEA 1
@ -658,12 +679,15 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <lzma.h> header file. */
#cmakedefine HAVE_LZMA_H 1
/* Define to 1 if you have the <lzo/lzo1x.h> header file. */
#cmakedefine HAVE_LZO_LZO1X_H 1
/* Define to 1 if you have the <lzo/lzoconf.h> header file. */
#cmakedefine HAVE_LZO_LZOCONF_H 1
/* Define to 1 if you have the `mbrtowc' function. */
#cmakedefine HAVE_MBRTOWC 1
/* Define to 1 if you have the `mbsnrtowcs' function. */
#cmakedefine HAVE_MBSNRTOWCS 1
/* Define to 1 if you have the `memmove' function. */
#cmakedefine HAVE_MEMMOVE 1
@ -685,6 +709,15 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#cmakedefine HAVE_NDIR_H 1
/* Define to 1 if you have the <nettle/md5.h> header file. */
#cmakedefine HAVE_NETTLE_MD5_H 1
/* Define to 1 if you have the <nettle/ripemd160.h> header file. */
#cmakedefine HAVE_NETTLE_RIPEMD160_H 1
/* Define to 1 if you have the <nettle/sha.h> header file. */
#cmakedefine HAVE_NETTLE_SHA_H 1
/* Define to 1 if you have the `nl_langinfo' function. */
#cmakedefine HAVE_NL_LANGINFO 1
@ -694,6 +727,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <paths.h> header file. */
#cmakedefine HAVE_PATHS_H 1
/* Define to 1 if you have the <pcreposix.h> header file. */
#cmakedefine HAVE_PCREPOSIX_H 1
/* Define to 1 if you have the `pipe' function. */
#cmakedefine HAVE_PIPE 1
@ -703,6 +739,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <poll.h> header file. */
#cmakedefine HAVE_POLL_H 1
/* Define to 1 if you have the `posix_spawnp' function. */
#cmakedefine HAVE_POSIX_SPAWNP 1
/* Define to 1 if you have the <process.h> header file. */
#cmakedefine HAVE_PROCESS_H 1
@ -736,6 +775,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <signal.h> header file. */
#cmakedefine HAVE_SIGNAL_H 1
/* Define to 1 if you have the <spawn.h> header file. */
#cmakedefine HAVE_SPAWN_H 1
/* Define to 1 if you have the `statfs' function. */
#cmakedefine HAVE_STATFS 1
@ -782,6 +824,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if `f_namemax' is a member of `struct statfs'. */
#cmakedefine HAVE_STRUCT_STATFS_F_NAMEMAX 1
/* Define to 1 if `f_iosize' is a member of `struct statvfs'. */
#cmakedefine HAVE_STRUCT_STATVFS_F_IOSIZE 1
/* Define to 1 if `st_birthtime' is a member of `struct stat'. */
#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIME 1
@ -943,9 +988,6 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `wcslen' function. */
#cmakedefine HAVE_WCSLEN 1
/* Define to 1 if you have the `wcsnrtombs' function. */
#cmakedefine HAVE_WCSNRTOMBS 1
/* Define to 1 if you have the `wctomb' function. */
#cmakedefine HAVE_WCTOMB 1

47
build/utils/gen_archive_string_composition_h.sh Normal file → Executable file
View File

@ -1,10 +1,13 @@
#!/bin/sh
#
# This needs http://unicode.org/Public/UNIDATA/UnicodeData.txt
# This needs http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt
#
inputfile="$1" # Expect UnicodeData.txt
outfile=archive_string_composition.h
pickout=/tmp/mk_unicode_composition_tbl$$.awk
pickout2=/tmp/mk_unicode_composition_tbl2$$.awk
#nfdtmp=/tmp/mk_unicode_decomposition_tmp$$.txt
nfdtmp="nfdtmpx"
#################################################################################
#
# Append the file header of "archive_string_composition.h"
@ -14,7 +17,7 @@ append_copyright()
{
cat > ${outfile} <<CR_END
/*-
* Copyright (c) 2011 libarchive Project
* Copyright (c) 2011-2012 libarchive Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -44,7 +47,7 @@ cat > ${outfile} <<CR_END
/*
* ATTENTION!
* This file is generated by build/utils/gen_archive_string_composition_h.sh
* from http://unicode.org/Public/UNIDATA/UnicodeData.txt
* from http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt
*
* See also http://unicode.org/report/tr15/
*/
@ -76,6 +79,7 @@ BEGIN {
min = "";
max = "";
cmd="sort | awk -F ' ' '{printf \"\\\\t{ 0x%s , 0x%s , 0x%s },\\\\n\",\$1,\$2,\$3}'"
nfdtbl="${nfdtmp}"
print "static const struct unicode_composition_table u_composition_table[] = {"
}
END {
@ -178,7 +182,6 @@ END {
}
print "};"
print ""
print "#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */"
}
#
#
@ -241,7 +244,7 @@ function hextoi(hex)
#}
#
# Exclusion code points specified by
# http://unicode.org/Public/UNIDATA/CompositionExclusions.txt
# http://unicode.org/Public/6.0.0/ucd/CompositionExclusions.txt
##
# 1. Script Specifices
##
@ -404,6 +407,35 @@ function hextoi(hex)
print "0"cp[1], "0"cp[2], "0"\$1 | cmd
else
print cp[1], cp[2], \$1 | cmd
# NFC ==> NFD table.
if (length(\$1) == 4)
print "0"\$1, "0"cp[1], "0"cp[2] >>nfdtbl
else
print \$1, cp[1], cp[2] >>nfdtbl
}
AWK_END
#################################################################################
# awk script
#
#################################################################################
cat > ${pickout2} <<AWK_END
#
BEGIN {
FS = " "
print "struct unicode_decomposition_table {"
print "\tuint32_t nfc;"
print "\tuint32_t cp1;"
print "\tuint32_t cp2;"
print "};"
print ""
print "static const struct unicode_decomposition_table u_decomposition_table[] = {"
}
END {
print "};"
print ""
}
{
printf "\t{ 0x%s , 0x%s , 0x%s },\n", \$1, \$2, \$3;
}
AWK_END
#################################################################################
@ -413,6 +445,11 @@ AWK_END
#################################################################################
append_copyright
awk -f ${pickout} ${inputfile} >> ${outfile}
awk -f ${pickout2} ${nfdtmp} >> ${outfile}
echo "#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */" >> ${outfile}
echo "" >> ${outfile}
#
# Remove awk the script.
rm ${pickout}
rm ${pickout2}
rm ${nfdtmp}

View File

@ -1 +1 @@
3000002
3001002

View File

@ -15,6 +15,9 @@ SET(include_HEADERS
SET(libarchive_SOURCES
archive_acl.c
archive_check_magic.c
archive_cmdline.c
archive_cmdline_private.h
archive_crc32.h
archive_crypto.c
archive_crypto_private.h
archive_endian.h
@ -28,8 +31,12 @@ SET(libarchive_SOURCES
archive_entry_stat.c
archive_entry_strmode.c
archive_entry_xattr.c
archive_getdate.c
archive_match.c
archive_options.c
archive_options_private.h
archive_pathmatch.c
archive_pathmatch.h
archive_platform.h
archive_ppmd_private.h
archive_ppmd7.c
@ -38,6 +45,7 @@ SET(libarchive_SOURCES
archive_rb.c
archive_rb.h
archive_read.c
archive_read_append_filter.c
archive_read_data_into_fd.c
archive_read_disk_entry_from_file.c
archive_read_disk_posix.c
@ -49,11 +57,15 @@ SET(libarchive_SOURCES
archive_read_open_filename.c
archive_read_open_memory.c
archive_read_private.h
archive_read_set_format.c
archive_read_set_options.c
archive_read_support_filter_all.c
archive_read_support_filter_bzip2.c
archive_read_support_filter_compress.c
archive_read_support_filter_gzip.c
archive_read_support_filter_grzip.c
archive_read_support_filter_lrzip.c
archive_read_support_filter_lzop.c
archive_read_support_filter_none.c
archive_read_support_filter_program.c
archive_read_support_filter_rpm.c
@ -81,6 +93,7 @@ SET(libarchive_SOURCES
archive_util.c
archive_virtual.c
archive_write.c
archive_write_disk_acl.c
archive_write_disk_posix.c
archive_write_disk_private.h
archive_write_disk_set_standard_lookup.c
@ -89,11 +102,18 @@ SET(libarchive_SOURCES
archive_write_open_file.c
archive_write_open_filename.c
archive_write_open_memory.c
archive_write_add_filter.c
archive_write_add_filter_b64encode.c
archive_write_add_filter_by_name.c
archive_write_add_filter_bzip2.c
archive_write_add_filter_compress.c
archive_write_add_filter_grzip.c
archive_write_add_filter_gzip.c
archive_write_add_filter_lrzip.c
archive_write_add_filter_lzop.c
archive_write_add_filter_none.c
archive_write_add_filter_program.c
archive_write_add_filter_uuencode.c
archive_write_add_filter_xz.c
archive_write_set_format.c
archive_write_set_format_7zip.c
@ -107,10 +127,11 @@ SET(libarchive_SOURCES
archive_write_set_format_pax.c
archive_write_set_format_shar.c
archive_write_set_format_ustar.c
archive_write_set_format_v7tar.c
archive_write_set_format_xar.c
archive_write_set_format_zip.c
archive_write_set_options.c
filter_fork.c
filter_fork_posix.c
filter_fork.h
)

View File

@ -56,23 +56,14 @@
# else
# define __LA_SSIZE_T long
# endif
# if defined(__BORLANDC__)
# define __LA_UID_T uid_t
# define __LA_GID_T gid_t
#else
# define __LA_UID_T short
# define __LA_GID_T short
# endif
#else
# include <unistd.h> /* ssize_t, uid_t, and gid_t */
# include <unistd.h> /* ssize_t */
# if defined(_SCO_DS)
# define __LA_INT64_T long long
# else
# define __LA_INT64_T int64_t
# endif
# define __LA_SSIZE_T ssize_t
# define __LA_UID_T uid_t
# define __LA_GID_T gid_t
#endif
/*
@ -106,6 +97,12 @@
#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */
#endif
#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
# define __LA_DEPRECATED __attribute__((deprecated))
#else
# define __LA_DEPRECATED
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -127,13 +124,13 @@ extern "C" {
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
#define ARCHIVE_VERSION_NUMBER 3000002
#define ARCHIVE_VERSION_NUMBER 3001002
__LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
#define ARCHIVE_VERSION_STRING "libarchive 3.0.2"
#define ARCHIVE_VERSION_STRING "libarchive 3.1.2"
__LA_DECL const char * archive_version_string(void);
/* Declare our basic types. */
@ -203,6 +200,13 @@ typedef int archive_open_callback(struct archive *, void *_client_data);
typedef int archive_close_callback(struct archive *, void *_client_data);
/* Switches from one client data object to the next/prev client data object.
* This is useful for reading from different data blocks such as a set of files
* that make up one large file.
*/
typedef int archive_switch_callback(struct archive *, void *_client_data1,
void *_client_data2);
/*
* Codes to identify various stream filters.
*/
@ -216,6 +220,9 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
#define ARCHIVE_FILTER_UU 7
#define ARCHIVE_FILTER_RPM 8
#define ARCHIVE_FILTER_LZIP 9
#define ARCHIVE_FILTER_LRZIP 10
#define ARCHIVE_FILTER_LZOP 11
#define ARCHIVE_FILTER_GRZIP 12
#if ARCHIVE_VERSION_NUMBER < 4000000
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
@ -228,6 +235,7 @@ typedef int archive_close_callback(struct archive *, void *_client_data);
#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU
#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM
#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP
#define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP
#endif
/*
@ -300,37 +308,49 @@ __LA_DECL struct archive *archive_read_new(void);
*/
#if ARCHIVE_VERSION_NUMBER < 4000000
__LA_DECL int archive_read_support_compression_all(struct archive *);
__LA_DECL int archive_read_support_compression_bzip2(struct archive *);
__LA_DECL int archive_read_support_compression_compress(struct archive *);
__LA_DECL int archive_read_support_compression_gzip(struct archive *);
__LA_DECL int archive_read_support_compression_lzip(struct archive *);
__LA_DECL int archive_read_support_compression_lzma(struct archive *);
__LA_DECL int archive_read_support_compression_none(struct archive *);
__LA_DECL int archive_read_support_compression_all(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_bzip2(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_compress(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_gzip(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_lzip(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_lzma(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_none(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_program(struct archive *,
const char *command);
const char *command) __LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_program_signature
(struct archive *, const char *,
const void * /* match */, size_t);
const void * /* match */, size_t) __LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_rpm(struct archive *);
__LA_DECL int archive_read_support_compression_uu(struct archive *);
__LA_DECL int archive_read_support_compression_xz(struct archive *);
__LA_DECL int archive_read_support_compression_rpm(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_uu(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_read_support_compression_xz(struct archive *)
__LA_DEPRECATED;
#endif
__LA_DECL int archive_read_support_filter_all(struct archive *);
__LA_DECL int archive_read_support_filter_bzip2(struct archive *);
__LA_DECL int archive_read_support_filter_compress(struct archive *);
__LA_DECL int archive_read_support_filter_gzip(struct archive *);
__LA_DECL int archive_read_support_filter_grzip(struct archive *);
__LA_DECL int archive_read_support_filter_lrzip(struct archive *);
__LA_DECL int archive_read_support_filter_lzip(struct archive *);
__LA_DECL int archive_read_support_filter_lzma(struct archive *);
__LA_DECL int archive_read_support_filter_lzop(struct archive *);
__LA_DECL int archive_read_support_filter_none(struct archive *);
__LA_DECL int archive_read_support_filter_program(struct archive *,
const char *command);
__LA_DECL int archive_read_support_filter_program_signature
(struct archive *, const char *,
(struct archive *, const char * /* cmd */,
const void * /* match */, size_t);
__LA_DECL int archive_read_support_filter_rpm(struct archive *);
__LA_DECL int archive_read_support_filter_uu(struct archive *);
__LA_DECL int archive_read_support_filter_xz(struct archive *);
@ -352,6 +372,17 @@ __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_zip(struct archive *);
/* Functions to manually set the format and filters to be used. This is
* useful to bypass the bidding process when the format and filters to use
* is known in advance.
*/
__LA_DECL int archive_read_set_format(struct archive *, int);
__LA_DECL int archive_read_append_filter(struct archive *, int);
__LA_DECL int archive_read_append_filter_program(struct archive *,
const char *);
__LA_DECL int archive_read_append_filter_program_signature
(struct archive *, const char *, const void * /* match */, size_t);
/* Set various callbacks. */
__LA_DECL int archive_read_set_open_callback(struct archive *,
archive_open_callback *);
@ -363,8 +394,23 @@ __LA_DECL int archive_read_set_skip_callback(struct archive *,
archive_skip_callback *);
__LA_DECL int archive_read_set_close_callback(struct archive *,
archive_close_callback *);
/* The callback data is provided to all of the callbacks above. */
/* Callback used to switch between one data object to the next */
__LA_DECL int archive_read_set_switch_callback(struct archive *,
archive_switch_callback *);
/* This sets the first data object. */
__LA_DECL int archive_read_set_callback_data(struct archive *, void *);
/* This sets data object at specified index */
__LA_DECL int archive_read_set_callback_data2(struct archive *, void *,
unsigned int);
/* This adds a data object at the specified index. */
__LA_DECL int archive_read_add_callback_data(struct archive *, void *,
unsigned int);
/* This appends a data object to the end of list */
__LA_DECL int archive_read_append_callback_data(struct archive *, void *);
/* This prepends a data object to the beginning of list */
__LA_DECL int archive_read_prepend_callback_data(struct archive *, void *);
/* Opening freezes the callbacks. */
__LA_DECL int archive_read_open1(struct archive *);
@ -384,11 +430,15 @@ __LA_DECL int archive_read_open2(struct archive *, void *_client_data,
/* Use this if you know the filename. Note: NULL indicates stdin. */
__LA_DECL int archive_read_open_filename(struct archive *,
const char *_filename, size_t _block_size);
/* Use this for reading multivolume files by filenames.
* NOTE: Must be NULL terminated. Sorting is NOT done. */
__LA_DECL int archive_read_open_filenames(struct archive *,
const char **_filenames, size_t _block_size);
__LA_DECL int archive_read_open_filename_w(struct archive *,
const wchar_t *_filename, size_t _block_size);
/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */
__LA_DECL int archive_read_open_file(struct archive *,
const char *_filename, size_t _block_size);
const char *_filename, size_t _block_size) __LA_DEPRECATED;
/* Read an archive that's stored in memory. */
__LA_DECL int archive_read_open_memory(struct archive *,
void * buff, size_t size);
@ -420,6 +470,9 @@ __LA_DECL __LA_INT64_T archive_read_header_position(struct archive *);
__LA_DECL __LA_SSIZE_T archive_read_data(struct archive *,
void *, size_t);
/* Seek within the body of an entry. Similar to lseek(2). */
__LA_DECL __LA_INT64_T archive_seek_data(struct archive *, __LA_INT64_T, int);
/*
* A zero-copy version of archive_read_data that also exposes the file offset
* of each returned block. Note that the client has no way to specify
@ -503,6 +556,12 @@ __LA_DECL int archive_read_set_options(struct archive *_a,
/* Default: Do not restore Mac extended metadata. */
/* This has no effect except on Mac OS. */
#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000)
/* Default: Use HFS+ compression if it was compressed. */
/* This has no effect except on Mac OS v10.6 or later. */
#define ARCHIVE_EXTRACT_NO_HFS_COMPRESSION (0x4000)
/* Default: Do not use HFS+ compression if it was not compressed. */
/* This has no effect except on Mac OS v10.6 or later. */
#define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000)
__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
int flags);
@ -523,7 +582,7 @@ __LA_DECL int archive_read_close(struct archive *);
__LA_DECL int archive_read_free(struct archive *);
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Synonym for archive_read_free() for backwards compatibility. */
__LA_DECL int archive_read_finish(struct archive *);
__LA_DECL int archive_read_finish(struct archive *) __LA_DEPRECATED;
#endif
/*-
@ -556,25 +615,41 @@ __LA_DECL int archive_write_set_skip_file(struct archive *,
__LA_INT64_T, __LA_INT64_T);
#if ARCHIVE_VERSION_NUMBER < 4000000
__LA_DECL int archive_write_set_compression_bzip2(struct archive *);
__LA_DECL int archive_write_set_compression_compress(struct archive *);
__LA_DECL int archive_write_set_compression_gzip(struct archive *);
__LA_DECL int archive_write_set_compression_lzip(struct archive *);
__LA_DECL int archive_write_set_compression_lzma(struct archive *);
__LA_DECL int archive_write_set_compression_none(struct archive *);
__LA_DECL int archive_write_set_compression_bzip2(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_write_set_compression_compress(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_write_set_compression_gzip(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_write_set_compression_lzip(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_write_set_compression_lzma(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_write_set_compression_none(struct archive *)
__LA_DEPRECATED;
__LA_DECL int archive_write_set_compression_program(struct archive *,
const char *cmd);
__LA_DECL int archive_write_set_compression_xz(struct archive *);
const char *cmd) __LA_DEPRECATED;
__LA_DECL int archive_write_set_compression_xz(struct archive *)
__LA_DEPRECATED;
#endif
/* A convenience function to set the filter based on the code. */
__LA_DECL int archive_write_add_filter(struct archive *, int filter_code);
__LA_DECL int archive_write_add_filter_by_name(struct archive *,
const char *name);
__LA_DECL int archive_write_add_filter_b64encode(struct archive *);
__LA_DECL int archive_write_add_filter_bzip2(struct archive *);
__LA_DECL int archive_write_add_filter_compress(struct archive *);
__LA_DECL int archive_write_add_filter_grzip(struct archive *);
__LA_DECL int archive_write_add_filter_gzip(struct archive *);
__LA_DECL int archive_write_add_filter_lrzip(struct archive *);
__LA_DECL int archive_write_add_filter_lzip(struct archive *);
__LA_DECL int archive_write_add_filter_lzma(struct archive *);
__LA_DECL int archive_write_add_filter_lzop(struct archive *);
__LA_DECL int archive_write_add_filter_none(struct archive *);
__LA_DECL int archive_write_add_filter_program(struct archive *,
const char *cmd);
__LA_DECL int archive_write_add_filter_uuencode(struct archive *);
__LA_DECL int archive_write_add_filter_xz(struct archive *);
@ -591,14 +666,18 @@ __LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
__LA_DECL int archive_write_set_format_gnutar(struct archive *);
__LA_DECL int archive_write_set_format_iso9660(struct archive *);
__LA_DECL int archive_write_set_format_mtree(struct archive *);
__LA_DECL int archive_write_set_format_mtree_classic(struct archive *);
/* TODO: int archive_write_set_format_old_tar(struct archive *); */
__LA_DECL int archive_write_set_format_pax(struct archive *);
__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
__LA_DECL int archive_write_set_format_shar(struct archive *);
__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
__LA_DECL int archive_write_set_format_ustar(struct archive *);
__LA_DECL int archive_write_set_format_v7tar(struct archive *);
__LA_DECL int archive_write_set_format_xar(struct archive *);
__LA_DECL int archive_write_set_format_zip(struct archive *);
__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
__LA_DECL int archive_write_zip_set_compression_store(struct archive *);
__LA_DECL int archive_write_open(struct archive *, void *,
archive_open_callback *, archive_write_callback *,
archive_close_callback *);
@ -607,7 +686,8 @@ __LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
__LA_DECL int archive_write_open_filename_w(struct archive *,
const wchar_t *_file);
/* A deprecated synonym for archive_write_open_filename() */
__LA_DECL int archive_write_open_file(struct archive *, const char *_file);
__LA_DECL int archive_write_open_file(struct archive *, const char *_file)
__LA_DEPRECATED;
__LA_DECL int archive_write_open_FILE(struct archive *, FILE *);
/* _buffSize is the size of the buffer, _used refers to a variable that
* will be updated after each write into the buffer. */
@ -629,12 +709,16 @@ __LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *,
__LA_DECL int archive_write_finish_entry(struct archive *);
__LA_DECL int archive_write_close(struct archive *);
/* Marks the archive as FATAL so that a subsequent free() operation
* won't try to close() cleanly. Provides a fast abort capability
* when the client discovers that things have gone wrong. */
__LA_DECL int archive_write_fail(struct archive *);
/* This can fail if the archive wasn't already closed, in which case
* archive_write_free() will implicitly call archive_write_close(). */
__LA_DECL int archive_write_free(struct archive *);
#if ARCHIVE_VERSION_NUMBER < 4000000
/* Synonym for archive_write_free() for backwards compatibility. */
__LA_DECL int archive_write_finish(struct archive *);
__LA_DECL int archive_write_finish(struct archive *) __LA_DEPRECATED;
#endif
/*
@ -758,11 +842,42 @@ __LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *);
* traversal.
*/
__LA_DECL int archive_read_disk_descend(struct archive *);
__LA_DECL int archive_read_disk_can_descend(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *);
__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *);
/* Request that the access time of the entry visited by travesal be restored. */
__LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
/*
* Set behavior. The "flags" argument selects optional behavior.
*/
/* Request that the access time of the entry visited by travesal be restored.
* This is the same as archive_read_disk_set_atime_restored. */
#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001)
/* Default: Do not skip an entry which has nodump flags. */
#define ARCHIVE_READDISK_HONOR_NODUMP (0x0002)
/* Default: Skip a mac resource fork file whose prefix is "._" because of
* using copyfile. */
#define ARCHIVE_READDISK_MAC_COPYFILE (0x0004)
/* Default: Do not traverse mount points. */
#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008)
__LA_DECL int archive_read_disk_set_behavior(struct archive *,
int flags);
/*
* Set archive_match object that will be used in archive_read_disk to
* know whether an entry should be skipped. The callback function
* _excluded_func will be invoked when an entry is skipped by the result
* of archive_match.
*/
__LA_DECL int archive_read_disk_set_matching(struct archive *,
struct archive *_matching, void (*_excluded_func)
(struct archive *, void *, struct archive_entry *),
void *_client_data);
__LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *,
int (*_metadata_filter_func)(struct archive *, void *,
struct archive_entry *), void *_client_data);
/*
* Accessor functions to read/set various information in
@ -782,13 +897,17 @@ __LA_DECL const char * archive_filter_name(struct archive *, int);
/* These don't properly handle multiple filters, so are deprecated and
* will eventually be removed. */
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */
__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *);
__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *)
__LA_DEPRECATED;
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */
__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *);
__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *)
__LA_DEPRECATED;
/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */
__LA_DECL const char *archive_compression_name(struct archive *);
__LA_DECL const char *archive_compression_name(struct archive *)
__LA_DEPRECATED;
/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */
__LA_DECL int archive_compression(struct archive *);
__LA_DECL int archive_compression(struct archive *)
__LA_DEPRECATED;
#endif
__LA_DECL int archive_errno(struct archive *);
@ -802,14 +921,116 @@ __LA_DECL void archive_copy_error(struct archive *dest,
struct archive *src);
__LA_DECL int archive_file_count(struct archive *);
/*
* ARCHIVE_MATCH API
*/
__LA_DECL struct archive *archive_match_new(void);
__LA_DECL int archive_match_free(struct archive *);
/*
* Test if archive_entry is excluded.
* This is a convenience function. This is the same as calling all
* archive_match_path_excluded, archive_match_time_excluded
* and archive_match_owner_excluded.
*/
__LA_DECL int archive_match_excluded(struct archive *,
struct archive_entry *);
/*
* Test if pathname is excluded. The conditions are set by following functions.
*/
__LA_DECL int archive_match_path_excluded(struct archive *,
struct archive_entry *);
/* Add exclusion pathname pattern. */
__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *);
__LA_DECL int archive_match_exclude_pattern_w(struct archive *,
const wchar_t *);
/* Add exclusion pathname pattern from file. */
__LA_DECL int archive_match_exclude_pattern_from_file(struct archive *,
const char *, int _nullSeparator);
__LA_DECL int archive_match_exclude_pattern_from_file_w(struct archive *,
const wchar_t *, int _nullSeparator);
/* Add inclusion pathname pattern. */
__LA_DECL int archive_match_include_pattern(struct archive *, const char *);
__LA_DECL int archive_match_include_pattern_w(struct archive *,
const wchar_t *);
/* Add inclusion pathname pattern from file. */
__LA_DECL int archive_match_include_pattern_from_file(struct archive *,
const char *, int _nullSeparator);
__LA_DECL int archive_match_include_pattern_from_file_w(struct archive *,
const wchar_t *, int _nullSeparator);
/*
* How to get statistic information for inclusion patterns.
*/
/* Return the amount number of unmatched inclusion patterns. */
__LA_DECL int archive_match_path_unmatched_inclusions(struct archive *);
/* Return the pattern of unmatched inclusion with ARCHIVE_OK.
* Return ARCHIVE_EOF if there is no inclusion pattern. */
__LA_DECL int archive_match_path_unmatched_inclusions_next(
struct archive *, const char **);
__LA_DECL int archive_match_path_unmatched_inclusions_next_w(
struct archive *, const wchar_t **);
/*
* Test if a file is excluded by its time stamp.
* The conditions are set by following functions.
*/
__LA_DECL int archive_match_time_excluded(struct archive *,
struct archive_entry *);
/*
* Flags to tell a matching type of time stamps. These are used for
* following functinos.
*/
/* Time flag: mtime to be tested. */
#define ARCHIVE_MATCH_MTIME (0x0100)
/* Time flag: ctime to be tested. */
#define ARCHIVE_MATCH_CTIME (0x0200)
/* Comparison flag: Match the time if it is newer than. */
#define ARCHIVE_MATCH_NEWER (0x0001)
/* Comparison flag: Match the time if it is older than. */
#define ARCHIVE_MATCH_OLDER (0x0002)
/* Comparison flag: Match the time if it is equal to. */
#define ARCHIVE_MATCH_EQUAL (0x0010)
/* Set inclusion time. */
__LA_DECL int archive_match_include_time(struct archive *, int _flag,
time_t _sec, long _nsec);
/* Set inclusion time by a date string. */
__LA_DECL int archive_match_include_date(struct archive *, int _flag,
const char *_datestr);
__LA_DECL int archive_match_include_date_w(struct archive *, int _flag,
const wchar_t *_datestr);
/* Set inclusion time by a particluar file. */
__LA_DECL int archive_match_include_file_time(struct archive *,
int _flag, const char *_pathname);
__LA_DECL int archive_match_include_file_time_w(struct archive *,
int _flag, const wchar_t *_pathname);
/* Add exclusion entry. */
__LA_DECL int archive_match_exclude_entry(struct archive *,
int _flag, struct archive_entry *);
/*
* Test if a file is excluded by its uid ,gid, uname or gname.
* The conditions are set by following functions.
*/
__LA_DECL int archive_match_owner_excluded(struct archive *,
struct archive_entry *);
/* Add inclusion uid, gid, uname and gname. */
__LA_DECL int archive_match_include_uid(struct archive *, __LA_INT64_T);
__LA_DECL int archive_match_include_gid(struct archive *, __LA_INT64_T);
__LA_DECL int archive_match_include_uname(struct archive *, const char *);
__LA_DECL int archive_match_include_uname_w(struct archive *,
const wchar_t *);
__LA_DECL int archive_match_include_gname(struct archive *, const char *);
__LA_DECL int archive_match_include_gname_w(struct archive *,
const wchar_t *);
#ifdef __cplusplus
}
#endif
/* These are meaningless outside of this header. */
#undef __LA_DECL
#undef __LA_GID_T
#undef __LA_UID_T
/* These need to remain defined because they're used in the
* callback type definitions. XXX Fix this. This is ugly. XXX */

View File

@ -52,6 +52,9 @@ static int acl_special(struct archive_acl *acl,
int type, int permset, int tag);
static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl,
int type, int permset, int tag, int id);
static int archive_acl_add_entry_len_l(struct archive_acl *acl,
int type, int permset, int tag, int id, const char *name,
size_t len, struct archive_string_conv *sc);
static int isint_w(const wchar_t *start, const wchar_t *end, int *result);
static int ismode_w(const wchar_t *start, const wchar_t *end, int *result);
static void next_field_w(const wchar_t **wp, const wchar_t **start,
@ -65,7 +68,7 @@ static int isint(const char *start, const char *end, int *result);
static int ismode(const char *start, const char *end, int *result);
static void next_field(const char **p, const char **start,
const char **end, char *sep);
static int prefix(const char *start, const char *end,
static int prefix_c(const char *start, const char *end,
const char *test);
static void append_entry(char **p, const char *prefix, int tag,
const char *name, int perm, int id);
@ -152,7 +155,7 @@ archive_acl_add_entry_w_len(struct archive_acl *acl,
return ARCHIVE_OK;
}
int
static int
archive_acl_add_entry_len_l(struct archive_acl *acl,
int type, int permset, int tag, int id, const char *name, size_t len,
struct archive_string_conv *sc)
@ -419,8 +422,11 @@ archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int
*permset = acl->acl_p->permset;
*tag = acl->acl_p->tag;
*id = acl->acl_p->id;
if (archive_mstring_get_mbs(a, &acl->acl_p->name, name) != 0)
if (archive_mstring_get_mbs(a, &acl->acl_p->name, name) != 0) {
if (errno == ENOMEM)
return (ARCHIVE_FATAL);
*name = NULL;
}
acl->acl_p = acl->acl_p->next;
return (ARCHIVE_OK);
}
@ -438,7 +444,7 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
const wchar_t *prefix;
wchar_t separator;
struct archive_acl_entry *ap;
int id;
int id, r;
wchar_t *wp;
if (acl->acl_text_w != NULL) {
@ -458,9 +464,11 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
length += 8; /* "default:" */
length += 5; /* tag name */
length += 1; /* colon */
if (archive_mstring_get_wcs(a, &ap->name, &wname) == 0 &&
wname != NULL)
r = archive_mstring_get_wcs(a, &ap->name, &wname);
if (r == 0 && wname != NULL)
length += wcslen(wname);
else if (r < 0 && errno == ENOMEM)
return (NULL);
else
length += sizeof(uid_t) * 3 + 1;
length ++; /* colon */
@ -484,7 +492,7 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
/* Now, allocate the string and actually populate it. */
wp = acl->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t));
if (wp == NULL)
__archive_errx(1, "No memory to generate the text version of the ACL");
return (NULL);
count = 0;
if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
@ -499,8 +507,9 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
ap = acl->acl_head;
while (ap != NULL) {
if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0 &&
archive_mstring_get_wcs(a, &ap->name, &wname) == 0) {
if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
r = archive_mstring_get_wcs(a, &ap->name, &wname);
if (r == 0) {
*wp++ = separator;
if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
id = ap->id;
@ -509,6 +518,8 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
append_entry_w(&wp, NULL, ap->tag, wname,
ap->permset, id);
count++;
} else if (r < 0 && errno == ENOMEM)
return (NULL);
}
ap = ap->next;
}
@ -523,8 +534,9 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
ap = acl->acl_head;
count = 0;
while (ap != NULL) {
if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0 &&
archive_mstring_get_wcs(a, &ap->name, &wname) == 0) {
if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) {
r = archive_mstring_get_wcs(a, &ap->name, &wname);
if (r == 0) {
if (count > 0)
*wp++ = separator;
if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
@ -534,6 +546,8 @@ archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags)
append_entry_w(&wp, prefix, ap->tag,
wname, ap->permset, id);
count ++;
} else if (r < 0 && errno == ENOMEM)
return (NULL);
}
ap = ap->next;
}
@ -672,7 +686,7 @@ archive_acl_text_l(struct archive_acl *acl, int flags,
/* Now, allocate the string and actually populate it. */
p = acl->acl_text = (char *)malloc(length);
if (p == NULL)
__archive_errx(1, "No memory to generate the text version of the ACL");
return (-1);
count = 0;
if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL,
@ -1088,7 +1102,7 @@ archive_acl_parse_l(struct archive_acl *acl,
type = default_type;
name.start = name.end = NULL;
if (prefix(field[0].start, field[0].end, "user")) {
if (prefix_c(field[0].start, field[0].end, "user")) {
if (!ismode(field[2].start, field[2].end, &permset))
return (ARCHIVE_WARN);
if (id != -1 || field[1].start < field[1].end) {
@ -1096,7 +1110,7 @@ archive_acl_parse_l(struct archive_acl *acl,
name = field[1];
} else
tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
} else if (prefix(field[0].start, field[0].end, "group")) {
} else if (prefix_c(field[0].start, field[0].end, "group")) {
if (!ismode(field[2].start, field[2].end, &permset))
return (ARCHIVE_WARN);
if (id != -1 || field[1].start < field[1].end) {
@ -1104,7 +1118,7 @@ archive_acl_parse_l(struct archive_acl *acl,
name = field[1];
} else
tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
} else if (prefix(field[0].start, field[0].end, "other")) {
} else if (prefix_c(field[0].start, field[0].end, "other")) {
if (fields == 2
&& field[1].start < field[1].end
&& ismode(field[1].start, field[1].end, &permset)) {
@ -1117,7 +1131,7 @@ archive_acl_parse_l(struct archive_acl *acl,
} else
return (ARCHIVE_WARN);
tag = ARCHIVE_ENTRY_ACL_OTHER;
} else if (prefix(field[0].start, field[0].end, "mask")) {
} else if (prefix_c(field[0].start, field[0].end, "mask")) {
if (fields == 2
&& field[1].start < field[1].end
&& ismode(field[1].start, field[1].end, &permset)) {
@ -1246,7 +1260,7 @@ next_field(const char **p, const char **start,
* This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc.
*/
static int
prefix(const char *start, const char *end, const char *test)
prefix_c(const char *start, const char *end, const char *test)
{
if (start == end)
return (0);

View File

@ -94,6 +94,7 @@ archive_handle_type_name(unsigned m)
case ARCHIVE_READ_MAGIC: return ("archive_read");
case ARCHIVE_WRITE_DISK_MAGIC: return ("archive_write_disk");
case ARCHIVE_READ_DISK_MAGIC: return ("archive_read_disk");
case ARCHIVE_MATCH_MAGIC: return ("archive_match");
default: return NULL;
}
}

View File

@ -0,0 +1,227 @@
/*-
* Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include "archive.h"
#include "archive_cmdline_private.h"
#include "archive_string.h"
static int cmdline_set_path(struct archive_cmdline *, const char *);
static int cmdline_add_arg(struct archive_cmdline *, const char *);
static ssize_t
extract_quotation(struct archive_string *as, const char *p)
{
const char *s;
for (s = p + 1; *s;) {
if (*s == '\\') {
if (s[1] != '\0') {
archive_strappend_char(as, s[1]);
s += 2;
} else
s++;
} else if (*s == '"')
break;
else {
archive_strappend_char(as, s[0]);
s++;
}
}
if (*s != '"')
return (ARCHIVE_FAILED);/* Invalid sequence. */
return ((ssize_t)(s + 1 - p));
}
static ssize_t
get_argument(struct archive_string *as, const char *p)
{
const char *s = p;
archive_string_empty(as);
/* Skip beginning space characters. */
while (*s != '\0' && *s == ' ')
s++;
/* Copy non-space characters. */
while (*s != '\0' && *s != ' ') {
if (*s == '\\') {
if (s[1] != '\0') {
archive_strappend_char(as, s[1]);
s += 2;
} else {
s++;/* Ignore this character.*/
break;
}
} else if (*s == '"') {
ssize_t q = extract_quotation(as, s);
if (q < 0)
return (ARCHIVE_FAILED);/* Invalid sequence. */
s += q;
} else {
archive_strappend_char(as, s[0]);
s++;
}
}
return ((ssize_t)(s - p));
}
/*
* Set up command line arguments.
* Returns ARChIVE_OK if everything okey.
* Returns ARChIVE_FAILED if there is a lack of the `"' terminator or an
* empty command line.
* Returns ARChIVE_FATAL if no memory.
*/
int
__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
{
struct archive_string as;
const char *p;
ssize_t al;
int r;
archive_string_init(&as);
/* Get first argument as a command path. */
al = get_argument(&as, cmd);
if (al < 0) {
r = ARCHIVE_FAILED;/* Invalid sequence. */
goto exit_function;
}
if (archive_strlen(&as) == 0) {
r = ARCHIVE_FAILED;/* An empty command path. */
goto exit_function;
}
r = cmdline_set_path(data, as.s);
if (r != ARCHIVE_OK)
goto exit_function;
p = strrchr(as.s, '/');
if (p == NULL)
p = as.s;
else
p++;
r = cmdline_add_arg(data, p);
if (r != ARCHIVE_OK)
goto exit_function;
cmd += al;
for (;;) {
al = get_argument(&as, cmd);
if (al < 0) {
r = ARCHIVE_FAILED;/* Invalid sequence. */
goto exit_function;
}
if (al == 0)
break;
cmd += al;
if (archive_strlen(&as) == 0 && *cmd == '\0')
break;
r = cmdline_add_arg(data, as.s);
if (r != ARCHIVE_OK)
goto exit_function;
}
r = ARCHIVE_OK;
exit_function:
archive_string_free(&as);
return (r);
}
/*
* Set the program path.
*/
static int
cmdline_set_path(struct archive_cmdline *data, const char *path)
{
char *newptr;
newptr = realloc(data->path, strlen(path) + 1);
if (newptr == NULL)
return (ARCHIVE_FATAL);
data->path = newptr;
strcpy(data->path, path);
return (ARCHIVE_OK);
}
/*
* Add a argument for the program.
*/
static int
cmdline_add_arg(struct archive_cmdline *data, const char *arg)
{
char **newargv;
if (data->path == NULL)
return (ARCHIVE_FAILED);
newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *));
if (newargv == NULL)
return (ARCHIVE_FATAL);
data->argv = newargv;
data->argv[data->argc] = strdup(arg);
if (data->argv[data->argc] == NULL)
return (ARCHIVE_FATAL);
/* Set the terminator of argv. */
data->argv[++data->argc] = NULL;
return (ARCHIVE_OK);
}
struct archive_cmdline *
__archive_cmdline_allocate(void)
{
return (struct archive_cmdline *)
calloc(1, sizeof(struct archive_cmdline));
}
/*
* Release the resources.
*/
int
__archive_cmdline_free(struct archive_cmdline *data)
{
if (data) {
free(data->path);
if (data->argv != NULL) {
int i;
for (i = 0; data->argv[i] != NULL; i++)
free(data->argv[i]);
free(data->argv);
}
free(data);
}
return (ARCHIVE_OK);
}

View File

@ -0,0 +1,47 @@
/*-
* Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __LIBARCHIVE_BUILD
#ifndef __LIBARCHIVE_TEST
#error This header is only to be used internally to libarchive.
#endif
#endif
#ifndef ARCHIVE_CMDLINE_PRIVATE_H
#define ARCHIVE_CMDLINE_PRIVATE_H
struct archive_cmdline {
char *path;
char **argv;
int argc;
};
struct archive_cmdline *__archive_cmdline_allocate(void);
int __archive_cmdline_parse(struct archive_cmdline *, const char *);
int __archive_cmdline_free(struct archive_cmdline *);
#endif

View File

@ -90,7 +90,7 @@ win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len)
static int
win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
{
DWORD siglen = bufsize;
DWORD siglen = (DWORD)bufsize;
if (!ctx->valid)
return (ARCHIVE_FAILED);
@ -1222,8 +1222,10 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md)
* 2. libc2
* 3. libc3
* 4. libSystem
* 5. OpenSSL
* 6. Windows API
* 5. Nettle
* 6. OpenSSL
* 7. libmd
* 8. Windows API
*/
const struct archive_crypto __archive_crypto =
{

View File

@ -126,8 +126,8 @@ archive_be64enc(void *pp, uint64_t u)
{
unsigned char *p = (unsigned char *)pp;
archive_be32enc(p, u >> 32);
archive_be32enc(p + 4, u & 0xffffffff);
archive_be32enc(p, (uint32_t)(u >> 32));
archive_be32enc(p + 4, (uint32_t)(u & 0xffffffff));
}
static inline void
@ -155,8 +155,8 @@ archive_le64enc(void *pp, uint64_t u)
{
unsigned char *p = (unsigned char *)pp;
archive_le32enc(p, u & 0xffffffff);
archive_le32enc(p + 4, u >> 32);
archive_le32enc(p, (uint32_t)(u & 0xffffffff));
archive_le32enc(p + 4, (uint32_t)(u >> 32));
}
#endif

View File

@ -23,9 +23,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $
.\" $FreeBSD$
.\"
.Dd Feburary 22, 2010
.Dd Feburary 2, 2012
.Dt ARCHIVE_ENTRY 3
.Os
.Sh NAME
@ -34,6 +34,8 @@
.Nm archive_entry_free ,
.Nm archive_entry_new ,
.Nd functions for managing archive entry descriptions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft "struct archive_entry *"

View File

@ -375,8 +375,11 @@ archive_entry_fflags_text(struct archive_entry *entry)
char *p;
if (archive_mstring_get_mbs(entry->archive,
&entry->ae_fflags_text, &f) == 0 && f != NULL)
&entry->ae_fflags_text, &f) == 0) {
if (f != NULL)
return (f);
} else if (errno == ENOMEM)
__archive_errx(1, "No memory");
if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0)
return (NULL);
@ -390,6 +393,8 @@ archive_entry_fflags_text(struct archive_entry *entry)
if (archive_mstring_get_mbs(entry->archive,
&entry->ae_fflags_text, &f) == 0)
return (f);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -405,6 +410,8 @@ archive_entry_gname(struct archive_entry *entry)
const char *p;
if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -414,6 +421,8 @@ archive_entry_gname_w(struct archive_entry *entry)
const wchar_t *p;
if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -428,9 +437,13 @@ const char *
archive_entry_hardlink(struct archive_entry *entry)
{
const char *p;
if ((entry->ae_set & AE_SET_HARDLINK) && archive_mstring_get_mbs(
if ((entry->ae_set & AE_SET_HARDLINK) == 0)
return (NULL);
if (archive_mstring_get_mbs(
entry->archive, &entry->ae_hardlink, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -438,9 +451,13 @@ const wchar_t *
archive_entry_hardlink_w(struct archive_entry *entry)
{
const wchar_t *p;
if ((entry->ae_set & AE_SET_HARDLINK) && archive_mstring_get_wcs(
if ((entry->ae_set & AE_SET_HARDLINK) == 0)
return (NULL);
if (archive_mstring_get_wcs(
entry->archive, &entry->ae_hardlink, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -511,6 +528,8 @@ archive_entry_pathname(struct archive_entry *entry)
if (archive_mstring_get_mbs(
entry->archive, &entry->ae_pathname, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -521,6 +540,8 @@ archive_entry_pathname_w(struct archive_entry *entry)
if (archive_mstring_get_wcs(
entry->archive, &entry->ae_pathname, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -584,6 +605,8 @@ archive_entry_sourcepath(struct archive_entry *entry)
if (archive_mstring_get_mbs(
entry->archive, &entry->ae_sourcepath, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -601,9 +624,13 @@ const char *
archive_entry_symlink(struct archive_entry *entry)
{
const char *p;
if ((entry->ae_set & AE_SET_SYMLINK) && archive_mstring_get_mbs(
if ((entry->ae_set & AE_SET_SYMLINK) == 0)
return (NULL);
if (archive_mstring_get_mbs(
entry->archive, &entry->ae_symlink, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -611,9 +638,13 @@ const wchar_t *
archive_entry_symlink_w(struct archive_entry *entry)
{
const wchar_t *p;
if ((entry->ae_set & AE_SET_SYMLINK) && archive_mstring_get_wcs(
if ((entry->ae_set & AE_SET_SYMLINK) == 0)
return (NULL);
if (archive_mstring_get_wcs(
entry->archive, &entry->ae_symlink, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -641,6 +672,8 @@ archive_entry_uname(struct archive_entry *entry)
const char *p;
if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -650,6 +683,8 @@ archive_entry_uname_w(struct archive_entry *entry)
const wchar_t *p;
if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0)
return (p);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (NULL);
}
@ -730,6 +765,8 @@ archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name)
if (archive_mstring_update_utf8(entry->archive,
&entry->ae_gname, name) == 0)
return (1);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (0);
}
@ -796,6 +833,8 @@ archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *targ
if (archive_mstring_update_utf8(entry->archive,
&entry->ae_hardlink, target) == 0)
return (1);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (0);
}
@ -932,7 +971,11 @@ archive_entry_update_link_utf8(struct archive_entry *entry, const char *target)
else
r = archive_mstring_update_utf8(entry->archive,
&entry->ae_hardlink, target);
return ((r == 0)? 1: 0);
if (r == 0)
return (1);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (0);
}
int
@ -1005,6 +1048,8 @@ archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name
if (archive_mstring_update_utf8(entry->archive,
&entry->ae_pathname, name) == 0)
return (1);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (0);
}
@ -1115,6 +1160,8 @@ archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkn
if (archive_mstring_update_utf8(entry->archive,
&entry->ae_symlink, linkname) == 0)
return (1);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (0);
}
@ -1164,6 +1211,8 @@ archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
if (archive_mstring_update_utf8(entry->archive,
&entry->ae_uname, name) == 0)
return (1);
if (errno == ENOMEM)
__archive_errx(1, "No memory");
return (0);
}
@ -1269,7 +1318,12 @@ int
archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
int *permset, int *tag, int *id, const char **name)
{
return archive_acl_next(entry->archive, &entry->acl, want_type, type, permset, tag, id, name);
int r;
r = archive_acl_next(entry->archive, &entry->acl, want_type, type,
permset, tag, id, name);
if (r == ARCHIVE_FATAL && errno == ENOMEM)
__archive_errx(1, "No memory");
return (r);
}
/*
@ -1279,7 +1333,11 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
const wchar_t *
archive_entry_acl_text_w(struct archive_entry *entry, int flags)
{
return archive_acl_text_w(entry->archive, &entry->acl, flags);
const wchar_t *r;
r = archive_acl_text_w(entry->archive, &entry->acl, flags);
if (r == NULL && errno == ENOMEM)
__archive_errx(1, "No memory");
return (r);
}
const char *
@ -1288,7 +1346,7 @@ archive_entry_acl_text(struct archive_entry *entry, int flags)
const char *p;
if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0
&& errno == ENOMEM)
return (NULL);
__archive_errx(1, "No memory");
return (p);
}
@ -1391,6 +1449,9 @@ static struct flag {
{ "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0 },
{ "nouunlink", L"nouunlink", UF_NOUNLINK, 0 },
#endif
#ifdef UF_COMPRESSED
{ "nocompressed",L"nocompressed", UF_COMPRESSED, 0 },
#endif
#ifdef EXT2_UNRM_FL
{ "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0},
#endif

View File

@ -29,7 +29,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
#define ARCHIVE_VERSION_NUMBER 3000002
#define ARCHIVE_VERSION_NUMBER 3001002
/*
* Note: archive_entry.h is for use outside of libarchive; the
@ -47,21 +47,9 @@
#include <windows.h>
#endif
/* Get appropriate definitions of standard POSIX-style types. */
/* These should match the types used in 'struct stat' */
/* Get a suitable 64-bit integer type. */
#if defined(_WIN32) && !defined(__CYGWIN__)
# define __LA_INT64_T __int64
# if defined(__BORLANDC__)
# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */
# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */
# define __LA_DEV_T dev_t
# define __LA_MODE_T mode_t
# else
# define __LA_UID_T short /* Remove in libarchive 3.2 */
# define __LA_GID_T short /* Remove in libarchive 3.2 */
# define __LA_DEV_T unsigned int
# define __LA_MODE_T unsigned short
# endif
#else
#include <unistd.h>
# if defined(_SCO_DS)
@ -69,17 +57,17 @@
# else
# define __LA_INT64_T int64_t
# endif
# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */
# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */
# define __LA_DEV_T dev_t
# define __LA_MODE_T mode_t
#endif
/*
* Remove this for libarchive 3.2, since ino_t is no longer used.
*/
#define __LA_INO_T ino_t
/* Get a suitable definition for mode_t */
#if ARCHIVE_VERSION_NUMBER >= 3999000
/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */
# define __LA_MODE_T int
#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__)
# define __LA_MODE_T unsigned short
#else
# define __LA_MODE_T mode_t
#endif
/*
* On Windows, define LIBARCHIVE_STATIC if you're building or using a
@ -149,14 +137,18 @@ struct archive_entry;
* portable values to platform-native values when entries are read from
* or written to disk.
*/
#define AE_IFMT 0170000
#define AE_IFREG 0100000
#define AE_IFLNK 0120000
#define AE_IFSOCK 0140000
#define AE_IFCHR 0020000
#define AE_IFBLK 0060000
#define AE_IFDIR 0040000
#define AE_IFIFO 0010000
/*
* In libarchive 4.0, we can drop the casts here.
* They're needed to work around Borland C's broken mode_t.
*/
#define AE_IFMT ((__LA_MODE_T)0170000)
#define AE_IFREG ((__LA_MODE_T)0100000)
#define AE_IFLNK ((__LA_MODE_T)0120000)
#define AE_IFSOCK ((__LA_MODE_T)0140000)
#define AE_IFCHR ((__LA_MODE_T)0020000)
#define AE_IFBLK ((__LA_MODE_T)0060000)
#define AE_IFDIR ((__LA_MODE_T)0040000)
#define AE_IFIFO ((__LA_MODE_T)0010000)
/*
* Basic object manipulation
@ -321,7 +313,10 @@ __LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char
* manipulate archives on systems different than the ones they were
* created on.
*
* TODO: On Linux, provide both stat32 and stat64 versions of these functions.
* TODO: On Linux and other LFS systems, provide both stat32 and
* stat64 versions of these functions and all of the macro glue so
* that archive_entry_stat is magically defined to
* archive_entry_stat32 or archive_entry_stat64 as appropriate.
*/
__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *);
__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *);

View File

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd February 21, 2010
.Dd February 2, 2012
.Dt ARCHIVE_ENTRY_ACL 3
.Os
.Sh NAME
@ -35,6 +35,8 @@
.Nm archive_entry_acl_reset ,
.Nm archive_entry_acl_text_w
.Nd functions for manipulating Access Control Lists in archive entry descriptions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft void
@ -132,7 +134,7 @@ All files have an access ACL
This specifies the permissions required for access to the file itself.
Directories have an additional ACL
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT ,
which controlls the initial access ACL for newly created directory entries.
which controls the initial access ACL for newly created directory entries.
.Pp
.Fn archive_entry_acl_add_entry
and

View File

@ -34,7 +34,7 @@ __FBSDID("$FreeBSD$");
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
__inline static void
fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
{
ULARGE_INTEGER utc;
@ -42,10 +42,10 @@ fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
utc.LowPart = filetime->dwLowDateTime;
if (utc.QuadPart >= EPOC_TIME) {
utc.QuadPart -= EPOC_TIME;
*time = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */
*t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */
*ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
} else {
*time = 0;
*t = 0;
*ns = 0;
}
}

View File

@ -244,6 +244,9 @@ archive_entry_linkify(struct archive_entry_linkresolver *res,
* for future use.
*/
le = insert_entry(res, *e);
if (le == NULL)
/* XXX We should return an error code XXX */
return;
le->entry = *e;
*e = NULL;
}
@ -362,7 +365,7 @@ insert_entry(struct archive_entry_linkresolver *res,
if (res->number_entries > res->number_buckets * 2)
grow_hash(res);
hash = archive_entry_dev(entry) ^ archive_entry_ino64(entry);
hash = (size_t)(archive_entry_dev(entry) ^ archive_entry_ino64(entry));
bucket = hash & (res->number_buckets - 1);
/* If we could allocate the entry, record it. */

View File

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd February 20, 2010
.Dd February 2, 2012
.Dt ARCHIVE_ENTRY_LINKIFY 3
.Os
.Sh NAME
@ -33,7 +33,7 @@
.Nm archive_entry_linkify
.Nd hardlink resolver functions
.Sh LIBRARY
.Lb libarchive
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft struct archive_entry_linkresolver *

View File

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd February 22, 2010
.Dd February 2, 2012
.Dt ARCHIVE_ENTRY_PATHS 3
.Os
.Sh NAME
@ -51,6 +51,8 @@
.Nm archive_entry_copy_symlink_w ,
.Nm archve_entry_update_symlink_utf8
.Nd functions for manipulating path names in archive entry descriptions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft const char *

View File

@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd February 22, 2010
.Dd February 2, 2012
.Dt ARCHIVE_ENTRY_PERMS 3
.Os
.Sh NAME
@ -52,6 +52,8 @@
.Nm archive_entry_copy_fflags_text ,
.Nm archive_entry_copy_fflags_text_w
.Nd functions for manipulating ownership and permissions in archive entry descriptions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft gid_t

View File

@ -22,8 +22,8 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd May 12, 2008
.Dt ARCHIVE_ENTRY 3
.Dd February 2, 2012
.Dt ARCHIVE_ENTRY_STAT 3
.Os
.Sh NAME
.Nm archive_entry_stat ,
@ -56,6 +56,8 @@
.Nm archive_entry_rdevminor ,
.Nm archive_entry_set_rdevminor ,
.Nd accessor functions for manipulating archive entry descriptions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft const struct stat *

View File

@ -70,12 +70,12 @@ archive_entry_stat(struct archive_entry *entry)
st->st_ctime = archive_entry_ctime(entry);
st->st_mtime = archive_entry_mtime(entry);
st->st_dev = archive_entry_dev(entry);
st->st_gid = archive_entry_gid(entry);
st->st_uid = archive_entry_uid(entry);
st->st_ino = archive_entry_ino64(entry);
st->st_gid = (gid_t)archive_entry_gid(entry);
st->st_uid = (uid_t)archive_entry_uid(entry);
st->st_ino = (ino_t)archive_entry_ino64(entry);
st->st_nlink = archive_entry_nlink(entry);
st->st_rdev = archive_entry_rdev(entry);
st->st_size = archive_entry_size(entry);
st->st_size = (off_t)archive_entry_size(entry);
st->st_mode = archive_entry_mode(entry);
/*
@ -110,7 +110,7 @@ archive_entry_stat(struct archive_entry *entry)
/*
* TODO: On Linux, store 32 or 64 here depending on whether
* the cached stat structure is a stat32 or a stat64. This
* will allow us to support both variants interchangably.
* will allow us to support both variants interchangeably.
*/
entry->stat_valid = 1;

View File

@ -23,9 +23,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $
.\" $FreeBSD$
.\"
.Dd February 21, 2010
.Dd February 2, 2012
.Dt ARCHIVE_ENTRY_TIME 3
.Os
.Sh NAME
@ -50,6 +50,8 @@
.Nm archive_entry_set_mtime ,
.Nm archive_entry_unset_mtime ,
.Nd functions for manipulating times in archive entry descriptions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive_entry.h
.Ft time_t

1037
libarchive/archive_getdate.c Normal file

File diff suppressed because it is too large Load Diff

1841
libarchive/archive_match.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,7 @@ _archive_set_option(struct archive *a,
int magic, const char *fn, option_handler use_option)
{
const char *mp, *op, *vp;
int r;
archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
@ -47,10 +48,24 @@ _archive_set_option(struct archive *a,
if (op == NULL && vp == NULL)
return (ARCHIVE_OK);
if (op == NULL)
if (op == NULL) {
archive_set_error(a, ARCHIVE_ERRNO_MISC, "Empty option");
return (ARCHIVE_FAILED);
}
return use_option(a, mp, op, vp);
r = use_option(a, mp, op, vp);
if (r == ARCHIVE_WARN - 1) {
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unknown module name: `%s'", mp);
return (ARCHIVE_FAILED);
}
if (r == ARCHIVE_WARN) {
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Undefined option: `%s%s%s%s%s%s'",
vp?"":"!", mp?mp:"", mp?":":"", op, vp?"=":"", vp?vp:"");
return (ARCHIVE_FAILED);
}
return (r);
}
int
@ -72,6 +87,8 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons
if (r2 == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
if (r2 == ARCHIVE_WARN - 1)
return r1;
return r1 > r2 ? r1 : r2;
}
@ -79,7 +96,7 @@ int
_archive_set_options(struct archive *a, const char *options,
int magic, const char *fn, option_handler use_option)
{
int allok = 1, anyok = 0, r;
int allok = 1, anyok = 0, ignore_mod_err = 0, r;
char *data;
const char *s, *mod, *opt, *val;
@ -96,12 +113,42 @@ _archive_set_options(struct archive *a, const char *options,
mod = opt = val = NULL;
parse_option(&s, &mod, &opt, &val);
if (mod == NULL && opt != NULL &&
strcmp("__ignore_wrong_module_name__", opt) == 0) {
/* Ignore module name error */
if (val != NULL) {
ignore_mod_err = 1;
anyok = 1;
}
continue;
}
r = use_option(a, mod, opt, val);
if (r == ARCHIVE_FATAL) {
free(data);
return (ARCHIVE_FATAL);
}
if (r == ARCHIVE_FAILED && mod != NULL) {
free(data);
return (ARCHIVE_FAILED);
}
if (r == ARCHIVE_WARN - 1) {
if (ignore_mod_err)
continue;
/* The module name is wrong. */
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unknown module name: `%s'", mod);
free(data);
return (ARCHIVE_FAILED);
}
if (r == ARCHIVE_WARN) {
/* The option name is wrong. No-one used this. */
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Undefined option: `%s%s%s'",
mod?mod:"", mod?":":"", opt);
free(data);
return (ARCHIVE_FAILED);
}
if (r == ARCHIVE_OK)
anyok = 1;
else

View File

@ -0,0 +1,459 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_WCHAR_H
#include <wchar.h>
#endif
#include "archive_pathmatch.h"
/*
* Check whether a character 'c' is matched by a list specification [...]:
* * Leading '!' or '^' negates the class.
* * <char>-<char> is a range of characters
* * \<char> removes any special meaning for <char>
*
* Some interesting boundary cases:
* a-d-e is one range (a-d) followed by two single characters - and e.
* \a-\d is same as a-d
* a\-d is three single characters: a, d, -
* Trailing - is not special (so [a-] is two characters a and -).
* Initial - is not special ([a-] is same as [-a] is same as [\\-a])
* This function never sees a trailing \.
* [] always fails
* [!] always succeeds
*/
static int
pm_list(const char *start, const char *end, const char c, int flags)
{
const char *p = start;
char rangeStart = '\0', nextRangeStart;
int match = 1, nomatch = 0;
/* This will be used soon... */
(void)flags; /* UNUSED */
/* If this is a negated class, return success for nomatch. */
if ((*p == '!' || *p == '^') && p < end) {
match = 0;
nomatch = 1;
++p;
}
while (p < end) {
nextRangeStart = '\0';
switch (*p) {
case '-':
/* Trailing or initial '-' is not special. */
if ((rangeStart == '\0') || (p == end - 1)) {
if (*p == c)
return (match);
} else {
char rangeEnd = *++p;
if (rangeEnd == '\\')
rangeEnd = *++p;
if ((rangeStart <= c) && (c <= rangeEnd))
return (match);
}
break;
case '\\':
++p;
/* Fall through */
default:
if (*p == c)
return (match);
nextRangeStart = *p; /* Possible start of range. */
}
rangeStart = nextRangeStart;
++p;
}
return (nomatch);
}
static int
pm_list_w(const wchar_t *start, const wchar_t *end, const wchar_t c, int flags)
{
const wchar_t *p = start;
wchar_t rangeStart = L'\0', nextRangeStart;
int match = 1, nomatch = 0;
/* This will be used soon... */
(void)flags; /* UNUSED */
/* If this is a negated class, return success for nomatch. */
if ((*p == L'!' || *p == L'^') && p < end) {
match = 0;
nomatch = 1;
++p;
}
while (p < end) {
nextRangeStart = L'\0';
switch (*p) {
case L'-':
/* Trailing or initial '-' is not special. */
if ((rangeStart == L'\0') || (p == end - 1)) {
if (*p == c)
return (match);
} else {
wchar_t rangeEnd = *++p;
if (rangeEnd == L'\\')
rangeEnd = *++p;
if ((rangeStart <= c) && (c <= rangeEnd))
return (match);
}
break;
case L'\\':
++p;
/* Fall through */
default:
if (*p == c)
return (match);
nextRangeStart = *p; /* Possible start of range. */
}
rangeStart = nextRangeStart;
++p;
}
return (nomatch);
}
/*
* If s is pointing to "./", ".//", "./././" or the like, skip it.
*/
static const char *
pm_slashskip(const char *s) {
while ((*s == '/')
|| (s[0] == '.' && s[1] == '/')
|| (s[0] == '.' && s[1] == '\0'))
++s;
return (s);
}
static const wchar_t *
pm_slashskip_w(const wchar_t *s) {
while ((*s == L'/')
|| (s[0] == L'.' && s[1] == L'/')
|| (s[0] == L'.' && s[1] == L'\0'))
++s;
return (s);
}
static int
pm(const char *p, const char *s, int flags)
{
const char *end;
/*
* Ignore leading './', './/', '././', etc.
*/
if (s[0] == '.' && s[1] == '/')
s = pm_slashskip(s + 1);
if (p[0] == '.' && p[1] == '/')
p = pm_slashskip(p + 1);
for (;;) {
switch (*p) {
case '\0':
if (s[0] == '/') {
if (flags & PATHMATCH_NO_ANCHOR_END)
return (1);
/* "dir" == "dir/" == "dir/." */
s = pm_slashskip(s);
}
return (*s == '\0');
case '?':
/* ? always succeeds, unless we hit end of 's' */
if (*s == '\0')
return (0);
break;
case '*':
/* "*" == "**" == "***" ... */
while (*p == '*')
++p;
/* Trailing '*' always succeeds. */
if (*p == '\0')
return (1);
while (*s) {
if (archive_pathmatch(p, s, flags))
return (1);
++s;
}
return (0);
case '[':
/*
* Find the end of the [...] character class,
* ignoring \] that might occur within the class.
*/
end = p + 1;
while (*end != '\0' && *end != ']') {
if (*end == '\\' && end[1] != '\0')
++end;
++end;
}
if (*end == ']') {
/* We found [...], try to match it. */
if (!pm_list(p + 1, end, *s, flags))
return (0);
p = end; /* Jump to trailing ']' char. */
break;
} else
/* No final ']', so just match '['. */
if (*p != *s)
return (0);
break;
case '\\':
/* Trailing '\\' matches itself. */
if (p[1] == '\0') {
if (*s != '\\')
return (0);
} else {
++p;
if (*p != *s)
return (0);
}
break;
case '/':
if (*s != '/' && *s != '\0')
return (0);
/* Note: pattern "/\./" won't match "/";
* pm_slashskip() correctly stops at backslash. */
p = pm_slashskip(p);
s = pm_slashskip(s);
if (*p == '\0' && (flags & PATHMATCH_NO_ANCHOR_END))
return (1);
--p; /* Counteract the increment below. */
--s;
break;
case '$':
/* '$' is special only at end of pattern and only
* if PATHMATCH_NO_ANCHOR_END is specified. */
if (p[1] == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)){
/* "dir" == "dir/" == "dir/." */
return (*pm_slashskip(s) == '\0');
}
/* Otherwise, '$' is not special. */
/* FALL THROUGH */
default:
if (*p != *s)
return (0);
break;
}
++p;
++s;
}
}
static int
pm_w(const wchar_t *p, const wchar_t *s, int flags)
{
const wchar_t *end;
/*
* Ignore leading './', './/', '././', etc.
*/
if (s[0] == L'.' && s[1] == L'/')
s = pm_slashskip_w(s + 1);
if (p[0] == L'.' && p[1] == L'/')
p = pm_slashskip_w(p + 1);
for (;;) {
switch (*p) {
case L'\0':
if (s[0] == L'/') {
if (flags & PATHMATCH_NO_ANCHOR_END)
return (1);
/* "dir" == "dir/" == "dir/." */
s = pm_slashskip_w(s);
}
return (*s == L'\0');
case L'?':
/* ? always succeeds, unless we hit end of 's' */
if (*s == L'\0')
return (0);
break;
case L'*':
/* "*" == "**" == "***" ... */
while (*p == L'*')
++p;
/* Trailing '*' always succeeds. */
if (*p == L'\0')
return (1);
while (*s) {
if (archive_pathmatch_w(p, s, flags))
return (1);
++s;
}
return (0);
case L'[':
/*
* Find the end of the [...] character class,
* ignoring \] that might occur within the class.
*/
end = p + 1;
while (*end != L'\0' && *end != L']') {
if (*end == L'\\' && end[1] != L'\0')
++end;
++end;
}
if (*end == L']') {
/* We found [...], try to match it. */
if (!pm_list_w(p + 1, end, *s, flags))
return (0);
p = end; /* Jump to trailing ']' char. */
break;
} else
/* No final ']', so just match '['. */
if (*p != *s)
return (0);
break;
case L'\\':
/* Trailing '\\' matches itself. */
if (p[1] == L'\0') {
if (*s != L'\\')
return (0);
} else {
++p;
if (*p != *s)
return (0);
}
break;
case L'/':
if (*s != L'/' && *s != L'\0')
return (0);
/* Note: pattern "/\./" won't match "/";
* pm_slashskip() correctly stops at backslash. */
p = pm_slashskip_w(p);
s = pm_slashskip_w(s);
if (*p == L'\0' && (flags & PATHMATCH_NO_ANCHOR_END))
return (1);
--p; /* Counteract the increment below. */
--s;
break;
case L'$':
/* '$' is special only at end of pattern and only
* if PATHMATCH_NO_ANCHOR_END is specified. */
if (p[1] == L'\0' && (flags & PATHMATCH_NO_ANCHOR_END)){
/* "dir" == "dir/" == "dir/." */
return (*pm_slashskip_w(s) == L'\0');
}
/* Otherwise, '$' is not special. */
/* FALL THROUGH */
default:
if (*p != *s)
return (0);
break;
}
++p;
++s;
}
}
/* Main entry point. */
int
__archive_pathmatch(const char *p, const char *s, int flags)
{
/* Empty pattern only matches the empty string. */
if (p == NULL || *p == '\0')
return (s == NULL || *s == '\0');
/* Leading '^' anchors the start of the pattern. */
if (*p == '^') {
++p;
flags &= ~PATHMATCH_NO_ANCHOR_START;
}
if (*p == '/' && *s != '/')
return (0);
/* Certain patterns and file names anchor implicitly. */
if (*p == '*' || *p == '/' || *p == '/') {
while (*p == '/')
++p;
while (*s == '/')
++s;
return (pm(p, s, flags));
}
/* If start is unanchored, try to match start of each path element. */
if (flags & PATHMATCH_NO_ANCHOR_START) {
for ( ; s != NULL; s = strchr(s, '/')) {
if (*s == '/')
s++;
if (pm(p, s, flags))
return (1);
}
return (0);
}
/* Default: Match from beginning. */
return (pm(p, s, flags));
}
int
__archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags)
{
/* Empty pattern only matches the empty string. */
if (p == NULL || *p == L'\0')
return (s == NULL || *s == L'\0');
/* Leading '^' anchors the start of the pattern. */
if (*p == L'^') {
++p;
flags &= ~PATHMATCH_NO_ANCHOR_START;
}
if (*p == L'/' && *s != L'/')
return (0);
/* Certain patterns and file names anchor implicitly. */
if (*p == L'*' || *p == L'/' || *p == L'/') {
while (*p == L'/')
++p;
while (*s == L'/')
++s;
return (pm_w(p, s, flags));
}
/* If start is unanchored, try to match start of each path element. */
if (flags & PATHMATCH_NO_ANCHOR_START) {
for ( ; s != NULL; s = wcschr(s, L'/')) {
if (*s == L'/')
s++;
if (pm_w(p, s, flags))
return (1);
}
return (0);
}
/* Default: Match from beginning. */
return (pm_w(p, s, flags));
}

View File

@ -0,0 +1,52 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __LIBARCHIVE_BUILD
#ifndef __LIBARCHIVE_TEST
#error This header is only to be used internally to libarchive.
#endif
#endif
#ifndef ARCHIVE_PATHMATCH_H
#define ARCHIVE_PATHMATCH_H
/* Don't anchor at beginning unless the pattern starts with "^" */
#define PATHMATCH_NO_ANCHOR_START 1
/* Don't anchor at end unless the pattern ends with "$" */
#define PATHMATCH_NO_ANCHOR_END 2
/* Note that "^" and "$" are not special unless you set the corresponding
* flag above. */
int __archive_pathmatch(const char *p, const char *s, int flags);
int __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags);
#define archive_pathmatch(p, s, f) __archive_pathmatch(p, s, f)
#define archive_pathmatch_w(p, s, f) __archive_pathmatch_w(p, s, f)
#endif

View File

@ -415,7 +415,7 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
}
do
while (numPs != 0)
{
/* Create Child */
CTX_PTR c1; /* = AllocContext(p); */
@ -435,7 +435,6 @@ static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
SetSuccessor(ps[--numPs], REF(c1));
c = c1;
}
while (numPs != 0);
return c;
}
@ -778,7 +777,7 @@ static void Range_Normalize(CPpmd7z_RangeDec *p)
if(p->Range >= p->Bottom)
break;
else
p->Range = -p->Low & (p->Bottom - 1);
p->Range = ((uint32_t)(-(int32_t)p->Low)) & (p->Bottom - 1);
}
p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
p->Range <<= 8;
@ -991,7 +990,7 @@ static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
p->Cache = (Byte)((UInt32)p->Low >> 24);
}
p->CacheSize++;
p->Low = (UInt32)p->Low << 8;
p->Low = ((UInt32)p->Low << 8) & 0xFFFFFFFF;
}
static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)

View File

@ -152,7 +152,7 @@ typedef
CPpmd_Byte_Ref;
#define PPMD_SetAllBitsIn256Bytes(p) \
{ unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \
p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}
{ unsigned j; for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \
p[j+7] = p[j+6] = p[j+5] = p[j+4] = p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; }}
#endif

View File

@ -50,6 +50,7 @@
#define ARCHIVE_READ_MAGIC (0xdeb0c5U)
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
#define ARCHIVE_READ_DISK_MAGIC (0xbadb0c5U)
#define ARCHIVE_MATCH_MAGIC (0xcad11c9U)
#define ARCHIVE_STATE_NEW 1U
#define ARCHIVE_STATE_HEADER 2U
@ -133,6 +134,7 @@ int __archive_check_magic(struct archive *, unsigned int magic,
void __archive_errx(int retvalue, const char *msg) __LA_DEAD;
void __archive_ensure_cloexec_flag(int fd);
int __archive_mktemp(const char *tmpdir);
int __archive_clean(struct archive *);

View File

@ -96,7 +96,7 @@ __archive_rb_tree_init(struct archive_rb_tree *rbt,
const struct archive_rb_tree_ops *ops)
{
rbt->rbt_ops = ops;
*((const struct archive_rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE;
*((struct archive_rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE;
}
struct archive_rb_node *
@ -237,6 +237,8 @@ __archive_rb_tree_reparent_nodes(
struct archive_rb_node * const new_father = old_child;
struct archive_rb_node * const new_child = old_father;
if (new_father == NULL)
return;
/*
* Exchange descendant linkages.
*/
@ -377,13 +379,13 @@ __archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt,
if (standin_father == self) {
/*
* As a child of self, any childen would be opposite of
* As a child of self, any children would be opposite of
* our parent.
*/
standin_son = standin->rb_nodes[standin_which];
} else {
/*
* Since we aren't a child of self, any childen would be
* Since we aren't a child of self, any children would be
* on the same side as our parent.
*/
standin_son = standin->rb_nodes[standin_other];
@ -410,7 +412,7 @@ __archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt,
/*
* If we are about to delete the standin's father, then when
* we call rebalance, we need to use ourselves as our father.
* Otherwise remember our original father. Also, sincef we are
* Otherwise remember our original father. Also, since we are
* our standin's father we only need to reparent the standin's
* brother.
*
@ -466,7 +468,7 @@ __archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt,
* __archive_rb_tree_node_swap(rbt, self, which);
* __archive_rb_tree_prune_node(rbt, self, F);
*
* But it's more efficient to just evalate and recolor the child.
* But it's more efficient to just evaluate and recolor the child.
*/
static void
__archive_rb_tree_prune_blackred_branch(
@ -505,7 +507,7 @@ __archive_rb_tree_remove_node(struct archive_rb_tree *rbt,
* red-black tree. So if we must remove a node, attempt to rearrange
* the tree so we can remove a red node.
*
* The simpliest case is a childless red node or a childless root node:
* The simplest case is a childless red node or a childless root node:
*
* | T --> T | or | R --> * |
* | s --> * |
@ -517,7 +519,7 @@ __archive_rb_tree_remove_node(struct archive_rb_tree *rbt,
}
if (!RB_TWOCHILDREN_P(self)) {
/*
* The next simpliest case is the node we are deleting is
* The next simplest case is the node we are deleting is
* black and has one red child.
*
* | T --> T --> T |
@ -552,6 +554,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
unsigned int other = which ^ RB_DIR_OTHER;
struct archive_rb_node *brother = parent->rb_nodes[other];
if (brother == NULL)
return;/* The tree may be broken. */
/*
* For cases 1, 2a, and 2b, our brother's children must
* be black and our father must be black
@ -573,6 +577,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
*/
__archive_rb_tree_reparent_nodes(parent, other);
brother = parent->rb_nodes[other];
if (brother == NULL)
return;/* The tree may be broken. */
} else {
/*
* Both our parent and brother are black.
@ -656,6 +662,8 @@ __archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
* If we had two red nephews, then after the swap,
* our former father would have a red grandson.
*/
if (brother->rb_nodes[other] == NULL)
return;/* The tree may be broken. */
RB_MARK_BLACK(brother->rb_nodes[other]);
__archive_rb_tree_reparent_nodes(parent, other);
break; /* We're done! */
@ -683,7 +691,7 @@ __archive_rb_tree_iterate(struct archive_rb_tree *rbt,
*/
if (RB_SENTINEL_P(self->rb_nodes[direction])) {
while (!RB_ROOT_P(rbt, self)) {
if (other == RB_POSITION(self))
if (other == (unsigned int)RB_POSITION(self))
return RB_FATHER(self);
self = RB_FATHER(self);
}

View File

@ -22,14 +22,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
.\" $FreeBSD$
.\"
.Dd March 23, 2011
.Dd February 2, 2012
.Dt ARCHIVE_READ 3
.Os
.Sh NAME
.Nm archive_read
.Nd functions for reading streaming archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Sh DESCRIPTION

View File

@ -57,8 +57,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:2
static int choose_filters(struct archive_read *);
static int choose_format(struct archive_read *);
static void free_filters(struct archive_read *);
static int close_filters(struct archive_read *);
static struct archive_vtable *archive_read_vtable(void);
static int64_t _archive_filter_bytes(struct archive *, int);
static int _archive_filter_code(struct archive *, int);
@ -194,14 +192,13 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
int64_t get, ask = request;
if (ask > skip_limit)
ask = skip_limit;
get = (self->archive->client.skipper)(&self->archive->archive,
self->data, ask);
get = (self->archive->client.skipper)
(&self->archive->archive, self->data, ask);
if (get == 0)
return (total);
request -= get;
total += get;
}
return total;
} else if (self->archive->client.seeker != NULL
&& request > 64 * 1024) {
/* If the client provided a seeker but not a skipper,
@ -216,8 +213,8 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
* only do this for skips of over 64k.
*/
int64_t before = self->position;
int64_t after = (self->archive->client.seeker)(&self->archive->archive,
self->data, request, SEEK_CUR);
int64_t after = (self->archive->client.seeker)
(&self->archive->archive, self->data, request, SEEK_CUR);
if (after != before + request)
return ARCHIVE_FATAL;
return after - before;
@ -242,12 +239,62 @@ client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence)
static int
client_close_proxy(struct archive_read_filter *self)
{
int r = ARCHIVE_OK;
int r = ARCHIVE_OK, r2;
unsigned int i;
if (self->archive->client.closer != NULL)
r = (self->archive->client.closer)((struct archive *)self->archive,
self->data);
if (self->archive->client.closer == NULL)
return (r);
for (i = 0; i < self->archive->client.nodes; i++)
{
r2 = (self->archive->client.closer)
((struct archive *)self->archive,
self->archive->client.dataset[i].data);
if (r > r2)
r = r2;
}
return (r);
}
static int
client_open_proxy(struct archive_read_filter *self)
{
int r = ARCHIVE_OK;
if (self->archive->client.opener != NULL)
r = (self->archive->client.opener)(
(struct archive *)self->archive, self->data);
return (r);
}
static int
client_switch_proxy(struct archive_read_filter *self, unsigned int iindex)
{
int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK;
void *data2 = NULL;
/* Don't do anything if already in the specified data node */
if (self->archive->client.cursor == iindex)
return (ARCHIVE_OK);
self->archive->client.cursor = iindex;
data2 = self->archive->client.dataset[self->archive->client.cursor].data;
if (self->archive->client.switcher != NULL)
{
r1 = r2 = (self->archive->client.switcher)
((struct archive *)self->archive, self->data, data2);
self->data = data2;
}
else
{
/* Attempt to call close and open instead */
if (self->archive->client.closer != NULL)
r1 = (self->archive->client.closer)
((struct archive *)self->archive, self->data);
self->data = data2;
if (self->archive->client.opener != NULL)
r2 = (self->archive->client.opener)
((struct archive *)self->archive, self->data);
}
return (r1 < r2) ? r1 : r2;
}
int
@ -306,21 +353,109 @@ archive_read_set_close_callback(struct archive *_a,
}
int
archive_read_set_callback_data(struct archive *_a, void *client_data)
archive_read_set_switch_callback(struct archive *_a,
archive_switch_callback *client_switcher)
{
struct archive_read *a = (struct archive_read *)_a;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
"archive_read_set_callback_data");
a->client.data = client_data;
"archive_read_set_switch_callback");
a->client.switcher = client_switcher;
return ARCHIVE_OK;
}
int
archive_read_set_callback_data(struct archive *_a, void *client_data)
{
return archive_read_set_callback_data2(_a, client_data, 0);
}
int
archive_read_set_callback_data2(struct archive *_a, void *client_data,
unsigned int iindex)
{
struct archive_read *a = (struct archive_read *)_a;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
"archive_read_set_callback_data2");
if (a->client.nodes == 0)
{
a->client.dataset = (struct archive_read_data_node *)
calloc(1, sizeof(*a->client.dataset));
if (a->client.dataset == NULL)
{
archive_set_error(&a->archive, ENOMEM,
"No memory.");
return ARCHIVE_FATAL;
}
a->client.nodes = 1;
}
if (iindex > a->client.nodes - 1)
{
archive_set_error(&a->archive, EINVAL,
"Invalid index specified.");
return ARCHIVE_FATAL;
}
a->client.dataset[iindex].data = client_data;
a->client.dataset[iindex].begin_position = -1;
a->client.dataset[iindex].total_size = -1;
return ARCHIVE_OK;
}
int
archive_read_add_callback_data(struct archive *_a, void *client_data,
unsigned int iindex)
{
struct archive_read *a = (struct archive_read *)_a;
void *p;
unsigned int i;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
"archive_read_add_callback_data");
if (iindex > a->client.nodes) {
archive_set_error(&a->archive, EINVAL,
"Invalid index specified.");
return ARCHIVE_FATAL;
}
p = realloc(a->client.dataset, sizeof(*a->client.dataset)
* (++(a->client.nodes)));
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"No memory.");
return ARCHIVE_FATAL;
}
a->client.dataset = (struct archive_read_data_node *)p;
for (i = a->client.nodes - 1; i > iindex && i > 0; i--) {
a->client.dataset[i].data = a->client.dataset[i-1].data;
a->client.dataset[i].begin_position = -1;
a->client.dataset[i].total_size = -1;
}
a->client.dataset[iindex].data = client_data;
a->client.dataset[iindex].begin_position = -1;
a->client.dataset[iindex].total_size = -1;
return ARCHIVE_OK;
}
int
archive_read_append_callback_data(struct archive *_a, void *client_data)
{
struct archive_read *a = (struct archive_read *)_a;
return archive_read_add_callback_data(_a, client_data, a->client.nodes);
}
int
archive_read_prepend_callback_data(struct archive *_a, void *client_data)
{
return archive_read_add_callback_data(_a, client_data, 0);
}
int
archive_read_open1(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter *filter;
struct archive_read_filter *filter, *tmp;
int slot, e;
unsigned int i;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
"archive_read_open");
@ -335,11 +470,14 @@ archive_read_open1(struct archive *_a)
/* Open data source. */
if (a->client.opener != NULL) {
e =(a->client.opener)(&a->archive, a->client.data);
e = (a->client.opener)(&a->archive, a->client.dataset[0].data);
if (e != 0) {
/* If the open failed, call the closer to clean up. */
if (a->client.closer)
(a->client.closer)(&a->archive, a->client.data);
if (a->client.closer) {
for (i = 0; i < a->client.nodes; i++)
(a->client.closer)(&a->archive,
a->client.dataset[i].data);
}
return (e);
}
}
@ -350,31 +488,51 @@ archive_read_open1(struct archive *_a)
filter->bidder = NULL;
filter->upstream = NULL;
filter->archive = a;
filter->data = a->client.data;
filter->data = a->client.dataset[0].data;
filter->open = client_open_proxy;
filter->read = client_read_proxy;
filter->skip = client_skip_proxy;
filter->seek = client_seek_proxy;
filter->close = client_close_proxy;
filter->sswitch = client_switch_proxy;
filter->name = "none";
filter->code = ARCHIVE_COMPRESSION_NONE;
a->filter = filter;
filter->code = ARCHIVE_FILTER_NONE;
a->client.dataset[0].begin_position = 0;
if (!a->filter || !a->bypass_filter_bidding)
{
a->filter = filter;
/* Build out the input pipeline. */
e = choose_filters(a);
if (e < ARCHIVE_WARN) {
a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
}
}
else
{
/* Need to add "NONE" type filter at the end of the filter chain */
tmp = a->filter;
while (tmp->upstream)
tmp = tmp->upstream;
tmp->upstream = filter;
}
if (!a->format)
{
slot = choose_format(a);
if (slot < 0) {
close_filters(a);
__archive_read_close_filters(a);
a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
}
a->format = &(a->formats[slot]);
}
a->archive.state = ARCHIVE_STATE_HEADER;
/* Ensure libarchive starts from the first node in a multivolume set */
client_switch_proxy(a->filter, 0);
return (e);
}
@ -414,8 +572,8 @@ choose_filters(struct archive_read *a)
/* Verify the filter by asking it for some data. */
__archive_read_filter_ahead(a->filter, 1, &avail);
if (avail < 0) {
close_filters(a);
free_filters(a);
__archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
a->archive.compression_name = a->filter->name;
@ -433,8 +591,8 @@ choose_filters(struct archive_read *a)
a->filter = filter;
r = (best_bidder->init)(a->filter);
if (r != ARCHIVE_OK) {
close_filters(a);
free_filters(a);
__archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
}
@ -502,6 +660,9 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
a->read_data_output_offset = 0;
a->read_data_remaining = 0;
a->read_data_is_posix_read = 0;
a->read_data_requested = 0;
a->data_start_node = a->client.cursor;
/* EOF always wins; otherwise return the worst error. */
return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1;
}
@ -612,6 +773,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
while (s > 0) {
if (a->read_data_remaining == 0) {
read_buf = a->read_data_block;
a->read_data_is_posix_read = 1;
a->read_data_requested = s;
r = _archive_read_data_block(&a->archive, &read_buf,
&a->read_data_remaining, &a->read_data_offset);
a->read_data_block = read_buf;
@ -633,13 +796,13 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
}
/* Compute the amount of zero padding needed. */
if (a->read_data_output_offset + s <
if (a->read_data_output_offset + (int64_t)s <
a->read_data_offset) {
len = s;
} else if (a->read_data_output_offset <
a->read_data_offset) {
len = a->read_data_offset -
a->read_data_output_offset;
len = (size_t)(a->read_data_offset -
a->read_data_output_offset);
} else
len = 0;
@ -665,6 +828,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
bytes_read += len;
}
}
a->read_data_is_posix_read = 0;
a->read_data_requested = 0;
return (bytes_read);
}
@ -699,6 +864,23 @@ archive_read_data_skip(struct archive *_a)
return (r);
}
int64_t
archive_seek_data(struct archive *_a, int64_t offset, int whence)
{
struct archive_read *a = (struct archive_read *)_a;
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
"archive_seek_data_block");
if (a->format->seek_data == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Internal error: "
"No format_seek_data_block function registered");
return (ARCHIVE_FATAL);
}
return (a->format->seek_data)(a, offset, whence);
}
/*
* Read the next block of entry data from the archive.
* This is a zero-copy interface; the client receives a pointer,
@ -725,8 +907,8 @@ _archive_read_data_block(struct archive *_a,
return (a->format->read_data)(a, buff, size, offset);
}
static int
close_filters(struct archive_read *a)
int
__archive_read_close_filters(struct archive_read *a)
{
struct archive_read_filter *f = a->filter;
int r = ARCHIVE_OK;
@ -746,8 +928,8 @@ close_filters(struct archive_read *a)
return r;
}
static void
free_filters(struct archive_read *a)
void
__archive_read_free_filters(struct archive_read *a)
{
while (a->filter != NULL) {
struct archive_read_filter *t = a->filter->upstream;
@ -791,7 +973,7 @@ _archive_read_close(struct archive *_a)
/* TODO: Clean up the formatters. */
/* Release the filter objects. */
r1 = close_filters(a);
r1 = __archive_read_close_filters(a);
if (r1 < r)
r = r1;
@ -830,7 +1012,7 @@ _archive_read_free(struct archive *_a)
}
/* Free the filters */
free_filters(a);
__archive_read_free_filters(a);
/* Release the bidder objects. */
n = sizeof(a->bidders)/sizeof(a->bidders[0]);
@ -847,6 +1029,7 @@ _archive_read_free(struct archive *_a)
archive_entry_free(a->entry);
a->archive.magic = 0;
__archive_clean(&a->archive);
free(a->client.dataset);
free(a);
return (r);
}
@ -856,7 +1039,8 @@ get_filter(struct archive *_a, int n)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter *f = a->filter;
/* We use n == -1 for 'the last filter', which is always the client proxy. */
/* We use n == -1 for 'the last filter', which is always the
* client proxy. */
if (n == -1 && f != NULL) {
struct archive_read_filter *last = f;
f = f->upstream;
@ -909,6 +1093,7 @@ __archive_read_register_format(struct archive_read *a,
int (*read_header)(struct archive_read *, struct archive_entry *),
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *),
int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *))
{
int i, number_slots;
@ -928,6 +1113,7 @@ __archive_read_register_format(struct archive_read *a,
a->formats[i].read_header = read_header;
a->formats[i].read_data = read_data;
a->formats[i].read_data_skip = read_data_skip;
a->formats[i].seek_data = seek_data;
a->formats[i].cleanup = cleanup;
a->formats[i].data = format_data;
a->formats[i].name = name;
@ -1074,7 +1260,8 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
if (filter->next > filter->buffer &&
filter->next + min > filter->buffer + filter->buffer_size) {
if (filter->avail > 0)
memmove(filter->buffer, filter->next, filter->avail);
memmove(filter->buffer, filter->next,
filter->avail);
filter->next = filter->buffer;
}
@ -1089,15 +1276,26 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
&filter->client_buff);
if (bytes_read < 0) { /* Read error. */
filter->client_total = filter->client_avail = 0;
filter->client_next = filter->client_buff = NULL;
filter->client_next =
filter->client_buff = NULL;
filter->fatal = 1;
if (avail != NULL)
*avail = ARCHIVE_FATAL;
return (NULL);
}
if (bytes_read == 0) { /* Premature end-of-file. */
if (bytes_read == 0) {
/* Check for another client object first */
if (filter->archive->client.cursor !=
filter->archive->client.nodes - 1) {
if (client_switch_proxy(filter,
filter->archive->client.cursor + 1)
== ARCHIVE_OK)
continue;
}
/* Premature end-of-file. */
filter->client_total = filter->client_avail = 0;
filter->client_next = filter->client_buff = NULL;
filter->client_next =
filter->client_buff = NULL;
filter->end_of_file = 1;
/* Return whatever we do have. */
if (avail != NULL)
@ -1107,9 +1305,7 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
filter->client_total = bytes_read;
filter->client_avail = filter->client_total;
filter->client_next = filter->client_buff;
}
else
{
} else {
/*
* We can't satisfy the request from the copy
* buffer or the existing client data, so we
@ -1132,7 +1328,8 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
archive_set_error(
&filter->archive->archive,
ENOMEM,
"Unable to allocate copy buffer");
"Unable to allocate copy"
" buffer");
filter->fatal = 1;
if (avail != NULL)
*avail = ARCHIVE_FATAL;
@ -1171,8 +1368,8 @@ __archive_read_filter_ahead(struct archive_read_filter *filter,
if (tocopy > filter->client_avail)
tocopy = filter->client_avail;
memcpy(filter->next + filter->avail, filter->client_next,
tocopy);
memcpy(filter->next + filter->avail,
filter->client_next, tocopy);
/* Remove this data from client buffer. */
filter->client_next += tocopy;
filter->client_avail -= tocopy;
@ -1231,7 +1428,7 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
/* Use up the copy buffer first. */
if (filter->avail > 0) {
min = minimum(request, (int64_t)filter->avail);
min = (size_t)minimum(request, (int64_t)filter->avail);
filter->next += min;
filter->avail -= min;
request -= min;
@ -1241,7 +1438,7 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
/* Then use up the client buffer. */
if (filter->client_avail > 0) {
min = minimum(request, (int64_t)filter->client_avail);
min = (size_t)minimum(request, (int64_t)filter->client_avail);
filter->client_next += min;
filter->client_avail -= min;
request -= min;
@ -1275,6 +1472,13 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
}
if (bytes_read == 0) {
if (filter->archive->client.cursor !=
filter->archive->client.nodes - 1) {
if (client_switch_proxy(filter,
filter->archive->client.cursor + 1)
== ARCHIVE_OK)
continue;
}
filter->client_buff = NULL;
filter->end_of_file = 1;
return (total_bytes_skipped);
@ -1283,7 +1487,7 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request)
if (bytes_read >= request) {
filter->client_next =
((const char *)filter->client_buff) + request;
filter->client_avail = bytes_read - request;
filter->client_avail = (size_t)(bytes_read - request);
filter->client_total = bytes_read;
total_bytes_skipped += request;
filter->position += request;
@ -1306,15 +1510,109 @@ __archive_read_seek(struct archive_read *a, int64_t offset, int whence)
}
int64_t
__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset, int whence)
__archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
int whence)
{
struct archive_read_client *client;
int64_t r;
unsigned int cursor;
if (filter->closed || filter->fatal)
return (ARCHIVE_FATAL);
if (filter->seek == NULL)
return (ARCHIVE_FAILED);
r = filter->seek(filter, offset, whence);
client = &(filter->archive->client);
switch (whence) {
case SEEK_CUR:
/* Adjust the offset and use SEEK_SET instead */
offset += filter->position;
case SEEK_SET:
cursor = 0;
while (1)
{
if (client->dataset[cursor].begin_position < 0 ||
client->dataset[cursor].total_size < 0 ||
client->dataset[cursor].begin_position +
client->dataset[cursor].total_size - 1 > offset ||
cursor + 1 >= client->nodes)
break;
r = client->dataset[cursor].begin_position +
client->dataset[cursor].total_size;
client->dataset[++cursor].begin_position = r;
}
while (1) {
r = client_switch_proxy(filter, cursor);
if (r != ARCHIVE_OK)
return r;
if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
return r;
client->dataset[cursor].total_size = r;
if (client->dataset[cursor].begin_position +
client->dataset[cursor].total_size - 1 > offset ||
cursor + 1 >= client->nodes)
break;
r = client->dataset[cursor].begin_position +
client->dataset[cursor].total_size;
client->dataset[++cursor].begin_position = r;
}
offset -= client->dataset[cursor].begin_position;
if (offset < 0)
offset = 0;
else if (offset > client->dataset[cursor].total_size - 1)
offset = client->dataset[cursor].total_size - 1;
if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0)
return r;
break;
case SEEK_END:
cursor = 0;
while (1) {
if (client->dataset[cursor].begin_position < 0 ||
client->dataset[cursor].total_size < 0 ||
cursor + 1 >= client->nodes)
break;
r = client->dataset[cursor].begin_position +
client->dataset[cursor].total_size;
client->dataset[++cursor].begin_position = r;
}
while (1) {
r = client_switch_proxy(filter, cursor);
if (r != ARCHIVE_OK)
return r;
if ((r = client_seek_proxy(filter, 0, SEEK_END)) < 0)
return r;
client->dataset[cursor].total_size = r;
r = client->dataset[cursor].begin_position +
client->dataset[cursor].total_size;
if (cursor + 1 >= client->nodes)
break;
client->dataset[++cursor].begin_position = r;
}
while (1) {
if (r + offset >=
client->dataset[cursor].begin_position)
break;
offset += client->dataset[cursor].total_size;
if (cursor == 0)
break;
cursor--;
r = client->dataset[cursor].begin_position +
client->dataset[cursor].total_size;
}
offset = (r + offset) - client->dataset[cursor].begin_position;
if ((r = client_switch_proxy(filter, cursor)) != ARCHIVE_OK)
return r;
r = client_seek_proxy(filter, offset, SEEK_SET);
if (r < ARCHIVE_OK)
return r;
break;
default:
return (ARCHIVE_FATAL);
}
r += client->dataset[cursor].begin_position;
if (r >= 0) {
/*
* Ouch. Clearing the buffer like this hurts, especially

View File

@ -0,0 +1,198 @@
/*-
* Copyright (c) 2003-2012 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include "archive.h"
#include "archive_private.h"
#include "archive_read_private.h"
int
archive_read_append_filter(struct archive *_a, int code)
{
int r1, r2, number_bidders, i;
char str[20];
struct archive_read_filter_bidder *bidder;
struct archive_read_filter *filter;
struct archive_read *a = (struct archive_read *)_a;
r1 = r2 = (ARCHIVE_OK);
switch (code)
{
case ARCHIVE_FILTER_NONE:
/* No filter to add, so do nothing.
* NOTE: An initial "NONE" type filter is always set at the end of the
* filter chain.
*/
r1 = (ARCHIVE_OK);
break;
case ARCHIVE_FILTER_GZIP:
strcpy(str, "gzip");
r1 = archive_read_support_filter_gzip(_a);
break;
case ARCHIVE_FILTER_BZIP2:
strcpy(str, "bzip2");
r1 = archive_read_support_filter_bzip2(_a);
break;
case ARCHIVE_FILTER_COMPRESS:
strcpy(str, "compress (.Z)");
r1 = archive_read_support_filter_compress(_a);
break;
case ARCHIVE_FILTER_PROGRAM:
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Cannot append program filter using archive_read_append_filter");
return (ARCHIVE_FATAL);
case ARCHIVE_FILTER_LZMA:
strcpy(str, "lzma");
r1 = archive_read_support_filter_lzma(_a);
break;
case ARCHIVE_FILTER_XZ:
strcpy(str, "xz");
r1 = archive_read_support_filter_xz(_a);
break;
case ARCHIVE_FILTER_UU:
strcpy(str, "uu");
r1 = archive_read_support_filter_uu(_a);
break;
case ARCHIVE_FILTER_RPM:
strcpy(str, "rpm");
r1 = archive_read_support_filter_rpm(_a);
break;
case ARCHIVE_FILTER_LZIP:
strcpy(str, "lzip");
r1 = archive_read_support_filter_lzip(_a);
break;
case ARCHIVE_FILTER_LRZIP:
strcpy(str, "lrzip");
r1 = archive_read_support_filter_lrzip(_a);
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Invalid filter code specified");
return (ARCHIVE_FATAL);
}
if (code != ARCHIVE_FILTER_NONE)
{
number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
bidder = a->bidders;
for (i = 0; i < number_bidders; i++, bidder++)
{
if (!bidder->name || !strcmp(bidder->name, str))
break;
}
if (!bidder->name || strcmp(bidder->name, str))
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Internal error: Unable to append filter");
return (ARCHIVE_FATAL);
}
filter
= (struct archive_read_filter *)calloc(1, sizeof(*filter));
if (filter == NULL)
{
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
filter->bidder = bidder;
filter->archive = a;
filter->upstream = a->filter;
a->filter = filter;
r2 = (bidder->init)(a->filter);
if (r2 != ARCHIVE_OK) {
__archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
}
a->bypass_filter_bidding = 1;
return (r1 < r2) ? r1 : r2;
}
int
archive_read_append_filter_program(struct archive *_a, const char *cmd)
{
return (archive_read_append_filter_program_signature(_a, cmd, NULL, 0));
}
int
archive_read_append_filter_program_signature(struct archive *_a,
const char *cmd, const void *signature, size_t signature_len)
{
int r, number_bidders, i;
struct archive_read_filter_bidder *bidder;
struct archive_read_filter *filter;
struct archive_read *a = (struct archive_read *)_a;
if (archive_read_support_filter_program_signature(_a, cmd, signature,
signature_len) != (ARCHIVE_OK))
return (ARCHIVE_FATAL);
number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
bidder = a->bidders;
for (i = 0; i < number_bidders; i++, bidder++)
{
/* Program bidder name set to filter name after initialization */
if (bidder->data && !bidder->name)
break;
}
if (!bidder->data)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Internal error: Unable to append program filter");
return (ARCHIVE_FATAL);
}
filter
= (struct archive_read_filter *)calloc(1, sizeof(*filter));
if (filter == NULL)
{
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
filter->bidder = bidder;
filter->archive = a;
filter->upstream = a->filter;
a->filter = filter;
r = (bidder->init)(a->filter);
if (r != ARCHIVE_OK) {
__archive_read_close_filters(a);
__archive_read_free_filters(a);
return (ARCHIVE_FATAL);
}
bidder->name = a->filter->name;
a->bypass_filter_bidding = 1;
return r;
}

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 22, 2011
.Dd February 2, 2012
.Dt ARCHIVE_READ_DATA 3
.Os
.Sh NAME
@ -33,6 +33,8 @@
.Nm archive_read_data_skip ,
.Nm archive_read_data_into_fd
.Nd functions for reading streaming archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft ssize_t

View File

@ -64,7 +64,7 @@ pad_to(struct archive *a, int fd, int can_lseek,
}
while (target_offset > actual_offset) {
to_write = nulls_size;
if (target_offset < actual_offset + nulls_size)
if (target_offset < actual_offset + (int64_t)nulls_size)
to_write = (size_t)(target_offset - actual_offset);
bytes_written = write(fd, nulls, to_write);
if (bytes_written < 0) {

View File

@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_read_disk.3 190957 2009-04-12 05:04:02Z kientzle $
.\" $FreeBSD$
.\"
.Dd March 10, 2009
.Dd February 2, 2012
.Dt ARCHIVE_READ_DISK 3
.Os
.Sh NAME
@ -42,6 +42,8 @@
.Nm archive_read_finish ,
.Nm archive_read_free
.Nd functions for reading objects from disk
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft struct archive *

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
* Copyright (c) 2010 Michihiro NAKAJIMA
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -49,8 +49,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_SYS_XATTR_H
#if defined(HAVE_SYS_XATTR_H)
#include <sys/xattr.h>
#elif defined(HAVE_ATTR_XATTR_H)
#include <attr/xattr.h>
#endif
#ifdef HAVE_SYS_EA_H
#include <sys/ea.h>
@ -58,9 +60,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#ifdef HAVE_ACL_LIBACL_H
#include <acl/libacl.h>
#endif
#ifdef HAVE_ATTR_XATTR_H
#include <attr/xattr.h>
#endif
#ifdef HAVE_COPYFILE_H
#include <copyfile.h>
#endif
@ -73,6 +72,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_LINUX_TYPES_H
#include <linux/types.h>
#endif
#ifdef HAVE_LINUX_FIEMAP_H
#include <linux/fiemap.h>
#endif
@ -101,6 +103,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#include "archive_private.h"
#include "archive_read_disk_private.h"
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
/*
* Linux and FreeBSD plug this obvious hole in POSIX.1e in
* different ways.
@ -111,14 +117,14 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010
#define ACL_GET_PERM acl_get_perm_np
#endif
static int setup_acls_posix1e(struct archive_read_disk *,
struct archive_entry *, int fd);
static int setup_acls(struct archive_read_disk *,
struct archive_entry *, int *fd);
static int setup_mac_metadata(struct archive_read_disk *,
struct archive_entry *, int fd);
struct archive_entry *, int *fd);
static int setup_xattrs(struct archive_read_disk *,
struct archive_entry *, int fd);
struct archive_entry *, int *fd);
static int setup_sparse(struct archive_read_disk *,
struct archive_entry *, int fd);
struct archive_entry *, int *fd);
int
archive_read_disk_entry_from_file(struct archive *_a,
@ -187,11 +193,18 @@ archive_read_disk_entry_from_file(struct archive *_a,
* this is an extra step, it has a nice side-effect: We get an
* open file descriptor which we can use in the subsequent lookups. */
if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
if (fd < 0)
fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
if (a->tree != NULL)
fd = a->open_on_current_dir(a->tree, path,
O_RDONLY | O_NONBLOCK | O_CLOEXEC);
else
fd = open(path, O_RDONLY | O_NONBLOCK |
O_CLOEXEC);
__archive_ensure_cloexec_flag(fd);
}
if (fd >= 0) {
unsigned long stflags;
int r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
int stflags;
r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
if (r == 0 && stflags != 0)
archive_entry_set_fflags(entry, stflags, 0);
}
@ -210,12 +223,20 @@ archive_read_disk_entry_from_file(struct archive *_a,
"Couldn't read link data");
return (ARCHIVE_FAILED);
}
if (a->tree != NULL) {
#ifdef HAVE_READLINKAT
if (a->entry_wd_fd >= 0)
lnklen = readlinkat(a->entry_wd_fd, path,
linkbuffer, linkbuffer_len);
else
lnklen = readlinkat(a->tree_current_dir_fd(a->tree),
path, linkbuffer, linkbuffer_len);
#else
if (a->tree_enter_working_dir(a->tree) != 0) {
archive_set_error(&a->archive, errno,
"Couldn't read link data");
free(linkbuffer);
return (ARCHIVE_FAILED);
}
lnklen = readlink(path, linkbuffer, linkbuffer_len);
#endif /* HAVE_READLINKAT */
} else
lnklen = readlink(path, linkbuffer, linkbuffer_len);
if (lnklen < 0) {
archive_set_error(&a->archive, errno,
@ -229,14 +250,16 @@ archive_read_disk_entry_from_file(struct archive *_a,
}
#endif /* HAVE_READLINK || HAVE_READLINKAT */
r = setup_acls_posix1e(a, entry, fd);
r1 = setup_xattrs(a, entry, fd);
r = setup_acls(a, entry, &fd);
r1 = setup_xattrs(a, entry, &fd);
if (r1 < r)
r = r1;
r1 = setup_mac_metadata(a, entry, fd);
if (a->enable_copyfile) {
r1 = setup_mac_metadata(a, entry, &fd);
if (r1 < r)
r = r1;
r1 = setup_sparse(a, entry, fd);
}
r1 = setup_sparse(a, entry, &fd);
if (r1 < r)
r = r1;
@ -262,16 +285,18 @@ archive_read_disk_entry_from_file(struct archive *_a,
*/
static int
setup_mac_metadata(struct archive_read_disk *a,
struct archive_entry *entry, int fd)
struct archive_entry *entry, int *fd)
{
int tempfd = -1;
int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
struct stat copyfile_stat;
int ret = ARCHIVE_OK;
void *buff;
void *buff = NULL;
int have_attrs;
const char *name, *tempdir, *tempfile = NULL;
const char *name, *tempdir;
struct archive_string tempfile;
(void)fd; /* UNUSED */
name = archive_entry_sourcepath(entry);
if (name == NULL)
name = archive_entry_pathname(entry);
@ -281,6 +306,14 @@ setup_mac_metadata(struct archive_read_disk *a,
return (ARCHIVE_WARN);
}
if (a->tree != NULL) {
if (a->tree_enter_working_dir(a->tree) != 0) {
archive_set_error(&a->archive, errno,
"Couldn't change dir");
return (ARCHIVE_FAILED);
}
}
/* Short-circuit if there's nothing to do. */
have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
if (have_attrs == -1) {
@ -296,25 +329,28 @@ setup_mac_metadata(struct archive_read_disk *a,
tempdir = getenv("TMPDIR");
if (tempdir == NULL)
tempdir = _PATH_TMP;
tempfile = tempnam(tempdir, "tar.md.");
archive_string_init(&tempfile);
archive_strcpy(&tempfile, tempdir);
archive_strcat(&tempfile, "tar.md.XXXXXX");
tempfd = mkstemp(tempfile.s);
if (tempfd < 0) {
archive_set_error(&a->archive, errno,
"Could not open extended attribute file");
ret = ARCHIVE_WARN;
goto cleanup;
}
__archive_ensure_cloexec_flag(tempfd);
/* XXX I wish copyfile() could pack directly to a memory
* buffer; that would avoid the temp file here. For that
* matter, it would be nice if fcopyfile() actually worked,
* that would reduce the many open/close races here. */
if (copyfile(name, tempfile, 0, copyfile_flags | COPYFILE_PACK)) {
if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) {
archive_set_error(&a->archive, errno,
"Could not pack extended attributes");
ret = ARCHIVE_WARN;
goto cleanup;
}
tempfd = open(tempfile, O_RDONLY);
if (tempfd < 0) {
archive_set_error(&a->archive, errno,
"Could not open extended attribute file");
ret = ARCHIVE_WARN;
goto cleanup;
}
if (fstat(tempfd, &copyfile_stat)) {
archive_set_error(&a->archive, errno,
"Could not check size of extended attributes");
@ -337,10 +373,12 @@ setup_mac_metadata(struct archive_read_disk *a,
archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
cleanup:
if (tempfd >= 0)
if (tempfd >= 0) {
close(tempfd);
if (tempfile != NULL)
unlink(tempfile);
unlink(tempfile.s);
}
archive_string_free(&tempfile);
free(buff);
return (ret);
}
@ -351,7 +389,7 @@ cleanup:
*/
static int
setup_mac_metadata(struct archive_read_disk *a,
struct archive_entry *entry, int fd)
struct archive_entry *entry, int *fd)
{
(void)a; /* UNUSED */
(void)entry; /* UNUSED */
@ -361,16 +399,19 @@ setup_mac_metadata(struct archive_read_disk *a,
#endif
#ifdef HAVE_POSIX_ACL
static void setup_acl_posix1e(struct archive_read_disk *a,
#if defined(HAVE_POSIX_ACL) && defined(ACL_TYPE_NFS4)
static int translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
static int
setup_acls_posix1e(struct archive_read_disk *a,
struct archive_entry *entry, int fd)
setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
const char *accpath;
acl_t acl;
#if HAVE_ACL_IS_TRIVIAL_NP
int r;
#endif
accpath = archive_entry_sourcepath(entry);
if (accpath == NULL)
@ -378,9 +419,38 @@ setup_acls_posix1e(struct archive_read_disk *a,
archive_entry_acl_clear(entry);
/* Try NFS4 ACL first. */
if (*fd >= 0)
acl = acl_get_fd(*fd);
#if HAVE_ACL_GET_LINK_NP
else if (!a->follow_symlinks)
acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
#else
else if ((!a->follow_symlinks)
&& (archive_entry_filetype(entry) == AE_IFLNK))
/* We can't get the ACL of a symlink, so we assume it can't
have one. */
acl = NULL;
#endif
else
acl = acl_get_file(accpath, ACL_TYPE_NFS4);
#if HAVE_ACL_IS_TRIVIAL_NP
/* Ignore "trivial" ACLs that just mirror the file mode. */
acl_is_trivial_np(acl, &r);
if (r) {
acl_free(acl);
acl = NULL;
}
#endif
if (acl != NULL) {
translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
acl_free(acl);
return (ARCHIVE_OK);
}
/* Retrieve access ACL from file. */
if (fd >= 0)
acl = acl_get_fd(fd);
if (*fd >= 0)
acl = acl_get_fd(*fd);
#if HAVE_ACL_GET_LINK_NP
else if (!a->follow_symlinks)
acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
@ -394,7 +464,7 @@ setup_acls_posix1e(struct archive_read_disk *a,
else
acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
if (acl != NULL) {
setup_acl_posix1e(a, entry, acl,
translate_acl(a, entry, acl,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
acl_free(acl);
}
@ -403,7 +473,7 @@ setup_acls_posix1e(struct archive_read_disk *a,
if (S_ISDIR(archive_entry_mode(entry))) {
acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
if (acl != NULL) {
setup_acl_posix1e(a, entry, acl,
translate_acl(a, entry, acl,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
acl_free(acl);
}
@ -412,69 +482,181 @@ setup_acls_posix1e(struct archive_read_disk *a,
}
/*
* Translate POSIX.1e ACL into libarchive internal structure.
* Translate system ACL into libarchive internal structure.
*/
static void
setup_acl_posix1e(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int archive_entry_acl_type)
static struct {
int archive_perm;
int platform_perm;
} acl_perm_map[] = {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
};
static struct {
int archive_inherit;
int platform_inherit;
} acl_inherit_map[] = {
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
};
static int
translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
{
acl_tag_t acl_tag;
acl_entry_type_t acl_type;
acl_flagset_t acl_flagset;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
int brand, i, r, entry_acl_type;
int s, ae_id, ae_tag, ae_perm;
const char *ae_name;
// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
// Make sure the "brand" on this ACL is consistent
// with the default_entry_acl_type bits provided.
acl_get_brand_np(acl, &brand);
switch (brand) {
case ACL_BRAND_POSIX:
switch (default_entry_acl_type) {
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
break;
default:
// XXX set warning message?
return ARCHIVE_FAILED;
}
break;
case ACL_BRAND_NFS4:
if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
// XXX set warning message?
return ARCHIVE_FAILED;
}
break;
default:
// XXX set warning message?
return ARCHIVE_FAILED;
break;
}
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
while (s == 1) {
ae_id = -1;
ae_name = NULL;
ae_perm = 0;
acl_get_tag_type(acl_entry, &acl_tag);
if (acl_tag == ACL_USER) {
switch (acl_tag) {
case ACL_USER:
ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
ae_name = archive_read_disk_uname(&a->archive, ae_id);
ae_tag = ARCHIVE_ENTRY_ACL_USER;
} else if (acl_tag == ACL_GROUP) {
break;
case ACL_GROUP:
ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
ae_name = archive_read_disk_gname(&a->archive, ae_id);
ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
} else if (acl_tag == ACL_MASK) {
break;
case ACL_MASK:
ae_tag = ARCHIVE_ENTRY_ACL_MASK;
} else if (acl_tag == ACL_USER_OBJ) {
break;
case ACL_USER_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
} else if (acl_tag == ACL_GROUP_OBJ) {
break;
case ACL_GROUP_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
} else if (acl_tag == ACL_OTHER) {
break;
case ACL_OTHER:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
} else {
break;
case ACL_EVERYONE:
ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
break;
default:
/* Skip types that libarchive can't support. */
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
continue;
}
// XXX acl type maps to allow/deny/audit/YYYY bits
// XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
// non-NFSv4 ACLs
entry_acl_type = default_entry_acl_type;
r = acl_get_entry_type_np(acl_entry, &acl_type);
if (r == 0) {
switch (acl_type) {
case ACL_ENTRY_TYPE_ALLOW:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
break;
case ACL_ENTRY_TYPE_DENY:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
break;
case ACL_ENTRY_TYPE_AUDIT:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
break;
case ACL_ENTRY_TYPE_ALARM:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
break;
}
}
/*
* Libarchive stores "flag" (NFSv4 inheritance bits)
* in the ae_perm bitmap.
*/
acl_get_flagset_np(acl_entry, &acl_flagset);
for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
if (acl_get_flag_np(acl_flagset,
acl_inherit_map[i].platform_inherit))
ae_perm |= acl_inherit_map[i].archive_inherit;
}
acl_get_permset(acl_entry, &acl_permset);
ae_perm = 0;
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
/*
* acl_get_perm() is spelled differently on different
* platforms; see above.
*/
if (ACL_GET_PERM(acl_permset, ACL_EXECUTE))
ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
if (ACL_GET_PERM(acl_permset, ACL_READ))
ae_perm |= ARCHIVE_ENTRY_ACL_READ;
if (ACL_GET_PERM(acl_permset, ACL_WRITE))
ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
ae_perm |= acl_perm_map[i].archive_perm;
}
archive_entry_acl_add_entry(entry,
archive_entry_acl_type, ae_perm, ae_tag,
archive_entry_acl_add_entry(entry, entry_acl_type,
ae_perm, ae_tag,
ae_id, ae_name);
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
}
return (ARCHIVE_OK);
}
#else
static int
setup_acls_posix1e(struct archive_read_disk *a,
struct archive_entry *entry, int fd)
setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
(void)a; /* UNUSED */
(void)entry; /* UNUSED */
@ -568,7 +750,7 @@ setup_xattr(struct archive_read_disk *a,
static int
setup_xattrs(struct archive_read_disk *a,
struct archive_entry *entry, int fd)
struct archive_entry *entry, int *fd)
{
char *list, *p;
const char *path;
@ -578,16 +760,30 @@ setup_xattrs(struct archive_read_disk *a,
if (path == NULL)
path = archive_entry_pathname(entry);
if (*fd < 0 && a->tree != NULL) {
if (a->follow_symlinks ||
archive_entry_filetype(entry) != AE_IFLNK)
*fd = a->open_on_current_dir(a->tree, path,
O_RDONLY | O_NONBLOCK);
if (*fd < 0) {
if (a->tree_enter_working_dir(a->tree) != 0) {
archive_set_error(&a->archive, errno,
"Couldn't access %s", path);
return (ARCHIVE_FAILED);
}
}
}
#if HAVE_FLISTXATTR
if (fd >= 0)
list_size = flistxattr(fd, NULL, 0);
if (*fd >= 0)
list_size = flistxattr(*fd, NULL, 0);
else if (!a->follow_symlinks)
list_size = llistxattr(path, NULL, 0);
else
list_size = listxattr(path, NULL, 0);
#elif HAVE_FLISTEA
if (fd >= 0)
list_size = flistea(fd, NULL, 0);
if (*fd >= 0)
list_size = flistea(*fd, NULL, 0);
else if (!a->follow_symlinks)
list_size = llistea(path, NULL, 0);
else
@ -611,15 +807,15 @@ setup_xattrs(struct archive_read_disk *a,
}
#if HAVE_FLISTXATTR
if (fd >= 0)
list_size = flistxattr(fd, list, list_size);
if (*fd >= 0)
list_size = flistxattr(*fd, list, list_size);
else if (!a->follow_symlinks)
list_size = llistxattr(path, list, list_size);
else
list_size = listxattr(path, list, list_size);
#elif HAVE_FLISTEA
if (fd >= 0)
list_size = flistea(fd, list, list_size);
if (*fd >= 0)
list_size = flistea(*fd, list, list_size);
else if (!a->follow_symlinks)
list_size = llistea(path, list, list_size);
else
@ -637,7 +833,7 @@ setup_xattrs(struct archive_read_disk *a,
if (strncmp(p, "system.", 7) == 0 ||
strncmp(p, "xfsroot.", 8) == 0)
continue;
setup_xattr(a, entry, p, fd);
setup_xattr(a, entry, p, *fd);
}
free(list);
@ -698,6 +894,7 @@ setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
size = extattr_get_file(accpath, namespace, name, value, size);
if (size == -1) {
free(value);
archive_set_error(&a->archive, errno,
"Couldn't read extended attribute");
return (ARCHIVE_WARN);
@ -711,7 +908,7 @@ setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
static int
setup_xattrs(struct archive_read_disk *a,
struct archive_entry *entry, int fd)
struct archive_entry *entry, int *fd)
{
char buff[512];
char *list, *p;
@ -723,8 +920,22 @@ setup_xattrs(struct archive_read_disk *a,
if (path == NULL)
path = archive_entry_pathname(entry);
if (fd >= 0)
list_size = extattr_list_fd(fd, namespace, NULL, 0);
if (*fd < 0 && a->tree != NULL) {
if (a->follow_symlinks ||
archive_entry_filetype(entry) != AE_IFLNK)
*fd = a->open_on_current_dir(a->tree, path,
O_RDONLY | O_NONBLOCK);
if (*fd < 0) {
if (a->tree_enter_working_dir(a->tree) != 0) {
archive_set_error(&a->archive, errno,
"Couldn't access %s", path);
return (ARCHIVE_FAILED);
}
}
}
if (*fd >= 0)
list_size = extattr_list_fd(*fd, namespace, NULL, 0);
else if (!a->follow_symlinks)
list_size = extattr_list_link(path, namespace, NULL, 0);
else
@ -746,8 +957,8 @@ setup_xattrs(struct archive_read_disk *a,
return (ARCHIVE_FATAL);
}
if (fd >= 0)
list_size = extattr_list_fd(fd, namespace, list, list_size);
if (*fd >= 0)
list_size = extattr_list_fd(*fd, namespace, list, list_size);
else if (!a->follow_symlinks)
list_size = extattr_list_link(path, namespace, list, list_size);
else
@ -769,7 +980,7 @@ setup_xattrs(struct archive_read_disk *a,
name = buff + strlen(buff);
memcpy(name, p + 1, len);
name[len] = '\0';
setup_xattr(a, entry, namespace, name, buff, fd);
setup_xattr(a, entry, namespace, name, buff, *fd);
p += 1 + len;
}
@ -784,7 +995,7 @@ setup_xattrs(struct archive_read_disk *a,
*/
static int
setup_xattrs(struct archive_read_disk *a,
struct archive_entry *entry, int fd)
struct archive_entry *entry, int *fd)
{
(void)a; /* UNUSED */
(void)entry; /* UNUSED */
@ -813,14 +1024,13 @@ setup_xattrs(struct archive_read_disk *a,
static int
setup_sparse(struct archive_read_disk *a,
struct archive_entry *entry, int fd)
struct archive_entry *entry, int *fd)
{
char buff[4096];
struct fiemap *fm;
struct fiemap_extent *fe;
int64_t size;
int count, do_fiemap;
int initial_fd = fd;
int exit_sts = ARCHIVE_OK;
if (archive_entry_filetype(entry) != AE_IFREG
@ -828,20 +1038,27 @@ setup_sparse(struct archive_read_disk *a,
|| archive_entry_hardlink(entry) != NULL)
return (ARCHIVE_OK);
if (fd < 0) {
if (*fd < 0) {
const char *path;
path = archive_entry_sourcepath(entry);
if (path == NULL)
path = archive_entry_pathname(entry);
fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
if (a->tree != NULL)
*fd = a->open_on_current_dir(a->tree, path,
O_RDONLY | O_NONBLOCK | O_CLOEXEC);
else
*fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
if (*fd < 0) {
archive_set_error(&a->archive, errno,
"Can't open `%s'", path);
return (ARCHIVE_FAILED);
}
__archive_ensure_cloexec_flag(*fd);
}
/* Initialize buffer to avoid the error valgrind complains about. */
memset(buff, 0, sizeof(buff));
count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
fm = (struct fiemap *)buff;
fm->fm_start = 0;
@ -853,29 +1070,22 @@ setup_sparse(struct archive_read_disk *a,
for (;;) {
int i, r;
r = ioctl(fd, FS_IOC_FIEMAP, fm);
r = ioctl(*fd, FS_IOC_FIEMAP, fm);
if (r < 0) {
/* When errno is ENOTTY, it is better we should
* return ARCHIVE_OK because an earlier version
*(<2.6.28) cannot perfom FS_IOC_FIEMAP.
* We should also check if errno is EOPNOTSUPP,
* it means "Operation not supported". */
if (errno != ENOTTY && errno != EOPNOTSUPP) {
archive_set_error(&a->archive, errno,
"FIEMAP failed");
exit_sts = ARCHIVE_FAILED;
}
/* When something error happens, it is better we
* should return ARCHIVE_OK because an earlier
* version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
goto exit_setup_sparse;
}
if (fm->fm_mapped_extents == 0)
break;
fe = fm->fm_extents;
for (i = 0; i < fm->fm_mapped_extents; i++, fe++) {
for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
/* The fe_length of the last block does not
* adjust itself to its size files. */
int64_t length = fe->fe_length;
if (fe->fe_logical + length > size)
if (fe->fe_logical + length > (uint64_t)size)
length -= fe->fe_logical + length - size;
if (fe->fe_logical == 0 && length == size) {
/* This is not sparse. */
@ -896,8 +1106,6 @@ setup_sparse(struct archive_read_disk *a,
break;
}
exit_setup_sparse:
if (initial_fd != fd)
close(fd);
return (exit_sts);
}
@ -909,10 +1117,9 @@ exit_setup_sparse:
static int
setup_sparse(struct archive_read_disk *a,
struct archive_entry *entry, int fd)
struct archive_entry *entry, int *fd)
{
int64_t size;
int initial_fd = fd;
off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
int exit_sts = ARCHIVE_OK;
@ -923,33 +1130,50 @@ setup_sparse(struct archive_read_disk *a,
return (ARCHIVE_OK);
/* Does filesystem support the reporting of hole ? */
if (fd >= 0) {
if (fpathconf(fd, _PC_MIN_HOLE_SIZE) <= 0)
if (*fd < 0 && a->tree != NULL) {
const char *path;
path = archive_entry_sourcepath(entry);
if (path == NULL)
path = archive_entry_pathname(entry);
*fd = a->open_on_current_dir(a->tree, path,
O_RDONLY | O_NONBLOCK);
if (*fd < 0) {
archive_set_error(&a->archive, errno,
"Can't open `%s'", path);
return (ARCHIVE_FAILED);
}
}
if (*fd >= 0) {
if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
return (ARCHIVE_OK);
initial_off = lseek(fd, 0, SEEK_CUR);
initial_off = lseek(*fd, 0, SEEK_CUR);
if (initial_off != 0)
lseek(fd, 0, SEEK_SET);
lseek(*fd, 0, SEEK_SET);
} else {
const char *path;
path = archive_entry_sourcepath(entry);
if (path == NULL)
path = archive_entry_pathname(entry);
if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
return (ARCHIVE_OK);
fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
*fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
if (*fd < 0) {
archive_set_error(&a->archive, errno,
"Can't open `%s'", path);
return (ARCHIVE_FAILED);
}
__archive_ensure_cloexec_flag(*fd);
initial_off = 0;
}
off_s = 0;
size = archive_entry_size(entry);
while (off_s < size) {
off_s = lseek(fd, off_s, SEEK_DATA);
off_s = lseek(*fd, off_s, SEEK_DATA);
if (off_s == (off_t)-1) {
if (errno == ENXIO)
break;/* no more hole */
@ -958,10 +1182,10 @@ setup_sparse(struct archive_read_disk *a,
exit_sts = ARCHIVE_FAILED;
goto exit_setup_sparse;
}
off_e = lseek(fd, off_s, SEEK_HOLE);
if (off_s == (off_t)-1) {
off_e = lseek(*fd, off_s, SEEK_HOLE);
if (off_e == (off_t)-1) {
if (errno == ENXIO) {
off_e = lseek(fd, 0, SEEK_END);
off_e = lseek(*fd, 0, SEEK_END);
if (off_e != (off_t)-1)
break;/* no more data */
}
@ -977,10 +1201,7 @@ setup_sparse(struct archive_read_disk *a,
off_s = off_e;
}
exit_setup_sparse:
if (initial_fd != fd)
close(fd);
else
lseek(fd, initial_off, SEEK_SET);
lseek(*fd, initial_off, SEEK_SET);
return (exit_sts);
}
@ -991,7 +1212,7 @@ exit_setup_sparse:
*/
static int
setup_sparse(struct archive_read_disk *a,
struct archive_entry *entry, int fd)
struct archive_entry *entry, int *fd)
{
(void)a; /* UNUSED */
(void)entry; /* UNUSED */

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
* Copyright (c) 2010,2011 Michihiro NAKAJIMA
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -52,6 +52,19 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_LINUX_MAGIC_H
#include <linux/magic.h>
#endif
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
#endif
/*
* Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
* As the include guards don't agree, the order of include is important.
*/
#ifdef HAVE_LINUX_EXT2_FS_H
#include <linux/ext2_fs.h> /* for Linux file flags */
#endif
#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
#endif
#ifdef HAVE_DIRECT_H
#include <direct.h>
#endif
@ -76,6 +89,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#include "archive.h"
#include "archive_string.h"
@ -89,6 +105,9 @@ __FBSDID("$FreeBSD$");
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
/*-
* This is a new directory-walking system that addresses a number
@ -222,6 +241,7 @@ struct tree {
char symlink_mode;
struct filesystem *current_filesystem;
struct filesystem *filesystem_table;
int initial_filesystem_id;
int current_filesystem_id;
int max_filesystem_id;
int allocated_filesytem;
@ -240,6 +260,7 @@ struct tree {
#define onWorkingDir 64 /* We are on the working dir where we are
* reading directory entry at this time. */
#define needsRestoreTimes 128
#define onInitialDir 256 /* We are on the initial dir. */
static int
tree_dir_next_posix(struct tree *t);
@ -342,6 +363,8 @@ static const char *trivial_lookup_uname(void *, int64_t uid);
static int setup_sparse(struct archive_read_disk *, struct archive_entry *);
static int close_and_restore_time(int fd, struct tree *,
struct restore_time *);
static int open_on_current_dir(struct tree *, const char *, int);
static int tree_dup(int);
static struct archive_vtable *
@ -430,16 +453,19 @@ archive_read_disk_new(void)
{
struct archive_read_disk *a;
a = (struct archive_read_disk *)malloc(sizeof(*a));
a = (struct archive_read_disk *)calloc(1, sizeof(*a));
if (a == NULL)
return (NULL);
memset(a, 0, sizeof(*a));
a->archive.magic = ARCHIVE_READ_DISK_MAGIC;
a->archive.state = ARCHIVE_STATE_NEW;
a->archive.vtable = archive_read_disk_vtable();
a->lookup_uname = trivial_lookup_uname;
a->lookup_gname = trivial_lookup_gname;
a->entry_wd_fd = -1;
a->enable_copyfile = 1;
a->traverse_mount_points = 1;
a->open_on_current_dir = open_on_current_dir;
a->tree_current_dir_fd = tree_current_dir_fd;
a->tree_enter_working_dir = tree_enter_working_dir;
return (&a->archive);
}
@ -555,6 +581,37 @@ archive_read_disk_set_atime_restored(struct archive *_a)
#endif
}
int
archive_read_disk_set_behavior(struct archive *_a, int flags)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
int r = ARCHIVE_OK;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump");
if (flags & ARCHIVE_READDISK_RESTORE_ATIME)
r = archive_read_disk_set_atime_restored(_a);
else {
a->restore_time = 0;
if (a->tree != NULL)
a->tree->flags &= ~needsRestoreTimes;
}
if (flags & ARCHIVE_READDISK_HONOR_NODUMP)
a->honor_nodump = 1;
else
a->honor_nodump = 0;
if (flags & ARCHIVE_READDISK_MAC_COPYFILE)
a->enable_copyfile = 1;
else
a->enable_copyfile = 0;
if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS)
a->traverse_mount_points = 0;
else
a->traverse_mount_points = 1;
return (r);
}
/*
* Trivial implementations of gname/uname lookup functions.
* These are normally overridden by the client, but these stub
@ -664,7 +721,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
* Open the current file.
*/
if (t->entry_fd < 0) {
int flags = O_RDONLY | O_BINARY;
int flags = O_RDONLY | O_BINARY | O_CLOEXEC;
/*
* Eliminate or reduce cache effects if we can.
@ -685,13 +742,9 @@ _archive_read_data_block(struct archive *_a, const void **buff,
flags |= O_NOATIME;
do {
#endif
#ifdef HAVE_OPENAT
t->entry_fd = openat(tree_current_dir_fd(t),
t->entry_fd = open_on_current_dir(t,
tree_current_access_path(t), flags);
#else
tree_enter_working_dir(t);
t->entry_fd = open(tree_current_access_path(t), flags);
#endif
__archive_ensure_cloexec_flag(t->entry_fd);
#if defined(O_NOATIME)
/*
* When we did open the file with O_NOATIME flag,
@ -733,7 +786,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
t->entry_buff_size = t->current_filesystem->buff_size;
buffbytes = t->entry_buff_size;
if (buffbytes > t->current_sparse->length)
if ((int64_t)buffbytes > t->current_sparse->length)
buffbytes = t->current_sparse->length;
/*
@ -802,29 +855,17 @@ abort_read_data:
}
static int
_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
next_entry(struct archive_read_disk *a, struct tree *t,
struct archive_entry *entry)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
struct tree *t;
const struct stat *st; /* info to use for this entry */
const struct stat *lst;/* lstat() information */
int descend, fd = -1, r;
const char *name;
int descend, r;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
"archive_read_next_header2");
t = a->tree;
if (t->entry_fd >= 0) {
close_and_restore_time(t->entry_fd, t, &t->restore_time);
t->entry_fd = -1;
}
#if !(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR))
/* Restore working directory. */
tree_enter_working_dir(t);
#endif
st = NULL;
lst = NULL;
t->descend = 0;
do {
switch (tree_next(t)) {
case TREE_ERROR_FATAL:
@ -859,6 +900,38 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
}
} while (lst == NULL);
#ifdef __APPLE__
if (a->enable_copyfile) {
/* If we're using copyfile(), ignore "._XXX" files. */
const char *bname = strrchr(tree_current_path(t), '/');
if (bname == NULL)
bname = tree_current_path(t);
else
++bname;
if (bname[0] == '.' && bname[1] == '_')
return (ARCHIVE_RETRY);
}
#endif
archive_entry_copy_pathname(entry, tree_current_path(t));
/*
* Perform path matching.
*/
if (a->matching) {
r = archive_match_path_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
"Faild : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
if (a->excluded_cb_func)
a->excluded_cb_func(&(a->archive),
a->excluded_cb_data, entry);
return (ARCHIVE_RETRY);
}
}
/*
* Distinguish 'L'/'P'/'H' symlink following.
*/
@ -897,13 +970,46 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
tree_enter_initial_dir(t);
return (ARCHIVE_FATAL);
}
if (t->initial_filesystem_id == -1)
t->initial_filesystem_id = t->current_filesystem_id;
if (!a->traverse_mount_points) {
if (t->initial_filesystem_id != t->current_filesystem_id)
return (ARCHIVE_RETRY);
}
t->descend = descend;
archive_entry_set_pathname(entry, tree_current_path(t));
archive_entry_copy_sourcepath(entry, tree_current_access_path(t));
/*
* Honor nodump flag.
* If the file is marked with nodump flag, do not return this entry.
*/
if (a->honor_nodump) {
#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
if (st->st_flags & UF_NODUMP)
return (ARCHIVE_RETRY);
#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\
defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) {
int stflags;
t->entry_fd = open_on_current_dir(t,
tree_current_access_path(t),
O_RDONLY | O_NONBLOCK | O_CLOEXEC);
__archive_ensure_cloexec_flag(t->entry_fd);
if (t->entry_fd >= 0) {
r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS,
&stflags);
if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0)
return (ARCHIVE_RETRY);
}
}
#endif
}
archive_entry_copy_stat(entry, st);
/* Save the times to be restored. */
/* Save the times to be restored. This must be in before
* calling archive_read_disk_descend() or any chance of it,
* especially, invokng a callback. */
t->restore_time.mtime = archive_entry_mtime(entry);
t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry);
t->restore_time.atime = archive_entry_atime(entry);
@ -911,39 +1017,102 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
t->restore_time.filetype = archive_entry_filetype(entry);
t->restore_time.noatime = t->current_filesystem->noatime;
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
/*
* Open the current file to freely gather its metadata anywhere in
* working directory.
* Note: A symbolic link file cannot be opened with O_NOFOLLOW.
* Perform time matching.
*/
if (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK)
fd = openat(tree_current_dir_fd(t), tree_current_access_path(t),
O_RDONLY | O_NONBLOCK);
/* Restore working directory if openat() operation failed or
* the file is a symbolic link. */
if (fd < 0)
tree_enter_working_dir(t);
if (a->matching) {
r = archive_match_time_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
"Faild : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
if (a->excluded_cb_func)
a->excluded_cb_func(&(a->archive),
a->excluded_cb_data, entry);
return (ARCHIVE_RETRY);
}
}
/* The current direcotry fd is needed at
* archive_read_disk_entry_from_file() function to read link data
* with readlinkat(). */
a->entry_wd_fd = tree_current_dir_fd(t);
#endif
/* Lookup uname/gname */
name = archive_read_disk_uname(&(a->archive), archive_entry_uid(entry));
if (name != NULL)
archive_entry_copy_uname(entry, name);
name = archive_read_disk_gname(&(a->archive), archive_entry_gid(entry));
if (name != NULL)
archive_entry_copy_gname(entry, name);
/*
* Perform owner matching.
*/
if (a->matching) {
r = archive_match_owner_excluded(a->matching, entry);
if (r < 0) {
archive_set_error(&(a->archive), errno,
"Faild : %s", archive_error_string(a->matching));
return (r);
}
if (r) {
if (a->excluded_cb_func)
a->excluded_cb_func(&(a->archive),
a->excluded_cb_data, entry);
return (ARCHIVE_RETRY);
}
}
/*
* Invoke a meta data filter callback.
*/
if (a->metadata_filter_func) {
if (!a->metadata_filter_func(&(a->archive),
a->metadata_filter_data, entry))
return (ARCHIVE_RETRY);
}
/*
* Populate the archive_entry with metadata from the disk.
*/
r = archive_read_disk_entry_from_file(&(a->archive), entry, fd, st);
archive_entry_copy_sourcepath(entry, tree_current_access_path(t));
r = archive_read_disk_entry_from_file(&(a->archive), entry,
t->entry_fd, st);
/* Close the file descriptor used for reding the current file
* metadata at archive_read_disk_entry_from_file(). */
if (fd >= 0)
close(fd);
return (r);
}
static int
_archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
struct tree *t;
int r;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
"archive_read_next_header2");
t = a->tree;
if (t->entry_fd >= 0) {
close_and_restore_time(t->entry_fd, t, &t->restore_time);
t->entry_fd = -1;
}
for (;;) {
r = next_entry(a, t, entry);
if (t->entry_fd >= 0) {
close(t->entry_fd);
t->entry_fd = -1;
}
if (r == ARCHIVE_RETRY) {
archive_entry_clear(entry);
continue;
}
break;
}
/* Return to the initial directory. */
tree_enter_initial_dir(t);
archive_entry_copy_sourcepath(entry, tree_current_path(t));
/*
* EOF and FATAL are persistent at this layer. By
@ -956,6 +1125,8 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
break;
case ARCHIVE_OK:
case ARCHIVE_WARN:
/* Overwrite the sourcepath based on the initial directory. */
archive_entry_copy_sourcepath(entry, tree_current_path(t));
t->entry_total = 0;
if (archive_entry_filetype(entry) == AE_IFREG) {
t->nlink = archive_entry_nlink(entry);
@ -1018,6 +1189,48 @@ setup_sparse(struct archive_read_disk *a, struct archive_entry *entry)
return (ARCHIVE_OK);
}
int
archive_read_disk_set_matching(struct archive *_a, struct archive *_ma,
void (*_excluded_func)(struct archive *, void *, struct archive_entry *),
void *_client_data)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_disk_set_matching");
a->matching = _ma;
a->excluded_cb_func = _excluded_func;
a->excluded_cb_data = _client_data;
return (ARCHIVE_OK);
}
int
archive_read_disk_set_metadata_filter_callback(struct archive *_a,
int (*_metadata_filter_func)(struct archive *, void *,
struct archive_entry *), void *_client_data)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY,
"archive_read_disk_set_metadata_filter_callback");
a->metadata_filter_func = _metadata_filter_func;
a->metadata_filter_data = _client_data;
return (ARCHIVE_OK);
}
int
archive_read_disk_can_descend(struct archive *_a)
{
struct archive_read_disk *a = (struct archive_read_disk *)_a;
struct tree *t = a->tree;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
"archive_read_disk_can_descend");
return (t->visit_type == TREE_REGULAR && t->descend);
}
/*
* Called by the client to mark the directory just returned from
* tree_next() as needing to be visited.
@ -1028,14 +1241,12 @@ archive_read_disk_descend(struct archive *_a)
struct archive_read_disk *a = (struct archive_read_disk *)_a;
struct tree *t = a->tree;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
"archive_read_disk_descend");
if (t->visit_type != TREE_REGULAR || !t->descend) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Ignored the request descending the current object");
return (ARCHIVE_WARN);
}
if (t->visit_type != TREE_REGULAR || !t->descend)
return (ARCHIVE_OK);
if (tree_current_is_physical_dir(t)) {
tree_push(t, t->basename, t->current_filesystem_id,
@ -1079,6 +1290,10 @@ archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname)
archive_string_init(&path);
if (archive_string_append_from_wcs(&path, pathname,
wcslen(pathname)) != 0) {
if (errno == ENOMEM)
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory");
else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Can't convert a path to a char string");
a->archive.state = ARCHIVE_STATE_FATAL;
@ -1151,15 +1366,17 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
fid = t->max_filesystem_id++;
if (t->max_filesystem_id > t->allocated_filesytem) {
size_t s;
void *p;
s = t->max_filesystem_id * 2;
t->filesystem_table = realloc(t->filesystem_table,
p = realloc(t->filesystem_table,
s * sizeof(*t->filesystem_table));
if (t->filesystem_table == NULL) {
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
return (ARCHIVE_FATAL);
}
t->filesystem_table = (struct filesystem *)p;
t->allocated_filesytem = s;
}
t->current_filesystem_id = fid;
@ -1268,13 +1485,14 @@ setup_current_filesystem(struct archive_read_disk *a)
t->current_filesystem->synthetic = -1;
t->current_filesystem->remote = -1;
if (tree_current_is_symblic_link_target(t)) {
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
#if defined(HAVE_OPENAT)
/*
* Get file system statistics on any directory
* where current is.
*/
int fd = openat(tree_current_dir_fd(t),
tree_current_access_path(t), O_RDONLY);
tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
__archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(&a->archive, errno,
"openat failed");
@ -1285,6 +1503,10 @@ setup_current_filesystem(struct archive_read_disk *a)
xr = get_xfer_size(t, fd, NULL);
close(fd);
#else
if (tree_enter_working_dir(t) != 0) {
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
r = statfs(tree_current_access_path(t), &sfs);
if (r == 0)
xr = get_xfer_size(t, -1, tree_current_access_path(t));
@ -1334,9 +1556,13 @@ setup_current_filesystem(struct archive_read_disk *a)
t->current_filesystem->name_max = sfs.f_namemax;
#else
/* Mac OS X does not have f_namemax in struct statfs. */
if (tree_current_is_symblic_link_target(t))
if (tree_current_is_symblic_link_target(t)) {
if (tree_enter_working_dir(t) != 0) {
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
else
} else
nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
if (nm == -1)
t->current_filesystem->name_max = NAME_MAX;
@ -1360,6 +1586,10 @@ setup_current_filesystem(struct archive_read_disk *a)
int r, xr = 0;
t->current_filesystem->synthetic = -1;
if (tree_enter_working_dir(t) != 0) {
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
if (tree_current_is_symblic_link_target(t)) {
r = statvfs(tree_current_access_path(t), &sfs);
if (r == 0)
@ -1384,17 +1614,24 @@ setup_current_filesystem(struct archive_read_disk *a)
* for pathconf() function. */
t->current_filesystem->xfer_align = sfs.f_frsize;
t->current_filesystem->max_xfer_size = -1;
#if defined(HAVE_STRUCT_STATVFS_F_IOSIZE)
t->current_filesystem->min_xfer_size = sfs.f_iosize;
t->current_filesystem->incr_xfer_size = sfs.f_iosize;
#else
t->current_filesystem->min_xfer_size = sfs.f_bsize;
t->current_filesystem->incr_xfer_size = sfs.f_bsize;
#endif
}
if (sfs.f_flag & ST_LOCAL)
t->current_filesystem->remote = 0;
else
t->current_filesystem->remote = 1;
#if defined(ST_NOATIME)
if (sfs.f_flag & ST_NOATIME)
t->current_filesystem->noatime = 1;
else
#endif
t->current_filesystem->noatime = 0;
/* Set maximum filename length. */
@ -1427,13 +1664,14 @@ setup_current_filesystem(struct archive_read_disk *a)
int r, vr = 0, xr = 0;
if (tree_current_is_symblic_link_target(t)) {
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
#if defined(HAVE_OPENAT)
/*
* Get file system statistics on any directory
* where current is.
*/
int fd = openat(tree_current_dir_fd(t),
tree_current_access_path(t), O_RDONLY);
tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
__archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(&a->archive, errno,
"openat failed");
@ -1445,6 +1683,10 @@ setup_current_filesystem(struct archive_read_disk *a)
xr = get_xfer_size(t, fd, NULL);
close(fd);
#else
if (tree_enter_working_dir(t) != 0) {
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
vr = statvfs(tree_current_access_path(t), &svfs);
r = statfs(tree_current_access_path(t), &sfs);
if (r == 0)
@ -1456,9 +1698,11 @@ setup_current_filesystem(struct archive_read_disk *a)
r = fstatfs(tree_current_dir_fd(t), &sfs);
if (r == 0)
xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
#elif defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
#error "Unexpected case. Please tell us about this error."
#else
if (tree_enter_working_dir(t) != 0) {
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
vr = statvfs(".", &svfs);
r = statfs(".", &sfs);
if (r == 0)
@ -1529,13 +1773,14 @@ setup_current_filesystem(struct archive_read_disk *a)
t->current_filesystem->synthetic = -1;/* Not supported */
t->current_filesystem->remote = -1;/* Not supported */
if (tree_current_is_symblic_link_target(t)) {
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
#if defined(HAVE_OPENAT)
/*
* Get file system statistics on any directory
* where current is.
*/
int fd = openat(tree_current_dir_fd(t),
tree_current_access_path(t), O_RDONLY);
tree_current_access_path(t), O_RDONLY | O_CLOEXEC);
__archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(&a->archive, errno,
"openat failed");
@ -1546,6 +1791,10 @@ setup_current_filesystem(struct archive_read_disk *a)
xr = get_xfer_size(t, fd, NULL);
close(fd);
#else
if (tree_enter_working_dir(t) != 0) {
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
r = statvfs(tree_current_access_path(t), &sfs);
if (r == 0)
xr = get_xfer_size(t, -1, tree_current_access_path(t));
@ -1555,9 +1804,11 @@ setup_current_filesystem(struct archive_read_disk *a)
r = fstatvfs(tree_current_dir_fd(t), &sfs);
if (r == 0)
xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
#elif defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
#error "Unexpected case. Please tell us about this error."
#else
if (tree_enter_working_dir(t) != 0) {
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
r = statvfs(".", &sfs);
if (r == 0)
xr = get_xfer_size(t, -1, ".");
@ -1615,9 +1866,13 @@ setup_current_filesystem(struct archive_read_disk *a)
#if defined(HAVE_READDIR_R)
/* Set maximum filename length. */
# if defined(_PC_NAME_MAX)
if (tree_current_is_symblic_link_target(t))
if (tree_current_is_symblic_link_target(t)) {
if (tree_enter_working_dir(t) != 0) {
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
else
} else
nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
if (nm == -1)
# endif /* _PC_NAME_MAX */
@ -1646,7 +1901,8 @@ static int
close_and_restore_time(int fd, struct tree *t, struct restore_time *rt)
{
#ifndef HAVE_UTIMES
(void)a; /* UNUSED */
(void)t; /* UNUSED */
(void)rt; /* UNUSED */
return (close(fd));
#else
#if defined(HAVE_FUTIMENS) && !defined(__CYGWIN__)
@ -1697,6 +1953,40 @@ close_and_restore_time(int fd, struct tree *t, struct restore_time *rt)
return (0);
}
static int
open_on_current_dir(struct tree *t, const char *path, int flags)
{
#ifdef HAVE_OPENAT
return (openat(tree_current_dir_fd(t), path, flags));
#else
if (tree_enter_working_dir(t) != 0)
return (-1);
return (open(path, flags));
#endif
}
static int
tree_dup(int fd)
{
int new_fd;
#ifdef F_DUPFD_CLOEXEC
static volatile int can_dupfd_cloexec = 1;
if (can_dupfd_cloexec) {
new_fd = fcntl(fd, F_DUPFD_CLOEXEC);
if (new_fd != -1)
return (new_fd);
/* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC,
* but it cannot be used. So we have to try dup(). */
/* We won't try F_DUPFD_CLOEXEC. */
can_dupfd_cloexec = 0;
}
#endif /* F_DUPFD_CLOEXEC */
new_fd = dup(fd);
__archive_ensure_cloexec_flag(new_fd);
return (new_fd);
}
/*
* Add a directory path to the current stack.
*/
@ -1778,6 +2068,7 @@ static struct tree *
tree_reopen(struct tree *t, const char *path, int restore_time)
{
t->flags = (restore_time)?needsRestoreTimes:0;
t->flags |= onInitialDir;
t->visit_type = 0;
t->tree_errno = 0;
t->dirname_length = 0;
@ -1790,25 +2081,30 @@ tree_reopen(struct tree *t, const char *path, int restore_time)
t->entry_fd = -1;
t->entry_eof = 0;
t->entry_remaining_bytes = 0;
t->initial_filesystem_id = -1;
/* First item is set up a lot like a symlink traversal. */
tree_push(t, path, 0, 0, 0, NULL);
t->stack->flags = needsFirstVisit;
t->maxOpenCount = t->openCount = 1;
t->initial_dir_fd = open(".", O_RDONLY);
t->working_dir_fd = dup(t->initial_dir_fd);
t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC);
__archive_ensure_cloexec_flag(t->initial_dir_fd);
t->working_dir_fd = tree_dup(t->initial_dir_fd);
return (t);
}
static int
tree_descent(struct tree *t)
{
int r = 0;
int flag, new_fd, r = 0;
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
int new_fd;
t->dirname_length = archive_strlen(&t->path);
new_fd = openat(t->working_dir_fd, t->stack->name.s, O_RDONLY);
flag = O_RDONLY | O_CLOEXEC;
#if defined(O_DIRECTORY)
flag |= O_DIRECTORY;
#endif
new_fd = open_on_current_dir(t, t->stack->name.s, flag);
__archive_ensure_cloexec_flag(new_fd);
if (new_fd < 0) {
t->tree_errno = errno;
r = TREE_ERROR_DIR;
@ -1822,30 +2118,10 @@ tree_descent(struct tree *t)
t->maxOpenCount = t->openCount;
} else
close(t->working_dir_fd);
/* Renew the current working directory. */
t->working_dir_fd = new_fd;
t->flags &= ~onWorkingDir;
}
#else
/* If it is a link, set up fd for the ascent. */
if (t->stack->flags & isDirLink)
t->stack->symlink_parent_fd = t->working_dir_fd;
else {
close(t->working_dir_fd);
t->openCount--;
}
t->working_dir_fd = -1;
t->dirname_length = archive_strlen(&t->path);
if (chdir(t->stack->name.s) != 0)
{
t->tree_errno = errno;
r = TREE_ERROR_DIR;
} else {
t->depth++;
t->working_dir_fd = open(".", O_RDONLY);
t->openCount++;
if (t->openCount > t->maxOpenCount)
t->maxOpenCount = t->openCount;
}
#endif
return (r);
}
@ -1856,37 +2132,23 @@ static int
tree_ascend(struct tree *t)
{
struct tree_entry *te;
int r = 0, prev_dir_fd;
int new_fd, r = 0, prev_dir_fd;
te = t->stack;
prev_dir_fd = t->working_dir_fd;
#if defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_FDOPENDIR)
if (te->flags & isDirLink)
t->working_dir_fd = te->symlink_parent_fd;
new_fd = te->symlink_parent_fd;
else {
int new_fd = openat(t->working_dir_fd, "..", O_RDONLY);
new_fd = open_on_current_dir(t, "..", O_RDONLY | O_CLOEXEC);
__archive_ensure_cloexec_flag(new_fd);
}
if (new_fd < 0) {
t->tree_errno = errno;
r = TREE_ERROR_FATAL;
} else
t->working_dir_fd = new_fd;
}
#else
if (te->flags & isDirLink) {
if (fchdir(te->symlink_parent_fd) != 0) {
t->tree_errno = errno;
r = TREE_ERROR_FATAL;
} else
t->working_dir_fd = te->symlink_parent_fd;
} else {
if (chdir("..") != 0) {
t->tree_errno = errno;
r = TREE_ERROR_FATAL;
} else
t->working_dir_fd = open(".", O_RDONLY);
}
#endif
if (r == 0) {
/* Renew the current working directory. */
t->working_dir_fd = new_fd;
t->flags &= ~onWorkingDir;
/* Current directory has been changed, we should
* close an fd of previous working directory. */
close_and_restore_time(prev_dir_fd, t, &te->restore_time);
@ -1907,10 +2169,12 @@ tree_enter_initial_dir(struct tree *t)
{
int r = 0;
if (t->flags & onWorkingDir) {
if ((t->flags & onInitialDir) == 0) {
r = fchdir(t->initial_dir_fd);
if (r == 0)
if (r == 0) {
t->flags &= ~onWorkingDir;
t->flags |= onInitialDir;
}
}
return (r);
}
@ -1930,9 +2194,11 @@ tree_enter_working_dir(struct tree *t)
*/
if (t->depth > 0 && (t->flags & onWorkingDir) == 0) {
r = fchdir(t->working_dir_fd);
if (r == 0)
if (r == 0) {
t->flags &= ~onInitialDir;
t->flags |= onWorkingDir;
}
}
return (r);
}
@ -2038,10 +2304,16 @@ tree_dir_next_posix(struct tree *t)
#endif
#if defined(HAVE_FDOPENDIR)
if ((t->d = fdopendir(dup(t->working_dir_fd))) == NULL) {
#else
if ((t->d = opendir(".")) == NULL) {
t->d = fdopendir(tree_dup(t->working_dir_fd));
#else /* HAVE_FDOPENDIR */
if (tree_enter_working_dir(t) == 0) {
t->d = opendir(".");
#if HAVE_DIRFD || defined(dirfd)
__archive_ensure_cloexec_flag(dirfd(t->d));
#endif
}
#endif /* HAVE_FDOPENDIR */
if (t->d == NULL) {
r = tree_ascend(t); /* Undo "chdir" */
tree_pop(t);
t->tree_errno = errno;
@ -2068,11 +2340,21 @@ tree_dir_next_posix(struct tree *t)
#endif /* HAVE_READDIR_R */
}
for (;;) {
errno = 0;
#if defined(HAVE_READDIR_R)
r = readdir_r(t->d, t->dirent, &t->de);
#ifdef _AIX
/* Note: According to the man page, return value 9 indicates
* that the readdir_r was not successful and the error code
* is set to the global errno variable. And then if the end
* of directory entries was reached, the return value is 9
* and the third parameter is set to NULL and errno is
* unchanged. */
if (r == 9)
r = errno;
#endif /* _AIX */
if (r != 0 || t->de == NULL) {
#else
errno = 0;
t->de = readdir(t->d);
if (t->de == NULL) {
r = errno;
@ -2111,6 +2393,8 @@ tree_current_stat(struct tree *t)
if (fstatat(tree_current_dir_fd(t),
tree_current_access_path(t), &t->st, 0) != 0)
#else
if (tree_enter_working_dir(t) != 0)
return NULL;
if (stat(tree_current_access_path(t), &t->st) != 0)
#endif
return NULL;
@ -2131,6 +2415,8 @@ tree_current_lstat(struct tree *t)
tree_current_access_path(t), &t->lst,
AT_SYMLINK_NOFOLLOW) != 0)
#else
if (tree_enter_working_dir(t) != 0)
return NULL;
if (lstat(tree_current_access_path(t), &t->lst) != 0)
#endif
return NULL;
@ -2152,11 +2438,14 @@ tree_current_is_dir(struct tree *t)
*/
if (t->flags & hasLstat) {
/* If lstat() says it's a dir, it must be a dir. */
if (S_ISDIR(tree_current_lstat(t)->st_mode))
st = tree_current_lstat(t);
if (st == NULL)
return 0;
if (S_ISDIR(st->st_mode))
return 1;
/* Not a dir; might be a link to a dir. */
/* If it's not a link, then it's not a link to a dir. */
if (!S_ISLNK(tree_current_lstat(t)->st_mode))
if (!S_ISLNK(st->st_mode))
return 0;
/*
* It's a link, but we don't know what it's a link to,
@ -2186,9 +2475,13 @@ tree_current_is_physical_dir(struct tree *t)
* If stat() says it isn't a dir, then it's not a dir.
* If stat() data is cached, this check is free, so do it first.
*/
if ((t->flags & hasStat)
&& (!S_ISDIR(tree_current_stat(t)->st_mode)))
return 0;
if (t->flags & hasStat) {
st = tree_current_stat(t);
if (st == NULL)
return (0);
if (!S_ISDIR(st->st_mode))
return (0);
}
/*
* Either stat() said it was a dir (in which case, we have
@ -2214,7 +2507,8 @@ tree_target_is_same_as_parent(struct tree *t, const struct stat *st)
struct tree_entry *te;
for (te = t->current->parent; te != NULL; te = te->parent) {
if (te->dev == st->st_dev && te->ino == st->st_ino)
if (te->dev == (int64_t)st->st_dev &&
te->ino == (int64_t)st->st_ino)
return (1);
}
return (0);
@ -2231,7 +2525,8 @@ tree_current_is_symblic_link_target(struct tree *t)
lst = tree_current_lstat(t);
st = tree_current_stat(t);
return (st != NULL && st->st_dev == t->current_filesystem->dev &&
return (st != NULL && lst != NULL &&
(int64_t)st->st_dev == t->current_filesystem->dev &&
st->st_dev != lst->st_dev);
}

View File

@ -34,6 +34,7 @@
#define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
struct tree;
struct archive_entry;
struct archive_read_disk {
struct archive archive;
@ -55,10 +56,18 @@ struct archive_read_disk {
/* Directory traversals. */
struct tree *tree;
int (*open_on_current_dir)(struct tree*, const char *, int);
int (*tree_current_dir_fd)(struct tree*);
int (*tree_enter_working_dir)(struct tree*);
/* Set 1 if users request to restore atime . */
int restore_time;
int entry_wd_fd;
/* Set 1 if users request to honor nodump flag . */
int honor_nodump;
/* Set 1 if users request to enable mac copyfile. */
int enable_copyfile;
/* Set 1 if users request to traverse mount points. */
int traverse_mount_points;
const char * (*lookup_gname)(void *private, int64_t gid);
void (*cleanup_gname)(void *private);
@ -66,6 +75,18 @@ struct archive_read_disk {
const char * (*lookup_uname)(void *private, int64_t uid);
void (*cleanup_uname)(void *private);
void *lookup_uname_data;
int (*metadata_filter_func)(struct archive *, void *,
struct archive_entry *);
void *metadata_filter_data;
/* ARCHIVE_MATCH object. */
struct archive *matching;
/* Callback function, this will be invoked when ARCHIVE_MATCH
* archive_match_*_excluded_ae return true. */
void (*excluded_cb_func)(struct archive *, void *,
struct archive_entry *);
void *excluded_cb_data;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 22, 2011
.Dd February 2, 2012
.Dt ARCHIVE_READ_EXTRACT 3
.Os
.Sh NAME
@ -32,6 +32,8 @@
.Nm archive_read_extract2 ,
.Nm archive_read_extract_set_progress_callback
.Nd functions for reading streaming archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int

View File

@ -154,7 +154,7 @@ copy_data(struct archive *ar, struct archive *aw)
return (ARCHIVE_OK);
if (r != ARCHIVE_OK)
return (r);
r = archive_write_data_block(aw, buff, size, offset);
r = (int)archive_write_data_block(aw, buff, size, offset);
if (r < ARCHIVE_WARN)
r = ARCHIVE_WARN;
if (r != ARCHIVE_OK) {

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 19, 2011
.Dd February 2, 2012
.Dt ARCHIVE_READ_FILTER 3
.Os
.Sh NAME
@ -39,6 +39,8 @@
.Nm archive_read_support_filter_program_signature
.Nd functions for reading streaming archives
.\"
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int

View File

@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
.\" $FreeBSD$
.\"
.Dd March 19, 2011
.Dd February 2, 2012
.Dt ARCHIVE_READ_FORMAT 3
.Os
.Sh NAME
@ -45,6 +45,8 @@
.Nm archive_read_support_format_zip
.Nd functions for reading streaming archives
.\"
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int

View File

@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
.\" $FreeBSD$
.\"
.Dd March 20, 2011
.Dd February 2, 2012
.Dt ARCHIVE_READ_FREE 3
.Os
.Sh NAME
@ -32,6 +32,8 @@
.Nm archive_read_finish ,
.Nm archive_read_free
.Nd functions for reading streaming archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int

View File

@ -24,13 +24,15 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 22, 2011
.Dd February 2, 2012
.Dt ARCHIVE_READ_HEADER 3
.Os
.Sh NAME
.Nm archive_read_next_header ,
.Nm archive_read_next_header2
.Nd functions for reading streaming archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int

View File

@ -22,14 +22,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
.\" $FreeBSD$
.\"
.Dd March 20, 2011
.Dd February 2, 2012
.Dt ARCHIVE_READ_NEW 3
.Os
.Sh NAME
.Nm archive_read_new
.Nd functions for reading streaming archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft struct archive *

View File

@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
.\" $FreeBSD$
.\"
.Dd March 19, 2011
.Dd February 2, 2012
.Dt ARCHIVE_READ_OPEN 3
.Os
.Sh NAME
@ -35,6 +35,8 @@
.Nm archive_read_open_filename ,
.Nm archive_read_open_memory ,
.Nd functions for reading streaming archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft int

View File

@ -119,7 +119,8 @@ file_read(struct archive *a, void *client_data, const void **buff)
if (bytes_read < 0) {
if (errno == EINTR)
continue;
archive_set_error(a, errno, "Error reading fd %d", mine->fd);
archive_set_error(a, errno, "Error reading fd %d",
mine->fd);
}
return (bytes_read);
}
@ -129,8 +130,8 @@ static int64_t
file_skip(struct archive *a, void *client_data, int64_t request)
{
struct read_fd_data *mine = (struct read_fd_data *)client_data;
off_t skip = (off_t)request;
off_t old_offset, new_offset;
int64_t skip = request;
int64_t old_offset, new_offset;
int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */
if (!mine->use_lseek)

View File

@ -108,11 +108,11 @@ static ssize_t
file_read(struct archive *a, void *client_data, const void **buff)
{
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
ssize_t bytes_read;
size_t bytes_read;
*buff = mine->buffer;
bytes_read = fread(mine->buffer, 1, mine->block_size, mine->f);
if (bytes_read < 0) {
if (bytes_read < mine->block_size && ferror(mine->f)) {
archive_set_error(a, errno, "Error reading file");
}
return (bytes_read);

View File

@ -60,11 +60,15 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_filename.c 201093 2009
#endif
#include "archive.h"
#include "archive_private.h"
#include "archive_string.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
struct read_file_data {
int fd;
@ -79,9 +83,10 @@ struct read_file_data {
} filename; /* Must be last! */
};
static int file_open(struct archive *, void *);
static int file_close(struct archive *, void *);
static int file_open_filename(struct archive *, enum fnt_e, const void *,
size_t);
static int file_close2(struct archive *, void *);
static int file_switch(struct archive *, void *, void *);
static ssize_t file_read(struct archive *, void *, const void **buff);
static int64_t file_seek(struct archive *, void *, int64_t request, int);
static int64_t file_skip(struct archive *, void *, int64_t request);
@ -98,26 +103,76 @@ int
archive_read_open_filename(struct archive *a, const char *filename,
size_t block_size)
{
enum fnt_e filename_type;
const char *filenames[2] = { filename, NULL };
return archive_read_open_filenames(a, filenames, block_size);
}
int
archive_read_open_filenames(struct archive *a, const char **filenames,
size_t block_size)
{
struct read_file_data *mine;
const char *filename = NULL;
if (filenames)
filename = *(filenames++);
archive_clear_error(a);
do
{
if (filename == NULL)
filename = "";
mine = (struct read_file_data *)calloc(1,
sizeof(*mine) + strlen(filename));
if (mine == NULL)
goto no_memory;
strcpy(mine->filename.m, filename);
mine->block_size = block_size;
mine->fd = -1;
mine->buffer = NULL;
mine->st_mode = mine->use_lseek = 0;
if (filename == NULL || filename[0] == '\0') {
filename_type = FNT_STDIN;
mine->filename_type = FNT_STDIN;
} else
filename_type = FNT_MBS;
return (file_open_filename(a, filename_type, filename, block_size));
mine->filename_type = FNT_MBS;
if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
return (ARCHIVE_FATAL);
if (filenames == NULL)
break;
filename = *(filenames++);
} while (filename != NULL && filename[0] != '\0');
archive_read_set_open_callback(a, file_open);
archive_read_set_read_callback(a, file_read);
archive_read_set_skip_callback(a, file_skip);
archive_read_set_close_callback(a, file_close);
archive_read_set_switch_callback(a, file_switch);
archive_read_set_seek_callback(a, file_seek);
return (archive_read_open1(a));
no_memory:
archive_set_error(a, ENOMEM, "No memory");
return (ARCHIVE_FATAL);
}
int
archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
size_t block_size)
{
enum fnt_e filename_type;
struct read_file_data *mine = (struct read_file_data *)calloc(1,
sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t));
if (!mine)
{
archive_set_error(a, ENOMEM, "No memory");
return (ARCHIVE_FATAL);
}
mine->fd = -1;
mine->block_size = block_size;
if (wfilename == NULL || wfilename[0] == L'\0') {
filename_type = FNT_STDIN;
mine->filename_type = FNT_STDIN;
} else {
#if defined(_WIN32) && !defined(__CYGWIN__)
filename_type = FNT_WCS;
mine->filename_type = FNT_WCS;
wcscpy(mine->filename.w, wfilename);
#else
/*
* POSIX system does not support a wchar_t interface for
@ -125,31 +180,43 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
* filename to multi-byte one and use it.
*/
struct archive_string fn;
int r;
archive_string_init(&fn);
if (archive_string_append_from_wcs(&fn, wfilename,
wcslen(wfilename)) != 0) {
if (errno == ENOMEM)
archive_set_error(a, errno,
"Can't allocate memory");
else
archive_set_error(a, EINVAL,
"Failed to convert a wide-character filename to"
" a multi-byte filename");
"Failed to convert a wide-character"
" filename to a multi-byte filename");
archive_string_free(&fn);
free(mine);
return (ARCHIVE_FATAL);
}
r = file_open_filename(a, FNT_MBS, fn.s, block_size);
mine->filename_type = FNT_MBS;
strcpy(mine->filename.m, fn.s);
archive_string_free(&fn);
return (r);
#endif
}
return (file_open_filename(a, filename_type, wfilename, block_size));
if (archive_read_append_callback_data(a, mine) != (ARCHIVE_OK))
return (ARCHIVE_FATAL);
archive_read_set_open_callback(a, file_open);
archive_read_set_read_callback(a, file_read);
archive_read_set_skip_callback(a, file_skip);
archive_read_set_close_callback(a, file_close);
archive_read_set_switch_callback(a, file_switch);
archive_read_set_seek_callback(a, file_seek);
return (archive_read_open1(a));
}
static int
file_open_filename(struct archive *a, enum fnt_e filename_type,
const void *_filename, size_t block_size)
file_open(struct archive *a, void *client_data)
{
struct stat st;
struct read_file_data *mine;
struct read_file_data *mine = (struct read_file_data *)client_data;
void *buffer;
const char *filename = NULL;
const wchar_t *wfilename = NULL;
@ -164,7 +231,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
#endif
archive_clear_error(a);
if (filename_type == FNT_STDIN) {
if (mine->filename_type == FNT_STDIN) {
/* We used to delegate stdin support by
* directly calling archive_read_open_fd(a,0,block_size)
* here, but that doesn't (and shouldn't) handle the
@ -179,9 +246,10 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
setmode(0, O_BINARY);
#endif
filename = "";
} else if (filename_type == FNT_MBS) {
filename = (const char *)_filename;
fd = open(filename, O_RDONLY | O_BINARY);
} else if (mine->filename_type == FNT_MBS) {
filename = mine->filename.m;
fd = open(filename, O_RDONLY | O_BINARY | O_CLOEXEC);
__archive_ensure_cloexec_flag(fd);
if (fd < 0) {
archive_set_error(a, errno,
"Failed to open '%s'", filename);
@ -189,7 +257,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
}
} else {
#if defined(_WIN32) && !defined(__CYGWIN__)
wfilename = (const wchar_t *)_filename;
wfilename = mine->filename.w;
fd = _wopen(wfilename, O_RDONLY | O_BINARY);
if (fd < 0 && errno == ENOENT) {
wchar_t *fullpath;
@ -211,7 +279,7 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
#endif
}
if (fstat(fd, &st) != 0) {
if (filename_type == FNT_WCS)
if (mine->filename_type == FNT_WCS)
archive_set_error(a, errno, "Can't stat '%S'",
wfilename);
else
@ -276,50 +344,32 @@ file_open_filename(struct archive *a, enum fnt_e filename_type,
#endif
/* TODO: Add an "is_tape_like" variable and appropriate tests. */
if (filename_type == FNT_WCS)
mine = (struct read_file_data *)calloc(1,
sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t));
else
mine = (struct read_file_data *)calloc(1,
sizeof(*mine) + strlen(filename));
/* Disk-like devices prefer power-of-two block sizes. */
/* Use provided block_size as a guide so users have some control. */
if (is_disk_like) {
size_t new_block_size = 64 * 1024;
while (new_block_size < block_size
while (new_block_size < mine->block_size
&& new_block_size < 64 * 1024 * 1024)
new_block_size *= 2;
block_size = new_block_size;
mine->block_size = new_block_size;
}
buffer = malloc(block_size);
buffer = malloc(mine->block_size);
if (mine == NULL || buffer == NULL) {
archive_set_error(a, ENOMEM, "No memory");
free(mine);
free(buffer);
return (ARCHIVE_FATAL);
}
if (filename_type == FNT_WCS)
wcscpy(mine->filename.w, wfilename);
else
strcpy(mine->filename.m, filename);
mine->filename_type = filename_type;
mine->block_size = block_size;
mine->buffer = buffer;
mine->fd = fd;
/* Remember mode so close can decide whether to flush. */
mine->st_mode = st.st_mode;
/* Disk-like inputs can use lseek(). */
if (is_disk_like) {
archive_read_set_seek_callback(a, file_seek);
if (is_disk_like)
mine->use_lseek = 1;
}
archive_read_set_read_callback(a, file_read);
archive_read_set_skip_callback(a, file_skip);
archive_read_set_close_callback(a, file_close);
archive_read_set_callback_data(a, mine);
return (archive_read_open1(a));
return (ARCHIVE_OK);
}
static ssize_t
@ -397,9 +447,7 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
/* TODO: Deal with case where off_t isn't 64 bits.
* This shouldn't be a problem on Linux or other POSIX
* systems, since the configuration logic for libarchive
* tries to obtain a 64-bit off_t. It's still an issue
* on Windows, though, so it might suffice to just use
* _lseeki64() on Windows.
* tries to obtain a 64-bit off_t.
*/
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
(new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
@ -450,7 +498,7 @@ static int64_t
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
{
struct read_file_data *mine = (struct read_file_data *)client_data;
off_t r;
int64_t r;
/* We use off_t here because lseek() is declared that way. */
/* See above for notes about when off_t is less than 64 bits. */
@ -471,7 +519,7 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence)
}
static int
file_close(struct archive *a, void *client_data)
file_close2(struct archive *a, void *client_data)
{
struct read_file_data *mine = (struct read_file_data *)client_data;
@ -504,6 +552,23 @@ file_close(struct archive *a, void *client_data)
close(mine->fd);
}
free(mine->buffer);
mine->buffer = NULL;
mine->fd = -1;
return (ARCHIVE_OK);
}
static int
file_close(struct archive *a, void *client_data)
{
struct read_file_data *mine = (struct read_file_data *)client_data;
file_close2(a, client_data);
free(mine);
return (ARCHIVE_OK);
}
static int
file_switch(struct archive *a, void *client_data1, void *client_data2)
{
file_close2(a, client_data1);
return file_open(a, client_data2);
}

View File

@ -149,6 +149,7 @@ memory_read_seek(struct archive *a, void *client_data, int64_t offset, int whenc
{
struct read_memory_data *mine = (struct read_memory_data *)client_data;
(void)a; /* UNUSED */
switch (whence) {
case SEEK_SET:
mine->p = mine->start + offset;

View File

@ -58,6 +58,8 @@ struct archive_read_filter;
struct archive_read_filter_bidder {
/* Configuration data for the bidder. */
void *data;
/* Name of the filter */
const char *name;
/* Taste the upstream filter to see if we handle this. */
int (*bid)(struct archive_read_filter_bidder *,
struct archive_read_filter *);
@ -82,6 +84,8 @@ struct archive_read_filter {
struct archive_read_filter_bidder *bidder; /* My bidder. */
struct archive_read_filter *upstream; /* Who I read from. */
struct archive_read *archive; /* Associated archive. */
/* Open a block for reading */
int (*open)(struct archive_read_filter *self);
/* Return next block. */
ssize_t (*read)(struct archive_read_filter *, const void **);
/* Skip forward this many bytes. */
@ -90,6 +94,8 @@ struct archive_read_filter {
int64_t (*seek)(struct archive_read_filter *self, int64_t offset, int whence);
/* Close (just this filter) and free(self). */
int (*close)(struct archive_read_filter *self);
/* Function that handles switching from reading one block to the next/prev */
int (*sswitch)(struct archive_read_filter *self, unsigned int iindex);
/* My private data. */
void *data;
@ -118,13 +124,22 @@ struct archive_read_filter {
* transformation filters. This will probably break the API/ABI and
* so should be deferred at least until libarchive 3.0.
*/
struct archive_read_data_node {
int64_t begin_position;
int64_t total_size;
void *data;
};
struct archive_read_client {
archive_open_callback *opener;
archive_read_callback *reader;
archive_skip_callback *skipper;
archive_seek_callback *seeker;
archive_close_callback *closer;
void *data;
archive_switch_callback *switcher;
unsigned int nodes;
unsigned int cursor;
int64_t position;
struct archive_read_data_node *dataset;
};
struct archive_read {
@ -134,8 +149,8 @@ struct archive_read {
/* Dev/ino of the archive being read/written. */
int skip_file_set;
dev_t skip_file_dev;
ino_t skip_file_ino;
int64_t skip_file_dev;
int64_t skip_file_ino;
/*
* Used by archive_read_data() to track blocks and copy
@ -146,18 +161,33 @@ struct archive_read {
int64_t read_data_output_offset;
size_t read_data_remaining;
/* Callbacks to open/read/write/close client archive stream. */
/*
* Used by formats/filters to determine the amount of data
* requested from a call to archive_read_data(). This is only
* useful when the format/filter has seek support.
*/
char read_data_is_posix_read;
size_t read_data_requested;
/* Callbacks to open/read/write/close client archive streams. */
struct archive_read_client client;
/* Registered filter bidders. */
struct archive_read_filter_bidder bidders[9];
struct archive_read_filter_bidder bidders[14];
/* Last filter in chain */
struct archive_read_filter *filter;
/* Whether to bypass filter bidding process */
int bypass_filter_bidding;
/* File offset of beginning of most recently-read header. */
int64_t header_position;
/* Nodes and offsets of compressed data block */
unsigned int data_start_node;
unsigned int data_end_node;
/*
* Format detection is mostly the same as compression
* detection, with one significant difference: The bidders
@ -175,6 +205,7 @@ struct archive_read {
int (*read_header)(struct archive_read *, struct archive_entry *);
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *);
int (*read_data_skip)(struct archive_read *);
int64_t (*seek_data)(struct archive_read *, int64_t, int);
int (*cleanup)(struct archive_read *);
} formats[16];
struct archive_format_descriptor *format; /* Active format. */
@ -194,6 +225,7 @@ int __archive_read_register_format(struct archive_read *a,
int (*read_header)(struct archive_read *, struct archive_entry *),
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *),
int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *));
int __archive_read_get_bidder(struct archive_read *a,
@ -207,4 +239,6 @@ int64_t __archive_read_filter_seek(struct archive_read_filter *, int64_t, int);
int64_t __archive_read_consume(struct archive_read *, int64_t);
int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t);
int __archive_read_program(struct archive_read_filter *, const char *);
void __archive_read_free_filters(struct archive_read *);
int __archive_read_close_filters(struct archive_read *);
#endif

View File

@ -0,0 +1,105 @@
/*-
* Copyright (c) 2003-2012 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include "archive.h"
#include "archive_private.h"
#include "archive_read_private.h"
int
archive_read_set_format(struct archive *_a, int code)
{
int r1, r2, slots, i;
char str[10];
struct archive_read *a = (struct archive_read *)_a;
if ((r1 = archive_read_support_format_by_code(_a, code)) < (ARCHIVE_OK))
return r1;
r1 = r2 = (ARCHIVE_OK);
if (a->format)
r2 = (ARCHIVE_WARN);
switch (code & ARCHIVE_FORMAT_BASE_MASK)
{
case ARCHIVE_FORMAT_7ZIP:
strcpy(str, "7zip");
break;
case ARCHIVE_FORMAT_AR:
strcpy(str, "ar");
break;
case ARCHIVE_FORMAT_CAB:
strcpy(str, "cab");
break;
case ARCHIVE_FORMAT_CPIO:
strcpy(str, "cpio");
break;
case ARCHIVE_FORMAT_ISO9660:
strcpy(str, "iso9660");
break;
case ARCHIVE_FORMAT_LHA:
strcpy(str, "lha");
break;
case ARCHIVE_FORMAT_MTREE:
strcpy(str, "mtree");
break;
case ARCHIVE_FORMAT_RAR:
strcpy(str, "rar");
break;
case ARCHIVE_FORMAT_TAR:
strcpy(str, "tar");
break;
case ARCHIVE_FORMAT_XAR:
strcpy(str, "xar");
break;
case ARCHIVE_FORMAT_ZIP:
strcpy(str, "zip");
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Invalid format code specified");
return (ARCHIVE_FATAL);
}
slots = sizeof(a->formats) / sizeof(a->formats[0]);
a->format = &(a->formats[0]);
for (i = 0; i < slots; i++, a->format++) {
if (!a->format->name || !strcmp(a->format->name, str))
break;
}
if (!a->format->name || strcmp(a->format->name, str))
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Internal error: Unable to set format");
r1 = (ARCHIVE_FATAL);
}
return (r1 < r2) ? r1 : r2;
}

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd April 13, 2009
.Dd February 2, 2012
.Dt ARCHIVE_READ_OPTIONS 3
.Os
.Sh NAME
@ -34,6 +34,8 @@
.Nm archive_read_set_options
.Nd functions controlling options for reading archives
.\"
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.Ft int
.Fo archive_read_set_filter_option

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_format_descriptor *format;
size_t i;
int r, rv = ARCHIVE_FAILED;
int r, rv = ARCHIVE_WARN;
for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) {
format = &a->formats[i];
@ -102,6 +102,10 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
if (r == ARCHIVE_OK)
rv = ARCHIVE_OK;
}
/* If the format name didn't match, return a special code for
* _archive_set_option[s]. */
if (rv == ARCHIVE_WARN && m != NULL)
rv = ARCHIVE_WARN - 1;
return (rv);
}
@ -112,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_filter *filter;
struct archive_read_filter_bidder *bidder;
int r, rv = ARCHIVE_FAILED;
int r, rv = ARCHIVE_WARN;
for (filter = a->filter; filter != NULL; filter = filter->upstream) {
bidder = filter->bidder;
@ -135,6 +139,10 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o,
if (r == ARCHIVE_OK)
rv = ARCHIVE_OK;
}
/* If the filter name didn't match, return a special code for
* _archive_set_option[s]. */
if (rv == ARCHIVE_WARN && m != NULL)
rv = ARCHIVE_WARN - 1;
return (rv);
}

View File

@ -48,7 +48,7 @@ archive_read_support_filter_all(struct archive *a)
archive_read_support_filter_bzip2(a);
/* The decompress code doesn't use an outside library. */
archive_read_support_filter_compress(a);
/* Gzip decompress falls back to "gunzip" command-line. */
/* Gzip decompress falls back to "gzip -d" command-line. */
archive_read_support_filter_gzip(a);
/* Lzip falls back to "unlzip" command-line program. */
archive_read_support_filter_lzip(a);
@ -63,6 +63,12 @@ archive_read_support_filter_all(struct archive *a)
archive_read_support_filter_uu(a);
/* The decode code doesn't use an outside library. */
archive_read_support_filter_rpm(a);
/* The decode code always uses "lrzip -q -d" command-line. */
archive_read_support_filter_lrzip(a);
/* Lzop decompress falls back to "lzop -d" command-line. */
archive_read_support_filter_lzop(a);
/* The decode code always uses "grzip -d" command-line. */
archive_read_support_filter_grzip(a);
/* Note: We always return ARCHIVE_OK here, even if some of the
* above return ARCHIVE_WARN. The intent here is to enable

View File

@ -94,6 +94,7 @@ archive_read_support_filter_bzip2(struct archive *_a)
return (ARCHIVE_FATAL);
reader->data = NULL;
reader->name = "bzip2";
reader->bid = bzip2_reader_bid;
reader->init = bzip2_reader_init;
reader->options = NULL;
@ -102,7 +103,7 @@ archive_read_support_filter_bzip2(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
"Using external bunzip2 program");
"Using external bzip2 program");
return (ARCHIVE_WARN);
#endif
}
@ -170,11 +171,11 @@ bzip2_reader_init(struct archive_read_filter *self)
{
int r;
r = __archive_read_program(self, "bunzip2");
r = __archive_read_program(self, "bzip2 -d");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
self->code = ARCHIVE_COMPRESSION_BZIP2;
self->code = ARCHIVE_FILTER_BZIP2;
self->name = "bzip2";
return (r);
}
@ -192,7 +193,7 @@ bzip2_reader_init(struct archive_read_filter *self)
void *out_block;
struct private_data *state;
self->code = ARCHIVE_COMPRESSION_BZIP2;
self->code = ARCHIVE_FILTER_BZIP2;
self->name = "bzip2";
state = (struct private_data *)calloc(sizeof(*state), 1);

View File

@ -163,6 +163,7 @@ archive_read_support_filter_compress(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
bidder->name = "compress (.Z)";
bidder->bid = compress_bidder_bid;
bidder->init = compress_bidder_init;
bidder->options = NULL;
@ -212,7 +213,7 @@ compress_bidder_init(struct archive_read_filter *self)
void *out_block;
int code;
self->code = ARCHIVE_COMPRESSION_COMPRESS;
self->code = ARCHIVE_FILTER_COMPRESS;
self->name = "compress (.Z)";
state = (struct private_data *)calloc(sizeof(*state), 1);

View File

@ -0,0 +1,121 @@
/*-
* Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "archive.h"
#include "archive_private.h"
#include "archive_read_private.h"
static const unsigned char grzip_magic[] = {
0x47, 0x52, 0x5a, 0x69, 0x70, 0x49, 0x49, 0x00,
0x02, 0x04, 0x3a, 0x29 };
static int grzip_bidder_bid(struct archive_read_filter_bidder *,
struct archive_read_filter *);
static int grzip_bidder_init(struct archive_read_filter *);
static int
grzip_reader_free(struct archive_read_filter_bidder *self)
{
(void)self; /* UNUSED */
return (ARCHIVE_OK);
}
int
archive_read_support_filter_grzip(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter_bidder *reader;
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
ARCHIVE_STATE_NEW, "archive_read_support_filter_grzip");
if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
reader->data = NULL;
reader->bid = grzip_bidder_bid;
reader->init = grzip_bidder_init;
reader->options = NULL;
reader->free = grzip_reader_free;
/* This filter always uses an external program. */
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
"Using external grzip program for grzip decompression");
return (ARCHIVE_WARN);
}
/*
* Bidder just verifies the header and returns the number of verified bits.
*/
static int
grzip_bidder_bid(struct archive_read_filter_bidder *self,
struct archive_read_filter *filter)
{
const unsigned char *p;
ssize_t avail;
(void)self; /* UNUSED */
p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), &avail);
if (p == NULL || avail == 0)
return (0);
if (memcmp(p, grzip_magic, sizeof(grzip_magic)))
return (0);
return (sizeof(grzip_magic) * 8);
}
static int
grzip_bidder_init(struct archive_read_filter *self)
{
int r;
r = __archive_read_program(self, "grzip -d");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
self->code = ARCHIVE_FILTER_GRZIP;
self->name = "grzip";
return (r);
}

View File

@ -72,7 +72,7 @@ static int gzip_filter_close(struct archive_read_filter *);
*
* TODO: If zlib is unavailable, gzip_bidder_init() should
* use the compress_program framework to try to fire up an external
* gunzip program.
* gzip program.
*/
static int gzip_bidder_bid(struct archive_read_filter_bidder *,
struct archive_read_filter *);
@ -100,6 +100,7 @@ archive_read_support_filter_gzip(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
bidder->name = "gzip";
bidder->bid = gzip_bidder_bid;
bidder->init = gzip_bidder_init;
bidder->options = NULL;
@ -109,7 +110,7 @@ archive_read_support_filter_gzip(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
"Using external gunzip program");
"Using external gzip program");
return (ARCHIVE_WARN);
#endif
}
@ -121,7 +122,7 @@ archive_read_support_filter_gzip(struct archive *_a)
* number of bytes in header. If pbits is non-NULL, it receives a
* count of bits verified, suitable for use by bidder.
*/
static int
static ssize_t
peek_at_header(struct archive_read_filter *filter, int *pbits)
{
const unsigned char *p;
@ -223,7 +224,7 @@ gzip_bidder_bid(struct archive_read_filter_bidder *self,
/*
* If we don't have the library on this system, we can't do the
* decompression directly. We can, however, try to run gunzip
* decompression directly. We can, however, try to run "gzip -d"
* in case that's available.
*/
static int
@ -231,11 +232,11 @@ gzip_bidder_init(struct archive_read_filter *self)
{
int r;
r = __archive_read_program(self, "gunzip");
r = __archive_read_program(self, "gzip -d");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
self->code = ARCHIVE_COMPRESSION_GZIP;
self->code = ARCHIVE_FILTER_GZIP;
self->name = "gzip";
return (r);
}
@ -252,7 +253,7 @@ gzip_bidder_init(struct archive_read_filter *self)
static const size_t out_block_size = 64 * 1024;
void *out_block;
self->code = ARCHIVE_COMPRESSION_GZIP;
self->code = ARCHIVE_FILTER_GZIP;
self->name = "gzip";
state = (struct private_data *)calloc(sizeof(*state), 1);
@ -299,7 +300,7 @@ consume_header(struct archive_read_filter *self)
/* Initialize compression library. */
state->stream.next_in = (unsigned char *)(uintptr_t)
__archive_read_filter_ahead(self->upstream, 1, &avail);
state->stream.avail_in = avail;
state->stream.avail_in = (uInt)avail;
ret = inflateInit2(&(state->stream),
-15 /* Don't check for zlib header */);
@ -380,7 +381,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
/* Empty our output buffer. */
state->stream.next_out = state->out_block;
state->stream.avail_out = state->out_block_size;
state->stream.avail_out = (uInt)state->out_block_size;
/* Try to fill the output buffer. */
while (state->stream.avail_out > 0 && !state->eof) {
@ -407,7 +408,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
"truncated gzip input");
return (ARCHIVE_FATAL);
}
state->stream.avail_in = avail_in;
state->stream.avail_in = (uInt)avail_in;
/* Decompress and consume some of that data. */
ret = inflate(&(state->stream), 0);

View File

@ -0,0 +1,132 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "archive.h"
#include "archive_private.h"
#include "archive_read_private.h"
#define LRZIP_HEADER_MAGIC "LRZI"
#define LRZIP_HEADER_MAGIC_LEN 4
static int lrzip_bidder_bid(struct archive_read_filter_bidder *,
struct archive_read_filter *);
static int lrzip_bidder_init(struct archive_read_filter *);
static int
lrzip_reader_free(struct archive_read_filter_bidder *self)
{
(void)self; /* UNUSED */
return (ARCHIVE_OK);
}
int
archive_read_support_filter_lrzip(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter_bidder *reader;
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
ARCHIVE_STATE_NEW, "archive_read_support_filter_lrzip");
if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
reader->data = NULL;
reader->name = "lrzip";
reader->bid = lrzip_bidder_bid;
reader->init = lrzip_bidder_init;
reader->options = NULL;
reader->free = lrzip_reader_free;
/* This filter always uses an external program. */
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
"Using external lrzip program for lrzip decompression");
return (ARCHIVE_WARN);
}
/*
* Bidder just verifies the header and returns the number of verified bits.
*/
static int
lrzip_bidder_bid(struct archive_read_filter_bidder *self,
struct archive_read_filter *filter)
{
const unsigned char *p;
ssize_t avail, len;
int i;
(void)self; /* UNUSED */
/* Start by looking at the first six bytes of the header, which
* is all fixed layout. */
len = 6;
p = __archive_read_filter_ahead(filter, len, &avail);
if (p == NULL || avail == 0)
return (0);
if (memcmp(p, LRZIP_HEADER_MAGIC, LRZIP_HEADER_MAGIC_LEN))
return (0);
/* current major version is always 0, verify this */
if (p[LRZIP_HEADER_MAGIC_LEN])
return 0;
/* support only v0.6+ lrzip for sanity */
i = p[LRZIP_HEADER_MAGIC_LEN + 1];
if ((i < 6) || (i > 10))
return 0;
return (int)len;
}
static int
lrzip_bidder_init(struct archive_read_filter *self)
{
int r;
r = __archive_read_program(self, "lrzip -d -q");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
self->code = ARCHIVE_FILTER_LRZIP;
self->name = "lrzip";
return (r);
}

View File

@ -0,0 +1,486 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_LZO_LZOCONF_H
#include <lzo/lzoconf.h>
#endif
#ifdef HAVE_LZO_LZO1X_H
#include <lzo/lzo1x.h>
#endif
#ifdef HAVE_ZLIB_H
#include <zlib.h> /* for crc32 and adler32 */
#endif
#include "archive.h"
#if !defined(HAVE_ZLIB_H) &&\
defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
#include "archive_crc32.h"
#endif
#include "archive_endian.h"
#include "archive_private.h"
#include "archive_read_private.h"
#ifndef HAVE_ZLIB_H
#define adler32 lzo_adler32
#endif
#define LZOP_HEADER_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a"
#define LZOP_HEADER_MAGIC_LEN 9
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
struct read_lzop {
unsigned char *out_block;
size_t out_block_size;
int64_t total_out;
int flags;
uint32_t compressed_cksum;
uint32_t uncompressed_cksum;
size_t compressed_size;
size_t uncompressed_size;
size_t unconsumed_bytes;
char in_stream;
char eof; /* True = found end of compressed data. */
};
#define FILTER 0x0800
#define CRC32_HEADER 0x1000
#define EXTRA_FIELD 0x0040
#define ADLER32_UNCOMPRESSED 0x0001
#define ADLER32_COMPRESSED 0x0002
#define CRC32_UNCOMPRESSED 0x0100
#define CRC32_COMPRESSED 0x0200
#define MAX_BLOCK_SIZE (64 * 1024 * 1024)
static ssize_t lzop_filter_read(struct archive_read_filter *, const void **);
static int lzop_filter_close(struct archive_read_filter *);
#endif
static int lzop_bidder_bid(struct archive_read_filter_bidder *,
struct archive_read_filter *);
static int lzop_bidder_init(struct archive_read_filter *);
int
archive_read_support_filter_lzop(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter_bidder *reader;
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
ARCHIVE_STATE_NEW, "archive_read_support_filter_lzop");
if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
reader->data = NULL;
reader->bid = lzop_bidder_bid;
reader->init = lzop_bidder_init;
reader->options = NULL;
reader->free = NULL;
/* Signal the extent of lzop support with the return value here. */
#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
return (ARCHIVE_OK);
#else
/* Return ARCHIVE_WARN since this always uses an external program. */
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
"Using external lzop program for lzop decompression");
return (ARCHIVE_WARN);
#endif
}
/*
* Bidder just verifies the header and returns the number of verified bits.
*/
static int
lzop_bidder_bid(struct archive_read_filter_bidder *self,
struct archive_read_filter *filter)
{
const unsigned char *p;
ssize_t avail;
(void)self; /* UNUSED */
p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail);
if (p == NULL || avail == 0)
return (0);
if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN))
return (0);
return (LZOP_HEADER_MAGIC_LEN * 8);
}
#if !defined(HAVE_LZO_LZOCONF_H) || !defined(HAVE_LZO_LZO1X_H)
/*
* If we don't have the library on this system, we can't do the
* decompression directly. We can, however, try to run "lzop -d"
* in case that's available.
*/
static int
lzop_bidder_init(struct archive_read_filter *self)
{
int r;
r = __archive_read_program(self, "lzop -d");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
self->code = ARCHIVE_FILTER_LZOP;
self->name = "lzop";
return (r);
}
#else
/*
* Initialize the filter object.
*/
static int
lzop_bidder_init(struct archive_read_filter *self)
{
struct read_lzop *state;
self->code = ARCHIVE_FILTER_LZOP;
self->name = "lzop";
state = (struct read_lzop *)calloc(sizeof(*state), 1);
if (state == NULL) {
archive_set_error(&self->archive->archive, ENOMEM,
"Can't allocate data for lzop decompression");
return (ARCHIVE_FATAL);
}
self->data = state;
self->read = lzop_filter_read;
self->skip = NULL; /* not supported */
self->close = lzop_filter_close;
return (ARCHIVE_OK);
}
static int
consume_header(struct archive_read_filter *self)
{
struct read_lzop *state = (struct read_lzop *)self->data;
const unsigned char *p, *_p;
unsigned checksum, flags, len, method, version;
/*
* Check LZOP magic code.
*/
p = __archive_read_filter_ahead(self->upstream,
LZOP_HEADER_MAGIC_LEN, NULL);
if (p == NULL)
return (ARCHIVE_EOF);
if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN))
return (ARCHIVE_EOF);
__archive_read_filter_consume(self->upstream,
LZOP_HEADER_MAGIC_LEN);
p = __archive_read_filter_ahead(self->upstream, 29, NULL);
if (p == NULL)
goto truncated;
_p = p;
version = archive_be16dec(p);
p += 4;/* version(2 bytes) + library version(2 bytes) */
if (version >= 0x940) {
unsigned reqversion = archive_be16dec(p); p += 2;
if (reqversion < 0x900) {
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC, "Invalid required version");
return (ARCHIVE_FAILED);
}
}
method = *p++;
if (method < 1 || method > 3) {
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
"Unsupported method");
return (ARCHIVE_FAILED);
}
if (version >= 0x940) {
unsigned level = *p++;
if (method == 1 && level == 0) level = 3;
if (method == 2 && level == 0) level = 1;
if (method == 3 && level == 0) level = 9;
if (level < 1 && level > 9) {
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC, "Invalid level");
return (ARCHIVE_FAILED);
}
}
flags = archive_be32dec(p); p += 4;
if (flags & FILTER)
p += 4; /* Skip filter */
p += 4; /* Skip mode */
if (version >= 0x940)
p += 8; /* Skip mtime */
else
p += 4; /* Skip mtime */
len = *p++; /* Read filename length */
len += p - _p;
/* Make sure we have all bytes we need to calculate checksum. */
p = __archive_read_filter_ahead(self->upstream, len + 4, NULL);
if (p == NULL)
goto truncated;
if (flags & CRC32_HEADER)
checksum = crc32(crc32(0, NULL, 0), p, len);
else
checksum = adler32(adler32(0, NULL, 0), p, len);
if (archive_be32dec(p + len) != checksum)
goto corrupted;
__archive_read_filter_consume(self->upstream, len + 4);
if (flags & EXTRA_FIELD) {
/* Skip extra field */
p = __archive_read_filter_ahead(self->upstream, 4, NULL);
if (p == NULL)
goto truncated;
len = archive_be32dec(p);
__archive_read_filter_consume(self->upstream, len + 4 + 4);
}
state->flags = flags;
state->in_stream = 1;
return (ARCHIVE_OK);
truncated:
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
return (ARCHIVE_FAILED);
corrupted:
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header");
return (ARCHIVE_FAILED);
}
static int
consume_block_info(struct archive_read_filter *self)
{
struct read_lzop *state = (struct read_lzop *)self->data;
const unsigned char *p;
unsigned flags = state->flags;
p = __archive_read_filter_ahead(self->upstream, 4, NULL);
if (p == NULL)
goto truncated;
state->uncompressed_size = archive_be32dec(p);
__archive_read_filter_consume(self->upstream, 4);
if (state->uncompressed_size == 0)
return (ARCHIVE_EOF);
if (state->uncompressed_size > MAX_BLOCK_SIZE)
goto corrupted;
p = __archive_read_filter_ahead(self->upstream, 4, NULL);
if (p == NULL)
goto truncated;
state->compressed_size = archive_be32dec(p);
__archive_read_filter_consume(self->upstream, 4);
if (state->compressed_size > state->uncompressed_size)
goto corrupted;
if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) {
p = __archive_read_filter_ahead(self->upstream, 4, NULL);
if (p == NULL)
goto truncated;
state->compressed_cksum = state->uncompressed_cksum =
archive_be32dec(p);
__archive_read_filter_consume(self->upstream, 4);
}
if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) &&
state->compressed_size < state->uncompressed_size) {
p = __archive_read_filter_ahead(self->upstream, 4, NULL);
if (p == NULL)
goto truncated;
state->compressed_cksum = archive_be32dec(p);
__archive_read_filter_consume(self->upstream, 4);
}
return (ARCHIVE_OK);
truncated:
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
return (ARCHIVE_FAILED);
corrupted:
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header");
return (ARCHIVE_FAILED);
}
static ssize_t
lzop_filter_read(struct archive_read_filter *self, const void **p)
{
struct read_lzop *state = (struct read_lzop *)self->data;
const void *b;
lzo_uint out_size;
uint32_t cksum;
int ret, r;
if (state->unconsumed_bytes) {
__archive_read_filter_consume(self->upstream,
state->unconsumed_bytes);
state->unconsumed_bytes = 0;
}
if (state->eof)
return (0);
for (;;) {
if (!state->in_stream) {
ret = consume_header(self);
if (ret < ARCHIVE_OK)
return (ret);
if (ret == ARCHIVE_EOF) {
state->eof = 1;
return (0);
}
}
ret = consume_block_info(self);
if (ret < ARCHIVE_OK)
return (ret);
if (ret == ARCHIVE_EOF)
state->in_stream = 0;
else
break;
}
if (state->out_block == NULL ||
state->out_block_size < state->uncompressed_size) {
void *new_block;
new_block = realloc(state->out_block, state->uncompressed_size);
if (new_block == NULL) {
archive_set_error(&self->archive->archive, ENOMEM,
"Can't allocate data for lzop decompression");
return (ARCHIVE_FATAL);
}
state->out_block = new_block;
state->out_block_size = state->uncompressed_size;
}
b = __archive_read_filter_ahead(self->upstream,
state->compressed_size, NULL);
if (b == NULL) {
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data");
return (ARCHIVE_FATAL);
}
if (state->flags & CRC32_COMPRESSED)
cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size);
else if (state->flags & ADLER32_COMPRESSED)
cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size);
else
cksum = state->compressed_cksum;
if (cksum != state->compressed_cksum) {
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC, "Corrupted data");
return (ARCHIVE_FATAL);
}
/*
* If the both uncompressed size and compressed size are the same,
* we do not decompress this block.
*/
if (state->uncompressed_size == state->compressed_size) {
*p = b;
state->total_out += state->compressed_size;
state->unconsumed_bytes = state->compressed_size;
return ((ssize_t)state->uncompressed_size);
}
/*
* Drive lzo uncompresison.
*/
out_size = (lzo_uint)state->uncompressed_size;
r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size,
state->out_block, &out_size, NULL);
switch (r) {
case LZO_E_OK:
if (out_size == state->uncompressed_size)
break;
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC, "Corrupted data");
return (ARCHIVE_FATAL);
case LZO_E_OUT_OF_MEMORY:
archive_set_error(&self->archive->archive, ENOMEM,
"lzop decompression failed: out of memory");
return (ARCHIVE_FATAL);
default:
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
"lzop decompression failed: %d", r);
return (ARCHIVE_FATAL);
}
if (state->flags & CRC32_UNCOMPRESSED)
cksum = crc32(crc32(0, NULL, 0), state->out_block,
state->uncompressed_size);
else if (state->flags & ADLER32_UNCOMPRESSED)
cksum = adler32(adler32(0, NULL, 0), state->out_block,
state->uncompressed_size);
else
cksum = state->uncompressed_cksum;
if (cksum != state->uncompressed_cksum) {
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC, "Corrupted data");
return (ARCHIVE_FATAL);
}
__archive_read_filter_consume(self->upstream, state->compressed_size);
*p = state->out_block;
state->total_out += out_size;
return ((ssize_t)out_size);
}
/*
* Clean up the decompressor.
*/
static int
lzop_filter_close(struct archive_read_filter *self)
{
struct read_lzop *state = (struct read_lzop *)self->data;
free(state->out_block);
free(state);
return (ARCHIVE_OK);
}
#endif

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2007 Joerg Sonnenberger
* Copyright (c) 2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -53,7 +54,9 @@ __FBSDID("$FreeBSD$");
#include "archive.h"
#include "archive_private.h"
#include "archive_string.h"
#include "archive_read_private.h"
#include "filter_fork.h"
#if ARCHIVE_VERSION_NUMBER < 4000000
@ -79,50 +82,13 @@ archive_read_support_filter_program(struct archive *a, const char *cmd)
return (archive_read_support_filter_program_signature(a, cmd, NULL, 0));
}
/* This capability is only available on POSIX systems. */
#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
!(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__))
/*
* On non-Posix systems, allow the program to build, but choke if
* this function is actually invoked.
*/
int
archive_read_support_filter_program_signature(struct archive *_a,
const char *cmd, const void *signature, size_t signature_len)
{
(void)_a; /* UNUSED */
(void)cmd; /* UNUSED */
(void)signature; /* UNUSED */
(void)signature_len; /* UNUSED */
archive_set_error(_a, -1,
"External compression programs not supported on this platform");
return (ARCHIVE_FATAL);
}
int
__archive_read_program(struct archive_read_filter *self, const char *cmd)
{
(void)self; /* UNUSED */
(void)cmd; /* UNUSED */
archive_set_error(&self->archive->archive, -1,
"External compression programs not supported on this platform");
return (ARCHIVE_FATAL);
}
#else
#include "filter_fork.h"
/*
* The bidder object stores the command and the signature to watch for.
* The 'inhibit' entry here is used to ensure that unchecked filters never
* bid twice in the same pipeline.
*/
struct program_bidder {
char *description;
char *cmd;
void *signature;
size_t signature_len;
@ -138,8 +104,12 @@ static int program_bidder_free(struct archive_read_filter_bidder *);
* The actual filter needs to track input and output data.
*/
struct program_filter {
char *description;
struct archive_string description;
#if defined(_WIN32) && !defined(__CYGWIN__)
HANDLE child;
#else
pid_t child;
#endif
int exit_status;
int waitpid_return;
int child_stdin, child_stdout;
@ -151,6 +121,29 @@ struct program_filter {
static ssize_t program_filter_read(struct archive_read_filter *,
const void **);
static int program_filter_close(struct archive_read_filter *);
static void free_state(struct program_bidder *);
static int
set_bidder_signature(struct archive_read_filter_bidder *bidder,
struct program_bidder *state, const void *signature, size_t signature_len)
{
if (signature != NULL && signature_len > 0) {
state->signature_len = signature_len;
state->signature = malloc(signature_len);
memcpy(state->signature, signature, signature_len);
}
/*
* Fill in the bidder object.
*/
bidder->data = state;
bidder->bid = program_bidder_bid;
bidder->init = program_bidder_init;
bidder->options = NULL;
bidder->free = program_bidder_free;
return (ARCHIVE_OK);
}
int
archive_read_support_filter_program_signature(struct archive *_a,
@ -169,35 +162,38 @@ archive_read_support_filter_program_signature(struct archive *_a,
/*
* Allocate our private state.
*/
state = (struct program_bidder *)calloc(sizeof (*state), 1);
state = (struct program_bidder *)calloc(1, sizeof (*state));
if (state == NULL)
return (ARCHIVE_FATAL);
goto memerr;
state->cmd = strdup(cmd);
if (signature != NULL && signature_len > 0) {
state->signature_len = signature_len;
state->signature = malloc(signature_len);
memcpy(state->signature, signature, signature_len);
}
if (state->cmd == NULL)
goto memerr;
/*
* Fill in the bidder object.
*/
bidder->data = state;
bidder->bid = program_bidder_bid;
bidder->init = program_bidder_init;
bidder->options = NULL;
bidder->free = program_bidder_free;
return (ARCHIVE_OK);
return set_bidder_signature(bidder, state, signature, signature_len);
memerr:
free_state(state);
archive_set_error(_a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
static int
program_bidder_free(struct archive_read_filter_bidder *self)
{
struct program_bidder *state = (struct program_bidder *)self->data;
free_state(state);
return (ARCHIVE_OK);
}
static void
free_state(struct program_bidder *state)
{
if (state) {
free(state->cmd);
free(state->signature);
free(self->data);
return (ARCHIVE_OK);
free(state);
}
}
/*
@ -258,6 +254,9 @@ child_stop(struct archive_read_filter *self, struct program_filter *state)
state->waitpid_return
= waitpid(state->child, &state->exit_status, 0);
} while (state->waitpid_return == -1 && errno == EINTR);
#if defined(_WIN32) && !defined(__CYGWIN__)
CloseHandle(state->child);
#endif
state->child = 0;
}
@ -310,11 +309,35 @@ child_read(struct archive_read_filter *self, char *buf, size_t buf_len)
struct program_filter *state = self->data;
ssize_t ret, requested, avail;
const char *p;
#if defined(_WIN32) && !defined(__CYGWIN__)
HANDLE handle = (HANDLE)_get_osfhandle(state->child_stdout);
#endif
requested = buf_len > SSIZE_MAX ? SSIZE_MAX : buf_len;
for (;;) {
do {
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Avoid infinity wait.
* Note: If there is no data in the pipe, ReadFile()
* called in read() never returns and so we won't
* write remaining encoded data to the pipe.
* Note: This way may cause performance problem.
* we are looking forward to great code to resolve
* this. */
DWORD pipe_avail = -1;
int cnt = 2;
while (PeekNamedPipe(handle, NULL, 0, NULL,
&pipe_avail, NULL) != 0 && pipe_avail == 0 &&
cnt--)
Sleep(5);
if (pipe_avail == 0) {
ret = -1;
errno = EAGAIN;
break;
}
#endif
ret = read(state->child_stdout, buf, requested);
} while (ret == -1 && errno == EINTR);
@ -376,38 +399,57 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
struct program_filter *state;
static const size_t out_buf_len = 65536;
char *out_buf;
char *description;
const char *prefix = "Program: ";
pid_t child;
size_t l;
l = strlen(prefix) + strlen(cmd) + 1;
state = (struct program_filter *)calloc(1, sizeof(*state));
out_buf = (char *)malloc(out_buf_len);
description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1);
if (state == NULL || out_buf == NULL || description == NULL) {
if (state == NULL || out_buf == NULL ||
archive_string_ensure(&state->description, l) == NULL) {
archive_set_error(&self->archive->archive, ENOMEM,
"Can't allocate input data");
if (state != NULL) {
archive_string_free(&state->description);
free(state);
}
free(out_buf);
free(description);
return (ARCHIVE_FATAL);
}
archive_strcpy(&state->description, prefix);
archive_strcat(&state->description, cmd);
self->code = ARCHIVE_COMPRESSION_PROGRAM;
state->description = description;
strcpy(state->description, prefix);
strcat(state->description, cmd);
self->name = state->description;
self->code = ARCHIVE_FILTER_PROGRAM;
self->name = state->description.s;
state->out_buf = out_buf;
state->out_buf_len = out_buf_len;
if ((state->child = __archive_create_child(cmd,
&state->child_stdin, &state->child_stdout)) == -1) {
child = __archive_create_child(cmd, &state->child_stdin,
&state->child_stdout);
if (child == -1) {
free(state->out_buf);
free(state);
archive_set_error(&self->archive->archive, EINVAL,
"Can't initialize filter; unable to run program \"%s\"", cmd);
"Can't initialize filter; unable to run program \"%s\"",
cmd);
return (ARCHIVE_FATAL);
}
#if defined(_WIN32) && !defined(__CYGWIN__)
state->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child);
if (state->child == NULL) {
child_stop(self, state);
free(state->out_buf);
free(state);
archive_set_error(&self->archive->archive, EINVAL,
"Can't initialize filter; unable to run program \"%s\"",
cmd);
return (ARCHIVE_FATAL);
}
#else
state->child = child;
#endif
self->data = state;
self->read = program_filter_read;
@ -467,10 +509,8 @@ program_filter_close(struct archive_read_filter *self)
/* Release our private data. */
free(state->out_buf);
free(state->description);
archive_string_free(&state->description);
free(state);
return (e);
}
#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */

View File

@ -85,6 +85,7 @@ archive_read_support_filter_rpm(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
bidder->name = "rpm";
bidder->bid = rpm_bidder_bid;
bidder->init = rpm_bidder_init;
bidder->options = NULL;
@ -137,7 +138,7 @@ rpm_bidder_init(struct archive_read_filter *self)
{
struct rpm *rpm;
self->code = ARCHIVE_COMPRESSION_RPM;
self->code = ARCHIVE_FILTER_RPM;
self->name = "rpm";
self->read = rpm_filter_read;
self->skip = NULL; /* not supported */
@ -188,7 +189,7 @@ rpm_filter_read(struct archive_read_filter *self, const void **buff)
if (rpm->total_in + avail_in < RPM_LEAD_SIZE)
used += avail_in;
else {
n = RPM_LEAD_SIZE - rpm->total_in;
n = (size_t)(RPM_LEAD_SIZE - rpm->total_in);
used += n;
b += n;
rpm->state = ST_HEADER;

View File

@ -56,6 +56,7 @@ struct uudecode {
#define ST_READ_UU 1
#define ST_UUEND 2
#define ST_READ_BASE64 3
#define ST_IGNORE 4
};
static int uudecode_bidder_bid(struct archive_read_filter_bidder *,
@ -88,6 +89,7 @@ archive_read_support_filter_uu(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
bidder->name = "uu";
bidder->bid = uudecode_bidder_bid;
bidder->init = uudecode_bidder_init;
bidder->options = NULL;
@ -377,7 +379,7 @@ uudecode_bidder_init(struct archive_read_filter *self)
void *out_buff;
void *in_buff;
self->code = ARCHIVE_COMPRESSION_UU;
self->code = ARCHIVE_FILTER_UU;
self->name = "uu";
self->read = uudecode_filter_read;
self->skip = NULL; /* not supported */
@ -470,6 +472,10 @@ read_more:
total = 0;
out = uudecode->out_buff;
ravail = avail_in;
if (uudecode->state == ST_IGNORE) {
used = avail_in;
goto finish;
}
if (uudecode->in_cnt) {
/*
* If there is remaining data which is saved by
@ -485,12 +491,18 @@ read_more:
uudecode->in_cnt = 0;
}
for (;used < avail_in; d += llen, used += llen) {
int l, body;
int64_t l, body;
b = d;
len = get_line(b, avail_in - used, &nl);
if (len < 0) {
/* Non-ascii character is found. */
if (uudecode->state == ST_FIND_HEAD &&
(uudecode->total > 0 || total > 0)) {
uudecode->state = ST_IGNORE;
used = avail_in;
goto finish;
}
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC,
"Insufficient compressed data");
@ -507,7 +519,7 @@ read_more:
return (ARCHIVE_FATAL);
if (uudecode->in_buff != b)
memmove(uudecode->in_buff, b, len);
uudecode->in_cnt = len;
uudecode->in_cnt = (int)len;
if (total == 0) {
/* Do not return 0; it means end-of-file.
* We should try to read bytes more. */
@ -545,7 +557,7 @@ read_more:
break;
case ST_READ_UU:
if (total + len * 2 > OUT_BUFF_SIZE)
break;
goto finish;
body = len - nl;
if (!uuchar[*b] || body <= 0) {
archive_set_error(&self->archive->archive,
@ -611,7 +623,7 @@ read_more:
break;
case ST_READ_BASE64:
if (total + len * 2 > OUT_BUFF_SIZE)
break;
goto finish;
l = len - nl;
if (l >= 3 && b[0] == '=' && b[1] == '=' &&
b[2] == '=') {
@ -657,8 +669,10 @@ read_more:
break;
}
}
__archive_read_filter_consume(self->upstream, ravail);
finish:
if (ravail < avail_in)
used -= avail_in - ravail;
__archive_read_filter_consume(self->upstream, used);
*buff = uudecode->out_buff;
uudecode->total += total;

View File

@ -136,6 +136,7 @@ archive_read_support_filter_xz(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
bidder->name = "xz";
bidder->bid = xz_bidder_bid;
bidder->init = xz_bidder_init;
bidder->options = NULL;
@ -144,7 +145,7 @@ archive_read_support_filter_xz(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
"Using external unxz program for xz decompression");
"Using external xz program for xz decompression");
return (ARCHIVE_WARN);
#endif
}
@ -170,6 +171,7 @@ archive_read_support_filter_lzma(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
bidder->name = "lzma";
bidder->bid = lzma_bidder_bid;
bidder->init = lzma_bidder_init;
bidder->options = NULL;
@ -180,7 +182,7 @@ archive_read_support_filter_lzma(struct archive *_a)
return (ARCHIVE_OK);
#else
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
"Using external unlzma program for lzma decompression");
"Using external lzma program for lzma decompression");
return (ARCHIVE_WARN);
#endif
}
@ -207,6 +209,7 @@ archive_read_support_filter_lzip(struct archive *_a)
return (ARCHIVE_FATAL);
bidder->data = NULL;
bidder->name = "lzip";
bidder->bid = lzip_bidder_bid;
bidder->init = lzip_bidder_init;
bidder->options = NULL;
@ -415,7 +418,7 @@ lzip_bidder_bid(struct archive_read_filter_bidder *self,
static int
xz_bidder_init(struct archive_read_filter *self)
{
self->code = ARCHIVE_COMPRESSION_XZ;
self->code = ARCHIVE_FILTER_XZ;
self->name = "xz";
return (xz_lzma_bidder_init(self));
}
@ -423,7 +426,7 @@ xz_bidder_init(struct archive_read_filter *self)
static int
lzma_bidder_init(struct archive_read_filter *self)
{
self->code = ARCHIVE_COMPRESSION_LZMA;
self->code = ARCHIVE_FILTER_LZMA;
self->name = "lzma";
return (xz_lzma_bidder_init(self));
}
@ -431,7 +434,7 @@ lzma_bidder_init(struct archive_read_filter *self)
static int
lzip_bidder_init(struct archive_read_filter *self)
{
self->code = ARCHIVE_COMPRESSION_LZIP;
self->code = ARCHIVE_FILTER_LZIP;
self->name = "lzip";
return (xz_lzma_bidder_init(self));
}
@ -518,7 +521,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self)
state->stream.avail_out = state->out_block_size;
state->crc32 = 0;
if (self->code == ARCHIVE_COMPRESSION_LZIP) {
if (self->code == ARCHIVE_FILTER_LZIP) {
/*
* We have to read a lzip header and use it to initialize
* compression library, thus we cannot initialize the
@ -530,7 +533,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self)
state->in_stream = 1;
/* Initialize compression library. */
if (self->code == ARCHIVE_COMPRESSION_XZ)
if (self->code == ARCHIVE_FILTER_XZ)
ret = lzma_stream_decoder(&(state->stream),
LZMA_MEMLIMIT,/* memlimit */
LZMA_CONCATENATED);
@ -730,7 +733,7 @@ xz_filter_read(struct archive_read_filter *self, const void **p)
*p = NULL;
else {
*p = state->out_block;
if (self->code == ARCHIVE_COMPRESSION_LZIP) {
if (self->code == ARCHIVE_FILTER_LZIP) {
state->crc32 = lzma_crc32(state->out_block,
decompressed, state->crc32);
if (state->eof) {
@ -778,7 +781,7 @@ lzma_bidder_init(struct archive_read_filter *self)
struct private_data *state;
ssize_t ret, avail_in;
self->code = ARCHIVE_COMPRESSION_LZMA;
self->code = ARCHIVE_FILTER_LZMA;
self->name = "lzma";
state = (struct private_data *)calloc(sizeof(*state), 1);
@ -941,11 +944,11 @@ lzma_bidder_init(struct archive_read_filter *self)
{
int r;
r = __archive_read_program(self, "unlzma");
r = __archive_read_program(self, "lzma -d -qq");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
self->code = ARCHIVE_COMPRESSION_LZMA;
self->code = ARCHIVE_FILTER_LZMA;
self->name = "lzma";
return (r);
}
@ -958,11 +961,11 @@ xz_bidder_init(struct archive_read_filter *self)
{
int r;
r = __archive_read_program(self, "unxz");
r = __archive_read_program(self, "xz -d -qq");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
self->code = ARCHIVE_COMPRESSION_XZ;
self->code = ARCHIVE_FILTER_XZ;
self->name = "xz";
return (r);
}
@ -972,11 +975,11 @@ lzip_bidder_init(struct archive_read_filter *self)
{
int r;
r = __archive_read_program(self, "unlzip");
r = __archive_read_program(self, "lzip -d -q");
/* Note: We set the format here even if __archive_read_program()
* above fails. We do, after all, know what the format is
* even if we weren't able to read it. */
self->code = ARCHIVE_COMPRESSION_LZIP;
self->code = ARCHIVE_FILTER_LZIP;
self->name = "lzip";
return (r);
}

View File

@ -318,7 +318,7 @@ struct _7zip {
uint32_t bcj2_code;
uint64_t bcj2_outPos;
/* Filename character-set convertion data. */
/* Filename character-set conversion data. */
struct archive_string_conv *sconv;
char format_name[64];
@ -409,6 +409,7 @@ archive_read_support_format_7zip(struct archive *_a)
archive_read_format_7zip_read_header,
archive_read_format_7zip_read_data,
archive_read_format_7zip_read_data_skip,
NULL,
archive_read_format_7zip_cleanup);
if (r != ARCHIVE_OK)
@ -481,7 +482,7 @@ check_7zip_header_in_sfx(const char *p)
* Magic Code, so we should do this in order not to
* make a mis-detection.
*/
if (crc32(0, (unsigned char *)p + 12, 20)
if (crc32(0, (const unsigned char *)p + 12, 20)
!= archive_le32dec(p + 8))
return (6);
/* Hit the header! */
@ -580,7 +581,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
free_Header(&header);
if (r != ARCHIVE_OK)
return (r);
zip->entries_remaining = zip->numFiles;
zip->entries_remaining = (size_t)zip->numFiles;
zip->entry = zip->entries;
} else {
++zip->entry;
@ -630,7 +631,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
if (zip_entry->flg & ATIME_IS_SET)
archive_entry_set_atime(entry, zip_entry->atime,
zip_entry->atime_ns);
if (zip_entry->ssIndex != -1) {
if (zip_entry->ssIndex != (uint32_t)-1) {
zip->entry_bytes_remaining =
zip->si.ss.unpackSizes[zip_entry->ssIndex];
archive_entry_set_size(entry, zip->entry_bytes_remaining);
@ -646,7 +647,6 @@ archive_read_format_7zip_read_header(struct archive_read *a,
if ((zip_entry->mode & AE_IFMT) == AE_IFLNK) {
unsigned char *symname = NULL;
size_t symsize = 0;
int r;
/*
* Symbolic-name is recorded as its contents. We have to
@ -654,19 +654,24 @@ archive_read_format_7zip_read_header(struct archive_read *a,
*/
while (zip->entry_bytes_remaining > 0) {
const void *buff;
unsigned char *mem;
size_t size;
int64_t offset;
r = archive_read_format_7zip_read_data(a, &buff,
&size, &offset);
if (r < ARCHIVE_WARN)
if (r < ARCHIVE_WARN) {
free(symname);
return (r);
symname = realloc(symname, symsize + size + 1);
if (symname == NULL) {
}
mem = realloc(symname, symsize + size + 1);
if (mem == NULL) {
free(symname);
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Symname");
return (ARCHIVE_FATAL);
}
symname = mem;
memcpy(symname+symsize, buff, size);
symsize += size;
}
@ -680,8 +685,8 @@ archive_read_format_7zip_read_header(struct archive_read *a,
symname[symsize] = '\0';
archive_entry_copy_symlink(entry,
(const char *)symname);
free(symname);
}
free(symname);
archive_entry_set_size(entry, 0);
}
@ -705,18 +710,18 @@ archive_read_format_7zip_read_data(struct archive_read *a,
if (zip->pack_stream_bytes_unconsumed)
read_consume(a);
*offset = zip->entry_offset;
*size = 0;
*buff = NULL;
/*
* If we hit end-of-entry last time, clean up and return
* ARCHIVE_EOF this time.
*/
if (zip->end_of_entry) {
*offset = zip->entry_offset;
*size = 0;
*buff = NULL;
if (zip->end_of_entry)
return (ARCHIVE_EOF);
}
bytes = read_stream(a, buff, zip->entry_bytes_remaining, 0);
bytes = read_stream(a, buff,
(size_t)zip->entry_bytes_remaining, 0);
if (bytes < 0)
return ((int)bytes);
if (bytes == 0) {
@ -731,7 +736,8 @@ archive_read_format_7zip_read_data(struct archive_read *a,
/* Update checksum */
if ((zip->entry->flg & CRC32_IS_SET) && bytes)
zip->entry_crc32 = crc32(zip->entry_crc32, *buff, bytes);
zip->entry_crc32 = crc32(zip->entry_crc32, *buff,
(unsigned)bytes);
/* If we hit the end, swallow any end-of-data marker. */
if (zip->end_of_entry) {
@ -774,7 +780,7 @@ archive_read_format_7zip_read_data_skip(struct archive_read *a)
* If the length is at the beginning, we can skip the
* compressed data much more quickly.
*/
bytes_skipped = skip_stream(a, zip->entry_bytes_remaining);
bytes_skipped = skip_stream(a, (size_t)zip->entry_bytes_remaining);
if (bytes_skipped < 0)
return (ARCHIVE_FATAL);
zip->entry_bytes_remaining = 0;
@ -1054,7 +1060,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
ff = &filters[fi];
#endif
r = lzma_properties_decode(&filters[fi], NULL,
coder1->properties, coder1->propertiesSize);
coder1->properties, (size_t)coder1->propertiesSize);
if (r != LZMA_OK) {
set_error(a, r);
return (ARCHIVE_FAILED);
@ -1358,9 +1364,9 @@ decompress(struct archive_read *a, struct _7zip *zip,
#ifdef HAVE_ZLIB_H
case _7Z_DEFLATE:
zip->stream.next_in = (Bytef *)(uintptr_t)t_next_in;
zip->stream.avail_in = t_avail_in;
zip->stream.avail_in = (uInt)t_avail_in;
zip->stream.next_out = t_next_out;
zip->stream.avail_out = t_avail_out;
zip->stream.avail_out = (uInt)t_avail_out;
r = inflate(&(zip->stream), 0);
switch (r) {
case Z_STREAM_END: /* Found end of stream. */
@ -1382,7 +1388,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
uint64_t flush_bytes;
if (!zip->ppmd7_valid || zip->ppmd7_stat < 0 ||
t_avail_in < 0 || t_avail_out <= 0) {
t_avail_out <= 0) {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
"Decompression internal error");
@ -1442,8 +1448,8 @@ decompress(struct archive_read *a, struct _7zip *zip,
} while (zip->ppstream.avail_out &&
(zip->ppstream.avail_in || flush_bytes));
t_avail_in = zip->ppstream.avail_in;
t_avail_out = zip->ppstream.avail_out;
t_avail_in = (size_t)zip->ppstream.avail_in;
t_avail_out = (size_t)zip->ppstream.avail_out;
break;
}
default:
@ -1506,6 +1512,10 @@ free_decompression(struct archive_read *a, struct _7zip *zip)
{
int r = ARCHIVE_OK;
#if !defined(HAVE_ZLIB_H) &&\
!(defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR))
(void)a;/* UNUSED */
#endif
#ifdef HAVE_LZMA_H
if (zip->lzstream_valid)
lzma_end(&(zip->lzstream));
@ -1598,9 +1608,10 @@ read_Digests(struct archive_read *a, struct _7z_digests *d, size_t num)
const unsigned char *p;
unsigned i;
if (num == 0)
return (-1);
memset(d, 0, sizeof(*d));
d->defineds = malloc(num);
if (d->defineds == NULL)
return (-1);
@ -1672,8 +1683,8 @@ read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi)
return (0);
if (*p != kSize)
return (-1);
pi->sizes = calloc(pi->numPackStreams, sizeof(uint64_t));
pi->positions = calloc(pi->numPackStreams, sizeof(uint64_t));
pi->sizes = calloc((size_t)pi->numPackStreams, sizeof(uint64_t));
pi->positions = calloc((size_t)pi->numPackStreams, sizeof(uint64_t));
if (pi->sizes == NULL || pi->positions == NULL)
return (-1);
@ -1690,9 +1701,9 @@ read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi)
if (*p == kEnd) {
/* PackStreamDigests[num] are not present. */
pi->digest.defineds =
calloc(pi->numPackStreams, sizeof(*pi->digest.defineds));
calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.defineds));
pi->digest.digests =
calloc(pi->numPackStreams, sizeof(*pi->digest.digests));
calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.digests));
if (pi->digest.defineds == NULL || pi->digest.digests == NULL)
return (-1);
return (0);
@ -1701,7 +1712,7 @@ read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi)
if (*p != kSize)
return (-1);
if (read_Digests(a, &(pi->digest), pi->numPackStreams) < 0)
if (read_Digests(a, &(pi->digest), (size_t)pi->numPackStreams) < 0)
return (-1);
/*
@ -1750,7 +1761,7 @@ read_Folder(struct archive_read *a, struct _7z_folder *f)
/* Too many coders. */
return (-1);
f->coders = calloc(f->numCoders, sizeof(*f->coders));
f->coders = calloc((size_t)f->numCoders, sizeof(*f->coders));
if (f->coders == NULL)
return (-1);
for (i = 0; i< f->numCoders; i++) {
@ -1802,14 +1813,14 @@ read_Folder(struct archive_read *a, struct _7z_folder *f)
a, &(f->coders[i].propertiesSize)) < 0)
return (-1);
if ((p = header_bytes(
a, f->coders[i].propertiesSize)) == NULL)
a, (size_t)f->coders[i].propertiesSize)) == NULL)
return (-1);
f->coders[i].properties =
malloc(f->coders[i].propertiesSize);
malloc((size_t)f->coders[i].propertiesSize);
if (f->coders[i].properties == NULL)
return (-1);
memcpy(f->coders[i].properties, p,
f->coders[i].propertiesSize);
(size_t)f->coders[i].propertiesSize);
}
numInStreamsTotal += f->coders[i].numInStreams;
@ -1823,9 +1834,13 @@ read_Folder(struct archive_read *a, struct _7z_folder *f)
f->numBindPairs = numOutStreamsTotal - 1;
if (zip->header_bytes_remaining < f->numBindPairs)
return (-1);
f->bindPairs = calloc(f->numBindPairs, sizeof(*f->bindPairs));
if (f->numBindPairs > 0) {
f->bindPairs =
calloc((size_t)f->numBindPairs, sizeof(*f->bindPairs));
if (f->bindPairs == NULL)
return (-1);
} else
f->bindPairs = NULL;
for (i = 0; i < f->numBindPairs; i++) {
if (parse_7zip_uint64(a, &(f->bindPairs[i].inIndex)) < 0)
return (-1);
@ -1839,7 +1854,7 @@ read_Folder(struct archive_read *a, struct _7z_folder *f)
f->numPackedStreams = numInStreamsTotal - f->numBindPairs;
f->packedStreams =
calloc(f->numPackedStreams, sizeof(*f->packedStreams));
calloc((size_t)f->numPackedStreams, sizeof(*f->packedStreams));
if (f->packedStreams == NULL)
return (-1);
if (f->numPackedStreams == 1) {
@ -1911,7 +1926,8 @@ read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci)
goto failed;
switch (*p) {
case 0:
ci->folders = calloc(ci->numFolders, sizeof(*ci->folders));
ci->folders =
calloc((size_t)ci->numFolders, sizeof(*ci->folders));
if (ci->folders == NULL)
return (-1);
for (i = 0; i < ci->numFolders; i++) {
@ -1937,7 +1953,7 @@ read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci)
unsigned j;
folder->unPackSize =
calloc(folder->numOutStreams, sizeof(*folder->unPackSize));
calloc((size_t)folder->numOutStreams, sizeof(*folder->unPackSize));
if (folder->unPackSize == NULL)
goto failed;
for (j = 0; j < folder->numOutStreams; j++) {
@ -1955,7 +1971,7 @@ read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci)
return (0);
if (*p != kCRC)
goto failed;
if (read_Digests(a, &digest, ci->numFolders) < 0)
if (read_Digests(a, &digest, (size_t)ci->numFolders) < 0)
goto failed;
for (i = 0; i < ci->numFolders; i++) {
ci->folders[i].digest_defined = digest.defineds[i];
@ -1979,13 +1995,13 @@ failed:
static uint64_t
folder_uncompressed_size(struct _7z_folder *f)
{
int n = f->numOutStreams;
unsigned pairs = f->numBindPairs;
int n = (int)f->numOutStreams;
unsigned pairs = (unsigned)f->numBindPairs;
while (--n >= 0) {
unsigned i;
for (i = 0; i < pairs; i++) {
if (f->bindPairs[i].outIndex == n)
if (f->bindPairs[i].outIndex == (uint64_t)n)
break;
}
if (i >= pairs)
@ -2029,7 +2045,7 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss,
return (-1);
if (1000000 < f[i].numUnpackStreams)
return (-1);
unpack_streams += f[i].numUnpackStreams;
unpack_streams += (size_t)f[i].numUnpackStreams;
}
if ((p = header_bytes(a, 1)) == NULL)
return (-1);
@ -2083,7 +2099,7 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss,
numDigests = 0;
for (i = 0; i < numFolders; i++) {
if (f[i].numUnpackStreams != 1 || !f[i].digest_defined)
numDigests += f[i].numUnpackStreams;
numDigests += (uint32_t)f[i].numUnpackStreams;
}
if (type == kCRC) {
@ -2181,7 +2197,7 @@ read_StreamsInfo(struct archive_read *a, struct _7z_stream_info *si)
f = si->ci.folders;
for (i = 0; i < si->ci.numFolders; i++) {
f[i].packIndex = packIndex;
packIndex += f[i].numPackedStreams;
packIndex += (uint32_t)f[i].numPackedStreams;
if (packIndex > si->pi.numPackStreams)
return (-1);
}
@ -2191,7 +2207,7 @@ read_StreamsInfo(struct archive_read *a, struct _7z_stream_info *si)
if (*p == kSubStreamsInfo) {
if (read_SubStreamsInfo(a, &(si->ss),
si->ci.folders, si->ci.numFolders) < 0)
si->ci.folders, (size_t)si->ci.numFolders) < 0)
return (-1);
if ((p = header_bytes(a, 1)) == NULL)
return (-1);
@ -2279,7 +2295,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if (1000000 < zip->numFiles)
return (-1);
zip->entries = calloc(zip->numFiles, sizeof(*zip->entries));
zip->entries = calloc((size_t)zip->numFiles, sizeof(*zip->entries));
if (zip->entries == NULL)
return (-1);
entries = zip->entries;
@ -2304,12 +2320,12 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
switch (type) {
case kEmptyStream:
h->emptyStreamBools = calloc(zip->numFiles,
h->emptyStreamBools = calloc((size_t)zip->numFiles,
sizeof(*h->emptyStreamBools));
if (h->emptyStreamBools == NULL)
return (-1);
if (read_Bools(
a, h->emptyStreamBools, zip->numFiles) < 0)
a, h->emptyStreamBools, (size_t)zip->numFiles) < 0)
return (-1);
empty_streams = 0;
for (i = 0; i < zip->numFiles; i++) {
@ -2318,6 +2334,12 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
}
break;
case kEmptyFile:
if (empty_streams <= 0) {
/* Unexcepted sequence. Skip this. */
if (header_bytes(a, ll) == NULL)
return (-1);
break;
}
h->emptyFileBools = calloc(empty_streams,
sizeof(*h->emptyFileBools));
if (h->emptyFileBools == NULL)
@ -2326,6 +2348,12 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
return (-1);
break;
case kAnti:
if (empty_streams <= 0) {
/* Unexcepted sequence. Skip this. */
if (header_bytes(a, ll) == NULL)
return (-1);
break;
}
h->antiBools = calloc(empty_streams,
sizeof(*h->antiBools));
if (h->antiBools == NULL)
@ -2404,15 +2432,15 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if ((p = header_bytes(a, 2)) == NULL)
return (-1);
allAreDefined = *p;
h->attrBools = calloc(zip->numFiles,
h->attrBools = calloc((size_t)zip->numFiles,
sizeof(*h->attrBools));
if (h->attrBools == NULL)
return (-1);
if (allAreDefined)
memset(h->attrBools, 1, zip->numFiles);
memset(h->attrBools, 1, (size_t)zip->numFiles);
else {
if (read_Bools(a, h->attrBools,
zip->numFiles) < 0)
(size_t)zip->numFiles) < 0)
return (-1);
}
for (i = 0; i < zip->numFiles; i++) {
@ -2446,7 +2474,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if ((size_t)sindex >= si->ss.unpack_streams)
return (-1);
if (entries[i].mode == 0)
entries[i].mode = AE_IFREG | 0777;
entries[i].mode = AE_IFREG | 0666;
if (si->ss.digestsDefined[sindex])
entries[i].flg |= CRC32_IS_SET;
entries[i].ssIndex = sindex;
@ -2466,7 +2494,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
if (dir)
entries[i].mode = AE_IFDIR | 0777;
else
entries[i].mode = AE_IFREG | 0777;
entries[i].mode = AE_IFREG | 0666;
} else if (dir &&
(entries[i].mode & AE_IFMT) != AE_IFDIR) {
entries[i].mode &= ~AE_IFMT;
@ -2517,17 +2545,17 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
static void
fileTimeToUtc(uint64_t fileTime, time_t *time, long *ns)
fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns)
{
if (fileTime >= EPOC_TIME) {
fileTime -= EPOC_TIME;
/* milli seconds base */
*time = (time_t)(fileTime / 10000000);
*timep = (time_t)(fileTime / 10000000);
/* nano seconds base */
*ns = (long)(fileTime % 10000000) * 100;
} else {
*time = 0;
*timep = 0;
*ns = 0;
}
}
@ -2542,7 +2570,7 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
int allAreDefined;
unsigned i;
timeBools = calloc(zip->numFiles, sizeof(*timeBools));
timeBools = calloc((size_t)zip->numFiles, sizeof(*timeBools));
if (timeBools == NULL)
return (-1);
@ -2551,9 +2579,9 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
goto failed;
allAreDefined = *p;
if (allAreDefined)
memset(timeBools, 1, zip->numFiles);
memset(timeBools, 1, (size_t)zip->numFiles);
else {
if (read_Bools(a, timeBools, zip->numFiles) < 0)
if (read_Bools(a, timeBools, (size_t)zip->numFiles) < 0)
goto failed;
}
@ -2564,7 +2592,7 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
if (parse_7zip_uint64(a, &(h->dataIndex)) < 0)
goto failed;
if (1000000 < h->dataIndex)
return (-1);
goto failed;
}
for (i = 0; i < zip->numFiles; i++) {
@ -2661,7 +2689,7 @@ header_bytes(struct archive_read *a, size_t rbytes)
}
/* Update checksum */
zip->header_crc32 = crc32(zip->header_crc32, p, rbytes);
zip->header_crc32 = crc32(zip->header_crc32, p, (unsigned)rbytes);
return (p);
}
@ -2695,7 +2723,8 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
}
/* CRC check. */
if (crc32(0, (unsigned char *)p + 12, 20) != archive_le32dec(p + 8)) {
if (crc32(0, (const unsigned char *)p + 12, 20)
!= archive_le32dec(p + 8)) {
archive_set_error(&a->archive, -1, "Header CRC error");
return (ARCHIVE_FATAL);
}
@ -2714,7 +2743,7 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
}
__archive_read_consume(a, 32);
if (next_header_offset != 0) {
if (bytes_avail >= next_header_offset)
if (bytes_avail >= (ssize_t)next_header_offset)
__archive_read_consume(a, next_header_offset);
else if (__archive_read_seek(a,
next_header_offset + zip->seek_base, SEEK_SET) < 0)
@ -2827,7 +2856,7 @@ get_uncompressed_data(struct archive_read *a, const void **buff, size_t size,
struct _7zip *zip = (struct _7zip *)a->format->data;
ssize_t bytes_avail;
if (zip->codec == _7Z_COPY && zip->codec2 == -1) {
if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) {
/* Copy mode. */
/*
@ -2886,7 +2915,7 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
ssize_t bytes_avail;
int r;
if (zip->codec == _7Z_COPY && zip->codec2 == -1) {
if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) {
if (minimum == 0)
minimum = 1;
if (__archive_read_ahead(a, minimum, &bytes_avail) == NULL
@ -2896,11 +2925,11 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
"Truncated 7-Zip file body");
return (ARCHIVE_FATAL);
}
if (bytes_avail > zip->pack_stream_inbytes_remaining)
bytes_avail = zip->pack_stream_inbytes_remaining;
if (bytes_avail > (ssize_t)zip->pack_stream_inbytes_remaining)
bytes_avail = (ssize_t)zip->pack_stream_inbytes_remaining;
zip->pack_stream_inbytes_remaining -= bytes_avail;
if (bytes_avail > zip->folder_outbytes_remaining)
bytes_avail = zip->folder_outbytes_remaining;
if (bytes_avail > (ssize_t)zip->folder_outbytes_remaining)
bytes_avail = (ssize_t)zip->folder_outbytes_remaining;
zip->folder_outbytes_remaining -= bytes_avail;
zip->uncompressed_buffer_bytes_remaining = bytes_avail;
return (ARCHIVE_OK);
@ -2939,16 +2968,19 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
* Expand the uncompressed buffer up to
* the minimum size.
*/
zip->uncompressed_buffer_size = minimum + 1023;
zip->uncompressed_buffer_size &= ~0x3ff;
zip->uncompressed_buffer =
realloc(zip->uncompressed_buffer,
zip->uncompressed_buffer_size);
if (zip->uncompressed_buffer == NULL) {
void *p;
size_t new_size;
new_size = minimum + 1023;
new_size &= ~0x3ff;
p = realloc(zip->uncompressed_buffer, new_size);
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM,
"No memory for 7-Zip decompression");
return (ARCHIVE_FATAL);
}
zip->uncompressed_buffer = (unsigned char *)p;
zip->uncompressed_buffer_size = new_size;
}
/*
* Move unconsumed bytes to the head.
@ -2965,7 +2997,7 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
size_t bytes_in, bytes_out;
const void *buff_in;
unsigned char *buff_out;
int eof;
int end_of_data;
/*
* Note: '1' here is a performance optimization.
@ -2987,23 +3019,23 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
- zip->uncompressed_buffer_bytes_remaining;
bytes_in = bytes_avail;
if (bytes_in > zip->pack_stream_inbytes_remaining)
bytes_in = zip->pack_stream_inbytes_remaining;
bytes_in = (size_t)zip->pack_stream_inbytes_remaining;
/* Drive decompression. */
r = decompress(a, zip, buff_out, &bytes_out,
buff_in, &bytes_in);
switch (r) {
case ARCHIVE_OK:
eof = 0;
end_of_data = 0;
break;
case ARCHIVE_EOF:
eof = 1;
end_of_data = 1;
break;
default:
return (ARCHIVE_FATAL);
}
zip->pack_stream_inbytes_remaining -= bytes_in;
if (bytes_out > zip->folder_outbytes_remaining)
bytes_out = zip->folder_outbytes_remaining;
bytes_out = (size_t)zip->folder_outbytes_remaining;
zip->folder_outbytes_remaining -= bytes_out;
zip->uncompressed_buffer_bytes_remaining += bytes_out;
zip->pack_stream_bytes_unconsumed = bytes_in;
@ -3021,7 +3053,7 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
if (zip->pack_stream_inbytes_remaining == 0 &&
zip->folder_outbytes_remaining == 0)
break;
if (eof || (bytes_in == 0 && bytes_out == 0)) {
if (end_of_data || (bytes_in == 0 && bytes_out == 0)) {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive");
return (ARCHIVE_FATAL);
@ -3041,7 +3073,7 @@ static int
seek_pack(struct archive_read *a)
{
struct _7zip *zip = (struct _7zip *)a->format->data;
uint64_t pack_offset;
int64_t pack_offset;
if (zip->pack_stream_remaining <= 0) {
archive_set_error(&(a->archive),
@ -3068,7 +3100,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
{
struct _7zip *zip = (struct _7zip *)a->format->data;
uint64_t skip_bytes = 0;
int r;
ssize_t r;
if (zip->uncompressed_buffer_bytes_remaining == 0) {
if (zip->pack_stream_inbytes_remaining > 0) {
@ -3160,7 +3192,8 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
return (ARCHIVE_FATAL);
}
}
skipped = get_uncompressed_data(a, buff, skip_bytes, 0);
skipped = get_uncompressed_data(
a, buff, (size_t)skip_bytes, 0);
if (skipped < 0)
return (skipped);
skip_bytes -= skipped;
@ -3292,13 +3325,13 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
}
coder2 = &(fc[3]);
zip->main_stream_bytes_remaining =
folder->unPackSize[2];
(size_t)folder->unPackSize[2];
} else if (coder2 != NULL && coder2->codec == _7Z_X86_BCJ2 &&
zip->pack_stream_remaining == 4 &&
folder->numInStreams == 5 && folder->numOutStreams == 2) {
/* Source type 0 made by 7z */
zip->main_stream_bytes_remaining =
folder->unPackSize[0];
(size_t)folder->unPackSize[0];
} else {
/* We got an unexpected form. */
archive_set_error(&(a->archive),
@ -3311,30 +3344,35 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
if ((r = seek_pack(a)) < 0)
return (r);
zip->pack_stream_bytes_unconsumed =
zip->pack_stream_inbytes_remaining;
(size_t)zip->pack_stream_inbytes_remaining;
read_consume(a);
/* Read following three sub streams. */
for (i = 0; i < 3; i++) {
const struct _7z_coder *coder = scoder[i];
if ((r = seek_pack(a)) < 0)
if ((r = seek_pack(a)) < 0) {
free(b[0]); free(b[1]); free(b[2]);
return (r);
}
if (sunpack[i] == -1)
if (sunpack[i] == (uint64_t)-1)
zip->folder_outbytes_remaining =
zip->pack_stream_inbytes_remaining;
else
zip->folder_outbytes_remaining = sunpack[i];
r = init_decompression(a, zip, coder, NULL);
if (r != ARCHIVE_OK)
if (r != ARCHIVE_OK) {
free(b[0]); free(b[1]); free(b[2]);
return (ARCHIVE_FATAL);
}
/* Allocate memory for the decorded data of a sub
* stream. */
b[i] = malloc(zip->folder_outbytes_remaining);
b[i] = malloc((size_t)zip->folder_outbytes_remaining);
if (b[i] == NULL) {
free(b[0]); free(b[1]); free(b[2]);
archive_set_error(&a->archive, ENOMEM,
"No memory for 7-Zip decompression");
return (ARCHIVE_FATAL);
@ -3342,14 +3380,18 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
/* Extract a sub stream. */
while (zip->pack_stream_inbytes_remaining > 0) {
r = extract_pack_stream(a, 0);
if (r < 0)
r = (int)extract_pack_stream(a, 0);
if (r < 0) {
free(b[0]); free(b[1]); free(b[2]);
return (r);
}
bytes = get_uncompressed_data(a, &buff,
zip->uncompressed_buffer_bytes_remaining,
0);
if (bytes < 0)
if (bytes < 0) {
free(b[0]); free(b[1]); free(b[2]);
return ((int)bytes);
}
memcpy(b[i]+s[i], buff, bytes);
s[i] += bytes;
if (zip->pack_stream_bytes_unconsumed)
@ -3428,7 +3470,7 @@ skip_stream(struct archive_read *a, size_t skip_bytes)
"Truncated 7-Zip file body");
return (ARCHIVE_FATAL);
}
bytes -= skipped_bytes;
bytes -= (size_t)skipped_bytes;
if (zip->pack_stream_bytes_unconsumed)
read_consume(a);
}
@ -3506,16 +3548,16 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size)
uint32_t dest;
for (;;) {
uint8_t b;
int index;
int b_index;
dest = src - (ip + (uint32_t)bufferPos);
if (prevMask == 0)
break;
index = kMaskToBitNumber[prevMask] * 8;
b = (uint8_t)(dest >> (24 - index));
b_index = kMaskToBitNumber[prevMask] * 8;
b = (uint8_t)(dest >> (24 - b_index));
if (!Test86MSByte(b))
break;
src = dest ^ ((1 << (32 - index)) - 1);
src = dest ^ ((1 << (32 - b_index)) - 1);
}
p[4] = (uint8_t)(~(((dest >> 24) & 1) - 1));
p[3] = (uint8_t)(dest >> 16);
@ -3529,7 +3571,7 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size)
}
zip->bcj_prevPosT = prevPosT;
zip->bcj_prevMask = prevMask;
zip->bcj_ip += bufferPos;
zip->bcj_ip += (uint32_t)bufferPos;
return (bufferPos);
}
@ -3556,7 +3598,7 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size)
#define RC_READ_BYTE (*buffer++)
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
#define RC_INIT2 zip->bcj2_code = 0; zip->bcj2_range = 0xFFFFFFFF; \
{ int i; for (i = 0; i < 5; i++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }}
{ int ii; for (ii = 0; ii < 5; ii++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }}
#define NORMALIZE if (zip->bcj2_range < kTopValue) { RC_TEST; zip->bcj2_range <<= 8; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }
@ -3622,14 +3664,14 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
if (zip->bcj_state == 1) {
while (limit != 0) {
uint8_t b = buf0[inPos];
outBuf[outPos++] = b;
if (IsJ(zip->bcj2_prevByte, b)) {
uint8_t bb = buf0[inPos];
outBuf[outPos++] = bb;
if (IsJ(zip->bcj2_prevByte, bb)) {
zip->bcj_state = 2;
break;
}
inPos++;
zip->bcj2_prevByte = b;
zip->bcj2_prevByte = bb;
limit--;
}
}
@ -3673,7 +3715,7 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
((uint32_t)v[1] << 16) |
((uint32_t)v[2] << 8) |
((uint32_t)v[3])) -
((uint32_t)zip->bcj2_outPos + outPos + 4);
((uint32_t)zip->bcj2_outPos + (uint32_t)outPos + 4);
out[0] = (uint8_t)dest;
out[1] = (uint8_t)(dest >> 8);
out[2] = (uint8_t)(dest >> 16);
@ -3688,7 +3730,7 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
*/
zip->odd_bcj_size = 4 -i;
for (; i < 4; i++) {
j = i - 4 + zip->odd_bcj_size;
j = i - 4 + (unsigned)zip->odd_bcj_size;
zip->odd_bcj[j] = out[i];
}
break;

View File

@ -121,6 +121,7 @@ archive_read_support_format_ar(struct archive *_a)
archive_read_format_ar_read_header,
archive_read_format_ar_read_data,
archive_read_format_ar_skip,
NULL,
archive_read_format_ar_cleanup);
if (r != ARCHIVE_OK) {

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2010-2011 Michihiro NAKAJIMA
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -292,6 +292,8 @@ struct cab {
char end_of_archive;
char end_of_entry;
char end_of_entry_cleanup;
char read_data_invoked;
int64_t bytes_skipped;
unsigned char *uncompressed_buffer;
size_t uncompressed_buffer_size;
@ -349,7 +351,7 @@ static int lzx_read_bitlen(struct lzx_stream *, struct huffman *, int);
static int lzx_huffman_init(struct huffman *, size_t, int);
static void lzx_huffman_free(struct huffman *);
static int lzx_make_huffman_table(struct huffman *);
static int inline lzx_decode_huffman(struct huffman *, unsigned);
static inline int lzx_decode_huffman(struct huffman *, unsigned);
static int lzx_decode_huffman_tree(struct huffman *, unsigned, int);
@ -380,6 +382,7 @@ archive_read_support_format_cab(struct archive *_a)
archive_read_format_cab_read_header,
archive_read_format_cab_read_data,
archive_read_format_cab_read_data_skip,
NULL,
archive_read_format_cab_cleanup);
if (r != ARCHIVE_OK)
@ -478,13 +481,15 @@ archive_read_format_cab_options(struct archive_read *a,
else
ret = ARCHIVE_FATAL;
}
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"cab: unknown keyword ``%s''", key);
return (ret);
}
/* 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 int
cab_skip_sfx(struct archive_read *a)
{
@ -535,7 +540,7 @@ truncated_error(struct archive_read *a)
return (ARCHIVE_FATAL);
}
static int
static ssize_t
cab_strnlen(const unsigned char *p, size_t maxlen)
{
size_t i;
@ -546,7 +551,7 @@ cab_strnlen(const unsigned char *p, size_t maxlen)
}
if (i > maxlen)
return (-1);/* invalid */
return (i);
return ((ssize_t)i);
}
/* Read bytes as much as remaining. */
@ -622,8 +627,9 @@ cab_read_header(struct archive_read *a)
struct cab *cab;
struct cfheader *hd;
size_t bytes, used;
ssize_t len;
int64_t skip;
int err, i, len;
int err, i;
int cur_folder, prev_folder;
uint32_t offset32;
@ -796,7 +802,7 @@ cab_read_header(struct archive_read *a)
file->offset = archive_le32dec(p + CFFILE_uoffFolderStart);
file->folder = archive_le16dec(p + CFFILE_iFolder);
file->mtime = cab_dos_time(p + CFFILE_date_time);
file->attr = archive_le16dec(p + CFFILE_attribs);
file->attr = (uint8_t)archive_le16dec(p + CFFILE_attribs);
__archive_read_consume(a, 16);
cab->cab_offset += 16;
@ -986,7 +992,7 @@ archive_read_format_cab_read_header(struct archive_read *a,
if (file->attr & ATTR_RDONLY)
archive_entry_set_mode(entry, AE_IFREG | 0555);
else
archive_entry_set_mode(entry, AE_IFREG | 0777);
archive_entry_set_mode(entry, AE_IFREG | 0666);
archive_entry_set_mtime(entry, file->mtime, 0);
cab->entry_bytes_remaining = file->uncompressed_size;
@ -1024,9 +1030,22 @@ archive_read_format_cab_read_data(struct archive_read *a,
default:
break;
}
if (cab->read_data_invoked == 0) {
if (cab->bytes_skipped) {
if (cab->entry_cfdata == NULL) {
r = cab_next_cfdata(a);
if (r < 0)
return (r);
}
if (cab_consume_cfdata(a, cab->bytes_skipped) < 0)
return (ARCHIVE_FATAL);
cab->bytes_skipped = 0;
}
cab->read_data_invoked = 1;
}
if (cab->entry_unconsumed) {
/* Consume as much as the compressor actually used. */
r = cab_consume_cfdata(a, cab->entry_unconsumed);
r = (int)cab_consume_cfdata(a, cab->entry_unconsumed);
cab->entry_unconsumed = 0;
if (r < 0)
return (r);
@ -1049,13 +1068,13 @@ static uint32_t
cab_checksum_cfdata_4(const void *p, size_t bytes, uint32_t seed)
{
const unsigned char *b;
int u32num;
unsigned u32num;
uint32_t sum;
u32num = bytes / 4;
u32num = (unsigned)bytes / 4;
sum = seed;
b = p;
while (--u32num >= 0) {
for (;u32num > 0; --u32num) {
sum ^= archive_le32dec(b);
b += 4;
}
@ -1356,19 +1375,9 @@ cab_read_ahead_cfdata_none(struct archive_read *a, ssize_t *avail)
struct cab *cab = (struct cab *)(a->format->data);
struct cfdata *cfdata;
const void *d;
int64_t skipped_bytes;
cfdata = cab->entry_cfdata;
if (cfdata->uncompressed_avail == 0 &&
cfdata->read_offset > 0) {
/* we've already skipped some bytes before really read. */
skipped_bytes = cfdata->read_offset;
cfdata->read_offset = 0;
cfdata->uncompressed_bytes_remaining += skipped_bytes;
} else
skipped_bytes = 0;
do {
/*
* Note: '1' here is a performance optimization.
* Recall that the decompression layer returns a count of
@ -1385,17 +1394,6 @@ cab_read_ahead_cfdata_none(struct archive_read *a, ssize_t *avail)
cfdata->uncompressed_avail = cfdata->uncompressed_size;
cfdata->unconsumed = *avail;
cfdata->sum_ptr = d;
if (skipped_bytes > 0) {
skipped_bytes =
cab_minimum_consume_cfdata(a, skipped_bytes);
if (skipped_bytes < 0) {
*avail = ARCHIVE_FATAL;
return (NULL);
}
continue;
}
} while (0);
return (d);
}
@ -1489,7 +1487,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
* cast to remove 'const'.
*/
cab->stream.next_in = (Bytef *)(uintptr_t)d;
cab->stream.avail_in = bytes_avail;
cab->stream.avail_in = (uInt)bytes_avail;
cab->stream.total_in = 0;
/* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */
@ -1510,7 +1508,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
*avail = ARCHIVE_FATAL;
return (NULL);
}
mszip -= bytes_avail;
mszip -= (int)bytes_avail;
continue;
}
if (mszip == 1 && cab->stream.next_in[0] != 0x4b)
@ -1541,7 +1539,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
return (NULL);
}
}
uavail = cab->stream.total_out;
uavail = (uint16_t)cab->stream.total_out;
if (uavail < cfdata->uncompressed_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@ -1719,7 +1717,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
}
}
uavail = cab->xstrm.total_out;
uavail = (uint16_t)cab->xstrm.total_out;
/*
* Make sure a read pointer advances to next CFDATA.
*/
@ -1791,8 +1789,7 @@ cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
rbytes -= cbytes;
if (cfdata->uncompressed_avail == 0 &&
(cab->entry_cffolder->comptype == COMPTYPE_NONE ||
cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT ||
(cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT ||
cab->entry_cffile->folder == iFoldCONTINUED_FROM_PREV)) {
/* We have not read any data yet. */
if (cbytes == cfdata->uncompressed_bytes_remaining) {
@ -1819,8 +1816,8 @@ cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
}
continue;
}
cfdata->read_offset += cbytes;
cfdata->uncompressed_bytes_remaining -= cbytes;
cfdata->read_offset += (uint16_t)cbytes;
cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
break;
} else if (cbytes == 0) {
err = cab_next_cfdata(a);
@ -1844,7 +1841,7 @@ cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
if (avail <= 0)
return (ARCHIVE_FATAL);
if (avail > cbytes)
avail = cbytes;
avail = (ssize_t)cbytes;
if (cab_minimum_consume_cfdata(a, avail) < 0)
return (ARCHIVE_FATAL);
cbytes -= avail;
@ -1873,8 +1870,8 @@ cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
else
cbytes = cfdata->unconsumed;
rbytes -= cbytes;
cfdata->read_offset += cbytes;
cfdata->uncompressed_bytes_remaining -= cbytes;
cfdata->read_offset += (uint16_t)cbytes;
cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
cfdata->unconsumed -= cbytes;
} else {
cbytes = cfdata->uncompressed_avail - cfdata->read_offset;
@ -1882,8 +1879,8 @@ cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
if (consumed_bytes < cbytes)
cbytes = consumed_bytes;
rbytes -= cbytes;
cfdata->read_offset += cbytes;
cfdata->uncompressed_bytes_remaining -= cbytes;
cfdata->read_offset += (uint16_t)cbytes;
cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes;
}
if (cfdata->unconsumed) {
@ -1894,12 +1891,12 @@ cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes)
}
if (cbytes) {
/* Compute the sum. */
cab_checksum_update(a, cbytes);
cab_checksum_update(a, (size_t)cbytes);
/* Consume as much as the compressor actually used. */
__archive_read_consume(a, cbytes);
cab->cab_offset += cbytes;
cfdata->compressed_bytes_remaining -= cbytes;
cfdata->compressed_bytes_remaining -= (uint16_t)cbytes;
if (cfdata->compressed_bytes_remaining == 0) {
err = cab_checksum_finish(a);
if (err < 0)
@ -1940,10 +1937,10 @@ cab_read_data(struct archive_read *a, const void **buff,
ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA");
return (ARCHIVE_FATAL);
} else
return (bytes_avail);
return ((int)bytes_avail);
}
if (bytes_avail > cab->entry_bytes_remaining)
bytes_avail = cab->entry_bytes_remaining;
bytes_avail = (ssize_t)cab->entry_bytes_remaining;
*size = bytes_avail;
*offset = cab->entry_offset;
@ -1952,6 +1949,11 @@ cab_read_data(struct archive_read *a, const void **buff,
if (cab->entry_bytes_remaining == 0)
cab->end_of_entry = 1;
cab->entry_unconsumed = bytes_avail;
if (cab->entry_cffolder->comptype == COMPTYPE_NONE) {
/* Don't consume more than current entry used. */
if (cab->entry_cfdata->unconsumed > cab->entry_unconsumed)
cab->entry_cfdata->unconsumed = cab->entry_unconsumed;
}
return (ARCHIVE_OK);
}
@ -1967,9 +1969,17 @@ archive_read_format_cab_read_data_skip(struct archive_read *a)
if (cab->end_of_archive)
return (ARCHIVE_EOF);
if (!cab->read_data_invoked) {
cab->bytes_skipped += cab->entry_bytes_remaining;
cab->entry_bytes_remaining = 0;
/* This entry is finished and done. */
cab->end_of_entry_cleanup = cab->end_of_entry = 1;
return (ARCHIVE_OK);
}
if (cab->entry_unconsumed) {
/* Consume as much as the compressor actually used. */
r = cab_consume_cfdata(a, cab->entry_unconsumed);
r = (int)cab_consume_cfdata(a, cab->entry_unconsumed);
cab->entry_unconsumed = 0;
if (r < 0)
return (r);
@ -1991,6 +2001,12 @@ archive_read_format_cab_read_data_skip(struct archive_read *a)
if (bytes_skipped < 0)
return (ARCHIVE_FATAL);
/* If the compression type is none(uncompressed), we've already
* consumed data as much as the current entry size. */
if (cab->entry_cffolder->comptype == COMPTYPE_NONE &&
cab->entry_cfdata != NULL)
cab->entry_cfdata->unconsumed = 0;
/* This entry is finished and done. */
cab->end_of_entry_cleanup = cab->end_of_entry = 1;
return (ARCHIVE_OK);
@ -2066,6 +2082,7 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits)
struct lzx_dec *ds;
int slot, w_size, w_slot;
int base, footer;
int base_inc[18];
if (strm->ds == NULL) {
strm->ds = calloc(1, sizeof(*strm->ds));
@ -2100,13 +2117,15 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits)
lzx_huffman_free(&(ds->mt));
}
for (footer = 0; footer < 18; footer++)
base_inc[footer] = 1 << footer;
base = footer = 0;
for (slot = 0; slot < w_slot; slot++) {
int n;
if (footer == 0)
base = slot;
else
base += 1 << footer;
base += base_inc[footer];
if (footer < 17) {
footer = -2;
for (n = base; n; n >>= 1)
@ -2180,11 +2199,11 @@ lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset)
end = b + size - 10;
while (b < end && (b = memchr(b, 0xE8, end - b)) != NULL) {
size_t i = b - (unsigned char *)p;
long cp, displacement, value;
int32_t cp, displacement, value;
cp = offset + i;
cp = (int32_t)(offset + (uint32_t)i);
value = archive_le32dec(&b[1]);
if (value >= -cp && value < (long)ds->translation_size) {
if (value >= -cp && value < (int32_t)ds->translation_size) {
if (value >= 0)
displacement = value - cp;
else
@ -2222,7 +2241,9 @@ lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset)
/* Notify how many bits we consumed. */
#define lzx_br_consume(br, n) ((br)->cache_avail -= (n))
#define lzx_br_consume_unalined_bits(br) ((br)->cache_avail &= ~0x0f)
#define lzx_br_consume_unaligned_bits(br) ((br)->cache_avail &= ~0x0f)
#define lzx_br_is_unaligned(br) ((br)->cache_avail & 0x0f)
static const uint32_t cache_masks[] = {
0x00000000, 0x00000001, 0x00000003, 0x00000007,
@ -2349,24 +2370,25 @@ lzx_cleanup_bitstream(struct lzx_stream *strm)
#define ST_RD_TRANSLATION_SIZE 1
#define ST_RD_BLOCK_TYPE 2
#define ST_RD_BLOCK_SIZE 3
#define ST_RD_R0 4
#define ST_RD_R1 5
#define ST_RD_R2 6
#define ST_COPY_UNCOMP1 7
#define ST_COPY_UNCOMP2 8
#define ST_RD_ALIGNED_OFFSET 9
#define ST_RD_VERBATIM 10
#define ST_RD_PRE_MAIN_TREE_256 11
#define ST_MAIN_TREE_256 12
#define ST_RD_PRE_MAIN_TREE_REM 13
#define ST_MAIN_TREE_REM 14
#define ST_RD_PRE_LENGTH_TREE 15
#define ST_LENGTH_TREE 16
#define ST_MAIN 17
#define ST_LENGTH 18
#define ST_OFFSET 19
#define ST_REAL_POS 20
#define ST_COPY 21
#define ST_RD_ALIGNMENT 4
#define ST_RD_R0 5
#define ST_RD_R1 6
#define ST_RD_R2 7
#define ST_COPY_UNCOMP1 8
#define ST_COPY_UNCOMP2 9
#define ST_RD_ALIGNED_OFFSET 10
#define ST_RD_VERBATIM 11
#define ST_RD_PRE_MAIN_TREE_256 12
#define ST_MAIN_TREE_256 13
#define ST_RD_PRE_MAIN_TREE_REM 14
#define ST_MAIN_TREE_REM 15
#define ST_RD_PRE_LENGTH_TREE 16
#define ST_LENGTH_TREE 17
#define ST_MAIN 18
#define ST_LENGTH 19
#define ST_OFFSET 20
#define ST_REAL_POS 21
#define ST_COPY 22
static int
lzx_decode(struct lzx_stream *strm, int last)
@ -2470,12 +2492,25 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
ds->state = ST_RD_ALIGNED_OFFSET;
break;
}
/* FALL THROUGH */
case ST_RD_ALIGNMENT:
/*
* Handle an Uncompressed Block.
*/
/* Skip padding to align following field on
* 16-bit boundary. */
lzx_br_consume_unalined_bits(br);
if (lzx_br_is_unaligned(br))
lzx_br_consume_unaligned_bits(br);
else {
if (lzx_br_read_ahead(strm, br, 16))
lzx_br_consume(br, 16);
else {
ds->state = ST_RD_ALIGNMENT;
if (last)
goto failed;
return (ARCHIVE_OK);
}
}
/* Preparation to read repeated offsets R0,R1 and R2. */
ds->rbytes_avail = 0;
ds->state = ST_RD_R0;
@ -2500,8 +2535,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
lzx_br_consume(br, 16);
archive_le16enc(ds->rbytes, u16);
ds->rbytes_avail = 2;
} else
ds->rbytes_avail = 0;
}
if (ds->rbytes_avail < 4 && ds->br.have_odd) {
ds->rbytes[ds->rbytes_avail++] =
ds->br.odd;
@ -2517,6 +2551,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
*strm->next_in++;
strm->avail_in--;
}
ds->rbytes_avail = 0;
if (ds->state == ST_RD_R0) {
ds->r0 = archive_le32dec(ds->rbytes);
if (ds->r0 < 0)
@ -2541,8 +2576,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
* Copy bytes form next_in to next_out directly.
*/
while (ds->block_bytes_avail) {
unsigned char *d;
int l,ll;
int l;
if (strm->avail_out <= 0)
/* Output buffer is empty. */
@ -2553,24 +2587,23 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
goto failed;
return (ARCHIVE_OK);
}
l = ds->block_bytes_avail;
l = (int)ds->block_bytes_avail;
if (l > ds->w_size - ds->w_pos)
l = ds->w_size - ds->w_pos;
if (l > strm->avail_out)
l = (int)strm->avail_out;
if (l > strm->avail_in)
l = (int)strm->avail_in;
ll = l;
d = &(ds->w_buff[ds->w_pos]);
while (--l >= 0) {
*strm->next_out++ = *strm->next_in;
*d++ = *strm->next_in++;
}
strm->avail_out -= ll;
strm->total_out += ll;
strm->avail_in -= ll;
ds->w_pos = (ds->w_pos + ll) & ds->w_mask;
ds->block_bytes_avail -= ll;
memcpy(strm->next_out, strm->next_in, l);
memcpy(&(ds->w_buff[ds->w_pos]),
strm->next_in, l);
strm->next_in += l;
strm->avail_in -= l;
strm->next_out += l;
strm->avail_out -= l;
strm->total_out += l;
ds->w_pos = (ds->w_pos + l) & ds->w_mask;
ds->block_bytes_avail -= l;
}
/* FALL THROUGH */
case ST_COPY_UNCOMP2:
@ -2716,8 +2749,8 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
struct lzx_br bre = ds->br;
struct huffman *at = &(ds->at), *lt = &(ds->lt), *mt = &(ds->mt);
const struct lzx_pos_tbl *pos_tbl = ds->pos_tbl;
unsigned char *outp = strm->next_out;
unsigned char *endp = outp + strm->avail_out;
unsigned char *noutp = strm->next_out;
unsigned char *endp = noutp + strm->avail_out;
unsigned char *w_buff = ds->w_buff;
unsigned char *at_bitlen = at->bitlen;
unsigned char *lt_bitlen = lt->bitlen;
@ -2751,10 +2784,10 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
ds->position_slot = position_slot;
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
ds->w_pos = w_pos;
strm->avail_out = endp - outp;
strm->avail_out = endp - noutp;
return (ARCHIVE_EOF);
}
if (outp >= endp)
if (noutp >= endp)
/* Output buffer is empty. */
goto next_data;
@ -2788,7 +2821,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
w_buff[w_pos] = c;
w_pos = (w_pos + 1) & w_mask;
/* Store the decoded code to output buffer. */
*outp++ = c;
*noutp++ = c;
block_bytes_avail--;
}
/*
@ -2933,22 +2966,22 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
if (l > w_size - w_pos)
l = w_size - w_pos;
}
if (outp + l >= endp)
l = endp - outp;
if (noutp + l >= endp)
l = (int)(endp - noutp);
s = w_buff + copy_pos;
if (l >= 8 && ((copy_pos + l < w_pos)
|| (w_pos + l < copy_pos))) {
memcpy(w_buff + w_pos, s, l);
memcpy(outp, s, l);
memcpy(noutp, s, l);
} else {
unsigned char *d;
int li;
d = w_buff + w_pos;
for (li = 0; li < l; li++)
outp[li] = d[li] = s[li];
noutp[li] = d[li] = s[li];
}
outp += l;
noutp += l;
copy_pos = (copy_pos + l) & w_mask;
w_pos = (w_pos + l) & w_mask;
block_bytes_avail -= l;
@ -2956,7 +2989,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
/* A copy of current pattern ended. */
break;
copy_len -= l;
if (outp >= endp) {
if (noutp >= endp) {
/* Output buffer is empty. */
state = ST_COPY;
goto next_data;
@ -2979,7 +3012,7 @@ next_data:
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
ds->state = state;
ds->w_pos = w_pos;
strm->avail_out = endp - outp;
strm->avail_out = endp - noutp;
return (ARCHIVE_OK);
}
@ -3096,7 +3129,7 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
hf->bitlen = calloc(len_size, sizeof(hf->bitlen[0]));
if (hf->bitlen == NULL)
return (ARCHIVE_FATAL);
hf->len_size = len_size;
hf->len_size = (int)len_size;
} else
memset(hf->bitlen, 0, len_size * sizeof(hf->bitlen[0]));
if (hf->tbl == NULL) {
@ -3104,7 +3137,7 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
bits = tbl_bits;
else
bits = HTBL_BITS;
hf->tbl = malloc((1 << bits) * sizeof(hf->tbl[0]));
hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
if (hf->tbl == NULL)
return (ARCHIVE_FATAL);
hf->tbl_bits = tbl_bits;

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2010-2011 Michihiro NAKAJIMA
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -242,6 +242,7 @@ archive_read_support_format_cpio(struct archive *_a)
archive_read_format_cpio_read_header,
archive_read_format_cpio_read_data,
archive_read_format_cpio_skip,
NULL,
archive_read_format_cpio_cleanup);
if (r != ARCHIVE_OK)
@ -325,7 +326,7 @@ archive_read_format_cpio_options(struct archive_read *a,
if (strcmp(key, "compat-2x") == 0) {
/* Handle filnames as libarchive 2.x */
cpio->init_default_conversion = (val != NULL)?1:0;
ret = ARCHIVE_OK;
return (ARCHIVE_OK);
} else if (strcmp(key, "hdrcharset") == 0) {
if (val == NULL || val[0] == 0)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@ -339,13 +340,15 @@ archive_read_format_cpio_options(struct archive_read *a,
else
ret = ARCHIVE_FATAL;
}
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"cpio: unknown keyword ``%s''", key);
return (ret);
}
/* 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 int
archive_read_format_cpio_read_header(struct archive_read *a,
struct archive_entry *entry)
@ -396,11 +399,12 @@ archive_read_format_cpio_read_header(struct archive_read *a,
/* If this is a symlink, read the link contents. */
if (archive_entry_filetype(entry) == AE_IFLNK) {
h = __archive_read_ahead(a, cpio->entry_bytes_remaining, NULL);
h = __archive_read_ahead(a,
(size_t)cpio->entry_bytes_remaining, NULL);
if (h == NULL)
return (ARCHIVE_FATAL);
if (archive_entry_copy_symlink_l(entry, (const char *)h,
cpio->entry_bytes_remaining, sconv) != 0) {
(size_t)cpio->entry_bytes_remaining, sconv) != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Linkname");
@ -456,7 +460,7 @@ archive_read_format_cpio_read_data(struct archive_read *a,
if (bytes_read <= 0)
return (ARCHIVE_FATAL);
if (bytes_read > cpio->entry_bytes_remaining)
bytes_read = cpio->entry_bytes_remaining;
bytes_read = (ssize_t)cpio->entry_bytes_remaining;
*size = bytes_read;
cpio->entry_bytes_unconsumed = bytes_read;
*offset = cpio->entry_offset;
@ -601,17 +605,23 @@ header_newc(struct archive_read *a, struct cpio *cpio,
/* TODO: Abort here? */
}
archive_entry_set_devmajor(entry, atol16(header + newc_devmajor_offset, newc_devmajor_size));
archive_entry_set_devminor(entry, atol16(header + newc_devminor_offset, newc_devminor_size));
archive_entry_set_devmajor(entry,
(dev_t)atol16(header + newc_devmajor_offset, newc_devmajor_size));
archive_entry_set_devminor(entry,
(dev_t)atol16(header + newc_devminor_offset, newc_devminor_size));
archive_entry_set_ino(entry, atol16(header + newc_ino_offset, newc_ino_size));
archive_entry_set_mode(entry, atol16(header + newc_mode_offset, newc_mode_size));
archive_entry_set_mode(entry,
(mode_t)atol16(header + newc_mode_offset, newc_mode_size));
archive_entry_set_uid(entry, atol16(header + newc_uid_offset, newc_uid_size));
archive_entry_set_gid(entry, atol16(header + newc_gid_offset, newc_gid_size));
archive_entry_set_nlink(entry, atol16(header + newc_nlink_offset, newc_nlink_size));
archive_entry_set_rdevmajor(entry, atol16(header + newc_rdevmajor_offset, newc_rdevmajor_size));
archive_entry_set_rdevminor(entry, atol16(header + newc_rdevminor_offset, newc_rdevminor_size));
archive_entry_set_nlink(entry,
(unsigned int)atol16(header + newc_nlink_offset, newc_nlink_size));
archive_entry_set_rdevmajor(entry,
(dev_t)atol16(header + newc_rdevmajor_offset, newc_rdevmajor_size));
archive_entry_set_rdevminor(entry,
(dev_t)atol16(header + newc_rdevminor_offset, newc_rdevminor_size));
archive_entry_set_mtime(entry, atol16(header + newc_mtime_offset, newc_mtime_size), 0);
*namelength = atol16(header + newc_namesize_offset, newc_namesize_size);
*namelength = (size_t)atol16(header + newc_namesize_offset, newc_namesize_size);
/* Pad name to 2 more than a multiple of 4. */
*name_pad = (2 - *namelength) & 3;
@ -765,15 +775,19 @@ header_odc(struct archive_read *a, struct cpio *cpio,
/* Parse out octal fields. */
header = (const char *)h;
archive_entry_set_dev(entry, atol8(header + odc_dev_offset, odc_dev_size));
archive_entry_set_dev(entry,
(dev_t)atol8(header + odc_dev_offset, odc_dev_size));
archive_entry_set_ino(entry, atol8(header + odc_ino_offset, odc_ino_size));
archive_entry_set_mode(entry, atol8(header + odc_mode_offset, odc_mode_size));
archive_entry_set_mode(entry,
(mode_t)atol8(header + odc_mode_offset, odc_mode_size));
archive_entry_set_uid(entry, atol8(header + odc_uid_offset, odc_uid_size));
archive_entry_set_gid(entry, atol8(header + odc_gid_offset, odc_gid_size));
archive_entry_set_nlink(entry, atol8(header + odc_nlink_offset, odc_nlink_size));
archive_entry_set_rdev(entry, atol8(header + odc_rdev_offset, odc_rdev_size));
archive_entry_set_nlink(entry,
(unsigned int)atol8(header + odc_nlink_offset, odc_nlink_size));
archive_entry_set_rdev(entry,
(dev_t)atol8(header + odc_rdev_offset, odc_rdev_size));
archive_entry_set_mtime(entry, atol8(header + odc_mtime_offset, odc_mtime_size), 0);
*namelength = atol8(header + odc_namesize_offset, odc_namesize_size);
*namelength = (size_t)atol8(header + odc_namesize_offset, odc_namesize_size);
*name_pad = 0; /* No padding of filename. */
/*
@ -814,15 +828,19 @@ header_afiol(struct archive_read *a, struct cpio *cpio,
/* Parse out octal fields. */
header = (const char *)h;
archive_entry_set_dev(entry, atol16(header + afiol_dev_offset, afiol_dev_size));
archive_entry_set_dev(entry,
(dev_t)atol16(header + afiol_dev_offset, afiol_dev_size));
archive_entry_set_ino(entry, atol16(header + afiol_ino_offset, afiol_ino_size));
archive_entry_set_mode(entry, atol8(header + afiol_mode_offset, afiol_mode_size));
archive_entry_set_mode(entry,
(mode_t)atol8(header + afiol_mode_offset, afiol_mode_size));
archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size));
archive_entry_set_gid(entry, atol16(header + afiol_gid_offset, afiol_gid_size));
archive_entry_set_nlink(entry, atol16(header + afiol_nlink_offset, afiol_nlink_size));
archive_entry_set_rdev(entry, atol16(header + afiol_rdev_offset, afiol_rdev_size));
archive_entry_set_nlink(entry,
(unsigned int)atol16(header + afiol_nlink_offset, afiol_nlink_size));
archive_entry_set_rdev(entry,
(dev_t)atol16(header + afiol_rdev_offset, afiol_rdev_size));
archive_entry_set_mtime(entry, atol16(header + afiol_mtime_offset, afiol_mtime_size), 0);
*namelength = atol16(header + afiol_namesize_offset, afiol_namesize_size);
*namelength = (size_t)atol16(header + afiol_namesize_offset, afiol_namesize_size);
*name_pad = 0; /* No padding of filename. */
cpio->entry_bytes_remaining =

View File

@ -53,6 +53,7 @@ archive_read_support_format_empty(struct archive *_a)
archive_read_format_empty_read_header,
archive_read_format_empty_read_data,
NULL,
NULL,
NULL);
return (r);

View File

@ -1,7 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2009 Andreas Henriksson <andreas@fatal.se>
* Copyright (c) 2009-2011 Michihiro NAKAJIMA
* Copyright (c) 2009-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -374,6 +374,8 @@ struct iso9660 {
size_t utf16be_path_len;
unsigned char *utf16be_previous_path;
size_t utf16be_previous_path_len;
/* Null buufer used in bidder to improve its performance. */
unsigned char null[2048];
};
static int archive_read_format_iso9660_bid(struct archive_read *, int);
@ -475,6 +477,7 @@ archive_read_support_format_iso9660(struct archive *_a)
archive_read_format_iso9660_read_header,
archive_read_format_iso9660_read_data,
archive_read_format_iso9660_read_data_skip,
NULL,
archive_read_format_iso9660_cleanup);
if (r != ARCHIVE_OK) {
@ -587,6 +590,23 @@ archive_read_format_iso9660_options(struct archive_read *a,
return (ARCHIVE_WARN);
}
static int
isNull(struct iso9660 *iso9660, const unsigned char *h, unsigned offset,
unsigned bytes)
{
while (bytes >= sizeof(iso9660->null)) {
if (!memcmp(iso9660->null, h + offset, sizeof(iso9660->null)))
return (0);
offset += sizeof(iso9660->null);
bytes -= sizeof(iso9660->null);
}
if (bytes)
return memcmp(iso9660->null, h + offset, bytes) == 0;
else
return (1);
}
static int
isBootRecord(struct iso9660 *iso9660, const unsigned char *h)
{
@ -632,8 +652,6 @@ isVolumePartition(struct iso9660 *iso9660, const unsigned char *h)
static int
isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h)
{
int i;
(void)iso9660; /* UNUSED */
/* Type of the Volume Descriptor Set Terminator must be 255. */
@ -645,8 +663,7 @@ isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
for (i = 7; i < 2048; ++i)
if (h[i] != 0)
if (!isNull(iso9660, h, 7, 2048-7))
return (0);
return (1);
@ -708,7 +725,6 @@ isSVD(struct iso9660 *iso9660, const unsigned char *h)
ssize_t logical_block_size;
int32_t volume_block;
int32_t location;
int i;
(void)iso9660; /* UNUSED */
@ -717,14 +733,11 @@ isSVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
for (i = 0; i < SVD_reserved1_size; ++i)
if (h[SVD_reserved1_offset + i] != 0)
if (!isNull(iso9660, h, SVD_reserved1_offset, SVD_reserved1_size))
return (0);
for (i = 0; i < SVD_reserved2_size; ++i)
if (h[SVD_reserved2_offset + i] != 0)
if (!isNull(iso9660, h, SVD_reserved2_offset, SVD_reserved2_size))
return (0);
for (i = 0; i < SVD_reserved3_size; ++i)
if (h[SVD_reserved3_offset + i] != 0)
if (!isNull(iso9660, h, SVD_reserved3_offset, SVD_reserved3_size))
return (0);
/* File structure version must be 1 for ISO9660/ECMA119. */
@ -771,7 +784,6 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
ssize_t logical_block_size;
int32_t volume_block;
int32_t location;
int i;
(void)iso9660; /* UNUSED */
@ -788,13 +800,11 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
for (i = 0; i < PVD_reserved2_size; ++i)
if (h[PVD_reserved2_offset + i] != 0)
if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size))
return (0);
/* Reserved field must be 0. */
for (i = 0; i < PVD_reserved3_size; ++i)
if (h[PVD_reserved3_offset + i] != 0)
if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size))
return (0);
/* Logical block size must be > 0. */
@ -830,13 +840,11 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
for (i = 0; i < PVD_reserved4_size; ++i)
if (h[PVD_reserved4_offset + i] != 0)
if (!isNull(iso9660, h, PVD_reserved4_offset, PVD_reserved4_size))
return (0);
/* Reserved field must be 0. */
for (i = 0; i < PVD_reserved5_size; ++i)
if (h[PVD_reserved5_offset + i] != 0)
if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size))
return (0);
/* Read Root Directory Record in Volume Descriptor. */
@ -869,13 +877,11 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
for (i = 0; i < PVD_reserved2_size; ++i)
if (h[PVD_reserved2_offset + i] != 0)
if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size))
return (0);
/* Reserved field must be 0. */
for (i = 0; i < PVD_reserved3_size; ++i)
if (h[PVD_reserved3_offset + i] != 0)
if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size))
return (0);
/* Logical block size must be > 0. */
@ -919,8 +925,7 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
return (0);
/* Reserved field must be 0. */
for (i = 0; i < PVD_reserved5_size; ++i)
if (h[PVD_reserved5_offset + i] != 0)
if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size))
return (0);
/* XXX TODO: Check other values for sanity; reject more
@ -934,8 +939,10 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
if (!iso9660->primary.location) {
iso9660->logical_block_size = logical_block_size;
iso9660->volume_block = volume_block;
iso9660->volume_size = logical_block_size * (uint64_t)volume_block;
iso9660->primary.location = archive_le32dec(p + DR_extent_offset);
iso9660->volume_size =
logical_block_size * (uint64_t)volume_block;
iso9660->primary.location =
archive_le32dec(p + DR_extent_offset);
iso9660->primary.size = archive_le32dec(p + DR_size_offset);
}
@ -951,6 +958,12 @@ read_children(struct archive_read *a, struct file_info *parent)
size_t step, skip_size;
iso9660 = (struct iso9660 *)(a->format->data);
/* flush any remaining bytes from the last round to ensure
* we're positioned */
if (iso9660->entry_bytes_unconsumed) {
__archive_read_consume(a, iso9660->entry_bytes_unconsumed);
iso9660->entry_bytes_unconsumed = 0;
}
if (iso9660->current_position > parent->offset) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Ignoring out-of-order directory (%s) %jd > %jd",
@ -975,8 +988,8 @@ read_children(struct archive_read *a, struct file_info *parent)
iso9660->current_position = parent->offset;
}
step = ((parent->size + iso9660->logical_block_size -1) /
iso9660->logical_block_size) * iso9660->logical_block_size;
step = (size_t)(((parent->size + iso9660->logical_block_size -1) /
iso9660->logical_block_size) * iso9660->logical_block_size);
b = __archive_read_ahead(a, step, NULL);
if (b == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@ -1060,21 +1073,9 @@ read_children(struct archive_read *a, struct file_info *parent)
}
static int
archive_read_format_iso9660_read_header(struct archive_read *a,
struct archive_entry *entry)
choose_volume(struct archive_read *a, struct iso9660 *iso9660)
{
struct iso9660 *iso9660;
struct file_info *file;
int r, rd_r = ARCHIVE_OK;
iso9660 = (struct iso9660 *)(a->format->data);
if (!a->archive.archive_format) {
a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
a->archive.archive_format_name = "ISO9660";
}
if (iso9660->current_position == 0) {
int64_t skipsize;
struct vd *vd;
const void *block;
@ -1096,17 +1097,16 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
block = __archive_read_ahead(a, vd->size, NULL);
if (block == NULL) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Failed to read full block when scanning "
"ISO9660 directory list");
return (ARCHIVE_FATAL);
}
/*
* While reading Root Directory, flag seenJoliet
* must be zero to avoid converting special name
* 0x00(Current Directory) and next byte to UCS2.
* While reading Root Directory, flag seenJoliet must be zero to
* avoid converting special name 0x00(Current Directory) and
* next byte to UCS2.
*/
seenJoliet = iso9660->seenJoliet;/* Save flag. */
iso9660->seenJoliet = 0;
@ -1114,13 +1114,15 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
if (file == NULL)
return (ARCHIVE_FATAL);
iso9660->seenJoliet = seenJoliet;
/*
* If the iso image has both RockRidge and Joliet, we preferentially
* use RockRidge Extensions rather than Joliet ones.
*/
if (vd == &(iso9660->primary) && iso9660->seenRockridge
&& iso9660->seenJoliet)
/*
* If iso image has RockRidge and Joliet,
* we use RockRidge Extensions.
*/
iso9660->seenJoliet = 0;
if (vd == &(iso9660->primary) && !iso9660->seenRockridge
&& iso9660->seenJoliet) {
/* Switch reading data from primary to joliet. */
@ -1134,8 +1136,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
block = __archive_read_ahead(a, vd->size, NULL);
if (block == NULL) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Failed to read full block when scanning "
"ISO9660 directory list");
return (ARCHIVE_FATAL);
@ -1146,15 +1147,38 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
return (ARCHIVE_FATAL);
iso9660->seenJoliet = seenJoliet;
}
/* Store the root directory in the pending list. */
if (add_entry(a, iso9660, file) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
if (iso9660->seenRockridge) {
a->archive.archive_format =
ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
a->archive.archive_format = ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
a->archive.archive_format_name =
"ISO9660 with Rockridge extensions";
}
return (ARCHIVE_OK);
}
static int
archive_read_format_iso9660_read_header(struct archive_read *a,
struct archive_entry *entry)
{
struct iso9660 *iso9660;
struct file_info *file;
int r, rd_r = ARCHIVE_OK;
iso9660 = (struct iso9660 *)(a->format->data);
if (!a->archive.archive_format) {
a->archive.archive_format = ARCHIVE_FORMAT_ISO9660;
a->archive.archive_format_name = "ISO9660";
}
if (iso9660->current_position == 0) {
r = choose_volume(a, iso9660);
if (r != ARCHIVE_OK)
return (r);
}
file = NULL;/* Eliminate a warning. */
@ -1227,14 +1251,14 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
}
iso9660->entry_bytes_remaining = file->size;
iso9660->entry_sparse_offset = 0; /* Offset for sparse-file-aware clients. */
/* Offset for sparse-file-aware clients. */
iso9660->entry_sparse_offset = 0;
if (file->offset + file->size > iso9660->volume_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"File is beyond end-of-media: %s",
archive_entry_pathname(entry));
iso9660->entry_bytes_remaining = 0;
iso9660->entry_sparse_offset = 0;
return (ARCHIVE_WARN);
}
@ -1286,27 +1310,23 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
iso9660->previous_pathname.s);
archive_entry_unset_size(entry);
iso9660->entry_bytes_remaining = 0;
iso9660->entry_sparse_offset = 0;
return (rd_r);
}
/* Except for the hardlink case above, if the offset of the
* next entry is before our current position, we can't seek
* backwards to extract it, so issue a warning. Note that
* this can only happen if this entry was added to the heap
* after we passed this offset, that is, only if the directory
* mentioning this entry is later than the body of the entry.
* Such layouts are very unusual; most ISO9660 writers lay out
* and record all directory information first, then store
* all file bodies. */
/* TODO: Someday, libarchive's I/O core will support optional
* seeking. When that day comes, this code should attempt to
* seek and only return the error if the seek fails. That
* will give us support for whacky ISO images that require
* seeking while retaining the ability to read almost all ISO
* images in a streaming fashion. */
if ((file->mode & AE_IFMT) != AE_IFDIR &&
file->offset < iso9660->current_position) {
int64_t r64;
r64 = __archive_read_seek(a, file->offset, SEEK_SET);
if (r64 != (int64_t)file->offset) {
/* We can't seek backwards to extract it, so issue
* a warning. Note that this can only happen if
* this entry was added to the heap after we passed
* this offset, that is, only if the directory
* mentioning this entry is later than the body of
* the entry. Such layouts are very unusual; most
* ISO9660 writers lay out and record all directory
* information first, then store all file bodies. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Ignoring out-of-order file @%jx (%s) %jd < %jd",
(intmax_t)file->number,
@ -1314,9 +1334,10 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
(intmax_t)file->offset,
(intmax_t)iso9660->current_position);
iso9660->entry_bytes_remaining = 0;
iso9660->entry_sparse_offset = 0;
return (ARCHIVE_WARN);
}
iso9660->current_position = (uint64_t)r64;
}
/* Initialize zisofs variables. */
iso9660->entry_zisofs.pz = file->pz;
@ -1356,7 +1377,6 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
archive_entry_set_nlink(entry, 2 + file->subdirs);
/* Directory data has been read completely. */
iso9660->entry_bytes_remaining = 0;
iso9660->entry_sparse_offset = 0;
}
if (rd_r != ARCHIVE_OK)
@ -1397,7 +1417,7 @@ zisofs_read_data(struct archive_read *a,
return (ARCHIVE_FATAL);
}
if (bytes_read > iso9660->entry_bytes_remaining)
bytes_read = iso9660->entry_bytes_remaining;
bytes_read = (ssize_t)iso9660->entry_bytes_remaining;
avail = bytes_read;
uncompressed_size = 0;
@ -1405,9 +1425,9 @@ zisofs_read_data(struct archive_read *a,
size_t ceil, xsize;
/* Allocate block pointers buffer. */
ceil = (zisofs->pz_uncompressed_size +
(1LL << zisofs->pz_log2_bs) - 1)
>> zisofs->pz_log2_bs;
ceil = (size_t)((zisofs->pz_uncompressed_size +
(((int64_t)1) << zisofs->pz_log2_bs) - 1)
>> zisofs->pz_log2_bs);
xsize = (ceil + 1) * 4;
if (zisofs->block_pointers_alloc < xsize) {
size_t alloc;
@ -1426,7 +1446,7 @@ zisofs_read_data(struct archive_read *a,
zisofs->block_pointers_size = xsize;
/* Allocate uncompressed data buffer. */
xsize = 1UL << zisofs->pz_log2_bs;
xsize = (size_t)1UL << zisofs->pz_log2_bs;
if (zisofs->uncompressed_buffer_size < xsize) {
if (zisofs->uncompressed_buffer != NULL)
free(zisofs->uncompressed_buffer);
@ -1563,9 +1583,10 @@ zisofs_read_data(struct archive_read *a,
if (avail > zisofs->block_avail)
zisofs->stream.avail_in = zisofs->block_avail;
else
zisofs->stream.avail_in = avail;
zisofs->stream.avail_in = (uInt)avail;
zisofs->stream.next_out = zisofs->uncompressed_buffer;
zisofs->stream.avail_out = zisofs->uncompressed_buffer_size;
zisofs->stream.avail_out =
(uInt)zisofs->uncompressed_buffer_size;
r = inflate(&zisofs->stream, 0);
switch (r) {
@ -1580,7 +1601,7 @@ zisofs_read_data(struct archive_read *a,
uncompressed_size =
zisofs->uncompressed_buffer_size - zisofs->stream.avail_out;
avail -= zisofs->stream.next_in - p;
zisofs->block_avail -= zisofs->stream.next_in - p;
zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p);
}
next_data:
bytes_read -= avail;
@ -1590,7 +1611,7 @@ next_data:
iso9660->entry_sparse_offset += uncompressed_size;
iso9660->entry_bytes_remaining -= bytes_read;
iso9660->current_position += bytes_read;
zisofs->pz_offset += bytes_read;
zisofs->pz_offset += (uint32_t)bytes_read;
iso9660->entry_bytes_unconsumed += bytes_read;
return (ARCHIVE_OK);
@ -1671,7 +1692,7 @@ archive_read_format_iso9660_read_data(struct archive_read *a,
if (*buff == NULL)
return (ARCHIVE_FATAL);
if (bytes_read > iso9660->entry_bytes_remaining)
bytes_read = iso9660->entry_bytes_remaining;
bytes_read = (ssize_t)iso9660->entry_bytes_remaining;
*size = bytes_read;
*offset = iso9660->entry_sparse_offset;
iso9660->entry_sparse_offset += bytes_read;
@ -1756,7 +1777,8 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
*/
if (location > 0 &&
(location + ((fsize + iso9660->logical_block_size -1)
/ iso9660->logical_block_size)) > iso9660->volume_block) {
/ iso9660->logical_block_size))
> (uint32_t)iso9660->volume_block) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Invalid location of extent of file");
return (NULL);
@ -1872,9 +1894,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
if (iso9660->opt_support_rockridge) {
if (parent == NULL && rr_end - rr_start >= 7) {
p = rr_start;
if (p[0] == 'S' && p[1] == 'P'
&& p[2] == 7 && p[3] == 1
&& p[4] == 0xBE && p[5] == 0xEF) {
if (memcmp(p, "SP\x07\x01\xbe\xef", 6) == 0) {
/*
* SP extension stores the suspOffset
* (Number of bytes to skip between
@ -1907,6 +1927,19 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
free(file);
return (NULL);
}
/*
* A file size of symbolic link files in ISO images
* made by makefs is not zero and its location is
* the same as those of next regular file. That is
* the same as hard like file and it causes unexpected
* error.
*/
if (file->size > 0 &&
(file->mode & AE_IFMT) == AE_IFLNK) {
file->size = 0;
file->number = -1;
file->offset = -1;
}
} else
/* If there isn't SUSP, disable parsing
* rock ridge extensions. */
@ -1921,6 +1954,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
if (iso9660->seenRockridge) {
if (parent != NULL && parent->parent == NULL &&
(flags & 0x02) && iso9660->rr_moved == NULL &&
file->name.s &&
(strcmp(file->name.s, "rr_moved") == 0 ||
strcmp(file->name.s, ".rr_moved") == 0)) {
iso9660->rr_moved = file;
@ -2053,14 +2087,9 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
int data_length = p[2] - 4;
int version = p[3];
/*
* Yes, each 'if' here does test p[0] again.
* Otherwise, the fall-through handling to catch
* unsupported extensions doesn't work.
*/
switch(p[0]) {
case 'C':
if (p[0] == 'C' && p[1] == 'E') {
if (p[1] == 'E') {
if (version == 1 && data_length == 24) {
/*
* CE extension comprises:
@ -2078,53 +2107,42 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
!= ARCHIVE_OK)
return (ARCHIVE_FATAL);
}
break;
}
if (p[0] == 'C' && p[1] == 'L') {
else if (p[1] == 'L') {
if (version == 1 && data_length == 8) {
file->cl_offset = (uint64_t)
iso9660->logical_block_size *
(uint64_t)archive_le32dec(data);
iso9660->seenRockridge = 1;
}
break;
}
/* FALLTHROUGH */
break;
case 'N':
if (p[0] == 'N' && p[1] == 'M') {
if (p[1] == 'M') {
if (version == 1) {
parse_rockridge_NM1(file,
data, data_length);
iso9660->seenRockridge = 1;
}
break;
}
/* FALLTHROUGH */
break;
case 'P':
if (p[0] == 'P' && p[1] == 'D') {
/*
* PD extension is padding;
* contents are always ignored.
*/
break;
}
if (p[0] == 'P' && p[1] == 'L') {
/*
*
* PL extension won't appear;
* contents are always ignored.
*/
break;
}
if (p[0] == 'P' && p[1] == 'N') {
if (p[1] == 'N') {
if (version == 1 && data_length == 16) {
file->rdev = toi(data,4);
file->rdev <<= 32;
file->rdev |= toi(data + 8, 4);
iso9660->seenRockridge = 1;
}
break;
}
if (p[0] == 'P' && p[1] == 'X') {
else if (p[1] == 'X') {
/*
* PX extension comprises:
* 8 bytes for mode,
@ -2151,35 +2169,31 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
= toi(data + 32, 4);
iso9660->seenRockridge = 1;
}
break;
}
/* FALLTHROUGH */
break;
case 'R':
if (p[0] == 'R' && p[1] == 'E' && version == 1) {
if (p[1] == 'E' && version == 1) {
file->re = 1;
iso9660->seenRockridge = 1;
break;
}
if (p[0] == 'R' && p[1] == 'R' && version == 1) {
else if (p[1] == 'R' && version == 1) {
/*
* RR extension comprises:
* one byte flag value
* This extension is obsolete,
* so contents are always ignored.
*/
break;
}
/* FALLTHROUGH */
break;
case 'S':
if (p[0] == 'S' && p[1] == 'L') {
if (p[1] == 'L') {
if (version == 1) {
parse_rockridge_SL1(file,
data, data_length);
iso9660->seenRockridge = 1;
}
break;
}
if (p[0] == 'S' && p[1] == 'T'
else if (p[1] == 'T'
&& data_length == 0 && version == 1) {
/*
* ST extension marks end of this
@ -2194,32 +2208,27 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
iso9660->seenRockridge = 0;
return (ARCHIVE_OK);
}
break;
case 'T':
if (p[0] == 'T' && p[1] == 'F') {
if (p[1] == 'F') {
if (version == 1) {
parse_rockridge_TF1(file,
data, data_length);
iso9660->seenRockridge = 1;
}
break;
}
/* FALLTHROUGH */
break;
case 'Z':
if (p[0] == 'Z' && p[1] == 'F') {
if (p[1] == 'F') {
if (version == 1)
parse_rockridge_ZF1(file,
data, data_length);
break;
}
/* FALLTHROUGH */
break;
default:
/* The FALLTHROUGHs above leave us here for
* any unsupported extension. */
break;
}
p += p[2];
}
return (ARCHIVE_OK);
@ -2241,7 +2250,7 @@ register_CE(struct archive_read *a, int32_t location,
offset >= file->offset) ||
offset < iso9660->current_position ||
(((uint64_t)file->ce_offset) + file->ce_size)
> iso9660->logical_block_size ||
> (uint64_t)iso9660->logical_block_size ||
offset + file->ce_offset + file->ce_size
> iso9660->volume_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@ -2263,7 +2272,7 @@ register_CE(struct archive_read *a, int32_t location,
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
p = malloc(new_size * sizeof(p[0]));
p = calloc(new_size, sizeof(p[0]));
if (p == NULL) {
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
@ -2513,9 +2522,6 @@ parse_rockridge_SL1(struct file_info *file, const unsigned char *data,
if (!file->symlink_continues || file->symlink.length < 1)
archive_string_empty(&file->symlink);
else if (!file->symlink_continues &&
file->symlink.s[file->symlink.length - 1] != '/')
separator = "/";
file->symlink_continues = 0;
/*
@ -2883,7 +2889,8 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
fatal_rr:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Failed to connect 'CL' pointer to 'RE' rr_moved pointer of "
"Rockridge extensions");
"Rockridge extensions: current position = %jd, CL offset = %jd",
(intmax_t)iso9660->current_position, (intmax_t)file->cl_offset);
return (ARCHIVE_FATAL);
}
@ -3085,6 +3092,8 @@ isodate7(const unsigned char *v)
{
struct tm tm;
int offset;
time_t t;
memset(&tm, 0, sizeof(tm));
tm.tm_year = v[0];
tm.tm_mon = v[1] - 1;
@ -3098,7 +3107,10 @@ isodate7(const unsigned char *v)
tm.tm_hour -= offset / 4;
tm.tm_min -= (offset % 4) * 15;
}
return (time_from_tm(&tm));
t = time_from_tm(&tm);
if (t == (time_t)-1)
return ((time_t)0);
return (t);
}
static time_t
@ -3106,6 +3118,8 @@ isodate17(const unsigned char *v)
{
struct tm tm;
int offset;
time_t t;
memset(&tm, 0, sizeof(tm));
tm.tm_year = (v[0] - '0') * 1000 + (v[1] - '0') * 100
+ (v[2] - '0') * 10 + (v[3] - '0')
@ -3121,7 +3135,10 @@ isodate17(const unsigned char *v)
tm.tm_hour -= offset / 4;
tm.tm_min -= (offset % 4) * 15;
}
return (time_from_tm(&tm));
t = time_from_tm(&tm);
if (t == (time_t)-1)
return ((time_t)0);
return (t);
}
static time_t
@ -3135,7 +3152,8 @@ time_from_tm(struct tm *t)
#else
/* Else use direct calculation using POSIX assumptions. */
/* First, fix up tm_yday based on the year/month/day. */
mktime(t);
if (mktime(t) == (time_t)-1)
return ((time_t)-1);
/* Then we can compute timegm() from first principles. */
return (t->tm_sec + t->tm_min * 60 + t->tm_hour * 3600
+ t->tm_yday * 86400 + (t->tm_year - 70) * 31536000
@ -3204,10 +3222,12 @@ dump_isodirrec(FILE *out, const unsigned char *isodirrec)
fprintf(out, " ilv %d,",
toi(isodirrec + DR_interleave_offset, DR_interleave_size));
fprintf(out, " seq %d,",
toi(isodirrec + DR_volume_sequence_number_offset, DR_volume_sequence_number_size));
toi(isodirrec + DR_volume_sequence_number_offset,
DR_volume_sequence_number_size));
fprintf(out, " nl %d:",
toi(isodirrec + DR_name_len_offset, DR_name_len_size));
fprintf(out, " `%.*s'",
toi(isodirrec + DR_name_len_offset, DR_name_len_size), isodirrec + DR_name_offset);
toi(isodirrec + DR_name_len_offset, DR_name_len_size),
isodirrec + DR_name_offset);
}
#endif

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2008-2011 Michihiro NAKAJIMA
* Copyright (c) 2008-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -272,7 +272,7 @@ static int lha_skip_sfx(struct archive_read *);
static time_t lha_dos_time(const unsigned char *);
static time_t lha_win_time(uint64_t, long *);
static unsigned char lha_calcsum(unsigned char, const void *,
int, int);
int, size_t);
static int lha_parse_linkname(struct archive_string *,
struct archive_string *);
static int lha_read_data_none(struct archive_read *, const void **,
@ -289,7 +289,7 @@ static void lzh_huffman_free(struct huffman *);
static int lzh_read_pt_bitlen(struct lzh_stream *, int start, int end);
static int lzh_make_fake_table(struct huffman *, uint16_t);
static int lzh_make_huffman_table(struct huffman *);
static int inline lzh_decode_huffman(struct huffman *, unsigned);
static inline int lzh_decode_huffman(struct huffman *, unsigned);
static int lzh_decode_huffman_tree(struct huffman *, unsigned, int);
@ -319,6 +319,7 @@ archive_read_support_format_lha(struct archive *_a)
archive_read_format_lha_read_header,
archive_read_format_lha_read_data,
archive_read_format_lha_read_data_skip,
NULL,
archive_read_format_lha_cleanup);
if (r != ARCHIVE_OK)
@ -445,13 +446,15 @@ archive_read_format_lha_options(struct archive_read *a,
else
ret = ARCHIVE_FATAL;
}
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"lha: unknown keyword ``%s''", key);
return (ret);
}
/* 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 int
lha_skip_sfx(struct archive_read *a)
{
@ -696,7 +699,7 @@ archive_read_format_lha_read_header(struct archive_read *a,
archive_entry_set_symlink(entry, NULL);
archive_string_free(&linkname);
/*
* When a header level is 0, there is a possibilty that
* When a header level is 0, there is a possibility that
* a pathname and a symlink has '\' character, a directory
* separator in DOS/Windows. So we should convert it to '/'.
*/
@ -949,7 +952,7 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha)
/* Read extended headers */
err2 = lha_read_file_extended_header(a, lha, NULL, 2,
lha->compsize + 2, &extdsize);
(size_t)(lha->compsize + 2), &extdsize);
if (err2 < ARCHIVE_WARN)
return (err2);
if (err2 < err)
@ -1444,7 +1447,7 @@ lha_read_data_none(struct archive_read *a, const void **buff,
return (ARCHIVE_FATAL);
}
if (bytes_avail > lha->entry_bytes_remaining)
bytes_avail = lha->entry_bytes_remaining;
bytes_avail = (ssize_t)lha->entry_bytes_remaining;
lha->entry_crc_calculated =
lha_crc16(lha->entry_crc_calculated, *buff, bytes_avail);
*size = bytes_avail;
@ -1527,7 +1530,7 @@ lha_read_data_lzh(struct archive_read *a, const void **buff,
return (ARCHIVE_FATAL);
}
if (bytes_avail > lha->entry_bytes_remaining)
bytes_avail = lha->entry_bytes_remaining;
bytes_avail = (ssize_t)lha->entry_bytes_remaining;
lha->strm.avail_in = bytes_avail;
lha->strm.total_in = 0;
@ -1573,7 +1576,7 @@ static int
archive_read_format_lha_read_data_skip(struct archive_read *a)
{
struct lha *lha;
off_t bytes_skipped;
int64_t bytes_skipped;
lha = (struct lha *)(a->format->data);
@ -1632,7 +1635,7 @@ lha_parse_linkname(struct archive_string *linkname,
struct archive_string *pathname)
{
char * linkptr;
int symlen;
size_t symlen;
linkptr = strchr(pathname->s, '|');
if (linkptr != NULL) {
@ -1687,12 +1690,12 @@ lha_win_time(uint64_t wintime, long *ns)
}
static unsigned char
lha_calcsum(unsigned char sum, const void *pp, int offset, int size)
lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size)
{
unsigned char const *p = (unsigned char const *)pp;
p += offset;
while (--size >= 0)
for (;size > 0; --size)
sum += *p++;
return (sum);
}
@ -2014,18 +2017,18 @@ lzh_copy_from_window(struct lzh_stream *strm, struct lzh_dec *ds)
if (ds->w_pos - ds->copy_pos <= strm->avail_out)
copy_bytes = ds->w_pos - ds->copy_pos;
else
copy_bytes = strm->avail_out;
copy_bytes = (size_t)strm->avail_out;
memcpy(strm->next_out,
ds->w_buff + ds->copy_pos, copy_bytes);
ds->copy_pos += copy_bytes;
ds->copy_pos += (int)copy_bytes;
} else {
if (ds->w_remaining <= strm->avail_out)
copy_bytes = ds->w_remaining;
else
copy_bytes = strm->avail_out;
copy_bytes = (size_t)strm->avail_out;
memcpy(strm->next_out,
ds->w_buff + ds->w_size - ds->w_remaining, copy_bytes);
ds->w_remaining -= copy_bytes;
ds->w_remaining -= (int)copy_bytes;
}
strm->next_out += copy_bytes;
strm->avail_out -= copy_bytes;
@ -2479,7 +2482,7 @@ lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
bits = tbl_bits;
else
bits = HTBL_BITS;
hf->tbl = malloc((1 << bits) * sizeof(hf->tbl[0]));
hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
if (hf->tbl == NULL)
return (ARCHIVE_FATAL);
}
@ -2489,7 +2492,7 @@ lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
if (hf->tree == NULL)
return (ARCHIVE_FATAL);
}
hf->len_size = len_size;
hf->len_size = (int)len_size;
hf->tbl_bits = tbl_bits;
return (ARCHIVE_OK);
}

View File

@ -1,7 +1,7 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2008 Joerg Sonnenberger
* Copyright (c) 2011 Michihiro NAKAJIMA
* Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -55,6 +55,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
#define MTREE_HAS_DEVICE 0x0001
#define MTREE_HAS_FFLAGS 0x0002
@ -69,6 +72,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#define MTREE_HAS_UNAME 0x0400
#define MTREE_HAS_OPTIONAL 0x0800
#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
struct mtree_option {
struct mtree_option *next;
@ -101,7 +105,9 @@ struct mtree {
int64_t cur_size;
};
static int bid_keycmp(const char *, const char *, ssize_t);
static int cleanup(struct archive_read *);
static int detect_form(struct archive_read *, int *);
static int mtree_bid(struct archive_read *, int);
static int parse_file(struct archive_read *, struct archive_entry *,
struct mtree *, struct mtree_entry *, int *);
@ -199,7 +205,7 @@ archive_read_support_format_mtree(struct archive *_a)
mtree->fd = -1;
r = __archive_read_register_format(a, mtree, "mtree",
mtree_bid, NULL, read_header, read_data, skip, cleanup);
mtree_bid, NULL, read_header, read_data, skip, NULL, cleanup);
if (r != ARCHIVE_OK)
free(mtree);
@ -317,7 +323,7 @@ next_line(struct archive_read *a,
* Returns the length of a mtree keyword if matched.
* Returns 0 if not matched.
*/
int
static int
bid_keycmp(const char *p, const char *key, ssize_t len)
{
int match_len = 0;
@ -348,7 +354,7 @@ bid_keycmp(const char *p, const char *key, ssize_t len)
* Returns the length of a detected keyword.
* Returns 0 if any keywords were not found.
*/
static ssize_t
static int
bid_keyword(const char *p, ssize_t len)
{
static const char *keys_c[] = {
@ -367,7 +373,7 @@ bid_keyword(const char *p, ssize_t len)
"md5", "md5digest", "mode", NULL
};
static const char *keys_no[] = {
"nlink", "optional", NULL
"nlink", "nochange", "optional", NULL
};
static const char *keys_r[] = {
"rmd160", "rmd160digest", NULL
@ -407,7 +413,7 @@ bid_keyword(const char *p, ssize_t len)
if (l > 0)
return (l);
}
return (0);/* Unkown key */
return (0);/* Unknown key */
}
/*
@ -418,7 +424,7 @@ bid_keyword(const char *p, ssize_t len)
* When "unset" is specified, expects a set of "<space characters>keyword".
*/
static int
bid_keyword_list(const char *p, ssize_t len, int unset)
bid_keyword_list(const char *p, ssize_t len, int unset, int last_is_path)
{
int l;
int keycnt = 0;
@ -436,8 +442,10 @@ bid_keyword_list(const char *p, ssize_t len, int unset)
break;
if (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r'))
break;
if (!blank) /* No blank character. */
if (!blank && !last_is_path) /* No blank character. */
return (-1);
if (last_is_path && len == 0)
return (keycnt);
if (unset) {
l = bid_keycmp(p, "all", len);
@ -472,7 +480,7 @@ bid_keyword_list(const char *p, ssize_t len, int unset)
}
static int
bid_entry(const char *p, ssize_t len)
bid_entry(const char *p, ssize_t len, ssize_t nl, int *last_is_path)
{
int f = 0;
static const unsigned char safe_char[256] = {
@ -499,22 +507,60 @@ bid_entry(const char *p, ssize_t len)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
};
ssize_t ll = len;
const char *pp = p;
*last_is_path = 0;
/*
* Skip the path-name which is quoted.
*/
while (len > 0 && *p != ' ' && *p != '\t') {
if (!safe_char[*(const unsigned char *)p])
return (-1);
++p;
--len;
while (ll > 0 && *pp != ' ' &&*pp != '\t' && *pp != '\r' &&
*pp != '\n') {
if (!safe_char[*(const unsigned char *)pp]) {
f = 0;
break;
}
++pp;
--ll;
++f;
}
/* If a path-name was not found, returns error. */
if (f == 0)
/* If a path-name was not found at the first, try to check
* a mtree format ``NetBSD's mtree -D'' creates, which
* places the path-name at the last. */
if (f == 0) {
const char *pb = p + len - nl;
int name_len = 0;
int slash;
/* Do not accept multi lines for form D. */
if (pb-2 >= p &&
pb[-1] == '\\' && (pb[-2] == ' ' || pb[-2] == '\t'))
return (-1);
if (pb-1 >= p && pb[-1] == '\\')
return (-1);
return (bid_keyword_list(p, len, 0));
slash = 0;
while (p <= --pb && *pb != ' ' && *pb != '\t') {
if (!safe_char[*(const unsigned char *)pb])
return (-1);
name_len++;
/* The pathname should have a slash in this
* format. */
if (*pb == '/')
slash = 1;
}
if (name_len == 0 || slash == 0)
return (-1);
/* If '/' is placed at the first in this field, this is not
* a valid filename. */
if (pb[1] == '/')
return (-1);
ll = len - nl - name_len;
pp = p;
*last_is_path = 1;
}
return (bid_keyword_list(pp, ll, 0, *last_is_path));
}
#define MAX_BID_ENTRY 3
@ -524,14 +570,11 @@ mtree_bid(struct archive_read *a, int best_bid)
{
const char *signature = "#mtree";
const char *p;
ssize_t avail, ravail;
ssize_t len, nl;
int detected_bytes = 0, entry_cnt = 0, multiline = 0;
(void)best_bid; /* UNUSED */
/* Now let's look at the actual header and see if it matches. */
p = __archive_read_ahead(a, strlen(signature), &avail);
p = __archive_read_ahead(a, strlen(signature), NULL);
if (p == NULL)
return (-1);
@ -541,6 +584,24 @@ mtree_bid(struct archive_read *a, int best_bid)
/*
* There is not a mtree signature. Let's try to detect mtree format.
*/
return (detect_form(a, NULL));
}
static int
detect_form(struct archive_read *a, int *is_form_d)
{
const char *p;
ssize_t avail, ravail;
ssize_t detected_bytes = 0, len, nl;
int entry_cnt = 0, multiline = 0;
int form_D = 0;/* The archive is generated by `NetBSD mtree -D'
* (In this source we call it `form D') . */
if (is_form_d != NULL)
*is_form_d = 0;
p = __archive_read_ahead(a, 1, &avail);
if (p == NULL)
return (-1);
ravail = avail;
for (;;) {
len = next_line(a, &p, &avail, &ravail, &nl);
@ -565,7 +626,7 @@ mtree_bid(struct archive_read *a, int best_bid)
} else {
/* A continuance line; the terminal
* character of previous line was '\' character. */
if (bid_keyword_list(p, len, 0) <= 0)
if (bid_keyword_list(p, len, 0, 0) <= 0)
break;
if (multiline == 1)
detected_bytes += len;
@ -580,9 +641,25 @@ mtree_bid(struct archive_read *a, int best_bid)
continue;
}
if (p[0] != '/') {
if (bid_entry(p, len) >= 0) {
int last_is_path, keywords;
keywords = bid_entry(p, len, nl, &last_is_path);
if (keywords >= 0) {
detected_bytes += len;
if (p[len-nl-1] == '\\')
if (form_D == 0) {
if (last_is_path)
form_D = 1;
else if (keywords > 0)
/* This line is not `form D'. */
form_D = -1;
} else if (form_D == 1) {
if (!last_is_path && keywords > 0)
/* This this is not `form D'
* and We cannot accept mixed
* format. */
break;
}
if (!last_is_path && p[len-nl-1] == '\\')
/* This line continues. */
multiline = 1;
else {
@ -595,13 +672,13 @@ mtree_bid(struct archive_read *a, int best_bid)
} else
break;
} else if (strncmp(p, "/set", 4) == 0) {
if (bid_keyword_list(p+4, len-4, 0) <= 0)
if (bid_keyword_list(p+4, len-4, 0, 0) <= 0)
break;
/* This line continues. */
if (p[len-nl-1] == '\\')
multiline = 2;
} else if (strncmp(p, "/unset", 6) == 0) {
if (bid_keyword_list(p+6, len-6, 1) <= 0)
if (bid_keyword_list(p+6, len-6, 1, 0) <= 0)
break;
/* This line continues. */
if (p[len-nl-1] == '\\')
@ -613,8 +690,13 @@ mtree_bid(struct archive_read *a, int best_bid)
p += len;
avail -= len;
}
if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0))
if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0)) {
if (is_form_d != NULL) {
if (form_D == 1)
*is_form_d = 1;
}
return (32);
}
return (0);
}
@ -738,12 +820,12 @@ process_global_unset(struct archive_read *a,
static int
process_add_entry(struct archive_read *a, struct mtree *mtree,
struct mtree_option **global, const char *line,
struct mtree_entry **last_entry)
struct mtree_option **global, const char *line, ssize_t line_len,
struct mtree_entry **last_entry, int is_form_d)
{
struct mtree_entry *entry;
struct mtree_option *iter;
const char *next, *eq;
const char *next, *eq, *name, *end;
size_t len;
int r;
@ -764,17 +846,46 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
(*last_entry)->next = entry;
*last_entry = entry;
if (is_form_d) {
/*
* This form places the file name as last parameter.
*/
name = line + line_len -1;
while (line_len > 0) {
if (*name != '\r' && *name != '\n' &&
*name != '\t' && *name != ' ')
break;
name--;
line_len--;
}
len = 0;
while (line_len > 0) {
if (*name == '\r' || *name == '\n' ||
*name == '\t' || *name == ' ') {
name++;
break;
}
name--;
line_len--;
len++;
}
end = name;
} else {
len = strcspn(line, " \t\r\n");
name = line;
line += len;
end = line + line_len;
}
if ((entry->name = malloc(len + 1)) == NULL) {
archive_set_error(&a->archive, errno, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
memcpy(entry->name, line, len);
memcpy(entry->name, name, len);
entry->name[len] = '\0';
parse_escapes(entry->name, entry);
line += len;
for (iter = *global; iter != NULL; iter = iter->next) {
r = add_option(a, &entry->options, iter->value,
strlen(iter->value));
@ -786,6 +897,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
next = line + strspn(line, " \t\r\n");
if (*next == '\0')
return (ARCHIVE_OK);
if (next >= end)
return (ARCHIVE_OK);
line = next;
next = line + strcspn(line, " \t\r\n");
eq = strchr(line, '=');
@ -810,7 +923,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
char *p;
struct mtree_option *global;
struct mtree_entry *last_entry;
int r;
int r, is_form_d;
mtree->archive_format = ARCHIVE_FORMAT_MTREE;
mtree->archive_format_name = "mtree";
@ -818,6 +931,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
global = NULL;
last_entry = NULL;
(void)detect_form(a, &is_form_d);
for (counter = 1; ; ++counter) {
len = readline(a, mtree, &p, 65536);
if (len == 0) {
@ -827,7 +942,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
}
if (len < 0) {
free_options(global);
return (len);
return ((int)len);
}
/* Leading whitespace is never significant, ignore it. */
while (*p == ' ' || *p == '\t') {
@ -840,8 +955,8 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
if (*p == '\r' || *p == '\n' || *p == '\0')
continue;
if (*p != '/') {
r = process_add_entry(a, mtree, &global, p,
&last_entry);
r = process_add_entry(a, mtree, &global, p, len,
&last_entry, is_form_d);
} else if (strncmp(p, "/set", 4) == 0) {
if (p[4] != ' ' && p[4] != '\t')
break;
@ -1007,7 +1122,8 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
if (archive_entry_filetype(entry) == AE_IFREG ||
archive_entry_filetype(entry) == AE_IFDIR) {
mtree->fd = open(path, O_RDONLY | O_BINARY);
mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
__archive_ensure_cloexec_flag(mtree->fd);
if (mtree->fd == -1 &&
(errno != ENOENT ||
archive_strlen(&mtree->contents_name) > 0)) {
@ -1090,15 +1206,19 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
* if it wasn't already parsed from the specification.
*/
if (st != NULL) {
if ((parsed_kws & MTREE_HAS_DEVICE) == 0 &&
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)
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)
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) {
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);
@ -1118,11 +1238,14 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
archive_entry_set_mtime(entry, st->st_mtime, 0);
#endif
}
if ((parsed_kws & MTREE_HAS_NLINK) == 0)
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)
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)
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);
@ -1182,7 +1305,7 @@ parse_device(struct archive *a, struct archive_entry *entry, char *val)
comma1 = strchr(val, ',');
if (comma1 == NULL) {
archive_entry_set_dev(entry, mtree_atol10(&val));
archive_entry_set_dev(entry, (dev_t)mtree_atol10(&val));
return (ARCHIVE_OK);
}
++comma1;
@ -1193,8 +1316,8 @@ parse_device(struct archive *a, struct archive_entry *entry, char *val)
return (ARCHIVE_WARN);
}
++comma2;
archive_entry_set_rdevmajor(entry, mtree_atol(&comma1));
archive_entry_set_rdevminor(entry, mtree_atol(&comma2));
archive_entry_set_rdevmajor(entry, (dev_t)mtree_atol(&comma1));
archive_entry_set_rdevminor(entry, (dev_t)mtree_atol(&comma2));
return (ARCHIVE_OK);
}
@ -1212,6 +1335,10 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
if (*key == '\0')
return (ARCHIVE_OK);
if (strcmp(key, "nochange") == 0) {
*parsed_kws |= MTREE_HAS_NOCHANGE;
return (ARCHIVE_OK);
}
if (strcmp(key, "optional") == 0) {
*parsed_kws |= MTREE_HAS_OPTIONAL;
return (ARCHIVE_OK);
@ -1279,7 +1406,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
if (val[0] >= '0' && val[0] <= '9') {
*parsed_kws |= MTREE_HAS_PERM;
archive_entry_set_perm(entry,
mtree_atol8(&val));
(mode_t)mtree_atol8(&val));
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
@ -1291,7 +1418,8 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
case 'n':
if (strcmp(key, "nlink") == 0) {
*parsed_kws |= MTREE_HAS_NLINK;
archive_entry_set_nlink(entry, mtree_atol10(&val));
archive_entry_set_nlink(entry,
(unsigned int)mtree_atol10(&val));
break;
}
case 'r':
@ -1433,7 +1561,7 @@ read_data(struct archive_read *a, const void **buff, size_t *size, int64_t *offs
*buff = mtree->buff;
*offset = mtree->offset;
if ((int64_t)mtree->buffsize > mtree->cur_size - mtree->offset)
bytes_to_read = mtree->cur_size - mtree->offset;
bytes_to_read = (size_t)(mtree->cur_size - mtree->offset);
else
bytes_to_read = mtree->buffsize;
bytes_read = read(mtree->fd, mtree->buff, bytes_to_read);

View File

@ -136,7 +136,7 @@
#define MAX_SYMBOLS 20
/*
* Considering L1,L2 cache miss and a calling of write sytem-call,
* Considering L1,L2 cache miss and a calling of write system-call,
* the best size of the output buffer(uncompressed buffer) is 128K.
* If the structure of extracting process is changed, this value
* might be researched again.
@ -199,6 +199,13 @@ struct lzss
int64_t position;
};
struct data_block_offsets
{
int64_t header_size;
int64_t start_offset;
int64_t end_offset;
};
struct rar
{
/* Entries from main RAR header */
@ -217,6 +224,7 @@ struct rar
long mnsec;
mode_t mode;
char *filename;
char *filename_save;
size_t filename_allocated;
/* File header optional entries */
@ -234,6 +242,7 @@ struct rar
int64_t bytes_uncopied;
int64_t offset;
int64_t offset_outgoing;
int64_t offset_seek;
char valid;
unsigned int unp_offset;
unsigned int unp_buffer_size;
@ -243,6 +252,10 @@ struct rar
char entry_eof;
unsigned long crc_calculated;
int found_first_header;
char has_endarc_header;
struct data_block_offsets *dbo;
unsigned int cursor;
unsigned int nodes;
/* LZSS members */
struct huffman_code maincode;
@ -301,11 +314,13 @@ static int archive_read_format_rar_read_header(struct archive_read *,
static int archive_read_format_rar_read_data(struct archive_read *,
const void **, size_t *, int64_t *);
static int archive_read_format_rar_read_data_skip(struct archive_read *a);
static int64_t archive_read_format_rar_seek_data(struct archive_read *, int64_t,
int);
static int archive_read_format_rar_cleanup(struct archive_read *);
/* Support functions */
static int read_header(struct archive_read *, struct archive_entry *, char);
static time_t get_time(int time);
static time_t get_time(int);
static int read_exttime(const char *, struct rar *, const char *);
static int read_symlink_stored(struct archive_read *, struct archive_entry *,
struct archive_string_conv *);
@ -328,6 +343,7 @@ static int make_table_recurse(struct archive_read *, struct huffman_code *, int,
static int64_t expand(struct archive_read *, int64_t);
static int copy_from_lzss_window(struct archive_read *, const void **,
int64_t, int);
static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *);
/*
* Bit stream reader.
@ -449,11 +465,9 @@ rar_br_fillup(struct archive_read *a, struct rar_br *br)
__archive_read_consume(a, rar->bytes_unconsumed);
rar->bytes_unconsumed = 0;
}
br->next_in = __archive_read_ahead(a, 1, &(br->avail_in));
br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
if (br->next_in == NULL)
return (0);
if (br->avail_in > rar->bytes_remaining)
br->avail_in = rar->bytes_remaining;
if (br->avail_in == 0)
return (0);
}
@ -473,15 +487,13 @@ rar_br_preparation(struct archive_read *a, struct rar_br *br)
struct rar *rar = (struct rar *)(a->format->data);
if (rar->bytes_remaining > 0) {
br->next_in = __archive_read_ahead(a, 1, &(br->avail_in));
br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
if (br->next_in == NULL) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated RAR file data");
return (ARCHIVE_FATAL);
}
if (br->avail_in > rar->bytes_remaining)
br->avail_in = rar->bytes_remaining;
if (br->cache_avail == 0)
(void)rar_br_fillup(a, br);
}
@ -522,7 +534,7 @@ lzss_size(struct lzss *lzss)
static inline int
lzss_offset_for_position(struct lzss *lzss, int64_t pos)
{
return pos & lzss->mask;
return (int)(pos & lzss->mask);
}
static inline unsigned char *
@ -642,6 +654,7 @@ archive_read_support_format_rar(struct archive *_a)
archive_read_format_rar_read_header,
archive_read_format_rar_read_data,
archive_read_format_rar_read_data_skip,
archive_read_format_rar_seek_data,
archive_read_format_rar_cleanup);
if (r != ARCHIVE_OK)
@ -757,13 +770,15 @@ archive_read_format_rar_options(struct archive_read *a,
else
ret = ARCHIVE_FATAL;
}
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"rar: unknown keyword ``%s''", key);
return (ret);
}
/* 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 int
archive_read_format_rar_read_header(struct archive_read *a,
struct archive_entry *entry)
@ -842,13 +857,6 @@ archive_read_format_rar_read_header(struct archive_read *a,
sizeof(rar->reserved2));
}
if (rar->main_flags & MHD_VOLUME ||
rar->main_flags & MHD_FIRSTVOLUME)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"RAR volume support unavailable.");
return (ARCHIVE_FATAL);
}
if (rar->main_flags & MHD_PASSWORD)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@ -856,7 +864,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
return (ARCHIVE_FATAL);
}
crc32_val = crc32(0, (const unsigned char *)p + 2, skip - 2);
crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
if ((crc32_val & 0xffff) != archive_le16dec(p)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
@ -873,6 +881,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
case SUB_HEAD:
case PROTECT_HEAD:
case SIGN_HEAD:
case ENDARC_HEAD:
flags = archive_le16dec(p + 3);
skip = archive_le16dec(p + 5);
if (skip < 7) {
@ -898,13 +907,15 @@ archive_read_format_rar_read_header(struct archive_read *a,
p = h;
}
crc32_val = crc32(0, (const unsigned char *)p + 2, skip - 2);
crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
if ((crc32_val & 0xffff) != archive_le16dec(p)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
return (ARCHIVE_FATAL);
}
__archive_read_consume(a, skip);
if (head_type == ENDARC_HEAD)
return (ARCHIVE_EOF);
break;
case NEWSUB_HEAD:
@ -912,9 +923,6 @@ archive_read_format_rar_read_header(struct archive_read *a,
return ret;
break;
case ENDARC_HEAD:
return (ARCHIVE_EOF);
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Bad RAR file");
@ -936,10 +944,12 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
rar->bytes_unconsumed = 0;
}
if (rar->entry_eof) {
if (rar->entry_eof || rar->offset_seek >= rar->unp_size) {
*buff = NULL;
*size = 0;
*offset = rar->offset;
if (*offset < rar->unp_size)
*offset = rar->unp_size;
return (ARCHIVE_EOF);
}
@ -973,6 +983,7 @@ archive_read_format_rar_read_data_skip(struct archive_read *a)
{
struct rar *rar;
int64_t bytes_skipped;
int ret;
rar = (struct rar *)(a->format->data);
@ -987,9 +998,179 @@ archive_read_format_rar_read_data_skip(struct archive_read *a)
if (bytes_skipped < 0)
return (ARCHIVE_FATAL);
}
/* Compressed data to skip must be read from each header in a multivolume
* archive.
*/
if (rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER)
{
ret = archive_read_format_rar_read_header(a, a->entry);
if (ret == (ARCHIVE_EOF))
ret = archive_read_format_rar_read_header(a, a->entry);
if (ret != (ARCHIVE_OK))
return ret;
return archive_read_format_rar_read_data_skip(a);
}
return (ARCHIVE_OK);
}
static int64_t
archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset,
int whence)
{
int64_t client_offset, ret;
unsigned int i;
struct rar *rar = (struct rar *)(a->format->data);
if (rar->compression_method == COMPRESS_METHOD_STORE)
{
/* Modify the offset for use with SEEK_SET */
switch (whence)
{
case SEEK_CUR:
client_offset = rar->offset_seek;
break;
case SEEK_END:
client_offset = rar->unp_size;
break;
case SEEK_SET:
default:
client_offset = 0;
}
client_offset += offset;
if (client_offset < 0)
{
/* Can't seek past beginning of data block */
return -1;
}
else if (client_offset > rar->unp_size)
{
/*
* Set the returned offset but only seek to the end of
* the data block.
*/
rar->offset_seek = client_offset;
client_offset = rar->unp_size;
}
client_offset += rar->dbo[0].start_offset;
i = 0;
while (i < rar->cursor)
{
i++;
client_offset += rar->dbo[i].start_offset - rar->dbo[i-1].end_offset;
}
if (rar->main_flags & MHD_VOLUME)
{
/* Find the appropriate offset among the multivolume archive */
while (1)
{
if (client_offset < rar->dbo[rar->cursor].start_offset &&
rar->file_flags & FHD_SPLIT_BEFORE)
{
/* Search backwards for the correct data block */
if (rar->cursor == 0)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Attempt to seek past beginning of RAR data block");
return (ARCHIVE_FAILED);
}
rar->cursor--;
client_offset -= rar->dbo[rar->cursor+1].start_offset -
rar->dbo[rar->cursor].end_offset;
if (client_offset < rar->dbo[rar->cursor].start_offset)
continue;
ret = __archive_read_seek(a, rar->dbo[rar->cursor].start_offset -
rar->dbo[rar->cursor].header_size, SEEK_SET);
if (ret < (ARCHIVE_OK))
return ret;
ret = archive_read_format_rar_read_header(a, a->entry);
if (ret != (ARCHIVE_OK))
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Error during seek of RAR file");
return (ARCHIVE_FAILED);
}
rar->cursor--;
break;
}
else if (client_offset > rar->dbo[rar->cursor].end_offset &&
rar->file_flags & FHD_SPLIT_AFTER)
{
/* Search forward for the correct data block */
rar->cursor++;
if (rar->cursor < rar->nodes &&
client_offset > rar->dbo[rar->cursor].end_offset)
{
client_offset += rar->dbo[rar->cursor].start_offset -
rar->dbo[rar->cursor-1].end_offset;
continue;
}
rar->cursor--;
ret = __archive_read_seek(a, rar->dbo[rar->cursor].end_offset,
SEEK_SET);
if (ret < (ARCHIVE_OK))
return ret;
ret = archive_read_format_rar_read_header(a, a->entry);
if (ret == (ARCHIVE_EOF))
{
rar->has_endarc_header = 1;
ret = archive_read_format_rar_read_header(a, a->entry);
}
if (ret != (ARCHIVE_OK))
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Error during seek of RAR file");
return (ARCHIVE_FAILED);
}
client_offset += rar->dbo[rar->cursor].start_offset -
rar->dbo[rar->cursor-1].end_offset;
continue;
}
break;
}
}
ret = __archive_read_seek(a, client_offset, SEEK_SET);
if (ret < (ARCHIVE_OK))
return ret;
rar->bytes_remaining = rar->dbo[rar->cursor].end_offset - ret;
i = rar->cursor;
while (i > 0)
{
i--;
ret -= rar->dbo[i+1].start_offset - rar->dbo[i].end_offset;
}
ret -= rar->dbo[0].start_offset;
/* Always restart reading the file after a seek */
a->read_data_block = NULL;
a->read_data_offset = 0;
a->read_data_output_offset = 0;
a->read_data_remaining = 0;
rar->bytes_unconsumed = 0;
rar->offset = 0;
/*
* If a seek past the end of file was requested, return the requested
* offset.
*/
if (ret == rar->unp_size && rar->offset_seek > rar->unp_size)
return rar->offset_seek;
/* Return the new offset */
rar->offset_seek = ret;
return rar->offset_seek;
}
else
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Seeking of compressed RAR files is unsupported");
}
return (ARCHIVE_FAILED);
}
static int
archive_read_format_rar_cleanup(struct archive_read *a)
{
@ -998,6 +1179,8 @@ archive_read_format_rar_cleanup(struct archive_read *a)
rar = (struct rar *)(a->format->data);
free_codes(a);
free(rar->filename);
free(rar->filename_save);
free(rar->dbo);
free(rar->unp_buffer);
free(rar->lzss.window);
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
@ -1021,7 +1204,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
char *strp;
char packed_size[8];
char unp_size[8];
int time;
int ttime;
struct archive_string_conv *sconv, *fn_sconv;
unsigned long crc32_val;
int ret = (ARCHIVE_OK), ret2;
@ -1047,7 +1230,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
memcpy(&rar_header, p, sizeof(rar_header));
rar->file_flags = archive_le16dec(rar_header.flags);
header_size = archive_le16dec(rar_header.size);
if (header_size < sizeof(file_header) + 7) {
if (header_size < (int64_t)sizeof(file_header) + 7) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid header size");
return (ARCHIVE_FATAL);
@ -1082,11 +1265,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
if ((h = __archive_read_ahead(a, header_size - 7, NULL)) == NULL)
if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
return (ARCHIVE_FATAL);
/* File Header CRC check. */
crc32_val = crc32(crc32_val, h, header_size - 7);
crc32_val = crc32(crc32_val, h, (unsigned)(header_size - 7));
if ((crc32_val & 0xffff) != archive_le16dec(rar_header.crc)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Header CRC error");
@ -1100,8 +1283,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
rar->compression_method = file_header.method;
time = archive_le32dec(file_header.file_time);
rar->mtime = get_time(time);
ttime = archive_le32dec(file_header.file_time);
rar->mtime = get_time(ttime);
rar->file_crc = archive_le32dec(file_header.file_crc);
@ -1129,9 +1312,6 @@ read_header(struct archive_read *a, struct archive_entry *entry,
rar->unp_size = archive_le32dec(file_header.unp_size);
}
/* TODO: Need to use CRC check for these kind of cases.
* For now, check if sizes are not < 0.
*/
if (rar->packed_size < 0 || rar->unp_size < 0)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@ -1139,6 +1319,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
rar->bytes_remaining = rar->packed_size;
/* TODO: RARv3 subblocks contain comments. For now the complete block is
* consumed at the end.
*/
@ -1146,7 +1328,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
size_t distance = p - (const char *)h;
header_size += rar->packed_size;
/* Make sure we have the extended data. */
if ((h = __archive_read_ahead(a, header_size - 7, NULL)) == NULL)
if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
return (ARCHIVE_FATAL);
p = h;
endp = p + header_size - 7;
@ -1159,13 +1341,17 @@ read_header(struct archive_read *a, struct archive_entry *entry,
"Invalid filename size");
return (ARCHIVE_FATAL);
}
if (rar->filename_allocated < filename_size+2) {
rar->filename = realloc(rar->filename, filename_size+2);
if (rar->filename == NULL) {
if (rar->filename_allocated < filename_size * 2 + 2) {
char *newptr;
size_t newsize = filename_size * 2 + 2;
newptr = realloc(rar->filename, newsize);
if (newptr == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Couldn't allocate memory.");
return (ARCHIVE_FATAL);
}
rar->filename = newptr;
rar->filename_allocated = newsize;
}
filename = rar->filename;
memcpy(filename, p, filename_size);
@ -1174,15 +1360,17 @@ read_header(struct archive_read *a, struct archive_entry *entry,
{
if (filename_size != strlen(filename))
{
unsigned char highbyte, flagbits, flagbyte, length, offset;
unsigned char highbyte, flagbits, flagbyte;
unsigned fn_end, offset;
end = filename_size;
fn_end = filename_size * 2;
filename_size = 0;
offset = strlen(filename) + 1;
offset = (unsigned)strlen(filename) + 1;
highbyte = *(p + offset++);
flagbits = 0;
flagbyte = 0;
while (offset < end && filename_size < end)
while (offset < end && filename_size < fn_end)
{
if (!flagbits)
{
@ -1208,19 +1396,26 @@ read_header(struct archive_read *a, struct archive_entry *entry,
break;
case 3:
{
length = *(p + offset++);
while (length)
{
if (filename_size >= end)
break;
filename[filename_size++] = *(p + offset);
char extra, high;
uint8_t length = *(p + offset++);
if (length & 0x80) {
extra = *(p + offset++);
high = (char)highbyte;
} else
extra = high = 0;
length = (length & 0x7f) + 2;
while (length && filename_size < fn_end) {
unsigned cp = filename_size >> 1;
filename[filename_size++] = high;
filename[filename_size++] = p[cp] + extra;
length--;
}
}
break;
}
}
if (filename_size >= end) {
if (filename_size > fn_end) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid filename");
return (ARCHIVE_FATAL);
@ -1272,6 +1467,51 @@ read_header(struct archive_read *a, struct archive_entry *entry,
p += filename_size;
}
/* Split file in multivolume RAR. No more need to process header. */
if (rar->filename_save &&
!memcmp(rar->filename, rar->filename_save, filename_size + 1))
{
__archive_read_consume(a, header_size - 7);
rar->cursor++;
if (rar->cursor >= rar->nodes)
{
rar->nodes++;
if ((rar->dbo =
realloc(rar->dbo, sizeof(*rar->dbo) * rar->nodes)) == NULL)
{
archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
return (ARCHIVE_FATAL);
}
rar->dbo[rar->cursor].header_size = header_size;
rar->dbo[rar->cursor].start_offset = -1;
rar->dbo[rar->cursor].end_offset = -1;
}
if (rar->dbo[rar->cursor].start_offset < 0)
{
rar->dbo[rar->cursor].start_offset = a->filter->position;
rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset +
rar->packed_size;
}
return ret;
}
rar->filename_save = (char*)realloc(rar->filename_save,
filename_size + 1);
memcpy(rar->filename_save, rar->filename, filename_size + 1);
/* Set info for seeking */
free(rar->dbo);
if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL)
{
archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
return (ARCHIVE_FATAL);
}
rar->dbo[0].header_size = header_size;
rar->dbo[0].start_offset = -1;
rar->dbo[0].end_offset = -1;
rar->cursor = 0;
rar->nodes = 1;
if (rar->file_flags & FHD_SALT)
{
if (p + 8 > endp) {
@ -1292,6 +1532,8 @@ read_header(struct archive_read *a, struct archive_entry *entry,
}
__archive_read_consume(a, header_size - 7);
rar->dbo[0].start_offset = a->filter->position;
rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size;
switch(file_header.host_os)
{
@ -1318,9 +1560,10 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
rar->bytes_remaining = rar->packed_size;
rar->bytes_uncopied = rar->bytes_unconsumed = 0;
rar->lzss.position = rar->dictionary_size = rar->offset = 0;
rar->lzss.position = rar->offset = 0;
rar->offset_seek = 0;
rar->dictionary_size = 0;
rar->offset_outgoing = 0;
rar->br.cache_avail = 0;
rar->br.avail_in = 0;
@ -1381,15 +1624,15 @@ read_header(struct archive_read *a, struct archive_entry *entry,
}
static time_t
get_time(int time)
get_time(int ttime)
{
struct tm tm;
tm.tm_sec = 2 * (time & 0x1f);
tm.tm_min = (time >> 5) & 0x3f;
tm.tm_hour = (time >> 11) & 0x1f;
tm.tm_mday = (time >> 16) & 0x1f;
tm.tm_mon = ((time >> 21) & 0x0f) - 1;
tm.tm_year = ((time >> 25) & 0x7f) + 80;
tm.tm_sec = 2 * (ttime & 0x1f);
tm.tm_min = (ttime >> 5) & 0x3f;
tm.tm_hour = (ttime >> 11) & 0x1f;
tm.tm_mday = (ttime >> 16) & 0x1f;
tm.tm_mon = ((ttime >> 21) & 0x0f) - 1;
tm.tm_year = ((ttime >> 25) & 0x7f) + 80;
tm.tm_isdst = -1;
return mktime(&tm);
}
@ -1398,7 +1641,7 @@ static int
read_exttime(const char *p, struct rar *rar, const char *endp)
{
unsigned rmode, flags, rem, j, count;
int time, i;
int ttime, i;
struct tm *tm;
time_t t;
long nsec;
@ -1420,8 +1663,8 @@ read_exttime(const char *p, struct rar *rar, const char *endp)
{
if (p + 4 > endp)
return (-1);
time = archive_le32dec(p);
t = get_time(time);
ttime = archive_le32dec(p);
t = get_time(ttime);
p += 4;
}
rem = 0;
@ -1475,11 +1718,12 @@ read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
int ret = (ARCHIVE_OK);
rar = (struct rar *)(a->format->data);
if ((h = __archive_read_ahead(a, rar->packed_size, NULL)) == NULL)
if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
return (ARCHIVE_FATAL);
p = h;
if (archive_entry_copy_symlink_l(entry, p, rar->packed_size, sconv))
if (archive_entry_copy_symlink_l(entry,
p, (size_t)rar->packed_size, sconv))
{
if (errno == ENOMEM)
{
@ -1504,7 +1748,8 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
ssize_t bytes_avail;
rar = (struct rar *)(a->format->data);
if (rar->bytes_remaining == 0)
if (rar->bytes_remaining == 0 &&
!(rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER))
{
*buff = NULL;
*size = 0;
@ -1518,23 +1763,23 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
return (ARCHIVE_EOF);
}
*buff = __archive_read_ahead(a, 1, &bytes_avail);
*buff = rar_read_ahead(a, 1, &bytes_avail);
if (bytes_avail <= 0)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated RAR file data");
return (ARCHIVE_FATAL);
}
if (bytes_avail > rar->bytes_remaining)
bytes_avail = rar->bytes_remaining;
*size = bytes_avail;
*offset = rar->offset;
rar->offset += bytes_avail;
rar->offset_seek += bytes_avail;
rar->bytes_remaining -= bytes_avail;
rar->bytes_unconsumed = bytes_avail;
/* Calculate File CRC. */
rar->crc_calculated = crc32(rar->crc_calculated, *buff, bytes_avail);
rar->crc_calculated = crc32(rar->crc_calculated, *buff,
(unsigned)bytes_avail);
return (ARCHIVE_OK);
}
@ -1564,7 +1809,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*offset = rar->offset_outgoing;
rar->offset_outgoing += *size;
/* Calculate File CRC. */
rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
rar->crc_calculated = crc32(rar->crc_calculated, *buff,
(unsigned)*size);
rar->unp_offset = 0;
return (ARCHIVE_OK);
}
@ -1585,8 +1831,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset))
bs = rar->unp_buffer_size - rar->unp_offset;
else
bs = rar->bytes_uncopied;
ret = copy_from_lzss_window(a, buff, rar->offset, bs);
bs = (size_t)rar->bytes_uncopied;
ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
if (ret != ARCHIVE_OK)
return (ret);
rar->offset += bs;
@ -1597,7 +1843,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*offset = rar->offset_outgoing;
rar->offset_outgoing += *size;
/* Calculate File CRC. */
rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
rar->crc_calculated = crc32(rar->crc_calculated, *buff,
(unsigned)*size);
return (ret);
}
continue;
@ -1713,8 +1960,8 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset))
bs = rar->unp_buffer_size - rar->unp_offset;
else
bs = rar->bytes_uncopied;
ret = copy_from_lzss_window(a, buff, rar->offset, bs);
bs = (size_t)rar->bytes_uncopied;
ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
if (ret != ARCHIVE_OK)
return (ret);
rar->offset += bs;
@ -1730,7 +1977,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
*offset = rar->offset_outgoing;
rar->offset_outgoing += *size;
/* Calculate File CRC. */
rar->crc_calculated = crc32(rar->crc_calculated, *buff, *size);
rar->crc_calculated = crc32(rar->crc_calculated, *buff, (unsigned)*size);
return ret;
}
@ -1973,17 +2220,21 @@ parse_codes(struct archive_read *a)
/* Seems as though dictionary sizes are not used. Even so, minimize
* memory usage as much as possible.
*/
void *new_window;
unsigned int new_size;
if (rar->unp_size >= DICTIONARY_MAX_SIZE)
rar->dictionary_size = DICTIONARY_MAX_SIZE;
new_size = DICTIONARY_MAX_SIZE;
else
rar->dictionary_size = rar_fls(rar->unp_size) << 1;
rar->lzss.window = (unsigned char *)realloc(rar->lzss.window,
rar->dictionary_size);
if (rar->lzss.window == NULL) {
new_size = rar_fls((unsigned int)rar->unp_size) << 1;
new_window = realloc(rar->lzss.window, new_size);
if (new_window == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Unable to allocate memory for uncompressed data.");
return (ARCHIVE_FATAL);
}
rar->lzss.window = (unsigned char *)new_window;
rar->dictionary_size = new_size;
memset(rar->lzss.window, 0, rar->dictionary_size);
rar->lzss.mask = rar->dictionary_size - 1;
}
@ -2221,10 +2472,12 @@ add_value(struct archive_read *a, struct huffman_code *code, int value,
static int
new_node(struct huffman_code *code)
{
code->tree = (struct huffman_tree_node *)realloc(code->tree,
(code->numentries + 1) * sizeof(*code->tree));
if (code->tree == NULL)
void *new_tree;
new_tree = realloc(code->tree, (code->numentries + 1) * sizeof(*code->tree));
if (new_tree == NULL)
return (-1);
code->tree = (struct huffman_tree_node *)new_tree;
code->tree[code->numentries].branches[0] = -1;
code->tree[code->numentries].branches[1] = -2;
return 1;
@ -2239,8 +2492,8 @@ make_table(struct archive_read *a, struct huffman_code *code)
code->tablesize = code->maxlength;
code->table =
(struct huffman_table_entry *)malloc(sizeof(*code->table)
* (1 << code->tablesize));
(struct huffman_table_entry *)calloc(1, sizeof(*code->table)
* ((size_t)1 << code->tablesize));
return make_table_recurse(a, code, 0, code->table, 0, code->tablesize);
}
@ -2408,9 +2661,9 @@ expand(struct archive_read *a, int64_t end)
if ((lensymbol = read_next_symbol(a, &rar->lengthcode)) < 0)
goto bad_data;
if (lensymbol > sizeof(lengthbases)/sizeof(lengthbases[0]))
if (lensymbol > (int)(sizeof(lengthbases)/sizeof(lengthbases[0])))
goto bad_data;
if (lensymbol > sizeof(lengthbits)/sizeof(lengthbits[0]))
if (lensymbol > (int)(sizeof(lengthbits)/sizeof(lengthbits[0])))
goto bad_data;
len = lengthbases[lensymbol] + 2;
if (lengthbits[lensymbol] > 0) {
@ -2442,9 +2695,9 @@ expand(struct archive_read *a, int64_t end)
}
else
{
if (symbol-271 > sizeof(lengthbases)/sizeof(lengthbases[0]))
if (symbol-271 > (int)(sizeof(lengthbases)/sizeof(lengthbases[0])))
goto bad_data;
if (symbol-271 > sizeof(lengthbits)/sizeof(lengthbits[0]))
if (symbol-271 > (int)(sizeof(lengthbits)/sizeof(lengthbits[0])))
goto bad_data;
len = lengthbases[symbol-271]+3;
if(lengthbits[symbol-271] > 0) {
@ -2456,9 +2709,9 @@ expand(struct archive_read *a, int64_t end)
if ((offssymbol = read_next_symbol(a, &rar->offsetcode)) < 0)
goto bad_data;
if (offssymbol > sizeof(offsetbases)/sizeof(offsetbases[0]))
if (offssymbol > (int)(sizeof(offsetbases)/sizeof(offsetbases[0])))
goto bad_data;
if (offssymbol > sizeof(offsetbits)/sizeof(offsetbits[0]))
if (offssymbol > (int)(sizeof(offsetbits)/sizeof(offsetbits[0])))
goto bad_data;
offs = offsetbases[offssymbol]+1;
if(offsetbits[offssymbol] > 0)
@ -2572,3 +2825,34 @@ copy_from_lzss_window(struct archive_read *a, const void **buffer,
*buffer = NULL;
return (ARCHIVE_OK);
}
static const void *
rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
{
struct rar *rar = (struct rar *)(a->format->data);
const void *h = __archive_read_ahead(a, min, avail);
int ret;
if (avail)
{
if (a->read_data_is_posix_read && *avail > (ssize_t)a->read_data_requested)
*avail = a->read_data_requested;
if (*avail > rar->bytes_remaining)
*avail = (ssize_t)rar->bytes_remaining;
if (*avail < 0)
return NULL;
else if (*avail == 0 && rar->main_flags & MHD_VOLUME &&
rar->file_flags & FHD_SPLIT_AFTER)
{
ret = archive_read_format_rar_read_header(a, a->entry);
if (ret == (ARCHIVE_EOF))
{
rar->has_endarc_header = 1;
ret = archive_read_format_rar_read_header(a, a->entry);
}
if (ret != (ARCHIVE_OK))
return NULL;
return rar_read_ahead(a, min, avail);
}
}
return h;
}

View File

@ -77,6 +77,7 @@ archive_read_support_format_raw(struct archive *_a)
archive_read_format_raw_read_header,
archive_read_format_raw_read_data,
archive_read_format_raw_read_data_skip,
NULL,
archive_read_format_raw_cleanup);
if (r != ARCHIVE_OK)
free(info);
@ -157,7 +158,7 @@ archive_read_format_raw_read_data(struct archive_read *a,
/* Record and return an error. */
*size = 0;
*offset = info->offset;
return (avail);
return ((int)avail);
}
}

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2007 Tim Kientzle
* Copyright (c) 2011 Michihiro NAKAJIMA
* Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -210,10 +210,10 @@ static int read_body_to_string(struct archive_read *, struct tar *,
struct archive_string *, const void *h, size_t *);
static int solaris_sparse_parse(struct archive_read *, struct tar *,
struct archive_entry *, const char *);
static int64_t tar_atol(const char *, unsigned);
static int64_t tar_atol10(const char *, unsigned);
static int64_t tar_atol256(const char *, unsigned);
static int64_t tar_atol8(const char *, unsigned);
static int64_t tar_atol(const char *, size_t);
static int64_t tar_atol10(const char *, size_t);
static int64_t tar_atol256(const char *, size_t);
static int64_t tar_atol8(const char *, size_t);
static int tar_read_header(struct archive_read *, struct tar *,
struct archive_entry *, size_t *);
static int tohex(int c);
@ -253,6 +253,7 @@ archive_read_support_format_tar(struct archive *_a)
archive_read_format_tar_read_header,
archive_read_format_tar_read_data,
archive_read_format_tar_skip,
NULL,
archive_read_format_tar_cleanup);
if (r != ARCHIVE_OK)
@ -369,7 +370,7 @@ archive_read_format_tar_options(struct archive_read *a,
/* Handle UTF-8 filnames as libarchive 2.x */
tar->compat_2x = (val != NULL)?1:0;
tar->init_default_conversion = tar->compat_2x;
ret = ARCHIVE_OK;
return (ARCHIVE_OK);
} else if (strcmp(key, "hdrcharset") == 0) {
if (val == NULL || val[0] == 0)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@ -383,13 +384,15 @@ archive_read_format_tar_options(struct archive_read *a,
else
ret = ARCHIVE_FATAL;
}
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"tar: unknown keyword ``%s''", key);
return (ret);
}
/* 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);
}
/* utility function- this exists to centralize the logic of tracking
* how much unconsumed data we have floating around, and to consume
* anything outstanding since we're going to do read_aheads
@ -525,7 +528,7 @@ archive_read_format_tar_read_data(struct archive_read *a,
tar = (struct tar *)(a->format->data);
skip_hole:
for (;;) {
/* Remove exhausted entries from sparse list. */
while (tar->sparse_list != NULL &&
tar->sparse_list->remaining == 0) {
@ -540,7 +543,8 @@ skip_hole:
}
/* If we're at end of file, return EOF. */
if (tar->sparse_list == NULL || tar->entry_bytes_remaining == 0) {
if (tar->sparse_list == NULL ||
tar->entry_bytes_remaining == 0) {
if (__archive_read_consume(a, tar->entry_padding) < 0)
return (ARCHIVE_FATAL);
tar->entry_padding = 0;
@ -559,11 +563,11 @@ skip_hole:
return (ARCHIVE_FATAL);
}
if (bytes_read > tar->entry_bytes_remaining)
bytes_read = tar->entry_bytes_remaining;
bytes_read = (ssize_t)tar->entry_bytes_remaining;
/* Don't read more than is available in the
* current sparse block. */
if (tar->sparse_list->remaining < bytes_read)
bytes_read = tar->sparse_list->remaining;
bytes_read = (ssize_t)tar->sparse_list->remaining;
*size = bytes_read;
*offset = tar->sparse_list->offset;
tar->sparse_list->remaining -= bytes_read;
@ -571,10 +575,10 @@ skip_hole:
tar->entry_bytes_remaining -= bytes_read;
tar->entry_bytes_unconsumed = bytes_read;
if (tar->sparse_list->hole)
goto skip_hole;
if (!tar->sparse_list->hole)
return (ARCHIVE_OK);
/* Current is hole data and skip this. */
}
}
static int
@ -613,13 +617,14 @@ tar_read_header(struct archive_read *a, struct tar *tar,
int err;
const char *h;
const struct archive_entry_header_ustar *header;
const struct archive_entry_header_gnutar *gnuheader;
tar_flush_unconsumed(a, unconsumed);
/* Read 512-byte header record */
h = __archive_read_ahead(a, 512, &bytes);
if (bytes < 0)
return (bytes);
return ((int)bytes);
if (bytes == 0) { /* EOF at a block boundary. */
/* Some writers do omit the block of nulls. <sigh> */
return (ARCHIVE_EOF);
@ -700,7 +705,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
err = header_pax_extensions(a, tar, entry, h, unconsumed);
break;
default:
if (memcmp(header->magic, "ustar \0", 8) == 0) {
gnuheader = (const struct archive_entry_header_gnutar *)h;
if (memcmp(gnuheader->magic, "ustar \0", 8) == 0) {
a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR;
a->archive.archive_format_name = "GNU tar format";
err = header_gnutar(a, tar, entry, h, unconsumed);
@ -749,7 +755,7 @@ tar_read_header(struct archive_read *a, struct tar *tar,
bytes_read = gnu_sparse_10_read(a, tar, unconsumed);
tar->entry_bytes_remaining -= bytes_read;
if (bytes_read < 0)
return (bytes_read);
return ((int)bytes_read);
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
@ -784,7 +790,7 @@ checksum(struct archive_read *a, const void *h)
* Test the checksum. Note that POSIX specifies _unsigned_
* bytes for this calculation.
*/
sum = tar_atol(header->checksum, sizeof(header->checksum));
sum = (int)tar_atol(header->checksum, sizeof(header->checksum));
check = 0;
for (i = 0; i < 148; i++)
check += (unsigned char)bytes[i];
@ -845,7 +851,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
* more to make sure that we don't overrun acl_text later.
*/
header = (const struct archive_entry_header_ustar *)h;
size = tar_atol(header->size, sizeof(header->size));
size = (size_t)tar_atol(header->size, sizeof(header->size));
err = read_body_to_string(a, tar, &(tar->acl_text), h, unconsumed);
if (err != ARCHIVE_OK)
return (err);
@ -1019,7 +1025,7 @@ read_body_to_string(struct archive_read *a, struct tar *tar,
}
/* Fail if we can't make our buffer big enough. */
if (archive_string_ensure(as, size+1) == NULL) {
if (archive_string_ensure(as, (size_t)size+1) == NULL) {
archive_set_error(&a->archive, ENOMEM,
"No memory");
return (ARCHIVE_FATAL);
@ -1028,15 +1034,15 @@ read_body_to_string(struct archive_read *a, struct tar *tar,
tar_flush_unconsumed(a, unconsumed);
/* Read the body into the string. */
*unconsumed = (size + 511) & ~ 511;
*unconsumed = (size_t)((size + 511) & ~ 511);
src = __archive_read_ahead(a, *unconsumed, NULL);
if (src == NULL) {
*unconsumed = 0;
return (ARCHIVE_FATAL);
}
memcpy(as->s, src, size);
memcpy(as->s, src, (size_t)size);
as->s[size] = '\0';
as->length = size;
as->length = (size_t)size;
return (ARCHIVE_OK);
}
@ -1066,7 +1072,8 @@ header_common(struct archive_read *a, struct tar *tar,
archive_string_empty(&(tar->entry_linkpath));
/* Parse out the numeric fields (all are octal) */
archive_entry_set_mode(entry, tar_atol(header->mode, sizeof(header->mode)));
archive_entry_set_mode(entry,
(mode_t)tar_atol(header->mode, sizeof(header->mode)));
archive_entry_set_uid(entry, tar_atol(header->uid, sizeof(header->uid)));
archive_entry_set_gid(entry, tar_atol(header->gid, sizeof(header->gid)));
tar->entry_bytes_remaining = tar_atol(header->size, sizeof(header->size));
@ -1308,13 +1315,13 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
* Q: Is the above idea really possible? Even
* when there are GNU or pax extension entries?
*/
data = __archive_read_ahead(a, size, NULL);
data = __archive_read_ahead(a, (size_t)size, NULL);
if (data == NULL) {
*unconsumed = 0;
return (ARCHIVE_FATAL);
}
archive_entry_copy_mac_metadata(entry, data, size);
*unconsumed = (size + 511) & ~ 511;
archive_entry_copy_mac_metadata(entry, data, (size_t)size);
*unconsumed = (size_t)((size + 511) & ~ 511);
tar_flush_unconsumed(a, unconsumed);
return (tar_read_header(a, tar, entry, unconsumed));
}
@ -1422,9 +1429,9 @@ header_ustar(struct archive_read *a, struct tar *tar,
/* Parse out device numbers only for char and block specials. */
if (header->typeflag[0] == '3' || header->typeflag[0] == '4') {
archive_entry_set_rdevmajor(entry,
archive_entry_set_rdevmajor(entry, (dev_t)
tar_atol(header->rdevmajor, sizeof(header->rdevmajor)));
archive_entry_set_rdevminor(entry,
archive_entry_set_rdevminor(entry, (dev_t)
tar_atol(header->rdevminor, sizeof(header->rdevminor)));
}
@ -1661,6 +1668,9 @@ pax_attribute(struct archive_read *a, struct tar *tar,
long n;
int err = ARCHIVE_OK, r;
if (value == NULL)
value = ""; /* Disable compiler warning; do not pass
* NULL pointer to strlen(). */
switch (key[0]) {
case 'G':
/* GNU "0.0" sparse pax format. */
@ -1707,11 +1717,11 @@ pax_attribute(struct archive_read *a, struct tar *tar,
/* GNU "1.0" sparse pax format */
if (strcmp(key, "GNU.sparse.major") == 0) {
tar->sparse_gnu_major = tar_atol10(value, strlen(value));
tar->sparse_gnu_major = (int)tar_atol10(value, strlen(value));
tar->sparse_gnu_pending = 1;
}
if (strcmp(key, "GNU.sparse.minor") == 0) {
tar->sparse_gnu_minor = tar_atol10(value, strlen(value));
tar->sparse_gnu_minor = (int)tar_atol10(value, strlen(value));
tar->sparse_gnu_pending = 1;
}
if (strcmp(key, "GNU.sparse.name") == 0) {
@ -1794,20 +1804,20 @@ pax_attribute(struct archive_read *a, struct tar *tar,
}
} else if (strcmp(key, "SCHILY.devmajor") == 0) {
archive_entry_set_rdevmajor(entry,
tar_atol10(value, strlen(value)));
(dev_t)tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.devminor") == 0) {
archive_entry_set_rdevminor(entry,
tar_atol10(value, strlen(value)));
(dev_t)tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.fflags") == 0) {
archive_entry_copy_fflags_text(entry, value);
} else if (strcmp(key, "SCHILY.dev") == 0) {
archive_entry_set_dev(entry,
tar_atol10(value, strlen(value)));
(dev_t)tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.ino") == 0) {
archive_entry_set_ino(entry,
tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.nlink") == 0) {
archive_entry_set_nlink(entry,
archive_entry_set_nlink(entry, (unsigned)
tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.realsize") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
@ -2016,9 +2026,9 @@ header_gnutar(struct archive_read *a, struct tar *tar,
/* Parse out device numbers only for char and block specials */
if (header->typeflag[0] == '3' || header->typeflag[0] == '4') {
archive_entry_set_rdevmajor(entry,
archive_entry_set_rdevmajor(entry, (dev_t)
tar_atol(header->rdevmajor, sizeof(header->rdevmajor)));
archive_entry_set_rdevminor(entry,
archive_entry_set_rdevminor(entry, (dev_t)
tar_atol(header->rdevminor, sizeof(header->rdevminor)));
} else
archive_entry_set_rdev(entry, 0);
@ -2253,7 +2263,8 @@ gnu_sparse_10_atol(struct archive_read *a, struct tar *tar,
* don't require this, but they should.
*/
do {
bytes_read = readline(a, tar, &p, tar_min(*remaining, 100), unconsumed);
bytes_read = readline(a, tar, &p,
(ssize_t)tar_min(*remaining, 100), unconsumed);
if (bytes_read <= 0)
return (ARCHIVE_FATAL);
*remaining -= bytes_read;
@ -2294,7 +2305,7 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
remaining = tar->entry_bytes_remaining;
/* Parse entries. */
entries = gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
entries = (int)gnu_sparse_10_atol(a, tar, &remaining, unconsumed);
if (entries < 0)
return (ARCHIVE_FATAL);
/* Parse the individual entries. */
@ -2312,16 +2323,16 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
}
/* Skip rest of block... */
tar_flush_unconsumed(a, unconsumed);
bytes_read = tar->entry_bytes_remaining - remaining;
bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining);
to_skip = 0x1ff & -bytes_read;
if (to_skip != __archive_read_consume(a, to_skip))
return (ARCHIVE_FATAL);
return (bytes_read + to_skip);
return ((ssize_t)(bytes_read + to_skip));
}
/*
* Solaris pax extension for a sparse file. This is recorded with the
* data and hole pairs. The way recording sparse infomation by Solaris'
* data and hole pairs. The way recording sparse information by Solaris'
* pax simply indicates where data and sparse are, so the stored contents
* consist of both data and hole.
*/
@ -2333,6 +2344,8 @@ solaris_sparse_parse(struct archive_read *a, struct tar *tar,
int64_t start, end;
int hole = 1;
(void)entry; /* UNUSED */
end = 0;
if (*p == ' ')
p++;
@ -2380,7 +2393,7 @@ solaris_sparse_parse(struct archive_read *a, struct tar *tar,
* On read, this implementation supports both extensions.
*/
static int64_t
tar_atol(const char *p, unsigned char_cnt)
tar_atol(const char *p, size_t char_cnt)
{
/*
* Technically, GNU tar considers a field to be in base-256
@ -2397,79 +2410,64 @@ tar_atol(const char *p, unsigned char_cnt)
* it does obey locale.
*/
static int64_t
tar_atol8(const char *p, unsigned char_cnt)
tar_atol_base_n(const char *p, size_t char_cnt, int base)
{
int64_t l, limit, last_digit_limit;
int digit, sign, base;
int digit, sign;
base = 8;
limit = INT64_MAX / base;
last_digit_limit = INT64_MAX % base;
while (*p == ' ' || *p == '\t')
p++;
if (*p == '-') {
sign = -1;
p++;
} else
sign = 1;
l = 0;
digit = *p - '0';
while (digit >= 0 && digit < base && char_cnt-- > 0) {
if (l>limit || (l == limit && digit > last_digit_limit)) {
l = INT64_MAX; /* Truncate on overflow. */
break;
}
l = (l * base) + digit;
digit = *++p - '0';
}
return (sign < 0) ? -l : l;
}
/*
* Note that this implementation does not (and should not!) obey
* locale settings; you cannot simply substitute strtol here, since
* it does obey locale.
/* the pointer will not be dereferenced if char_cnt is zero
* due to the way the && operator is evaulated.
*/
static int64_t
tar_atol10(const char *p, unsigned char_cnt)
{
int64_t l, limit, last_digit_limit;
int base, digit, sign;
base = 10;
limit = INT64_MAX / base;
last_digit_limit = INT64_MAX % base;
while (*p == ' ' || *p == '\t')
while (char_cnt != 0 && (*p == ' ' || *p == '\t')) {
p++;
if (*p == '-') {
char_cnt--;
}
sign = 1;
if (char_cnt != 0 && *p == '-') {
sign = -1;
p++;
} else
sign = 1;
char_cnt--;
}
l = 0;
if (char_cnt != 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)) {
l = INT64_MAX; /* Truncate on overflow. */
break;
}
l = (l * base) + digit;
digit = *++p - '0';
char_cnt--;
}
}
return (sign < 0) ? -l : l;
}
static int64_t
tar_atol8(const char *p, size_t char_cnt)
{
return tar_atol_base_n(p, char_cnt, 8);
}
static int64_t
tar_atol10(const char *p, size_t char_cnt)
{
return tar_atol_base_n(p, char_cnt, 10);
}
/*
* Parse a base-256 integer. This is just a straight signed binary
* value in big-endian order, except that the high-order bit is
* ignored.
*/
static int64_t
tar_atol256(const char *_p, unsigned char_cnt)
tar_atol256(const char *_p, size_t char_cnt)
{
int64_t l, upper_limit, lower_limit;
const unsigned char *p = (const unsigned char *)_p;

View File

@ -183,9 +183,9 @@ struct xar_file {
time_t mtime;
time_t atime;
struct archive_string uname;
uid_t uid;
int64_t uid;
struct archive_string gname;
gid_t gid;
int64_t gid;
mode_t mode;
dev_t dev;
dev_t devmajor;
@ -467,6 +467,7 @@ archive_read_support_format_xar(struct archive *_a)
xar_read_header,
xar_read_data,
xar_read_data_skip,
NULL,
xar_cleanup);
if (r != ARCHIVE_OK)
free(xar);
@ -602,7 +603,8 @@ read_toc(struct archive_read *a)
r = move_reading_point(a, xar->toc_chksum_offset);
if (r != ARCHIVE_OK)
return (r);
b = __archive_read_ahead(a, xar->toc_chksum_size, &bytes);
b = __archive_read_ahead(a,
(size_t)xar->toc_chksum_size, &bytes);
if (bytes < 0)
return ((int)bytes);
if ((uint64_t)bytes < xar->toc_chksum_size) {
@ -611,7 +613,8 @@ read_toc(struct archive_read *a)
"Truncated archive file");
return (ARCHIVE_FATAL);
}
r = checksum_final(a, b, xar->toc_chksum_size, NULL, 0);
r = checksum_final(a, b,
(size_t)xar->toc_chksum_size, NULL, 0);
__archive_read_consume(a, xar->toc_chksum_size);
xar->offset += xar->toc_chksum_size;
if (r != ARCHIVE_OK)
@ -2065,7 +2068,7 @@ xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list)
xar->file->hdnext = xar->hdlink_orgs;
xar->hdlink_orgs = xar->file;
} else {
xar->file->link = atol10(attr->value,
xar->file->link = (unsigned)atol10(attr->value,
strlen(attr->value));
if (xar->file->link > 0)
if (add_link(a, xar, xar->file) != ARCHIVE_OK) {
@ -2624,6 +2627,7 @@ strappend_base64(struct xar *xar,
const unsigned char *b;
size_t len;
(void)xar; /* UNUSED */
len = 0;
out = buff;
b = (const unsigned char *)s;
@ -2760,7 +2764,7 @@ xml_data(void *userData, const char *s, int len)
xar->file->has |= HAS_MODE;
xar->file->mode =
(xar->file->mode & AE_IFMT) |
(atol8(s, len) & ~AE_IFMT);
((mode_t)(atol8(s, len)) & ~AE_IFMT);
break;
case FILE_GROUP:
xar->file->has |= HAS_GID;
@ -3075,12 +3079,15 @@ xml2_xmlattr_setup(struct archive_read *a,
attr->name = strdup(
(const char *)xmlTextReaderConstLocalName(reader));
if (attr->name == NULL) {
free(attr);
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
attr->value = strdup(
(const char *)xmlTextReaderConstValue(reader));
if (attr->value == NULL) {
free(attr->name);
free(attr);
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -110,18 +110,20 @@ archive_string_conversion_charset_name(struct archive_string_conv *);
void
archive_string_conversion_set_opt(struct archive_string_conv *, int);
#define SCONV_SET_OPT_UTF8_LIBARCHIVE2X 1
#define SCONV_SET_OPT_NORMALIZATION_C 2
#define SCONV_SET_OPT_NORMALIZATION_D 4
/* Copy one archive_string to another in locale conversion.
* Return -1 if conversion failes. */
int
archive_strncpy_in_locale(struct archive_string *, const void *, size_t,
archive_strncpy_l(struct archive_string *, const void *, size_t,
struct archive_string_conv *);
/* Copy one archive_string to another in locale conversion.
* Return -1 if conversion failes. */
int
archive_strncat_in_locale(struct archive_string *, const void *, size_t,
archive_strncat_l(struct archive_string *, const void *, size_t,
struct archive_string_conv *);
@ -162,8 +164,8 @@ archive_wstrcat(struct archive_wstring *, const wchar_t *);
archive_strncpy((as), (p), ((p) == NULL ? 0 : strlen(p)))
#define archive_wstrcpy(as,p) \
archive_wstrncpy((as), (p), ((p) == NULL ? 0 : wcslen(p)))
#define archive_strcpy_in_locale(as,p,lo) \
archive_strncpy_in_locale((as), (p), ((p) == NULL ? 0 : strlen(p)), (lo))
#define archive_strcpy_l(as,p,lo) \
archive_strncpy_l((as), (p), ((p) == NULL ? 0 : strlen(p)), (lo))
/* Copy a C string to an archive_string with limit, resizing as necessary. */
#define archive_strncpy(as,p,l) \

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2011 libarchive Project
* Copyright (c) 2011-2012 libarchive Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -29,7 +29,7 @@
/*
* ATTENTION!
* This file is generated by build/utils/gen_archive_string_composition_h.sh
* from http://unicode.org/Public/UNIDATA/UnicodeData.txt
* from http://unicode.org/Public/6.0.0/ucd/UnicodeData.txt
*
* See also http://unicode.org/report/tr15/
*/
@ -1348,4 +1348,945 @@ static const unsigned char ccc_index[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,37,38,};
struct unicode_decomposition_table {
uint32_t nfc;
uint32_t cp1;
uint32_t cp2;
};
static const struct unicode_decomposition_table u_decomposition_table[] = {
{ 0x000C0 , 0x00041 , 0x00300 },
{ 0x000C1 , 0x00041 , 0x00301 },
{ 0x000C2 , 0x00041 , 0x00302 },
{ 0x000C3 , 0x00041 , 0x00303 },
{ 0x000C4 , 0x00041 , 0x00308 },
{ 0x000C5 , 0x00041 , 0x0030A },
{ 0x000C7 , 0x00043 , 0x00327 },
{ 0x000C8 , 0x00045 , 0x00300 },
{ 0x000C9 , 0x00045 , 0x00301 },
{ 0x000CA , 0x00045 , 0x00302 },
{ 0x000CB , 0x00045 , 0x00308 },
{ 0x000CC , 0x00049 , 0x00300 },
{ 0x000CD , 0x00049 , 0x00301 },
{ 0x000CE , 0x00049 , 0x00302 },
{ 0x000CF , 0x00049 , 0x00308 },
{ 0x000D1 , 0x0004E , 0x00303 },
{ 0x000D2 , 0x0004F , 0x00300 },
{ 0x000D3 , 0x0004F , 0x00301 },
{ 0x000D4 , 0x0004F , 0x00302 },
{ 0x000D5 , 0x0004F , 0x00303 },
{ 0x000D6 , 0x0004F , 0x00308 },
{ 0x000D9 , 0x00055 , 0x00300 },
{ 0x000DA , 0x00055 , 0x00301 },
{ 0x000DB , 0x00055 , 0x00302 },
{ 0x000DC , 0x00055 , 0x00308 },
{ 0x000DD , 0x00059 , 0x00301 },
{ 0x000E0 , 0x00061 , 0x00300 },
{ 0x000E1 , 0x00061 , 0x00301 },
{ 0x000E2 , 0x00061 , 0x00302 },
{ 0x000E3 , 0x00061 , 0x00303 },
{ 0x000E4 , 0x00061 , 0x00308 },
{ 0x000E5 , 0x00061 , 0x0030A },
{ 0x000E7 , 0x00063 , 0x00327 },
{ 0x000E8 , 0x00065 , 0x00300 },
{ 0x000E9 , 0x00065 , 0x00301 },
{ 0x000EA , 0x00065 , 0x00302 },
{ 0x000EB , 0x00065 , 0x00308 },
{ 0x000EC , 0x00069 , 0x00300 },
{ 0x000ED , 0x00069 , 0x00301 },
{ 0x000EE , 0x00069 , 0x00302 },
{ 0x000EF , 0x00069 , 0x00308 },
{ 0x000F1 , 0x0006E , 0x00303 },
{ 0x000F2 , 0x0006F , 0x00300 },
{ 0x000F3 , 0x0006F , 0x00301 },
{ 0x000F4 , 0x0006F , 0x00302 },
{ 0x000F5 , 0x0006F , 0x00303 },
{ 0x000F6 , 0x0006F , 0x00308 },
{ 0x000F9 , 0x00075 , 0x00300 },
{ 0x000FA , 0x00075 , 0x00301 },
{ 0x000FB , 0x00075 , 0x00302 },
{ 0x000FC , 0x00075 , 0x00308 },
{ 0x000FD , 0x00079 , 0x00301 },
{ 0x000FF , 0x00079 , 0x00308 },
{ 0x00100 , 0x00041 , 0x00304 },
{ 0x00101 , 0x00061 , 0x00304 },
{ 0x00102 , 0x00041 , 0x00306 },
{ 0x00103 , 0x00061 , 0x00306 },
{ 0x00104 , 0x00041 , 0x00328 },
{ 0x00105 , 0x00061 , 0x00328 },
{ 0x00106 , 0x00043 , 0x00301 },
{ 0x00107 , 0x00063 , 0x00301 },
{ 0x00108 , 0x00043 , 0x00302 },
{ 0x00109 , 0x00063 , 0x00302 },
{ 0x0010A , 0x00043 , 0x00307 },
{ 0x0010B , 0x00063 , 0x00307 },
{ 0x0010C , 0x00043 , 0x0030C },
{ 0x0010D , 0x00063 , 0x0030C },
{ 0x0010E , 0x00044 , 0x0030C },
{ 0x0010F , 0x00064 , 0x0030C },
{ 0x00112 , 0x00045 , 0x00304 },
{ 0x00113 , 0x00065 , 0x00304 },
{ 0x00114 , 0x00045 , 0x00306 },
{ 0x00115 , 0x00065 , 0x00306 },
{ 0x00116 , 0x00045 , 0x00307 },
{ 0x00117 , 0x00065 , 0x00307 },
{ 0x00118 , 0x00045 , 0x00328 },
{ 0x00119 , 0x00065 , 0x00328 },
{ 0x0011A , 0x00045 , 0x0030C },
{ 0x0011B , 0x00065 , 0x0030C },
{ 0x0011C , 0x00047 , 0x00302 },
{ 0x0011D , 0x00067 , 0x00302 },
{ 0x0011E , 0x00047 , 0x00306 },
{ 0x0011F , 0x00067 , 0x00306 },
{ 0x00120 , 0x00047 , 0x00307 },
{ 0x00121 , 0x00067 , 0x00307 },
{ 0x00122 , 0x00047 , 0x00327 },
{ 0x00123 , 0x00067 , 0x00327 },
{ 0x00124 , 0x00048 , 0x00302 },
{ 0x00125 , 0x00068 , 0x00302 },
{ 0x00128 , 0x00049 , 0x00303 },
{ 0x00129 , 0x00069 , 0x00303 },
{ 0x0012A , 0x00049 , 0x00304 },
{ 0x0012B , 0x00069 , 0x00304 },
{ 0x0012C , 0x00049 , 0x00306 },
{ 0x0012D , 0x00069 , 0x00306 },
{ 0x0012E , 0x00049 , 0x00328 },
{ 0x0012F , 0x00069 , 0x00328 },
{ 0x00130 , 0x00049 , 0x00307 },
{ 0x00134 , 0x0004A , 0x00302 },
{ 0x00135 , 0x0006A , 0x00302 },
{ 0x00136 , 0x0004B , 0x00327 },
{ 0x00137 , 0x0006B , 0x00327 },
{ 0x00139 , 0x0004C , 0x00301 },
{ 0x0013A , 0x0006C , 0x00301 },
{ 0x0013B , 0x0004C , 0x00327 },
{ 0x0013C , 0x0006C , 0x00327 },
{ 0x0013D , 0x0004C , 0x0030C },
{ 0x0013E , 0x0006C , 0x0030C },
{ 0x00143 , 0x0004E , 0x00301 },
{ 0x00144 , 0x0006E , 0x00301 },
{ 0x00145 , 0x0004E , 0x00327 },
{ 0x00146 , 0x0006E , 0x00327 },
{ 0x00147 , 0x0004E , 0x0030C },
{ 0x00148 , 0x0006E , 0x0030C },
{ 0x0014C , 0x0004F , 0x00304 },
{ 0x0014D , 0x0006F , 0x00304 },
{ 0x0014E , 0x0004F , 0x00306 },
{ 0x0014F , 0x0006F , 0x00306 },
{ 0x00150 , 0x0004F , 0x0030B },
{ 0x00151 , 0x0006F , 0x0030B },
{ 0x00154 , 0x00052 , 0x00301 },
{ 0x00155 , 0x00072 , 0x00301 },
{ 0x00156 , 0x00052 , 0x00327 },
{ 0x00157 , 0x00072 , 0x00327 },
{ 0x00158 , 0x00052 , 0x0030C },
{ 0x00159 , 0x00072 , 0x0030C },
{ 0x0015A , 0x00053 , 0x00301 },
{ 0x0015B , 0x00073 , 0x00301 },
{ 0x0015C , 0x00053 , 0x00302 },
{ 0x0015D , 0x00073 , 0x00302 },
{ 0x0015E , 0x00053 , 0x00327 },
{ 0x0015F , 0x00073 , 0x00327 },
{ 0x00160 , 0x00053 , 0x0030C },
{ 0x00161 , 0x00073 , 0x0030C },
{ 0x00162 , 0x00054 , 0x00327 },
{ 0x00163 , 0x00074 , 0x00327 },
{ 0x00164 , 0x00054 , 0x0030C },
{ 0x00165 , 0x00074 , 0x0030C },
{ 0x00168 , 0x00055 , 0x00303 },
{ 0x00169 , 0x00075 , 0x00303 },
{ 0x0016A , 0x00055 , 0x00304 },
{ 0x0016B , 0x00075 , 0x00304 },
{ 0x0016C , 0x00055 , 0x00306 },
{ 0x0016D , 0x00075 , 0x00306 },
{ 0x0016E , 0x00055 , 0x0030A },
{ 0x0016F , 0x00075 , 0x0030A },
{ 0x00170 , 0x00055 , 0x0030B },
{ 0x00171 , 0x00075 , 0x0030B },
{ 0x00172 , 0x00055 , 0x00328 },
{ 0x00173 , 0x00075 , 0x00328 },
{ 0x00174 , 0x00057 , 0x00302 },
{ 0x00175 , 0x00077 , 0x00302 },
{ 0x00176 , 0x00059 , 0x00302 },
{ 0x00177 , 0x00079 , 0x00302 },
{ 0x00178 , 0x00059 , 0x00308 },
{ 0x00179 , 0x0005A , 0x00301 },
{ 0x0017A , 0x0007A , 0x00301 },
{ 0x0017B , 0x0005A , 0x00307 },
{ 0x0017C , 0x0007A , 0x00307 },
{ 0x0017D , 0x0005A , 0x0030C },
{ 0x0017E , 0x0007A , 0x0030C },
{ 0x001A0 , 0x0004F , 0x0031B },
{ 0x001A1 , 0x0006F , 0x0031B },
{ 0x001AF , 0x00055 , 0x0031B },
{ 0x001B0 , 0x00075 , 0x0031B },
{ 0x001CD , 0x00041 , 0x0030C },
{ 0x001CE , 0x00061 , 0x0030C },
{ 0x001CF , 0x00049 , 0x0030C },
{ 0x001D0 , 0x00069 , 0x0030C },
{ 0x001D1 , 0x0004F , 0x0030C },
{ 0x001D2 , 0x0006F , 0x0030C },
{ 0x001D3 , 0x00055 , 0x0030C },
{ 0x001D4 , 0x00075 , 0x0030C },
{ 0x001D5 , 0x000DC , 0x00304 },
{ 0x001D6 , 0x000FC , 0x00304 },
{ 0x001D7 , 0x000DC , 0x00301 },
{ 0x001D8 , 0x000FC , 0x00301 },
{ 0x001D9 , 0x000DC , 0x0030C },
{ 0x001DA , 0x000FC , 0x0030C },
{ 0x001DB , 0x000DC , 0x00300 },
{ 0x001DC , 0x000FC , 0x00300 },
{ 0x001DE , 0x000C4 , 0x00304 },
{ 0x001DF , 0x000E4 , 0x00304 },
{ 0x001E0 , 0x00226 , 0x00304 },
{ 0x001E1 , 0x00227 , 0x00304 },
{ 0x001E2 , 0x000C6 , 0x00304 },
{ 0x001E3 , 0x000E6 , 0x00304 },
{ 0x001E6 , 0x00047 , 0x0030C },
{ 0x001E7 , 0x00067 , 0x0030C },
{ 0x001E8 , 0x0004B , 0x0030C },
{ 0x001E9 , 0x0006B , 0x0030C },
{ 0x001EA , 0x0004F , 0x00328 },
{ 0x001EB , 0x0006F , 0x00328 },
{ 0x001EC , 0x001EA , 0x00304 },
{ 0x001ED , 0x001EB , 0x00304 },
{ 0x001EE , 0x001B7 , 0x0030C },
{ 0x001EF , 0x00292 , 0x0030C },
{ 0x001F0 , 0x0006A , 0x0030C },
{ 0x001F4 , 0x00047 , 0x00301 },
{ 0x001F5 , 0x00067 , 0x00301 },
{ 0x001F8 , 0x0004E , 0x00300 },
{ 0x001F9 , 0x0006E , 0x00300 },
{ 0x001FA , 0x000C5 , 0x00301 },
{ 0x001FB , 0x000E5 , 0x00301 },
{ 0x001FC , 0x000C6 , 0x00301 },
{ 0x001FD , 0x000E6 , 0x00301 },
{ 0x001FE , 0x000D8 , 0x00301 },
{ 0x001FF , 0x000F8 , 0x00301 },
{ 0x00200 , 0x00041 , 0x0030F },
{ 0x00201 , 0x00061 , 0x0030F },
{ 0x00202 , 0x00041 , 0x00311 },
{ 0x00203 , 0x00061 , 0x00311 },
{ 0x00204 , 0x00045 , 0x0030F },
{ 0x00205 , 0x00065 , 0x0030F },
{ 0x00206 , 0x00045 , 0x00311 },
{ 0x00207 , 0x00065 , 0x00311 },
{ 0x00208 , 0x00049 , 0x0030F },
{ 0x00209 , 0x00069 , 0x0030F },
{ 0x0020A , 0x00049 , 0x00311 },
{ 0x0020B , 0x00069 , 0x00311 },
{ 0x0020C , 0x0004F , 0x0030F },
{ 0x0020D , 0x0006F , 0x0030F },
{ 0x0020E , 0x0004F , 0x00311 },
{ 0x0020F , 0x0006F , 0x00311 },
{ 0x00210 , 0x00052 , 0x0030F },
{ 0x00211 , 0x00072 , 0x0030F },
{ 0x00212 , 0x00052 , 0x00311 },
{ 0x00213 , 0x00072 , 0x00311 },
{ 0x00214 , 0x00055 , 0x0030F },
{ 0x00215 , 0x00075 , 0x0030F },
{ 0x00216 , 0x00055 , 0x00311 },
{ 0x00217 , 0x00075 , 0x00311 },
{ 0x00218 , 0x00053 , 0x00326 },
{ 0x00219 , 0x00073 , 0x00326 },
{ 0x0021A , 0x00054 , 0x00326 },
{ 0x0021B , 0x00074 , 0x00326 },
{ 0x0021E , 0x00048 , 0x0030C },
{ 0x0021F , 0x00068 , 0x0030C },
{ 0x00226 , 0x00041 , 0x00307 },
{ 0x00227 , 0x00061 , 0x00307 },
{ 0x00228 , 0x00045 , 0x00327 },
{ 0x00229 , 0x00065 , 0x00327 },
{ 0x0022A , 0x000D6 , 0x00304 },
{ 0x0022B , 0x000F6 , 0x00304 },
{ 0x0022C , 0x000D5 , 0x00304 },
{ 0x0022D , 0x000F5 , 0x00304 },
{ 0x0022E , 0x0004F , 0x00307 },
{ 0x0022F , 0x0006F , 0x00307 },
{ 0x00230 , 0x0022E , 0x00304 },
{ 0x00231 , 0x0022F , 0x00304 },
{ 0x00232 , 0x00059 , 0x00304 },
{ 0x00233 , 0x00079 , 0x00304 },
{ 0x00385 , 0x000A8 , 0x00301 },
{ 0x00386 , 0x00391 , 0x00301 },
{ 0x00388 , 0x00395 , 0x00301 },
{ 0x00389 , 0x00397 , 0x00301 },
{ 0x0038A , 0x00399 , 0x00301 },
{ 0x0038C , 0x0039F , 0x00301 },
{ 0x0038E , 0x003A5 , 0x00301 },
{ 0x0038F , 0x003A9 , 0x00301 },
{ 0x00390 , 0x003CA , 0x00301 },
{ 0x003AA , 0x00399 , 0x00308 },
{ 0x003AB , 0x003A5 , 0x00308 },
{ 0x003AC , 0x003B1 , 0x00301 },
{ 0x003AD , 0x003B5 , 0x00301 },
{ 0x003AE , 0x003B7 , 0x00301 },
{ 0x003AF , 0x003B9 , 0x00301 },
{ 0x003B0 , 0x003CB , 0x00301 },
{ 0x003CA , 0x003B9 , 0x00308 },
{ 0x003CB , 0x003C5 , 0x00308 },
{ 0x003CC , 0x003BF , 0x00301 },
{ 0x003CD , 0x003C5 , 0x00301 },
{ 0x003CE , 0x003C9 , 0x00301 },
{ 0x003D3 , 0x003D2 , 0x00301 },
{ 0x003D4 , 0x003D2 , 0x00308 },
{ 0x00400 , 0x00415 , 0x00300 },
{ 0x00401 , 0x00415 , 0x00308 },
{ 0x00403 , 0x00413 , 0x00301 },
{ 0x00407 , 0x00406 , 0x00308 },
{ 0x0040C , 0x0041A , 0x00301 },
{ 0x0040D , 0x00418 , 0x00300 },
{ 0x0040E , 0x00423 , 0x00306 },
{ 0x00419 , 0x00418 , 0x00306 },
{ 0x00439 , 0x00438 , 0x00306 },
{ 0x00450 , 0x00435 , 0x00300 },
{ 0x00451 , 0x00435 , 0x00308 },
{ 0x00453 , 0x00433 , 0x00301 },
{ 0x00457 , 0x00456 , 0x00308 },
{ 0x0045C , 0x0043A , 0x00301 },
{ 0x0045D , 0x00438 , 0x00300 },
{ 0x0045E , 0x00443 , 0x00306 },
{ 0x00476 , 0x00474 , 0x0030F },
{ 0x00477 , 0x00475 , 0x0030F },
{ 0x004C1 , 0x00416 , 0x00306 },
{ 0x004C2 , 0x00436 , 0x00306 },
{ 0x004D0 , 0x00410 , 0x00306 },
{ 0x004D1 , 0x00430 , 0x00306 },
{ 0x004D2 , 0x00410 , 0x00308 },
{ 0x004D3 , 0x00430 , 0x00308 },
{ 0x004D6 , 0x00415 , 0x00306 },
{ 0x004D7 , 0x00435 , 0x00306 },
{ 0x004DA , 0x004D8 , 0x00308 },
{ 0x004DB , 0x004D9 , 0x00308 },
{ 0x004DC , 0x00416 , 0x00308 },
{ 0x004DD , 0x00436 , 0x00308 },
{ 0x004DE , 0x00417 , 0x00308 },
{ 0x004DF , 0x00437 , 0x00308 },
{ 0x004E2 , 0x00418 , 0x00304 },
{ 0x004E3 , 0x00438 , 0x00304 },
{ 0x004E4 , 0x00418 , 0x00308 },
{ 0x004E5 , 0x00438 , 0x00308 },
{ 0x004E6 , 0x0041E , 0x00308 },
{ 0x004E7 , 0x0043E , 0x00308 },
{ 0x004EA , 0x004E8 , 0x00308 },
{ 0x004EB , 0x004E9 , 0x00308 },
{ 0x004EC , 0x0042D , 0x00308 },
{ 0x004ED , 0x0044D , 0x00308 },
{ 0x004EE , 0x00423 , 0x00304 },
{ 0x004EF , 0x00443 , 0x00304 },
{ 0x004F0 , 0x00423 , 0x00308 },
{ 0x004F1 , 0x00443 , 0x00308 },
{ 0x004F2 , 0x00423 , 0x0030B },
{ 0x004F3 , 0x00443 , 0x0030B },
{ 0x004F4 , 0x00427 , 0x00308 },
{ 0x004F5 , 0x00447 , 0x00308 },
{ 0x004F8 , 0x0042B , 0x00308 },
{ 0x004F9 , 0x0044B , 0x00308 },
{ 0x00622 , 0x00627 , 0x00653 },
{ 0x00623 , 0x00627 , 0x00654 },
{ 0x00624 , 0x00648 , 0x00654 },
{ 0x00625 , 0x00627 , 0x00655 },
{ 0x00626 , 0x0064A , 0x00654 },
{ 0x006C0 , 0x006D5 , 0x00654 },
{ 0x006C2 , 0x006C1 , 0x00654 },
{ 0x006D3 , 0x006D2 , 0x00654 },
{ 0x00929 , 0x00928 , 0x0093C },
{ 0x00931 , 0x00930 , 0x0093C },
{ 0x00934 , 0x00933 , 0x0093C },
{ 0x009CB , 0x009C7 , 0x009BE },
{ 0x009CC , 0x009C7 , 0x009D7 },
{ 0x00B48 , 0x00B47 , 0x00B56 },
{ 0x00B4B , 0x00B47 , 0x00B3E },
{ 0x00B4C , 0x00B47 , 0x00B57 },
{ 0x00B94 , 0x00B92 , 0x00BD7 },
{ 0x00BCA , 0x00BC6 , 0x00BBE },
{ 0x00BCB , 0x00BC7 , 0x00BBE },
{ 0x00BCC , 0x00BC6 , 0x00BD7 },
{ 0x00C48 , 0x00C46 , 0x00C56 },
{ 0x00CC0 , 0x00CBF , 0x00CD5 },
{ 0x00CC7 , 0x00CC6 , 0x00CD5 },
{ 0x00CC8 , 0x00CC6 , 0x00CD6 },
{ 0x00CCA , 0x00CC6 , 0x00CC2 },
{ 0x00CCB , 0x00CCA , 0x00CD5 },
{ 0x00D4A , 0x00D46 , 0x00D3E },
{ 0x00D4B , 0x00D47 , 0x00D3E },
{ 0x00D4C , 0x00D46 , 0x00D57 },
{ 0x00DDA , 0x00DD9 , 0x00DCA },
{ 0x00DDC , 0x00DD9 , 0x00DCF },
{ 0x00DDD , 0x00DDC , 0x00DCA },
{ 0x00DDE , 0x00DD9 , 0x00DDF },
{ 0x01026 , 0x01025 , 0x0102E },
{ 0x01B06 , 0x01B05 , 0x01B35 },
{ 0x01B08 , 0x01B07 , 0x01B35 },
{ 0x01B0A , 0x01B09 , 0x01B35 },
{ 0x01B0C , 0x01B0B , 0x01B35 },
{ 0x01B0E , 0x01B0D , 0x01B35 },
{ 0x01B12 , 0x01B11 , 0x01B35 },
{ 0x01B3B , 0x01B3A , 0x01B35 },
{ 0x01B3D , 0x01B3C , 0x01B35 },
{ 0x01B40 , 0x01B3E , 0x01B35 },
{ 0x01B41 , 0x01B3F , 0x01B35 },
{ 0x01B43 , 0x01B42 , 0x01B35 },
{ 0x01E00 , 0x00041 , 0x00325 },
{ 0x01E01 , 0x00061 , 0x00325 },
{ 0x01E02 , 0x00042 , 0x00307 },
{ 0x01E03 , 0x00062 , 0x00307 },
{ 0x01E04 , 0x00042 , 0x00323 },
{ 0x01E05 , 0x00062 , 0x00323 },
{ 0x01E06 , 0x00042 , 0x00331 },
{ 0x01E07 , 0x00062 , 0x00331 },
{ 0x01E08 , 0x000C7 , 0x00301 },
{ 0x01E09 , 0x000E7 , 0x00301 },
{ 0x01E0A , 0x00044 , 0x00307 },
{ 0x01E0B , 0x00064 , 0x00307 },
{ 0x01E0C , 0x00044 , 0x00323 },
{ 0x01E0D , 0x00064 , 0x00323 },
{ 0x01E0E , 0x00044 , 0x00331 },
{ 0x01E0F , 0x00064 , 0x00331 },
{ 0x01E10 , 0x00044 , 0x00327 },
{ 0x01E11 , 0x00064 , 0x00327 },
{ 0x01E12 , 0x00044 , 0x0032D },
{ 0x01E13 , 0x00064 , 0x0032D },
{ 0x01E14 , 0x00112 , 0x00300 },
{ 0x01E15 , 0x00113 , 0x00300 },
{ 0x01E16 , 0x00112 , 0x00301 },
{ 0x01E17 , 0x00113 , 0x00301 },
{ 0x01E18 , 0x00045 , 0x0032D },
{ 0x01E19 , 0x00065 , 0x0032D },
{ 0x01E1A , 0x00045 , 0x00330 },
{ 0x01E1B , 0x00065 , 0x00330 },
{ 0x01E1C , 0x00228 , 0x00306 },
{ 0x01E1D , 0x00229 , 0x00306 },
{ 0x01E1E , 0x00046 , 0x00307 },
{ 0x01E1F , 0x00066 , 0x00307 },
{ 0x01E20 , 0x00047 , 0x00304 },
{ 0x01E21 , 0x00067 , 0x00304 },
{ 0x01E22 , 0x00048 , 0x00307 },
{ 0x01E23 , 0x00068 , 0x00307 },
{ 0x01E24 , 0x00048 , 0x00323 },
{ 0x01E25 , 0x00068 , 0x00323 },
{ 0x01E26 , 0x00048 , 0x00308 },
{ 0x01E27 , 0x00068 , 0x00308 },
{ 0x01E28 , 0x00048 , 0x00327 },
{ 0x01E29 , 0x00068 , 0x00327 },
{ 0x01E2A , 0x00048 , 0x0032E },
{ 0x01E2B , 0x00068 , 0x0032E },
{ 0x01E2C , 0x00049 , 0x00330 },
{ 0x01E2D , 0x00069 , 0x00330 },
{ 0x01E2E , 0x000CF , 0x00301 },
{ 0x01E2F , 0x000EF , 0x00301 },
{ 0x01E30 , 0x0004B , 0x00301 },
{ 0x01E31 , 0x0006B , 0x00301 },
{ 0x01E32 , 0x0004B , 0x00323 },
{ 0x01E33 , 0x0006B , 0x00323 },
{ 0x01E34 , 0x0004B , 0x00331 },
{ 0x01E35 , 0x0006B , 0x00331 },
{ 0x01E36 , 0x0004C , 0x00323 },
{ 0x01E37 , 0x0006C , 0x00323 },
{ 0x01E38 , 0x01E36 , 0x00304 },
{ 0x01E39 , 0x01E37 , 0x00304 },
{ 0x01E3A , 0x0004C , 0x00331 },
{ 0x01E3B , 0x0006C , 0x00331 },
{ 0x01E3C , 0x0004C , 0x0032D },
{ 0x01E3D , 0x0006C , 0x0032D },
{ 0x01E3E , 0x0004D , 0x00301 },
{ 0x01E3F , 0x0006D , 0x00301 },
{ 0x01E40 , 0x0004D , 0x00307 },
{ 0x01E41 , 0x0006D , 0x00307 },
{ 0x01E42 , 0x0004D , 0x00323 },
{ 0x01E43 , 0x0006D , 0x00323 },
{ 0x01E44 , 0x0004E , 0x00307 },
{ 0x01E45 , 0x0006E , 0x00307 },
{ 0x01E46 , 0x0004E , 0x00323 },
{ 0x01E47 , 0x0006E , 0x00323 },
{ 0x01E48 , 0x0004E , 0x00331 },
{ 0x01E49 , 0x0006E , 0x00331 },
{ 0x01E4A , 0x0004E , 0x0032D },
{ 0x01E4B , 0x0006E , 0x0032D },
{ 0x01E4C , 0x000D5 , 0x00301 },
{ 0x01E4D , 0x000F5 , 0x00301 },
{ 0x01E4E , 0x000D5 , 0x00308 },
{ 0x01E4F , 0x000F5 , 0x00308 },
{ 0x01E50 , 0x0014C , 0x00300 },
{ 0x01E51 , 0x0014D , 0x00300 },
{ 0x01E52 , 0x0014C , 0x00301 },
{ 0x01E53 , 0x0014D , 0x00301 },
{ 0x01E54 , 0x00050 , 0x00301 },
{ 0x01E55 , 0x00070 , 0x00301 },
{ 0x01E56 , 0x00050 , 0x00307 },
{ 0x01E57 , 0x00070 , 0x00307 },
{ 0x01E58 , 0x00052 , 0x00307 },
{ 0x01E59 , 0x00072 , 0x00307 },
{ 0x01E5A , 0x00052 , 0x00323 },
{ 0x01E5B , 0x00072 , 0x00323 },
{ 0x01E5C , 0x01E5A , 0x00304 },
{ 0x01E5D , 0x01E5B , 0x00304 },
{ 0x01E5E , 0x00052 , 0x00331 },
{ 0x01E5F , 0x00072 , 0x00331 },
{ 0x01E60 , 0x00053 , 0x00307 },
{ 0x01E61 , 0x00073 , 0x00307 },
{ 0x01E62 , 0x00053 , 0x00323 },
{ 0x01E63 , 0x00073 , 0x00323 },
{ 0x01E64 , 0x0015A , 0x00307 },
{ 0x01E65 , 0x0015B , 0x00307 },
{ 0x01E66 , 0x00160 , 0x00307 },
{ 0x01E67 , 0x00161 , 0x00307 },
{ 0x01E68 , 0x01E62 , 0x00307 },
{ 0x01E69 , 0x01E63 , 0x00307 },
{ 0x01E6A , 0x00054 , 0x00307 },
{ 0x01E6B , 0x00074 , 0x00307 },
{ 0x01E6C , 0x00054 , 0x00323 },
{ 0x01E6D , 0x00074 , 0x00323 },
{ 0x01E6E , 0x00054 , 0x00331 },
{ 0x01E6F , 0x00074 , 0x00331 },
{ 0x01E70 , 0x00054 , 0x0032D },
{ 0x01E71 , 0x00074 , 0x0032D },
{ 0x01E72 , 0x00055 , 0x00324 },
{ 0x01E73 , 0x00075 , 0x00324 },
{ 0x01E74 , 0x00055 , 0x00330 },
{ 0x01E75 , 0x00075 , 0x00330 },
{ 0x01E76 , 0x00055 , 0x0032D },
{ 0x01E77 , 0x00075 , 0x0032D },
{ 0x01E78 , 0x00168 , 0x00301 },
{ 0x01E79 , 0x00169 , 0x00301 },
{ 0x01E7A , 0x0016A , 0x00308 },
{ 0x01E7B , 0x0016B , 0x00308 },
{ 0x01E7C , 0x00056 , 0x00303 },
{ 0x01E7D , 0x00076 , 0x00303 },
{ 0x01E7E , 0x00056 , 0x00323 },
{ 0x01E7F , 0x00076 , 0x00323 },
{ 0x01E80 , 0x00057 , 0x00300 },
{ 0x01E81 , 0x00077 , 0x00300 },
{ 0x01E82 , 0x00057 , 0x00301 },
{ 0x01E83 , 0x00077 , 0x00301 },
{ 0x01E84 , 0x00057 , 0x00308 },
{ 0x01E85 , 0x00077 , 0x00308 },
{ 0x01E86 , 0x00057 , 0x00307 },
{ 0x01E87 , 0x00077 , 0x00307 },
{ 0x01E88 , 0x00057 , 0x00323 },
{ 0x01E89 , 0x00077 , 0x00323 },
{ 0x01E8A , 0x00058 , 0x00307 },
{ 0x01E8B , 0x00078 , 0x00307 },
{ 0x01E8C , 0x00058 , 0x00308 },
{ 0x01E8D , 0x00078 , 0x00308 },
{ 0x01E8E , 0x00059 , 0x00307 },
{ 0x01E8F , 0x00079 , 0x00307 },
{ 0x01E90 , 0x0005A , 0x00302 },
{ 0x01E91 , 0x0007A , 0x00302 },
{ 0x01E92 , 0x0005A , 0x00323 },
{ 0x01E93 , 0x0007A , 0x00323 },
{ 0x01E94 , 0x0005A , 0x00331 },
{ 0x01E95 , 0x0007A , 0x00331 },
{ 0x01E96 , 0x00068 , 0x00331 },
{ 0x01E97 , 0x00074 , 0x00308 },
{ 0x01E98 , 0x00077 , 0x0030A },
{ 0x01E99 , 0x00079 , 0x0030A },
{ 0x01E9B , 0x0017F , 0x00307 },
{ 0x01EA0 , 0x00041 , 0x00323 },
{ 0x01EA1 , 0x00061 , 0x00323 },
{ 0x01EA2 , 0x00041 , 0x00309 },
{ 0x01EA3 , 0x00061 , 0x00309 },
{ 0x01EA4 , 0x000C2 , 0x00301 },
{ 0x01EA5 , 0x000E2 , 0x00301 },
{ 0x01EA6 , 0x000C2 , 0x00300 },
{ 0x01EA7 , 0x000E2 , 0x00300 },
{ 0x01EA8 , 0x000C2 , 0x00309 },
{ 0x01EA9 , 0x000E2 , 0x00309 },
{ 0x01EAA , 0x000C2 , 0x00303 },
{ 0x01EAB , 0x000E2 , 0x00303 },
{ 0x01EAC , 0x01EA0 , 0x00302 },
{ 0x01EAD , 0x01EA1 , 0x00302 },
{ 0x01EAE , 0x00102 , 0x00301 },
{ 0x01EAF , 0x00103 , 0x00301 },
{ 0x01EB0 , 0x00102 , 0x00300 },
{ 0x01EB1 , 0x00103 , 0x00300 },
{ 0x01EB2 , 0x00102 , 0x00309 },
{ 0x01EB3 , 0x00103 , 0x00309 },
{ 0x01EB4 , 0x00102 , 0x00303 },
{ 0x01EB5 , 0x00103 , 0x00303 },
{ 0x01EB6 , 0x01EA0 , 0x00306 },
{ 0x01EB7 , 0x01EA1 , 0x00306 },
{ 0x01EB8 , 0x00045 , 0x00323 },
{ 0x01EB9 , 0x00065 , 0x00323 },
{ 0x01EBA , 0x00045 , 0x00309 },
{ 0x01EBB , 0x00065 , 0x00309 },
{ 0x01EBC , 0x00045 , 0x00303 },
{ 0x01EBD , 0x00065 , 0x00303 },
{ 0x01EBE , 0x000CA , 0x00301 },
{ 0x01EBF , 0x000EA , 0x00301 },
{ 0x01EC0 , 0x000CA , 0x00300 },
{ 0x01EC1 , 0x000EA , 0x00300 },
{ 0x01EC2 , 0x000CA , 0x00309 },
{ 0x01EC3 , 0x000EA , 0x00309 },
{ 0x01EC4 , 0x000CA , 0x00303 },
{ 0x01EC5 , 0x000EA , 0x00303 },
{ 0x01EC6 , 0x01EB8 , 0x00302 },
{ 0x01EC7 , 0x01EB9 , 0x00302 },
{ 0x01EC8 , 0x00049 , 0x00309 },
{ 0x01EC9 , 0x00069 , 0x00309 },
{ 0x01ECA , 0x00049 , 0x00323 },
{ 0x01ECB , 0x00069 , 0x00323 },
{ 0x01ECC , 0x0004F , 0x00323 },
{ 0x01ECD , 0x0006F , 0x00323 },
{ 0x01ECE , 0x0004F , 0x00309 },
{ 0x01ECF , 0x0006F , 0x00309 },
{ 0x01ED0 , 0x000D4 , 0x00301 },
{ 0x01ED1 , 0x000F4 , 0x00301 },
{ 0x01ED2 , 0x000D4 , 0x00300 },
{ 0x01ED3 , 0x000F4 , 0x00300 },
{ 0x01ED4 , 0x000D4 , 0x00309 },
{ 0x01ED5 , 0x000F4 , 0x00309 },
{ 0x01ED6 , 0x000D4 , 0x00303 },
{ 0x01ED7 , 0x000F4 , 0x00303 },
{ 0x01ED8 , 0x01ECC , 0x00302 },
{ 0x01ED9 , 0x01ECD , 0x00302 },
{ 0x01EDA , 0x001A0 , 0x00301 },
{ 0x01EDB , 0x001A1 , 0x00301 },
{ 0x01EDC , 0x001A0 , 0x00300 },
{ 0x01EDD , 0x001A1 , 0x00300 },
{ 0x01EDE , 0x001A0 , 0x00309 },
{ 0x01EDF , 0x001A1 , 0x00309 },
{ 0x01EE0 , 0x001A0 , 0x00303 },
{ 0x01EE1 , 0x001A1 , 0x00303 },
{ 0x01EE2 , 0x001A0 , 0x00323 },
{ 0x01EE3 , 0x001A1 , 0x00323 },
{ 0x01EE4 , 0x00055 , 0x00323 },
{ 0x01EE5 , 0x00075 , 0x00323 },
{ 0x01EE6 , 0x00055 , 0x00309 },
{ 0x01EE7 , 0x00075 , 0x00309 },
{ 0x01EE8 , 0x001AF , 0x00301 },
{ 0x01EE9 , 0x001B0 , 0x00301 },
{ 0x01EEA , 0x001AF , 0x00300 },
{ 0x01EEB , 0x001B0 , 0x00300 },
{ 0x01EEC , 0x001AF , 0x00309 },
{ 0x01EED , 0x001B0 , 0x00309 },
{ 0x01EEE , 0x001AF , 0x00303 },
{ 0x01EEF , 0x001B0 , 0x00303 },
{ 0x01EF0 , 0x001AF , 0x00323 },
{ 0x01EF1 , 0x001B0 , 0x00323 },
{ 0x01EF2 , 0x00059 , 0x00300 },
{ 0x01EF3 , 0x00079 , 0x00300 },
{ 0x01EF4 , 0x00059 , 0x00323 },
{ 0x01EF5 , 0x00079 , 0x00323 },
{ 0x01EF6 , 0x00059 , 0x00309 },
{ 0x01EF7 , 0x00079 , 0x00309 },
{ 0x01EF8 , 0x00059 , 0x00303 },
{ 0x01EF9 , 0x00079 , 0x00303 },
{ 0x01F00 , 0x003B1 , 0x00313 },
{ 0x01F01 , 0x003B1 , 0x00314 },
{ 0x01F02 , 0x01F00 , 0x00300 },
{ 0x01F03 , 0x01F01 , 0x00300 },
{ 0x01F04 , 0x01F00 , 0x00301 },
{ 0x01F05 , 0x01F01 , 0x00301 },
{ 0x01F06 , 0x01F00 , 0x00342 },
{ 0x01F07 , 0x01F01 , 0x00342 },
{ 0x01F08 , 0x00391 , 0x00313 },
{ 0x01F09 , 0x00391 , 0x00314 },
{ 0x01F0A , 0x01F08 , 0x00300 },
{ 0x01F0B , 0x01F09 , 0x00300 },
{ 0x01F0C , 0x01F08 , 0x00301 },
{ 0x01F0D , 0x01F09 , 0x00301 },
{ 0x01F0E , 0x01F08 , 0x00342 },
{ 0x01F0F , 0x01F09 , 0x00342 },
{ 0x01F10 , 0x003B5 , 0x00313 },
{ 0x01F11 , 0x003B5 , 0x00314 },
{ 0x01F12 , 0x01F10 , 0x00300 },
{ 0x01F13 , 0x01F11 , 0x00300 },
{ 0x01F14 , 0x01F10 , 0x00301 },
{ 0x01F15 , 0x01F11 , 0x00301 },
{ 0x01F18 , 0x00395 , 0x00313 },
{ 0x01F19 , 0x00395 , 0x00314 },
{ 0x01F1A , 0x01F18 , 0x00300 },
{ 0x01F1B , 0x01F19 , 0x00300 },
{ 0x01F1C , 0x01F18 , 0x00301 },
{ 0x01F1D , 0x01F19 , 0x00301 },
{ 0x01F20 , 0x003B7 , 0x00313 },
{ 0x01F21 , 0x003B7 , 0x00314 },
{ 0x01F22 , 0x01F20 , 0x00300 },
{ 0x01F23 , 0x01F21 , 0x00300 },
{ 0x01F24 , 0x01F20 , 0x00301 },
{ 0x01F25 , 0x01F21 , 0x00301 },
{ 0x01F26 , 0x01F20 , 0x00342 },
{ 0x01F27 , 0x01F21 , 0x00342 },
{ 0x01F28 , 0x00397 , 0x00313 },
{ 0x01F29 , 0x00397 , 0x00314 },
{ 0x01F2A , 0x01F28 , 0x00300 },
{ 0x01F2B , 0x01F29 , 0x00300 },
{ 0x01F2C , 0x01F28 , 0x00301 },
{ 0x01F2D , 0x01F29 , 0x00301 },
{ 0x01F2E , 0x01F28 , 0x00342 },
{ 0x01F2F , 0x01F29 , 0x00342 },
{ 0x01F30 , 0x003B9 , 0x00313 },
{ 0x01F31 , 0x003B9 , 0x00314 },
{ 0x01F32 , 0x01F30 , 0x00300 },
{ 0x01F33 , 0x01F31 , 0x00300 },
{ 0x01F34 , 0x01F30 , 0x00301 },
{ 0x01F35 , 0x01F31 , 0x00301 },
{ 0x01F36 , 0x01F30 , 0x00342 },
{ 0x01F37 , 0x01F31 , 0x00342 },
{ 0x01F38 , 0x00399 , 0x00313 },
{ 0x01F39 , 0x00399 , 0x00314 },
{ 0x01F3A , 0x01F38 , 0x00300 },
{ 0x01F3B , 0x01F39 , 0x00300 },
{ 0x01F3C , 0x01F38 , 0x00301 },
{ 0x01F3D , 0x01F39 , 0x00301 },
{ 0x01F3E , 0x01F38 , 0x00342 },
{ 0x01F3F , 0x01F39 , 0x00342 },
{ 0x01F40 , 0x003BF , 0x00313 },
{ 0x01F41 , 0x003BF , 0x00314 },
{ 0x01F42 , 0x01F40 , 0x00300 },
{ 0x01F43 , 0x01F41 , 0x00300 },
{ 0x01F44 , 0x01F40 , 0x00301 },
{ 0x01F45 , 0x01F41 , 0x00301 },
{ 0x01F48 , 0x0039F , 0x00313 },
{ 0x01F49 , 0x0039F , 0x00314 },
{ 0x01F4A , 0x01F48 , 0x00300 },
{ 0x01F4B , 0x01F49 , 0x00300 },
{ 0x01F4C , 0x01F48 , 0x00301 },
{ 0x01F4D , 0x01F49 , 0x00301 },
{ 0x01F50 , 0x003C5 , 0x00313 },
{ 0x01F51 , 0x003C5 , 0x00314 },
{ 0x01F52 , 0x01F50 , 0x00300 },
{ 0x01F53 , 0x01F51 , 0x00300 },
{ 0x01F54 , 0x01F50 , 0x00301 },
{ 0x01F55 , 0x01F51 , 0x00301 },
{ 0x01F56 , 0x01F50 , 0x00342 },
{ 0x01F57 , 0x01F51 , 0x00342 },
{ 0x01F59 , 0x003A5 , 0x00314 },
{ 0x01F5B , 0x01F59 , 0x00300 },
{ 0x01F5D , 0x01F59 , 0x00301 },
{ 0x01F5F , 0x01F59 , 0x00342 },
{ 0x01F60 , 0x003C9 , 0x00313 },
{ 0x01F61 , 0x003C9 , 0x00314 },
{ 0x01F62 , 0x01F60 , 0x00300 },
{ 0x01F63 , 0x01F61 , 0x00300 },
{ 0x01F64 , 0x01F60 , 0x00301 },
{ 0x01F65 , 0x01F61 , 0x00301 },
{ 0x01F66 , 0x01F60 , 0x00342 },
{ 0x01F67 , 0x01F61 , 0x00342 },
{ 0x01F68 , 0x003A9 , 0x00313 },
{ 0x01F69 , 0x003A9 , 0x00314 },
{ 0x01F6A , 0x01F68 , 0x00300 },
{ 0x01F6B , 0x01F69 , 0x00300 },
{ 0x01F6C , 0x01F68 , 0x00301 },
{ 0x01F6D , 0x01F69 , 0x00301 },
{ 0x01F6E , 0x01F68 , 0x00342 },
{ 0x01F6F , 0x01F69 , 0x00342 },
{ 0x01F70 , 0x003B1 , 0x00300 },
{ 0x01F72 , 0x003B5 , 0x00300 },
{ 0x01F74 , 0x003B7 , 0x00300 },
{ 0x01F76 , 0x003B9 , 0x00300 },
{ 0x01F78 , 0x003BF , 0x00300 },
{ 0x01F7A , 0x003C5 , 0x00300 },
{ 0x01F7C , 0x003C9 , 0x00300 },
{ 0x01F80 , 0x01F00 , 0x00345 },
{ 0x01F81 , 0x01F01 , 0x00345 },
{ 0x01F82 , 0x01F02 , 0x00345 },
{ 0x01F83 , 0x01F03 , 0x00345 },
{ 0x01F84 , 0x01F04 , 0x00345 },
{ 0x01F85 , 0x01F05 , 0x00345 },
{ 0x01F86 , 0x01F06 , 0x00345 },
{ 0x01F87 , 0x01F07 , 0x00345 },
{ 0x01F88 , 0x01F08 , 0x00345 },
{ 0x01F89 , 0x01F09 , 0x00345 },
{ 0x01F8A , 0x01F0A , 0x00345 },
{ 0x01F8B , 0x01F0B , 0x00345 },
{ 0x01F8C , 0x01F0C , 0x00345 },
{ 0x01F8D , 0x01F0D , 0x00345 },
{ 0x01F8E , 0x01F0E , 0x00345 },
{ 0x01F8F , 0x01F0F , 0x00345 },
{ 0x01F90 , 0x01F20 , 0x00345 },
{ 0x01F91 , 0x01F21 , 0x00345 },
{ 0x01F92 , 0x01F22 , 0x00345 },
{ 0x01F93 , 0x01F23 , 0x00345 },
{ 0x01F94 , 0x01F24 , 0x00345 },
{ 0x01F95 , 0x01F25 , 0x00345 },
{ 0x01F96 , 0x01F26 , 0x00345 },
{ 0x01F97 , 0x01F27 , 0x00345 },
{ 0x01F98 , 0x01F28 , 0x00345 },
{ 0x01F99 , 0x01F29 , 0x00345 },
{ 0x01F9A , 0x01F2A , 0x00345 },
{ 0x01F9B , 0x01F2B , 0x00345 },
{ 0x01F9C , 0x01F2C , 0x00345 },
{ 0x01F9D , 0x01F2D , 0x00345 },
{ 0x01F9E , 0x01F2E , 0x00345 },
{ 0x01F9F , 0x01F2F , 0x00345 },
{ 0x01FA0 , 0x01F60 , 0x00345 },
{ 0x01FA1 , 0x01F61 , 0x00345 },
{ 0x01FA2 , 0x01F62 , 0x00345 },
{ 0x01FA3 , 0x01F63 , 0x00345 },
{ 0x01FA4 , 0x01F64 , 0x00345 },
{ 0x01FA5 , 0x01F65 , 0x00345 },
{ 0x01FA6 , 0x01F66 , 0x00345 },
{ 0x01FA7 , 0x01F67 , 0x00345 },
{ 0x01FA8 , 0x01F68 , 0x00345 },
{ 0x01FA9 , 0x01F69 , 0x00345 },
{ 0x01FAA , 0x01F6A , 0x00345 },
{ 0x01FAB , 0x01F6B , 0x00345 },
{ 0x01FAC , 0x01F6C , 0x00345 },
{ 0x01FAD , 0x01F6D , 0x00345 },
{ 0x01FAE , 0x01F6E , 0x00345 },
{ 0x01FAF , 0x01F6F , 0x00345 },
{ 0x01FB0 , 0x003B1 , 0x00306 },
{ 0x01FB1 , 0x003B1 , 0x00304 },
{ 0x01FB2 , 0x01F70 , 0x00345 },
{ 0x01FB3 , 0x003B1 , 0x00345 },
{ 0x01FB4 , 0x003AC , 0x00345 },
{ 0x01FB6 , 0x003B1 , 0x00342 },
{ 0x01FB7 , 0x01FB6 , 0x00345 },
{ 0x01FB8 , 0x00391 , 0x00306 },
{ 0x01FB9 , 0x00391 , 0x00304 },
{ 0x01FBA , 0x00391 , 0x00300 },
{ 0x01FBC , 0x00391 , 0x00345 },
{ 0x01FC1 , 0x000A8 , 0x00342 },
{ 0x01FC2 , 0x01F74 , 0x00345 },
{ 0x01FC3 , 0x003B7 , 0x00345 },
{ 0x01FC4 , 0x003AE , 0x00345 },
{ 0x01FC6 , 0x003B7 , 0x00342 },
{ 0x01FC7 , 0x01FC6 , 0x00345 },
{ 0x01FC8 , 0x00395 , 0x00300 },
{ 0x01FCA , 0x00397 , 0x00300 },
{ 0x01FCC , 0x00397 , 0x00345 },
{ 0x01FCD , 0x01FBF , 0x00300 },
{ 0x01FCE , 0x01FBF , 0x00301 },
{ 0x01FCF , 0x01FBF , 0x00342 },
{ 0x01FD0 , 0x003B9 , 0x00306 },
{ 0x01FD1 , 0x003B9 , 0x00304 },
{ 0x01FD2 , 0x003CA , 0x00300 },
{ 0x01FD6 , 0x003B9 , 0x00342 },
{ 0x01FD7 , 0x003CA , 0x00342 },
{ 0x01FD8 , 0x00399 , 0x00306 },
{ 0x01FD9 , 0x00399 , 0x00304 },
{ 0x01FDA , 0x00399 , 0x00300 },
{ 0x01FDD , 0x01FFE , 0x00300 },
{ 0x01FDE , 0x01FFE , 0x00301 },
{ 0x01FDF , 0x01FFE , 0x00342 },
{ 0x01FE0 , 0x003C5 , 0x00306 },
{ 0x01FE1 , 0x003C5 , 0x00304 },
{ 0x01FE2 , 0x003CB , 0x00300 },
{ 0x01FE4 , 0x003C1 , 0x00313 },
{ 0x01FE5 , 0x003C1 , 0x00314 },
{ 0x01FE6 , 0x003C5 , 0x00342 },
{ 0x01FE7 , 0x003CB , 0x00342 },
{ 0x01FE8 , 0x003A5 , 0x00306 },
{ 0x01FE9 , 0x003A5 , 0x00304 },
{ 0x01FEA , 0x003A5 , 0x00300 },
{ 0x01FEC , 0x003A1 , 0x00314 },
{ 0x01FED , 0x000A8 , 0x00300 },
{ 0x01FF2 , 0x01F7C , 0x00345 },
{ 0x01FF3 , 0x003C9 , 0x00345 },
{ 0x01FF4 , 0x003CE , 0x00345 },
{ 0x01FF6 , 0x003C9 , 0x00342 },
{ 0x01FF7 , 0x01FF6 , 0x00345 },
{ 0x01FF8 , 0x0039F , 0x00300 },
{ 0x01FFA , 0x003A9 , 0x00300 },
{ 0x01FFC , 0x003A9 , 0x00345 },
{ 0x0219A , 0x02190 , 0x00338 },
{ 0x0219B , 0x02192 , 0x00338 },
{ 0x021AE , 0x02194 , 0x00338 },
{ 0x021CD , 0x021D0 , 0x00338 },
{ 0x021CE , 0x021D4 , 0x00338 },
{ 0x021CF , 0x021D2 , 0x00338 },
{ 0x02204 , 0x02203 , 0x00338 },
{ 0x02209 , 0x02208 , 0x00338 },
{ 0x0220C , 0x0220B , 0x00338 },
{ 0x02224 , 0x02223 , 0x00338 },
{ 0x02226 , 0x02225 , 0x00338 },
{ 0x02241 , 0x0223C , 0x00338 },
{ 0x02244 , 0x02243 , 0x00338 },
{ 0x02247 , 0x02245 , 0x00338 },
{ 0x02249 , 0x02248 , 0x00338 },
{ 0x02260 , 0x0003D , 0x00338 },
{ 0x02262 , 0x02261 , 0x00338 },
{ 0x0226D , 0x0224D , 0x00338 },
{ 0x0226E , 0x0003C , 0x00338 },
{ 0x0226F , 0x0003E , 0x00338 },
{ 0x02270 , 0x02264 , 0x00338 },
{ 0x02271 , 0x02265 , 0x00338 },
{ 0x02274 , 0x02272 , 0x00338 },
{ 0x02275 , 0x02273 , 0x00338 },
{ 0x02278 , 0x02276 , 0x00338 },
{ 0x02279 , 0x02277 , 0x00338 },
{ 0x02280 , 0x0227A , 0x00338 },
{ 0x02281 , 0x0227B , 0x00338 },
{ 0x02284 , 0x02282 , 0x00338 },
{ 0x02285 , 0x02283 , 0x00338 },
{ 0x02288 , 0x02286 , 0x00338 },
{ 0x02289 , 0x02287 , 0x00338 },
{ 0x022AC , 0x022A2 , 0x00338 },
{ 0x022AD , 0x022A8 , 0x00338 },
{ 0x022AE , 0x022A9 , 0x00338 },
{ 0x022AF , 0x022AB , 0x00338 },
{ 0x022E0 , 0x0227C , 0x00338 },
{ 0x022E1 , 0x0227D , 0x00338 },
{ 0x022E2 , 0x02291 , 0x00338 },
{ 0x022E3 , 0x02292 , 0x00338 },
{ 0x022EA , 0x022B2 , 0x00338 },
{ 0x022EB , 0x022B3 , 0x00338 },
{ 0x022EC , 0x022B4 , 0x00338 },
{ 0x022ED , 0x022B5 , 0x00338 },
{ 0x0304C , 0x0304B , 0x03099 },
{ 0x0304E , 0x0304D , 0x03099 },
{ 0x03050 , 0x0304F , 0x03099 },
{ 0x03052 , 0x03051 , 0x03099 },
{ 0x03054 , 0x03053 , 0x03099 },
{ 0x03056 , 0x03055 , 0x03099 },
{ 0x03058 , 0x03057 , 0x03099 },
{ 0x0305A , 0x03059 , 0x03099 },
{ 0x0305C , 0x0305B , 0x03099 },
{ 0x0305E , 0x0305D , 0x03099 },
{ 0x03060 , 0x0305F , 0x03099 },
{ 0x03062 , 0x03061 , 0x03099 },
{ 0x03065 , 0x03064 , 0x03099 },
{ 0x03067 , 0x03066 , 0x03099 },
{ 0x03069 , 0x03068 , 0x03099 },
{ 0x03070 , 0x0306F , 0x03099 },
{ 0x03071 , 0x0306F , 0x0309A },
{ 0x03073 , 0x03072 , 0x03099 },
{ 0x03074 , 0x03072 , 0x0309A },
{ 0x03076 , 0x03075 , 0x03099 },
{ 0x03077 , 0x03075 , 0x0309A },
{ 0x03079 , 0x03078 , 0x03099 },
{ 0x0307A , 0x03078 , 0x0309A },
{ 0x0307C , 0x0307B , 0x03099 },
{ 0x0307D , 0x0307B , 0x0309A },
{ 0x03094 , 0x03046 , 0x03099 },
{ 0x0309E , 0x0309D , 0x03099 },
{ 0x030AC , 0x030AB , 0x03099 },
{ 0x030AE , 0x030AD , 0x03099 },
{ 0x030B0 , 0x030AF , 0x03099 },
{ 0x030B2 , 0x030B1 , 0x03099 },
{ 0x030B4 , 0x030B3 , 0x03099 },
{ 0x030B6 , 0x030B5 , 0x03099 },
{ 0x030B8 , 0x030B7 , 0x03099 },
{ 0x030BA , 0x030B9 , 0x03099 },
{ 0x030BC , 0x030BB , 0x03099 },
{ 0x030BE , 0x030BD , 0x03099 },
{ 0x030C0 , 0x030BF , 0x03099 },
{ 0x030C2 , 0x030C1 , 0x03099 },
{ 0x030C5 , 0x030C4 , 0x03099 },
{ 0x030C7 , 0x030C6 , 0x03099 },
{ 0x030C9 , 0x030C8 , 0x03099 },
{ 0x030D0 , 0x030CF , 0x03099 },
{ 0x030D1 , 0x030CF , 0x0309A },
{ 0x030D3 , 0x030D2 , 0x03099 },
{ 0x030D4 , 0x030D2 , 0x0309A },
{ 0x030D6 , 0x030D5 , 0x03099 },
{ 0x030D7 , 0x030D5 , 0x0309A },
{ 0x030D9 , 0x030D8 , 0x03099 },
{ 0x030DA , 0x030D8 , 0x0309A },
{ 0x030DC , 0x030DB , 0x03099 },
{ 0x030DD , 0x030DB , 0x0309A },
{ 0x030F4 , 0x030A6 , 0x03099 },
{ 0x030F7 , 0x030EF , 0x03099 },
{ 0x030F8 , 0x030F0 , 0x03099 },
{ 0x030F9 , 0x030F1 , 0x03099 },
{ 0x030FA , 0x030F2 , 0x03099 },
{ 0x030FE , 0x030FD , 0x03099 },
{ 0x1109A , 0x11099 , 0x110BA },
{ 0x1109C , 0x1109B , 0x110BA },
{ 0x110AB , 0x110A5 , 0x110BA },
};
#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */

View File

@ -38,7 +38,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_string_sprintf.c 189435 2009-03-
* here. This is only used to format error messages, so doesn't
* require any floating-point support or field-width handling.
*/
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <stdio.h>
#include "archive_string.h"
@ -129,7 +131,7 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
break;
case 'c':
s = va_arg(ap, int);
archive_strappend_char(as, s);
archive_strappend_char(as, (char)s);
break;
case 'd':
switch(long_flag) {
@ -146,7 +148,9 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
pw = va_arg(ap, wchar_t *);
if (pw == NULL)
pw = L"(null)";
archive_string_append_from_wcs(as, pw, wcslen(pw));
if (archive_string_append_from_wcs(as, pw,
wcslen(pw)) != 0 && errno == ENOMEM)
__archive_errx(1, "Out of memory");
break;
default:
p2 = va_arg(ap, char *);
@ -160,7 +164,9 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
pw = va_arg(ap, wchar_t *);
if (pw == NULL)
pw = L"(null)";
archive_string_append_from_wcs(as, pw, wcslen(pw));
if (archive_string_append_from_wcs(as, pw,
wcslen(pw)) != 0 && errno == ENOMEM)
__archive_errx(1, "Out of memory");
break;
case 'o': case 'u': case 'x': case 'X':
/* Common handling for unsigned integer formats. */

View File

@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_util.3 201098 2009-12-28 02:58:14Z kientzle $
.\" $FreeBSD$
.\"
.Dd January 8, 2005
.Dd February 2, 2012
.Dt ARCHIVE_UTIL 3
.Os
.Sh NAME
@ -43,6 +43,8 @@
.Nm archive_position ,
.Nm archive_set_error
.Nd libarchive utility functions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Ft void

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2009,2010 Michihiro NAKAJIMA
* Copyright (c) 2009-2012 Michihiro NAKAJIMA
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
@ -50,6 +50,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1
#include "archive_private.h"
#include "archive_string.h"
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
/* Generic initialization of 'struct archive' objects. */
int
__archive_clean(struct archive *a)
@ -239,12 +243,13 @@ __archive_mktemp(const char *tmpdir)
errno = ENOMEM;
goto exit_tmpfile;
}
GetTempPathW(l, tmp);
GetTempPathW((DWORD)l, tmp);
archive_wstrcpy(&temp_name, tmp);
free(tmp);
} else {
archive_wstring_append_from_mbs(&temp_name, tmpdir,
strlen(tmpdir));
if (archive_wstring_append_from_mbs(&temp_name, tmpdir,
strlen(tmpdir)) < 0)
goto exit_tmpfile;
if (temp_name.s[temp_name.length-1] != L'/')
archive_wstrappend_wchar(&temp_name, L'/');
}
@ -292,7 +297,8 @@ __archive_mktemp(const char *tmpdir)
/* Generate a random file name through CryptGenRandom(). */
p = xp;
if (!CryptGenRandom(hProv, (ep - p)*sizeof(wchar_t), (BYTE*)p)) {
if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t),
(BYTE*)p)) {
la_dosmaperr(GetLastError());
goto exit_tmpfile;
}
@ -384,6 +390,7 @@ __archive_mktemp(const char *tmpdir)
fd = mkstemp(temp_name.s);
if (fd < 0)
goto exit_tmpfile;
__archive_ensure_cloexec_flag(fd);
unlink(temp_name.s);
exit_tmpfile:
archive_string_free(&temp_name);
@ -437,7 +444,8 @@ __archive_mktemp(const char *tmpdir)
archive_strcat(&temp_name, "XXXXXXXXXX");
ep = temp_name.s + archive_strlen(&temp_name);
fd = open("/dev/random", O_RDONLY);
fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
__archive_ensure_cloexec_flag(fd);
if (fd < 0)
seed = time(NULL);
else {
@ -451,10 +459,12 @@ __archive_mktemp(const char *tmpdir)
p = tp;
while (p < ep)
*p++ = num[((unsigned)rand_r(&seed)) % sizeof(num)];
fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR, 0600);
fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC,
0600);
} while (fd < 0 && errno == EEXIST);
if (fd < 0)
goto exit_tmpfile;
__archive_ensure_cloexec_flag(fd);
unlink(temp_name.s);
exit_tmpfile:
archive_string_free(&temp_name);
@ -463,3 +473,29 @@ exit_tmpfile:
#endif /* HAVE_MKSTEMP */
#endif /* !_WIN32 || __CYGWIN__ */
/*
* Set FD_CLOEXEC flag to a file descriptor if it is not set.
* We have to set the flag if the platform does not provide O_CLOEXEC
* or F_DUPFD_CLOEXEC flags.
*
* Note: This function is absolutely called after creating a new file
* descriptor even if the platform seemingly provides O_CLOEXEC or
* F_DUPFD_CLOEXEC macros because it is possible that the platform
* merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it.
*/
void
__archive_ensure_cloexec_flag(int fd)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
(void)fd; /* UNSED */
#else
int flags;
if (fd >= 0) {
flags = fcntl(fd, F_GETFD);
if (flags != -1 && (flags & FD_CLOEXEC) == 0)
fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
}
#endif
}

View File

@ -66,9 +66,18 @@ archive_read_close(struct archive *a)
return ((a->vtable->archive_close)(a));
}
int
archive_write_fail(struct archive *a)
{
a->state = ARCHIVE_STATE_FATAL;
return a->state;
}
int
archive_write_free(struct archive *a)
{
if (a == NULL)
return (ARCHIVE_OK);
return ((a->vtable->archive_free)(a));
}
@ -77,13 +86,15 @@ archive_write_free(struct archive *a)
int
archive_write_finish(struct archive *a)
{
return ((a->vtable->archive_free)(a));
return archive_write_free(a);
}
#endif
int
archive_read_free(struct archive *a)
{
if (a == NULL)
return (ARCHIVE_OK);
return ((a->vtable->archive_free)(a));
}
@ -92,7 +103,7 @@ archive_read_free(struct archive *a)
int
archive_read_finish(struct archive *a)
{
return ((a->vtable->archive_free)(a));
return archive_read_free(a);
}
#endif

View File

@ -48,6 +48,7 @@
#include "archive_platform.h"
#include "archive_private.h"
#include "archive_entry.h"
#include <ctype.h>
#include <errno.h>
#include <stddef.h>
@ -64,6 +65,23 @@
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
#if defined(__LA_LSEEK_NEEDED)
static BOOL SetFilePointerEx_perso(HANDLE hFile,
LARGE_INTEGER liDistanceToMove,
PLARGE_INTEGER lpNewFilePointer,
DWORD dwMoveMethod)
{
LARGE_INTEGER li;
li.QuadPart = liDistanceToMove.QuadPart;
li.LowPart = SetFilePointer(
hFile, li.LowPart, &li.HighPart, dwMoveMethod);
if(lpNewFilePointer) {
lpNewFilePointer->QuadPart = li.QuadPart;
}
return li.LowPart != -1 || GetLastError() == NO_ERROR;
}
#endif
struct ustat {
int64_t st_atime;
uint32_t st_atime_nsec;
@ -92,7 +110,7 @@ getino(struct ustat *ub)
ULARGE_INTEGER ino64;
ino64.QuadPart = ub->st_ino;
/* I don't know this hashing is correct way */
return (ino64.LowPart ^ (ino64.LowPart >> INOSIZE));
return ((ino_t)(ino64.LowPart ^ (ino64.LowPart >> INOSIZE)));
}
/*
@ -136,7 +154,7 @@ __la_win_permissive_name_w(const wchar_t *wname)
if (l == 0)
return (NULL);
/* NOTE: GetFullPathNameW has a bug that if the length of the file
* name is just one that return imcomplete buffer size. Thus, we
* name is just 1 then it returns incomplete buffer size. Thus, we
* have to add three to the size to allocate a sufficient buffer
* size for the full-pathname of the file name. */
l += 3;
@ -234,6 +252,40 @@ la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
return (handle);
}
#if defined(__LA_LSEEK_NEEDED)
__int64
__la_lseek(int fd, __int64 offset, int whence)
{
LARGE_INTEGER distance;
LARGE_INTEGER newpointer;
HANDLE handle;
if (fd < 0) {
errno = EBADF;
return (-1);
}
handle = (HANDLE)_get_osfhandle(fd);
if (GetFileType(handle) != FILE_TYPE_DISK) {
errno = EBADF;
return (-1);
}
distance.QuadPart = offset;
if (!SetFilePointerEx_perso(handle, distance, &newpointer, whence)) {
DWORD lasterr;
lasterr = GetLastError();
if (lasterr == ERROR_BROKEN_PIPE)
return (0);
if (lasterr == ERROR_ACCESS_DENIED)
errno = EBADF;
else
la_dosmaperr(lasterr);
return (-1);
}
return (newpointer.QuadPart);
}
#endif
/* This can exceed MAX_PATH limitation. */
int
__la_open(const char *path, int flags, ...)
@ -373,7 +425,7 @@ __la_read(int fd, void *buf, size_t nbytes)
/* Convert Windows FILETIME to UTC */
__inline static void
fileTimeToUTC(const FILETIME *filetime, time_t *time, long *ns)
fileTimeToUTC(const FILETIME *filetime, time_t *t, long *ns)
{
ULARGE_INTEGER utc;
@ -381,10 +433,10 @@ fileTimeToUTC(const FILETIME *filetime, time_t *time, long *ns)
utc.LowPart = filetime->dwLowDateTime;
if (utc.QuadPart >= EPOC_TIME) {
utc.QuadPart -= EPOC_TIME;
*time = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */
*t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */
*ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
} else {
*time = 0;
*t = 0;
*ns = 0;
}
}
@ -407,7 +459,7 @@ __hstat(HANDLE handle, struct ustat *st)
ULARGE_INTEGER ino64;
DWORD ftype;
mode_t mode;
time_t time;
time_t t;
long ns;
switch (ftype = GetFileType(handle)) {
@ -464,14 +516,14 @@ __hstat(HANDLE handle, struct ustat *st)
mode |= S_IFREG;
st->st_mode = mode;
fileTimeToUTC(&info.ftLastAccessTime, &time, &ns);
st->st_atime = time;
fileTimeToUTC(&info.ftLastAccessTime, &t, &ns);
st->st_atime = t;
st->st_atime_nsec = ns;
fileTimeToUTC(&info.ftLastWriteTime, &time, &ns);
st->st_mtime = time;
fileTimeToUTC(&info.ftLastWriteTime, &t, &ns);
st->st_mtime = t;
st->st_mtime_nsec = ns;
fileTimeToUTC(&info.ftCreationTime, &time, &ns);
st->st_ctime = time;
fileTimeToUTC(&info.ftCreationTime, &t, &ns);
st->st_ctime = t;
st->st_ctime_nsec = ns;
st->st_size =
((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1))
@ -507,7 +559,7 @@ copy_stat(struct stat *st, struct ustat *us)
st->st_ino = getino(us);
st->st_mode = us->st_mode;
st->st_nlink = us->st_nlink;
st->st_size = us->st_size;
st->st_size = (off_t)us->st_size;
st->st_uid = us->st_uid;
st->st_dev = us->st_dev;
st->st_rdev = us->st_rdev;
@ -581,35 +633,22 @@ __la_stat(const char *path, struct stat *st)
* This waitpid is limited implementation.
*/
pid_t
__la_waitpid(pid_t wpid, int *status, int option)
__la_waitpid(HANDLE child, int *status, int option)
{
HANDLE child;
DWORD cs, ret;
DWORD cs;
(void)option;/* UNUSED */
*status = 0;
child = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, wpid);
if (child == NULL) {
la_dosmaperr(GetLastError());
return (-1);
}
ret = WaitForSingleObject(child, INFINITE);
if (ret == WAIT_FAILED) {
CloseHandle(child);
la_dosmaperr(GetLastError());
return (-1);
}
do {
if (GetExitCodeProcess(child, &cs) == 0) {
CloseHandle(child);
la_dosmaperr(GetLastError());
*status = 0;
return (-1);
}
if (cs == STILL_ACTIVE)
*status = 0x100;
else
} while (cs == STILL_ACTIVE);
*status = (int)(cs & 0xff);
CloseHandle(child);
return (wpid);
return (0);
}
ssize_t
@ -639,6 +678,113 @@ __la_write(int fd, const void *buf, size_t nbytes)
return (bytes_written);
}
/*
* Replace the Windows path separator '\' with '/'.
*/
static int
replace_pathseparator(struct archive_wstring *ws, const wchar_t *wp)
{
wchar_t *w;
size_t path_length;
if (wp == NULL)
return(0);
if (wcschr(wp, L'\\') == NULL)
return(0);
path_length = wcslen(wp);
if (archive_wstring_ensure(ws, path_length) == NULL)
return(-1);
archive_wstrncpy(ws, wp, path_length);
for (w = ws->s; *w; w++) {
if (*w == L'\\')
*w = L'/';
}
return(1);
}
static int
fix_pathseparator(struct archive_entry *entry)
{
struct archive_wstring ws;
const wchar_t *wp;
int ret = ARCHIVE_OK;
archive_string_init(&ws);
wp = archive_entry_pathname_w(entry);
switch (replace_pathseparator(&ws, wp)) {
case 0: /* Not replaced. */
break;
case 1: /* Replaced. */
archive_entry_copy_pathname_w(entry, ws.s);
break;
default:
ret = ARCHIVE_FAILED;
}
wp = archive_entry_hardlink_w(entry);
switch (replace_pathseparator(&ws, wp)) {
case 0: /* Not replaced. */
break;
case 1: /* Replaced. */
archive_entry_copy_hardlink_w(entry, ws.s);
break;
default:
ret = ARCHIVE_FAILED;
}
wp = archive_entry_symlink_w(entry);
switch (replace_pathseparator(&ws, wp)) {
case 0: /* Not replaced. */
break;
case 1: /* Replaced. */
archive_entry_copy_symlink_w(entry, ws.s);
break;
default:
ret = ARCHIVE_FAILED;
}
archive_wstring_free(&ws);
return(ret);
}
struct archive_entry *
__la_win_entry_in_posix_pathseparator(struct archive_entry *entry)
{
struct archive_entry *entry_main;
const wchar_t *wp;
int has_backslash = 0;
int ret;
wp = archive_entry_pathname_w(entry);
if (wp != NULL && wcschr(wp, L'\\') != NULL)
has_backslash = 1;
if (!has_backslash) {
wp = archive_entry_hardlink_w(entry);
if (wp != NULL && wcschr(wp, L'\\') != NULL)
has_backslash = 1;
}
if (!has_backslash) {
wp = archive_entry_symlink_w(entry);
if (wp != NULL && wcschr(wp, L'\\') != NULL)
has_backslash = 1;
}
/*
* If there is no backslach chars, return the original.
*/
if (!has_backslash)
return (entry);
/* Copy entry so we can modify it as needed. */
entry_main = archive_entry_clone(entry);
if (entry_main == NULL)
return (NULL);
/* Replace the Windows path-separator '\' with '/'. */
ret = fix_pathseparator(entry_main);
if (ret < ARCHIVE_WARN) {
archive_entry_free(entry_main);
return (NULL);
}
return (entry_main);
}
/*
* The following function was modified from PostgreSQL sources and is
* subject to the copyright below.
@ -745,7 +891,7 @@ __la_dosmaperr(unsigned long e)
return;
}
for (i = 0; i < sizeof(doserrors); i++)
for (i = 0; i < (int)sizeof(doserrors); i++)
{
if (doserrors[i].winerr == e)
{

View File

@ -49,6 +49,9 @@
#define LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED
/* Start of configuration for native Win32 */
#ifndef MINGW_HAS_SECURE_API
#define MINGW_HAS_SECURE_API 1
#endif
#include <errno.h>
#define set_errno(val) ((errno)=val)
@ -71,10 +74,6 @@
#include <windows.h>
//#define EFTYPE 7
#if defined(_MSC_VER)
/* TODO: Fix the code, don't suppress the warnings. */
#pragma warning(disable:4244) /* 'conversion' conversion from 'type1' to 'type2', possible loss of data */
#endif
#if defined(__BORLANDC__)
#pragma warn -8068 /* Constant out of range in comparison. */
#pragma warn -8072 /* Suspicious pointer arithmetic. */
@ -94,14 +93,28 @@
#ifndef fileno
#define fileno _fileno
#endif
#ifdef fstat
#undef fstat
#endif
#define fstat __la_fstat
#if !defined(__BORLANDC__)
#ifdef lseek
#undef lseek
#endif
#define lseek _lseeki64
#else
#define lseek __la_lseek
#define __LA_LSEEK_NEEDED
#endif
#define lstat __la_stat
#define open __la_open
#define read __la_read
#if !defined(__BORLANDC__)
#define setmode _setmode
#endif
#ifdef stat
#undef stat
#endif
#define stat(path,stref) __la_stat(path,stref)
#if !defined(__BORLANDC__)
#define strdup _strdup
@ -245,10 +258,13 @@
/* Replacement POSIX function */
extern int __la_fstat(int fd, struct stat *st);
extern int __la_lstat(const char *path, struct stat *st);
#if defined(__LA_LSEEK_NEEDED)
extern __int64 __la_lseek(int fd, __int64 offset, int whence);
#endif
extern int __la_open(const char *path, int flags, ...);
extern ssize_t __la_read(int fd, void *buf, size_t nbytes);
extern int __la_stat(const char *path, struct stat *st);
extern pid_t __la_waitpid(pid_t wpid, int *status, int option);
extern pid_t __la_waitpid(HANDLE child, int *status, int option);
extern ssize_t __la_write(int fd, const void *buf, size_t nbytes);
#define _stat64i32(path, st) __la_stat(path, st)
@ -261,6 +277,30 @@ extern wchar_t *__la_win_permissive_name(const char *name);
extern wchar_t *__la_win_permissive_name_w(const wchar_t *wname);
extern void __la_dosmaperr(unsigned long e);
#define la_dosmaperr(e) __la_dosmaperr(e)
extern struct archive_entry *__la_win_entry_in_posix_pathseparator(
struct archive_entry *);
#if defined(HAVE_WCRTOMB) && defined(__BORLANDC__)
typedef int mbstate_t;
size_t wcrtomb(char *, wchar_t, mbstate_t *);
#endif
#if defined(_MSC_VER) && _MSC_VER < 1300
WINBASEAPI BOOL WINAPI GetVolumePathNameW(
LPCWSTR lpszFileName,
LPWSTR lpszVolumePathName,
DWORD cchBufferLength
);
# if _WIN32_WINNT < 0x0500 /* windows.h not providing 0x500 API */
typedef struct _FILE_ALLOCATED_RANGE_BUFFER {
LARGE_INTEGER FileOffset;
LARGE_INTEGER Length;
} FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER;
# define FSCTL_SET_SPARSE \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_WRITE_DATA)
# define FSCTL_QUERY_ALLOCATED_RANGES \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 51, METHOD_NEITHER, FILE_READ_DATA)
# endif
#endif
#endif /* LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED */

View File

@ -22,14 +22,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $
.\" $FreeBSD$
.\"
.Dd March 23, 2011
.Dd February 2, 2012
.Dt ARCHIVE_WRITE 3
.Os
.Sh NAME
.Nm archive_write
.Nd functions for creating archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
.Sh SYNOPSIS
.In archive.h
.Sh DESCRIPTION

View File

@ -232,6 +232,10 @@ __archive_write_filter(struct archive_write_filter *f,
int r;
if (length == 0)
return(ARCHIVE_OK);
if (f->write == NULL)
/* If unset, a fatal error has already ocuured, so this filter
* didn't open. We cannot write anything. */
return(ARCHIVE_FATAL);
r = (f->write)(f, buff, length);
f->bytes_written += length;
return (r);
@ -380,7 +384,7 @@ archive_write_client_write(struct archive_write_filter *f,
}
}
while ((size_t)remaining > state->buffer_size) {
while ((size_t)remaining >= state->buffer_size) {
/* Write out full blocks directly to client. */
bytes_written = (a->client_writer)(&a->archive,
a->client_data, buff, state->buffer_size);
@ -437,6 +441,8 @@ archive_write_client_close(struct archive_write_filter *f)
(*a->client_closer)(&a->archive, a->client_data);
free(state->buffer);
free(state);
/* Clear the close handler myself not to be called again. */
f->close = NULL;
a->client_data = NULL;
return (ret);
}
@ -623,7 +629,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
if (a->skip_file_set &&
archive_entry_dev_is_set(entry) &&
archive_entry_ino_is_set(entry) &&
archive_entry_dev(entry) == a->skip_file_dev &&
archive_entry_dev(entry) == (dev_t)a->skip_file_dev &&
archive_entry_ino64(entry) == a->skip_file_ino) {
archive_set_error(&a->archive, 0,
"Can't add archive to itself");

Some files were not shown because too many files have changed in this diff Show More