Common: Add a function to get the path to the running program

This commit is contained in:
Connor McLaughlin 2020-01-24 14:50:57 +10:00
parent 9456dc5d9b
commit de4e45a433
3 changed files with 133 additions and 25 deletions

View file

@ -32,25 +32,6 @@ CDImageCueSheet::~CDImageCueSheet()
cd_delete(m_cd);
}
static std::string GetPathDirectory(const char* path)
{
const char* forwardslash_ptr = std::strrchr(path, '/');
const char* backslash_ptr = std::strrchr(path, '\\');
const char* slash_ptr;
if (forwardslash_ptr && backslash_ptr)
slash_ptr = std::max(forwardslash_ptr, backslash_ptr);
else if (backslash_ptr)
slash_ptr = backslash_ptr;
else if (forwardslash_ptr)
slash_ptr = forwardslash_ptr;
else
return {};
std::string str;
str.append(path, slash_ptr - path + 1);
return str;
}
static std::string ReplaceExtension(std::string_view path, std::string_view new_extension)
{
std::string_view::size_type pos = path.rfind('.');
@ -80,7 +61,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename)
}
// get the directory of the filename
std::string basepath = GetPathDirectory(filename);
std::string basepath = FileSystem::GetPathDirectory(filename) + "/";
m_filename = filename;
u32 disc_lba = 0;

View file

@ -144,6 +144,11 @@ void CanonicalizePath(String& Destination, bool OSPath /* = true */)
CanonicalizePath(Destination, Destination);
}
void CanonicalizePath(std::string& path, bool OSPath /*= true*/)
{
CanonicalizePath(path.data(), static_cast<u32>(path.size() + 1), path.c_str(), OSPath);
}
static inline bool FileSystemCharacterIsSane(char c, bool StripSlashes)
{
if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9') && c != ' ' && c != ' ' &&
@ -217,6 +222,34 @@ void SanitizeFileName(String& Destination, bool StripSlashes /* = true */)
return SanitizeFileName(Destination, Destination, StripSlashes);
}
std::string GetPathDirectory(const char* path)
{
#ifdef WIN32
const char* forwardslash_ptr = std::strrchr(path, '/');
const char* backslash_ptr = std::strrchr(path, '\\');
const char* slash_ptr;
if (forwardslash_ptr && backslash_ptr)
slash_ptr = std::max(forwardslash_ptr, backslash_ptr);
else if (backslash_ptr)
slash_ptr = backslash_ptr;
else if (forwardslash_ptr)
slash_ptr = forwardslash_ptr;
else
return {};
#else
const char* slash_ptr = std::strrchr(path, '/');
if (!slash_ptr)
return {};
#endif
if (slash_ptr == path)
return {};
std::string str;
str.append(path, slash_ptr - path);
return str;
}
void BuildPathRelativeToFile(char* Destination, u32 cbDestination, const char* CurrentFileName, const char* NewFileName,
bool OSPath /* = true */, bool Canonicalize /* = true */)
{
@ -957,6 +990,31 @@ bool FileSystem::DeleteDirectory(const char* Path, bool Recursive)
return true;
}
std::string GetProgramPath()
{
const HANDLE hProcess = GetCurrentProcess();
std::string buffer;
buffer.resize(MAX_PATH);
for (;;)
{
DWORD nChars = static_cast<DWORD>(buffer.size());
if (!QueryFullProcessImageNameA(GetCurrentProcess(), 0, buffer.data(), &nChars) &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
buffer.resize(buffer.size() * 2);
continue;
}
buffer.resize(nChars);
break;
}
CanonicalizePath(buffer);
return buffer;
}
#else
std::unique_ptr<ChangeNotifier> CreateChangeNotifier(const char* path, bool recursiveWatch)
@ -1270,6 +1328,72 @@ bool DeleteDirectory(const char* Path, bool Recursive)
return false;
}
std::string GetProgramPath()
{
#if defined(__linux__)
static const char* exeFileName = "/proc/self/exe";
int curSize = PATH_MAX;
char* buffer = static_cast<char*>(std::realloc(nullptr, curSize));
for (;;)
{
int len = readlink(exeFileName, buffer, curSize);
if (len < 0)
{
std::free(buffer);
return {};
}
else if (len < curSize)
{
buffer[len] = '\0';
std::string ret(buffer, len);
std::free(buffer);
return ret;
}
curSize *= 2;
buffer = static_cast<char*>(std::realloc(buffer, curSize));
}
#elif defined(__APPLE__)
int curSize = PATH_MAX;
char* buffer = static_cast<char*>(std::realloc(nullptr, curSize + 1));
for (;;)
{
uint32 nChars = PATH_MAX - 1;
int res = _NSGetExecutablePath(buffer, &nChars);
if (res == 0)
{
buffer[nChars] = 0;
char* resolvedBuffer = realpath(buffer, nullptr);
if (resolvedBuffer == nullptr)
{
std::free(buffer);
return {};
}
std::string ret(buffer, len);
std::free(buffer);
return ret;
}
if (curSize >= 1048576)
{
std::free(buffer);
return {};
}
curSize *= 2;
buffer = static_cast<char*>(std::realloc(buffer, curSize + 1));
}
#else
return {};
#endif
}
#endif
} // namespace FileSystem

View file

@ -8,7 +8,7 @@
class ByteStream;
#ifdef Y_PLATFORM_WINDOWS
#ifdef WIN32
#define FS_OSPATH_SEPERATOR_CHARACTER '\\'
#else
#define FS_OSPATH_SEPERATOR_CHARACTER '/'
@ -111,15 +111,12 @@ protected:
// create a change notifier
std::unique_ptr<ChangeNotifier> CreateChangeNotifier(const char* path, bool recursiveWatch);
// appends a path string to the current path string. optionally canonicalizes it.
void AppendPath(char* Path, u32 cbPath, const char* NewPath);
void AppendPath(String& Path, const char* NewPath);
// canonicalize a path string (i.e. replace .. with actual folder name, etc), if OS path is used, on windows, the
// separators will be \, otherwise /
void CanonicalizePath(char* Destination, u32 cbDestination, const char* Path, bool OSPath = true);
void CanonicalizePath(String& Destination, const char* Path, bool OSPath = true);
void CanonicalizePath(String& Destination, bool OSPath = true);
void CanonicalizePath(std::string& path, bool OSPath = true);
// translates the specified path into a string compatible with the hosting OS
void BuildOSPath(char* Destination, u32 cbDestination, const char* Path);
@ -137,6 +134,9 @@ void SanitizeFileName(char* Destination, u32 cbDestination, const char* FileName
void SanitizeFileName(String& Destination, const char* FileName, bool StripSlashes = true);
void SanitizeFileName(String& Destination, bool StripSlashes = true);
/// Returns the directory component of a filename.
std::string GetPathDirectory(const char* path);
// search for files
bool FindFiles(const char* Path, const char* Pattern, u32 Flags, FindResultsArray* pResults);
@ -173,4 +173,7 @@ bool CreateDirectory(const char* Path, bool Recursive);
// if the directory has files, unless the recursive flag is set, it will fail
bool DeleteDirectory(const char* Path, bool Recursive);
/// Returns the path to the current executable.
std::string GetProgramPath();
}; // namespace FileSystem