diff options
Diffstat (limited to 'tests')
-rwxr-xr-x | tests/tests.sh | 20 | ||||
-rw-r--r-- | tests/xtouch.c | 39 |
2 files changed, 32 insertions, 27 deletions
diff --git a/tests/tests.sh b/tests/tests.sh index 66a79a8..121cd85 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -393,18 +393,14 @@ function make_deep() { local names="$name/$name/$name/$name" for i in {0..9} A B C D E F; do - ( - mkdir "$1/$i" - cd "$1/$i" - - # 4 * 1024 == 4096 == PATH_MAX - for _ in {1..4}; do - mkdir -p "$names" - cd "$names" - done - - "$XTOUCH" "$name" - ) + "$XTOUCH" -p "$1/$i/$name" + + # 4 * 1024 == 4096 == PATH_MAX + for _ in {1..4}; do + mv "$1/$i/$name" "$1/" + mkdir -p "$1/$i/$names" + mv "$1/$name" "$1/$i/$names/" + done done } make_deep "$TMP/deep" 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; } |