summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2016-02-06 22:49:35 -0500
committerTavian Barnes <tavianator@tavianator.com>2016-02-06 22:49:35 -0500
commitb46da967104df09edcad706e5e8ef31326a113dd (patch)
tree2f5e10dff126bf590f552a5bd73410f1db8844cf
parent0f91c5861cacaeb17729b7727d07260273345393 (diff)
downloadbfs-b46da967104df09edcad706e5e8ef31326a113dd.tar.xz
bftw: Don't give up when following a broken symlink.
-rw-r--r--bftw.c10
-rwxr-xr-xtests.sh8
2 files changed, 16 insertions, 2 deletions
diff --git a/bftw.c b/bftw.c
index a49cbed..e445432 100644
--- a/bftw.c
+++ b/bftw.c
@@ -631,7 +631,15 @@ static void bftw_init_buffers(struct bftw_state *state, const struct dirent *de)
|| ftwbuf->typeflag == BFTW_UNKNOWN
|| (ftwbuf->typeflag == BFTW_LNK && follow)) {
int flags = follow ? 0 : AT_SYMLINK_NOFOLLOW;
- if (ftwbuf_stat(ftwbuf, &state->statbuf, flags) != 0) {
+
+ int ret = ftwbuf_stat(ftwbuf, &state->statbuf, flags);
+ if (ret != 0 && follow && errno == ENOENT) {
+ // Could be a broken symlink, retry without following
+ flags = AT_SYMLINK_NOFOLLOW;
+ ret = ftwbuf_stat(ftwbuf, &state->statbuf, flags);
+ }
+
+ if (ret != 0) {
state->error = errno;
ftwbuf_set_error(ftwbuf, state->error);
}
diff --git a/tests.sh b/tests.sh
index 0a2f60a..493bfab 100755
--- a/tests.sh
+++ b/tests.sh
@@ -36,6 +36,7 @@ function links_structure() {
mkdir -p "$1/d/e"
ln -s ../../d "$1/d/e/f"
touchp "$1/d/e/g"
+ ln -s q "$1/d/e/h"
}
# Checks for any (order-independent) differences between bfs and find
@@ -168,7 +169,12 @@ function test_0023() {
find_diff -H "$1" -newer "$1/d/e/f"
}
-for i in {1..23}; do
+function test_0024() {
+ links_structure "$1"
+ find_diff -H "$1/d/e/h"
+}
+
+for i in {1..24}; do
dir="$(mktemp -d "${TMPDIR:-/tmp}"/bfs.XXXXXXXXXX)"
test="test_$(printf '%04d' $i)"
"$test" "$dir"