summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2020-09-27 12:55:55 -0400
committerTavian Barnes <tavianator@tavianator.com>2020-09-27 13:23:49 -0400
commit62bbbe1a4165f63b31c68b1595ecb0e67d7af3dc (patch)
treec770ff13f37023cae132108b29077a904e6d4dfb /eval.c
parent3c83bf4e1920be909f65945e56dc8b779c472a59 (diff)
downloadbfs-62bbbe1a4165f63b31c68b1595ecb0e67d7af3dc.tar.xz
Rename struct cmdline to bfs_ctx
The API remains similar, with some added accessor functions for lazy initialization of the pwcache and mtab.
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c146
1 files changed, 80 insertions, 66 deletions
diff --git a/eval.c b/eval.c
index 1498282..ca8c78f 100644
--- a/eval.c
+++ b/eval.c
@@ -20,7 +20,6 @@
#include "eval.h"
#include "bftw.h"
-#include "cmdline.h"
#include "color.h"
#include "darray.h"
#include "diag.h"
@@ -54,11 +53,11 @@
struct eval_state {
/** Data about the current file. */
const struct BFTW *ftwbuf;
- /** The parsed command line. */
- const struct cmdline *cmdline;
+ /** The bfs context. */
+ const struct bfs_ctx *ctx;
/** The bftw() callback return value. */
enum bftw_action action;
- /** The eval_cmdline() return value. */
+ /** The bfs_eval() return value. */
int *ret;
/** Whether to quit immediately. */
bool quit;
@@ -70,10 +69,10 @@ struct eval_state {
BFS_FORMATTER(2, 3)
static void eval_error(struct eval_state *state, const char *format, ...) {
int error = errno;
- const struct cmdline *cmdline = state->cmdline;
- CFILE *cerr = cmdline->cerr;
+ const struct bfs_ctx *ctx = state->ctx;
+ CFILE *cerr = ctx->cerr;
- bfs_error(cmdline, "%pP: ", state->ftwbuf);
+ bfs_error(ctx, "%pP: ", state->ftwbuf);
va_list args;
va_start(args, format);
@@ -86,7 +85,7 @@ static void eval_error(struct eval_state *state, const char *format, ...) {
* Check if an error should be ignored.
*/
static bool eval_should_ignore(const struct eval_state *state, int error) {
- return state->cmdline->ignore_races
+ return state->ctx->ignore_races
&& is_nonexistence_error(error)
&& state->ftwbuf->depth > 0;
}
@@ -295,7 +294,13 @@ bool eval_nogroup(const struct expr *expr, struct eval_state *state) {
return false;
}
- return bfs_getgrgid(state->cmdline->groups, statbuf->gid) == NULL;
+ const struct bfs_groups *groups = bfs_ctx_groups(state->ctx);
+ if (!groups) {
+ eval_report_error(state);
+ return false;
+ }
+
+ return bfs_getgrgid(groups, statbuf->gid) == NULL;
}
/**
@@ -307,7 +312,13 @@ bool eval_nouser(const struct expr *expr, struct eval_state *state) {
return false;
}
- return bfs_getpwuid(state->cmdline->users, statbuf->uid) == NULL;
+ const struct bfs_users *users = bfs_ctx_users(state->ctx);
+ if (!users) {
+ eval_report_error(state);
+ return false;
+ }
+
+ return bfs_getpwuid(users, statbuf->uid) == NULL;
}
/**
@@ -341,18 +352,18 @@ bool eval_delete(const struct expr *expr, struct eval_state *state) {
}
/** Finish any pending -exec ... + operations. */
-static int eval_exec_finish(const struct expr *expr, const struct cmdline *cmdline) {
+static int eval_exec_finish(const struct expr *expr, const struct bfs_ctx *ctx) {
int ret = 0;
if (expr->execbuf && bfs_exec_finish(expr->execbuf) != 0) {
if (errno != 0) {
- bfs_error(cmdline, "%s %s: %m.\n", expr->argv[0], expr->argv[1]);
+ bfs_error(ctx, "%s %s: %m.\n", expr->argv[0], expr->argv[1]);
}
ret = -1;
}
- if (expr->lhs && eval_exec_finish(expr->lhs, cmdline) != 0) {
+ if (expr->lhs && eval_exec_finish(expr->lhs, ctx) != 0) {
ret = -1;
}
- if (expr->rhs && eval_exec_finish(expr->rhs, cmdline) != 0) {
+ if (expr->rhs && eval_exec_finish(expr->rhs, ctx) != 0) {
ret = -1;
}
return ret;
@@ -436,7 +447,13 @@ bool eval_fstype(const struct expr *expr, struct eval_state *state) {
return false;
}
- const char *type = bfs_fstype(state->cmdline->mtab, statbuf);
+ const struct bfs_mtab *mtab = bfs_ctx_mtab(state->ctx);
+ if (!mtab) {
+ eval_report_error(state);
+ return false;
+ }
+
+ const char *type = bfs_fstype(mtab, statbuf);
return strcmp(type, expr->sdata) == 0;
}
@@ -572,8 +589,8 @@ bool eval_perm(const struct expr *expr, struct eval_state *state) {
bool eval_fls(const struct expr *expr, struct eval_state *state) {
CFILE *cfile = expr->cfile;
FILE *file = cfile->file;
- const struct bfs_users *users = state->cmdline->users;
- const struct bfs_groups *groups = state->cmdline->groups;
+ const struct bfs_users *users = bfs_ctx_users(state->ctx);
+ const struct bfs_groups *groups = bfs_ctx_groups(state->ctx);
const struct BFTW *ftwbuf = state->ftwbuf;
const struct bfs_stat *statbuf = eval_stat(state);
if (!statbuf) {
@@ -930,7 +947,7 @@ static void add_elapsed(struct expr *expr, const struct timespec *start, const s
*/
static bool eval_expr(struct expr *expr, struct eval_state *state) {
struct timespec start, end;
- bool time = state->cmdline->debug & DEBUG_RATES;
+ bool time = state->ctx->debug & DEBUG_RATES;
if (time) {
if (eval_gettime(&start) != 0) {
time = false;
@@ -1051,8 +1068,8 @@ static bool eval_file_unique(struct eval_state *state, struct trie *seen) {
/**
* Log a stat() call.
*/
-static void debug_stat(const struct cmdline *cmdline, const struct BFTW *ftwbuf, const struct bftw_stat *cache, enum bfs_stat_flags flags) {
- bfs_debug_prefix(cmdline, DEBUG_STAT);
+static void debug_stat(const struct bfs_ctx *ctx, const struct BFTW *ftwbuf, const struct bftw_stat *cache, enum bfs_stat_flags flags) {
+ bfs_debug_prefix(ctx, DEBUG_STAT);
fprintf(stderr, "bfs_stat(");
if (ftwbuf->at_fd == AT_FDCWD) {
@@ -1082,19 +1099,19 @@ static void debug_stat(const struct cmdline *cmdline, const struct BFTW *ftwbuf,
/**
* Log any stat() calls that happened.
*/
-static void debug_stats(const struct cmdline *cmdline, const struct BFTW *ftwbuf) {
- if (!(cmdline->debug & DEBUG_STAT)) {
+static void debug_stats(const struct bfs_ctx *ctx, const struct BFTW *ftwbuf) {
+ if (!(ctx->debug & DEBUG_STAT)) {
return;
}
const struct bfs_stat *statbuf = ftwbuf->stat_cache.buf;
if (statbuf || ftwbuf->stat_cache.error) {
- debug_stat(cmdline, ftwbuf, &ftwbuf->stat_cache, BFS_STAT_FOLLOW);
+ debug_stat(ctx, ftwbuf, &ftwbuf->stat_cache, BFS_STAT_FOLLOW);
}
const struct bfs_stat *lstatbuf = ftwbuf->lstat_cache.buf;
if ((lstatbuf && lstatbuf != statbuf) || ftwbuf->lstat_cache.error) {
- debug_stat(cmdline, ftwbuf, &ftwbuf->lstat_cache, BFS_STAT_NOFOLLOW);
+ debug_stat(ctx, ftwbuf, &ftwbuf->lstat_cache, BFS_STAT_NOFOLLOW);
}
}
@@ -1152,25 +1169,25 @@ static const char *dump_bftw_action(enum bftw_action action) {
* Type passed as the argument to the bftw() callback.
*/
struct callback_args {
- /** The parsed command line. */
- const struct cmdline *cmdline;
+ /** The bfs context. */
+ const struct bfs_ctx *ctx;
/** The set of seen files. */
struct trie *seen;
- /** Eventual return value from eval_cmdline(). */
+ /** Eventual return value from bfs_eval(). */
int ret;
};
/**
* bftw() callback.
*/
-static enum bftw_action cmdline_callback(const struct BFTW *ftwbuf, void *ptr) {
+static enum bftw_action eval_callback(const struct BFTW *ftwbuf, void *ptr) {
struct callback_args *args = ptr;
- const struct cmdline *cmdline = args->cmdline;
+ const struct bfs_ctx *ctx = args->ctx;
struct eval_state state;
state.ftwbuf = ftwbuf;
- state.cmdline = cmdline;
+ state.ctx = ctx;
state.action = BFTW_CONTINUE;
state.ret = &args->ret;
state.quit = false;
@@ -1184,46 +1201,46 @@ static enum bftw_action cmdline_callback(const struct BFTW *ftwbuf, void *ptr) {
goto done;
}
- if (cmdline->unique && ftwbuf->visit == BFTW_PRE) {
+ if (ctx->unique && ftwbuf->visit == BFTW_PRE) {
if (!eval_file_unique(&state, args->seen)) {
goto done;
}
}
- if (eval_expr(cmdline->exclude, &state)) {
+ if (eval_expr(ctx->exclude, &state)) {
state.action = BFTW_PRUNE;
goto done;
}
- if (cmdline->xargs_safe && strpbrk(ftwbuf->path, " \t\n\'\"\\")) {
+ if (ctx->xargs_safe && strpbrk(ftwbuf->path, " \t\n\'\"\\")) {
args->ret = EXIT_FAILURE;
eval_error(&state, "Path is not safe for xargs.\n");
state.action = BFTW_PRUNE;
goto done;
}
- if (cmdline->maxdepth < 0 || ftwbuf->depth >= cmdline->maxdepth) {
+ if (ctx->maxdepth < 0 || ftwbuf->depth >= ctx->maxdepth) {
state.action = BFTW_PRUNE;
}
// In -depth mode, only handle directories on the BFTW_POST visit
enum bftw_visit expected_visit = BFTW_PRE;
- if ((cmdline->flags & BFTW_POST_ORDER)
- && (cmdline->strategy == BFTW_IDS || ftwbuf->type == BFTW_DIR)
- && ftwbuf->depth < cmdline->maxdepth) {
+ if ((ctx->flags & BFTW_POST_ORDER)
+ && (ctx->strategy == BFTW_IDS || ftwbuf->type == BFTW_DIR)
+ && ftwbuf->depth < ctx->maxdepth) {
expected_visit = BFTW_POST;
}
if (ftwbuf->visit == expected_visit
- && ftwbuf->depth >= cmdline->mindepth
- && ftwbuf->depth <= cmdline->maxdepth) {
- eval_expr(cmdline->expr, &state);
+ && ftwbuf->depth >= ctx->mindepth
+ && ftwbuf->depth <= ctx->maxdepth) {
+ eval_expr(ctx->expr, &state);
}
done:
- debug_stats(cmdline, ftwbuf);
+ debug_stats(ctx, ftwbuf);
- if (bfs_debug(cmdline, DEBUG_SEARCH, "cmdline_callback({\n")) {
+ if (bfs_debug(ctx, DEBUG_SEARCH, "eval_callback({\n")) {
fprintf(stderr, "\t.path = \"%s\",\n", ftwbuf->path);
fprintf(stderr, "\t.root = \"%s\",\n", ftwbuf->root);
fprintf(stderr, "\t.depth = %zu,\n", ftwbuf->depth);
@@ -1239,7 +1256,7 @@ done:
/**
* Infer the number of open file descriptors we're allowed to have.
*/
-static int infer_fdlimit(const struct cmdline *cmdline) {
+static int infer_fdlimit(const struct bfs_ctx *ctx) {
int ret = 4096;
struct rlimit rl;
@@ -1250,7 +1267,7 @@ static int infer_fdlimit(const struct cmdline *cmdline) {
}
// 3 for std{in,out,err}
- int nopen = 3 + cmdline->nopen_files;
+ int nopen = 3 + ctx->nfiles;
// Check /proc/self/fd for the current number of open fds, if possible
// (we may have inherited more than just the standard ones)
@@ -1271,8 +1288,8 @@ static int infer_fdlimit(const struct cmdline *cmdline) {
}
ret -= nopen;
- ret -= cmdline->expr->persistent_fds;
- ret -= cmdline->expr->ephemeral_fds;
+ ret -= ctx->expr->persistent_fds;
+ ret -= ctx->expr->ephemeral_fds;
// bftw() needs at least 2 available fds
if (ret < 2) {
@@ -1313,44 +1330,41 @@ static const char *dump_bftw_strategy(enum bftw_strategy strategy) {
return strategies[strategy];
}
-/**
- * Evaluate the command line.
- */
-int eval_cmdline(const struct cmdline *cmdline) {
- if (!cmdline->expr) {
+int bfs_eval(const struct bfs_ctx *ctx) {
+ if (!ctx->expr) {
return EXIT_SUCCESS;
}
struct callback_args args = {
- .cmdline = cmdline,
+ .ctx = ctx,
.ret = EXIT_SUCCESS,
};
struct trie seen;
- if (cmdline->unique) {
+ if (ctx->unique) {
trie_init(&seen);
args.seen = &seen;
}
struct bftw_args bftw_args = {
- .paths = cmdline->paths,
- .npaths = darray_length(cmdline->paths),
- .callback = cmdline_callback,
+ .paths = ctx->paths,
+ .npaths = darray_length(ctx->paths),
+ .callback = eval_callback,
.ptr = &args,
- .nopenfd = infer_fdlimit(cmdline),
- .flags = cmdline->flags,
- .strategy = cmdline->strategy,
- .mtab = cmdline->mtab,
+ .nopenfd = infer_fdlimit(ctx),
+ .flags = ctx->flags,
+ .strategy = ctx->strategy,
+ .mtab = bfs_ctx_mtab(ctx),
};
- if (bfs_debug(cmdline, DEBUG_SEARCH, "bftw({\n")) {
+ if (bfs_debug(ctx, DEBUG_SEARCH, "bftw({\n")) {
fprintf(stderr, "\t.paths = {\n");
for (size_t i = 0; i < bftw_args.npaths; ++i) {
fprintf(stderr, "\t\t\"%s\",\n", bftw_args.paths[i]);
}
fprintf(stderr, "\t},\n");
fprintf(stderr, "\t.npaths = %zu,\n", bftw_args.npaths);
- fprintf(stderr, "\t.callback = cmdline_callback,\n");
+ fprintf(stderr, "\t.callback = eval_callback,\n");
fprintf(stderr, "\t.ptr = &args,\n");
fprintf(stderr, "\t.nopenfd = %d,\n", bftw_args.nopenfd);
fprintf(stderr, "\t.flags = ");
@@ -1358,7 +1372,7 @@ int eval_cmdline(const struct cmdline *cmdline) {
fprintf(stderr, ",\n\t.strategy = %s,\n", dump_bftw_strategy(bftw_args.strategy));
fprintf(stderr, "\t.mtab = ");
if (bftw_args.mtab) {
- fprintf(stderr, "cmdline->mtab");
+ fprintf(stderr, "ctx->mtab");
} else {
fprintf(stderr, "NULL");
}
@@ -1370,13 +1384,13 @@ int eval_cmdline(const struct cmdline *cmdline) {
perror("bftw()");
}
- if (eval_exec_finish(cmdline->expr, cmdline) != 0) {
+ if (eval_exec_finish(ctx->expr, ctx) != 0) {
args.ret = EXIT_FAILURE;
}
- dump_cmdline(cmdline, DEBUG_RATES);
+ bfs_ctx_dump(ctx, DEBUG_RATES);
- if (cmdline->unique) {
+ if (ctx->unique) {
trie_destroy(&seen);
}