summaryrefslogtreecommitdiffstats
path: root/fsade.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2020-03-16 16:11:07 -0400
committerTavian Barnes <tavianator@tavianator.com>2020-03-16 16:11:07 -0400
commit1f0bacd901fe2f54ca4d441fad92b51e851ed439 (patch)
tree1096b50d620a0c17a59557005bd544103f87c760 /fsade.c
parent5ea7f4ea1f5015290b90bc51e503298aeef6cfb5 (diff)
downloadbfs-1f0bacd901fe2f54ca4d441fad92b51e851ed439.tar.xz
fsade: Fix default ACL processing.
For default ACLs, any entries at all makes them non-trivial. C.f.: https://lists.freebsd.org/pipermail/posix1e/2014-July/000517.html
Diffstat (limited to 'fsade.c')
-rw-r--r--fsade.c88
1 files changed, 50 insertions, 38 deletions
diff --git a/fsade.c b/fsade.c
index 668f586..a4c50ee 100644
--- a/fsade.c
+++ b/fsade.c
@@ -126,29 +126,10 @@ static bool is_absence_error(int error) {
#if BFS_CAN_CHECK_ACL
-/** Check if any ACLs of the given type are non-trivial. */
-static int bfs_check_acl_type(const char *path, acl_type_t type) {
- acl_t acl = acl_get_file(path, type);
- if (!acl) {
- if (is_absence_error(errno)) {
- return 0;
- } else {
- return -1;
- }
- }
-
+/** Check if a POSIX.1e ACL is non-trivial. */
+static int bfs_check_posix1e_acl(acl_t acl, bool ignore_required) {
int ret = 0;
-#if __FreeBSD__
- int trivial;
- if (acl_is_trivial_np(acl, &trivial) < 0) {
- ret = -1;
- } else if (trivial) {
- ret = 0;
- } else {
- ret = 1;
- }
-#else
acl_entry_t entry;
for (int status = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
#if __APPLE__
@@ -160,27 +141,46 @@ static int bfs_check_acl_type(const char *path, acl_type_t type) {
#endif
status = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry)) {
#if defined(ACL_USER_OBJ) && defined(ACL_GROUP_OBJ) && defined(ACL_OTHER)
- acl_tag_t tag;
- if (acl_get_tag_type(entry, &tag) != 0) {
- continue;
- }
- if (tag != ACL_USER_OBJ && tag != ACL_GROUP_OBJ && tag != ACL_OTHER) {
- ret = 1;
- break;
+ if (ignore_required) {
+ acl_tag_t tag;
+ if (acl_get_tag_type(entry, &tag) != 0) {
+ ret = -1;
+ continue;
+ }
+ if (tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER) {
+ continue;
+ }
}
-#else
+#endif
+
ret = 1;
break;
-#endif
}
-#endif // !__FreeBSD__
- int error = errno;
- acl_free(acl);
- errno = error;
return ret;
}
+/** Check if an ACL of the given type is non-trivial. */
+static int bfs_check_acl_type(acl_t acl, acl_type_t type) {
+ if (type == ACL_TYPE_DEFAULT) {
+ // For directory default ACLs, any entries make them non-trivial
+ return bfs_check_posix1e_acl(acl, false);
+ }
+
+#if __FreeBSD__
+ int trivial;
+ if (acl_is_trivial_np(acl, &trivial) < 0) {
+ return -1;
+ } else if (trivial) {
+ return 0;
+ } else {
+ return 1;
+ }
+#endif
+
+ return bfs_check_posix1e_acl(acl, true);
+}
+
int bfs_check_acl(const struct BFTW *ftwbuf) {
static const acl_type_t acl_types[] = {
#if __APPLE__
@@ -205,18 +205,30 @@ int bfs_check_acl(const struct BFTW *ftwbuf) {
const char *path = fake_at(ftwbuf);
- int ret = -1;
+ int ret = -1, error = 0;
for (size_t i = 0; i < n_acl_types && ret <= 0; ++i) {
- if (acl_types[i] == ACL_TYPE_DEFAULT && ftwbuf->typeflag != BFTW_DIR) {
+ acl_type_t type = acl_types[i];
+
+ if (type == ACL_TYPE_DEFAULT && ftwbuf->typeflag != BFTW_DIR) {
// ACL_TYPE_DEFAULT is supported only for directories,
// otherwise acl_get_file() gives EACCESS
continue;
}
- ret = bfs_check_acl_type(path, acl_types[i]);
+ acl_t acl = acl_get_file(path, type);
+ if (!acl) {
+ error = errno;
+ if (is_absence_error(error)) {
+ ret = 0;
+ }
+ continue;
+ }
+
+ ret = bfs_check_acl_type(acl, type);
+ error = errno;
+ acl_free(acl);
}
- int error = errno;
free_fake_at(ftwbuf, path);
errno = error;
return ret;