diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2019-07-04 17:07:50 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2019-07-04 17:07:50 -0400 |
commit | d3e64d6e1f905cd67264845c38b38fc6d1bdb088 (patch) | |
tree | 52a303272ec29b520b7d9d1f0237290b1e38ab3d /bftw.c | |
parent | 43039c98eb6bc2514434fe3b33faa3eb32e75ba3 (diff) | |
download | bfs-d3e64d6e1f905cd67264845c38b38fc6d1bdb088.tar.xz |
Make -mount and -xdev do different things
POSIX now says -mount should skip the whole mount point, while -xdev
should only skip its descendents.
C.f. http://austingroupbugs.net/view.php?id=1133
C.f. https://savannah.gnu.org/bugs/?42318
C.f. https://savannah.gnu.org/bugs/?54745
Diffstat (limited to 'bftw.c')
-rw-r--r-- | bftw.c | 39 |
1 files changed, 25 insertions, 14 deletions
@@ -901,7 +901,7 @@ static bool bftw_need_stat(const struct bftw_state *state) { } if (ftwbuf->typeflag == BFTW_DIR) { - if (state->flags & (BFTW_DETECT_CYCLES | BFTW_XDEV)) { + if (state->flags & (BFTW_DETECT_CYCLES | BFTW_MOUNT | BFTW_XDEV)) { return true; } #if __linux__ @@ -1041,6 +1041,23 @@ static void bftw_init_ftwbuf(struct bftw_state *state, enum bftw_visit visit) { } } +/** Check if the current file is a mount point. */ +static bool bftw_is_mount(struct bftw_state *state, const char *name) { + const struct bftw_file *file = state->file; + if (!file) { + return false; + } + + const struct bftw_file *parent = name ? file : file->parent; + if (!parent) { + return false; + } + + const struct BFTW *ftwbuf = &state->ftwbuf; + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + return statbuf && statbuf->dev != parent->dev; +} + /** Fill file identity information from an ftwbuf. */ static void bftw_fill_id(struct bftw_file *file, const struct BFTW *ftwbuf) { const struct bfs_stat *statbuf = ftwbuf->stat_cache.buf; @@ -1071,6 +1088,10 @@ static enum bftw_action bftw_visit(struct bftw_state *state, const char *name, e return BFTW_STOP; } + if ((state->flags & BFTW_MOUNT) && bftw_is_mount(state, name)) { + return BFTW_PRUNE; + } + enum bftw_action ret = state->callback(ftwbuf, state->ptr); switch (ret) { case BFTW_CONTINUE: @@ -1088,19 +1109,9 @@ static enum bftw_action bftw_visit(struct bftw_state *state, const char *name, e goto done; } - if (state->flags & BFTW_XDEV) { - const struct bftw_file *parent = state->file; - if (parent && !name) { - parent = parent->parent; - } - - if (parent) { - const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); - if (statbuf && statbuf->dev != parent->dev) { - ret = BFTW_PRUNE; - goto done; - } - } + if ((state->flags & BFTW_XDEV) && bftw_is_mount(state, name)) { + ret = BFTW_PRUNE; + goto done; } done: |