From acd7f7ed437793e7c67ecd869cfac32a87c1ec52 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sat, 12 Aug 2017 18:12:13 -0400 Subject: Unify broken symlink handling Rather than open-code the fallback logic for broken symlinks everywhere it's needed, introduce a new xfstatat() utility function that performs the fallback automatically. Using xfstatat() consistently fixes a few bugs, including cases where broken symlinks are given as arguments to predicates like -samefile. --- eval.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'eval.c') diff --git a/eval.c b/eval.c index 6883ce4..a3c55d5 100644 --- a/eval.c +++ b/eval.c @@ -76,7 +76,7 @@ static void eval_error(struct eval_state *state) { static const struct stat *fill_statbuf(struct eval_state *state) { struct BFTW *ftwbuf = state->ftwbuf; if (!ftwbuf->statbuf) { - if (fstatat(ftwbuf->at_fd, ftwbuf->at_path, &state->statbuf, ftwbuf->at_flags) == 0) { + if (xfstatat(ftwbuf->at_fd, ftwbuf->at_path, &state->statbuf, &ftwbuf->at_flags) == 0) { ftwbuf->statbuf = &state->statbuf; } else { eval_error(state); @@ -821,29 +821,19 @@ bool eval_type(const struct expr *expr, struct eval_state *state) { bool eval_xtype(const struct expr *expr, struct eval_state *state) { struct BFTW *ftwbuf = state->ftwbuf; - int follow_flags = BFTW_LOGICAL; - if (ftwbuf->depth == 0) { - follow_flags |= BFTW_COMFOLLOW; - } - bool follow = state->cmdline->flags & follow_flags; - + bool follow = !(ftwbuf->at_flags & AT_SYMLINK_NOFOLLOW); bool is_link = ftwbuf->typeflag == BFTW_LNK; if (follow == is_link) { return eval_type(expr, state); } // -xtype does the opposite of everything else - int at_flags = follow ? AT_SYMLINK_NOFOLLOW : 0; + int at_flags = ftwbuf->at_flags ^ AT_SYMLINK_NOFOLLOW; struct stat sb; - if (fstatat(ftwbuf->at_fd, ftwbuf->at_path, &sb, at_flags) != 0) { - if (!follow && (errno == ENOENT || errno == ENOTDIR)) { - // Broken symlink - return eval_type(expr, state); - } else { - eval_error(state); - return false; - } + if (xfstatat(ftwbuf->at_fd, ftwbuf->at_path, &sb, &at_flags) != 0) { + eval_error(state); + return false; } return mode_to_typeflag(sb.st_mode) & expr->idata; -- cgit v1.2.3