summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt69
-rw-r--r--NEWS2
-rw-r--r--build/cmake/config.h.in8
-rw-r--r--cat/test/CMakeLists.txt7
-rw-r--r--configure.ac45
-rw-r--r--cpio/test/CMakeLists.txt7
-rw-r--r--libarchive/archive_acl_maps_linux.c41
-rw-r--r--libarchive/archive_platform_acl.h3
-rw-r--r--libarchive/archive_read_disk_acl_linux.c142
-rw-r--r--libarchive/archive_write_disk_acl_darwin.c4
-rw-r--r--libarchive/archive_write_disk_acl_freebsd.c4
-rw-r--r--libarchive/archive_write_disk_acl_linux.c198
-rw-r--r--libarchive/archive_write_disk_acl_sunos.c4
-rw-r--r--libarchive/archive_write_disk_posix.c103
-rw-r--r--libarchive/archive_write_disk_private.h7
-rw-r--r--libarchive/test/test_acl_platform_nfs4.c324
-rw-r--r--tar/test/CMakeLists.txt7
-rw-r--r--test_utils/test_main.c25
18 files changed, 827 insertions, 173 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c91b1dea..f62153cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -602,6 +602,7 @@ 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)
@@ -1739,21 +1740,59 @@ int main(void) { return ACL_SYNCHRONIZE; }" HAVE_DECL_ACL_SYNCHRONIZE)
ENDIF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND
HAVE_ACL_TAG_T)
-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)
- MESSAGE(STATUS "ACL support: libacl (POSIX.1e)")
-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()
+ # 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()
ELSE(ENABLE_ACL)
# If someone runs cmake, then disables ACL support, we need
diff --git a/NEWS b/NEWS
index fdd971d7..9e517934 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,5 @@
+Mar 16, 2017: NFSv4 ACL support for Linux (librichacl)
+
Feb 26, 2017: libarchive 3.3.1 released
Security & Feature release
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index c46a341a..cfd2a5c0 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -188,9 +188,12 @@ typedef uint64_t uintmax_t;
/* FreeBSD NFSv4 ACL support */
#cmakedefine ARCHIVE_ACL_FREEBSD_NFS4 1
-/* Linux ACL support via libacl */
+/* 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
@@ -1031,6 +1034,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
diff --git a/cat/test/CMakeLists.txt b/cat/test/CMakeLists.txt
index 0623cc36..0cd3aad8 100644
--- a/cat/test/CMakeLists.txt
+++ b/cat/test/CMakeLists.txt
@@ -30,9 +30,14 @@ IF(ENABLE_CAT AND ENABLE_TEST)
#
ADD_EXECUTABLE(bsdcat_test ${bsdcat_test_SOURCES})
IF(ENABLE_ACL)
+ SET(TEST_ACL_LIBS "")
IF(HAVE_LIBACL)
- TARGET_LINK_LIBRARIES(bsdcat_test ${ACL_LIBRARY})
+ LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY})
ENDIF(HAVE_LIBACL)
+ IF(HAVE_LIBRICHACL)
+ LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY})
+ ENDIF(HAVE_LIBRICHACL)
+ TARGET_LINK_LIBRARIES(bsdcat_test ${TEST_ACL_LIBS})
ENDIF(ENABLE_ACL)
SET_PROPERTY(TARGET bsdcat_test PROPERTY COMPILE_DEFINITIONS LIST_H)
diff --git a/configure.ac b/configure.ac
index 24e96d68..05b5a099 100644
--- a/configure.ac
+++ b/configure.ac
@@ -289,7 +289,8 @@ AC_CHECK_HEADERS([readpassphrase.h signal.h spawn.h])
AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.h])
AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/extattr.h])
AC_CHECK_HEADERS([sys/ioctl.h sys/mkdev.h sys/mount.h])
-AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/select.h sys/statfs.h sys/statvfs.h])
+AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/richacl.h])
+AC_CHECK_HEADERS([sys/select.h sys/statfs.h sys/statvfs.h])
AC_CHECK_HEADERS([sys/time.h sys/utime.h sys/utsname.h sys/vfs.h])
AC_CHECK_HEADERS([time.h unistd.h utime.h wchar.h wctype.h])
AC_CHECK_HEADERS([windows.h])
@@ -712,9 +713,31 @@ if test "x$enable_acl" != "xno"; then
#endif
])
+ AC_CHECK_LIB([richacl], [richacl_get_file])
+
+ AC_CHECK_TYPES([[struct richace], [struct richacl]], [], [], [
+ #if HAVE_SYS_RICHACL_H
+ #include <sys/richacl.h>
+ #endif
+ ])
+
# Solaris and derivates ACLs
AC_CHECK_FUNCS(acl facl)
+ if test "x$ac_cv_lib_richacl_richacl_get_file" = "xyes" \
+ -a "x$ac_cv_type_struct_richace" = "xyes" \
+ -a "x$ac_cv_type_struct_richacl" = "xyes"; then
+ AC_CACHE_VAL([ac_cv_archive_acl_librichacl],
+ [AC_CHECK_FUNCS(richacl_alloc \
+ richacl_equiv_mode \
+ richacl_free \
+ richacl_get_fd \
+ richacl_get_file \
+ richacl_set_fd \
+ richacl_set_file,
+ [ac_cv_archive_acl_librichacl=yes], [ac_cv_archive_acl_librichacl=no], [#include <sys/richacl.h>])])
+ fi
+
if test "x$ac_cv_func_acl" = "xyes" \
-a "x$ac_cv_func_facl" = "xyes"; then
AC_CHECK_TYPES([aclent_t], [], [], [[#include <sys/acl.h>]])
@@ -833,9 +856,21 @@ if test "x$enable_acl" != "xno"; then
fi
fi
AC_MSG_CHECKING([for ACL support])
- if test "x$ac_cv_archive_acl_libacl" = "xyes"; then
+ if test "x$ac_cv_archive_acl_libacl" = "xyes" \
+ -a "x$ac_cv_archive_acl_librichacl" = "xyes"; then
+ AC_MSG_RESULT([libacl (POSIX.1e) + librichacl (NFSv4)])
+ AC_DEFINE([ARCHIVE_ACL_LIBACL], [1],
+ [Linux POSIX.1e ACL support via libacl])
+ AC_DEFINE([ARCHIVE_ACL_LIBRICHACL], [1],
+ [Linux NFSv4 ACL support via librichacl])
+ elif test "x$ac_cv_archive_acl_libacl" = "xyes"; then
AC_MSG_RESULT([libacl (POSIX.1e)])
- AC_DEFINE([ARCHIVE_ACL_LIBACL], [1], [Linux ACL support via libacl])
+ AC_DEFINE([ARCHIVE_ACL_LIBACL], [1],
+ [Linux POSIX.1e ACL support via libacl])
+ elif test "x$ac_cv_archive_acl_librichacl" = "xyes"; then
+ AC_MSG_RESULT([librichacl (NFSv4)])
+ AC_DEFINE([ARCHIVE_ACL_LIBRICHACL], [1],
+ [Linux NFSv4 ACL support via librichacl])
elif test "x$ac_cv_archive_acl_darwin" = "xyes"; then
AC_DEFINE([ARCHIVE_ACL_DARWIN], [1], [Darwin ACL support])
AC_MSG_RESULT([Darwin (limited NFSv4)])
@@ -863,7 +898,9 @@ if test "x$enable_acl" != "xno"; then
fi
-AM_CONDITIONAL([INC_LINUX_ACL], [test "x$ac_cv_archive_acl_libacl" = "xyes"])
+AM_CONDITIONAL([INC_LINUX_ACL],
+ [test "x$ac_cv_archive_acl_libacl" = "xyes" \
+ -o "x$ac_cv_archive_acl_librichacl" = "xyes"])
AM_CONDITIONAL([INC_SUNOS_ACL], [test "x$ac_cv_archive_acl_sunos" = "xyes"])
AM_CONDITIONAL([INC_DARWIN_ACL],
[test "x$ac_cv_archive_acl_darwin" = "xyes"])
diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt
index cc5fe011..4c3fb88a 100644
--- a/cpio/test/CMakeLists.txt
+++ b/cpio/test/CMakeLists.txt
@@ -63,9 +63,14 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
#
ADD_EXECUTABLE(bsdcpio_test ${bsdcpio_test_SOURCES})
IF(ENABLE_ACL)
+ SET(TEST_ACL_LIBS "")
IF(HAVE_LIBACL)
- TARGET_LINK_LIBRARIES(bsdcpio_test ${ACL_LIBRARY})
+ LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY})
ENDIF(HAVE_LIBACL)
+ IF(HAVE_LIBRICHACL)
+ LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY})
+ ENDIF(HAVE_LIBRICHACL)
+ TARGET_LINK_LIBRARIES(bsdcpio_test ${TEST_ACL_LIBS})
ENDIF(ENABLE_ACL)
SET_PROPERTY(TARGET bsdcpio_test PROPERTY COMPILE_DEFINITIONS LIST_H)
diff --git a/libarchive/archive_acl_maps_linux.c b/libarchive/archive_acl_maps_linux.c
index c184f20b..3476e12c 100644
--- a/libarchive/archive_acl_maps_linux.c
+++ b/libarchive/archive_acl_maps_linux.c
@@ -32,6 +32,9 @@
#define _ACL_PRIVATE /* For debugging */
#include <sys/acl.h>
#endif
+#ifdef HAVE_SYS_RICHACL_H
+#include <sys/richacl.h>
+#endif
#include "archive_entry.h"
#include "archive_private.h"
@@ -39,6 +42,7 @@
#define _ARCHIVE_ACL_MAPS_DEFS
#include "archive_acl_maps.h"
+#if ARCHIVE_ACL_LIBACL
const acl_perm_map_t acl_posix_perm_map[] = {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
@@ -47,3 +51,40 @@ const acl_perm_map_t acl_posix_perm_map[] = {
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
+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}
+};
+
+const int acl_nfs4_perm_map_size =
+ (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
+
+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}
+};
+
+const int acl_nfs4_flag_map_size =
+ (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
+#endif /* ARCHIVE_ACL_LIBRICHACL */
diff --git a/libarchive/archive_platform_acl.h b/libarchive/archive_platform_acl.h
index 8c091cf5..3498f78b 100644
--- a/libarchive/archive_platform_acl.h
+++ b/libarchive/archive_platform_acl.h
@@ -37,7 +37,8 @@
#define ARCHIVE_ACL_POSIX1E 1
#endif
-#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_DARWIN
+#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || \
+ ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL
#define ARCHIVE_ACL_NFS4 1
#endif
diff --git a/libarchive/archive_read_disk_acl_linux.c b/libarchive/archive_read_disk_acl_linux.c
index 23146dba..3ddee2fe 100644
--- a/libarchive/archive_read_disk_acl_linux.c
+++ b/libarchive/archive_read_disk_acl_linux.c
@@ -33,12 +33,15 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#if HAVE_ACL_LIBACL_H && HAVE_LIBACL
+#if HAVE_ACL_LIBACL_H
#include <acl/libacl.h>
#endif
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
+#if HAVE_SYS_RICHACL_H
+#include <sys/richacl.h>
+#endif
#include "archive_entry.h"
#include "archive_private.h"
@@ -49,6 +52,7 @@
#include <acl/libacl.h>
#endif
+#if ARCHIVE_ACL_LIBACL
/*
* Translate POSIX.1e ACLs into libarchive internal structure
*/
@@ -154,15 +158,104 @@ translate_acl(struct archive_read_disk *a,
}
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 */
+
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;
+#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)))
@@ -185,8 +278,50 @@ archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
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);
@@ -224,5 +359,6 @@ archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
}
}
}
- return (ARCHIVE_OK);
+#endif /* ARCHIVE_ACL_LIBACL */
+ return (r);
}
diff --git a/libarchive/archive_write_disk_acl_darwin.c b/libarchive/archive_write_disk_acl_darwin.c
index 22375c76..4ffdd66b 100644
--- a/libarchive/archive_write_disk_acl_darwin.c
+++ b/libarchive/archive_write_disk_acl_darwin.c
@@ -219,10 +219,12 @@ exit_free:
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
- struct archive_acl *abstract_acl)
+ 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,
diff --git a/libarchive/archive_write_disk_acl_freebsd.c b/libarchive/archive_write_disk_acl_freebsd.c
index d6b87671..29e64adf 100644
--- a/libarchive/archive_write_disk_acl_freebsd.c
+++ b/libarchive/archive_write_disk_acl_freebsd.c
@@ -287,10 +287,12 @@ exit_free:
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
- struct archive_acl *abstract_acl)
+ 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)
diff --git a/libarchive/archive_write_disk_acl_linux.c b/libarchive/archive_write_disk_acl_linux.c
index 15af1a1b..2239df6c 100644
--- a/libarchive/archive_write_disk_acl_linux.c
+++ b/libarchive/archive_write_disk_acl_linux.c
@@ -32,41 +32,206 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#if HAVE_ACL_LIBACL_H && HAVE_LIBACL
+#if HAVE_ACL_LIBACL_H
#include <acl/libacl.h>
#endif
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
+#if HAVE_SYS_RICHACL_H
+#include <sys/richacl.h>
+#endif
#include "archive.h"
#include "archive_entry.h"
#include "archive_write_disk_private.h"
#include "archive_acl_maps.h"
+#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;
- acl_t acl;
- acl_entry_t acl_entry;
- acl_permset_t acl_permset;
- int ret;
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;
@@ -89,12 +254,14 @@ set_acl(struct archive *a, int fd, const char *name,
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);
@@ -179,13 +346,29 @@ exit_free:
acl_free(acl);
return (ret);
}
+#endif /* ARCHIVE_ACL_LIBACL */
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
- struct archive_acl *abstract_acl)
+ 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)
@@ -200,5 +383,6 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
ret = set_acl(a, fd, name, abstract_acl,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
}
+#endif /* ARCHIVE_ACL_LIBACL */
return (ret);
}
diff --git a/libarchive/archive_write_disk_acl_sunos.c b/libarchive/archive_write_disk_acl_sunos.c
index e8002396..ebc0b095 100644
--- a/libarchive/archive_write_disk_acl_sunos.c
+++ b/libarchive/archive_write_disk_acl_sunos.c
@@ -303,10 +303,12 @@ exit_free:
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
- struct archive_acl *abstract_acl)
+ 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 */
diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
index 6c0dd19b..adb15c0e 100644
--- a/libarchive/archive_write_disk_posix.c
+++ b/libarchive/archive_write_disk_posix.c
@@ -369,10 +369,6 @@ static ssize_t hfs_write_data_block(struct archive_write_disk *,
static int fixup_appledouble(struct archive_write_disk *, const char *);
static int older(struct stat *, struct archive_entry *);
static int restore_entry(struct archive_write_disk *);
-#ifndef ARCHIVE_ACL_SUPPORT
-static int archive_write_disk_set_acls(struct archive *, int, const char *,
- struct archive_acl *);
-#endif
static int set_mac_metadata(struct archive_write_disk *, const char *,
const void *, size_t);
static int set_xattrs(struct archive_write_disk *);
@@ -429,19 +425,6 @@ lazy_stat(struct archive_write_disk *a)
return (ARCHIVE_WARN);
}
-#ifndef ARCHIVE_ACL_SUPPORT
-static 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);
-}
-#endif
-
static struct archive_vtable *
archive_write_disk_vtable(void)
{
@@ -592,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)
@@ -1720,25 +1748,11 @@ _archive_write_disk_finish_entry(struct archive *_a)
*/
if (a->todo & TODO_ACLS) {
int r2;
-#if ARCHIVE_ACL_DARWIN
- /*
- * 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;
-#if ARCHIVE_ACL_DARWIN
- }
-#endif
}
finish_metadata:
@@ -2310,13 +2324,8 @@ _archive_write_disk_close(struct archive *_a)
if (p->fixup & TODO_MODE_BASE)
chmod(p->name, p->mode);
if (p->fixup & TODO_ACLS)
-#if ARCHIVE_ACL_DARWIN
- 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);
@@ -4256,5 +4265,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__ */
diff --git a/libarchive/archive_write_disk_private.h b/libarchive/archive_write_disk_private.h
index c5814b4b..b655dea2 100644
--- a/libarchive/archive_write_disk_private.h
+++ b/libarchive/archive_write_disk_private.h
@@ -35,12 +35,11 @@
#include "archive_platform_acl.h"
#include "archive_acl_private.h"
+#include "archive_entry.h"
struct archive_write_disk;
-#if ARCHIVE_ACL_SUPPORT
-int
-archive_write_disk_set_acls(struct archive *, int /* fd */, const char * /* pathname */, struct archive_acl *);
-#endif
+int archive_write_disk_set_acls(struct archive *, int, const char *,
+ struct archive_acl *, __LA_MODE_T);
#endif
diff --git a/libarchive/test/test_acl_platform_nfs4.c b/libarchive/test/test_acl_platform_nfs4.c
index b8dce122..a3868a62 100644
--- a/libarchive/test/test_acl_platform_nfs4.c
+++ b/libarchive/test/test_acl_platform_nfs4.c
@@ -27,8 +27,13 @@
__FBSDID("$FreeBSD$");
#if ARCHIVE_ACL_NFS4
+#if HAVE_SYS_ACL_H
#define _ACL_PRIVATE
#include <sys/acl.h>
+#endif
+#if HAVE_SYS_RICHACL_H
+#include <sys/richacl.h>
+#endif
#if HAVE_MEMBERSHIP_H
#include <membership.h>
#endif
@@ -273,78 +278,96 @@ set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
}
static int
-#ifdef ARCHIVE_ACL_SUNOS_NFS4
-acl_permset_to_bitmap(uint32_t a_access_mask)
+#if ARCHIVE_ACL_SUNOS_NFS4
+acl_permset_to_bitmap(uint32_t mask)
+#elif ARCHIVE_ACL_LIBRICHACL
+acl_permset_to_bitmap(unsigned int mask)
#else
acl_permset_to_bitmap(acl_permset_t opaque_ps)
#endif
{
- static struct { int machine; int portable; } perms[] = {
+ static struct { int portable; int machine; } perms[] = {
#ifdef ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFSv4 ACL permissions */
- {ACE_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
- {ACE_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
- {ACE_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
- {ACE_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
- {ACE_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
- {ACE_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
- {ACE_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
- {ACE_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
- {ACE_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
- {ACE_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
- {ACE_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
- {ACE_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
- {ACE_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
- {ACE_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
- {ACE_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
- {ACE_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
- {ACE_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
+ {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 ARCHIVE_ACL_DARWIN /* MacOS NFSv4 ACL permissions */
- {ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
- {ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
- {ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
- {ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
- {ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
- {ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
- {ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
- {ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
- {ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
- {ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
- {ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
- {ACL_READ_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
- {ACL_WRITE_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
- {ACL_READ_SECURITY, ARCHIVE_ENTRY_ACL_READ_ACL},
- {ACL_WRITE_SECURITY, ARCHIVE_ENTRY_ACL_WRITE_ACL},
- {ACL_CHANGE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
+ {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
- {ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE},
+ {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
+#elif ARCHIVE_ACL_LIBRICHACL
+ {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}
#else /* FreeBSD NFSv4 ACL permissions */
- {ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
- {ACL_WRITE, ARCHIVE_ENTRY_ACL_WRITE},
- {ACL_READ, ARCHIVE_ENTRY_ACL_READ},
- {ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
- {ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
- {ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
- {ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
- {ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
- {ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
- {ACL_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
- {ACL_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
- {ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
- {ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
- {ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
- {ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
- {ACL_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
- {ACL_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
- {ACL_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
- {ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
+ {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}
#endif
};
int i, permset = 0;
for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
-#if ARCHIVE_ACL_SUNOS_NFS4
- if (a_access_mask & perms[i].machine)
+#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
+ if (mask & perms[i].machine)
#else
if (acl_get_perm_np(opaque_ps, perms[i].machine))
#endif
@@ -354,47 +377,55 @@ acl_permset_to_bitmap(acl_permset_t opaque_ps)
static int
#if ARCHIVE_ACL_SUNOS_NFS4
-acl_flagset_to_bitmap(uint16_t a_flags)
+acl_flagset_to_bitmap(uint16_t flags)
+#elif ARCHIVE_ACL_LIBRICHACL
+acl_flagset_to_bitmap(int flags)
#else
acl_flagset_to_bitmap(acl_flagset_t opaque_fs)
#endif
{
- static struct { int machine; int portable; } flags[] = {
+ static struct { int portable; int machine; } perms[] = {
#if ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFSv4 ACL inheritance flags */
- {ACE_FILE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
- {ACE_DIRECTORY_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
- {ACE_NO_PROPAGATE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
- {ACE_INHERIT_ONLY_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
- {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
- {ACE_FAILED_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
+ {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
- {ACE_INHERITED_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED}
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
#endif
#elif ARCHIVE_ACL_DARWIN /* MacOS NFSv4 ACL inheritance flags */
- {ACL_ENTRY_INHERITED, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED},
- {ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
- {ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
- {ACL_ENTRY_LIMIT_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
- {ACL_ENTRY_ONLY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY}
+ {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}
+#elif ARCHIVE_ACL_LIBRICHACL
+ {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}
#else /* FreeBSD NFSv4 ACL inheritance flags */
- {ACL_ENTRY_INHERITED, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED},
- {ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
- {ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
- {ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
- {ACL_ENTRY_SUCCESSFUL_ACCESS, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
- {ACL_ENTRY_FAILED_ACCESS, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
- {ACL_ENTRY_INHERIT_ONLY, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
+ {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_NO_PROPAGATE_INHERIT},
+ {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
+ {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
+ {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
#endif
};
int i, flagset = 0;
- for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); ++i)
-#if ARCHIVE_ACL_SUNOS_NFS4
- if (a_flags & flags[i].machine)
+ for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
+#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
+ if (flags & perms[i].machine)
#else
- if (acl_get_flag_np(opaque_fs, flags[i].machine))
+ if (acl_get_flag_np(opaque_fs, perms[i].machine))
#endif
- flagset |= flags[i].portable;
+ flagset |= perms[i].portable;
return flagset;
}
@@ -452,6 +483,62 @@ acl_match(ace_t *ace, struct myacl_t *myacl)
}
return (1);
}
+#elif ARCHIVE_ACL_LIBRICHACL
+static int
+acl_match(struct richace *richace, struct myacl_t *myacl)
+{
+ int perms;
+
+ perms = acl_permset_to_bitmap(richace->e_mask) |
+ acl_flagset_to_bitmap(richace->e_flags);
+
+ if (perms != myacl->permset)
+ return (0);
+
+ switch (richace->e_type) {
+ case RICHACE_ACCESS_ALLOWED_ACE_TYPE:
+ if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
+ return (0);
+ break;
+ case RICHACE_ACCESS_DENIED_ACE_TYPE:
+ if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
+ return (0);
+ break;
+ default:
+ return (0);
+ }
+
+ if (richace->e_flags & RICHACE_SPECIAL_WHO) {
+ switch (richace->e_id) {
+ case RICHACE_OWNER_SPECIAL_ID:
+ if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
+ return (0);
+ break;
+ case RICHACE_GROUP_SPECIAL_ID:
+ if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
+ return (0);
+ break;
+ case RICHACE_EVERYONE_SPECIAL_ID:
+ if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
+ return (0);
+ break;
+ default:
+ /* Invalid e_id */
+ return (0);
+ }
+ } else if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) {
+ if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
+ return (0);
+ if ((gid_t)myacl->qual != richace->e_id)
+ return (0);
+ } else {
+ if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
+ return (0);
+ if ((uid_t)myacl->qual != richace->e_id)
+ return (0);
+ }
+ return (1);
+}
#elif ARCHIVE_ACL_DARWIN
static int
acl_match(acl_entry_t aclent, struct myacl_t *myacl)
@@ -593,6 +680,8 @@ compare_acls(
#if ARCHIVE_ACL_SUNOS_NFS4
void *aclp,
int aclcnt,
+#elif ARCHIVE_ACL_LIBRICHACL
+ struct richacl *richacl,
#else
acl_t acl,
#endif
@@ -604,6 +693,10 @@ compare_acls(
#if ARCHIVE_ACL_SUNOS_NFS4
int e;
ace_t *acl_entry;
+#elif ARCHIVE_ACL_LIBRICHACL
+ int e;
+ struct richace *acl_entry;
+ int aclcnt;
#else
int entry_id = ACL_FIRST_ENTRY;
acl_entry_t acl_entry;
@@ -614,6 +707,18 @@ compare_acls(
#endif
#endif
+#if ARCHIVE_ACL_SUNOS_NFS4
+ if (aclp == NULL)
+ return;
+#elif ARCHIVE_ACL_LIBRICHACL
+ if (richacl == NULL)
+ return;
+ aclcnt = richacl->a_count;
+#else
+ if (acl == NULL)
+ return;
+#endif
+
n = end - start;
marker = malloc(sizeof(marker[0]) * (n + 1));
for (i = 0; i < n; i++)
@@ -630,7 +735,7 @@ compare_acls(
* Iterate over acls in system acl object, try to match each
* one with an item in the myacls array.
*/
-#if ARCHIVE_ACL_SUNOS_NFS4
+#if ARCHIVE_ACL_SUNOS_NFS4 || ARCHIVE_ACL_LIBRICHACL
for (e = 0; e < aclcnt; e++)
#else
while (acl_get_entry_ret == acl_get_entry(acl, entry_id, &acl_entry))
@@ -638,6 +743,8 @@ compare_acls(
{
#if ARCHIVE_ACL_SUNOS_NFS4
acl_entry = &((ace_t *)aclp)[e];
+#elif ARCHIVE_ACL_LIBRICHACL
+ acl_entry = &(richacl->a_entries[e]);
#else
/* After the first time... */
entry_id = ACL_NEXT_ENTRY;
@@ -756,6 +863,8 @@ DEFINE_TEST(test_acl_platform_nfs4)
#if ARCHIVE_ACL_SUNOS_NFS4
void *aclp;
int aclcnt;
+#elif ARCHIVE_ACL_LIBRICHACL
+ struct richacl *richacl;
#else /* !ARCHIVE_ACL_SUNOS_NFS4 */
acl_t acl;
#endif
@@ -814,21 +923,31 @@ DEFINE_TEST(test_acl_platform_nfs4)
assertEqualInt(st.st_mtime, 123456);
#if ARCHIVE_ACL_SUNOS_NFS4
aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "testall");
- failure("acl(): errno = %d (%s)", errno, strerror(errno));
+ failure("acl(\"%s\"): errno = %d (%s)", "testall", errno,
+ strerror(errno));
assert(aclp != NULL);
+#elif ARCHIVE_ACL_LIBRICHACL
+ richacl = richacl_get_file("testall");
+ failure("richacl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
+ strerror(errno));
+ assert(richacl != NULL);
#else
#if ARCHIVE_ACL_DARWIN
acl = acl_get_file("testall", ACL_TYPE_EXTENDED);
#else
acl = acl_get_file("testall", ACL_TYPE_NFS4);
#endif
- failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
+ failure("acl_get_file(\"%s\"): errno = %d (%s)", "testall", errno,
+ strerror(errno));
assert(acl != (acl_t)NULL);
#endif
#if ARCHIVE_ACL_SUNOS_NFS4
compare_acls(aclp, aclcnt, acls_reg, "testall", 0, regcnt);
free(aclp);
aclp = NULL;
+#elif ARCHIVE_ACL_LIBRICHACL
+ compare_acls(richacl, acls_reg, "testall", 0, regcnt);
+ richacl_free(richacl);
#else
compare_acls(acl, acls_reg, "testall", 0, regcnt);
acl_free(acl);
@@ -842,15 +961,25 @@ DEFINE_TEST(test_acl_platform_nfs4)
assertEqualInt(st.st_mtime, 123456 + i);
#if ARCHIVE_ACL_SUNOS_NFS4
aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, buff);
- failure("acl(): errno = %d (%s)", errno, strerror(errno));
+ failure("acl(\"%s\"): errno = %d (%s)", buff, errno,
+ strerror(errno));
assert(aclp != NULL);
+#elif ARCHIVE_ACL_LIBRICHACL
+ richacl = richacl_get_file(buff);
+ /* First and last two dir do not return a richacl */
+ if ((i == 0 || i >= dircnt - 2) && richacl == NULL &&
+ errno == ENODATA)
+ continue;
+ failure("richacl_get_file(\"%s\"): errno = %d (%s)", buff,
+ errno, strerror(errno));
+ assert(richacl != NULL);
#else
#if ARCHIVE_ACL_DARWIN
acl = acl_get_file(buff, ACL_TYPE_EXTENDED);
#else
acl = acl_get_file(buff, ACL_TYPE_NFS4);
#endif
- failure("acl_get_file(): errno = %d (%s)", errno,
+ failure("acl_get_file(\"%s\"): errno = %d (%s)", buff, errno,
strerror(errno));
assert(acl != (acl_t)NULL);
#endif
@@ -858,6 +987,9 @@ DEFINE_TEST(test_acl_platform_nfs4)
compare_acls(aclp, aclcnt, acls_dir, buff, i, i + 1);
free(aclp);
aclp = NULL;
+#elif ARCHIVE_ACL_LIBRICHACL
+ compare_acls(richacl, acls_dir, buff, i, i + 1);
+ richacl_free(richacl);
#else
compare_acls(acl, acls_dir, buff, i, i + 1);
acl_free(acl);
@@ -869,21 +1001,31 @@ DEFINE_TEST(test_acl_platform_nfs4)
assertEqualInt(st.st_mtime, 123456);
#if ARCHIVE_ACL_SUNOS_NFS4
aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "dirall");
- failure("acl(): errno = %d (%s)", errno, strerror(errno));
+ failure("acl(\"%s\"): errno = %d (%s)", "dirall", errno,
+ strerror(errno));
assert(aclp != NULL);
+#elif ARCHIVE_ACL_LIBRICHACL
+ richacl = richacl_get_file("dirall");
+ failure("richacl_get_file(\"%s\"): errno = %d (%s)", "dirall",
+ errno, strerror(errno));
+ assert(richacl != NULL);
#else
#if ARCHIVE_ACL_DARWIN
acl = acl_get_file("dirall", ACL_TYPE_EXTENDED);
#else
acl = acl_get_file("dirall", ACL_TYPE_NFS4);
#endif
- failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
+ failure("acl_get_file(\"%s\"): errno = %d (%s)", "dirall", errno,
+ strerror(errno));
assert(acl != (acl_t)NULL);
#endif
#if ARCHIVE_ACL_SUNOS_NFS4
compare_acls(aclp, aclcnt, acls_dir, "dirall", 0, dircnt);
free(aclp);
aclp = NULL;
+#elif ARCHIVE_ACL_LIBRICHACL
+ compare_acls(richacl, acls_dir, "dirall", 0, dircnt);
+ richacl_free(richacl);
#else
compare_acls(acl, acls_dir, "dirall", 0, dircnt);
acl_free(acl);
diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt
index e6054bab..318eb06e 100644
--- a/tar/test/CMakeLists.txt
+++ b/tar/test/CMakeLists.txt
@@ -74,9 +74,14 @@ IF(ENABLE_TAR AND ENABLE_TEST)
#
ADD_EXECUTABLE(bsdtar_test ${bsdtar_test_SOURCES})
IF(ENABLE_ACL)
+ SET(TEST_ACL_LIBS "")
IF(HAVE_LIBACL)
- TARGET_LINK_LIBRARIES(bsdtar_test ${ACL_LIBRARY})
+ LIST(APPEND TEST_ACL_LIBS ${ACL_LIBRARY})
ENDIF(HAVE_LIBACL)
+ IF(HAVE_LIBRICHACL)
+ LIST(APPEND TEST_ACL_LIBS ${RICHACL_LIBRARY})
+ ENDIF(HAVE_LIBRICHACL)
+ TARGET_LINK_LIBRARIES(bsdtar_test ${TEST_ACL_LIBS})
ENDIF(ENABLE_ACL)
SET_PROPERTY(TARGET bsdtar_test PROPERTY COMPILE_DEFINITIONS LIST_H)
diff --git a/test_utils/test_main.c b/test_utils/test_main.c
index 699dcf8d..0ef6d6fc 100644
--- a/test_utils/test_main.c
+++ b/test_utils/test_main.c
@@ -67,6 +67,9 @@
#ifdef HAVE_SYS_ACL_H
#include <sys/acl.h>
#endif
+#ifdef HAVE_SYS_RICHACL_H
+#include <sys/richacl.h>
+#endif
#if HAVE_MEMBERSHIP_H
#include <membership.h>
#endif
@@ -2507,9 +2510,12 @@ setTestAcl(const char *path)
{
#if ARCHIVE_ACL_SUPPORT
int r = 1;
-#if !ARCHIVE_ACL_SUNOS
+#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_DARWIN
acl_t acl;
#endif
+#if ARCHIVE_ACL_LIBRICHACL
+ struct richacl *richacl;
+#endif
#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_FREEBSD
const char *acltext_posix1e = "user:1:rw-,"
"group:15:r-x,"
@@ -2533,6 +2539,15 @@ setTestAcl(const char *path)
"owner@:rwpxaARWcCos::allow,"
"group@:rwpxaRcs::allow,"
"everyone@:rxaRcs::allow";
+#elif ARCHIVE_ACL_LIBRICHACL
+ const char *acltext_nfs4 = "owner:rwpxaARWcCoS::mask,"
+ "group:rwpxaRcS::mask,"
+ "other:rxaRcS::mask,"
+ "user:1:rwpaRcS::allow,"
+ "group:15:rxaRcS::allow,"
+ "owner@:rwpxaARWcCoS::allow,"
+ "group@:rwpxaRcS::allow,"
+ "everyone@:rxaRcS::allow";
#elif ARCHIVE_ACL_SUNOS_NFS4 /* Solaris NFS4 */
ace_t aclp_nfs4[] = {
{ 1, ACE_READ_DATA | ACE_WRITE_DATA | ACE_APPEND_DATA |
@@ -2579,6 +2594,11 @@ setTestAcl(const char *path)
failure("acl_from_text() error: %s", strerror(errno));
if (assert(acl != NULL) == 0)
return (0);
+#elif ARCHIVE_ACL_LIBRICHACL
+ richacl = richacl_from_text(acltext_nfs4, NULL, NULL);
+ failure("richacl_from_text() error: %s", strerror(errno));
+ if (assert(richacl != NULL) == 0)
+ return (0);
#elif ARCHIVE_ACL_DARWIN
acl = acl_init(1);
failure("acl_init() error: %s", strerror(errno));
@@ -2620,6 +2640,9 @@ setTestAcl(const char *path)
#if ARCHIVE_ACL_FREEBSD
r = acl_set_file(path, ACL_TYPE_NFS4, acl);
acl_free(acl);
+#elif ARCHIVE_ACL_LIBRICHACL
+ r = richacl_set_file(path, richacl);
+ richacl_free(richacl);
#elif ARCHIVE_ACL_SUNOS_NFS4
r = acl(path, ACE_SETACL,
(int)(sizeof(aclp_nfs4)/sizeof(aclp_nfs4[0])), aclp_nfs4);