From f1592d350f1ebe0b90eb293541a198b0434e2278 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 8 Dec 2020 19:31:01 -0800 Subject: [PATCH] Core: Clean up and extend config saving/loading --- include/mgba-util/configuration.h | 1 + include/mgba/core/config.h | 4 + src/core/config.c | 125 +++++++++++++++------------ src/platform/qt/ConfigController.cpp | 4 + src/platform/qt/ConfigController.h | 1 + src/util/configuration.c | 7 +- 6 files changed, 84 insertions(+), 58 deletions(-) diff --git a/include/mgba-util/configuration.h b/include/mgba-util/configuration.h index d9aacddeb..3409db0eb 100644 --- a/include/mgba-util/configuration.h +++ b/include/mgba-util/configuration.h @@ -36,6 +36,7 @@ bool ConfigurationRead(struct Configuration*, const char* path); bool ConfigurationReadVFile(struct Configuration*, struct VFile* vf); bool ConfigurationWrite(const struct Configuration*, const char* path); bool ConfigurationWriteSection(const struct Configuration*, const char* path, const char* section); +bool ConfigurationWriteVFile(const struct Configuration*, struct VFile* vf); void ConfigurationEnumerateSections(const struct Configuration* configuration, void (*handler)(const char* sectionName, void* user), void* user); void ConfigurationEnumerate(const struct Configuration* configuration, const char* section, void (*handler)(const char* key, const char* value, void* user), void* user); diff --git a/include/mgba/core/config.h b/include/mgba/core/config.h index da664ed47..063b14e02 100644 --- a/include/mgba/core/config.h +++ b/include/mgba/core/config.h @@ -68,9 +68,13 @@ bool mCoreConfigLoad(struct mCoreConfig*); bool mCoreConfigSave(const struct mCoreConfig*); bool mCoreConfigLoadPath(struct mCoreConfig*, const char* path); bool mCoreConfigSavePath(const struct mCoreConfig*, const char* path); +bool mCoreConfigLoadVFile(struct mCoreConfig*, struct VFile* vf); +bool mCoreConfigSaveVFile(const struct mCoreConfig*, struct VFile* vf); void mCoreConfigMakePortable(const struct mCoreConfig*); void mCoreConfigDirectory(char* out, size_t outLength); +void mCoreConfigPortablePath(char* out, size_t outLength); +bool mCoreConfigIsPortable(void); #endif const char* mCoreConfigGetValue(const struct mCoreConfig*, const char* key); diff --git a/src/core/config.c b/src/core/config.c index 97e9b5505..c2f019465 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -170,27 +170,23 @@ bool mCoreConfigSavePath(const struct mCoreConfig* config, const char* path) { return ConfigurationWrite(&config->configTable, path); } +bool mCoreConfigLoadVFile(struct mCoreConfig* config, struct VFile* vf) { + return ConfigurationReadVFile(&config->configTable, vf); +} + +bool mCoreConfigSaveVFile(const struct mCoreConfig* config, struct VFile* vf) { + return ConfigurationWriteVFile(&config->configTable, vf); +} + void mCoreConfigMakePortable(const struct mCoreConfig* config) { - struct VFile* portable = 0; -#ifdef _WIN32 - char out[MAX_PATH]; - wchar_t wpath[MAX_PATH]; - wchar_t wprojectName[MAX_PATH]; - MultiByteToWideChar(CP_UTF8, 0, projectName, -1, wprojectName, MAX_PATH); - HMODULE hModule = GetModuleHandleW(NULL); - GetModuleFileNameW(hModule, wpath, MAX_PATH); - PathRemoveFileSpecW(wpath); - WideCharToMultiByte(CP_UTF8, 0, wpath, -1, out, MAX_PATH, 0, 0); - StringCchCatA(out, MAX_PATH, "\\portable.ini"); - portable = VFileOpen(out, O_WRONLY | O_CREAT); -#elif defined(PSP2) || defined(_3DS) || defined(__SWITCH__) || defined(GEKKO) - // Already portable -#else + struct VFile* portable = NULL; char out[PATH_MAX]; - getcwd(out, PATH_MAX); - strncat(out, PATH_SEP "portable.ini", PATH_MAX - strlen(out)); + mCoreConfigPortablePath(out, sizeof(out)); + if (!out[0]) { + // Cannot be made portable + return; + } portable = VFileOpen(out, O_WRONLY | O_CREAT); -#endif if (portable) { portable->close(portable); mCoreConfigSave(config); @@ -199,62 +195,44 @@ void mCoreConfigMakePortable(const struct mCoreConfig* config) { void mCoreConfigDirectory(char* out, size_t outLength) { struct VFile* portable; + char portableDir[PATH_MAX]; + mCoreConfigPortablePath(portableDir, sizeof(portableDir)); + if (portableDir[0]) { + portable = VFileOpen(portableDir, O_RDONLY); + if (portable) { + portable->close(portable); + if (outLength < PATH_MAX) { + char outTmp[PATH_MAX]; + separatePath(portableDir, outTmp, NULL, NULL); + strlcpy(out, outTmp, outLength); + } else { + separatePath(portableDir, out, NULL, NULL); + } + return; + } + } #ifdef _WIN32 wchar_t wpath[MAX_PATH]; - wchar_t wprojectName[MAX_PATH]; - MultiByteToWideChar(CP_UTF8, 0, projectName, -1, wprojectName, MAX_PATH); - HMODULE hModule = GetModuleHandleW(NULL); - GetModuleFileNameW(hModule, wpath, MAX_PATH); - PathRemoveFileSpecW(wpath); - WideCharToMultiByte(CP_UTF8, 0, wpath, -1, out, outLength, 0, 0); - StringCchCatA(out, outLength, "\\portable.ini"); - portable = VFileOpen(out, O_RDONLY); - if (portable) { - portable->close(portable); - } else { - wchar_t* home; - SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &home); - StringCchPrintfW(wpath, MAX_PATH, L"%ws\\%ws", home, wprojectName); - CoTaskMemFree(home); - CreateDirectoryW(wpath, NULL); - } - WideCharToMultiByte(CP_UTF8, 0, wpath, -1, out, outLength, 0, 0); + wchar_t* home; + SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &home); + StringCchPrintfW(wpath, MAX_PATH, L"%ws\\%ws", home, wprojectName); + CoTaskMemFree(home); + CreateDirectoryW(wpath, NULL); #elif defined(PSP2) - UNUSED(portable); snprintf(out, outLength, "ux0:data/%s", projectName); sceIoMkdir(out, 0777); #elif defined(GEKKO) || defined(__SWITCH__) - UNUSED(portable); snprintf(out, outLength, "/%s", projectName); mkdir(out, 0777); #elif defined(_3DS) - UNUSED(portable); snprintf(out, outLength, "/%s", projectName); FSUSER_CreateDirectory(sdmcArchive, fsMakePath(PATH_ASCII, out), 0); #elif defined(__HAIKU__) - getcwd(out, outLength); - strncat(out, PATH_SEP "portable.ini", outLength - strlen(out)); - portable = VFileOpen(out, O_RDONLY); - if (portable) { - getcwd(out, outLength); - portable->close(portable); - return; - } - char path[B_PATH_NAME_LENGTH]; find_directory(B_USER_SETTINGS_DIRECTORY, 0, false, path, B_PATH_NAME_LENGTH); snprintf(out, outLength, "%s/%s", path, binaryName); mkdir(out, 0755); #else - getcwd(out, outLength); - strncat(out, PATH_SEP "portable.ini", outLength - strlen(out)); - portable = VFileOpen(out, O_RDONLY); - if (portable) { - getcwd(out, outLength); - portable->close(portable); - return; - } - char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); if (xdgConfigHome && xdgConfigHome[0] == '/') { snprintf(out, outLength, "%s/%s", xdgConfigHome, binaryName); @@ -268,6 +246,39 @@ void mCoreConfigDirectory(char* out, size_t outLength) { mkdir(out, 0755); #endif } + +void mCoreConfigPortablePath(char* out, size_t outLength) { +#ifdef _WIN32 + wchar_t wpath[MAX_PATH]; + wchar_t wprojectName[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0, projectName, -1, wprojectName, MAX_PATH); + HMODULE hModule = GetModuleHandleW(NULL); + GetModuleFileNameW(hModule, wpath, MAX_PATH); + PathRemoveFileSpecW(wpath); + WideCharToMultiByte(CP_UTF8, 0, wpath, -1, out, outLength, 0, 0); + StringCchCatA(out, outLength, "\\portable.ini"); +#elif defined(PSP2) || defined(GEKKO) || defined(__SWITCH__) || defined(_3DS) + out[0] = '\0'; +#else + getcwd(out, outLength); + strncat(out, PATH_SEP "portable.ini", outLength - strlen(out)); +#endif +} + +bool mCoreConfigIsPortable(void) { + struct VFile* portable; + char portableDir[PATH_MAX]; + mCoreConfigPortablePath(portableDir, sizeof(portableDir)); + if (portableDir[0]) { + portable = VFileOpen(portableDir, O_RDONLY); + if (portable) { + portable->close(portable); + return true; + } + } + return false; +} + #endif const char* mCoreConfigGetValue(const struct mCoreConfig* config, const char* key) { diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp index d0794fa94..dd2464e4b 100644 --- a/src/platform/qt/ConfigController.cpp +++ b/src/platform/qt/ConfigController.cpp @@ -297,6 +297,10 @@ void ConfigController::makePortable() { m_settings = settings2; } +bool ConfigController::isPortable() { + return mCoreConfigIsPortable(); +} + const QString& ConfigController::configDir() { if (s_configDir.isNull()) { char path[PATH_MAX]; diff --git a/src/platform/qt/ConfigController.h b/src/platform/qt/ConfigController.h index 0d77f8946..7f2943fad 100644 --- a/src/platform/qt/ConfigController.h +++ b/src/platform/qt/ConfigController.h @@ -91,6 +91,7 @@ public: mCoreConfig* config() { return &m_config; } static const QString& configDir(); + static bool isPortable(); public slots: void setOption(const char* key, bool value); diff --git a/src/util/configuration.c b/src/util/configuration.c index 1cf26104c..e0dada00c 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c @@ -177,9 +177,14 @@ bool ConfigurationWrite(const struct Configuration* configuration, const char* p if (!vf) { return false; } + bool res = ConfigurationWriteVFile(configuration, vf); + vf->close(vf); + return true; +} + +bool ConfigurationWriteVFile(const struct Configuration* configuration, struct VFile* vf) { HashTableEnumerate(&configuration->root, _keyHandler, vf); HashTableEnumerate(&configuration->sections, _sectionHandler, vf); - vf->close(vf); return true; }