summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2017-08-22 18:34:36 -0400
committerTavian Barnes <tavianator@tavianator.com>2017-08-22 18:37:23 -0400
commitd548b86e120db7e1327eea957a698d4bb874a1fb (patch)
tree874e34926ee12fbbf076a834d6822ab751cf378b /eval.c
parent2a561b66f48ab4deafb0a031cad3ad541ea79449 (diff)
downloadbfs-d548b86e120db7e1327eea957a698d4bb874a1fb.tar.xz
Avoid multiple extra stat()s of broken symlinks for -xtype
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/eval.c b/eval.c
index a3c55d5..21204d8 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 (xfstatat(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);
@@ -831,9 +831,14 @@ bool eval_xtype(const struct expr *expr, struct eval_state *state) {
int at_flags = ftwbuf->at_flags ^ AT_SYMLINK_NOFOLLOW;
struct stat sb;
- if (xfstatat(ftwbuf->at_fd, ftwbuf->at_path, &sb, &at_flags) != 0) {
- eval_error(state);
- return false;
+ 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;
+ }
}
return mode_to_typeflag(sb.st_mode) & expr->idata;