2021-06-27 21:25:29 +00:00
/***
Copyright ( C ) 2021 J Reece Wilson ( a / k / a " Reece " ) . All rights reserved .
File : Resources . cpp
Date : 2021 - 6 - 16
Author : Reece
* * */
2021-09-30 14:57:41 +00:00
# include <Source/RuntimeInternal.hpp>
2021-06-27 21:25:29 +00:00
# include "FS.hpp"
# include "Resources.hpp"
# if defined(AURORA_PLATFORM_LINUX)
# include <sys/types.h>
# include <pwd.h>
# include <unistd.h>
# elif defined(AURORA_PLATFORM_WIN32)
# include <ShlObj_core.h>
# endif
namespace Aurora : : IO : : FS
{
static AuString gHomeDirectory ;
static AuString gApplicationData ;
2021-09-06 10:58:08 +00:00
static AuOptional < AuString > gSystemLibPath ;
static AuOptional < AuString > gSystemLibPath2 ;
static AuOptional < AuString > gUserLibPath ;
static AuOptional < AuString > gUserLibPath2 ;
2021-10-15 23:35:49 +00:00
static const AuString kUnixAppData { " /opt " } ;
2021-06-27 21:25:29 +00:00
AUKN_SYM bool GetSystemDomain ( AuString & path )
{
path = gApplicationData ;
return true ;
}
AUKN_SYM bool GetProfileDomain ( AuString & path )
{
path = gHomeDirectory ;
return true ;
}
AUKN_SYM bool GetSystemResourcePath ( const AuString & fileName , AuString & path )
{
path . clear ( ) ;
if ( fileName . find ( " .. " ) ! = AuString : : npos )
{
2021-09-06 10:58:08 +00:00
LogWarn ( " Exploit Attempt? A system resource path may not contain relative directory move tokens: {} " , fileName ) ;
2021-06-27 21:25:29 +00:00
return false ;
}
{
AuString tempPath ;
if ( Process : : GetWorkingDirectory ( tempPath ) )
{
tempPath + = " / " + fileName ;
if ( FileExists ( tempPath ) )
{
path = tempPath ;
return true ;
}
}
}
{
AuString tempPath ;
if ( Process : : GetProcPath ( tempPath ) )
{
tempPath + = " / " + fileName ;
if ( FileExists ( tempPath ) )
{
path = tempPath ;
return true ;
}
}
}
2021-06-30 12:00:32 +00:00
{
auto systemPath = gHomeDirectory + fileName ;
if ( FileExists ( systemPath ) )
{
path = systemPath ;
return true ;
}
}
2021-06-27 21:25:29 +00:00
{
2021-06-30 12:00:32 +00:00
auto systemPath = gApplicationData + fileName ;
2021-06-27 21:25:29 +00:00
if ( FileExists ( systemPath ) )
{
path = systemPath ;
return true ;
}
}
return false ;
}
# if defined(AURORA_PLATFORM_WIN32)
static AuString GetSpecialDir ( REFKNOWNFOLDERID rfid )
{
PWSTR directory ;
if ( SHGetKnownFolderPath ( rfid , KF_FLAG_DEFAULT , NULL , & directory ) ! = S_OK )
{
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 ] ) ;
}
return Locale : : ConvertFromWChar ( directory ) ;
}
2021-09-06 10:58:08 +00:00
2021-06-27 21:25:29 +00:00
static void SetNamespaceDirectories ( )
{
gHomeDirectory = GetSpecialDir ( FOLDERID_RoamingAppData ) ;
gApplicationData = GetSpecialDir ( FOLDERID_ProgramData ) ;
2021-09-06 10:58:08 +00:00
gSystemLibPath = GetSpecialDir ( FOLDERID_System ) ;
2021-06-27 21:25:29 +00:00
}
2021-09-06 10:58:08 +00:00
# elif defined(AURORA_PLATFORM_LINUX) || defined(AURORA_PLATFORM_BSD)
static void SetUnixPaths ( AuOptional < AuString > & primary , AuOptional < AuString > & secondary , const AuString & base )
{
primary = base ;
if ( Aurora : : Build : : IsPlatformX32 ( ) )
{
secondary = base + " 32 " ;
}
else
{
secondary = base + " 64 " ;
}
if ( DirExists ( * secondary ) )
{
std : : swap ( secondary , primary ) ;
}
else
{
secondary . reset ( ) ;
}
if ( ! DirExists ( * primary ) )
{
primary . reset ( ) ;
}
}
2021-06-27 21:25:29 +00:00
2021-11-05 17:34:23 +00:00
static void SetXdg ( AuString & out , const char * envvar , const char * home , const char * defaultHomeExt , const char * fallback )
{
auto value = getenv ( envvar ) ;
if ( value )
{
out = value ;
}
else if ( home )
{
out = AuString ( home ) + defaultHomeExt ;
}
else
{
out = fallback ;
}
}
2021-06-27 21:25:29 +00:00
static void SetNamespaceDirectories ( )
{
const char * homedir ;
homedir = getenv ( " HOME " ) ;
if ( ! homedir )
{
homedir = getpwuid ( getuid ( ) ) - > pw_dir ;
}
2021-11-05 17:34:23 +00:00
// XDG Base Directory Specification
// $XDG_CONFIG_HOME defines the base directory relative to which user-specific configuration files should be stored. If $XDG_CONFIG_HOME is either not set or empty, a default equal to $HOME/.config should be used.
// $XDG_DATA_HOME defines the base directory relative to which user-specific data files should be stored
SetXdg ( gApplicationData , " XDG_CONFIG_HOME " , homedir , " /.config " , kUnixAppData ) ;
SetXdg ( gHomeDirectory , " XDG_DATA_HOME " , homedir , " /.local/share " , " . " ) ;
2021-09-06 10:58:08 +00:00
2021-11-15 19:35:15 +00:00
// https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/
// Arch 2012: https://archlinux.org/news/the-lib-directory-becomes-a-symlink/
// Ubuntu 2018 (mandatory 2021+): https://lists.ubuntu.com/archives/ubuntu-devel-announce/2018-November/001253.html https://wiki.debian.org/UsrMerge
// Fedora (2011?): https://fedoraproject.org/wiki/Features/UsrMove
SetUnixPaths ( gUserLibPath , gUserLibPath2 , " /usr/local/lib " ) ;
SetUnixPaths ( gSystemLibPath , gSystemLibPath2 , " /usr/lib " ) ;
2021-06-27 21:25:29 +00:00
}
# else
static void SetNamespaceDirectories ( )
{
gHomeDirectory = " . " ;
gApplicationData = " . " ;
}
# endif
2021-09-06 10:58:08 +00:00
AuOptional < AuString > GetSystemLibPath ( )
{
return gSystemLibPath ;
}
AuOptional < AuString > GetUserLibPath ( )
{
return gUserLibPath ;
}
AuOptional < AuString > GetSystemLibPath2 ( )
{
return gSystemLibPath2 ;
}
AuOptional < AuString > GetUserLibPath2 ( )
{
return gUserLibPath2 ;
}
2021-06-27 21:25:29 +00:00
static void ChangeDir ( )
{
2021-07-13 13:07:22 +00:00
# if !defined(AU_NO_AU_HOME_BRANDING)
2021-11-05 17:34:23 +00:00
if ( gRuntimeConfig . fio . defaultBrand . size ( ) )
2021-09-06 10:58:08 +00:00
{
2021-11-05 17:34:23 +00:00
gApplicationData + = " / " + gRuntimeConfig . fio . defaultBrand ;
gHomeDirectory + = " / " + gRuntimeConfig . fio . defaultBrand ;
2021-09-06 10:58:08 +00:00
}
2021-07-13 13:07:22 +00:00
# endif
2021-09-06 10:58:08 +00:00
2021-06-27 21:25:29 +00:00
NormalizePath ( gApplicationData ) ;
NormalizePath ( gHomeDirectory ) ;
2021-11-05 17:34:23 +00:00
if ( gApplicationData = = gHomeDirectory )
{
gApplicationData + = kPathSplitter ;
gHomeDirectory + = kPathSplitter ;
gApplicationData + = " System " ;
gHomeDirectory + = " Profile " ;
}
2021-06-27 21:25:29 +00:00
2021-07-13 13:07:22 +00:00
// Noting we append a path splitter to prevent hair pulling over missing path delimiters
// Eg: GetHome() + "myAwesomeApp/Config" = %HOME%/Aurora/ProfilemyAwsomeApp/Config
2021-06-27 21:25:29 +00:00
gApplicationData + = kPathSplitter ;
gHomeDirectory + = kPathSplitter ;
}
void InitResources ( )
{
SetNamespaceDirectories ( ) ;
ChangeDir ( ) ;
}
}