summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bftw.c4
-rw-r--r--src/dir.c18
-rw-r--r--src/dir.h10
-rw-r--r--src/ioq.c1
4 files changed, 24 insertions, 9 deletions
diff --git a/src/bftw.c b/src/bftw.c
index 916a56b..a3e8d9b 100644
--- a/src/bftw.c
+++ b/src/bftw.c
@@ -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);
}
}
diff --git a/src/dir.c b/src/dir.c
index 01d26db..126f473 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -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;
}
diff --git a/src/dir.h b/src/dir.h
index 01eaaba..e0fe913 100644
--- a/src/dir.h
+++ b/src/dir.h
@@ -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
diff --git a/src/ioq.c b/src/ioq.c
index e09c2a9..1b61fb0 100644
--- a/src/ioq.c
+++ b/src/ioq.c
@@ -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);