summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bfs.h1
-rw-r--r--eval.c36
-rw-r--r--parse.c14
-rwxr-xr-xtests.sh18
4 files changed, 67 insertions, 2 deletions
diff --git a/bfs.h b/bfs.h
index 1b3457a..8e879f5 100644
--- a/bfs.h
+++ b/bfs.h
@@ -168,6 +168,7 @@ bool eval_samefile(const struct expr *expr, struct eval_state *state);
bool eval_type(const struct expr *expr, struct eval_state *state);
bool eval_xtype(const struct expr *expr, struct eval_state *state);
+bool eval_lname(const struct expr *expr, struct eval_state *state);
bool eval_name(const struct expr *expr, struct eval_state *state);
bool eval_path(const struct expr *expr, struct eval_state *state);
diff --git a/eval.c b/eval.c
index 63c1348..26596f0 100644
--- a/eval.c
+++ b/eval.c
@@ -308,6 +308,42 @@ bool eval_links(const struct expr *expr, struct eval_state *state) {
}
/**
+ * -i?lname test.
+ */
+bool eval_lname(const struct expr *expr, struct eval_state *state) {
+ struct BFTW *ftwbuf = state->ftwbuf;
+ if (ftwbuf->typeflag != BFTW_LNK) {
+ return false;
+ }
+
+ const struct stat *statbuf = fill_statbuf(state);
+ if (!statbuf) {
+ return false;
+ }
+
+ size_t size = statbuf->st_size + 1;
+ char *name = malloc(size);
+ if (!name) {
+ eval_error(state);
+ return false;
+ }
+
+ ssize_t ret = readlinkat(ftwbuf->at_fd, ftwbuf->at_path, name, size);
+ if (ret < 0) {
+ eval_error(state);
+ return false;
+ } else if (ret >= size) {
+ return false;
+ }
+
+ name[ret] = '\0';
+
+ bool match = fnmatch(expr->sdata, name, expr->idata) == 0;
+ free(name);
+ return match;
+}
+
+/**
* -i?name test.
*/
bool eval_name(const struct expr *expr, struct eval_state *state) {
diff --git a/parse.c b/parse.c
index 7cdc685..7951589 100644
--- a/parse.c
+++ b/parse.c
@@ -457,6 +457,14 @@ static struct expr *parse_path(struct parser_state *state, const char *option, b
}
/**
+ * Parse -i?lname.
+ */
+static struct expr *parse_lname(struct parser_state *state, const char *option, bool casefold) {
+ struct expr *expr = parse_test_sdata(state, option, eval_lname);
+ return set_fnm_casefold(expr, casefold);
+}
+
+/**
* Parse -noleaf.
*/
static struct expr *parse_noleaf(struct parser_state *state, const char *option) {
@@ -670,7 +678,9 @@ static struct expr *parse_literal(struct parser_state *state) {
break;
case 'i':
- if (strcmp(arg, "-iname") == 0) {
+ if (strcmp(arg, "-ilname") == 0) {
+ return parse_lname(state, arg, true);
+ } if (strcmp(arg, "-iname") == 0) {
return parse_name(state, arg, true);
} else if (strcmp(arg, "-inum") == 0) {
return parse_test_icmp(state, arg, eval_inum);
@@ -682,6 +692,8 @@ static struct expr *parse_literal(struct parser_state *state) {
case 'l':
if (strcmp(arg, "-links") == 0) {
return parse_test_icmp(state, arg, eval_links);
+ } else if (strcmp(arg, "-lname") == 0) {
+ return parse_lname(state, arg, false);
}
break;
diff --git a/tests.sh b/tests.sh
index cbfefcb..e6b52be 100755
--- a/tests.sh
+++ b/tests.sh
@@ -223,7 +223,23 @@ function test_0038() {
find_diff "$basic" -ipath "$basic/*F*"
}
-for i in {1..38}; do
+function test_0039() {
+ find_diff "$links" -lname '[aq]'
+}
+
+function test_0040() {
+ find_diff "$links" -ilname '[AQ]'
+}
+
+function test_0041() {
+ find_diff -L "$links" -lname '[aq]' 2>/dev/null
+}
+
+function test_0042() {
+ find_diff -L "$links" -lname '[AQ]' 2>/dev/null
+}
+
+for i in {1..42}; do
test="test_$(printf '%04d' $i)"
"$test" "$dir"
status=$?