Skip to content

Commit fd07114

Browse files
committed
common/file: improve create_directory
* simplify code * accept absolute path * accept redundant and trailing slashes
1 parent c71ada3 commit fd07114

File tree

1 file changed

+16
-41
lines changed

1 file changed

+16
-41
lines changed

common/file/file_utils.c2

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -21,61 +21,36 @@ import string;
2121
import sys_stat local;
2222
import unistd local;
2323

24-
fn const char* find_char(const char* full, char delim) {
25-
while (1) {
26-
char c = *full;
27-
if (c == delim) return full;
28-
if (c == 0) break;
29-
full++;
30-
}
31-
return nil;
32-
}
33-
34-
35-
// return 0 on succes, -1 otherwise
36-
fn i32 create_dir(const char* path, bool follow) {
37-
i32 err = mkdir(path, 0777);
38-
if (err && errno != EEXIST) return -1;
39-
40-
if (!follow) return 0;
41-
42-
i32 fd = openat(AT_FDCWD, path, O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_DIRECTORY);
43-
if (fd == -1) return errno;
44-
45-
err = fchdir(fd);
46-
if (err == -1) return -1;
47-
48-
close(fd);
49-
return 0;
50-
}
51-
5224
// returns 0 on success, errno on failure
5325
public fn i32 create_directory(const char* path) {
5426
i32 fd = openat(AT_FDCWD, ".", O_RDONLY);
5527
if (fd == -1) return errno;
5628

57-
// TODO handle . / .., empty path
58-
char[128] tmp;
29+
char[256] tmp;
5930
const char* cp = path;
60-
i32 err = 0;
61-
while (*cp) {
62-
const char* slash = find_char(cp, '/');
63-
// TODO check for empty string (//)
31+
i32 errno_ = 0;
32+
if (*cp == '/') {
33+
cp++;
34+
if (chdir("/")) errno_ = errno;
35+
}
36+
while (!errno_ && *cp) {
37+
const char* slash = string.strchr(cp, '/');
6438
if (slash) {
6539
usize len = cast<usize>(slash - cp);
40+
assert(len < elemsof(tmp));
6641
string.memcpy(tmp, cp, len);
67-
tmp[len] = 0;
42+
tmp[len] = '\0';
6843
cp = slash + 1;
69-
err = create_dir(tmp, true);
70-
if (err != 0) break;
44+
if (!len) continue; // ignore // and trailing slash
45+
if ((mkdir(tmp, 0777) && errno != EEXIST) || chdir(tmp)) {
46+
errno_ = errno;
47+
break;
48+
}
7149
} else {
72-
err = create_dir(cp, false);
50+
if (mkdir(cp, 0777) && errno != EEXIST) errno_ = errno;
7351
break;
7452
}
7553
}
76-
i32 errno_ = 0;
77-
if (err) errno_ = errno;
78-
7954
fchdir(fd);
8055
close(fd);
8156
return errno_;

0 commit comments

Comments
 (0)