aboutsummaryrefslogtreecommitdiff
path: root/lib/std/fs/Dir.zig
diff options
context:
space:
mode:
authorAmir Alawi <83512437+amiralawi@users.noreply.github.com>2024-01-08 15:58:14 -0500
committerGitHub <noreply@github.com>2024-01-08 15:58:14 -0500
commit4cbf74bd9b839501a4fd4bc5f39a25e216237b3c (patch)
tree6cc25456391073e1820167cf896c2cf710dd18dc /lib/std/fs/Dir.zig
parented410b9c1e9a09e674f862b5f3af9d207837a472 (diff)
downloadzig-4cbf74bd9b839501a4fd4bc5f39a25e216237b3c.tar.gz
zig-4cbf74bd9b839501a4fd4bc5f39a25e216237b3c.zip
fix std.fs.Dir.makePath silent failure (#16878)
std.fs.dir.makePath silently failed if one of the items in the path already exists. For example: cwd.makePath("foo/bar/baz") Silently failing is OK if "bar" is already a directory - this is the intended use of makePath (like mkdir -p). But if bar is a file then the subdirectory baz cannot be created - the end result is that makePath doesn't do anything which should be a detectable error because baz is never created. The existing code had a TODO comment that did not specifically cover this error, but the solution for this silent failure also accomplishes the TODO task - the code now stats "foo" and returns an appropriate error. The new code also handles potential race condition if "bar" is deleted/permissions changed/etc in between the initial makeDir and statFile calls.
Diffstat (limited to 'lib/std/fs/Dir.zig')
-rw-r--r--lib/std/fs/Dir.zig10
1 files changed, 9 insertions, 1 deletions
diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig
index 8a1d38996e..0f996affcc 100644
--- a/lib/std/fs/Dir.zig
+++ b/lib/std/fs/Dir.zig
@@ -1125,9 +1125,17 @@ pub fn makePath(self: Dir, sub_path: []const u8) !void {
while (true) {
self.makeDir(component.path) catch |err| switch (err) {
error.PathAlreadyExists => {
- // TODO stat the file and return an error if it's not a directory
+ // 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
+ check_dir: {
+ // workaround for windows, see https://github.com/ziglang/zig/issues/16738
+ const fstat = self.statFile(component.path) catch |stat_err| switch (stat_err) {
+ error.IsDir => break :check_dir,
+ else => |e| return e,
+ };
+ if (fstat.kind != .directory) return error.NotDir;
+ }
},
error.FileNotFound => |e| {
component = it.previous() orelse return e;