summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bfs.c57
-rw-r--r--bftw.c42
-rw-r--r--bftw.h20
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
@@ -212,6 +212,59 @@ static bool eval_nohidden(const char *fpath, const struct BFTW *ftwbuf, const cm
}
/**
+ * -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
* | ACTION
@@ -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