From fc98276e1401366fd91a437af3e7fa5f1471f94e Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 21 Nov 2016 14:40:46 -0500 Subject: Fix -execdir for / --- eval.c | 17 ++++++++++++----- tests.sh | 16 +++++++++++++++- tests/test_0098.out | 1 + tests/test_0099.out | 1 + tests/test_0100.out | 1 + 5 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 tests/test_0098.out create mode 100644 tests/test_0099.out create mode 100644 tests/test_0100.out diff --git a/eval.c b/eval.c index 16c4dac..4fc91cc 100644 --- a/eval.c +++ b/eval.c @@ -261,14 +261,21 @@ bool eval_delete(const struct expr *expr, struct eval_state *state) { return true; } +static const char *exec_slash = "/"; + static const char *exec_format_path(const struct expr *expr, const struct BFTW *ftwbuf) { if (!(expr->exec_flags & EXEC_CHDIR)) { return ftwbuf->path; } - // For compatibility with GNU find, use './name' instead of just 'name' const char *name = ftwbuf->path + ftwbuf->nameoff; + if (name[0] == '/') { + // Must be the root path ("/", "//", etc.), which we canonicalize + return exec_slash; + } + + // For compatibility with GNU find, use './name' instead of just 'name' char *path = dstralloc(2 + strlen(name)); if (!path) { perror("dstralloc()"); @@ -292,7 +299,7 @@ err: } static void exec_free_path(const char *path, const struct BFTW *ftwbuf) { - if (path != ftwbuf->path) { + if (path != ftwbuf->path && path != exec_slash) { dstrfree((char *)path); } } @@ -388,12 +395,12 @@ static void exec_chdir(const struct BFTW *ftwbuf) { while (end > path && end[-1] != '/') { --end; } - if (end == path) { + if (end > path) { + *end = '\0'; + } if (path[0] != '/') { // The path is something like "foo", so we're already in the // right directory return; - } else { - *end = '\0'; } if (chdir(path) != 0) { diff --git a/tests.sh b/tests.sh index ba731eb..3d3d10b 100755 --- a/tests.sh +++ b/tests.sh @@ -522,7 +522,21 @@ function test_0097() { (cd scratch && "$BFS" -delete) } -for i in {1..97}; do +function test_0098() { + bfs_diff / -maxdepth 0 -execdir pwd ';' +} + +function test_0099() { + # Don't prepend ./ for absolute paths in -execdir + bfs_diff / -maxdepth 0 -execdir echo '{}' ';' +} + +function test_0100() { + # // is canonicalized to / + bfs_diff // -maxdepth 0 -execdir echo '{}' ';' +} + +for i in {1..100}; do test="test_$(printf '%04d' $i)" if [ -t 1 ]; then diff --git a/tests/test_0098.out b/tests/test_0098.out new file mode 100644 index 0000000..b498fd4 --- /dev/null +++ b/tests/test_0098.out @@ -0,0 +1 @@ +/ diff --git a/tests/test_0099.out b/tests/test_0099.out new file mode 100644 index 0000000..b498fd4 --- /dev/null +++ b/tests/test_0099.out @@ -0,0 +1 @@ +/ diff --git a/tests/test_0100.out b/tests/test_0100.out new file mode 100644 index 0000000..b498fd4 --- /dev/null +++ b/tests/test_0100.out @@ -0,0 +1 @@ +/ -- cgit v1.2.3