/** * Default directory fallback is: * - (command line argument) * - <exePath>/data * - <platform dependent> */ void platform_resolve_openrct_data_path() { const char separator[2] = { platform_get_path_separator(), 0 }; if (gCustomOpenrctDataPath[0] != 0) { if (realpath(gCustomOpenrctDataPath, _openrctDataDirectoryPath)) { log_error("Could not resolve path \"%s\"", gCustomUserDataPath); return; } // Ensure path ends with separator int len = strlen(_openrctDataDirectoryPath); if (_openrctDataDirectoryPath[len - 1] != separator[0]) { strncat(_openrctDataDirectoryPath, separator, MAX_PATH - 1); } return; } char buffer[MAX_PATH] = { 0 }; platform_get_exe_path(buffer); strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); strncat(buffer, "data", MAX_PATH - strnlen(buffer, MAX_PATH) - 1); log_verbose("Looking for OpenRCT2 data in %s", buffer); if (platform_directory_exists(buffer)) { _openrctDataDirectoryPath[0] = '\0'; safe_strcpy(_openrctDataDirectoryPath, buffer, MAX_PATH); log_verbose("Found OpenRCT2 data in %s", _openrctDataDirectoryPath); return; } platform_posix_sub_resolve_openrct_data_path(_openrctDataDirectoryPath); log_verbose("Trying to use OpenRCT2 data in %s", _openrctDataDirectoryPath); }
/** * Default directory fallback is: * - (command line argument) * - <exePath>/data * - <platform dependent> */ void platform_resolve_openrct_data_path() { if (gCustomOpenrctDataPath[0] != 0) { // NOTE: second argument to `realpath` is meant to either be NULL or `PATH_MAX`-sized buffer, // since our `MAX_PATH` macro is set to some other value, pass NULL to have `realpath` return // a `malloc`ed buffer. char *resolved_path = realpath(gCustomOpenrctDataPath, NULL); if (resolved_path == NULL) { log_error("Could not resolve path \"%s\", errno = %d", gCustomOpenrctDataPath, errno); return; } else { safe_strcpy(_openrctDataDirectoryPath, resolved_path, MAX_PATH); free(resolved_path); } path_end_with_separator(_openrctDataDirectoryPath, MAX_PATH); return; } char buffer[MAX_PATH]; platform_get_exe_path(buffer, sizeof(buffer)); safe_strcat_path(buffer, "data", MAX_PATH); log_verbose("Looking for OpenRCT2 data in %s", buffer); if (platform_directory_exists(buffer)) { _openrctDataDirectoryPath[0] = '\0'; safe_strcpy(_openrctDataDirectoryPath, buffer, MAX_PATH); log_verbose("Found OpenRCT2 data in %s", _openrctDataDirectoryPath); return; } platform_posix_sub_resolve_openrct_data_path(_openrctDataDirectoryPath, sizeof(_openrctDataDirectoryPath)); log_verbose("Trying to use OpenRCT2 data in %s", _openrctDataDirectoryPath); }
/** * Default directory fallback is: * - <exePath>/doc * - /usr/share/doc/openrct2 */ static void platform_posix_sub_resolve_openrct_doc_path(utf8 *out, size_t size) { static const utf8 *searchLocations[] = { "./doc", "/usr/share/doc/openrct2", }; for (size_t i = 0; i < countof(searchLocations); i++) { log_verbose("Looking for OpenRCT2 doc path at %s", searchLocations[i]); if (platform_directory_exists(searchLocations[i])) { safe_strcpy(out, searchLocations[i], size); return; } } }
std::string GetDocsPath() { static const utf8 * searchLocations[] = { "./doc", "/usr/share/doc/openrct2", }; for (auto searchLocation : searchLocations) { log_verbose("Looking for OpenRCT2 doc path at %s", searchLocation); if (platform_directory_exists(searchLocation)) { return searchLocation; } } return std::string(); }
/** * Default directory fallback is: * - (command line argument) * - <platform dependent> */ void platform_resolve_user_data_path() { if (gCustomUserDataPath[0] != 0) { if (!platform_ensure_directory_exists(gCustomUserDataPath)) { log_error("Failed to create directory \"%s\", make sure you have permissions.", gCustomUserDataPath); return; } char *path; if ((path = realpath(gCustomUserDataPath, NULL)) == NULL) { log_error("Could not resolve path \"%s\"", gCustomUserDataPath); return; } safe_strcpy(_userDataDirectoryPath, path, MAX_PATH); free(path); // Ensure path ends with separator path_end_with_separator(_userDataDirectoryPath, MAX_PATH); log_verbose("User data path resolved to: %s", _userDataDirectoryPath); if (!platform_directory_exists(_userDataDirectoryPath)) { log_error("Custom user data directory %s does not exist", _userDataDirectoryPath); } return; } char buffer[MAX_PATH]; log_verbose("buffer = '%s'", buffer); const char *homedir = getpwuid(getuid())->pw_dir; platform_posix_sub_user_data_path(buffer, MAX_PATH, homedir); log_verbose("OpenRCT2 user data directory = '%s'", buffer); sint32 len = strnlen(buffer, MAX_PATH); wchar_t *w_buffer = regular_to_wchar(buffer); w_buffer[len] = '\0'; utf8 *path = widechar_to_utf8(w_buffer); free(w_buffer); safe_strcpy(_userDataDirectoryPath, path, MAX_PATH); free(path); log_verbose("User data path resolved to: %s", _userDataDirectoryPath); }
/** * Default directory fallback is: * - (command line argument) * - <exePath>/data * - /usr/local/share/openrct2 * - /var/lib/openrct2 * - /usr/share/openrct2 */ void platform_posix_sub_resolve_openrct_data_path(utf8 *out, size_t size) { static const utf8 *searchLocations[] = { "../share/openrct2", #ifdef ORCT2_RESOURCE_DIR // defined in CMakeLists.txt ORCT2_RESOURCE_DIR, #endif // ORCT2_RESOURCE_DIR "/usr/local/share/openrct2", "/var/lib/openrct2", "/usr/share/openrct2", }; for (size_t i = 0; i < countof(searchLocations); i++) { log_verbose("Looking for OpenRCT2 data in %s", searchLocations[i]); if (platform_directory_exists(searchLocations[i])) { safe_strcpy(out, searchLocations[i], size); return; } } }
static exitcode_t HandleCommandSetRCT2(CommandLineArgEnumerator * enumerator) { exitcode_t result = CommandLine::HandleCommandDefault(); if (result != EXITCODE_CONTINUE) { return result; } // Get the path that was passed const utf8 * rawPath; if (!enumerator->TryPopString(&rawPath)) { Console::Error::WriteLine("Expected a path."); return EXITCODE_FAIL; } utf8 path[MAX_PATH]; Path::GetAbsolute(path, sizeof(path), rawPath); // Check if path exists Console::WriteLine("Checking path..."); if (!platform_directory_exists(path)) { Console::Error::WriteLine("The path '%s' does not exist", path); return EXITCODE_FAIL; } // Check if g1.dat exists (naive but good check) Console::WriteLine("Checking g1.dat..."); utf8 pathG1Check[MAX_PATH]; String::Set(pathG1Check, sizeof(pathG1Check), path); Path::Append(pathG1Check, sizeof(pathG1Check), "Data"); Path::Append(pathG1Check, sizeof(pathG1Check), "g1.dat"); if (!platform_file_exists(pathG1Check)) { Console::Error::WriteLine("RCT2 path not valid."); Console::Error::WriteLine("Unable to find %s.", pathG1Check); return EXITCODE_FAIL; } // Check user path that will contain the config utf8 userPath[MAX_PATH]; platform_resolve_user_data_path(); platform_get_user_directory(userPath, NULL, sizeof(userPath)); if (!platform_ensure_directory_exists(userPath)) { Console::Error::WriteLine("Unable to access or create directory '%s'.", userPath); return EXITCODE_FAIL; } // Update RCT2 path in config config_set_defaults(); config_open_default(); String::DiscardDuplicate(&gConfigGeneral.rct2_path, path); if (config_save_default()) { Console::WriteFormat("Updating RCT2 path to '%s'.", path); Console::WriteLine(); Console::WriteLine("Updated config.ini"); return EXITCODE_OK; } else { Console::Error::WriteLine("Unable to update config.ini"); return EXITCODE_FAIL; } }