summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2017-09-02 17:05:04 -0400
committerTavian Barnes <tavianator@tavianator.com>2017-09-02 17:05:04 -0400
commit84064a0bccf8cbabd54b76afee890df880c5d581 (patch)
treedc2f9a99cf197afc87a4e2da4582969072c2c688
parent2741f580ffb6a05f52f0e2b05fa77ff3a15d967f (diff)
downloadbfs-84064a0bccf8cbabd54b76afee890df880c5d581.tar.xz
Implement -D search
-rw-r--r--bfs.h14
-rw-r--r--eval.c100
-rw-r--r--parse.c3
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
@@ -992,6 +992,59 @@ static void debug_stat(const struct eval_state *state) {
}
/**
+ * 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.
*/
struct callback_args {
@@ -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;
}
@@ -1110,6 +1180,30 @@ static int infer_fdlimit(const struct cmdline *cmdline) {
}
/**
+ * 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.
*/
int eval_cmdline(const struct cmdline *cmdline) {
@@ -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) {