Commit 51946f5adc

Ryan Liptak <squeek502@hotmail.com>
2024-01-05 08:03:46
Dir.makePath: Document/test platform differences around .. component handling
Closes #18452
1 parent 9335529
Changed files (2)
lib
lib/std/fs/Dir.zig
@@ -1111,6 +1111,14 @@ pub fn makeDirW(self: Dir, sub_path: [*:0]const u16) !void {
 /// Returns success if the path 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.
+///
+/// Paths containing `..` components are handled differently depending on the platform:
+/// - On Windows, `..` are resolved before the path is passed to NtCreateFile, meaning
+///   a `sub_path` like "first/../second" will resolve to "second" and only a
+///   `./second` directory will be created.
+/// - On other platforms, `..` are not resolved before the path is passed to `mkdirat`,
+///   meaning a `sub_path` like "first/../second" will create both a `./first`
+///   and a `./second` directory.
 pub fn makePath(self: Dir, sub_path: []const u8) !void {
     var it = try fs.path.componentIterator(sub_path);
     var component = it.last() orelse return;
lib/std/fs/test.zig
@@ -1131,12 +1131,23 @@ test "makepath relative walks" {
 
     try tmp.dir.makePath(relPath);
 
-    // verify created directories exist:
-    try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "A");
-    try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "B");
-    try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "C");
-    try expectDir(tmp.dir, "second");
-    try expectDir(tmp.dir, "third");
+    // How .. is handled is different on Windows than non-Windows
+    switch (builtin.os.tag) {
+        .windows => {
+            // On Windows, .. is resolved before passing the path to NtCreateFile,
+            // meaning everything except `first/C` drops out.
+            try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "C");
+            try testing.expectError(error.FileNotFound, tmp.dir.access("second", .{}));
+            try testing.expectError(error.FileNotFound, tmp.dir.access("third", .{}));
+        },
+        else => {
+            try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "A");
+            try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "B");
+            try expectDir(tmp.dir, "first" ++ fs.path.sep_str ++ "C");
+            try expectDir(tmp.dir, "second");
+            try expectDir(tmp.dir, "third");
+        },
+    }
 }
 
 test "makepath ignores '.'" {