summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2017-07-09 16:35:38 -0400
committerTavian Barnes <tavianator@tavianator.com>2017-07-09 16:35:38 -0400
commit2328d8dbb5a8c774afb99d363b6e98cd25ee304d (patch)
tree53822ecfebc872335e9b13f2fb255f0b2aa808d6
parentf4eed3b771a987ef441fea49ababc356a2933086 (diff)
downloadbfs-2328d8dbb5a8c774afb99d363b6e98cd25ee304d.tar.xz
Handle ENOTDIR the same as ENOENT
For a/b/c, ENOTDIR is returned instead of ENOENT if a or b are not directories. Handle this uniformly when detecting broken symlinks, readdir races, etc.
-rw-r--r--bftw.c2
-rw-r--r--eval.c4
-rw-r--r--printf.c1
-rwxr-xr-xtests.sh10
-rw-r--r--tests/test_L.out1
-rw-r--r--tests/test_L_depth.out1
-rw-r--r--tests/test_L_xtype_l.out1
-rw-r--r--tests/test_colors.out1
-rw-r--r--tests/test_follow.out1
-rw-r--r--tests/test_printf_types.out1
-rw-r--r--tests/test_xtype_l.out1
11 files changed, 21 insertions, 3 deletions
diff --git a/bftw.c b/bftw.c
index 991176a..baf7e65 100644
--- a/bftw.c
+++ b/bftw.c
@@ -836,7 +836,7 @@ static void bftw_init_buffers(struct bftw_state *state, const struct dirent *de)
|| (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) {
+ 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);
diff --git a/eval.c b/eval.c
index 90b854e..daee9d6 100644
--- a/eval.c
+++ b/eval.c
@@ -51,7 +51,7 @@ struct eval_state {
*/
static bool eval_should_ignore(const struct eval_state *state, int error) {
return state->cmdline->ignore_races
- && error == ENOENT
+ && (error == ENOENT || errno == ENOTDIR)
&& state->ftwbuf->depth > 0;
}
@@ -788,7 +788,7 @@ bool eval_xtype(const struct expr *expr, struct eval_state *state) {
struct stat sb;
if (fstatat(ftwbuf->at_fd, ftwbuf->at_path, &sb, at_flags) != 0) {
- if (!follow && errno == ENOENT) {
+ if (!follow && (errno == ENOENT || errno == ENOTDIR)) {
// Broken symlink
return eval_type(expr, state);
} else {
diff --git a/printf.c b/printf.c
index 888fecb..9b284b4 100644
--- a/printf.c
+++ b/printf.c
@@ -371,6 +371,7 @@ static int bfs_printf_Y(FILE *file, const struct bfs_printf_directive *directive
type = "L";
break;
case ENOENT:
+ case ENOTDIR:
type = "N";
break;
}
diff --git a/tests.sh b/tests.sh
index c8aeb63..b150046 100755
--- a/tests.sh
+++ b/tests.sh
@@ -74,6 +74,7 @@ function make_links() {
ln -s ../../d "$1/d/e/g"
ln -s d/e "$1/h"
ln -s q "$1/d/e/i"
+ ln -s b/c "$1/j"
}
make_links "$TMP/links"
@@ -299,6 +300,7 @@ gnu_tests=(
test_flag_double_dash
test_ignore_readdir_race
test_ignore_readdir_race_root
+ test_ignore_readdir_race_notdir
test_perm_222_slash
test_perm_644_slash
test_perm_symbolic_slash
@@ -797,6 +799,14 @@ function test_ignore_readdir_race_root() {
! $BFS basic/nonexistent -ignore_readdir_race 2>/dev/null
}
+function test_ignore_readdir_race_notdir() {
+ # Check -ignore_readdir_race handling when a directory is replaced with a file
+ rm -rf scratch/*
+ touchp scratch/foo/bar
+
+ $BFS scratch -mindepth 1 -ignore_readdir_race -execdir rm -r '{}' \; -execdir touch '{}' \;
+}
+
function test_perm_222() {
bfs_diff perms -perm 222
}
diff --git a/tests/test_L.out b/tests/test_L.out
index 36087e8..f9ded0a 100644
--- a/tests/test_L.out
+++ b/tests/test_L.out
@@ -4,6 +4,7 @@ links/b
links/c
links/d
links/h
+links/j
links/d/e
links/h/f
links/h/g
diff --git a/tests/test_L_depth.out b/tests/test_L_depth.out
index 36087e8..f9ded0a 100644
--- a/tests/test_L_depth.out
+++ b/tests/test_L_depth.out
@@ -4,6 +4,7 @@ links/b
links/c
links/d
links/h
+links/j
links/d/e
links/h/f
links/h/g
diff --git a/tests/test_L_xtype_l.out b/tests/test_L_xtype_l.out
index 1052fc0..57bee1b 100644
--- a/tests/test_L_xtype_l.out
+++ b/tests/test_L_xtype_l.out
@@ -1,5 +1,6 @@
links/b
links/h
+links/j
links/h/g
links/h/i
links/d/e/i
diff --git a/tests/test_colors.out b/tests/test_colors.out
index a9ab84a..8c8b244 100644
--- a/tests/test_colors.out
+++ b/tests/test_colors.out
@@ -2,6 +2,7 @@
links/d
links/b
links/h
+links/j
links/a
links/c
links/d/e
diff --git a/tests/test_follow.out b/tests/test_follow.out
index 36087e8..f9ded0a 100644
--- a/tests/test_follow.out
+++ b/tests/test_follow.out
@@ -4,6 +4,7 @@ links/b
links/c
links/d
links/h
+links/j
links/d/e
links/h/f
links/h/g
diff --git a/tests/test_printf_types.out b/tests/test_printf_types.out
index 94fa833..bd89b47 100644
--- a/tests/test_printf_types.out
+++ b/tests/test_printf_types.out
@@ -5,6 +5,7 @@
(links/d) () d d
(links/d/e) () d d
(links/h) (d/e) l d
+(links/j) (b/c) l N
(links/d/e/f) () d d
(links/d/e/i) (q) l N
(links/d/e/g) (../../d) l d
diff --git a/tests/test_xtype_l.out b/tests/test_xtype_l.out
index e5e13fc..2d1293f 100644
--- a/tests/test_xtype_l.out
+++ b/tests/test_xtype_l.out
@@ -1 +1,2 @@
+links/j
links/d/e/i