Merge topic 'update-libarchive'

d49176e9 libarchive: Avoid using isblank
ce8f117f libarchive: Avoid declaration after statement in C code
e0f725f8 libarchive: Fix use of ssize_t in archive_entry.h
ae4861ec libarchive: Define __LA_DEPRECATED consistently
fecb70dd Update CMake pre-cached values for libarchive 3.3.0
a59a7ee9 Merge branch 'upstream-LibArchive' into update-libarchive
c206211a LibArchive 2017-02-19 (100ee75a)
cdce7c61 libarchive: Update script to get 3.3.0
This commit is contained in:
Brad King 2017-02-24 09:31:22 -05:00 committed by CMake Topic Stage
commit 33f636264a
88 changed files with 4734 additions and 1995 deletions

View File

@ -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")

View File

@ -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

View File

@ -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)
#

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -1 +1 @@
3002001
3003000

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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);
}
/*

View File

@ -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 */);

View File

@ -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

View File

@ -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 *);

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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

View File

@ -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_;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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 *);

View File

@ -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) {

View File

@ -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,

View File

@ -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\"",

View File

@ -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) {

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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.

View File

@ -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))

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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++;

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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 *);

View File

@ -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 },

View File

@ -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;

View File

@ -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)
{

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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 ,

View File

@ -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;

View File

@ -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);

View File

@ -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";

View File

@ -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) {

View File

@ -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) {

View File

@ -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)

View File

@ -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:

View File

@ -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.

View File

@ -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. */

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -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;

View File

@ -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];

View File

@ -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

View File

@ -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.

View File

@ -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).

View File

@ -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.
*/