From cd40b0aefb79e7b4559407957b7e0d65a7c77cf7 Mon Sep 17 00:00:00 2001 From: Colin Wallace Date: Sun, 23 Aug 2015 01:02:40 -0700 Subject: [PATCH] Follow symbolic links when searching for executable directory --- src/RageFileManager.cpp | 47 +++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/RageFileManager.cpp b/src/RageFileManager.cpp index cda430fe78..9a58f02fdd 100644 --- a/src/RageFileManager.cpp +++ b/src/RageFileManager.cpp @@ -172,6 +172,42 @@ public: }; static RageFileDriverMountpoints *g_Mountpoints = NULL; +static RString ExtractDirectory( RString sPath ) +{ + // return the directory containing sPath + size_t n = sPath.find_last_of("/"); + if( n != sPath.npos ) + sPath.erase(n); + else + sPath.erase(); + return sPath; +} + +static RString ReadlinkRecursive( RString sPath ) +{ +#if defined(UNIX) || defined(MACOSX) + // unices support symbolic links; dereference them + RString dereferenced = sPath; + do + { + sPath = dereferenced; + char derefPath[512]; + ssize_t linkSize = readlink(sPath, derefPath, sizeof(derefPath)); + if ( linkSize != -1 && linkSize != sizeof(derefPath) ) + { + dereferenced = RString( derefPath, linkSize ); + if (derefPath[0] != '/') + { + // relative link + dereferenced = RString( ExtractDirectory(sPath) + "/" + dereferenced); + } + } + } while (sPath != dereferenced); +#endif + + return sPath; +} + static RString GetDirOfExecutable( RString argv0 ) { // argv[0] can be wrong in most OS's; try to avoid using it. @@ -196,11 +232,7 @@ static RString GetDirOfExecutable( RString argv0 ) #endif // strip off executable name - size_t n = sPath.find_last_of("/"); - if( n != sPath.npos ) - sPath.erase(n); - else - sPath.erase(); + sPath = ExtractDirectory(sPath); if( !bIsAbsolutePath ) { @@ -219,17 +251,18 @@ static RString GetDirOfExecutable( RString argv0 ) { if( access(*i + "/" + argv0, X_OK|R_OK) ) continue; - sPath = *i; + sPath = ExtractDirectory(ReadlinkRecursive(*i + "/" + argv0)); break; } if( sPath.empty() ) sPath = GetCwd(); // What? else if( sPath[0] != '/' ) // For example, if . is in $PATH. sPath = GetCwd() + "/" + sPath; + } else { - sPath = GetCwd() + "/" + sPath; + sPath = ExtractDirectory(ReadlinkRecursive(GetCwd() + "/" + argv0)); } #else sPath = GetCwd() + "/" + sPath;