From 585a9dafe86b51a2d120d107bb04a77b34cc1af0 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sun, 14 Feb 2016 13:35:23 -0500 Subject: Implement -lname and -ilname. --- bfs.h | 1 + eval.c | 36 ++++++++++++++++++++++++++++++++++++ parse.c | 14 +++++++++++++- tests.sh | 18 +++++++++++++++++- 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 @@ -307,6 +307,42 @@ bool eval_links(const struct expr *expr, struct eval_state *state) { return do_cmp(expr, statbuf->st_nlink); } +/** + * -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. */ diff --git a/parse.c b/parse.c index 7cdc685..7951589 100644 --- a/parse.c +++ b/parse.c @@ -456,6 +456,14 @@ static struct expr *parse_path(struct parser_state *state, const char *option, b return set_fnm_casefold(expr, casefold); } +/** + * 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. */ @@ -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=$? -- cgit v1.2.3