Commit 86bb7e5984

Andrew Kelley <andrew@ziglang.org>
2019-05-27 21:34:46
fixes for windows to build self hosted compiler
1 parent 5de07ab
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);
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);
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;
+
+
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()) {
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;
     }
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;
         };
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);