From 275fbdbe040dc07b2705c92d4cd24ad3f3c7d069 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 22 Feb 2016 14:13:26 -0500 Subject: Implement -D stat. --- bfs.h | 13 ++++++++++++- eval.c | 31 +++++++++++++++++++++++++++++++ parse.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/bfs.h b/bfs.h index b365a53..a80ff17 100644 --- a/bfs.h +++ b/bfs.h @@ -48,6 +48,14 @@ struct eval_state; */ typedef bool eval_fn(const struct expr *expr, struct eval_state *state); +/** + * Various debugging flags. + */ +enum debugflags { + /** Trace all stat() calls. */ + DEBUG_STAT = 1 << 0, +}; + /** * The parsed command line. */ @@ -70,7 +78,10 @@ struct cmdline { int maxdepth; /** bftw() flags. */ - int flags; + enum bftw_flags flags; + + /** Debugging flags. */ + enum debugflags debug; /** The command line expression. */ struct expr *expr; diff --git a/eval.c b/eval.c index 66ba895..f69c890 100644 --- a/eval.c +++ b/eval.c @@ -519,6 +519,33 @@ bool eval_comma(const struct expr *expr, struct eval_state *state) { return eval_expr(expr->rhs, state); } +/** + * Debug stat() calls. + */ +void debug_stat(const struct eval_state *state) { + struct BFTW *ftwbuf = state->ftwbuf; + + fprintf(stderr, "fstatat("); + if (ftwbuf->at_fd == AT_FDCWD) { + fprintf(stderr, "AT_FDCWD"); + } else { + size_t baselen = strlen(ftwbuf->path) - strlen(ftwbuf->at_path); + fprintf(stderr, "\""); + fwrite(ftwbuf->path, 1, baselen, stderr); + fprintf(stderr, "\""); + } + + fprintf(stderr, ", \"%s\", ", ftwbuf->at_path); + + if (ftwbuf->at_flags == AT_SYMLINK_NOFOLLOW) { + fprintf(stderr, "AT_SYMLINK_NOFOLLOW"); + } else { + fprintf(stderr, "%d", ftwbuf->at_flags); + } + + fprintf(stderr, ")\n"); +} + /** * Type passed as the argument to the bftw() callback. */ @@ -567,6 +594,10 @@ static enum bftw_action cmdline_callback(struct BFTW *ftwbuf, void *ptr) { eval_expr(cmdline->expr, &state); } + if ((cmdline->debug & DEBUG_STAT) && ftwbuf->statbuf) { + debug_stat(&state); + } + args->ret = state.ret; return state.action; } diff --git a/parse.c b/parse.c index 8376378..fb0170b 100644 --- a/parse.c +++ b/parse.c @@ -335,6 +335,39 @@ static struct expr *parse_test_sdata(struct parser_state *state, const char *tes return new_test_sdata(state, eval, arg); } +/** + * Parse -D FLAG. + */ +static struct expr *parse_debug(struct parser_state *state, const char *option) { + struct cmdline *cmdline = state->cmdline; + + const char *arg = state->argv[state->i]; + if (!arg) { + pretty_error(cmdline->stderr_colors, + "error: %s needs a flag.\n", option); + return NULL; + } + + ++state->i; + + if (strcmp(arg, "help") == 0) { + printf("Supported debug flags:\n\n"); + + printf(" help: This message.\n"); + printf(" stat: Trace all stat() calls.\n"); + + state->just_info = true; + return NULL; + } else if (strcmp(arg, "stat") == 0) { + cmdline->debug |= DEBUG_STAT; + } else { + pretty_warning(cmdline->stderr_colors, + "warning: Unrecognized debug flag '%s'.\n\n", arg); + } + + return new_positional_option(state); +} + /** * Parse -[acm]{min,time}. */ @@ -670,6 +703,12 @@ static struct expr *parse_literal(struct parser_state *state) { } switch (arg[1]) { + case 'D': + if (strcmp(arg, "-D") == 0) { + return parse_debug(state, arg); + } + break; + case 'P': if (strcmp(arg, "-P") == 0) { cmdline->flags &= ~(BFTW_FOLLOW | BFTW_DETECT_CYCLES); @@ -1128,6 +1167,7 @@ struct cmdline *parse_cmdline(int argc, char *argv[]) { cmdline->mindepth = 0; cmdline->maxdepth = INT_MAX; cmdline->flags = BFTW_RECOVER; + cmdline->debug = 0; cmdline->expr = &expr_true; cmdline->colors = parse_colors(getenv("LS_COLORS")); -- cgit v1.2.3