summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2015-11-28 11:26:51 -0500
committerTavian Barnes <tavianator@tavianator.com>2015-11-28 11:26:51 -0500
commitf81be72020a886b5eca21bc1d8a5b0d62b9954d9 (patch)
tree0857734c416768778dd27b7b87b12c417594ea62
parent85bb6db3e14a38a2b9c6085e806873aeeacc9b95 (diff)
downloadbfs-f81be72020a886b5eca21bc1d8a5b0d62b9954d9.tar.xz
Implement -executable, -readable, and -writable.
-rw-r--r--bfs.c14
-rwxr-xr-xtests.sh27
2 files changed, 40 insertions, 1 deletions
diff --git a/bfs.c b/bfs.c
index 4ec9026..d9d1f7a 100644
--- a/bfs.c
+++ b/bfs.c
@@ -284,6 +284,14 @@ static const char *skip_paths(parser_state *state) {
}
/**
+ * -executable, -readable, -writable action.
+ */
+static bool eval_access(const expression *expr, eval_state *state) {
+ struct BFTW *ftwbuf = state->ftwbuf;
+ return faccessat(ftwbuf->at_fd, ftwbuf->at_path, expr->idata, AT_SYMLINK_NOFOLLOW) == 0;
+}
+
+/**
* -delete action.
*/
static bool eval_delete(const expression *expr, eval_state *state) {
@@ -567,6 +575,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, "-executable") == 0) {
+ return new_test_idata(state, eval_access, X_OK);
} else if (strcmp(arg, "-false") == 0) {
return &expr_false;
} else if (strcmp(arg, "-hidden") == 0) {
@@ -589,6 +599,8 @@ static expression *parse_literal(parser_state *state) {
return new_action(state, eval_prune);
} else if (strcmp(arg, "-quit") == 0) {
return new_action(state, eval_quit);
+ } else if (strcmp(arg, "-readable") == 0) {
+ return new_test_idata(state, eval_access, R_OK);
} else if (strcmp(arg, "-true") == 0) {
return &expr_true;
} else if (strcmp(arg, "-type") == 0) {
@@ -599,6 +611,8 @@ static expression *parse_literal(parser_state *state) {
} else if (strcmp(arg, "-nowarn") == 0) {
state->warn = false;
return new_positional_option(state);
+ } else if (strcmp(arg, "-writable") == 0) {
+ return new_test_idata(state, eval_access, W_OK);
} else {
fprintf(stderr, "Unknown argument '%s'.\n", arg);
return NULL;
diff --git a/tests.sh b/tests.sh
index 060448b..90ef066 100755
--- a/tests.sh
+++ b/tests.sh
@@ -18,6 +18,16 @@ function basic_structure() {
touchp "$1/l/foo/bar/baz"
}
+# Creates a file+directory structure with various permissions for tests
+function perms_structure() {
+ install -Dm444 /dev/null "$1/r"
+ install -Dm222 /dev/null "$1/w"
+ install -Dm644 /dev/null "$1/rw"
+ install -Dm555 /dev/null "$1/rx"
+ install -Dm311 /dev/null "$1/wx"
+ install -Dm755 /dev/null "$1/rwx"
+}
+
# Checks for any (order-independent) differences between bfs and find
function find_diff() {
diff -u <(./bfs "$@" | sort) <(find "$@" | sort)
@@ -80,7 +90,22 @@ function test_0011() {
find_diff "$1" -path "$1/*f*"
}
-for i in {1..11}; do
+function test_0012() {
+ perms_structure "$1"
+ find_diff "$1" -executable
+}
+
+function test_0013() {
+ perms_structure "$1"
+ find_diff "$1" -readable
+}
+
+function test_0014() {
+ perms_structure "$1"
+ find_diff "$1" -writable
+}
+
+for i in {1..14}; do
dir="$(mktemp -d "${TMPDIR:-/tmp}"/bfs.XXXXXXXXXX)"
test="test_$(printf '%04d' $i)"
"$test" "$dir"