summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2019-05-24 23:26:43 -0400
committerTavian Barnes <tavianator@tavianator.com>2019-05-24 23:26:43 -0400
commitc6769208d4c7c774982fbb76afad0d95a6e4c9e8 (patch)
tree07e3eb40402705a480c0522ab35ec5d5aa73ade1
parent3edc432a60a5db633351a52f1adbcdd0ee1ff838 (diff)
downloadbfs-c6769208d4c7c774982fbb76afad0d95a6e4c9e8.tar.xz
fsade: Fix ACL detection on macOS
-rw-r--r--Makefile2
-rw-r--r--fsade.c39
-rwxr-xr-xtests.sh66
3 files changed, 86 insertions, 21 deletions
diff --git a/Makefile b/Makefile
index f37c4ba..ed7be9e 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,7 @@ LOCAL_LDFLAGS += -Wl,--as-needed
LOCAL_LDLIBS += -lacl -lcap -lattr -lrt
# These libraries are not built with msan, so disable them
-MSAN_CFLAGS := -DBFS_HAS_SYS_ACL=0 -DBFS_HAS_SYS_CAPABILITY=0 -DBFS_HAS_SYS_XATTRS=0
+MSAN_CFLAGS := -DBFS_HAS_SYS_ACL=0 -DBFS_HAS_SYS_CAPABILITY=0 -DBFS_HAS_SYS_XATTR=0
endif
ALL_CPPFLAGS = $(LOCAL_CPPFLAGS) $(CPPFLAGS)
diff --git a/fsade.c b/fsade.c
index 822fbd1..8f8f8b1 100644
--- a/fsade.c
+++ b/fsade.c
@@ -104,6 +104,13 @@ static bool is_absence_error(int error) {
}
#endif
+#if __APPLE__
+ // On macOS, ENOENT can also signal that a file has no ACLs
+ if (error == ENOENT) {
+ return true;
+ }
+#endif
+
return false;
}
@@ -125,7 +132,13 @@ static int bfs_check_acl_type(const char *path, acl_type_t type) {
int ret = 0;
acl_entry_t entry;
for (int status = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
+#if __APPLE__
+ // POSIX.1e specifies a return value of 1 for success, but macOS
+ // returns 0 instead
+ status == 0;
+#else
status > 0;
+#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;
@@ -153,22 +166,28 @@ int bfs_check_acl(const struct BFTW *ftwbuf) {
const char *path = fake_at(ftwbuf);
- int error = 0;
- int ret = bfs_check_acl_type(path, ACL_TYPE_ACCESS);
- if (ret < 0) {
- error = errno;
- }
+ int error = ENOTSUP;
+ int ret = -1;
- if (ret <= 0 && ftwbuf->typeflag == BFTW_DIR) {
- ret = bfs_check_acl_type(path, ACL_TYPE_DEFAULT);
+#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;
}
}
-
-#ifdef ACL_TYPE_EXTENDED
+#else
if (ret <= 0) {
- ret = bfs_check_acl_type(path, ACL_TYPE_EXTENDED);
+ ret = bfs_check_acl_type(path, ACL_TYPE_ACCESS);
+ if (ret < 0) {
+ error = errno;
+ }
+ }
+
+ if (ret <= 0 && ftwbuf->typeflag == BFTW_DIR) {
+ ret = bfs_check_acl_type(path, ACL_TYPE_DEFAULT);
if (ret < 0) {
error = errno;
}
diff --git a/tests.sh b/tests.sh
index 75319d7..fd8d4a1 100755
--- a/tests.sh
+++ b/tests.sh
@@ -2313,12 +2313,18 @@ function test_xtype_bind_mount() {
function test_acl() {
rm -rf scratch/*
- if ! invoke_bfs scratch -acl 2>/dev/null; then
+ if ! invoke_bfs scratch -quit -acl 2>/dev/null; then
return 0
fi
touch scratch/{normal,acl}
- setfacl -m "u:$(id -un):rw" scratch/acl
+
+ if [ "$(uname)" = "Darwin" ]; then
+ chmod +a "$(id -un) allow read,write" scratch/acl
+ else
+ setfacl -m "u:$(id -un):rw" scratch/acl
+ fi
+
ln -s acl scratch/link
bfs_diff scratch -acl
@@ -2327,12 +2333,18 @@ function test_acl() {
function test_L_acl() {
rm -rf scratch/*
- if ! invoke_bfs scratch -acl 2>/dev/null; then
+ if ! invoke_bfs scratch -quit -acl 2>/dev/null; then
return 0
fi
touch scratch/{normal,acl}
- setfacl -m "u:$(id -un):rw" scratch/acl
+
+ if [ "$(uname)" = "Darwin" ]; then
+ chmod +a "$(id -un) allow read,write" scratch/acl
+ else
+ setfacl -m "u:$(id -un):rw" scratch/acl
+ fi
+
ln -s acl scratch/link
bfs_diff -L scratch -acl
@@ -2340,6 +2352,11 @@ function test_L_acl() {
function test_capable() {
rm -rf scratch/*
+
+ if ! invoke_bfs scratch -quit -capable 2>/dev/null; then
+ return 0
+ fi
+
touch scratch/{normal,capable}
sudo setcap all+ep scratch/capable
ln -s capable scratch/link
@@ -2349,6 +2366,11 @@ function test_capable() {
function test_L_capable() {
rm -rf scratch/*
+
+ if ! invoke_bfs scratch -quit -capable 2>/dev/null; then
+ return 0
+ fi
+
touch scratch/{normal,capable}
sudo setcap all+ep scratch/capable
ln -s capable scratch/link
@@ -2358,24 +2380,48 @@ function test_L_capable() {
function test_xattr() {
rm -rf scratch/*
+
+ if ! invoke_bfs scratch -quit -xattr 2>/dev/null; then
+ return 0
+ fi
+
touch scratch/{normal,xattr}
- # Linux tmpfs doesn't support the user.* namespace, so we use the security.*
- # namespace, which is writable by root and readable by others
- sudo setfattr -n security.bfs_test scratch/xattr
ln -s xattr scratch/link
ln -s normal scratch/xattr_link
- sudo setfattr -h -n security.bfs_test scratch/xattr_link
+
+ if [ "$(uname)" = "Darwin" ]; then
+ xattr -w bfs_test true scratch/xattr
+ xattr -s -w bfs_test true scratch/xattr_link
+ else
+ # Linux tmpfs doesn't support the user.* namespace, so we use the security.*
+ # namespace, which is writable by root and readable by others
+ sudo setfattr -n security.bfs_test scratch/xattr
+ sudo setfattr -h -n security.bfs_test scratch/xattr_link
+ fi
bfs_diff scratch -xattr
}
function test_L_xattr() {
rm -rf scratch/*
+
+ if ! invoke_bfs scratch -quit -xattr 2>/dev/null; then
+ return 0
+ fi
+
touch scratch/{normal,xattr}
- sudo setfattr -n security.bfs_test scratch/xattr
ln -s xattr scratch/link
ln -s normal scratch/xattr_link
- sudo setfattr -h -n security.bfs_test scratch/xattr_link
+
+ if [ "$(uname)" = "Darwin" ]; then
+ xattr -w bfs_test true scratch/xattr
+ xattr -s -w bfs_test true scratch/xattr_link
+ else
+ # Linux tmpfs doesn't support the user.* namespace, so we use the security.*
+ # namespace, which is writable by root and readable by others
+ sudo setfattr -n security.bfs_test scratch/xattr
+ sudo setfattr -h -n security.bfs_test scratch/xattr_link
+ fi
bfs_diff -L scratch -xattr
}