From e8b42e513fa97af5c9978eb95ea97712f0ea5bbb Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 28 Jun 2019 20:34:33 -0400 Subject: Merge everything into one file --- fsade.c | 297 ---------------------------------------------------------------- 1 file changed, 297 deletions(-) delete mode 100644 fsade.c (limited to 'fsade.c') diff --git a/fsade.c b/fsade.c deleted file mode 100644 index 8f8f8b1..0000000 --- a/fsade.c +++ /dev/null @@ -1,297 +0,0 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2019 Tavian Barnes * - * * - * 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 "fsade.h" -#include "bftw.h" -#include "dstring.h" -#include "util.h" -#include -#include -#include - -#if BFS_CAN_CHECK_ACL -# include -#endif - -#if BFS_CAN_CHECK_CAPABILITIES -# include -#endif - -#if BFS_CAN_CHECK_XATTRS -# include -#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 - * emulate something similar if /proc/self/fd is available. - */ -static const char *fake_at(const struct BFTW *ftwbuf) { - static bool proc_works = true; - static bool proc_checked = false; - - char *path = NULL; - if (!proc_works || ftwbuf->at_fd == AT_FDCWD) { - goto fail; - } - - path = dstrprintf("/proc/self/fd/%d/", ftwbuf->at_fd); - if (!path) { - goto fail; - } - - if (!proc_checked) { - proc_checked = true; - if (xfaccessat(AT_FDCWD, path, F_OK) != 0) { - proc_works = false; - goto fail; - } - } - - if (dstrcat(&path, ftwbuf->at_path) != 0) { - goto fail; - } - - return path; - -fail: - dstrfree(path); - return ftwbuf->path; -} - -static void free_fake_at(const struct BFTW *ftwbuf, const char *path) { - if (path != ftwbuf->path) { - dstrfree((char *)path); - } -} - -/** - * Check if an error was caused by the absence of support or data for a feature. - */ -static bool is_absence_error(int error) { - // If the OS doesn't support the feature, it's obviously not enabled for - // any files - if (error == ENOTSUP) { - return true; - } - - // On Linux, ACLs and capabilities are implemented in terms of extended - // attributes, which report ENODATA/ENOATTR when missing - -#ifdef ENODATA - if (error == ENODATA) { - return true; - } -#endif - -#if defined(ENOATTR) && ENOATTR != ENODATA - if (error == ENOATTR) { - return true; - } -#endif - -#if __APPLE__ - // On macOS, ENOENT can also signal that a file has no ACLs - if (error == ENOENT) { - return true; - } -#endif - - return false; -} - -#endif // BFS_CAN_CHECK_ACL || BFS_CAN_CHECK_CAPABILITIES || BFS_CAN_CHECK_XATTRS - -#if BFS_CAN_CHECK_ACL - -/** Check if any ACLs of the given type are non-trivial. */ -static int bfs_check_acl_type(const char *path, acl_type_t type) { - acl_t acl = acl_get_file(path, type); - if (!acl) { - if (is_absence_error(errno)) { - return 0; - } else { - return -1; - } - } - - 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; - if (acl_get_tag_type(entry, &tag) != 0) { - continue; - } - if (tag != ACL_USER_OBJ && tag != ACL_GROUP_OBJ && tag != ACL_OTHER) { - ret = 1; - break; - } -#else - ret = 1; - break; -#endif - } - - acl_free(acl); - return ret; -} - -int bfs_check_acl(const struct BFTW *ftwbuf) { - 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; - } - } - - if (ret <= 0 && ftwbuf->typeflag == BFTW_DIR) { - ret = bfs_check_acl_type(path, ACL_TYPE_DEFAULT); - if (ret < 0) { - error = errno; - } - } -#endif - - free_fake_at(ftwbuf, path); - errno = error; - return ret; -} - -#else // !BFS_CAN_CHECK_ACL - -int bfs_check_acl(const struct BFTW *ftwbuf) { - errno = ENOTSUP; - return -1; -} - -#endif - -#if BFS_CAN_CHECK_CAPABILITIES - -int bfs_check_capabilities(const struct BFTW *ftwbuf) { - if (ftwbuf->typeflag == BFTW_LNK) { - return 0; - } - - int ret = -1, error; - const char *path = fake_at(ftwbuf); - - cap_t caps = cap_get_file(path); - if (!caps) { - error = errno; - if (is_absence_error(error)) { - ret = 0; - } - goto out_path; - } - - // TODO: Any better way to check for a non-empty capability set? - char *text = cap_to_text(caps, NULL); - if (!text) { - error = errno; - goto out_caps; - } - ret = text[0] ? 1 : 0; - - error = errno; - cap_free(text); -out_caps: - cap_free(caps); -out_path: - free_fake_at(ftwbuf, path); - errno = error; - return ret; -} - -#else // !BFS_CAN_CHECK_CAPABILITIES - -int bfs_check_capabilities(const struct BFTW *ftwbuf) { - errno = ENOTSUP; - return -1; -} - -#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 -- cgit v1.2.3