summaryrefslogtreecommitdiffstats
path: root/src/fsade.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fsade.c')
-rw-r--r--src/fsade.c131
1 files changed, 95 insertions, 36 deletions
diff --git a/src/fsade.c b/src/fsade.c
index 0810c7f..d56fb07 100644
--- a/src/fsade.c
+++ b/src/fsade.c
@@ -1,11 +1,11 @@
// Copyright © Tavian Barnes <tavianator@tavianator.com>
// SPDX-License-Identifier: 0BSD
+#include "prelude.h"
#include "fsade.h"
#include "atomic.h"
#include "bfstd.h"
#include "bftw.h"
-#include "config.h"
#include "dir.h"
#include "dstring.h"
#include "sanity.h"
@@ -121,11 +121,23 @@ static bool is_absence_error(int error) {
#if BFS_CAN_CHECK_ACL
+#if BFS_HAS_ACL_GET_FILE
+
/** Unified interface for incompatible acl_get_entry() implementations. */
static int bfs_acl_entry(acl_t acl, int which, acl_entry_t *entry) {
-#if __DragonFly__ && !defined(ACL_FIRST_ENTRY) && !defined(ACL_NEXT_ENTRY)
-# define ACL_FIRST_ENTRY 0
-# define ACL_NEXT_ENTRY 1
+#if BFS_HAS_ACL_GET_ENTRY
+ int ret = acl_get_entry(acl, which, entry);
+# if __APPLE__
+ // POSIX.1e specifies a return value of 1 for success, but macOS returns 0 instead
+ return !ret;
+# else
+ return ret;
+# endif
+#elif __DragonFly__
+# if !defined(ACL_FIRST_ENTRY) && !defined(ACL_NEXT_ENTRY)
+# define ACL_FIRST_ENTRY 0
+# define ACL_NEXT_ENTRY 1
+# endif
switch (which) {
case ACL_FIRST_ENTRY:
@@ -142,24 +154,22 @@ static int bfs_acl_entry(acl_t acl, int which, acl_entry_t *entry) {
acl_entry_t last = &acl->acl_entry[acl->acl_cnt];
return *entry == last;
#else
- int ret = acl_get_entry(acl, which, entry);
-# if __APPLE__
- // POSIX.1e specifies a return value of 1 for success, but macOS returns 0 instead
- return !ret;
-# else
- return ret;
-# endif
+ errno = ENOTSUP;
+ return -1;
#endif
}
/** Unified interface for acl_get_tag_type(). */
attr(maybe_unused)
static int bfs_acl_tag_type(acl_entry_t entry, acl_tag_t *tag) {
-#if __DragonFly__
+#if BFS_HAS_ACL_GET_TAG_TYPE
+ return acl_get_tag_type(entry, tag);
+#elif __DragonFly__
*tag = entry->ae_tag;
return 0;
#else
- return acl_get_tag_type(entry, tag);
+ errno = ENOTSUP;
+ return -1;
#endif
}
@@ -199,7 +209,7 @@ static int bfs_check_acl_type(acl_t acl, acl_type_t type) {
return bfs_check_posix1e_acl(acl, false);
}
-#if __FreeBSD__
+#if BFS_HAS_ACL_IS_TRIVIAL_NP
int trivial;
int ret = acl_is_trivial_np(acl, &trivial);
@@ -213,34 +223,40 @@ static int bfs_check_acl_type(acl_t acl, acl_type_t type) {
} else {
return 1;
}
-#else // !__FreeBSD__
+#else
return bfs_check_posix1e_acl(acl, true);
#endif
}
+#endif // BFS_HAS_ACL_GET_FILE
+
int bfs_check_acl(const struct BFTW *ftwbuf) {
+ if (ftwbuf->type == BFS_LNK) {
+ return 0;
+ }
+
+ const char *path = fake_at(ftwbuf);
+
+#if BFS_HAS_ACL_TRIVIAL
+ int ret = acl_trivial(path);
+ int error = errno;
+#elif BFS_HAS_ACL_GET_FILE
static const acl_type_t acl_types[] = {
-#if __APPLE__
+# if __APPLE__
// macOS gives EINVAL for either of the two standard ACL types,
// supporting only ACL_TYPE_EXTENDED
ACL_TYPE_EXTENDED,
-#else
+# else
// The two standard POSIX.1e ACL types
ACL_TYPE_ACCESS,
ACL_TYPE_DEFAULT,
-#endif
+# endif
-#ifdef ACL_TYPE_NFS4
+# ifdef ACL_TYPE_NFS4
ACL_TYPE_NFS4,
-#endif
+# endif
};
- if (ftwbuf->type == BFS_LNK) {
- return 0;
- }
-
- const char *path = fake_at(ftwbuf);
-
int ret = -1, error = 0;
for (size_t i = 0; i < countof(acl_types) && ret <= 0; ++i) {
acl_type_t type = acl_types[i];
@@ -264,6 +280,7 @@ int bfs_check_acl(const struct BFTW *ftwbuf) {
error = errno;
acl_free(acl);
}
+#endif
free_fake_at(ftwbuf, path);
errno = error;
@@ -327,17 +344,62 @@ int bfs_check_capabilities(const struct BFTW *ftwbuf) {
#if BFS_CAN_CHECK_XATTRS
+#if BFS_USE_SYS_EXTATTR_H
+
+/** Wrapper for extattr_list_{file,link}. */
+static ssize_t bfs_extattr_list(const char *path, enum bfs_type type, int namespace) {
+ if (type == BFS_LNK) {
+#if BFS_HAS_EXTATTR_LIST_LINK
+ return extattr_list_link(path, namespace, NULL, 0);
+#elif BFS_HAS_EXTATTR_GET_LINK
+ return extattr_get_link(path, namespace, "", NULL, 0);
+#else
+ return 0;
+#endif
+ }
+
+#if BFS_HAS_EXTATTR_LIST_FILE
+ return extattr_list_file(path, namespace, NULL, 0);
+#elif BFS_HAS_EXTATTR_GET_FILE
+ // From man extattr(2):
+ //
+ // In earlier versions of this API, passing an empty string for the
+ // attribute name to extattr_get_file() would return the list of attributes
+ // defined for the target object. This interface has been deprecated in
+ // preference to using the explicit list API, and should not be used.
+ return extattr_get_file(path, namespace, "", NULL, 0);
+#else
+ return 0;
+#endif
+}
+
+/** Wrapper for extattr_get_{file,link}. */
+static ssize_t bfs_extattr_get(const char *path, enum bfs_type type, int namespace, const char *name) {
+ if (type == BFS_LNK) {
+#if BFS_HAS_EXTATTR_GET_LINK
+ return extattr_get_link(path, namespace, name, NULL, 0);
+#else
+ return 0;
+#endif
+ }
+
+#if BFS_HAS_EXTATTR_GET_FILE
+ return extattr_get_file(path, namespace, name, NULL, 0);
+#else
+ return 0;
+#endif
+}
+
+#endif // BFS_USE_SYS_EXTATTR_H
+
int bfs_check_xattrs(const struct BFTW *ftwbuf) {
const char *path = fake_at(ftwbuf);
ssize_t len;
#if BFS_USE_SYS_EXTATTR_H
- ssize_t (*extattr_list)(const char *, int, void *, size_t) =
- ftwbuf->type == BFS_LNK ? extattr_list_link : extattr_list_file;
-
- len = extattr_list(path, EXTATTR_NAMESPACE_SYSTEM, NULL, 0);
+ len = bfs_extattr_list(path, ftwbuf->type, EXTATTR_NAMESPACE_SYSTEM);
if (len <= 0) {
- len = extattr_list(path, EXTATTR_NAMESPACE_USER, NULL, 0);
+ len = bfs_extattr_list(path, ftwbuf->type, EXTATTR_NAMESPACE_USER);
}
#elif __APPLE__
int options = ftwbuf->type == BFS_LNK ? XATTR_NOFOLLOW : 0;
@@ -371,12 +433,9 @@ int bfs_check_xattr_named(const struct BFTW *ftwbuf, const char *name) {
ssize_t len;
#if BFS_USE_SYS_EXTATTR_H
- ssize_t (*extattr_get)(const char *, int, const char *, void *, size_t) =
- ftwbuf->type == BFS_LNK ? extattr_get_link : extattr_get_file;
-
- len = extattr_get(path, EXTATTR_NAMESPACE_SYSTEM, name, NULL, 0);
+ len = bfs_extattr_get(path, ftwbuf->type, EXTATTR_NAMESPACE_SYSTEM, name);
if (len < 0) {
- len = extattr_get(path, EXTATTR_NAMESPACE_USER, name, NULL, 0);
+ len = bfs_extattr_get(path, ftwbuf->type, EXTATTR_NAMESPACE_USER, name);
}
#elif __APPLE__
int options = ftwbuf->type == BFS_LNK ? XATTR_NOFOLLOW : 0;