AuroraRuntime/Source/IO/FS/Resources.cpp

253 lines
7.0 KiB
C++
Raw Normal View History

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;
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
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;
}
// 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
// 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()
{
#if !defined(AU_NO_AU_HOME_BRANDING)
if (gRuntimeConfig.fio.defaultBrand.size())
2021-09-06 10:58:08 +00:00
{
gApplicationData += "/" + gRuntimeConfig.fio.defaultBrand;
gHomeDirectory += "/" + gRuntimeConfig.fio.defaultBrand;
2021-09-06 10:58:08 +00:00
}
#endif
2021-09-06 10:58:08 +00:00
2021-06-27 21:25:29 +00:00
NormalizePath(gApplicationData);
NormalizePath(gHomeDirectory);
if (gApplicationData == gHomeDirectory)
{
gApplicationData += kPathSplitter;
gHomeDirectory += kPathSplitter;
gApplicationData += "System";
gHomeDirectory += "Profile";
}
2021-06-27 21:25:29 +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();
}
}