Merge topic 'update-libarchive'

c80d8cb2 libarchive: Fix inclusion of zlib, bzlib, and lzma for build within CMake
6df1bda1 Merge branch 'upstream-LibArchive' into update-libarchive
11f3dcb0 LibArchive 2017-07-09 (98a69539)
b6674431 libarchive: Update script to get 3.3.2

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !1071
This commit is contained in:
Brad King
2017-08-02 15:45:19 +00:00
committed by Kitware Robot
65 changed files with 4370 additions and 2759 deletions
+1 -1
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="v3.3.1"
readonly tag="v3.3.2"
readonly shortlog=false
readonly paths="
CMakeLists.txt
+297 -108
View File
@@ -422,6 +422,7 @@ int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS)
LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H)
LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H)
LA_CHECK_INCLUDE_FILE("membership.h" HAVE_MEMBERSHIP_H)
LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H)
LA_CHECK_INCLUDE_FILE("paths.h" HAVE_PATHS_H)
LA_CHECK_INCLUDE_FILE("poll.h" HAVE_POLL_H)
@@ -439,11 +440,13 @@ LA_CHECK_INCLUDE_FILE("string.h" HAVE_STRING_H)
LA_CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H)
LA_CHECK_INCLUDE_FILE("sys/acl.h" HAVE_SYS_ACL_H)
LA_CHECK_INCLUDE_FILE("sys/cdefs.h" HAVE_SYS_CDEFS_H)
LA_CHECK_INCLUDE_FILE("sys/extattr.h" HAVE_SYS_EXTATTR_H)
LA_CHECK_INCLUDE_FILE("sys/ioctl.h" HAVE_SYS_IOCTL_H)
LA_CHECK_INCLUDE_FILE("sys/mkdev.h" HAVE_SYS_MKDEV_H)
LA_CHECK_INCLUDE_FILE("sys/mount.h" HAVE_SYS_MOUNT_H)
LA_CHECK_INCLUDE_FILE("sys/param.h" HAVE_SYS_PARAM_H)
LA_CHECK_INCLUDE_FILE("sys/poll.h" HAVE_SYS_POLL_H)
LA_CHECK_INCLUDE_FILE("sys/richacl.h" HAVE_SYS_RICHACL_H)
LA_CHECK_INCLUDE_FILE("sys/select.h" HAVE_SYS_SELECT_H)
LA_CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H)
LA_CHECK_INCLUDE_FILE("sys/statfs.h" HAVE_SYS_STATFS_H)
@@ -453,6 +456,7 @@ LA_CHECK_INCLUDE_FILE("sys/utime.h" HAVE_SYS_UTIME_H)
LA_CHECK_INCLUDE_FILE("sys/utsname.h" HAVE_SYS_UTSNAME_H)
LA_CHECK_INCLUDE_FILE("sys/vfs.h" HAVE_SYS_VFS_H)
LA_CHECK_INCLUDE_FILE("sys/wait.h" HAVE_SYS_WAIT_H)
LA_CHECK_INCLUDE_FILE("sys/xattr.h" HAVE_SYS_XATTR_H)
LA_CHECK_INCLUDE_FILE("time.h" HAVE_TIME_H)
LA_CHECK_INCLUDE_FILE("unistd.h" HAVE_UNISTD_H)
LA_CHECK_INCLUDE_FILE("utime.h" HAVE_UTIME_H)
@@ -461,6 +465,9 @@ LA_CHECK_INCLUDE_FILE("wctype.h" HAVE_WCTYPE_H)
LA_CHECK_INCLUDE_FILE("windows.h" HAVE_WINDOWS_H)
IF(ENABLE_CNG)
LA_CHECK_INCLUDE_FILE("Bcrypt.h" HAVE_BCRYPT_H)
IF(HAVE_BCRYPT_H)
LIST(APPEND ADDITIONAL_LIBS "Bcrypt")
ENDIF(HAVE_BCRYPT_H)
ELSE(ENABLE_CNG)
UNSET(HAVE_BCRYPT_H CACHE)
ENDIF(ENABLE_CNG)
@@ -924,7 +931,6 @@ CHECK_FUNCTION_EXISTS_GLIBC(chflags HAVE_CHFLAGS)
CHECK_FUNCTION_EXISTS_GLIBC(chown HAVE_CHOWN)
CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT)
CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R)
CHECK_FUNCTION_EXISTS_GLIBC(dirfd HAVE_DIRFD)
CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR)
CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS)
CHECK_FUNCTION_EXISTS_GLIBC(fchmod HAVE_FCHMOD)
@@ -1024,6 +1030,10 @@ CHECK_C_SOURCE_COMPILES(
"#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}"
HAVE_READDIR_R)
# dirfd can be either a function or a macro.
CHECK_C_SOURCE_COMPILES(
"#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); return dirfd(d);}"
HAVE_DIRFD)
# Only detect readlinkat() if we also have AT_FDCWD in unistd.h.
# NOTE: linux requires fcntl.h for AT_FDCWD.
@@ -1256,60 +1266,105 @@ CHECK_FILE_OFFSET_BITS()
# Check for Extended Attribute libraries, headers, and functions
#
IF(ENABLE_XATTR)
LA_CHECK_INCLUDE_FILE(attr/xattr.h HAVE_ATTR_XATTR_H)
LA_CHECK_INCLUDE_FILE(sys/xattr.h HAVE_SYS_XATTR_H)
LA_CHECK_INCLUDE_FILE(sys/extattr.h HAVE_SYS_EXTATTR_H)
CHECK_LIBRARY_EXISTS(attr "setxattr" "" HAVE_LIBATTR)
IF(HAVE_LIBATTR)
SET(CMAKE_REQUIRED_LIBRARIES "attr")
ENDIF(HAVE_LIBATTR)
CHECK_SYMBOL_EXISTS(EXTATTR_NAMESPACE_USER "sys/types.h;sys/extattr.h" HAVE_DECL_EXTATTR_NAMESPACE_USER)
CHECK_FUNCTION_EXISTS_GLIBC(extattr_get_file HAVE_EXTATTR_GET_FILE)
CHECK_FUNCTION_EXISTS_GLIBC(extattr_list_file HAVE_EXTATTR_LIST_FILE)
CHECK_FUNCTION_EXISTS_GLIBC(extattr_set_fd HAVE_EXTATTR_SET_FD)
CHECK_FUNCTION_EXISTS_GLIBC(extattr_set_file HAVE_EXTATTR_SET_FILE)
CHECK_FUNCTION_EXISTS_GLIBC(fgetxattr HAVE_FGETXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(flistxattr HAVE_FLISTXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(fsetxattr HAVE_FSETXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(getxattr HAVE_GETXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(lgetxattr HAVE_LGETXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(listxattr HAVE_LISTXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(llistxattr HAVE_LLISTXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(lsetxattr HAVE_LSETXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(fgetea HAVE_FGETEA)
CHECK_FUNCTION_EXISTS_GLIBC(flistea HAVE_FLISTEA)
CHECK_FUNCTION_EXISTS_GLIBC(fsetea HAVE_FSETEA)
CHECK_FUNCTION_EXISTS_GLIBC(getea HAVE_GETEA)
CHECK_FUNCTION_EXISTS_GLIBC(lgetea HAVE_LGETEA)
CHECK_FUNCTION_EXISTS_GLIBC(listea HAVE_LISTEA)
CHECK_FUNCTION_EXISTS_GLIBC(llistea HAVE_LLISTEA)
CHECK_FUNCTION_EXISTS_GLIBC(lsetea HAVE_LSETEA)
CHECK_SYMBOL_EXISTS(XATTR_NOFOLLOW "sys/xattr.h" HAVE_DECL_XATTR_NOFOLLOW)
IF(HAVE_SYS_XATTR_H AND HAVE_DECL_XATTR_NOFOLLOW)
CHECK_FUNCTION_EXISTS(fgetxattr HAVE_FGETXATTR)
CHECK_FUNCTION_EXISTS(flistxattr HAVE_FLISTXATTR)
CHECK_FUNCTION_EXISTS(fsetxattr HAVE_FSETXATTR)
CHECK_FUNCTION_EXISTS(getxattr HAVE_GETXATTR)
CHECK_FUNCTION_EXISTS(listxattr HAVE_LISTXATTR)
CHECK_FUNCTION_EXISTS(setxattr HAVE_SETXATTR)
IF(HAVE_FGETXATTR AND
HAVE_FLISTXATTR AND
HAVE_FSETXATTR AND
HAVE_GETXATTR AND
HAVE_LISTXATTR AND
HAVE_SETXATTR)
SET(ARCHIVE_XATTR_DARWIN TRUE)
ENDIF()
ELSEIF(HAVE_SYS_EXTATTR_H AND HAVE_DECL_EXTATTR_NAMESPACE_USER)
# FreeBSD xattr support
CHECK_FUNCTION_EXISTS(extattr_get_fd HAVE_EXTATTR_GET_FD)
CHECK_FUNCTION_EXISTS(extattr_get_file HAVE_EXTATTR_GET_FILE)
CHECK_FUNCTION_EXISTS(extattr_get_link HAVE_EXTATTR_GET_LINK)
CHECK_FUNCTION_EXISTS(extattr_list_fd HAVE_EXTATTR_LIST_FD)
CHECK_FUNCTION_EXISTS(extattr_list_file HAVE_EXTATTR_LIST_FILE)
CHECK_FUNCTION_EXISTS(extattr_list_link HAVE_EXTATTR_LIST_LINK)
CHECK_FUNCTION_EXISTS(extattr_set_fd HAVE_EXTATTR_SET_FD)
CHECK_FUNCTION_EXISTS(extattr_set_link HAVE_EXTATTR_SET_LINK)
IF(HAVE_EXTATTR_GET_FD AND
HAVE_EXTATTR_GET_FILE AND
HAVE_EXTATTR_GET_LINK AND
HAVE_EXTATTR_LIST_FD AND
HAVE_EXTATTR_LIST_FILE AND
HAVE_EXTATTR_LIST_LINK AND
HAVE_EXTATTR_SET_FD AND
HAVE_EXTATTR_SET_LINK)
SET(ARCHIVE_XATTR_FREEBSD TRUE)
ENDIF()
ELSEIF(HAVE_SYS_XATTR_H OR HAVE_ATTR_XATTR_H)
# Linux xattr support
CHECK_FUNCTION_EXISTS_GLIBC(fgetxattr HAVE_FGETXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(flistxattr HAVE_FLISTXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(fsetxattr HAVE_FSETXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(getxattr HAVE_GETXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(lgetxattr HAVE_LGETXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(listxattr HAVE_LISTXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(llistxattr HAVE_LLISTXATTR)
CHECK_FUNCTION_EXISTS_GLIBC(lsetxattr HAVE_LSETXATTR)
IF(HAVE_FGETXATTR AND
HAVE_FLISTXATTR AND
HAVE_FSETXATTR AND
HAVE_GETXATTR AND
HAVE_LGETXATTR AND
HAVE_LISTXATTR AND
HAVE_LLISTXATTR AND
HAVE_LSETXATTR)
SET(ARCHIVE_XATTR_LINUX TRUE)
ENDIF()
ELSEIF(HAVE_SYS_EA_H)
# AIX xattr support
CHECK_FUNCTION_EXISTS(fgetea HAVE_FGETEA)
CHECK_FUNCTION_EXISTS(flistea HAVE_FLISTEA)
CHECK_FUNCTION_EXISTS(fsetea HAVE_FSETEA)
CHECK_FUNCTION_EXISTS(getea HAVE_GETEA)
CHECK_FUNCTION_EXISTS(lgetea HAVE_LGETEA)
CHECK_FUNCTION_EXISTS(listea HAVE_LISTEA)
CHECK_FUNCTION_EXISTS(llistea HAVE_LLISTEA)
CHECK_FUNCTION_EXISTS(lsetea HAVE_LSETEA)
IF(HAVE_FGETEA AND
HAVE_FLISTEA AND
HAVE_FSETEA AND
HAVE_GETEA AND
HAVE_LGETEA AND
HAVE_LISTEA AND
HAVE_LLISTEA AND
HAVE_LSETEA)
SET(ARCHIVE_XATTR_AIX TRUE)
ENDIF()
ENDIF()
IF(ARCHIVE_XATTR_DARWIN)
MESSAGE(STATUS "Extended attributes support: Darwin")
ELSEIF(ARCHIVE_XATTR_FREEBSD)
MESSAGE(STATUS "Extended attributes support: FreeBSD")
ELSEIF(ARCHIVE_XATTR_LINUX)
MESSAGE(STATUS "Extended attributes support: Linux")
ELSEIF(ARCHIVE_XATTR_AIX)
MESSAGE(STATUS "Extended attributes support: AIX")
ELSE()
MESSAGE(STATUS "Extended attributes support: none")
ENDIF()
ELSE(ENABLE_XATTR)
SET(HAVE_ATTR_LIB FALSE)
SET(HAVE_ATTR_XATTR_H FALSE)
SET(HAVE_DECL_EXTATTR_NAMESPACE_USER FALSE)
SET(HAVE_EXTATTR_GET_FILE FALSE)
SET(HAVE_EXTATTR_LIST_FILE FALSE)
SET(HAVE_EXTATTR_SET_FD FALSE)
SET(HAVE_EXTATTR_SET_FILE FALSE)
SET(HAVE_FGETEA FALSE)
SET(HAVE_FGETXATTR FALSE)
SET(HAVE_FLISTEA FALSE)
SET(HAVE_FLISTXATTR FALSE)
SET(HAVE_FSETEA FALSE)
SET(HAVE_FSETXATTR FALSE)
SET(HAVE_GETEA FALSE)
SET(HAVE_GETXATTR FALSE)
SET(HAVE_LGETEA FALSE)
SET(HAVE_LGETXATTR FALSE)
SET(HAVE_LISTEA FALSE)
SET(HAVE_LISTXATTR FALSE)
SET(HAVE_LLISTEA FALSE)
SET(HAVE_LLISTXATTR FALSE)
SET(HAVE_LSETEA FALSE)
SET(HAVE_LSETXATTR FALSE)
SET(HAVE_SYS_EXTATTR_H FALSE)
SET(HAVE_SYS_XATTR_H FALSE)
SET(ARCHIVE_XATTR_DARWIN FALSE)
SET(ARCHIVE_XATTR_FREEBSD FALSE)
SET(ARCHIVE_XATTR_LINUX FALSE)
SET(ARCHIVE_XATTR_AIX FALSE)
ENDIF(ENABLE_XATTR)
#
@@ -1321,78 +1376,212 @@ ENDIF(ENABLE_XATTR)
# which makes the following checks rather more complex than I would like.
#
IF(ENABLE_ACL)
# Solaris and derivates ACLs
CHECK_FUNCTION_EXISTS(acl HAVE_ACL)
CHECK_FUNCTION_EXISTS(facl HAVE_FACL)
# Libacl
CHECK_LIBRARY_EXISTS(acl "acl_get_file" "" HAVE_LIBACL)
IF(HAVE_LIBACL)
SET(CMAKE_REQUIRED_LIBRARIES "acl")
FIND_LIBRARY(ACL_LIBRARY NAMES acl)
LIST(APPEND ADDITIONAL_LIBS ${ACL_LIBRARY})
ENDIF(HAVE_LIBACL)
#
CHECK_FUNCTION_EXISTS_GLIBC(acl_create_entry HAVE_ACL_CREATE_ENTRY)
CHECK_FUNCTION_EXISTS_GLIBC(acl_init HAVE_ACL_INIT)
CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd HAVE_ACL_SET_FD)
CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd_np HAVE_ACL_SET_FD_NP)
CHECK_FUNCTION_EXISTS_GLIBC(acl_set_file HAVE_ACL_SET_FILE)
CHECK_TYPE_EXISTS(acl_permset_t "${INCLUDES}" HAVE_ACL_PERMSET_T)
# The "acl_get_perm()" function was omitted from the POSIX draft.
# (It's a pretty obvious oversight; otherwise, there's no way to
# 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)
CHECK_TYPE_EXISTS(acl_t "sys/types.h;sys/acl.h" HAVE_ACL_T)
CHECK_TYPE_EXISTS(acl_entry_t "sys/types.h;sys/acl.h" HAVE_ACL_ENTRY_T)
CHECK_TYPE_EXISTS(acl_permset_t "sys/types.h;sys/acl.h" HAVE_ACL_PERMSET_T)
CHECK_TYPE_EXISTS(acl_tag_t "sys/types.h;sys/acl.h" HAVE_ACL_TAG_T)
# 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>
IF(HAVE_ACL AND HAVE_FACL)
CHECK_TYPE_EXISTS(aclent_t "sys/acl.h" HAVE_ACLENT_T)
IF(HAVE_ACLENT_T)
CHECK_SYMBOL_EXISTS(GETACL "sys/acl.h" HAVE_DECL_GETACL)
CHECK_SYMBOL_EXISTS(GETACLCNT "sys/acl.h" HAVE_DECL_GETACLCNT)
CHECK_SYMBOL_EXISTS(SETACL "sys/acl.h" HAVE_DECL_SETACL)
IF(HAVE_DECL_GETACL AND
HAVE_DECL_GETACLCNT AND
HAVE_DECL_SETACL)
SET(ARCHIVE_ACL_SUNOS TRUE)
ENDIF()
CHECK_TYPE_EXISTS(ace_t "sys/acl.h" HAVE_ACE_T)
IF(HAVE_ACE_T)
CHECK_SYMBOL_EXISTS(ACE_GETACL "sys/acl.h" HAVE_DECL_ACE_GETACL)
CHECK_SYMBOL_EXISTS(ACE_GETACLCNT "sys/acl.h" HAVE_DECL_ACE_GETACLCNT)
CHECK_SYMBOL_EXISTS(ACE_SETACL "sys/acl.h" HAVE_DECL_ACE_SETACL)
IF(HAVE_DECL_ACE_GETACL AND
HAVE_DECL_ACE_GETACLCNT AND
HAVE_DECL_ACE_SETACL)
SET(ARCHIVE_ACL_SUNOS_NFS4 TRUE)
ENDIF()
ENDIF(HAVE_ACE_T)
ENDIF(HAVE_ACLENT_T)
ENDIF(HAVE_ACL AND HAVE_FACL)
IF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND HAVE_ACL_TAG_T)
CHECK_FUNCTION_EXISTS_GLIBC(acl_add_perm HAVE_ACL_ADD_PERM)
CHECK_FUNCTION_EXISTS_GLIBC(acl_clear_perms HAVE_ACL_CLEAR_PERMS)
CHECK_FUNCTION_EXISTS_GLIBC(acl_create_entry HAVE_ACL_CREATE_ENTRY)
CHECK_FUNCTION_EXISTS_GLIBC(acl_delete_def_file HAVE_ACL_DELETE_DEF_FILE)
CHECK_FUNCTION_EXISTS_GLIBC(acl_free HAVE_ACL_FREE)
CHECK_FUNCTION_EXISTS_GLIBC(acl_get_entry HAVE_ACL_GET_ENTRY)
CHECK_FUNCTION_EXISTS_GLIBC(acl_get_fd HAVE_ACL_GET_FD)
CHECK_FUNCTION_EXISTS_GLIBC(acl_get_file HAVE_ACL_GET_FILE)
CHECK_FUNCTION_EXISTS_GLIBC(acl_get_permset HAVE_ACL_GET_PERMSET)
CHECK_FUNCTION_EXISTS_GLIBC(acl_get_qualifier HAVE_ACL_GET_QUALIFIER)
CHECK_FUNCTION_EXISTS_GLIBC(acl_get_tag_type HAVE_ACL_GET_TAG_TYPE)
CHECK_FUNCTION_EXISTS_GLIBC(acl_init HAVE_ACL_INIT)
CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd HAVE_ACL_SET_FD)
CHECK_FUNCTION_EXISTS_GLIBC(acl_set_file HAVE_ACL_SET_FILE)
CHECK_FUNCTION_EXISTS_GLIBC(acl_set_qualifier HAVE_ACL_SET_QUALIFIER)
CHECK_FUNCTION_EXISTS_GLIBC(acl_set_tag_type HAVE_ACL_SET_TAG_TYPE)
IF(HAVE_ACL_ADD_PERM AND
HAVE_ACL_CLEAR_PERMS AND
HAVE_ACL_CREATE_ENTRY AND
HAVE_ACL_DELETE_DEF_FILE AND
HAVE_ACL_FREE AND
HAVE_ACL_GET_ENTRY AND
HAVE_ACL_GET_FD AND
HAVE_ACL_GET_FILE AND
HAVE_ACL_GET_PERMSET AND
HAVE_ACL_GET_QUALIFIER AND
HAVE_ACL_GET_TAG_TYPE AND
HAVE_ACL_INIT AND
HAVE_ACL_SET_FD AND
HAVE_ACL_SET_FILE AND
HAVE_ACL_SET_QUALIFIER AND
HAVE_ACL_SET_TAG_TYPE)
SET(HAVE_POSIX_ACL_FUNCS 1)
ENDIF()
CHECK_FUNCTION_EXISTS_GLIBC(acl_get_perm HAVE_ACL_GET_PERM)
IF(HAVE_POSIX_ACL_FUNCS AND HAVE_ACL_LIBACL_H AND HAVE_LIBACL AND
HAVE_ACL_GET_PERM)
SET(ARCHIVE_ACL_LIBACL TRUE)
ELSE()
CHECK_FUNCTION_EXISTS(acl_add_flag_np HAVE_ACL_ADD_FLAG_NP)
CHECK_FUNCTION_EXISTS(acl_clear_flags_np HAVE_ACL_CLEAR_FLAGS_NP)
CHECK_FUNCTION_EXISTS(acl_get_brand_np HAVE_ACL_GET_BRAND_NP)
CHECK_FUNCTION_EXISTS(acl_get_entry_type_np HAVE_ACL_GET_ENTRY_TYPE_NP)
CHECK_FUNCTION_EXISTS(acl_get_flag_np HAVE_ACL_GET_FLAG_NP)
CHECK_FUNCTION_EXISTS(acl_get_flagset_np HAVE_ACL_GET_FLAGSET_NP)
CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP)
CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP)
CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP)
CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP)
CHECK_FUNCTION_EXISTS(acl_set_entry_type_np HAVE_ACL_SET_ENTRY_TYPE_NP)
CHECK_FUNCTION_EXISTS(acl_set_fd_np HAVE_ACL_SET_FD_NP)
CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP)
CHECK_FUNCTION_EXISTS(mbr_gid_to_uuid HAVE_MBR_GID_TO_UUID)
CHECK_FUNCTION_EXISTS(mbr_uid_to_uuid HAVE_MBR_UID_TO_UUID)
CHECK_FUNCTION_EXISTS(mbr_uuid_to_id HAVE_MBR_UUID_TO_ID)
CHECK_C_SOURCE_COMPILES("#include <sys/types.h>
#include <sys/acl.h>
int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED)
int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_DECL_ACL_TYPE_EXTENDED)
CHECK_C_SOURCE_COMPILES("#include <sys/types.h>
#include <sys/acl.h>
int main(void) { return ACL_SYNCHRONIZE; }" HAVE_DECL_ACL_SYNCHRONIZE)
CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "sys/acl.h" HAVE_DECL_ACL_TYPE_NFS4)
CHECK_SYMBOL_EXISTS(ACL_USER "sys/acl.h" HAVE_DECL_ACL_USER)
IF(HAVE_POSIX_ACL_FUNCS AND
HAVE_ACL_GET_FD_NP AND
HAVE_ACL_GET_PERM_NP AND
NOT HAVE_ACL_GET_PERM AND
HAVE_ACL_SET_FD_NP)
IF(HAVE_DECL_ACL_USER)
SET(ARCHIVE_ACL_FREEBSD TRUE)
IF(HAVE_DECL_ACL_TYPE_NFS4 AND
HAVE_ACL_ADD_FLAG_NP AND
HAVE_ACL_CLEAR_FLAGS_NP AND
HAVE_ACL_GET_BRAND_NP AND
HAVE_ACL_GET_ENTRY_TYPE_NP AND
HAVE_ACL_GET_FLAGSET_NP AND
HAVE_ACL_SET_ENTRY_TYPE_NP)
SET(ARCHIVE_ACL_FREEBSD_NFS4 TRUE)
ENDIF()
ELSEIF(HAVE_DECL_ACL_TYPE_EXTENDED AND
HAVE_MEMBERSHIP_H AND
HAVE_ACL_ADD_FLAG_NP AND
HAVE_ACL_CLEAR_FLAGS_NP AND
HAVE_ACL_GET_FLAGSET_NP AND
HAVE_ACL_GET_LINK_NP AND
HAVE_ACL_SET_LINK_NP AND
HAVE_MBR_UID_TO_UUID AND
HAVE_MBR_GID_TO_UUID AND
HAVE_MBR_UUID_TO_ID)
SET(ARCHIVE_ACL_DARWIN TRUE)
ENDIF()
ENDIF()
ENDIF()
ENDIF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND
HAVE_ACL_TAG_T)
# Richacl
CHECK_LIBRARY_EXISTS(richacl "richacl_get_file" "" HAVE_LIBRICHACL)
IF(HAVE_LIBRICHACL)
SET(CMAKE_REQUIRED_LIBRARIES "richacl")
FIND_LIBRARY(RICHACL_LIBRARY NAMES richacl)
LIST(APPEND ADDITIONAL_LIBS ${RICHACL_LIBRARY})
ENDIF(HAVE_LIBRICHACL)
CHECK_STRUCT_HAS_MEMBER("struct richace" e_type "sys/richacl.h"
HAVE_STRUCT_RICHACE)
CHECK_STRUCT_HAS_MEMBER("struct richacl" a_flags "sys/richacl.h"
HAVE_STRUCT_RICHACL)
IF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE)
CHECK_FUNCTION_EXISTS_GLIBC(richacl_alloc HAVE_RICHACL_ALLOC)
CHECK_FUNCTION_EXISTS_GLIBC(richacl_equiv_mode HAVE_RICHACL_EQUIV_MODE)
CHECK_FUNCTION_EXISTS_GLIBC(richacl_free HAVE_RICHACL_FREE)
CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_fd HAVE_RICHACL_GET_FD)
CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_file HAVE_RICHACL_GET_FILE)
CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_fd HAVE_RICHACL_SET_FD)
CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_file HAVE_RICHACL_SET_FILE)
IF(HAVE_RICHACL_ALLOC AND
HAVE_RICHACL_EQUIV_MODE AND
HAVE_RICHACL_FREE AND
HAVE_RICHACL_GET_FD AND
HAVE_RICHACL_GET_FILE AND
HAVE_RICHACL_SET_FD AND
HAVE_RICHACL_SET_FILE)
SET(ARCHIVE_ACL_LIBRICHACL TRUE)
ENDIF()
ENDIF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE)
IF(ARCHIVE_ACL_DARWIN)
MESSAGE(STATUS "ACL support: Darwin (limited NFSv4)")
ELSEIF(ARCHIVE_ACL_FREEBSD_NFS4)
MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e and NFSv4)")
ELSEIF(ARCHIVE_ACL_FREEBSD)
MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e)")
ELSEIF(ARCHIVE_ACL_LIBACL OR ARCHIVE_ACL_LIBRICHACL)
IF(ARCHIVE_ACL_LIBACL AND ARCHIVE_ACL_LIBRICHACL)
MESSAGE(STATUS "ACL support: libacl (POSIX.1e) + librichacl (NFSv4)")
ELSEIF(ARCHIVE_ACL_LIBRICHACL)
MESSAGE(STATUS "ACL support: librichacl (NFSv4)")
ELSE()
MESSAGE(STATUS "ACL support: libacl (POSIX.1e)")
ENDIF()
ELSEIF(ARCHIVE_ACL_SUNOS_NFS4)
MESSAGE(STATUS "ACL support: Solaris (POSIX.1e and NFSv4)")
ELSEIF(ARCHIVE_ACL_SUNOS)
MESSAGE(STATUS "ACL support: Solaris (POSIX.1e)")
ELSE()
MESSAGE(STATUS "ACL support: none")
ENDIF()
# 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.
SET(HAVE_ACL_CREATE_ENTRY FALSE)
SET(HAVE_ACL_GET_LINK FALSE)
SET(HAVE_ACL_GET_LINK_NP FALSE)
SET(HAVE_ACL_GET_PERM FALSE)
SET(HAVE_ACL_GET_PERM_NP FALSE)
SET(HAVE_ACL_INIT FALSE)
SET(HAVE_ACL_LIB FALSE)
SET(HAVE_ACL_PERMSET_T FALSE)
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)
SET(ARCHIVE_ACL_DARWIN FALSE)
SET(ARCHIVE_ACL_FREEBSD FALSE)
SET(ARCHIVE_ACL_FREEBSD_NFS4 FALSE)
SET(ARCHIVE_ACL_LIBACL FALSE)
SET(ARCHIVE_ACL_SUNOS FALSE)
SET(ARCHIVE_ACL_SUNOS_NFS4 FALSE)
ENDIF(ENABLE_ACL)
#
+83 -9
View File
@@ -182,6 +182,27 @@ typedef uint64_t uintmax_t;
/* Define ZLIB_WINAPI if zlib was built on Visual Studio. */
#cmakedefine ZLIB_WINAPI 1
/* Darwin ACL support */
#cmakedefine ARCHIVE_ACL_DARWIN 1
/* FreeBSD ACL support */
#cmakedefine ARCHIVE_ACL_FREEBSD 1
/* FreeBSD NFSv4 ACL support */
#cmakedefine ARCHIVE_ACL_FREEBSD_NFS4 1
/* Linux POSIX.1e ACL support via libacl */
#cmakedefine ARCHIVE_ACL_LIBACL 1
/* Linux NFSv4 ACL support via librichacl */
#cmakedefine ARCHIVE_ACL_LIBRICHACL 1
/* Solaris ACL support */
#cmakedefine ARCHIVE_ACL_SUNOS 1
/* Solaris NFSv4 ACL support */
#cmakedefine ARCHIVE_ACL_SUNOS_NFS4 1
/* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */
#cmakedefine ARCHIVE_CRYPTO_MD5_LIBC 1
@@ -284,6 +305,18 @@ typedef uint64_t uintmax_t;
/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */
#cmakedefine ARCHIVE_CRYPTO_SHA512_WIN 1
/* AIX xattr support */
#cmakedefine ARCHIVE_XATTR_AIX 1
/* Darwin xattr support */
#cmakedefine ARCHIVE_XATTR_DARWIN 1
/* FreeBSD xattr support */
#cmakedefine ARCHIVE_XATTR_FREEBSD 1
/* Linux xattr support */
#cmakedefine ARCHIVE_XATTR_LINUX 1
/* Version number of bsdcpio */
#cmakedefine BSDCPIO_VERSION_STRING "${BSDCPIO_VERSION_STRING}"
@@ -329,15 +362,6 @@ 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
/* Define to 1 if you have the `arc4random_buf' function. */
#cmakedefine HAVE_ARC4RANDOM_BUF 1
@@ -374,6 +398,34 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `cygwin_conv_path' function. */
#cmakedefine HAVE_CYGWIN_CONV_PATH 1
/* Define to 1 if you have the declaration of `ACE_GETACL', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_ACE_GETACL 1
/* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_ACE_GETACLCNT 1
/* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_ACE_SETACL 1
/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if
you don't. */
#cmakedefine HAVE_DECL_ACL_SYNCHRONIZE 1
/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if
you don't. */
#cmakedefine HAVE_DECL_ACL_TYPE_EXTENDED 1
/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_ACL_TYPE_NFS4 1
/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_ACL_USER 1
/* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_INT32_MAX 1
@@ -398,6 +450,10 @@ typedef uint64_t uintmax_t;
don't. */
#cmakedefine HAVE_DECL_INTMAX_MIN 1
/* Define to 1 if you have the declaration of `SETACL', and to 0 if you don't.
*/
#cmakedefine HAVE_DECL_SETACL 1
/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_SIZE_MAX 1
@@ -422,6 +478,10 @@ typedef uint64_t uintmax_t;
don't. */
#cmakedefine HAVE_DECL_UINTMAX_MAX 1
/* Define to 1 if you have the declaration of `XATTR_NOFOLLOW', and to 0 if
you don't. */
#cmakedefine HAVE_DECL_XATTR_NOFOLLOW 1
/* Define to 1 if you have the <direct.h> header file. */
#cmakedefine HAVE_DIRECT_H 1
@@ -471,6 +531,14 @@ typedef uint64_t uintmax_t;
/* Define to 1 if EXTATTR_NAMESPACE_USER is defined in sys/extattr.h. */
#cmakedefine HAVE_DECL_EXTATTR_NAMESPACE_USER 1
/* Define to 1 if you have the declaration of `GETACL', and to 0 if you don't.
*/
#cmakedefine HAVE_DECL_GETACL 1
/* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_GETACLCNT 1
/* Define to 1 if you have the `fchdir' function. */
#cmakedefine HAVE_FCHDIR 1
@@ -748,6 +816,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `mbrtowc' function. */
#cmakedefine HAVE_MBRTOWC 1
/* Define to 1 if you have the <membership.h> header file. */
#cmakedefine HAVE_MEMBERSHIP_H 1
/* Define to 1 if you have the `memmove' function. */
#cmakedefine HAVE_MEMMOVE 1
@@ -985,6 +1056,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <sys/poll.h> header file. */
#cmakedefine HAVE_SYS_POLL_H 1
/* Define to 1 if you have the <sys/richacl.h> header file. */
#cmakedefine HAVE_SYS_RICHACL_H 1
/* Define to 1 if you have the <sys/select.h> header file. */
#cmakedefine HAVE_SYS_SELECT_H 1
+1 -1
View File
@@ -1 +1 @@
3003001
3003002
@@ -14,6 +14,7 @@ SET(include_HEADERS
# Sources and private headers
SET(libarchive_SOURCES
archive_acl.c
archive_acl_private.h
archive_check_magic.c
archive_cmdline.c
archive_cmdline_private.h
@@ -47,6 +48,8 @@ SET(libarchive_SOURCES
archive_pathmatch.c
archive_pathmatch.h
archive_platform.h
archive_platform_acl.h
archive_platform_xattr.h
archive_ppmd_private.h
archive_ppmd7.c
archive_ppmd7_private.h
@@ -106,9 +109,9 @@ SET(libarchive_SOURCES
archive_string_composition.h
archive_string_sprintf.c
archive_util.c
archive_version_details.c
archive_virtual.c
archive_write.c
archive_write_disk_acl.c
archive_write_disk_posix.c
archive_write_disk_private.h
archive_write_disk_set_standard_lookup.c
@@ -210,6 +213,16 @@ IF(WIN32 AND NOT CYGWIN)
LIST(APPEND libarchive_SOURCES filter_fork_windows.c)
ENDIF(WIN32 AND NOT CYGWIN)
IF(ARCHIVE_ACL_DARWIN)
LIST(APPEND libarchive_SOURCES archive_disk_acl_darwin.c)
ELSEIF(ARCHIVE_ACL_FREEBSD)
LIST(APPEND libarchive_SOURCES archive_disk_acl_freebsd.c)
ELSEIF(ARCHIVE_ACL_LIBACL)
LIST(APPEND libarchive_SOURCES archive_disk_acl_linux.c)
ELSEIF(ARCHIVE_ACL_SUNOS)
LIST(APPEND libarchive_SOURCES archive_disk_acl_sunos.c)
ENDIF()
# CMake needs just one static "cmlibarchive" library.
ADD_LIBRARY(cmlibarchive STATIC ${libarchive_SOURCES} ${include_HEADERS})
TARGET_LINK_LIBRARIES(cmlibarchive ${ADDITIONAL_LIBS})
+2 -2
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 3003001
#define ARCHIVE_VERSION_NUMBER 3003002
#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.3.1"
#define ARCHIVE_VERSION_ONLY_STRING "3.3.2"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -62,7 +62,7 @@ errmsg(const char *m)
}
}
static void
static __LA_DEAD void
diediedie(void)
{
#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
@@ -0,0 +1,559 @@
/*-
* Copyright (c) 2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
#if ARCHIVE_ACL_DARWIN
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#if HAVE_MEMBERSHIP_H
#include <membership.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_ACL_H
#define _ACL_PRIVATE /* For debugging */
#include <sys/acl.h>
#endif
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_read_disk_private.h"
#include "archive_write_disk_private.h"
typedef struct {
const int a_perm; /* Libarchive permission or flag */
const int p_perm; /* Platform permission or flag */
} acl_perm_map_t;
static const acl_perm_map_t acl_nfs4_perm_map[] = {
{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},
#if HAVE_DECL_ACL_SYNCHRONIZE
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
};
static const int acl_nfs4_perm_map_size =
(int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
static const acl_perm_map_t acl_nfs4_flag_map[] = {
{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}
};
static const int acl_nfs4_flag_map_size =
(int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
static int translate_guid(struct archive *a, acl_entry_t acl_entry,
int *ae_id, int *ae_tag, const char **ae_name)
{
void *q;
uid_t ugid;
int r, idtype;
q = acl_get_qualifier(acl_entry);
if (q == NULL)
return (1);
r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
if (r != 0) {
acl_free(q);
return (1);
}
if (idtype == ID_TYPE_UID) {
*ae_tag = ARCHIVE_ENTRY_ACL_USER;
*ae_id = ugid;
*ae_name = archive_read_disk_uname(a, *ae_id);
} else if (idtype == ID_TYPE_GID) {
*ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
*ae_id = ugid;
*ae_name = archive_read_disk_gname(a, *ae_id);
} else
r = 1;
acl_free(q);
return (r);
}
static void
add_trivial_nfs4_acl(struct archive_entry *entry)
{
mode_t mode;
int i;
const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
ARCHIVE_ENTRY_ACL_APPEND_DATA;
const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE;
const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_READ_ACL |
ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
ARCHIVE_ENTRY_ACL_WRITE_ACL |
ARCHIVE_ENTRY_ACL_WRITE_OWNER;
struct {
const int type;
const int tag;
int permset;
} tacl_entry[] = {
{ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
{ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
{ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0},
{ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset},
{ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset},
{ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset}
};
mode = archive_entry_mode(entry);
/* Permissions for everyone@ */
if (mode & 0004)
tacl_entry[5].permset |= rperm;
if (mode & 0002)
tacl_entry[5].permset |= wperm;
if (mode & 0001)
tacl_entry[5].permset |= eperm;
/* Permissions for group@ */
if (mode & 0040)
tacl_entry[4].permset |= rperm;
else if (mode & 0004)
tacl_entry[2].permset |= rperm;
if (mode & 0020)
tacl_entry[4].permset |= wperm;
else if (mode & 0002)
tacl_entry[2].permset |= wperm;
if (mode & 0010)
tacl_entry[4].permset |= eperm;
else if (mode & 0001)
tacl_entry[2].permset |= eperm;
/* Permissions for owner@ */
if (mode & 0400) {
tacl_entry[3].permset |= rperm;
if (!(mode & 0040) && (mode & 0004))
tacl_entry[0].permset |= rperm;
} else if ((mode & 0040) || (mode & 0004))
tacl_entry[1].permset |= rperm;
if (mode & 0200) {
tacl_entry[3].permset |= wperm;
if (!(mode & 0020) && (mode & 0002))
tacl_entry[0].permset |= wperm;
} else if ((mode & 0020) || (mode & 0002))
tacl_entry[1].permset |= wperm;
if (mode & 0100) {
tacl_entry[3].permset |= eperm;
if (!(mode & 0010) && (mode & 0001))
tacl_entry[0].permset |= eperm;
} else if ((mode & 0010) || (mode & 0001))
tacl_entry[1].permset |= eperm;
for (i = 0; i < 6; i++) {
if (tacl_entry[i].permset != 0) {
archive_entry_acl_add_entry(entry,
tacl_entry[i].type, tacl_entry[i].permset,
tacl_entry[i].tag, -1, NULL);
}
}
return;
}
static int
translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl)
{
acl_tag_t acl_tag;
acl_flagset_t acl_flagset;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
int i, entry_acl_type;
int r, s, ae_id, ae_tag, ae_perm;
const char *ae_name;
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
if (s == -1) {
archive_set_error(&a->archive, errno,
"Failed to get first ACL entry");
return (ARCHIVE_WARN);
}
while (s == 0) {
ae_id = -1;
ae_name = NULL;
ae_perm = 0;
if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
archive_set_error(&a->archive, errno,
"Failed to get ACL tag type");
return (ARCHIVE_WARN);
}
switch (acl_tag) {
case ACL_EXTENDED_ALLOW:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
r = translate_guid(&a->archive, acl_entry,
&ae_id, &ae_tag, &ae_name);
break;
case ACL_EXTENDED_DENY:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
r = translate_guid(&a->archive, acl_entry,
&ae_id, &ae_tag, &ae_name);
break;
default:
/* Skip types that libarchive can't support. */
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
continue;
}
/* Skip if translate_guid() above failed */
if (r != 0) {
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
continue;
}
/*
* Libarchive stores "flag" (NFSv4 inheritance bits)
* in the ae_perm bitmap.
*
* acl_get_flagset_np() fails with non-NFSv4 ACLs
*/
if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
archive_set_error(&a->archive, errno,
"Failed to get flagset from a NFSv4 ACL entry");
return (ARCHIVE_WARN);
}
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
r = acl_get_flag_np(acl_flagset,
acl_nfs4_flag_map[i].p_perm);
if (r == -1) {
archive_set_error(&a->archive, errno,
"Failed to check flag in a NFSv4 "
"ACL flagset");
return (ARCHIVE_WARN);
} else if (r)
ae_perm |= acl_nfs4_flag_map[i].a_perm;
}
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
archive_set_error(&a->archive, errno,
"Failed to get ACL permission set");
return (ARCHIVE_WARN);
}
for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
/*
* acl_get_perm() is spelled differently on different
* platforms; see above.
*/
r = acl_get_perm_np(acl_permset,
acl_nfs4_perm_map[i].p_perm);
if (r == -1) {
archive_set_error(&a->archive, errno,
"Failed to check permission in an ACL "
"permission set");
return (ARCHIVE_WARN);
} else if (r)
ae_perm |= acl_nfs4_perm_map[i].a_perm;
}
#if !HAVE_DECL_ACL_SYNCHRONIZE
/* On Mac OS X without ACL_SYNCHRONIZE assume it is set */
ae_perm |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
#endif
archive_entry_acl_add_entry(entry, entry_acl_type,
ae_perm, ae_tag,
ae_id, ae_name);
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
}
return (ARCHIVE_OK);
}
static int
set_acl(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl,
int ae_requested_type, const char *tname)
{
acl_t acl;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
acl_flagset_t acl_flagset;
int ret;
int ae_type, ae_permset, ae_tag, ae_id;
uuid_t ae_uuid;
uid_t ae_uid;
gid_t ae_gid;
const char *ae_name;
int entries;
int i;
ret = ARCHIVE_OK;
entries = archive_acl_reset(abstract_acl, ae_requested_type);
if (entries == 0)
return (ARCHIVE_OK);
if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
errno = ENOENT;
archive_set_error(a, errno, "Unsupported ACL type");
return (ARCHIVE_FAILED);
}
acl = acl_init(entries);
if (acl == (acl_t)NULL) {
archive_set_error(a, errno,
"Failed to initialize ACL working storage");
return (ARCHIVE_FAILED);
}
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
/*
* 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;
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;
}
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;
}
switch (ae_tag) {
case ARCHIVE_ENTRY_ACL_USER:
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
if (mbr_uid_to_uuid(ae_uid, ae_uuid) != 0)
continue;
if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
continue;
break;
case ARCHIVE_ENTRY_ACL_GROUP:
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
if (mbr_gid_to_uuid(ae_gid, ae_uuid) != 0)
continue;
if (acl_set_qualifier(acl_entry, &ae_uuid) != 0)
continue;
break;
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unsupported ACL tag");
ret = ARCHIVE_FAILED;
goto exit_free;
}
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;
}
for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
if (ae_permset & acl_nfs4_perm_map[i].a_perm) {
if (acl_add_perm(acl_permset,
acl_nfs4_perm_map[i].p_perm) != 0) {
archive_set_error(a, errno,
"Failed to add ACL permission");
ret = ARCHIVE_FAILED;
goto exit_free;
}
}
}
/*
* 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;
}
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
if (acl_add_flag_np(acl_flagset,
acl_nfs4_flag_map[i].p_perm) != 0) {
archive_set_error(a, errno,
"Failed to add flag to "
"NFSv4 ACL flagset");
ret = ARCHIVE_FAILED;
goto exit_free;
}
}
}
}
if (fd >= 0) {
if (acl_set_fd_np(fd, acl, ACL_TYPE_EXTENDED) == 0)
ret = ARCHIVE_OK;
else {
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno,
"Failed to set acl on fd: %s", tname);
ret = ARCHIVE_WARN;
}
}
} else if (acl_set_link_np(name, ACL_TYPE_EXTENDED, acl) != 0) {
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno, "Failed to set acl: %s",
tname);
ret = ARCHIVE_WARN;
}
}
exit_free:
acl_free(acl);
return (ret);
}
int
archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
const char *accpath;
acl_t acl;
int r;
accpath = NULL;
if (*fd < 0) {
accpath = archive_read_disk_entry_setup_path(a, entry, fd);
if (accpath == NULL)
return (ARCHIVE_WARN);
}
archive_entry_acl_clear(entry);
acl = NULL;
if (*fd >= 0)
acl = acl_get_fd_np(*fd, ACL_TYPE_EXTENDED);
else if (!a->follow_symlinks)
acl = acl_get_link_np(accpath, ACL_TYPE_EXTENDED);
else
acl = acl_get_file(accpath, ACL_TYPE_EXTENDED);
if (acl != NULL) {
r = translate_acl(a, entry, acl);
acl_free(acl);
acl = NULL;
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate NFSv4 ACLs");
}
/*
* Because Mac OS doesn't support owner@, group@ and everyone@
* ACLs we need to add NFSv4 ACLs mirroring the file mode to
* the archive entry. Otherwise extraction on non-Mac platforms
* would lead to an invalid file mode.
*/
if ((archive_entry_acl_types(entry) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
add_trivial_nfs4_acl(entry);
return (r);
}
return (ARCHIVE_OK);
}
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl, __LA_MODE_T mode)
{
int ret = ARCHIVE_OK;
(void)mode; /* UNUSED */
if ((archive_acl_types(abstract_acl) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
ret = set_acl(a, fd, name, abstract_acl,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
}
return (ret);
}
#endif /* ARCHIVE_ACL_DARWIN */
@@ -0,0 +1,700 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
* Copyright (c) 2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
#if ARCHIVE_ACL_FREEBSD
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_ACL_H
#define _ACL_PRIVATE /* For debugging */
#include <sys/acl.h>
#endif
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_read_disk_private.h"
#include "archive_write_disk_private.h"
typedef struct {
const int a_perm; /* Libarchive permission or flag */
const int p_perm; /* Platform permission or flag */
} acl_perm_map_t;
static const acl_perm_map_t acl_posix_perm_map[] = {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
};
static const int acl_posix_perm_map_size =
(int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
#if ARCHIVE_ACL_FREEBSD_NFS4
static const acl_perm_map_t acl_nfs4_perm_map[] = {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
};
static const int acl_nfs4_perm_map_size =
(int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
static const acl_perm_map_t acl_nfs4_flag_map[] = {
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
{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}
};
static const int acl_nfs4_flag_map_size =
(int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */
static int
translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
{
#if ARCHIVE_ACL_FREEBSD_NFS4
int brand;
acl_flagset_t acl_flagset;
acl_entry_type_t acl_type;
#endif
acl_tag_t acl_tag;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
int i, entry_acl_type, perm_map_size;
const acl_perm_map_t *perm_map;
int r, s, ae_id, ae_tag, ae_perm;
void *q;
const char *ae_name;
#if ARCHIVE_ACL_FREEBSD_NFS4
// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
// Make sure the "brand" on this ACL is consistent
// with the default_entry_acl_type bits provided.
if (acl_get_brand_np(acl, &brand) != 0) {
archive_set_error(&a->archive, errno,
"Failed to read ACL brand");
return (ARCHIVE_WARN);
}
switch (brand) {
case ACL_BRAND_POSIX:
switch (default_entry_acl_type) {
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Invalid ACL entry type for POSIX.1e ACL");
return (ARCHIVE_WARN);
}
break;
case ACL_BRAND_NFS4:
if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Invalid ACL entry type for NFSv4 ACL");
return (ARCHIVE_WARN);
}
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unknown ACL brand");
return (ARCHIVE_WARN);
}
#endif
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
if (s == -1) {
archive_set_error(&a->archive, errno,
"Failed to get first ACL entry");
return (ARCHIVE_WARN);
}
while (s == 1) {
ae_id = -1;
ae_name = NULL;
ae_perm = 0;
if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
archive_set_error(&a->archive, errno,
"Failed to get ACL tag type");
return (ARCHIVE_WARN);
}
switch (acl_tag) {
case ACL_USER:
q = acl_get_qualifier(acl_entry);
if (q != NULL) {
ae_id = (int)*(uid_t *)q;
acl_free(q);
ae_name = archive_read_disk_uname(&a->archive,
ae_id);
}
ae_tag = ARCHIVE_ENTRY_ACL_USER;
break;
case ACL_GROUP:
q = acl_get_qualifier(acl_entry);
if (q != NULL) {
ae_id = (int)*(gid_t *)q;
acl_free(q);
ae_name = archive_read_disk_gname(&a->archive,
ae_id);
}
ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
break;
case ACL_MASK:
ae_tag = ARCHIVE_ENTRY_ACL_MASK;
break;
case ACL_USER_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
break;
case ACL_GROUP_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
break;
case ACL_OTHER:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
break;
#if ARCHIVE_ACL_FREEBSD_NFS4
case ACL_EVERYONE:
ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
break;
#endif
default:
/* Skip types that libarchive can't support. */
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
continue;
}
// XXX acl_type maps to allow/deny/audit/YYYY bits
entry_acl_type = default_entry_acl_type;
#if ARCHIVE_ACL_FREEBSD_NFS4
if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
/*
* acl_get_entry_type_np() fails with non-NFSv4 ACLs
*/
if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
archive_set_error(&a->archive, errno, "Failed "
"to get ACL type from a NFSv4 ACL entry");
return (ARCHIVE_WARN);
}
switch (acl_type) {
case ACL_ENTRY_TYPE_ALLOW:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
break;
case ACL_ENTRY_TYPE_DENY:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
break;
case ACL_ENTRY_TYPE_AUDIT:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
break;
case ACL_ENTRY_TYPE_ALARM:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
break;
default:
archive_set_error(&a->archive, errno,
"Invalid NFSv4 ACL entry type");
return (ARCHIVE_WARN);
}
/*
* Libarchive stores "flag" (NFSv4 inheritance bits)
* in the ae_perm bitmap.
*
* acl_get_flagset_np() fails with non-NFSv4 ACLs
*/
if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
archive_set_error(&a->archive, errno,
"Failed to get flagset from a NFSv4 "
"ACL entry");
return (ARCHIVE_WARN);
}
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
r = acl_get_flag_np(acl_flagset,
acl_nfs4_flag_map[i].p_perm);
if (r == -1) {
archive_set_error(&a->archive, errno,
"Failed to check flag in a NFSv4 "
"ACL flagset");
return (ARCHIVE_WARN);
} else if (r)
ae_perm |= acl_nfs4_flag_map[i].a_perm;
}
}
#endif
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
archive_set_error(&a->archive, errno,
"Failed to get ACL permission set");
return (ARCHIVE_WARN);
}
#if ARCHIVE_ACL_FREEBSD_NFS4
if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
perm_map_size = acl_nfs4_perm_map_size;
perm_map = acl_nfs4_perm_map;
} else {
#endif
perm_map_size = acl_posix_perm_map_size;
perm_map = acl_posix_perm_map;
#if ARCHIVE_ACL_FREEBSD_NFS4
}
#endif
for (i = 0; i < perm_map_size; ++i) {
r = acl_get_perm_np(acl_permset, perm_map[i].p_perm);
if (r == -1) {
archive_set_error(&a->archive, errno,
"Failed to check permission in an ACL "
"permission set");
return (ARCHIVE_WARN);
} else if (r)
ae_perm |= perm_map[i].a_perm;
}
archive_entry_acl_add_entry(entry, entry_acl_type,
ae_perm, ae_tag,
ae_id, ae_name);
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
if (s == -1) {
archive_set_error(&a->archive, errno,
"Failed to get next ACL entry");
return (ARCHIVE_WARN);
}
}
return (ARCHIVE_OK);
}
static int
set_acl(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl,
int ae_requested_type, const char *tname)
{
int acl_type = 0;
acl_t acl;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
#if ARCHIVE_ACL_FREEBSD_NFS4
acl_flagset_t acl_flagset;
int r;
#endif
int ret;
int ae_type, ae_permset, ae_tag, ae_id;
int perm_map_size;
const acl_perm_map_t *perm_map;
uid_t ae_uid;
gid_t ae_gid;
const char *ae_name;
int entries;
int i;
ret = ARCHIVE_OK;
entries = archive_acl_reset(abstract_acl, ae_requested_type);
if (entries == 0)
return (ARCHIVE_OK);
switch (ae_requested_type) {
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
acl_type = ACL_TYPE_ACCESS;
break;
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
acl_type = ACL_TYPE_DEFAULT;
break;
#if ARCHIVE_ACL_FREEBSD_NFS4
case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
acl_type = ACL_TYPE_NFS4;
break;
#endif
default:
errno = ENOENT;
archive_set_error(a, errno, "Unsupported ACL type");
return (ARCHIVE_FAILED);
}
acl = acl_init(entries);
if (acl == (acl_t)NULL) {
archive_set_error(a, errno,
"Failed to initialize ACL working storage");
return (ARCHIVE_FAILED);
}
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
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;
}
switch (ae_tag) {
case ARCHIVE_ENTRY_ACL_USER:
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
acl_set_tag_type(acl_entry, ACL_USER);
acl_set_qualifier(acl_entry, &ae_uid);
break;
case ARCHIVE_ENTRY_ACL_GROUP:
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
acl_set_tag_type(acl_entry, ACL_GROUP);
acl_set_qualifier(acl_entry, &ae_gid);
break;
case ARCHIVE_ENTRY_ACL_USER_OBJ:
acl_set_tag_type(acl_entry, ACL_USER_OBJ);
break;
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
break;
case ARCHIVE_ENTRY_ACL_MASK:
acl_set_tag_type(acl_entry, ACL_MASK);
break;
case ARCHIVE_ENTRY_ACL_OTHER:
acl_set_tag_type(acl_entry, ACL_OTHER);
break;
#if ARCHIVE_ACL_FREEBSD_NFS4
case ARCHIVE_ENTRY_ACL_EVERYONE:
acl_set_tag_type(acl_entry, ACL_EVERYONE);
break;
#endif
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unsupported ACL tag");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#if ARCHIVE_ACL_FREEBSD_NFS4
r = 0;
switch (ae_type) {
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;
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unsupported ACL entry type");
ret = ARCHIVE_FAILED;
goto exit_free;
}
if (r != 0) {
archive_set_error(a, errno,
"Failed to set ACL entry type");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#endif
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;
}
#if ARCHIVE_ACL_FREEBSD_NFS4
if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
perm_map_size = acl_nfs4_perm_map_size;
perm_map = acl_nfs4_perm_map;
} else {
#endif
perm_map_size = acl_posix_perm_map_size;
perm_map = acl_posix_perm_map;
#if ARCHIVE_ACL_FREEBSD_NFS4
}
#endif
for (i = 0; i < perm_map_size; ++i) {
if (ae_permset & perm_map[i].a_perm) {
if (acl_add_perm(acl_permset,
perm_map[i].p_perm) != 0) {
archive_set_error(a, errno,
"Failed to add ACL permission");
ret = ARCHIVE_FAILED;
goto exit_free;
}
}
}
#if ARCHIVE_ACL_FREEBSD_NFS4
if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
/*
* 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;
}
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
if (acl_add_flag_np(acl_flagset,
acl_nfs4_flag_map[i].p_perm) != 0) {
archive_set_error(a, errno,
"Failed to add flag to "
"NFSv4 ACL flagset");
ret = ARCHIVE_FAILED;
goto exit_free;
}
}
}
}
#endif
}
/* Try restoring the ACL through 'fd' if we can. */
if (fd >= 0) {
if (acl_set_fd_np(fd, acl, acl_type) == 0)
ret = ARCHIVE_OK;
else {
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno,
"Failed to set acl on fd: %s", tname);
ret = ARCHIVE_WARN;
}
}
}
#if HAVE_ACL_SET_LINK_NP
else if (acl_set_link_np(name, acl_type, acl) != 0)
#else
/* FreeBSD older than 8.0 */
else 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 acl: %s",
tname);
ret = ARCHIVE_WARN;
}
}
exit_free:
acl_free(acl);
return (ret);
}
int
archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
const char *accpath;
acl_t acl;
int r;
accpath = NULL;
if (*fd < 0) {
accpath = archive_read_disk_entry_setup_path(a, entry, fd);
if (accpath == NULL)
return (ARCHIVE_WARN);
}
archive_entry_acl_clear(entry);
acl = NULL;
#if ARCHIVE_ACL_FREEBSD_NFS4
/* Try NFSv4 ACL first. */
if (*fd >= 0)
acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
else if (!a->follow_symlinks)
acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
else
acl = acl_get_file(accpath, ACL_TYPE_NFS4);
/* Ignore "trivial" ACLs that just mirror the file mode. */
if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
acl_free(acl);
acl = NULL;
return (ARCHIVE_OK);
}
if (acl != NULL) {
r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
acl_free(acl);
acl = NULL;
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate NFSv4 ACLs");
}
return (r);
}
#endif
/* Retrieve access ACL from file. */
if (*fd >= 0)
acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS);
#if HAVE_ACL_GET_LINK_NP
else if (!a->follow_symlinks)
acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
#else
else if ((!a->follow_symlinks)
&& (archive_entry_filetype(entry) == AE_IFLNK))
/* We can't get the ACL of a symlink, so we assume it can't
have one. */
acl = NULL;
#endif
else
acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
#if HAVE_ACL_IS_TRIVIAL_NP
/* Ignore "trivial" ACLs that just mirror the file mode. */
if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
acl_free(acl);
acl = NULL;
}
#endif
if (acl != NULL) {
r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
acl_free(acl);
acl = NULL;
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate access ACLs");
return (r);
}
}
/* Only directories can have default ACLs. */
if (S_ISDIR(archive_entry_mode(entry))) {
if (*fd >= 0)
acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
else
acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
if (acl != NULL) {
r = translate_acl(a, entry, acl,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
acl_free(acl);
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate default ACLs");
return (r);
}
}
}
return (ARCHIVE_OK);
}
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl, __LA_MODE_T mode)
{
int ret = ARCHIVE_OK;
(void)mode; /* UNUSED */
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
ret = set_acl(a, fd, name, abstract_acl,
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,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
/* Simultaneous POSIX.1e and NFSv4 is not supported */
return (ret);
}
#if ARCHIVE_ACL_FREEBSD_NFS4
else if ((archive_acl_types(abstract_acl) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
ret = set_acl(a, fd, name, abstract_acl,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
}
#endif
return (ret);
}
#endif /* ARCHIVE_ACL_FREEBSD */
@@ -0,0 +1,743 @@
/*-
* Copyright (c) 2003-2009 Tim Kientzle
* Copyright (c) 2010-2012 Michihiro NAKAJIMA
* Copyright (c) 2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if HAVE_ACL_LIBACL_H
#include <acl/libacl.h>
#endif
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
#ifdef HAVE_SYS_RICHACL_H
#include <sys/richacl.h>
#endif
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_read_disk_private.h"
#include "archive_write_disk_private.h"
typedef struct {
const int a_perm; /* Libarchive permission or flag */
const int p_perm; /* Platform permission or flag */
} acl_perm_map_t;
#if ARCHIVE_ACL_LIBACL
static const acl_perm_map_t acl_posix_perm_map[] = {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
};
static const int acl_posix_perm_map_size =
(int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
#endif /* ARCHIVE_ACL_LIBACL */
#if ARCHIVE_ACL_LIBRICHACL
static const acl_perm_map_t acl_nfs4_perm_map[] = {
{ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE},
{ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA},
{ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE},
{ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE}
};
static const int acl_nfs4_perm_map_size =
(int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
static const acl_perm_map_t acl_nfs4_flag_map[] = {
{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE}
};
static const int acl_nfs4_flag_map_size =
(int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
#endif /* ARCHIVE_ACL_LIBRICHACL */
#if ARCHIVE_ACL_LIBACL
/*
* Translate POSIX.1e ACLs into libarchive internal structure
*/
static int
translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
{
acl_tag_t acl_tag;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
int i, entry_acl_type;
int r, s, ae_id, ae_tag, ae_perm;
void *q;
const char *ae_name;
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
if (s == -1) {
archive_set_error(&a->archive, errno,
"Failed to get first ACL entry");
return (ARCHIVE_WARN);
}
while (s == 1) {
ae_id = -1;
ae_name = NULL;
ae_perm = 0;
if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
archive_set_error(&a->archive, errno,
"Failed to get ACL tag type");
return (ARCHIVE_WARN);
}
switch (acl_tag) {
case ACL_USER:
q = acl_get_qualifier(acl_entry);
if (q != NULL) {
ae_id = (int)*(uid_t *)q;
acl_free(q);
ae_name = archive_read_disk_uname(&a->archive,
ae_id);
}
ae_tag = ARCHIVE_ENTRY_ACL_USER;
break;
case ACL_GROUP:
q = acl_get_qualifier(acl_entry);
if (q != NULL) {
ae_id = (int)*(gid_t *)q;
acl_free(q);
ae_name = archive_read_disk_gname(&a->archive,
ae_id);
}
ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
break;
case ACL_MASK:
ae_tag = ARCHIVE_ENTRY_ACL_MASK;
break;
case ACL_USER_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
break;
case ACL_GROUP_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
break;
case ACL_OTHER:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
break;
default:
/* Skip types that libarchive can't support. */
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
continue;
}
// XXX acl_type maps to allow/deny/audit/YYYY bits
entry_acl_type = default_entry_acl_type;
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
archive_set_error(&a->archive, errno,
"Failed to get ACL permission set");
return (ARCHIVE_WARN);
}
for (i = 0; i < acl_posix_perm_map_size; ++i) {
r = acl_get_perm(acl_permset,
acl_posix_perm_map[i].p_perm);
if (r == -1) {
archive_set_error(&a->archive, errno,
"Failed to check permission in an ACL "
"permission set");
return (ARCHIVE_WARN);
} else if (r)
ae_perm |= acl_posix_perm_map[i].a_perm;
}
archive_entry_acl_add_entry(entry, entry_acl_type,
ae_perm, ae_tag,
ae_id, ae_name);
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
if (s == -1) {
archive_set_error(&a->archive, errno,
"Failed to get next ACL entry");
return (ARCHIVE_WARN);
}
}
return (ARCHIVE_OK);
}
#endif /* ARCHIVE_ACL_LIBACL */
#if ARCHIVE_ACL_LIBRICHACL
/*
* Translate RichACL into libarchive internal ACL
*/
static int
translate_richacl(struct archive_read_disk *a, struct archive_entry *entry,
struct richacl *richacl)
{
int ae_id, ae_tag, ae_perm;
int entry_acl_type, i;
const char *ae_name;
struct richace *richace;
richacl_for_each_entry(richace, richacl) {
ae_name = NULL;
ae_tag = 0;
ae_perm = 0;
ae_id = -1;
switch (richace->e_type) {
case RICHACE_ACCESS_ALLOWED_ACE_TYPE:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
break;
case RICHACE_ACCESS_DENIED_ACE_TYPE:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
break;
default: /* Unknown entry type, skip */
continue;
}
/* Unsupported */
if (richace->e_flags & RICHACE_UNMAPPED_WHO)
continue;
if (richace->e_flags & RICHACE_SPECIAL_WHO) {
switch (richace->e_id) {
case RICHACE_OWNER_SPECIAL_ID:
ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
break;
case RICHACE_GROUP_SPECIAL_ID:
ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
break;
case RICHACE_EVERYONE_SPECIAL_ID:
ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
break;
default: /* Unknown special ID type */
continue;
}
} else {
ae_id = richace->e_id;
if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {
ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
ae_name = archive_read_disk_gname(&a->archive,
(gid_t)(richace->e_id));
} else {
ae_tag = ARCHIVE_ENTRY_ACL_USER;
ae_name = archive_read_disk_uname(&a->archive,
(uid_t)(richace->e_id));
}
}
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
if ((richace->e_flags &
acl_nfs4_flag_map[i].p_perm) != 0)
ae_perm |= acl_nfs4_flag_map[i].a_perm;
}
for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
if ((richace->e_mask &
acl_nfs4_perm_map[i].p_perm) != 0)
ae_perm |=
acl_nfs4_perm_map[i].a_perm;
}
archive_entry_acl_add_entry(entry, entry_acl_type,
ae_perm, ae_tag, ae_id, ae_name);
}
return (ARCHIVE_OK);
}
#endif /* ARCHIVE_ACL_LIBRICHACL */
#if ARCHIVE_ACL_LIBRICHACL
static int
_richacl_mode_to_mask(short mode)
{
int mask = 0;
if (mode & S_IROTH)
mask |= RICHACE_POSIX_MODE_READ;
if (mode & S_IWOTH)
mask |= RICHACE_POSIX_MODE_WRITE;
if (mode & S_IXOTH)
mask |= RICHACE_POSIX_MODE_EXEC;
return (mask);
}
static void
_richacl_mode_to_masks(struct richacl *richacl, __LA_MODE_T mode)
{
richacl->a_owner_mask = _richacl_mode_to_mask((mode & 0700) >> 6);
richacl->a_group_mask = _richacl_mode_to_mask((mode & 0070) >> 3);
richacl->a_other_mask = _richacl_mode_to_mask(mode & 0007);
}
#endif /* ARCHIVE_ACL_LIBRICHACL */
#if ARCHIVE_ACL_LIBRICHACL
static int
set_richacl(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl, __LA_MODE_T mode,
int ae_requested_type, const char *tname)
{
int ae_type, ae_permset, ae_tag, ae_id;
uid_t ae_uid;
gid_t ae_gid;
const char *ae_name;
int entries;
int i;
int ret;
int e = 0;
struct richacl *richacl = NULL;
struct richace *richace;
ret = ARCHIVE_OK;
entries = archive_acl_reset(abstract_acl, ae_requested_type);
if (entries == 0)
return (ARCHIVE_OK);
if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
errno = ENOENT;
archive_set_error(a, errno, "Unsupported ACL type");
return (ARCHIVE_FAILED);
}
richacl = richacl_alloc(entries);
if (richacl == NULL) {
archive_set_error(a, errno,
"Failed to initialize RichACL working storage");
return (ARCHIVE_FAILED);
}
e = 0;
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
richace = &(richacl->a_entries[e]);
richace->e_flags = 0;
richace->e_mask = 0;
switch (ae_tag) {
case ARCHIVE_ENTRY_ACL_USER:
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
richace->e_id = ae_uid;
break;
case ARCHIVE_ENTRY_ACL_GROUP:
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
richace->e_id = ae_gid;
richace->e_flags |= RICHACE_IDENTIFIER_GROUP;
break;
case ARCHIVE_ENTRY_ACL_USER_OBJ:
richace->e_flags |= RICHACE_SPECIAL_WHO;
richace->e_id = RICHACE_OWNER_SPECIAL_ID;
break;
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
richace->e_flags |= RICHACE_SPECIAL_WHO;
richace->e_id = RICHACE_GROUP_SPECIAL_ID;
break;
case ARCHIVE_ENTRY_ACL_EVERYONE:
richace->e_flags |= RICHACE_SPECIAL_WHO;
richace->e_id = RICHACE_EVERYONE_SPECIAL_ID;
break;
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unsupported ACL tag");
ret = ARCHIVE_FAILED;
goto exit_free;
}
switch (ae_type) {
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
richace->e_type =
RICHACE_ACCESS_ALLOWED_ACE_TYPE;
break;
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
richace->e_type =
RICHACE_ACCESS_DENIED_ACE_TYPE;
break;
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
break;
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unsupported ACL entry type");
ret = ARCHIVE_FAILED;
goto exit_free;
}
for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
if (ae_permset & acl_nfs4_perm_map[i].a_perm)
richace->e_mask |= acl_nfs4_perm_map[i].p_perm;
}
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
if (ae_permset &
acl_nfs4_flag_map[i].a_perm)
richace->e_flags |= acl_nfs4_flag_map[i].p_perm;
}
e++;
}
/* Fill RichACL masks */
_richacl_mode_to_masks(richacl, mode);
if (fd >= 0) {
if (richacl_set_fd(fd, richacl) == 0)
ret = ARCHIVE_OK;
else {
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno,
"Failed to set richacl on fd: %s", tname);
ret = ARCHIVE_WARN;
}
}
} else if (richacl_set_file(name, richacl) != 0) {
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno, "Failed to set richacl: %s",
tname);
ret = ARCHIVE_WARN;
}
}
exit_free:
richacl_free(richacl);
return (ret);
}
#endif /* ARCHIVE_ACL_RICHACL */
#if ARCHIVE_ACL_LIBACL
static int
set_acl(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl,
int ae_requested_type, const char *tname)
{
int acl_type = 0;
int ae_type, ae_permset, ae_tag, ae_id;
uid_t ae_uid;
gid_t ae_gid;
const char *ae_name;
int entries;
int i;
int ret;
acl_t acl = NULL;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
ret = ARCHIVE_OK;
entries = archive_acl_reset(abstract_acl, ae_requested_type);
if (entries == 0)
return (ARCHIVE_OK);
switch (ae_requested_type) {
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
acl_type = ACL_TYPE_ACCESS;
break;
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
acl_type = ACL_TYPE_DEFAULT;
break;
default:
errno = ENOENT;
archive_set_error(a, errno, "Unsupported ACL type");
return (ARCHIVE_FAILED);
}
acl = acl_init(entries);
if (acl == (acl_t)NULL) {
archive_set_error(a, errno,
"Failed to initialize ACL working storage");
return (ARCHIVE_FAILED);
}
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
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;
}
switch (ae_tag) {
case ARCHIVE_ENTRY_ACL_USER:
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
acl_set_tag_type(acl_entry, ACL_USER);
acl_set_qualifier(acl_entry, &ae_uid);
break;
case ARCHIVE_ENTRY_ACL_GROUP:
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
acl_set_tag_type(acl_entry, ACL_GROUP);
acl_set_qualifier(acl_entry, &ae_gid);
break;
case ARCHIVE_ENTRY_ACL_USER_OBJ:
acl_set_tag_type(acl_entry, ACL_USER_OBJ);
break;
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
break;
case ARCHIVE_ENTRY_ACL_MASK:
acl_set_tag_type(acl_entry, ACL_MASK);
break;
case ARCHIVE_ENTRY_ACL_OTHER:
acl_set_tag_type(acl_entry, ACL_OTHER);
break;
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unsupported ACL tag");
ret = ARCHIVE_FAILED;
goto exit_free;
}
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;
}
for (i = 0; i < acl_posix_perm_map_size; ++i) {
if (ae_permset & acl_posix_perm_map[i].a_perm) {
if (acl_add_perm(acl_permset,
acl_posix_perm_map[i].p_perm) != 0) {
archive_set_error(a, errno,
"Failed to add ACL permission");
ret = ARCHIVE_FAILED;
goto exit_free;
}
}
}
}
if (fd >= 0 && ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
if (acl_set_fd(fd, acl) == 0)
ret = ARCHIVE_OK;
else {
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno,
"Failed to set acl on fd: %s", tname);
ret = ARCHIVE_WARN;
}
}
} else if (acl_set_file(name, acl_type, acl) != 0) {
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno, "Failed to set acl: %s",
tname);
ret = ARCHIVE_WARN;
}
}
exit_free:
acl_free(acl);
return (ret);
}
#endif /* ARCHIVE_ACL_LIBACL */
int
archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
const char *accpath;
int r;
#if ARCHIVE_ACL_LIBACL
acl_t acl;
#endif
#if ARCHIVE_ACL_LIBRICHACL
struct richacl *richacl;
mode_t mode;
#endif
accpath = NULL;
r = ARCHIVE_OK;
/* For default ACLs we need reachable accpath */
if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) {
accpath = archive_read_disk_entry_setup_path(a, entry, fd);
if (accpath == NULL)
return (ARCHIVE_WARN);
}
archive_entry_acl_clear(entry);
#if ARCHIVE_ACL_LIBACL
acl = NULL;
#endif
#if ARCHIVE_ACL_LIBRICHACL
richacl = NULL;
#endif
#if ARCHIVE_ACL_LIBRICHACL
/* Try NFSv4 ACL first. */
if (*fd >= 0)
richacl = richacl_get_fd(*fd);
else if ((!a->follow_symlinks)
&& (archive_entry_filetype(entry) == AE_IFLNK))
/* We can't get the ACL of a symlink, so we assume it can't
have one */
richacl = NULL;
else
richacl = richacl_get_file(accpath);
/* Ignore "trivial" ACLs that just mirror the file mode. */
if (richacl != NULL) {
mode = archive_entry_mode(entry);
if (richacl_equiv_mode(richacl, &mode) == 0) {
richacl_free(richacl);
richacl = NULL;
return (ARCHIVE_OK);
}
}
if (richacl != NULL) {
r = translate_richacl(a, entry, richacl);
richacl_free(richacl);
richacl = NULL;
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate NFSv4 ACLs");
}
return (r);
}
#endif /* ARCHIVE_ACL_LIBRICHACL */
#if ARCHIVE_ACL_LIBACL
/* Retrieve access ACL from file. */
if (*fd >= 0)
acl = acl_get_fd(*fd);
else if ((!a->follow_symlinks)
&& (archive_entry_filetype(entry) == AE_IFLNK))
/* We can't get the ACL of a symlink, so we assume it can't
have one. */
acl = NULL;
else
acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
if (acl != NULL) {
r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
acl_free(acl);
acl = NULL;
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate access ACLs");
return (r);
}
}
/* Only directories can have default ACLs. */
if (S_ISDIR(archive_entry_mode(entry))) {
acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
if (acl != NULL) {
r = translate_acl(a, entry, acl,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
acl_free(acl);
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate default ACLs");
return (r);
}
}
}
#endif /* ARCHIVE_ACL_LIBACL */
return (r);
}
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl, __LA_MODE_T mode)
{
int ret = ARCHIVE_OK;
#if !ARCHIVE_ACL_LIBRICHACL
(void)mode; /* UNUSED */
#endif
#if ARCHIVE_ACL_LIBRICHACL
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
ret = set_richacl(a, fd, name, abstract_acl, mode,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
}
#if ARCHIVE_ACL_LIBACL
else
#endif
#endif /* ARCHIVE_ACL_LIBRICHACL */
#if ARCHIVE_ACL_LIBACL
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
ret = set_acl(a, fd, name, abstract_acl,
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,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
}
#endif /* ARCHIVE_ACL_LIBACL */
return (ret);
}
#endif /* ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL */
@@ -0,0 +1,821 @@
/*-
* Copyright (c) 2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
#if ARCHIVE_ACL_SUNOS
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_ACL_H
#define _ACL_PRIVATE /* For debugging */
#include <sys/acl.h>
#endif
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_read_disk_private.h"
#include "archive_write_disk_private.h"
typedef struct {
const int a_perm; /* Libarchive permission or flag */
const int p_perm; /* Platform permission or flag */
} acl_perm_map_t;
static const acl_perm_map_t acl_posix_perm_map[] = {
{ARCHIVE_ENTRY_ACL_EXECUTE, S_IXOTH },
{ARCHIVE_ENTRY_ACL_WRITE, S_IWOTH },
{ARCHIVE_ENTRY_ACL_READ, S_IROTH }
};
static const int acl_posix_perm_map_size =
(int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
#if ARCHIVE_ACL_SUNOS_NFS4
static const acl_perm_map_t acl_nfs4_perm_map[] = {
{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}
};
static const int acl_nfs4_perm_map_size =
(int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
static const acl_perm_map_t acl_nfs4_flag_map[] = {
{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},
#ifdef ACE_INHERITED_ACE
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
#endif
};
const int acl_nfs4_flag_map_size =
(int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
static void *
sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
{
int cnt, cntcmd;
size_t size;
void *aclp;
if (cmd == GETACL) {
cntcmd = GETACLCNT;
size = sizeof(aclent_t);
}
#if ARCHIVE_ACL_SUNOS_NFS4
else if (cmd == ACE_GETACL) {
cntcmd = ACE_GETACLCNT;
size = sizeof(ace_t);
}
#endif
else {
errno = EINVAL;
*aclcnt = -1;
return (NULL);
}
aclp = NULL;
cnt = -2;
while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) {
if (path != NULL)
cnt = acl(path, cntcmd, 0, NULL);
else
cnt = facl(fd, cntcmd, 0, NULL);
if (cnt > 0) {
if (aclp == NULL)
aclp = malloc(cnt * size);
else
aclp = realloc(NULL, cnt * size);
if (aclp != NULL) {
if (path != NULL)
cnt = acl(path, cmd, cnt, aclp);
else
cnt = facl(fd, cmd, cnt, aclp);
}
} else {
if (aclp != NULL) {
free(aclp);
aclp = NULL;
}
break;
}
}
*aclcnt = cnt;
return (aclp);
}
/*
* Check if acl is trivial
* This is a FreeBSD acl_is_trivial_np() implementation for Solaris
*/
static int
sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4,
int is_dir, int *trivialp)
{
#if ARCHIVE_ACL_SUNOS_NFS4
int i, p;
const uint32_t rperm = ACE_READ_DATA;
const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
const uint32_t eperm = ACE_EXECUTE;
const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
ACE_READ_ACL | ACE_SYNCHRONIZE;
const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
ace_t *ace;
ace_t tace[6];
#endif
if (aclp == NULL || trivialp == NULL)
return (-1);
*trivialp = 0;
/*
* POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
* FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
* including mask.
*/
if (!is_nfs4) {
if (aclcnt == 4)
*trivialp = 1;
return (0);
}
#if ARCHIVE_ACL_SUNOS_NFS4
/*
* Continue with checking NFSv4 ACLs
*
* Create list of trivial ace's to be compared
*/
/* owner@ allow pre */
tace[0].a_flags = ACE_OWNER;
tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
tace[0].a_access_mask = 0;
/* owner@ deny */
tace[1].a_flags = ACE_OWNER;
tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
tace[1].a_access_mask = 0;
/* group@ deny */
tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
tace[2].a_access_mask = 0;
/* owner@ allow */
tace[3].a_flags = ACE_OWNER;
tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
tace[3].a_access_mask = ownset;
/* group@ allow */
tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
tace[4].a_access_mask = pubset;
/* everyone@ allow */
tace[5].a_flags = ACE_EVERYONE;
tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
tace[5].a_access_mask = pubset;
/* Permissions for everyone@ */
if (mode & 0004)
tace[5].a_access_mask |= rperm;
if (mode & 0002)
tace[5].a_access_mask |= wperm;
if (mode & 0001)
tace[5].a_access_mask |= eperm;
/* Permissions for group@ */
if (mode & 0040)
tace[4].a_access_mask |= rperm;
else if (mode & 0004)
tace[2].a_access_mask |= rperm;
if (mode & 0020)
tace[4].a_access_mask |= wperm;
else if (mode & 0002)
tace[2].a_access_mask |= wperm;
if (mode & 0010)
tace[4].a_access_mask |= eperm;
else if (mode & 0001)
tace[2].a_access_mask |= eperm;
/* Permissions for owner@ */
if (mode & 0400) {
tace[3].a_access_mask |= rperm;
if (!(mode & 0040) && (mode & 0004))
tace[0].a_access_mask |= rperm;
} else if ((mode & 0040) || (mode & 0004))
tace[1].a_access_mask |= rperm;
if (mode & 0200) {
tace[3].a_access_mask |= wperm;
if (!(mode & 0020) && (mode & 0002))
tace[0].a_access_mask |= wperm;
} else if ((mode & 0020) || (mode & 0002))
tace[1].a_access_mask |= wperm;
if (mode & 0100) {
tace[3].a_access_mask |= eperm;
if (!(mode & 0010) && (mode & 0001))
tace[0].a_access_mask |= eperm;
} else if ((mode & 0010) || (mode & 0001))
tace[1].a_access_mask |= eperm;
/* Check if the acl count matches */
p = 3;
for (i = 0; i < 3; i++) {
if (tace[i].a_access_mask != 0)
p++;
}
if (aclcnt != p)
return (0);
p = 0;
for (i = 0; i < 6; i++) {
if (tace[i].a_access_mask != 0) {
ace = &((ace_t *)aclp)[p];
/*
* Illumos added ACE_DELETE_CHILD to write perms for
* directories. We have to check against that, too.
*/
if (ace->a_flags != tace[i].a_flags ||
ace->a_type != tace[i].a_type ||
(ace->a_access_mask != tace[i].a_access_mask &&
(!is_dir || (tace[i].a_access_mask & wperm) == 0 ||
ace->a_access_mask !=
(tace[i].a_access_mask | ACE_DELETE_CHILD))))
return (0);
p++;
}
}
*trivialp = 1;
#else /* !ARCHIVE_ACL_SUNOS_NFS4 */
(void)is_dir; /* UNUSED */
(void)aclp; /* UNUSED */
#endif /* !ARCHIVE_ACL_SUNOS_NFS4 */
return (0);
}
/*
* Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
*/
static int
translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, void *aclp, int aclcnt,
int default_entry_acl_type)
{
int e, i;
int ae_id, ae_tag, ae_perm;
int entry_acl_type;
const char *ae_name;
aclent_t *aclent;
#if ARCHIVE_ACL_SUNOS_NFS4
ace_t *ace;
#endif
if (aclcnt <= 0)
return (ARCHIVE_OK);
for (e = 0; e < aclcnt; e++) {
ae_name = NULL;
ae_tag = 0;
ae_perm = 0;
#if ARCHIVE_ACL_SUNOS_NFS4
if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
ace = &((ace_t *)aclp)[e];
ae_id = ace->a_who;
switch(ace->a_type) {
case ACE_ACCESS_ALLOWED_ACE_TYPE:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
break;
case ACE_ACCESS_DENIED_ACE_TYPE:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
break;
case ACE_SYSTEM_AUDIT_ACE_TYPE:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
break;
case ACE_SYSTEM_ALARM_ACE_TYPE:
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
break;
default:
/* Unknown entry type, skip */
continue;
}
if ((ace->a_flags & ACE_OWNER) != 0)
ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
else if ((ace->a_flags & ACE_GROUP) != 0)
ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
else if ((ace->a_flags & ACE_EVERYONE) != 0)
ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
ae_name = archive_read_disk_gname(&a->archive,
ae_id);
} else {
ae_tag = ARCHIVE_ENTRY_ACL_USER;
ae_name = archive_read_disk_uname(&a->archive,
ae_id);
}
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
if ((ace->a_flags &
acl_nfs4_flag_map[i].p_perm) != 0)
ae_perm |= acl_nfs4_flag_map[i].a_perm;
}
for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
if ((ace->a_access_mask &
acl_nfs4_perm_map[i].p_perm) != 0)
ae_perm |= acl_nfs4_perm_map[i].a_perm;
}
} else
#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
aclent = &((aclent_t *)aclp)[e];
if ((aclent->a_type & ACL_DEFAULT) != 0)
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
else
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
ae_id = aclent->a_id;
switch(aclent->a_type) {
case DEF_USER:
case USER:
ae_name = archive_read_disk_uname(&a->archive,
ae_id);
ae_tag = ARCHIVE_ENTRY_ACL_USER;
break;
case DEF_GROUP:
case GROUP:
ae_name = archive_read_disk_gname(&a->archive,
ae_id);
ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
break;
case DEF_CLASS_OBJ:
case CLASS_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_MASK;
break;
case DEF_USER_OBJ:
case USER_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
break;
case DEF_GROUP_OBJ:
case GROUP_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
break;
case DEF_OTHER_OBJ:
case OTHER_OBJ:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
break;
default:
/* Unknown tag type, skip */
continue;
}
for (i = 0; i < acl_posix_perm_map_size; ++i) {
if ((aclent->a_perm &
acl_posix_perm_map[i].p_perm) != 0)
ae_perm |= acl_posix_perm_map[i].a_perm;
}
} else
return (ARCHIVE_WARN);
archive_entry_acl_add_entry(entry, entry_acl_type,
ae_perm, ae_tag, ae_id, ae_name);
}
return (ARCHIVE_OK);
}
static int
set_acl(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl,
int ae_requested_type, const char *tname)
{
aclent_t *aclent;
#if ARCHIVE_ACL_SUNOS_NFS4
ace_t *ace;
#endif
int cmd, e, r;
void *aclp;
int ret;
int ae_type, ae_permset, ae_tag, ae_id;
int perm_map_size;
const acl_perm_map_t *perm_map;
uid_t ae_uid;
gid_t ae_gid;
const char *ae_name;
int entries;
int i;
ret = ARCHIVE_OK;
entries = archive_acl_reset(abstract_acl, ae_requested_type);
if (entries == 0)
return (ARCHIVE_OK);
switch (ae_requested_type) {
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
cmd = SETACL;
aclp = malloc(entries * sizeof(aclent_t));
break;
#if ARCHIVE_ACL_SUNOS_NFS4
case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
cmd = ACE_SETACL;
aclp = malloc(entries * sizeof(ace_t));
break;
#endif
default:
errno = ENOENT;
archive_set_error(a, errno, "Unsupported ACL type");
return (ARCHIVE_FAILED);
}
if (aclp == NULL) {
archive_set_error(a, errno,
"Can't allocate memory for acl buffer");
return (ARCHIVE_FAILED);
}
e = 0;
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
aclent = NULL;
#if ARCHIVE_ACL_SUNOS_NFS4
ace = NULL;
#endif
if (cmd == SETACL) {
aclent = &((aclent_t *)aclp)[e];
aclent->a_id = -1;
aclent->a_type = 0;
aclent->a_perm = 0;
}
#if ARCHIVE_ACL_SUNOS_NFS4
else { /* cmd == ACE_SETACL */
ace = &((ace_t *)aclp)[e];
ace->a_who = -1;
ace->a_access_mask = 0;
ace->a_flags = 0;
}
#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
switch (ae_tag) {
case ARCHIVE_ENTRY_ACL_USER:
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
if (aclent != NULL) {
aclent->a_id = ae_uid;
aclent->a_type |= USER;
}
#if ARCHIVE_ACL_SUNOS_NFS4
else {
ace->a_who = ae_uid;
}
#endif
break;
case ARCHIVE_ENTRY_ACL_GROUP:
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
if (aclent != NULL) {
aclent->a_id = ae_gid;
aclent->a_type |= GROUP;
}
#if ARCHIVE_ACL_SUNOS_NFS4
else {
ace->a_who = ae_gid;
ace->a_flags |= ACE_IDENTIFIER_GROUP;
}
#endif
break;
case ARCHIVE_ENTRY_ACL_USER_OBJ:
if (aclent != NULL)
aclent->a_type |= USER_OBJ;
#if ARCHIVE_ACL_SUNOS_NFS4
else {
ace->a_flags |= ACE_OWNER;
}
#endif
break;
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
if (aclent != NULL)
aclent->a_type |= GROUP_OBJ;
#if ARCHIVE_ACL_SUNOS_NFS4
else {
ace->a_flags |= ACE_GROUP;
ace->a_flags |= ACE_IDENTIFIER_GROUP;
}
#endif
break;
case ARCHIVE_ENTRY_ACL_MASK:
if (aclent != NULL)
aclent->a_type |= CLASS_OBJ;
break;
case ARCHIVE_ENTRY_ACL_OTHER:
if (aclent != NULL)
aclent->a_type |= OTHER_OBJ;
break;
#if ARCHIVE_ACL_SUNOS_NFS4
case ARCHIVE_ENTRY_ACL_EVERYONE:
if (ace != NULL)
ace->a_flags |= ACE_EVERYONE;
break;
#endif
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unsupported ACL tag");
ret = ARCHIVE_FAILED;
goto exit_free;
}
r = 0;
switch (ae_type) {
#if ARCHIVE_ACL_SUNOS_NFS4
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
if (ace != NULL)
ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
else
r = -1;
break;
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
if (ace != NULL)
ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
else
r = -1;
break;
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
if (ace != NULL)
ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
else
r = -1;
break;
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
if (ace != NULL)
ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
else
r = -1;
break;
#endif
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;
default:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unsupported ACL entry type");
ret = ARCHIVE_FAILED;
goto exit_free;
}
if (r != 0) {
errno = EINVAL;
archive_set_error(a, errno,
"Failed to set ACL entry type");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#if ARCHIVE_ACL_SUNOS_NFS4
if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
perm_map_size = acl_nfs4_perm_map_size;
perm_map = acl_nfs4_perm_map;
} else {
#endif
perm_map_size = acl_posix_perm_map_size;
perm_map = acl_posix_perm_map;
#if ARCHIVE_ACL_SUNOS_NFS4
}
#endif
for (i = 0; i < perm_map_size; ++i) {
if (ae_permset & perm_map[i].a_perm) {
#if ARCHIVE_ACL_SUNOS_NFS4
if (ae_requested_type ==
ARCHIVE_ENTRY_ACL_TYPE_NFS4)
ace->a_access_mask |=
perm_map[i].p_perm;
else
#endif
aclent->a_perm |= perm_map[i].p_perm;
}
}
#if ARCHIVE_ACL_SUNOS_NFS4
if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
ace->a_flags |=
acl_nfs4_flag_map[i].p_perm;
}
}
}
#endif
e++;
}
/* Try restoring the ACL through 'fd' if we can. */
if (fd >= 0) {
if (facl(fd, cmd, entries, aclp) == 0)
ret = ARCHIVE_OK;
else {
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno,
"Failed to set acl on fd: %s", tname);
ret = ARCHIVE_WARN;
}
}
} else if (acl(name, cmd, entries, aclp) != 0) {
if (errno == EOPNOTSUPP) {
/* Filesystem doesn't support ACLs */
ret = ARCHIVE_OK;
} else {
archive_set_error(a, errno, "Failed to set acl: %s",
tname);
ret = ARCHIVE_WARN;
}
}
exit_free:
free(aclp);
return (ret);
}
int
archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
struct archive_entry *entry, int *fd)
{
const char *accpath;
void *aclp;
int aclcnt;
int r;
accpath = NULL;
if (*fd < 0) {
accpath = archive_read_disk_entry_setup_path(a, entry, fd);
if (accpath == NULL)
return (ARCHIVE_WARN);
}
archive_entry_acl_clear(entry);
aclp = NULL;
#if ARCHIVE_ACL_SUNOS_NFS4
if (*fd >= 0)
aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL);
else if ((!a->follow_symlinks)
&& (archive_entry_filetype(entry) == AE_IFLNK))
/* We can't get the ACL of a symlink, so we assume it can't
have one. */
aclp = NULL;
else
aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath);
if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)),
&r) == 0 && r == 1) {
free(aclp);
aclp = NULL;
return (ARCHIVE_OK);
}
if (aclp != NULL) {
r = translate_acl(a, entry, aclp, aclcnt,
ARCHIVE_ENTRY_ACL_TYPE_NFS4);
free(aclp);
aclp = NULL;
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate NFSv4 ACLs");
}
return (r);
}
#endif /* ARCHIVE_ACL_SUNOS_NFS4 */
/* Retrieve POSIX.1e ACLs from file. */
if (*fd >= 0)
aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL);
else if ((!a->follow_symlinks)
&& (archive_entry_filetype(entry) == AE_IFLNK))
/* We can't get the ACL of a symlink, so we assume it can't
have one. */
aclp = NULL;
else
aclp = sunacl_get(GETACL, &aclcnt, 0, accpath);
/* Ignore "trivial" ACLs that just mirror the file mode. */
if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)),
&r) == 0 && r == 1) {
free(aclp);
aclp = NULL;
}
if (aclp != NULL)
{
r = translate_acl(a, entry, aclp, aclcnt,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
free(aclp);
aclp = NULL;
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, errno,
"Couldn't translate access ACLs");
return (r);
}
}
return (ARCHIVE_OK);
}
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl, __LA_MODE_T mode)
{
int ret = ARCHIVE_OK;
(void)mode; /* UNUSED */
if ((archive_acl_types(abstract_acl)
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
/* Solaris writes POSIX.1e access and default ACLs together */
ret = set_acl(a, fd, name, abstract_acl,
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
/* Simultaneous POSIX.1e and NFSv4 is not supported */
return (ret);
}
#if ARCHIVE_ACL_SUNOS_NFS4
else if ((archive_acl_types(abstract_acl) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
ret = set_acl(a, fd, name, abstract_acl,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
}
#endif
return (ret);
}
#endif /* ARCHIVE_ACL_SUNOS */
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd Feburary 2, 2012
.Dd February 2, 2012
.Dt ARCHIVE_ENTRY 3
.Os
.Sh NAME
@@ -401,7 +401,7 @@ archive_entry_fflags_text(struct archive_entry *entry)
return (NULL);
}
int64_t
la_int64_t
archive_entry_gid(struct archive_entry *entry)
{
return (entry->ae_stat.aest_gid);
@@ -502,7 +502,7 @@ _archive_entry_hardlink_l(struct archive_entry *entry,
return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc));
}
int64_t
la_int64_t
archive_entry_ino(struct archive_entry *entry)
{
return (entry->ae_stat.aest_ino);
@@ -514,7 +514,7 @@ archive_entry_ino_is_set(struct archive_entry *entry)
return (entry->ae_set & AE_SET_INO);
}
int64_t
la_int64_t
archive_entry_ino64(struct archive_entry *entry)
{
return (entry->ae_stat.aest_ino);
@@ -627,7 +627,7 @@ archive_entry_rdevminor(struct archive_entry *entry)
return minor(entry->ae_stat.aest_rdev);
}
int64_t
la_int64_t
archive_entry_size(struct archive_entry *entry)
{
return (entry->ae_stat.aest_size);
@@ -715,7 +715,7 @@ _archive_entry_symlink_l(struct archive_entry *entry,
return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc));
}
int64_t
la_int64_t
archive_entry_uid(struct archive_entry *entry)
{
return (entry->ae_stat.aest_uid);
@@ -819,7 +819,7 @@ archive_entry_copy_fflags_text_w(struct archive_entry *entry,
}
void
archive_entry_set_gid(struct archive_entry *entry, int64_t g)
archive_entry_set_gid(struct archive_entry *entry, la_int64_t g)
{
entry->stat_valid = 0;
entry->ae_stat.aest_gid = g;
@@ -868,7 +868,7 @@ _archive_entry_copy_gname_l(struct archive_entry *entry,
}
void
archive_entry_set_ino(struct archive_entry *entry, int64_t ino)
archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
{
entry->stat_valid = 0;
entry->ae_set |= AE_SET_INO;
@@ -876,7 +876,7 @@ archive_entry_set_ino(struct archive_entry *entry, int64_t ino)
}
void
archive_entry_set_ino64(struct archive_entry *entry, int64_t ino)
archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
{
entry->stat_valid = 0;
entry->ae_set |= AE_SET_INO;
@@ -1209,7 +1209,7 @@ archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
}
void
archive_entry_set_size(struct archive_entry *entry, int64_t s)
archive_entry_set_size(struct archive_entry *entry, la_int64_t s)
{
entry->stat_valid = 0;
entry->ae_stat.aest_size = s;
@@ -1306,7 +1306,7 @@ _archive_entry_copy_symlink_l(struct archive_entry *entry,
}
void
archive_entry_set_uid(struct archive_entry *entry, int64_t u)
archive_entry_set_uid(struct archive_entry *entry, la_int64_t u)
{
entry->stat_valid = 0;
entry->ae_stat.aest_uid = u;
@@ -1638,7 +1638,7 @@ _archive_entry_acl_text_l(struct archive_entry *entry, int flags,
* SUCH DAMAGE.
*/
static struct flag {
static const struct flag {
const char *name;
const wchar_t *wname;
unsigned long set;
@@ -1708,6 +1708,9 @@ static struct flag {
#ifdef UF_COMPRESSED
{ "nocompressed",L"nocompressed", UF_COMPRESSED, 0 },
#endif
#ifdef UF_HIDDEN
{ "nohidden", L"nohidden", UF_HIDDEN, 0 },
#endif
#if defined(FS_UNRM_FL)
{ "nouunlink", L"nouunlink", FS_UNRM_FL, 0},
#elif defined(EXT2_UNRM_FL)
@@ -1840,7 +1843,7 @@ ae_fflagstostr(unsigned long bitset, unsigned long bitclear)
char *string, *dp;
const char *sp;
unsigned long bits;
struct flag *flag;
const struct flag *flag;
size_t length;
bits = bitset | bitclear;
@@ -1892,7 +1895,7 @@ static const char *
ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp)
{
const char *start, *end;
struct flag *flag;
const struct flag *flag;
unsigned long set, clear;
const char *failed;
@@ -1960,7 +1963,7 @@ static const wchar_t *
ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)
{
const wchar_t *start, *end;
struct flag *flag;
const struct flag *flag;
unsigned long set, clear;
const wchar_t *failed;
@@ -30,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
#define ARCHIVE_VERSION_NUMBER 3003001
#define ARCHIVE_VERSION_NUMBER 3003002
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -32,7 +32,7 @@
.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_from_text_w ,
.Nm archive_entry_acl_next ,
.Nm archive_entry_acl_next_w ,
.Nm archive_entry_acl_reset ,
@@ -267,7 +267,7 @@ 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.
Trigger alarm or audit on successful 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 )
@@ -279,7 +279,7 @@ 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. An archive enry cannot contain both POSIX.1e and NFSv4 ACL
are updated. An archive entry cannot contain both POSIX.1e and NFSv4 ACL
entries.
.Pp
.Fn archive_entry_acl_clear
@@ -303,7 +303,7 @@ for POSIX.1e ACLs and
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.
the three non-extended ACLs are added.
.Pp
.Fn archive_entry_acl_from_text
and
@@ -367,7 +367,7 @@ and
.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
string of ACL entries separated by newline. If the pointer
.Fa len_p
is not NULL, then the function shall return the length of the string
.Pq not including the NULL terminator
@@ -31,25 +31,25 @@
.Nm archive_entry_set_hardlink ,
.Nm archive_entry_copy_hardlink ,
.Nm archive_entry_copy_hardlink_w ,
.Nm archve_entry_update_hardlink_utf8 ,
.Nm archive_entry_update_hardlink_utf8 ,
.Nm archive_entry_set_link ,
.Nm archive_entry_copy_link ,
.Nm archive_entry_copy_link_w ,
.Nm archve_entry_update_link_utf8 ,
.Nm archive_entry_update_link_utf8 ,
.Nm archive_entry_pathname ,
.Nm archive_entry_pathname_w ,
.Nm archive_entry_set_pathname ,
.Nm archive_entry_copy_pathname ,
.Nm archive_entry_copy_pathname_w ,
.Nm archve_entry_update_pathname_utf8 ,
.Nm archive_entry_update_pathname_utf8 ,
.Nm archive_entry_sourcepath ,
.Nm archive_entry_copy_sourcepath ,
.Nm archive_entry_symlink,
.Nm archive_entry_symlink_w,
.Nm archive_entry_symlink ,
.Nm archive_entry_symlink_w ,
.Nm archive_entry_set_symlink ,
.Nm archive_entry_copy_symlink ,
.Nm archive_entry_copy_symlink_w ,
.Nm archve_entry_update_symlink_utf8
.Nm archive_entry_update_symlink_utf8
.Nd functions for manipulating path names in archive entry descriptions
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
@@ -34,8 +34,8 @@
.Nm archive_entry_perm ,
.Nm archive_entry_set_perm ,
.Nm archive_entry_strmode ,
.Nm archive_entry_uname
.Nm archive_entry_uname_w
.Nm archive_entry_uname ,
.Nm archive_entry_uname_w ,
.Nm archive_entry_set_uname ,
.Nm archive_entry_copy_uname ,
.Nm archive_entry_copy_uname_w ,
@@ -51,7 +51,7 @@ archive_entry_sparse_clear(struct archive_entry *entry)
void
archive_entry_sparse_add_entry(struct archive_entry *entry,
int64_t offset, int64_t length)
la_int64_t offset, la_int64_t length)
{
struct ae_sparse *sp;
@@ -135,7 +135,7 @@ archive_entry_sparse_reset(struct archive_entry * entry)
int
archive_entry_sparse_next(struct archive_entry * entry,
int64_t *offset, int64_t *length)
la_int64_t *offset, la_int64_t *length)
{
if (entry->sparse_p) {
*offset = entry->sparse_p->offset;
@@ -691,7 +691,7 @@ Convert(time_t Month, time_t Day, time_t Year,
time_t Hours, time_t Minutes, time_t Seconds,
time_t Timezone, enum DSTMODE DSTmode)
{
static int DaysInMonth[12] = {
signed char DaysInMonth[12] = {
31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
time_t Julian;
@@ -28,7 +28,7 @@
#include <openssl/hmac.h>
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memset */
static inline HMAC_CTX *HMAC_CTX_new(void)
@@ -280,7 +280,7 @@ pack_bsdos(int n, unsigned long numbers[], const char **error)
/* list of formats and pack functions */
/* this list must be sorted lexically */
static struct format {
static const struct format {
const char *name;
pack_t *pack;
} formats[] = {
@@ -147,32 +147,6 @@
#define INTMAX_MIN ((intmax_t)(~INTMAX_MAX))
#endif
/*
* If this platform has <sys/acl.h>, acl_create(), acl_init(),
* 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
#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
/*
* If we can't restore metadata using a file descriptor, then
* for compatibility's sake, close files before trying to restore metadata.
@@ -0,0 +1,49 @@
/*-
* Copyright (c) 2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
#ifndef ARCHIVE_PLATFORM_ACL_H_INCLUDED
#define ARCHIVE_PLATFORM_ACL_H_INCLUDED
/*
* Determine what ACL types are supported
*/
#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_SUNOS || ARCHIVE_ACL_LIBACL
#define ARCHIVE_ACL_POSIX1E 1
#endif
#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || \
ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
#define ARCHIVE_ACL_NFS4 1
#endif
#if ARCHIVE_ACL_POSIX1E || ARCHIVE_ACL_NFS4
#define ARCHIVE_ACL_SUPPORT 1
#endif
#endif /* ARCHIVE_PLATFORM_ACL_H_INCLUDED */
@@ -0,0 +1,41 @@
/*-
* Copyright (c) 2017 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
#ifndef ARCHIVE_PLATFORM_XATTR_H_INCLUDED
#define ARCHIVE_PLATFORM_XATTR_H_INCLUDED
/*
* Determine if we support extended attributes
*/
#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_FREEBSD || \
ARCHIVE_XATTR_AIX
#define ARCHIVE_XATTR_SUPPORT 1
#endif
#endif /* ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
@@ -221,7 +221,10 @@ arc4_stir(void)
/*
* Discard early keystream, as per recommendations in:
* "(Not So) Random Shuffles of RC4" by Ilya Mironov.
* As per the Network Operations Division, cryptographic requirements
* published on wikileaks on March 2017.
*/
for (i = 0; i < 3072; i++)
(void)arc4_getbyte();
arc4_count = 1600000;
@@ -881,7 +881,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
len = a->read_data_remaining;
if (len > s)
len = s;
memcpy(dest, a->read_data_block, len);
if (len)
memcpy(dest, a->read_data_block, len);
s -= len;
a->read_data_block += len;
a->read_data_remaining -= len;
@@ -24,11 +24,12 @@
.\"
.\" $FreeBSD$
.\"
.Dd December 30, 2016
.Dd April 3, 2017
.Dt ARCHIVE_READ_DISK 3
.Os
.Sh NAME
.Nm archive_read_disk_new ,
.Nm archive_read_disk_set_behavior ,
.Nm archive_read_disk_set_symlink_logical ,
.Nm archive_read_disk_set_symlink_physical ,
.Nm archive_read_disk_set_symlink_hybrid ,
@@ -37,10 +38,7 @@
.Nm archive_read_disk_uname ,
.Nm archive_read_disk_set_uname_lookup ,
.Nm archive_read_disk_set_gname_lookup ,
.Nm archive_read_disk_set_standard_lookup ,
.Nm archive_read_close ,
.Nm archive_read_finish ,
.Nm archive_read_free
.Nm archive_read_disk_set_standard_lookup
.Nd functions for reading objects from disk
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
@@ -49,6 +47,8 @@ Streaming Archive Library (libarchive, -larchive)
.Ft struct archive *
.Fn archive_read_disk_new "void"
.Ft int
.Fn archive_read_disk_set_behavior "struct archive *" "int"
.Ft int
.Fn archive_read_disk_set_symlink_logical "struct archive *"
.Ft int
.Fn archive_read_disk_set_symlink_physical "struct archive *"
@@ -81,12 +81,6 @@ Streaming Archive Library (libarchive, -larchive)
.Fa "int fd"
.Fa "const struct stat *"
.Fc
.Ft int
.Fn archive_read_close "struct archive *"
.Ft int
.Fn archive_read_finish "struct archive *"
.Ft int
.Fn archive_read_free "struct archive *"
.Sh DESCRIPTION
These functions provide an API for reading information about
objects on disk.
@@ -98,6 +92,51 @@ objects.
Allocates and initializes a
.Tn struct archive
object suitable for reading object information from disk.
.It Fn archive_read_disk_set_behavior
Configures various behavior options when reading entries from disk.
The flags field consists of a bitwise OR of one or more of the
following values:
.Bl -tag -compact -width "indent"
.It Cm ARCHIVE_READDISK_HONOR_NODUMP
Skip files and directories with the nodump file attribute (file flag) set.
By default, the nodump file atrribute is ignored.
.It Cm ARCHIVE_READDISK_MAC_COPYFILE
Mac OS X specific. Read metadata (ACLs and extended attributes) with
.Xr copyfile 3 .
By default, metadata is read using
.Xr copyfile 3 .
.It Cm ARCHIVE_READDISK_NO_ACL
Do not read Access Control Lists.
By default, ACLs are read from disk.
.It Cm ARCHIVE_READDISK_NO_FFLAGS
Do not read file attributes (file flags).
By default, file attributes are read from disk.
See
.Xr chattr 1
.Pq Linux
or
.Xr chflags 1
.Pq FreeBSD, Mac OS X
for more information on file attributes.
.It Cm ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS
Do not traverse mount points.
By defaut, moint points are traversed.
.It Cm ARCHIVE_READDISK_NO_XATTR
Do not read extended file attributes (xattrs).
By default, extended file attributes are read from disk.
See
.Xr xattr 7
.Pq Linux ,
.Xr xattr 2
.Pq Mac OS X ,
or
.Xr getextattr 8
.Pq FreeBSD
for more information on extended file attributes.
.It Cm ARCHIVE_READDISK_RESTORE_ATIME
Restore access time of traversed files.
By default, access time of traversed files is not restored.
.El
.It Xo
.Fn archive_read_disk_set_symlink_logical ,
.Fn archive_read_disk_set_symlink_physical ,
@@ -181,17 +220,6 @@ using the currently registered lookup functions above.
This affects the file ownership fields and ACL values in the
.Tn struct archive_entry
object.
.It Fn archive_read_close
Does nothing for
.Tn archive_read_disk
handles.
.It Fn archive_read_finish
This is a deprecated synonym for
.Fn archive_read_free .
.It Fn archive_read_free
Invokes
.Fn archive_read_close
if it was not invoked manually, then releases all resources.
.El
More information about the
.Va struct archive
File diff suppressed because it is too large Load Diff
@@ -33,6 +33,8 @@
#ifndef ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
#define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
#include "archive_platform_acl.h"
struct tree;
struct archive_entry;
@@ -86,4 +88,11 @@ struct archive_read_disk {
void *excluded_cb_data;
};
const char *
archive_read_disk_entry_setup_path(struct archive_read_disk *,
struct archive_entry *, int *);
int
archive_read_disk_entry_setup_acls(struct archive_read_disk *,
struct archive_entry *, int *);
#endif
@@ -37,9 +37,9 @@
.Nm archive_read_support_format_empty ,
.Nm archive_read_support_format_iso9660 ,
.Nm archive_read_support_format_lha ,
.Nm archive_read_support_format_mtree,
.Nm archive_read_support_format_rar,
.Nm archive_read_support_format_raw,
.Nm archive_read_support_format_mtree ,
.Nm archive_read_support_format_rar ,
.Nm archive_read_support_format_raw ,
.Nm archive_read_support_format_tar ,
.Nm archive_read_support_format_xar ,
.Nm archive_read_support_format_zip
@@ -33,7 +33,7 @@
.Nm archive_read_open_fd ,
.Nm archive_read_open_FILE ,
.Nm archive_read_open_filename ,
.Nm archive_read_open_memory ,
.Nm archive_read_open_memory
.Nd functions for reading streaming archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
@@ -67,7 +67,7 @@ Streaming Archive Library (libarchive, -larchive)
.Fa "size_t block_size"
.Fc
.Ft int
.Fn archive_read_open_memory "struct archive *" "void *buff" "size_t size"
.Fn archive_read_open_memory "struct archive *" "const void *buff" "size_t size"
.Sh DESCRIPTION
.Bl -tag -compact -width indent
.It Fn archive_read_open
@@ -494,7 +494,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
if (read_buf == NULL)
goto truncated_error;
compressed_size = archive_le32dec(read_buf);
if ((compressed_size & ~(1 << 31)) > state->flags.block_maximum_size)
if ((compressed_size & 0x7fffffff) > state->flags.block_maximum_size)
goto malformed_error;
/* A compressed size == 0 means the end of stream blocks. */
if (compressed_size == 0) {
@@ -504,8 +504,8 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
checksum_size = state->flags.block_checksum;
/* Check if the block is uncompressed. */
if (compressed_size & (1 << 31)) {
compressed_size &= ~(1 << 31);
if (compressed_size & 0x80000000U) {
compressed_size &= 0x7fffffff;
uncompressed_size = compressed_size;
} else
uncompressed_size = 0;/* Unknown yet. */
@@ -116,19 +116,11 @@ struct lzx_dec {
* coding tree, which is a binary tree. But a use of a large
* index table causes L1 cache read miss many times.
*/
#define HTBL_BITS 10
int max_bits;
int shift_bits;
int tbl_bits;
int tree_used;
int tree_avail;
/* Direct access table. */
uint16_t *tbl;
/* Binary tree table for extra bits over the direct access. */
struct htree_t {
uint16_t left;
uint16_t right;
} *tree;
} at, lt, mt, pt;
int loop;
@@ -187,7 +179,7 @@ struct lzx_stream {
#define CFDATA_cbData 4
#define CFDATA_cbUncomp 6
static const char *compression_name[] = {
static const char * const compression_name[] = {
"NONE",
"MSZIP",
"Quantum",
@@ -352,7 +344,6 @@ static int lzx_huffman_init(struct huffman *, size_t, int);
static void lzx_huffman_free(struct huffman *);
static int lzx_make_huffman_table(struct huffman *);
static inline int lzx_decode_huffman(struct huffman *, unsigned);
static int lzx_decode_huffman_tree(struct huffman *, unsigned, int);
int
@@ -3127,7 +3118,6 @@ getdata:
static int
lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
{
int bits;
if (hf->bitlen == NULL || hf->len_size != (int)len_size) {
free(hf->bitlen);
@@ -3138,21 +3128,11 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
} else
memset(hf->bitlen, 0, len_size * sizeof(hf->bitlen[0]));
if (hf->tbl == NULL) {
if (tbl_bits < HTBL_BITS)
bits = tbl_bits;
else
bits = HTBL_BITS;
hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
hf->tbl = malloc(((size_t)1 << tbl_bits) * sizeof(hf->tbl[0]));
if (hf->tbl == NULL)
return (ARCHIVE_FATAL);
hf->tbl_bits = tbl_bits;
}
if (hf->tree == NULL && tbl_bits > HTBL_BITS) {
hf->tree_avail = 1 << (tbl_bits - HTBL_BITS + 4);
hf->tree = malloc(hf->tree_avail * sizeof(hf->tree[0]));
if (hf->tree == NULL)
return (ARCHIVE_FATAL);
}
return (ARCHIVE_OK);
}
@@ -3161,7 +3141,6 @@ lzx_huffman_free(struct huffman *hf)
{
free(hf->bitlen);
free(hf->tbl);
free(hf->tree);
}
/*
@@ -3174,7 +3153,7 @@ lzx_make_huffman_table(struct huffman *hf)
const unsigned char *bitlen;
int bitptn[17], weight[17];
int i, maxbits = 0, ptn, tbl_size, w;
int diffbits, len_avail;
int len_avail;
/*
* Initialize bit patterns.
@@ -3205,28 +3184,11 @@ lzx_make_huffman_table(struct huffman *hf)
weight[i] >>= ebits;
}
}
if (maxbits > HTBL_BITS) {
int htbl_max;
uint16_t *p;
diffbits = maxbits - HTBL_BITS;
for (i = 1; i <= HTBL_BITS; i++) {
bitptn[i] >>= diffbits;
weight[i] >>= diffbits;
}
htbl_max = bitptn[HTBL_BITS] +
weight[HTBL_BITS] * hf->freq[HTBL_BITS];
p = &(hf->tbl[htbl_max]);
while (p < &hf->tbl[1U<<HTBL_BITS])
*p++ = 0;
} else
diffbits = 0;
hf->shift_bits = diffbits;
/*
* Make the table.
*/
tbl_size = 1 << HTBL_BITS;
tbl_size = 1 << hf->tbl_bits;
tbl = hf->tbl;
bitlen = hf->bitlen;
len_avail = hf->len_size;
@@ -3234,120 +3196,32 @@ lzx_make_huffman_table(struct huffman *hf)
for (i = 0; i < len_avail; i++) {
uint16_t *p;
int len, cnt;
uint16_t bit;
int extlen;
struct htree_t *ht;
if (bitlen[i] == 0)
continue;
/* Get a bit pattern */
len = bitlen[i];
if (len > tbl_size)
return (0);
ptn = bitptn[len];
cnt = weight[len];
if (len <= HTBL_BITS) {
/* Calculate next bit pattern */
if ((bitptn[len] = ptn + cnt) > tbl_size)
return (0);/* Invalid */
/* Update the table */
p = &(tbl[ptn]);
while (--cnt >= 0)
p[cnt] = (uint16_t)i;
continue;
}
/*
* A bit length is too big to be housed to a direct table,
* so we use a tree model for its extra bits.
*/
bitptn[len] = ptn + cnt;
bit = 1U << (diffbits -1);
extlen = len - HTBL_BITS;
p = &(tbl[ptn >> diffbits]);
if (*p == 0) {
*p = len_avail + hf->tree_used;
ht = &(hf->tree[hf->tree_used++]);
if (hf->tree_used > hf->tree_avail)
return (0);/* Invalid */
ht->left = 0;
ht->right = 0;
} else {
if (*p < len_avail ||
*p >= (len_avail + hf->tree_used))
return (0);/* Invalid */
ht = &(hf->tree[*p - len_avail]);
}
while (--extlen > 0) {
if (ptn & bit) {
if (ht->left < len_avail) {
ht->left = len_avail + hf->tree_used;
ht = &(hf->tree[hf->tree_used++]);
if (hf->tree_used > hf->tree_avail)
return (0);/* Invalid */
ht->left = 0;
ht->right = 0;
} else {
ht = &(hf->tree[ht->left - len_avail]);
}
} else {
if (ht->right < len_avail) {
ht->right = len_avail + hf->tree_used;
ht = &(hf->tree[hf->tree_used++]);
if (hf->tree_used > hf->tree_avail)
return (0);/* Invalid */
ht->left = 0;
ht->right = 0;
} else {
ht = &(hf->tree[ht->right - len_avail]);
}
}
bit >>= 1;
}
if (ptn & bit) {
if (ht->left != 0)
return (0);/* Invalid */
ht->left = (uint16_t)i;
} else {
if (ht->right != 0)
return (0);/* Invalid */
ht->right = (uint16_t)i;
}
/* Calculate next bit pattern */
if ((bitptn[len] = ptn + cnt) > tbl_size)
return (0);/* Invalid */
/* Update the table */
p = &(tbl[ptn]);
while (--cnt >= 0)
p[cnt] = (uint16_t)i;
}
return (1);
}
static int
lzx_decode_huffman_tree(struct huffman *hf, unsigned rbits, int c)
{
struct htree_t *ht;
int extlen;
ht = hf->tree;
extlen = hf->shift_bits;
while (c >= hf->len_size) {
c -= hf->len_size;
if (extlen-- <= 0 || c >= hf->tree_used)
return (0);
if (rbits & (1U << extlen))
c = ht[c].left;
else
c = ht[c].right;
}
return (c);
}
static inline int
lzx_decode_huffman(struct huffman *hf, unsigned rbits)
{
int c;
/*
* At first search an index table for a bit pattern.
* If it fails, search a huffman tree for.
*/
c = hf->tbl[rbits >> hf->shift_bits];
c = hf->tbl[rbits];
if (c < hf->len_size)
return (c);
/* This bit pattern needs to be found out at a huffman tree. */
return (lzx_decode_huffman_tree(hf, rbits, c));
return (0);
}
@@ -165,7 +165,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_cpio.c 20116
struct links_entry {
struct links_entry *next;
struct links_entry *previous;
int links;
unsigned int links;
dev_t dev;
int64_t ino;
char *name;
@@ -3021,8 +3021,9 @@ heap_add_entry(struct archive_read *a, struct heap_queue *heap,
ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
memcpy(new_pending_files, heap->files,
heap->allocated * sizeof(new_pending_files[0]));
if (heap->allocated)
memcpy(new_pending_files, heap->files,
heap->allocated * sizeof(new_pending_files[0]));
if (heap->files != NULL)
free(heap->files);
heap->files = new_pending_files;
@@ -2480,7 +2480,7 @@ lzh_huffman_free(struct huffman *hf)
free(hf->tree);
}
static char bitlen_tbl[0x400] = {
static const char bitlen_tbl[0x400] = {
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
@@ -130,9 +130,7 @@ static ssize_t readline(struct archive_read *, struct mtree *, char **, ssize_t)
static int skip(struct archive_read *a);
static int read_header(struct archive_read *,
struct archive_entry *);
static int64_t mtree_atol10(char **);
static int64_t mtree_atol8(char **);
static int64_t mtree_atol(char **);
static int64_t mtree_atol(char **, int base);
/*
* There's no standard for TIME_T_MAX/TIME_T_MIN. So we compute them
@@ -399,41 +397,41 @@ bid_keycmp(const char *p, const char *key, ssize_t len)
static int
bid_keyword(const char *p, ssize_t len)
{
static const char *keys_c[] = {
static const char * const keys_c[] = {
"content", "contents", "cksum", NULL
};
static const char *keys_df[] = {
static const char * const keys_df[] = {
"device", "flags", NULL
};
static const char *keys_g[] = {
static const char * const keys_g[] = {
"gid", "gname", NULL
};
static const char *keys_il[] = {
static const char * const keys_il[] = {
"ignore", "inode", "link", NULL
};
static const char *keys_m[] = {
static const char * const keys_m[] = {
"md5", "md5digest", "mode", NULL
};
static const char *keys_no[] = {
static const char * const keys_no[] = {
"nlink", "nochange", "optional", NULL
};
static const char *keys_r[] = {
static const char * const keys_r[] = {
"resdevice", "rmd160", "rmd160digest", NULL
};
static const char *keys_s[] = {
static const char * const keys_s[] = {
"sha1", "sha1digest",
"sha256", "sha256digest",
"sha384", "sha384digest",
"sha512", "sha512digest",
"size", NULL
};
static const char *keys_t[] = {
static const char * const keys_t[] = {
"tags", "time", "type", NULL
};
static const char *keys_u[] = {
static const char * const keys_u[] = {
"uid", "uname", NULL
};
const char **keys;
const char * const *keys;
int i;
switch (*p) {
@@ -1418,7 +1416,7 @@ parse_device(dev_t *pdev, struct archive *a, char *val)
"Too many arguments");
return ARCHIVE_WARN;
}
numbers[argc++] = (unsigned long)mtree_atol(&p);
numbers[argc++] = (unsigned long)mtree_atol(&p, 0);
}
if (argc < 2) {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
@@ -1433,7 +1431,7 @@ parse_device(dev_t *pdev, struct archive *a, char *val)
}
} else {
/* file system raw value. */
result = (dev_t)mtree_atol(&val);
result = (dev_t)mtree_atol(&val, 0);
}
*pdev = result;
return ARCHIVE_OK;
@@ -1513,7 +1511,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
case 'g':
if (strcmp(key, "gid") == 0) {
*parsed_kws |= MTREE_HAS_GID;
archive_entry_set_gid(entry, mtree_atol10(&val));
archive_entry_set_gid(entry, mtree_atol(&val, 10));
break;
}
if (strcmp(key, "gname") == 0) {
@@ -1523,7 +1521,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
}
case 'i':
if (strcmp(key, "inode") == 0) {
archive_entry_set_ino(entry, mtree_atol10(&val));
archive_entry_set_ino(entry, mtree_atol(&val, 10));
break;
}
case 'l':
@@ -1535,14 +1533,14 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0)
break;
if (strcmp(key, "mode") == 0) {
if (val[0] >= '0' && val[0] <= '9') {
if (val[0] >= '0' && val[0] <= '7') {
*parsed_kws |= MTREE_HAS_PERM;
archive_entry_set_perm(entry,
(mode_t)mtree_atol8(&val));
(mode_t)mtree_atol(&val, 8));
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Symbolic mode \"%s\" unsupported", val);
"Symbolic or non-octal mode \"%s\" unsupported", val);
return ARCHIVE_WARN;
}
break;
@@ -1551,7 +1549,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
if (strcmp(key, "nlink") == 0) {
*parsed_kws |= MTREE_HAS_NLINK;
archive_entry_set_nlink(entry,
(unsigned int)mtree_atol10(&val));
(unsigned int)mtree_atol(&val, 10));
break;
}
case 'r':
@@ -1582,7 +1580,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
strcmp(key, "sha512digest") == 0)
break;
if (strcmp(key, "size") == 0) {
archive_entry_set_size(entry, mtree_atol10(&val));
archive_entry_set_size(entry, mtree_atol(&val, 10));
break;
}
case 't':
@@ -1601,13 +1599,13 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
long ns = 0;
*parsed_kws |= MTREE_HAS_MTIME;
m = mtree_atol10(&val);
m = mtree_atol(&val, 10);
/* Replicate an old mtree bug:
* 123456789.1 represents 123456789
* seconds and 1 nanosecond. */
if (*val == '.') {
++val;
ns = (long)mtree_atol10(&val);
ns = (long)mtree_atol(&val, 10);
if (ns < 0)
ns = 0;
else if (ns > 999999999)
@@ -1670,7 +1668,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
case 'u':
if (strcmp(key, "uid") == 0) {
*parsed_kws |= MTREE_HAS_UID;
archive_entry_set_uid(entry, mtree_atol10(&val));
archive_entry_set_uid(entry, mtree_atol(&val, 10));
break;
}
if (strcmp(key, "uname") == 0) {
@@ -1825,72 +1823,9 @@ parse_escapes(char *src, struct mtree_entry *mentry)
*dest = '\0';
}
/*
* Note that this implementation does not (and should not!) obey
* locale settings; you cannot simply substitute strtol here, since
* it does obey locale.
*/
static int64_t
mtree_atol8(char **p)
{
int64_t l, limit, last_digit_limit;
int digit, base;
base = 8;
limit = INT64_MAX / base;
last_digit_limit = INT64_MAX % base;
l = 0;
digit = **p - '0';
while (digit >= 0 && digit < base) {
if (l>limit || (l == limit && digit > last_digit_limit)) {
l = INT64_MAX; /* Truncate on overflow. */
break;
}
l = (l * base) + digit;
digit = *++(*p) - '0';
}
return (l);
}
/*
* Note that this implementation does not (and should not!) obey
* locale settings; you cannot simply substitute strtol here, since
* it does obey locale.
*/
static int64_t
mtree_atol10(char **p)
{
int64_t l, limit, last_digit_limit;
int base, digit, sign;
base = 10;
if (**p == '-') {
sign = -1;
limit = ((uint64_t)(INT64_MAX) + 1) / base;
last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base;
++(*p);
} else {
sign = 1;
limit = INT64_MAX / base;
last_digit_limit = INT64_MAX % base;
}
l = 0;
digit = **p - '0';
while (digit >= 0 && digit < base) {
if (l > limit || (l == limit && digit > last_digit_limit))
return (sign < 0) ? INT64_MIN : INT64_MAX;
l = (l * base) + digit;
digit = *++(*p) - '0';
}
return (sign < 0) ? -l : l;
}
/* Parse a hex digit. */
static int
parsehex(char c)
parsedigit(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
@@ -1908,45 +1843,50 @@ parsehex(char c)
* it does obey locale.
*/
static int64_t
mtree_atol16(char **p)
mtree_atol(char **p, int base)
{
int64_t l, limit, last_digit_limit;
int base, digit, sign;
int64_t l, limit;
int digit, last_digit_limit;
base = 16;
if (base == 0) {
if (**p != '0')
base = 10;
else if ((*p)[1] == 'x' || (*p)[1] == 'X') {
*p += 2;
base = 16;
} else {
base = 8;
}
}
if (**p == '-') {
sign = -1;
limit = ((uint64_t)(INT64_MAX) + 1) / base;
last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base;
limit = INT64_MIN / base;
last_digit_limit = INT64_MIN % base;
++(*p);
l = 0;
digit = parsedigit(**p);
while (digit >= 0 && digit < base) {
if (l < limit || (l == limit && digit > last_digit_limit))
return INT64_MIN;
l = (l * base) - digit;
digit = parsedigit(*++(*p));
}
return l;
} else {
sign = 1;
limit = INT64_MAX / base;
last_digit_limit = INT64_MAX % base;
}
l = 0;
digit = parsehex(**p);
while (digit >= 0 && digit < base) {
if (l > limit || (l == limit && digit > last_digit_limit))
return (sign < 0) ? INT64_MIN : INT64_MAX;
l = (l * base) + digit;
digit = parsehex(*++(*p));
l = 0;
digit = parsedigit(**p);
while (digit >= 0 && digit < base) {
if (l > limit || (l == limit && digit > last_digit_limit))
return INT64_MAX;
l = (l * base) + digit;
digit = parsedigit(*++(*p));
}
return l;
}
return (sign < 0) ? -l : l;
}
static int64_t
mtree_atol(char **p)
{
if (**p != '0')
return mtree_atol10(p);
if ((*p)[1] == 'x' || (*p)[1] == 'X') {
*p += 2;
return mtree_atol16(p);
}
return mtree_atol8(p);
}
/*
@@ -1750,7 +1750,7 @@ read_exttime(const char *p, struct rar *rar, const char *endp)
return (-1);
for (j = 0; j < count; j++)
{
rem = ((*p) << 16) | (rem >> 8);
rem = (((unsigned)(unsigned char)*p) << 16) | (rem >> 8);
p++;
}
tm = localtime(&t);
@@ -155,6 +155,7 @@ struct tar {
int compat_2x;
int process_mac_extensions;
int read_concatenated_archives;
int realsize_override;
};
static int archive_block_is_null(const char *p);
@@ -527,6 +528,7 @@ archive_read_format_tar_read_header(struct archive_read *a,
tar->entry_offset = 0;
gnu_clear_sparse_list(tar);
tar->realsize = -1; /* Mark this as "unset" */
tar->realsize_override = 0;
/* Setup default string conversion. */
tar->sconv = tar->opt_sconv;
@@ -1894,6 +1896,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
if (strcmp(key, "GNU.sparse.size") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
archive_entry_set_size(entry, tar->realsize);
tar->realsize_override = 1;
}
/* GNU "0.1" sparse pax format. */
@@ -1925,6 +1928,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
if (strcmp(key, "GNU.sparse.realsize") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
archive_entry_set_size(entry, tar->realsize);
tar->realsize_override = 1;
}
break;
case 'L':
@@ -1977,6 +1981,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
tar_atol10(value, strlen(value)));
} else if (strcmp(key, "SCHILY.realsize") == 0) {
tar->realsize = tar_atol10(value, strlen(value));
tar->realsize_override = 1;
archive_entry_set_size(entry, tar->realsize);
} else if (strncmp(key, "SCHILY.xattr.", 13) == 0) {
pax_attribute_schily_xattr(entry, key, value,
@@ -2055,14 +2060,12 @@ pax_attribute(struct archive_read *a, struct tar *tar,
tar->entry_bytes_remaining
= tar_atol10(value, strlen(value));
/*
* But, "size" is not necessarily the size of
* the file on disk; if this is a sparse file,
* the disk size may have already been set from
* GNU.sparse.realsize or GNU.sparse.size or
* an old GNU header field or SCHILY.realsize
* or ....
* The "size" pax header keyword always overrides the
* "size" field in the tar header.
* GNU.sparse.realsize, GNU.sparse.size and
* SCHILY.realsize override this value.
*/
if (tar->realsize < 0) {
if (!tar->realsize_override) {
archive_entry_set_size(entry,
tar->entry_bytes_remaining);
tar->realsize
@@ -2206,6 +2209,7 @@ header_gnutar(struct archive_read *a, struct tar *tar,
tar->realsize
= tar_atol(header->realsize, sizeof(header->realsize));
archive_entry_set_size(entry, tar->realsize);
tar->realsize_override = 1;
}
if (header->sparse[0].offset[0] != 0) {
@@ -600,9 +600,10 @@ _warc_rdver(const char *buf, size_t bsz)
/* looks good so far, read the version number for a laugh */
buf += sizeof(magic) - 1U;
if (isdigit(buf[0U]) && (buf[1U] == '.') && isdigit(buf[2U])) {
if (isdigit((unsigned char)buf[0U]) && (buf[1U] == '.') &&
isdigit((unsigned char)buf[2U])) {
/* we support a maximum of 2 digits in the minor version */
if (isdigit(buf[3U]))
if (isdigit((unsigned char)buf[3U]))
end = 1U;
/* set up major version */
ver = (buf[0U] - '0') * 10000U;
@@ -686,7 +687,7 @@ _warc_rduri(const char *buf, size_t bsz)
/* spaces inside uri are not allowed, CRLF should follow */
for (p = val; p < eol; p++) {
if (isspace(*p))
if (isspace((unsigned char)*p))
return res;
}
@@ -736,7 +737,7 @@ _warc_rdlen(const char *buf, size_t bsz)
while (val < eol && (*val == ' ' || *val == '\t'))
val++;
/* there must be at least one digit */
if (!isdigit(*val))
if (!isdigit((unsigned char)*val))
return -1;
len = strtol(val, &on, 10);
if (on != eol) {
@@ -347,7 +347,7 @@ fake_crc32(unsigned long crc, const void *buff, size_t len)
return 0;
}
static struct {
static const struct {
int id;
const char * name;
} compression_methods[] = {
@@ -2407,7 +2407,7 @@ read_eocd(struct zip *zip, const char *p, int64_t current_offset)
* Examine Zip64 EOCD locator: If it's valid, store the information
* from it.
*/
static void
static int
read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
{
int64_t eocd64_offset;
@@ -2417,35 +2417,37 @@ read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
/* Central dir must be on first volume. */
if (archive_le32dec(p + 4) != 0)
return;
return 0;
/* Must be only a single volume. */
if (archive_le32dec(p + 16) != 1)
return;
return 0;
/* Find the Zip64 EOCD record. */
eocd64_offset = archive_le64dec(p + 8);
if (__archive_read_seek(a, eocd64_offset, SEEK_SET) < 0)
return;
return 0;
if ((p = __archive_read_ahead(a, 56, NULL)) == NULL)
return;
return 0;
/* Make sure we can read all of it. */
eocd64_size = archive_le64dec(p + 4) + 12;
if (eocd64_size < 56 || eocd64_size > 16384)
return;
return 0;
if ((p = __archive_read_ahead(a, (size_t)eocd64_size, NULL)) == NULL)
return;
return 0;
/* Sanity-check the EOCD64 */
if (archive_le32dec(p + 16) != 0) /* Must be disk #0 */
return;
return 0;
if (archive_le32dec(p + 20) != 0) /* CD must be on disk #0 */
return;
return 0;
/* CD can't be split. */
if (archive_le64dec(p + 24) != archive_le64dec(p + 32))
return;
return 0;
/* Save the central directory offset for later use. */
zip->central_directory_offset = archive_le64dec(p + 48);
return 32;
}
static int
@@ -2483,15 +2485,14 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
if (memcmp(p + i, "PK\005\006", 4) == 0) {
int ret = read_eocd(zip, p + i,
current_offset + i);
if (ret > 0) {
/* Zip64 EOCD locator precedes
* regular EOCD if present. */
if (i >= 20
&& memcmp(p + i - 20, "PK\006\007", 4) == 0) {
read_zip64_eocd(a, zip, p + i - 20);
}
return (ret);
/* Zip64 EOCD locator precedes
* regular EOCD if present. */
if (i >= 20 && memcmp(p + i - 20, "PK\006\007", 4) == 0) {
int ret_zip64 = read_zip64_eocd(a, zip, p + i - 20);
if (ret_zip64 > ret)
ret = ret_zip64;
}
return (ret);
}
i -= 4;
break;
@@ -202,7 +202,8 @@ archive_string_append(struct archive_string *as, const char *p, size_t s)
{
if (archive_string_ensure(as, as->length + s + 1) == NULL)
return (NULL);
memmove(as->s + as->length, p, s);
if (s)
memmove(as->s + as->length, p, s);
as->length += s;
as->s[as->length] = 0;
return (as);
@@ -53,7 +53,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_string_sprintf.c 189435 2009-03-
static void
append_uint(struct archive_string *as, uintmax_t d, unsigned base)
{
static const char *digits = "0123456789abcdef";
static const char digits[] = "0123456789abcdef";
if (d >= base)
append_uint(as, d/base, base);
archive_strappend_char(as, digits[d % base]);
@@ -89,88 +89,6 @@ archive_version_string(void)
return (ARCHIVE_VERSION_STRING);
}
const char *
archive_version_details(void)
{
static struct archive_string str;
static int init = 0;
const char *zlib = archive_zlib_version();
const char *liblzma = archive_liblzma_version();
const char *bzlib = archive_bzlib_version();
const char *liblz4 = archive_liblz4_version();
if (!init) {
archive_string_init(&str);
archive_strcat(&str, ARCHIVE_VERSION_STRING);
if (zlib != NULL) {
archive_strcat(&str, " zlib/");
archive_strcat(&str, zlib);
}
if (liblzma) {
archive_strcat(&str, " liblzma/");
archive_strcat(&str, liblzma);
}
if (bzlib) {
const char *p = bzlib;
const char *sep = strchr(p, ',');
if (sep == NULL)
sep = p + strlen(p);
archive_strcat(&str, " bz2lib/");
archive_strncat(&str, p, sep - p);
}
if (liblz4) {
archive_strcat(&str, " liblz4/");
archive_strcat(&str, liblz4);
}
}
return str.s;
}
const char *
archive_zlib_version(void)
{
#ifdef HAVE_ZLIB_H
return ZLIB_VERSION;
#else
return NULL;
#endif
}
const char *
archive_liblzma_version(void)
{
#ifdef HAVE_LZMA_H
return LZMA_VERSION_STRING;
#else
return NULL;
#endif
}
const char *
archive_bzlib_version(void)
{
#ifdef HAVE_BZLIB_H
return BZ2_bzlibVersion();
#else
return NULL;
#endif
}
const char *
archive_liblz4_version(void)
{
#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
#define str(s) #s
#define NUMBER(x) str(x)
return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
#undef NUMBER
#undef str
#else
return NULL;
#endif
}
int
archive_errno(struct archive *a)
{
@@ -275,7 +193,7 @@ archive_copy_error(struct archive *dest, struct archive *src)
void
__archive_errx(int retvalue, const char *msg)
{
static const char *msg1 = "Fatal Internal Error in libarchive: ";
static const char msg1[] = "Fatal Internal Error in libarchive: ";
size_t s;
s = write(2, msg1, strlen(msg1));
@@ -303,8 +221,8 @@ __archive_errx(int retvalue, const char *msg)
int
__archive_mktemp(const char *tmpdir)
{
static const wchar_t *prefix = L"libarchive_";
static const wchar_t *suffix = L"XXXXXXXXXX";
static const wchar_t prefix[] = L"libarchive_";
static const wchar_t suffix[] = L"XXXXXXXXXX";
static const wchar_t num[] = {
L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7',
L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F',
@@ -0,0 +1,133 @@
/*-
* Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA
* Copyright (c) 2003-2007 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $");
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_ZLIB_H
#include <cm_zlib.h>
#endif
#ifdef HAVE_LZMA_H
#include <cm_lzma.h>
#endif
#ifdef HAVE_BZLIB_H
#include <cm_bzlib.h>
#endif
#ifdef HAVE_LZ4_H
#include <lz4.h>
#endif
#include "archive.h"
#include "archive_private.h"
#include "archive_string.h"
const char *
archive_version_details(void)
{
static struct archive_string str;
static int init = 0;
const char *zlib = archive_zlib_version();
const char *liblzma = archive_liblzma_version();
const char *bzlib = archive_bzlib_version();
const char *liblz4 = archive_liblz4_version();
if (!init) {
archive_string_init(&str);
archive_strcat(&str, ARCHIVE_VERSION_STRING);
if (zlib != NULL) {
archive_strcat(&str, " zlib/");
archive_strcat(&str, zlib);
}
if (liblzma) {
archive_strcat(&str, " liblzma/");
archive_strcat(&str, liblzma);
}
if (bzlib) {
const char *p = bzlib;
const char *sep = strchr(p, ',');
if (sep == NULL)
sep = p + strlen(p);
archive_strcat(&str, " bz2lib/");
archive_strncat(&str, p, sep - p);
}
if (liblz4) {
archive_strcat(&str, " liblz4/");
archive_strcat(&str, liblz4);
}
}
return str.s;
}
const char *
archive_zlib_version(void)
{
#ifdef HAVE_ZLIB_H
return ZLIB_VERSION;
#else
return NULL;
#endif
}
const char *
archive_liblzma_version(void)
{
#ifdef HAVE_LZMA_H
return LZMA_VERSION_STRING;
#else
return NULL;
#endif
}
const char *
archive_bzlib_version(void)
{
#ifdef HAVE_BZLIB_H
return BZ2_bzlibVersion();
#else
return NULL;
#endif
}
const char *
archive_liblz4_version(void)
{
#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
#define str(s) #s
#define NUMBER(x) str(x)
return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
#undef NUMBER
#undef str
#else
return NULL;
#endif
}
@@ -38,7 +38,7 @@ __FBSDID("$FreeBSD$");
#include "archive_private.h"
/* A table that maps filter codes to functions. */
static
static const
struct { int code; int (*setter)(struct archive *); } codes[] =
{
{ ARCHIVE_FILTER_NONE, archive_write_add_filter_none },
@@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$");
#include "archive_private.h"
/* A table that maps names to functions. */
static
static const
struct { const char *name; int (*setter)(struct archive *); } names[] =
{
{ "b64encode", archive_write_add_filter_b64encode },
@@ -225,7 +225,7 @@ archive_filter_lz4_open(struct archive_write_filter *f)
struct private_data *data = (struct private_data *)f->data;
int ret;
size_t required_size;
static size_t bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024,
static size_t const bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024,
4 * 1024 * 1024 };
size_t pre_block_size;
@@ -92,7 +92,7 @@ archive_write_add_filter_program(struct archive *_a, const char *cmd)
{
struct archive_write_filter *f = __archive_write_allocate_filter(_a);
struct private_data *data;
static const char *prefix = "Program: ";
static const char prefix[] = "Program: ";
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_program");
@@ -24,11 +24,12 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 2, 2012
.Dd February 28, 2017
.Dt ARCHIVE_WRITE_DATA 3
.Os
.Sh NAME
.Nm archive_write_data
.Nm archive_write_data ,
.Nm archive_write_data_block
.Nd functions for creating archives
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
@@ -36,8 +37,27 @@ Streaming Archive Library (libarchive, -larchive)
.In archive.h
.Ft la_ssize_t
.Fn archive_write_data "struct archive *" "const void *" "size_t"
.Ft la_ssize_t
.Fn archive_write_data_block "struct archive *" "const void *" "size_t size" "int64_t offset"
.Sh DESCRIPTION
.Bl -tag -width indent
.It Fn archive_write_data
Write data corresponding to the header just written.
.It Fn archive_write_data_block
Write data corresponding to the header just written.
This is like
.Fn archive_write_data
except that it performs a seek on the file being
written to the specified offset before writing the data.
This is useful when restoring sparse files from archive
formats that support sparse files.
Returns number of bytes written or -1 on error.
(Note: This is currently not supported for
.Tn archive_write
handles, only for
.Tn archive_write_disk
handles.
.El
.\" .Sh EXAMPLE
.\"
.Sh RETURN VALUES
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 2, 2012
.Dd April 3, 2017
.Dt ARCHIVE_WRITE_DISK 3
.Os
.Sh NAME
@@ -33,14 +33,7 @@
.Nm archive_write_disk_set_skip_file ,
.Nm archive_write_disk_set_group_lookup ,
.Nm archive_write_disk_set_standard_lookup ,
.Nm archive_write_disk_set_user_lookup ,
.Nm archive_write_header ,
.Nm archive_write_data ,
.Nm archive_write_data_block ,
.Nm archive_write_finish_entry ,
.Nm archive_write_close ,
.Nm archive_write_finish
.Nm archive_write_free
.Nm archive_write_disk_set_user_lookup
.Nd functions for creating objects on disk
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
@@ -68,20 +61,6 @@ Streaming Archive Library (libarchive, -larchive)
.Fa "uid_t (*)(void *, const char *uname, uid_t uid)"
.Fa "void (*cleanup)(void *)"
.Fc
.Ft int
.Fn archive_write_header "struct archive *" "struct archive_entry *"
.Ft la_ssize_t
.Fn archive_write_data "struct archive *" "const void *" "size_t"
.Ft la_ssize_t
.Fn archive_write_data_block "struct archive *" "const void *" "size_t size" "int64_t offset"
.Ft int
.Fn archive_write_finish_entry "struct archive *"
.Ft int
.Fn archive_write_close "struct archive *"
.Ft int
.Fn archive_write_finish "struct archive *"
.Ft int
.Fn archive_write_free "struct archive *"
.Sh DESCRIPTION
These functions provide a complete API for creating objects on
disk from
@@ -117,6 +96,33 @@ performance optimization in practice.
The options field consists of a bitwise OR of one or more of the
following values:
.Bl -tag -compact -width "indent"
.It Cm ARCHIVE_EXTRACT_ACL
Attempt to restore Access Control Lists.
By default, extended ACLs are ignored.
.It Cm ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS
Before removing a file system object prior to replacing it, clear
platform-specific file flags which might prevent its removal.
.It Cm ARCHIVE_EXTRACT_FFLAGS
Attempt to restore file attributes (file flags).
By default, file attributes are ignored.
See
.Xr chattr 1
.Pq Linux
or
.Xr chflags 1
.Pq FreeBSD, Mac OS X
for more information on file attributes.
.It Cm ARCHIVE_EXTRACT_MAC_METADATA
Mac OS X specific. Restore metadata using
.Xr copyfile 3 .
By default,
.Xr copyfile 3
metadata is ignored.
.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE
Existing files on disk will not be overwritten.
By default, existing regular files are truncated and overwritten;
existing directories will have their permissions updated;
other pre-existing objects are unlinked and recreated from scratch.
.It Cm ARCHIVE_EXTRACT_OWNER
The user and group IDs should be set on the restored file.
By default, the user and group IDs are not restored.
@@ -132,43 +138,9 @@ is not specified, then SUID and SGID bits will only be restored
if the default user and group IDs of newly-created objects on disk
happen to match those specified in the archive entry.
By default, only basic permissions are restored, and umask is obeyed.
.It Cm ARCHIVE_EXTRACT_TIME
The timestamps (mtime, ctime, and atime) should be restored.
By default, they are ignored.
Note that restoring of atime is not currently supported.
.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE
Existing files on disk will not be overwritten.
By default, existing regular files are truncated and overwritten;
existing directories will have their permissions updated;
other pre-existing objects are unlinked and recreated from scratch.
.It Cm ARCHIVE_EXTRACT_UNLINK
Existing files on disk will be unlinked before any attempt to
create them.
In some cases, this can prove to be a significant performance improvement.
By default, existing files are truncated and rewritten, but
the file is not recreated.
In particular, the default behavior does not break existing hard links.
.It Cm ARCHIVE_EXTRACT_ACL
Attempt to restore ACLs.
By default, extended ACLs are ignored.
.It Cm ARCHIVE_EXTRACT_FFLAGS
Attempt to restore extended file flags.
By default, file flags are ignored.
.It Cm ARCHIVE_EXTRACT_XATTR
Attempt to restore POSIX.1e extended attributes.
By default, they are ignored.
.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS
Refuse to extract any object whose final location would be altered
by a symlink on disk.
This is intended to help guard against a variety of mischief
caused by archives that (deliberately or otherwise) extract
files outside of the current directory.
The default is not to perform this check.
If
.Cm ARCHIVE_EXTRACT_UNLINK
is specified together with this option, the library will
remove any intermediate symlinks it finds and return an
error only if such symlink could not be removed.
.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
Refuse to extract an absolute path.
The default is to not refuse such paths.
.It Cm ARCHIVE_EXTRACT_SECURE_NODOTDOT
Refuse to extract a path that contains a
.Pa ..
@@ -177,16 +149,45 @@ The default is to not refuse such paths.
Note that paths ending in
.Pa ..
always cause an error, regardless of this flag.
.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
Refuse to extract an absolute path.
The default is to not refuse such paths.
.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS
Refuse to extract any object whose final location would be altered
by a symlink on disk.
This is intended to help guard against a variety of mischief
caused by archives that (deliberately or otherwise) extract
files outside of the current directory.
The default is not to perform this check.
If
.It Cm ARCHIVE_EXTRACT_SPARSE
Scan data for blocks of NUL bytes and try to recreate them with holes.
This results in sparse files, independent of whether the archive format
supports or uses them.
.It Cm ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS
Before removing a file system object prior to replacing it, clear
platform-specific file flags which might prevent its removal.
.Cm ARCHIVE_EXTRACT_UNLINK
is specified together with this option, the library will
remove any intermediate symlinks it finds and return an
error only if such symlink could not be removed.
.It Cm ARCHIVE_EXTRACT_TIME
The timestamps (mtime, ctime, and atime) should be restored.
By default, they are ignored.
Note that restoring of atime is not currently supported.
.It Cm ARCHIVE_EXTRACT_UNLINK
Existing files on disk will be unlinked before any attempt to
create them.
In some cases, this can prove to be a significant performance improvement.
By default, existing files are truncated and rewritten, but
the file is not recreated.
In particular, the default behavior does not break existing hard links.
.It Cm ARCHIVE_EXTRACT_XATTR
Attempt to restore extended file attributes.
By default, they are ignored.
See
.Xr xattr 7
.Pq Linux ,
.Xr xattr 2
.Pq Mac OS X ,
or
.Xr getextattr 8
.Pq FreeBSD
for more information on extended file attributes.
.El
.It Xo
.Fn archive_write_disk_set_group_lookup ,
@@ -223,60 +224,6 @@ the number of calls to
.Xr getpwnam 3
and
.Xr getgrnam 3 .
.It Fn archive_write_header
Build and write a header using the data in the provided
.Tn struct archive_entry
structure.
See
.Xr archive_entry 3
for information on creating and populating
.Tn struct archive_entry
objects.
.It Fn archive_write_data
Write data corresponding to the header just written.
Returns number of bytes written or -1 on error.
.It Fn archive_write_data_block
Write data corresponding to the header just written.
This is like
.Fn archive_write_data
except that it performs a seek on the file being
written to the specified offset before writing the data.
This is useful when restoring sparse files from archive
formats that support sparse files.
Returns number of bytes written or -1 on error.
(Note: This is currently not supported for
.Tn archive_write
handles, only for
.Tn archive_write_disk
handles.)
.It Fn archive_write_finish_entry
Close out the entry just written.
Ordinarily, clients never need to call this, as it
is called automatically by
.Fn archive_write_next_header
and
.Fn archive_write_close
as needed.
However, some file attributes are written to disk only
after the file is closed, so this can be necessary
if you need to work with the file on disk right away.
.It Fn archive_write_close
Set any attributes that could not be set during the initial restore.
For example, directory timestamps are not restored initially because
restoring a subsequent file would alter that timestamp.
Similarly, non-writable directories are initially created with
write permissions (so that their contents can be restored).
The
.Nm
library maintains a list of all such deferred attributes and
sets them when this function is invoked.
.It Fn archive_write_finish
This is a deprecated synonym for
.Fn archive_write_free .
.It Fn archive_write_free
Invokes
.Fn archive_write_close
if it was not invoked manually, then releases all resources.
.El
More information about the
.Va struct archive
@@ -1,654 +0,0 @@
/*-
* Copyright (c) 2003-2010 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 05:35:40Z kientzle $");
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_ACL_H
#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
#include "archive.h"
#include "archive_entry.h"
#include "archive_acl_private.h"
#include "archive_write_disk_private.h"
#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,
struct archive_acl *abstract_acl)
{
(void)a; /* UNUSED */
(void)fd; /* UNUSED */
(void)name; /* UNUSED */
(void)abstract_acl; /* UNUSED */
return (ARCHIVE_OK);
}
#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);
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl)
{
int ret = ARCHIVE_OK;
#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);
}
#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");
}
#endif /* HAVE_NFS4_ACL */
return (ret);
}
/*
* 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},
#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},
{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
};
#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_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 /* 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;
#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;
int entries;
int i;
ret = ARCHIVE_OK;
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) {
#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:
ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
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:
ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
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;
case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
break;
case ARCHIVE_ENTRY_ACL_MASK:
acl_set_tag_type(acl_entry, ACL_MASK);
break;
case ARCHIVE_ENTRY_ACL_OTHER:
acl_set_tag_type(acl_entry, ACL_OTHER);
break;
#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:
archive_set_error(a, ARCHIVE_ERRNO_MISC,
"Unknown ACL tag");
ret = ARCHIVE_FAILED;
goto exit_free;
}
#if HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL
r = 0;
switch (ae_type) {
#if HAVE_SUN_ACL
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
if (ace != NULL)
ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
else
r = -1;
break;
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
if (ace != NULL)
ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
else
r = -1;
break;
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
if (ace != NULL)
ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
else
r = -1;
break;
case ARCHIVE_ENTRY_ACL_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:
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 */
#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) {
#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
}
}
#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_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
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)
#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 /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */
@@ -39,9 +39,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_EXTATTR_H
#include <sys/extattr.h>
#endif
#if defined(HAVE_SYS_XATTR_H)
#if HAVE_SYS_XATTR_H
#include <sys/xattr.h>
#elif defined(HAVE_ATTR_XATTR_H)
#elif HAVE_ATTR_XATTR_H
#include <attr/xattr.h>
#endif
#ifdef HAVE_SYS_EA_H
@@ -575,10 +575,55 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
if (a->flags & ARCHIVE_EXTRACT_TIME)
a->todo |= TODO_TIMES;
if (a->flags & ARCHIVE_EXTRACT_ACL) {
#if ARCHIVE_ACL_DARWIN
/*
* On MacOS, platform ACLs get stored in mac_metadata, too.
* If we intend to extract mac_metadata and it is present
* we skip extracting libarchive NFSv4 ACLs.
*/
size_t metadata_size;
if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 ||
archive_entry_mac_metadata(a->entry,
&metadata_size) == NULL || metadata_size == 0)
#endif
#if ARCHIVE_ACL_LIBRICHACL
/*
* RichACLs are stored in an extended attribute.
* If we intend to extract extended attributes and have this
* attribute we skip extracting libarchive NFSv4 ACLs.
*/
short extract_acls = 1;
if (a->flags & ARCHIVE_EXTRACT_XATTR && (
archive_entry_acl_types(a->entry) &
ARCHIVE_ENTRY_ACL_TYPE_NFS4)) {
const char *attr_name;
const void *attr_value;
size_t attr_size;
int i = archive_entry_xattr_reset(a->entry);
while (i--) {
archive_entry_xattr_next(a->entry, &attr_name,
&attr_value, &attr_size);
if (attr_name != NULL && attr_value != NULL &&
attr_size > 0 && strcmp(attr_name,
"trusted.richacl") == 0) {
extract_acls = 0;
break;
}
}
}
if (extract_acls)
#endif
#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
{
#endif
if (archive_entry_filetype(a->entry) == AE_IFDIR)
a->deferred |= TODO_ACLS;
else
a->todo |= TODO_ACLS;
#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
}
#endif
}
if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) {
if (archive_entry_filetype(a->entry) == AE_IFDIR)
@@ -619,8 +664,21 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
}
#endif
if (a->flags & ARCHIVE_EXTRACT_XATTR)
if (a->flags & ARCHIVE_EXTRACT_XATTR) {
#if ARCHIVE_XATTR_DARWIN
/*
* On MacOS, extended attributes get stored in mac_metadata,
* too. If we intend to extract mac_metadata and it is present
* we skip extracting extended attributes.
*/
size_t metadata_size;
if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 ||
archive_entry_mac_metadata(a->entry,
&metadata_size) == NULL || metadata_size == 0)
#endif
a->todo |= TODO_XATTR;
}
if (a->flags & ARCHIVE_EXTRACT_FFLAGS)
a->todo |= TODO_FFLAGS;
if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) {
@@ -1703,25 +1761,11 @@ _archive_write_disk_finish_entry(struct archive *_a)
*/
if (a->todo & TODO_ACLS) {
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 ((a->todo & TODO_MAC_METADATA) == 0 ||
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));
archive_entry_acl(a->entry),
archive_entry_mode(a->entry));
if (r2 < ret) ret = r2;
#ifdef HAVE_DARWIN_ACL
}
#endif
}
finish_metadata:
@@ -2293,13 +2337,8 @@ _archive_write_disk_close(struct archive *_a)
if (p->fixup & TODO_MODE_BASE)
chmod(p->name, p->mode);
if (p->fixup & TODO_ACLS)
#ifdef HAVE_DARWIN_ACL
if ((p->fixup & TODO_MAC_METADATA) == 0 ||
p->mac_metadata == NULL ||
p->mac_metadata_size == 0)
#endif
archive_write_disk_set_acls(&a->archive,
-1, p->name, &p->acl);
archive_write_disk_set_acls(&a->archive, -1, p->name,
&p->acl, p->mode);
if (p->fixup & TODO_FFLAGS)
set_fflags_platform(a, -1, p->name,
p->mode, p->fflags_set, 0);
@@ -2467,7 +2506,7 @@ fsobj_error(int *a_eno, struct archive_string *a_estr,
if (a_eno)
*a_eno = err;
if (a_estr)
archive_string_sprintf(a_estr, errstr, path);
archive_string_sprintf(a_estr, "%s%s", errstr, path);
}
/*
@@ -2573,7 +2612,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
* with the deep-directory editing.
*/
fsobj_error(a_eno, a_estr, errno,
"Could not stat %s", path);
"Could not stat ", path);
res = ARCHIVE_FAILED;
break;
}
@@ -2582,7 +2621,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
if (chdir(head) != 0) {
tail[0] = c;
fsobj_error(a_eno, a_estr, errno,
"Could not chdir %s", path);
"Could not chdir ", path);
res = (ARCHIVE_FATAL);
break;
}
@@ -2599,7 +2638,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
if (unlink(head)) {
tail[0] = c;
fsobj_error(a_eno, a_estr, errno,
"Could not remove symlink %s",
"Could not remove symlink ",
path);
res = ARCHIVE_FAILED;
break;
@@ -2618,7 +2657,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
/*
if (!S_ISLNK(path)) {
fsobj_error(a_eno, a_estr, 0,
"Removing symlink %s", path);
"Removing symlink ", path);
}
*/
/* Symlink gone. No more problem! */
@@ -2630,7 +2669,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
tail[0] = c;
fsobj_error(a_eno, a_estr, 0,
"Cannot remove intervening "
"symlink %s", path);
"symlink ", path);
res = ARCHIVE_FAILED;
break;
}
@@ -2652,7 +2691,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
} else {
fsobj_error(a_eno, a_estr,
errno,
"Could not stat %s", path);
"Could not stat ", path);
res = (ARCHIVE_FAILED);
break;
}
@@ -2661,7 +2700,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
tail[0] = c;
fsobj_error(a_eno, a_estr,
errno,
"Could not chdir %s", path);
"Could not chdir ", path);
res = (ARCHIVE_FATAL);
break;
}
@@ -2674,14 +2713,14 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
tail[0] = c;
fsobj_error(a_eno, a_estr, 0,
"Cannot extract through "
"symlink %s", path);
"symlink ", path);
res = ARCHIVE_FAILED;
break;
}
} else {
tail[0] = c;
fsobj_error(a_eno, a_estr, 0,
"Cannot extract through symlink %s", path);
"Cannot extract through symlink ", path);
res = ARCHIVE_FAILED;
break;
}
@@ -4044,71 +4083,98 @@ skip_appledouble:
}
#endif
#if HAVE_LSETXATTR || HAVE_LSETEA
#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX
/*
* Restore extended attributes - Linux and AIX implementations:
* Restore extended attributes - Linux, Darwin and AIX implementations:
* AIX' ea interface is syntaxwise identical to the Linux xattr interface.
*/
static int
set_xattrs(struct archive_write_disk *a)
{
struct archive_entry *entry = a->entry;
static int warning_done = 0;
struct archive_string errlist;
int ret = ARCHIVE_OK;
int i = archive_entry_xattr_reset(entry);
short fail = 0;
archive_string_init(&errlist);
while (i--) {
const char *name;
const void *value;
size_t size;
int e;
archive_entry_xattr_next(entry, &name, &value, &size);
if (name != NULL &&
strncmp(name, "xfsroot.", 8) != 0 &&
strncmp(name, "system.", 7) != 0) {
int e;
#if HAVE_FSETXATTR
if (a->fd >= 0)
e = fsetxattr(a->fd, name, value, size, 0);
else
#elif HAVE_FSETEA
if (a->fd >= 0)
e = fsetea(a->fd, name, value, size, 0);
else
if (name == NULL)
continue;
#if ARCHIVE_XATTR_LINUX
/* Linux: quietly skip POSIX.1e ACL extended attributes */
if (strncmp(name, "system.", 7) == 0 &&
(strcmp(name + 7, "posix_acl_access") == 0 ||
strcmp(name + 7, "posix_acl_default") == 0))
continue;
if (strncmp(name, "trusted.SGI_", 12) == 0 &&
(strcmp(name + 12, "ACL_DEFAULT") == 0 ||
strcmp(name + 12, "ACL_FILE") == 0))
continue;
/* Linux: xfsroot namespace is obsolete and unsupported */
if (strncmp(name, "xfsroot.", 8) == 0) {
fail = 1;
archive_strcat(&errlist, name);
archive_strappend_char(&errlist, ' ');
continue;
}
#endif
{
#if HAVE_LSETXATTR
e = lsetxattr(archive_entry_pathname(entry),
name, value, size, 0);
#elif HAVE_LSETEA
e = lsetea(archive_entry_pathname(entry),
name, value, size, 0);
if (a->fd >= 0) {
#if ARCHIVE_XATTR_LINUX
e = fsetxattr(a->fd, name, value, size, 0);
#elif ARCHIVE_XATTR_DARWIN
e = fsetxattr(a->fd, name, value, size, 0, 0);
#elif ARCHIVE_XATTR_AIX
e = fsetea(a->fd, name, value, size, 0);
#endif
}
if (e == -1) {
if (errno == ENOTSUP || errno == ENOSYS) {
if (!warning_done) {
warning_done = 1;
archive_set_error(&a->archive,
errno,
"Cannot restore extended "
"attributes on this file "
"system");
}
} else
archive_set_error(&a->archive, errno,
"Failed to set extended attribute");
ret = ARCHIVE_WARN;
}
} else {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid extended attribute encountered");
#if ARCHIVE_XATTR_LINUX
e = lsetxattr(archive_entry_pathname(entry),
name, value, size, 0);
#elif ARCHIVE_XATTR_DARWIN
e = setxattr(archive_entry_pathname(entry),
name, value, size, 0, XATTR_NOFOLLOW);
#elif ARCHIVE_XATTR_AIX
e = lsetea(archive_entry_pathname(entry),
name, value, size, 0);
#endif
}
if (e == -1) {
ret = ARCHIVE_WARN;
archive_strcat(&errlist, name);
archive_strappend_char(&errlist, ' ');
if (errno != ENOTSUP && errno != ENOSYS)
fail = 1;
}
}
if (ret == ARCHIVE_WARN) {
if (fail && errlist.length > 0) {
errlist.length--;
errlist.s[errlist.length] = '\0';
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore extended attributes: %s",
errlist.s);
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore extended "
"attributes on this file system.");
}
archive_string_free(&errlist);
return (ret);
}
#elif HAVE_EXTATTR_SET_FILE && HAVE_DECL_EXTATTR_NAMESPACE_USER
#elif ARCHIVE_XATTR_FREEBSD
/*
* Restore extended attributes - FreeBSD implementation
*/
@@ -4116,9 +4182,12 @@ static int
set_xattrs(struct archive_write_disk *a)
{
struct archive_entry *entry = a->entry;
static int warning_done = 0;
struct archive_string errlist;
int ret = ARCHIVE_OK;
int i = archive_entry_xattr_reset(entry);
short fail = 0;
archive_string_init(&errlist);
while (i--) {
const char *name;
@@ -4134,46 +4203,47 @@ set_xattrs(struct archive_write_disk *a)
name += 5;
namespace = EXTATTR_NAMESPACE_USER;
} else {
/* Warn about other extended attributes. */
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't restore extended attribute ``%s''",
name);
/* Other namespaces are unsupported */
archive_strcat(&errlist, name);
archive_strappend_char(&errlist, ' ');
fail = 1;
ret = ARCHIVE_WARN;
continue;
}
errno = 0;
#if HAVE_EXTATTR_SET_FD
if (a->fd >= 0)
if (a->fd >= 0) {
e = extattr_set_fd(a->fd, namespace, name,
value, size);
else
#endif
/* TODO: should we use extattr_set_link() instead? */
{
e = extattr_set_file(
} else {
e = extattr_set_link(
archive_entry_pathname(entry), namespace,
name, value, size);
}
if (e != (int)size) {
if (errno == ENOTSUP || errno == ENOSYS) {
if (!warning_done) {
warning_done = 1;
archive_set_error(&a->archive,
errno,
"Cannot restore extended "
"attributes on this file "
"system");
}
} else {
archive_set_error(&a->archive, errno,
"Failed to set extended attribute");
}
archive_strcat(&errlist, name);
archive_strappend_char(&errlist, ' ');
ret = ARCHIVE_WARN;
if (errno != ENOTSUP && errno != ENOSYS)
fail = 1;
}
}
}
if (ret == ARCHIVE_WARN) {
if (fail && errlist.length > 0) {
errlist.length--;
errlist.s[errlist.length] = '\0';
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore extended attributes: %s",
errlist.s);
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Cannot restore extended "
"attributes on this file system.");
}
archive_string_free(&errlist);
return (ret);
}
#else
@@ -4239,5 +4309,19 @@ older(struct stat *st, struct archive_entry *entry)
return (0);
}
#ifndef ARCHIVE_ACL_SUPPORT
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
struct archive_acl *abstract_acl, __LA_MODE_T mode)
{
(void)a; /* UNUSED */
(void)fd; /* UNUSED */
(void)name; /* UNUSED */
(void)abstract_acl; /* UNUSED */
(void)mode; /* UNUSED */
return (ARCHIVE_OK);
}
#endif
#endif /* !_WIN32 || __CYGWIN__ */
@@ -33,11 +33,13 @@
#ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
#define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
#include "archive_platform_acl.h"
#include "archive_acl_private.h"
#include "archive_entry.h"
struct archive_write_disk;
int
archive_write_disk_set_acls(struct archive *, int /* fd */, const char * /* pathname */, struct archive_acl *);
int archive_write_disk_set_acls(struct archive *, int, const char *,
struct archive_acl *, __LA_MODE_T);
#endif
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 2, 2012
.Dd February 28, 2017
.Dt ARCHIVE_WRITE_FINISH_ENTRY 3
.Os
.Sh NAME
@@ -45,6 +45,9 @@ is called automatically by
and
.Fn archive_write_close
as needed.
For
.Tn archive_write_disk
handles, this flushes pending file attribute changes like modification time.
.\" .Sh EXAMPLE
.Sh RETURN VALUES
This function returns
@@ -108,7 +108,6 @@ Streaming Archive Library (libarchive, -larchive)
These functions set the format that will be used for the archive.
.Pp
The library can write a variety of common archive formats.
.Bl -tag -width indent
.It Fn archive_write_set_format
Sets the format based on the format code (see
@@ -38,7 +38,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format.c 201168 2009-1
#include "archive_private.h"
/* A table that maps format codes to functions. */
static
static const
struct { int code; int (*setter)(struct archive *); } codes[] =
{
{ ARCHIVE_FORMAT_7ZIP, archive_write_set_format_7zip },
@@ -41,7 +41,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_by_name.c 20116
#include "archive_private.h"
/* A table that maps names to functions. */
static
static const
struct { const char *name; int (*setter)(struct archive *); } names[] =
{
{ "7zip", archive_write_set_format_7zip },
@@ -42,7 +42,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_by_name.c 20116
#include "archive_private.h"
/* A table that maps names to functions. */
static
static const
struct { const char *name; int (*format)(struct archive *); int (*filter)(struct archive *); } names[] =
{
{ ".7z", archive_write_set_format_7zip, archive_write_add_filter_none},
@@ -1196,8 +1196,12 @@ archive_write_pax_header(struct archive_write *a,
"GNU.sparse.major", 1);
add_pax_attr_int(&(pax->pax_header),
"GNU.sparse.minor", 0);
/*
* Make sure to store the original path, since
* truncation to ustar limit happened already.
*/
add_pax_attr(&(pax->pax_header),
"GNU.sparse.name", entry_name.s);
"GNU.sparse.name", path);
add_pax_attr_int(&(pax->pax_header),
"GNU.sparse.realsize",
archive_entry_size(entry_main));
@@ -1650,13 +1654,14 @@ build_pax_attribute_name(char *dest, const char *src)
* GNU PAX Format 1.0 requires the special name, which pattern is:
* <dir>/GNUSparseFile.<pid>/<original file name>
*
* Since reproducable archives are more important, use 0 as pid.
*
* This function is used for only Sparse file, a file type of which
* is regular file.
*/
static char *
build_gnu_sparse_name(char *dest, const char *src)
{
char buff[64];
const char *p;
/* Handle the null filename case. */
@@ -1682,15 +1687,9 @@ build_gnu_sparse_name(char *dest, const char *src)
break;
}
#if HAVE_GETPID && 0 /* Disable this as pax attribute name. */
sprintf(buff, "GNUSparseFile.%d", getpid());
#else
/* If the platform can't fetch the pid, don't include it. */
strcpy(buff, "GNUSparseFile");
#endif
/* General case: build a ustar-compatible name adding
* "/GNUSparseFile/". */
build_ustar_entry_name(dest, src, p - src, buff);
build_ustar_entry_name(dest, src, p - src, "GNUSparseFile.0");
return (dest);
}
@@ -354,7 +354,7 @@ static ssize_t
_popul_ehdr(struct archive_string *tgt, size_t tsz, warc_essential_hdr_t hdr)
{
static const char _ver[] = "WARC/1.0\r\n";
static const char *_typ[LAST_WT] = {
static const char * const _typ[LAST_WT] = {
NULL, "warcinfo", "metadata", "resource", NULL
};
char std_uuid[48U];
+224 -127
View File
@@ -22,141 +22,238 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: head/lib/libarchive/config_freebsd.h 201079 2009-12-28 02:01:42Z kientzle $
* $FreeBSD$
*/
/* FreeBSD 5.0 and later have ACL and extattr support. */
#include <osreldate.h>
/* FreeBSD 5.0 and later has ACL and extattr support. */
#if __FreeBSD__ > 4
#define HAVE_ACL_CREATE_ENTRY 1
#define HAVE_ACL_GET_FD_NP 1
#define HAVE_ACL_GET_LINK_NP 1
#define HAVE_ACL_GET_PERM_NP 1
#define HAVE_ACL_INIT 1
#define HAVE_ACL_SET_FD 1
#define HAVE_ACL_SET_FD_NP 1
#define HAVE_ACL_SET_FILE 1
#define HAVE_ACL_USER 1
#define HAVE_EXTATTR_GET_FILE 1
#define HAVE_EXTATTR_LIST_FILE 1
#define HAVE_EXTATTR_SET_FD 1
#define HAVE_EXTATTR_SET_FILE 1
#define HAVE_STRUCT_XVFSCONF 1
#define HAVE_SYS_ACL_H 1
#define HAVE_SYS_EXTATTR_H 1
#endif
#define ARCHIVE_ACL_FREEBSD 1
#define HAVE_ACL_GET_PERM_NP 1
#define HAVE_ARC4RANDOM_BUF 1
#define HAVE_EXTATTR_GET_FILE 1
#define HAVE_EXTATTR_LIST_FILE 1
#define HAVE_EXTATTR_SET_FD 1
#define HAVE_EXTATTR_SET_FILE 1
#define HAVE_STRUCT_XVFSCONF 1
#define HAVE_SYS_ACL_H 1
#define HAVE_SYS_EXTATTR_H 1
#if __FreeBSD__ > 7
/* FreeBSD 8.0 and later has NFSv4 ACL support */
#define ARCHIVE_ACL_FREEBSD_NFS4 1
#define HAVE_ACL_GET_LINK_NP 1
#define HAVE_ACL_IS_TRIVIAL_NP 1
#define HAVE_ACL_SET_LINK_NP 1
#endif /* __FreeBSD__ > 7 */
#endif /* __FreeBSD__ > 4 */
#ifdef WITH_OPENSSL
#define HAVE_OPENSSL_MD5_H 1
#define HAVE_OPENSSL_RIPEMD_H 1
#define HAVE_OPENSSL_SHA_H 1
#define HAVE_SHA384 1
#define HAVE_SHA512 1
#define HAVE_LIBCRYPTO 1
#define HAVE_OPENSSL_EVP_H 1
#define HAVE_OPENSSL_MD5_H 1
#define HAVE_OPENSSL_RIPEMD_H 1
#define HAVE_OPENSSL_SHA_H 1
#define HAVE_OPENSSL_SHA256_INIT 1
#define HAVE_OPENSSL_SHA384_INIT 1
#define HAVE_OPENSSL_SHA512_INIT 1
#define HAVE_PKCS5_PBKDF2_HMAC_SHA1 1
#define HAVE_SHA256 1
#define HAVE_SHA384 1
#define HAVE_SHA512 1
#else
#define HAVE_LIBMD 1
#define HAVE_MD5_H 1
#define HAVE_MD5INIT 1
#define HAVE_RIPEMD_H 1
#define HAVE_SHA_H 1
#define HAVE_SHA1 1
#define HAVE_SHA1_INIT 1
#define HAVE_SHA256 1
#define HAVE_SHA256_H 1
#define HAVE_SHA256_INIT 1
#define HAVE_SHA512 1
#define HAVE_SHA512_H 1
#define HAVE_SHA512_INIT 1
#endif
#define HAVE_BSDXML_H 1
#define HAVE_BZLIB_H 1
#define HAVE_CHFLAGS 1
#define HAVE_CHOWN 1
#define HAVE_DECL_INT64_MAX 1
#define HAVE_DECL_INT64_MIN 1
#define HAVE_DECL_SIZE_MAX 1
#define HAVE_DECL_SSIZE_MAX 1
#define HAVE_DECL_STRERROR_R 1
#define HAVE_DECL_UINT32_MAX 1
#define HAVE_DECL_UINT64_MAX 1
#define HAVE_DIRENT_H 1
#define HAVE_EFTYPE 1
#define HAVE_EILSEQ 1
#define HAVE_ERRNO_H 1
#define HAVE_FCHDIR 1
#define HAVE_FCHFLAGS 1
#define HAVE_FCHMOD 1
#define HAVE_FCHOWN 1
#define HAVE_FCNTL 1
#define HAVE_FCNTL_H 1
#define HAVE_FSEEKO 1
#define HAVE_FSTAT 1
#define HAVE_FTRUNCATE 1
#define HAVE_FUTIMES 1
#define HAVE_GETEUID 1
#define HAVE_GETGRGID_R 1
#define HAVE_GETPID 1
#define HAVE_GETPWUID_R 1
#define HAVE_GRP_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_LCHFLAGS 1
#define HAVE_LCHMOD 1
#define HAVE_LCHOWN 1
#define HAVE_LIMITS_H 1
#define HAVE_LINK 1
#define HAVE_LSTAT 1
#define HAVE_LUTIMES 1
#define HAVE_MALLOC 1
#define HAVE_MD5 1
#define HAVE_MD5_H 1
#define HAVE_MEMMOVE 1
#define HAVE_MKDIR 1
#define HAVE_MKFIFO 1
#define HAVE_MKNOD 1
#define HAVE_PIPE 1
#define HAVE_POLL 1
#define HAVE_POLL_H 1
#define HAVE_PWD_H 1
#define HAVE_READLINK 1
#define HAVE_RMD160 1
#define HAVE_SELECT 1
#define HAVE_SETENV 1
#define HAVE_SHA_H 1
#define HAVE_SHA1 1
#define HAVE_SHA256 1
#define HAVE_SHA256_H 1
#define HAVE_SIGNAL_H 1
#define HAVE_STDINT_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRCHR 1
#define HAVE_STRDUP 1
#define HAVE_STRERROR 1
#define HAVE_STRERROR_R 1
#define HAVE_STRINGS_H 1
#define HAVE_STRING_H 1
#define HAVE_STRRCHR 1
#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1
#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1
#define HAVE_STRUCT_STAT_ST_FLAGS 1
#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
#define HAVE_STRUCT_TM_TM_GMTOFF 1
#define HAVE_SYMLINK 1
#define HAVE_SYS_CDEFS_H 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_SYS_MOUNT_H 1
#define HAVE_SYS_PARAM_H 1
#define HAVE_SYS_SELECT_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TYPES_H 1
#undef HAVE_SYS_UTIME_H
#define HAVE_SYS_UTSNAME_H 1
#define HAVE_SYS_WAIT_H 1
#define HAVE_TIMEGM 1
#define HAVE_TZSET 1
#define HAVE_UNISTD_H 1
#define HAVE_UNSETENV 1
#define HAVE_UTIME 1
#define HAVE_UTIMES 1
#define HAVE_UTIME_H 1
#define HAVE_VFORK 1
#define HAVE_WCHAR_H 1
#define HAVE_WCSCPY 1
#define HAVE_WCSLEN 1
#define HAVE_WCTOMB 1
#define HAVE_WMEMCMP 1
#define HAVE_WMEMCPY 1
#define HAVE_ZLIB_H 1
#define TIME_WITH_SYS_TIME 1
#define HAVE_BSDXML_H 1
#define HAVE_BZLIB_H 1
#define HAVE_CHFLAGS 1
#define HAVE_CHOWN 1
#define HAVE_CHROOT 1
#define HAVE_CTIME_R 1
#define HAVE_CTYPE_H 1
#define HAVE_DECL_EXTATTR_NAMESPACE_USER 1
#define HAVE_DECL_INT32_MAX 1
#define HAVE_DECL_INT32_MIN 1
#define HAVE_DECL_INT64_MAX 1
#define HAVE_DECL_INT64_MIN 1
#define HAVE_DECL_INTMAX_MAX 1
#define HAVE_DECL_INTMAX_MIN 1
#define HAVE_DECL_SIZE_MAX 1
#define HAVE_DECL_SSIZE_MAX 1
#define HAVE_DECL_STRERROR_R 1
#define HAVE_DECL_UINT32_MAX 1
#define HAVE_DECL_UINT64_MAX 1
#define HAVE_DECL_UINTMAX_MAX 1
#define HAVE_DIRENT_H 1
#define HAVE_DLFCN_H 1
#define HAVE_D_MD_ORDER 1
#define HAVE_EFTYPE 1
#define HAVE_EILSEQ 1
#define HAVE_ERRNO_H 1
#define HAVE_FCHDIR 1
#define HAVE_FCHFLAGS 1
#define HAVE_FCHMOD 1
#define HAVE_FCHOWN 1
#define HAVE_FCNTL 1
#define HAVE_FCNTL_H 1
#define HAVE_FDOPENDIR 1
#define HAVE_FORK 1
#define HAVE_FSEEKO 1
#define HAVE_FSTAT 1
#define HAVE_FSTATAT 1
#define HAVE_FSTATFS 1
#define HAVE_FSTATVFS 1
#define HAVE_FTRUNCATE 1
#define HAVE_FUTIMES 1
#define HAVE_FUTIMESAT 1
#define HAVE_GETEUID 1
#define HAVE_GETGRGID_R 1
#define HAVE_GETGRNAM_R 1
#define HAVE_GETPID 1
#define HAVE_GETPWNAM_R 1
#define HAVE_GETPWUID_R 1
#define HAVE_GETVFSBYNAME 1
#define HAVE_GMTIME_R 1
#define HAVE_GRP_H 1
#define HAVE_INTMAX_T 1
#define HAVE_INTTYPES_H 1
#define HAVE_LANGINFO_H 1
#define HAVE_LCHFLAGS 1
#define HAVE_LCHMOD 1
#define HAVE_LCHOWN 1
#define HAVE_LIBZ 1
#define HAVE_LIMITS_H 1
#define HAVE_LINK 1
#define HAVE_LOCALE_H 1
#define HAVE_LOCALTIME_R 1
#define HAVE_LONG_LONG_INT 1
#define HAVE_LSTAT 1
#define HAVE_LUTIMES 1
#define HAVE_MBRTOWC 1
#define HAVE_MEMMOVE 1
#define HAVE_MEMORY_H 1
#define HAVE_MEMSET 1
#define HAVE_MKDIR 1
#define HAVE_MKFIFO 1
#define HAVE_MKNOD 1
#define HAVE_MKSTEMP 1
#define HAVE_NL_LANGINFO 1
#define HAVE_OPENAT 1
#define HAVE_PATHS_H 1
#define HAVE_PIPE 1
#define HAVE_POLL 1
#define HAVE_POLL_H 1
#define HAVE_POSIX_SPAWNP 1
#define HAVE_PTHREAD_H 1
#define HAVE_PWD_H 1
#define HAVE_READDIR_R 1
#define HAVE_READLINK 1
#define HAVE_READLINKAT 1
#define HAVE_READPASSPHRASE 1
#define HAVE_READPASSPHRASE_H 1
#define HAVE_REGEX_H 1
#define HAVE_SELECT 1
#define HAVE_SETENV 1
#define HAVE_SETLOCALE 1
#define HAVE_SIGACTION 1
#define HAVE_SIGNAL_H 1
#define HAVE_SPAWN_H 1
#define HAVE_STATFS 1
#define HAVE_STATVFS 1
#define HAVE_STDARG_H 1
#define HAVE_STDINT_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRCHR 1
#define HAVE_STRDUP 1
#define HAVE_STRERROR 1
#define HAVE_STRERROR_R 1
#define HAVE_STRFTIME 1
#define HAVE_STRINGS_H 1
#define HAVE_STRING_H 1
#define HAVE_STRRCHR 1
#define HAVE_STRUCT_STATFS_F_NAMEMAX 1
#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1
#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1
#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
#define HAVE_STRUCT_STAT_ST_FLAGS 1
#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
#define HAVE_STRUCT_TM_TM_GMTOFF 1
#define HAVE_SYMLINK 1
#define HAVE_SYS_CDEFS_H 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_SYS_MOUNT_H 1
#define HAVE_SYS_PARAM_H 1
#define HAVE_SYS_POLL_H 1
#define HAVE_SYS_SELECT_H 1
#define HAVE_SYS_STATVFS_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_UTSNAME_H 1
#define HAVE_SYS_WAIT_H 1
#define HAVE_TIMEGM 1
#define HAVE_TIME_H 1
#define HAVE_TZSET 1
#define HAVE_UINTMAX_T 1
#define HAVE_UNISTD_H 1
#define HAVE_UNSETENV 1
#define HAVE_UNSIGNED_LONG_LONG 1
#define HAVE_UNSIGNED_LONG_LONG_INT 1
#define HAVE_UTIME 1
#define HAVE_UTIMES 1
#define HAVE_UTIME_H 1
#define HAVE_VFORK 1
#define HAVE_VPRINTF 1
#define HAVE_WCHAR_H 1
#define HAVE_WCHAR_T 1
#define HAVE_WCRTOMB 1
#define HAVE_WCSCMP 1
#define HAVE_WCSCPY 1
#define HAVE_WCSLEN 1
#define HAVE_WCTOMB 1
#define HAVE_WCTYPE_H 1
#define HAVE_WMEMCMP 1
#define HAVE_WMEMCPY 1
#define HAVE_WMEMMOVE 1
#define HAVE_ZLIB_H 1
#define TIME_WITH_SYS_TIME 1
#if __FreeBSD_version >= 1100056
#define HAVE_FUTIMENS 1
#define HAVE_UTIMENSAT 1
#endif
/* FreeBSD 4 and earlier lack intmax_t/uintmax_t */
#if __FreeBSD__ < 5
#define intmax_t int64_t
#define uintmax_t uint64_t
#define intmax_t int64_t
#define uintmax_t uint64_t
#endif
/* FreeBSD defines for archive_hash.h */
#ifdef WITH_OPENSSL
#define ARCHIVE_CRYPTO_MD5_OPENSSL 1
#define ARCHIVE_CRYPTO_RMD160_OPENSSL 1
#define ARCHIVE_CRYPTO_SHA1_OPENSSL
#define ARCHIVE_CRYPTO_SHA256_OPENSSL 1
#define ARCHIVE_CRYPTO_SHA384_OPENSSL 1
#define ARCHIVE_CRYPTO_SHA512_OPENSSL 1
#else
#define ARCHIVE_CRYPTO_MD5_LIBMD 1
#define ARCHIVE_CRYPTO_SHA1_LIBMD 1
#define ARCHIVE_CRYPTO_SHA256_LIBMD 1
#define ARCHIVE_CRYPTO_SHA512_LIBMD 1
#endif
@@ -28,6 +28,7 @@
.Dt LIBARCHIVE_CHANGES 3
.Os
.Sh NAME
.Nm libarchive_changes
.Nd changes in libarchive interface
.\"
.Sh CHANGES IN LIBARCHIVE 3
+1 -1
View File
@@ -48,7 +48,7 @@ Leading whitespace is always ignored.
.Pp
When encoding file or pathnames, any backslash character or
character outside of the 95 printable ASCII characters must be
encoded as a a backslash followed by three
encoded as a backslash followed by three
octal digits.
When reading mtree files, any appearance of a backslash
followed by three octal digits should be converted into the
+9 -3
View File
@@ -141,13 +141,19 @@ typedef struct _U32_S { U32 v; } _PACKED U32_S;
# pragma pack(pop)
#endif
#define A32(x) (((const U32_S *)(x))->v)
/****************************************
** Compiler-specific Functions and Macros
*****************************************/
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#define GCC_VERSION ((__GNUC__-0) * 100 + (__GNUC_MINOR__ - 0))
#if GCC_VERSION >= 409
__attribute__((__no_sanitize_undefined__))
#endif
static inline U32 A32(const void * x)
{
return (((const U32_S *)(x))->v);
}
/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
#if defined(_MSC_VER)