From ac11476e20136976bf689acf847fdcea4e05e37a Mon Sep 17 00:00:00 2001
From: Tavian Barnes <tavianator@tavianator.com>
Date: Thu, 18 Jun 2015 23:35:43 -0400
Subject: bftw: Add flags parameter and BFTW_STAT flag.

---
 bfs.c  |  4 ++--
 bftw.c | 12 ++++++++----
 bftw.h | 13 +++++++++++--
 3 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/bfs.c b/bfs.c
index 7a7b789..6c0e07c 100644
--- a/bfs.c
+++ b/bfs.c
@@ -20,7 +20,7 @@ typedef struct {
 	bool hidden;
 } options;
 
-static int callback(const char *fpath, int typeflag, void *ptr) {
+static int callback(const char *fpath, const struct stat *sb, int typeflag, void *ptr) {
 	const options *opts = ptr;
 
 	const char *filename = strrchr(fpath, '/');
@@ -64,7 +64,7 @@ int main(int argc, char* argv[]) {
 	}
 
 	// TODO: getrlimit(RLIMIT_NOFILE)
-	if (bftw(opts.path, callback, 1024, &opts) != 0) {
+	if (bftw(opts.path, callback, 1024, 0, &opts) != 0) {
 		perror("bftw()");
 		return EXIT_FAILURE;
 	}
diff --git a/bftw.c b/bftw.c
index e8228c6..0d55a65 100644
--- a/bftw.c
+++ b/bftw.c
@@ -368,7 +368,7 @@ static dircache_entry *dirqueue_pop(dirqueue *queue) {
 	return entry;
 }
 
-int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, void *ptr) {
+int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, int flags, void *ptr) {
 	int ret = -1, err;
 
 	dircache cache;
@@ -419,9 +419,13 @@ int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, void *ptr) {
 			}
 #endif
 
-			if (typeflag == BFTW_UNKNOWN) {
-				struct stat sb;
+			struct stat sb;
+			struct stat *sp = NULL;
+
+			if ((flags & BFTW_STAT) || typeflag == BFTW_UNKNOWN) {
 				if (fstatat(dirfd(dir), de->d_name, &sb, AT_SYMLINK_NOFOLLOW) == 0) {
+					sp = &sb;
+
 					switch (sb.st_mode & S_IFMT) {
 					case S_IFDIR:
 						typeflag = BFTW_D;
@@ -436,7 +440,7 @@ int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, void *ptr) {
 				}
 			}
 
-			int action = fn(path.str, typeflag, ptr);
+			int action = fn(path.str, sp, typeflag, ptr);
 
 			switch (action) {
 			case BFTW_CONTINUE:
diff --git a/bftw.h b/bftw.h
index be538a8..09c7943 100644
--- a/bftw.h
+++ b/bftw.h
@@ -9,11 +9,15 @@
  * the COPYING file or http://www.wtfpl.net/ for more details.       *
  *********************************************************************/
 
+#include <sys/stat.h>
+
 /**
  * Callback function type for bftw().
  *
  * @param fpath
  *         The path to the encountered file.
+ * @param sb
+ *         A stat() buffer; may be NULL if no stat() call was needed.
  * @param typeflag
  *         A typeflag value (see below).
  * @param ptr
@@ -21,7 +25,7 @@
  * @return
  *         An action value (see below).
  */
-typedef int bftw_fn(const char *fpath, int typeflag, void *ptr);
+typedef int bftw_fn(const char *fpath, const struct stat *sb, int typeflag, void *ptr);
 
 /**
  * Breadth First Tree Walk (or Better File Tree Walk).
@@ -36,12 +40,14 @@ typedef int bftw_fn(const char *fpath, int typeflag, void *ptr);
  *         The callback to invoke.
  * @param nopenfd
  *         The maximum number of file descriptors to keep open.
+ * @param flags
+ *         Flags that control bftw() behavior (see below).
  * @param ptr
  *         A generic pointer which is passed to fn().
  * @return
  *         0 on success, or -1 on failure.
  */
-int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, void *ptr);
+int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, int flags, void *ptr);
 
 /** typeflag: Directory. */
 #define BFTW_D        0
@@ -60,3 +66,6 @@ int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, void *ptr);
 #define BFTW_SKIP_SUBTREE   2
 /** action: Stop walking. */
 #define BFTW_STOP           3
+
+/** flag: stat() each encountered file. */
+#define BFTW_STAT  (1 << 0)
-- 
cgit v1.2.3