authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-21 18:51:12-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-21 18:51:12-05:00
logbf1cbebea1fd846c982e568ef4f013dfaf232e3e
treee7e95cf078d70e2f88071ef55d0f4197faf7bcd6
parentcd37c1a377483154e82dce47b10ab0c54264f4e9

improve std.fs.selfExePath and related functions on Windows


2 files changed, 26 insertions(+), 9 deletions(-)

lib/std/fs.zig+8-8
...@@ -1243,9 +1243,9 @@ pub fn openSelfExe() OpenSelfExeError!File {...@@ -1243,9 +1243,9 @@ pub fn openSelfExe() OpenSelfExeError!File {
1243 return File.openReadC(c"/proc/self/exe");1243 return File.openReadC(c"/proc/self/exe");
1244 }1244 }
1245 if (builtin.os == .windows) {1245 if (builtin.os == .windows) {
1246 var buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;1246 const wide_slice = selfExePathW();
1247 const wide_slice = try selfExePathW(&buf);1247 const prefixed_path_w = try os.windows.wToPrefixedFileW(wide_slice);
1248 return File.openReadW(wide_slice.ptr);1248 return Dir.cwd().openReadW(&prefixed_path_w);
1249 }1249 }
1250 var buf: [MAX_PATH_BYTES]u8 = undefined;1250 var buf: [MAX_PATH_BYTES]u8 = undefined;
1251 const self_exe_path = try selfExePath(&buf);1251 const self_exe_path = try selfExePath(&buf);
...@@ -1296,8 +1296,7 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {...@@ -1296,8 +1296,7 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
1296 return mem.toSlice(u8, out_buffer);1296 return mem.toSlice(u8, out_buffer);
1297 },1297 },
1298 .windows => {1298 .windows => {
1299 var utf16le_buf: [os.windows.PATH_MAX_WIDE]u16 = undefined;1299 const utf16le_slice = selfExePathW();
1300 const utf16le_slice = try selfExePathW(&utf16le_buf);
1301 // Trust that Windows gives us valid UTF-16LE.1300 // Trust that Windows gives us valid UTF-16LE.
1302 const end_index = std.unicode.utf16leToUtf8(out_buffer, utf16le_slice) catch unreachable;1301 const end_index = std.unicode.utf16leToUtf8(out_buffer, utf16le_slice) catch unreachable;
1303 return out_buffer[0..end_index];1302 return out_buffer[0..end_index];
...@@ -1306,9 +1305,10 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {...@@ -1306,9 +1305,10 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
1306 }1305 }
1307}1306}
13081307
1309/// Same as `selfExePath` except the result is UTF16LE-encoded.1308/// The result is UTF16LE-encoded.
1310pub fn selfExePathW(out_buffer: *[os.windows.PATH_MAX_WIDE]u16) SelfExePathError![]u16 {1309pub fn selfExePathW() []const u16 {
1311 return os.windows.GetModuleFileNameW(null, out_buffer, out_buffer.len);1310 const image_path_name = &os.windows.peb().ProcessParameters.ImagePathName;
1311 return mem.toSliceConst(u16, image_path_name.Buffer);
1312}1312}
13131313
1314/// `selfExeDirPath` except allocates the result on the heap.1314/// `selfExeDirPath` except allocates the result on the heap.
lib/std/os/windows.zig+18-1
...@@ -927,6 +927,24 @@ pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE + 1]u16 {...@@ -927,6 +927,24 @@ pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE + 1]u16 {
927 return sliceToPrefixedSuffixedFileW(s, [_]u16{0});927 return sliceToPrefixedSuffixedFileW(s, [_]u16{0});
928}928}
929929
930/// Assumes an absolute path.
931pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE + 1]u16 {
932 // TODO https://github.com/ziglang/zig/issues/2765
933 var result: [PATH_MAX_WIDE + 1]u16 = undefined;
934
935 const start_index = if (mem.startsWith(u16, s, [_]u16{'\\', '?'})) 0 else blk: {
936 const prefix = [_]u16{ '\\', '?', '?', '\\' };
937 mem.copy(u16, result[0..], prefix);
938 break :blk prefix.len;
939 };
940 const end_index = start_index + s.len;
941 if (end_index + 1 > result.len) return error.NameTooLong;
942 mem.copy(u16, result[start_index..], s);
943 result[end_index] = 0;
944 return result;
945
946}
947
930pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len]u16 {948pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len]u16 {
931 // TODO https://github.com/ziglang/zig/issues/2765949 // TODO https://github.com/ziglang/zig/issues/2765
932 var result: [PATH_MAX_WIDE + suffix.len]u16 = undefined;950 var result: [PATH_MAX_WIDE + suffix.len]u16 = undefined;
...@@ -948,7 +966,6 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)...@@ -948,7 +966,6 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
948 break :blk prefix.len;966 break :blk prefix.len;
949 };967 };
950 const end_index = start_index + try std.unicode.utf8ToUtf16Le(result[start_index..], s);968 const end_index = start_index + try std.unicode.utf8ToUtf16Le(result[start_index..], s);
951 assert(end_index <= result.len);
952 if (end_index + suffix.len > result.len) return error.NameTooLong;969 if (end_index + suffix.len > result.len) return error.NameTooLong;
953 mem.copy(u16, result[end_index..], suffix);970 mem.copy(u16, result[end_index..], suffix);
954 return result;971 return result;