From 25648b2999b918dd1ebd9faa1f8dbff705a7a46c Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 12 Feb 2016 14:42:46 -0500 Subject: Report failures that happen inside predicates. --- bfs.h | 2 +- eval.c | 35 +++++++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/bfs.h b/bfs.h index c20fa17..82edd98 100644 --- a/bfs.h +++ b/bfs.h @@ -138,7 +138,7 @@ struct cmdline *parse_cmdline(int argc, char *argv[]); /** * Evaluate the command line. */ -int eval_cmdline(struct cmdline *cl); +int eval_cmdline(const struct cmdline *cl); /** * Free the parsed command line. diff --git a/eval.c b/eval.c index 10379a3..0698857 100644 --- a/eval.c +++ b/eval.c @@ -29,6 +29,8 @@ struct eval_state { const struct cmdline *cl; /** The bftw() callback return value. */ enum bftw_action action; + /** The eval_cmdline() return value. */ + int ret; /** A stat() buffer, if necessary. */ struct stat statbuf; }; @@ -42,6 +44,7 @@ static const struct stat *fill_statbuf(struct eval_state *state) { if (fstatat(ftwbuf->at_fd, ftwbuf->at_path, &state->statbuf, AT_SYMLINK_NOFOLLOW) == 0) { ftwbuf->statbuf = &state->statbuf; } else { + state->ret = -1; perror("fstatat()"); } } @@ -211,12 +214,14 @@ bool eval_empty(const struct expr *expr, struct eval_state *state) { if (ftwbuf->typeflag == BFTW_DIR) { int dfd = openat(ftwbuf->at_fd, ftwbuf->at_path, O_DIRECTORY); if (dfd < 0) { + state->ret = -1; perror("openat()"); goto done; } DIR *dir = fdopendir(dfd); if (!dir) { + state->ret = -1; perror("fdopendir()"); close(dfd); goto done; @@ -410,11 +415,23 @@ static int infer_nopenfd() { return ret; } +/** + * Type passed as the argument to the bftw() callback. + */ +struct callback_args { + /** The parsed command line. */ + const struct cmdline *cl; + /** Eventual return value from eval_cmdline(). */ + int ret; +}; + /** * bftw() callback. */ static enum bftw_action cmdline_callback(struct BFTW *ftwbuf, void *ptr) { - const struct cmdline *cl = ptr; + struct callback_args *args = ptr; + + const struct cmdline *cl = args->cl; if (ftwbuf->typeflag == BFTW_ERROR) { print_error(cl->colors, ftwbuf->path, ftwbuf->error); @@ -425,6 +442,7 @@ static enum bftw_action cmdline_callback(struct BFTW *ftwbuf, void *ptr) { .ftwbuf = ftwbuf, .cl = cl, .action = BFTW_CONTINUE, + .ret = args->ret, }; if (ftwbuf->depth >= cl->maxdepth) { @@ -445,22 +463,27 @@ static enum bftw_action cmdline_callback(struct BFTW *ftwbuf, void *ptr) { cl->expr->eval(cl->expr, &state); } + args->ret = state.ret; return state.action; } /** * Evaluate the command line. */ -int eval_cmdline(struct cmdline *cl) { - int ret = 0; +int eval_cmdline(const struct cmdline *cl) { int nopenfd = infer_nopenfd(); + struct callback_args args = { + .cl = cl, + .ret = 0, + }; + for (size_t i = 0; i < cl->nroots; ++i) { - if (bftw(cl->roots[i], cmdline_callback, nopenfd, cl->flags, cl) != 0) { - ret = -1; + if (bftw(cl->roots[i], cmdline_callback, nopenfd, cl->flags, &args) != 0) { + args.ret = -1; perror("bftw()"); } } - return ret; + return args.ret; } -- cgit v1.2.3