mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-05 05:39:57 -05:00
Merge topic 'update-libarchive'
c80d8cb2libarchive: Fix inclusion of zlib, bzlib, and lzma for build within CMake6df1bda1Merge branch 'upstream-LibArchive' into update-libarchive11f3dcb0LibArchive 2017-07-09 (98a69539)b6674431libarchive: Update script to get 3.3.2 Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !1071
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
#
|
||||
|
||||
@@ -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 @@
|
||||
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})
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user