summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/tests.sh20
-rw-r--r--tests/xtouch.c39
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;
}