summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2016-11-21 14:40:46 -0500
committerTavian Barnes <tavianator@tavianator.com>2016-11-21 14:40:46 -0500
commitfc98276e1401366fd91a437af3e7fa5f1471f94e (patch)
tree5758c00b122c2d7737e731a5ca3de6b356d6f725 /eval.c
parentcd09f52da8596295841cb832d84f0e728bff449d (diff)
downloadbfs-fc98276e1401366fd91a437af3e7fa5f1471f94e.tar.xz
Fix -execdir for /
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c17
1 files changed, 12 insertions, 5 deletions
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) {