commit d8f966a04b09ede06840b5fdd42b7d8e65b0cb25 (tree)
parent bfc569bc9877a4f305080bc6cde0e42fed7433e0
Author: daurnimator <quae@daurnimator.com>
Date: Wed, 15 Jan 2020 18:17:14 +1000
std: fix fs.makePath
The previous behaviour of using path.resolve has unexpected behaviour around symlinks.
This more simple implementation is more correct and doesn't require an allocator
Diffstat:
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
@@ -301,35 +301,32 @@ pub fn makeDirW(dir_path: [*:0]const u16) !void {
/// already exists and is a directory.
/// This function is not atomic, and if it returns an error, the file system may
/// have been modified regardless.
-/// TODO determine if we can remove the allocator requirement from this function
-pub fn makePath(allocator: *Allocator, full_path: []const u8) !void {
- const resolved_path = try path.resolve(allocator, &[_][]const u8{full_path});
- defer allocator.free(resolved_path);
-
- var end_index: usize = resolved_path.len;
+pub fn makePath(full_path: []const u8) !void {
+ var end_index: usize = full_path.len;
while (true) {
- makeDir(resolved_path[0..end_index]) catch |err| switch (err) {
+ cwd().makeDir(full_path[0..end_index]) catch |err| switch (err) {
error.PathAlreadyExists => {
// TODO stat the file and return an error if it's not a directory
// this is important because otherwise a dangling symlink
// could cause an infinite loop
- if (end_index == resolved_path.len) return;
+ if (end_index == full_path.len) return;
},
error.FileNotFound => {
+ if (end_index == 0) return err;
// march end_index backward until next path component
while (true) {
end_index -= 1;
- if (path.isSep(resolved_path[end_index])) break;
+ if (path.isSep(full_path[end_index])) break;
}
continue;
},
else => return err,
};
- if (end_index == resolved_path.len) return;
+ if (end_index == full_path.len) return;
// march end_index forward until next path component
while (true) {
end_index += 1;
- if (end_index == resolved_path.len or path.isSep(resolved_path[end_index])) break;
+ if (end_index == full_path.len or path.isSep(full_path[end_index])) break;
}
}
}