| author | |
| committer | |
| log | aa6e8eff40bdf35c838c8cd93080f2e9d4fad3b2 |
| tree | 3d39b4b01c9d6af60dc8a83f5950535ddecfc5a7 |
| parent | 482343f2e253f2078627e696fb98ff0e1d8e82df |
6 files changed, 66 insertions(+), 14 deletions(-)
lib/std/Io/Threaded.zig+48-3| ... | @@ -182,7 +182,7 @@ pub fn io(t: *Threaded) Io { | ... | @@ -182,7 +182,7 @@ pub fn io(t: *Threaded) Io { |
| 182 | else => fileStatPosix, | 182 | else => fileStatPosix, |
| 183 | }, | 183 | }, |
| 184 | .dirAccess = switch (builtin.os.tag) { | 184 | .dirAccess = switch (builtin.os.tag) { |
| 185 | .windows => @panic("TODO"), | 185 | .windows => dirAccessWindows, |
| 186 | .wasi => dirAccessWasi, | 186 | .wasi => dirAccessWasi, |
| 187 | else => dirAccessPosix, | 187 | else => dirAccessPosix, |
| 188 | }, | 188 | }, |
| ... | @@ -1315,6 +1315,51 @@ fn dirAccessWasi( | ... | @@ -1315,6 +1315,51 @@ fn dirAccessWasi( |
| 1315 | return error.AccessDenied; | 1315 | return error.AccessDenied; |
| 1316 | } | 1316 | } |
| 1317 | 1317 | ||
| 1318 | fn dirAccessWindows( | ||
| 1319 | userdata: ?*anyopaque, | ||
| 1320 | dir: Io.Dir, | ||
| 1321 | sub_path: []const u8, | ||
| 1322 | options: Io.Dir.AccessOptions, | ||
| 1323 | ) Io.Dir.AccessError!void { | ||
| 1324 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | ||
| 1325 | try t.checkCancel(); | ||
| 1326 | |||
| 1327 | _ = options; // TODO | ||
| 1328 | |||
| 1329 | const sub_path_w_array = try windows.sliceToPrefixedFileW(dir.handle, sub_path); | ||
| 1330 | const sub_path_w = sub_path_w_array.span(); | ||
| 1331 | |||
| 1332 | if (sub_path_w[0] == '.' and sub_path_w[1] == 0) return; | ||
| 1333 | if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) return; | ||
| 1334 | |||
| 1335 | const path_len_bytes = std.math.cast(u16, std.mem.sliceTo(sub_path_w, 0).len * 2) orelse | ||
| 1336 | return error.NameTooLong; | ||
| 1337 | var nt_name: windows.UNICODE_STRING = .{ | ||
| 1338 | .Length = path_len_bytes, | ||
| 1339 | .MaximumLength = path_len_bytes, | ||
| 1340 | .Buffer = @constCast(sub_path_w.ptr), | ||
| 1341 | }; | ||
| 1342 | var attr = windows.OBJECT_ATTRIBUTES{ | ||
| 1343 | .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), | ||
| 1344 | .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, | ||
| 1345 | .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. | ||
| 1346 | .ObjectName = &nt_name, | ||
| 1347 | .SecurityDescriptor = null, | ||
| 1348 | .SecurityQualityOfService = null, | ||
| 1349 | }; | ||
| 1350 | var basic_info: windows.FILE_BASIC_INFORMATION = undefined; | ||
| 1351 | switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) { | ||
| 1352 | .SUCCESS => return, | ||
| 1353 | .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, | ||
| 1354 | .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, | ||
| 1355 | .OBJECT_NAME_INVALID => |err| return windows.statusBug(err), | ||
| 1356 | .INVALID_PARAMETER => |err| return windows.statusBug(err), | ||
| 1357 | .ACCESS_DENIED => return error.AccessDenied, | ||
| 1358 | .OBJECT_PATH_SYNTAX_BAD => |err| return windows.statusBug(err), | ||
| 1359 | else => |rc| return windows.unexpectedStatus(rc), | ||
| 1360 | } | ||
| 1361 | } | ||
| 1362 | |||
| 1318 | fn dirCreateFilePosix( | 1363 | fn dirCreateFilePosix( |
| 1319 | userdata: ?*anyopaque, | 1364 | userdata: ?*anyopaque, |
| 1320 | dir: Io.Dir, | 1365 | dir: Io.Dir, |
| ... | @@ -1818,7 +1863,7 @@ fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File | ... | @@ -1818,7 +1863,7 @@ fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File |
| 1818 | var n: DWORD = undefined; | 1863 | var n: DWORD = undefined; |
| 1819 | if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, null) == 0) { | 1864 | if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, null) == 0) { |
| 1820 | switch (windows.GetLastError()) { | 1865 | switch (windows.GetLastError()) { |
| 1821 | .IO_PENDING => unreachable, | 1866 | .IO_PENDING => |err| return windows.statusBug(err), |
| 1822 | .OPERATION_ABORTED => continue, | 1867 | .OPERATION_ABORTED => continue, |
| 1823 | .BROKEN_PIPE => return 0, | 1868 | .BROKEN_PIPE => return 0, |
| 1824 | .HANDLE_EOF => return 0, | 1869 | .HANDLE_EOF => return 0, |
| ... | @@ -1935,7 +1980,7 @@ fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset | ... | @@ -1935,7 +1980,7 @@ fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset |
| 1935 | } else null; | 1980 | } else null; |
| 1936 | if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, overlapped) == 0) { | 1981 | if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, overlapped) == 0) { |
| 1937 | switch (windows.GetLastError()) { | 1982 | switch (windows.GetLastError()) { |
| 1938 | .IO_PENDING => unreachable, | 1983 | .IO_PENDING => |err| return windows.statusBug(err), |
| 1939 | .OPERATION_ABORTED => continue, | 1984 | .OPERATION_ABORTED => continue, |
| 1940 | .BROKEN_PIPE => return 0, | 1985 | .BROKEN_PIPE => return 0, |
| 1941 | .HANDLE_EOF => return 0, | 1986 | .HANDLE_EOF => return 0, |
lib/std/fs.zig+1-1| ... | @@ -263,7 +263,7 @@ pub fn openFileAbsolute(absolute_path: []const u8, flags: File.OpenFlags) File.O | ... | @@ -263,7 +263,7 @@ pub fn openFileAbsolute(absolute_path: []const u8, flags: File.OpenFlags) File.O |
| 263 | 263 | ||
| 264 | /// Same as `openFileAbsolute` but the path parameter is WTF-16-encoded. | 264 | /// Same as `openFileAbsolute` but the path parameter is WTF-16-encoded. |
| 265 | pub fn openFileAbsoluteW(absolute_path_w: []const u16, flags: File.OpenFlags) File.OpenError!File { | 265 | pub fn openFileAbsoluteW(absolute_path_w: []const u16, flags: File.OpenFlags) File.OpenError!File { |
| 266 | assert(path.isAbsoluteWindowsWTF16(absolute_path_w)); | 266 | assert(path.isAbsoluteWindowsWtf16(absolute_path_w)); |
| 267 | return cwd().openFileW(absolute_path_w, flags); | 267 | return cwd().openFileW(absolute_path_w, flags); |
| 268 | } | 268 | } |
| 269 | 269 |
lib/std/fs/path.zig+1-1| ... | @@ -313,7 +313,7 @@ pub fn isAbsoluteWindowsW(path_w: [*:0]const u16) bool { | ... | @@ -313,7 +313,7 @@ pub fn isAbsoluteWindowsW(path_w: [*:0]const u16) bool { |
| 313 | return isAbsoluteWindowsImpl(u16, mem.sliceTo(path_w, 0)); | 313 | return isAbsoluteWindowsImpl(u16, mem.sliceTo(path_w, 0)); |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | pub fn isAbsoluteWindowsWTF16(path: []const u16) bool { | 316 | pub fn isAbsoluteWindowsWtf16(path: []const u16) bool { |
| 317 | return isAbsoluteWindowsImpl(u16, path); | 317 | return isAbsoluteWindowsImpl(u16, path); |
| 318 | } | 318 | } |
| 319 | 319 |
lib/std/os/windows.zig+13-6| ... | @@ -89,7 +89,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN | ... | @@ -89,7 +89,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN |
| 89 | }; | 89 | }; |
| 90 | var attr = OBJECT_ATTRIBUTES{ | 90 | var attr = OBJECT_ATTRIBUTES{ |
| 91 | .Length = @sizeOf(OBJECT_ATTRIBUTES), | 91 | .Length = @sizeOf(OBJECT_ATTRIBUTES), |
| 92 | .RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(sub_path_w)) null else options.dir, | 92 | .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir, |
| 93 | .Attributes = if (options.sa) |ptr| blk: { // Note we do not use OBJ_CASE_INSENSITIVE here. | 93 | .Attributes = if (options.sa) |ptr| blk: { // Note we do not use OBJ_CASE_INSENSITIVE here. |
| 94 | const inherit: ULONG = if (ptr.bInheritHandle == TRUE) OBJ_INHERIT else 0; | 94 | const inherit: ULONG = if (ptr.bInheritHandle == TRUE) OBJ_INHERIT else 0; |
| 95 | break :blk inherit; | 95 | break :blk inherit; |
| ... | @@ -847,7 +847,7 @@ pub fn CreateSymbolicLink( | ... | @@ -847,7 +847,7 @@ pub fn CreateSymbolicLink( |
| 847 | // the C:\ drive. | 847 | // the C:\ drive. |
| 848 | .rooted => break :target_path target_path, | 848 | .rooted => break :target_path target_path, |
| 849 | // Keep relative paths relative, but anything else needs to get NT-prefixed. | 849 | // Keep relative paths relative, but anything else needs to get NT-prefixed. |
| 850 | else => if (!std.fs.path.isAbsoluteWindowsWTF16(target_path)) | 850 | else => if (!std.fs.path.isAbsoluteWindowsWtf16(target_path)) |
| 851 | break :target_path target_path, | 851 | break :target_path target_path, |
| 852 | }, | 852 | }, |
| 853 | // Already an NT path, no need to do anything to it | 853 | // Already an NT path, no need to do anything to it |
| ... | @@ -856,7 +856,7 @@ pub fn CreateSymbolicLink( | ... | @@ -856,7 +856,7 @@ pub fn CreateSymbolicLink( |
| 856 | } | 856 | } |
| 857 | var prefixed_target_path = try wToPrefixedFileW(dir, target_path); | 857 | var prefixed_target_path = try wToPrefixedFileW(dir, target_path); |
| 858 | // We do this after prefixing to ensure that drive-relative paths are treated as absolute | 858 | // We do this after prefixing to ensure that drive-relative paths are treated as absolute |
| 859 | is_target_absolute = std.fs.path.isAbsoluteWindowsWTF16(prefixed_target_path.span()); | 859 | is_target_absolute = std.fs.path.isAbsoluteWindowsWtf16(prefixed_target_path.span()); |
| 860 | break :target_path prefixed_target_path.span(); | 860 | break :target_path prefixed_target_path.span(); |
| 861 | }; | 861 | }; |
| 862 | 862 | ||
| ... | @@ -864,7 +864,7 @@ pub fn CreateSymbolicLink( | ... | @@ -864,7 +864,7 @@ pub fn CreateSymbolicLink( |
| 864 | var buffer: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; | 864 | var buffer: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; |
| 865 | const buf_len = @sizeOf(SYMLINK_DATA) + final_target_path.len * 4; | 865 | const buf_len = @sizeOf(SYMLINK_DATA) + final_target_path.len * 4; |
| 866 | const header_len = @sizeOf(ULONG) + @sizeOf(USHORT) * 2; | 866 | const header_len = @sizeOf(ULONG) + @sizeOf(USHORT) * 2; |
| 867 | const target_is_absolute = std.fs.path.isAbsoluteWindowsWTF16(final_target_path); | 867 | const target_is_absolute = std.fs.path.isAbsoluteWindowsWtf16(final_target_path); |
| 868 | const symlink_data = SYMLINK_DATA{ | 868 | const symlink_data = SYMLINK_DATA{ |
| 869 | .ReparseTag = IO_REPARSE_TAG_SYMLINK, | 869 | .ReparseTag = IO_REPARSE_TAG_SYMLINK, |
| 870 | .ReparseDataLength = @intCast(buf_len - header_len), | 870 | .ReparseDataLength = @intCast(buf_len - header_len), |
| ... | @@ -905,7 +905,7 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLin | ... | @@ -905,7 +905,7 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLin |
| 905 | }; | 905 | }; |
| 906 | var attr = OBJECT_ATTRIBUTES{ | 906 | var attr = OBJECT_ATTRIBUTES{ |
| 907 | .Length = @sizeOf(OBJECT_ATTRIBUTES), | 907 | .Length = @sizeOf(OBJECT_ATTRIBUTES), |
| 908 | .RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(sub_path_w)) null else dir, | 908 | .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir, |
| 909 | .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. | 909 | .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. |
| 910 | .ObjectName = &nt_name, | 910 | .ObjectName = &nt_name, |
| 911 | .SecurityDescriptor = null, | 911 | .SecurityDescriptor = null, |
| ... | @@ -1035,7 +1035,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil | ... | @@ -1035,7 +1035,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil |
| 1035 | 1035 | ||
| 1036 | var attr = OBJECT_ATTRIBUTES{ | 1036 | var attr = OBJECT_ATTRIBUTES{ |
| 1037 | .Length = @sizeOf(OBJECT_ATTRIBUTES), | 1037 | .Length = @sizeOf(OBJECT_ATTRIBUTES), |
| 1038 | .RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(sub_path_w)) null else options.dir, | 1038 | .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir, |
| 1039 | .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. | 1039 | .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. |
| 1040 | .ObjectName = &nt_name, | 1040 | .ObjectName = &nt_name, |
| 1041 | .SecurityDescriptor = null, | 1041 | .SecurityDescriptor = null, |
| ... | @@ -2885,6 +2885,13 @@ pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError { | ... | @@ -2885,6 +2885,13 @@ pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError { |
| 2885 | return error.Unexpected; | 2885 | return error.Unexpected; |
| 2886 | } | 2886 | } |
| 2887 | 2887 | ||
| 2888 | pub fn statusBug(status: NTSTATUS) UnexpectedError { | ||
| 2889 | switch (builtin.mode) { | ||
| 2890 | .Debug => std.debug.panic("programmer bug caused syscall status: {t}", .{status}), | ||
| 2891 | else => return error.Unexpected, | ||
| 2892 | } | ||
| 2893 | } | ||
| 2894 | |||
| 2888 | pub const Win32Error = @import("windows/win32error.zig").Win32Error; | 2895 | pub const Win32Error = @import("windows/win32error.zig").Win32Error; |
| 2889 | pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS; | 2896 | pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS; |
| 2890 | pub const LANG = @import("windows/lang.zig"); | 2897 | pub const LANG = @import("windows/lang.zig"); |
lib/std/posix.zig+2-2| ... | @@ -2617,7 +2617,7 @@ pub fn renameatW( | ... | @@ -2617,7 +2617,7 @@ pub fn renameatW( |
| 2617 | if (ReplaceIfExists == windows.TRUE) flags |= windows.FILE_RENAME_REPLACE_IF_EXISTS; | 2617 | if (ReplaceIfExists == windows.TRUE) flags |= windows.FILE_RENAME_REPLACE_IF_EXISTS; |
| 2618 | rename_info.* = .{ | 2618 | rename_info.* = .{ |
| 2619 | .Flags = flags, | 2619 | .Flags = flags, |
| 2620 | .RootDirectory = if (fs.path.isAbsoluteWindowsWTF16(new_path_w)) null else new_dir_fd, | 2620 | .RootDirectory = if (fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd, |
| 2621 | .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong | 2621 | .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong |
| 2622 | .FileName = undefined, | 2622 | .FileName = undefined, |
| 2623 | }; | 2623 | }; |
| ... | @@ -2654,7 +2654,7 @@ pub fn renameatW( | ... | @@ -2654,7 +2654,7 @@ pub fn renameatW( |
| 2654 | 2654 | ||
| 2655 | rename_info.* = .{ | 2655 | rename_info.* = .{ |
| 2656 | .Flags = ReplaceIfExists, | 2656 | .Flags = ReplaceIfExists, |
| 2657 | .RootDirectory = if (fs.path.isAbsoluteWindowsWTF16(new_path_w)) null else new_dir_fd, | 2657 | .RootDirectory = if (fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd, |
| 2658 | .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong | 2658 | .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong |
| 2659 | .FileName = undefined, | 2659 | .FileName = undefined, |
| 2660 | }; | 2660 | }; |
lib/std/start.zig+1-1| ... | @@ -708,7 +708,7 @@ pub inline fn callMain() u8 { | ... | @@ -708,7 +708,7 @@ pub inline fn callMain() u8 { |
| 708 | switch (native_os) { | 708 | switch (native_os) { |
| 709 | .freestanding, .other => {}, | 709 | .freestanding, .other => {}, |
| 710 | else => if (@errorReturnTrace()) |trace| { | 710 | else => if (@errorReturnTrace()) |trace| { |
| 711 | std.debug.dumpStackTrace(trace); | 711 | std.debug.dumpStackTrace(trace.*); |
| 712 | }, | 712 | }, |
| 713 | } | 713 | } |
| 714 | return 1; | 714 | return 1; |