From 84064a0bccf8cbabd54b76afee890df880c5d581 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sat, 2 Sep 2017 17:05:04 -0400 Subject: Implement -D search --- bfs.h | 14 +++++---- eval.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ parse.c | 3 ++ 3 files changed, 111 insertions(+), 6 deletions(-) diff --git a/bfs.h b/bfs.h index 0f782a5..97efb5d 100644 --- a/bfs.h +++ b/bfs.h @@ -63,17 +63,19 @@ typedef bool eval_fn(const struct expr *expr, struct eval_state *state); */ enum debug_flags { /** Print cost estimates. */ - DEBUG_COST = 1 << 0, + DEBUG_COST = 1 << 0, /** Print executed command details. */ - DEBUG_EXEC = 1 << 1, + DEBUG_EXEC = 1 << 1, /** Print optimization details. */ - DEBUG_OPT = 1 << 2, + DEBUG_OPT = 1 << 2, /** Print rate information. */ - DEBUG_RATES = 1 << 3, + DEBUG_RATES = 1 << 3, + /** Trace the filesystem traversal. */ + DEBUG_SEARCH = 1 << 4, /** Trace all stat() calls. */ - DEBUG_STAT = 1 << 4, + DEBUG_STAT = 1 << 5, /** Print the parse tree. */ - DEBUG_TREE = 1 << 5, + DEBUG_TREE = 1 << 6, }; /** diff --git a/eval.c b/eval.c index d455aeb..03c3d91 100644 --- a/eval.c +++ b/eval.c @@ -991,6 +991,59 @@ static void debug_stat(const struct eval_state *state) { fprintf(stderr, ")\n"); } +/** + * Dump the bftw_typeflag for -D search. + */ +static const char *dump_bftw_typeflag(enum bftw_typeflag type) { +#define DUMP_BFTW_TYPEFLAG_CASE(flag) \ + case flag: \ + return #flag + + switch (type) { + DUMP_BFTW_TYPEFLAG_CASE(BFTW_BLK); + DUMP_BFTW_TYPEFLAG_CASE(BFTW_CHR); + DUMP_BFTW_TYPEFLAG_CASE(BFTW_DIR); + DUMP_BFTW_TYPEFLAG_CASE(BFTW_DOOR); + DUMP_BFTW_TYPEFLAG_CASE(BFTW_FIFO); + DUMP_BFTW_TYPEFLAG_CASE(BFTW_LNK); + DUMP_BFTW_TYPEFLAG_CASE(BFTW_PORT); + DUMP_BFTW_TYPEFLAG_CASE(BFTW_REG); + DUMP_BFTW_TYPEFLAG_CASE(BFTW_SOCK); + DUMP_BFTW_TYPEFLAG_CASE(BFTW_WHT); + + DUMP_BFTW_TYPEFLAG_CASE(BFTW_ERROR); + + default: + DUMP_BFTW_TYPEFLAG_CASE(BFTW_UNKNOWN); + } +} + +#define DUMP_BFTW_MAP(value) [value] = #value + +/** + * Dump the bftw_visit for -D search. + */ +static const char *dump_bftw_visit(enum bftw_visit visit) { + static const char *visits[] = { + DUMP_BFTW_MAP(BFTW_PRE), + DUMP_BFTW_MAP(BFTW_POST), + }; + return visits[visit]; +} + +/** + * Dump the bftw_action for -D search. + */ +static const char *dump_bftw_action(enum bftw_action action) { + static const char *actions[] = { + DUMP_BFTW_MAP(BFTW_CONTINUE), + DUMP_BFTW_MAP(BFTW_SKIP_SIBLINGS), + DUMP_BFTW_MAP(BFTW_SKIP_SUBTREE), + DUMP_BFTW_MAP(BFTW_STOP), + }; + return actions[action]; +} + /** * Type passed as the argument to the bftw() callback. */ @@ -1058,6 +1111,23 @@ done: debug_stat(&state); } + if (cmdline->debug & DEBUG_SEARCH) { + fprintf(stderr, + "cmdline_callback({ " + ".path = \"%s\", " + ".depth = %zu, " + ".visit = %s, " + ".typeflag = %s, " + ".error = %d " + "}) == %s\n", + ftwbuf->path, + ftwbuf->depth, + dump_bftw_visit(ftwbuf->visit), + dump_bftw_typeflag(ftwbuf->typeflag), + ftwbuf->error, + dump_bftw_action(state.action)); + } + return state.action; } @@ -1109,6 +1179,30 @@ static int infer_fdlimit(const struct cmdline *cmdline) { return ret; } +/** + * Dump the bftw() flags for -D search. + */ +static void dump_bftw_flags(enum bftw_flags flags) { +#define DUMP_BFTW_FLAG(flag) \ + if (flags & flag) { \ + fputs(#flag, stderr); \ + flags ^= flag; \ + if (flags) { \ + fputs(" | ", stderr); \ + } \ + } + + DUMP_BFTW_FLAG(BFTW_STAT); + DUMP_BFTW_FLAG(BFTW_RECOVER); + DUMP_BFTW_FLAG(BFTW_DEPTH); + DUMP_BFTW_FLAG(BFTW_COMFOLLOW); + DUMP_BFTW_FLAG(BFTW_LOGICAL); + DUMP_BFTW_FLAG(BFTW_DETECT_CYCLES); + DUMP_BFTW_FLAG(BFTW_XDEV); + + assert(!flags); +} + /** * Evaluate the command line. */ @@ -1133,6 +1227,12 @@ int eval_cmdline(const struct cmdline *cmdline) { }; for (struct root *root = cmdline->roots; root && !args.quit; root = root->next) { + if (cmdline->debug & DEBUG_SEARCH) { + fprintf(stderr, "bftw(\"%s\", cmdline_callback, %d, ", root->path, nopenfd); + dump_bftw_flags(cmdline->flags); + fprintf(stderr, ", &args)\n"); + } + if (bftw(root->path, cmdline_callback, nopenfd, cmdline->flags, &args) != 0) { args.ret = EXIT_FAILURE; perror("bftw()"); diff --git a/parse.c b/parse.c index 9bed82c..08d450c 100644 --- a/parse.c +++ b/parse.c @@ -755,6 +755,7 @@ static struct expr *parse_debug(struct parser_state *state, int arg1, int arg2) printf(" exec: Print executed command details.\n"); printf(" opt: Print optimization details.\n"); printf(" rates: Print predicate success rates.\n"); + printf(" search: Trace the filesystem traversal.\n"); printf(" stat: Trace all stat() calls.\n"); printf(" tree: Print the parse tree.\n"); @@ -768,6 +769,8 @@ static struct expr *parse_debug(struct parser_state *state, int arg1, int arg2) cmdline->debug |= DEBUG_OPT; } else if (strcmp(flag, "rates") == 0) { cmdline->debug |= DEBUG_RATES; + } else if (strcmp(flag, "search") == 0) { + cmdline->debug |= DEBUG_SEARCH; } else if (strcmp(flag, "stat") == 0) { cmdline->debug |= DEBUG_STAT; } else if (strcmp(flag, "tree") == 0) { -- cgit v1.2.3