From e1c03d9e8eb52b489d9b47bbe2f12cacac8a999f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 4 Jan 2018 13:48:45 -0500 Subject: self-hosted compiler works on windows * better error message for realpath failing * fix bug in std.io.readFileAllocExtra incorrectly returning error.EndOfStream * implement std.os.selfExePath and std.os.selfExeDirPath for windows --- std/io.zig | 2 +- std/os/index.zig | 51 ++++++++++++++++++++++++++++++++++++------------ std/os/windows/index.zig | 2 ++ 3 files changed, 41 insertions(+), 14 deletions(-) (limited to 'std') diff --git a/std/io.zig b/std/io.zig index 44e5634ae0..9c39a02a8c 100644 --- a/std/io.zig +++ b/std/io.zig @@ -513,7 +513,7 @@ pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len %defer allocator.free(buf); var adapter = FileInStream.init(&file); - %return adapter.stream.readNoEof(buf); + %return adapter.stream.readNoEof(buf[0..size]); return buf; } diff --git a/std/os/index.zig b/std/os/index.zig index f668546a37..96d374503f 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -1544,6 +1544,40 @@ pub fn openSelfExe() -> %io.File { } } +/// Get the path to the current executable. +/// If you only need the directory, use selfExeDirPath. +/// If you only want an open file handle, use openSelfExe. +/// This function may return an error if the current executable +/// was deleted after spawning. +/// Caller owns returned memory. +pub fn selfExePath(allocator: &mem.Allocator) -> %[]u8 { + switch (builtin.os) { + Os.linux => { + @compileError("TODO: selfExePath for linux"); + }, + Os.windows => { + var out_path = %return Buffer.initSize(allocator, 256); + %defer out_path.deinit(); + while (true) { + const dword_len = %return math.cast(windows.DWORD, out_path.len()); + const copied_amt = windows.GetModuleFileNameA(null, out_path.ptr(), dword_len); + if (copied_amt <= 0) { + const err = windows.GetLastError(); + return switch (err) { + else => unexpectedErrorWindows(err), + }; + } + if (copied_amt < out_path.len()) { + out_path.shrink(copied_amt); + return out_path.toOwnedSlice(); + } + %return out_path.resize(out_path.len() * 2); + } + }, + else => @compileError("Unsupported OS"), + } +} + /// Get the directory path that contains the current executable. /// Caller owns returned memory. pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 { @@ -1559,19 +1593,10 @@ pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 { return allocator.shrink(u8, full_exe_path, dir.len); }, Os.windows => { - @panic("TODO windows std.os.selfExeDirPath"); - //buf_resize(out_path, 256); - //for (;;) { - // DWORD copied_amt = GetModuleFileName(nullptr, buf_ptr(out_path), buf_len(out_path)); - // if (copied_amt <= 0) { - // return ErrorFileNotFound; - // } - // if (copied_amt < buf_len(out_path)) { - // buf_resize(out_path, copied_amt); - // return 0; - // } - // buf_resize(out_path, buf_len(out_path) * 2); - //} + const self_exe_path = %return selfExePath(allocator); + %defer allocator.free(self_exe_path); + const dirname = os.path.dirname(self_exe_path); + return allocator.shrink(u8, self_exe_path, dirname.len); }, else => @compileError("unimplemented: std.os.selfExeDirPath for " ++ @tagName(builtin.os)), } diff --git a/std/os/windows/index.zig b/std/os/windows/index.zig index 0ce3794cdc..d460e94f64 100644 --- a/std/os/windows/index.zig +++ b/std/os/windows/index.zig @@ -48,6 +48,8 @@ pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCo pub extern "kernel32" stdcallcc fn GetFileSizeEx(hFile: HANDLE, lpFileSize: &LARGE_INTEGER) -> BOOL; +pub extern "kernel32" stdcallcc fn GetModuleFileNameA(hModule: ?HMODULE, lpFilename: LPSTR, nSize: DWORD) -> DWORD; + pub extern "kernel32" stdcallcc fn GetLastError() -> DWORD; pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(in_hFile: HANDLE, -- cgit v1.2.3