authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2023-08-19 12:48:51-07:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2023-08-19 17:48:18-07:00
log2c2ecd624ad6d85d005f4728f834c0e3377f8f99
treeff17bff644b5eac7243df227c51fb78547b60d35
parent7ef1eb1c27754cb0349fdc10db1f02ff2dddd99b

fs.selfExePath: Make the Windows implementation follow symlinks

Before, selfExePath would be the path of the symlink on Windows instead of the path of what the symlink points to. This deprecates fs.selfExePathW since it does not provide a separate use-case over selfExePath (before, the W version could return [:0]u16 directly) Fixes #16670

1 files changed, 16 insertions(+), 12 deletions(-)

lib/std/fs.zig+16-12
......@@ -2949,8 +2949,12 @@ pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File {
29492949 return openFileAbsoluteZ("/proc/self/exe", flags);
29502950 }
29512951 if (builtin.os.tag == .windows) {
2952 const wide_slice = selfExePathW();
2953 const prefixed_path_w = try os.windows.wToPrefixedFileW(null, wide_slice);
2952 // If ImagePathName is a symlink, then it will contain the path of the symlink,
2953 // not the path that the symlink points to. However, because we are opening
2954 // the file, we can let the openFileW call follow the symlink for us.
2955 const image_path_unicode_string = &os.windows.peb().ProcessParameters.ImagePathName;
2956 const image_path_name = image_path_unicode_string.Buffer[0 .. image_path_unicode_string.Length / 2 :0];
2957 const prefixed_path_w = try os.windows.wToPrefixedFileW(null, image_path_name);
29542958 return cwd().openFileW(prefixed_path_w.span(), flags);
29552959 }
29562960 // Use of MAX_PATH_BYTES here is valid as the resulting path is immediately
......@@ -2977,7 +2981,7 @@ pub fn selfExePathAlloc(allocator: Allocator) ![]u8 {
29772981 return allocator.dupe(u8, try selfExePath(&buf));
29782982}
29792983
2980/// Get the path to the current executable.
2984/// Get the path to the current executable. Follows symlinks.
29812985/// If you only need the directory, use selfExeDirPath.
29822986/// If you only want an open file handle, use openSelfExe.
29832987/// This function may return an error if the current executable
......@@ -3060,21 +3064,21 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
30603064 return error.FileNotFound;
30613065 },
30623066 .windows => {
3063 const utf16le_slice = selfExePathW();
3064 // Trust that Windows gives us valid UTF-16LE.
3065 const end_index = std.unicode.utf16leToUtf8(out_buffer, utf16le_slice) catch unreachable;
3066 return out_buffer[0..end_index];
3067 const image_path_unicode_string = &os.windows.peb().ProcessParameters.ImagePathName;
3068 const image_path_name = image_path_unicode_string.Buffer[0 .. image_path_unicode_string.Length / 2 :0];
3069
3070 // If ImagePathName is a symlink, then it will contain the path of the
3071 // symlink, not the path that the symlink points to. We want the path
3072 // that the symlink points to, though, so we need to get the realpath.
3073 const pathname_w = try os.windows.wToPrefixedFileW(null, image_path_name);
3074 return std.fs.cwd().realpathW(pathname_w.span(), out_buffer);
30673075 },
30683076 .wasi => @compileError("std.fs.selfExePath not supported for WASI. Use std.fs.selfExePathAlloc instead."),
30693077 else => @compileError("std.fs.selfExePath not supported for this target"),
30703078 }
30713079}
30723080
3073/// The result is UTF16LE-encoded.
3074pub fn selfExePathW() [:0]const u16 {
3075 const image_path_name = &os.windows.peb().ProcessParameters.ImagePathName;
3076 return image_path_name.Buffer[0 .. image_path_name.Length / 2 :0];
3077}
3081pub const selfExePathW = @compileError("deprecated; use selfExePath instead");
30783082
30793083/// `selfExeDirPath` except allocates the result on the heap.
30803084/// Caller owns returned memory.