diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2023-10-17 11:55:19 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2023-10-17 12:33:39 -0400 |
commit | 68949cf1b9cb5336ea06ad7f87db8e28b620f2ac (patch) | |
tree | b481fbc43d98d5e3606dd8646440ce0ae0f09b9f | |
parent | 332f38aff0e6b7bc1a3a648eb66437d2d043ad21 (diff) | |
download | bfs-68949cf1b9cb5336ea06ad7f87db8e28b620f2ac.tar.xz |
bftw: New flag to control whiteout visibility
-rw-r--r-- | src/bftw.c | 18 | ||||
-rw-r--r-- | src/bftw.h | 2 | ||||
-rw-r--r-- | src/eval.c | 1 |
3 files changed, 19 insertions, 2 deletions
@@ -41,6 +41,13 @@ static const struct bfs_stat *bftw_stat_impl(struct BFTW *ftwbuf, struct bftw_st errno = cache->error; } else if (bfs_stat(ftwbuf->at_fd, ftwbuf->at_path, flags, &cache->storage) == 0) { cache->buf = &cache->storage; +#ifdef S_IFWHT + } else if (errno == ENOENT && ftwbuf->type == BFS_WHT) { + // This matches the behavior of FTS_WHITEOUT on BSD + memset(&cache->storage, 0, sizeof(cache->storage)); + cache->storage.mode = S_IFWHT; + cache->buf = &cache->storage; +#endif } else { cache->error = errno; } @@ -410,6 +417,8 @@ struct bftw_state { enum bftw_strategy strategy; /** The mount table. */ const struct bfs_mtab *mtab; + /** bfs_opendir() flags. */ + enum bfs_dir_flags dir_flags; /** The appropriate errno value, if any. */ int error; @@ -492,6 +501,7 @@ static int bftw_state_init(struct bftw_state *state, const struct bftw_args *arg state->flags = args->flags; state->strategy = args->strategy; state->mtab = args->mtab; + state->dir_flags = 0; state->error = 0; if (args->nopenfd < 2) { @@ -527,6 +537,10 @@ static int bftw_state_init(struct bftw_state *state, const struct bftw_args *arg state->flags |= BFTW_BUFFER; } + if (state->flags & BFTW_WHITEOUTS) { + state->dir_flags |= BFS_DIR_WHITEOUTS; + } + SLIST_INIT(&state->dir_batch); SLIST_INIT(&state->to_open); SLIST_INIT(&state->to_read); @@ -856,7 +870,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, 0, file) != 0) { + if (ioq_opendir(state->ioq, dir, dfd, file->name, state->dir_flags, file) != 0) { goto free; } @@ -1018,7 +1032,7 @@ static struct bfs_dir *bftw_file_opendir(struct bftw_state *state, struct bftw_f return NULL; } - if (bfs_opendir(dir, fd, NULL, 0) != 0) { + if (bfs_opendir(dir, fd, NULL, state->dir_flags) != 0) { bftw_freedir(cache, dir); return NULL; } @@ -156,6 +156,8 @@ enum bftw_flags { BFTW_SORT = 1 << 8, /** Read each directory into memory before processing its children. */ BFTW_BUFFER = 1 << 9, + /** Include whiteouts in the search results. */ + BFTW_WHITEOUTS = 1 << 10, }; /** @@ -1572,6 +1572,7 @@ static void dump_bftw_flags(enum bftw_flags flags) { DEBUG_FLAG(flags, BFTW_PRUNE_MOUNTS); DEBUG_FLAG(flags, BFTW_SORT); DEBUG_FLAG(flags, BFTW_BUFFER); + DEBUG_FLAG(flags, BFTW_WHITEOUTS); bfs_assert(flags == 0, "Missing bftw flag 0x%X", flags); } |