diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2016-02-14 13:35:23 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2016-02-14 13:35:23 -0500 |
commit | 585a9dafe86b51a2d120d107bb04a77b34cc1af0 (patch) | |
tree | 7f715d1d8c8a4dd711548f3f19528722a739db00 | |
parent | 94432cd2a3185ce97dfd28a6a1b236449d91268f (diff) | |
download | bfs-585a9dafe86b51a2d120d107bb04a77b34cc1af0.tar.xz |
Implement -lname and -ilname.
-rw-r--r-- | bfs.h | 1 | ||||
-rw-r--r-- | eval.c | 36 | ||||
-rw-r--r-- | parse.c | 14 | ||||
-rwxr-xr-x | tests.sh | 18 |
4 files changed, 67 insertions, 2 deletions
@@ -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); @@ -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) { @@ -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; @@ -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=$? |