std::string GetSysDirectory() { std::string sysDir; #if defined(_WIN32) || defined(LINUX_LOCAL_DEV) #define SYSDATA_DIR "Sys" #elif defined __APPLE__ #define SYSDATA_DIR "Contents/Resources/Sys" #else #ifdef DATA_DIR #define SYSDATA_DIR DATA_DIR "sys" #else #define SYSDATA_DIR "sys" #endif #endif #if defined(__APPLE__) sysDir = GetBundleDirectory() + DIR_SEP + SYSDATA_DIR; #elif defined(_WIN32) || defined(LINUX_LOCAL_DEV) sysDir = GetExeDirectory() + DIR_SEP + SYSDATA_DIR; #elif defined ANDROID sysDir = s_android_sys_directory; ASSERT_MSG(COMMON, !sysDir.empty(), "Sys directory has not been set"); #else sysDir = SYSDATA_DIR; #endif sysDir += DIR_SEP; INFO_LOG(COMMON, "GetSysDirectory: Setting to %s:", sysDir.c_str()); return sysDir; }
std::string GetExePath() { static std::string dolphin_path; if (dolphin_path.empty()) { #ifdef _WIN32 TCHAR dolphin_exe_path[2048]; TCHAR dolphin_exe_expanded_path[MAX_PATH]; GetModuleFileName(nullptr, dolphin_exe_path, ARRAYSIZE(dolphin_exe_path)); if (_tfullpath(dolphin_exe_expanded_path, dolphin_exe_path, ARRAYSIZE(dolphin_exe_expanded_path)) != nullptr) dolphin_path = TStrToUTF8(dolphin_exe_expanded_path); else dolphin_path = TStrToUTF8(dolphin_exe_path); #elif defined(__APPLE__) dolphin_path = GetBundleDirectory(); dolphin_path = dolphin_path.substr(0, dolphin_path.find_last_of("Dolphin.app/Contents/MacOS")); #else char dolphin_exe_path[PATH_MAX]; ssize_t len = ::readlink("/proc/self/exe", dolphin_exe_path, sizeof(dolphin_exe_path)); if (len == -1 || len == sizeof(dolphin_exe_path)) { len = 0; } dolphin_exe_path[len] = '\0'; dolphin_path = dolphin_exe_path; #endif } return dolphin_path; }
std::string GetSysDirectory() { std::string sysDir; #if defined (__APPLE__) sysDir = GetBundleDirectory(); sysDir += DIR_SEP; sysDir += SYSDATA_DIR; #else sysDir = SYSDATA_DIR; #endif sysDir += DIR_SEP; INFO_LOG(COMMON, "GetSysDirectory: Setting to %s:", sysDir.c_str()); return sysDir; }
std::string GetSysDirectory() { std::string sysDir; #if defined (__APPLE__) sysDir = GetBundleDirectory(); sysDir += DIR_SEP; sysDir += SYSDATA_DIR; #else sysDir = SYSDATA_DIR; #endif sysDir += DIR_SEP; LOG_DEBUG(Common_Filesystem, "Setting to %s:", sysDir.c_str()); return sysDir; }
std::string GetSysDirectory() { std::string sysDir; #if defined(__APPLE__) sysDir = GetBundleDirectory() + DIR_SEP + SYSDATA_DIR; #elif defined(_WIN32) || defined(LINUX_LOCAL_DEV) sysDir = GetExeDirectory() + DIR_SEP + SYSDATA_DIR; #else sysDir = SYSDATA_DIR; #endif sysDir += DIR_SEP; INFO_LOG(COMMON, "GetSysDirectory: Setting to %s:", sysDir.c_str()); return sysDir; }
// Returns the current directory std::string GetCurrentDir() { // Get the current working directory (getcwd uses malloc) #ifdef _WIN32 wchar_t *dir; if (!(dir = _wgetcwd(nullptr, 0))) { #else char *dir; if (!(dir = getcwd(nullptr, 0))) { #endif LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: %s", GetLastErrorMsg()); return nullptr; } #ifdef _WIN32 std::string strDir = Common::UTF16ToUTF8(dir); #else std::string strDir = dir; #endif free(dir); return strDir; } // Sets the current directory to the given directory bool SetCurrentDir(const std::string &directory) { #ifdef _WIN32 return _wchdir(Common::UTF8ToUTF16W(directory).c_str()) == 0; #else return chdir(directory.c_str()) == 0; #endif } #if defined(__APPLE__) std::string GetBundleDirectory() { CFURLRef BundleRef; char AppBundlePath[MAXPATHLEN]; // Get the main bundle for the app BundleRef = CFBundleCopyBundleURL(CFBundleGetMainBundle()); CFStringRef BundlePath = CFURLCopyFileSystemPath(BundleRef, kCFURLPOSIXPathStyle); CFStringGetFileSystemRepresentation(BundlePath, AppBundlePath, sizeof(AppBundlePath)); CFRelease(BundleRef); CFRelease(BundlePath); return AppBundlePath; } #endif #ifdef _WIN32 std::string& GetExeDirectory() { static std::string exe_path; if (exe_path.empty()) { wchar_t wchar_exe_path[2048]; GetModuleFileNameW(nullptr, wchar_exe_path, 2048); exe_path = Common::UTF16ToUTF8(wchar_exe_path); exe_path = exe_path.substr(0, exe_path.find_last_of('\\')); } return exe_path; } #else /** * @return The user’s home directory on POSIX systems */ static const std::string& GetHomeDirectory() { static std::string home_path; if (home_path.empty()) { const char* envvar = getenv("HOME"); if (envvar) { home_path = envvar; } else { auto pw = getpwuid(getuid()); ASSERT_MSG(pw, "$HOME isn’t defined, and the current user can’t be found in /etc/passwd."); home_path = pw->pw_dir; } } return home_path; } /** * Follows the XDG Base Directory Specification to get a directory path * @param envvar The XDG environment variable to get the value from * @return The directory path * @sa http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html */ static const std::string GetUserDirectory(const std::string& envvar) { const char* directory = getenv(envvar.c_str()); std::string user_dir; if (directory) { user_dir = directory; } else { std::string subdirectory; if (envvar == "XDG_DATA_HOME") subdirectory = DIR_SEP ".local" DIR_SEP "share"; else if (envvar == "XDG_CONFIG_HOME") subdirectory = DIR_SEP ".config"; else if (envvar == "XDG_CACHE_HOME") subdirectory = DIR_SEP ".cache"; else ASSERT_MSG(false, "Unknown XDG variable %s.", envvar.c_str()); user_dir = GetHomeDirectory() + subdirectory; } ASSERT_MSG(!user_dir.empty(), "User directory %s musn’t be empty.", envvar.c_str()); ASSERT_MSG(user_dir[0] == '/', "User directory %s must be absolute.", envvar.c_str()); return user_dir; } #endif std::string GetSysDirectory() { std::string sysDir; #if defined (__APPLE__) sysDir = GetBundleDirectory(); sysDir += DIR_SEP; sysDir += SYSDATA_DIR; #else sysDir = SYSDATA_DIR; #endif sysDir += DIR_SEP; LOG_DEBUG(Common_Filesystem, "Setting to %s:", sysDir.c_str()); 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(const unsigned int DirIDX, const std::string &newPath) { static std::string paths[NUM_PATH_INDICES]; // Set up all paths and files on the first run if (paths[D_USER_IDX].empty()) { #ifdef _WIN32 paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; #else if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) { paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; paths[D_CACHE_IDX] = paths[D_USER_IDX] + 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"); paths[D_USER_IDX] = data_dir + DIR_SEP EMU_DATA_DIR DIR_SEP; paths[D_CONFIG_IDX] = config_dir + DIR_SEP EMU_DATA_DIR DIR_SEP; paths[D_CACHE_IDX] = cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP; } #endif paths[D_GAMECONFIG_IDX] = paths[D_USER_IDX] + GAMECONFIG_DIR DIR_SEP; paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP; paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP; paths[D_SYSDATA_IDX] = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP; paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP; paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP; paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP; paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP; paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; } if (!newPath.empty()) { if (!FileUtil::IsDirectory(newPath)) { LOG_ERROR(Common_Filesystem, "Invalid path specified %s", newPath.c_str()); return paths[DirIDX]; } else { paths[DirIDX] = newPath; } switch (DirIDX) { case D_ROOT_IDX: paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP; paths[D_SYSCONF_IDX] = paths[D_USER_IDX] + SYSCONF_DIR + DIR_SEP; paths[F_SYSCONF_IDX] = paths[D_SYSCONF_IDX] + SYSCONF; break; case D_USER_IDX: paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP; paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; paths[D_GAMECONFIG_IDX] = paths[D_USER_IDX] + GAMECONFIG_DIR DIR_SEP; paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP; paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP; paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP; paths[D_SCREENSHOTS_IDX] = paths[D_USER_IDX] + SCREENSHOTS_DIR DIR_SEP; paths[D_DUMP_IDX] = paths[D_USER_IDX] + DUMP_DIR DIR_SEP; paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOGS_DIR DIR_SEP; paths[D_SYSCONF_IDX] = paths[D_USER_IDX] + SYSCONF_DIR DIR_SEP; paths[F_EMUCONFIG_IDX] = paths[D_CONFIG_IDX] + EMU_CONFIG; paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; break; case D_CONFIG_IDX: paths[F_EMUCONFIG_IDX] = paths[D_CONFIG_IDX] + EMU_CONFIG; paths[F_DEBUGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + DEBUGGER_CONFIG; paths[F_LOGGERCONFIG_IDX] = paths[D_CONFIG_IDX] + LOGGER_CONFIG; break; case D_DUMP_IDX: paths[D_DUMPFRAMES_IDX] = paths[D_DUMP_IDX] + DUMP_FRAMES_DIR DIR_SEP; paths[D_DUMPAUDIO_IDX] = paths[D_DUMP_IDX] + DUMP_AUDIO_DIR DIR_SEP; paths[D_DUMPTEXTURES_IDX] = paths[D_DUMP_IDX] + DUMP_TEXTURES_DIR DIR_SEP; break; case D_LOGS_IDX: paths[F_MAINLOG_IDX] = paths[D_LOGS_IDX] + MAIN_LOG; } } return paths[DirIDX]; } size_t WriteStringToFile(bool text_file, const std::string &str, const char *filename) { return FileUtil::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size()); } size_t ReadFileToString(bool text_file, const char *filename, std::string &str) { IOFile file(filename, text_file ? "r" : "rb"); if (!file) return false; str.resize(static_cast<u32>(file.GetSize())); return file.ReadArray(&str[0], str.size()); }