diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2022-04-15 14:34:45 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2022-04-15 14:34:45 -0400 |
commit | 33b477d90dbad8664d7393d65f8df4e73882cb66 (patch) | |
tree | 8f6d5ec49ba69d5771f7229ca677adf128cb7db5 | |
parent | acf934993a8112023f111ae1dfedc90f40e1d496 (diff) | |
download | bfs-33b477d90dbad8664d7393d65f8df4e73882cb66.tar.xz |
eval: Use BFTW_BUFFER when deleting files on FreeBSD
Works around #67.
-rw-r--r-- | eval.c | 35 |
1 files changed, 35 insertions, 0 deletions
@@ -1512,6 +1512,7 @@ static void dump_bftw_flags(enum bftw_flags flags) { DEBUG_FLAG(flags, BFTW_SKIP_MOUNTS); DEBUG_FLAG(flags, BFTW_PRUNE_MOUNTS); DEBUG_FLAG(flags, BFTW_SORT); + DEBUG_FLAG(flags, BFTW_BUFFER); assert(!flags); } @@ -1529,6 +1530,36 @@ static const char *dump_bftw_strategy(enum bftw_strategy strategy) { return strategies[strategy]; } +/** Check if we need to enable BFTW_BUFFER. */ +static bool eval_must_buffer(const struct bfs_expr *expr) { +#if __FreeBSD__ + // FreeBSD doesn't properly handle adding/removing directory entries + // during readdir() on NFS mounts. Work around it by passing BFTW_BUFFER + // whenever we could be mutating the directory ourselves through -delete + // or -exec. We don't attempt to handle concurrent modification by other + // processes, which are racey anyway. + // + // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=57696 + // https://github.com/tavianator/bfs/issues/67 + + if (expr->eval_fn == eval_delete || expr->eval_fn == eval_exec) { + return true; + } + + if (bfs_expr_has_children(expr)) { + if (expr->lhs && eval_must_buffer(expr->lhs)) { + return true; + } + + if (expr->rhs && eval_must_buffer(expr->rhs)) { + return true; + } + } +#endif // __FreeBSD__ + + return false; +} + int bfs_eval(const struct bfs_ctx *ctx) { if (!ctx->expr) { return EXIT_SUCCESS; @@ -1566,6 +1597,10 @@ int bfs_eval(const struct bfs_ctx *ctx) { .mtab = bfs_ctx_mtab(ctx), }; + if (eval_must_buffer(ctx->expr)) { + bftw_args.flags |= BFTW_BUFFER; + } + if (bfs_debug(ctx, DEBUG_SEARCH, "bftw({\n")) { fprintf(stderr, "\t.paths = {\n"); for (size_t i = 0; i < bftw_args.npaths; ++i) { |