mirror of
https://github.com/reactos/CMake.git
synced 2024-12-02 00:26:18 +00:00
Merge topic 'update-libarchive'
d49176e9
libarchive: Avoid using isblankce8f117f
libarchive: Avoid declaration after statement in C codee0f725f8
libarchive: Fix use of ssize_t in archive_entry.hae4861ec
libarchive: Define __LA_DEPRECATED consistentlyfecb70dd
Update CMake pre-cached values for libarchive 3.3.0a59a7ee9
Merge branch 'upstream-LibArchive' into update-libarchivec206211a
LibArchive 2017-02-19 (100ee75a)cdce7c61
libarchive: Update script to get 3.3.0
This commit is contained in:
commit
33f636264a
@ -421,14 +421,15 @@ macro (CMAKE_BUILD_UTILITIES)
|
||||
if(NOT LIBLZMA_FOUND)
|
||||
message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBLZMA is ON but LibLZMA is not found!")
|
||||
endif()
|
||||
set(LZMA_INCLUDE_DIR ${LIBLZMA_INCLUDE_DIRS})
|
||||
set(LZMA_LIBRARY ${LIBLZMA_LIBRARIES})
|
||||
else()
|
||||
add_subdirectory(Utilities/cmliblzma)
|
||||
CMAKE_SET_TARGET_FOLDER(cmliblzma "Utilities/3rdParty")
|
||||
set(LZMA_INCLUDE_DIR
|
||||
set(LIBLZMA_HAS_AUTO_DECODER 1)
|
||||
set(LIBLZMA_HAS_EASY_ENCODER 1)
|
||||
set(LIBLZMA_HAS_LZMA_PRESET 1)
|
||||
set(LIBLZMA_INCLUDE_DIR
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmliblzma/liblzma/api")
|
||||
set(LZMA_LIBRARY cmliblzma)
|
||||
set(LIBLZMA_LIBRARY cmliblzma)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -449,13 +450,14 @@ macro (CMAKE_BUILD_UTILITIES)
|
||||
add_definitions(-DLIBARCHIVE_STATIC)
|
||||
set(ENABLE_NETTLE OFF CACHE INTERNAL "Enable use of Nettle")
|
||||
set(ENABLE_OPENSSL ${CMAKE_USE_OPENSSL} CACHE INTERNAL "Enable use of OpenSSL")
|
||||
set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system found LZMA library if found")
|
||||
set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system found ZLIB library if found")
|
||||
set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system found BZip2 library if found")
|
||||
set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system found libxml2 library if found")
|
||||
set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system found EXPAT library if found")
|
||||
set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system found PCREPOSIX library if found")
|
||||
set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system found LibGCC library if found")
|
||||
set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system LZMA library if found")
|
||||
set(ENABLE_LZO OFF CACHE INTERNAL "Enable the use of the system LZO library if found")
|
||||
set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system ZLIB library if found")
|
||||
set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system BZip2 library if found")
|
||||
set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system libxml2 library if found")
|
||||
set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system EXPAT library if found")
|
||||
set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system PCREPOSIX library if found")
|
||||
set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system LibGCC library if found")
|
||||
set(ENABLE_XATTR OFF CACHE INTERNAL "Enable extended attribute support")
|
||||
set(ENABLE_ACL OFF CACHE INTERNAL "Enable ACL support")
|
||||
set(ENABLE_ICONV OFF CACHE INTERNAL "Enable iconv support")
|
||||
|
@ -8,7 +8,7 @@ readonly name="LibArchive"
|
||||
readonly ownership="LibArchive Upstream <libarchive-discuss@googlegroups.com>"
|
||||
readonly subtree="Utilities/cmlibarchive"
|
||||
readonly repo="https://github.com/libarchive/libarchive.git"
|
||||
readonly tag="master"
|
||||
readonly tag="v3.3.0"
|
||||
readonly shortlog=false
|
||||
readonly paths="
|
||||
CMakeLists.txt
|
||||
|
@ -71,13 +71,15 @@ include(CTest)
|
||||
|
||||
OPTION(ENABLE_NETTLE "Enable use of Nettle" ON)
|
||||
OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
|
||||
OPTION(ENABLE_LZMA "Enable the use of the system found LZMA library if found" ON)
|
||||
OPTION(ENABLE_ZLIB "Enable the use of the system found ZLIB library if found" ON)
|
||||
OPTION(ENABLE_BZip2 "Enable the use of the system found BZip2 library if found" ON)
|
||||
OPTION(ENABLE_LIBXML2 "Enable the use of the system found libxml2 library if found" ON)
|
||||
OPTION(ENABLE_EXPAT "Enable the use of the system found EXPAT library if found" ON)
|
||||
OPTION(ENABLE_PCREPOSIX "Enable the use of the system found PCREPOSIX library if found" ON)
|
||||
OPTION(ENABLE_LibGCC "Enable the use of the system found LibGCC library if found" ON)
|
||||
OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF)
|
||||
OPTION(ENABLE_LZMA "Enable the use of the system LZMA library if found" ON)
|
||||
|
||||
OPTION(ENABLE_ZLIB "Enable the use of the system ZLIB library if found" ON)
|
||||
OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON)
|
||||
OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON)
|
||||
OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON)
|
||||
OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON)
|
||||
OPTION(ENABLE_LibGCC "Enable the use of the system LibGCC library if found" ON)
|
||||
# CNG is used for encrypt/decrypt Zip archives on Windows.
|
||||
OPTION(ENABLE_CNG "Enable the use of CNG(Crypto Next Generation)" ON)
|
||||
|
||||
@ -107,7 +109,7 @@ INCLUDE(CheckHeaderDirent)
|
||||
INCLUDE(CheckIncludeFile)
|
||||
INCLUDE(CheckIncludeFiles)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
INCLUDE(CheckStructMember)
|
||||
INCLUDE(CheckStructHasMember)
|
||||
INCLUDE(CheckSymbolExists)
|
||||
INCLUDE(CheckTypeExists)
|
||||
INCLUDE(CheckTypeSize)
|
||||
@ -285,21 +287,20 @@ MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES)
|
||||
# Find LZMA
|
||||
#
|
||||
IF(ENABLE_LZMA)
|
||||
FIND_PACKAGE(LZMA)
|
||||
FIND_PACKAGE(LibLZMA)
|
||||
ELSE()
|
||||
SET(LZMA_FOUND FALSE) # Override cached value
|
||||
SET(LZMADEC_FOUND FALSE) # Override cached value
|
||||
SET(LIBZMA_FOUND FALSE) # Override cached value
|
||||
ENDIF()
|
||||
|
||||
IF(LZMA_FOUND)
|
||||
IF(LIBLZMA_FOUND)
|
||||
SET(HAVE_LIBLZMA 1)
|
||||
SET(HAVE_LZMA_H 1)
|
||||
INCLUDE_DIRECTORIES(${LZMA_INCLUDE_DIR})
|
||||
LIST(APPEND ADDITIONAL_LIBS ${LZMA_LIBRARIES})
|
||||
INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS})
|
||||
LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES})
|
||||
IF(CMAKE_USE_SYSTEM_LIBLZMA)
|
||||
# Test if a macro is needed for the library.
|
||||
TRY_MACRO_FOR_LIBRARY(
|
||||
"${LZMA_INCLUDE_DIR}" "${LZMA_LIBRARIES}"
|
||||
"${LIBLZMA_INCLUDE_DIRS}" "${LIBLZMA_LIBRARIES}"
|
||||
COMPILES
|
||||
"#include <lzma.h>\nint main() {return (int)lzma_version_number(); }"
|
||||
"WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC")
|
||||
@ -309,27 +310,26 @@ IF(LZMA_FOUND)
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-DLZMA_API_STATIC)
|
||||
ENDIF()
|
||||
ELSEIF(LZMADEC_FOUND)
|
||||
SET(HAVE_LIBLZMADEC 1)
|
||||
SET(HAVE_LZMADEC_H 1)
|
||||
INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR})
|
||||
LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES})
|
||||
ELSE(LZMA_FOUND)
|
||||
ELSE(LIBLZMA_FOUND)
|
||||
# LZMA not found and will not be used.
|
||||
ENDIF(LZMA_FOUND)
|
||||
ENDIF(LIBLZMA_FOUND)
|
||||
IF(0) # CMake does not need LZO2 support in libarchive
|
||||
#
|
||||
# Find LZO2
|
||||
#
|
||||
IF (LZO2_INCLUDE_DIR)
|
||||
# Already in cache, be silent
|
||||
SET(LZO2_FIND_QUIETLY TRUE)
|
||||
ENDIF (LZO2_INCLUDE_DIR)
|
||||
IF(ENABLE_LZO)
|
||||
IF (LZO2_INCLUDE_DIR)
|
||||
# Already in cache, be silent
|
||||
SET(LZO2_FIND_QUIETLY TRUE)
|
||||
ENDIF (LZO2_INCLUDE_DIR)
|
||||
|
||||
FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h)
|
||||
FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2)
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
|
||||
FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h)
|
||||
FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2)
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR)
|
||||
ELSE(ENABLE_LZO)
|
||||
SET(LIBZMA_FOUND FALSE) # Override cached value
|
||||
ENDIF(ENABLE_LZO)
|
||||
IF(LZO2_FOUND)
|
||||
SET(HAVE_LIBLZO2 1)
|
||||
SET(HAVE_LZO_LZOCONF_H 1)
|
||||
@ -459,7 +459,7 @@ IF(ENABLE_CNG)
|
||||
ELSE(ENABLE_CNG)
|
||||
UNSET(HAVE_BCRYPT_H CACHE)
|
||||
ENDIF(ENABLE_CNG)
|
||||
# Following files need windwos.h, so we should test it after windows.h test.
|
||||
# Following files need windows.h, so we should test it after windows.h test.
|
||||
LA_CHECK_INCLUDE_FILE("wincrypt.h" HAVE_WINCRYPT_H)
|
||||
LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H)
|
||||
|
||||
@ -1005,6 +1005,14 @@ CHECK_FUNCTION_EXISTS(wmemmove HAVE_WMEMMOVE)
|
||||
|
||||
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
|
||||
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct vfsconf v; return sizeof(v);}"
|
||||
HAVE_STRUCT_VFSCONF)
|
||||
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct xvfsconf v; return sizeof(v);}"
|
||||
HAVE_STRUCT_XVFSCONF)
|
||||
|
||||
# Make sure we have the POSIX version of readdir_r, not the
|
||||
# older 2-argument version.
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
@ -1030,6 +1038,10 @@ CHECK_C_SOURCE_COMPILES(
|
||||
"#include <sys/sysmacros.h>\nint main() { return major(256); }"
|
||||
MAJOR_IN_SYSMACROS)
|
||||
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"#include <lzma.h>\n#if LZMA_VERSION < 50020000\n#error unsupported\n#endif\nint main(void){lzma_stream_encoder_mt(0, 0); return 0;}"
|
||||
HAVE_LZMA_STREAM_ENCODER_MT)
|
||||
|
||||
IF(HAVE_STRERROR_R)
|
||||
SET(HAVE_DECL_STRERROR_R 1)
|
||||
ENDIF(HAVE_STRERROR_R)
|
||||
@ -1063,47 +1075,47 @@ CHECK_SYMBOL_EXISTS(SSIZE_MAX "limits.h" HAVE_DECL_SSIZE_MAX)
|
||||
# Check struct members
|
||||
#
|
||||
# Check for tm_gmtoff in struct tm
|
||||
CHECK_STRUCT_MEMBER("struct tm" tm_gmtoff
|
||||
CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff
|
||||
"time.h" HAVE_STRUCT_TM_TM_GMTOFF)
|
||||
CHECK_STRUCT_MEMBER("struct tm" __tm_gmtoff
|
||||
CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff
|
||||
"time.h" HAVE_STRUCT_TM___TM_GMTOFF)
|
||||
|
||||
# Check for f_namemax in struct statfs
|
||||
CHECK_STRUCT_MEMBER("struct statfs" f_namemax
|
||||
CHECK_STRUCT_HAS_MEMBER("struct statfs" f_namemax
|
||||
"sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_NAMEMAX)
|
||||
|
||||
# Check for birthtime in struct stat
|
||||
CHECK_STRUCT_MEMBER("struct stat" st_birthtime
|
||||
CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime
|
||||
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIME)
|
||||
|
||||
# Check for high-resolution timestamps in struct stat
|
||||
CHECK_STRUCT_MEMBER("struct stat" st_birthtimespec.tv_nsec
|
||||
CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtimespec.tv_nsec
|
||||
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
|
||||
CHECK_STRUCT_MEMBER("struct stat" st_mtimespec.tv_nsec
|
||||
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec
|
||||
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
|
||||
CHECK_STRUCT_MEMBER("struct stat" st_mtim.tv_nsec
|
||||
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec
|
||||
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
|
||||
CHECK_STRUCT_MEMBER("struct stat" st_mtime_n
|
||||
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_n
|
||||
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_N)
|
||||
CHECK_STRUCT_MEMBER("struct stat" st_umtime
|
||||
CHECK_STRUCT_HAS_MEMBER("struct stat" st_umtime
|
||||
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_UMTIME)
|
||||
CHECK_STRUCT_MEMBER("struct stat" st_mtime_usec
|
||||
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_usec
|
||||
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_USEC)
|
||||
# Check for block size support in struct stat
|
||||
CHECK_STRUCT_MEMBER("struct stat" st_blksize
|
||||
CHECK_STRUCT_HAS_MEMBER("struct stat" st_blksize
|
||||
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BLKSIZE)
|
||||
# Check for st_flags in struct stat (BSD fflags)
|
||||
CHECK_STRUCT_MEMBER("struct stat" st_flags
|
||||
CHECK_STRUCT_HAS_MEMBER("struct stat" st_flags
|
||||
"sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_FLAGS)
|
||||
|
||||
IF(HAVE_SYS_STATVFS_H)
|
||||
CHECK_STRUCT_MEMBER("struct statvfs" f_iosize
|
||||
CHECK_STRUCT_HAS_MEMBER("struct statvfs" f_iosize
|
||||
"sys/types.h;sys/statvfs.h" HAVE_STRUCT_STATVFS_F_IOSIZE)
|
||||
ENDIF()
|
||||
|
||||
#
|
||||
#
|
||||
CHECK_STRUCT_MEMBER("struct tm" tm_sec
|
||||
CHECK_STRUCT_HAS_MEMBER("struct tm" tm_sec
|
||||
"sys/types.h;sys/time.h;time.h" TIME_WITH_SYS_TIME)
|
||||
|
||||
#
|
||||
@ -1323,16 +1335,36 @@ IF(ENABLE_ACL)
|
||||
# test for specific permissions in a permset.) Linux uses the obvious
|
||||
# name, FreeBSD adds _np to mark it as "non-Posix extension."
|
||||
# Test for both as a double-check that we really have POSIX-style ACL support.
|
||||
CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP)
|
||||
CHECK_FUNCTION_EXISTS(acl_get_perm HAVE_ACL_GET_PERM)
|
||||
CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP)
|
||||
CHECK_FUNCTION_EXISTS(acl_get_link HAVE_ACL_GET_LINK)
|
||||
CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP)
|
||||
CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP)
|
||||
CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP)
|
||||
CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "${INCLUDES}" HAVE_ACL_TYPE_NFS4)
|
||||
|
||||
# MacOS has an acl.h that isn't POSIX. It can be detected by
|
||||
# checking for ACL_USER
|
||||
CHECK_SYMBOL_EXISTS(ACL_USER "${INCLUDES}" HAVE_ACL_USER)
|
||||
CHECK_C_SOURCE_COMPILES("#include <sys/types.h>
|
||||
#include <sys/acl.h>
|
||||
int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED)
|
||||
|
||||
# Solaris and derivates ACLs
|
||||
CHECK_LIBRARY_EXISTS(sec "acl_get" "" HAVE_LIBSEC)
|
||||
IF(HAVE_LIBSEC)
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "sec")
|
||||
FIND_LIBRARY(SEC_LIBRARY NAMES sec)
|
||||
LIST(APPEND ADDITIONAL_LIBS ${SEC_LIBRARY})
|
||||
ENDIF(HAVE_LIBSEC)
|
||||
#
|
||||
CHECK_TYPE_EXISTS(aclent_t "${INCLUDES}" HAVE_ACLENT_T)
|
||||
CHECK_TYPE_EXISTS(ace_t "${INCLUDES}" HAVE_ACE_T)
|
||||
CHECK_FUNCTION_EXISTS(acl_get HAVE_FACL_GET)
|
||||
CHECK_FUNCTION_EXISTS(facl_get HAVE_FACL_GET)
|
||||
CHECK_FUNCTION_EXISTS(acl_set HAVE_FACL_SET)
|
||||
CHECK_FUNCTION_EXISTS(facl_set HAVE_FACL_SET)
|
||||
ELSE(ENABLE_ACL)
|
||||
# If someone runs cmake, then disables ACL support, we need
|
||||
# to forcibly override the cached values for these.
|
||||
@ -1347,7 +1379,15 @@ ELSE(ENABLE_ACL)
|
||||
SET(HAVE_ACL_SET_FD FALSE)
|
||||
SET(HAVE_ACL_SET_FD_NP FALSE)
|
||||
SET(HAVE_ACL_SET_FILE FALSE)
|
||||
SET(HAVE_ACL_TYPE_NFS4 FALSE)
|
||||
SET(HAVE_ACL_USER FALSE)
|
||||
SET(HAVE_ACL_TYPE_EXTENDED FALSE)
|
||||
SET(HAVE_ACL_GET FALSE)
|
||||
SET(HAVE_ACLENT_T FALSE)
|
||||
SET(HAVE_ACE_T FALSE)
|
||||
SET(HAVE_FACL_GET FALSE)
|
||||
SET(HAVE_ACL_SET FALSE)
|
||||
SET(HAVE_FACL_SET FALSE)
|
||||
ENDIF(ENABLE_ACL)
|
||||
|
||||
#
|
||||
|
@ -1,43 +0,0 @@
|
||||
# - Check if the given struct or class has the specified member variable
|
||||
# CHECK_STRUCT_MEMBER (STRUCT MEMBER HEADER VARIABLE)
|
||||
#
|
||||
# STRUCT - the name of the struct or class you are interested in
|
||||
# MEMBER - the member which existence you want to check
|
||||
# HEADER - the header(s) where the prototype should be declared
|
||||
# VARIABLE - variable to store the result
|
||||
#
|
||||
# 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
|
||||
|
||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
|
||||
MACRO (CHECK_STRUCT_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
|
||||
SET(_INCLUDE_FILES)
|
||||
FOREACH (it ${_HEADER})
|
||||
SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
|
||||
ENDFOREACH (it)
|
||||
|
||||
SET(_CHECK_STRUCT_MEMBER_SOURCE_CODE "
|
||||
${_INCLUDE_FILES}
|
||||
int main()
|
||||
{
|
||||
static ${_STRUCT} tmp;
|
||||
if (sizeof(tmp.${_MEMBER}))
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
")
|
||||
CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
|
||||
|
||||
ENDMACRO (CHECK_STRUCT_MEMBER)
|
||||
|
@ -1,48 +0,0 @@
|
||||
# - Find lzma and lzmadec
|
||||
# Find the native LZMA includes and library
|
||||
#
|
||||
# LZMA_INCLUDE_DIR - where to find lzma.h, etc.
|
||||
# LZMA_LIBRARIES - List of libraries when using liblzma.
|
||||
# LZMA_FOUND - True if liblzma found.
|
||||
# LZMADEC_INCLUDE_DIR - where to find lzmadec.h, etc.
|
||||
# LZMADEC_LIBRARIES - List of libraries when using liblzmadec.
|
||||
# LZMADEC_FOUND - True if liblzmadec found.
|
||||
|
||||
IF (LZMA_INCLUDE_DIR)
|
||||
# Already in cache, be silent
|
||||
SET(LZMA_FIND_QUIETLY TRUE)
|
||||
ENDIF (LZMA_INCLUDE_DIR)
|
||||
|
||||
FIND_PATH(LZMA_INCLUDE_DIR lzma.h)
|
||||
FIND_LIBRARY(LZMA_LIBRARY NAMES lzma liblzma)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set LZMA_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMA DEFAULT_MSG LZMA_LIBRARY LZMA_INCLUDE_DIR)
|
||||
|
||||
IF(LZMA_FOUND)
|
||||
SET( LZMA_LIBRARIES ${LZMA_LIBRARY} )
|
||||
ELSE(LZMA_FOUND)
|
||||
SET( LZMA_LIBRARIES )
|
||||
|
||||
IF (LZMADEC_INCLUDE_DIR)
|
||||
# Already in cache, be silent
|
||||
SET(LZMADEC_FIND_QUIETLY TRUE)
|
||||
ENDIF (LZMADEC_INCLUDE_DIR)
|
||||
|
||||
FIND_PATH(LZMADEC_INCLUDE_DIR lzmadec.h)
|
||||
FIND_LIBRARY(LZMADEC_LIBRARY NAMES lzmadec )
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set LZMADEC_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMADEC DEFAULT_MSG LZMADEC_LIBRARY
|
||||
LZMADEC_INCLUDE_DIR)
|
||||
|
||||
IF(LZMADEC_FOUND)
|
||||
SET( LZMADEC_LIBRARIES ${LZMADEC_LIBRARY} )
|
||||
ELSE(LZMADEC_FOUND)
|
||||
SET( LZMADEC_LIBRARIES )
|
||||
ENDIF(LZMADEC_FOUND)
|
||||
ENDIF(LZMA_FOUND)
|
@ -296,6 +296,9 @@ typedef uint64_t uintmax_t;
|
||||
/* Define to 1 if you have the `acl_create_entry' function. */
|
||||
#cmakedefine HAVE_ACL_CREATE_ENTRY 1
|
||||
|
||||
/* Define to 1 if you have the `acl_get_fd_np' function. */
|
||||
#cmakedefine HAVE_ACL_GET_FD_NP 1
|
||||
|
||||
/* Define to 1 if you have the `acl_get_link' function. */
|
||||
#cmakedefine HAVE_ACL_GET_LINK 1
|
||||
|
||||
@ -326,6 +329,12 @@ typedef uint64_t uintmax_t;
|
||||
/* Define to 1 if you have the `acl_set_file' function. */
|
||||
#cmakedefine HAVE_ACL_SET_FILE 1
|
||||
|
||||
/* True for FreeBSD with NFSv4 ACL support */
|
||||
#cmakedefine HAVE_ACL_TYPE_NFS4 1
|
||||
|
||||
/* True for MacOS ACL support */
|
||||
#cmakedefine HAVE_ACL_TYPE_EXTENDED 1
|
||||
|
||||
/* True for systems with POSIX ACL support */
|
||||
#cmakedefine HAVE_ACL_USER 1
|
||||
|
||||
@ -727,6 +736,9 @@ 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 a working `lzma_stream_encoder_mt' function. */
|
||||
#cmakedefine HAVE_LZMA_STREAM_ENCODER_MT 1
|
||||
|
||||
/* Define to 1 if you have the <lzo/lzo1x.h> header file. */
|
||||
#cmakedefine HAVE_LZO_LZO1X_H 1
|
||||
|
||||
@ -929,6 +941,12 @@ typedef uint64_t uintmax_t;
|
||||
/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */
|
||||
#cmakedefine HAVE_STRUCT_TM___TM_GMTOFF 1
|
||||
|
||||
/* Define to 1 if you have `struct vfsconf'. */
|
||||
#cmakedefine HAVE_STRUCT_VFSCONF 1
|
||||
|
||||
/* Define to 1 if you have `struct xvfsconf'. */
|
||||
#cmakedefine HAVE_STRUCT_XVFSCONF 1
|
||||
|
||||
/* Define to 1 if you have the `symlink' function. */
|
||||
#cmakedefine HAVE_SYMLINK 1
|
||||
|
||||
|
@ -1 +1 @@
|
||||
3002001
|
||||
3003000
|
||||
|
@ -168,15 +168,33 @@ SET(libarchive_MANS
|
||||
archive_entry_time.3
|
||||
archive_read.3
|
||||
archive_read_add_passphrase.3
|
||||
archive_read_data.3
|
||||
archive_read_disk.3
|
||||
archive_read_extract.3
|
||||
archive_read_filter.3
|
||||
archive_read_format.3
|
||||
archive_read_free.3
|
||||
archive_read_header.3
|
||||
archive_read_new.3
|
||||
archive_read_open.3
|
||||
archive_read_set_options.3
|
||||
archive_util.3
|
||||
archive_write.3
|
||||
archive_write_blocksize.3
|
||||
archive_write_data.3
|
||||
archive_write_disk.3
|
||||
archive_write_filter.3
|
||||
archive_write_finish_entry.3
|
||||
archive_write_format.3
|
||||
archive_write_free.3
|
||||
archive_write_header.3
|
||||
archive_write_new.3
|
||||
archive_write_open.3
|
||||
archive_write_set_options.3
|
||||
archive_write_set_passphrase.3
|
||||
cpio.5
|
||||
libarchive.3
|
||||
libarchive_changes.3
|
||||
libarchive_internals.3
|
||||
libarchive-formats.5
|
||||
mtree.5
|
||||
|
@ -36,7 +36,7 @@
|
||||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
||||
*/
|
||||
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3002001
|
||||
#define ARCHIVE_VERSION_NUMBER 3003000
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
@ -152,7 +152,7 @@ __LA_DECL int archive_version_number(void);
|
||||
/*
|
||||
* Textual name/version of the library, useful for version displays.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.2.1"
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.3.0"
|
||||
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
||||
__LA_DECL const char * archive_version_string(void);
|
||||
|
||||
@ -370,7 +370,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
|
||||
* 4) Repeatedly call archive_read_next_header to get information about
|
||||
* successive archive entries. Call archive_read_data to extract
|
||||
* data for entries of interest.
|
||||
* 5) Call archive_read_finish to end processing.
|
||||
* 5) Call archive_read_free to end processing.
|
||||
*/
|
||||
__LA_DECL struct archive *archive_read_new(void);
|
||||
|
||||
@ -559,7 +559,7 @@ __LA_DECL la_int64_t archive_read_header_position(struct archive *);
|
||||
* we cannot say whether there are encrypted entries, then
|
||||
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
|
||||
* In general, this function will return values below zero when the
|
||||
* reader is uncertain or totally uncapable of encryption support.
|
||||
* reader is uncertain or totally incapable of encryption support.
|
||||
* When this function returns 0 you can be sure that the reader
|
||||
* supports encryption detection but no encrypted entries have
|
||||
* been found yet.
|
||||
@ -981,12 +981,12 @@ __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. */
|
||||
/* Request that the access time of the entry visited by traversal be restored. */
|
||||
__LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
|
||||
/*
|
||||
* Set behavior. The "flags" argument selects optional behavior.
|
||||
*/
|
||||
/* Request that the access time of the entry visited by travesal be restored.
|
||||
/* Request that the access time of the entry visited by traversal be restored.
|
||||
* This is the same as archive_read_disk_set_atime_restored. */
|
||||
#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001)
|
||||
/* Default: Do not skip an entry which has nodump flags. */
|
||||
@ -1121,7 +1121,7 @@ __LA_DECL int archive_match_time_excluded(struct archive *,
|
||||
|
||||
/*
|
||||
* Flags to tell a matching type of time stamps. These are used for
|
||||
* following functinos.
|
||||
* following functions.
|
||||
*/
|
||||
/* Time flag: mtime to be tested. */
|
||||
#define ARCHIVE_MATCH_MTIME (0x0100)
|
||||
@ -1141,7 +1141,7 @@ __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. */
|
||||
/* Set inclusion time by a particular file. */
|
||||
__LA_DECL int archive_match_include_file_time(struct archive *,
|
||||
int _flag, const char *_pathname);
|
||||
__LA_DECL int archive_match_include_file_time_w(struct archive *,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,7 @@ struct archive_acl {
|
||||
void archive_acl_clear(struct archive_acl *);
|
||||
void archive_acl_copy(struct archive_acl *, struct archive_acl *);
|
||||
int archive_acl_count(struct archive_acl *, int);
|
||||
int archive_acl_types(struct archive_acl *);
|
||||
int archive_acl_reset(struct archive_acl *, int);
|
||||
int archive_acl_next(struct archive *, struct archive_acl *, int,
|
||||
int *, int *, int *, int *, const char **);
|
||||
@ -66,22 +67,17 @@ int archive_acl_add_entry_w_len(struct archive_acl *,
|
||||
int archive_acl_add_entry_len(struct archive_acl *,
|
||||
int, int, int, int, const char *, size_t);
|
||||
|
||||
const wchar_t *archive_acl_text_w(struct archive *, struct archive_acl *, int);
|
||||
int archive_acl_text_l(struct archive_acl *, int, const char **, size_t *,
|
||||
wchar_t *archive_acl_to_text_w(struct archive_acl *, ssize_t *, int,
|
||||
struct archive *);
|
||||
char *archive_acl_to_text_l(struct archive_acl *, ssize_t *, int,
|
||||
struct archive_string_conv *);
|
||||
|
||||
/*
|
||||
* Private ACL parser. This is private because it handles some
|
||||
* very weird formats that clients should not be messing with.
|
||||
* Clients should only deal with their platform-native formats.
|
||||
* Because of the need to support many formats cleanly, new arguments
|
||||
* are likely to get added on a regular basis. Clients who try to use
|
||||
* this interface are likely to be surprised when it changes.
|
||||
* ACL text parser.
|
||||
*/
|
||||
int archive_acl_parse_w(struct archive_acl *,
|
||||
const wchar_t *, int /* type */);
|
||||
int archive_acl_parse_l(struct archive_acl *,
|
||||
const char *, int /* type */,
|
||||
struct archive_string_conv *);
|
||||
int archive_acl_from_text_w(struct archive_acl *, const wchar_t * /* wtext */,
|
||||
int /* type */);
|
||||
int archive_acl_from_text_l(struct archive_acl *, const char * /* text */,
|
||||
int /* type */, struct archive_string_conv *);
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
||||
|
@ -302,7 +302,8 @@ aes_ctr_release(archive_crypto_ctx *ctx)
|
||||
static int
|
||||
aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
|
||||
{
|
||||
ctx->ctx = EVP_CIPHER_CTX_new();
|
||||
if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL)
|
||||
return -1;
|
||||
|
||||
switch (key_len) {
|
||||
case 16: ctx->type = EVP_aes_128_ecb(); break;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2016 Martin Matuska
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -248,10 +249,9 @@ archive_entry_new2(struct archive *a)
|
||||
{
|
||||
struct archive_entry *entry;
|
||||
|
||||
entry = (struct archive_entry *)malloc(sizeof(*entry));
|
||||
entry = (struct archive_entry *)calloc(1, sizeof(*entry));
|
||||
if (entry == NULL)
|
||||
return (NULL);
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
entry->archive = a;
|
||||
return (entry);
|
||||
}
|
||||
@ -1441,6 +1441,15 @@ archive_entry_acl_add_entry_w(struct archive_entry *entry,
|
||||
type, permset, tag, id, name, wcslen(name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a bitmask of ACL types in an archive entry ACL list
|
||||
*/
|
||||
int
|
||||
archive_entry_acl_types(struct archive_entry *entry)
|
||||
{
|
||||
return (archive_acl_types(&entry->acl));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a count of entries matching "want_type".
|
||||
*/
|
||||
@ -1478,34 +1487,121 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a text version of the ACL. The flags parameter controls
|
||||
* Generate a text version of the ACL. The flags parameter controls
|
||||
* the style of the generated ACL.
|
||||
*/
|
||||
wchar_t *
|
||||
archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
|
||||
int flags)
|
||||
{
|
||||
return (archive_acl_to_text_w(&entry->acl, len, flags,
|
||||
entry->archive));
|
||||
}
|
||||
|
||||
char *
|
||||
archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len,
|
||||
int flags)
|
||||
{
|
||||
return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
|
||||
}
|
||||
|
||||
char *
|
||||
_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,
|
||||
int flags, struct archive_string_conv *sc)
|
||||
{
|
||||
return (archive_acl_to_text_l(&entry->acl, len, flags, sc));
|
||||
}
|
||||
|
||||
/*
|
||||
* ACL text parser.
|
||||
*/
|
||||
int
|
||||
archive_entry_acl_from_text_w(struct archive_entry *entry,
|
||||
const wchar_t *wtext, int type)
|
||||
{
|
||||
return (archive_acl_from_text_w(&entry->acl, wtext, type));
|
||||
}
|
||||
|
||||
int
|
||||
archive_entry_acl_from_text(struct archive_entry *entry,
|
||||
const char *text, int type)
|
||||
{
|
||||
return (archive_acl_from_text_l(&entry->acl, text, type, NULL));
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,
|
||||
int type, struct archive_string_conv *sc)
|
||||
{
|
||||
return (archive_acl_from_text_l(&entry->acl, text, type, sc));
|
||||
}
|
||||
|
||||
/* Deprecated */
|
||||
static int
|
||||
archive_entry_acl_text_compat(int *flags)
|
||||
{
|
||||
if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0)
|
||||
return (1);
|
||||
|
||||
/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */
|
||||
if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0)
|
||||
*flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID;
|
||||
|
||||
/* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */
|
||||
if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0)
|
||||
*flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT;
|
||||
|
||||
*flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Deprecated */
|
||||
const wchar_t *
|
||||
archive_entry_acl_text_w(struct archive_entry *entry, int flags)
|
||||
{
|
||||
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);
|
||||
if (entry->acl.acl_text_w != NULL) {
|
||||
free(entry->acl.acl_text_w);
|
||||
entry->acl.acl_text_w = NULL;
|
||||
}
|
||||
if (archive_entry_acl_text_compat(&flags) == 0)
|
||||
entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,
|
||||
NULL, flags, entry->archive);
|
||||
return (entry->acl.acl_text_w);
|
||||
}
|
||||
|
||||
/* Deprecated */
|
||||
const char *
|
||||
archive_entry_acl_text(struct archive_entry *entry, int flags)
|
||||
{
|
||||
const char *p;
|
||||
if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0
|
||||
&& errno == ENOMEM)
|
||||
__archive_errx(1, "No memory");
|
||||
return (p);
|
||||
if (entry->acl.acl_text != NULL) {
|
||||
free(entry->acl.acl_text);
|
||||
entry->acl.acl_text = NULL;
|
||||
}
|
||||
if (archive_entry_acl_text_compat(&flags) == 0)
|
||||
entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,
|
||||
flags, NULL);
|
||||
|
||||
return (entry->acl.acl_text);
|
||||
}
|
||||
|
||||
/* Deprecated */
|
||||
int
|
||||
_archive_entry_acl_text_l(struct archive_entry *entry, int flags,
|
||||
const char **acl_text, size_t *len, struct archive_string_conv *sc)
|
||||
{
|
||||
return (archive_acl_text_l(&entry->acl, flags, acl_text, len, sc));
|
||||
if (entry->acl.acl_text != NULL) {
|
||||
free(entry->acl.acl_text);
|
||||
entry->acl.acl_text = NULL;
|
||||
}
|
||||
|
||||
if (archive_entry_acl_text_compat(&flags) == 0)
|
||||
entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,
|
||||
(ssize_t *)len, flags, sc);
|
||||
|
||||
*acl_text = entry->acl.acl_text;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2008 Tim Kientzle
|
||||
* Copyright (c) 2016 Martin Matuska
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -29,7 +30,7 @@
|
||||
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||
|
||||
/* Note: Compiler will complain if this does not match archive.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3002001
|
||||
#define ARCHIVE_VERSION_NUMBER 3003000
|
||||
|
||||
/*
|
||||
* Note: archive_entry.h is for use outside of libarchive; the
|
||||
@ -65,6 +66,27 @@ typedef int64_t la_int64_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The la_ssize_t should match the type used in 'struct stat' */
|
||||
#if !defined(__LA_SSIZE_T_DEFINED)
|
||||
/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
|
||||
# if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
#define __LA_SSIZE_T la_ssize_t
|
||||
# endif
|
||||
#define __LA_SSIZE_T_DEFINED
|
||||
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
|
||||
# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
|
||||
typedef ssize_t la_ssize_t;
|
||||
# elif defined(_WIN64)
|
||||
typedef __int64 la_ssize_t;
|
||||
# else
|
||||
typedef long la_ssize_t;
|
||||
# endif
|
||||
# else
|
||||
# include <unistd.h> /* ssize_t */
|
||||
typedef ssize_t la_ssize_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Get a suitable definition for mode_t */
|
||||
#if ARCHIVE_VERSION_NUMBER >= 3999000
|
||||
/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */
|
||||
@ -104,6 +126,9 @@ typedef int64_t la_int64_t;
|
||||
# define __LA_DECL
|
||||
#endif
|
||||
|
||||
/* CMake uses some deprecated APIs to build with old libarchive versions. */
|
||||
#define __LA_DEPRECATED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -420,6 +445,7 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
|
||||
/*
|
||||
* Inheritance values (NFS4 ACLs only); included in permset.
|
||||
*/
|
||||
#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000
|
||||
#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000
|
||||
#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000
|
||||
#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000
|
||||
@ -433,15 +459,16 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
|
||||
| ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \
|
||||
| ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \
|
||||
| ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \
|
||||
| ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS)
|
||||
| ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \
|
||||
| ARCHIVE_ENTRY_ACL_ENTRY_INHERITED)
|
||||
|
||||
/* We need to be able to specify combinations of these. */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 /* POSIX.1e only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 /* POSIX.1e only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 1024 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_DENY 2048 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 4096 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 8192 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \
|
||||
| ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \
|
||||
@ -492,21 +519,51 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type
|
||||
* Construct a text-format ACL. The flags argument is a bitmask that
|
||||
* can include any of the following:
|
||||
*
|
||||
* Flags only for archive entries with POSIX.1e ACL:
|
||||
* ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries.
|
||||
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries.
|
||||
* ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries.
|
||||
* ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
|
||||
* each ACL entry. ('star' introduced this for POSIX.1e, this flag
|
||||
* also applies to NFS4.)
|
||||
* ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each
|
||||
* default ACL entry, as used in old Solaris ACLs.
|
||||
* default ACL entry.
|
||||
* ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and
|
||||
* "mask" entries.
|
||||
*
|
||||
* Flags only for archive entries with NFSv4 ACL:
|
||||
* ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for
|
||||
* unset permissions and flags in NFSv4 ACL permission and flag fields
|
||||
*
|
||||
* Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL:
|
||||
* ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
|
||||
* each ACL entry.
|
||||
* ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma
|
||||
* instead of newline.
|
||||
*/
|
||||
#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
|
||||
#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
|
||||
#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001
|
||||
#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002
|
||||
#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004
|
||||
#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008
|
||||
#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010
|
||||
|
||||
__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *,
|
||||
la_ssize_t * /* len */, int /* flags */);
|
||||
__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *,
|
||||
la_ssize_t * /* len */, int /* flags */);
|
||||
__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *,
|
||||
const wchar_t * /* wtext */, int /* type */);
|
||||
__LA_DECL int archive_entry_acl_from_text(struct archive_entry *,
|
||||
const char * /* text */, int /* type */);
|
||||
|
||||
/* Deprecated constants */
|
||||
#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
|
||||
#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
|
||||
|
||||
/* Deprecated functions */
|
||||
__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *,
|
||||
int /* flags */);
|
||||
int /* flags */) __LA_DEPRECATED;
|
||||
__LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
|
||||
int /* flags */);
|
||||
int /* flags */) __LA_DEPRECATED;
|
||||
|
||||
/* Return bitmask of ACL types in an archive entry */
|
||||
__LA_DECL int archive_entry_acl_types(struct archive_entry *);
|
||||
|
||||
/* Return a count of entries matching 'want_type' */
|
||||
__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */);
|
||||
|
@ -1,4 +1,5 @@
|
||||
.\" Copyright (c) 2010 Joerg Sonnenberger
|
||||
.\" Copyright (c) 2016 Martin Matuska
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -22,7 +23,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd February 2, 2012
|
||||
.Dd February 15, 2017
|
||||
.Dt ARCHIVE_ENTRY_ACL 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -30,10 +31,14 @@
|
||||
.Nm archive_entry_acl_add_entry_w ,
|
||||
.Nm archive_entry_acl_clear ,
|
||||
.Nm archive_entry_acl_count ,
|
||||
.Nm archive_entry_acl_from_text ,
|
||||
.Nm archive_entry_acl_from_text_w,
|
||||
.Nm archive_entry_acl_next ,
|
||||
.Nm archive_entry_acl_next_w ,
|
||||
.Nm archive_entry_acl_reset ,
|
||||
.Nm archive_entry_acl_text_w
|
||||
.Nm archive_entry_acl_to_text ,
|
||||
.Nm archive_entry_acl_to_text_w ,
|
||||
.Nm archive_entry_acl_types
|
||||
.Nd functions for manipulating Access Control Lists in archive entry descriptions
|
||||
.Sh LIBRARY
|
||||
Streaming Archive Library (libarchive, -larchive)
|
||||
@ -62,6 +67,18 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Ft int
|
||||
.Fn archive_entry_acl_count "struct archive_entry *a" "int type"
|
||||
.Ft int
|
||||
.Fo archive_entry_acl_from_text
|
||||
.Fa "struct archive_entry *a"
|
||||
.Fa "const char *text"
|
||||
.Fa "int type"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo archive_entry_acl_from_text_w
|
||||
.Fa "struct archive_entry *a"
|
||||
.Fa "const wchar_t *text"
|
||||
.Fa "int type"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo archive_entry_acl_next
|
||||
.Fa "struct archive_entry *a"
|
||||
.Fa "int type"
|
||||
@ -83,31 +100,48 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fn archive_entry_acl_reset "struct archive_entry *a" "int type"
|
||||
.Ft const wchar_t *
|
||||
.Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags"
|
||||
.Ft char *
|
||||
.Fo archive_entry_acl_to_text
|
||||
.Fa "struct archive_entry *a"
|
||||
.Fa "ssize_t *len_p"
|
||||
.Fa "int flags"
|
||||
.Fc
|
||||
.Ft wchar_t *
|
||||
.Fo archive_entry_acl_to_text_w
|
||||
.Fa "struct archive_entry *a"
|
||||
.Fa "ssize_t *len_p"
|
||||
.Fa "int flags"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fn archive_entry_acl_types "struct archive_entry *a"
|
||||
.\" enum?
|
||||
.Sh DESCRIPTION
|
||||
An
|
||||
.Dq Access Control List
|
||||
is a generalisation of the classic Unix permission system.
|
||||
The
|
||||
.Dq Access Control Lists (ACLs)
|
||||
extend the standard Unix perssion model.
|
||||
The ACL interface of
|
||||
.Nm libarchive
|
||||
is derived from the POSIX.1e draft, but restricted to simplify dealing
|
||||
with practical implementations in various Operating Systems and archive formats.
|
||||
.Pp
|
||||
An ACL consists of a number of independent entries.
|
||||
supports both POSIX.1e and NFSv4 style ACLs. Use of ACLs is restricted by
|
||||
various levels of ACL support in operating systems, file systems and archive
|
||||
formats.
|
||||
.Ss POSIX.1e Access Control Lists
|
||||
A POSIX.1e ACL consists of a number of independent entries.
|
||||
Each entry specifies the permission set as bitmask of basic permissions.
|
||||
Valid permissions are:
|
||||
Valid permissions in the
|
||||
.Fa permset
|
||||
are:
|
||||
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_EXECUTE"
|
||||
.It Dv ARCHIVE_ENTRY_ACL_EXECUTE
|
||||
.It Dv ARCHIVE_ENTRY_ACL_WRITE
|
||||
.It Dv ARCHIVE_ENTRY_ACL_READ
|
||||
.It Dv ARCHIVE_ENTRY_ACL_READ ( Sy r )
|
||||
.It Dv ARCHIVE_ENTRY_ACL_WRITE ( Sy w )
|
||||
.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x )
|
||||
.El
|
||||
The permissions correspond to the normal Unix permissions.
|
||||
.Pp
|
||||
The tag specifies the principal to which the permission applies.
|
||||
The
|
||||
.Fa tag
|
||||
specifies the principal to which the permission applies.
|
||||
Valid values are:
|
||||
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
|
||||
.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
|
||||
.It Dv ARCHIVE_ENTRY_ACL_USER
|
||||
The user specified by the name field.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
|
||||
@ -119,8 +153,9 @@ The group who owns the file.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_MASK
|
||||
The maximum permissions to be obtained via group permissions.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_OTHER
|
||||
Any principal who doesn't have a user or group entry.
|
||||
Any principal who is not file owner or a member of the owning group.
|
||||
.El
|
||||
.Pp
|
||||
The principals
|
||||
.Dv ARCHIVE_ENTRY_ACL_USER_OBJ ,
|
||||
.Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
|
||||
@ -129,19 +164,123 @@ and
|
||||
are equivalent to user, group and other in the classic Unix permission
|
||||
model and specify non-extended ACL entries.
|
||||
.Pp
|
||||
All files have an access ACL
|
||||
All files with have an access ACL
|
||||
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS .
|
||||
This specifies the permissions required for access to the file itself.
|
||||
Directories have an additional ACL
|
||||
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT ,
|
||||
which controls the initial access ACL for newly created directory entries.
|
||||
.Ss NFSv4 Access Control Lists
|
||||
A NFSv4 ACL consists of multiple individual entries called Access Control
|
||||
Entries (ACEs).
|
||||
.Pp
|
||||
There are four possible types of a NFSv4 ACE:
|
||||
.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYE_ALLOW"
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW
|
||||
Allow principal to perform actions requiring given permissions.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY
|
||||
Prevent principal from performing actions requiring given permissions.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT
|
||||
Log access attempts by principal which require given permissions.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM
|
||||
Trigger a system alarm on access attempts by principal which require given
|
||||
permissions.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fa tag
|
||||
specifies the principal to which the permission applies.
|
||||
Valid values are:
|
||||
.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
|
||||
.It Dv ARCHIVE_ENTRY_ACL_USER
|
||||
The user specified by the name field.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
|
||||
The owner of the file.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_GROUP
|
||||
The group specied by the name field.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
|
||||
The group who owns the file.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_EVERYONE
|
||||
Any principal who is not file owner or a member of the owning group.
|
||||
.El
|
||||
.Pp
|
||||
Entries with the
|
||||
.Dv ARCHIVE_ENTRY_ACL_USER
|
||||
or
|
||||
.Dv ARCHIVE_ENTRY_ACL_GROUP
|
||||
tag store the user and group name in the
|
||||
.Fa name
|
||||
string and optionally the user or group ID in the
|
||||
.Fa qualifier
|
||||
integer.
|
||||
.Pp
|
||||
NFSv4 ACE permissions and flags are stored in the same
|
||||
.Fa permset
|
||||
bitfield. Some permissions share the same constant and permission character but
|
||||
have different effect on directories than on files. The following ACE
|
||||
permissions are supported:
|
||||
.Bl -tag -offset indent -compact -width ARCHIV
|
||||
.It Dv ARCHIVE_ENTRY_ACL_READ_DATA ( Sy r )
|
||||
Read data (file).
|
||||
.It Dv ARCHIVE_ENTRY_ACL_LIST_DIRECTORY ( Sy r )
|
||||
List entries (directory).
|
||||
.It ARCHIVE_ENTRY_ACL_WRITE_DATA ( Sy w )
|
||||
Write data (file).
|
||||
.It ARCHIVE_ENTRY_ACL_ADD_FILE ( Sy w )
|
||||
Create files (directory).
|
||||
.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x )
|
||||
Execute file or change into a directory.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_APPEND_DATA ( Sy p )
|
||||
Append data (file).
|
||||
.It Dv ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY ( Sy p )
|
||||
Create subdirectories (directory).
|
||||
.It Dv ARCHIVE_ENTRY_ACL_DELETE_CHILD ( Sy D )
|
||||
Remove files and subdirectories inside a directory.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_DELETE ( Sy d )
|
||||
Remove file or directory.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES ( Sy a )
|
||||
Read file or directory attributes.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES ( Sy A )
|
||||
Write file or directory attributes.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS ( Sy R )
|
||||
Read named file or directory attributes.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS ( Sy W )
|
||||
Write named file or directory attributes.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_READ_ACL ( Sy c )
|
||||
Read file or directory ACL.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_WRITE_ACL ( Sy C )
|
||||
Write file or directory ACL.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_WRITE_OWNER ( Sy o )
|
||||
Change owner of a file or directory.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_SYNCHRONIZE ( Sy s )
|
||||
Use synchronous I/O.
|
||||
.El
|
||||
.Pp
|
||||
The following NFSv4 ACL inheritance flags are supported:
|
||||
.Bl -tag -offset indent -compact -width ARCHIV
|
||||
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT ( Sy f )
|
||||
Inherit parent directory ACE to files.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT ( Sy d )
|
||||
Inherit parent directory ACE to subdirectories.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY ( Sy i )
|
||||
Only inherit, do not apply the permission on the directory itself.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n )
|
||||
Do not propagate inherit flags. Only first-level entries inherit ACLs.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S )
|
||||
Trigger alarm or audit on succesful access.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F )
|
||||
Trigger alarm or audit on failed access.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I )
|
||||
Mark that ACE was inherited.
|
||||
.El
|
||||
.Ss Functions
|
||||
.Fn archive_entry_acl_add_entry
|
||||
and
|
||||
.Fn archive_entry_acl_add_entry_w
|
||||
add a single ACL entry.
|
||||
For the access ACL and non-extended principals, the classic Unix permissions
|
||||
are updated.
|
||||
are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL
|
||||
entries.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_clear
|
||||
removes all ACL entries and resets the enumeration pointer.
|
||||
@ -150,14 +289,58 @@ removes all ACL entries and resets the enumeration pointer.
|
||||
counts the ACL entries that have the given type mask.
|
||||
.Fa type
|
||||
can be the bitwise-or of
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
and
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT .
|
||||
If
|
||||
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT"
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
|
||||
.El
|
||||
for POSIX.1e ACLs and
|
||||
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_ALLOW"
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM
|
||||
.El
|
||||
for NFSv4 ACLs. For POSIX.1e ACLs if
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
is included and at least one extended ACL entry is found,
|
||||
the three non-extened ACLs are added.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_from_text
|
||||
and
|
||||
.Fn archive_entry_acl_from_text_w
|
||||
add new
|
||||
.Pq or merge with existing
|
||||
ACL entries from
|
||||
.Pq wide
|
||||
text. The argument
|
||||
.Fa type
|
||||
may take one of the following values:
|
||||
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT"
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4
|
||||
.El
|
||||
Supports all formats that can be created with
|
||||
.Fn archive_entry_acl_to_text
|
||||
or respective
|
||||
.Fn archive_entry_acl_to_text_w .
|
||||
Existing ACL entries are preserved. To get a clean new ACL from text
|
||||
.Fn archive_entry_acl_clear
|
||||
must be called first. Entries prefixed with
|
||||
.Dq default:
|
||||
are treated as
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
|
||||
unless
|
||||
.Fa type
|
||||
is
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4 .
|
||||
Invalid entries, non-parseable ACL entries and entries beginning with
|
||||
the
|
||||
.Sq #
|
||||
character
|
||||
.Pq comments
|
||||
are skipped.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_next
|
||||
and
|
||||
.Fn archive_entry_acl_next_w
|
||||
@ -179,29 +362,81 @@ or set using
|
||||
Otherwise, the function returns the same value as
|
||||
.Fn archive_entry_acl_count .
|
||||
.Pp
|
||||
.Fn archive_entry_acl_text_w
|
||||
converts the ACL entries for the given type mask into a wide string.
|
||||
In addition to the normal type flags,
|
||||
.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
|
||||
.Fn archive_entry_acl_to_text
|
||||
and
|
||||
.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
|
||||
can be specified to further customize the result.
|
||||
The returned long string is valid until the next call to
|
||||
.Fn archive_entry_acl_clear ,
|
||||
.Fn archive_entry_acl_add_entry ,
|
||||
.Fn archive_entry_acl_add_entry_w
|
||||
.Fn archive_entry_acl_to_text_w
|
||||
convert the ACL entries for the given type into a
|
||||
.Pq wide
|
||||
string of ACL entries separated by newline. If the the pointer
|
||||
.Fa len_p
|
||||
is not NULL, then the function shall return the length of the string
|
||||
.Pq not including the NULL terminator
|
||||
in the location pointed to by
|
||||
.Fa len_p .
|
||||
The
|
||||
.Fa flag
|
||||
argument is a bitwise-or.
|
||||
.Pp
|
||||
The following flags are effective only on POSIX.1e ACL:
|
||||
.Bl -tag -offset indent -compact -width ARCHIV
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
Output access ACLs.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
|
||||
Output POSIX.1e default ACLs.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
|
||||
Prefix each default ACL entry with the word
|
||||
.Dq default: .
|
||||
.It Dv ARCHIVE_ENTRY_ACL_STYLE_SOLARIS
|
||||
The mask and other ACLs don not contain a double colon.
|
||||
.El
|
||||
.Pp
|
||||
The following flags are effecive only on NFSv4 ACL:
|
||||
.Bl -tag -offset indent -compact -width ARCHIV
|
||||
.It Dv ARCHIVE_ENTRY_ACL_STYLE_COMPACT
|
||||
Do not output minus characters for unset permissions and flags in NFSv4 ACL
|
||||
permission and flag fields.
|
||||
.El
|
||||
.Pp
|
||||
The following flags are effective on both POSIX.1e and NFSv4 ACL:
|
||||
.Bl -tag -offset indent -compact -width ARCHIV
|
||||
.It Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
|
||||
Add an additional colon-separated field containing the user or group id.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
|
||||
Separate ACL entries with comma instead of newline.
|
||||
.El
|
||||
.Pp
|
||||
If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are returned.
|
||||
It the entry contains POSIX.1e ACLs and none of the flags
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
or
|
||||
.Fn archive_entry_acl_text_w .
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
|
||||
are specified, both access and default entries are returned and default entries
|
||||
are prefixed with
|
||||
.Dq default: .
|
||||
.Pp
|
||||
.Fn archive_entry_acl_types
|
||||
get ACL entry types contained in an archive entry's ACL. As POSIX.1e and NFSv4
|
||||
ACL entries cannot be mixed, this function is a very efficient way to detect if
|
||||
an ACL already contains POSIX.1e or NFSv4 ACL entries.
|
||||
.Sh RETURN VALUES
|
||||
.Fn archive_entry_acl_count
|
||||
and
|
||||
.Fn archive_entry_acl_reset
|
||||
returns the number of ACL entries that match the given type mask.
|
||||
If the type mask includes
|
||||
For POSIX.1e ACLS if the type mask includes
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
and at least one extended ACL entry exists, the three classic Unix
|
||||
permissions are counted.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_from_text
|
||||
and
|
||||
.Fn archive_entry_acl_from_text_w
|
||||
return
|
||||
.Dv ARCHIVE_OK
|
||||
if all entries were successfully parsed and
|
||||
.Dv ARCHIVE_WARN
|
||||
if one or more entries were invalid or non-parseable.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_next
|
||||
and
|
||||
.Fn archive_entry_acl_next_w
|
||||
@ -216,20 +451,16 @@ if
|
||||
.Fn archive_entry_acl_reset
|
||||
has not been called first.
|
||||
.Pp
|
||||
.Fn archive_entry_text_w
|
||||
returns a wide string representation of the ACL entrise matching the
|
||||
given type mask.
|
||||
The returned long string is valid until the next call to
|
||||
.Fn archive_entry_acl_clear ,
|
||||
.Fn archive_entry_acl_add_entry ,
|
||||
.Fn archive_entry_acl_add_entry_w
|
||||
or
|
||||
.Fn archive_entry_acl_text_w .
|
||||
.Fn archive_entry_acl_to_text
|
||||
returns a string representing the ACL entries matching the given type and
|
||||
flags on success or NULL on error.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_to_text_w
|
||||
returns a wide string representing the ACL entries matching the given type
|
||||
and flags on success or NULL on error.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_types
|
||||
returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries.
|
||||
.Sh SEE ALSO
|
||||
.Xr archive_entry 3
|
||||
.Xr libarchive 3 ,
|
||||
.Sh BUGS
|
||||
.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
|
||||
and
|
||||
.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
|
||||
are not documented.
|
||||
.Xr archive_entry 3 ,
|
||||
.Xr libarchive 3
|
||||
|
@ -63,9 +63,13 @@ int _archive_entry_uname_l(struct archive_entry *,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
#define archive_entry_acl_text_l _archive_entry_acl_text_l
|
||||
int _archive_entry_acl_text_l(struct archive_entry *, int,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
|
||||
|
||||
const char **, size_t *, struct archive_string_conv *) __LA_DEPRECATED;
|
||||
#define archive_entry_acl_to_text_l _archive_entry_acl_to_text_l
|
||||
char *_archive_entry_acl_to_text_l(struct archive_entry *, ssize_t *, int,
|
||||
struct archive_string_conv *);
|
||||
#define archive_entry_acl_from_text_l _archive_entry_acl_from_text_l
|
||||
int _archive_entry_acl_from_text_l(struct archive_entry *, const char* text,
|
||||
int type, struct archive_string_conv *);
|
||||
#define archive_entry_copy_gname_l _archive_entry_copy_gname_l
|
||||
int _archive_entry_copy_gname_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
|
@ -80,7 +80,7 @@ archive_entry_strmode(struct archive_entry *entry)
|
||||
if (mode & 0001) bp[9] = 't';
|
||||
else bp[9] = 'T';
|
||||
}
|
||||
if (archive_entry_acl_count(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS))
|
||||
if (archive_entry_acl_types(entry) != 0)
|
||||
bp[10] = '+';
|
||||
|
||||
return (bp);
|
||||
|
@ -471,7 +471,7 @@ archive_match_path_excluded(struct archive *_a,
|
||||
}
|
||||
|
||||
/*
|
||||
* Utilty functions to get statistic information for inclusion patterns.
|
||||
* Utility functions to get statistic information for inclusion patterns.
|
||||
*/
|
||||
int
|
||||
archive_match_path_unmatched_inclusions(struct archive *_a)
|
||||
@ -655,7 +655,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
|
||||
}
|
||||
}
|
||||
|
||||
/* If something error happend, report it immediately. */
|
||||
/* If an error occurred, report it immediately. */
|
||||
if (r < ARCHIVE_OK) {
|
||||
archive_copy_error(&(a->archive), ar);
|
||||
archive_read_free(ar);
|
||||
@ -1270,7 +1270,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
|
||||
#endif /* _WIN32 && !__CYGWIN__ */
|
||||
|
||||
/*
|
||||
* Call back funtions for archive_rb.
|
||||
* Call back functions for archive_rb.
|
||||
*/
|
||||
static int
|
||||
cmp_node_mbs(const struct archive_rb_node *n1,
|
||||
@ -1405,7 +1405,7 @@ add_entry(struct archive_match *a, int flag,
|
||||
&(a->exclusion_tree), pathname);
|
||||
|
||||
/*
|
||||
* We always overwrite comparison condision.
|
||||
* We always overwrite comparison condition.
|
||||
* If you do not want to overwrite it, you should not
|
||||
* call archive_match_exclude_entry(). We cannot know
|
||||
* what behavior you really expect since overwriting
|
||||
@ -1481,7 +1481,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
|
||||
if (nsec == a->older_ctime_nsec &&
|
||||
(a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
|
||||
== 0)
|
||||
return (1); /* Eeual, skip it. */
|
||||
return (1); /* Equal, skip it. */
|
||||
}
|
||||
}
|
||||
if (a->newer_mtime_filter) {
|
||||
@ -1513,7 +1513,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is no excluson list, include the file. */
|
||||
/* If there is no exclusion list, include the file. */
|
||||
if (a->exclusion_entry_list.count == 0)
|
||||
return (0);
|
||||
|
||||
@ -1700,7 +1700,7 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Add oowner id. */
|
||||
/* Add owner id. */
|
||||
if (i == ids->count)
|
||||
ids->ids[ids->count++] = id;
|
||||
else if (ids->ids[i] != id) {
|
||||
|
@ -33,10 +33,7 @@
|
||||
#include <string.h> /* memset */
|
||||
static inline EVP_MD_CTX *EVP_MD_CTX_new(void)
|
||||
{
|
||||
EVP_MD_CTX *ctx = (EVP_MD_CTX *)malloc(sizeof(EVP_MD_CTX));
|
||||
if (ctx != NULL) {
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
EVP_MD_CTX *ctx = (EVP_MD_CTX *)calloc(1, sizeof(EVP_MD_CTX));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
@ -33,11 +33,7 @@
|
||||
#include <string.h> /* memset */
|
||||
static inline HMAC_CTX *HMAC_CTX_new(void)
|
||||
{
|
||||
HMAC_CTX *ctx = (HMAC_CTX *)malloc(sizeof(HMAC_CTX));
|
||||
if (ctx != NULL) {
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
HMAC_CTX_init(ctx);
|
||||
}
|
||||
HMAC_CTX *ctx = (HMAC_CTX *)calloc(1, sizeof(HMAC_CTX));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "archive_options_private.h"
|
||||
|
||||
static const char *
|
||||
@ -105,8 +109,11 @@ _archive_set_options(struct archive *a, const char *options,
|
||||
if (options == NULL || options[0] == '\0')
|
||||
return ARCHIVE_OK;
|
||||
|
||||
data = (char *)malloc(strlen(options) + 1);
|
||||
strcpy(data, options);
|
||||
if ((data = strdup(options)) == NULL) {
|
||||
archive_set_error(a,
|
||||
ENOMEM, "Out of memory adding file to list");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
s = (const char *)data;
|
||||
|
||||
do {
|
||||
|
@ -152,8 +152,25 @@
|
||||
* acl_set_file(), and ACL_USER, we assume it has the rest of the
|
||||
* POSIX.1e draft functions used in archive_read_extract.c.
|
||||
*/
|
||||
#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE && HAVE_ACL_USER
|
||||
#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE
|
||||
#if HAVE_ACL_USER
|
||||
#define HAVE_POSIX_ACL 1
|
||||
#elif HAVE_ACL_TYPE_EXTENDED
|
||||
#define HAVE_DARWIN_ACL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(),
|
||||
* facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions
|
||||
*/
|
||||
#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T
|
||||
#define HAVE_SUN_ACL 1
|
||||
#endif
|
||||
|
||||
/* Define if platform supports NFSv4 ACLs */
|
||||
#if (HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL
|
||||
#define HAVE_NFS4_ACL 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -164,6 +181,15 @@
|
||||
#define CAN_RESTORE_METADATA_FD
|
||||
#endif
|
||||
|
||||
/*
|
||||
* glibc 2.24 deprecates readdir_r
|
||||
*/
|
||||
#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24))
|
||||
#define USE_READDIR_R 1
|
||||
#else
|
||||
#undef USE_READDIR_R
|
||||
#endif
|
||||
|
||||
/* Set up defaults for internal error codes. */
|
||||
#ifndef ARCHIVE_ERRNO_FILE_FORMAT
|
||||
#if HAVE_EFTYPE
|
||||
|
@ -19,7 +19,7 @@ If you need the compatibility with original PPMd var.H, you can use external Ran
|
||||
#define PPMD7_MAX_ORDER 64
|
||||
|
||||
#define PPMD7_MIN_MEM_SIZE (1 << 11)
|
||||
#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
|
||||
#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFFu - 12 * 3)
|
||||
|
||||
struct CPpmd7_Context_;
|
||||
|
||||
|
@ -80,7 +80,7 @@ archive_random(void *buf, size_t nbytes)
|
||||
|
||||
success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT);
|
||||
if (!success && GetLastError() == NTE_BAD_KEYSET) {
|
||||
if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) {
|
||||
success = CryptAcquireContext(&hProv, NULL, NULL,
|
||||
PROV_RSA_FULL, CRYPT_NEWKEYSET);
|
||||
}
|
||||
|
@ -312,7 +312,7 @@ __archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt,
|
||||
father = RB_FATHER(self);
|
||||
if (RB_BLACK_P(father)) {
|
||||
/*
|
||||
* If our greatgrandpa is black, we're done.
|
||||
* If our great-grandpa is black, we're done.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ __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 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);
|
||||
@ -528,7 +529,7 @@ archive_read_open1(struct archive *_a)
|
||||
{
|
||||
slot = choose_format(a);
|
||||
if (slot < 0) {
|
||||
__archive_read_close_filters(a);
|
||||
close_filters(a);
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -582,7 +583,6 @@ 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) {
|
||||
__archive_read_close_filters(a);
|
||||
__archive_read_free_filters(a);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -601,7 +601,6 @@ choose_filters(struct archive_read *a)
|
||||
a->filter = filter;
|
||||
r = (best_bidder->init)(a->filter);
|
||||
if (r != ARCHIVE_OK) {
|
||||
__archive_read_close_filters(a);
|
||||
__archive_read_free_filters(a);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@ -765,7 +764,7 @@ archive_read_header_position(struct archive *_a)
|
||||
* we cannot say whether there are encrypted entries, then
|
||||
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
|
||||
* In general, this function will return values below zero when the
|
||||
* reader is uncertain or totally uncapable of encryption support.
|
||||
* reader is uncertain or totally incapable of encryption support.
|
||||
* When this function returns 0 you can be sure that the reader
|
||||
* supports encryption detection but no encrypted entries have
|
||||
* been found yet.
|
||||
@ -986,8 +985,8 @@ _archive_read_data_block(struct archive *_a,
|
||||
return (a->format->read_data)(a, buff, size, offset);
|
||||
}
|
||||
|
||||
int
|
||||
__archive_read_close_filters(struct archive_read *a)
|
||||
static int
|
||||
close_filters(struct archive_read *a)
|
||||
{
|
||||
struct archive_read_filter *f = a->filter;
|
||||
int r = ARCHIVE_OK;
|
||||
@ -1010,6 +1009,9 @@ __archive_read_close_filters(struct archive_read *a)
|
||||
void
|
||||
__archive_read_free_filters(struct archive_read *a)
|
||||
{
|
||||
/* Make sure filters are closed and their buffers are freed */
|
||||
close_filters(a);
|
||||
|
||||
while (a->filter != NULL) {
|
||||
struct archive_read_filter *t = a->filter->upstream;
|
||||
free(a->filter);
|
||||
@ -1052,7 +1054,7 @@ _archive_read_close(struct archive *_a)
|
||||
/* TODO: Clean up the formatters. */
|
||||
|
||||
/* Release the filter objects. */
|
||||
r1 = __archive_read_close_filters(a);
|
||||
r1 = close_filters(a);
|
||||
if (r1 < r)
|
||||
r = r1;
|
||||
|
||||
|
@ -125,7 +125,7 @@ void
|
||||
__archive_read_reset_passphrase(struct archive_read *a)
|
||||
{
|
||||
|
||||
a->passphrases.candiate = -1;
|
||||
a->passphrases.candidate = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -137,31 +137,31 @@ __archive_read_next_passphrase(struct archive_read *a)
|
||||
struct archive_read_passphrase *p;
|
||||
const char *passphrase;
|
||||
|
||||
if (a->passphrases.candiate < 0) {
|
||||
if (a->passphrases.candidate < 0) {
|
||||
/* Count out how many passphrases we have. */
|
||||
int cnt = 0;
|
||||
|
||||
for (p = a->passphrases.first; p != NULL; p = p->next)
|
||||
cnt++;
|
||||
a->passphrases.candiate = cnt;
|
||||
a->passphrases.candidate = cnt;
|
||||
p = a->passphrases.first;
|
||||
} else if (a->passphrases.candiate > 1) {
|
||||
} else if (a->passphrases.candidate > 1) {
|
||||
/* Rotate a passphrase list. */
|
||||
a->passphrases.candiate--;
|
||||
a->passphrases.candidate--;
|
||||
p = remove_passphrases_from_head(a);
|
||||
add_passphrase_to_tail(a, p);
|
||||
/* Pick a new passphrase candiate up. */
|
||||
/* Pick a new passphrase candidate up. */
|
||||
p = a->passphrases.first;
|
||||
} else if (a->passphrases.candiate == 1) {
|
||||
/* This case is that all cadiates failed to decryption. */
|
||||
a->passphrases.candiate = 0;
|
||||
} else if (a->passphrases.candidate == 1) {
|
||||
/* This case is that all candidates failed to decrypt. */
|
||||
a->passphrases.candidate = 0;
|
||||
if (a->passphrases.first->next != NULL) {
|
||||
/* Rotate a passphrase list. */
|
||||
p = remove_passphrases_from_head(a);
|
||||
add_passphrase_to_tail(a, p);
|
||||
}
|
||||
p = NULL;
|
||||
} else /* There is no passphrase candaite. */
|
||||
} else /* There is no passphrase candidate. */
|
||||
p = NULL;
|
||||
|
||||
if (p != NULL)
|
||||
@ -177,7 +177,7 @@ __archive_read_next_passphrase(struct archive_read *a)
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
insert_passphrase_to_head(a, p);
|
||||
a->passphrases.candiate = 1;
|
||||
a->passphrases.candidate = 1;
|
||||
}
|
||||
} else
|
||||
passphrase = NULL;
|
||||
|
@ -133,7 +133,6 @@ archive_read_append_filter(struct archive *_a, int code)
|
||||
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);
|
||||
}
|
||||
@ -191,7 +190,6 @@ archive_read_append_filter_program_signature(struct archive *_a,
|
||||
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);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 2, 2012
|
||||
.Dd December 30, 2016
|
||||
.Dt ARCHIVE_READ_DISK 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -54,9 +54,9 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Fn archive_read_disk_set_symlink_physical "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_disk_set_symlink_hybrid "struct archive *"
|
||||
.Ft int
|
||||
.Ft const char *
|
||||
.Fn archive_read_disk_gname "struct archive *" "gid_t"
|
||||
.Ft int
|
||||
.Ft const char *
|
||||
.Fn archive_read_disk_uname "struct archive *" "uid_t"
|
||||
.Ft int
|
||||
.Fo archive_read_disk_set_gname_lookup
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -165,7 +165,7 @@ struct filesystem {
|
||||
int synthetic;
|
||||
int remote;
|
||||
int noatime;
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
size_t name_max;
|
||||
#endif
|
||||
long incr_xfer_size;
|
||||
@ -200,7 +200,7 @@ struct tree {
|
||||
DIR *d;
|
||||
#define INVALID_DIR_HANDLE NULL
|
||||
struct dirent *de;
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
struct dirent *dirent;
|
||||
size_t dirent_allocated;
|
||||
#endif
|
||||
@ -244,7 +244,7 @@ struct tree {
|
||||
int initial_filesystem_id;
|
||||
int current_filesystem_id;
|
||||
int max_filesystem_id;
|
||||
int allocated_filesytem;
|
||||
int allocated_filesystem;
|
||||
|
||||
int entry_fd;
|
||||
int entry_eof;
|
||||
@ -675,7 +675,7 @@ setup_suitable_read_buffer(struct archive_read_disk *a)
|
||||
asize = cf->min_xfer_size;
|
||||
|
||||
/* Increase a buffer size up to 64K bytes in
|
||||
* a proper incremant size. */
|
||||
* a proper increment size. */
|
||||
while (asize < 1024*64)
|
||||
asize += incr;
|
||||
/* Take a margin to adjust to the filesystem
|
||||
@ -938,7 +938,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
||||
r = archive_match_path_excluded(a->matching, entry);
|
||||
if (r < 0) {
|
||||
archive_set_error(&(a->archive), errno,
|
||||
"Faild : %s", archive_error_string(a->matching));
|
||||
"Failed : %s", archive_error_string(a->matching));
|
||||
return (r);
|
||||
}
|
||||
if (r) {
|
||||
@ -1026,7 +1026,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
||||
|
||||
/* 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. */
|
||||
* especially, invoking 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);
|
||||
@ -1041,7 +1041,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
||||
r = archive_match_time_excluded(a->matching, entry);
|
||||
if (r < 0) {
|
||||
archive_set_error(&(a->archive), errno,
|
||||
"Faild : %s", archive_error_string(a->matching));
|
||||
"Failed : %s", archive_error_string(a->matching));
|
||||
return (r);
|
||||
}
|
||||
if (r) {
|
||||
@ -1067,7 +1067,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
||||
r = archive_match_owner_excluded(a->matching, entry);
|
||||
if (r < 0) {
|
||||
archive_set_error(&(a->archive), errno,
|
||||
"Faild : %s", archive_error_string(a->matching));
|
||||
"Failed : %s", archive_error_string(a->matching));
|
||||
return (r);
|
||||
}
|
||||
if (r) {
|
||||
@ -1382,7 +1382,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
|
||||
|
||||
for (i = 0; i < t->max_filesystem_id; i++) {
|
||||
if (t->filesystem_table[i].dev == dev) {
|
||||
/* There is the filesytem ID we've already generated. */
|
||||
/* There is the filesystem ID we've already generated. */
|
||||
t->current_filesystem_id = i;
|
||||
t->current_filesystem = &(t->filesystem_table[i]);
|
||||
return (ARCHIVE_OK);
|
||||
@ -1390,10 +1390,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the new filesytem which we have to generate a new ID for.
|
||||
* This is the new filesystem which we have to generate a new ID for.
|
||||
*/
|
||||
fid = t->max_filesystem_id++;
|
||||
if (t->max_filesystem_id > t->allocated_filesytem) {
|
||||
if (t->max_filesystem_id > t->allocated_filesystem) {
|
||||
size_t s;
|
||||
void *p;
|
||||
|
||||
@ -1406,7 +1406,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
t->filesystem_table = (struct filesystem *)p;
|
||||
t->allocated_filesytem = s;
|
||||
t->allocated_filesystem = s;
|
||||
}
|
||||
t->current_filesystem_id = fid;
|
||||
t->current_filesystem = &(t->filesystem_table[fid]);
|
||||
@ -1504,7 +1504,20 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
struct tree *t = a->tree;
|
||||
struct statfs sfs;
|
||||
#if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC)
|
||||
/* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make
|
||||
* this accurate; some platforms have both and we need the one that's
|
||||
* used by getvfsbyname()
|
||||
*
|
||||
* Then the following would become:
|
||||
* #if defined(GETVFSBYNAME_ARG_TYPE)
|
||||
* GETVFSBYNAME_ARG_TYPE vfc;
|
||||
* #endif
|
||||
*/
|
||||
# if defined(HAVE_STRUCT_XVFSCONF)
|
||||
struct xvfsconf vfc;
|
||||
# else
|
||||
struct vfsconf vfc;
|
||||
# endif
|
||||
#endif
|
||||
int r, xr = 0;
|
||||
#if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
|
||||
@ -1579,7 +1592,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
#endif
|
||||
t->current_filesystem->noatime = 0;
|
||||
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
/* Set maximum filename length. */
|
||||
#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
|
||||
t->current_filesystem->name_max = sfs.f_namemax;
|
||||
@ -1602,7 +1615,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
else
|
||||
t->current_filesystem->name_max = nm;
|
||||
#endif
|
||||
#endif /* HAVE_READDIR_R */
|
||||
#endif /* USE_READDIR_R */
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -1643,7 +1656,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
archive_set_error(&a->archive, errno, "statvfs failed");
|
||||
return (ARCHIVE_FAILED);
|
||||
} else if (xr == 1) {
|
||||
/* Usuall come here unless NetBSD supports _PC_REC_XFER_ALIGN
|
||||
/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
|
||||
* for pathconf() function. */
|
||||
t->current_filesystem->xfer_align = sfs.f_frsize;
|
||||
t->current_filesystem->max_xfer_size = -1;
|
||||
@ -1804,7 +1817,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
#endif
|
||||
t->current_filesystem->noatime = 0;
|
||||
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
/* Set maximum filename length. */
|
||||
t->current_filesystem->name_max = sfs.f_namelen;
|
||||
#endif
|
||||
@ -1888,7 +1901,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
#endif
|
||||
t->current_filesystem->noatime = 0;
|
||||
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
/* Set maximum filename length. */
|
||||
t->current_filesystem->name_max = sfs.f_namemax;
|
||||
#endif
|
||||
@ -1905,7 +1918,7 @@ static int
|
||||
setup_current_filesystem(struct archive_read_disk *a)
|
||||
{
|
||||
struct tree *t = a->tree;
|
||||
#if defined(_PC_NAME_MAX) && defined(HAVE_READDIR_R)
|
||||
#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R)
|
||||
long nm;
|
||||
#endif
|
||||
t->current_filesystem->synthetic = -1;/* Not supported */
|
||||
@ -1917,7 +1930,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
t->current_filesystem->min_xfer_size = -1;
|
||||
t->current_filesystem->incr_xfer_size = -1;
|
||||
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
/* Set maximum filename length. */
|
||||
# if defined(_PC_NAME_MAX)
|
||||
if (tree_current_is_symblic_link_target(t)) {
|
||||
@ -1931,7 +1944,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
if (nm == -1)
|
||||
# endif /* _PC_NAME_MAX */
|
||||
/*
|
||||
* Some sysmtes (HP-UX or others?) incorrectly defined
|
||||
* Some systems (HP-UX or others?) incorrectly defined
|
||||
* NAME_MAX macro to be a smaller value.
|
||||
*/
|
||||
# if defined(NAME_MAX) && NAME_MAX >= 255
|
||||
@ -1945,7 +1958,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
else
|
||||
t->current_filesystem->name_max = nm;
|
||||
# endif /* _PC_NAME_MAX */
|
||||
#endif /* HAVE_READDIR_R */
|
||||
#endif /* USE_READDIR_R */
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -2050,8 +2063,7 @@ tree_push(struct tree *t, const char *path, int filesystem_id,
|
||||
{
|
||||
struct tree_entry *te;
|
||||
|
||||
te = malloc(sizeof(*te));
|
||||
memset(te, 0, sizeof(*te));
|
||||
te = calloc(1, sizeof(*te));
|
||||
te->next = t->stack;
|
||||
te->parent = t->current;
|
||||
if (te->parent)
|
||||
@ -2109,9 +2121,8 @@ tree_open(const char *path, int symlink_mode, int restore_time)
|
||||
{
|
||||
struct tree *t;
|
||||
|
||||
if ((t = malloc(sizeof(*t))) == NULL)
|
||||
if ((t = calloc(1, sizeof(*t))) == NULL)
|
||||
return (NULL);
|
||||
memset(t, 0, sizeof(*t));
|
||||
archive_string_init(&t->path);
|
||||
archive_string_ensure(&t->path, 31);
|
||||
t->initial_symlink_mode = symlink_mode;
|
||||
@ -2353,7 +2364,7 @@ tree_dir_next_posix(struct tree *t)
|
||||
size_t namelen;
|
||||
|
||||
if (t->d == NULL) {
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
size_t dirent_size;
|
||||
#endif
|
||||
|
||||
@ -2374,7 +2385,7 @@ tree_dir_next_posix(struct tree *t)
|
||||
t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
|
||||
return (t->visit_type);
|
||||
}
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
dirent_size = offsetof(struct dirent, d_name) +
|
||||
t->filesystem_table[t->current->filesystem_id].name_max + 1;
|
||||
if (t->dirent == NULL || t->dirent_allocated < dirent_size) {
|
||||
@ -2391,11 +2402,11 @@ tree_dir_next_posix(struct tree *t)
|
||||
}
|
||||
t->dirent_allocated = dirent_size;
|
||||
}
|
||||
#endif /* HAVE_READDIR_R */
|
||||
#endif /* USE_READDIR_R */
|
||||
}
|
||||
for (;;) {
|
||||
errno = 0;
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
r = readdir_r(t->d, t->dirent, &t->de);
|
||||
#ifdef _AIX
|
||||
/* Note: According to the man page, return value 9 indicates
|
||||
@ -2647,7 +2658,7 @@ tree_free(struct tree *t)
|
||||
if (t == NULL)
|
||||
return;
|
||||
archive_string_free(&t->path);
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
free(t->dirent);
|
||||
#endif
|
||||
free(t->sparse_list);
|
||||
|
@ -232,6 +232,7 @@ static const char *
|
||||
lookup_uname_helper(struct name_cache *cache, id_t id)
|
||||
{
|
||||
struct passwd *result;
|
||||
(void)cache; /* UNUSED */
|
||||
|
||||
result = getpwuid((uid_t)id);
|
||||
|
||||
@ -298,6 +299,7 @@ static const char *
|
||||
lookup_gname_helper(struct name_cache *cache, id_t id)
|
||||
{
|
||||
struct group *result;
|
||||
(void)cache; /* UNUSED */
|
||||
|
||||
result = getgrgid((gid_t)id);
|
||||
|
||||
|
@ -168,7 +168,7 @@ struct tree {
|
||||
int initial_filesystem_id;
|
||||
int current_filesystem_id;
|
||||
int max_filesystem_id;
|
||||
int allocated_filesytem;
|
||||
int allocated_filesystem;
|
||||
|
||||
HANDLE entry_fh;
|
||||
int entry_eof;
|
||||
@ -389,10 +389,9 @@ 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();
|
||||
@ -803,7 +802,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
||||
r = archive_match_path_excluded(a->matching, entry);
|
||||
if (r < 0) {
|
||||
archive_set_error(&(a->archive), errno,
|
||||
"Faild : %s", archive_error_string(a->matching));
|
||||
"Failed : %s", archive_error_string(a->matching));
|
||||
return (r);
|
||||
}
|
||||
if (r) {
|
||||
@ -863,7 +862,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
||||
|
||||
/* 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. */
|
||||
* especially, invoking a callback. */
|
||||
t->restore_time.lastWriteTime = st->ftLastWriteTime;
|
||||
t->restore_time.lastAccessTime = st->ftLastAccessTime;
|
||||
t->restore_time.filetype = archive_entry_filetype(entry);
|
||||
@ -875,7 +874,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
||||
r = archive_match_time_excluded(a->matching, entry);
|
||||
if (r < 0) {
|
||||
archive_set_error(&(a->archive), errno,
|
||||
"Faild : %s", archive_error_string(a->matching));
|
||||
"Failed : %s", archive_error_string(a->matching));
|
||||
return (r);
|
||||
}
|
||||
if (r) {
|
||||
@ -901,7 +900,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
||||
r = archive_match_owner_excluded(a->matching, entry);
|
||||
if (r < 0) {
|
||||
archive_set_error(&(a->archive), errno,
|
||||
"Faild : %s", archive_error_string(a->matching));
|
||||
"Failed : %s", archive_error_string(a->matching));
|
||||
return (r);
|
||||
}
|
||||
if (r) {
|
||||
@ -1261,7 +1260,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
|
||||
|
||||
for (i = 0; i < t->max_filesystem_id; i++) {
|
||||
if (t->filesystem_table[i].dev == dev) {
|
||||
/* There is the filesytem ID we've already generated. */
|
||||
/* There is the filesystem ID we've already generated. */
|
||||
t->current_filesystem_id = i;
|
||||
t->current_filesystem = &(t->filesystem_table[i]);
|
||||
return (ARCHIVE_OK);
|
||||
@ -1269,10 +1268,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* There is a new filesytem, we generate a new ID for.
|
||||
* There is a new filesystem, we generate a new ID for.
|
||||
*/
|
||||
fid = t->max_filesystem_id++;
|
||||
if (t->max_filesystem_id > t->allocated_filesytem) {
|
||||
if (t->max_filesystem_id > t->allocated_filesystem) {
|
||||
size_t s;
|
||||
void *p;
|
||||
|
||||
@ -1285,7 +1284,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
t->filesystem_table = (struct filesystem *)p;
|
||||
t->allocated_filesytem = (int)s;
|
||||
t->allocated_filesystem = (int)s;
|
||||
}
|
||||
t->current_filesystem_id = fid;
|
||||
t->current_filesystem = &(t->filesystem_table[fid]);
|
||||
@ -1402,7 +1401,7 @@ close_and_restore_time(HANDLE h, struct tree *t, struct restore_time *rt)
|
||||
if (h == INVALID_HANDLE_VALUE && AE_IFLNK == rt->filetype)
|
||||
return (0);
|
||||
|
||||
/* Close a file descritor.
|
||||
/* Close a file descriptor.
|
||||
* It will not be used for SetFileTime() because it has been opened
|
||||
* by a read only mode.
|
||||
*/
|
||||
@ -1437,8 +1436,7 @@ tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path,
|
||||
{
|
||||
struct tree_entry *te;
|
||||
|
||||
te = malloc(sizeof(*te));
|
||||
memset(te, 0, sizeof(*te));
|
||||
te = calloc(1, sizeof(*te));
|
||||
te->next = t->stack;
|
||||
te->parent = t->current;
|
||||
if (te->parent)
|
||||
@ -1507,8 +1505,7 @@ tree_open(const wchar_t *path, int symlink_mode, int restore_time)
|
||||
{
|
||||
struct tree *t;
|
||||
|
||||
t = malloc(sizeof(*t));
|
||||
memset(t, 0, sizeof(*t));
|
||||
t = calloc(1, sizeof(*t));
|
||||
archive_string_init(&(t->full_path));
|
||||
archive_string_init(&t->path);
|
||||
archive_wstring_ensure(&t->path, 15);
|
||||
|
@ -52,12 +52,11 @@ struct archive_read_extract *
|
||||
__archive_read_get_extract(struct archive_read *a)
|
||||
{
|
||||
if (a->extract == NULL) {
|
||||
a->extract = (struct archive_read_extract *)malloc(sizeof(*a->extract));
|
||||
a->extract = (struct archive_read_extract *)calloc(1, sizeof(*a->extract));
|
||||
if (a->extract == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't extract");
|
||||
return (NULL);
|
||||
}
|
||||
memset(a->extract, 0, sizeof(*a->extract));
|
||||
a->cleanup_archive_extract = archive_read_extract_cleanup;
|
||||
}
|
||||
return (a->extract);
|
||||
|
@ -222,7 +222,7 @@ file_open(struct archive *a, void *client_data)
|
||||
void *buffer;
|
||||
const char *filename = NULL;
|
||||
const wchar_t *wfilename = NULL;
|
||||
int fd;
|
||||
int fd = -1;
|
||||
int is_disk_like = 0;
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
off_t mediasize = 0; /* FreeBSD-specific, so off_t okay here. */
|
||||
@ -277,7 +277,7 @@ file_open(struct archive *a, void *client_data)
|
||||
#else
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Unexpedted operation in archive_read_open_filename");
|
||||
return (ARCHIVE_FATAL);
|
||||
goto fail;
|
||||
#endif
|
||||
}
|
||||
if (fstat(fd, &st) != 0) {
|
||||
@ -287,7 +287,7 @@ file_open(struct archive *a, void *client_data)
|
||||
else
|
||||
archive_set_error(a, errno, "Can't stat '%s'",
|
||||
filename);
|
||||
return (ARCHIVE_FATAL);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -356,11 +356,9 @@ file_open(struct archive *a, void *client_data)
|
||||
mine->block_size = new_block_size;
|
||||
}
|
||||
buffer = malloc(mine->block_size);
|
||||
if (mine == NULL || buffer == NULL) {
|
||||
if (buffer == NULL) {
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
free(mine);
|
||||
free(buffer);
|
||||
return (ARCHIVE_FATAL);
|
||||
goto fail;
|
||||
}
|
||||
mine->buffer = buffer;
|
||||
mine->fd = fd;
|
||||
@ -372,6 +370,14 @@ file_open(struct archive *a, void *client_data)
|
||||
mine->use_lseek = 1;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
fail:
|
||||
/*
|
||||
* Don't close file descriptors not opened or ones pointing referring
|
||||
* to `FNT_STDIN`.
|
||||
*/
|
||||
if (fd != -1 && fd != 0)
|
||||
close(fd);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
|
@ -70,12 +70,11 @@ archive_read_open_memory2(struct archive *a, const void *buff,
|
||||
{
|
||||
struct read_memory_data *mine;
|
||||
|
||||
mine = (struct read_memory_data *)malloc(sizeof(*mine));
|
||||
mine = (struct read_memory_data *)calloc(1, sizeof(*mine));
|
||||
if (mine == NULL) {
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(mine, 0, sizeof(*mine));
|
||||
mine->start = mine->p = (const unsigned char *)buff;
|
||||
mine->end = mine->start + size;
|
||||
mine->read_size = read_size;
|
||||
|
@ -221,7 +221,7 @@ struct archive_read {
|
||||
struct {
|
||||
struct archive_read_passphrase *first;
|
||||
struct archive_read_passphrase **last;
|
||||
int candiate;
|
||||
int candidate;
|
||||
archive_passphrase_callback *callback;
|
||||
void *client_data;
|
||||
} passphrases;
|
||||
@ -252,7 +252,6 @@ 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 *);
|
||||
struct archive_read_extract *__archive_read_get_extract(struct archive_read *);
|
||||
|
||||
|
||||
|
@ -180,7 +180,7 @@ lz4_reader_bid(struct archive_read_filter_bidder *self,
|
||||
return (0);
|
||||
bits_checked += 8;
|
||||
BD = buffer[5];
|
||||
/* A block maximum size shuld be more than 3. */
|
||||
/* A block maximum size should be more than 3. */
|
||||
if (((BD & 0x70) >> 4) < 4)
|
||||
return (0);
|
||||
/* Reserved bits must be "0". */
|
||||
@ -417,7 +417,7 @@ lz4_filter_read_descriptor(struct archive_read_filter *self)
|
||||
/* Reserved bits must be zero. */
|
||||
if (bd & 0x8f)
|
||||
goto malformed_error;
|
||||
/* Get a maxinum block size. */
|
||||
/* Get a maximum block size. */
|
||||
switch (read_buf[1] >> 4) {
|
||||
case 4: /* 64 KB */
|
||||
state->flags.block_maximum_size = 64 * 1024;
|
||||
@ -595,7 +595,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if an error happend in decompression process. */
|
||||
/* Check if an error occurred in the decompression process. */
|
||||
if (uncompressed_size < 0) {
|
||||
archive_set_error(&(self->archive->archive),
|
||||
ARCHIVE_ERRNO_MISC, "lz4 decompression failed");
|
||||
@ -627,7 +627,7 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p)
|
||||
|
||||
if (state->stage == SELECT_STREAM) {
|
||||
state->stage = READ_DEFAULT_STREAM;
|
||||
/* First, read a desciprtor. */
|
||||
/* First, read a descriptor. */
|
||||
if((ret = lz4_filter_read_descriptor(self)) != ARCHIVE_OK)
|
||||
return (ret);
|
||||
state->stage = READ_DEFAULT_BLOCK;
|
||||
@ -706,6 +706,11 @@ lz4_filter_read_legacy_stream(struct archive_read_filter *self, const void **p)
|
||||
/* Make sure we have a whole block. */
|
||||
read_buf = __archive_read_filter_ahead(self->upstream,
|
||||
4 + compressed, NULL);
|
||||
if (read_buf == NULL) {
|
||||
archive_set_error(&(self->archive->archive),
|
||||
ARCHIVE_ERRNO_MISC, "truncated lz4 input");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
ret = LZ4_decompress_safe(read_buf + 4, state->out_block,
|
||||
compressed, (int)state->out_block_size);
|
||||
if (ret < 0) {
|
||||
|
@ -436,7 +436,7 @@ lzop_filter_read(struct archive_read_filter *self, const void **p)
|
||||
}
|
||||
|
||||
/*
|
||||
* Drive lzo uncompresison.
|
||||
* Drive lzo uncompression.
|
||||
*/
|
||||
out_size = (lzo_uint)state->uncompressed_size;
|
||||
r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size,
|
||||
|
@ -430,6 +430,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
|
||||
&state->child_stdout);
|
||||
if (child == -1) {
|
||||
free(state->out_buf);
|
||||
archive_string_free(&state->description);
|
||||
free(state);
|
||||
archive_set_error(&self->archive->archive, EINVAL,
|
||||
"Can't initialize filter; unable to run program \"%s\"",
|
||||
@ -441,6 +442,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
|
||||
if (state->child == NULL) {
|
||||
child_stop(self, state);
|
||||
free(state->out_buf);
|
||||
archive_string_free(&state->description);
|
||||
free(state);
|
||||
archive_set_error(&self->archive->archive, EINVAL,
|
||||
"Can't initialize filter; unable to run program \"%s\"",
|
||||
|
@ -312,6 +312,7 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
avail -= len;
|
||||
|
||||
if (l == 6) {
|
||||
/* "begin " */
|
||||
if (!uuchar[*b])
|
||||
return (0);
|
||||
/* Get a length of decoded bytes. */
|
||||
@ -319,30 +320,14 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
if (l > 45)
|
||||
/* Normally, maximum length is 45(character 'M'). */
|
||||
return (0);
|
||||
while (l && len-nl > 0) {
|
||||
if (l > 0) {
|
||||
if (!uuchar[*b++])
|
||||
return (0);
|
||||
if (!uuchar[*b++])
|
||||
return (0);
|
||||
len -= 2;
|
||||
--l;
|
||||
}
|
||||
if (l > 0) {
|
||||
if (!uuchar[*b++])
|
||||
return (0);
|
||||
--len;
|
||||
--l;
|
||||
}
|
||||
if (l > 0) {
|
||||
if (!uuchar[*b++])
|
||||
return (0);
|
||||
--len;
|
||||
--l;
|
||||
}
|
||||
if (l > len - nl)
|
||||
return (0); /* Line too short. */
|
||||
while (l) {
|
||||
if (!uuchar[*b++])
|
||||
return (0);
|
||||
--len;
|
||||
--l;
|
||||
}
|
||||
if (len-nl < 0)
|
||||
return (0);
|
||||
if (len-nl == 1 &&
|
||||
(uuchar[*b] || /* Check sum. */
|
||||
(*b >= 'a' && *b <= 'z'))) {/* Padding data(MINIX). */
|
||||
@ -352,8 +337,8 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
b += nl;
|
||||
if (avail && uuchar[*b])
|
||||
return (firstline+30);
|
||||
}
|
||||
if (l == 13) {
|
||||
} else if (l == 13) {
|
||||
/* "begin-base64 " */
|
||||
while (len-nl > 0) {
|
||||
if (!base64[*b++])
|
||||
return (0);
|
||||
@ -510,6 +495,13 @@ read_more:
|
||||
}
|
||||
llen = len;
|
||||
if ((nl == 0) && (uudecode->state != ST_UUEND)) {
|
||||
if (total == 0 && ravail <= 0) {
|
||||
/* There is nothing more to read, fail */
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Missing format data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/*
|
||||
* Save remaining data which does not contain
|
||||
* NL('\n','\r').
|
||||
@ -566,7 +558,7 @@ read_more:
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/* Get length of undecoded bytes of curent line. */
|
||||
/* Get length of undecoded bytes of current line. */
|
||||
l = UUDECODE(*b++);
|
||||
body--;
|
||||
if (l > body) {
|
||||
|
@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
#if HAVE_LZMA_H
|
||||
#include <cm_lzma.h>
|
||||
#elif HAVE_LZMADEC_H
|
||||
#include <lzmadec.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
@ -82,19 +80,6 @@ static ssize_t xz_filter_read(struct archive_read_filter *, const void **);
|
||||
static int xz_filter_close(struct archive_read_filter *);
|
||||
static int xz_lzma_bidder_init(struct archive_read_filter *);
|
||||
|
||||
#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
|
||||
|
||||
struct private_data {
|
||||
lzmadec_stream stream;
|
||||
unsigned char *out_block;
|
||||
size_t out_block_size;
|
||||
int64_t total_out;
|
||||
char eof; /* True = found end of compressed data. */
|
||||
};
|
||||
|
||||
/* Lzma-only filter */
|
||||
static ssize_t lzma_filter_read(struct archive_read_filter *, const void **);
|
||||
static int lzma_filter_close(struct archive_read_filter *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -178,8 +163,6 @@ archive_read_support_filter_lzma(struct archive *_a)
|
||||
bidder->free = NULL;
|
||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||
return (ARCHIVE_OK);
|
||||
#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external lzma program for lzma decompression");
|
||||
@ -310,7 +293,7 @@ lzma_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
/* Second through fifth bytes are dictionary size, stored in
|
||||
* little-endian order. The minimum dictionary size is
|
||||
* 1 << 12(4KiB) which the lzma of LZMA SDK uses with option
|
||||
* -d12 and the maxinam dictionary size is 1 << 27(128MiB)
|
||||
* -d12 and the maximum dictionary size is 1 << 27(128MiB)
|
||||
* which the one uses with option -d27.
|
||||
* NOTE: A comment of LZMA SDK source code says this dictionary
|
||||
* range is from 1 << 12 to 1 << 30. */
|
||||
@ -601,9 +584,7 @@ lzip_init(struct archive_read_filter *self)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
ret = lzma_raw_decoder(&(state->stream), filters);
|
||||
#if LZMA_VERSION < 50010000
|
||||
free(filters[0].options);
|
||||
#endif
|
||||
if (ret != LZMA_OK) {
|
||||
set_error(self, ret);
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -763,175 +744,6 @@ xz_filter_close(struct archive_read_filter *self)
|
||||
|
||||
#else
|
||||
|
||||
#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC
|
||||
|
||||
/*
|
||||
* If we have the older liblzmadec library, then we can handle
|
||||
* LZMA streams but not XZ streams.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Setup the callbacks.
|
||||
*/
|
||||
static int
|
||||
lzma_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
static const size_t out_block_size = 64 * 1024;
|
||||
void *out_block;
|
||||
struct private_data *state;
|
||||
ssize_t ret, avail_in;
|
||||
|
||||
self->code = ARCHIVE_FILTER_LZMA;
|
||||
self->name = "lzma";
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
out_block = (unsigned char *)malloc(out_block_size);
|
||||
if (state == NULL || out_block == NULL) {
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for lzma decompression");
|
||||
free(out_block);
|
||||
free(state);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = state;
|
||||
state->out_block_size = out_block_size;
|
||||
state->out_block = out_block;
|
||||
self->read = lzma_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = lzma_filter_close;
|
||||
|
||||
/* Prime the lzma library with 18 bytes of input. */
|
||||
state->stream.next_in = (unsigned char *)(uintptr_t)
|
||||
__archive_read_filter_ahead(self->upstream, 18, &avail_in);
|
||||
if (state->stream.next_in == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
state->stream.avail_in = avail_in;
|
||||
state->stream.next_out = state->out_block;
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
|
||||
/* Initialize compression library. */
|
||||
ret = lzmadec_init(&(state->stream));
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
avail_in - state->stream.avail_in);
|
||||
if (ret == LZMADEC_OK)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
/* Library setup failed: Clean up. */
|
||||
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing lzma library");
|
||||
|
||||
/* Override the error message if we know what really went wrong. */
|
||||
switch (ret) {
|
||||
case LZMADEC_HEADER_ERROR:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"invalid header");
|
||||
break;
|
||||
case LZMADEC_MEM_ERROR:
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Internal error initializing compression library: "
|
||||
"out of memory");
|
||||
break;
|
||||
}
|
||||
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
self->data = NULL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next block of decompressed data.
|
||||
*/
|
||||
static ssize_t
|
||||
lzma_filter_read(struct archive_read_filter *self, const void **p)
|
||||
{
|
||||
struct private_data *state;
|
||||
size_t decompressed;
|
||||
ssize_t avail_in, ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
/* Empty our output buffer. */
|
||||
state->stream.next_out = state->out_block;
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
|
||||
/* Try to fill the output buffer. */
|
||||
while (state->stream.avail_out > 0 && !state->eof) {
|
||||
state->stream.next_in = (unsigned char *)(uintptr_t)
|
||||
__archive_read_filter_ahead(self->upstream, 1, &avail_in);
|
||||
if (state->stream.next_in == NULL && avail_in < 0) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"truncated lzma input");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
state->stream.avail_in = avail_in;
|
||||
|
||||
/* Decompress as much as we can in one pass. */
|
||||
ret = lzmadec_decode(&(state->stream), avail_in == 0);
|
||||
switch (ret) {
|
||||
case LZMADEC_STREAM_END: /* Found end of stream. */
|
||||
state->eof = 1;
|
||||
/* FALL THROUGH */
|
||||
case LZMADEC_OK: /* Decompressor made some progress. */
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
avail_in - state->stream.avail_in);
|
||||
break;
|
||||
case LZMADEC_BUF_ERROR: /* Insufficient input data? */
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
default:
|
||||
/* Return an error. */
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Lzma decompression failed");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
decompressed = state->stream.next_out - state->out_block;
|
||||
state->total_out += decompressed;
|
||||
if (decompressed == 0)
|
||||
*p = NULL;
|
||||
else
|
||||
*p = state->out_block;
|
||||
return (decompressed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the decompressor.
|
||||
*/
|
||||
static int
|
||||
lzma_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
int ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
ret = ARCHIVE_OK;
|
||||
switch (lzmadec_end(&(state->stream))) {
|
||||
case LZMADEC_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&(self->archive->archive),
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up %s compressor",
|
||||
self->archive->archive.compression_name);
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
*
|
||||
* If we have no suitable library on this system, we can't actually do
|
||||
@ -953,9 +765,6 @@ lzma_bidder_init(struct archive_read_filter *self)
|
||||
return (r);
|
||||
}
|
||||
|
||||
#endif /* HAVE_LZMADEC_H */
|
||||
|
||||
|
||||
static int
|
||||
xz_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
@ -984,5 +793,4 @@ lzip_bidder_init(struct archive_read_filter *self)
|
||||
return (r);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_LZMA_H */
|
||||
|
@ -213,7 +213,7 @@ struct _7zip {
|
||||
int header_is_encoded;
|
||||
uint64_t header_bytes_remaining;
|
||||
unsigned long header_crc32;
|
||||
/* Header offset to check that reading pointes of the file contens
|
||||
/* Header offset to check that reading points of the file contents
|
||||
* will not exceed the header. */
|
||||
uint64_t header_offset;
|
||||
/* Base offset of the archive file for a seek in case reading SFX. */
|
||||
@ -263,22 +263,22 @@ struct _7zip {
|
||||
/*
|
||||
* Decompressor controllers.
|
||||
*/
|
||||
/* Decording LZMA1 and LZMA2 data. */
|
||||
/* Decoding LZMA1 and LZMA2 data. */
|
||||
#ifdef HAVE_LZMA_H
|
||||
lzma_stream lzstream;
|
||||
int lzstream_valid;
|
||||
#endif
|
||||
/* Decording bzip2 data. */
|
||||
/* Decoding bzip2 data. */
|
||||
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
|
||||
bz_stream bzstream;
|
||||
int bzstream_valid;
|
||||
#endif
|
||||
/* Decording deflate data. */
|
||||
/* Decoding deflate data. */
|
||||
#ifdef HAVE_ZLIB_H
|
||||
z_stream stream;
|
||||
int stream_valid;
|
||||
#endif
|
||||
/* Decording PPMd data. */
|
||||
/* Decoding PPMd data. */
|
||||
int ppmd7_stat;
|
||||
CPpmd7 ppmd7_context;
|
||||
CPpmd7z_RangeDec range_dec;
|
||||
@ -552,7 +552,7 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail)
|
||||
/*
|
||||
* If bytes_avail > SFX_MIN_ADDR we do not have to call
|
||||
* __archive_read_seek() at this time since we have
|
||||
* alredy had enough data.
|
||||
* already had enough data.
|
||||
*/
|
||||
if (bytes_avail > SFX_MIN_ADDR)
|
||||
__archive_read_consume(a, SFX_MIN_ADDR);
|
||||
@ -760,7 +760,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
|
||||
symsize += size;
|
||||
}
|
||||
if (symsize == 0) {
|
||||
/* If there is no synname, handle it as a regular
|
||||
/* If there is no symname, handle it as a regular
|
||||
* file. */
|
||||
zip_entry->mode &= ~AE_IFMT;
|
||||
zip_entry->mode |= AE_IFREG;
|
||||
@ -1056,10 +1056,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
#endif
|
||||
{
|
||||
lzma_options_delta delta_opt;
|
||||
lzma_filter filters[LZMA_FILTERS_MAX];
|
||||
#if LZMA_VERSION < 50010000
|
||||
lzma_filter *ff;
|
||||
#endif
|
||||
lzma_filter filters[LZMA_FILTERS_MAX], *ff;
|
||||
int fi = 0;
|
||||
|
||||
if (zip->lzstream_valid) {
|
||||
@ -1144,9 +1141,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
else
|
||||
filters[fi].id = LZMA_FILTER_LZMA1;
|
||||
filters[fi].options = NULL;
|
||||
#if LZMA_VERSION < 50010000
|
||||
ff = &filters[fi];
|
||||
#endif
|
||||
r = lzma_properties_decode(&filters[fi], NULL,
|
||||
coder1->properties, (size_t)coder1->propertiesSize);
|
||||
if (r != LZMA_OK) {
|
||||
@ -1158,9 +1153,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
filters[fi].id = LZMA_VLI_UNKNOWN;
|
||||
filters[fi].options = NULL;
|
||||
r = lzma_raw_decoder(&(zip->lzstream), filters);
|
||||
#if LZMA_VERSION < 50010000
|
||||
free(ff->options);
|
||||
#endif
|
||||
if (r != LZMA_OK) {
|
||||
set_error(a, r);
|
||||
return (ARCHIVE_FAILED);
|
||||
@ -2431,6 +2424,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||||
|
||||
switch (type) {
|
||||
case kEmptyStream:
|
||||
if (h->emptyStreamBools != NULL)
|
||||
return (-1);
|
||||
h->emptyStreamBools = calloc((size_t)zip->numFiles,
|
||||
sizeof(*h->emptyStreamBools));
|
||||
if (h->emptyStreamBools == NULL)
|
||||
@ -2451,6 +2446,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||||
return (-1);
|
||||
break;
|
||||
}
|
||||
if (h->emptyFileBools != NULL)
|
||||
return (-1);
|
||||
h->emptyFileBools = calloc(empty_streams,
|
||||
sizeof(*h->emptyFileBools));
|
||||
if (h->emptyFileBools == NULL)
|
||||
@ -2465,6 +2462,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||||
return (-1);
|
||||
break;
|
||||
}
|
||||
if (h->antiBools != NULL)
|
||||
return (-1);
|
||||
h->antiBools = calloc(empty_streams,
|
||||
sizeof(*h->antiBools));
|
||||
if (h->antiBools == NULL)
|
||||
@ -2491,6 +2490,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||||
if ((ll & 1) || ll < zip->numFiles * 4)
|
||||
return (-1);
|
||||
|
||||
if (zip->entry_names != NULL)
|
||||
return (-1);
|
||||
zip->entry_names = malloc(ll);
|
||||
if (zip->entry_names == NULL)
|
||||
return (-1);
|
||||
@ -2543,6 +2544,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||||
if ((p = header_bytes(a, 2)) == NULL)
|
||||
return (-1);
|
||||
allAreDefined = *p;
|
||||
if (h->attrBools != NULL)
|
||||
return (-1);
|
||||
h->attrBools = calloc((size_t)zip->numFiles,
|
||||
sizeof(*h->attrBools));
|
||||
if (h->attrBools == NULL)
|
||||
@ -3285,7 +3288,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
|
||||
return (r);
|
||||
|
||||
/*
|
||||
* Skip the bytes we alrady has skipped in skip_stream().
|
||||
* Skip the bytes we already has skipped in skip_stream().
|
||||
*/
|
||||
while (skip_bytes) {
|
||||
ssize_t skipped;
|
||||
@ -3503,7 +3506,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* Allocate memory for the decorded data of a sub
|
||||
/* Allocate memory for the decoded data of a sub
|
||||
* stream. */
|
||||
b[i] = malloc((size_t)zip->folder_outbytes_remaining);
|
||||
if (b[i] == NULL) {
|
||||
@ -3588,7 +3591,7 @@ skip_stream(struct archive_read *a, size_t skip_bytes)
|
||||
if (zip->folder_index == 0) {
|
||||
/*
|
||||
* Optimization for a list mode.
|
||||
* Avoid unncecessary decoding operations.
|
||||
* Avoid unnecessary decoding operations.
|
||||
*/
|
||||
zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes
|
||||
+= skip_bytes;
|
||||
|
@ -104,13 +104,12 @@ archive_read_support_format_ar(struct archive *_a)
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_format_ar");
|
||||
|
||||
ar = (struct ar *)malloc(sizeof(*ar));
|
||||
ar = (struct ar *)calloc(1, sizeof(*ar));
|
||||
if (ar == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate ar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(ar, 0, sizeof(*ar));
|
||||
ar->strtab = NULL;
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
@ -260,7 +259,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
archive_entry_set_filetype(entry, AE_IFREG);
|
||||
/* Get the size of the filename table. */
|
||||
number = ar_atol10(h + AR_size_offset, AR_size_size);
|
||||
if (number > SIZE_MAX) {
|
||||
if (number > SIZE_MAX || number > 1024 * 1024 * 1024) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Filename table too large");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -316,7 +315,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
* If we can't look up the real name, warn and return
|
||||
* the entry with the wrong name.
|
||||
*/
|
||||
if (ar->strtab == NULL || number > ar->strtab_size) {
|
||||
if (ar->strtab == NULL || number >= ar->strtab_size) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Can't find long filename for GNU/SVR4 archive entry");
|
||||
archive_entry_copy_pathname(entry, filename);
|
||||
@ -342,16 +341,19 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
|
||||
/* Parse the size of the name, adjust the file size. */
|
||||
number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3);
|
||||
bsd_name_length = (size_t)number;
|
||||
/* Guard against the filename + trailing NUL
|
||||
* overflowing a size_t and against the filename size
|
||||
* being larger than the entire entry. */
|
||||
if (number > (uint64_t)(bsd_name_length + 1)
|
||||
|| (int64_t)bsd_name_length > ar->entry_bytes_remaining) {
|
||||
/* Sanity check the filename length:
|
||||
* = Must be <= SIZE_MAX - 1
|
||||
* = Must be <= 1MB
|
||||
* = Cannot be bigger than the entire entry
|
||||
*/
|
||||
if (number > SIZE_MAX - 1
|
||||
|| number > 1024 * 1024
|
||||
|| (int64_t)number > ar->entry_bytes_remaining) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Bad input file size");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
bsd_name_length = (size_t)number;
|
||||
ar->entry_bytes_remaining -= bsd_name_length;
|
||||
/* Adjust file size reported to client. */
|
||||
archive_entry_set_size(entry, ar->entry_bytes_remaining);
|
||||
|
@ -67,7 +67,7 @@ struct lzx_dec {
|
||||
/* The length how many bytes we can copy decoded code from
|
||||
* the window. */
|
||||
int copy_len;
|
||||
/* Translation reversal for x86 proccessor CALL byte sequence(E8).
|
||||
/* Translation reversal for x86 processor CALL byte sequence(E8).
|
||||
* This is used for LZX only. */
|
||||
uint32_t translation_size;
|
||||
char translation;
|
||||
@ -645,12 +645,13 @@ cab_read_header(struct archive_read *a)
|
||||
cab = (struct cab *)(a->format->data);
|
||||
if (cab->found_header == 0 &&
|
||||
p[0] == 'M' && p[1] == 'Z') {
|
||||
/* This is an executable? Must be self-extracting... */
|
||||
/* This is an executable? Must be self-extracting... */
|
||||
err = cab_skip_sfx(a);
|
||||
if (err < ARCHIVE_WARN)
|
||||
return (err);
|
||||
|
||||
if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL)
|
||||
/* Re-read header after processing the SFX. */
|
||||
if ((p = __archive_read_ahead(a, 42, NULL)) == NULL)
|
||||
return (truncated_error(a));
|
||||
}
|
||||
|
||||
@ -1494,6 +1495,8 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
|
||||
|
||||
/* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */
|
||||
if (mszip > 0) {
|
||||
if (bytes_avail <= 0)
|
||||
goto nomszip;
|
||||
if (bytes_avail <= mszip) {
|
||||
if (mszip == 2) {
|
||||
if (cab->stream.next_in[0] != 0x43)
|
||||
@ -1554,7 +1557,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
|
||||
/*
|
||||
* Note: I suspect there is a bug in makecab.exe because, in rare
|
||||
* case, compressed bytes are still remaining regardless we have
|
||||
* gotten all uncompressed bytes, which size is recoded in CFDATA,
|
||||
* gotten all uncompressed bytes, which size is recorded in CFDATA,
|
||||
* as much as we need, and we have to use the garbage so as to
|
||||
* correctly compute the sum of CFDATA accordingly.
|
||||
*/
|
||||
@ -1741,7 +1744,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
|
||||
}
|
||||
|
||||
/*
|
||||
* Translation reversal of x86 proccessor CALL byte sequence(E8).
|
||||
* Translation reversal of x86 processor CALL byte sequence(E8).
|
||||
*/
|
||||
lzx_translation(&cab->xstrm, cab->uncompressed_buffer,
|
||||
cfdata->uncompressed_size,
|
||||
@ -2270,7 +2273,7 @@ static int
|
||||
lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br)
|
||||
{
|
||||
/*
|
||||
* x86 proccessor family can read misaligned data without an access error.
|
||||
* x86 processor family can read misaligned data without an access error.
|
||||
*/
|
||||
int n = CACHE_BITS - br->cache_avail;
|
||||
|
||||
|
@ -326,7 +326,7 @@ archive_read_format_cpio_options(struct archive_read *a,
|
||||
|
||||
cpio = (struct cpio *)(a->format->data);
|
||||
if (strcmp(key, "compat-2x") == 0) {
|
||||
/* Handle filnames as libarchive 2.x */
|
||||
/* Handle filenames as libarchive 2.x */
|
||||
cpio->init_default_conversion = (val != NULL)?1:0;
|
||||
return (ARCHIVE_OK);
|
||||
} else if (strcmp(key, "hdrcharset") == 0) {
|
||||
@ -356,7 +356,7 @@ archive_read_format_cpio_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
struct cpio *cpio;
|
||||
const void *h;
|
||||
const void *h, *hl;
|
||||
struct archive_string_conv *sconv;
|
||||
size_t namelength;
|
||||
size_t name_pad;
|
||||
@ -406,11 +406,11 @@ archive_read_format_cpio_read_header(struct archive_read *a,
|
||||
"Rejecting malformed cpio archive: symlink contents exceed 1 megabyte");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
h = __archive_read_ahead(a,
|
||||
hl = __archive_read_ahead(a,
|
||||
(size_t)cpio->entry_bytes_remaining, NULL);
|
||||
if (h == NULL)
|
||||
if (hl == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (archive_entry_copy_symlink_l(entry, (const char *)h,
|
||||
if (archive_entry_copy_symlink_l(entry, (const char *)hl,
|
||||
(size_t)cpio->entry_bytes_remaining, sconv) != 0) {
|
||||
if (errno == ENOMEM) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
@ -434,7 +434,8 @@ archive_read_format_cpio_read_header(struct archive_read *a,
|
||||
* header. XXX */
|
||||
|
||||
/* Compare name to "TRAILER!!!" to test for end-of-archive. */
|
||||
if (namelength == 11 && strcmp((const char *)h, "TRAILER!!!") == 0) {
|
||||
if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!",
|
||||
11) == 0) {
|
||||
/* TODO: Store file location of start of block. */
|
||||
archive_clear_error(&a->archive);
|
||||
return (ARCHIVE_EOF);
|
||||
@ -814,8 +815,8 @@ header_odc(struct archive_read *a, struct cpio *cpio,
|
||||
* NOTE: if a filename suffix is ".z", it is the file gziped by afio.
|
||||
* it would be nice that we can show uncompressed file size and we can
|
||||
* uncompressed file contents automatically, unfortunately we have nothing
|
||||
* to get a uncompressed file size while reading each header. it means
|
||||
* we also cannot uncompressed file contens under the our framework.
|
||||
* to get a uncompressed file size while reading each header. It means
|
||||
* we also cannot uncompress file contents under our framework.
|
||||
*/
|
||||
static int
|
||||
header_afiol(struct archive_read *a, struct cpio *cpio,
|
||||
|
@ -322,7 +322,7 @@ struct iso9660 {
|
||||
|
||||
struct archive_string pathname;
|
||||
char seenRockridge; /* Set true if RR extensions are used. */
|
||||
char seenSUSP; /* Set true if SUSP is beging used. */
|
||||
char seenSUSP; /* Set true if SUSP is being used. */
|
||||
char seenJoliet;
|
||||
|
||||
unsigned char suspOffset;
|
||||
@ -374,7 +374,7 @@ 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. */
|
||||
/* Null buffer used in bidder to improve its performance. */
|
||||
unsigned char null[2048];
|
||||
};
|
||||
|
||||
@ -1199,7 +1199,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
|
||||
archive_string_conversion_from_charset(
|
||||
&(a->archive), "UTF-16BE", 1);
|
||||
if (iso9660->sconv_utf16be == NULL)
|
||||
/* Coundn't allocate memory */
|
||||
/* Couldn't allocate memory */
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (iso9660->utf16be_path == NULL) {
|
||||
@ -1864,7 +1864,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
if ((file->utf16be_name = malloc(name_len)) == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"No memory for file name");
|
||||
return (NULL);
|
||||
goto fail;
|
||||
}
|
||||
memcpy(file->utf16be_name, p, name_len);
|
||||
file->utf16be_bytes = name_len;
|
||||
@ -1943,10 +1943,8 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
file->symlink_continues = 0;
|
||||
rr_start += iso9660->suspOffset;
|
||||
r = parse_rockridge(a, file, rr_start, rr_end);
|
||||
if (r != ARCHIVE_OK) {
|
||||
free(file);
|
||||
return (NULL);
|
||||
}
|
||||
if (r != ARCHIVE_OK)
|
||||
goto fail;
|
||||
/*
|
||||
* A file size of symbolic link files in ISO images
|
||||
* made by makefs is not zero and its location is
|
||||
@ -1990,7 +1988,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Invalid Rockridge RE");
|
||||
return (NULL);
|
||||
goto fail;
|
||||
}
|
||||
/*
|
||||
* Sanity check: file does not have "CL" extension.
|
||||
@ -1999,7 +1997,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Invalid Rockridge RE and CL");
|
||||
return (NULL);
|
||||
goto fail;
|
||||
}
|
||||
/*
|
||||
* Sanity check: The file type must be a directory.
|
||||
@ -2008,7 +2006,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Invalid Rockridge RE");
|
||||
return (NULL);
|
||||
goto fail;
|
||||
}
|
||||
} else if (parent != NULL && parent->rr_moved)
|
||||
file->rr_moved_has_re_only = 0;
|
||||
@ -2022,7 +2020,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Invalid Rockridge CL");
|
||||
return (NULL);
|
||||
goto fail;
|
||||
}
|
||||
/*
|
||||
* Sanity check: The file type must be a regular file.
|
||||
@ -2031,7 +2029,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Invalid Rockridge CL");
|
||||
return (NULL);
|
||||
goto fail;
|
||||
}
|
||||
parent->subdirs++;
|
||||
/* Overwrite an offset and a number of this "CL" entry
|
||||
@ -2049,7 +2047,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Invalid Rockridge CL");
|
||||
return (NULL);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (file->cl_offset == file->offset ||
|
||||
@ -2057,7 +2055,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Invalid Rockridge CL");
|
||||
return (NULL);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2088,6 +2086,10 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
#endif
|
||||
register_file(iso9660, file);
|
||||
return (file);
|
||||
fail:
|
||||
archive_string_free(&file->name);
|
||||
free(file);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2407,7 +2409,7 @@ read_CE(struct archive_read *a, struct iso9660 *iso9660)
|
||||
return (ARCHIVE_FATAL);
|
||||
} while (heap->cnt &&
|
||||
heap->reqs[0].offset == iso9660->current_position);
|
||||
/* NOTE: Do not move this consume's code to fron of
|
||||
/* NOTE: Do not move this consume's code to front of
|
||||
* do-while loop. Registration of nested CE extension
|
||||
* might cause error because of current position. */
|
||||
__archive_read_consume(a, step);
|
||||
@ -2729,7 +2731,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
|
||||
if (file == NULL) {
|
||||
/*
|
||||
* If directory entries all which are descendant of
|
||||
* rr_moved are stil remaning, expose their.
|
||||
* rr_moved are still remaining, expose their.
|
||||
*/
|
||||
if (iso9660->re_files.first != NULL &&
|
||||
iso9660->rr_moved != NULL &&
|
||||
@ -2852,7 +2854,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
|
||||
empty_files.last = &empty_files.first;
|
||||
/* Collect files which has the same file serial number.
|
||||
* Peek pending_files so that file which number is different
|
||||
* is not put bak. */
|
||||
* is not put back. */
|
||||
while (iso9660->pending_files.used > 0 &&
|
||||
(iso9660->pending_files.files[0]->number == -1 ||
|
||||
iso9660->pending_files.files[0]->number == number)) {
|
||||
@ -2860,7 +2862,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
|
||||
/* This file has the same offset
|
||||
* but it's wrong offset which empty files
|
||||
* and symlink files have.
|
||||
* NOTE: This wrong offse was recorded by
|
||||
* NOTE: This wrong offset was recorded by
|
||||
* old mkisofs utility. If ISO images is
|
||||
* created by latest mkisofs, this does not
|
||||
* happen.
|
||||
|
@ -924,6 +924,9 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha)
|
||||
/* Get a real compressed file size. */
|
||||
lha->compsize -= extdsize - 2;
|
||||
|
||||
if (lha->compsize < 0)
|
||||
goto invalid; /* Invalid compressed file size */
|
||||
|
||||
if (sum_calculated != headersum) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"LHa header sum error");
|
||||
@ -1711,14 +1714,18 @@ lha_crc16(uint16_t crc, const void *pp, size_t len)
|
||||
*/
|
||||
for (;len >= 8; len -= 8) {
|
||||
/* This if statement expects compiler optimization will
|
||||
* remove the stament which will not be executed. */
|
||||
* remove the statement which will not be executed. */
|
||||
#undef bswap16
|
||||
#ifndef __has_builtin
|
||||
# define __has_builtin(x) 0
|
||||
#endif
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400 /* Visual Studio */
|
||||
# define bswap16(x) _byteswap_ushort(x)
|
||||
#elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8) \
|
||||
|| (defined(__clang__) && __has_builtin(__builtin_bswap16))
|
||||
#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4)
|
||||
/* GCC 4.8 and later has __builtin_bswap16() */
|
||||
# define bswap16(x) __builtin_bswap16(x)
|
||||
#elif defined(__clang__) && __has_builtin(__builtin_bswap16)
|
||||
/* All clang versions have __builtin_bswap16() */
|
||||
# define bswap16(x) __builtin_bswap16(x)
|
||||
#else
|
||||
# define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8))
|
||||
|
@ -75,6 +75,8 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
|
||||
#define MTREE_HAS_OPTIONAL 0x0800
|
||||
#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
|
||||
|
||||
#define MTREE_HASHTABLE_SIZE 1024
|
||||
|
||||
struct mtree_option {
|
||||
struct mtree_option *next;
|
||||
char *value;
|
||||
@ -86,6 +88,8 @@ struct mtree_entry {
|
||||
char *name;
|
||||
char full;
|
||||
char used;
|
||||
unsigned int name_hash;
|
||||
struct mtree_entry *hashtable_next;
|
||||
};
|
||||
|
||||
struct mtree {
|
||||
@ -98,6 +102,7 @@ struct mtree {
|
||||
const char *archive_format_name;
|
||||
struct mtree_entry *entries;
|
||||
struct mtree_entry *this_entry;
|
||||
struct mtree_entry *entry_hashtable[MTREE_HASHTABLE_SIZE];
|
||||
struct archive_string current_dir;
|
||||
struct archive_string contents_name;
|
||||
|
||||
@ -110,6 +115,7 @@ struct mtree {
|
||||
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 unsigned int hash(const char *);
|
||||
static int mtree_bid(struct archive_read *, int);
|
||||
static int parse_file(struct archive_read *, struct archive_entry *,
|
||||
struct mtree *, struct mtree_entry *, int *);
|
||||
@ -223,13 +229,12 @@ archive_read_support_format_mtree(struct archive *_a)
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_format_mtree");
|
||||
|
||||
mtree = (struct mtree *)malloc(sizeof(*mtree));
|
||||
mtree = (struct mtree *)calloc(1, sizeof(*mtree));
|
||||
if (mtree == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate mtree data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(mtree, 0, sizeof(*mtree));
|
||||
mtree->fd = -1;
|
||||
|
||||
r = __archive_read_register_format(a, mtree, "mtree",
|
||||
@ -301,6 +306,15 @@ get_line_size(const char *b, ssize_t avail, ssize_t *nlsize)
|
||||
return (avail);
|
||||
}
|
||||
|
||||
/*
|
||||
* <---------------- ravail --------------------->
|
||||
* <-- diff ------> <--- avail ----------------->
|
||||
* <---- len ----------->
|
||||
* | Previous lines | line being parsed nl extra |
|
||||
* ^
|
||||
* b
|
||||
*
|
||||
*/
|
||||
static ssize_t
|
||||
next_line(struct archive_read *a,
|
||||
const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl)
|
||||
@ -339,7 +353,7 @@ next_line(struct archive_read *a,
|
||||
*b += diff;
|
||||
*avail -= diff;
|
||||
tested = len;/* Skip some bytes we already determinated. */
|
||||
len = get_line_size(*b, *avail, nl);
|
||||
len = get_line_size(*b + len, *avail - len, nl);
|
||||
if (len >= 0)
|
||||
len += tested;
|
||||
}
|
||||
@ -701,13 +715,13 @@ detect_form(struct archive_read *a, int *is_form_d)
|
||||
}
|
||||
} else
|
||||
break;
|
||||
} else if (strncmp(p, "/set", 4) == 0) {
|
||||
} else if (len > 4 && strncmp(p, "/set", 4) == 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) {
|
||||
} else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
|
||||
if (bid_keyword_list(p+6, len-6, 1, 0) <= 0)
|
||||
break;
|
||||
/* This line continues. */
|
||||
@ -853,11 +867,12 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
||||
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_entry *entry, *ht_iter;
|
||||
struct mtree_option *iter;
|
||||
const char *next, *eq, *name, *end;
|
||||
size_t name_len, len;
|
||||
int r, i;
|
||||
unsigned int ht_idx;
|
||||
|
||||
if ((entry = malloc(sizeof(*entry))) == NULL) {
|
||||
archive_set_error(&a->archive, errno, "Can't allocate memory");
|
||||
@ -868,6 +883,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
||||
entry->name = NULL;
|
||||
entry->used = 0;
|
||||
entry->full = 0;
|
||||
entry->name_hash = 0;
|
||||
entry->hashtable_next = NULL;
|
||||
|
||||
/* Add this entry to list. */
|
||||
if (*last_entry == NULL)
|
||||
@ -920,6 +937,16 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
||||
memcpy(entry->name, name, name_len);
|
||||
entry->name[name_len] = '\0';
|
||||
parse_escapes(entry->name, entry);
|
||||
entry->name_hash = hash(entry->name);
|
||||
|
||||
ht_idx = entry->name_hash % MTREE_HASHTABLE_SIZE;
|
||||
if ((ht_iter = mtree->entry_hashtable[ht_idx]) != NULL) {
|
||||
while (ht_iter->hashtable_next)
|
||||
ht_iter = ht_iter->hashtable_next;
|
||||
ht_iter->hashtable_next = entry;
|
||||
} else {
|
||||
mtree->entry_hashtable[ht_idx] = entry;
|
||||
}
|
||||
|
||||
for (iter = *global; iter != NULL; iter = iter->next) {
|
||||
r = add_option(a, &entry->options, iter->value,
|
||||
@ -992,11 +1019,11 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
|
||||
if (*p != '/') {
|
||||
r = process_add_entry(a, mtree, &global, p, len,
|
||||
&last_entry, is_form_d);
|
||||
} else if (strncmp(p, "/set", 4) == 0) {
|
||||
} else if (len > 4 && strncmp(p, "/set", 4) == 0) {
|
||||
if (p[4] != ' ' && p[4] != '\t')
|
||||
break;
|
||||
r = process_global_set(a, &global, p);
|
||||
} else if (strncmp(p, "/unset", 6) == 0) {
|
||||
} else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
|
||||
if (p[6] != ' ' && p[6] != '\t')
|
||||
break;
|
||||
r = process_global_unset(a, &global, p);
|
||||
@ -1113,9 +1140,10 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
|
||||
* with pathname canonicalization, which is a very
|
||||
* tricky subject.)
|
||||
*/
|
||||
for (mp = mentry->next; mp != NULL; mp = mp->next) {
|
||||
for (mp = mentry->hashtable_next; mp != NULL; mp = mp->hashtable_next) {
|
||||
if (mp->full && !mp->used
|
||||
&& strcmp(mentry->name, mp->name) == 0) {
|
||||
&& mentry->name_hash == mp->name_hash
|
||||
&& strcmp(mentry->name, mp->name) == 0) {
|
||||
/* Later lines override earlier ones. */
|
||||
mp->used = 1;
|
||||
r1 = parse_line(a, entry, mtree, mp,
|
||||
@ -1580,8 +1608,11 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
||||
if (*val == '.') {
|
||||
++val;
|
||||
ns = (long)mtree_atol10(&val);
|
||||
} else
|
||||
ns = 0;
|
||||
if (ns < 0)
|
||||
ns = 0;
|
||||
else if (ns > 999999999)
|
||||
ns = 999999999;
|
||||
}
|
||||
if (m > my_time_t_max)
|
||||
m = my_time_t_max;
|
||||
else if (m < my_time_t_min)
|
||||
@ -1991,3 +2022,19 @@ readline(struct archive_read *a, struct mtree *mtree, char **start,
|
||||
find_off = u - mtree->line.s;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
hash(const char *p)
|
||||
{
|
||||
/* A 32-bit version of Peter Weinberger's (PJW) hash algorithm,
|
||||
as used by ELF for hashing function names. */
|
||||
unsigned g, h = 0;
|
||||
while (*p != '\0') {
|
||||
h = (h << 4) + *p++;
|
||||
if ((g = h & 0xF0000000) != 0) {
|
||||
h ^= g >> 24;
|
||||
h &= 0x0FFFFFFF;
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
@ -647,13 +647,12 @@ archive_read_support_format_rar(struct archive *_a)
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
||||
"archive_read_support_format_rar");
|
||||
|
||||
rar = (struct rar *)malloc(sizeof(*rar));
|
||||
rar = (struct rar *)calloc(sizeof(*rar), 1);
|
||||
if (rar == NULL)
|
||||
{
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate rar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(rar, 0, sizeof(*rar));
|
||||
|
||||
/*
|
||||
* Until enough data has been read, we cannot tell about
|
||||
@ -907,7 +906,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
sizeof(rar->reserved2));
|
||||
}
|
||||
|
||||
/* Main header is password encrytped, so we cannot read any
|
||||
/* Main header is password encrypted, so we cannot read any
|
||||
file names or any other info about files from the header. */
|
||||
if (rar->main_flags & MHD_PASSWORD)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2011-2012 Michihiro NAKAJIMA
|
||||
* Copyright (c) 2016 Martin Matuska
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -136,6 +137,7 @@ struct tar {
|
||||
int64_t entry_padding;
|
||||
int64_t entry_bytes_unconsumed;
|
||||
int64_t realsize;
|
||||
int sparse_allowed;
|
||||
struct sparse_block *sparse_list;
|
||||
struct sparse_block *sparse_last;
|
||||
int64_t sparse_offset;
|
||||
@ -202,9 +204,14 @@ static int archive_read_format_tar_read_header(struct archive_read *,
|
||||
struct archive_entry *);
|
||||
static int checksum(struct archive_read *, const void *);
|
||||
static int pax_attribute(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const char *key, const char *value);
|
||||
struct archive_entry *, const char *key, const char *value,
|
||||
size_t value_length);
|
||||
static int pax_attribute_acl(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const char *, int);
|
||||
static int pax_attribute_xattr(struct archive_entry *, const char *,
|
||||
const char *);
|
||||
static int pax_header(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, char *attr);
|
||||
struct archive_entry *, struct archive_string *);
|
||||
static void pax_time(const char *, int64_t *sec, long *nanos);
|
||||
static ssize_t readline(struct archive_read *, struct tar *, const char **,
|
||||
ssize_t limit, size_t *);
|
||||
@ -293,6 +300,57 @@ archive_read_format_tar_cleanup(struct archive_read *a)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate number field
|
||||
*
|
||||
* This has to be pretty lenient in order to accommodate the enormous
|
||||
* variety of tar writers in the world:
|
||||
* = POSIX (IEEE Std 1003.1-1988) ustar requires octal values with leading
|
||||
* zeros and allows fields to be terminated with space or null characters
|
||||
* = Many writers use different termination (in particular, libarchive
|
||||
* omits terminator bytes to squeeze one or two more digits)
|
||||
* = Many writers pad with space and omit leading zeros
|
||||
* = GNU tar and star write base-256 values if numbers are too
|
||||
* big to be represented in octal
|
||||
*
|
||||
* Examples of specific tar headers that we should support:
|
||||
* = Perl Archive::Tar terminates uid, gid, devminor and devmajor with two
|
||||
* null bytes, pads size with spaces and other numeric fields with zeroes
|
||||
* = plexus-archiver prior to 2.6.3 (before switching to commons-compress)
|
||||
* may have uid and gid fields filled with spaces without any octal digits
|
||||
* at all and pads all numeric fields with spaces
|
||||
*
|
||||
* This should tolerate all variants in use. It will reject a field
|
||||
* where the writer just left garbage after a trailing NUL.
|
||||
*/
|
||||
static int
|
||||
validate_number_field(const char* p_field, size_t i_size)
|
||||
{
|
||||
unsigned char marker = (unsigned char)p_field[0];
|
||||
if (marker == 128 || marker == 255 || marker == 0) {
|
||||
/* Base-256 marker, there's nothing we can check. */
|
||||
return 1;
|
||||
} else {
|
||||
/* Must be octal */
|
||||
size_t i = 0;
|
||||
/* Skip any leading spaces */
|
||||
while (i < i_size && p_field[i] == ' ') {
|
||||
++i;
|
||||
}
|
||||
/* Skip octal digits. */
|
||||
while (i < i_size && p_field[i] >= '0' && p_field[i] <= '7') {
|
||||
++i;
|
||||
}
|
||||
/* Any remaining characters must be space or NUL padding. */
|
||||
while (i < i_size) {
|
||||
if (p_field[i] != ' ' && p_field[i] != 0) {
|
||||
return 0;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_tar_bid(struct archive_read *a, int best_bid)
|
||||
@ -345,23 +403,19 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid)
|
||||
return (0);
|
||||
bid += 2; /* 6 bits of variation in an 8-bit field leaves 2 bits. */
|
||||
|
||||
/* Sanity check: Look at first byte of mode field. */
|
||||
switch (255 & (unsigned)header->mode[0]) {
|
||||
case 0: case 255:
|
||||
/* Base-256 value: No further verification possible! */
|
||||
break;
|
||||
case ' ': /* Not recommended, but not illegal, either. */
|
||||
break;
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
/* Octal Value. */
|
||||
/* TODO: Check format of remainder of this field. */
|
||||
break;
|
||||
default:
|
||||
/* Not a valid mode; bail out here. */
|
||||
return (0);
|
||||
/*
|
||||
* Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields.
|
||||
*/
|
||||
if (bid > 0 && (
|
||||
validate_number_field(header->mode, sizeof(header->mode)) == 0
|
||||
|| validate_number_field(header->uid, sizeof(header->uid)) == 0
|
||||
|| validate_number_field(header->gid, sizeof(header->gid)) == 0
|
||||
|| validate_number_field(header->mtime, sizeof(header->mtime)) == 0
|
||||
|| validate_number_field(header->size, sizeof(header->size)) == 0
|
||||
|| validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0
|
||||
|| validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) {
|
||||
bid = 0;
|
||||
}
|
||||
/* TODO: Sanity test uid/gid/size/mtime/rdevmajor/rdevminor fields. */
|
||||
|
||||
return (bid);
|
||||
}
|
||||
@ -375,7 +429,7 @@ archive_read_format_tar_options(struct archive_read *a,
|
||||
|
||||
tar = (struct tar *)(a->format->data);
|
||||
if (strcmp(key, "compat-2x") == 0) {
|
||||
/* Handle UTF-8 filnames as libarchive 2.x */
|
||||
/* Handle UTF-8 filenames as libarchive 2.x */
|
||||
tar->compat_2x = (val != NULL && val[0] != 0);
|
||||
tar->init_default_conversion = tar->compat_2x;
|
||||
return (ARCHIVE_OK);
|
||||
@ -793,9 +847,9 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
||||
tar->sparse_gnu_pending = 0;
|
||||
/* Read initial sparse map. */
|
||||
bytes_read = gnu_sparse_10_read(a, tar, unconsumed);
|
||||
tar->entry_bytes_remaining -= bytes_read;
|
||||
if (bytes_read < 0)
|
||||
return ((int)bytes_read);
|
||||
tar->entry_bytes_remaining -= bytes_read;
|
||||
} else {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
@ -890,7 +944,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
|
||||
{
|
||||
const struct archive_entry_header_ustar *header;
|
||||
size_t size;
|
||||
int err;
|
||||
int err, acl_type;
|
||||
int64_t type;
|
||||
char *acl, *p;
|
||||
|
||||
@ -935,11 +989,12 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
|
||||
switch ((int)type & ~0777777) {
|
||||
case 01000000:
|
||||
/* POSIX.1e ACL */
|
||||
acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
|
||||
break;
|
||||
case 03000000:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Solaris NFSv4 ACLs not supported");
|
||||
return (ARCHIVE_WARN);
|
||||
/* NFSv4 ACL */
|
||||
acl_type = ARCHIVE_ENTRY_ACL_TYPE_NFS4;
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Malformed Solaris ACL attribute (unsupported type %o)",
|
||||
@ -968,8 +1023,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar,
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_strncpy(&(tar->localname), acl, p - acl);
|
||||
err = archive_acl_parse_l(archive_entry_acl(entry),
|
||||
tar->localname.s, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, tar->sconv_acl);
|
||||
err = archive_acl_from_text_l(archive_entry_acl(entry),
|
||||
tar->localname.s, acl_type, tar->sconv_acl);
|
||||
if (err != ARCHIVE_OK) {
|
||||
if (errno == ENOMEM) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
@ -1128,8 +1183,15 @@ header_common(struct archive_read *a, struct tar *tar,
|
||||
if (tar->entry_bytes_remaining < 0) {
|
||||
tar->entry_bytes_remaining = 0;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Tar entry has negative size?");
|
||||
err = ARCHIVE_WARN;
|
||||
"Tar entry has negative size");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (tar->entry_bytes_remaining == INT64_MAX) {
|
||||
/* Note: tar_atol returns INT64_MAX on overflow */
|
||||
tar->entry_bytes_remaining = 0;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Tar entry size overflow");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
tar->realsize = tar->entry_bytes_remaining;
|
||||
archive_entry_set_size(entry, tar->entry_bytes_remaining);
|
||||
@ -1264,6 +1326,14 @@ header_common(struct archive_read *a, struct tar *tar,
|
||||
* sparse information in the extended area.
|
||||
*/
|
||||
/* FALLTHROUGH */
|
||||
case '0':
|
||||
/*
|
||||
* Enable sparse file "read" support only for regular
|
||||
* files and explicit GNU sparse files. However, we
|
||||
* don't allow non-standard file types to be sparse.
|
||||
*/
|
||||
tar->sparse_allowed = 1;
|
||||
/* FALLTHROUGH */
|
||||
default: /* Regular file and non-standard types */
|
||||
/*
|
||||
* Per POSIX: non-recognized types should always be
|
||||
@ -1415,7 +1485,7 @@ header_pax_extensions(struct archive_read *a, struct tar *tar,
|
||||
* and then skip any fields in the standard header that were
|
||||
* defined in the pax header.
|
||||
*/
|
||||
err2 = pax_header(a, tar, entry, tar->pax_header.s);
|
||||
err2 = pax_header(a, tar, entry, &tar->pax_header);
|
||||
err = err_combine(err, err2);
|
||||
tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining);
|
||||
return (err);
|
||||
@ -1496,16 +1566,17 @@ header_ustar(struct archive_read *a, struct tar *tar,
|
||||
*/
|
||||
static int
|
||||
pax_header(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, char *attr)
|
||||
struct archive_entry *entry, struct archive_string *in_as)
|
||||
{
|
||||
size_t attr_length, l, line_length;
|
||||
size_t attr_length, l, line_length, value_length;
|
||||
char *p;
|
||||
char *key, *value;
|
||||
struct archive_string *as;
|
||||
struct archive_string_conv *sconv;
|
||||
int err, err2;
|
||||
char *attr = in_as->s;
|
||||
|
||||
attr_length = strlen(attr);
|
||||
attr_length = in_as->length;
|
||||
tar->pax_hdrcharset_binary = 0;
|
||||
archive_string_empty(&(tar->entry_gname));
|
||||
archive_string_empty(&(tar->entry_linkpath));
|
||||
@ -1570,11 +1641,13 @@ pax_header(struct archive_read *a, struct tar *tar,
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
/* Identify null-terminated 'value' portion. */
|
||||
value = p + 1;
|
||||
|
||||
/* Some values may be binary data */
|
||||
value_length = attr + line_length - 1 - value;
|
||||
|
||||
/* Identify this attribute and set it in the entry. */
|
||||
err2 = pax_attribute(a, tar, entry, key, value);
|
||||
err2 = pax_attribute(a, tar, entry, key, value, value_length);
|
||||
if (err2 == ARCHIVE_FATAL)
|
||||
return (err2);
|
||||
err = err_combine(err, err2);
|
||||
@ -1695,6 +1768,66 @@ pax_attribute_xattr(struct archive_entry *entry,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pax_attribute_schily_xattr(struct archive_entry *entry,
|
||||
const char *name, const char *value, size_t value_length)
|
||||
{
|
||||
if (strlen(name) < 14 || (memcmp(name, "SCHILY.xattr.", 13)) != 0)
|
||||
return 1;
|
||||
|
||||
name += 13;
|
||||
|
||||
archive_entry_xattr_add_entry(entry, name, value, value_length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pax_attribute_acl(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const char *value, int type)
|
||||
{
|
||||
int r;
|
||||
const char* errstr;
|
||||
|
||||
switch (type) {
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
|
||||
errstr = "SCHILY.acl.access";
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
|
||||
errstr = "SCHILY.acl.default";
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
|
||||
errstr = "SCHILY.acl.ace";
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Unknown ACL type: %d", type);
|
||||
return(ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (tar->sconv_acl == NULL) {
|
||||
tar->sconv_acl =
|
||||
archive_string_conversion_from_charset(
|
||||
&(a->archive), "UTF-8", 1);
|
||||
if (tar->sconv_acl == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
r = archive_acl_from_text_l(archive_entry_acl(entry), value, type,
|
||||
tar->sconv_acl);
|
||||
if (r != ARCHIVE_OK) {
|
||||
if (r == ARCHIVE_FATAL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"%s %s", "Can't allocate memory for ",
|
||||
errstr);
|
||||
return (r);
|
||||
}
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC, "%s %s", "Parse error: ", errstr);
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a single key=value attribute. key/value pointers are
|
||||
* assumed to point into reasonably long-lived storage.
|
||||
@ -1710,7 +1843,7 @@ pax_attribute_xattr(struct archive_entry *entry,
|
||||
*/
|
||||
static int
|
||||
pax_attribute(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const char *key, const char *value)
|
||||
struct archive_entry *entry, const char *key, const char *value, size_t value_length)
|
||||
{
|
||||
int64_t s;
|
||||
long n;
|
||||
@ -1721,6 +1854,14 @@ pax_attribute(struct archive_read *a, struct tar *tar,
|
||||
* NULL pointer to strlen(). */
|
||||
switch (key[0]) {
|
||||
case 'G':
|
||||
/* Reject GNU.sparse.* headers on non-regular files. */
|
||||
if (strncmp(key, "GNU.sparse", 10) == 0 &&
|
||||
!tar->sparse_allowed) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Non-regular file cannot be sparse");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* GNU "0.0" sparse pax format. */
|
||||
if (strcmp(key, "GNU.sparse.numblocks") == 0) {
|
||||
tar->sparse_offset = -1;
|
||||
@ -1803,53 +1944,20 @@ pax_attribute(struct archive_read *a, struct tar *tar,
|
||||
case 'S':
|
||||
/* We support some keys used by the "star" archiver */
|
||||
if (strcmp(key, "SCHILY.acl.access") == 0) {
|
||||
if (tar->sconv_acl == NULL) {
|
||||
tar->sconv_acl =
|
||||
archive_string_conversion_from_charset(
|
||||
&(a->archive), "UTF-8", 1);
|
||||
if (tar->sconv_acl == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
r = archive_acl_parse_l(archive_entry_acl(entry),
|
||||
value, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
|
||||
tar->sconv_acl);
|
||||
if (r != ARCHIVE_OK) {
|
||||
err = r;
|
||||
if (err == ARCHIVE_FATAL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory for "
|
||||
"SCHILY.acl.access");
|
||||
return (err);
|
||||
}
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Parse error: SCHILY.acl.access");
|
||||
}
|
||||
r = pax_attribute_acl(a, tar, entry, value,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
|
||||
if (r == ARCHIVE_FATAL)
|
||||
return (r);
|
||||
} else if (strcmp(key, "SCHILY.acl.default") == 0) {
|
||||
if (tar->sconv_acl == NULL) {
|
||||
tar->sconv_acl =
|
||||
archive_string_conversion_from_charset(
|
||||
&(a->archive), "UTF-8", 1);
|
||||
if (tar->sconv_acl == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
r = archive_acl_parse_l(archive_entry_acl(entry),
|
||||
value, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
|
||||
tar->sconv_acl);
|
||||
if (r != ARCHIVE_OK) {
|
||||
err = r;
|
||||
if (err == ARCHIVE_FATAL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory for "
|
||||
"SCHILY.acl.default");
|
||||
return (err);
|
||||
}
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Parse error: SCHILY.acl.default");
|
||||
}
|
||||
r = pax_attribute_acl(a, tar, entry, value,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
|
||||
if (r == ARCHIVE_FATAL)
|
||||
return (r);
|
||||
} else if (strcmp(key, "SCHILY.acl.ace") == 0) {
|
||||
r = pax_attribute_acl(a, tar, entry, value,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_NFS4);
|
||||
if (r == ARCHIVE_FATAL)
|
||||
return (r);
|
||||
} else if (strcmp(key, "SCHILY.devmajor") == 0) {
|
||||
archive_entry_set_rdevmajor(entry,
|
||||
(dev_t)tar_atol10(value, strlen(value)));
|
||||
@ -1870,6 +1978,9 @@ pax_attribute(struct archive_read *a, struct tar *tar,
|
||||
} else if (strcmp(key, "SCHILY.realsize") == 0) {
|
||||
tar->realsize = tar_atol10(value, strlen(value));
|
||||
archive_entry_set_size(entry, tar->realsize);
|
||||
} else if (strncmp(key, "SCHILY.xattr.", 13) == 0) {
|
||||
pax_attribute_schily_xattr(entry, key, value,
|
||||
value_length);
|
||||
} else if (strcmp(key, "SUN.holesdata") == 0) {
|
||||
/* A Solaris extension for sparse. */
|
||||
r = solaris_sparse_parse(a, tar, entry, value);
|
||||
@ -2116,12 +2227,11 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar,
|
||||
{
|
||||
struct sparse_block *p;
|
||||
|
||||
p = (struct sparse_block *)malloc(sizeof(*p));
|
||||
p = (struct sparse_block *)calloc(1, sizeof(*p));
|
||||
if (p == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(p, 0, sizeof(*p));
|
||||
if (tar->sparse_last != NULL)
|
||||
tar->sparse_last->next = p;
|
||||
else
|
||||
@ -2377,6 +2487,9 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed)
|
||||
tar_flush_unconsumed(a, unconsumed);
|
||||
bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining);
|
||||
to_skip = 0x1ff & -bytes_read;
|
||||
/* Fail if tar->entry_bytes_remaing would get negative */
|
||||
if (to_skip > remaining)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (to_skip != __archive_read_consume(a, to_skip))
|
||||
return (ARCHIVE_FATAL);
|
||||
return ((ssize_t)(bytes_read + to_skip));
|
||||
@ -2472,7 +2585,7 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
|
||||
last_digit_limit = INT64_MAX % base;
|
||||
|
||||
/* the pointer will not be dereferenced if char_cnt is zero
|
||||
* due to the way the && operator is evaulated.
|
||||
* due to the way the && operator is evaluated.
|
||||
*/
|
||||
while (char_cnt != 0 && (*p == ' ' || *p == '\t')) {
|
||||
p++;
|
||||
|
@ -88,7 +88,7 @@ typedef enum {
|
||||
WT_RVIS,
|
||||
/* conversion, unsupported */
|
||||
WT_CONV,
|
||||
/* continutation, unsupported at the moment */
|
||||
/* continuation, unsupported at the moment */
|
||||
WT_CONT,
|
||||
/* invalid type */
|
||||
LAST_WT
|
||||
@ -134,8 +134,8 @@ static ssize_t _warc_rdlen(const char *buf, size_t bsz);
|
||||
static time_t _warc_rdrtm(const char *buf, size_t bsz);
|
||||
static time_t _warc_rdmtm(const char *buf, size_t bsz);
|
||||
static const char *_warc_find_eoh(const char *buf, size_t bsz);
|
||||
static const char *_warc_find_eol(const char *buf, size_t bsz);
|
||||
|
||||
|
||||
int
|
||||
archive_read_support_format_warc(struct archive *_a)
|
||||
{
|
||||
@ -146,12 +146,11 @@ archive_read_support_format_warc(struct archive *_a)
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_format_warc");
|
||||
|
||||
if ((w = malloc(sizeof(*w))) == NULL) {
|
||||
if ((w = calloc(1, sizeof(*w))) == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate warc data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(w, 0, sizeof(*w));
|
||||
|
||||
r = __archive_read_register_format(
|
||||
a, w, "warc",
|
||||
@ -199,8 +198,8 @@ _warc_bid(struct archive_read *a, int best_bid)
|
||||
|
||||
/* otherwise snarf the record's version number */
|
||||
ver = _warc_rdver(hdr, nrd);
|
||||
if (ver == 0U || ver > 10000U) {
|
||||
/* oh oh oh, best not to wager ... */
|
||||
if (ver < 1200U || ver > 10000U) {
|
||||
/* we only support WARC 0.12 to 1.0 */
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -255,23 +254,32 @@ start_over:
|
||||
&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Bad record header");
|
||||
return (ARCHIVE_FATAL);
|
||||
} else if ((ver = _warc_rdver(buf, eoh - buf)) > 10000U) {
|
||||
/* nawww, I wish they promised backward compatibility
|
||||
* anyhoo, in their infinite wisdom the 28500 guys might
|
||||
* come up with something we can't possibly handle so
|
||||
* best end things here */
|
||||
}
|
||||
ver = _warc_rdver(buf, eoh - buf);
|
||||
/* we currently support WARC 0.12 to 1.0 */
|
||||
if (ver == 0U) {
|
||||
archive_set_error(
|
||||
&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Unsupported record version");
|
||||
"Invalid record version");
|
||||
return (ARCHIVE_FATAL);
|
||||
} else if ((cntlen = _warc_rdlen(buf, eoh - buf)) < 0) {
|
||||
} else if (ver < 1200U || ver > 10000U) {
|
||||
archive_set_error(
|
||||
&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Unsupported record version: %u.%u",
|
||||
ver / 10000, (ver % 10000) / 100);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
cntlen = _warc_rdlen(buf, eoh - buf);
|
||||
if (cntlen < 0) {
|
||||
/* nightmare! the specs say content-length is mandatory
|
||||
* so I don't feel overly bad stopping the reader here */
|
||||
archive_set_error(
|
||||
&a->archive, EINVAL,
|
||||
"Bad content length");
|
||||
return (ARCHIVE_FATAL);
|
||||
} else if ((rtime = _warc_rdrtm(buf, eoh - buf)) == (time_t)-1) {
|
||||
}
|
||||
rtime = _warc_rdrtm(buf, eoh - buf);
|
||||
if (rtime == (time_t)-1) {
|
||||
/* record time is mandatory as per WARC/1.0,
|
||||
* so just barf here, fast and loud */
|
||||
archive_set_error(
|
||||
@ -285,7 +293,7 @@ start_over:
|
||||
if (ver != w->pver) {
|
||||
/* stringify this entry's version */
|
||||
archive_string_sprintf(&w->sver,
|
||||
"WARC/%u.%u", ver / 10000, ver % 10000);
|
||||
"WARC/%u.%u", ver / 10000, (ver % 10000) / 100);
|
||||
/* remember the version */
|
||||
w->pver = ver;
|
||||
}
|
||||
@ -318,7 +326,7 @@ start_over:
|
||||
}
|
||||
memcpy(w->pool.str, fnam.str, fnam.len);
|
||||
w->pool.str[fnam.len] = '\0';
|
||||
/* let noone else know about the pool, it's a secret, shhh */
|
||||
/* let no one else know about the pool, it's a secret, shhh */
|
||||
fnam.str = w->pool.str;
|
||||
|
||||
/* snarf mtime or deduce from rtime
|
||||
@ -523,6 +531,10 @@ time_from_tm(struct tm *t)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int la_isblank(int c) {
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
|
||||
static time_t
|
||||
xstrpisotime(const char *s, char **endptr)
|
||||
{
|
||||
@ -535,7 +547,8 @@ xstrpisotime(const char *s, char **endptr)
|
||||
|
||||
/* as a courtesy to our callers, and since this is a non-standard
|
||||
* routine, we skip leading whitespace */
|
||||
for (; isspace(*s); s++);
|
||||
while (la_isblank((unsigned char)*s))
|
||||
++s;
|
||||
|
||||
/* read year */
|
||||
if ((tm.tm_year = strtoi_lim(s, &s, 1583, 4095)) < 0 || *s++ != '-') {
|
||||
@ -562,7 +575,7 @@ xstrpisotime(const char *s, char **endptr)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* massage TM to fulfill some of POSIX' contraints */
|
||||
/* massage TM to fulfill some of POSIX' constraints */
|
||||
tm.tm_year -= 1900;
|
||||
tm.tm_mon--;
|
||||
|
||||
@ -577,51 +590,41 @@ out:
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
_warc_rdver(const char buf[10], size_t bsz)
|
||||
_warc_rdver(const char *buf, size_t bsz)
|
||||
{
|
||||
static const char magic[] = "WARC/";
|
||||
unsigned int ver;
|
||||
unsigned int ver = 0U;
|
||||
unsigned int end = 0U;
|
||||
|
||||
(void)bsz; /* UNUSED */
|
||||
|
||||
if (memcmp(buf, magic, sizeof(magic) - 1U) != 0) {
|
||||
/* nope */
|
||||
return 99999U;
|
||||
if (bsz < 12 || memcmp(buf, magic, sizeof(magic) - 1U) != 0) {
|
||||
/* buffer too small or invalid magic */
|
||||
return ver;
|
||||
}
|
||||
/* looks good so far, read the version number for a laugh */
|
||||
buf += sizeof(magic) - 1U;
|
||||
/* most common case gets a quick-check here */
|
||||
if (memcmp(buf, "1.0\r\n", 5U) == 0) {
|
||||
ver = 10000U;
|
||||
} else {
|
||||
switch (*buf) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
if (buf[1U] == '.') {
|
||||
char *on;
|
||||
|
||||
/* set up major version */
|
||||
ver = (buf[0U] - '0') * 10000U;
|
||||
/* minor version, anyone? */
|
||||
ver += (strtol(buf + 2U, &on, 10)) * 100U;
|
||||
/* don't parse anything else */
|
||||
if (on > buf + 2U) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case '9':
|
||||
default:
|
||||
/* just make the version ridiculously high */
|
||||
ver = 999999U;
|
||||
break;
|
||||
if (isdigit(buf[0U]) && (buf[1U] == '.') && isdigit(buf[2U])) {
|
||||
/* we support a maximum of 2 digits in the minor version */
|
||||
if (isdigit(buf[3U]))
|
||||
end = 1U;
|
||||
/* set up major version */
|
||||
ver = (buf[0U] - '0') * 10000U;
|
||||
/* set up minor version */
|
||||
if (end == 1U) {
|
||||
ver += (buf[2U] - '0') * 1000U;
|
||||
ver += (buf[3U] - '0') * 100U;
|
||||
} else
|
||||
ver += (buf[2U] - '0') * 100U;
|
||||
/*
|
||||
* WARC below version 0.12 has a space-separated header
|
||||
* WARC 0.12 and above terminates the version with a CRLF
|
||||
*/
|
||||
if (ver >= 1200U) {
|
||||
if (memcmp(buf + 3U + end, "\r\n", 2U) != 0)
|
||||
ver = 0U;
|
||||
} else if (ver < 1200U) {
|
||||
if (!la_isblank(*(buf + 3U + end)))
|
||||
ver = 0U;
|
||||
}
|
||||
}
|
||||
return ver;
|
||||
@ -631,32 +634,27 @@ static unsigned int
|
||||
_warc_rdtyp(const char *buf, size_t bsz)
|
||||
{
|
||||
static const char _key[] = "\r\nWARC-Type:";
|
||||
const char *const eob = buf + bsz;
|
||||
const char *val;
|
||||
const char *val, *eol;
|
||||
|
||||
if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
|
||||
/* no bother */
|
||||
return WT_NONE;
|
||||
}
|
||||
/* overread whitespace */
|
||||
for (val += sizeof(_key) - 1U; val < eob && isspace(*val); val++);
|
||||
val += sizeof(_key) - 1U;
|
||||
if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
|
||||
/* no end of line */
|
||||
return WT_NONE;
|
||||
}
|
||||
|
||||
if (val + 8U > eob) {
|
||||
;
|
||||
} else if (memcmp(val, "resource", 8U) == 0) {
|
||||
return WT_RSRC;
|
||||
} else if (memcmp(val, "warcinfo", 8U) == 0) {
|
||||
return WT_INFO;
|
||||
} else if (memcmp(val, "metadata", 8U) == 0) {
|
||||
return WT_META;
|
||||
} else if (memcmp(val, "request", 7U) == 0) {
|
||||
return WT_REQ;
|
||||
} else if (memcmp(val, "response", 8U) == 0) {
|
||||
return WT_RSP;
|
||||
} else if (memcmp(val, "conversi", 8U) == 0) {
|
||||
return WT_CONV;
|
||||
} else if (memcmp(val, "continua", 8U) == 0) {
|
||||
return WT_CONT;
|
||||
/* overread whitespace */
|
||||
while (val < eol && la_isblank((unsigned char)*val))
|
||||
++val;
|
||||
|
||||
if (val + 8U == eol) {
|
||||
if (memcmp(val, "resource", 8U) == 0)
|
||||
return WT_RSRC;
|
||||
else if (memcmp(val, "response", 8U) == 0)
|
||||
return WT_RSP;
|
||||
}
|
||||
return WT_NONE;
|
||||
}
|
||||
@ -665,10 +663,7 @@ static warc_string_t
|
||||
_warc_rduri(const char *buf, size_t bsz)
|
||||
{
|
||||
static const char _key[] = "\r\nWARC-Target-URI:";
|
||||
const char *const eob = buf + bsz;
|
||||
const char *val;
|
||||
const char *uri;
|
||||
const char *eol;
|
||||
const char *val, *uri, *eol, *p;
|
||||
warc_string_t res = {0U, NULL};
|
||||
|
||||
if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
|
||||
@ -676,23 +671,33 @@ _warc_rduri(const char *buf, size_t bsz)
|
||||
return res;
|
||||
}
|
||||
/* overread whitespace */
|
||||
for (val += sizeof(_key) - 1U; val < eob && isspace(*val); val++);
|
||||
|
||||
/* overread URL designators */
|
||||
if ((uri = xmemmem(val, eob - val, "://", 3U)) == NULL) {
|
||||
/* not touching that! */
|
||||
return res;
|
||||
} else if ((eol = memchr(uri, '\n', eob - uri)) == NULL) {
|
||||
/* no end of line? :O */
|
||||
val += sizeof(_key) - 1U;
|
||||
if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
|
||||
/* no end of line */
|
||||
return res;
|
||||
}
|
||||
|
||||
/* massage uri to point to after :// */
|
||||
while (val < eol && la_isblank((unsigned char)*val))
|
||||
++val;
|
||||
|
||||
/* overread URL designators */
|
||||
if ((uri = xmemmem(val, eol - val, "://", 3U)) == NULL) {
|
||||
/* not touching that! */
|
||||
return res;
|
||||
}
|
||||
|
||||
/* spaces inside uri are not allowed, CRLF should follow */
|
||||
for (p = val; p < eol; p++) {
|
||||
if (isspace(*p))
|
||||
return res;
|
||||
}
|
||||
|
||||
/* there must be at least space for ftp */
|
||||
if (uri < (val + 3U))
|
||||
return res;
|
||||
|
||||
/* move uri to point to after :// */
|
||||
uri += 3U;
|
||||
/* also massage eol to point to the first whitespace
|
||||
* after the last non-whitespace character before
|
||||
* the end of the line */
|
||||
for (; eol > uri && isspace(eol[-1]); eol--);
|
||||
|
||||
/* now then, inspect the URI */
|
||||
if (memcmp(val, "file", 4U) == 0) {
|
||||
@ -715,7 +720,7 @@ static ssize_t
|
||||
_warc_rdlen(const char *buf, size_t bsz)
|
||||
{
|
||||
static const char _key[] = "\r\nContent-Length:";
|
||||
const char *val;
|
||||
const char *val, *eol;
|
||||
char *on = NULL;
|
||||
long int len;
|
||||
|
||||
@ -723,14 +728,24 @@ _warc_rdlen(const char *buf, size_t bsz)
|
||||
/* no bother */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* strtol kindly overreads whitespace for us, so use that */
|
||||
val += sizeof(_key) - 1U;
|
||||
len = strtol(val, &on, 10);
|
||||
if (on == NULL || !isspace(*on)) {
|
||||
/* hm, can we trust that number? Best not. */
|
||||
if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) {
|
||||
/* no end of line */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* skip leading whitespace */
|
||||
while (val < eol && la_isblank(*val))
|
||||
val++;
|
||||
/* there must be at least one digit */
|
||||
if (!isdigit(*val))
|
||||
return -1;
|
||||
len = strtol(val, &on, 10);
|
||||
if (on != eol) {
|
||||
/* line must end here */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (size_t)len;
|
||||
}
|
||||
|
||||
@ -738,7 +753,7 @@ static time_t
|
||||
_warc_rdrtm(const char *buf, size_t bsz)
|
||||
{
|
||||
static const char _key[] = "\r\nWARC-Date:";
|
||||
const char *val;
|
||||
const char *val, *eol;
|
||||
char *on = NULL;
|
||||
time_t res;
|
||||
|
||||
@ -746,13 +761,17 @@ _warc_rdrtm(const char *buf, size_t bsz)
|
||||
/* no bother */
|
||||
return (time_t)-1;
|
||||
}
|
||||
val += sizeof(_key) - 1U;
|
||||
if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) {
|
||||
/* no end of line */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* xstrpisotime() kindly overreads whitespace for us, so use that */
|
||||
val += sizeof(_key) - 1U;
|
||||
res = xstrpisotime(val, &on);
|
||||
if (on == NULL || !isspace(*on)) {
|
||||
/* hm, can we trust that number? Best not. */
|
||||
return (time_t)-1;
|
||||
if (on != eol) {
|
||||
/* line must end here */
|
||||
return -1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -761,7 +780,7 @@ static time_t
|
||||
_warc_rdmtm(const char *buf, size_t bsz)
|
||||
{
|
||||
static const char _key[] = "\r\nLast-Modified:";
|
||||
const char *val;
|
||||
const char *val, *eol;
|
||||
char *on = NULL;
|
||||
time_t res;
|
||||
|
||||
@ -769,13 +788,17 @@ _warc_rdmtm(const char *buf, size_t bsz)
|
||||
/* no bother */
|
||||
return (time_t)-1;
|
||||
}
|
||||
val += sizeof(_key) - 1U;
|
||||
if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) {
|
||||
/* no end of line */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* xstrpisotime() kindly overreads whitespace for us, so use that */
|
||||
val += sizeof(_key) - 1U;
|
||||
res = xstrpisotime(val, &on);
|
||||
if (on == NULL || !isspace(*on)) {
|
||||
/* hm, can we trust that number? Best not. */
|
||||
return (time_t)-1;
|
||||
if (on != eol) {
|
||||
/* line must end here */
|
||||
return -1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -792,4 +815,12 @@ _warc_find_eoh(const char *buf, size_t bsz)
|
||||
return hit;
|
||||
}
|
||||
|
||||
static const char*
|
||||
_warc_find_eol(const char *buf, size_t bsz)
|
||||
{
|
||||
static const char _marker[] = "\r\n";
|
||||
const char *hit = xmemmem(buf, bsz, _marker, sizeof(_marker) - 1U);
|
||||
|
||||
return hit;
|
||||
}
|
||||
/* archive_read_support_format_warc.c ends here */
|
||||
|
@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
#if HAVE_LZMA_H
|
||||
#include <cm_lzma.h>
|
||||
#elif HAVE_LZMADEC_H
|
||||
#include <lzmadec.h>
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB_H
|
||||
#include <cm_zlib.h>
|
||||
@ -334,9 +332,6 @@ struct xar {
|
||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||
lzma_stream lzstream;
|
||||
int lzstream_valid;
|
||||
#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
|
||||
lzmadec_stream lzstream;
|
||||
int lzstream_valid;
|
||||
#endif
|
||||
/*
|
||||
* For Checksum data.
|
||||
@ -399,6 +394,7 @@ static void checksum_update(struct archive_read *, const void *,
|
||||
size_t, const void *, size_t);
|
||||
static int checksum_final(struct archive_read *, const void *,
|
||||
size_t, const void *, size_t);
|
||||
static void checksum_cleanup(struct archive_read *);
|
||||
static int decompression_init(struct archive_read *, enum enctype);
|
||||
static int decompress(struct archive_read *, const void **,
|
||||
size_t *, const void *, size_t *);
|
||||
@ -928,6 +924,7 @@ xar_cleanup(struct archive_read *a)
|
||||
int r;
|
||||
|
||||
xar = (struct xar *)(a->format->data);
|
||||
checksum_cleanup(a);
|
||||
r = decompression_cleanup(a);
|
||||
hdlink = xar->hdlink_list;
|
||||
while (hdlink != NULL) {
|
||||
@ -938,6 +935,7 @@ xar_cleanup(struct archive_read *a)
|
||||
}
|
||||
for (i = 0; i < xar->file_queue.used; i++)
|
||||
file_free(xar->file_queue.files[i]);
|
||||
free(xar->file_queue.files);
|
||||
while (xar->unknowntags != NULL) {
|
||||
struct unknown_tag *tag;
|
||||
|
||||
@ -1526,34 +1524,6 @@ decompression_init(struct archive_read *a, enum enctype encoding)
|
||||
xar->lzstream.total_in = 0;
|
||||
xar->lzstream.total_out = 0;
|
||||
break;
|
||||
#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
|
||||
case LZMA:
|
||||
if (xar->lzstream_valid)
|
||||
lzmadec_end(&(xar->lzstream));
|
||||
r = lzmadec_init(&(xar->lzstream));
|
||||
if (r != LZMADEC_OK) {
|
||||
switch (r) {
|
||||
case LZMADEC_HEADER_ERROR:
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing "
|
||||
"compression library: "
|
||||
"invalid header");
|
||||
break;
|
||||
case LZMADEC_MEM_ERROR:
|
||||
archive_set_error(&a->archive,
|
||||
ENOMEM,
|
||||
"Internal error initializing "
|
||||
"compression library: "
|
||||
"out of memory");
|
||||
break;
|
||||
}
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
xar->lzstream_valid = 1;
|
||||
xar->lzstream.total_in = 0;
|
||||
xar->lzstream.total_out = 0;
|
||||
break;
|
||||
#endif
|
||||
/*
|
||||
* Unsupported compression.
|
||||
@ -1563,9 +1533,7 @@ decompression_init(struct archive_read *a, enum enctype encoding)
|
||||
case BZIP2:
|
||||
#endif
|
||||
#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
|
||||
#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
|
||||
case LZMA:
|
||||
#endif
|
||||
case XZ:
|
||||
#endif
|
||||
switch (xar->entry_encoding) {
|
||||
@ -1685,46 +1653,12 @@ decompress(struct archive_read *a, const void **buff, size_t *outbytes,
|
||||
*used = avail_in - xar->lzstream.avail_in;
|
||||
*outbytes = avail_out - xar->lzstream.avail_out;
|
||||
break;
|
||||
#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC)
|
||||
case LZMA:
|
||||
xar->lzstream.next_in = (unsigned char *)(uintptr_t)b;
|
||||
xar->lzstream.avail_in = avail_in;
|
||||
xar->lzstream.next_out = (unsigned char *)outbuff;
|
||||
xar->lzstream.avail_out = avail_out;
|
||||
r = lzmadec_decode(&(xar->lzstream), 0);
|
||||
switch (r) {
|
||||
case LZMADEC_STREAM_END: /* Found end of stream. */
|
||||
switch (lzmadec_end(&(xar->lzstream))) {
|
||||
case LZMADEC_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&(a->archive),
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up lzmadec decompressor");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
xar->lzstream_valid = 0;
|
||||
/* FALLTHROUGH */
|
||||
case LZMADEC_OK: /* Decompressor made some progress. */
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&(a->archive),
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"lzmadec decompression failed(%d)",
|
||||
r);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
*used = avail_in - xar->lzstream.avail_in;
|
||||
*outbytes = avail_out - xar->lzstream.avail_out;
|
||||
break;
|
||||
#endif
|
||||
#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
|
||||
case BZIP2:
|
||||
#endif
|
||||
#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA)
|
||||
#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC)
|
||||
case LZMA:
|
||||
#endif
|
||||
case XZ:
|
||||
#endif
|
||||
case NONE:
|
||||
@ -1787,6 +1721,16 @@ decompression_cleanup(struct archive_read *a)
|
||||
return (r);
|
||||
}
|
||||
|
||||
static void
|
||||
checksum_cleanup(struct archive_read *a) {
|
||||
struct xar *xar;
|
||||
|
||||
xar = (struct xar *)(a->format->data);
|
||||
|
||||
_checksum_final(&(xar->a_sumwrk), NULL, 0);
|
||||
_checksum_final(&(xar->e_sumwrk), NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
xmlattr_cleanup(struct xmlattr_list *list)
|
||||
{
|
||||
@ -3116,7 +3060,7 @@ xml2_read_cb(void *context, char *buffer, int len)
|
||||
struct xar *xar;
|
||||
const void *d;
|
||||
size_t outbytes;
|
||||
size_t used;
|
||||
size_t used = 0;
|
||||
int r;
|
||||
|
||||
a = (struct archive_read *)context;
|
||||
@ -3240,6 +3184,9 @@ expat_xmlattr_setup(struct archive_read *a,
|
||||
value = strdup(atts[1]);
|
||||
if (attr == NULL || name == NULL || value == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
free(attr);
|
||||
free(name);
|
||||
free(value);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
attr->name = name;
|
||||
|
@ -199,7 +199,7 @@ struct zip {
|
||||
struct trad_enc_ctx tctx;
|
||||
char tctx_valid;
|
||||
|
||||
/* WinZip AES decyption. */
|
||||
/* WinZip AES decryption. */
|
||||
/* Contexts used for AES decryption. */
|
||||
archive_crypto_ctx cctx;
|
||||
char cctx_valid;
|
||||
@ -242,7 +242,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
trad_enc_decypt_byte(struct trad_enc_ctx *ctx)
|
||||
trad_enc_decrypt_byte(struct trad_enc_ctx *ctx)
|
||||
{
|
||||
unsigned temp = ctx->keys[2] | 2;
|
||||
return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff;
|
||||
@ -257,7 +257,7 @@ trad_enc_decrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in,
|
||||
max = (unsigned)((in_len < out_len)? in_len: out_len);
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t t = in[i] ^ trad_enc_decypt_byte(ctx);
|
||||
uint8_t t = in[i] ^ trad_enc_decrypt_byte(ctx);
|
||||
out[i] = t;
|
||||
trad_enc_update_keys(ctx, t);
|
||||
}
|
||||
@ -418,18 +418,30 @@ zip_time(const char *p)
|
||||
* id1+size1+data1 + id2+size2+data2 ...
|
||||
* triplets. id and size are 2 bytes each.
|
||||
*/
|
||||
static void
|
||||
process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
|
||||
static int
|
||||
process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry)
|
||||
{
|
||||
unsigned offset = 0;
|
||||
|
||||
while (offset < extra_length - 4) {
|
||||
if (extra_length == 0) {
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
if (extra_length < 4) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length);
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
while (offset <= extra_length - 4) {
|
||||
unsigned short headerid = archive_le16dec(p + offset);
|
||||
unsigned short datasize = archive_le16dec(p + offset + 2);
|
||||
|
||||
offset += 4;
|
||||
if (offset + datasize > extra_length) {
|
||||
break;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Extra data overflow: Need %d bytes but only found %d bytes",
|
||||
(int)datasize, (int)(extra_length - offset));
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Header id 0x%04x, length %d\n",
|
||||
@ -440,26 +452,38 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
|
||||
/* Zip64 extended information extra field. */
|
||||
zip_entry->flags |= LA_USED_ZIP64;
|
||||
if (zip_entry->uncompressed_size == 0xffffffff) {
|
||||
if (datasize < 8)
|
||||
break;
|
||||
zip_entry->uncompressed_size =
|
||||
archive_le64dec(p + offset);
|
||||
uint64_t t = 0;
|
||||
if (datasize < 8
|
||||
|| (t = archive_le64dec(p + offset)) > INT64_MAX) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Malformed 64-bit uncompressed size");
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
zip_entry->uncompressed_size = t;
|
||||
offset += 8;
|
||||
datasize -= 8;
|
||||
}
|
||||
if (zip_entry->compressed_size == 0xffffffff) {
|
||||
if (datasize < 8)
|
||||
break;
|
||||
zip_entry->compressed_size =
|
||||
archive_le64dec(p + offset);
|
||||
uint64_t t = 0;
|
||||
if (datasize < 8
|
||||
|| (t = archive_le64dec(p + offset)) > INT64_MAX) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Malformed 64-bit compressed size");
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
zip_entry->compressed_size = t;
|
||||
offset += 8;
|
||||
datasize -= 8;
|
||||
}
|
||||
if (zip_entry->local_header_offset == 0xffffffff) {
|
||||
if (datasize < 8)
|
||||
break;
|
||||
zip_entry->local_header_offset =
|
||||
archive_le64dec(p + offset);
|
||||
uint64_t t = 0;
|
||||
if (datasize < 8
|
||||
|| (t = archive_le64dec(p + offset)) > INT64_MAX) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Malformed 64-bit local header offset");
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
zip_entry->local_header_offset = t;
|
||||
offset += 8;
|
||||
datasize -= 8;
|
||||
}
|
||||
@ -698,7 +722,7 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
|
||||
break;
|
||||
}
|
||||
case 0x9901:
|
||||
/* WinZIp AES extra data field. */
|
||||
/* WinZip AES extra data field. */
|
||||
if (p[offset + 2] == 'A' && p[offset + 3] == 'E') {
|
||||
/* Vendor version. */
|
||||
zip_entry->aes_extra.vendor =
|
||||
@ -715,13 +739,13 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
|
||||
}
|
||||
offset += datasize;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (offset != extra_length)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Extra data field contents do not match reported size!\n");
|
||||
if (offset != extra_length) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Malformed extra data: Consumed %d bytes of %d bytes",
|
||||
(int)offset, (int)extra_length);
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
#endif
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -840,7 +864,9 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
process_extra(h, extra_length, zip_entry);
|
||||
if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) {
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
__archive_read_consume(a, extra_length);
|
||||
|
||||
/* Work around a bug in Info-Zip: When reading from a pipe, it
|
||||
@ -850,29 +876,33 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
zip_entry->mode |= AE_IFREG;
|
||||
}
|
||||
|
||||
if ((zip_entry->mode & AE_IFMT) == 0) {
|
||||
/* Especially in streaming mode, we can end up
|
||||
here without having seen proper mode information.
|
||||
Guess from the filename. */
|
||||
/* If the mode is totally empty, set some sane default. */
|
||||
if (zip_entry->mode == 0) {
|
||||
zip_entry->mode |= 0664;
|
||||
}
|
||||
|
||||
/* Make sure that entries with a trailing '/' are marked as directories
|
||||
* even if the External File Attributes contains bogus values. If this
|
||||
* is not a directory and there is no type, assume regularfile. */
|
||||
if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) {
|
||||
int has_slash;
|
||||
|
||||
wp = archive_entry_pathname_w(entry);
|
||||
if (wp != NULL) {
|
||||
len = wcslen(wp);
|
||||
if (len > 0 && wp[len - 1] == L'/')
|
||||
zip_entry->mode |= AE_IFDIR;
|
||||
else
|
||||
zip_entry->mode |= AE_IFREG;
|
||||
has_slash = len > 0 && wp[len - 1] == L'/';
|
||||
} else {
|
||||
cp = archive_entry_pathname(entry);
|
||||
len = (cp != NULL)?strlen(cp):0;
|
||||
if (len > 0 && cp[len - 1] == '/')
|
||||
zip_entry->mode |= AE_IFDIR;
|
||||
else
|
||||
zip_entry->mode |= AE_IFREG;
|
||||
has_slash = len > 0 && cp[len - 1] == '/';
|
||||
}
|
||||
if (zip_entry->mode == AE_IFDIR) {
|
||||
zip_entry->mode |= 0775;
|
||||
} else if (zip_entry->mode == AE_IFREG) {
|
||||
zip_entry->mode |= 0664;
|
||||
/* Correct file type as needed. */
|
||||
if (has_slash) {
|
||||
zip_entry->mode &= ~AE_IFMT;
|
||||
zip_entry->mode |= AE_IFDIR;
|
||||
zip_entry->mode |= 0111;
|
||||
} else if ((zip_entry->mode & AE_IFMT) == 0) {
|
||||
zip_entry->mode |= AE_IFREG;
|
||||
}
|
||||
}
|
||||
|
||||
@ -887,6 +917,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
archive_wstrcat(&s, wp);
|
||||
archive_wstrappend_wchar(&s, L'/');
|
||||
archive_entry_copy_pathname_w(entry, s.s);
|
||||
archive_wstring_free(&s);
|
||||
}
|
||||
} else {
|
||||
cp = archive_entry_pathname(entry);
|
||||
@ -897,6 +928,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
archive_strcat(&s, cp);
|
||||
archive_strappend_char(&s, '/');
|
||||
archive_entry_set_pathname(entry, s.s);
|
||||
archive_string_free(&s);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1136,11 +1168,18 @@ zip_read_data_none(struct archive_read *a, const void **_buff,
|
||||
|| (zip->hctx_valid
|
||||
&& zip->entry->aes_extra.vendor == AES_VENDOR_AE_2))) {
|
||||
if (zip->entry->flags & LA_USED_ZIP64) {
|
||||
uint64_t compressed, uncompressed;
|
||||
zip->entry->crc32 = archive_le32dec(p + 4);
|
||||
zip->entry->compressed_size =
|
||||
archive_le64dec(p + 8);
|
||||
zip->entry->uncompressed_size =
|
||||
archive_le64dec(p + 16);
|
||||
compressed = archive_le64dec(p + 8);
|
||||
uncompressed = archive_le64dec(p + 16);
|
||||
if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Overflow of 64-bit file sizes");
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
zip->entry->compressed_size = compressed;
|
||||
zip->entry->uncompressed_size = uncompressed;
|
||||
zip->unconsumed = 24;
|
||||
} else {
|
||||
zip->entry->crc32 = archive_le32dec(p + 4);
|
||||
@ -1293,7 +1332,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
&& bytes_avail > zip->entry_bytes_remaining) {
|
||||
bytes_avail = (ssize_t)zip->entry_bytes_remaining;
|
||||
}
|
||||
if (bytes_avail <= 0) {
|
||||
if (bytes_avail < 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated ZIP file body");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -1417,9 +1456,18 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
zip->unconsumed = 4;
|
||||
}
|
||||
if (zip->entry->flags & LA_USED_ZIP64) {
|
||||
uint64_t compressed, uncompressed;
|
||||
zip->entry->crc32 = archive_le32dec(p);
|
||||
zip->entry->compressed_size = archive_le64dec(p + 4);
|
||||
zip->entry->uncompressed_size = archive_le64dec(p + 12);
|
||||
compressed = archive_le64dec(p + 4);
|
||||
uncompressed = archive_le64dec(p + 12);
|
||||
if (compressed > INT64_MAX || uncompressed > INT64_MAX) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Overflow of 64-bit file sizes");
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
zip->entry->compressed_size = compressed;
|
||||
zip->entry->uncompressed_size = uncompressed;
|
||||
zip->unconsumed += 20;
|
||||
} else {
|
||||
zip->entry->crc32 = archive_le32dec(p);
|
||||
@ -1500,7 +1548,7 @@ read_decryption_header(struct archive_read *a)
|
||||
case 0x6720:/* Blowfish */
|
||||
case 0x6721:/* Twofish */
|
||||
case 0x6801:/* RC4 */
|
||||
/* Suuported encryption algorithm. */
|
||||
/* Supported encryption algorithm. */
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&a->archive,
|
||||
@ -1609,7 +1657,7 @@ read_decryption_header(struct archive_read *a)
|
||||
__archive_read_consume(a, 4);
|
||||
|
||||
/*return (ARCHIVE_OK);
|
||||
* This is not fully implemnted yet.*/
|
||||
* This is not fully implemented yet.*/
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Encrypted file is unsupported");
|
||||
return (ARCHIVE_FAILED);
|
||||
@ -1691,7 +1739,7 @@ init_traditional_PKWARE_decryption(struct archive_read *a)
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize ctx for Traditional PKWARE Decyption.
|
||||
* Initialize ctx for Traditional PKWARE Decryption.
|
||||
*/
|
||||
r = trad_enc_init(&zip->tctx, passphrase, strlen(passphrase),
|
||||
p, ENC_HEADER_SIZE, &crcchk);
|
||||
@ -2691,7 +2739,9 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
|
||||
"Truncated ZIP file header");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
process_extra(p + filename_length, extra_length, zip_entry);
|
||||
if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) {
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mac resource fork files are stored under the
|
||||
|
@ -219,6 +219,12 @@ archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s)
|
||||
return (as);
|
||||
}
|
||||
|
||||
struct archive_string *
|
||||
archive_array_append(struct archive_string *as, const char *p, size_t s)
|
||||
{
|
||||
return archive_string_append(as, p, s);
|
||||
}
|
||||
|
||||
void
|
||||
archive_string_concat(struct archive_string *dest, struct archive_string *src)
|
||||
{
|
||||
@ -559,7 +565,8 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest,
|
||||
}
|
||||
if (count == 0 && length != 0)
|
||||
ret = -1;
|
||||
} while (0);
|
||||
break;
|
||||
} while (1);
|
||||
}
|
||||
dest->length += count;
|
||||
dest->s[dest->length] = L'\0';
|
||||
@ -596,7 +603,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest,
|
||||
wcs = dest->s + dest->length;
|
||||
/*
|
||||
* We cannot use mbsrtowcs/mbstowcs here because those may convert
|
||||
* extra MBS when strlen(p) > len and one wide character consis of
|
||||
* extra MBS when strlen(p) > len and one wide character consists of
|
||||
* multi bytes.
|
||||
*/
|
||||
while (*mbs && mbs_length > 0) {
|
||||
@ -1247,7 +1254,7 @@ create_sconv_object(const char *fc, const char *tc,
|
||||
sc->cd = iconv_open(tc, fc);
|
||||
if (sc->cd == (iconv_t)-1 && (sc->flag & SCONV_BEST_EFFORT)) {
|
||||
/*
|
||||
* Unfortunaly, all of iconv implements do support
|
||||
* Unfortunately, all of iconv implements do support
|
||||
* "CP932" character-set, so we should use "SJIS"
|
||||
* instead if iconv_open failed.
|
||||
*/
|
||||
@ -1260,7 +1267,7 @@ create_sconv_object(const char *fc, const char *tc,
|
||||
/*
|
||||
* archive_mstring on Windows directly convert multi-bytes
|
||||
* into archive_wstring in order not to depend on locale
|
||||
* so that you can do a I18N programing. This will be
|
||||
* so that you can do a I18N programming. This will be
|
||||
* used only in archive_mstring_copy_mbs_len_l so far.
|
||||
*/
|
||||
if (flag & SCONV_FROM_CHARSET) {
|
||||
@ -1725,7 +1732,7 @@ archive_string_conversion_from_charset(struct archive *a, const char *charset,
|
||||
* in tar or zip files. But mbstowcs/wcstombs(CRT) usually use CP_ACP
|
||||
* unless you use setlocale(LC_ALL, ".OCP")(specify CP_OEMCP).
|
||||
* So we should make a string conversion between CP_ACP and CP_OEMCP
|
||||
* for compatibillty.
|
||||
* for compatibility.
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
struct archive_string_conv *
|
||||
@ -1826,7 +1833,7 @@ archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt)
|
||||
* A filename in UTF-8 was made with libarchive 2.x in a wrong
|
||||
* assumption that wchar_t was Unicode.
|
||||
* This option enables simulating the assumption in order to read
|
||||
* that filname correctly.
|
||||
* that filename correctly.
|
||||
*/
|
||||
case SCONV_SET_OPT_UTF8_LIBARCHIVE2X:
|
||||
#if (defined(_WIN32) && !defined(__CYGWIN__)) \
|
||||
@ -1938,12 +1945,19 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
|
||||
struct archive_string_conv *sc)
|
||||
{
|
||||
const void *s;
|
||||
size_t length;
|
||||
size_t length = 0;
|
||||
int i, r = 0, r2;
|
||||
|
||||
if (_p != NULL && n > 0) {
|
||||
if (sc != NULL && (sc->flag & SCONV_FROM_UTF16))
|
||||
length = utf16nbytes(_p, n);
|
||||
else
|
||||
length = mbsnbytes(_p, n);
|
||||
}
|
||||
|
||||
/* We must allocate memory even if there is no data for conversion
|
||||
* or copy. This simulates archive_string_append behavior. */
|
||||
if (_p == NULL || n == 0) {
|
||||
if (length == 0) {
|
||||
int tn = 1;
|
||||
if (sc != NULL && (sc->flag & SCONV_TO_UTF16))
|
||||
tn = 2;
|
||||
@ -1959,16 +1973,11 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
|
||||
* If sc is NULL, we just make a copy.
|
||||
*/
|
||||
if (sc == NULL) {
|
||||
length = mbsnbytes(_p, n);
|
||||
if (archive_string_append(as, _p, length) == NULL)
|
||||
return (-1);/* No memory */
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (sc->flag & SCONV_FROM_UTF16)
|
||||
length = utf16nbytes(_p, n);
|
||||
else
|
||||
length = mbsnbytes(_p, n);
|
||||
s = _p;
|
||||
i = 0;
|
||||
if (sc->nconverter > 1) {
|
||||
@ -1991,7 +2000,7 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n,
|
||||
#if HAVE_ICONV
|
||||
|
||||
/*
|
||||
* Return -1 if conversion failes.
|
||||
* Return -1 if conversion fails.
|
||||
*/
|
||||
static int
|
||||
iconv_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
@ -2093,7 +2102,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
|
||||
/*
|
||||
* Translate a string from a some CodePage to an another CodePage by
|
||||
* Windows APIs, and copy the result. Return -1 if conversion failes.
|
||||
* Windows APIs, and copy the result. Return -1 if conversion fails.
|
||||
*/
|
||||
static int
|
||||
strncat_in_codepage(struct archive_string *as,
|
||||
@ -2217,7 +2226,7 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
|
||||
/*
|
||||
* If a character is ASCII, this just copies it. If not, this
|
||||
* assigns '?' charater instead but in UTF-8 locale this assigns
|
||||
* assigns '?' character instead but in UTF-8 locale this assigns
|
||||
* byte sequence 0xEF 0xBD 0xBD, which are code point U+FFFD,
|
||||
* a Replacement Character in Unicode.
|
||||
*/
|
||||
@ -2297,7 +2306,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
|
||||
return (0); /* Standard: return 0 for end-of-string. */
|
||||
cnt = utf8_count[ch];
|
||||
|
||||
/* Invalide sequence or there are not plenty bytes. */
|
||||
/* Invalid sequence or there are not plenty bytes. */
|
||||
if ((int)n < cnt) {
|
||||
cnt = (int)n;
|
||||
for (i = 1; i < cnt; i++) {
|
||||
@ -2378,7 +2387,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
|
||||
goto invalid_sequence;
|
||||
}
|
||||
|
||||
/* The code point larger than 0x10FFFF is not leagal
|
||||
/* The code point larger than 0x10FFFF is not legal
|
||||
* Unicode values. */
|
||||
if (wc > UNICODE_MAX)
|
||||
goto invalid_sequence;
|
||||
@ -2396,7 +2405,7 @@ utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
|
||||
int cnt;
|
||||
|
||||
cnt = _utf8_to_unicode(pwc, s, n);
|
||||
/* Any of Surrogate pair is not leagal Unicode values. */
|
||||
/* Any of Surrogate pair is not legal Unicode values. */
|
||||
if (cnt == 3 && IS_SURROGATE_PAIR_LA(*pwc))
|
||||
return (-3);
|
||||
return (cnt);
|
||||
@ -2457,7 +2466,7 @@ invalid_sequence:
|
||||
/*
|
||||
* Convert a Unicode code point to a single UTF-8 sequence.
|
||||
*
|
||||
* NOTE:This function does not check if the Unicode is leagal or not.
|
||||
* NOTE:This function does not check if the Unicode is legal or not.
|
||||
* Please you definitely check it before calling this.
|
||||
*/
|
||||
static size_t
|
||||
@ -2551,9 +2560,9 @@ utf16_to_unicode(uint32_t *pwc, const char *s, size_t n, int be)
|
||||
|
||||
/*
|
||||
* Surrogate pair values(0xd800 through 0xdfff) are only
|
||||
* used by UTF-16, so, after above culculation, the code
|
||||
* used by UTF-16, so, after above calculation, the code
|
||||
* must not be surrogate values, and Unicode has no codes
|
||||
* larger than 0x10ffff. Thus, those are not leagal Unicode
|
||||
* larger than 0x10ffff. Thus, those are not legal Unicode
|
||||
* values.
|
||||
*/
|
||||
if (IS_SURROGATE_PAIR_LA(uc) || uc > UNICODE_MAX) {
|
||||
@ -2900,7 +2909,7 @@ get_nfc(uint32_t uc, uint32_t uc2)
|
||||
/*
|
||||
* Normalize UTF-8/UTF-16BE characters to Form C and copy the result.
|
||||
*
|
||||
* TODO: Convert composition exclusions,which are never converted
|
||||
* TODO: Convert composition exclusions, which are never converted
|
||||
* from NFC,NFD,NFKC and NFKD, to Form C.
|
||||
*/
|
||||
static int
|
||||
@ -3434,7 +3443,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as,
|
||||
}
|
||||
|
||||
/*
|
||||
* As libarchie 2.x, translates the UTF-8 characters into
|
||||
* As libarchive 2.x, translates the UTF-8 characters into
|
||||
* wide-characters in the assumption that WCS is Unicode.
|
||||
*/
|
||||
if (n < 0) {
|
||||
@ -3473,7 +3482,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as,
|
||||
|
||||
/*
|
||||
* Convert a UTF-16BE/LE string to current locale and copy the result.
|
||||
* Return -1 if conversion failes.
|
||||
* Return -1 if conversion fails.
|
||||
*/
|
||||
static int
|
||||
win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
|
||||
@ -3552,18 +3561,19 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
|
||||
ll = WideCharToMultiByte(sc->to_cp, 0,
|
||||
(LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size,
|
||||
NULL, &defchar);
|
||||
if (ll == 0 &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
/* Need more buffer for MBS. */
|
||||
ll = WideCharToMultiByte(sc->to_cp, 0,
|
||||
(LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
|
||||
if (archive_string_ensure(as, ll +1) == NULL)
|
||||
return (-1);
|
||||
mbs = as->s + as->length;
|
||||
mbs_size = as->buffer_length - as->length -1;
|
||||
continue;
|
||||
/* Exit loop if we succeeded */
|
||||
if (ll != 0 ||
|
||||
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
/* Else expand buffer and loop to try again. */
|
||||
ll = WideCharToMultiByte(sc->to_cp, 0,
|
||||
(LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL);
|
||||
if (archive_string_ensure(as, ll +1) == NULL)
|
||||
return (-1);
|
||||
mbs = as->s + as->length;
|
||||
mbs_size = as->buffer_length - as->length -1;
|
||||
} while (1);
|
||||
archive_string_free(&tmp);
|
||||
as->length += ll;
|
||||
as->s[as->length] = '\0';
|
||||
@ -3596,7 +3606,7 @@ is_big_endian(void)
|
||||
|
||||
/*
|
||||
* Convert a current locale string to UTF-16BE/LE and copy the result.
|
||||
* Return -1 if conversion failes.
|
||||
* Return -1 if conversion fails.
|
||||
*/
|
||||
static int
|
||||
win_strncat_to_utf16(struct archive_string *as16, const void *_p,
|
||||
@ -3634,19 +3644,20 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
|
||||
do {
|
||||
count = MultiByteToWideChar(sc->from_cp,
|
||||
MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1);
|
||||
if (count == 0 &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
/* Need more buffer for UTF-16 string */
|
||||
count = MultiByteToWideChar(sc->from_cp,
|
||||
MB_PRECOMPOSED, s, (int)length, NULL, 0);
|
||||
if (archive_string_ensure(as16, (count +1) * 2)
|
||||
== NULL)
|
||||
return (-1);
|
||||
u16 = as16->s + as16->length;
|
||||
avail = as16->buffer_length - 2;
|
||||
continue;
|
||||
/* Exit loop if we succeeded */
|
||||
if (count != 0 ||
|
||||
GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
/* Expand buffer and try again */
|
||||
count = MultiByteToWideChar(sc->from_cp,
|
||||
MB_PRECOMPOSED, s, (int)length, NULL, 0);
|
||||
if (archive_string_ensure(as16, (count +1) * 2)
|
||||
== NULL)
|
||||
return (-1);
|
||||
u16 = as16->s + as16->length;
|
||||
avail = as16->buffer_length - 2;
|
||||
} while (1);
|
||||
as16->length += count * 2;
|
||||
as16->s[as16->length] = 0;
|
||||
as16->s[as16->length+1] = 0;
|
||||
@ -3700,7 +3711,7 @@ win_strncat_to_utf16le(struct archive_string *as16, const void *_p,
|
||||
|
||||
/*
|
||||
* Convert a UTF-16BE string to current locale and copy the result.
|
||||
* Return -1 if conversion failes.
|
||||
* Return -1 if conversion fails.
|
||||
*/
|
||||
static int
|
||||
best_effort_strncat_from_utf16(struct archive_string *as, const void *_p,
|
||||
@ -3758,7 +3769,7 @@ best_effort_strncat_from_utf16le(struct archive_string *as, const void *_p,
|
||||
|
||||
/*
|
||||
* Convert a current locale string to UTF-16BE/LE and copy the result.
|
||||
* Return -1 if conversion failes.
|
||||
* Return -1 if conversion fails.
|
||||
*/
|
||||
static int
|
||||
best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p,
|
||||
@ -3942,7 +3953,7 @@ archive_mstring_get_mbs_l(struct archive_mstring *aes,
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/*
|
||||
* Internationalization programing on Windows must use Wide
|
||||
* Internationalization programming on Windows must use Wide
|
||||
* characters because Windows platform cannot make locale UTF-8.
|
||||
*/
|
||||
if (sc != NULL && (aes->aes_set & AES_SET_WCS) != 0) {
|
||||
@ -4074,7 +4085,7 @@ archive_mstring_copy_mbs_len_l(struct archive_mstring *aes,
|
||||
archive_string_empty(&(aes->aes_utf8));
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/*
|
||||
* Internationalization programing on Windows must use Wide
|
||||
* Internationalization programming on Windows must use Wide
|
||||
* characters because Windows platform cannot make locale UTF-8.
|
||||
*/
|
||||
if (sc == NULL) {
|
||||
|
@ -81,6 +81,10 @@ archive_strappend_char(struct archive_string *, char);
|
||||
struct archive_wstring *
|
||||
archive_wstrappend_wchar(struct archive_wstring *, wchar_t);
|
||||
|
||||
/* Append a raw array to an archive_string, resizing as necessary */
|
||||
struct archive_string *
|
||||
archive_array_append(struct archive_string *, const char *, size_t);
|
||||
|
||||
/* Convert a Unicode string to current locale and append the result. */
|
||||
/* Returns -1 if conversion fails. */
|
||||
int
|
||||
@ -115,13 +119,13 @@ archive_string_conversion_set_opt(struct archive_string_conv *, int);
|
||||
|
||||
|
||||
/* Copy one archive_string to another in locale conversion.
|
||||
* Return -1 if conversion failes. */
|
||||
* Return -1 if conversion fails. */
|
||||
int
|
||||
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. */
|
||||
* Return -1 if conversion fails. */
|
||||
int
|
||||
archive_strncat_l(struct archive_string *, const void *, size_t,
|
||||
struct archive_string_conv *);
|
||||
|
@ -1009,7 +1009,7 @@ static const char u_decomposable_blocks[0x1D2+1] = {
|
||||
(((uc) > 0x1D244)?0:\
|
||||
ccc_val[ccc_val_index[ccc_index[(uc)>>8]][((uc)>>4)&0x0F]][(uc)&0x0F])
|
||||
|
||||
/* The table of the value of Canonical Cimbining Class */
|
||||
/* The table of the value of Canonical Combining Class */
|
||||
static const unsigned char ccc_val[][16] = {
|
||||
/* idx=0: XXXX0 - XXXXF */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
|
@ -580,7 +580,7 @@ void
|
||||
__archive_ensure_cloexec_flag(int fd)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
(void)fd; /* UNSED */
|
||||
(void)fd; /* UNUSED */
|
||||
#else
|
||||
int flags;
|
||||
|
||||
|
@ -766,7 +766,7 @@ __la_win_entry_in_posix_pathseparator(struct archive_entry *entry)
|
||||
has_backslash = 1;
|
||||
}
|
||||
/*
|
||||
* If there is no backslach chars, return the original.
|
||||
* If there is no backslash chars, return the original.
|
||||
*/
|
||||
if (!has_backslash)
|
||||
return (entry);
|
||||
@ -891,7 +891,7 @@ __la_dosmaperr(unsigned long e)
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)sizeof(doserrors); i++)
|
||||
for (i = 0; i < (int)(sizeof(doserrors)/sizeof(doserrors[0])); i++)
|
||||
{
|
||||
if (doserrors[i].winerr == e)
|
||||
{
|
||||
|
@ -224,16 +224,20 @@
|
||||
#define S_IWUSR _S_IWUSR
|
||||
#define S_IRUSR _S_IRUSR
|
||||
#endif
|
||||
#ifndef S_IRWXG
|
||||
#define S_IRWXG _S_IRWXG
|
||||
#define S_IXGRP _S_IXGRP
|
||||
#define S_IWGRP _S_IWGRP
|
||||
#endif
|
||||
#ifndef S_IRGRP
|
||||
#define S_IRGRP _S_IRGRP
|
||||
#endif
|
||||
#ifndef S_IRWXO
|
||||
#define S_IRWXO _S_IRWXO
|
||||
#define S_IXOTH _S_IXOTH
|
||||
#define S_IWOTH _S_IWOTH
|
||||
#define S_IROTH _S_IROTH
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -109,10 +109,9 @@ archive_write_new(void)
|
||||
struct archive_write *a;
|
||||
unsigned char *nulls;
|
||||
|
||||
a = (struct archive_write *)malloc(sizeof(*a));
|
||||
a = (struct archive_write *)calloc(1, sizeof(*a));
|
||||
if (a == NULL)
|
||||
return (NULL);
|
||||
memset(a, 0, sizeof(*a));
|
||||
a->archive.magic = ARCHIVE_WRITE_MAGIC;
|
||||
a->archive.state = ARCHIVE_STATE_NEW;
|
||||
a->archive.vtable = archive_write_vtable();
|
||||
@ -126,12 +125,11 @@ archive_write_new(void)
|
||||
|
||||
/* Initialize a block of nulls for padding purposes. */
|
||||
a->null_length = 1024;
|
||||
nulls = (unsigned char *)malloc(a->null_length);
|
||||
nulls = (unsigned char *)calloc(1, a->null_length);
|
||||
if (nulls == NULL) {
|
||||
free(a);
|
||||
return (NULL);
|
||||
}
|
||||
memset(nulls, 0, a->null_length);
|
||||
a->nulls = nulls;
|
||||
return (&a->archive);
|
||||
}
|
||||
@ -233,7 +231,7 @@ __archive_write_filter(struct archive_write_filter *f,
|
||||
if (length == 0)
|
||||
return(ARCHIVE_OK);
|
||||
if (f->write == NULL)
|
||||
/* If unset, a fatal error has already ocuured, so this filter
|
||||
/* If unset, a fatal error has already occurred, so this filter
|
||||
* didn't open. We cannot write anything. */
|
||||
return(ARCHIVE_FATAL);
|
||||
r = (f->write)(f, buff, length);
|
||||
|
@ -523,7 +523,7 @@ drive_compressor_independence(struct archive_write_filter *f, const char *p,
|
||||
archive_le32enc(data->out, outsize);
|
||||
data->out += 4;
|
||||
} else {
|
||||
/* The buffer is not compressed. The commpressed size was
|
||||
/* The buffer is not compressed. The compressed size was
|
||||
* bigger than its uncompressed size. */
|
||||
archive_le32enc(data->out, length | 0x80000000);
|
||||
data->out += 4;
|
||||
@ -608,7 +608,7 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p,
|
||||
archive_le32enc(data->out, outsize);
|
||||
data->out += 4;
|
||||
} else {
|
||||
/* The buffer is not compressed. The commpressed size was
|
||||
/* The buffer is not compressed. The compressed size was
|
||||
* bigger than its uncompressed size. */
|
||||
archive_le32enc(data->out, length | 0x80000000);
|
||||
data->out += 4;
|
||||
|
@ -200,6 +200,7 @@ __archive_write_program_free(struct archive_write_program_data *data)
|
||||
if (data->child)
|
||||
CloseHandle(data->child);
|
||||
#endif
|
||||
free(data->program_name);
|
||||
free(data->child_buf);
|
||||
free(data);
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ archive_compressor_xz_init_stream(struct archive_write_filter *f,
|
||||
if (f->code == ARCHIVE_FILTER_XZ) {
|
||||
#ifdef HAVE_LZMA_STREAM_ENCODER_MT
|
||||
if (data->threads != 1) {
|
||||
bzero(&mt_options, sizeof(mt_options));
|
||||
memset(&mt_options, 0, sizeof(mt_options));
|
||||
mt_options.threads = data->threads;
|
||||
mt_options.timeout = 300;
|
||||
mt_options.filters = data->lzmafilters;
|
||||
|
@ -34,6 +34,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0
|
||||
#define _ACL_PRIVATE /* For debugging */
|
||||
#include <sys/acl.h>
|
||||
#endif
|
||||
#if HAVE_DARWIN_ACL
|
||||
#include <membership.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
@ -43,7 +46,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0
|
||||
#include "archive_acl_private.h"
|
||||
#include "archive_write_disk_private.h"
|
||||
|
||||
#ifndef HAVE_POSIX_ACL
|
||||
#if !HAVE_POSIX_ACL && !HAVE_NFS4_ACL
|
||||
/* Default empty function body to satisfy mainline code. */
|
||||
int
|
||||
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
||||
@ -56,47 +59,111 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
|
||||
|
||||
#if HAVE_SUN_ACL
|
||||
#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T
|
||||
#elif HAVE_DARWIN_ACL
|
||||
#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED
|
||||
#elif HAVE_ACL_TYPE_NFS4
|
||||
#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4
|
||||
#endif
|
||||
|
||||
static int set_acl(struct archive *, int fd, const char *,
|
||||
struct archive_acl *,
|
||||
acl_type_t, int archive_entry_acl_type, const char *tn);
|
||||
|
||||
/*
|
||||
* XXX TODO: What about ACL types other than ACCESS and DEFAULT?
|
||||
*/
|
||||
int
|
||||
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
||||
struct archive_acl *abstract_acl)
|
||||
{
|
||||
int ret;
|
||||
int ret = ARCHIVE_OK;
|
||||
|
||||
if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) > 0) {
|
||||
ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_ACCESS,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
|
||||
#if !HAVE_DARWIN_ACL
|
||||
if ((archive_acl_types(abstract_acl)
|
||||
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
||||
#if HAVE_SUN_ACL
|
||||
/* Solaris writes POSIX.1e access and default ACLs together */
|
||||
ret = set_acl(a, fd, name, abstract_acl, ACLENT_T,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
|
||||
#else /* HAVE_POSIX_ACL */
|
||||
if ((archive_acl_types(abstract_acl)
|
||||
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
||||
ret = set_acl(a, fd, name, abstract_acl,
|
||||
ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
|
||||
"access");
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
}
|
||||
if ((archive_acl_types(abstract_acl)
|
||||
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
||||
ret = set_acl(a, fd, name, abstract_acl,
|
||||
ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
|
||||
"default");
|
||||
#endif /* !HAVE_SUN_ACL */
|
||||
/* Simultaneous POSIX.1e and NFSv4 is not supported */
|
||||
return (ret);
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
} else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) {
|
||||
ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4,
|
||||
}
|
||||
#endif /* !HAVE_DARWIN_ACL */
|
||||
#if HAVE_NFS4_ACL
|
||||
if ((archive_acl_types(abstract_acl) &
|
||||
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
||||
ret = set_acl(a, fd, name, abstract_acl,
|
||||
ARCHIVE_PLATFORM_ACL_TYPE_NFS4,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
|
||||
return (ret);
|
||||
#endif
|
||||
} else
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
#endif /* HAVE_NFS4_ACL */
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static struct {
|
||||
int archive_perm;
|
||||
int platform_perm;
|
||||
/*
|
||||
* Translate system ACL permissions into libarchive internal structure
|
||||
*/
|
||||
static const struct {
|
||||
const int archive_perm;
|
||||
const int platform_perm;
|
||||
} acl_perm_map[] = {
|
||||
#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */
|
||||
{ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
|
||||
{ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
|
||||
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
|
||||
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
|
||||
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
|
||||
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
|
||||
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
|
||||
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
|
||||
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
|
||||
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
|
||||
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
|
||||
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
|
||||
{ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
|
||||
{ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
|
||||
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
|
||||
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
|
||||
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
|
||||
#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */
|
||||
{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_EXECUTE, ACL_EXECUTE},
|
||||
{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
|
||||
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
|
||||
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
|
||||
{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_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
|
||||
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
|
||||
{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
|
||||
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
|
||||
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
|
||||
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
|
||||
#else /* POSIX.1e ACL permissions */
|
||||
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
|
||||
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
|
||||
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */
|
||||
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
|
||||
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
|
||||
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
|
||||
@ -114,33 +181,69 @@ static struct {
|
||||
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
|
||||
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
|
||||
#endif
|
||||
#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
|
||||
};
|
||||
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
static struct {
|
||||
int archive_inherit;
|
||||
int platform_inherit;
|
||||
#if HAVE_NFS4_ACL
|
||||
/*
|
||||
* Translate system NFSv4 inheritance flags into libarchive internal structure
|
||||
*/
|
||||
static const struct {
|
||||
const int archive_inherit;
|
||||
const int platform_inherit;
|
||||
} acl_inherit_map[] = {
|
||||
#if HAVE_SUN_ACL /* Solaris NFSv4 inheritance flags */
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
|
||||
#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
|
||||
{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_LIMIT_INHERIT},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
|
||||
#else /* FreeBSD NFSv4 ACL inheritance flags */
|
||||
{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}
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
|
||||
#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
|
||||
};
|
||||
#endif
|
||||
#endif /* HAVE_NFS4_ACL */
|
||||
|
||||
static int
|
||||
set_acl(struct archive *a, int fd, const char *name,
|
||||
struct archive_acl *abstract_acl,
|
||||
acl_type_t acl_type, int ae_requested_type, const char *tname)
|
||||
{
|
||||
#if HAVE_SUN_ACL
|
||||
aclent_t *aclent;
|
||||
ace_t *ace;
|
||||
int e, r;
|
||||
acl_t *acl;
|
||||
#else
|
||||
acl_t acl;
|
||||
acl_entry_t acl_entry;
|
||||
acl_permset_t acl_permset;
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL
|
||||
acl_flagset_t acl_flagset;
|
||||
#endif
|
||||
#endif /* HAVE_SUN_ACL */
|
||||
#if HAVE_ACL_TYPE_NFS4
|
||||
int r;
|
||||
#endif
|
||||
int ret;
|
||||
int ae_type, ae_permset, ae_tag, ae_id;
|
||||
#if HAVE_DARWIN_ACL
|
||||
uuid_t ae_uuid;
|
||||
#endif
|
||||
uid_t ae_uid;
|
||||
gid_t ae_gid;
|
||||
const char *ae_name;
|
||||
@ -151,22 +254,165 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
entries = archive_acl_reset(abstract_acl, ae_requested_type);
|
||||
if (entries == 0)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
#if HAVE_SUN_ACL
|
||||
acl = NULL;
|
||||
acl = malloc(sizeof(acl_t));
|
||||
if (acl == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid ACL type");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
if (acl_type == ACE_T)
|
||||
acl->acl_entry_size = sizeof(ace_t);
|
||||
else if (acl_type == ACLENT_T)
|
||||
acl->acl_entry_size = sizeof(aclent_t);
|
||||
else {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid ACL type");
|
||||
acl_free(acl);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
acl->acl_type = acl_type;
|
||||
acl->acl_cnt = entries;
|
||||
|
||||
acl->acl_aclp = malloc(entries * acl->acl_entry_size);
|
||||
if (acl->acl_aclp == NULL) {
|
||||
archive_set_error(a, errno,
|
||||
"Can't allocate memory for acl buffer");
|
||||
acl_free(acl);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
#else /* !HAVE_SUN_ACL */
|
||||
acl = acl_init(entries);
|
||||
if (acl == (acl_t)NULL) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to initialize ACL working storage");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
#endif /* !HAVE_SUN_ACL */
|
||||
#if HAVE_SUN_ACL
|
||||
e = 0;
|
||||
#endif
|
||||
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
|
||||
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
|
||||
acl_create_entry(&acl, &acl_entry);
|
||||
|
||||
#if HAVE_SUN_ACL
|
||||
ace = NULL;
|
||||
aclent = NULL;
|
||||
if (acl->acl_type == ACE_T) {
|
||||
ace = &((ace_t *)acl->acl_aclp)[e];
|
||||
ace->a_who = -1;
|
||||
ace->a_access_mask = 0;
|
||||
ace->a_flags = 0;
|
||||
} else {
|
||||
aclent = &((aclent_t *)acl->acl_aclp)[e];
|
||||
aclent->a_id = -1;
|
||||
aclent->a_type = 0;
|
||||
aclent->a_perm = 0;
|
||||
}
|
||||
#else /* !HAVE_SUN_ACL */
|
||||
#if HAVE_DARWIN_ACL
|
||||
/*
|
||||
* Mac OS doesn't support NFSv4 ACLs for
|
||||
* owner@, group@ and everyone@.
|
||||
* We skip any of these ACLs found.
|
||||
*/
|
||||
if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ ||
|
||||
ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ ||
|
||||
ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE)
|
||||
continue;
|
||||
#endif
|
||||
if (acl_create_entry(&acl, &acl_entry) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to create a new ACL entry");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
#endif /* !HAVE_SUN_ACL */
|
||||
#if HAVE_DARWIN_ACL
|
||||
switch (ae_type) {
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
|
||||
acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW);
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
|
||||
acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY);
|
||||
break;
|
||||
default:
|
||||
/* We don't support any other types on MacOS */
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
switch (ae_tag) {
|
||||
#if HAVE_SUN_ACL
|
||||
case ARCHIVE_ENTRY_ACL_USER:
|
||||
acl_set_tag_type(acl_entry, ACL_USER);
|
||||
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
|
||||
acl_set_qualifier(acl_entry, &ae_uid);
|
||||
if (acl->acl_type == ACE_T)
|
||||
ace->a_who = ae_uid;
|
||||
else {
|
||||
aclent->a_id = ae_uid;
|
||||
aclent->a_type |= USER;
|
||||
}
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_GROUP:
|
||||
acl_set_tag_type(acl_entry, ACL_GROUP);
|
||||
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
|
||||
acl_set_qualifier(acl_entry, &ae_gid);
|
||||
if (acl->acl_type == ACE_T) {
|
||||
ace->a_who = ae_gid;
|
||||
ace->a_flags |= ACE_IDENTIFIER_GROUP;
|
||||
} else {
|
||||
aclent->a_id = ae_gid;
|
||||
aclent->a_type |= GROUP;
|
||||
}
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_USER_OBJ:
|
||||
if (acl->acl_type == ACE_T)
|
||||
ace->a_flags |= ACE_OWNER;
|
||||
else
|
||||
aclent->a_type |= USER_OBJ;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
|
||||
if (acl->acl_type == ACE_T) {
|
||||
ace->a_flags |= ACE_GROUP;
|
||||
ace->a_flags |= ACE_IDENTIFIER_GROUP;
|
||||
} else
|
||||
aclent->a_type |= GROUP_OBJ;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_MASK:
|
||||
aclent->a_type |= CLASS_OBJ;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_OTHER:
|
||||
aclent->a_type |= OTHER_OBJ;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_EVERYONE:
|
||||
ace->a_flags |= ACE_EVERYONE;
|
||||
break;
|
||||
#else /* !HAVE_SUN_ACL */
|
||||
case ARCHIVE_ENTRY_ACL_USER:
|
||||
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
|
||||
#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
|
||||
acl_set_tag_type(acl_entry, ACL_USER);
|
||||
acl_set_qualifier(acl_entry, &ae_uid);
|
||||
#else /* MacOS */
|
||||
if (mbr_identifier_to_uuid(ID_TYPE_UID, &ae_uid,
|
||||
sizeof(uid_t), ae_uuid) != 0)
|
||||
continue;
|
||||
if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
|
||||
continue;
|
||||
#endif /* HAVE_DARWIN_ACL */
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_GROUP:
|
||||
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
|
||||
#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
|
||||
acl_set_tag_type(acl_entry, ACL_GROUP);
|
||||
acl_set_qualifier(acl_entry, &ae_gid);
|
||||
#else /* MacOS */
|
||||
if (mbr_identifier_to_uuid(ID_TYPE_GID, &ae_gid,
|
||||
sizeof(gid_t), ae_uuid) != 0)
|
||||
continue;
|
||||
if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
|
||||
continue;
|
||||
#endif /* HAVE_DARWIN_ACL */
|
||||
break;
|
||||
#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
|
||||
case ARCHIVE_ENTRY_ACL_USER_OBJ:
|
||||
acl_set_tag_type(acl_entry, ACL_USER_OBJ);
|
||||
break;
|
||||
@ -179,85 +425,230 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
case ARCHIVE_ENTRY_ACL_OTHER:
|
||||
acl_set_tag_type(acl_entry, ACL_OTHER);
|
||||
break;
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
#if HAVE_ACL_TYPE_NFS4 /* FreeBSD only */
|
||||
case ARCHIVE_ENTRY_ACL_EVERYONE:
|
||||
acl_set_tag_type(acl_entry, ACL_EVERYONE);
|
||||
break;
|
||||
#endif
|
||||
#endif /* !HAVE_DARWIN_ACL */
|
||||
#endif /* !HAVE_SUN_ACL */
|
||||
default:
|
||||
/* XXX */
|
||||
break;
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Unknown ACL tag");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
#if HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL
|
||||
r = 0;
|
||||
switch (ae_type) {
|
||||
#if HAVE_SUN_ACL
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
|
||||
acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
|
||||
if (ace != NULL)
|
||||
ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
|
||||
else
|
||||
r = -1;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
|
||||
acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
|
||||
if (ace != NULL)
|
||||
ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
|
||||
else
|
||||
r = -1;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
|
||||
acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
|
||||
if (ace != NULL)
|
||||
ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
|
||||
else
|
||||
r = -1;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
|
||||
acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
|
||||
if (ace != NULL)
|
||||
ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
|
||||
else
|
||||
r = -1;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
|
||||
if (aclent == NULL)
|
||||
r = -1;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
|
||||
if (aclent != NULL)
|
||||
aclent->a_type |= ACL_DEFAULT;
|
||||
else
|
||||
r = -1;
|
||||
break;
|
||||
#else /* !HAVE_SUN_ACL */
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
|
||||
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
|
||||
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
|
||||
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
|
||||
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
|
||||
// These don't translate directly into the system ACL.
|
||||
break;
|
||||
#endif /* !HAVE_SUN_ACL */
|
||||
default:
|
||||
// XXX error handling here.
|
||||
break;
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Unknown ACL entry type");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
if (r != 0) {
|
||||
#if HAVE_SUN_ACL
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
archive_set_error(a, errno,
|
||||
"Failed to set ACL entry type");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL */
|
||||
|
||||
acl_get_permset(acl_entry, &acl_permset);
|
||||
acl_clear_perms(acl_permset);
|
||||
|
||||
#if HAVE_SUN_ACL
|
||||
if (acl->acl_type == ACLENT_T) {
|
||||
if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE)
|
||||
aclent->a_perm |= 1;
|
||||
if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE)
|
||||
aclent->a_perm |= 2;
|
||||
if (ae_permset & ARCHIVE_ENTRY_ACL_READ)
|
||||
aclent->a_perm |= 4;
|
||||
} else
|
||||
#else
|
||||
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to get ACL permission set");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
if (acl_clear_perms(acl_permset) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to clear ACL permissions");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
#endif /* !HAVE_SUN_ACL */
|
||||
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
|
||||
if (ae_permset & acl_perm_map[i].archive_perm)
|
||||
acl_add_perm(acl_permset,
|
||||
acl_perm_map[i].platform_perm);
|
||||
if (ae_permset & acl_perm_map[i].archive_perm) {
|
||||
#if HAVE_SUN_ACL
|
||||
ace->a_access_mask |=
|
||||
acl_perm_map[i].platform_perm;
|
||||
#else
|
||||
if (acl_add_perm(acl_permset,
|
||||
acl_perm_map[i].platform_perm) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to add ACL permission");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
acl_get_flagset_np(acl_entry, &acl_flagset);
|
||||
acl_clear_flags_np(acl_flagset);
|
||||
for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
|
||||
if (ae_permset & acl_inherit_map[i].archive_inherit)
|
||||
acl_add_flag_np(acl_flagset,
|
||||
acl_inherit_map[i].platform_inherit);
|
||||
#if HAVE_NFS4_ACL
|
||||
#if HAVE_SUN_ACL
|
||||
if (acl_type == ACE_T)
|
||||
#elif HAVE_DARWIN_ACL
|
||||
if (acl_type == ACL_TYPE_EXTENDED)
|
||||
#else /* FreeBSD */
|
||||
if (acl_type == ACL_TYPE_NFS4)
|
||||
#endif
|
||||
{
|
||||
#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL
|
||||
/*
|
||||
* acl_get_flagset_np() fails with non-NFSv4 ACLs
|
||||
*/
|
||||
if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to get flagset from an NFSv4 ACL entry");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
if (acl_clear_flags_np(acl_flagset) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to clear flags from an NFSv4 ACL flagset");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */
|
||||
for (i = 0; i < (int)(sizeof(acl_inherit_map) /sizeof(acl_inherit_map[0])); ++i) {
|
||||
if (ae_permset & acl_inherit_map[i].archive_inherit) {
|
||||
#if HAVE_SUN_ACL
|
||||
ace->a_flags |=
|
||||
acl_inherit_map[i].platform_inherit;
|
||||
#else /* !HAVE_SUN_ACL */
|
||||
if (acl_add_flag_np(acl_flagset,
|
||||
acl_inherit_map[i].platform_inherit) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to add flag to NFSv4 ACL flagset");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
#endif /* HAVE_SUN_ACL */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_NFS4_ACL */
|
||||
#if HAVE_SUN_ACL
|
||||
e++;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL
|
||||
/* Try restoring the ACL through 'fd' if we can. */
|
||||
#if HAVE_ACL_SET_FD
|
||||
if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0)
|
||||
ret = ARCHIVE_OK;
|
||||
else
|
||||
#else
|
||||
#if HAVE_ACL_SET_FD_NP
|
||||
if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0)
|
||||
ret = ARCHIVE_OK;
|
||||
else
|
||||
#if HAVE_SUN_ACL || HAVE_ACL_SET_FD_NP
|
||||
if (fd >= 0)
|
||||
#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
|
||||
if (fd >= 0 && acl_type == ACL_TYPE_ACCESS)
|
||||
#endif
|
||||
{
|
||||
#if HAVE_SUN_ACL
|
||||
if (facl_set(fd, acl) == 0)
|
||||
#elif HAVE_ACL_SET_FD_NP
|
||||
if (acl_set_fd_np(fd, acl, acl_type) == 0)
|
||||
#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */
|
||||
if (acl_set_fd(fd, acl) == 0)
|
||||
#endif
|
||||
#if HAVE_ACL_SET_LINK_NP
|
||||
if (acl_set_link_np(name, acl_type, acl) != 0) {
|
||||
archive_set_error(a, errno, "Failed to set %s acl", tname);
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
ret = ARCHIVE_OK;
|
||||
else {
|
||||
if (errno == EOPNOTSUPP) {
|
||||
/* Filesystem doesn't support ACLs */
|
||||
ret = ARCHIVE_OK;
|
||||
} else {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to set %s acl on fd", tname);
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif /* HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL */
|
||||
#if HAVE_SUN_ACL
|
||||
if (acl_set(name, acl) != 0)
|
||||
#elif HAVE_ACL_SET_LINK_NP
|
||||
if (acl_set_link_np(name, acl_type, acl) != 0)
|
||||
#else
|
||||
/* TODO: Skip this if 'name' is a symlink. */
|
||||
if (acl_set_file(name, acl_type, acl) != 0) {
|
||||
archive_set_error(a, errno, "Failed to set %s acl", tname);
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
if (acl_set_file(name, acl_type, acl) != 0)
|
||||
#endif
|
||||
{
|
||||
if (errno == EOPNOTSUPP) {
|
||||
/* Filesystem doesn't support ACLs */
|
||||
ret = ARCHIVE_OK;
|
||||
} else {
|
||||
archive_set_error(a, errno, "Failed to set %s acl",
|
||||
tname);
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
}
|
||||
exit_free:
|
||||
acl_free(acl);
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
|
||||
|
@ -110,6 +110,18 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/fcntl1.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared.
|
||||
*
|
||||
* It assumes that the input is an integer type of no more than 64 bits.
|
||||
* If the number is less than zero, t must be a signed type, so it fits in
|
||||
* int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t
|
||||
* without loss. But it could be a large unsigned value, so we have to clip it
|
||||
* to INT64_MAX.*
|
||||
*/
|
||||
#define to_int64_time(t) \
|
||||
((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t))
|
||||
|
||||
#if __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H
|
||||
@ -140,7 +152,17 @@ __FBSDID("$FreeBSD$");
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
/* Ignore non-int O_NOFOLLOW constant. */
|
||||
/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */
|
||||
#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
|
||||
#undef O_NOFOLLOW
|
||||
#endif
|
||||
|
||||
#ifndef O_NOFOLLOW
|
||||
#define O_NOFOLLOW 0
|
||||
#endif
|
||||
|
||||
struct fixup_entry {
|
||||
@ -298,7 +320,7 @@ struct archive_write_disk {
|
||||
#define MAXIMUM_DIR_MODE 0775
|
||||
|
||||
/*
|
||||
* Maxinum uncompressed size of a decmpfs block.
|
||||
* Maximum uncompressed size of a decmpfs block.
|
||||
*/
|
||||
#define MAX_DECMPFS_BLOCK_SIZE (64 * 1024)
|
||||
/*
|
||||
@ -313,7 +335,7 @@ struct archive_write_disk {
|
||||
#define RSRC_F_SIZE 50 /* Size of Resource fork footer. */
|
||||
/* Size to write compressed data to resource fork. */
|
||||
#define COMPRESSED_W_SIZE (64 * 1024)
|
||||
/* decmpfs difinitions. */
|
||||
/* decmpfs definitions. */
|
||||
#define MAX_DECMPFS_XATTR_SIZE 3802
|
||||
#ifndef DECMPFS_XATTR_NAME
|
||||
#define DECMPFS_XATTR_NAME "com.apple.decmpfs"
|
||||
@ -326,12 +348,19 @@ struct archive_write_disk {
|
||||
|
||||
#define HFS_BLOCKS(s) ((s) >> 12)
|
||||
|
||||
static void fsobj_error(int *, struct archive_string *, int, const char *,
|
||||
const char *);
|
||||
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
|
||||
int);
|
||||
static int check_symlinks(struct archive_write_disk *);
|
||||
static int create_filesystem_object(struct archive_write_disk *);
|
||||
static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname);
|
||||
static struct fixup_entry *current_fixup(struct archive_write_disk *,
|
||||
const char *pathname);
|
||||
#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
|
||||
static void edit_deep_directories(struct archive_write_disk *ad);
|
||||
#endif
|
||||
static int cleanup_pathname_fsobj(char *, int *, struct archive_string *,
|
||||
int);
|
||||
static int cleanup_pathname(struct archive_write_disk *);
|
||||
static int create_dir(struct archive_write_disk *, char *);
|
||||
static int create_parent_dir(struct archive_write_disk *, char *);
|
||||
@ -362,11 +391,14 @@ static struct archive_vtable *archive_write_disk_vtable(void);
|
||||
|
||||
static int _archive_write_disk_close(struct archive *);
|
||||
static int _archive_write_disk_free(struct archive *);
|
||||
static int _archive_write_disk_header(struct archive *, struct archive_entry *);
|
||||
static int _archive_write_disk_header(struct archive *,
|
||||
struct archive_entry *);
|
||||
static int64_t _archive_write_disk_filter_bytes(struct archive *, int);
|
||||
static int _archive_write_disk_finish_entry(struct archive *);
|
||||
static ssize_t _archive_write_disk_data(struct archive *, const void *, size_t);
|
||||
static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t);
|
||||
static ssize_t _archive_write_disk_data(struct archive *, const void *,
|
||||
size_t);
|
||||
static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
|
||||
size_t, int64_t);
|
||||
|
||||
static int
|
||||
lazy_stat(struct archive_write_disk *a)
|
||||
@ -612,9 +644,9 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
/*
|
||||
* NOTE: UF_COMPRESSED is ignored even if the filesystem
|
||||
* supports HFS+ Compression because the file should
|
||||
* have at least an extended attriute "com.apple.decmpfs"
|
||||
* have at least an extended attribute "com.apple.decmpfs"
|
||||
* before the flag is set to indicate that the file have
|
||||
* been compressed. If hte filesystem does not support
|
||||
* been compressed. If the filesystem does not support
|
||||
* HFS+ Compression the system call will fail.
|
||||
*/
|
||||
if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0)
|
||||
@ -637,7 +669,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
if (a->restore_pwd >= 0) {
|
||||
r = fchdir(a->restore_pwd);
|
||||
if (r != 0) {
|
||||
archive_set_error(&a->archive, errno, "chdir() failure");
|
||||
archive_set_error(&a->archive, errno,
|
||||
"chdir() failure");
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
close(a->restore_pwd);
|
||||
@ -685,7 +718,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
}
|
||||
if (archive_entry_birthtime_is_set(entry)) {
|
||||
fe->birthtime = archive_entry_birthtime(entry);
|
||||
fe->birthtime_nanos = archive_entry_birthtime_nsec(entry);
|
||||
fe->birthtime_nanos = archive_entry_birthtime_nsec(
|
||||
entry);
|
||||
} else {
|
||||
/* If birthtime is unset, use mtime. */
|
||||
fe->birthtime = fe->mtime;
|
||||
@ -711,7 +745,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->mac_metadata = malloc(metadata_size);
|
||||
if (fe->mac_metadata != NULL) {
|
||||
memcpy(fe->mac_metadata, metadata, metadata_size);
|
||||
memcpy(fe->mac_metadata, metadata,
|
||||
metadata_size);
|
||||
fe->mac_metadata_size = metadata_size;
|
||||
fe->fixup |= TODO_MAC_METADATA;
|
||||
}
|
||||
@ -1224,7 +1259,7 @@ hfs_drive_compressor(struct archive_write_disk *a, const char *buff,
|
||||
ret = hfs_write_compressed_data(a, bytes_used + rsrc_size);
|
||||
a->compressed_buffer_remaining = a->compressed_buffer_size;
|
||||
|
||||
/* If the compressed size is not enouph smaller than
|
||||
/* If the compressed size is not enough smaller than
|
||||
* the uncompressed size. cancel HFS+ compression.
|
||||
* TODO: study a behavior of ditto utility and improve
|
||||
* the condition to fall back into no HFS+ compression. */
|
||||
@ -1329,7 +1364,7 @@ hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff,
|
||||
(uint32_t *)(a->resource_fork + RSRC_H_SIZE);
|
||||
/* Set the block count to the resource fork. */
|
||||
archive_le32enc(a->decmpfs_block_info++, block_count);
|
||||
/* Get the position where we are goint to set compressed
|
||||
/* Get the position where we are going to set compressed
|
||||
* data. */
|
||||
a->compressed_rsrc_position =
|
||||
RSRC_H_SIZE + 4 + (block_count * 8);
|
||||
@ -1402,7 +1437,7 @@ hfs_write_data_block(struct archive_write_disk *a, const char *buff,
|
||||
bytes_to_write = size;
|
||||
/* Seek if necessary to the specified offset. */
|
||||
if (a->offset < a->fd_offset) {
|
||||
/* Can't support backword move. */
|
||||
/* Can't support backward move. */
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Seek failed");
|
||||
return (ARCHIVE_FATAL);
|
||||
@ -1468,7 +1503,8 @@ _archive_write_disk_data_block(struct archive *_a,
|
||||
return (r);
|
||||
if ((size_t)r < size) {
|
||||
archive_set_error(&a->archive, 0,
|
||||
"Too much data: Truncating file at %ju bytes", (uintmax_t)a->filesize);
|
||||
"Too much data: Truncating file at %ju bytes",
|
||||
(uintmax_t)a->filesize);
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
#if ARCHIVE_VERSION_NUMBER < 3999000
|
||||
@ -1666,10 +1702,25 @@ _archive_write_disk_finish_entry(struct archive *_a)
|
||||
* ACLs that prevent attribute changes (including time).
|
||||
*/
|
||||
if (a->todo & TODO_ACLS) {
|
||||
int r2 = archive_write_disk_set_acls(&a->archive, a->fd,
|
||||
archive_entry_pathname(a->entry),
|
||||
archive_entry_acl(a->entry));
|
||||
int r2;
|
||||
#ifdef HAVE_DARWIN_ACL
|
||||
/*
|
||||
* On Mac OS, platform ACLs are stored also in mac_metadata by
|
||||
* the operating system. If mac_metadata is present it takes
|
||||
* precedence and we skip extracting libarchive NFSv4 ACLs
|
||||
*/
|
||||
const void *metadata;
|
||||
size_t metadata_size;
|
||||
metadata = archive_entry_mac_metadata(a->entry, &metadata_size);
|
||||
if (metadata == NULL || metadata_size == 0) {
|
||||
#endif
|
||||
r2 = archive_write_disk_set_acls(&a->archive, a->fd,
|
||||
archive_entry_pathname(a->entry),
|
||||
archive_entry_acl(a->entry));
|
||||
if (r2 < ret) ret = r2;
|
||||
#ifdef HAVE_DARWIN_ACL
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
finish_metadata:
|
||||
@ -1755,10 +1806,9 @@ archive_write_disk_new(void)
|
||||
{
|
||||
struct archive_write_disk *a;
|
||||
|
||||
a = (struct archive_write_disk *)malloc(sizeof(*a));
|
||||
a = (struct archive_write_disk *)calloc(1, sizeof(*a));
|
||||
if (a == NULL)
|
||||
return (NULL);
|
||||
memset(a, 0, sizeof(*a));
|
||||
a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
|
||||
/* We're ready to write a header immediately. */
|
||||
a->archive.state = ARCHIVE_STATE_HEADER;
|
||||
@ -1796,7 +1846,7 @@ edit_deep_directories(struct archive_write_disk *a)
|
||||
char *tail = a->name;
|
||||
|
||||
/* If path is short, avoid the open() below. */
|
||||
if (strlen(tail) <= PATH_MAX)
|
||||
if (strlen(tail) < PATH_MAX)
|
||||
return;
|
||||
|
||||
/* Try to record our starting dir. */
|
||||
@ -1806,7 +1856,7 @@ edit_deep_directories(struct archive_write_disk *a)
|
||||
return;
|
||||
|
||||
/* As long as the path is too long... */
|
||||
while (strlen(tail) > PATH_MAX) {
|
||||
while (strlen(tail) >= PATH_MAX) {
|
||||
/* Locate a dir prefix shorter than PATH_MAX. */
|
||||
tail += PATH_MAX - 8;
|
||||
while (tail > a->name && *tail != '/')
|
||||
@ -1993,8 +2043,9 @@ restore_entry(struct archive_write_disk *a)
|
||||
|
||||
if (en) {
|
||||
/* Everything failed; give up here. */
|
||||
archive_set_error(&a->archive, en, "Can't create '%s'",
|
||||
a->name);
|
||||
if ((&a->archive)->error == NULL)
|
||||
archive_set_error(&a->archive, en, "Can't create '%s'",
|
||||
a->name);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
@ -2014,6 +2065,11 @@ create_filesystem_object(struct archive_write_disk *a)
|
||||
const char *linkname;
|
||||
mode_t final_mode, mode;
|
||||
int r;
|
||||
/* these for check_symlinks_fsobj */
|
||||
char *linkname_copy; /* non-const copy of linkname */
|
||||
struct stat st;
|
||||
struct archive_string error_string;
|
||||
int error_number;
|
||||
|
||||
/* We identify hard/symlinks according to the link names. */
|
||||
/* Since link(2) and symlink(2) don't handle modes, we're done here. */
|
||||
@ -2022,6 +2078,43 @@ create_filesystem_object(struct archive_write_disk *a)
|
||||
#if !HAVE_LINK
|
||||
return (EPERM);
|
||||
#else
|
||||
archive_string_init(&error_string);
|
||||
linkname_copy = strdup(linkname);
|
||||
if (linkname_copy == NULL) {
|
||||
return (EPERM);
|
||||
}
|
||||
/*
|
||||
* TODO: consider using the cleaned-up path as the link
|
||||
* target?
|
||||
*/
|
||||
r = cleanup_pathname_fsobj(linkname_copy, &error_number,
|
||||
&error_string, a->flags);
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s",
|
||||
error_string.s);
|
||||
free(linkname_copy);
|
||||
archive_string_free(&error_string);
|
||||
/*
|
||||
* EPERM is more appropriate than error_number for our
|
||||
* callers
|
||||
*/
|
||||
return (EPERM);
|
||||
}
|
||||
r = check_symlinks_fsobj(linkname_copy, &error_number,
|
||||
&error_string, a->flags);
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s",
|
||||
error_string.s);
|
||||
free(linkname_copy);
|
||||
archive_string_free(&error_string);
|
||||
/*
|
||||
* EPERM is more appropriate than error_number for our
|
||||
* callers
|
||||
*/
|
||||
return (EPERM);
|
||||
}
|
||||
free(linkname_copy);
|
||||
archive_string_free(&error_string);
|
||||
r = link(linkname, a->name) ? errno : 0;
|
||||
/*
|
||||
* New cpio and pax formats allow hardlink entries
|
||||
@ -2039,11 +2132,20 @@ create_filesystem_object(struct archive_write_disk *a)
|
||||
a->todo = 0;
|
||||
a->deferred = 0;
|
||||
} else if (r == 0 && a->filesize > 0) {
|
||||
a->fd = open(a->name,
|
||||
O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(a->fd);
|
||||
if (a->fd < 0)
|
||||
#ifdef HAVE_LSTAT
|
||||
r = lstat(a->name, &st);
|
||||
#else
|
||||
r = stat(a->name, &st);
|
||||
#endif
|
||||
if (r != 0)
|
||||
r = errno;
|
||||
else if ((st.st_mode & AE_IFMT) == AE_IFREG) {
|
||||
a->fd = open(a->name, O_WRONLY | O_TRUNC |
|
||||
O_BINARY | O_CLOEXEC | O_NOFOLLOW);
|
||||
__archive_ensure_cloexec_flag(a->fd);
|
||||
if (a->fd < 0)
|
||||
r = errno;
|
||||
}
|
||||
}
|
||||
return (r);
|
||||
#endif
|
||||
@ -2190,8 +2292,12 @@ _archive_write_disk_close(struct archive *_a)
|
||||
if (p->fixup & TODO_MODE_BASE)
|
||||
chmod(p->name, p->mode);
|
||||
if (p->fixup & TODO_ACLS)
|
||||
archive_write_disk_set_acls(&a->archive,
|
||||
-1, p->name, &p->acl);
|
||||
#ifdef HAVE_DARWIN_ACL
|
||||
if (p->mac_metadata == NULL ||
|
||||
p->mac_metadata_size == 0)
|
||||
#endif
|
||||
archive_write_disk_set_acls(&a->archive,
|
||||
-1, p->name, &p->acl);
|
||||
if (p->fixup & TODO_FFLAGS)
|
||||
set_fflags_platform(a, -1, p->name,
|
||||
p->mode, p->fflags_set, 0);
|
||||
@ -2351,116 +2457,283 @@ current_fixup(struct archive_write_disk *a, const char *pathname)
|
||||
return (a->current_fixup);
|
||||
}
|
||||
|
||||
/* TODO: Make this work. */
|
||||
/*
|
||||
* TODO: The deep-directory support bypasses this; disable deep directory
|
||||
* support if we're doing symlink checks.
|
||||
*/
|
||||
/* Error helper for new *_fsobj functions */
|
||||
static void
|
||||
fsobj_error(int *a_eno, struct archive_string *a_estr,
|
||||
int err, const char *errstr, const char *path)
|
||||
{
|
||||
if (a_eno)
|
||||
*a_eno = err;
|
||||
if (a_estr)
|
||||
archive_string_sprintf(a_estr, errstr, path);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Someday, integrate this with the deep dir support; they both
|
||||
* scan the path and both can be optimized by comparing against other
|
||||
* recent paths.
|
||||
*/
|
||||
/* TODO: Extend this to support symlinks on Windows Vista and later. */
|
||||
|
||||
/*
|
||||
* Checks the given path to see if any elements along it are symlinks. Returns
|
||||
* ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
|
||||
*/
|
||||
static int
|
||||
check_symlinks(struct archive_write_disk *a)
|
||||
check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
||||
int flags)
|
||||
{
|
||||
#if !defined(HAVE_LSTAT)
|
||||
/* Platform doesn't have lstat, so we can't look for symlinks. */
|
||||
(void)a; /* UNUSED */
|
||||
(void)path; /* UNUSED */
|
||||
(void)error_number; /* UNUSED */
|
||||
(void)error_string; /* UNUSED */
|
||||
(void)flags; /* UNUSED */
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
char *pn;
|
||||
int res = ARCHIVE_OK;
|
||||
char *tail;
|
||||
char *head;
|
||||
int last;
|
||||
char c;
|
||||
int r;
|
||||
struct stat st;
|
||||
int restore_pwd;
|
||||
|
||||
/* Nothing to do here if name is empty */
|
||||
if(path[0] == '\0')
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
/*
|
||||
* Guard against symlink tricks. Reject any archive entry whose
|
||||
* destination would be altered by a symlink.
|
||||
*
|
||||
* Walk the filename in chunks separated by '/'. For each segment:
|
||||
* - if it doesn't exist, continue
|
||||
* - if it's symlink, abort or remove it
|
||||
* - if it's a directory and it's not the last chunk, cd into it
|
||||
* As we go:
|
||||
* head points to the current (relative) path
|
||||
* tail points to the temporary \0 terminating the segment we're
|
||||
* currently examining
|
||||
* c holds what used to be in *tail
|
||||
* last is 1 if this is the last tail
|
||||
*/
|
||||
/* Whatever we checked last time doesn't need to be re-checked. */
|
||||
pn = a->name;
|
||||
if (archive_strlen(&(a->path_safe)) > 0) {
|
||||
char *p = a->path_safe.s;
|
||||
while ((*pn != '\0') && (*p == *pn))
|
||||
++p, ++pn;
|
||||
}
|
||||
restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(restore_pwd);
|
||||
if (restore_pwd < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
head = path;
|
||||
tail = path;
|
||||
last = 0;
|
||||
/* TODO: reintroduce a safe cache here? */
|
||||
/* Skip the root directory if the path is absolute. */
|
||||
if(pn == a->name && pn[0] == '/')
|
||||
++pn;
|
||||
c = pn[0];
|
||||
/* Keep going until we've checked the entire name. */
|
||||
while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) {
|
||||
if(tail == path && tail[0] == '/')
|
||||
++tail;
|
||||
/* Keep going until we've checked the entire name.
|
||||
* head, tail, path all alias the same string, which is
|
||||
* temporarily zeroed at tail, so be careful restoring the
|
||||
* stashed (c=tail[0]) for error messages.
|
||||
* Exiting the loop with break is okay; continue is not.
|
||||
*/
|
||||
while (!last) {
|
||||
/*
|
||||
* Skip the separator we just consumed, plus any adjacent ones
|
||||
*/
|
||||
while (*tail == '/')
|
||||
++tail;
|
||||
/* Skip the next path element. */
|
||||
while (*pn != '\0' && *pn != '/')
|
||||
++pn;
|
||||
c = pn[0];
|
||||
pn[0] = '\0';
|
||||
while (*tail != '\0' && *tail != '/')
|
||||
++tail;
|
||||
/* is this the last path component? */
|
||||
last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0');
|
||||
/* temporarily truncate the string here */
|
||||
c = tail[0];
|
||||
tail[0] = '\0';
|
||||
/* Check that we haven't hit a symlink. */
|
||||
r = lstat(a->name, &st);
|
||||
r = lstat(head, &st);
|
||||
if (r != 0) {
|
||||
tail[0] = c;
|
||||
/* We've hit a dir that doesn't exist; stop now. */
|
||||
if (errno == ENOENT)
|
||||
if (errno == ENOENT) {
|
||||
break;
|
||||
} else {
|
||||
/*
|
||||
* Treat any other error as fatal - best to be
|
||||
* paranoid here.
|
||||
* Note: This effectively disables deep
|
||||
* directory support when security checks are
|
||||
* enabled. Otherwise, very long pathnames that
|
||||
* trigger an error here could evade the
|
||||
* sandbox.
|
||||
* TODO: We could do better, but it would
|
||||
* probably require merging the symlink checks
|
||||
* with the deep-directory editing.
|
||||
*/
|
||||
fsobj_error(a_eno, a_estr, errno,
|
||||
"Could not stat %s", path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
} else if (S_ISDIR(st.st_mode)) {
|
||||
if (!last) {
|
||||
if (chdir(head) != 0) {
|
||||
tail[0] = c;
|
||||
fsobj_error(a_eno, a_estr, errno,
|
||||
"Could not chdir %s", path);
|
||||
res = (ARCHIVE_FATAL);
|
||||
break;
|
||||
}
|
||||
/* Our view is now from inside this dir: */
|
||||
head = tail + 1;
|
||||
}
|
||||
} else if (S_ISLNK(st.st_mode)) {
|
||||
if (c == '\0') {
|
||||
if (last) {
|
||||
/*
|
||||
* Last element is symlink; remove it
|
||||
* so we can overwrite it with the
|
||||
* item being extracted.
|
||||
*/
|
||||
if (unlink(a->name)) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
if (unlink(head)) {
|
||||
tail[0] = c;
|
||||
fsobj_error(a_eno, a_estr, errno,
|
||||
"Could not remove symlink %s",
|
||||
a->name);
|
||||
pn[0] = c;
|
||||
return (ARCHIVE_FAILED);
|
||||
path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
a->pst = NULL;
|
||||
/*
|
||||
* Even if we did remove it, a warning
|
||||
* is in order. The warning is silly,
|
||||
* though, if we're just replacing one
|
||||
* symlink with another symlink.
|
||||
*/
|
||||
if (!S_ISLNK(a->mode)) {
|
||||
archive_set_error(&a->archive, 0,
|
||||
"Removing symlink %s",
|
||||
a->name);
|
||||
tail[0] = c;
|
||||
/*
|
||||
* FIXME: not sure how important this is to
|
||||
* restore
|
||||
*/
|
||||
/*
|
||||
if (!S_ISLNK(path)) {
|
||||
fsobj_error(a_eno, a_estr, 0,
|
||||
"Removing symlink %s", path);
|
||||
}
|
||||
*/
|
||||
/* Symlink gone. No more problem! */
|
||||
pn[0] = c;
|
||||
return (0);
|
||||
} else if (a->flags & ARCHIVE_EXTRACT_UNLINK) {
|
||||
res = ARCHIVE_OK;
|
||||
break;
|
||||
} else if (flags & ARCHIVE_EXTRACT_UNLINK) {
|
||||
/* User asked us to remove problems. */
|
||||
if (unlink(a->name) != 0) {
|
||||
archive_set_error(&a->archive, 0,
|
||||
"Cannot remove intervening symlink %s",
|
||||
a->name);
|
||||
pn[0] = c;
|
||||
return (ARCHIVE_FAILED);
|
||||
if (unlink(head) != 0) {
|
||||
tail[0] = c;
|
||||
fsobj_error(a_eno, a_estr, 0,
|
||||
"Cannot remove intervening "
|
||||
"symlink %s", path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
tail[0] = c;
|
||||
} else if ((flags &
|
||||
ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) {
|
||||
/*
|
||||
* We are not the last element and we want to
|
||||
* follow symlinks if they are a directory.
|
||||
*
|
||||
* This is needed to extract hardlinks over
|
||||
* symlinks.
|
||||
*/
|
||||
r = stat(head, &st);
|
||||
if (r != 0) {
|
||||
tail[0] = c;
|
||||
if (errno == ENOENT) {
|
||||
break;
|
||||
} else {
|
||||
fsobj_error(a_eno, a_estr,
|
||||
errno,
|
||||
"Could not stat %s", path);
|
||||
res = (ARCHIVE_FAILED);
|
||||
break;
|
||||
}
|
||||
} else if (S_ISDIR(st.st_mode)) {
|
||||
if (chdir(head) != 0) {
|
||||
tail[0] = c;
|
||||
fsobj_error(a_eno, a_estr,
|
||||
errno,
|
||||
"Could not chdir %s", path);
|
||||
res = (ARCHIVE_FATAL);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Our view is now from inside
|
||||
* this dir:
|
||||
*/
|
||||
head = tail + 1;
|
||||
} else {
|
||||
tail[0] = c;
|
||||
fsobj_error(a_eno, a_estr, 0,
|
||||
"Cannot extract through "
|
||||
"symlink %s", path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
a->pst = NULL;
|
||||
} else {
|
||||
archive_set_error(&a->archive, 0,
|
||||
"Cannot extract through symlink %s",
|
||||
a->name);
|
||||
pn[0] = c;
|
||||
return (ARCHIVE_FAILED);
|
||||
tail[0] = c;
|
||||
fsobj_error(a_eno, a_estr, 0,
|
||||
"Cannot extract through symlink %s", path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pn[0] = c;
|
||||
if (pn[0] != '\0')
|
||||
pn++; /* Advance to the next segment. */
|
||||
/* be sure to always maintain this */
|
||||
tail[0] = c;
|
||||
if (tail[0] != '\0')
|
||||
tail++; /* Advance to the next segment. */
|
||||
}
|
||||
pn[0] = c;
|
||||
/* We've checked and/or cleaned the whole path, so remember it. */
|
||||
archive_strcpy(&a->path_safe, a->name);
|
||||
return (ARCHIVE_OK);
|
||||
/* Catches loop exits via break */
|
||||
tail[0] = c;
|
||||
#ifdef HAVE_FCHDIR
|
||||
/* If we changed directory above, restore it here. */
|
||||
if (restore_pwd >= 0) {
|
||||
r = fchdir(restore_pwd);
|
||||
if (r != 0) {
|
||||
fsobj_error(a_eno, a_estr, errno,
|
||||
"chdir() failure", "");
|
||||
}
|
||||
close(restore_pwd);
|
||||
restore_pwd = -1;
|
||||
if (r != 0) {
|
||||
res = (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* TODO: reintroduce a safe cache here? */
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise
|
||||
* calls archive_set_error and returns ARCHIVE_{FATAL,FAILED}
|
||||
*/
|
||||
static int
|
||||
check_symlinks(struct archive_write_disk *a)
|
||||
{
|
||||
struct archive_string error_string;
|
||||
int error_number;
|
||||
int rc;
|
||||
archive_string_init(&error_string);
|
||||
rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
|
||||
a->flags);
|
||||
if (rc != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s",
|
||||
error_string.s);
|
||||
}
|
||||
archive_string_free(&error_string);
|
||||
a->pst = NULL; /* to be safe */
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
/*
|
||||
* 1. Convert a path separator from '\' to '/' .
|
||||
@ -2471,7 +2744,7 @@ check_symlinks(struct archive_write_disk *a)
|
||||
* See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx
|
||||
*/
|
||||
static void
|
||||
cleanup_pathname_win(struct archive_write_disk *a)
|
||||
cleanup_pathname_win(char *path)
|
||||
{
|
||||
wchar_t wc;
|
||||
char *p;
|
||||
@ -2482,7 +2755,7 @@ cleanup_pathname_win(struct archive_write_disk *a)
|
||||
mb = 0;
|
||||
complete = 1;
|
||||
utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0;
|
||||
for (p = a->name; *p != '\0'; p++) {
|
||||
for (p = path; *p != '\0'; p++) {
|
||||
++alen;
|
||||
if (*p == '\\') {
|
||||
/* If previous byte is smaller than 128,
|
||||
@ -2507,7 +2780,7 @@ cleanup_pathname_win(struct archive_write_disk *a)
|
||||
/*
|
||||
* Convert path separator in wide-character.
|
||||
*/
|
||||
p = a->name;
|
||||
p = path;
|
||||
while (*p != '\0' && alen) {
|
||||
l = mbtowc(&wc, p, alen);
|
||||
if (l == (size_t)-1) {
|
||||
@ -2534,26 +2807,27 @@ cleanup_pathname_win(struct archive_write_disk *a)
|
||||
* is set) if the path is absolute.
|
||||
*/
|
||||
static int
|
||||
cleanup_pathname(struct archive_write_disk *a)
|
||||
cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
||||
int flags)
|
||||
{
|
||||
char *dest, *src;
|
||||
char separator = '\0';
|
||||
|
||||
dest = src = a->name;
|
||||
dest = src = path;
|
||||
if (*src == '\0') {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid empty pathname");
|
||||
fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid empty ", "pathname");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
cleanup_pathname_win(a);
|
||||
cleanup_pathname_win(path);
|
||||
#endif
|
||||
/* Skip leading '/'. */
|
||||
if (*src == '/') {
|
||||
if (a->flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Path is absolute");
|
||||
if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
|
||||
fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC,
|
||||
"Path is ", "absolute");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
@ -2580,10 +2854,11 @@ cleanup_pathname(struct archive_write_disk *a)
|
||||
} else if (src[1] == '.') {
|
||||
if (src[2] == '/' || src[2] == '\0') {
|
||||
/* Conditionally warn about '..' */
|
||||
if (a->flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
|
||||
archive_set_error(&a->archive,
|
||||
if (flags
|
||||
& ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
|
||||
fsobj_error(a_eno, a_estr,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Path contains '..'");
|
||||
"Path contains ", "'..'");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
}
|
||||
@ -2614,7 +2889,7 @@ cleanup_pathname(struct archive_write_disk *a)
|
||||
* We've just copied zero or more path elements, not including the
|
||||
* final '/'.
|
||||
*/
|
||||
if (dest == a->name) {
|
||||
if (dest == path) {
|
||||
/*
|
||||
* Nothing got copied. The path must have been something
|
||||
* like '.' or '/' or './' or '/././././/./'.
|
||||
@ -2629,6 +2904,23 @@ cleanup_pathname(struct archive_write_disk *a)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
cleanup_pathname(struct archive_write_disk *a)
|
||||
{
|
||||
struct archive_string error_string;
|
||||
int error_number;
|
||||
int rc;
|
||||
archive_string_init(&error_string);
|
||||
rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string,
|
||||
a->flags);
|
||||
if (rc != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s",
|
||||
error_string.s);
|
||||
}
|
||||
archive_string_free(&error_string);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the parent directory of the specified path, assuming path
|
||||
* is already in mutable storage.
|
||||
@ -2707,7 +2999,8 @@ create_dir(struct archive_write_disk *a, char *path)
|
||||
}
|
||||
} else if (errno != ENOENT && errno != ENOTDIR) {
|
||||
/* Stat failed? */
|
||||
archive_set_error(&a->archive, errno, "Can't test directory '%s'", path);
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Can't test directory '%s'", path);
|
||||
return (ARCHIVE_FAILED);
|
||||
} else if (slash != NULL) {
|
||||
*slash = '\0';
|
||||
@ -3232,7 +3525,8 @@ clear_nochange_fflags(struct archive_write_disk *a)
|
||||
nochange_flags |= EXT2_IMMUTABLE_FL;
|
||||
#endif
|
||||
|
||||
return (set_fflags_platform(a, a->fd, a->name, mode, 0, nochange_flags));
|
||||
return (set_fflags_platform(a, a->fd, a->name, mode, 0,
|
||||
nochange_flags));
|
||||
}
|
||||
|
||||
|
||||
@ -3487,6 +3781,9 @@ exit_xattr:
|
||||
static int
|
||||
copy_acls(struct archive_write_disk *a, int tmpfd, int dffd)
|
||||
{
|
||||
#ifndef HAVE_SYS_ACL_H
|
||||
return 0;
|
||||
#else
|
||||
acl_t acl, dfacl = NULL;
|
||||
int acl_r, ret = ARCHIVE_OK;
|
||||
|
||||
@ -3514,6 +3811,7 @@ exit_acl:
|
||||
if (dfacl)
|
||||
acl_free(dfacl);
|
||||
return (ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
@ -3753,7 +4051,8 @@ set_xattrs(struct archive_write_disk *a)
|
||||
if (errno == ENOTSUP || errno == ENOSYS) {
|
||||
if (!warning_done) {
|
||||
warning_done = 1;
|
||||
archive_set_error(&a->archive, errno,
|
||||
archive_set_error(&a->archive,
|
||||
errno,
|
||||
"Cannot restore extended "
|
||||
"attributes on this file "
|
||||
"system");
|
||||
@ -3764,7 +4063,8 @@ set_xattrs(struct archive_write_disk *a)
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
} else {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid extended attribute encountered");
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
@ -3808,19 +4108,22 @@ set_xattrs(struct archive_write_disk *a)
|
||||
errno = 0;
|
||||
#if HAVE_EXTATTR_SET_FD
|
||||
if (a->fd >= 0)
|
||||
e = extattr_set_fd(a->fd, namespace, name, value, size);
|
||||
e = extattr_set_fd(a->fd, namespace, name,
|
||||
value, size);
|
||||
else
|
||||
#endif
|
||||
/* TODO: should we use extattr_set_link() instead? */
|
||||
{
|
||||
e = extattr_set_file(archive_entry_pathname(entry),
|
||||
namespace, name, value, size);
|
||||
e = extattr_set_file(
|
||||
archive_entry_pathname(entry), namespace,
|
||||
name, value, size);
|
||||
}
|
||||
if (e != (int)size) {
|
||||
if (errno == ENOTSUP || errno == ENOSYS) {
|
||||
if (!warning_done) {
|
||||
warning_done = 1;
|
||||
archive_set_error(&a->archive, errno,
|
||||
archive_set_error(&a->archive,
|
||||
errno,
|
||||
"Cannot restore extended "
|
||||
"attributes on this file "
|
||||
"system");
|
||||
@ -3866,10 +4169,10 @@ older(struct stat *st, struct archive_entry *entry)
|
||||
{
|
||||
/* First, test the seconds and return if we have a definite answer. */
|
||||
/* Definitely older. */
|
||||
if (st->st_mtime < archive_entry_mtime(entry))
|
||||
if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry)))
|
||||
return (1);
|
||||
/* Definitely younger. */
|
||||
if (st->st_mtime > archive_entry_mtime(entry))
|
||||
if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry)))
|
||||
return (0);
|
||||
/* If this platform supports fractional seconds, try those. */
|
||||
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
|
||||
|
@ -84,15 +84,13 @@ static void cleanup(void *);
|
||||
int
|
||||
archive_write_disk_set_standard_lookup(struct archive *a)
|
||||
{
|
||||
struct bucket *ucache = malloc(cache_size * sizeof(struct bucket));
|
||||
struct bucket *gcache = malloc(cache_size * sizeof(struct bucket));
|
||||
struct bucket *ucache = calloc(cache_size, sizeof(struct bucket));
|
||||
struct bucket *gcache = calloc(cache_size, sizeof(struct bucket));
|
||||
if (ucache == NULL || gcache == NULL) {
|
||||
free(ucache);
|
||||
free(gcache);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(ucache, 0, cache_size * sizeof(struct bucket));
|
||||
memset(gcache, 0, cache_size * sizeof(struct bucket));
|
||||
archive_write_disk_set_group_lookup(a, gcache, lookup_gid, cleanup);
|
||||
archive_write_disk_set_user_lookup(a, ucache, lookup_uid, cleanup);
|
||||
return (ARCHIVE_OK);
|
||||
|
@ -192,7 +192,7 @@ struct archive_write_disk {
|
||||
|
||||
/*
|
||||
* Default mode for dirs created automatically (will be modified by umask).
|
||||
* Note that POSIX specifies 0777 for implicity-created dirs, "modified
|
||||
* Note that POSIX specifies 0777 for implicitly-created dirs, "modified
|
||||
* by the process' file creation mask."
|
||||
*/
|
||||
#define DEFAULT_DIR_MODE 0777
|
||||
@ -396,7 +396,7 @@ permissive_name_w(struct archive_write_disk *a)
|
||||
}
|
||||
|
||||
/*
|
||||
* A full-pathname pointig a network drive
|
||||
* A full-pathname pointing to a network drive
|
||||
* like "\\<server-name>\<share-name>\file".
|
||||
*/
|
||||
if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') {
|
||||
@ -1221,10 +1221,9 @@ archive_write_disk_new(void)
|
||||
{
|
||||
struct archive_write_disk *a;
|
||||
|
||||
a = (struct archive_write_disk *)malloc(sizeof(*a));
|
||||
a = (struct archive_write_disk *)calloc(1, sizeof(*a));
|
||||
if (a == NULL)
|
||||
return (NULL);
|
||||
memset(a, 0, sizeof(*a));
|
||||
a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
|
||||
/* We're ready to write a header immediately. */
|
||||
a->archive.state = ARCHIVE_STATE_HEADER;
|
||||
|
@ -66,6 +66,7 @@ Freeze the settings, open the archive, and prepare for writing entries.
|
||||
This is the most generic form of this function, which accepts
|
||||
pointers to three callback functions which will be invoked by
|
||||
the compression layer to write the constructed archive.
|
||||
This does not alter the default archive padding.
|
||||
.It Fn archive_write_open_fd
|
||||
A convenience form of
|
||||
.Fn archive_write_open
|
||||
@ -123,12 +124,21 @@ is currently in use.
|
||||
You should be careful to ensure that this variable
|
||||
remains allocated until after the archive is
|
||||
closed.
|
||||
This function will disable padding unless you
|
||||
have specifically set the block size.
|
||||
.El
|
||||
More information about the
|
||||
.Va struct archive
|
||||
object and the overall design of the library can be found in the
|
||||
.Xr libarchive 3
|
||||
overview.
|
||||
.Pp
|
||||
Note that the convenience forms above vary in how
|
||||
they block the output.
|
||||
See
|
||||
.Xr archive_write_blocksize 3
|
||||
if you need to control the block size used for writes
|
||||
or the end-of-file padding behavior.
|
||||
.\"
|
||||
.Sh CLIENT CALLBACKS
|
||||
To use this library, you will need to define and register
|
||||
@ -226,6 +236,7 @@ functions.
|
||||
.Xr tar 1 ,
|
||||
.Xr libarchive 3 ,
|
||||
.Xr archive_write 3 ,
|
||||
.Xr archive_write_blocksize 3 ,
|
||||
.Xr archive_write_filter 3 ,
|
||||
.Xr archive_write_format 3 ,
|
||||
.Xr archive_write_new 3 ,
|
||||
|
@ -53,12 +53,11 @@ archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t
|
||||
{
|
||||
struct write_memory_data *mine;
|
||||
|
||||
mine = (struct write_memory_data *)malloc(sizeof(*mine));
|
||||
mine = (struct write_memory_data *)calloc(1, sizeof(*mine));
|
||||
if (mine == NULL) {
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(mine, 0, sizeof(*mine));
|
||||
mine->buff = buff;
|
||||
mine->size = buffSize;
|
||||
mine->client_size = used;
|
||||
|
@ -205,7 +205,7 @@ struct _7zip {
|
||||
/*
|
||||
* The list of the file entries which has its contents is used to
|
||||
* manage struct file objects.
|
||||
* We use 'next' a menber of struct file to chain.
|
||||
* We use 'next' (a member of struct file) to chain.
|
||||
*/
|
||||
struct {
|
||||
struct file *first;
|
||||
@ -1358,7 +1358,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
|
||||
if (r < 0)
|
||||
return (r);
|
||||
|
||||
/* Write Nume size. */
|
||||
/* Write Name size. */
|
||||
r = enc_uint64(a, zip->total_bytes_entry_name+1);
|
||||
if (r < 0)
|
||||
return (r);
|
||||
|
@ -126,12 +126,11 @@ archive_write_set_format_ar(struct archive_write *a)
|
||||
if (a->format_free != NULL)
|
||||
(a->format_free)(a);
|
||||
|
||||
ar = (struct ar_w *)malloc(sizeof(*ar));
|
||||
ar = (struct ar_w *)calloc(1, sizeof(*ar));
|
||||
if (ar == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate ar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(ar, 0, sizeof(*ar));
|
||||
a->format_data = ar;
|
||||
|
||||
a->format_name = "ar";
|
||||
|
@ -289,7 +289,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
|
||||
sconv = get_sconv(a);
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Make sure the path separators in pahtname, hardlink and symlink
|
||||
/* Make sure the path separators in pathname, hardlink and symlink
|
||||
* are all slash '/', not the Windows path separator '\'. */
|
||||
entry_main = __la_win_entry_in_posix_pathseparator(entry);
|
||||
if (entry_main == NULL) {
|
||||
|
@ -116,12 +116,11 @@ archive_write_set_format_cpio_newc(struct archive *_a)
|
||||
if (a->format_free != NULL)
|
||||
(a->format_free)(a);
|
||||
|
||||
cpio = (struct cpio *)malloc(sizeof(*cpio));
|
||||
cpio = (struct cpio *)calloc(1, sizeof(*cpio));
|
||||
if (cpio == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(cpio, 0, sizeof(*cpio));
|
||||
a->format_data = cpio;
|
||||
a->format_name = "cpio";
|
||||
a->format_options = archive_write_newc_options;
|
||||
@ -232,7 +231,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
|
||||
sconv = get_sconv(a);
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Make sure the path separators in pahtname, hardlink and symlink
|
||||
/* Make sure the path separators in pathname, hardlink and symlink
|
||||
* are all slash '/', not the Windows path separator '\'. */
|
||||
entry_main = __la_win_entry_in_posix_pathseparator(entry);
|
||||
if (entry_main == NULL) {
|
||||
|
@ -119,9 +119,9 @@ static const char template_header[] = {
|
||||
'0','0','0','0','0','0', '0','\0',
|
||||
/* gid, null termination: 8 bytes */
|
||||
'0','0','0','0','0','0', '0','\0',
|
||||
/* size, space termation: 12 bytes */
|
||||
/* size, space termination: 12 bytes */
|
||||
'0','0','0','0','0','0','0','0','0','0','0', '\0',
|
||||
/* mtime, space termation: 12 bytes */
|
||||
/* mtime, space termination: 12 bytes */
|
||||
'0','0','0','0','0','0','0','0','0','0','0', '\0',
|
||||
/* Initial checksum value: 8 spaces */
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',
|
||||
@ -368,7 +368,7 @@ archive_write_gnutar_header(struct archive_write *a,
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Make sure the path separators in pahtname, hardlink and symlink
|
||||
/* Make sure the path separators in pathname, hardlink and symlink
|
||||
* are all slash '/', not the Windows path separator '\'. */
|
||||
entry_main = __la_win_entry_in_posix_pathseparator(entry);
|
||||
if (entry_main == NULL) {
|
||||
@ -478,15 +478,15 @@ archive_write_gnutar_header(struct archive_write *a,
|
||||
archive_entry_set_pathname(temp, "././@LongLink");
|
||||
archive_entry_set_size(temp, length);
|
||||
ret = archive_format_gnutar_header(a, buff, temp, 'K');
|
||||
archive_entry_free(temp);
|
||||
if (ret < ARCHIVE_WARN)
|
||||
goto exit_write_header;
|
||||
ret = __archive_write_output(a, buff, 512);
|
||||
if(ret < ARCHIVE_WARN)
|
||||
if (ret < ARCHIVE_WARN)
|
||||
goto exit_write_header;
|
||||
archive_entry_free(temp);
|
||||
/* Write name and trailing null byte. */
|
||||
ret = __archive_write_output(a, gnutar->linkname, length);
|
||||
if(ret < ARCHIVE_WARN)
|
||||
if (ret < ARCHIVE_WARN)
|
||||
goto exit_write_header;
|
||||
/* Pad to 512 bytes */
|
||||
ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)length));
|
||||
@ -508,12 +508,12 @@ archive_write_gnutar_header(struct archive_write *a,
|
||||
archive_entry_set_pathname(temp, "././@LongLink");
|
||||
archive_entry_set_size(temp, length);
|
||||
ret = archive_format_gnutar_header(a, buff, temp, 'L');
|
||||
archive_entry_free(temp);
|
||||
if (ret < ARCHIVE_WARN)
|
||||
goto exit_write_header;
|
||||
ret = __archive_write_output(a, buff, 512);
|
||||
if(ret < ARCHIVE_WARN)
|
||||
goto exit_write_header;
|
||||
archive_entry_free(temp);
|
||||
/* Write pathname + trailing null byte. */
|
||||
ret = __archive_write_output(a, pathname, length);
|
||||
if(ret < ARCHIVE_WARN)
|
||||
|
@ -161,7 +161,7 @@ struct isofile {
|
||||
/* Used for managing struct isofile list. */
|
||||
struct isofile *allnext;
|
||||
struct isofile *datanext;
|
||||
/* Used for managing a hardlined struct isofile list. */
|
||||
/* Used for managing a hardlinked struct isofile list. */
|
||||
struct isofile *hlnext;
|
||||
struct isofile *hardlink_target;
|
||||
|
||||
@ -436,7 +436,7 @@ struct iso_option {
|
||||
* Type : string
|
||||
* Default: Auto detect
|
||||
* : We check a size of boot image;
|
||||
* : If ths size is just 1.22M/1.44M/2.88M,
|
||||
* : If the size is just 1.22M/1.44M/2.88M,
|
||||
* : we assume boot_type is 'fd';
|
||||
* : otherwise boot_type is 'no-emulation'.
|
||||
* COMPAT :
|
||||
@ -528,7 +528,7 @@ struct iso_option {
|
||||
* - allow more then 8 depths of directory trees;
|
||||
* - disable a version number to a File Name;
|
||||
* - disable a forced period to the tail of a File Name;
|
||||
* - the maxinum length of files and directories is raised to 193.
|
||||
* - the maximum length of files and directories is raised to 193.
|
||||
* if rockridge option is disabled, raised to 207.
|
||||
*/
|
||||
unsigned int iso_level:3;
|
||||
@ -626,7 +626,7 @@ struct iso_option {
|
||||
* : NOTE Our rockridge=useful option does not set a zero
|
||||
* : to uid and gid, you should use application
|
||||
* : option such as --gid,--gname,--uid and --uname
|
||||
* : badtar options instead.
|
||||
* : bsdtar options instead.
|
||||
* Type : boolean/string
|
||||
* Default: Enabled as rockridge=useful
|
||||
* COMPAT : mkisofs -r / -R
|
||||
@ -660,7 +660,7 @@ struct iso_option {
|
||||
* : for making zisofs.
|
||||
* : When the file size is less than one Logical Block
|
||||
* : size, that file will not zisofs'ed since it does
|
||||
* : reduece an ISO-image size.
|
||||
* : reduce an ISO-image size.
|
||||
* :
|
||||
* : When you specify option 'boot=<boot-image>', that
|
||||
* : 'boot-image' file won't be converted to zisofs file.
|
||||
@ -680,7 +680,7 @@ struct iso9660 {
|
||||
/* The creation time of ISO image. */
|
||||
time_t birth_time;
|
||||
/* A file stream of a temporary file, which file contents
|
||||
* save to until ISO iamge can be created. */
|
||||
* save to until ISO image can be created. */
|
||||
int temp_fd;
|
||||
|
||||
struct isofile *cur_file;
|
||||
@ -703,7 +703,7 @@ struct iso9660 {
|
||||
} all_file_list;
|
||||
|
||||
/* A list of struct isofile entries which have its
|
||||
* contents and are not a directory, a hardlined file
|
||||
* contents and are not a directory, a hardlinked file
|
||||
* and a symlink file. */
|
||||
struct {
|
||||
struct isofile *first;
|
||||
@ -1907,9 +1907,9 @@ iso9660_close(struct archive_write *a)
|
||||
iso9660->primary.rootent);
|
||||
if (ret < 0)
|
||||
return (ret);
|
||||
/* Make sure we have UTF-16BE convertors.
|
||||
* if there is no file entry, convertors are still
|
||||
* uninitilized. */
|
||||
/* Make sure we have UTF-16BE converters.
|
||||
* if there is no file entry, converters are still
|
||||
* uninitialized. */
|
||||
if (iso9660->sconv_to_utf16be == NULL) {
|
||||
iso9660->sconv_to_utf16be =
|
||||
archive_string_conversion_to_charset(
|
||||
@ -1995,7 +1995,7 @@ iso9660_close(struct archive_write *a)
|
||||
* Write an ISO 9660 image.
|
||||
*/
|
||||
|
||||
/* Switc to start using wbuff as file buffer. */
|
||||
/* Switch to start using wbuff as file buffer. */
|
||||
iso9660->wbuff_remaining = wb_buffmax();
|
||||
iso9660->wbuff_type = WB_TO_STREAM;
|
||||
iso9660->wbuff_offset = 0;
|
||||
@ -2524,7 +2524,8 @@ get_tmfromtime(struct tm *tm, time_t *t)
|
||||
tzset();
|
||||
localtime_r(t, tm);
|
||||
#elif HAVE__LOCALTIME64_S
|
||||
_localtime64_s(tm, t);
|
||||
__time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits
|
||||
_localtime64_s(tm, &tmp_t);
|
||||
#else
|
||||
memcpy(tm, localtime(t), sizeof(*tm));
|
||||
#endif
|
||||
@ -2553,7 +2554,7 @@ set_date_time(unsigned char *p, time_t t)
|
||||
static void
|
||||
set_date_time_null(unsigned char *p)
|
||||
{
|
||||
memset(p, '0', 16);
|
||||
memset(p, (int)'0', 16);
|
||||
p[16] = 0;
|
||||
}
|
||||
|
||||
@ -2959,7 +2960,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
|
||||
gid = archive_entry_gid(file->entry);
|
||||
if (iso9660->opt.rr == OPT_RR_USEFUL) {
|
||||
/*
|
||||
* This action is simular mkisofs -r option
|
||||
* This action is similar to mkisofs -r option
|
||||
* but our rockridge=useful option does not
|
||||
* set a zero to uid and gid.
|
||||
*/
|
||||
@ -3024,8 +3025,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
|
||||
* +----+----+----+----+----+
|
||||
* 10 11 12 13 14 15
|
||||
*
|
||||
* - cflg : flag of componet
|
||||
* - clen : length of componet
|
||||
* - cflg : flag of component
|
||||
* - clen : length of component
|
||||
*/
|
||||
const char *sl;
|
||||
char sl_last;
|
||||
@ -3108,7 +3109,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len,
|
||||
/*
|
||||
* flg len
|
||||
* +----+----+
|
||||
* | 02 | 00 | CURREENT component.
|
||||
* | 02 | 00 | CURRENT component.
|
||||
* +----+----+ (".")
|
||||
*/
|
||||
if (nc != NULL) {
|
||||
@ -3947,7 +3948,7 @@ write_VD(struct archive_write *a, struct vdd *vdd)
|
||||
"Abstract File", 0, D_CHAR);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
/* Bibliongraphic File Identifier */
|
||||
/* Bibliographic File Identifier */
|
||||
r = set_file_identifier(bp, 777, 813, vdc, a, vdd,
|
||||
&(iso9660->bibliographic_file_identifier),
|
||||
"Bibliongraphic File", 0, D_CHAR);
|
||||
@ -4073,7 +4074,10 @@ write_information_block(struct archive_write *a)
|
||||
memset(info.s, 0, info_size);
|
||||
opt = 0;
|
||||
#if defined(HAVE__CTIME64_S)
|
||||
_ctime64_s(buf, sizeof(buf), &(iso9660->birth_time));
|
||||
{
|
||||
__time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits
|
||||
_ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp));
|
||||
}
|
||||
#elif defined(HAVE_CTIME_R)
|
||||
ctime_r(&(iso9660->birth_time), buf);
|
||||
#else
|
||||
@ -4558,7 +4562,7 @@ write_file_descriptors(struct archive_write *a)
|
||||
file->cur_content = &(file->content);
|
||||
do {
|
||||
blocks += file->cur_content->blocks;
|
||||
/* Next fragument */
|
||||
/* Next fragment */
|
||||
file->cur_content = file->cur_content->next;
|
||||
} while (file->cur_content != NULL);
|
||||
}
|
||||
@ -4748,7 +4752,7 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file)
|
||||
}
|
||||
|
||||
/*
|
||||
* Converte a filename to UTF-16BE.
|
||||
* Convert a filename to UTF-16BE.
|
||||
*/
|
||||
if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len,
|
||||
iso9660->sconv_to_utf16be)) {
|
||||
@ -5512,7 +5516,7 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location)
|
||||
file->cur_content->location = location;
|
||||
location += file->cur_content->blocks;
|
||||
total_block += file->cur_content->blocks;
|
||||
/* Next fragument */
|
||||
/* Next fragment */
|
||||
file->cur_content = file->cur_content->next;
|
||||
} while (file->cur_content != NULL);
|
||||
}
|
||||
@ -6135,7 +6139,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
|
||||
off = ffmax - extlen;
|
||||
if (off == 0) {
|
||||
/* A dot('.') character
|
||||
* does't place to the first
|
||||
* doesn't place to the first
|
||||
* byte of identifier. */
|
||||
off ++;
|
||||
extlen --;
|
||||
@ -6164,7 +6168,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent,
|
||||
np->id_len = l = ext_off + np->ext_len;
|
||||
|
||||
/* Make an offset of the number which is used to be set
|
||||
* hexadecimal number to avoid duplicate identififier. */
|
||||
* hexadecimal number to avoid duplicate identifier. */
|
||||
if (iso9660->opt.iso_level == 1) {
|
||||
if (ext_off >= 5)
|
||||
noff = 5;
|
||||
@ -6742,7 +6746,7 @@ isoent_rr_move(struct archive_write *a)
|
||||
int r;
|
||||
|
||||
pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]);
|
||||
/* Theare aren't level 8 directories reaching a deepr level. */
|
||||
/* There aren't level 8 directories reaching a deeper level. */
|
||||
if (pt->cnt == 0)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
@ -6813,7 +6817,7 @@ _compare_path_table(const void *v1, const void *v2)
|
||||
if (cmp != 0)
|
||||
return (cmp);
|
||||
|
||||
/* Compare indetifier */
|
||||
/* Compare identifier */
|
||||
s1 = p1->identifier;
|
||||
s2 = p2->identifier;
|
||||
l = p1->ext_off;
|
||||
@ -6855,7 +6859,7 @@ _compare_path_table_joliet(const void *v1, const void *v2)
|
||||
if (cmp != 0)
|
||||
return (cmp);
|
||||
|
||||
/* Compare indetifier */
|
||||
/* Compare identifier */
|
||||
s1 = (const unsigned char *)p1->identifier;
|
||||
s2 = (const unsigned char *)p2->identifier;
|
||||
l = p1->ext_off;
|
||||
@ -7149,7 +7153,7 @@ isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent)
|
||||
|
||||
iso9660->el_torito.catalog = isoent;
|
||||
/*
|
||||
* Get a boot medai type.
|
||||
* Get a boot media type.
|
||||
*/
|
||||
switch (iso9660->opt.boot_type) {
|
||||
default:
|
||||
|
@ -1840,9 +1840,9 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
|
||||
len = strlen(p);
|
||||
|
||||
/*
|
||||
* Add "./" prefiex.
|
||||
* Add "./" prefix.
|
||||
* NOTE: If the pathname does not have a path separator, we have
|
||||
* to add "./" to the head of the pathename because mtree reader
|
||||
* to add "./" to the head of the pathname because mtree reader
|
||||
* will suppose that it is v1(a.k.a classic) mtree format and
|
||||
* change the directory unexpectedly and so it will make a wrong
|
||||
* path.
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
|
||||
* Copyright (c) 2016 Martin Matuska
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -61,15 +62,24 @@ struct pax {
|
||||
struct sparse_block *sparse_tail;
|
||||
struct archive_string_conv *sconv_utf8;
|
||||
int opt_binary;
|
||||
|
||||
unsigned flags;
|
||||
#define WRITE_SCHILY_XATTR (1 << 0)
|
||||
#define WRITE_LIBARCHIVE_XATTR (1 << 1)
|
||||
};
|
||||
|
||||
static void add_pax_attr(struct archive_string *, const char *key,
|
||||
const char *value);
|
||||
static void add_pax_attr_binary(struct archive_string *,
|
||||
const char *key,
|
||||
const char *value, size_t value_len);
|
||||
static void add_pax_attr_int(struct archive_string *,
|
||||
const char *key, int64_t value);
|
||||
static void add_pax_attr_time(struct archive_string *,
|
||||
const char *key, int64_t sec,
|
||||
unsigned long nanos);
|
||||
static int add_pax_acl(struct archive_write *,
|
||||
struct archive_entry *, struct pax *, int);
|
||||
static ssize_t archive_write_pax_data(struct archive_write *,
|
||||
const void *, size_t);
|
||||
static int archive_write_pax_close(struct archive_write *);
|
||||
@ -127,13 +137,14 @@ archive_write_set_format_pax(struct archive *_a)
|
||||
if (a->format_free != NULL)
|
||||
(a->format_free)(a);
|
||||
|
||||
pax = (struct pax *)malloc(sizeof(*pax));
|
||||
pax = (struct pax *)calloc(1, sizeof(*pax));
|
||||
if (pax == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate pax data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(pax, 0, sizeof(*pax));
|
||||
pax->flags = WRITE_LIBARCHIVE_XATTR | WRITE_SCHILY_XATTR;
|
||||
|
||||
a->format_data = pax;
|
||||
a->format_name = "pax";
|
||||
a->format_options = archive_write_pax_options;
|
||||
@ -272,6 +283,17 @@ add_pax_attr_int(struct archive_string *as, const char *key, int64_t value)
|
||||
*/
|
||||
static void
|
||||
add_pax_attr(struct archive_string *as, const char *key, const char *value)
|
||||
{
|
||||
add_pax_attr_binary(as, key, value, strlen(value));
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a key/value attribute to the pax header. This function handles
|
||||
* binary values.
|
||||
*/
|
||||
static void
|
||||
add_pax_attr_binary(struct archive_string *as, const char *key,
|
||||
const char *value, size_t value_len)
|
||||
{
|
||||
int digits, i, len, next_ten;
|
||||
char tmp[1 + 3 * sizeof(int)]; /* < 3 base-10 digits per byte */
|
||||
@ -280,7 +302,7 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value)
|
||||
* PAX attributes have the following layout:
|
||||
* <len> <space> <key> <=> <value> <nl>
|
||||
*/
|
||||
len = 1 + (int)strlen(key) + 1 + (int)strlen(value) + 1;
|
||||
len = 1 + (int)strlen(key) + 1 + (int)value_len + 1;
|
||||
|
||||
/*
|
||||
* The <len> field includes the length of the <len> field, so
|
||||
@ -311,21 +333,47 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value)
|
||||
archive_strappend_char(as, ' ');
|
||||
archive_strcat(as, key);
|
||||
archive_strappend_char(as, '=');
|
||||
archive_strcat(as, value);
|
||||
archive_array_append(as, value, value_len);
|
||||
archive_strappend_char(as, '\n');
|
||||
}
|
||||
|
||||
static void
|
||||
archive_write_pax_header_xattr(struct pax *pax, const char *encoded_name,
|
||||
const void *value, size_t value_len)
|
||||
{
|
||||
struct archive_string s;
|
||||
char *encoded_value;
|
||||
|
||||
if (pax->flags & WRITE_LIBARCHIVE_XATTR) {
|
||||
encoded_value = base64_encode((const char *)value, value_len);
|
||||
|
||||
if (encoded_name != NULL && encoded_value != NULL) {
|
||||
archive_string_init(&s);
|
||||
archive_strcpy(&s, "LIBARCHIVE.xattr.");
|
||||
archive_strcat(&s, encoded_name);
|
||||
add_pax_attr(&(pax->pax_header), s.s, encoded_value);
|
||||
archive_string_free(&s);
|
||||
}
|
||||
free(encoded_value);
|
||||
}
|
||||
if (pax->flags & WRITE_SCHILY_XATTR) {
|
||||
archive_string_init(&s);
|
||||
archive_strcpy(&s, "SCHILY.xattr.");
|
||||
archive_strcat(&s, encoded_name);
|
||||
add_pax_attr_binary(&(pax->pax_header), s.s, value, value_len);
|
||||
archive_string_free(&s);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
archive_write_pax_header_xattrs(struct archive_write *a,
|
||||
struct pax *pax, struct archive_entry *entry)
|
||||
{
|
||||
struct archive_string s;
|
||||
int i = archive_entry_xattr_reset(entry);
|
||||
|
||||
while (i--) {
|
||||
const char *name;
|
||||
const void *value;
|
||||
char *encoded_value;
|
||||
char *url_encoded_name = NULL, *encoded_name = NULL;
|
||||
size_t size;
|
||||
int r;
|
||||
@ -346,16 +394,9 @@ archive_write_pax_header_xattrs(struct archive_write *a,
|
||||
}
|
||||
}
|
||||
|
||||
encoded_value = base64_encode((const char *)value, size);
|
||||
archive_write_pax_header_xattr(pax, encoded_name,
|
||||
value, size);
|
||||
|
||||
if (encoded_name != NULL && encoded_value != NULL) {
|
||||
archive_string_init(&s);
|
||||
archive_strcpy(&s, "LIBARCHIVE.xattr.");
|
||||
archive_strcat(&s, encoded_name);
|
||||
add_pax_attr(&(pax->pax_header), s.s, encoded_value);
|
||||
archive_string_free(&s);
|
||||
}
|
||||
free(encoded_value);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
@ -450,6 +491,45 @@ get_entry_symlink(struct archive_write *a, struct archive_entry *entry,
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/* Add ACL to pax header */
|
||||
static int
|
||||
add_pax_acl(struct archive_write *a,
|
||||
struct archive_entry *entry, struct pax *pax, int flags)
|
||||
{
|
||||
char *p;
|
||||
const char *attr;
|
||||
int acl_types;
|
||||
|
||||
acl_types = archive_entry_acl_types(entry);
|
||||
|
||||
if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
|
||||
attr = "SCHILY.acl.ace";
|
||||
else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)
|
||||
attr = "SCHILY.acl.access";
|
||||
else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
||||
attr = "SCHILY.acl.default";
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
p = archive_entry_acl_to_text_l(entry, NULL, flags, pax->sconv_utf8);
|
||||
if (p == NULL) {
|
||||
if (errno == ENOMEM) {
|
||||
archive_set_error(&a->archive, ENOMEM, "%s %s",
|
||||
"Can't allocate memory for ", attr);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT, "%s %s %s",
|
||||
"Can't translate ", attr, " to UTF-8");
|
||||
return(ARCHIVE_WARN);
|
||||
} else if (*p != '\0') {
|
||||
add_pax_attr(&(pax->pax_header),
|
||||
attr, p);
|
||||
free(p);
|
||||
}
|
||||
return(ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Consider adding 'comment' and 'charset' fields to
|
||||
* archive_entry so that clients can specify them. Also, consider
|
||||
@ -466,6 +546,7 @@ archive_write_pax_header(struct archive_write *a,
|
||||
const char *p;
|
||||
const char *suffix;
|
||||
int need_extension, r, ret;
|
||||
int acl_types;
|
||||
int sparse_count;
|
||||
uint64_t sparse_total, real_size;
|
||||
struct pax *pax;
|
||||
@ -709,7 +790,7 @@ archive_write_pax_header(struct archive_write *a,
|
||||
|
||||
/* Copy entry so we can modify it as needed. */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Make sure the path separators in pahtname, hardlink and symlink
|
||||
/* Make sure the path separators in pathname, hardlink and symlink
|
||||
* are all slash '/', not the Windows path separator '\'. */
|
||||
entry_main = __la_win_entry_in_posix_pathseparator(entry_original);
|
||||
if (entry_main == entry_original)
|
||||
@ -1017,16 +1098,6 @@ archive_write_pax_header(struct archive_write *a,
|
||||
if (!need_extension && p != NULL && *p != '\0')
|
||||
need_extension = 1;
|
||||
|
||||
/* If there are non-trivial ACL entries, we need an extension. */
|
||||
if (!need_extension && archive_entry_acl_count(entry_original,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS) > 0)
|
||||
need_extension = 1;
|
||||
|
||||
/* If there are non-trivial ACL entries, we need an extension. */
|
||||
if (!need_extension && archive_entry_acl_count(entry_original,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) > 0)
|
||||
need_extension = 1;
|
||||
|
||||
/* If there are extended attributes, we need an extension */
|
||||
if (!need_extension && archive_entry_xattr_count(entry_original) > 0)
|
||||
need_extension = 1;
|
||||
@ -1035,6 +1106,12 @@ archive_write_pax_header(struct archive_write *a,
|
||||
if (!need_extension && sparse_count > 0)
|
||||
need_extension = 1;
|
||||
|
||||
acl_types = archive_entry_acl_types(entry_original);
|
||||
|
||||
/* If there are any ACL entries, we need an extension */
|
||||
if (!need_extension && acl_types != 0)
|
||||
need_extension = 1;
|
||||
|
||||
/*
|
||||
* Libarchive used to include these in extended headers for
|
||||
* restricted pax format, but that confused people who
|
||||
@ -1086,43 +1163,29 @@ archive_write_pax_header(struct archive_write *a,
|
||||
add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p);
|
||||
|
||||
/* I use star-compatible ACL attributes. */
|
||||
r = archive_entry_acl_text_l(entry_original,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
|
||||
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID,
|
||||
&p, NULL, pax->sconv_utf8);
|
||||
if (r != 0) {
|
||||
if (errno == ENOMEM) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory for "
|
||||
"ACL.access");
|
||||
if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
||||
ret = add_pax_acl(a, entry_original, pax,
|
||||
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
|
||||
ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA |
|
||||
ARCHIVE_ENTRY_ACL_STYLE_COMPACT);
|
||||
if (ret == ARCHIVE_FATAL)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate ACL.access to UTF-8");
|
||||
ret = ARCHIVE_WARN;
|
||||
} else if (p != NULL && *p != '\0') {
|
||||
add_pax_attr(&(pax->pax_header),
|
||||
"SCHILY.acl.access", p);
|
||||
}
|
||||
r = archive_entry_acl_text_l(entry_original,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
|
||||
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID,
|
||||
&p, NULL, pax->sconv_utf8);
|
||||
if (r != 0) {
|
||||
if (errno == ENOMEM) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory for "
|
||||
"ACL.default");
|
||||
if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
|
||||
ret = add_pax_acl(a, entry_original, pax,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
|
||||
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
|
||||
ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
|
||||
if (ret == ARCHIVE_FATAL)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) {
|
||||
ret = add_pax_acl(a, entry_original, pax,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
|
||||
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
|
||||
ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
|
||||
if (ret == ARCHIVE_FATAL)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate ACL.default to UTF-8");
|
||||
ret = ARCHIVE_WARN;
|
||||
} else if (p != NULL && *p != '\0') {
|
||||
add_pax_attr(&(pax->pax_header),
|
||||
"SCHILY.acl.default", p);
|
||||
}
|
||||
|
||||
/* We use GNU-tar-compatible sparse attributes. */
|
||||
|
@ -113,12 +113,11 @@ archive_write_set_format_shar(struct archive *_a)
|
||||
if (a->format_free != NULL)
|
||||
(a->format_free)(a);
|
||||
|
||||
shar = (struct shar *)malloc(sizeof(*shar));
|
||||
shar = (struct shar *)calloc(1, sizeof(*shar));
|
||||
if (shar == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate shar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(shar, 0, sizeof(*shar));
|
||||
archive_string_init(&shar->work);
|
||||
archive_string_init(&shar->quoted_name);
|
||||
a->format_data = shar;
|
||||
|
@ -114,9 +114,9 @@ static const char template_header[] = {
|
||||
'0','0','0','0','0','0', ' ','\0',
|
||||
/* gid, space-null termination: 8 bytes */
|
||||
'0','0','0','0','0','0', ' ','\0',
|
||||
/* size, space termation: 12 bytes */
|
||||
/* size, space termination: 12 bytes */
|
||||
'0','0','0','0','0','0','0','0','0','0','0', ' ',
|
||||
/* mtime, space termation: 12 bytes */
|
||||
/* mtime, space termination: 12 bytes */
|
||||
'0','0','0','0','0','0','0','0','0','0','0', ' ',
|
||||
/* Initial checksum value: 8 spaces */
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',
|
||||
@ -184,13 +184,12 @@ archive_write_set_format_ustar(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
ustar = (struct ustar *)malloc(sizeof(*ustar));
|
||||
ustar = (struct ustar *)calloc(1, sizeof(*ustar));
|
||||
if (ustar == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate ustar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(ustar, 0, sizeof(*ustar));
|
||||
a->format_data = ustar;
|
||||
a->format_name = "ustar";
|
||||
a->format_options = archive_write_ustar_options;
|
||||
@ -307,7 +306,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
|
||||
* case getting WCS failed. On POSIX, this is a
|
||||
* normal operation.
|
||||
*/
|
||||
if (p != NULL && p[strlen(p) - 1] != '/') {
|
||||
if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') {
|
||||
struct archive_string as;
|
||||
|
||||
archive_string_init(&as);
|
||||
@ -336,7 +335,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Make sure the path separators in pahtname, hardlink and symlink
|
||||
/* Make sure the path separators in pathname, hardlink and symlink
|
||||
* are all slash '/', not the Windows path separator '\'. */
|
||||
entry_main = __la_win_entry_in_posix_pathseparator(entry);
|
||||
if (entry_main == NULL) {
|
||||
|
@ -98,9 +98,9 @@ static const char template_header[] = {
|
||||
'0','0','0','0','0','0', ' ','\0',
|
||||
/* gid, space-null termination: 8 bytes */
|
||||
'0','0','0','0','0','0', ' ','\0',
|
||||
/* size, space termation: 12 bytes */
|
||||
/* size, space termination: 12 bytes */
|
||||
'0','0','0','0','0','0','0','0','0','0','0', ' ',
|
||||
/* mtime, space termation: 12 bytes */
|
||||
/* mtime, space termination: 12 bytes */
|
||||
'0','0','0','0','0','0','0','0','0','0','0', ' ',
|
||||
/* Initial checksum value: 8 spaces */
|
||||
' ',' ',' ',' ',' ',' ',' ',' ',
|
||||
@ -161,13 +161,12 @@ archive_write_set_format_v7tar(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
v7tar = (struct v7tar *)malloc(sizeof(*v7tar));
|
||||
v7tar = (struct v7tar *)calloc(1, sizeof(*v7tar));
|
||||
if (v7tar == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate v7tar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(v7tar, 0, sizeof(*v7tar));
|
||||
a->format_data = v7tar;
|
||||
a->format_name = "tar (non-POSIX)";
|
||||
a->format_options = archive_write_v7tar_options;
|
||||
@ -314,7 +313,7 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry)
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Make sure the path separators in pahtname, hardlink and symlink
|
||||
/* Make sure the path separators in pathname, hardlink and symlink
|
||||
* are all slash '/', not the Windows path separator '\'. */
|
||||
entry_main = __la_win_entry_in_posix_pathseparator(entry);
|
||||
if (entry_main == NULL) {
|
||||
|
@ -79,7 +79,7 @@ typedef enum {
|
||||
WT_RVIS,
|
||||
/* conversion, unsupported */
|
||||
WT_CONV,
|
||||
/* continutation, unsupported at the moment */
|
||||
/* continuation, unsupported at the moment */
|
||||
WT_CONT,
|
||||
/* invalid type */
|
||||
LAST_WT
|
||||
|
@ -63,7 +63,7 @@ __FBSDID("$FreeBSD$");
|
||||
* - When writing an XML element <link type="<file-type>">, <file-type>
|
||||
* which is a file type a symbolic link is referencing is always marked
|
||||
* as "broken". Xar utility uses stat(2) to get the file type, but, in
|
||||
* libarcive format writer, we should not use it; if it is needed, we
|
||||
* libarchive format writer, we should not use it; if it is needed, we
|
||||
* should get about it at archive_read_disk.c.
|
||||
* - It is possible to appear both <flags> and <ext2> elements.
|
||||
* Xar utility generates <flags> on BSD platform and <ext2> on Linux
|
||||
@ -192,7 +192,7 @@ struct file {
|
||||
struct file *parent; /* parent directory entry */
|
||||
/*
|
||||
* To manage sub directory files.
|
||||
* We use 'chnext' a menber of struct file to chain.
|
||||
* We use 'chnext' (a member of struct file) to chain.
|
||||
*/
|
||||
struct {
|
||||
struct file *first;
|
||||
@ -258,7 +258,7 @@ struct xar {
|
||||
/*
|
||||
* The list of all file entries is used to manage struct file
|
||||
* objects.
|
||||
* We use 'next' a menber of struct file to chain.
|
||||
* We use 'next' (a member of struct file) to chain.
|
||||
*/
|
||||
struct {
|
||||
struct file *first;
|
||||
@ -266,7 +266,7 @@ struct xar {
|
||||
} file_list;
|
||||
/*
|
||||
* The list of hard-linked file entries.
|
||||
* We use 'hlnext' a menber of struct file to chain.
|
||||
* We use 'hlnext' (a member of struct file) to chain.
|
||||
*/
|
||||
struct archive_rb_tree hardlink_rbtree;
|
||||
};
|
||||
@ -1227,7 +1227,7 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
|
||||
case AE_IFLNK:
|
||||
/*
|
||||
* xar utility has checked a file type, which
|
||||
* a symblic-link file has referenced.
|
||||
* a symbolic-link file has referenced.
|
||||
* For example:
|
||||
* <link type="directory">../ref/</link>
|
||||
* The symlink target file is "../ref/" and its
|
||||
@ -1237,8 +1237,8 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer,
|
||||
* The symlink target file is "../f" and its
|
||||
* file type is a regular file.
|
||||
*
|
||||
* But our implemention cannot do it, and then we
|
||||
* always record that a attribute "type" is "borken",
|
||||
* But our implementation cannot do it, and then we
|
||||
* always record that a attribute "type" is "broken",
|
||||
* for example:
|
||||
* <link type="broken">foo/bar</link>
|
||||
* It means "foo/bar" is not reachable.
|
||||
@ -1544,7 +1544,7 @@ make_toc(struct archive_write *a)
|
||||
}
|
||||
|
||||
/*
|
||||
* Start recoding TOC
|
||||
* Start recording TOC
|
||||
*/
|
||||
r = xmlTextWriterStartElement(writer, BAD_CAST("xar"));
|
||||
if (r < 0) {
|
||||
@ -1961,6 +1961,7 @@ file_free(struct file *file)
|
||||
archive_string_free(&(file->basename));
|
||||
archive_string_free(&(file->symlink));
|
||||
archive_string_free(&(file->script));
|
||||
archive_entry_free(file->entry);
|
||||
free(file);
|
||||
}
|
||||
|
||||
@ -2484,7 +2485,7 @@ file_connect_hardlink_files(struct xar *xar)
|
||||
archive_entry_set_nlink(target->entry, hl->nlink);
|
||||
if (hl->nlink > 1)
|
||||
/* It means this file is a hardlink
|
||||
* targe itself. */
|
||||
* target itself. */
|
||||
target->hardlink_target = target;
|
||||
for (nf = target->hlnext;
|
||||
nf != NULL; nf = nf->hlnext) {
|
||||
@ -2913,7 +2914,7 @@ compression_init_encoder_xz(struct archive *a,
|
||||
*strm = lzma_init_data;
|
||||
#ifdef HAVE_LZMA_STREAM_ENCODER_MT
|
||||
if (threads > 1) {
|
||||
bzero(&mt_options, sizeof(mt_options));
|
||||
memset(&mt_options, 0, sizeof(mt_options));
|
||||
mt_options.threads = threads;
|
||||
mt_options.timeout = 300;
|
||||
mt_options.filters = lzmafilters;
|
||||
|
@ -592,7 +592,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
|
||||
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Make sure the path separators in pahtname, hardlink and symlink
|
||||
/* Make sure the path separators in pathname, hardlink and symlink
|
||||
* are all slash '/', not the Windows path separator '\'. */
|
||||
zip->entry = __la_win_entry_in_posix_pathseparator(entry);
|
||||
if (zip->entry == entry)
|
||||
@ -878,7 +878,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
|
||||
|| zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) {
|
||||
|
||||
memcpy(e, "\001\231\007\000\001\000AE", 8);
|
||||
/* AES vendoer version AE-2 does not store a CRC.
|
||||
/* AES vendor version AE-2 does not store a CRC.
|
||||
* WinZip 11 uses AE-1, which does store the CRC,
|
||||
* but it does not store the CRC when the file size
|
||||
* is less than 20 bytes. So we simulate what
|
||||
@ -1013,7 +1013,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
|
||||
if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) {
|
||||
switch (zip->entry_encryption) {
|
||||
case ENCRYPTION_TRADITIONAL:
|
||||
/* Initialize traditoinal PKWARE encryption context. */
|
||||
/* Initialize traditional PKWARE encryption context. */
|
||||
if (!zip->tctx_valid) {
|
||||
ret = init_traditional_pkware_encryption(a);
|
||||
if (ret != ARCHIVE_OK)
|
||||
@ -1499,7 +1499,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
trad_enc_decypt_byte(struct trad_enc_ctx *ctx)
|
||||
trad_enc_decrypt_byte(struct trad_enc_ctx *ctx)
|
||||
{
|
||||
unsigned temp = ctx->keys[2] | 2;
|
||||
return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff;
|
||||
@ -1515,7 +1515,7 @@ trad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in,
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
uint8_t t = in[i];
|
||||
out[i] = t ^ trad_enc_decypt_byte(ctx);
|
||||
out[i] = t ^ trad_enc_decrypt_byte(ctx);
|
||||
trad_enc_update_keys(ctx, t);
|
||||
}
|
||||
return i;
|
||||
@ -1626,7 +1626,7 @@ init_winzip_aes_encryption(struct archive_write *a)
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
/* Set a passowrd verification value after the 'salt'. */
|
||||
/* Set a password verification value after the 'salt'. */
|
||||
salt[salt_len] = derived_key[key_len * 2];
|
||||
salt[salt_len + 1] = derived_key[key_len * 2 + 1];
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
/* FreeBSD 5.0 and later have ACL and extattr support. */
|
||||
#if __FreeBSD__ > 4
|
||||
#define HAVE_ACL_CREATE_ENTRY 1
|
||||
#define HAVE_ACL_GET_FD_NP 1
|
||||
#define HAVE_ACL_GET_LINK_NP 1
|
||||
#define HAVE_ACL_GET_PERM_NP 1
|
||||
#define HAVE_ACL_INIT 1
|
||||
@ -39,6 +40,7 @@
|
||||
#define HAVE_EXTATTR_LIST_FILE 1
|
||||
#define HAVE_EXTATTR_SET_FD 1
|
||||
#define HAVE_EXTATTR_SET_FILE 1
|
||||
#define HAVE_STRUCT_XVFSCONF 1
|
||||
#define HAVE_SYS_ACL_H 1
|
||||
#define HAVE_SYS_EXTATTR_H 1
|
||||
#endif
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 18, 2012
|
||||
.Dd December 27, 2016
|
||||
.Dt LIBARCHIVE-FORMATS 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -191,8 +191,6 @@ and device numbers.
|
||||
.It Solaris extensions
|
||||
Libarchive recognizes ACL and extended attribute records written
|
||||
by Solaris tar.
|
||||
Currently, libarchive only has support for old-style ACLs; the
|
||||
newer NFSv4 ACLs are recognized but discarded.
|
||||
.El
|
||||
.Pp
|
||||
The first tar program appeared in Seventh Edition Unix in 1979.
|
||||
|
@ -1,4 +1,5 @@
|
||||
.\" Copyright (c) 2003-2009 Tim Kientzle
|
||||
.\" Copyright (c) 2016 Martin Matuska
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -24,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 23, 2011
|
||||
.Dd December 27, 2016
|
||||
.Dt TAR 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -440,11 +441,11 @@ archives to store files much larger than the historic 8GB limit.
|
||||
Vendor-specific attributes used by Joerg Schilling's
|
||||
.Nm star
|
||||
implementation.
|
||||
.It Cm SCHILY.acl.access , Cm SCHILY.acl.default
|
||||
Stores the access and default ACLs as textual strings in a format
|
||||
.It Cm SCHILY.acl.access , Cm SCHILY.acl.default, Cm SCHILY.acl.ace
|
||||
Stores the access, default and NFSv4 ACLs as textual strings in a format
|
||||
that is an extension of the format specified by POSIX.1e draft 17.
|
||||
In particular, each user or group access specification can include a fourth
|
||||
colon-separated field with the numeric UID or GID.
|
||||
In particular, each user or group access specification can include
|
||||
an additional colon-separated field with the numeric UID or GID.
|
||||
This allows ACLs to be restored on systems that may not have complete
|
||||
user or group information available (such as when NIS/YP or LDAP services
|
||||
are temporarily unavailable).
|
||||
|
@ -29,13 +29,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
You can contact the author at :
|
||||
- xxHash source repository : http://code.google.com/p/xxhash/
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
#include "archive_xxhash.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "archive_xxhash.h"
|
||||
|
||||
#ifdef HAVE_LIBLZ4
|
||||
|
||||
/***************************************
|
||||
@ -61,7 +61,7 @@ You can contact the author at :
|
||||
** By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
|
||||
** Results are therefore identical for little-endian and big-endian CPU.
|
||||
** This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
|
||||
** Should endian-independance be of no importance for your application, you may set the #define below to 1.
|
||||
** Should endian-independence be of no importance for your application, you may set the #define below to 1.
|
||||
** It will improve speed for Big-endian CPU.
|
||||
** This option has no impact on Little_Endian CPU.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user