From 214a1f9215d33d4b9f34a3d258da1e1f4e3eb01f Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 16 Oct 2023 16:44:46 -0400 Subject: dir: Add a flags parameter to bfs_opendir() --- src/bftw.c | 4 ++-- src/dir.c | 31 ++++++++++++++++++++----------- src/dir.h | 12 +++++++++++- src/eval.c | 6 +++--- src/ioq.c | 7 ++++--- src/ioq.h | 6 +++++- 6 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/bftw.c b/src/bftw.c index 06a0085..e2f1a66 100644 --- a/src/bftw.c +++ b/src/bftw.c @@ -856,7 +856,7 @@ static int bftw_ioq_opendir(struct bftw_state *state, struct bftw_file *file) { goto unpin; } - if (ioq_opendir(state->ioq, dir, dfd, file->name, file) != 0) { + if (ioq_opendir(state->ioq, dir, dfd, file->name, 0, file) != 0) { goto free; } @@ -1018,7 +1018,7 @@ static struct bfs_dir *bftw_file_opendir(struct bftw_state *state, struct bftw_f return NULL; } - if (bfs_opendir(dir, fd, NULL) != 0) { + if (bfs_opendir(dir, fd, NULL, 0) != 0) { bftw_freedir(cache, dir); return NULL; } diff --git a/src/dir.c b/src/dir.c index a7423e9..dee02e5 100644 --- a/src/dir.c +++ b/src/dir.c @@ -96,18 +96,26 @@ enum bfs_type bfs_mode_to_type(mode_t mode) { } } +/** + * Private directory flags. + */ +enum { + /** We've reached the end of the directory. */ + BFS_DIR_EOF = BFS_DIR_PRIVATE << 0, +}; + struct bfs_dir { + unsigned int flags; + #if BFS_USE_GETDENTS - alignas(sys_dirent) int fd; + int fd; unsigned short pos; unsigned short size; - // sys_dirent buf[]; + alignas(sys_dirent) char buf[]; #else DIR *dir; struct dirent *de; #endif - - bool eof; }; #if BFS_USE_GETDENTS @@ -125,7 +133,7 @@ void bfs_dir_arena(struct arena *arena) { arena_init(arena, alignof(struct bfs_dir), DIR_SIZE); } -int bfs_opendir(struct bfs_dir *dir, int at_fd, const char *at_path) { +int bfs_opendir(struct bfs_dir *dir, int at_fd, const char *at_path, enum bfs_dir_flags flags) { int fd; if (at_path) { fd = openat(at_fd, at_path, O_RDONLY | O_CLOEXEC | O_DIRECTORY); @@ -139,6 +147,8 @@ int bfs_opendir(struct bfs_dir *dir, int at_fd, const char *at_path) { return -1; } + dir->flags = flags; + #if BFS_USE_GETDENTS dir->fd = fd; dir->pos = 0; @@ -154,7 +164,6 @@ int bfs_opendir(struct bfs_dir *dir, int at_fd, const char *at_path) { dir->de = NULL; #endif - dir->eof = false; return 0; } @@ -170,14 +179,14 @@ int bfs_polldir(struct bfs_dir *dir) { #if BFS_USE_GETDENTS if (dir->pos < dir->size) { return 1; - } else if (dir->eof) { + } else if (dir->flags & BFS_DIR_EOF) { return 0; } char *buf = (char *)(dir + 1); ssize_t size = bfs_getdents(dir->fd, buf, BUF_SIZE); if (size == 0) { - dir->eof = true; + dir->flags |= BFS_DIR_EOF; return 0; } else if (size < 0) { return -1; @@ -194,7 +203,7 @@ int bfs_polldir(struct bfs_dir *dir) { if (size > 0) { dir->size += size; } else if (size == 0) { - dir->eof = true; + dir->flags |= BFS_DIR_EOF; } } @@ -202,7 +211,7 @@ int bfs_polldir(struct bfs_dir *dir) { #else // !BFS_USE_GETDENTS if (dir->de) { return 1; - } else if (dir->eof) { + } else if (dir->flags & BFS_DIR_EOF) { return 0; } @@ -211,7 +220,7 @@ int bfs_polldir(struct bfs_dir *dir) { if (dir->de) { return 1; } else if (errno == 0) { - dir->eof = true; + dir->flags |= BFS_DIR_EOF; return 0; } else { return -1; diff --git a/src/dir.h b/src/dir.h index 1137ff5..7e0cbba 100644 --- a/src/dir.h +++ b/src/dir.h @@ -86,6 +86,14 @@ struct bfs_dir *bfs_allocdir(void); */ void bfs_dir_arena(struct arena *arena); +/** + * bfs_opendir() flags. + */ +enum bfs_dir_flags { + /** @internal Start of private flags. */ + BFS_DIR_PRIVATE = 1 << 0, +}; + /** * Open a directory. * @@ -96,10 +104,12 @@ void bfs_dir_arena(struct arena *arena); * @param at_path * The path of the directory to open, relative to at_fd. Pass NULL to * open at_fd itself. + * @param flags + * Flags that control which directory entries are listed. * @return * 0 on success, or -1 on failure. */ -int bfs_opendir(struct bfs_dir *dir, int at_fd, const char *at_path); +int bfs_opendir(struct bfs_dir *dir, int at_fd, const char *at_path, enum bfs_dir_flags flags); /** * Get the file descriptor for a directory. diff --git a/src/eval.c b/src/eval.c index e0dd97b..adf7a0b 100644 --- a/src/eval.c +++ b/src/eval.c @@ -427,7 +427,7 @@ bool eval_empty(const struct bfs_expr *expr, struct bfs_eval *state) { return ret; } - if (bfs_opendir(dir, ftwbuf->at_fd, ftwbuf->at_path) != 0) { + if (bfs_opendir(dir, ftwbuf->at_fd, ftwbuf->at_path, 0) != 0) { eval_report_error(state); return ret; } @@ -1517,8 +1517,8 @@ static int infer_fdlimit(const struct bfs_ctx *ctx, int limit) { goto done; } - if (bfs_opendir(dir, AT_FDCWD, "/proc/self/fd") != 0 - && bfs_opendir(dir, AT_FDCWD, "/dev/fd") != 0) { + if (bfs_opendir(dir, AT_FDCWD, "/proc/self/fd", 0) != 0 + && bfs_opendir(dir, AT_FDCWD, "/dev/fd", 0) != 0) { goto done; } diff --git a/src/ioq.c b/src/ioq.c index 04b9c0d..8c1bdbe 100644 --- a/src/ioq.c +++ b/src/ioq.c @@ -348,7 +348,7 @@ static void ioq_handle(struct ioq *ioq, struct ioq_ent *ent) { break; case IOQ_OPENDIR: - ret = bfs_opendir(ent->opendir.dir, ent->opendir.dfd, ent->opendir.path); + ret = bfs_opendir(ent->opendir.dir, ent->opendir.dfd, ent->opendir.path, ent->opendir.flags); if (ret == 0) { bfs_polldir(ent->opendir.dir); } @@ -505,7 +505,7 @@ static void ioq_ring_reap(struct ioq_ring_state *state) { continue; } - ent->ret = bfs_opendir(ent->opendir.dir, fd, NULL); + ent->ret = bfs_opendir(ent->opendir.dir, fd, NULL, ent->opendir.flags); if (ent->ret == 0) { // TODO: io_uring_prep_getdents() bfs_polldir(ent->opendir.dir); @@ -659,7 +659,7 @@ int ioq_close(struct ioq *ioq, int fd, void *ptr) { return 0; } -int ioq_opendir(struct ioq *ioq, struct bfs_dir *dir, int dfd, const char *path, void *ptr) { +int ioq_opendir(struct ioq *ioq, struct bfs_dir *dir, int dfd, const char *path, enum bfs_dir_flags flags, void *ptr) { struct ioq_ent *ent = ioq_request(ioq, IOQ_OPENDIR, ptr); if (!ent) { return -1; @@ -669,6 +669,7 @@ int ioq_opendir(struct ioq *ioq, struct bfs_dir *dir, int dfd, const char *path, args->dir = dir; args->dfd = dfd; args->path = path; + args->flags = flags; ioqq_push(ioq->pending, ent); return 0; diff --git a/src/ioq.h b/src/ioq.h index 99c18c2..eab89ec 100644 --- a/src/ioq.h +++ b/src/ioq.h @@ -8,6 +8,7 @@ #ifndef BFS_IOQ_H #define BFS_IOQ_H +#include "dir.h" #include /** @@ -53,6 +54,7 @@ struct ioq_ent { struct bfs_dir *dir; int dfd; const char *path; + enum bfs_dir_flags flags; } opendir; /** ioq_closedir() args. */ struct ioq_closedir { @@ -103,12 +105,14 @@ int ioq_close(struct ioq *ioq, int fd, void *ptr); * The base file descriptor. * @param path * The path to open, relative to dfd. + * @param flags + * Flags that control which directory entries are listed. * @param ptr * An arbitrary pointer to associate with the request. * @return * 0 on success, or -1 on failure. */ -int ioq_opendir(struct ioq *ioq, struct bfs_dir *dir, int dfd, const char *path, void *ptr); +int ioq_opendir(struct ioq *ioq, struct bfs_dir *dir, int dfd, const char *path, enum bfs_dir_flags flags, void *ptr); /** * Asynchronous bfs_closedir(). -- cgit v1.2.3