diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2023-09-29 15:13:41 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2023-09-29 15:14:40 -0400 |
commit | 25660f5c062cf1e0d0982457614c9aa4584fa565 (patch) | |
tree | 79139e7afbdc492925599870918b7e91a471f683 | |
parent | 52de184ba28551734e1cb13233588504ab5f62ec (diff) | |
download | bfs-25660f5c062cf1e0d0982457614c9aa4584fa565.tar.xz |
tests/xtouch: Try creating the immediate parent first
-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; } |