summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c8
-rw-r--r--src/alloc.h2
-rw-r--r--src/bar.c2
-rw-r--r--src/bfstd.c130
-rw-r--r--src/bfstd.h22
-rw-r--r--src/bftw.c2
-rw-r--r--src/bftw.h4
-rw-r--r--src/bit.h2
-rw-r--r--src/color.c2
-rw-r--r--src/color.h2
-rw-r--r--src/ctx.c2
-rw-r--r--src/ctx.h2
-rw-r--r--src/diag.c2
-rw-r--r--src/diag.h2
-rw-r--r--src/dir.c18
-rw-r--r--src/dir.h7
-rw-r--r--src/dstring.c3
-rw-r--r--src/dstring.h2
-rw-r--r--src/eval.c42
-rw-r--r--src/eval.h2
-rw-r--r--src/exec.c2
-rw-r--r--src/expr.h2
-rw-r--r--src/fsade.c131
-rw-r--r--src/fsade.h11
-rw-r--r--src/ioq.c7
-rw-r--r--src/ioq.h2
-rw-r--r--src/main.c4
-rw-r--r--src/mtab.c2
-rw-r--r--src/mtab.h2
-rw-r--r--src/opt.c8
-rw-r--r--src/parse.c4
-rw-r--r--src/prelude.h (renamed from src/config.h)52
-rw-r--r--src/printf.c120
-rw-r--r--src/pwcache.c2
-rw-r--r--src/sanity.h2
-rw-r--r--src/stat.c19
-rw-r--r--src/stat.h10
-rw-r--r--src/thread.c2
-rw-r--r--src/thread.h2
-rw-r--r--src/trie.c2
-rw-r--r--src/xregex.c2
-rw-r--r--src/xspawn.c28
-rw-r--r--src/xspawn.h2
-rw-r--r--src/xtime.c2
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>
diff --git a/src/bar.c b/src/bar.c
index 8ab4112..184d9a0 100644
--- a/src/bar.c
+++ b/src/bar.c
@@ -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>
diff --git a/src/bftw.c b/src/bftw.c
index 6130c44..c4d3c17 100644
--- a/src/bftw.c
+++ b/src/bftw.c
@@ -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"
diff --git a/src/bftw.h b/src/bftw.h
index 2805361..8656ca7 100644
--- a/src/bftw.h
+++ b/src/bftw.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);
diff --git a/src/bit.h b/src/bit.h
index 69df21e..17cfbcf 100644
--- a/src/bit.h
+++ b/src/bit.h
@@ -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>
diff --git a/src/ctx.c b/src/ctx.c
index f5b28c7..aa73b35 100644
--- a/src/ctx.c
+++ b/src/ctx.c
@@ -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;
}
diff --git a/src/ctx.h b/src/ctx.h
index e14db21..fc3020c 100644
--- a/src/ctx.h
+++ b/src/ctx.h
@@ -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"
diff --git a/src/diag.c b/src/diag.c
index cb27b92..deb6f26 100644
--- a/src/diag.c
+++ b/src/diag.c
@@ -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"
diff --git a/src/diag.h b/src/diag.h
index 4054c48..2b13609 100644
--- a/src/diag.h
+++ b/src/diag.h
@@ -8,7 +8,7 @@
#ifndef BFS_DIAG_H
#define BFS_DIAG_H
-#include "config.h"
+#include "prelude.h"
#include <stdarg.h>
/**
diff --git a/src/dir.c b/src/dir.c
index 98518f2..cfbbca4 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -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
diff --git a/src/dir.h b/src/dir.h
index 18d907e..6d5c9c5 100644
--- a/src/dir.h
+++ b/src/dir.h
@@ -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>
diff --git a/src/eval.c b/src/eval.c
index d0112c2..49028b7 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -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;
+ }
}
/**
diff --git a/src/eval.h b/src/eval.h
index ae43628..4dd7996 100644
--- a/src/eval.h
+++ b/src/eval.h
@@ -9,7 +9,7 @@
#ifndef BFS_EVAL_H
#define BFS_EVAL_H
-#include "config.h"
+#include "prelude.h"
struct bfs_ctx;
struct bfs_expr;
diff --git a/src/exec.c b/src/exec.c
index 60bfd28..e782d49 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -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"
diff --git a/src/expr.h b/src/expr.h
index 75cb5fd..7bcace7 100644
--- a/src/expr.h
+++ b/src/expr.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
diff --git a/src/ioq.c b/src/ioq.c
index b936681..43a1b35 100644
--- a/src/ioq.c
+++ b/src/ioq.c
@@ -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
diff --git a/src/ioq.h b/src/ioq.h
index 818eea6..d8e1573 100644
--- a/src/ioq.h
+++ b/src/ioq.h
@@ -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>
diff --git a/src/main.c b/src/main.c
index e120f03..9d8b206 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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"
diff --git a/src/mtab.c b/src/mtab.c
index 86ae151..7905d14 100644
--- a/src/mtab.c
+++ b/src/mtab.c
@@ -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>
diff --git a/src/mtab.h b/src/mtab.h
index d99d78f..67290c2 100644
--- a/src/mtab.h
+++ b/src/mtab.h
@@ -8,7 +8,7 @@
#ifndef BFS_MTAB_H
#define BFS_MTAB_H
-#include "config.h"
+#include "prelude.h"
struct bfs_stat;
diff --git a/src/opt.c b/src/opt.c
index b74b4e1..883d598 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -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", &copybuf);
} 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__)
diff --git a/src/stat.c b/src/stat.c
index 2f2743b..f5cf3fe 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -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);
diff --git a/src/stat.h b/src/stat.h
index 856a2ca..8d7144d 100644
--- a/src/stat.h
+++ b/src/stat.h
@@ -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)
diff --git a/src/trie.c b/src/trie.c
index f275064..808953e 100644
--- a/src/trie.c
+++ b/src/trie.c
@@ -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>