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;
}
return NULL;
}
- if (bfs_opendir(dir, fd, NULL) != 0) {
+ if (bfs_opendir(dir, fd, NULL, 0) != 0) {
bftw_freedir(cache, dir);
return NULL;
}
}
}
+/**
+ * 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
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);
return -1;
}
+ dir->flags = flags;
+
#if BFS_USE_GETDENTS
dir->fd = fd;
dir->pos = 0;
dir->de = NULL;
#endif
- dir->eof = false;
return 0;
}
#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;
if (size > 0) {
dir->size += size;
} else if (size == 0) {
- dir->eof = true;
+ dir->flags |= BFS_DIR_EOF;
}
}
#else // !BFS_USE_GETDENTS
if (dir->de) {
return 1;
- } else if (dir->eof) {
+ } else if (dir->flags & BFS_DIR_EOF) {
return 0;
}
if (dir->de) {
return 1;
} else if (errno == 0) {
- dir->eof = true;
+ dir->flags |= BFS_DIR_EOF;
return 0;
} else {
return -1;
*/
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.
*
* @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.
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;
}
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;
}
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);
}
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);
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;
args->dir = dir;
args->dfd = dfd;
args->path = path;
+ args->flags = flags;
ioqq_push(ioq->pending, ent);
return 0;
#ifndef BFS_IOQ_H
#define BFS_IOQ_H
+#include "dir.h"
#include <stddef.h>
/**
struct bfs_dir *dir;
int dfd;
const char *path;
+ enum bfs_dir_flags flags;
} opendir;
/** ioq_closedir() args. */
struct ioq_closedir {
* 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().