diff options
-rw-r--r-- | CMakeLists.txt | 69 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | build/cmake/config.h.in | 8 | ||||
-rw-r--r-- | cat/test/CMakeLists.txt | 7 | ||||
-rw-r--r-- | configure.ac | 45 | ||||
-rw-r--r-- | cpio/test/CMakeLists.txt | 7 | ||||
-rw-r--r-- | libarchive/archive_acl_maps_linux.c | 41 | ||||
-rw-r--r-- | libarchive/archive_platform_acl.h | 3 | ||||
-rw-r--r-- | libarchive/archive_read_disk_acl_linux.c | 142 | ||||
-rw-r--r-- | libarchive/archive_write_disk_acl_darwin.c | 4 | ||||
-rw-r--r-- | libarchive/archive_write_disk_acl_freebsd.c | 4 | ||||
-rw-r--r-- | libarchive/archive_write_disk_acl_linux.c | 198 | ||||
-rw-r--r-- | libarchive/archive_write_disk_acl_sunos.c | 4 | ||||
-rw-r--r-- | libarchive/archive_write_disk_posix.c | 103 | ||||
-rw-r--r-- | libarchive/archive_write_disk_private.h | 7 | ||||
-rw-r--r-- | libarchive/test/test_acl_platform_nfs4.c | 324 | ||||
-rw-r--r-- | tar/test/CMakeLists.txt | 7 | ||||
-rw-r--r-- | test_utils/test_main.c | 25 |
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 @@ -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); |