summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2020-01-07 10:36:33 -0500
committerTavian Barnes <tavianator@tavianator.com>2020-01-07 10:36:33 -0500
commit3fa560ca6e0d68938f71ed1984f63f8c5cb7e7cc (patch)
treee27913a1146b563d2fe202a289e326ef9071b2de
parent8644e0e5ce28b662a0b4e4b19351a38be5fa6681 (diff)
downloadbfs-3fa560ca6e0d68938f71ed1984f63f8c5cb7e7cc.tar.xz
fsade: Support NFSv4 ACLs on FreeBSD
-rw-r--r--fsade.c61
-rwxr-xr-xtests.sh34
2 files changed, 58 insertions, 37 deletions
diff --git a/fsade.c b/fsade.c
index c7f9fed..df85431 100644
--- a/fsade.c
+++ b/fsade.c
@@ -136,6 +136,17 @@ static int bfs_check_acl_type(const char *path, acl_type_t type) {
}
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,46 +171,50 @@ static int bfs_check_acl_type(const char *path, acl_type_t type) {
break;
#endif
}
+#endif // !__FreeBSD__
+ int error = errno;
acl_free(acl);
+ errno = error;
return ret;
}
int bfs_check_acl(const struct BFTW *ftwbuf) {
+ static const acl_type_t acl_types[] = {
+#if __APPLE__
+ // macOS gives EINVAL for either of the two standard ACL types,
+ // supporting only ACL_TYPE_EXTENDED
+ ACL_TYPE_EXTENDED,
+#else
+ // The two standard POSIX.1e ACL types
+ ACL_TYPE_ACCESS,
+ ACL_TYPE_DEFAULT,
+#endif
+
+#ifdef ACL_TYPE_NFS4
+ ACL_TYPE_NFS4,
+#endif
+ };
+ static const size_t n_acl_types = sizeof(acl_types)/sizeof(acl_types[0]);
+
if (ftwbuf->typeflag == BFTW_LNK) {
return 0;
}
const char *path = fake_at(ftwbuf);
- int error = ENOTSUP;
int ret = -1;
-
-#if __APPLE__
- // macOS gives EINVAL for either of the two standard ACL types,
- // supporting only ACL_TYPE_EXTENDED
- if (ret <= 0) {
- ret = bfs_check_acl_type(path, ACL_TYPE_EXTENDED);
- if (ret < 0) {
- error = errno;
- }
- }
-#else
- if (ret <= 0) {
- ret = bfs_check_acl_type(path, ACL_TYPE_ACCESS);
- if (ret < 0) {
- error = errno;
+ 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_DEFAULT is supported only for directories,
+ // otherwise acl_get_file() gives EACCESS
+ continue;
}
- }
- if (ret <= 0 && ftwbuf->typeflag == BFTW_DIR) {
- ret = bfs_check_acl_type(path, ACL_TYPE_DEFAULT);
- if (ret < 0) {
- error = errno;
- }
+ ret = bfs_check_acl_type(path, acl_types[i]);
}
-#endif
+ int error = errno;
free_fake_at(ftwbuf, path);
errno = error;
return ret;
diff --git a/tests.sh b/tests.sh
index 3b05bf6..900cf4e 100755
--- a/tests.sh
+++ b/tests.sh
@@ -2391,19 +2391,31 @@ function test_xtype_bind_mount() {
return $ret
}
+function set_acl() {
+ uname="$(uname)"
+
+ if [ "$uname" = "Darwin" ]; then
+ chmod +a "$(id -un) allow read,write" "$1"
+ elif [ "$uname" = "FreeBSD" ]; then
+ if [ "$(getconf ACL_EXTENDED "$1")" -gt 0 ]; then
+ setfacl -m "u:$(id -un):rw" "$1"
+ elif [ "$(getconf ACL_NFS4 "$1")" -gt 0 ]; then
+ setfacl -m "u:$(id -un):rw::allow" "$1"
+ else
+ return 1
+ fi
+ else
+ return 1
+ fi
+}
+
function test_acl() {
rm -rf scratch/*
invoke_bfs scratch -quit -acl 2>/dev/null || return 0
touch scratch/{normal,acl}
-
- if [ "$(uname)" = "Darwin" ]; then
- chmod +a "$(id -un) allow read,write" scratch/acl || return 0
- else
- setfacl -m "u:$(id -un):rw" scratch/acl || return 0
- fi
-
+ set_acl scratch/acl || return 0
ln -s acl scratch/link
bfs_diff scratch -acl
@@ -2415,13 +2427,7 @@ function test_L_acl() {
invoke_bfs scratch -quit -acl 2>/dev/null || return 0
touch scratch/{normal,acl}
-
- if [ "$(uname)" = "Darwin" ]; then
- chmod +a "$(id -un) allow read,write" scratch/acl || return 0
- else
- setfacl -m "u:$(id -un):rw" scratch/acl || return 0
- fi
-
+ set_acl scratch/acl || return 0
ln -s acl scratch/link
bfs_diff -L scratch -acl