From e24ffc3a9ea195016a9543d9cc4bf99049f245ce Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sun, 30 Aug 2015 14:38:01 -0400 Subject: Add -type support. Fixes #2. --- bfs.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- bftw.c | 42 +++++++++++++++++++++++++++++++++--------- bftw.h | 20 ++++++++++++++------ 3 files changed, 103 insertions(+), 16 deletions(-) diff --git a/bfs.c b/bfs.c index da9479c..5d0203b 100644 --- a/bfs.c +++ b/bfs.c @@ -211,6 +211,59 @@ static bool eval_nohidden(const char *fpath, const struct BFTW *ftwbuf, const cm || eval_prune(fpath, ftwbuf, cl, expr, ret); } +/** + * -type test. + */ +static bool eval_type(const char *fpath, const struct BFTW *ftwbuf, const cmdline *cl, const expression *expr, int *ret) { + return ftwbuf->typeflag == expr->data; +} + +/** + * Parse -type [bcdpfls]. + */ +static expression *parse_type(parser_state *state) { + const char *arg = state->argv[state->i]; + if (!arg) { + fputs("-type needs a value.\n", stderr); + return NULL; + } + + int typeflag = BFTW_UNKNOWN; + + switch (arg[0]) { + case 'b': + typeflag = BFTW_BLK; + break; + case 'c': + typeflag = BFTW_CHR; + break; + case 'd': + typeflag = BFTW_DIR; + break; + case 'p': + typeflag = BFTW_FIFO; + break; + case 'f': + typeflag = BFTW_REG; + break; + case 'l': + typeflag = BFTW_LNK; + break; + case 's': + typeflag = BFTW_SOCK; + break; + } + + if (typeflag == BFTW_UNKNOWN || arg[1] != '\0') { + fprintf(stderr, "Unknown type flag '%s'.\n", arg); + return NULL; + } + + ++state->i; + + return new_expression(NULL, NULL, eval_type, typeflag); +} + /** * LITERAL : OPTION * | TEST @@ -235,8 +288,10 @@ static expression *parse_literal(parser_state *state) { return new_expression(NULL, NULL, eval_print, 0); } else if (strcmp(arg, "-prune") == 0) { return new_expression(NULL, NULL, eval_prune, 0); + } else if (strcmp(arg, "-type") == 0) { + return parse_type(state); } else { - fprintf(stderr, "Unknown argument '%s'.\n", arg); + fprintf(stderr, "Unknown argument '%s'.\n", arg); return NULL; } } diff --git a/bftw.c b/bftw.c index 75a208c..d5aad22 100644 --- a/bftw.c +++ b/bftw.c @@ -489,14 +489,26 @@ int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, int flags, void *ptr) { #if defined(_DIRENT_HAVE_D_TYPE) || defined(DT_DIR) switch (de->d_type) { + case DT_BLK: + ftwbuf.typeflag = BFTW_BLK; + break; + case DT_CHR: + ftwbuf.typeflag = BFTW_CHR; + break; case DT_DIR: - ftwbuf.typeflag = BFTW_D; + ftwbuf.typeflag = BFTW_DIR; break; - case DT_REG: - ftwbuf.typeflag = BFTW_R; + case DT_FIFO: + ftwbuf.typeflag = BFTW_FIFO; break; case DT_LNK: - ftwbuf.typeflag = BFTW_SL; + ftwbuf.typeflag = BFTW_LNK; + break; + case DT_REG: + ftwbuf.typeflag = BFTW_REG; + break; + case DT_SOCK: + ftwbuf.typeflag = BFTW_SOCK; break; } #endif @@ -508,14 +520,26 @@ int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, int flags, void *ptr) { ftwbuf.statbuf = &sb; switch (sb.st_mode & S_IFMT) { + case S_IFBLK: + ftwbuf.typeflag = BFTW_BLK; + break; + case S_IFCHR: + ftwbuf.typeflag = BFTW_CHR; + break; case S_IFDIR: - ftwbuf.typeflag = BFTW_D; + ftwbuf.typeflag = BFTW_DIR; break; - case S_IFREG: - ftwbuf.typeflag = BFTW_R; + case S_IFIFO: + ftwbuf.typeflag = BFTW_FIFO; break; case S_IFLNK: - ftwbuf.typeflag = BFTW_SL; + ftwbuf.typeflag = BFTW_LNK; + break; + case S_IFREG: + ftwbuf.typeflag = BFTW_REG; + break; + case S_IFSOCK: + ftwbuf.typeflag = BFTW_SOCK; break; } } @@ -525,7 +549,7 @@ int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, int flags, void *ptr) { switch (action) { case BFTW_CONTINUE: - if (ftwbuf.typeflag == BFTW_D) { + if (ftwbuf.typeflag == BFTW_DIR) { dircache_entry *next = dircache_add(&cache, current, de->d_name); if (!next) { goto fail; diff --git a/bftw.h b/bftw.h index 45cc0c3..0946054 100644 --- a/bftw.h +++ b/bftw.h @@ -66,16 +66,24 @@ typedef int bftw_fn(const char *fpath, const struct BFTW *ftwbuf, void *ptr); */ int bftw(const char *dirpath, bftw_fn *fn, int nopenfd, int flags, void *ptr); +/** typeflag: Block device. */ +#define BFTW_BLK 0 +/** typeflag: Character device. */ +#define BFTW_CHR 1 /** typeflag: Directory. */ -#define BFTW_D 0 -/** typeflag: Regular file. */ -#define BFTW_R 1 +#define BFTW_DIR 2 +/** typeflag: Pipe. */ +#define BFTW_FIFO 3 /** typeflag: Symbolic link. */ -#define BFTW_SL 2 +#define BFTW_LNK 4 +/** typeflag: Regular file. */ +#define BFTW_REG 5 +/** typeflag: Socket. */ +#define BFTW_SOCK 6 /** typeflag: Unknown type. */ -#define BFTW_UNKNOWN 3 +#define BFTW_UNKNOWN 7 /** typeflag: An error occurred for this file. */ -#define BFTW_ERROR 4 +#define BFTW_ERROR 8 /** action: Keep walking. */ #define BFTW_CONTINUE 0 -- cgit v1.2.3