diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2017-08-12 18:12:13 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2017-08-12 18:12:13 -0400 |
commit | acd7f7ed437793e7c67ecd869cfac32a87c1ec52 (patch) | |
tree | abfb1561c90aca00362fb0f99b8a8da4a70fe08a /bftw.c | |
parent | 01a754bc5572103f9a49242d756dc04b0e86bb6e (diff) | |
download | bfs-acd7f7ed437793e7c67ecd869cfac32a87c1ec52.tar.xz |
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.
Diffstat (limited to 'bftw.c')
-rw-r--r-- | bftw.c | 22 |
1 files changed, 6 insertions, 16 deletions
@@ -551,15 +551,12 @@ static void bftw_queue_destroy(struct bftw_queue *queue) { /** Call stat() and use the results. */ static int ftwbuf_stat(struct BFTW *ftwbuf, struct stat *sb) { - int ret = fstatat(ftwbuf->at_fd, ftwbuf->at_path, sb, ftwbuf->at_flags); - if (ret != 0) { - return ret; + int ret = xfstatat(ftwbuf->at_fd, ftwbuf->at_path, sb, &ftwbuf->at_flags); + if (ret == 0) { + ftwbuf->statbuf = sb; + ftwbuf->typeflag = mode_to_typeflag(sb->st_mode); } - - ftwbuf->statbuf = sb; - ftwbuf->typeflag = mode_to_typeflag(sb->st_mode); - - return 0; + return ret; } /** @@ -837,14 +834,7 @@ static void bftw_init_buffers(struct bftw_state *state, const struct dirent *de) || ftwbuf->typeflag == BFTW_UNKNOWN || (ftwbuf->typeflag == BFTW_LNK && follow) || (ftwbuf->typeflag == BFTW_DIR && (detect_cycles || xdev))) { - int ret = ftwbuf_stat(ftwbuf, &state->statbuf); - if (ret != 0 && follow && (errno == ENOENT || errno == ENOTDIR)) { - // Could be a broken symlink, retry without following - ftwbuf->at_flags = AT_SYMLINK_NOFOLLOW; - ret = ftwbuf_stat(ftwbuf, &state->statbuf); - } - - if (ret != 0) { + if (ftwbuf_stat(ftwbuf, &state->statbuf) != 0) { bftw_set_error(state, errno); return; } |