Reece
050f48f9dc
when /lib = sys, /usr/lib = usr/vendor is wrong nowadays: /lib >>SYMLINK>> /usr/lib, /usr/lib = system libraries, /usr/local/lib = vendor.
253 lines
7.0 KiB
C++
253 lines
7.0 KiB
C++
/***
|
|
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: Resources.cpp
|
|
Date: 2021-6-16
|
|
Author: Reece
|
|
***/
|
|
#include <Source/RuntimeInternal.hpp>
|
|
#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;
|
|
static AuOptional<AuString> gSystemLibPath;
|
|
static AuOptional<AuString> gSystemLibPath2;
|
|
static AuOptional<AuString> gUserLibPath;
|
|
static AuOptional<AuString> gUserLibPath2;
|
|
static const AuString kUnixAppData {"/opt"};
|
|
|
|
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)
|
|
{
|
|
LogWarn("Exploit Attempt? A system resource path may not contain relative directory move tokens: {}", fileName);
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
auto systemPath = gHomeDirectory + fileName;
|
|
if (FileExists(systemPath))
|
|
{
|
|
path = systemPath;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
{
|
|
auto systemPath = gApplicationData + fileName;
|
|
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);
|
|
}
|
|
|
|
static void SetNamespaceDirectories()
|
|
{
|
|
gHomeDirectory = GetSpecialDir(FOLDERID_RoamingAppData);
|
|
gApplicationData = GetSpecialDir(FOLDERID_ProgramData);
|
|
gSystemLibPath = GetSpecialDir(FOLDERID_System);
|
|
}
|
|
|
|
#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();
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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", ".");
|
|
|
|
// 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");
|
|
}
|
|
|
|
#else
|
|
|
|
static void SetNamespaceDirectories()
|
|
{
|
|
gHomeDirectory = ".";
|
|
gApplicationData = ".";
|
|
}
|
|
|
|
#endif
|
|
|
|
AuOptional<AuString> GetSystemLibPath()
|
|
{
|
|
return gSystemLibPath;
|
|
}
|
|
|
|
AuOptional<AuString> GetUserLibPath()
|
|
{
|
|
return gUserLibPath;
|
|
}
|
|
|
|
AuOptional<AuString> GetSystemLibPath2()
|
|
{
|
|
return gSystemLibPath2;
|
|
}
|
|
|
|
AuOptional<AuString> GetUserLibPath2()
|
|
{
|
|
return gUserLibPath2;
|
|
}
|
|
|
|
static void ChangeDir()
|
|
{
|
|
#if !defined(AU_NO_AU_HOME_BRANDING)
|
|
if (gRuntimeConfig.fio.defaultBrand.size())
|
|
{
|
|
gApplicationData += "/" + gRuntimeConfig.fio.defaultBrand;
|
|
gHomeDirectory += "/" + gRuntimeConfig.fio.defaultBrand;
|
|
}
|
|
#endif
|
|
|
|
NormalizePath(gApplicationData);
|
|
NormalizePath(gHomeDirectory);
|
|
|
|
if (gApplicationData == gHomeDirectory)
|
|
{
|
|
gApplicationData += kPathSplitter;
|
|
gHomeDirectory += kPathSplitter;
|
|
gApplicationData += "System";
|
|
gHomeDirectory += "Profile";
|
|
}
|
|
|
|
// Noting we append a path splitter to prevent hair pulling over missing path delimiters
|
|
// Eg: GetHome() + "myAwesomeApp/Config" = %HOME%/Aurora/ProfilemyAwsomeApp/Config
|
|
gApplicationData += kPathSplitter;
|
|
gHomeDirectory += kPathSplitter;
|
|
}
|
|
|
|
void InitResources()
|
|
{
|
|
SetNamespaceDirectories();
|
|
ChangeDir();
|
|
}
|
|
} |