From e248f5b2a8254d20ded7685e426e53ac90940cba Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 17 Jan 2021 17:30:31 -0800 Subject: Improved handling of directories (e.g. `bp foo dir/`) --- bp.c | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/bp.c b/bp.c index 2b57a36..4624b4d 100644 --- a/bp.c +++ b/bp.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -377,6 +378,31 @@ static int process_file(def_t *defs, const char *filename, pat_t *pattern) return matches; } +// +// Recursively process all non-dotfile files in the given directory. +// +static int process_dir(def_t *defs, const char *dirname, pat_t *pattern) +{ + int matches = 0; + glob_t globbuf; + char globpath[PATH_MAX+1] = {0}; + check(snprintf(globpath, PATH_MAX, "%s/*", dirname) <= PATH_MAX, + "Filename is too long: %s/*", dirname); + glob(globpath, 0, NULL, &globbuf); + struct stat statbuf; + for (size_t i = 0; i < globbuf.gl_pathc; i++) { + if (lstat(globbuf.gl_pathv[i], &statbuf) != 0) continue; + if (S_ISLNK(statbuf.st_mode)) + continue; // Skip symbolic links + else if (S_ISDIR(statbuf.st_mode)) + matches += process_dir(defs, globbuf.gl_pathv[i], pattern); + else if (is_text_file(globbuf.gl_pathv[i])) + matches += process_file(defs, globbuf.gl_pathv[i], pattern); + } + globfree(&globbuf); + return matches; +} + #define FLAG(f) (flag=getflag((f), argv, &i)) #define BOOLFLAG(f) (boolflag((f), argv, &i)) @@ -564,19 +590,18 @@ int main(int argc, char *argv[]) "`git --ls-files` failed. Do you have git installed?"); } else if (i < argc) { // Files pass in as command line args: + struct stat statbuf; for (int nfiles = 0; i < argc; nfiles++, i++) { - found += process_file(defs, argv[i], pattern); + check(stat(argv[i], &statbuf) == 0, + "File does not exist: %s", argv[i]); + if (S_ISDIR(statbuf.st_mode)) // Symlinks are okay if manually specified + found += process_dir(defs, argv[i], pattern); + else + found += process_file(defs, argv[i], pattern); } } else if (isatty(STDIN_FILENO)) { - // No files, no piped in input, so use * **/*: - glob_t globbuf; - glob("*", 0, NULL, &globbuf); - glob("**/*", GLOB_APPEND, NULL, &globbuf); - for (size_t i = 0; i < globbuf.gl_pathc; i++) { - if (is_text_file(globbuf.gl_pathv[i])) - found += process_file(defs, globbuf.gl_pathv[i], pattern); - } - globfree(&globbuf); + // No files, no piped in input, so use files in current dir, recursively + found += process_dir(defs, ".", pattern); } else { // Piped in input: found += process_file(defs, NULL, pattern); -- cgit v1.2.3