AuroraRuntime/Source/Process/Paths.cpp

221 lines
4.9 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Paths.cpp
Date: 2021-7-14
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "Paths.hpp"
#if defined(AURORA_IS_POSIX_DERIVED)
#include <stdlib.h>
#include <unistd.h>
#define _USE_GET_CWD
#endif
namespace Aurora::Process
{
AUKN_SYM bool GetWorkingDirectory(AuString &path)
{
if (!AuTryResize(path, 0x4000))
{
return false;
}
#if defined(AURORA_IS_MODERNNT_DERIVED)
std::wstring eh;
eh.resize(path.size());
auto length = ::GetCurrentDirectoryW(eh.size(), eh.data());
if (length == 0)
{
return false;
}
path = Locale::ConvertFromWChar(eh.data(), length);
return true;
#elif defined(AURORA_PLATFORM_ANDROID)
// TODO: consider pulling internal storage package directory
return false;
#elif defined(_USE_GET_CWD)
if (getcwd(path.data(), path.size()) == nullptr)
{
return false;
}
path.resize(strlen(path.data()));
return true;
#endif
return false;
}
static bool GetModulePathSlow(AuString &path, char &splitter)
{
path.clear();
splitter = 0;
#if defined(AURORA_IS_MODERNNT_DERIVED)
wchar_t chungus[0x4000];
auto len = GetModuleFileNameW(
NULL,
chungus,
AuArraySize(chungus)
);
if (!len)
{
return false;
}
path = Aurora::Locale::ConvertFromWChar(chungus, len);
splitter = '\\';
return true;
#elif defined(AURORA_IS_XNU_DERIVED)
CFURLRef bundleURL = CFBundleCopyExecutableURL(CFBundleGetMainBundle());
CFStringRef pathRef = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
auto utf16length = CFStringGetLength(pathRef);
auto maxUtf8len = CFStringGetMaximumSizeForEncoding(utf16length, kCFStringEncodingUTF8);
path.resize(maxUtf8len);
if (!CFStringGetCString(pathRef, path.data(), maxUtf8len, kCFStringEncodingUTF8))
{
path.clear();
return false;
}
path.resize(std::strlen(path.c_str()));
splitter = '\\';
#elif defined(AURORA_PLATFORM_ANDROID)
// SELinux gets in the way in some instances
// There is no reason we should be searching for the jre binary
// I'm also not convined pulling a cached apk path is the best thing to do here
return false;
#elif defined(AURORA_IS_POSIX_DERIVED)
static const AuList<AuString> procFsPaths = {
"/proc/self/exe",
"/proc/self/file",
"/proc/curproc/exe",
"/proc/curproc/file"
};
for (const auto &name : procFsPaths)
{
if (Aurora::IO::FS::ReadString(name, path))
{
splitter = '/';
return true;
}
}
return false;
#endif
}
static bool GetModulePath(AuString &module, AuString &partialPath, AuString &fullPath)
{
static AuString cachedModule, cachedPartialPath, cachedFullPath;
static bool init = false;
char spitter;
if (std::exchange(init, true))
{
if (!cachedModule.size())
{
return false;
}
goto returnCached;
}
if (!GetModulePathSlow(cachedFullPath, spitter))
{
return false;
}
// this scope is required for c++20, bleh
{
auto indexA = cachedFullPath.find_last_of(spitter);
if (indexA == AuString::npos)
{
return false;
}
cachedModule = cachedFullPath.substr(indexA + 1);
cachedPartialPath = cachedFullPath.substr(0, indexA);
}
returnCached:
module = cachedModule;
fullPath = cachedFullPath;
partialPath = cachedPartialPath;
return true;
}
AUKN_SYM bool GetProcName(AuString &executable)
{
AuString module, partial, full;
if (!GetModulePath(module, partial, full))
{
return false;
}
executable = module;
return true;
}
AUKN_SYM bool GetProcPath(AuString &path)
{
AuString module, partial, full;
if (!GetModulePath(module, partial, full))
{
return false;
}
path = partial;
if (path.empty())
{
return GetWorkingDirectory(path);
}
return true;
}
AUKN_SYM bool GetProcFullPath(AuString &path)
{
AuString module, partial, full;
if (!GetModulePath(module, partial, full))
{
return false;
}
path = full;
return true;
}
}