diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2023-04-11 22:06:42 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2023-06-12 14:39:34 -0400 |
commit | 0c10a1e984bc2bed1fe3a7dadbd94a9c24139a91 (patch) | |
tree | 43073ba63fc54b0b30e587aaf71c9e66b721c888 /src | |
parent | e8df57b5a49a70e2daa5bb6c00b8e0e06c51306a (diff) | |
download | bfs-0c10a1e984bc2bed1fe3a7dadbd94a9c24139a91.tar.xz |
dir: Add a flag to bfs_freedir() to force the fd to stay the same
Diffstat (limited to 'src')
-rw-r--r-- | src/bftw.c | 4 | ||||
-rw-r--r-- | src/dir.c | 18 | ||||
-rw-r--r-- | src/dir.h | 10 | ||||
-rw-r--r-- | src/ioq.c | 1 |
4 files changed, 24 insertions, 9 deletions
@@ -853,13 +853,13 @@ static int bftw_gc(struct bftw_state *state, enum bftw_gc_flags flags) { if (file->refcount > 1) { // Keep the fd around if any subdirectories exist - file->fd = bfs_freedir(state->dir); + file->fd = bfs_freedir(state->dir, false); } else { - bfs_closedir(state->dir); file->fd = -1; } if (file->fd < 0) { + bfs_closedir(state->dir); bftw_cache_remove(&state->cache, file); } } @@ -243,13 +243,15 @@ int bfs_closedir(struct bfs_dir *dir) { int ret = xclose(dir->fd); #else int ret = closedir(dir->dir); - bfs_verify(ret == 0 || errno != EBADF); + if (ret != 0) { + bfs_verify(errno != EBADF); + } #endif free(dir); return ret; } -int bfs_freedir(struct bfs_dir *dir) { +int bfs_freedir(struct bfs_dir *dir, bool same_fd) { #if BFS_GETDENTS int ret = dir->fd; free(dir); @@ -257,10 +259,16 @@ int bfs_freedir(struct bfs_dir *dir) { int ret = fdclosedir(dir->dir); free(dir); #else + if (same_fd) { + errno = ENOTSUP; + return -1; + } + int ret = dup_cloexec(dirfd(dir->dir)); - int error = errno; - bfs_closedir(dir); - errno = error; + if (ret >= 0) { + bfs_closedir(dir); + } #endif + return ret; } @@ -8,6 +8,7 @@ #ifndef BFS_DIR_H #define BFS_DIR_H +#include "config.h" #include <sys/types.h> /** @@ -103,9 +104,14 @@ int bfs_closedir(struct bfs_dir *dir); * * @param dir * The directory to free. + * @param same_fd + * If true, require that the returned file descriptor is the same one + * that bfs_dirfd() would have returned. Otherwise, it may be a new + * file descriptor for the same directory. * @return - * The file descriptor on success, or -1 on failure. + * On success, a file descriptor for the directory is returned. On + * failure, -1 is returned, and the directory remains open. */ -int bfs_freedir(struct bfs_dir *dir); +int bfs_freedir(struct bfs_dir *dir, bool same_fd); #endif // BFS_DIR_H @@ -155,6 +155,7 @@ static void *ioq_work(void *ptr) { sanitize_uninit(cmd); struct ioq_res *res = &cmd->res; + res->ptr = req.ptr; res->dir = bfs_opendir(req.dfd, req.path); res->error = errno; ioqq_push(ioq->ready, cmd); |