[*] Refactor some APIs to use string views instead of strings

[+] Added new shell dirs API
[+] AuOptional<AuROString> GetUserDocuments()
[+] AuOptional<AuROString> GetUserDownloads()
[+] AuOptional<AuROString> GetUserDesktop()
[+] AuOptional<AuROString> GetUserPhotos()
[+] AuOptional<AuROString> GetUserVideos()
[+] AuOptional<AuROString> GetUserMusic()
[*] Amend IPCHandle::InitFromSharing (use string view)
[*] AuFS devices API should now use string views
[*] AuProcess, Process APIs now use string views (ModuleLoadRequest, LoadModule, GetProcAddressEx, etc)
[*] AuProcess, Paths APIs now use string views (GetProcessDirectory, GetProcessFullPath, etc)
[*] Fix XP using common my documents vs local user documents
This commit is contained in:
Reece Wilson 2024-09-24 18:53:54 +01:00
parent 9b1ff8889e
commit 94970d689c
16 changed files with 704 additions and 336 deletions

View File

@ -107,53 +107,53 @@ namespace Aurora::IO::FS
* Provides the best-fit FSLogicalPartition::filesystemMountPoints of a string.
* Sometimes the platform shell can help, some platforms need to pull the fs devices cache.
*/
AUKN_SYM AuString GetRootFromPath(const AuString &fileOrDirPath);
AUKN_SYM AuString GetRootFromPath(const AuROString &fileOrDirPath);
/**
* Provides a FSDevice::devicePath of a file or directory.
*/
AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuString &fileOrDirPath);
AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuROString &fileOrDirPath);
/**
* Provides a FSDevice::devicePath of a root mountpoint.
*/
AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuString &root);
AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuROString &root);
/**
* Provides the FSLogicalPartition::logicalMount of a file or directory.
*/
AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuString &fileOrDirPath);
AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuROString &fileOrDirPath);
AUKN_SYM AuString TrySimplifyDevicePath(const AuString &deviceOrLogicalMountPath);
AUKN_SYM AuString TrySimplifyDevicePath(const AuROString &deviceOrLogicalMountPath);
// max: unbuffered pipe io
AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuString &fileOrDirPath);
AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuROString &fileOrDirPath);
// min: unbuffered pipe io
AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuString &fileOrDirPath);
AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuROString &fileOrDirPath);
// min viable sector size with abstractions on top of the disk
AUKN_SYM AuUInt32 GetLogicalSectorSizeFromPath(const AuString &fileOrDirPath);
AUKN_SYM AuUInt32 GetLogicalSectorSizeFromPath(const AuROString &fileOrDirPath);
/**
* Provides a FSLogicalPartition::space of a file or directory.
*/
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuString &fileOrDirPath);
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuROString &fileOrDirPath);
/**
* Provides a FSLogicalPartition::space of a logical volume path / FSLogicalPartition::logicalMount string.
*/
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuString &logicalMountPath);
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuROString &logicalMountPath);
// Convenience function
AUKN_SYM AuUInt64 GetDeviceSizeInBytes(const AuString& physicalDevicePath);
AUKN_SYM AuUInt64 GetDeviceSizeInBytes(const AuROString &physicalDevicePath);
// Convenience function
AUKN_SYM AuResult<AuString> GetDeviceModel(const AuString& physicalDevicePath);
AUKN_SYM AuResult<AuString> GetDeviceModel(const AuROString &physicalDevicePath);
// Convenience function
AUKN_SYM AuResult<FSDevice> GetFSDeviceByFilePath(const AuString &fileOrDirPath);
AUKN_SYM AuResult<FSDevice> GetFSDeviceByFilePath(const AuROString &fileOrDirPath);
// Convenience function
AUKN_SYM AuResult<FSDevice> GetFSDeviceByDevice(const AuString &physicalDevicePath);
AUKN_SYM AuResult<FSDevice> GetFSDeviceByDevice(const AuROString &physicalDevicePath);
/*
* Provides a copy of the internal FSDevice cache under lock

View File

@ -10,17 +10,19 @@
namespace Aurora::IO::FS
{
/**
* @brief Provides an application specific storage path for sharing data amongst Aurora applications sharing the same branding info (defer to the init structure)
* @brief Provides an application specific storage path for sharing data amongst Aurora applications sharing the same branding info (defer to the init structure).
* This should be used for machine local configs and caches.
*/
AUKN_SYM AuOptional<const AuString &> GetSystemDomain();
AUKN_SYM AuOptional<AuROString> GetSystemDomain();
/**
* @brief Provides an application specific storage path for user-local application data, isolated with respect to your Aurora application brand info (defer to the init structure)
*/
AUKN_SYM AuOptional<const AuString &> GetProfileDomain();
* @brief Provides an application specific storage path for user-local application data, isolated with respect to your Aurora application brand info (defer to the init structure).
* This should be used for storing private user configs under an application data subdirectory.
*/
AUKN_SYM AuOptional<AuROString> GetProfileDomain();
AUKN_SYM bool GetSystemResourcePath(const AuString &fileName, AuString &path);
AUKN_SYM bool GetSystemResourcePath(const AuROString &fileName, AuString &path);
/**
* @brief Get package path
@ -31,39 +33,64 @@ namespace Aurora::IO::FS
* ...on platforms with read-only application specific data directories
* @param path
* @return
*/
AUKN_SYM AuOptional<const AuString &> GetPackagePath();
*/
AUKN_SYM AuOptional<AuROString> GetPackagePath();
/**
* @brief Pulls the application directory as defined by the operating system standard file system hierarchy
* Otherwise, XDG_CONFIG_CONFIG or %appdata%.
* @brief Pulls the application directory as defined by the operating system standard file system hierarchy.
* This is often $XDG_CONFIG_HOME or %APPDATA%.
* This directory might be sandboxed to the user or application by the operating system.
*/
AUKN_SYM AuOptional<const AuString &> GetAppData();
* Are you looking for GetProfileDomain()/GetSystemDomain()? These will provide better paths for storing configs and caches respectively.
*/
AUKN_SYM AuOptional<AuROString> GetAppData();
/**
* @brief Pulls the users home directory, untouched
*/
AUKN_SYM AuOptional<const AuString &> GetUserHome();
*/
AUKN_SYM AuOptional<AuROString> GetUserHome();
AUKN_SYM AuOptional<AuROString> GetUserDocuments();
AUKN_SYM AuOptional<AuROString> GetUserDownloads();
AUKN_SYM AuOptional<AuROString> GetUserDesktop();
AUKN_SYM AuOptional<AuROString> GetUserPhotos();
AUKN_SYM AuOptional<AuROString> GetUserVideos();
AUKN_SYM AuOptional<AuROString> GetUserMusic();
/**
* @brief Global application data that requires no special permissions to access.
* This could be an SD-Card or user profile.
* This could be the root of the user managable aplication directory.
*/
AUKN_SYM AuOptional<const AuString &> GetWritableAppdata();
*/
AUKN_SYM AuOptional<AuROString> GetWritableAppdata();
/**
* @brief Global application data that requires special permissions to access, usually configured by a system account during installation
*/
AUKN_SYM AuOptional<const AuString &> GetRootAppdata();
*/
AUKN_SYM AuOptional<AuROString> GetRootAppdata();
/**
* @brief Get user installable application directory
*/
AUKN_SYM AuOptional<const AuString &> GetUserProgramsFolder();
*/
AUKN_SYM AuOptional<AuROString> GetUserProgramsFolder();
AUKN_SYM AuOptional<AuString> NewTempFile();
/**
* @brief Creates an empty temp file and returns its' path.
* It should be marked for deletion on shutdown, or be located in a directory marked for auto-deletion, or be located on a temporary ramdisk, or exist in a temporary file system mount.
* If you can delete it for us, even better.
* Windows XP warning: this does not use C:\Windows\Temp. Check documents instead.
*/
AUKN_SYM AuOptional<AuString> NewTempFile();
AUKN_SYM AuOptional<AuString> NewTempDirectory();
/**
* @brief Creates an empty temp directory and returns its' path.
* It should be marked for deletion on shutdown, or be located in a directory marked for auto-deletion, or be located on a temporary ramdisk, or exist in a temporary file system mount.
* If you can delete it for us, even better.
* Windows XP warning: this does not use C:\Windows\Temp. Check documents instead.
*/
AUKN_SYM AuOptional<AuString> NewTempDirectory();
}

View File

@ -129,7 +129,7 @@ namespace Aurora::IO
virtual bool InitFromStreamEnum(EStandardStream eStream) = 0;
virtual bool InitFromSharing(const AuString &handle) = 0;
virtual bool InitFromSharing(const AuROString &handle) = 0;
virtual AuUInt64 GetOSHandle() const = 0;

View File

@ -20,17 +20,17 @@ namespace Aurora::Process
* @brief Fetches the applications binary or package directory
* @return
*/
AUKN_SYM AuOptional<const AuString &> GetProcessDirectory();
AUKN_SYM AuOptional<AuROString> GetProcessDirectory();
/**
* @brief Fetches the full-path of the applications binary, if known
* @return
*/
AUKN_SYM AuOptional<const AuString &> GetProcessFullPath();
AUKN_SYM AuOptional<AuROString> GetProcessFullPath();
/**
* @brief Fetches the applications primary module name
* @return
*/
AUKN_SYM AuOptional<const AuString &> GetProcessName();
AUKN_SYM AuOptional<AuROString> GetProcessName();
}

View File

@ -48,50 +48,136 @@ namespace Aurora::Process
static AuList<EModulePath> kCWDPath = { EModulePath::eModulePathCWD };
static AuList<EModulePath> kProcPath = { EModulePath::eProcessDirectory };
// Binding warning: this object takes references to references/pointers within the full-expressions (we live here) to parent scope[s] (your callframe lives here, with the provided temp string views).
// this object is therefore not expected to outlive any references you pass at it.
// we should only exist in the scope of FULL-EXPRESSION := { LoadModule({ ModuleLoadRequest: { temp raw string pointer view to anywhere valid throughout the call }}) }
// binders will need to create a derived type to contain two AuStrings to fill mod and version.
struct ModuleLoadRequest
{
inline ModuleLoadRequest(const AuList<AuString> &directories, const AuString &mod) : mod(mod), specifiedSearchPaths(&directories), searchPath(&kSpecifiedPathStrict)
inline ModuleLoadRequest() :
searchPath(&kSpecifiedPathStrict)
{
}
inline ModuleLoadRequest(const AuList<AuString> &directories,
const AuString &mod) :
mod(mod),
specifiedSearchPaths(&directories),
searchPath(&kSpecifiedPathStrict)
{}
inline ModuleLoadRequest(const AuList<AuString> &directories, const AuString &mod, const AuString &version) : mod(mod), version(version), specifiedSearchPaths(&directories), searchPath(&kSpecifiedPathStrict)
inline ModuleLoadRequest(const AuList<AuString> &directories,
const AuROString &mod,
const AuROString &version) :
mod(mod), version(version),
specifiedSearchPaths(&directories),
searchPath(&kSpecifiedPathStrict)
{}
inline ModuleLoadRequest(const AuString &mod) : mod(mod), searchPath(&kAdminOverloadableSearchPath)
inline ModuleLoadRequest(const AuROString &mod) :
mod(mod),
searchPath(&kAdminOverloadableSearchPath)
{}
inline ModuleLoadRequest(const AuString &mod, const AuString &version) : mod(mod), version(version), searchPath(&kAdminOverloadableSearchPath)
inline ModuleLoadRequest(const AuROString &mod,
const AuROString &version) :
mod(mod),
version(version),
searchPath(&kAdminOverloadableSearchPath)
{}
AuString mod;
AuString version;
AuROString mod;
AuROString version;
AuList<AuString> const * specifiedSearchPaths {};
AuList<EModulePath> const * searchPath {};
bool verify {}; // always effectively true if the executable is signed and enableMitigations is true
bool unixCheckPlusX { true };
bool enableMitigations { true };
bool forceMitigations { false };
char padZero[128] { 0 };
};
/**
* @brief Loads a dynamic link module into cache, by the name of 'mod', somewhere in the directories specified by 'searchPath'.
* You should not provide a suffix, platform extension, or the full aurora dll string. Path resolution will take care of
* resolving the Aurora ABI, falling back to mod.platformext.
* @param request
* @return
*/
/// Provides a scriptability style DLL suffix including the relevant file extension.
/// I do not recommend trying to build DLL filenames yourself, use LoadModule instead.
/// Different version, file extension, and unique suffix order and values may apply.
AUKN_SYM AuROString GetViewOfAuroraDLLSuffix();
/// Provides the platform extension for dynamically linked objects.
/// This may become before or after the version string, depending on the host platform style.
/// I do not recommend trying to build DLL filenames yourself, use LoadModule instead.
AUKN_SYM AuROString GetViewOfDynamicLibraryExtensionSuffix();
/// Provides the scriptability style architecture string for platform local build artefects.
AUKN_SYM AuROString GetViewOfArchitectureSuffix();
/// @brief Loads a dynamic link module into cache, by the name of 'mod', somewhere in the directories specified by 'searchPath'.
/// You should not provide a suffix, platform extension, or the full aurora dll string. Path resolution will take care of
/// resolving the Aurora build ABI strings, falling back to "${request.mod}.${GetViewOfDynamicLibraryExtensionSuffix()}".
/// @param request
/// @return
AUKN_SYM bool LoadModule(const ModuleLoadRequest &request);
/// Updated version of LoadModule.
/// Returns a VOID* handle to be used as a replacement for win32 LoadLibraryW(...) / posix dlopen(...), to be followed up by a/multiple GetProcessAddress / dlsym calls.
/// GetProcAddressEx is to be used with this VOID* handle.
AUKN_SYM void *LoadModuleEx(const ModuleLoadRequest &request);
AUKN_SYM void *GetProcHandle(const AuString &name);
/// Safe (without unloads) handle fetch of LoadModuleEx.
AUKN_SYM void *GetProcHandle(const AuROString &name);
AUKN_SYM AuMach GetProcAddress(const AuString &mod, const AuString &symbol);
/// Safe process address fetch a symbol inside of a nammed LoadModule object.
AUKN_SYM AuMach GetProcAddress(const AuROString &mod, const AuRONString &symbol);
AUKN_SYM AuMach GetProcAddressEx(void *pHandle, const AuString &symbol);
/// Safe (without unloads) process address fetch a symbol inside of LoadModuleEx object.
AUKN_SYM AuMach GetProcAddressEx(void *pHandle, const AuRONString &symbol);
/// Returns a copy of the directories in which the requests of LoadModule can be fulfilled.
AUKN_SYM AuList<AuString> GetBinaryClassPath();
AUKN_SYM bool SetBinaryClassPath(const AuList<AuString> &list, bool preloadAll = false);
/// Warning: in production applications, becareful about preloading binaries of unknown origin.
///
/// Consider every directory in "list" to be within the perview of the plugin-write user group.
/// Anybody, presumably the local user and all its processes, can write/install plugins, is capable of loading any arbitrary code whatsoever.
/// On Windows, the local user will have these user-write permissions in these plugin-write areas, to write any arbitrary DLL to inject. At best, you can try to limit yourself to read-only directories of admin-assisted origin.
/// On Linux, the local user is king, with sandboxing being a joke and almost every system is full of holes. btw freebsd has native POSIX ACL and jail support.
/// On Android, the local user will NOT have these write permissions, so that no unwanted dynamic code objects can be loaded through the hardened libc and selinux sandbox (see: application.android:extractNativeLibs).
/// On UWP and WinRT-Likes, LoadPackagedLibrary will ensure we're sandboxed from dynamic attacks.
/// Therefore, on some platforms it is possible for any library to get accidentally preloaded or hit (loaded, tls init code hit, static init code hit, etc).
/// DRM and sandboxing solutions should be monitoring the APIs we use, so it shouldn't be too much of a problem, if your application is packed properly.
///
/// This is relevant for DRMs, anticheats, web browsers, and sandboxes that want to prevent arbitrary code injections.
/// Historically software such as FireFox (against malware/adware), Chrome (against malware/adware), anticheats (skids CreateRemoteThread at kernel32::LoadLibraryW attempts),
/// sandboxes of arxan nature (Microsoft Playready, Widevine, Xbox Live game ports to PC, GTA V, et al), EasyAnticheat, all care for the tiniest bit of process isolation security.
/// When packing such software, be careful not to allow for arbitrary LoadLibraryW from trusted code locations, because we could be just loading everything... Even tho we try not to. We even have WinTrust checks.
///
/// This is intended for loading widgets, plugins, and various static extensions on relatively static platforms.
/// If shared modules exist on a platform within directories we have file iterate permissions to read, and we're capable of loading dynamic modules (sometimes prevetted), this function will work.
/// This includes some environments such as WinRT/UWP-Likes (incl packaged modules?) and Android where ApplicationInfo#nativeLibraryDir since API9 instantiated by "application.android:extractNativeLibs" is allowed through the sandbox.
AUKN_SYM bool SetBinaryClassPath(const AuList<AuString> &list, AuOptional<bool> optBoolPreloadAll = { false });
AUKN_SYM bool AddBinaryClassPath(const AuString &dir, bool preloadAll = false);
/// Warning: in production applications, becareful about preloading binaries of unknown origin.
///
/// Consider every directory in "list" to be within the perview of the plugin-write user group.
/// Anybody, the local user and its processes, who can write/install plugins, is capable of loading any arbitrary code whatsoever.
/// On Windows, the local user will have these user-write permissions in these plugin-write areas, to write any arbitrary DLL to inject. At best, you can try to limit yourself to read-only directories of admin-assisted origin.
/// On Linux, the local user is king, with sandboxing being a joke and almost every system is full of holes. btw freebsd has native POSIX ACL and jail support.
/// On Android, the local user will NOT have these write permissions, so that no unwanted dynamic code objects can be loaded through the hardened libc and selinux sandbox (see: application.android:extractNativeLibs).
/// On UWP and WinRT-Likes, LoadPackagedLibrary will ensure we're sandboxed from dynamic attacks.
/// Therefore, on some platforms it is possible for any library to get accidentally preloaded or hit (loaded, tls init code hit, static init code hit, etc).
/// DRM and sandboxing solutions should be monitoring the APIs we use, so it shouldn't be too much of a problem, if your application is packed properly.
///
/// This is relevant for DRMs, anticheats, web browsers, and sandboxes that want to prevent arbitrary code injections.
/// Historically software such as FireFox (against malware/adware), Chrome (against malware/adware), anticheats (skids CreateRemoteThread at kernel32::LoadLibraryW attempts),
/// sandboxes of arxan nature (Microsoft Playready, Widevine, Xbox Live game ports to PC, GTA V, et al), EasyAnticheat, all care for the tiniest bit of process isolation security.
/// When packing such software, be careful not to allow for arbitrary LoadLibraryW from trusted code locations, because we could be just loading everything... Even tho we try not to. We even have WinTrust checks.
///
/// This is intended for loading widgets, plugins, and various static extensions on relatively static platforms.
/// If shared modules exist on a platform within directories we have file iterate permissions to read, and we're capable of loading dynamic modules (sometimes prevetted), this function will work.
/// This includes some environments such as WinRT/UWP-Likes (incl packaged modules?) and Android where ApplicationInfo#nativeLibraryDir since API9 instantiated by "application.android:extractNativeLibs" is allowed through the sandbox.
AUKN_SYM bool AddBinaryClassPath(const AuROString &dir, AuOptional<bool> optBoolPreloadAll = { false });
/// TODO: Most platforms *hate* unloading dynamic linked libraries. on the otherhand, artists writing native scripts love them.
/// At some point, we'll probably add an API for unloading handles, and flushing out the internal cache table.
/// If the platform ignores it, and we just load the old internal handle from the os loader, oh well... guess we dont have dynamic code reloading.
}

View File

@ -29,6 +29,7 @@ namespace Aurora::Async
{
gAsyncAppMem->Shutdown();
AuResetMember(gAsyncAppMem);
AuResetMember(gAsyncApp);
}
}

View File

@ -562,7 +562,7 @@ namespace Aurora::Debug
return;
}
auto procNameWide = AuLocale::ConvertFromUTF8(pProcName->c_str());
auto procNameWide = AuLocale::ConvertFromUTF8(*pProcName);
HKEY hKey;
if (pRegOpenKeyExW &&

View File

@ -359,7 +359,7 @@ namespace Aurora::IO
return FS::UnapplyFileSectionLock(AuUnsafeRaiiToShared(this), uOffset, uLength);
}
bool AFileHandle::InitFromSharing(const AuString &handle)
bool AFileHandle::InitFromSharing(const AuROString &handle)
{
AU_LOCK_GUARD(this);

View File

@ -36,7 +36,7 @@ namespace Aurora::IO
bool InitFromHandleCopy(const IIOHandle *pHandle) override;
bool InitFromSharing(const AuString &handle) override;
bool InitFromSharing(const AuROString &handle) override;
bool InitFromPath(HandleCreate create) override;

View File

@ -279,27 +279,38 @@ namespace Aurora::IO::FS
//for (auto &character : str)
for (auto itr = str.begin();
itr != str.end();
itr++)
)
{
auto &character = *itr;
auto holding = *itr;
if ((character == '\\') || (character == '/'))
{
// AuFS::Devices will break if this is not correct
// Turns out POSIX files can have valid NT separators
#if defined(AURORA_IS_POSIX_DERIVED)
if (character == '\\' &&
prevC == '\\')
{
*(itr - 1) = '\\';
itr = str.erase(itr);
doubleSlash--;
}
#endif
else
{
itr++;
doubleSlash++;
}
character = kPathSplitter;
#else
itr++;
character = kPathSplitter;
doubleSlash++;
#endif
}
else
{
itr++;
doubleSlash = 0;
}

View File

@ -29,7 +29,7 @@ namespace Aurora::IO::FS
bool SpecialsInDirectory(const AuROString &string, AuList<AuString> &dirs);
static AuOptional<AuString> ReadLink(const AuString &path)
static AuOptional<AuString> ReadLink(const AuROString &path)
{
AuString ret;
ret.resize(4096);
@ -39,8 +39,12 @@ namespace Aurora::IO::FS
{
return {};
}
else
{
ret.resize(count);
}
if (ret[0] != '/')
if (ret.size() && ret[0] != '/')
{
AuROString dir;
AuString path2 = path;
@ -70,44 +74,52 @@ namespace Aurora::IO::FS
// to a handful of in thread IPC and intraprocess memcpy. posix and derived systems are
// going to suck regardless. its not like there some magic database with a nice little
// pnp or wsock api that'll just dump all the related fields in a handful of API calls.
static int CachedStat(const AuString &path, struct stat *pstat)
static int CachedStat(const AuROString &path, struct stat *pstat)
{
AU_LOCK_GUARD(gMutex);
auto itr = gCachedStat.find(path);
if (itr == gCachedStat.end())
try
{
int err = ::stat(path.c_str(), pstat);
if (-1 == err)
// TODO: use roxtl het lookup instead of allocating AuString
auto itr = gCachedStat.find(AuString(path));
if (itr == gCachedStat.end())
{
gCachedStat[path] = {};
errno = 0;
int err = ::stat(path.c_str(), pstat);
if (-1 == err)
{
gCachedStat[path] = {};
errno = 0;
}
else
{
gCachedStat[path] = *pstat;
}
return err;
}
else
{
gCachedStat[path] = *pstat;
auto &that = itr->second;
if (that)
{
*pstat = that.Value();
return 0;
}
else
{
return -1;
}
}
return err;
}
else
catch (...)
{
auto &that = itr->second;
if (that)
{
*pstat = that.Value();
return 0;
}
else
{
return -1;
}
return -1;
}
}
static bool BlockExists(const AuString &path)
static bool BlockExists(const AuROString &path)
{
struct stat s;
int err = CachedStat(path.c_str(), &s);
int err = CachedStat(path, &s);
if (-1 == err)
{
return false;
@ -115,7 +127,7 @@ namespace Aurora::IO::FS
return S_ISBLK(s.st_mode);
}
static AuString _DevFromPath(const AuString &path)
static AuString _DevFromPath(const AuROString &path)
{
auto pos = path.find_last_of('/');
if (pos == AuString::npos)
@ -132,7 +144,7 @@ namespace Aurora::IO::FS
return dev;
}
static AuString GetDevDevPathFromSysDev(const AuString &path)
static AuString GetDevDevPathFromSysDev(const AuROString &path)
{
if (AuStartsWith(path, "/sys/block/"))
{
@ -160,7 +172,7 @@ namespace Aurora::IO::FS
}
}
static AuPair<AuUInt32, AuUInt32> ReadIDPair(const AuString &path)
static AuPair<AuUInt32, AuUInt32> ReadIDPair(const AuROString &path)
{
struct stat s;
if (path.empty())
@ -168,7 +180,7 @@ namespace Aurora::IO::FS
return {};
}
auto err = CachedStat(path.c_str(), &s);
auto err = CachedStat(path, &s);
if (err == -1)
{
return {};
@ -182,7 +194,7 @@ namespace Aurora::IO::FS
return AuMakePair(major(s.st_rdev), minor(s.st_rdev));
}
static AuPair<AuUInt32, AuUInt32> ReadIDPairSym(const AuString &path)
static AuPair<AuUInt32, AuUInt32> ReadIDPairSym(const AuROString &path)
{
if (auto optLink = ReadLink(path))
{
@ -194,7 +206,7 @@ namespace Aurora::IO::FS
}
}
static AuString GetSysDevFromPathLogical(const AuString &path)
static AuString GetSysDevFromPathLogical(const AuROString &path)
{
struct stat s;
auto pathEx = NormalizePathRet(path);
@ -203,7 +215,7 @@ namespace Aurora::IO::FS
return {};
}
auto err = CachedStat(pathEx.c_str(), &s);
auto err = CachedStat(pathEx, &s);
if (err == -1)
{
return {};
@ -212,7 +224,7 @@ namespace Aurora::IO::FS
return AuString(fmt::format("/sys/dev/block/{}:{}", major(s.st_dev), minor(s.st_dev)));
}
static AuString GetSysDevFromDev(const AuString &path)
static AuString GetSysDevFromDev(const AuROString &path)
{
struct stat s;
if (path.empty())
@ -220,7 +232,7 @@ namespace Aurora::IO::FS
return {};
}
auto err = CachedStat(path.c_str(), &s);
auto err = CachedStat(path, &s);
if (err == -1)
{
return {};
@ -234,7 +246,7 @@ namespace Aurora::IO::FS
return AuString(fmt::format("/sys/dev/block/{}:{}", major(s.st_rdev), minor(s.st_rdev)));
}
static AuString MagicPathRd(const AuString &shortLogical)
static AuString MagicPathRd(const AuROString &shortLogical)
{
if (auto optLink = ReadLink(shortLogical))
{
@ -257,7 +269,7 @@ namespace Aurora::IO::FS
}
}
static AuString MagicPath(const AuString &path)
static AuString MagicPath(const AuROString &path)
{
auto shortLogical = GetSysDevFromPathLogical(path);
if (shortLogical.empty())
@ -269,7 +281,7 @@ namespace Aurora::IO::FS
}
// isnt posshit a nice family of os?
static AuString GetSysDevFromPathPhysical(const AuString &path)
static AuString GetSysDevFromPathPhysical(const AuROString &path)
{
if (AuStartsWith(path, "/dev/"))
{
@ -311,7 +323,7 @@ namespace Aurora::IO::FS
return {};
}
static AuString GetDevParent(const AuString &str)
static AuString GetDevParent(const AuROString &str)
{
auto b = GetSysDevFromDev(str);
auto slavesDir = fmt::format("{}/slaves", b);
@ -418,7 +430,7 @@ namespace Aurora::IO::FS
return ret;
}
static bool ReadIsROFromPartition(const AuString &path)
static bool ReadIsROFromPartition(const AuROString &path)
{
if (auto optFile = ReadPosixFile(fmt::format("{}/ro", path)))
{
@ -520,7 +532,7 @@ namespace Aurora::IO::FS
return uuids::uuid(hash.begin(), hash.end());
}
AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuString &path)
AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuROString &path)
{
try
{
@ -551,7 +563,7 @@ namespace Aurora::IO::FS
}
}
AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuString &fileOrDirPath)
AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuROString &fileOrDirPath)
{
try
{
@ -576,7 +588,7 @@ namespace Aurora::IO::FS
}
}
AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuString &root)
AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuROString &root)
{
try
{
@ -589,7 +601,7 @@ namespace Aurora::IO::FS
}
}
AUKN_SYM AuUInt32 GetLogicalSectorSizeFromPath(const AuString &path)
AUKN_SYM AuUInt32 GetLogicalSectorSizeFromPath(const AuROString &path)
{
struct statvfs data;
@ -608,7 +620,7 @@ namespace Aurora::IO::FS
return data.f_bsize;
}
AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuString &path)
AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuROString &path)
{
try
{
@ -638,7 +650,7 @@ namespace Aurora::IO::FS
}
}
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuString &logicalMountPath)
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuROString &logicalMountPath)
{
try
{
@ -677,7 +689,7 @@ namespace Aurora::IO::FS
}
}
AUKN_SYM AuUInt64 GetDeviceSizeInBytes(const AuString &physicalDevicePath)
AUKN_SYM AuUInt64 GetDeviceSizeInBytes(const AuROString &physicalDevicePath)
{
try
{
@ -716,7 +728,7 @@ namespace Aurora::IO::FS
}
}
AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuString &path)
AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuROString &path)
{
try
{
@ -747,7 +759,7 @@ namespace Aurora::IO::FS
}
}
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuString &path)
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuROString &path)
{
struct statvfs data;
@ -1583,7 +1595,7 @@ namespace Aurora::IO::FS
return devices;
}
AUKN_SYM AuString GetRootFromPath(const AuString &path)
AUKN_SYM AuString GetRootFromPath(const AuROString &path)
{
AuString ret;

View File

@ -36,7 +36,7 @@ namespace Aurora::IO::FS
static AuString PathToMount(const AuString &root);
AUKN_SYM AuString GetRootFromPath(const AuString &path)
AUKN_SYM AuString GetRootFromPath(const AuROString &path)
{
auto widePath = Locale::ConvertFromUTF8(NormalizePathRet(path));
#if defined(AURORA_PLATFORM_WIN32)
@ -61,12 +61,12 @@ namespace Aurora::IO::FS
#endif
}
AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuString &path)
AUKN_SYM AuResult<AuString> GetDeviceFromPath(const AuROString &path)
{
return GetDeviceFromRoot(GetRootFromPath(path));
}
AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuString &fileOrDirPath)
AUKN_SYM AuResult<AuString> GetLogicalMountFromPath(const AuROString &fileOrDirPath)
{
auto root = GetRootFromPath(fileOrDirPath);
@ -91,7 +91,7 @@ namespace Aurora::IO::FS
return AuString(utf8Root);
}
AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuString& root)
AUKN_SYM AuResult<AuString> GetDeviceFromRoot(const AuROString &root)
{
VOLUME_DISK_EXTENTS extents;
DWORD dwBytesWritten {};
@ -104,6 +104,11 @@ namespace Aurora::IO::FS
}
auto widePath = Locale::ConvertFromUTF8(utf8Root);
if (widePath.empty() && utf8Root.size())
{
SysPushErrorMemory();
return {};
}
if (::GetDriveTypeW(Locale::ConvertFromUTF8(utf8Root2).data()) != DRIVE_FIXED)
{
@ -161,7 +166,7 @@ namespace Aurora::IO::FS
}
}
static AuUInt32 GetSectorSizeFromPathFromDevice(const AuString &path, bool bIsLogical)
static AuUInt32 GetSectorSizeFromPathFromDevice(const AuROString &path, bool bIsLogical)
{
DISK_GEOMETRY_EX geo {};
DWORD cbBytesReturned;
@ -256,7 +261,7 @@ namespace Aurora::IO::FS
}
}
AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuString &path)
AUKN_SYM AuUInt32 GetPerformanceBufferSizeFromPath(const AuROString &path)
{
if (kBUsePerformantIoRecommendation)
{
@ -289,12 +294,12 @@ namespace Aurora::IO::FS
}
}
AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuString &path)
AUKN_SYM AuUInt32 GetPhysicalSectorSizeFromPath(const AuROString &path)
{
return GetSectorSizeFromPathFromDevice(path, false);
}
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuString &path)
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromPath(const AuROString &path)
{
auto rootPath = GetLogicalMountFromPath(path);
if (!rootPath)
@ -305,7 +310,7 @@ namespace Aurora::IO::FS
return GetLogicalUsedFromLogicalDevice(rootPath.GetResult());
}
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuString &logicalMountPath)
AUKN_SYM LogicalUsedResponse GetLogicalUsedFromLogicalDevice(const AuROString &logicalMountPath)
{
auto widePath = Locale::ConvertFromUTF8(logicalMountPath);
@ -1035,12 +1040,12 @@ namespace Aurora::IO::FS
}
#endif
AUKN_SYM AuString TrySimplifyDevicePath(const AuString &deviceOrLogicalMountPath)
AUKN_SYM AuString TrySimplifyDevicePath(const AuROString &deviceOrLogicalMountPath)
{
#if defined(AURORA_PLATFORM_WIN32)
return ResolveObjSymLink(deviceOrLogicalMountPath);
return ResolveObjSymLink(AuString(deviceOrLogicalMountPath));
#else
return deviceOrLogicalMountPath;
return AuString(deviceOrLogicalMountPath);
#endif
}

View File

@ -22,7 +22,7 @@ namespace Aurora::IO::FS
});
}
AUKN_SYM AuResult<AuString> GetDeviceModel(const AuString &physicalDevicePath)
AUKN_SYM AuResult<AuString> GetDeviceModel(const AuROString &physicalDevicePath)
{
InitPlatformFSCacheAtLoad();
@ -39,7 +39,7 @@ namespace Aurora::IO::FS
return {};
}
AUKN_SYM AuResult<FSDevice> GetFSDeviceByFilePath(const AuString &path)
AUKN_SYM AuResult<FSDevice> GetFSDeviceByFilePath(const AuROString &path)
{
AuPair<AuUInt, const FSDevice *> lastDev =
AuMakePair<AuUInt, const FSDevice *>(0, nullptr);
@ -87,7 +87,7 @@ namespace Aurora::IO::FS
return gCachedDevices;
}
AUKN_SYM AuResult<FSDevice> GetFSDeviceByDevice(const AuString &physicalDevicePath)
AUKN_SYM AuResult<FSDevice> GetFSDeviceByDevice(const AuROString &physicalDevicePath)
{
InitPlatformFSCacheAtLoad();

View File

@ -32,6 +32,12 @@ namespace Aurora::IO::FS
static AuString gAdminWritableAppDirectory;
static AuString gProgramsFolder;
static AuString gApplicationData;
static AuString gUserShellDocuments;
static AuString gUserShellDownloads;
static AuString gUserShellPhotos;
static AuString gUserShellVideos;
static AuString gUserShellMusic;
static AuString gUserShellDesktop;
static AuOptional<AuString> gSystemLibPath;
static AuOptional<AuString> gSystemLibPath2;
static AuOptional<AuString> gUserLibPath;
@ -48,21 +54,21 @@ namespace Aurora::IO::FS
// we don't have any good examples of home family computer-esc posix machines
static const char * kUnixAppData {"/var"};
AUKN_SYM AuOptional<const AuString &> GetSystemDomain()
AUKN_SYM AuOptional<AuROString> GetSystemDomain()
{
return gApplicationData.size() ?
gApplicationData :
AuOptional<const AuString &> {};
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<const AuString &> GetProfileDomain()
AUKN_SYM AuOptional<AuROString> GetProfileDomain()
{
return gHomeDirectory.size() ?
gHomeDirectory :
AuOptional<const AuString &> {};
AuOptional<AuROString> {};
}
AUKN_SYM bool GetSystemResourcePath(const AuString &fileName, AuString &path)
AUKN_SYM bool GetSystemResourcePath(const AuROString &fileName, AuString &path)
{
path.clear();
@ -72,44 +78,52 @@ namespace Aurora::IO::FS
return false;
}
#if defined(AU_CFG_ID_INTERNAL) || defined(AU_CFG_ID_DEBUG)
try
{
AuString tempPath;
if (Process::GetWorkingDirectory(tempPath))
#if defined(AU_CFG_ID_INTERNAL) || defined(AU_CFG_ID_DEBUG)
{
tempPath += "/" + fileName;
if (FileExists(tempPath))
AuString tempPath;
if (Process::GetWorkingDirectory(tempPath))
{
path = tempPath;
return true;
tempPath += "/" + fileName;
if (FileExists(tempPath))
{
path = tempPath;
return true;
}
}
}
}
#endif
#endif
{
if (auto pProcPath = Process::GetProcessDirectory())
{
auto tempPath = *pProcPath + "/" + fileName;
if (FileExists(tempPath))
{
path = tempPath;
return true;
}
}
}
{
if (auto optPackagePath = GetPackagePath())
{
auto tempPath = *optPackagePath + "/" + fileName;
if (auto pProcPath = Process::GetProcessDirectory())
{
auto tempPath2 = *pProcPath + "/" + fileName;
if (tempPath2 == tempPath)
auto tempPath = AuString(*pProcPath) + "/" + AuString(fileName);
if (FileExists(tempPath))
{
// nop
path = tempPath;
return true;
}
}
}
{
if (auto optPackagePath = GetPackagePath())
{
auto tempPath = AuString(*optPackagePath) + "/" + AuString(fileName);
if (auto pProcPath = Process::GetProcessDirectory())
{
auto tempPath2 = AuString(*pProcPath) + "/" + AuString(fileName);
if (tempPath2 == tempPath)
{
// nop
}
else if (FileExists(tempPath))
{
path = tempPath;
return true;
}
}
else if (FileExists(tempPath))
{
@ -117,45 +131,44 @@ namespace Aurora::IO::FS
return true;
}
}
else if (FileExists(tempPath))
}
#if defined(AU_CFG_ID_SHIP)
{
AuString tempPath;
if (Process::GetWorkingDirectory(tempPath))
{
path = tempPath;
tempPath += "/" + fileName;
if (FileExists(tempPath))
{
path = tempPath;
return true;
}
}
}
#endif
{
auto systemPath = gHomeDirectory + AuString(fileName);
if (FileExists(systemPath))
{
path = systemPath;
return true;
}
}
{
auto systemPath = gApplicationData + AuString(fileName);
if (FileExists(systemPath))
{
path = systemPath;
return true;
}
}
}
#if defined(AU_CFG_ID_SHIP)
catch (...)
{
AuString tempPath;
if (Process::GetWorkingDirectory(tempPath))
{
tempPath += "/" + fileName;
if (FileExists(tempPath))
{
path = tempPath;
return true;
}
}
}
#endif
{
auto systemPath = gHomeDirectory + fileName;
if (FileExists(systemPath))
{
path = systemPath;
return true;
}
}
{
auto systemPath = gApplicationData + fileName;
if (FileExists(systemPath))
{
path = systemPath;
return true;
}
SysPushErrorCatch();
}
return false;
@ -175,9 +188,30 @@ namespace Aurora::IO::FS
return CSIDL_COMMON_APPDATA;
}
if (rfid == FOLDERID_Documents)
if (rfid == FOLDERID_Documents ||
rfid == FOLDERID_Downloads)
{
return CSIDL_COMMON_DOCUMENTS;
return CSIDL_MYDOCUMENTS;
}
if (rfid == FOLDERID_Music)
{
return CSIDL_MYMUSIC;
}
if (rfid == FOLDERID_Pictures)
{
return CSIDL_MYPICTURES;
}
if (rfid == FOLDERID_Desktop)
{
return CSIDL_DESKTOP;
}
if (rfid == FOLDERID_Videos)
{
return CSIDL_MYVIDEO;
}
if (rfid == FOLDERID_System ||
@ -194,7 +228,6 @@ namespace Aurora::IO::FS
return {};
}
static AuString GetSpecialDirOldOS(REFKNOWNFOLDERID rfid)
{
if (!pSHGetFolderPathA)
@ -214,7 +247,7 @@ namespace Aurora::IO::FS
return "";
}
static AuString GetSpecialDir(REFKNOWNFOLDERID rfid)
static AuString GetSpecialDir(REFKNOWNFOLDERID rfid, bool bNoThrow = false)
{
PWSTR directory;
@ -231,10 +264,11 @@ namespace Aurora::IO::FS
return str;
}
if (rfid == FOLDERID_UserProgramFiles)
if (rfid == FOLDERID_UserProgramFiles || bNoThrow)
{
return "";
}
SysPanic("Couldn't get known special directory path of [MS:{}-{}-{}-{}{}{}{}{}{}{}{}] with a NULL access token",
rfid.Data1, rfid.Data2, rfid.Data3, rfid.Data4[0], rfid.Data4[1], rfid.Data4[2], rfid.Data4[3], rfid.Data4[4], rfid.Data4[5], rfid.Data4[6], rfid.Data4[7]);
}
@ -250,17 +284,17 @@ namespace Aurora::IO::FS
static void SetNamespaceDirectories()
{
gHomeDirectory = GetSpecialDir(FOLDERID_RoamingAppData);
gApplicationData = GetSpecialDir(FOLDERID_ProgramData);
gHomeDirectory = GetSpecialDir(FOLDERID_RoamingAppData);
gApplicationData = GetSpecialDir(FOLDERID_ProgramData);
if constexpr (AuBuild::IsPlatformX32())
{
gSystemLibPath = GetSpecialDir(FOLDERID_SystemX86);
gSystemLibPath = GetSpecialDir(FOLDERID_SystemX86);
}
else
{
gSystemLibPath = GetSpecialDir(FOLDERID_System);
gSystemLibPath = GetSpecialDir(FOLDERID_System);
}
gUserHomeDirectory = GetSpecialDir(FOLDERID_Profile);
gUserHomeDirectory = GetSpecialDir(FOLDERID_Profile);
gAdminWritableAppDirectory = gApplicationData;
gUserWritableAppData = gHomeDirectory;
gProgramsFolder = AuSwInfo::IsWindows7OrGreater() ? GetSpecialDir(FOLDERID_UserProgramFiles) : "";
@ -278,6 +312,13 @@ namespace Aurora::IO::FS
}
}
gUserShellDocuments = GetSpecialDir(FOLDERID_Documents, true);
gUserShellDownloads = GetSpecialDir(FOLDERID_Downloads, true);
gUserShellPhotos = GetSpecialDir(FOLDERID_Pictures, true);
gUserShellVideos = GetSpecialDir(FOLDERID_Videos, true);
gUserShellMusic = GetSpecialDir(FOLDERID_Music, true);
gUserShellDesktop = GetSpecialDir(FOLDERID_Desktop, true);
if (pGetTempPathW)
{
wchar_t tempPath[2048];
@ -341,6 +382,20 @@ namespace Aurora::IO::FS
}
}
static void SetPosixOptionalUserShellDir(AuString &str, const AuROString &suffix)
{
AuString strA = gUserHomeDirectory + "/" + AuString({ AuToUpper(suffix[0]) }) + AuString(suffix.SubStr(1));
AuString strB = gUserHomeDirectory + "/" + AuString({ AuToLower(suffix[0]) }) + AuString(suffix.SubStr(1));
if (AuFS::DirExists(strA))
{
str = strA;
}
else if (AuFS::DirExists(strB))
{
str = strB;
}
}
static void SetNamespaceDirectories()
{
const char *homedir;
@ -371,6 +426,17 @@ namespace Aurora::IO::FS
gAdminWritableAppDirectory = kUnixAppData;
gUserWritableAppData = gApplicationData;
SetPosixOptionalUserShellDir(gUserShellDocuments, "Documents");
SetPosixOptionalUserShellDir(gUserShellDownloads, "Downloads");
SetPosixOptionalUserShellDir(gUserShellPhotos, "Pictures");
SetPosixOptionalUserShellDir(gUserShellVideos, "Videos");
SetPosixOptionalUserShellDir(gUserShellMusic, "Music");
SetPosixOptionalUserShellDir(gUserShellDesktop, "Desktop");
// Android: gApplicationData = ANativeActivity::internalDataPath
// Android: gHomeDirectory = ANativeActivity::externalDataPath (?)
// Android: SetPosixOptionalUserShellDir maybe overload the home path with emulated 0 DCIM if we have external file permissions? externalDataPath?
// iOS Package Dir: CFBundleCopyResourcesDirectoryURL
// iOS/MacOS : NSTemporaryDirectory
#if defined(AURORA_PLATFORM_ANDROID)
gTempDir = "/data/local/tmp/";
@ -504,21 +570,21 @@ namespace Aurora::IO::FS
gApplicationData.clear();
}
AUKN_SYM AuOptional<const AuString &> GetAppData()
AUKN_SYM AuOptional<AuROString> GetAppData()
{
return gUserWritableAppData.size() ?
gUserWritableAppData :
AuOptional<const AuString &> {};
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<const AuString &> GetUserHome()
AUKN_SYM AuOptional<AuROString> GetUserHome()
{
return gUserHomeDirectory.size() ?
gUserHomeDirectory :
AuOptional<const AuString &> {};
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<const AuString &> GetPackagePath()
AUKN_SYM AuOptional<AuROString> GetPackagePath()
{
// TODO: iOS/mac OS -> CFBundleCopyResourcesDirectoryURL
if (auto optProcessDirectory = Process::GetProcessDirectory())
@ -526,86 +592,156 @@ namespace Aurora::IO::FS
return optProcessDirectory;
}
return AuOptional<const AuString &>{};
return AuOptional<AuROString>{};
}
AUKN_SYM AuOptional<const AuString &> GetWritableAppdata()
AUKN_SYM AuOptional<AuROString> GetWritableAppdata()
{
return gGlobalWritableAppDirectory.size() ?
gGlobalWritableAppDirectory :
AuOptional<const AuString &> {};
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<const AuString &> GetRootAppdata()
AUKN_SYM AuOptional<AuROString> GetRootAppdata()
{
return gAdminWritableAppDirectory.size() ?
gAdminWritableAppDirectory :
AuOptional<const AuString &> {};
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<const AuString &> GetUserProgramsFolder()
AUKN_SYM AuOptional<AuROString> GetUserProgramsFolder()
{
return gProgramsFolder.size() ?
gProgramsFolder :
AuOptional<const AuString &> {};
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserDocuments()
{
return gUserShellDocuments.size() ?
gUserShellDocuments :
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserDesktop()
{
return gUserShellDesktop.size() ?
gUserShellDesktop :
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserPhotos()
{
return gUserShellPhotos.size() ?
gUserShellPhotos :
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserVideos()
{
return gUserShellVideos.size() ?
gUserShellVideos :
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserMusic()
{
return gUserShellMusic.size() ?
gUserShellMusic :
AuOptional<AuROString> {};
}
AUKN_SYM AuOptional<AuROString> GetUserDownloads()
{
return gUserShellDownloads.size() ?
gUserShellDownloads :
GetUserDocuments();
}
AUKN_SYM AuOptional<AuString> NewTempFile()
{
AuString path;
path = gTempDir;
if (path.empty())
try
{
SysPushErrorUninitialized();
AuString path;
path = gTempDir;
if (path.empty())
{
SysPushErrorUninitialized();
return {};
}
path += fmt::format("TempFile_{}", AuRNG::ReadString(64, AuRNG::ERngStringCharacters::eAlphaNumericCharacters));
if (!AuFS::WriteNewFile(path, {}))
{
SysPushErrorIO();
return {};
}
auto normalizedPath = AuFS::NormalizePathRet(path);
if (normalizedPath.empty() && path.size())
{
SysPushErrorMemory();
return {};
}
#if defined(AURORA_PLATFORM_WIN32)
auto widePath = AuLocale::ConvertFromUTF8(normalizedPath);
MoveFileExW(widePath.c_str(), nullptr, MOVEFILE_DELAY_UNTIL_REBOOT);
#endif
return normalizedPath;
}
catch (...)
{
// I hate C++ strings
SysPushErrorCatch();
return {};
}
path += fmt::format("TempFile_{}", AuRNG::ReadString(64, AuRNG::ERngStringCharacters::eAlphaNumericCharacters));
if (!AuFS::WriteNewFile(path, {}))
{
SysPushErrorIO();
return {};
}
auto normalizedPath = AuFS::NormalizePathRet(path);
#if defined(AURORA_PLATFORM_WIN32)
auto widePath = AuLocale::ConvertFromUTF8(normalizedPath);
MoveFileExW(widePath.c_str(), nullptr, MOVEFILE_DELAY_UNTIL_REBOOT);
#endif
return normalizedPath;
}
AUKN_SYM AuOptional<AuString> NewTempDirectory()
{
AuString path;
path = gTempDir;
if (path.empty())
try
{
SysPushErrorUninitialized();
AuString path;
path = gTempDir;
if (path.empty())
{
SysPushErrorUninitialized();
return {};
}
path += fmt::format("TempDirectory_{}", AuRNG::ReadString(32, AuRNG::ERngStringCharacters::eAlphaNumericCharacters));
if (!_MkDir(path))
{
SysPushErrorIO();
return {};
}
auto normalizedPath = AuFS::NormalizePathRet(path);
if (normalizedPath.empty() && path.size())
{
SysPushErrorMemory();
return {};
}
#if defined(AURORA_PLATFORM_WIN32)
auto widePath = AuLocale::ConvertFromUTF8(normalizedPath);
MoveFileExW(widePath.c_str(), nullptr, MOVEFILE_DELAY_UNTIL_REBOOT);
#endif
return normalizedPath + AuString(1, kPathSplitter);
}
catch (...)
{
// I hate C++ strings
SysPushErrorCatch();
return {};
}
path += fmt::format("TempDirectory_{}", AuRNG::ReadString(32, AuRNG::ERngStringCharacters::eAlphaNumericCharacters));
if (!_MkDir(path))
{
SysPushErrorIO();
return {};
}
auto normalizedPath = AuFS::NormalizePathRet(path);
#if defined(AURORA_PLATFORM_WIN32)
auto widePath = AuLocale::ConvertFromUTF8(normalizedPath);
MoveFileExW(widePath.c_str(), nullptr, MOVEFILE_DELAY_UNTIL_REBOOT);
#endif
return normalizedPath + AuString(1, kPathSplitter);
}
#if defined(AURORA_PLATFORM_WIN32)

View File

@ -259,7 +259,7 @@ namespace Aurora::Process
return true;
}
AUKN_SYM AuOptional<const AuString &> GetProcessName()
AUKN_SYM AuOptional<AuROString> GetProcessName()
{
const AuString *pModule, *pPartial, *pFull;
@ -280,7 +280,7 @@ namespace Aurora::Process
return {};
}
AUKN_SYM AuOptional<const AuString &> GetProcessDirectory()
AUKN_SYM AuOptional<AuROString> GetProcessDirectory()
{
const AuString *pModule, *pPartial, *pFull;
@ -316,7 +316,7 @@ namespace Aurora::Process
return {};
}
AUKN_SYM AuOptional<const AuString &> GetProcessFullPath()
AUKN_SYM AuOptional<AuROString> GetProcessFullPath()
{
const AuString *pModule, *pPartial, *pFull;

View File

@ -39,6 +39,10 @@
namespace Aurora::Process
{
// Because we're only protecting gModuleHandles in practice, and we cannot fuck up any iterator handles, we can use renterable mutexes.
// We only use AuTryFind/AuTryInsert for the most part.
// The only iterators created for gModuleHandles call out to apis that should not allow for further recursion.
// So we should be fine.
static AuCriticalSection gSpinLock;
static AuList<AuString> gClassPath;
static AuHashMap<AuString, void *> gModuleHandles;
@ -102,18 +106,18 @@ namespace Aurora::Process
static AuString ConstructAuDllSuffixUncached()
{
auto platform = GetPlatformString(Build::kCurrentPlatform);
auto platform = GetPlatformString(Build::kCurrentPlatform);
auto architecture = GetArchString(Build::kCurrentArchitecture);
auto ext = GetPlatformExt(Build::kCurrentPlatform);
auto ext = GetPlatformExt(Build::kCurrentPlatform);
AuString ret;
#if defined(DEBUG)
ret += ".Debug";
ret = ".Debug";
#elif defined(STAGING)
ret += ".Stage";
ret = ".Stage";
#elif defined(SHIP)
ret += ".Ship";
ret = ".Ship";
#endif
if (platform)
@ -134,28 +138,47 @@ namespace Aurora::Process
return ret;
}
AUKN_SYM const AuString& ConstructAuDllSuffix()
AUKN_SYM AuROString GetViewOfAuroraDLLSuffix()
{
static AuString dllSuffixString {};
static AuInitOnce gInitOnce;
gInitOnce.Call([]
gInitOnce.TryCall([]
{
dllSuffixString = ConstructAuDllSuffixUncached();
try
{
dllSuffixString = ConstructAuDllSuffixUncached();
return true;
}
catch (...)
{
// I hate C++ strings so much
return false;
}
});
return dllSuffixString;
}
AUKN_SYM AuROString GetViewOfDynamicLibraryExtensionSuffix()
{
return GetPlatformExt(Build::kCurrentPlatform);
}
AUKN_SYM AuROString GetViewOfArchitectureSuffix()
{
return GetArchString(Build::kCurrentArchitecture);
}
static AuString GetModuleNameFromFileName(const AuString &filename)
{
static const auto &kStringSuffixA = ConstructAuDllSuffix();
static const auto kStringSuffixA = GetViewOfAuroraDLLSuffix();
static const auto kStringSuffixB = GetPlatformExt(Build::kCurrentPlatform);
if (filename.ends_with(kStringSuffixA))
if (AuEndsWith(filename, kStringSuffixA))
{
return filename.substr(0, filename.size() - kStringSuffixA.size());
}
if (filename.ends_with(kStringSuffixB))
if (AuEndsWith(filename, kStringSuffixB))
{
return filename.substr(0, filename.size() - strlen(kStringSuffixB));
}
@ -292,12 +315,13 @@ namespace Aurora::Process
}
#endif
static void *LoadModule(const AuString &name, const AuString &path)
static void *LoadModule(const AuROString &name, const AuROString &path)
{
auto itr = gModuleHandles.find(path);
if (itr != gModuleHandles.end())
void *pFound {};
if (AuTryFind(gModuleHandles, path, pFound))
{
return itr->second;
return pFound;
}
#if defined(AURORA_IS_MODERNNT_DERIVED)
@ -322,8 +346,8 @@ namespace Aurora::Process
#endif
auto pRet = (void *)handle;
gModuleHandles.insert(AuMakePair(name, pRet));
gModuleHandles.insert(AuMakePair(path, pRet));
gModuleHandles.insert(AuMakePair(AuMove(AuString(name)), AuConstReference(pRet)));
gModuleHandles.insert(AuMakePair(AuMove(AuString(path)), AuConstReference(pRet)));
return pRet;
}
@ -338,9 +362,20 @@ namespace Aurora::Process
fail = false;
auto pathNrml = AuIOFS::NormalizePathRet(path);
if (pathNrml.empty() && path.size())
{
SysPushErrorMemory();
return nullptr;
}
#if defined(AURORA_IS_MODERNNT_DERIVED)
auto widePath = Locale::ConvertFromUTF8(pathNrml);
if (widePath.empty() && pathNrml.size())
{
SysPushErrorMemory();
return nullptr;
}
auto mitigateTimeOfUse = Win32Open(widePath.c_str(), GENERIC_READ, FILE_SHARE_READ, false, OPEN_EXISTING, 0, 0);
if (mitigateTimeOfUse == INVALID_HANDLE_VALUE)
@ -351,6 +386,11 @@ namespace Aurora::Process
}
auto absPath = AuIOFS::NormalizePathRet(abs);
if (absPath.empty() && abs.size())
{
SysPushErrorMemory();
return nullptr;
}
#endif
if (request.verify || ((kIsMainSigned || request.forceMitigations) && request.enableMitigations))
@ -404,10 +444,10 @@ namespace Aurora::Process
return returnValue;
}
static void *TryLoadModule(const AuString &path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request, bool &fail)
static void *TryLoadModuleNTC(const AuString &path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request, bool &fail)
{
AuString a = path + AuString({ AuFS::kPathSplitter }) + auDll;
AuString b = path + AuString({ AuFS::kPathSplitter }) + genericDll;
AuString a = AuString(path) + AuString({ AuFS::kPathSplitter }) + AuString(auDll);
AuString b = AuString(path) + AuString({ AuFS::kPathSplitter }) + AuString(genericDll);
#if defined(AURORA_IS_MODERNNT_DERIVED)
#if defined(AURORA_PLATFORM_WIN32)
@ -430,8 +470,8 @@ namespace Aurora::Process
}
#endif
AuString aAbs = path + AuString({ AuFS::kPathSplitter }) + auDll + ".";
AuString bAbs = path + AuString({ AuFS::kPathSplitter }) + genericDll + ".";
AuString aAbs = AuString(path) + /*SOO save us pls*/ AuString({ AuFS::kPathSplitter }) + auDll + ".";
AuString bAbs = AuString(path) + /*SOO save us pls*/ AuString({ AuFS::kPathSplitter }) + genericDll + ".";
#endif
if (AuIOFS::FileExists(a))
@ -459,17 +499,29 @@ namespace Aurora::Process
return {};
}
static void *TryLoadModule(const AuString &path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request, bool &fail)
{
// TODO: need safe string container
try
{
return TryLoadModuleNTC(path, auDll, genericDll, request, fail);
}
catch (...)
{
return {};
}
}
static void *TryLoadModule(EModulePath path, const AuString &auDll, const AuString &genericDll, const ModuleLoadRequest &request)
{
AuString pathA, pathB;
AuList<AuString> arrayPaths;
AuList<AuString> *pArrayPaths {};
switch (path)
{
case EModulePath::eClassPath:
{
AU_LOCK_GLOBAL_GUARD(gSpinLock);
arrayPaths = gClassPath;
pArrayPaths = &gClassPath;
break;
}
case EModulePath::eModulePathCWD:
@ -553,16 +605,21 @@ namespace Aurora::Process
}
}
for (const auto &dir : arrayPaths)
if (pArrayPaths)
{
if (auto pRet = TryLoadModule(dir, auDll, genericDll, request, fail))
{
return pRet;
}
AU_LOCK_GLOBAL_GUARD(gSpinLock);
if (fail)
for (const auto &dir : *pArrayPaths)
{
return {};
if (auto pRet = TryLoadModule(dir, auDll, genericDll, request, fail))
{
return pRet;
}
if (fail)
{
return {};
}
}
}
@ -594,30 +651,43 @@ namespace Aurora::Process
{
AU_LOCK_GLOBAL_GUARD(gSpinLock);
auto h = gModuleHandles.find(request.mod);
if (h != gModuleHandles.end())
void *pFound {};
if (AuTryFind(gModuleHandles, request.mod, pFound))
{
return h->second;
return pFound;
}
auto au = request.mod + ConstructAuDllSuffix();
auto base = request.mod;
auto ext = GetPlatformExt(Build::kCurrentPlatform);
if (ext && !Build::kIsNtDerived)
// TODO: need safe string container
AuString base, au;
const char *ext {};
try
{
base += ext;
base = AuString(request.mod);
au = base + AuString(GetViewOfAuroraDLLSuffix());
ext = GetPlatformExt(Build::kCurrentPlatform);
if (ext && !Build::kIsNtDerived)
{
base += ext;
}
if (request.version.size())
{
au += "." + request.version;
base += "." + request.version;
}
if (ext && Build::kIsNtDerived)
{
base += ext;
}
}
if (request.version.size())
catch (...)
{
au += "." + request.version;
base += "." + request.version;
}
if (ext && Build::kIsNtDerived)
{
base += ext;
// stupid unsafe strings
SysPushErrorMemory();
return {};
}
auto searchPath = request.searchPath ? request.searchPath : &kUserOverloadableSearchPath;
@ -632,7 +702,7 @@ namespace Aurora::Process
return {};
}
AUKN_SYM AuMach GetProcAddressEx(void *pHandle, const AuString &symbol)
AUKN_SYM AuMach GetProcAddressEx(void *pHandle, const AuRONString &symbol)
{
AuMach ret {};
@ -706,21 +776,22 @@ namespace Aurora::Process
return ret;
}
AUKN_SYM void *GetProcHandle(const AuString &name)
AUKN_SYM void *GetProcHandle(const AuROString &name)
{
AU_LOCK_GLOBAL_GUARD(gSpinLock);
auto h = gModuleHandles.find(name);
if (h == gModuleHandles.end())
void *pFound {};
if (!AuTryFind(gModuleHandles, name, pFound))
{
SysPushErrorGen("Module {} is not loaded", name);
return {};
}
return h->second;
return pFound;
}
AUKN_SYM AuMach GetProcAddress(const AuString &mod, const AuString &symbol)
AUKN_SYM AuMach GetProcAddress(const AuROString &mod, const AuRONString &symbol)
{
if (mod.empty())
{
@ -771,10 +842,14 @@ namespace Aurora::Process
AuList<void *> cookieList;
#if defined(AURORA_PLATFORM_WIN32)
for (const auto dir : dirs)
for (const auto &dir : dirs)
{
void *pCookie {};
// Yay I love required nevis era plugin load fighting
// MSDN still states this function should be dynamically loaded for some KB that probably wont work on Vista or 7.
// Also, GNU LibC - the architectures ld linker, cannot keep track of preload directory lists.
// So for older Win32 targets, and POSIX, we have to....
if (pRemoveDllDirectory)
{
if (pAddDllDirectory)
@ -787,7 +862,10 @@ namespace Aurora::Process
}
#endif
for (const auto dir : dirs)
// ...just try to probe every file manually.
// ...and later on, try to load each file again manually by full real path
// This makes sure we have future basic dependencies loaded of LoadModuleXXX calls, at the very least, we hope.
for (const auto &dir : dirs)
{
AuList<AuString> files;
AuList<AuString> sharedObjects;
@ -798,13 +876,13 @@ namespace Aurora::Process
continue;
}
auto endingPattern = ConstructAuDllSuffix();
auto endingPattern = GetViewOfAuroraDLLSuffix();
auto endingAlt = GetPlatformExt(Build::kCurrentPlatform);
for (const auto &file : files)
{
if (!(file.ends_with(endingPattern.c_str()) ||
file.ends_with(endingAlt)))
if (!(AuEndsWith(file, endingPattern) ||
AuEndsWith(file, endingAlt)))
{
continue;
}
@ -840,7 +918,10 @@ namespace Aurora::Process
}
auto modName = GetModuleNameFromFileName(sharedDLL);
AuLogDbg("[attempt] Loading shared object: {} (path: {})", modName, sharedDLL);
//AuLogDbg("[attempt] Loading shared object: {} (path: {})", modName, sharedDLL);
//This got really spammy some time
//Best just keep dynamic loads as a singular verbose, "hey dipshit, this file actually managed to get into our address space"
//...
bool fail {};
ModuleLoadRequest request { AuList<AuString>{ dir }, modName };
@ -855,7 +936,8 @@ namespace Aurora::Process
{
if (!fail)
{
AuLogDbg("[attempt] Loaded shared object: {} (path: {})", modName, sharedDLL);
//..here
AuLogDbg("[attempt] Loaded shared object: {} (path: {})", modName, sharedDLL); //get hacked retard
uSuccess++;
itr = sharedObjects.erase(itr);
}
@ -888,7 +970,7 @@ namespace Aurora::Process
#endif
}
static void PreloadDLLs(const AuString &dir)
static void PreloadDLLs(const AuROString &dir)
{
AU_DEBUG_MEMCRUNCH;
if (gRuntimeConfig.processConfig.bAlwaysPreloadEntireClassPath)
@ -897,17 +979,17 @@ namespace Aurora::Process
}
else
{
PreloadDLLsDoOnce({ dir });
PreloadDLLsDoOnce({ AuString(dir) });
}
}
AUKN_SYM bool SetBinaryClassPath(const AuList<AuString> &list, bool preloadAll)
AUKN_SYM bool SetBinaryClassPath(const AuList<AuString> &list, AuOptional<bool> optBoolPreloadAll)
{
AU_DEBUG_MEMCRUNCH;
AU_LOCK_GLOBAL_GUARD(gSpinLock);
AuExchange(gClassPath, list);
if (((preloadAll && gRuntimeConfig.processConfig.bEnablePreload)) ||
if (((optBoolPreloadAll.ValueOr(false) && gRuntimeConfig.processConfig.bEnablePreload)) ||
(gRuntimeConfig.processConfig.bForcePreload))
{
if (gRuntimeConfig.processConfig.bAlwaysPreloadEntireClassPath)
@ -923,16 +1005,16 @@ namespace Aurora::Process
return true;
}
AUKN_SYM bool AddBinaryClassPath(const AuString &dir, bool preloadAll)
AUKN_SYM bool AddBinaryClassPath(const AuROString &dir, AuOptional<bool> optBoolPreloadAll)
{
AU_LOCK_GLOBAL_GUARD(gSpinLock);
if (!AuTryInsert(gClassPath, dir))
if (!AuTryInsert(gClassPath, AuString(dir)))
{
return false;
}
if (((preloadAll && gRuntimeConfig.processConfig.bEnablePreload)) ||
if (((optBoolPreloadAll.ValueOr(false) && gRuntimeConfig.processConfig.bEnablePreload)) ||
(gRuntimeConfig.processConfig.bForcePreload))
{
PreloadDLLs(dir);
@ -943,8 +1025,16 @@ namespace Aurora::Process
AUKN_SYM AuList<AuString> GetBinaryClassPath()
{
AU_LOCK_GLOBAL_GUARD(gSpinLock);
return gClassPath;
try
{
AU_LOCK_GLOBAL_GUARD(gSpinLock);
return gClassPath;
}
catch (...)
{
SysPushErrorMemory();
return {};
}
}
void InitProcess()