1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-23 19:29:37 +00:00

change GetProgPath() to return full & resolved binary path

GetProgPath() now resolves the path derived from argv[0] always
via realpath(3p) to its real location in the filesystem, and returns
the path including binary name, effectively making it work like
windows' GetModuleFileName(), so we can re-use the existing code
to strip the trailing binary name.
since symlinks are now always resolved, we no longer need the
special case code for linux to use /proc/self/exe for this purpose.
This commit is contained in:
rofl0r 2022-05-02 08:22:21 +00:00 committed by mrdudz
parent 546e82965d
commit 5867d3a020

View File

@ -232,44 +232,32 @@ static int SearchPathBin(const char* bin, char* buf, size_t buflen)
static char* MyDirname(char* in)
/* returns the dirname() part of a filename.
** the passed string is modified in place, then returned.
*/
{
char* p = strrchr (in, '/');
if (p) {
*p = 0;
}
return in;
}
static char* GetProgPath(char* pathbuf, char* a0)
/* search for the full path of the binary using the argv[0] parameter
** passed to int main(), according to the description above.
** if the binary was started using a relative path, realpath(3p) will
** turn the relative path into an absolute path with pwd resolved, and
** gratuitous path components such as "./" or ".." removed.
**
** the binary name will be passed to realpath(3p) to have all symlinks
** resolved and gratuitous path components like "../" removed.
**
** argument "pathbuf" is a work buffer of size PATH_MAX,
** "a0" the original argv[0].
** returns pathbuf with the full path of the binary, minus the binary
** name itself.
** returns pathbuf with the full path of the binary.
*/
{
if (a0[0] == '/') {
strcpy (pathbuf, a0);
} else if (a0[0] == '.' || strrchr (a0, '/')) {
/* realpath returns the work buffer passed to it, so checking the
return value is superfluous. gcc11 warns anyway. */
if (realpath (a0, pathbuf)) {}
} else {
SearchPathBin (a0, pathbuf, PATH_MAX);
char tmp[PATH_MAX];
if (!strchr(a0, '/')) {
/* path doesn't contain directory separator, so it was looked up
via PATH environment variable */
SearchPathBin (a0, tmp, PATH_MAX);
a0 = tmp;
}
return MyDirname(pathbuf);
/* realpath returns the work buffer passed to it, so checking the
return value is superfluous. gcc11 warns anyway. */
if (realpath (a0, pathbuf)) {}
return pathbuf;
}
#endif
@ -289,32 +277,19 @@ void AddSubSearchPathFromBin (SearchPaths* P, const char* SubDir)
return;
}
#else
GetProgPath(Dir, ArgVec[0]);
#endif
/* Remove binary name */
Ptr = strrchr (Dir, '\\');
Ptr = strrchr (Dir, PATHSEP[0]);
if (Ptr == 0) {
return;
}
*Ptr = '\0';
#elif defined(__linux__)
/* reading from proc will return the real location, excluding symlinked
pathes - which is needed for certain edgy cases */
if (readlink("/proc/self/exe", Dir, sizeof(Dir) - 1) < 0) {
GetProgPath(Dir, ArgVec[0]);
} else {
/* Remove binary name */
Ptr = strrchr (Dir, PATHSEP[0]);
if (Ptr == 0) {
return;
}
*Ptr = '\0';
}
#else
GetProgPath(Dir, ArgVec[0]);
#endif
/* Check for 'bin' directory */
Ptr = strrchr (Dir, PATHSEP[0]);
if (Ptr == 0) {