@@ -55,25 +55,32 @@ std::filesystem::path getExecutablePath(const std::filesystem::path &suggestedPa
55
55
}
56
56
}
57
57
#elif defined(__APPLE__)
58
- static std::array<char , PATH_MAX> buffer{};
58
+ std::array<char , PATH_MAX> buffer{};
59
59
uint32_t size = static_cast <uint32_t >(buffer.size ());
60
60
if (_NSGetExecutablePath (buffer.data (), &size) == 0 ) {
61
61
// TODO: What to do about the allocation here?
62
- return ( buffer.data () );
63
- }
62
+ return buffer.data ();
63
+ } else
64
64
#elif defined(_WIN32)
65
- static std::array<char , PATH_MAX> buffer{};
65
+ std::array<char , PATH_MAX> buffer{};
66
66
// TODO: Do we need to support this?
67
67
DWORD size = GetModuleFileNameA (nullptr , buffer.data (), static_cast <DWORD>(buffer.size ()));
68
68
if (size > 0 && size < buffer.size ()) {
69
- return ( buffer.data () );
70
- }
69
+ return buffer.data ();
70
+ } else
71
71
#endif
72
- // If the above fails, try to convert argv0 to a path.
73
- if (std::filesystem::exists (suggestedPath)) {
74
- return suggestedPath;
72
+ if (auto *path = getenv (" _" )) {
73
+ return path;
74
+ }
75
+ // If the above fails, try to convert suggestedPath to a path.
76
+ try {
77
+ // std::filesystem::canonical will throw on error if the path is invalid.
78
+ // It will also try to resolve symlinks.
79
+ return std::filesystem::canonical (suggestedPath);
80
+ } catch (const std::filesystem::filesystem_error &) {
81
+ // In the case of an error, return an empty path.
82
+ return {};
75
83
}
76
- return {};
77
84
}
78
85
79
86
const char *exename (const char *argv0) {
@@ -84,6 +91,7 @@ const char *exename(const char *argv0) {
84
91
if (path.empty ()) {
85
92
return nullptr ;
86
93
}
94
+ // TODO: There is a potential leak here.
87
95
return strdup (path.c_str ());
88
96
}
89
97
0 commit comments