summaryrefslogtreecommitdiffstats
path: root/fsade.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2019-05-23 17:13:39 -0400
committerTavian Barnes <tavianator@tavianator.com>2019-05-24 09:00:51 -0400
commitf1fb3158d3f242f1884d8d8a7473ab0719e93e8c (patch)
tree4ab193109db3da98b779ed807f40adb3bb0b9fbd /fsade.c
parentd9b3196d6c8f4fa0e7d0a4771040762edaebb1ee (diff)
downloadbfs-f1fb3158d3f242f1884d8d8a7473ab0719e93e8c.tar.xz
Implement -xattr predicate
Diffstat (limited to 'fsade.c')
-rw-r--r--fsade.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/fsade.c b/fsade.c
index 7d796e0..822fbd1 100644
--- a/fsade.c
+++ b/fsade.c
@@ -30,7 +30,11 @@
# include <sys/capability.h>
#endif
-#if BFS_CAN_CHECK_ACL || BFS_CAN_CHECK_CAPABILITIES
+#if BFS_CAN_CHECK_XATTRS
+# include <sys/xattr.h>
+#endif
+
+#if BFS_CAN_CHECK_ACL || BFS_CAN_CHECK_CAPABILITIES || BFS_CAN_CHECK_XATTRS
/**
* Many of the APIs used here don't have *at() variants, but we can try to
@@ -103,7 +107,7 @@ static bool is_absence_error(int error) {
return false;
}
-#endif // BFS_CAN_CHECK_ACL || BFS_CAN_CHECK_CAPABILITIES
+#endif // BFS_CAN_CHECK_ACL || BFS_CAN_CHECK_CAPABILITIES || BFS_CAN_CHECK_XATTRS
#if BFS_CAN_CHECK_ACL
@@ -230,3 +234,45 @@ int bfs_check_capabilities(const struct BFTW *ftwbuf) {
}
#endif
+
+#if BFS_CAN_CHECK_XATTRS
+
+int bfs_check_xattrs(const struct BFTW *ftwbuf) {
+ const char *path = fake_at(ftwbuf);
+ ssize_t len;
+
+#if __APPLE__
+ int options = ftwbuf->typeflag == BFTW_LNK ? XATTR_NOFOLLOW : 0;
+ len = listxattr(path, NULL, 0, options);
+#else
+ if (ftwbuf->typeflag == BFTW_LNK) {
+ len = llistxattr(path, NULL, 0);
+ } else {
+ len = listxattr(path, NULL, 0);
+ }
+#endif
+
+ int error = errno;
+
+ free_fake_at(ftwbuf, path);
+
+ if (len > 0) {
+ return 1;
+ } else if (len == 0 || is_absence_error(error)) {
+ return 0;
+ } else if (error == E2BIG) {
+ return 1;
+ } else {
+ errno = error;
+ return -1;
+ }
+}
+
+#else // !BFS_CAN_CHECK_XATTRS
+
+int bfs_check_xattrs(const struct BFTW *ftwbuf) {
+ errno = ENOTSUP;
+ return -1;
+}
+
+#endif