diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 0ae9e2c5f0..52288847a6 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -672,14 +672,19 @@ std::string GetSysDirectory() { return sysDir; } -// Returns a string with a Citra data dir or file in the user's home -// directory. To be used in "multi-user" mode (that is, installed). -const std::string& GetUserPath(UserPath path, const std::string& new_path) { - static std::unordered_map paths; - auto& user_path = paths[UserPath::UserDir]; +namespace { +std::unordered_map g_paths; +} - // Set up all paths and files on the first run - if (user_path.empty()) { +void SetUserPath(const std::string& path) { + std::string& user_path = g_paths[UserPath::UserDir]; + + if (!path.empty() && CreateFullPath(path)) { + LOG_INFO(Common_Filesystem, "Using {} as the user directory", path); + user_path = path; + g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); + g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); + } else { #ifdef _WIN32 user_path = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; if (!FileUtil::IsDirectory(user_path)) { @@ -688,56 +693,40 @@ const std::string& GetUserPath(UserPath path, const std::string& new_path) { LOG_INFO(Common_Filesystem, "Using the local user directory"); } - paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); - paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); + g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); + g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); #else if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) { user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; - paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); - paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); + g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); + g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); } else { std::string data_dir = GetUserDirectory("XDG_DATA_HOME"); std::string config_dir = GetUserDirectory("XDG_CONFIG_HOME"); std::string cache_dir = GetUserDirectory("XDG_CACHE_HOME"); user_path = data_dir + DIR_SEP EMU_DATA_DIR DIR_SEP; - paths.emplace(UserPath::ConfigDir, config_dir + DIR_SEP EMU_DATA_DIR DIR_SEP); - paths.emplace(UserPath::CacheDir, cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP); + g_paths.emplace(UserPath::ConfigDir, config_dir + DIR_SEP EMU_DATA_DIR DIR_SEP); + g_paths.emplace(UserPath::CacheDir, cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP); } #endif - paths.emplace(UserPath::SDMCDir, user_path + SDMC_DIR DIR_SEP); - paths.emplace(UserPath::NANDDir, user_path + NAND_DIR DIR_SEP); - paths.emplace(UserPath::SysDataDir, user_path + SYSDATA_DIR DIR_SEP); - // TODO: Put the logs in a better location for each OS - paths.emplace(UserPath::LogDir, user_path + LOG_DIR DIR_SEP); - paths.emplace(UserPath::CheatsDir, user_path + CHEATS_DIR DIR_SEP); - paths.emplace(UserPath::DLLDir, user_path + DLL_DIR DIR_SEP); } + g_paths.emplace(UserPath::SDMCDir, user_path + SDMC_DIR DIR_SEP); + g_paths.emplace(UserPath::NANDDir, user_path + NAND_DIR DIR_SEP); + g_paths.emplace(UserPath::SysDataDir, user_path + SYSDATA_DIR DIR_SEP); + // TODO: Put the logs in a better location for each OS + g_paths.emplace(UserPath::LogDir, user_path + LOG_DIR DIR_SEP); + g_paths.emplace(UserPath::CheatsDir, user_path + CHEATS_DIR DIR_SEP); + g_paths.emplace(UserPath::DLLDir, user_path + DLL_DIR DIR_SEP); +} - if (!new_path.empty()) { - if (!FileUtil::IsDirectory(new_path)) { - LOG_ERROR(Common_Filesystem, "Invalid path specified {}", new_path); - return paths[path]; - } else { - paths[path] = new_path; - } - - switch (path) { - case UserPath::RootDir: - user_path = paths[UserPath::RootDir] + DIR_SEP; - break; - - case UserPath::UserDir: - user_path = paths[UserPath::RootDir] + DIR_SEP; - paths[UserPath::ConfigDir] = user_path + CONFIG_DIR DIR_SEP; - paths[UserPath::CacheDir] = user_path + CACHE_DIR DIR_SEP; - paths[UserPath::SDMCDir] = user_path + SDMC_DIR DIR_SEP; - paths[UserPath::NANDDir] = user_path + NAND_DIR DIR_SEP; - break; - } - } - - return paths[path]; +// Returns a string with a Citra data dir or file in the user's home +// directory. To be used in "multi-user" mode (that is, installed). +const std::string& GetUserPath(UserPath path) { + // Set up all paths and files on the first run + if (g_paths.empty()) + SetUserPath(); + return g_paths[path]; } size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename) { diff --git a/src/common/file_util.h b/src/common/file_util.h index d30780b978..c94057ccdc 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h @@ -123,9 +123,11 @@ void CopyDir(const std::string& source_path, const std::string& dest_path); // Set the current directory to given directory bool SetCurrentDir(const std::string& directory); +void SetUserPath(const std::string& path = ""); + // Returns a pointer to a string with a Citra data dir in the user's home // directory. To be used in "multi-user" mode (that is, installed). -const std::string& GetUserPath(UserPath path, const std::string& new_path = ""); +const std::string& GetUserPath(UserPath path); // Returns the path to where the sys file are std::string GetSysDirectory();