]> Sergey Matveev's repositories - bfs.git/commitdiff
bftw: New flag to control whiteout visibility
authorTavian Barnes <tavianator@tavianator.com>
Tue, 17 Oct 2023 15:55:19 +0000 (11:55 -0400)
committerTavian Barnes <tavianator@tavianator.com>
Tue, 17 Oct 2023 16:33:39 +0000 (12:33 -0400)
src/bftw.c
src/bftw.h
src/eval.c

index e2f1a660f4606c7ba752ca6e6f66b5d93941a456..dff949f0d977cb5c35eb54500207cec478da11ce 100644 (file)
@@ -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;
        }
index 940532c4b419ee012e33ffbce146d81aee8745e5..2b36b8b172e06736c1f0781f97f31b22b4b378c8 100644 (file)
@@ -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,
 };
 
 /**
index adf7a0b92d787ca65b15bbbbbdfca17ccbac92b9..3d396fa0a938c50fcc48c19a0675faa82452aaf4 100644 (file)
@@ -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);
 }