diff --git a/std/c.zig b/std/c.zig index bffb8a9bd3..e041a638c1 100644 --- a/std/c.zig +++ b/std/c.zig @@ -13,9 +13,9 @@ pub use switch (builtin.os) { else => struct {}, }; -pub fn getErrno(rc: var) u12 { +pub fn getErrno(rc: var) u16 { if (rc == -1) { - return @intCast(u12, _errno().*); + return @intCast(u16, _errno().*); } else { return 0; } diff --git a/std/child_process.zig b/std/child_process.zig index e4588d2ec9..1268f72c37 100644 --- a/std/child_process.zig +++ b/std/child_process.zig @@ -412,7 +412,7 @@ pub const ChildProcess = struct { const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); const nul_handle = if (any_ignore) blk: { - break :blk try windows.CreateFile("NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ, windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL); + break :blk try windows.CreateFile("NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ, null, windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL, null); } else blk: { break :blk undefined; }; diff --git a/std/event/fs.zig b/std/event/fs.zig index b7afe7070c..55731a607c 100644 --- a/std/event/fs.zig +++ b/std/event/fs.zig @@ -147,14 +147,14 @@ pub async fn pwriteWindows(loop: *Loop, fd: fd_t, data: []const u8, offset: u64) errdefer loop.finishOneEvent(); errdefer { - _ = windows.CancelIoEx(fd, &resume_node.base.overlapped); + _ = windows.kernel32.CancelIoEx(fd, &resume_node.base.overlapped); } suspend { - _ = windows.WriteFile(fd, data.ptr, @intCast(windows.DWORD, data.len), null, &resume_node.base.overlapped); + _ = windows.kernel32.WriteFile(fd, data.ptr, @intCast(windows.DWORD, data.len), null, &resume_node.base.overlapped); } var bytes_transferred: windows.DWORD = undefined; - if (windows.GetOverlappedResult(fd, &resume_node.base.overlapped, &bytes_transferred, windows.FALSE) == 0) { - switch (windows.GetLastError()) { + if (windows.kernel32.GetOverlappedResult(fd, &resume_node.base.overlapped, &bytes_transferred, windows.FALSE) == 0) { + switch (windows.kernel32.GetLastError()) { windows.ERROR.IO_PENDING => unreachable, windows.ERROR.INVALID_USER_BUFFER => return error.SystemResources, windows.ERROR.NOT_ENOUGH_MEMORY => return error.SystemResources, @@ -247,7 +247,7 @@ pub async fn preadv(loop: *Loop, fd: fd_t, data: []const []u8, offset: usize) PR } /// data must outlive the returned promise -pub async fn preadvWindows(loop: *Loop, fd: fd_t, data: []const []u8, offset: u64) os.WindowsReadError!usize { +pub async fn preadvWindows(loop: *Loop, fd: fd_t, data: []const []u8, offset: u64) !usize { assert(data.len != 0); if (data.len == 1) return await (async preadWindows(loop, fd, data[0], offset) catch unreachable); @@ -291,19 +291,19 @@ pub async fn preadWindows(loop: *Loop, fd: fd_t, data: []u8, offset: u64) !usize }, }; // TODO only call create io completion port once per fd - _ = windows.CreateIoCompletionPort(fd, loop.os_data.io_port, undefined, undefined); + _ = windows.CreateIoCompletionPort(fd, loop.os_data.io_port, undefined, undefined) catch undefined; loop.beginOneEvent(); errdefer loop.finishOneEvent(); errdefer { - _ = windows.CancelIoEx(fd, &resume_node.base.overlapped); + _ = windows.kernel32.CancelIoEx(fd, &resume_node.base.overlapped); } suspend { - _ = windows.ReadFile(fd, data.ptr, @intCast(windows.DWORD, data.len), null, &resume_node.base.overlapped); + _ = windows.kernel32.ReadFile(fd, data.ptr, @intCast(windows.DWORD, data.len), null, &resume_node.base.overlapped); } var bytes_transferred: windows.DWORD = undefined; - if (windows.GetOverlappedResult(fd, &resume_node.base.overlapped, &bytes_transferred, windows.FALSE) == 0) { - switch (windows.GetLastError()) { + if (windows.kernel32.GetOverlappedResult(fd, &resume_node.base.overlapped, &bytes_transferred, windows.FALSE) == 0) { + switch (windows.kernel32.GetLastError()) { windows.ERROR.IO_PENDING => unreachable, windows.ERROR.OPERATION_ABORTED => return error.OperationAborted, windows.ERROR.BROKEN_PIPE => return error.BrokenPipe, @@ -408,12 +408,14 @@ pub async fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t { return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable); }, - builtin.Os.windows => return os.windowsOpen( + builtin.Os.windows => return windows.CreateFile( path, windows.GENERIC_READ, windows.FILE_SHARE_READ, + null, windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL | windows.FILE_FLAG_OVERLAPPED, + null, ), else => @compileError("Unsupported OS"), @@ -437,12 +439,14 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File. const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC; return await (async openPosix(loop, path, flags, File.default_mode) catch unreachable); }, - builtin.Os.windows => return os.windowsOpen( + builtin.Os.windows => return windows.CreateFile( path, windows.GENERIC_WRITE, windows.FILE_SHARE_WRITE | windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE, + null, windows.CREATE_ALWAYS, windows.FILE_ATTRIBUTE_NORMAL | windows.FILE_FLAG_OVERLAPPED, + null, ), else => @compileError("Unsupported OS"), } @@ -460,12 +464,14 @@ pub async fn openReadWrite( return await (async openPosix(loop, path, flags, mode) catch unreachable); }, - builtin.Os.windows => return os.windowsOpen( + builtin.Os.windows => return windows.CreateFile( path, windows.GENERIC_WRITE | windows.GENERIC_READ, windows.FILE_SHARE_WRITE | windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE, + null, windows.OPEN_ALWAYS, windows.FILE_ATTRIBUTE_NORMAL | windows.FILE_FLAG_OVERLAPPED, + null, ), else => @compileError("Unsupported OS"), @@ -622,12 +628,14 @@ pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8, } async fn writeFileWindows(loop: *Loop, path: []const u8, contents: []const u8) !void { - const handle = try os.windowsOpen( + const handle = try windows.CreateFile( path, windows.GENERIC_WRITE, windows.FILE_SHARE_WRITE | windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE, + null, windows.CREATE_ALWAYS, windows.FILE_ATTRIBUTE_NORMAL | windows.FILE_FLAG_OVERLAPPED, + null, ); defer os.close(handle); @@ -1028,7 +1036,7 @@ pub fn Watch(comptime V: type) type { defer if (!basename_utf16le_null_consumed) self.channel.loop.allocator.free(basename_utf16le_null); const basename_utf16le_no_null = basename_utf16le_null[0 .. basename_utf16le_null.len - 1]; - const dir_handle = windows.CreateFileW( + const dir_handle = try windows.CreateFileW( dirname_utf16le.ptr, windows.FILE_LIST_DIRECTORY, windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE | windows.FILE_SHARE_WRITE, @@ -1037,15 +1045,8 @@ pub fn Watch(comptime V: type) type { windows.FILE_FLAG_BACKUP_SEMANTICS | windows.FILE_FLAG_OVERLAPPED, null, ); - if (dir_handle == windows.INVALID_HANDLE_VALUE) { - switch (windows.GetLastError()) { - windows.ERROR.FILE_NOT_FOUND => return error.FileNotFound, - windows.ERROR.PATH_NOT_FOUND => return error.FileNotFound, - else => |err| return windows.unexpectedError(err), - } - } var dir_handle_consumed = false; - defer if (!dir_handle_consumed) os.close(dir_handle); + defer if (!dir_handle_consumed) windows.CloseHandle(dir_handle); const held = await (async self.os_data.table_lock.acquire() catch unreachable); defer held.release(); @@ -1124,7 +1125,7 @@ pub fn Watch(comptime V: type) type { var event_buf: [4096]u8 align(@alignOf(windows.FILE_NOTIFY_INFORMATION)) = undefined; // TODO handle this error not in the channel but in the setup - _ = os.windowsCreateIoCompletionPort( + _ = windows.CreateIoCompletionPort( dir_handle, self.channel.loop.os_data.io_port, undefined, @@ -1140,10 +1141,10 @@ pub fn Watch(comptime V: type) type { self.channel.loop.beginOneEvent(); errdefer self.channel.loop.finishOneEvent(); errdefer { - _ = windows.CancelIoEx(dir_handle, &resume_node.base.overlapped); + _ = windows.kernel32.CancelIoEx(dir_handle, &resume_node.base.overlapped); } suspend { - _ = windows.ReadDirectoryChangesW( + _ = windows.kernel32.ReadDirectoryChangesW( dir_handle, &event_buf, @intCast(windows.DWORD, event_buf.len), @@ -1159,8 +1160,8 @@ pub fn Watch(comptime V: type) type { } } var bytes_transferred: windows.DWORD = undefined; - if (windows.GetOverlappedResult(dir_handle, &resume_node.base.overlapped, &bytes_transferred, windows.FALSE) == 0) { - const err = switch (windows.GetLastError()) { + if (windows.kernel32.GetOverlappedResult(dir_handle, &resume_node.base.overlapped, &bytes_transferred, windows.FALSE) == 0) { + const err = switch (windows.kernel32.GetLastError()) { else => |err| windows.unexpectedError(err), }; await (async self.channel.put(err) catch unreachable); diff --git a/std/fs/file.zig b/std/fs/file.zig index 7cb722292c..589927b823 100644 --- a/std/fs/file.zig +++ b/std/fs/file.zig @@ -27,7 +27,7 @@ pub const File = struct { /// Call close to clean up. pub fn openRead(path: []const u8) OpenError!File { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { const path_w = try windows.sliceToPrefixedFileW(path); return openReadW(&path_w); } @@ -37,7 +37,7 @@ pub const File = struct { /// `openRead` except with a null terminated path pub fn openReadC(path: [*]const u8) OpenError!File { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { const path_w = try windows.cStrToPrefixedFileW(path); return openReadW(&path_w); } @@ -52,8 +52,10 @@ pub const File = struct { path_w, windows.GENERIC_READ, windows.FILE_SHARE_READ, + null, windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL, + null, ); return openHandle(handle); } @@ -67,7 +69,7 @@ pub const File = struct { /// If a file already exists in the destination it will be truncated. /// Call close to clean up. pub fn openWriteMode(path: []const u8, file_mode: Mode) OpenError!File { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { const path_w = try windows.sliceToPrefixedFileW(path); return openWriteModeW(&path_w, file_mode); } @@ -77,7 +79,7 @@ pub const File = struct { /// Same as `openWriteMode` except `path` is null-terminated. pub fn openWriteModeC(path: [*]const u8, file_mode: Mode) OpenError!File { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { const path_w = try windows.cStrToPrefixedFileW(path); return openWriteModeW(&path_w, file_mode); } @@ -92,8 +94,10 @@ pub const File = struct { path_w, windows.GENERIC_WRITE, windows.FILE_SHARE_WRITE | windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE, + null, windows.CREATE_ALWAYS, windows.FILE_ATTRIBUTE_NORMAL, + null, ); return openHandle(handle); } @@ -102,7 +106,7 @@ pub const File = struct { /// If a file already exists in the destination this returns OpenError.PathAlreadyExists /// Call close to clean up. pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { const path_w = try windows.sliceToPrefixedFileW(path); return openWriteNoClobberW(&path_w, file_mode); } @@ -111,7 +115,7 @@ pub const File = struct { } pub fn openWriteNoClobberC(path: [*]const u8, file_mode: Mode) OpenError!File { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { const path_w = try windows.cStrToPrefixedFileW(path); return openWriteNoClobberW(&path_w, file_mode); } @@ -125,8 +129,10 @@ pub const File = struct { path_w, windows.GENERIC_WRITE, windows.FILE_SHARE_WRITE | windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE, + null, windows.CREATE_NEW, windows.FILE_ATTRIBUTE_NORMAL, + null, ); return openHandle(handle); } @@ -198,7 +204,7 @@ pub const File = struct { } pub fn getEndPos(self: File) GetPosError!u64 { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { return windows.GetFileSizeEx(self.handle); } const stat = try os.fstat(self.handle); @@ -208,7 +214,7 @@ pub const File = struct { pub const ModeError = os.FStatError; pub fn mode(self: File) ModeError!Mode { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { return {}; } const stat = try os.fstat(self.handle); diff --git a/std/os.zig b/std/os.zig index a181f58ac2..58df5aa067 100644 --- a/std/os.zig +++ b/std/os.zig @@ -70,7 +70,7 @@ pub const errno = system.getErrno; /// must call `fsync` before `close`. /// Note: The Zig standard library does not support POSIX thread cancellation. pub fn close(fd: fd_t) void { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { return windows.CloseHandle(fd); } if (wasi.is_the_target) { @@ -236,7 +236,7 @@ pub const ReadError = error{ /// This function is for blocking file descriptors only. For non-blocking, see /// `readAsync`. pub fn read(fd: fd_t, buf: []u8) ReadError!usize { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { return windows.ReadFile(fd, buf); } @@ -363,7 +363,7 @@ pub const WriteError = error{ /// This function is for blocking file descriptors only. For non-blocking, see /// `writeAsync`. pub fn write(fd: fd_t, bytes: []const u8) WriteError!void { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { return windows.WriteFile(fd, bytes); } @@ -1736,7 +1736,7 @@ pub const FStatError = error{ pub fn fstat(fd: fd_t) FStatError!Stat { var stat: Stat = undefined; if (darwin.is_the_target) { - switch (errno(system.@"fstat$INODE64"(fd, &stat))) { + switch (darwin.getErrno(darwin.@"fstat$INODE64"(fd, &stat))) { 0 => return stat, EBADF => unreachable, // Always a race condition. ENOMEM => return error.SystemResources, @@ -2265,7 +2265,7 @@ pub const RealPathError = error{ /// The return value is a slice of `out_buffer`, but not necessarily from the beginning. /// See also `realpathC` and `realpathW`. pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { const pathname_w = try windows.sliceToPrefixedFileW(pathname); return realpathW(&pathname_w, out_buffer); } @@ -2275,12 +2275,12 @@ pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathE /// Same as `realpath` except `pathname` is null-terminated. pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { - if (windows.is_the_target and !builtin.link_libc) { + if (windows.is_the_target) { const pathname_w = try windows.cStrToPrefixedFileW(pathname); return realpathW(&pathname_w, out_buffer); } if (linux.is_the_target and !builtin.link_libc) { - const fd = try openC(pathname, O_PATH | O_NONBLOCK | O_CLOEXEC, 0); + const fd = try openC(pathname, linux.O_PATH | linux.O_NONBLOCK | linux.O_CLOEXEC, 0); defer close(fd); var procfs_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined; @@ -2310,8 +2310,10 @@ pub fn realpathW(pathname: [*]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPa pathname, windows.GENERIC_READ, windows.FILE_SHARE_READ, + null, windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL, + null, ); defer windows.CloseHandle(h_file); diff --git a/std/os/bits/windows.zig b/std/os/bits/windows.zig index e4ea450002..a242113ba0 100644 --- a/std/os/bits/windows.zig +++ b/std/os/bits/windows.zig @@ -5,6 +5,8 @@ use @import("../windows/bits.zig"); pub const fd_t = HANDLE; pub const pid_t = HANDLE; +pub const PATH_MAX = 260; + pub const time_t = c_longlong; pub const timespec = extern struct { @@ -153,10 +155,13 @@ pub const ETIME = 137; pub const ETIMEDOUT = 138; pub const ETXTBSY = 139; pub const EWOULDBLOCK = 140; +pub const EDQUOT = 10069; + +pub const F_OK = 0; // These are workarounds for "use of undeclared identifier" compile errors // TODO make the compiler even more lazy. don't emit "use of undeclared identifier" errors // for if branches that aren't taken. pub const SIGKILL = @compileError("Windows libc does not have this"); -pub const EDQUOT = @compileError("Windows libc does not have this"); -pub const F_OK = 0; + + diff --git a/std/os/windows.zig b/std/os/windows.zig index 07758bd195..526ac1cfd6 100644 --- a/std/os/windows.zig +++ b/std/os/windows.zig @@ -48,21 +48,25 @@ pub fn CreateFile( file_path: []const u8, desired_access: DWORD, share_mode: DWORD, + lpSecurityAttributes: ?LPSECURITY_ATTRIBUTES, creation_disposition: DWORD, flags_and_attrs: DWORD, + hTemplateFile: ?HANDLE, ) CreateFileError!HANDLE { const file_path_w = try sliceToPrefixedFileW(file_path); - return CreateFileW(&file_path_w, desired_access, share_mode, creation_disposition, flags_and_attrs); + return CreateFileW(&file_path_w, desired_access, share_mode, lpSecurityAttributes, creation_disposition, flags_and_attrs, hTemplateFile); } pub fn CreateFileW( file_path_w: [*]const u16, desired_access: DWORD, share_mode: DWORD, + lpSecurityAttributes: ?LPSECURITY_ATTRIBUTES, creation_disposition: DWORD, flags_and_attrs: DWORD, + hTemplateFile: ?HANDLE, ) CreateFileError!HANDLE { - const result = kernel32.CreateFileW(file_path_w, desired_access, share_mode, null, creation_disposition, flags_and_attrs, null); + const result = kernel32.CreateFileW(file_path_w, desired_access, share_mode, lpSecurityAttributes, creation_disposition, flags_and_attrs, hTemplateFile); if (result == INVALID_HANDLE_VALUE) { switch (kernel32.GetLastError()) {