From 4bedd5a6f7b12e0923dd6fa180dcaad7e1f75fc2 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 16 Sep 2015 12:44:56 -0400 Subject: Don't call stat() until absolutely necessary. This way we only call stat() if we're actually pretty-printing the path, potentially saving lots of calls on paths that don't get printed. --- bfs.c | 30 ++++++++++++++++++++++++------ bftw.h | 2 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/bfs.c b/bfs.c index d640068..5e166de 100644 --- a/bfs.c +++ b/bfs.c @@ -20,6 +20,7 @@ #include #include #include +#include #include /** @@ -37,13 +38,28 @@ typedef struct cmdline cmdline; */ typedef struct { /** Data about the current file. */ - const struct BFTW *ftwbuf; + struct BFTW *ftwbuf; /** The parsed command line. */ const cmdline *cl; /** The bftw() callback return value. */ bftw_action action; + /** A stat() buffer, if necessary. */ + struct stat statbuf; } eval_state; +/** + * Perform a stat() call if necessary. + */ +static void fill_statbuf(eval_state *state) { + struct BFTW *ftwbuf = state->ftwbuf; + + if (fstatat(ftwbuf->at_fd, ftwbuf->at_path, &state->statbuf, AT_SYMLINK_NOFOLLOW) == 0) { + ftwbuf->statbuf = &state->statbuf; + } else { + perror("fstatat()"); + } +} + /** * Expression evaluation function. * @@ -286,7 +302,7 @@ static const char *skip_paths(parser_state *state) { * -delete action. */ static bool eval_delete(const expression *expr, eval_state *state) { - const struct BFTW *ftwbuf = state->ftwbuf; + struct BFTW *ftwbuf = state->ftwbuf; int flag = 0; if (ftwbuf->typeflag == BFTW_DIR) { @@ -313,7 +329,7 @@ static bool eval_prune(const expression *expr, eval_state *state) { * -hidden test. */ static bool eval_hidden(const expression *expr, eval_state *state) { - const struct BFTW *ftwbuf = state->ftwbuf; + struct BFTW *ftwbuf = state->ftwbuf; return ftwbuf->nameoff > 0 && ftwbuf->path[ftwbuf->nameoff] == '.'; } @@ -333,7 +349,7 @@ static bool eval_nohidden(const expression *expr, eval_state *state) { * -name test. */ static bool eval_name(const expression *expr, eval_state *state) { - const struct BFTW *ftwbuf = state->ftwbuf; + struct BFTW *ftwbuf = state->ftwbuf; return fnmatch(expr->sdata, ftwbuf->path + ftwbuf->nameoff, 0) == 0; } @@ -341,6 +357,9 @@ static bool eval_name(const expression *expr, eval_state *state) { * -print action. */ static bool eval_print(const expression *expr, eval_state *state) { + if (state->cl->colors) { + fill_statbuf(state); + } pretty_print(state->cl->colors, state->ftwbuf); return true; } @@ -821,7 +840,6 @@ static cmdline *parse_cmdline(int argc, char *argv[]) { if (cl->color) { cl->colors = parse_colors(getenv("LS_COLORS")); - cl->flags |= BFTW_STAT; } return cl; @@ -855,7 +873,7 @@ static int infer_nopenfd() { /** * bftw() callback. */ -static bftw_action cmdline_callback(const struct BFTW *ftwbuf, void *ptr) { +static bftw_action cmdline_callback(struct BFTW *ftwbuf, void *ptr) { const cmdline *cl = ptr; if (ftwbuf->typeflag == BFTW_ERROR) { diff --git a/bftw.h b/bftw.h index 14055ac..f3be182 100644 --- a/bftw.h +++ b/bftw.h @@ -86,7 +86,7 @@ typedef enum { * @return * An action value. */ -typedef bftw_action bftw_fn(const struct BFTW *ftwbuf, void *ptr); +typedef bftw_action bftw_fn(struct BFTW *ftwbuf, void *ptr); typedef enum { /** stat() each encountered file. */ -- cgit v1.2.3