summaryrefslogtreecommitdiffstats
path: root/posix1e.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2019-05-23 17:11:23 -0400
committerTavian Barnes <tavianator@tavianator.com>2019-05-24 09:00:50 -0400
commitd9b3196d6c8f4fa0e7d0a4771040762edaebb1ee (patch)
treef378d6955cf3cd6817a47e3a95284441552b221e /posix1e.c
parent28bbaeac8058653a4a46ae439c37d251a550f4f9 (diff)
downloadbfs-d9b3196d6c8f4fa0e7d0a4771040762edaebb1ee.tar.xz
fsade: Refactor the POSIX.1e abstractions
Since we're going to want to abstract more things that aren't part of POSIX.1e (like xattrs) in a similar way, let's give this a more generic name. And while we're at it, give it some more precise error reporting, and add some tests.
Diffstat (limited to 'posix1e.c')
-rw-r--r--posix1e.c192
1 files changed, 0 insertions, 192 deletions
diff --git a/posix1e.c b/posix1e.c
deleted file mode 100644
index a898b39..0000000
--- a/posix1e.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/****************************************************************************
- * bfs *
- * Copyright (C) 2019 Tavian Barnes <tavianator@tavianator.com> *
- * *
- * Permission to use, copy, modify, and/or distribute this software for any *
- * purpose with or without fee is hereby granted. *
- * *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES *
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF *
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR *
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES *
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN *
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
- ****************************************************************************/
-
-#include "posix1e.h"
-#include "bftw.h"
-#include "util.h"
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#if BFS_HAS_SYS_ACL
-# include <sys/acl.h>
-#endif
-
-#if BFS_HAS_POSIX1E_CAPABILITIES
-# include <sys/capability.h>
-#endif
-
-#if BFS_HAS_SYS_ACL || BFS_HAS_POSIX1E_CAPABILITIES
-
-static const char *open_path(const struct BFTW *ftwbuf, int *fd) {
-#ifdef O_PATH
- // The POSIX.1e APIS predate the *at() family of functions. We'd still
- // like to do something to avoid path re-traversals and limit races
- // though. Ideally we could just do openat(..., O_PATH) (since we may
- // not have read access) and pass that fd to something like cap_get_fd()
- // but that will fail since fgetxattr() needs read access to the file.
- // The workaround is to use O_PATH to open an fd and then pass
- // /proc/self/fd/<fd> to cap_get_path(). Inspired by
- // https://android.googlesource.com/platform/bionic/+/2825f10b7f61558c264231a536cf3affc0d84204
- int flags = O_PATH;
- if (ftwbuf->stat_flags & BFS_STAT_NOFOLLOW) {
- flags |= O_NOFOLLOW;
- }
-
- *fd = openat(ftwbuf->at_fd, ftwbuf->at_path, flags);
- if (*fd < 0) {
- return NULL;
- }
-
- size_t size = strlen("/proc/self/fd/") + CHAR_BIT*sizeof(int) + 1;
- char *path = malloc(size);
- if (!path) {
- close(*fd);
- *fd = -1;
- return NULL;
- }
-
- snprintf(path, size, "/proc/self/fd/%d", *fd);
- return path;
-#else
- *fd = -1;
- return ftwbuf->path;
-#endif
-}
-
-static void close_path(const struct BFTW *ftwbuf, const char *path, int fd) {
- if (path && path != ftwbuf->path) {
- free((void *)path);
- }
- if (fd >= 0) {
- close(fd);
- }
-}
-
-#endif // BFS_HAS_SYS_ACL || BFS_HAS_POSIX1E_CAPABILITIES
-
-#if BFS_HAS_SYS_ACL
-
-/** Check if any ACLs of the given type are non-trivial. */
-static bool bfs_check_acl_type(const char *path, acl_type_t type) {
- acl_t acl = acl_get_file(path, type);
- if (!acl) {
- return false;
- }
-
- bool ret = false;
- acl_entry_t entry;
- for (int status = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
- status > 0;
- 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;
- if (acl_get_tag_type(entry, &tag) != 0) {
- continue;
- }
- if (tag != ACL_USER_OBJ && tag != ACL_GROUP_OBJ && tag != ACL_OTHER) {
- ret = true;
- break;
- }
-#else
- ret = true;
- break;
-#endif
- }
-
- acl_free(acl);
- return ret;
-}
-
-bool bfs_check_acl(const struct BFTW *ftwbuf) {
- if (ftwbuf->typeflag == BFTW_LNK) {
- return false;
- }
-
- int fd;
- const char *path = open_path(ftwbuf, &fd);
- if (!path) {
- return false;
- }
-
- bool ret = false;
- if (bfs_check_acl_type(path, ACL_TYPE_ACCESS)) {
- ret = true;
- } else if (bfs_check_acl_type(path, ACL_TYPE_DEFAULT)) {
- ret = true;
-#ifdef ACL_TYPE_EXTENDED
- } else if (bfs_check_acl_type(path, ACL_TYPE_EXTENDED)) {
- ret = true;
-#endif
- }
-
- close_path(ftwbuf, path, fd);
- return ret;
-}
-
-#else // !BFS_HAS_SYS_ACL
-
-bool bfs_check_acl(const struct BFTW *ftwbuf) {
- return false;
-}
-
-#endif
-
-#if BFS_HAS_POSIX1E_CAPABILITIES
-
-bool bfs_check_capabilities(const struct BFTW *ftwbuf) {
- bool ret = false;
-
- if (ftwbuf->typeflag == BFTW_LNK) {
- goto out;
- }
-
- int fd;
- const char *path = open_path(ftwbuf, &fd);
- if (!path) {
- goto out;
- }
-
- cap_t caps = cap_get_file(path);
- if (!caps) {
- goto out_close;
- }
-
- // TODO: Any better way to check for a non-empty capability set?
- char *text = cap_to_text(caps, NULL);
- if (!text) {
- goto out_free_caps;
- }
- ret = text[0];
-
- cap_free(text);
-out_free_caps:
- cap_free(caps);
-out_close:
- close_path(ftwbuf, path, fd);
-out:
- return ret;
-}
-
-#else // !BFS_HAS_POSIX1E_CAPABILITIES
-
-bool bfs_check_capabilities(const struct BFTW *ftwbuf) {
- return false;
-}
-
-#endif