diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/alloc.c | 8 | ||||
-rw-r--r-- | src/alloc.h | 2 | ||||
-rw-r--r-- | src/bar.c | 2 | ||||
-rw-r--r-- | src/bfstd.c | 130 | ||||
-rw-r--r-- | src/bfstd.h | 22 | ||||
-rw-r--r-- | src/bftw.c | 2 | ||||
-rw-r--r-- | src/bftw.h | 4 | ||||
-rw-r--r-- | src/bit.h | 2 | ||||
-rw-r--r-- | src/color.c | 2 | ||||
-rw-r--r-- | src/color.h | 2 | ||||
-rw-r--r-- | src/ctx.c | 2 | ||||
-rw-r--r-- | src/ctx.h | 2 | ||||
-rw-r--r-- | src/diag.c | 2 | ||||
-rw-r--r-- | src/diag.h | 2 | ||||
-rw-r--r-- | src/dir.c | 18 | ||||
-rw-r--r-- | src/dir.h | 7 | ||||
-rw-r--r-- | src/dstring.c | 3 | ||||
-rw-r--r-- | src/dstring.h | 2 | ||||
-rw-r--r-- | src/eval.c | 42 | ||||
-rw-r--r-- | src/eval.h | 2 | ||||
-rw-r--r-- | src/exec.c | 2 | ||||
-rw-r--r-- | src/expr.h | 2 | ||||
-rw-r--r-- | src/fsade.c | 131 | ||||
-rw-r--r-- | src/fsade.h | 11 | ||||
-rw-r--r-- | src/ioq.c | 7 | ||||
-rw-r--r-- | src/ioq.h | 2 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/mtab.c | 2 | ||||
-rw-r--r-- | src/mtab.h | 2 | ||||
-rw-r--r-- | src/opt.c | 8 | ||||
-rw-r--r-- | src/parse.c | 4 | ||||
-rw-r--r-- | src/prelude.h (renamed from src/config.h) | 52 | ||||
-rw-r--r-- | src/printf.c | 120 | ||||
-rw-r--r-- | src/pwcache.c | 2 | ||||
-rw-r--r-- | src/sanity.h | 2 | ||||
-rw-r--r-- | src/stat.c | 19 | ||||
-rw-r--r-- | src/stat.h | 10 | ||||
-rw-r--r-- | src/thread.c | 2 | ||||
-rw-r--r-- | src/thread.h | 2 | ||||
-rw-r--r-- | src/trie.c | 2 | ||||
-rw-r--r-- | src/xregex.c | 2 | ||||
-rw-r--r-- | src/xspawn.c | 28 | ||||
-rw-r--r-- | src/xspawn.h | 2 | ||||
-rw-r--r-- | src/xtime.c | 2 |
44 files changed, 367 insertions, 311 deletions
diff --git a/src/alloc.c b/src/alloc.c index b65d0c5..ebaff38 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "alloc.h" #include "bit.h" -#include "config.h" #include "diag.h" #include "sanity.h" #include <errno.h> @@ -24,12 +24,12 @@ static void *xmemalign(size_t align, size_t size) { bfs_assert(align >= sizeof(void *)); bfs_assert(is_aligned(align, size)); -#if __APPLE__ +#if BFS_HAS_ALIGNED_ALLOC + return aligned_alloc(align, size); +#else void *ptr = NULL; errno = posix_memalign(&ptr, align, size); return ptr; -#else - return aligned_alloc(align, size); #endif } diff --git a/src/alloc.h b/src/alloc.h index ae055bc..095134a 100644 --- a/src/alloc.h +++ b/src/alloc.h @@ -8,7 +8,7 @@ #ifndef BFS_ALLOC_H #define BFS_ALLOC_H -#include "config.h" +#include "prelude.h" #include <errno.h> #include <stddef.h> #include <stdlib.h> @@ -1,11 +1,11 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "bar.h" #include "atomic.h" #include "bfstd.h" #include "bit.h" -#include "config.h" #include "dstring.h" #include <errno.h> #include <fcntl.h> diff --git a/src/bfstd.c b/src/bfstd.c index 2499f00..f8ce871 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "bfstd.h" #include "bit.h" -#include "config.h" #include "diag.h" #include "sanity.h" #include "thread.h" @@ -186,10 +186,10 @@ char *xgetdelim(FILE *file, char delim) { const char *xgetprogname(void) { const char *cmd = NULL; -#if __GLIBC__ - cmd = program_invocation_short_name; -#elif BSD +#if BFS_HAS_GETPROGNAME cmd = getprogname(); +#elif BFS_HAS_GETPROGNAME_GNU + cmd = program_invocation_short_name; #endif if (!cmd) { @@ -252,40 +252,6 @@ int ynprompt(void) { return ret; } -/** Get the single character describing the given file type. */ -static char type_char(mode_t mode) { - switch (mode & S_IFMT) { - case S_IFREG: - return '-'; - case S_IFBLK: - return 'b'; - case S_IFCHR: - return 'c'; - case S_IFDIR: - return 'd'; - case S_IFLNK: - return 'l'; - case S_IFIFO: - return 'p'; - case S_IFSOCK: - return 's'; -#ifdef S_IFDOOR - case S_IFDOOR: - return 'D'; -#endif -#ifdef S_IFPORT - case S_IFPORT: - return 'P'; -#endif -#ifdef S_IFWHT - case S_IFWHT: - return 'w'; -#endif - } - - return '?'; -} - void *xmemdup(const void *src, size_t size) { void *ret = malloc(size); if (ret) { @@ -317,35 +283,33 @@ const char *xstrerror(int errnum) { const char *ret = NULL; static thread_local char buf[256]; - // - __APPLE__ - // - __COSMOPOLITAN__ - // - No strerror_l() - // - __FreeBSD__ && SANITIZE_MEMORY - // - duplocale() triggers https://github.com/llvm/llvm-project/issues/65532 -#if __APPLE__ || __COSMOPOLITAN__ || (__FreeBSD__ && SANITIZE_MEMORY) - if (strerror_r(errnum, buf, sizeof(buf)) == 0) { - ret = buf; - } -#else -# if __NetBSD__ - // NetBSD has no thread-specific locales - locale_t loc = LC_GLOBAL_LOCALE; -# else + // On FreeBSD with MemorySanitizer, duplocale() triggers + // https://github.com/llvm/llvm-project/issues/65532 +#if BFS_HAS_STRERROR_L && !(__FreeBSD__ && SANITIZE_MEMORY) +# if BFS_HAS_USELOCALE locale_t loc = uselocale((locale_t)0); +# else + locale_t loc = LC_GLOBAL_LOCALE; # endif - locale_t copy = loc; - if (copy == LC_GLOBAL_LOCALE) { - copy = duplocale(copy); + bool free_loc = false; + if (loc == LC_GLOBAL_LOCALE) { + loc = duplocale(loc); + free_loc = true; } - if (copy != (locale_t)0) { - ret = strerror_l(errnum, copy); - - if (loc == LC_GLOBAL_LOCALE) { - freelocale(copy); + if (loc != (locale_t)0) { + ret = strerror_l(errnum, loc); + if (free_loc) { + freelocale(loc); } } +#elif BFS_HAS_STRERROR_R_POSIX + if (strerror_r(errnum, buf, sizeof(buf)) == 0) { + ret = buf; + } +#elif BFS_HAS_STRERROR_R_GNU + ret = strerror_r(errnum, buf, sizeof(buf)); #endif if (!ret) { @@ -358,6 +322,40 @@ const char *xstrerror(int errnum) { return ret; } +/** Get the single character describing the given file type. */ +static char type_char(mode_t mode) { + switch (mode & S_IFMT) { + case S_IFREG: + return '-'; + case S_IFBLK: + return 'b'; + case S_IFCHR: + return 'c'; + case S_IFDIR: + return 'd'; + case S_IFLNK: + return 'l'; + case S_IFIFO: + return 'p'; + case S_IFSOCK: + return 's'; +#ifdef S_IFDOOR + case S_IFDOOR: + return 'D'; +#endif +#ifdef S_IFPORT + case S_IFPORT: + return 'P'; +#endif +#ifdef S_IFWHT + case S_IFWHT: + return 'w'; +#endif + } + + return '?'; +} + void xstrmode(mode_t mode, char str[11]) { strcpy(str, "----------"); @@ -489,7 +487,7 @@ int dup_cloexec(int fd) { } int pipe_cloexec(int pipefd[2]) { -#if __linux__ || (BSD && !__APPLE__) +#if BFS_HAS_PIPE2 return pipe2(pipefd, O_CLOEXEC); #else if (pipe(pipefd) != 0) { @@ -581,10 +579,7 @@ int xfaccessat(int fd, const char *path, int amode) { } char *xconfstr(int name) { -#if __ANDROID__ - errno = ENOTSUP; - return NULL; -#else +#if BFS_HAS_CONFSTR size_t len = confstr(name, NULL, 0); if (len == 0) { return NULL; @@ -601,7 +596,10 @@ char *xconfstr(int name) { } return str; -#endif // !__ANDROID__ +#else + errno = ENOTSUP; + return NULL; +#endif } char *xreadlinkat(int fd, const char *path, size_t size) { diff --git a/src/bfstd.h b/src/bfstd.h index fc22971..f91e380 100644 --- a/src/bfstd.h +++ b/src/bfstd.h @@ -8,7 +8,7 @@ #ifndef BFS_BFSTD_H #define BFS_BFSTD_H -#include "config.h" +#include "prelude.h" #include "sanity.h" #include <stddef.h> @@ -283,11 +283,21 @@ int xminor(dev_t dev); // #include <sys/stat.h> -#if __APPLE__ -# define st_atim st_atimespec -# define st_ctim st_ctimespec -# define st_mtim st_mtimespec -# define st_birthtim st_birthtimespec +/** + * Get the access/change/modification time from a struct stat. + */ +#if BFS_HAS_ST_ACMTIM +# define ST_ATIM(sb) (sb).st_atim +# define ST_CTIM(sb) (sb).st_ctim +# define ST_MTIM(sb) (sb).st_mtim +#elif BFS_HAS_ST_ACMTIMESPEC +# define ST_ATIM(sb) (sb).st_atimespec +# define ST_CTIM(sb) (sb).st_ctimespec +# define ST_MTIM(sb) (sb).st_mtimespec +#else +# define ST_ATIM(sb) ((struct timespec) { .tv_sec = (sb).st_atime }) +# define ST_CTIM(sb) ((struct timespec) { .tv_sec = (sb).st_ctime }) +# define ST_MTIM(sb) ((struct timespec) { .tv_sec = (sb).st_mtime }) #endif // #include <sys/wait.h> @@ -18,10 +18,10 @@ * various helper functions to take fewer parameters. */ +#include "prelude.h" #include "bftw.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include "dir.h" #include "dstring.h" @@ -54,7 +54,7 @@ struct BFTW { /** The file type. */ enum bfs_type type; - /** The errno that occurred, if type == BFTW_ERROR. */ + /** The errno that occurred, if type == BFS_ERROR. */ int error; /** A parent file descriptor for the *at() family of calls. */ @@ -104,7 +104,7 @@ const struct bfs_stat *bftw_cached_stat(const struct BFTW *ftwbuf, enum bfs_stat * @param flags * flags for bfs_stat(). Pass ftwbuf->stat_flags for the default flags. * @return - * The type of the file, or BFTW_ERROR if an error occurred. + * The type of the file, or BFS_ERROR if an error occurred. */ enum bfs_type bftw_type(const struct BFTW *ftwbuf, enum bfs_stat_flags flags); @@ -8,7 +8,7 @@ #ifndef BFS_BIT_H #define BFS_BIT_H -#include "config.h" +#include "prelude.h" #include <limits.h> #include <stdint.h> diff --git a/src/color.c b/src/color.c index 8c32a68..f004bf2 100644 --- a/src/color.c +++ b/src/color.c @@ -1,11 +1,11 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "color.h" #include "alloc.h" #include "bfstd.h" #include "bftw.h" -#include "config.h" #include "diag.h" #include "dir.h" #include "dstring.h" diff --git a/src/color.h b/src/color.h index e3e7973..3278cd6 100644 --- a/src/color.h +++ b/src/color.h @@ -8,7 +8,7 @@ #ifndef BFS_COLOR_H #define BFS_COLOR_H -#include "config.h" +#include "prelude.h" #include "dstring.h" #include <stdio.h> @@ -237,7 +237,7 @@ int bfs_ctx_free(struct bfs_ctx *ctx) { if (bfs_ctx_fclose(ctx, ctx_file) != 0) { if (cerr) { - bfs_error(ctx, "'%s': %m.\n", ctx_file->path); + bfs_error(ctx, "%pq: %m.\n", ctx_file->path); } ret = -1; } @@ -8,9 +8,9 @@ #ifndef BFS_CTX_H #define BFS_CTX_H +#include "prelude.h" #include "alloc.h" #include "bftw.h" -#include "config.h" #include "diag.h" #include "expr.h" #include "trie.h" @@ -1,11 +1,11 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "diag.h" #include "alloc.h" #include "bfstd.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "dstring.h" #include "expr.h" @@ -8,7 +8,7 @@ #ifndef BFS_DIAG_H #define BFS_DIAG_H -#include "config.h" +#include "prelude.h" #include <stdarg.h> /** @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "dir.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include "sanity.h" #include "trie.h" @@ -17,7 +17,7 @@ #include <unistd.h> #if BFS_USE_GETDENTS -# if __linux__ +# if BFS_HAS_GETDENTS64_SYSCALL # include <sys/syscall.h> # endif @@ -25,12 +25,14 @@ static ssize_t bfs_getdents(int fd, void *buf, size_t size) { sanitize_uninit(buf, size); -#if (__linux__ && __GLIBC__ && !__GLIBC_PREREQ(2, 30)) || __ANDROID__ - ssize_t ret = syscall(SYS_getdents64, fd, buf, size); -#elif __linux__ +#if BFS_HAS_GETDENTS + ssize_t ret = getdents(fd, buf, size); +#elif BFS_HAS_GETDENTS64 ssize_t ret = getdents64(fd, buf, size); +#elif BFS_HAS_GETDENTS64_SYSCALL + ssize_t ret = syscall(SYS_getdents64, fd, buf, size); #else - ssize_t ret = getdents(fd, buf, size); +# error "No getdents() implementation" #endif if (ret > 0) { @@ -42,7 +44,7 @@ static ssize_t bfs_getdents(int fd, void *buf, size_t size) { #endif // BFS_USE_GETDENTS -#if BFS_USE_GETDENTS && __linux__ +#if BFS_USE_GETDENTS && !BFS_HAS_GETDENTS /** Directory entry type for bfs_getdents() */ typedef struct dirent64 sys_dirent; #else @@ -351,7 +353,7 @@ int bfs_closedir(struct bfs_dir *dir) { int bfs_unwrapdir(struct bfs_dir *dir) { #if BFS_USE_GETDENTS int ret = dir->fd; -#elif __FreeBSD__ +#elif BFS_HAS_FDCLOSEDIR int ret = fdclosedir(dir->dir); #endif @@ -8,14 +8,15 @@ #ifndef BFS_DIR_H #define BFS_DIR_H +#include "prelude.h" #include <sys/types.h> /** * Whether the implementation uses the getdents() syscall directly, rather than * libc's readdir(). */ -#ifndef BFS_USE_GETDENTS -# define BFS_USE_GETDENTS (__linux__ || __FreeBSD__) +#if !defined(BFS_USE_GETDENTS) && (__linux__ || __FreeBSD__) +# define BFS_USE_GETDENTS (BFS_HAS_GETDENTS || BFS_HAS_GETDENTS64 | BFS_HAS_GETDENTS64_SYSCALL) #endif /** @@ -152,7 +153,7 @@ int bfs_closedir(struct bfs_dir *dir); * Whether the bfs_unwrapdir() function is supported. */ #ifndef BFS_USE_UNWRAPDIR -# define BFS_USE_UNWRAPDIR (BFS_USE_GETDENTS || __FreeBSD__) +# define BFS_USE_UNWRAPDIR (BFS_USE_GETDENTS || BFS_HAS_FDCLOSEDIR) #endif #if BFS_USE_UNWRAPDIR diff --git a/src/dstring.c b/src/dstring.c index 10b0fad..b5bf3d3 100644 --- a/src/dstring.c +++ b/src/dstring.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "dstring.h" #include "alloc.h" #include "bit.h" -#include "config.h" #include "diag.h" #include <stdarg.h> #include <stddef.h> @@ -245,6 +245,7 @@ int dstrvcatf(dchar **str, const char *format, va_list args) { return 0; fail: + va_end(copy); *tail = '\0'; return -1; } diff --git a/src/dstring.h b/src/dstring.h index 6006199..9ea7eb9 100644 --- a/src/dstring.h +++ b/src/dstring.h @@ -8,8 +8,8 @@ #ifndef BFS_DSTRING_H #define BFS_DSTRING_H +#include "prelude.h" #include "bfstd.h" -#include "config.h" #include <stdarg.h> #include <stddef.h> @@ -5,12 +5,12 @@ * Implementation of all the primary expressions. */ +#include "prelude.h" #include "eval.h" #include "bar.h" #include "bfstd.h" #include "bftw.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "dir.h" @@ -445,38 +445,42 @@ bool eval_depth(const struct bfs_expr *expr, struct bfs_eval *state) { * -empty test. */ bool eval_empty(const struct bfs_expr *expr, struct bfs_eval *state) { - bool ret = false; const struct BFTW *ftwbuf = state->ftwbuf; + const struct bfs_stat *statbuf; + struct bfs_dir *dir; + + switch (ftwbuf->type) { + case BFS_REG: + statbuf = eval_stat(state); + return statbuf && statbuf->size == 0; - if (ftwbuf->type == BFS_DIR) { - struct bfs_dir *dir = bfs_allocdir(); + case BFS_DIR: + dir = bfs_allocdir(); if (!dir) { - eval_report_error(state); - return ret; + goto error; } if (bfs_opendir(dir, ftwbuf->at_fd, ftwbuf->at_path, 0) != 0) { - eval_report_error(state); - return ret; + goto error; } int did_read = bfs_readdir(dir, NULL); + bfs_closedir(dir); + if (did_read < 0) { - eval_report_error(state); - } else { - ret = !did_read; + goto error; } - bfs_closedir(dir); free(dir); - } else if (ftwbuf->type == BFS_REG) { - const struct bfs_stat *statbuf = eval_stat(state); - if (statbuf) { - ret = statbuf->size == 0; - } - } + return did_read == 0; + error: + eval_report_error(state); + free(dir); + return false; - return ret; + default: + return false; + } } /** @@ -9,7 +9,7 @@ #ifndef BFS_EVAL_H #define BFS_EVAL_H -#include "config.h" +#include "prelude.h" struct bfs_ctx; struct bfs_expr; @@ -1,12 +1,12 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "exec.h" #include "alloc.h" #include "bfstd.h" #include "bftw.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "dstring.h" @@ -8,8 +8,8 @@ #ifndef BFS_EXPR_H #define BFS_EXPR_H +#include "prelude.h" #include "color.h" -#include "config.h" #include "eval.h" #include "stat.h" #include <sys/types.h> 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; diff --git a/src/fsade.h b/src/fsade.h index 1f1dbfc..eefef9f 100644 --- a/src/fsade.h +++ b/src/fsade.h @@ -9,16 +9,11 @@ #ifndef BFS_FSADE_H #define BFS_FSADE_H -#include "config.h" +#include "prelude.h" -#define BFS_CAN_CHECK_ACL BFS_USE_SYS_ACL_H +#define BFS_CAN_CHECK_ACL (BFS_HAS_ACL_GET_FILE || BFS_HAS_ACL_TRIVIAL) -#if !defined(BFS_CAN_CHECK_CAPABILITIES) && BFS_USE_SYS_CAPABILITY_H -# include <sys/capability.h> -# ifdef CAP_CHOWN -# define BFS_CAN_CHECK_CAPABILITIES true -# endif -#endif +#define BFS_CAN_CHECK_CAPABILITIES BFS_USE_LIBCAP #define BFS_CAN_CHECK_CONTEXT BFS_USE_LIBSELINUX @@ -118,12 +118,12 @@ * [1]: https://arxiv.org/abs/2201.02179 */ +#include "prelude.h" #include "ioq.h" #include "alloc.h" #include "atomic.h" #include "bfstd.h" #include "bit.h" -#include "config.h" #include "diag.h" #include "dir.h" #include "stat.h" @@ -918,17 +918,14 @@ static void ioq_thread_join(struct ioq_thread *thread) { } struct ioq *ioq_create(size_t depth, size_t nthreads) { - struct ioq *ioq = ALLOC_FLEX(struct ioq, threads, nthreads); + struct ioq *ioq = ZALLOC_FLEX(struct ioq, threads, nthreads); if (!ioq) { goto fail; } ioq->depth = depth; - ioq->size = 0; - ioq->cancel = false; ARENA_INIT(&ioq->ents, struct ioq_ent); - #if BFS_USE_LIBURING && BFS_USE_STATX ARENA_INIT(&ioq->xbufs, struct statx); #endif @@ -8,7 +8,7 @@ #ifndef BFS_IOQ_H #define BFS_IOQ_H -#include "config.h" +#include "prelude.h" #include "dir.h" #include "stat.h" #include <stddef.h> @@ -26,7 +26,7 @@ * - bit.h (bit manipulation) * - bfstd.[ch] (standard library wrappers/polyfills) * - color.[ch] (for pretty terminal colors) - * - config.h (configuration and feature/platform detection) + * - prelude.h (configuration and feature/platform detection) * - diag.[ch] (formats diagnostic messages) * - dir.[ch] (a directory API facade) * - dstring.[ch] (a dynamic string library) @@ -45,8 +45,8 @@ * - xtime.[ch] (date/time handling utilities) */ +#include "prelude.h" #include "bfstd.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "eval.h" @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "mtab.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" #include "stat.h" #include "trie.h" #include <errno.h> @@ -8,7 +8,7 @@ #ifndef BFS_MTAB_H #define BFS_MTAB_H -#include "config.h" +#include "prelude.h" struct bfs_stat; @@ -25,11 +25,11 @@ * effects are reachable at all, skipping the traversal if not. */ +#include "prelude.h" #include "opt.h" #include "bftw.h" #include "bit.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "dir.h" @@ -947,8 +947,12 @@ static struct bfs_expr *visit_shallow(struct bfs_opt *opt, struct bfs_expr *expr expr = general(opt, expr, visitor); } + if (!expr) { + return NULL; + } + visit_fn *specific = look_up_visitor(expr, visitor->table); - if (expr && specific) { + if (specific) { expr = specific(opt, expr, visitor); } diff --git a/src/parse.c b/src/parse.c index a3e32fe..a1155c0 100644 --- a/src/parse.c +++ b/src/parse.c @@ -8,12 +8,12 @@ * flags like always-true options, and skipping over paths wherever they appear. */ +#include "prelude.h" #include "parse.h" #include "alloc.h" #include "bfstd.h" #include "bftw.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "dir.h" @@ -1755,7 +1755,7 @@ static int parse_reftime(const struct bfs_parser *parser, struct bfs_expr *expr) fprintf(stderr, " - %04d-%02d-%02d\n", year, month, tm.tm_mday); fprintf(stderr, " - %04d-%02d-%02dT%02d:%02d:%02d\n", year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); -#if __FreeBSD__ +#if BFS_HAS_TM_GMTOFF int gmtoff = tm.tm_gmtoff; #else int gmtoff = -timezone; diff --git a/src/config.h b/src/prelude.h index 2eff1fc..ddeacbd 100644 --- a/src/config.h +++ b/src/prelude.h @@ -5,8 +5,8 @@ * Configuration and feature/platform detection. */ -#ifndef BFS_CONFIG_H -#define BFS_CONFIG_H +#ifndef BFS_PRELUDE_H +#define BFS_PRELUDE_H // Possible __STDC_VERSION__ values @@ -26,6 +26,8 @@ // bfs packaging configuration +#include "config.h" + #ifndef BFS_COMMAND # define BFS_COMMAND "bfs" #endif @@ -47,12 +49,6 @@ extern const char bfs_version[]; #if __has_include(<paths.h>) # define BFS_HAS_PATHS_H true #endif -#if __has_include(<sys/acl.h>) -# define BFS_HAS_SYS_ACL_H true -#endif -#if __has_include(<sys/capability.h>) -# define BFS_HAS_SYS_CAPABILITY_H true -#endif #if __has_include(<sys/extattr.h>) # define BFS_HAS_SYS_EXTATTR_H true #endif @@ -79,8 +75,6 @@ extern const char bfs_version[]; #define BFS_HAS_MNTENT_H __GLIBC__ #define BFS_HAS_PATHS_H true -#define BFS_HAS_SYS_ACL_H true -#define BFS_HAS_SYS_CAPABILITY_H __linux__ #define BFS_HAS_SYS_EXTATTR_H __FreeBSD__ #define BFS_HAS_SYS_MKDEV_H false #define BFS_HAS_SYS_PARAM_H true @@ -97,14 +91,8 @@ extern const char bfs_version[]; #ifndef BFS_USE_PATHS_H # define BFS_USE_PATHS_H BFS_HAS_PATHS_H #endif -#ifndef BFS_USE_SYS_ACL_H -# define BFS_USE_SYS_ACL_H (BFS_HAS_SYS_ACL_H && !__illumos__ && (!__linux__ || BFS_USE_LIBACL)) -#endif -#ifndef BFS_USE_SYS_CAPABILITY_H -# define BFS_USE_SYS_CAPABILITY_H (BFS_HAS_SYS_CAPABILITY_H && !__FreeBSD__ && (!__linux__ || BFS_USE_LIBCAP)) -#endif #ifndef BFS_USE_SYS_EXTATTR_H -# define BFS_USE_SYS_EXTATTR_H (BFS_HAS_SYS_EXTATTR_H && !__DragonFly__) +# define BFS_USE_SYS_EXTATTR_H BFS_HAS_SYS_EXTATTR_H #endif #ifndef BFS_USE_SYS_MKDEV_H # define BFS_USE_SYS_MKDEV_H BFS_HAS_SYS_MKDEV_H @@ -180,14 +168,25 @@ extern const char bfs_version[]; #endif /** + * Polyfill max_align_t if we don't already have it. + */ +#if !BFS_HAS_MAX_ALIGN_T +typedef union { +# ifdef __BIGGEST_ALIGNMENT__ + alignas(__BIGGEST_ALIGNMENT__) char c; +# else + long double ld; + long long ll; + void *ptr; +# endif +} max_align_t; +#endif + +/** * Alignment specifier that avoids false sharing. */ #define cache_align alignas(FALSE_SHARING_SIZE) -#if __COSMOPOLITAN__ -typedef long double max_align_t; -#endif - // Wrappers for attributes /** @@ -245,6 +244,15 @@ typedef long double max_align_t; #endif /** + * Annotates functions that potentially modify and return format strings. + */ +#if __has_attribute(format_arg) +# define attr_format_arg(arg) __attribute__((format_arg(arg))) +#else +# define attr_format_arg(args) +#endif + +/** * Annotates allocator-like functions. */ #if __has_attribute(malloc) @@ -374,4 +382,4 @@ typedef long double max_align_t; // Only trigger an error on more than 9 arguments #define attr_too_many_none(...) -#endif // BFS_CONFIG_H +#endif // BFS_PRELUDE_H diff --git a/src/printf.c b/src/printf.c index 3b8269e..f8428f7 100644 --- a/src/printf.c +++ b/src/printf.c @@ -1,12 +1,12 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "printf.h" #include "alloc.h" #include "bfstd.h" #include "bftw.h" #include "color.h" -#include "config.h" #include "ctx.h" #include "diag.h" #include "dir.h" @@ -88,22 +88,20 @@ static bool should_color(CFILE *cfile, const struct bfs_fmt *fmt) { bfs_assert(ret >= 0 && (size_t)ret < sizeof(buf)); \ (void)ret -/** - * Common entry point for fprintf() with a dynamic format string. - */ -static int dyn_fprintf(FILE *file, const struct bfs_fmt *fmt, ...) { - va_list args; - va_start(args, fmt); - -#if __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wformat-nonliteral" -#endif - int ret = vfprintf(file, fmt->str, args); -#if __GNUC__ -# pragma GCC diagnostic pop -#endif +/** Return a dynamic format string. */ +attr(format_arg(2)) +static const char *dyn_fmt(const char *str, const char *fake) { + bfs_assert(strcmp(str + strlen(str) - strlen(fake) + 1, fake + 1) == 0, + "Mismatched format specifiers: '%s' vs. '%s'", str, fake); + return str; +} +/** Wrapper for fprintf(). */ +attr(printf(3, 4)) +static int bfs_fprintf(CFILE *cfile, const struct bfs_fmt *fmt, const char *fake, ...) { + va_list args; + va_start(args, fake); + int ret = vfprintf(cfile->file, dyn_fmt(fmt->str, fake), args); va_end(args); return ret; } @@ -139,7 +137,7 @@ static int bfs_printf_ctime(CFILE *cfile, const struct bfs_fmt *fmt, const struc (long)ts->tv_nsec, 1900 + tm.tm_year); - return dyn_fprintf(cfile->file, fmt, buf); + return bfs_fprintf(cfile, fmt, "%s", buf); } /** %A, %B/%W, %C, %T: strftime() */ @@ -214,7 +212,7 @@ static int bfs_printf_strftime(CFILE *cfile, const struct bfs_fmt *fmt, const st bfs_assert(ret >= 0 && (size_t)ret < sizeof(buf)); (void)ret; - return dyn_fprintf(cfile->file, fmt, buf); + return bfs_fprintf(cfile, fmt, "%s", buf); } /** %b: blocks */ @@ -226,12 +224,12 @@ static int bfs_printf_b(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF uintmax_t blocks = ((uintmax_t)statbuf->blocks * BFS_STAT_BLKSIZE + 511) / 512; BFS_PRINTF_BUF(buf, "%ju", blocks); - return dyn_fprintf(cfile->file, fmt, buf); + return bfs_fprintf(cfile, fmt, "%s", buf); } /** %d: depth */ static int bfs_printf_d(CFILE *cfile, const struct bfs_fmt *fmt, const struct BFTW *ftwbuf) { - return dyn_fprintf(cfile->file, fmt, (intmax_t)ftwbuf->depth); + return bfs_fprintf(cfile, fmt, "%jd", (intmax_t)ftwbuf->depth); } /** %D: device */ @@ -242,7 +240,7 @@ static int bfs_printf_D(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->dev); - return dyn_fprintf(cfile->file, fmt, buf); + return bfs_fprintf(cfile, fmt, "%s", buf); } /** %f: file name */ @@ -250,7 +248,7 @@ static int bfs_printf_f(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF if (should_color(cfile, fmt)) { return cfprintf(cfile, "%pF", ftwbuf); } else { - return dyn_fprintf(cfile->file, fmt, ftwbuf->path + ftwbuf->nameoff); + return bfs_fprintf(cfile, fmt, "%s", ftwbuf->path + ftwbuf->nameoff); } } @@ -266,7 +264,7 @@ static int bfs_printf_F(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF return -1; } - return dyn_fprintf(cfile->file, fmt, type); + return bfs_fprintf(cfile, fmt, "%s", type); } /** %G: gid */ @@ -277,7 +275,7 @@ static int bfs_printf_G(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->gid); - return dyn_fprintf(cfile->file, fmt, buf); + return bfs_fprintf(cfile, fmt, "%s", buf); } /** %g: group name */ @@ -293,7 +291,7 @@ static int bfs_printf_g(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF return bfs_printf_G(cfile, fmt, ftwbuf); } - return dyn_fprintf(cfile->file, fmt, grp->gr_name); + return bfs_fprintf(cfile, fmt, "%s", grp->gr_name); } /** %h: leading directories */ @@ -322,7 +320,7 @@ static int bfs_printf_h(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF if (should_color(cfile, fmt)) { ret = cfprintf(cfile, "${di}%pQ${rs}", buf); } else { - ret = dyn_fprintf(cfile->file, fmt, buf); + ret = bfs_fprintf(cfile, fmt, "%s", buf); } free(copy); @@ -338,7 +336,7 @@ static int bfs_printf_H(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF return cfprintf(cfile, "${di}%pQ${rs}", ftwbuf->root); } } else { - return dyn_fprintf(cfile->file, fmt, ftwbuf->root); + return bfs_fprintf(cfile, fmt, "%s", ftwbuf->root); } } @@ -350,7 +348,7 @@ static int bfs_printf_i(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->ino); - return dyn_fprintf(cfile->file, fmt, buf); + return bfs_fprintf(cfile, fmt, "%s", buf); } /** %k: 1K blocks */ @@ -362,7 +360,7 @@ static int bfs_printf_k(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF uintmax_t blocks = ((uintmax_t)statbuf->blocks * BFS_STAT_BLKSIZE + 1023) / 1024; BFS_PRINTF_BUF(buf, "%ju", blocks); - return dyn_fprintf(cfile->file, fmt, buf); + return bfs_fprintf(cfile, fmt, "%s", buf); } /** %l: link target */ @@ -384,7 +382,7 @@ static int bfs_printf_l(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF } } - int ret = dyn_fprintf(cfile->file, fmt, target); + int ret = bfs_fprintf(cfile, fmt, "%s", target); free(buf); return ret; } @@ -396,7 +394,7 @@ static int bfs_printf_m(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF return -1; } - return dyn_fprintf(cfile->file, fmt, (unsigned int)(statbuf->mode & 07777)); + return bfs_fprintf(cfile, fmt, "%o", (unsigned int)(statbuf->mode & 07777)); } /** %M: symbolic mode */ @@ -408,7 +406,7 @@ static int bfs_printf_M(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF char buf[11]; xstrmode(statbuf->mode, buf); - return dyn_fprintf(cfile->file, fmt, buf); + return bfs_fprintf(cfile, fmt, "%s", buf); } /** %n: link count */ @@ -419,7 +417,7 @@ static int bfs_printf_n(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->nlink); - return dyn_fprintf(cfile->file, fmt, buf); + return bfs_fprintf(cfile, fmt, "%s", buf); } /** %p: full path */ @@ -427,7 +425,7 @@ static int bfs_printf_p(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF if (should_color(cfile, fmt)) { return cfprintf(cfile, "%pP", ftwbuf); } else { - return dyn_fprintf(cfile->file, fmt, ftwbuf->path); + return bfs_fprintf(cfile, fmt, "%s", ftwbuf->path); } } @@ -448,7 +446,7 @@ static int bfs_printf_P(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF copybuf.nameoff -= offset; return cfprintf(cfile, "%pP", ©buf); } else { - return dyn_fprintf(cfile->file, fmt, ftwbuf->path + offset); + return bfs_fprintf(cfile, fmt, "%s", ftwbuf->path + offset); } } @@ -460,7 +458,7 @@ static int bfs_printf_s(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->size); - return dyn_fprintf(cfile->file, fmt, buf); + return bfs_fprintf(cfile, fmt, "%s", buf); } /** %S: sparseness */ @@ -476,7 +474,7 @@ static int bfs_printf_S(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF } else { sparsity = (double)BFS_STAT_BLKSIZE * statbuf->blocks / statbuf->size; } - return dyn_fprintf(cfile->file, fmt, sparsity); + return bfs_fprintf(cfile, fmt, "%g", sparsity); } /** %U: uid */ @@ -487,7 +485,7 @@ static int bfs_printf_U(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF } BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->uid); - return dyn_fprintf(cfile->file, fmt, buf); + return bfs_fprintf(cfile, fmt, "%s", buf); } /** %u: user name */ @@ -503,7 +501,7 @@ static int bfs_printf_u(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF return bfs_printf_U(cfile, fmt, ftwbuf); } - return dyn_fprintf(cfile->file, fmt, pwd->pw_name); + return bfs_fprintf(cfile, fmt, "%s", pwd->pw_name); } static const char *bfs_printf_type(enum bfs_type type) { @@ -520,10 +518,14 @@ static const char *bfs_printf_type(enum bfs_type type) { return "p"; case BFS_LNK: return "l"; + case BFS_PORT: + return "P"; case BFS_REG: return "f"; case BFS_SOCK: return "s"; + case BFS_WHT: + return "w"; default: return "U"; } @@ -532,39 +534,29 @@ static const char *bfs_printf_type(enum bfs_type type) { /** %y: type */ static int bfs_printf_y(CFILE *cfile, const struct bfs_fmt *fmt, const struct BFTW *ftwbuf) { const char *type = bfs_printf_type(ftwbuf->type); - return dyn_fprintf(cfile->file, fmt, type); + return bfs_fprintf(cfile, fmt, "%s", type); } /** %Y: target type */ static int bfs_printf_Y(CFILE *cfile, const struct bfs_fmt *fmt, const struct BFTW *ftwbuf) { - int error = 0; - - if (ftwbuf->type != BFS_LNK) { - return bfs_printf_y(cfile, fmt, ftwbuf); - } + enum bfs_type type = bftw_type(ftwbuf, BFS_STAT_FOLLOW); + const char *str; - const char *type = "U"; - - const struct bfs_stat *statbuf = bftw_stat(ftwbuf, BFS_STAT_FOLLOW); - if (statbuf) { - type = bfs_printf_type(bfs_mode_to_type(statbuf->mode)); - } else { - switch (errno) { - case ELOOP: - type = "L"; - break; - case ENOENT: - case ENOTDIR: - type = "N"; - break; - default: - type = "?"; + int error = 0; + if (type == BFS_ERROR) { + if (errno_is_like(ELOOP)) { + str = "L"; + } else if (errno_is_like(ENOENT)) { + str = "N"; + } else { + str = "?"; error = errno; - break; } + } else { + str = bfs_printf_type(type); } - int ret = dyn_fprintf(cfile->file, fmt, type); + int ret = bfs_fprintf(cfile, fmt, "%s", str); if (error != 0) { ret = -1; errno = error; @@ -580,7 +572,7 @@ static int bfs_printf_Z(CFILE *cfile, const struct bfs_fmt *fmt, const struct BF return -1; } - int ret = dyn_fprintf(cfile->file, fmt, con); + int ret = bfs_fprintf(cfile, fmt, "%s", con); bfs_freecon(con); return ret; } diff --git a/src/pwcache.c b/src/pwcache.c index 79437d8..af8c237 100644 --- a/src/pwcache.c +++ b/src/pwcache.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "pwcache.h" #include "alloc.h" -#include "config.h" #include "trie.h" #include <errno.h> #include <grp.h> diff --git a/src/sanity.h b/src/sanity.h index 423e6ff..e168b8f 100644 --- a/src/sanity.h +++ b/src/sanity.h @@ -8,7 +8,7 @@ #ifndef BFS_SANITY_H #define BFS_SANITY_H -#include "config.h" +#include "prelude.h" #include <stddef.h> #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "stat.h" #include "atomic.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include "sanity.h" #include <errno.h> @@ -13,7 +13,7 @@ #include <sys/stat.h> #include <sys/types.h> -#if BFS_USE_STATX && !BFS_HAS_LIBC_STATX +#if BFS_USE_STATX && !BFS_HAS_STATX # include <linux/stat.h> # include <sys/syscall.h> # include <unistd.h> @@ -99,23 +99,26 @@ void bfs_stat_convert(struct bfs_stat *dest, const struct stat *src) { dest->rdev = src->st_rdev; dest->mask |= BFS_STAT_RDEV; -#if BSD +#if BFS_HAS_ST_FLAGS dest->attrs = src->st_flags; dest->mask |= BFS_STAT_ATTRS; #endif - dest->atime = src->st_atim; + dest->atime = ST_ATIM(*src); dest->mask |= BFS_STAT_ATIME; - dest->ctime = src->st_ctim; + dest->ctime = ST_CTIM(*src); dest->mask |= BFS_STAT_CTIME; - dest->mtime = src->st_mtim; + dest->mtime = ST_MTIM(*src); dest->mask |= BFS_STAT_MTIME; -#if __APPLE__ || __FreeBSD__ || __NetBSD__ +#if BFS_HAS_ST_BIRTHTIM dest->btime = src->st_birthtim; dest->mask |= BFS_STAT_BTIME; +#elif BFS_HAS_ST_BIRTHTIMESPEC + dest->btime = src->st_birthtimespec; + dest->mask |= BFS_STAT_BTIME; #endif } @@ -137,7 +140,7 @@ static int bfs_stat_impl(int at_fd, const char *at_path, int at_flags, struct bf * Wrapper for the statx() system call, which had no glibc wrapper prior to 2.28. */ static int bfs_statx(int at_fd, const char *at_path, int at_flags, unsigned int mask, struct statx *buf) { -#if BFS_HAS_LIBC_STATX +#if BFS_HAS_STATX int ret = statx(at_fd, at_path, at_flags, mask, buf); #else int ret = syscall(SYS_statx, at_fd, at_path, at_flags, mask, buf); @@ -12,21 +12,17 @@ #ifndef BFS_STAT_H #define BFS_STAT_H -#include "config.h" +#include "prelude.h" #include <sys/stat.h> #include <sys/types.h> #include <time.h> -#if defined(STATX_BASIC_STATS) && (!__ANDROID__ || __ANDROID_API__ >= 30) -# define BFS_HAS_LIBC_STATX true -#elif __linux__ +#if !BFS_HAS_STATX && BFS_HAS_STATX_SYSCALL # include <linux/stat.h> #endif #ifndef BFS_USE_STATX -# ifdef STATX_BASIC_STATS -# define BFS_USE_STATX true -# endif +# define BFS_USE_STATX (BFS_HAS_STATX || BFS_HAS_STATX_SYSCALL) #endif #if BFS_USE_SYS_PARAM_H diff --git a/src/thread.c b/src/thread.c index 200d8c3..3793896 100644 --- a/src/thread.c +++ b/src/thread.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "thread.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include <errno.h> #include <pthread.h> diff --git a/src/thread.h b/src/thread.h index 8174fe4..db11bd8 100644 --- a/src/thread.h +++ b/src/thread.h @@ -8,7 +8,7 @@ #ifndef BFS_THREAD_H #define BFS_THREAD_H -#include "config.h" +#include "prelude.h" #include <pthread.h> #if __STDC_VERSION__ < C23 && !defined(thread_local) @@ -81,10 +81,10 @@ * and insert intermediate singleton "jump" nodes when necessary. */ +#include "prelude.h" #include "trie.h" #include "alloc.h" #include "bit.h" -#include "config.h" #include "diag.h" #include "list.h" #include <stdint.h> diff --git a/src/xregex.c b/src/xregex.c index 3df27f0..c2711bc 100644 --- a/src/xregex.c +++ b/src/xregex.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "xregex.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include "sanity.h" #include "thread.h" diff --git a/src/xspawn.c b/src/xspawn.c index 347625d..0b0cea4 100644 --- a/src/xspawn.c +++ b/src/xspawn.c @@ -1,10 +1,10 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "xspawn.h" #include "alloc.h" #include "bfstd.h" -#include "config.h" #include "list.h" #include <errno.h> #include <fcntl.h> @@ -212,7 +212,7 @@ int bfs_spawn_adddup2(struct bfs_spawn *ctx, int oldfd, int newfd) { * but macOS and NetBSD resolve the PATH *before* file_actions (because there * posix_spawn() is its own syscall). */ -#define BFS_POSIX_SPAWNP_AFTER_FCHDIR !(__APPLE__ || __NetBSD_Prereq__(10, 0, 0)) +#define BFS_POSIX_SPAWNP_AFTER_FCHDIR !(__APPLE__ || __NetBSD__) int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) { struct bfs_spawn_action *action = bfs_spawn_action(BFS_SPAWN_FCHDIR); @@ -220,29 +220,15 @@ int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) { return -1; } -#ifndef BFS_HAS_POSIX_SPAWN_FCHDIR -# define BFS_HAS_POSIX_SPAWN_FCHDIR __NetBSD_Prereq__(10, 0, 0) -#endif - -#ifndef BFS_HAS_POSIX_SPAWN_FCHDIR_NP -# if __GLIBC__ -# define BFS_HAS_POSIX_SPAWN_FCHDIR_NP __GLIBC_PREREQ(2, 29) -# elif __ANDROID__ -# define BFS_HAS_POSIX_SPAWN_FCHDIR_NP (__ANDROID_API__ >= 34) -# else -# define BFS_HAS_POSIX_SPAWN_FCHDIR_NP (__linux__ || __FreeBSD__ || __APPLE__) -# endif -#endif - -#if BFS_HAS_POSIX_SPAWN_FCHDIR -# define BFS_POSIX_SPAWN_FCHDIR posix_spawn_file_actions_addfchdir -#elif BFS_HAS_POSIX_SPAWN_FCHDIR_NP -# define BFS_POSIX_SPAWN_FCHDIR posix_spawn_file_actions_addfchdir_np +#if BFS_HAS_POSIX_SPAWN_ADDFCHDIR +# define BFS_POSIX_SPAWN_ADDFCHDIR posix_spawn_file_actions_addfchdir +#elif BFS_HAS_POSIX_SPAWN_ADDFCHDIR_NP +# define BFS_POSIX_SPAWN_ADDFCHDIR posix_spawn_file_actions_addfchdir_np #endif #if _POSIX_SPAWN > 0 && defined(BFS_POSIX_SPAWN_FCHDIR) if (ctx->flags & BFS_SPAWN_USE_POSIX) { - errno = BFS_POSIX_SPAWN_FCHDIR(&ctx->actions, fd); + errno = BFS_POSIX_SPAWN_ADDFCHDIR(&ctx->actions, fd); if (errno != 0) { free(action); return -1; diff --git a/src/xspawn.h b/src/xspawn.h index a20cbd0..6a8f54a 100644 --- a/src/xspawn.h +++ b/src/xspawn.h @@ -8,7 +8,7 @@ #ifndef BFS_XSPAWN_H #define BFS_XSPAWN_H -#include "config.h" +#include "prelude.h" #include <sys/resource.h> #include <sys/types.h> #include <unistd.h> diff --git a/src/xtime.c b/src/xtime.c index bcf6dd3..91ed915 100644 --- a/src/xtime.c +++ b/src/xtime.c @@ -1,9 +1,9 @@ // Copyright © Tavian Barnes <tavianator@tavianator.com> // SPDX-License-Identifier: 0BSD +#include "prelude.h" #include "xtime.h" #include "bfstd.h" -#include "config.h" #include "diag.h" #include <errno.h> #include <limits.h> |