Files
aee/source/core/jail/jfile.cpp
T

137 lines
4.2 KiB
C++

#include "core/jail/jfile.hpp"
#include <sys/stat.h>
#include <unistd.h>
#include <algorithm>
#include <filesystem>
#include <fstream>
#include <string>
#include <vector>
#ifndef _WIN32
#include <pwd.h>
#endif
namespace {
struct keyvalue {
std::string key;
std::string value;
};
std::vector<keyvalue> config;
std::string resource_folder;
std::string config_folder;
void load_config_values() {
config.clear();
const std::string config_file = config_folder + "/config.txt";
std::ifstream fi(config_file);
if (!fi.is_open()) {
return;
}
std::string line;
while (std::getline(fi, line)) {
const auto eq = line.find('=');
if (eq == std::string::npos) {
continue;
}
config.push_back({line.substr(0, eq), line.substr(eq + 1)});
}
}
void save_config_values() {
const std::string config_file = config_folder + "/config.txt";
std::ofstream fo(config_file);
if (!fo.is_open()) {
return;
}
for (const auto& pair : config) {
fo << pair.key << '=' << pair.value << '\n';
}
}
} // namespace
void file_setresourcefolder(const char* str) {
resource_folder = str;
}
auto file_getresourcefolder() -> const char* {
return resource_folder.c_str();
}
// Crea la carpeta del sistema on guardar les dades.
// Accepta rutes amb subdirectoris (ex: "jailgames/aee") i crea tota la jerarquia.
void file_setconfigfolder(const char* foldername) {
#ifdef _WIN32
const char* base = getenv("APPDATA");
if (!base) base = "C:/";
config_folder = std::string(base) + "/" + foldername;
#elif __APPLE__
struct passwd* pw = getpwuid(getuid());
const char* homedir = (pw && pw->pw_dir) ? pw->pw_dir : nullptr;
if (!homedir) homedir = getenv("HOME");
if (!homedir) homedir = "/tmp";
config_folder = std::string(homedir) + "/Library/Application Support/" + foldername;
#elif __linux__
// Nota emscripten: `__linux__` també està definit, però `getpwuid` pot
// retornar nullptr (sense /etc/passwd al MEMFS) o un passwd amb pw_dir
// buit. Amb els fallbacks HOME → /tmp evitem crashejar al primer
// arranque dins del navegador. La config no persistirà entre recàrregues
// (MEMFS és volàtil); caldria IDBFS si volguéssem persistència a web.
struct passwd* pw = getpwuid(getuid());
const char* homedir = ((pw != nullptr) && (pw->pw_dir != nullptr) && (pw->pw_dir[0] != 0)) ? pw->pw_dir : nullptr;
if ((homedir == nullptr) || (homedir[0] == 0)) {
homedir = getenv("HOME");
}
if ((homedir == nullptr) || (homedir[0] == 0)) {
homedir = "/tmp";
}
config_folder = std::string(homedir) + "/.config/" + foldername;
#else
config_folder = std::string("/tmp/jailgames_config/") + foldername;
#endif
std::error_code ec;
std::filesystem::create_directories(config_folder, ec);
// A emscripten/MEMFS create_directories pot fallar (p.ex. parent
// read-only o libc++ amb path empty-check estricte). La config és
// volàtil al navegador de totes formes: ignorem l'error i continuem.
}
auto file_getconfigfolder() -> const char* {
thread_local std::string folder;
folder = config_folder + "/";
return folder.c_str();
}
auto file_getconfigvalue(const char* key) -> const char* {
if (config.empty()) {
load_config_values();
}
const auto it = std::find_if(config.begin(), config.end(), [key](const keyvalue& pair) { return pair.key == key; });
if (it != config.end()) {
thread_local std::string value_cache;
value_cache = it->value;
return value_cache.c_str();
}
return nullptr;
}
void file_setconfigvalue(const char* key, const char* value) {
if (config.empty()) {
load_config_values();
}
const auto it = std::find_if(config.begin(), config.end(), [key](const keyvalue& pair) { return pair.key == key; });
if (it != config.end()) {
it->value = value;
save_config_values();
return;
}
config.push_back({std::string(key), std::string(value)});
save_config_values();
}