diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 4f2fe5e7b1..93d4cc1b42 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -182,7 +182,7 @@ pub fn io(t: *Threaded) Io { else => fileStatPosix, }, .dirAccess = switch (builtin.os.tag) { - .windows => @panic("TODO"), + .windows => dirAccessWindows, .wasi => dirAccessWasi, else => dirAccessPosix, }, @@ -1315,6 +1315,51 @@ fn dirAccessWasi( return error.AccessDenied; } +fn dirAccessWindows( + userdata: ?*anyopaque, + dir: Io.Dir, + sub_path: []const u8, + options: Io.Dir.AccessOptions, +) Io.Dir.AccessError!void { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + try t.checkCancel(); + + _ = options; // TODO + + const sub_path_w_array = try windows.sliceToPrefixedFileW(dir.handle, sub_path); + const sub_path_w = sub_path_w_array.span(); + + if (sub_path_w[0] == '.' and sub_path_w[1] == 0) return; + if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) return; + + const path_len_bytes = std.math.cast(u16, std.mem.sliceTo(sub_path_w, 0).len * 2) orelse + return error.NameTooLong; + var nt_name: windows.UNICODE_STRING = .{ + .Length = path_len_bytes, + .MaximumLength = path_len_bytes, + .Buffer = @constCast(sub_path_w.ptr), + }; + var attr = windows.OBJECT_ATTRIBUTES{ + .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), + .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, + .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }; + var basic_info: windows.FILE_BASIC_INFORMATION = undefined; + switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) { + .SUCCESS => return, + .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, + .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, + .OBJECT_NAME_INVALID => |err| return windows.statusBug(err), + .INVALID_PARAMETER => |err| return windows.statusBug(err), + .ACCESS_DENIED => return error.AccessDenied, + .OBJECT_PATH_SYNTAX_BAD => |err| return windows.statusBug(err), + else => |rc| return windows.unexpectedStatus(rc), + } +} + fn dirCreateFilePosix( userdata: ?*anyopaque, dir: Io.Dir, @@ -1818,7 +1863,7 @@ fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File var n: DWORD = undefined; if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, null) == 0) { switch (windows.GetLastError()) { - .IO_PENDING => unreachable, + .IO_PENDING => |err| return windows.statusBug(err), .OPERATION_ABORTED => continue, .BROKEN_PIPE => return 0, .HANDLE_EOF => return 0, @@ -1935,7 +1980,7 @@ fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset } else null; if (windows.kernel32.ReadFile(file.handle, buffer.ptr, want_read_count, &n, overlapped) == 0) { switch (windows.GetLastError()) { - .IO_PENDING => unreachable, + .IO_PENDING => |err| return windows.statusBug(err), .OPERATION_ABORTED => continue, .BROKEN_PIPE => return 0, .HANDLE_EOF => return 0, diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 7fae26cb62..01188e29a3 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -263,7 +263,7 @@ pub fn openFileAbsolute(absolute_path: []const u8, flags: File.OpenFlags) File.O /// Same as `openFileAbsolute` but the path parameter is WTF-16-encoded. pub fn openFileAbsoluteW(absolute_path_w: []const u16, flags: File.OpenFlags) File.OpenError!File { - assert(path.isAbsoluteWindowsWTF16(absolute_path_w)); + assert(path.isAbsoluteWindowsWtf16(absolute_path_w)); return cwd().openFileW(absolute_path_w, flags); } diff --git a/lib/std/fs/path.zig b/lib/std/fs/path.zig index ff69c21cdd..966c481c23 100644 --- a/lib/std/fs/path.zig +++ b/lib/std/fs/path.zig @@ -313,7 +313,7 @@ pub fn isAbsoluteWindowsW(path_w: [*:0]const u16) bool { return isAbsoluteWindowsImpl(u16, mem.sliceTo(path_w, 0)); } -pub fn isAbsoluteWindowsWTF16(path: []const u16) bool { +pub fn isAbsoluteWindowsWtf16(path: []const u16) bool { return isAbsoluteWindowsImpl(u16, path); } diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index fd6e2926c9..f1649fafc1 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -89,7 +89,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN }; var attr = OBJECT_ATTRIBUTES{ .Length = @sizeOf(OBJECT_ATTRIBUTES), - .RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(sub_path_w)) null else options.dir, + .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir, .Attributes = if (options.sa) |ptr| blk: { // Note we do not use OBJ_CASE_INSENSITIVE here. const inherit: ULONG = if (ptr.bInheritHandle == TRUE) OBJ_INHERIT else 0; break :blk inherit; @@ -847,7 +847,7 @@ pub fn CreateSymbolicLink( // the C:\ drive. .rooted => break :target_path target_path, // Keep relative paths relative, but anything else needs to get NT-prefixed. - else => if (!std.fs.path.isAbsoluteWindowsWTF16(target_path)) + else => if (!std.fs.path.isAbsoluteWindowsWtf16(target_path)) break :target_path target_path, }, // Already an NT path, no need to do anything to it @@ -856,7 +856,7 @@ pub fn CreateSymbolicLink( } var prefixed_target_path = try wToPrefixedFileW(dir, target_path); // We do this after prefixing to ensure that drive-relative paths are treated as absolute - is_target_absolute = std.fs.path.isAbsoluteWindowsWTF16(prefixed_target_path.span()); + is_target_absolute = std.fs.path.isAbsoluteWindowsWtf16(prefixed_target_path.span()); break :target_path prefixed_target_path.span(); }; @@ -864,7 +864,7 @@ pub fn CreateSymbolicLink( var buffer: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 = undefined; const buf_len = @sizeOf(SYMLINK_DATA) + final_target_path.len * 4; const header_len = @sizeOf(ULONG) + @sizeOf(USHORT) * 2; - const target_is_absolute = std.fs.path.isAbsoluteWindowsWTF16(final_target_path); + const target_is_absolute = std.fs.path.isAbsoluteWindowsWtf16(final_target_path); const symlink_data = SYMLINK_DATA{ .ReparseTag = IO_REPARSE_TAG_SYMLINK, .ReparseDataLength = @intCast(buf_len - header_len), @@ -905,7 +905,7 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLin }; var attr = OBJECT_ATTRIBUTES{ .Length = @sizeOf(OBJECT_ATTRIBUTES), - .RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(sub_path_w)) null else dir, + .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir, .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. .ObjectName = &nt_name, .SecurityDescriptor = null, @@ -1035,7 +1035,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil var attr = OBJECT_ATTRIBUTES{ .Length = @sizeOf(OBJECT_ATTRIBUTES), - .RootDirectory = if (std.fs.path.isAbsoluteWindowsWTF16(sub_path_w)) null else options.dir, + .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir, .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. .ObjectName = &nt_name, .SecurityDescriptor = null, @@ -2885,6 +2885,13 @@ pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError { return error.Unexpected; } +pub fn statusBug(status: NTSTATUS) UnexpectedError { + switch (builtin.mode) { + .Debug => std.debug.panic("programmer bug caused syscall status: {t}", .{status}), + else => return error.Unexpected, + } +} + pub const Win32Error = @import("windows/win32error.zig").Win32Error; pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS; pub const LANG = @import("windows/lang.zig"); diff --git a/lib/std/posix.zig b/lib/std/posix.zig index fd4958c5e8..a186ac7074 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -2617,7 +2617,7 @@ pub fn renameatW( if (ReplaceIfExists == windows.TRUE) flags |= windows.FILE_RENAME_REPLACE_IF_EXISTS; rename_info.* = .{ .Flags = flags, - .RootDirectory = if (fs.path.isAbsoluteWindowsWTF16(new_path_w)) null else new_dir_fd, + .RootDirectory = if (fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd, .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong .FileName = undefined, }; @@ -2654,7 +2654,7 @@ pub fn renameatW( rename_info.* = .{ .Flags = ReplaceIfExists, - .RootDirectory = if (fs.path.isAbsoluteWindowsWTF16(new_path_w)) null else new_dir_fd, + .RootDirectory = if (fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd, .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong .FileName = undefined, }; diff --git a/lib/std/start.zig b/lib/std/start.zig index 09c1f3b5c4..4063b2027b 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -708,7 +708,7 @@ pub inline fn callMain() u8 { switch (native_os) { .freestanding, .other => {}, else => if (@errorReturnTrace()) |trace| { - std.debug.dumpStackTrace(trace); + std.debug.dumpStackTrace(trace.*); }, } return 1;