diff options
Diffstat (limited to 'tests/xtouch.c')
-rw-r--r-- | tests/xtouch.c | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/tests/xtouch.c b/tests/xtouch.c index 4a02bf3..80fad8d 100644 --- a/tests/xtouch.c +++ b/tests/xtouch.c @@ -48,31 +48,40 @@ static int at_flags(const struct args *args) { /** Create any parent directories of the given path. */ static int mkdirs(const char *path, mode_t mode) { - char *copy = strdup(path); - if (!copy) { - return -1; + int ret = -1; + char *dir = xdirname(path); + if (!dir) { + goto err; } - int ret = -1; - char *cur = copy + strspn(copy, "/"); - while (true) { - cur += strcspn(cur, "/"); + if (strcmp(dir, ".") == 0) { + goto done; + } + + // Optimistically try the immediate parent first + if (mkdir(dir, mode) == 0 || errno == EEXIST) { + goto done; + } + // Create the parents one-at-a-time + char *cur = dir + strspn(dir, "/"); + while (*cur) { + cur += strcspn(cur, "/"); char *next = cur + strspn(cur, "/"); - if (!*next) { - ret = 0; - break; - } + char c = *cur; *cur = '\0'; - if (mkdir(copy, mode) != 0 && errno != EEXIST) { - break; + if (mkdir(dir, mode) != 0 && errno != EEXIST) { + goto err; } - *cur = '/'; + *cur = c; cur = next; } - free(copy); +done: + ret = 0; +err: + free(dir); return ret; } |