diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 87e0096bb1..bcf4bf5c97 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -95,8 +95,8 @@ test "openDirAbsolute" { test "openDir cwd parent .." { if (builtin.os.tag == .wasi) return error.SkipZigTest; - var cwd = try fs.cwd().openDir("..", .{}); - defer cwd.close(); + var dir = try fs.cwd().openDir("..", .{}); + defer dir.close(); } test "readLinkAbsolute" { diff --git a/lib/std/mem.zig b/lib/std/mem.zig index e57bd2fe49..56391bcfe1 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -2151,7 +2151,7 @@ pub fn collapseRepeats(comptime T: type, slice: []T, elem: T) []T { fn testCollapseRepeats(str: []const u8, elem: u8, expected: []const u8) !void { const mutable = try std.testing.allocator.dupe(u8, str); defer std.testing.allocator.free(mutable); - testing.expect(std.mem.eql(u8, collapseRepeats(u8, mutable, elem), expected)); + try testing.expect(std.mem.eql(u8, collapseRepeats(u8, mutable, elem), expected)); } test "collapseRepeats" { try testCollapseRepeats("", '/', ""); diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index aa33159b74..e02cf4e280 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -1817,20 +1817,42 @@ pub fn sliceToPrefixedFileW(s: []const u8) !PathSpace { else => {}, } } + const prefix_u16 = [_]u16{ '\\', '?', '?', '\\' }; const start_index = if (prefix_index > 0 or !std.fs.path.isAbsolute(s)) 0 else blk: { - const prefix_u16 = [_]u16{ '\\', '?', '?', '\\' }; mem.copy(u16, path_space.data[0..], prefix_u16[0..]); break :blk prefix_u16.len; }; path_space.len = start_index + try std.unicode.utf8ToUtf16Le(path_space.data[start_index..], s); if (path_space.len > path_space.data.len) return error.NameTooLong; path_space.len = start_index + (normalizePath(u16, path_space.data[start_index..path_space.len]) catch |err| switch (err) { - error.TooManyParentDirs => return error.BadPathName, + error.TooManyParentDirs => { + if (!std.fs.path.isAbsolute(s)) { + var temp_path: PathSpace = undefined; + temp_path.len = try std.unicode.utf8ToUtf16Le(&temp_path.data, s); + std.debug.assert(temp_path.len == path_space.len); + temp_path.data[path_space.len] = 0; + path_space.len = prefix_u16.len + try getFullPathNameW(&temp_path.data, path_space.data[prefix_u16.len..]); + mem.copy(u16, &path_space.data, &prefix_u16); + std.debug.assert(path_space.data[path_space.len] == 0); + return path_space; + } + return error.BadPathName; + }, }); path_space.data[path_space.len] = 0; return path_space; } +fn getFullPathNameW(path: [*:0]const u16, out: []u16) !usize { + const result= kernel32.GetFullPathNameW(path, @intCast(u32, out.len), std.meta.assumeSentinel(out.ptr, 0), null); + if (result == 0) { + switch (kernel32.GetLastError()) { + else => |err| return unexpectedError(err), + } + } + return result; +} + /// Assumes an absolute path. pub fn wToPrefixedFileW(s: []const u16) !PathSpace { // TODO https://github.com/ziglang/zig/issues/2765 diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig index e117f362eb..f2e8b87d74 100644 --- a/lib/std/os/windows/kernel32.zig +++ b/lib/std/os/windows/kernel32.zig @@ -136,6 +136,13 @@ pub extern "kernel32" fn GetFinalPathNameByHandleW( dwFlags: DWORD, ) callconv(WINAPI) DWORD; +pub extern "kernel32" fn GetFullPathNameW( + lpFileName: [*:0]const u16, + nBufferLength: u32, + lpBuffer: ?[*:0]u16, + lpFilePart: ?*?[*:0]u16, +) callconv(@import("std").os.windows.WINAPI) u32; + pub extern "kernel32" fn GetOverlappedResult(hFile: HANDLE, lpOverlapped: *OVERLAPPED, lpNumberOfBytesTransferred: *DWORD, bWait: BOOL) callconv(WINAPI) BOOL; pub extern "kernel32" fn GetProcessHeap() callconv(WINAPI) ?HANDLE; diff --git a/lib/std/os/windows/test.zig b/lib/std/os/windows/test.zig index ceffc17bc2..8c18d413ca 100644 --- a/lib/std/os/windows/test.zig +++ b/lib/std/os/windows/test.zig @@ -14,12 +14,12 @@ fn testRemoveDotDirs(str: []const u8, expected: []const u8) !void { const mutable = try testing.allocator.dupe(u8, str); defer testing.allocator.free(mutable); const actual = mutable[0..try windows.removeDotDirsSanitized(u8, mutable)]; - testing.expect(mem.eql(u8, actual, expected)); + try testing.expect(mem.eql(u8, actual, expected)); } fn testRemoveDotDirsError(err: anyerror, str: []const u8) !void { const mutable = try testing.allocator.dupe(u8, str); defer testing.allocator.free(mutable); - testing.expectError(err, windows.removeDotDirsSanitized(u8, mutable)); + try testing.expectError(err, windows.removeDotDirsSanitized(u8, mutable)); } test "removeDotDirs" { try testRemoveDotDirs("", "");