summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bfs.h13
-rw-r--r--eval.c31
-rw-r--r--parse.c40
3 files changed, 83 insertions, 1 deletions
diff --git a/bfs.h b/bfs.h
index b365a53..a80ff17 100644
--- a/bfs.h
+++ b/bfs.h
@@ -49,6 +49,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.
*/
struct cmdline {
@@ -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
@@ -520,6 +520,33 @@ bool eval_comma(const struct expr *expr, struct eval_state *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.
*/
struct callback_args {
@@ -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
@@ -336,6 +336,39 @@ static struct expr *parse_test_sdata(struct parser_state *state, const char *tes
}
/**
+ * 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}.
*/
static struct expr *parse_acmtime(struct parser_state *state, const char *option, enum timefield field, enum timeunit unit) {
@@ -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"));