diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2016-01-30 14:00:02 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2016-01-30 14:00:02 -0500 |
commit | 132dc9eaf7d6aa9e7892d9b55889f762f1140f4d (patch) | |
tree | 3c8dd890176873edcbc4a06852b4a64690c53488 | |
parent | 3f9f913f5302b71ef57467798f62dd3e83b217bc (diff) | |
download | bfs-132dc9eaf7d6aa9e7892d9b55889f762f1140f4d.tar.xz |
Implement -empty.
-rw-r--r-- | bfs.h | 1 | ||||
-rw-r--r-- | eval.c | 44 | ||||
-rw-r--r-- | parse.c | 2 | ||||
-rwxr-xr-x | tests.sh | 7 |
4 files changed, 53 insertions, 1 deletions
@@ -97,6 +97,7 @@ void free_cmdline(cmdline *cl); // Predicate evaluation functions bool eval_access(const expression *expr, eval_state *state); bool eval_delete(const expression *expr, eval_state *state); +bool eval_empty(const expression *expr, eval_state *state); bool eval_false(const expression *expr, eval_state *state); bool eval_hidden(const expression *expr, eval_state *state); bool eval_name(const expression *expr, eval_state *state); @@ -1,5 +1,6 @@ #include "bfs.h" #include "bftw.h" +#include <dirent.h> #include <errno.h> #include <fcntl.h> #include <fnmatch.h> @@ -78,6 +79,49 @@ bool eval_delete(const expression *expr, eval_state *state) { } /** + * -empty test. + */ +bool eval_empty(const expression *expr, eval_state *state) { + bool ret = false; + struct BFTW *ftwbuf = state->ftwbuf; + + if (ftwbuf->typeflag == BFTW_DIR) { + int dfd = openat(ftwbuf->at_fd, ftwbuf->at_path, O_DIRECTORY); + if (dfd < 0) { + perror("openat()"); + goto done; + } + + DIR *dir = fdopendir(dfd); + if (!dir) { + perror("fdopendir()"); + close(dfd); + goto done; + } + + ret = true; + + struct dirent *de; + while ((de = readdir(dir)) != NULL) { + if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) { + ret = false; + break; + } + } + + closedir(dir); + } else { + fill_statbuf(state); + if (ftwbuf->statbuf) { + ret = ftwbuf->statbuf->st_size == 0; + } + } + +done: + return ret; +} + +/** * -prune action. */ bool eval_prune(const expression *expr, eval_state *state) { @@ -348,6 +348,8 @@ static expression *parse_literal(parser_state *state) { } else if (strcmp(arg, "-d") == 0 || strcmp(arg, "-depth") == 0) { state->cl->flags |= BFTW_DEPTH; return new_option(state, arg); + } else if (strcmp(arg, "-empty") == 0) { + return new_test(state, eval_empty); } else if (strcmp(arg, "-executable") == 0) { return new_test_idata(state, eval_access, X_OK); } else if (strcmp(arg, "-false") == 0) { @@ -105,7 +105,12 @@ function test_0014() { find_diff "$1" -writable } -for i in {1..14}; do +function test_0015() { + basic_structure "$1" + find_diff "$1" -empty +} + +for i in {1..15}; do dir="$(mktemp -d "${TMPDIR:-/tmp}"/bfs.XXXXXXXXXX)" test="test_$(printf '%04d' $i)" "$test" "$dir" |