From 3fa560ca6e0d68938f71ed1984f63f8c5cb7e7cc Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 7 Jan 2020 10:36:33 -0500 Subject: fsade: Support NFSv4 ACLs on FreeBSD --- fsade.c | 61 ++++++++++++++++++++++++++++++++++++++----------------------- tests.sh | 34 ++++++++++++++++++++-------------- 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 -- cgit v1.2.3