summaryrefslogtreecommitdiffstats
path: root/bftw.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2019-07-04 17:07:50 -0400
committerTavian Barnes <tavianator@tavianator.com>2019-07-04 17:07:50 -0400
commitd3e64d6e1f905cd67264845c38b38fc6d1bdb088 (patch)
tree52a303272ec29b520b7d9d1f0237290b1e38ab3d /bftw.c
parent43039c98eb6bc2514434fe3b33faa3eb32e75ba3 (diff)
downloadbfs-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.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/bftw.c b/bftw.c
index 444310c..370ab12 100644
--- a/bftw.c
+++ b/bftw.c
@@ -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: