| author | |
| committer | |
| log | 3f9294c73501f55bcba1fe8b5da1ad2f2b0af9e5 |
| tree | 86fce350a6c04eeffbc28f9860865090e8115256 |
| parent | ac95cfe4496a5504b42bf37b02f34eff390fe956 |
Previously, a relative path like `..` would:
- Attempt to be normalized (i.e. remove . and .. without any path resolution), but would error with TooManyParentDirs
- This would make wToPrefixedFileW run it through `RtlGetFullPathName_U` to do the necessary path resolution, but `RtlGetFullPathName_U` always resolves relative paths relative to the CWD
Instead, when TooManyParentDirs occurs, we now look up the path of the passed in `dir` (if it's non-null) and append the relative path to it before giving it to `RtlGetFullPathName_U`. If `dir` is null, then we just give it RtlGetFullPathName_U directly and let it resolve it relative to the CWD.
Closes #167796 files changed, 112 insertions(+), 72 deletions(-)
lib/std/child_process.zig+1-1| ... | @@ -961,7 +961,7 @@ fn windowsCreateProcessPathExt( | ... | @@ -961,7 +961,7 @@ fn windowsCreateProcessPathExt( |
| 961 | try dir_buf.append(allocator, 0); | 961 | try dir_buf.append(allocator, 0); |
| 962 | defer dir_buf.shrinkRetainingCapacity(dir_path_len); | 962 | defer dir_buf.shrinkRetainingCapacity(dir_path_len); |
| 963 | const dir_path_z = dir_buf.items[0 .. dir_buf.items.len - 1 :0]; | 963 | const dir_path_z = dir_buf.items[0 .. dir_buf.items.len - 1 :0]; |
| 964 | const prefixed_path = try windows.wToPrefixedFileW(dir_path_z); | 964 | const prefixed_path = try windows.wToPrefixedFileW(null, dir_path_z); |
| 965 | break :dir fs.cwd().openDirW(prefixed_path.span().ptr, .{}, true) catch return error.FileNotFound; | 965 | break :dir fs.cwd().openDirW(prefixed_path.span().ptr, .{}, true) catch return error.FileNotFound; |
| 966 | }; | 966 | }; |
| 967 | defer dir.close(); | 967 | defer dir.close(); |
lib/std/dynamic_library.zig+2-2| ... | @@ -317,12 +317,12 @@ pub const WindowsDynLib = struct { | ... | @@ -317,12 +317,12 @@ pub const WindowsDynLib = struct { |
| 317 | dll: windows.HMODULE, | 317 | dll: windows.HMODULE, |
| 318 | 318 | ||
| 319 | pub fn open(path: []const u8) !WindowsDynLib { | 319 | pub fn open(path: []const u8) !WindowsDynLib { |
| 320 | const path_w = try windows.sliceToPrefixedFileW(path); | 320 | const path_w = try windows.sliceToPrefixedFileW(null, path); |
| 321 | return openW(path_w.span().ptr); | 321 | return openW(path_w.span().ptr); |
| 322 | } | 322 | } |
| 323 | 323 | ||
| 324 | pub fn openZ(path_c: [*:0]const u8) !WindowsDynLib { | 324 | pub fn openZ(path_c: [*:0]const u8) !WindowsDynLib { |
| 325 | const path_w = try windows.cStrToPrefixedFileW(path_c); | 325 | const path_w = try windows.cStrToPrefixedFileW(null, path_c); |
| 326 | return openW(path_w.span().ptr); | 326 | return openW(path_w.span().ptr); |
| 327 | } | 327 | } |
| 328 | 328 |
lib/std/fs.zig+28-22| ... | @@ -1118,7 +1118,7 @@ pub const Dir = struct { | ... | @@ -1118,7 +1118,7 @@ pub const Dir = struct { |
| 1118 | /// Asserts that the path parameter has no null bytes. | 1118 | /// Asserts that the path parameter has no null bytes. |
| 1119 | pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File { | 1119 | pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File { |
| 1120 | if (builtin.os.tag == .windows) { | 1120 | if (builtin.os.tag == .windows) { |
| 1121 | const path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 1121 | const path_w = try os.windows.sliceToPrefixedFileW(self.fd, sub_path); |
| 1122 | return self.openFileW(path_w.span(), flags); | 1122 | return self.openFileW(path_w.span(), flags); |
| 1123 | } | 1123 | } |
| 1124 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1124 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| ... | @@ -1156,7 +1156,7 @@ pub const Dir = struct { | ... | @@ -1156,7 +1156,7 @@ pub const Dir = struct { |
| 1156 | /// Same as `openFile` but the path parameter is null-terminated. | 1156 | /// Same as `openFile` but the path parameter is null-terminated. |
| 1157 | pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File.OpenError!File { | 1157 | pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File.OpenError!File { |
| 1158 | if (builtin.os.tag == .windows) { | 1158 | if (builtin.os.tag == .windows) { |
| 1159 | const path_w = try os.windows.cStrToPrefixedFileW(sub_path); | 1159 | const path_w = try os.windows.cStrToPrefixedFileW(self.fd, sub_path); |
| 1160 | return self.openFileW(path_w.span(), flags); | 1160 | return self.openFileW(path_w.span(), flags); |
| 1161 | } | 1161 | } |
| 1162 | 1162 | ||
| ... | @@ -1282,7 +1282,7 @@ pub const Dir = struct { | ... | @@ -1282,7 +1282,7 @@ pub const Dir = struct { |
| 1282 | /// Asserts that the path parameter has no null bytes. | 1282 | /// Asserts that the path parameter has no null bytes. |
| 1283 | pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { | 1283 | pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { |
| 1284 | if (builtin.os.tag == .windows) { | 1284 | if (builtin.os.tag == .windows) { |
| 1285 | const path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 1285 | const path_w = try os.windows.sliceToPrefixedFileW(self.fd, sub_path); |
| 1286 | return self.createFileW(path_w.span(), flags); | 1286 | return self.createFileW(path_w.span(), flags); |
| 1287 | } | 1287 | } |
| 1288 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1288 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| ... | @@ -1323,7 +1323,7 @@ pub const Dir = struct { | ... | @@ -1323,7 +1323,7 @@ pub const Dir = struct { |
| 1323 | /// Same as `createFile` but the path parameter is null-terminated. | 1323 | /// Same as `createFile` but the path parameter is null-terminated. |
| 1324 | pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File { | 1324 | pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File { |
| 1325 | if (builtin.os.tag == .windows) { | 1325 | if (builtin.os.tag == .windows) { |
| 1326 | const path_w = try os.windows.cStrToPrefixedFileW(sub_path_c); | 1326 | const path_w = try os.windows.cStrToPrefixedFileW(self.fd, sub_path_c); |
| 1327 | return self.createFileW(path_w.span(), flags); | 1327 | return self.createFileW(path_w.span(), flags); |
| 1328 | } | 1328 | } |
| 1329 | 1329 | ||
| ... | @@ -1513,7 +1513,7 @@ pub const Dir = struct { | ... | @@ -1513,7 +1513,7 @@ pub const Dir = struct { |
| 1513 | @compileError("realpath is not available on WASI"); | 1513 | @compileError("realpath is not available on WASI"); |
| 1514 | } | 1514 | } |
| 1515 | if (builtin.os.tag == .windows) { | 1515 | if (builtin.os.tag == .windows) { |
| 1516 | const pathname_w = try os.windows.sliceToPrefixedFileW(pathname); | 1516 | const pathname_w = try os.windows.sliceToPrefixedFileW(self.fd, pathname); |
| 1517 | return self.realpathW(pathname_w.span(), out_buffer); | 1517 | return self.realpathW(pathname_w.span(), out_buffer); |
| 1518 | } | 1518 | } |
| 1519 | const pathname_c = try os.toPosixPath(pathname); | 1519 | const pathname_c = try os.toPosixPath(pathname); |
| ... | @@ -1524,7 +1524,7 @@ pub const Dir = struct { | ... | @@ -1524,7 +1524,7 @@ pub const Dir = struct { |
| 1524 | /// See also `Dir.realpath`, `realpathZ`. | 1524 | /// See also `Dir.realpath`, `realpathZ`. |
| 1525 | pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) ![]u8 { | 1525 | pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) ![]u8 { |
| 1526 | if (builtin.os.tag == .windows) { | 1526 | if (builtin.os.tag == .windows) { |
| 1527 | const pathname_w = try os.windows.cStrToPrefixedFileW(pathname); | 1527 | const pathname_w = try os.windows.cStrToPrefixedFileW(self.fd, pathname); |
| 1528 | return self.realpathW(pathname_w.span(), out_buffer); | 1528 | return self.realpathW(pathname_w.span(), out_buffer); |
| 1529 | } | 1529 | } |
| 1530 | 1530 | ||
| ... | @@ -1656,7 +1656,7 @@ pub const Dir = struct { | ... | @@ -1656,7 +1656,7 @@ pub const Dir = struct { |
| 1656 | /// Asserts that the path parameter has no null bytes. | 1656 | /// Asserts that the path parameter has no null bytes. |
| 1657 | pub fn openDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir { | 1657 | pub fn openDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir { |
| 1658 | if (builtin.os.tag == .windows) { | 1658 | if (builtin.os.tag == .windows) { |
| 1659 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 1659 | const sub_path_w = try os.windows.sliceToPrefixedFileW(self.fd, sub_path); |
| 1660 | return self.openDirW(sub_path_w.span().ptr, args, false); | 1660 | return self.openDirW(sub_path_w.span().ptr, args, false); |
| 1661 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1661 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1662 | return self.openDirWasi(sub_path, args); | 1662 | return self.openDirWasi(sub_path, args); |
| ... | @@ -1672,7 +1672,7 @@ pub const Dir = struct { | ... | @@ -1672,7 +1672,7 @@ pub const Dir = struct { |
| 1672 | /// Asserts that the path parameter has no null bytes. | 1672 | /// Asserts that the path parameter has no null bytes. |
| 1673 | pub fn openIterableDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!IterableDir { | 1673 | pub fn openIterableDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!IterableDir { |
| 1674 | if (builtin.os.tag == .windows) { | 1674 | if (builtin.os.tag == .windows) { |
| 1675 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 1675 | const sub_path_w = try os.windows.sliceToPrefixedFileW(self.fd, sub_path); |
| 1676 | return IterableDir{ .dir = try self.openDirW(sub_path_w.span().ptr, args, true) }; | 1676 | return IterableDir{ .dir = try self.openDirW(sub_path_w.span().ptr, args, true) }; |
| 1677 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1677 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1678 | return IterableDir{ .dir = try self.openDirWasi(sub_path, args) }; | 1678 | return IterableDir{ .dir = try self.openDirWasi(sub_path, args) }; |
| ... | @@ -1732,7 +1732,7 @@ pub const Dir = struct { | ... | @@ -1732,7 +1732,7 @@ pub const Dir = struct { |
| 1732 | /// Same as `openDir` except the parameter is null-terminated. | 1732 | /// Same as `openDir` except the parameter is null-terminated. |
| 1733 | pub fn openDirZ(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions, iterable: bool) OpenError!Dir { | 1733 | pub fn openDirZ(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions, iterable: bool) OpenError!Dir { |
| 1734 | if (builtin.os.tag == .windows) { | 1734 | if (builtin.os.tag == .windows) { |
| 1735 | const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c); | 1735 | const sub_path_w = try os.windows.cStrToPrefixedFileW(self.fd, sub_path_c); |
| 1736 | return self.openDirW(sub_path_w.span().ptr, args, iterable); | 1736 | return self.openDirW(sub_path_w.span().ptr, args, iterable); |
| 1737 | } | 1737 | } |
| 1738 | const symlink_flags: u32 = if (args.no_follow) os.O.NOFOLLOW else 0x0; | 1738 | const symlink_flags: u32 = if (args.no_follow) os.O.NOFOLLOW else 0x0; |
| ... | @@ -1831,7 +1831,7 @@ pub const Dir = struct { | ... | @@ -1831,7 +1831,7 @@ pub const Dir = struct { |
| 1831 | /// Asserts that the path parameter has no null bytes. | 1831 | /// Asserts that the path parameter has no null bytes. |
| 1832 | pub fn deleteFile(self: Dir, sub_path: []const u8) DeleteFileError!void { | 1832 | pub fn deleteFile(self: Dir, sub_path: []const u8) DeleteFileError!void { |
| 1833 | if (builtin.os.tag == .windows) { | 1833 | if (builtin.os.tag == .windows) { |
| 1834 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 1834 | const sub_path_w = try os.windows.sliceToPrefixedFileW(self.fd, sub_path); |
| 1835 | return self.deleteFileW(sub_path_w.span()); | 1835 | return self.deleteFileW(sub_path_w.span()); |
| 1836 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1836 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1837 | os.unlinkat(self.fd, sub_path, 0) catch |err| switch (err) { | 1837 | os.unlinkat(self.fd, sub_path, 0) catch |err| switch (err) { |
| ... | @@ -1894,7 +1894,7 @@ pub const Dir = struct { | ... | @@ -1894,7 +1894,7 @@ pub const Dir = struct { |
| 1894 | /// Asserts that the path parameter has no null bytes. | 1894 | /// Asserts that the path parameter has no null bytes. |
| 1895 | pub fn deleteDir(self: Dir, sub_path: []const u8) DeleteDirError!void { | 1895 | pub fn deleteDir(self: Dir, sub_path: []const u8) DeleteDirError!void { |
| 1896 | if (builtin.os.tag == .windows) { | 1896 | if (builtin.os.tag == .windows) { |
| 1897 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 1897 | const sub_path_w = try os.windows.sliceToPrefixedFileW(self.fd, sub_path); |
| 1898 | return self.deleteDirW(sub_path_w.span()); | 1898 | return self.deleteDirW(sub_path_w.span()); |
| 1899 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1899 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1900 | os.unlinkat(self.fd, sub_path, os.AT.REMOVEDIR) catch |err| switch (err) { | 1900 | os.unlinkat(self.fd, sub_path, os.AT.REMOVEDIR) catch |err| switch (err) { |
| ... | @@ -1959,8 +1959,8 @@ pub const Dir = struct { | ... | @@ -1959,8 +1959,8 @@ pub const Dir = struct { |
| 1959 | return self.symLinkWasi(target_path, sym_link_path, flags); | 1959 | return self.symLinkWasi(target_path, sym_link_path, flags); |
| 1960 | } | 1960 | } |
| 1961 | if (builtin.os.tag == .windows) { | 1961 | if (builtin.os.tag == .windows) { |
| 1962 | const target_path_w = try os.windows.sliceToPrefixedFileW(target_path); | 1962 | const target_path_w = try os.windows.sliceToPrefixedFileW(self.fd, target_path); |
| 1963 | const sym_link_path_w = try os.windows.sliceToPrefixedFileW(sym_link_path); | 1963 | const sym_link_path_w = try os.windows.sliceToPrefixedFileW(self.fd, sym_link_path); |
| 1964 | return self.symLinkW(target_path_w.span(), sym_link_path_w.span(), flags); | 1964 | return self.symLinkW(target_path_w.span(), sym_link_path_w.span(), flags); |
| 1965 | } | 1965 | } |
| 1966 | const target_path_c = try os.toPosixPath(target_path); | 1966 | const target_path_c = try os.toPosixPath(target_path); |
| ... | @@ -1986,8 +1986,8 @@ pub const Dir = struct { | ... | @@ -1986,8 +1986,8 @@ pub const Dir = struct { |
| 1986 | flags: SymLinkFlags, | 1986 | flags: SymLinkFlags, |
| 1987 | ) !void { | 1987 | ) !void { |
| 1988 | if (builtin.os.tag == .windows) { | 1988 | if (builtin.os.tag == .windows) { |
| 1989 | const target_path_w = try os.windows.cStrToPrefixedFileW(target_path_c); | 1989 | const target_path_w = try os.windows.cStrToPrefixedFileW(self.fd, target_path_c); |
| 1990 | const sym_link_path_w = try os.windows.cStrToPrefixedFileW(sym_link_path_c); | 1990 | const sym_link_path_w = try os.windows.cStrToPrefixedFileW(self.fd, sym_link_path_c); |
| 1991 | return self.symLinkW(target_path_w.span(), sym_link_path_w.span(), flags); | 1991 | return self.symLinkW(target_path_w.span(), sym_link_path_w.span(), flags); |
| 1992 | } | 1992 | } |
| 1993 | return os.symlinkatZ(target_path_c, self.fd, sym_link_path_c); | 1993 | return os.symlinkatZ(target_path_c, self.fd, sym_link_path_c); |
| ... | @@ -2012,7 +2012,7 @@ pub const Dir = struct { | ... | @@ -2012,7 +2012,7 @@ pub const Dir = struct { |
| 2012 | return self.readLinkWasi(sub_path, buffer); | 2012 | return self.readLinkWasi(sub_path, buffer); |
| 2013 | } | 2013 | } |
| 2014 | if (builtin.os.tag == .windows) { | 2014 | if (builtin.os.tag == .windows) { |
| 2015 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 2015 | const sub_path_w = try os.windows.sliceToPrefixedFileW(self.fd, sub_path); |
| 2016 | return self.readLinkW(sub_path_w.span(), buffer); | 2016 | return self.readLinkW(sub_path_w.span(), buffer); |
| 2017 | } | 2017 | } |
| 2018 | const sub_path_c = try os.toPosixPath(sub_path); | 2018 | const sub_path_c = try os.toPosixPath(sub_path); |
| ... | @@ -2027,7 +2027,7 @@ pub const Dir = struct { | ... | @@ -2027,7 +2027,7 @@ pub const Dir = struct { |
| 2027 | /// Same as `readLink`, except the `pathname` parameter is null-terminated. | 2027 | /// Same as `readLink`, except the `pathname` parameter is null-terminated. |
| 2028 | pub fn readLinkZ(self: Dir, sub_path_c: [*:0]const u8, buffer: []u8) ![]u8 { | 2028 | pub fn readLinkZ(self: Dir, sub_path_c: [*:0]const u8, buffer: []u8) ![]u8 { |
| 2029 | if (builtin.os.tag == .windows) { | 2029 | if (builtin.os.tag == .windows) { |
| 2030 | const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c); | 2030 | const sub_path_w = try os.windows.cStrToPrefixedFileW(self.fd, sub_path_c); |
| 2031 | return self.readLinkW(sub_path_w.span(), buffer); | 2031 | return self.readLinkW(sub_path_w.span(), buffer); |
| 2032 | } | 2032 | } |
| 2033 | return os.readlinkatZ(self.fd, sub_path_c, buffer); | 2033 | return os.readlinkatZ(self.fd, sub_path_c, buffer); |
| ... | @@ -2501,7 +2501,10 @@ pub const Dir = struct { | ... | @@ -2501,7 +2501,10 @@ pub const Dir = struct { |
| 2501 | /// open it and handle the error for file not found. | 2501 | /// open it and handle the error for file not found. |
| 2502 | pub fn access(self: Dir, sub_path: []const u8, flags: File.OpenFlags) AccessError!void { | 2502 | pub fn access(self: Dir, sub_path: []const u8, flags: File.OpenFlags) AccessError!void { |
| 2503 | if (builtin.os.tag == .windows) { | 2503 | if (builtin.os.tag == .windows) { |
| 2504 | const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); | 2504 | const sub_path_w = os.windows.sliceToPrefixedFileW(self.fd, sub_path) catch |err| switch (err) { |
| 2505 | error.AccessDenied => return error.PermissionDenied, | ||
| 2506 | else => |e| return e, | ||
| 2507 | }; | ||
| 2505 | return self.accessW(sub_path_w.span().ptr, flags); | 2508 | return self.accessW(sub_path_w.span().ptr, flags); |
| 2506 | } | 2509 | } |
| 2507 | const path_c = try os.toPosixPath(sub_path); | 2510 | const path_c = try os.toPosixPath(sub_path); |
| ... | @@ -2511,7 +2514,10 @@ pub const Dir = struct { | ... | @@ -2511,7 +2514,10 @@ pub const Dir = struct { |
| 2511 | /// Same as `access` except the path parameter is null-terminated. | 2514 | /// Same as `access` except the path parameter is null-terminated. |
| 2512 | pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) AccessError!void { | 2515 | pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) AccessError!void { |
| 2513 | if (builtin.os.tag == .windows) { | 2516 | if (builtin.os.tag == .windows) { |
| 2514 | const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path); | 2517 | const sub_path_w = os.windows.cStrToPrefixedFileW(self.fd, sub_path) catch |err| switch (err) { |
| 2518 | error.AccessDenied => return error.PermissionDenied, | ||
| 2519 | else => |e| return e, | ||
| 2520 | }; | ||
| 2515 | return self.accessW(sub_path_w.span().ptr, flags); | 2521 | return self.accessW(sub_path_w.span().ptr, flags); |
| 2516 | } | 2522 | } |
| 2517 | const os_mode = switch (flags.mode) { | 2523 | const os_mode = switch (flags.mode) { |
| ... | @@ -2894,8 +2900,8 @@ pub fn symLinkAbsolute(target_path: []const u8, sym_link_path: []const u8, flags | ... | @@ -2894,8 +2900,8 @@ pub fn symLinkAbsolute(target_path: []const u8, sym_link_path: []const u8, flags |
| 2894 | assert(path.isAbsolute(target_path)); | 2900 | assert(path.isAbsolute(target_path)); |
| 2895 | assert(path.isAbsolute(sym_link_path)); | 2901 | assert(path.isAbsolute(sym_link_path)); |
| 2896 | if (builtin.os.tag == .windows) { | 2902 | if (builtin.os.tag == .windows) { |
| 2897 | const target_path_w = try os.windows.sliceToPrefixedFileW(target_path); | 2903 | const target_path_w = try os.windows.sliceToPrefixedFileW(null, target_path); |
| 2898 | const sym_link_path_w = try os.windows.sliceToPrefixedFileW(sym_link_path); | 2904 | const sym_link_path_w = try os.windows.sliceToPrefixedFileW(null, sym_link_path); |
| 2899 | return os.windows.CreateSymbolicLink(null, sym_link_path_w.span(), target_path_w.span(), flags.is_directory); | 2905 | return os.windows.CreateSymbolicLink(null, sym_link_path_w.span(), target_path_w.span(), flags.is_directory); |
| 2900 | } | 2906 | } |
| 2901 | return os.symlink(target_path, sym_link_path); | 2907 | return os.symlink(target_path, sym_link_path); |
| ... | @@ -2945,7 +2951,7 @@ pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File { | ... | @@ -2945,7 +2951,7 @@ pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File { |
| 2945 | } | 2951 | } |
| 2946 | if (builtin.os.tag == .windows) { | 2952 | if (builtin.os.tag == .windows) { |
| 2947 | const wide_slice = selfExePathW(); | 2953 | const wide_slice = selfExePathW(); |
| 2948 | const prefixed_path_w = try os.windows.wToPrefixedFileW(wide_slice); | 2954 | const prefixed_path_w = try os.windows.wToPrefixedFileW(null, wide_slice); |
| 2949 | return cwd().openFileW(prefixed_path_w.span(), flags); | 2955 | return cwd().openFileW(prefixed_path_w.span(), flags); |
| 2950 | } | 2956 | } |
| 2951 | // Use of MAX_PATH_BYTES here is valid as the resulting path is immediately | 2957 | // Use of MAX_PATH_BYTES here is valid as the resulting path is immediately |
lib/std/os.zig+37-31| ... | @@ -1464,7 +1464,7 @@ pub const OpenError = error{ | ... | @@ -1464,7 +1464,7 @@ pub const OpenError = error{ |
| 1464 | /// See also `openZ`. | 1464 | /// See also `openZ`. |
| 1465 | pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t { | 1465 | pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t { |
| 1466 | if (builtin.os.tag == .windows) { | 1466 | if (builtin.os.tag == .windows) { |
| 1467 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); | 1467 | const file_path_w = try windows.sliceToPrefixedFileW(null, file_path); |
| 1468 | return openW(file_path_w.span(), flags, perm); | 1468 | return openW(file_path_w.span(), flags, perm); |
| 1469 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1469 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1470 | return openat(wasi.AT.FDCWD, file_path, flags, perm); | 1470 | return openat(wasi.AT.FDCWD, file_path, flags, perm); |
| ... | @@ -1477,7 +1477,7 @@ pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t { | ... | @@ -1477,7 +1477,7 @@ pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t { |
| 1477 | /// See also `open`. | 1477 | /// See also `open`. |
| 1478 | pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: mode_t) OpenError!fd_t { | 1478 | pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: mode_t) OpenError!fd_t { |
| 1479 | if (builtin.os.tag == .windows) { | 1479 | if (builtin.os.tag == .windows) { |
| 1480 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); | 1480 | const file_path_w = try windows.cStrToPrefixedFileW(null, file_path); |
| 1481 | return openW(file_path_w.span(), flags, perm); | 1481 | return openW(file_path_w.span(), flags, perm); |
| 1482 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1482 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1483 | return open(mem.sliceTo(file_path, 0), flags, perm); | 1483 | return open(mem.sliceTo(file_path, 0), flags, perm); |
| ... | @@ -1568,7 +1568,7 @@ pub fn openW(file_path_w: []const u16, flags: u32, perm: mode_t) OpenError!fd_t | ... | @@ -1568,7 +1568,7 @@ pub fn openW(file_path_w: []const u16, flags: u32, perm: mode_t) OpenError!fd_t |
| 1568 | /// See also `openatZ`. | 1568 | /// See also `openatZ`. |
| 1569 | pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) OpenError!fd_t { | 1569 | pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) OpenError!fd_t { |
| 1570 | if (builtin.os.tag == .windows) { | 1570 | if (builtin.os.tag == .windows) { |
| 1571 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); | 1571 | const file_path_w = try windows.sliceToPrefixedFileW(dir_fd, file_path); |
| 1572 | return openatW(dir_fd, file_path_w.span(), flags, mode); | 1572 | return openatW(dir_fd, file_path_w.span(), flags, mode); |
| 1573 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1573 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1574 | // `mode` is ignored on WASI, which does not support unix-style file permissions | 1574 | // `mode` is ignored on WASI, which does not support unix-style file permissions |
| ... | @@ -1690,7 +1690,7 @@ pub fn openatWasi( | ... | @@ -1690,7 +1690,7 @@ pub fn openatWasi( |
| 1690 | /// See also `openat`. | 1690 | /// See also `openat`. |
| 1691 | pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: u32, mode: mode_t) OpenError!fd_t { | 1691 | pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: u32, mode: mode_t) OpenError!fd_t { |
| 1692 | if (builtin.os.tag == .windows) { | 1692 | if (builtin.os.tag == .windows) { |
| 1693 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); | 1693 | const file_path_w = try windows.cStrToPrefixedFileW(dir_fd, file_path); |
| 1694 | return openatW(dir_fd, file_path_w.span(), flags, mode); | 1694 | return openatW(dir_fd, file_path_w.span(), flags, mode); |
| 1695 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1695 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1696 | return openat(dir_fd, mem.sliceTo(file_path, 0), flags, mode); | 1696 | return openat(dir_fd, mem.sliceTo(file_path, 0), flags, mode); |
| ... | @@ -2305,7 +2305,7 @@ pub fn unlink(file_path: []const u8) UnlinkError!void { | ... | @@ -2305,7 +2305,7 @@ pub fn unlink(file_path: []const u8) UnlinkError!void { |
| 2305 | else => |e| return e, | 2305 | else => |e| return e, |
| 2306 | }; | 2306 | }; |
| 2307 | } else if (builtin.os.tag == .windows) { | 2307 | } else if (builtin.os.tag == .windows) { |
| 2308 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); | 2308 | const file_path_w = try windows.sliceToPrefixedFileW(null, file_path); |
| 2309 | return unlinkW(file_path_w.span()); | 2309 | return unlinkW(file_path_w.span()); |
| 2310 | } else { | 2310 | } else { |
| 2311 | const file_path_c = try toPosixPath(file_path); | 2311 | const file_path_c = try toPosixPath(file_path); |
| ... | @@ -2316,7 +2316,7 @@ pub fn unlink(file_path: []const u8) UnlinkError!void { | ... | @@ -2316,7 +2316,7 @@ pub fn unlink(file_path: []const u8) UnlinkError!void { |
| 2316 | /// Same as `unlink` except the parameter is a null terminated UTF8-encoded string. | 2316 | /// Same as `unlink` except the parameter is a null terminated UTF8-encoded string. |
| 2317 | pub fn unlinkZ(file_path: [*:0]const u8) UnlinkError!void { | 2317 | pub fn unlinkZ(file_path: [*:0]const u8) UnlinkError!void { |
| 2318 | if (builtin.os.tag == .windows) { | 2318 | if (builtin.os.tag == .windows) { |
| 2319 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); | 2319 | const file_path_w = try windows.cStrToPrefixedFileW(null, file_path); |
| 2320 | return unlinkW(file_path_w.span()); | 2320 | return unlinkW(file_path_w.span()); |
| 2321 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2321 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2322 | return unlink(mem.sliceTo(file_path, 0)); | 2322 | return unlink(mem.sliceTo(file_path, 0)); |
| ... | @@ -2354,7 +2354,7 @@ pub const UnlinkatError = UnlinkError || error{ | ... | @@ -2354,7 +2354,7 @@ pub const UnlinkatError = UnlinkError || error{ |
| 2354 | /// Asserts that the path parameter has no null bytes. | 2354 | /// Asserts that the path parameter has no null bytes. |
| 2355 | pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void { | 2355 | pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void { |
| 2356 | if (builtin.os.tag == .windows) { | 2356 | if (builtin.os.tag == .windows) { |
| 2357 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); | 2357 | const file_path_w = try windows.sliceToPrefixedFileW(dirfd, file_path); |
| 2358 | return unlinkatW(dirfd, file_path_w.span(), flags); | 2358 | return unlinkatW(dirfd, file_path_w.span(), flags); |
| 2359 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2359 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2360 | return unlinkatWasi(dirfd, file_path, flags); | 2360 | return unlinkatWasi(dirfd, file_path, flags); |
| ... | @@ -2399,7 +2399,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro | ... | @@ -2399,7 +2399,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro |
| 2399 | /// Same as `unlinkat` but `file_path` is a null-terminated string. | 2399 | /// Same as `unlinkat` but `file_path` is a null-terminated string. |
| 2400 | pub fn unlinkatZ(dirfd: fd_t, file_path_c: [*:0]const u8, flags: u32) UnlinkatError!void { | 2400 | pub fn unlinkatZ(dirfd: fd_t, file_path_c: [*:0]const u8, flags: u32) UnlinkatError!void { |
| 2401 | if (builtin.os.tag == .windows) { | 2401 | if (builtin.os.tag == .windows) { |
| 2402 | const file_path_w = try windows.cStrToPrefixedFileW(file_path_c); | 2402 | const file_path_w = try windows.cStrToPrefixedFileW(dirfd, file_path_c); |
| 2403 | return unlinkatW(dirfd, file_path_w.span(), flags); | 2403 | return unlinkatW(dirfd, file_path_w.span(), flags); |
| 2404 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2404 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2405 | return unlinkat(dirfd, mem.sliceTo(file_path_c, 0), flags); | 2405 | return unlinkat(dirfd, mem.sliceTo(file_path_c, 0), flags); |
| ... | @@ -2468,8 +2468,8 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void { | ... | @@ -2468,8 +2468,8 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void { |
| 2468 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2468 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2469 | return renameat(wasi.AT.FDCWD, old_path, wasi.AT.FDCWD, new_path); | 2469 | return renameat(wasi.AT.FDCWD, old_path, wasi.AT.FDCWD, new_path); |
| 2470 | } else if (builtin.os.tag == .windows) { | 2470 | } else if (builtin.os.tag == .windows) { |
| 2471 | const old_path_w = try windows.sliceToPrefixedFileW(old_path); | 2471 | const old_path_w = try windows.sliceToPrefixedFileW(null, old_path); |
| 2472 | const new_path_w = try windows.sliceToPrefixedFileW(new_path); | 2472 | const new_path_w = try windows.sliceToPrefixedFileW(null, new_path); |
| 2473 | return renameW(old_path_w.span().ptr, new_path_w.span().ptr); | 2473 | return renameW(old_path_w.span().ptr, new_path_w.span().ptr); |
| 2474 | } else { | 2474 | } else { |
| 2475 | const old_path_c = try toPosixPath(old_path); | 2475 | const old_path_c = try toPosixPath(old_path); |
| ... | @@ -2481,8 +2481,8 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void { | ... | @@ -2481,8 +2481,8 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void { |
| 2481 | /// Same as `rename` except the parameters are null-terminated byte arrays. | 2481 | /// Same as `rename` except the parameters are null-terminated byte arrays. |
| 2482 | pub fn renameZ(old_path: [*:0]const u8, new_path: [*:0]const u8) RenameError!void { | 2482 | pub fn renameZ(old_path: [*:0]const u8, new_path: [*:0]const u8) RenameError!void { |
| 2483 | if (builtin.os.tag == .windows) { | 2483 | if (builtin.os.tag == .windows) { |
| 2484 | const old_path_w = try windows.cStrToPrefixedFileW(old_path); | 2484 | const old_path_w = try windows.cStrToPrefixedFileW(null, old_path); |
| 2485 | const new_path_w = try windows.cStrToPrefixedFileW(new_path); | 2485 | const new_path_w = try windows.cStrToPrefixedFileW(null, new_path); |
| 2486 | return renameW(old_path_w.span().ptr, new_path_w.span().ptr); | 2486 | return renameW(old_path_w.span().ptr, new_path_w.span().ptr); |
| 2487 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2487 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2488 | return rename(mem.sliceTo(old_path, 0), mem.sliceTo(new_path, 0)); | 2488 | return rename(mem.sliceTo(old_path, 0), mem.sliceTo(new_path, 0)); |
| ... | @@ -2526,8 +2526,8 @@ pub fn renameat( | ... | @@ -2526,8 +2526,8 @@ pub fn renameat( |
| 2526 | new_path: []const u8, | 2526 | new_path: []const u8, |
| 2527 | ) RenameError!void { | 2527 | ) RenameError!void { |
| 2528 | if (builtin.os.tag == .windows) { | 2528 | if (builtin.os.tag == .windows) { |
| 2529 | const old_path_w = try windows.sliceToPrefixedFileW(old_path); | 2529 | const old_path_w = try windows.sliceToPrefixedFileW(old_dir_fd, old_path); |
| 2530 | const new_path_w = try windows.sliceToPrefixedFileW(new_path); | 2530 | const new_path_w = try windows.sliceToPrefixedFileW(new_dir_fd, new_path); |
| 2531 | return renameatW(old_dir_fd, old_path_w.span(), new_dir_fd, new_path_w.span(), windows.TRUE); | 2531 | return renameatW(old_dir_fd, old_path_w.span(), new_dir_fd, new_path_w.span(), windows.TRUE); |
| 2532 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2532 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2533 | const old: RelativePathWasi = .{ .dir_fd = old_dir_fd, .relative_path = old_path }; | 2533 | const old: RelativePathWasi = .{ .dir_fd = old_dir_fd, .relative_path = old_path }; |
| ... | @@ -2576,8 +2576,8 @@ pub fn renameatZ( | ... | @@ -2576,8 +2576,8 @@ pub fn renameatZ( |
| 2576 | new_path: [*:0]const u8, | 2576 | new_path: [*:0]const u8, |
| 2577 | ) RenameError!void { | 2577 | ) RenameError!void { |
| 2578 | if (builtin.os.tag == .windows) { | 2578 | if (builtin.os.tag == .windows) { |
| 2579 | const old_path_w = try windows.cStrToPrefixedFileW(old_path); | 2579 | const old_path_w = try windows.cStrToPrefixedFileW(old_dir_fd, old_path); |
| 2580 | const new_path_w = try windows.cStrToPrefixedFileW(new_path); | 2580 | const new_path_w = try windows.cStrToPrefixedFileW(new_dir_fd, new_path); |
| 2581 | return renameatW(old_dir_fd, old_path_w.span(), new_dir_fd, new_path_w.span(), windows.TRUE); | 2581 | return renameatW(old_dir_fd, old_path_w.span(), new_dir_fd, new_path_w.span(), windows.TRUE); |
| 2582 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2582 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2583 | return renameat(old_dir_fd, mem.sliceTo(old_path, 0), new_dir_fd, mem.sliceTo(new_path, 0)); | 2583 | return renameat(old_dir_fd, mem.sliceTo(old_path, 0), new_dir_fd, mem.sliceTo(new_path, 0)); |
| ... | @@ -2670,7 +2670,7 @@ pub fn renameatW( | ... | @@ -2670,7 +2670,7 @@ pub fn renameatW( |
| 2670 | 2670 | ||
| 2671 | pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!void { | 2671 | pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!void { |
| 2672 | if (builtin.os.tag == .windows) { | 2672 | if (builtin.os.tag == .windows) { |
| 2673 | const sub_dir_path_w = try windows.sliceToPrefixedFileW(sub_dir_path); | 2673 | const sub_dir_path_w = try windows.sliceToPrefixedFileW(dir_fd, sub_dir_path); |
| 2674 | return mkdiratW(dir_fd, sub_dir_path_w.span(), mode); | 2674 | return mkdiratW(dir_fd, sub_dir_path_w.span(), mode); |
| 2675 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2675 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2676 | return mkdiratWasi(dir_fd, sub_dir_path, mode); | 2676 | return mkdiratWasi(dir_fd, sub_dir_path, mode); |
| ... | @@ -2705,7 +2705,7 @@ pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirErr | ... | @@ -2705,7 +2705,7 @@ pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirErr |
| 2705 | 2705 | ||
| 2706 | pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirError!void { | 2706 | pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirError!void { |
| 2707 | if (builtin.os.tag == .windows) { | 2707 | if (builtin.os.tag == .windows) { |
| 2708 | const sub_dir_path_w = try windows.cStrToPrefixedFileW(sub_dir_path); | 2708 | const sub_dir_path_w = try windows.cStrToPrefixedFileW(dir_fd, sub_dir_path); |
| 2709 | return mkdiratW(dir_fd, sub_dir_path_w.span().ptr, mode); | 2709 | return mkdiratW(dir_fd, sub_dir_path_w.span().ptr, mode); |
| 2710 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2710 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2711 | return mkdirat(dir_fd, mem.sliceTo(sub_dir_path, 0), mode); | 2711 | return mkdirat(dir_fd, mem.sliceTo(sub_dir_path, 0), mode); |
| ... | @@ -2776,7 +2776,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void { | ... | @@ -2776,7 +2776,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void { |
| 2776 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2776 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2777 | return mkdirat(wasi.AT.FDCWD, dir_path, mode); | 2777 | return mkdirat(wasi.AT.FDCWD, dir_path, mode); |
| 2778 | } else if (builtin.os.tag == .windows) { | 2778 | } else if (builtin.os.tag == .windows) { |
| 2779 | const dir_path_w = try windows.sliceToPrefixedFileW(dir_path); | 2779 | const dir_path_w = try windows.sliceToPrefixedFileW(null, dir_path); |
| 2780 | return mkdirW(dir_path_w.span(), mode); | 2780 | return mkdirW(dir_path_w.span(), mode); |
| 2781 | } else { | 2781 | } else { |
| 2782 | const dir_path_c = try toPosixPath(dir_path); | 2782 | const dir_path_c = try toPosixPath(dir_path); |
| ... | @@ -2787,7 +2787,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void { | ... | @@ -2787,7 +2787,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void { |
| 2787 | /// Same as `mkdir` but the parameter is a null-terminated UTF8-encoded string. | 2787 | /// Same as `mkdir` but the parameter is a null-terminated UTF8-encoded string. |
| 2788 | pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void { | 2788 | pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void { |
| 2789 | if (builtin.os.tag == .windows) { | 2789 | if (builtin.os.tag == .windows) { |
| 2790 | const dir_path_w = try windows.cStrToPrefixedFileW(dir_path); | 2790 | const dir_path_w = try windows.cStrToPrefixedFileW(null, dir_path); |
| 2791 | return mkdirW(dir_path_w.span(), mode); | 2791 | return mkdirW(dir_path_w.span(), mode); |
| 2792 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2792 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2793 | return mkdir(mem.sliceTo(dir_path, 0), mode); | 2793 | return mkdir(mem.sliceTo(dir_path, 0), mode); |
| ... | @@ -2854,7 +2854,7 @@ pub fn rmdir(dir_path: []const u8) DeleteDirError!void { | ... | @@ -2854,7 +2854,7 @@ pub fn rmdir(dir_path: []const u8) DeleteDirError!void { |
| 2854 | else => |e| return e, | 2854 | else => |e| return e, |
| 2855 | }; | 2855 | }; |
| 2856 | } else if (builtin.os.tag == .windows) { | 2856 | } else if (builtin.os.tag == .windows) { |
| 2857 | const dir_path_w = try windows.sliceToPrefixedFileW(dir_path); | 2857 | const dir_path_w = try windows.sliceToPrefixedFileW(null, dir_path); |
| 2858 | return rmdirW(dir_path_w.span()); | 2858 | return rmdirW(dir_path_w.span()); |
| 2859 | } else { | 2859 | } else { |
| 2860 | const dir_path_c = try toPosixPath(dir_path); | 2860 | const dir_path_c = try toPosixPath(dir_path); |
| ... | @@ -2865,7 +2865,7 @@ pub fn rmdir(dir_path: []const u8) DeleteDirError!void { | ... | @@ -2865,7 +2865,7 @@ pub fn rmdir(dir_path: []const u8) DeleteDirError!void { |
| 2865 | /// Same as `rmdir` except the parameter is null-terminated. | 2865 | /// Same as `rmdir` except the parameter is null-terminated. |
| 2866 | pub fn rmdirZ(dir_path: [*:0]const u8) DeleteDirError!void { | 2866 | pub fn rmdirZ(dir_path: [*:0]const u8) DeleteDirError!void { |
| 2867 | if (builtin.os.tag == .windows) { | 2867 | if (builtin.os.tag == .windows) { |
| 2868 | const dir_path_w = try windows.cStrToPrefixedFileW(dir_path); | 2868 | const dir_path_w = try windows.cStrToPrefixedFileW(null, dir_path); |
| 2869 | return rmdirW(dir_path_w.span()); | 2869 | return rmdirW(dir_path_w.span()); |
| 2870 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2870 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2871 | return rmdir(mem.sliceTo(dir_path, 0)); | 2871 | return rmdir(mem.sliceTo(dir_path, 0)); |
| ... | @@ -3003,7 +3003,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { | ... | @@ -3003,7 +3003,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| 3003 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 3003 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 3004 | return readlinkat(wasi.AT.FDCWD, file_path, out_buffer); | 3004 | return readlinkat(wasi.AT.FDCWD, file_path, out_buffer); |
| 3005 | } else if (builtin.os.tag == .windows) { | 3005 | } else if (builtin.os.tag == .windows) { |
| 3006 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); | 3006 | const file_path_w = try windows.sliceToPrefixedFileW(null, file_path); |
| 3007 | return readlinkW(file_path_w.span(), out_buffer); | 3007 | return readlinkW(file_path_w.span(), out_buffer); |
| 3008 | } else { | 3008 | } else { |
| 3009 | const file_path_c = try toPosixPath(file_path); | 3009 | const file_path_c = try toPosixPath(file_path); |
| ... | @@ -3049,7 +3049,7 @@ pub fn readlinkat(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLink | ... | @@ -3049,7 +3049,7 @@ pub fn readlinkat(dirfd: fd_t, file_path: []const u8, out_buffer: []u8) ReadLink |
| 3049 | return readlinkatWasi(dirfd, file_path, out_buffer); | 3049 | return readlinkatWasi(dirfd, file_path, out_buffer); |
| 3050 | } | 3050 | } |
| 3051 | if (builtin.os.tag == .windows) { | 3051 | if (builtin.os.tag == .windows) { |
| 3052 | const file_path_w = try windows.sliceToPrefixedFileW(file_path); | 3052 | const file_path_w = try windows.sliceToPrefixedFileW(dirfd, file_path); |
| 3053 | return readlinkatW(dirfd, file_path_w.span(), out_buffer); | 3053 | return readlinkatW(dirfd, file_path_w.span(), out_buffer); |
| 3054 | } | 3054 | } |
| 3055 | const file_path_c = try toPosixPath(file_path); | 3055 | const file_path_c = try toPosixPath(file_path); |
| ... | @@ -3086,7 +3086,7 @@ pub fn readlinkatW(dirfd: fd_t, file_path: []const u16, out_buffer: []u8) ReadLi | ... | @@ -3086,7 +3086,7 @@ pub fn readlinkatW(dirfd: fd_t, file_path: []const u16, out_buffer: []u8) ReadLi |
| 3086 | /// See also `readlinkat`. | 3086 | /// See also `readlinkat`. |
| 3087 | pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { | 3087 | pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 { |
| 3088 | if (builtin.os.tag == .windows) { | 3088 | if (builtin.os.tag == .windows) { |
| 3089 | const file_path_w = try windows.cStrToPrefixedFileW(file_path); | 3089 | const file_path_w = try windows.cStrToPrefixedFileW(dirfd, file_path); |
| 3090 | return readlinkatW(dirfd, file_path_w.span(), out_buffer); | 3090 | return readlinkatW(dirfd, file_path_w.span(), out_buffer); |
| 3091 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 3091 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 3092 | return readlinkat(dirfd, mem.sliceTo(file_path, 0), out_buffer); | 3092 | return readlinkat(dirfd, mem.sliceTo(file_path, 0), out_buffer); |
| ... | @@ -4443,7 +4443,10 @@ pub const AccessError = error{ | ... | @@ -4443,7 +4443,10 @@ pub const AccessError = error{ |
| 4443 | /// TODO currently this assumes `mode` is `F.OK` on Windows. | 4443 | /// TODO currently this assumes `mode` is `F.OK` on Windows. |
| 4444 | pub fn access(path: []const u8, mode: u32) AccessError!void { | 4444 | pub fn access(path: []const u8, mode: u32) AccessError!void { |
| 4445 | if (builtin.os.tag == .windows) { | 4445 | if (builtin.os.tag == .windows) { |
| 4446 | const path_w = try windows.sliceToPrefixedFileW(path); | 4446 | const path_w = windows.sliceToPrefixedFileW(null, path) catch |err| switch (err) { |
| 4447 | error.AccessDenied => return error.PermissionDenied, | ||
| 4448 | else => |e| return e, | ||
| 4449 | }; | ||
| 4447 | _ = try windows.GetFileAttributesW(path_w.span().ptr); | 4450 | _ = try windows.GetFileAttributesW(path_w.span().ptr); |
| 4448 | return; | 4451 | return; |
| 4449 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 4452 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| ... | @@ -4456,7 +4459,10 @@ pub fn access(path: []const u8, mode: u32) AccessError!void { | ... | @@ -4456,7 +4459,10 @@ pub fn access(path: []const u8, mode: u32) AccessError!void { |
| 4456 | /// Same as `access` except `path` is null-terminated. | 4459 | /// Same as `access` except `path` is null-terminated. |
| 4457 | pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void { | 4460 | pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void { |
| 4458 | if (builtin.os.tag == .windows) { | 4461 | if (builtin.os.tag == .windows) { |
| 4459 | const path_w = try windows.cStrToPrefixedFileW(path); | 4462 | const path_w = windows.cStrToPrefixedFileW(null, path) catch |err| switch (err) { |
| 4463 | error.AccessDenied => return error.PermissionDenied, | ||
| 4464 | else => |e| return e, | ||
| 4465 | }; | ||
| 4460 | _ = try windows.GetFileAttributesW(path_w.span().ptr); | 4466 | _ = try windows.GetFileAttributesW(path_w.span().ptr); |
| 4461 | return; | 4467 | return; |
| 4462 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 4468 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| ... | @@ -4500,7 +4506,7 @@ pub fn accessW(path: [*:0]const u16, mode: u32) windows.GetFileAttributesError!v | ... | @@ -4500,7 +4506,7 @@ pub fn accessW(path: [*:0]const u16, mode: u32) windows.GetFileAttributesError!v |
| 4500 | /// TODO currently this ignores `mode` and `flags` on Windows. | 4506 | /// TODO currently this ignores `mode` and `flags` on Windows. |
| 4501 | pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessError!void { | 4507 | pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessError!void { |
| 4502 | if (builtin.os.tag == .windows) { | 4508 | if (builtin.os.tag == .windows) { |
| 4503 | const path_w = try windows.sliceToPrefixedFileW(path); | 4509 | const path_w = try windows.sliceToPrefixedFileW(dirfd, path); |
| 4504 | return faccessatW(dirfd, path_w.span().ptr, mode, flags); | 4510 | return faccessatW(dirfd, path_w.span().ptr, mode, flags); |
| 4505 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 4511 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 4506 | var resolved = RelativePathWasi{ .dir_fd = dirfd, .relative_path = path }; | 4512 | var resolved = RelativePathWasi{ .dir_fd = dirfd, .relative_path = path }; |
| ... | @@ -4543,7 +4549,7 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr | ... | @@ -4543,7 +4549,7 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr |
| 4543 | /// Same as `faccessat` except the path parameter is null-terminated. | 4549 | /// Same as `faccessat` except the path parameter is null-terminated. |
| 4544 | pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) AccessError!void { | 4550 | pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) AccessError!void { |
| 4545 | if (builtin.os.tag == .windows) { | 4551 | if (builtin.os.tag == .windows) { |
| 4546 | const path_w = try windows.cStrToPrefixedFileW(path); | 4552 | const path_w = try windows.cStrToPrefixedFileW(dirfd, path); |
| 4547 | return faccessatW(dirfd, path_w.span().ptr, mode, flags); | 4553 | return faccessatW(dirfd, path_w.span().ptr, mode, flags); |
| 4548 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 4554 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 4549 | return faccessat(dirfd, mem.sliceTo(path, 0), mode, flags); | 4555 | return faccessat(dirfd, mem.sliceTo(path, 0), mode, flags); |
| ... | @@ -5079,7 +5085,7 @@ pub const RealPathError = error{ | ... | @@ -5079,7 +5085,7 @@ pub const RealPathError = error{ |
| 5079 | /// See also `realpathZ` and `realpathW`. | 5085 | /// See also `realpathZ` and `realpathW`. |
| 5080 | pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { | 5086 | pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { |
| 5081 | if (builtin.os.tag == .windows) { | 5087 | if (builtin.os.tag == .windows) { |
| 5082 | const pathname_w = try windows.sliceToPrefixedFileW(pathname); | 5088 | const pathname_w = try windows.sliceToPrefixedFileW(null, pathname); |
| 5083 | return realpathW(pathname_w.span(), out_buffer); | 5089 | return realpathW(pathname_w.span(), out_buffer); |
| 5084 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 5090 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 5085 | @compileError("WASI does not support os.realpath"); | 5091 | @compileError("WASI does not support os.realpath"); |
| ... | @@ -5091,7 +5097,7 @@ pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathE | ... | @@ -5091,7 +5097,7 @@ pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathE |
| 5091 | /// Same as `realpath` except `pathname` is null-terminated. | 5097 | /// Same as `realpath` except `pathname` is null-terminated. |
| 5092 | pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { | 5098 | pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { |
| 5093 | if (builtin.os.tag == .windows) { | 5099 | if (builtin.os.tag == .windows) { |
| 5094 | const pathname_w = try windows.cStrToPrefixedFileW(pathname); | 5100 | const pathname_w = try windows.cStrToPrefixedFileW(null, pathname); |
| 5095 | return realpathW(pathname_w.span(), out_buffer); | 5101 | return realpathW(pathname_w.span(), out_buffer); |
| 5096 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 5102 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 5097 | return realpath(mem.sliceTo(pathname, 0), out_buffer); | 5103 | return realpath(mem.sliceTo(pathname, 0), out_buffer); |
lib/std/os/windows.zig+42-14| ... | @@ -170,7 +170,7 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C | ... | @@ -170,7 +170,7 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | pub fn CreateEventEx(attributes: ?*SECURITY_ATTRIBUTES, name: []const u8, flags: DWORD, desired_access: DWORD) !HANDLE { | 172 | pub fn CreateEventEx(attributes: ?*SECURITY_ATTRIBUTES, name: []const u8, flags: DWORD, desired_access: DWORD) !HANDLE { |
| 173 | const nameW = try sliceToPrefixedFileW(name); | 173 | const nameW = try sliceToPrefixedFileW(null, name); |
| 174 | return CreateEventExW(attributes, nameW.span().ptr, flags, desired_access); | 174 | return CreateEventExW(attributes, nameW.span().ptr, flags, desired_access); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| ... | @@ -1007,8 +1007,8 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil | ... | @@ -1007,8 +1007,8 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil |
| 1007 | pub const MoveFileError = error{ FileNotFound, AccessDenied, Unexpected }; | 1007 | pub const MoveFileError = error{ FileNotFound, AccessDenied, Unexpected }; |
| 1008 | 1008 | ||
| 1009 | pub fn MoveFileEx(old_path: []const u8, new_path: []const u8, flags: DWORD) MoveFileError!void { | 1009 | pub fn MoveFileEx(old_path: []const u8, new_path: []const u8, flags: DWORD) MoveFileError!void { |
| 1010 | const old_path_w = try sliceToPrefixedFileW(old_path); | 1010 | const old_path_w = try sliceToPrefixedFileW(null, old_path); |
| 1011 | const new_path_w = try sliceToPrefixedFileW(new_path); | 1011 | const new_path_w = try sliceToPrefixedFileW(null, new_path); |
| 1012 | return MoveFileExW(old_path_w.span().ptr, new_path_w.span().ptr, flags); | 1012 | return MoveFileExW(old_path_w.span().ptr, new_path_w.span().ptr, flags); |
| 1013 | } | 1013 | } |
| 1014 | 1014 | ||
| ... | @@ -1317,7 +1317,7 @@ pub const GetFileAttributesError = error{ | ... | @@ -1317,7 +1317,7 @@ pub const GetFileAttributesError = error{ |
| 1317 | }; | 1317 | }; |
| 1318 | 1318 | ||
| 1319 | pub fn GetFileAttributes(filename: []const u8) GetFileAttributesError!DWORD { | 1319 | pub fn GetFileAttributes(filename: []const u8) GetFileAttributesError!DWORD { |
| 1320 | const filename_w = try sliceToPrefixedFileW(filename); | 1320 | const filename_w = try sliceToPrefixedFileW(null, filename); |
| 1321 | return GetFileAttributesW(filename_w.span().ptr); | 1321 | return GetFileAttributesW(filename_w.span().ptr); |
| 1322 | } | 1322 | } |
| 1323 | 1323 | ||
| ... | @@ -2120,16 +2120,16 @@ pub fn normalizePath(comptime T: type, path: []T) RemoveDotDirsError!usize { | ... | @@ -2120,16 +2120,16 @@ pub fn normalizePath(comptime T: type, path: []T) RemoveDotDirsError!usize { |
| 2120 | 2120 | ||
| 2121 | /// Same as `sliceToPrefixedFileW` but accepts a pointer | 2121 | /// Same as `sliceToPrefixedFileW` but accepts a pointer |
| 2122 | /// to a null-terminated path. | 2122 | /// to a null-terminated path. |
| 2123 | pub fn cStrToPrefixedFileW(s: [*:0]const u8) !PathSpace { | 2123 | pub fn cStrToPrefixedFileW(dir: ?HANDLE, s: [*:0]const u8) !PathSpace { |
| 2124 | return sliceToPrefixedFileW(mem.sliceTo(s, 0)); | 2124 | return sliceToPrefixedFileW(dir, mem.sliceTo(s, 0)); |
| 2125 | } | 2125 | } |
| 2126 | 2126 | ||
| 2127 | /// Same as `wToPrefixedFileW` but accepts a UTF-8 encoded path. | 2127 | /// Same as `wToPrefixedFileW` but accepts a UTF-8 encoded path. |
| 2128 | pub fn sliceToPrefixedFileW(path: []const u8) !PathSpace { | 2128 | pub fn sliceToPrefixedFileW(dir: ?HANDLE, path: []const u8) !PathSpace { |
| 2129 | var temp_path: PathSpace = undefined; | 2129 | var temp_path: PathSpace = undefined; |
| 2130 | temp_path.len = try std.unicode.utf8ToUtf16Le(&temp_path.data, path); | 2130 | temp_path.len = try std.unicode.utf8ToUtf16Le(&temp_path.data, path); |
| 2131 | temp_path.data[temp_path.len] = 0; | 2131 | temp_path.data[temp_path.len] = 0; |
| 2132 | return wToPrefixedFileW(temp_path.span()); | 2132 | return wToPrefixedFileW(dir, temp_path.span()); |
| 2133 | } | 2133 | } |
| 2134 | 2134 | ||
| 2135 | /// Converts the `path` to WTF16, null-terminated. If the path contains any | 2135 | /// Converts the `path` to WTF16, null-terminated. If the path contains any |
| ... | @@ -2139,11 +2139,11 @@ pub fn sliceToPrefixedFileW(path: []const u8) !PathSpace { | ... | @@ -2139,11 +2139,11 @@ pub fn sliceToPrefixedFileW(path: []const u8) !PathSpace { |
| 2139 | /// Similar to RtlDosPathNameToNtPathName_U with a few differences: | 2139 | /// Similar to RtlDosPathNameToNtPathName_U with a few differences: |
| 2140 | /// - Does not allocate on the heap. | 2140 | /// - Does not allocate on the heap. |
| 2141 | /// - Relative paths are kept as relative unless they contain too many .. | 2141 | /// - Relative paths are kept as relative unless they contain too many .. |
| 2142 | /// components, in which case they are treated as drive-relative and resolved | 2142 | /// components, in which case they are resolved against the `dir` if it |
| 2143 | /// against the CWD. | 2143 | /// is non-null, or the CWD if it is null. |
| 2144 | /// - Special case device names like COM1, NUL, etc are not handled specially (TODO) | 2144 | /// - Special case device names like COM1, NUL, etc are not handled specially (TODO) |
| 2145 | /// - . and space are not stripped from the end of relative paths (potential TODO) | 2145 | /// - . and space are not stripped from the end of relative paths (potential TODO) |
| 2146 | pub fn wToPrefixedFileW(path: [:0]const u16) !PathSpace { | 2146 | pub fn wToPrefixedFileW(dir: ?HANDLE, path: [:0]const u16) !PathSpace { |
| 2147 | const nt_prefix = [_]u16{ '\\', '?', '?', '\\' }; | 2147 | const nt_prefix = [_]u16{ '\\', '?', '?', '\\' }; |
| 2148 | switch (getNamespacePrefix(u16, path)) { | 2148 | switch (getNamespacePrefix(u16, path)) { |
| 2149 | // TODO: Figure out a way to design an API that can avoid the copy for .nt, | 2149 | // TODO: Figure out a way to design an API that can avoid the copy for .nt, |
| ... | @@ -2194,8 +2194,7 @@ pub fn wToPrefixedFileW(path: [:0]const u16) !PathSpace { | ... | @@ -2194,8 +2194,7 @@ pub fn wToPrefixedFileW(path: [:0]const u16) !PathSpace { |
| 2194 | 2194 | ||
| 2195 | @memcpy(path_space.data[0..path.len], path); | 2195 | @memcpy(path_space.data[0..path.len], path); |
| 2196 | // Try to normalize, but if we get too many parent directories, | 2196 | // Try to normalize, but if we get too many parent directories, |
| 2197 | // then this is effectively a 'drive relative' path, so we need to | 2197 | // then we need to start over and use RtlGetFullPathName_U instead. |
| 2198 | // start over and use RtlGetFullPathName_U instead. | ||
| 2199 | path_space.len = normalizePath(u16, path_space.data[0..path.len]) catch |err| switch (err) { | 2198 | path_space.len = normalizePath(u16, path_space.data[0..path.len]) catch |err| switch (err) { |
| 2200 | error.TooManyParentDirs => break :relative, | 2199 | error.TooManyParentDirs => break :relative, |
| 2201 | }; | 2200 | }; |
| ... | @@ -2224,8 +2223,37 @@ pub fn wToPrefixedFileW(path: [:0]const u16) !PathSpace { | ... | @@ -2224,8 +2223,37 @@ pub fn wToPrefixedFileW(path: [:0]const u16) !PathSpace { |
| 2224 | else => nt_prefix.len, | 2223 | else => nt_prefix.len, |
| 2225 | }; | 2224 | }; |
| 2226 | const buf_len = @as(u32, @intCast(path_space.data.len - path_buf_offset)); | 2225 | const buf_len = @as(u32, @intCast(path_space.data.len - path_buf_offset)); |
| 2226 | const path_to_get: [:0]const u16 = path_to_get: { | ||
| 2227 | // If dir is null, then we don't need to bother with GetFinalPathNameByHandle because | ||
| 2228 | // RtlGetFullPathName_U will resolve relative paths against the CWD for us. | ||
| 2229 | if (path_type != .relative or dir == null) { | ||
| 2230 | break :path_to_get path; | ||
| 2231 | } | ||
| 2232 | // We can also skip GetFinalPathNameByHandle if the handle matches | ||
| 2233 | // the handle returned by fs.cwd() | ||
| 2234 | if (dir.? == std.fs.cwd().fd) { | ||
| 2235 | break :path_to_get path; | ||
| 2236 | } | ||
| 2237 | // At this point, we know we have a relative path that had too many | ||
| 2238 | // `..` components to be resolved by normalizePath, so we need to | ||
| 2239 | // convert it into an absolute path and let RtlGetFullPathName_U | ||
| 2240 | // canonicalize it. We do this by getting the path of the `dir` | ||
| 2241 | // and appending the relative path to it. | ||
| 2242 | var dir_path_buf: [PATH_MAX_WIDE:0]u16 = undefined; | ||
| 2243 | const dir_path = try GetFinalPathNameByHandle(dir.?, .{}, &dir_path_buf); | ||
| 2244 | if (dir_path.len + 1 + path.len > PATH_MAX_WIDE) { | ||
| 2245 | return error.NameTooLong; | ||
| 2246 | } | ||
| 2247 | // We don't have to worry about potentially doubling up path separators | ||
| 2248 | // here since RtlGetFullPathName_U will handle canonicalizing it. | ||
| 2249 | dir_path_buf[dir_path.len] = '\\'; | ||
| 2250 | @memcpy(dir_path_buf[dir_path.len + 1 ..][0..path.len], path); | ||
| 2251 | const full_len = dir_path.len + 1 + path.len; | ||
| 2252 | dir_path_buf[full_len] = 0; | ||
| 2253 | break :path_to_get dir_path_buf[0..full_len :0]; | ||
| 2254 | }; | ||
| 2227 | const path_byte_len = ntdll.RtlGetFullPathName_U( | 2255 | const path_byte_len = ntdll.RtlGetFullPathName_U( |
| 2228 | path.ptr, | 2256 | path_to_get.ptr, |
| 2229 | buf_len * 2, | 2257 | buf_len * 2, |
| 2230 | path_space.data[path_buf_offset..].ptr, | 2258 | path_space.data[path_buf_offset..].ptr, |
| 2231 | null, | 2259 | null, |
lib/std/os/windows/test.zig+2-2| ... | @@ -28,7 +28,7 @@ fn RtlDosPathNameToNtPathName_U(path: [:0]const u16) !windows.PathSpace { | ... | @@ -28,7 +28,7 @@ fn RtlDosPathNameToNtPathName_U(path: [:0]const u16) !windows.PathSpace { |
| 28 | fn testToPrefixedFileNoOracle(comptime path: []const u8, comptime expected_path: []const u8) !void { | 28 | fn testToPrefixedFileNoOracle(comptime path: []const u8, comptime expected_path: []const u8) !void { |
| 29 | const path_utf16 = std.unicode.utf8ToUtf16LeStringLiteral(path); | 29 | const path_utf16 = std.unicode.utf8ToUtf16LeStringLiteral(path); |
| 30 | const expected_path_utf16 = std.unicode.utf8ToUtf16LeStringLiteral(expected_path); | 30 | const expected_path_utf16 = std.unicode.utf8ToUtf16LeStringLiteral(expected_path); |
| 31 | const actual_path = try windows.wToPrefixedFileW(path_utf16); | 31 | const actual_path = try windows.wToPrefixedFileW(null, path_utf16); |
| 32 | std.testing.expectEqualSlices(u16, expected_path_utf16, actual_path.span()) catch |e| { | 32 | std.testing.expectEqualSlices(u16, expected_path_utf16, actual_path.span()) catch |e| { |
| 33 | std.debug.print("got '{s}', expected '{s}'\n", .{ std.unicode.fmtUtf16le(actual_path.span()), std.unicode.fmtUtf16le(expected_path_utf16) }); | 33 | std.debug.print("got '{s}', expected '{s}'\n", .{ std.unicode.fmtUtf16le(actual_path.span()), std.unicode.fmtUtf16le(expected_path_utf16) }); |
| 34 | return e; | 34 | return e; |
| ... | @@ -45,7 +45,7 @@ fn testToPrefixedFileWithOracle(comptime path: []const u8, comptime expected_pat | ... | @@ -45,7 +45,7 @@ fn testToPrefixedFileWithOracle(comptime path: []const u8, comptime expected_pat |
| 45 | /// Test that the Zig conversion matches the conversion that RtlDosPathNameToNtPathName_U does. | 45 | /// Test that the Zig conversion matches the conversion that RtlDosPathNameToNtPathName_U does. |
| 46 | fn testToPrefixedFileOnlyOracle(comptime path: []const u8) !void { | 46 | fn testToPrefixedFileOnlyOracle(comptime path: []const u8) !void { |
| 47 | const path_utf16 = std.unicode.utf8ToUtf16LeStringLiteral(path); | 47 | const path_utf16 = std.unicode.utf8ToUtf16LeStringLiteral(path); |
| 48 | const zig_result = try windows.wToPrefixedFileW(path_utf16); | 48 | const zig_result = try windows.wToPrefixedFileW(null, path_utf16); |
| 49 | const win32_api_result = try RtlDosPathNameToNtPathName_U(path_utf16); | 49 | const win32_api_result = try RtlDosPathNameToNtPathName_U(path_utf16); |
| 50 | std.testing.expectEqualSlices(u16, win32_api_result.span(), zig_result.span()) catch |e| { | 50 | std.testing.expectEqualSlices(u16, win32_api_result.span(), zig_result.span()) catch |e| { |
| 51 | std.debug.print("got '{s}', expected '{s}'\n", .{ std.unicode.fmtUtf16le(zig_result.span()), std.unicode.fmtUtf16le(win32_api_result.span()) }); | 51 | std.debug.print("got '{s}', expected '{s}'\n", .{ std.unicode.fmtUtf16le(zig_result.span()), std.unicode.fmtUtf16le(win32_api_result.span()) }); |