summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2015-09-16 12:44:56 -0400
committerTavian Barnes <tavianator@tavianator.com>2015-09-26 12:31:19 -0400
commit4bedd5a6f7b12e0923dd6fa180dcaad7e1f75fc2 (patch)
tree32fece0561ab29bc7d1aaa2d67d4a4a5dd13af64
parent309c9a29e32edc07cb06e329669be7e30f8d9ed5 (diff)
downloadbfs-4bedd5a6f7b12e0923dd6fa180dcaad7e1f75fc2.tar.xz
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.
-rw-r--r--bfs.c30
-rw-r--r--bftw.h2
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 <stdlib.h>
#include <string.h>
#include <sys/resource.h>
+#include <sys/stat.h>
#include <unistd.h>
/**
@@ -37,14 +38,29 @@ 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.
*
* @param expr
@@ -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. */