@@ -2949,8 +2949,12 @@ pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File {
2949
2949
return openFileAbsoluteZ ("/proc/self/exe" , flags );
2950
2950
}
2951
2951
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 );
2954
2958
return cwd ().openFileW (prefixed_path_w .span (), flags );
2955
2959
}
2956
2960
// Use of MAX_PATH_BYTES here is valid as the resulting path is immediately
@@ -2977,7 +2981,7 @@ pub fn selfExePathAlloc(allocator: Allocator) ![]u8 {
2977
2981
return allocator .dupe (u8 , try selfExePath (& buf ));
2978
2982
}
2979
2983
2980
- /// Get the path to the current executable.
2984
+ /// Get the path to the current executable. Follows symlinks.
2981
2985
/// If you only need the directory, use selfExeDirPath.
2982
2986
/// If you only want an open file handle, use openSelfExe.
2983
2987
/// This function may return an error if the current executable
@@ -3060,21 +3064,21 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
3060
3064
return error .FileNotFound ;
3061
3065
},
3062
3066
.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 );
3067
3075
},
3068
3076
.wasi = > @compileError ("std.fs.selfExePath not supported for WASI. Use std.fs.selfExePathAlloc instead." ),
3069
3077
else = > @compileError ("std.fs.selfExePath not supported for this target" ),
3070
3078
}
3071
3079
}
3072
3080
3073
- /// The result is UTF16LE-encoded.
3074
- pub 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
- }
3081
+ pub const selfExePathW = @compileError ("deprecated; use selfExePath instead" );
3078
3082
3079
3083
/// `selfExeDirPath` except allocates the result on the heap.
3080
3084
/// Caller owns returned memory.
0 commit comments