diff --git a/conf/config_file.c b/conf/config_file.c index 71e4e339f8..cbbaa4c530 100644 --- a/conf/config_file.c +++ b/conf/config_file.c @@ -658,45 +658,8 @@ bool config_get_path(config_file_t *conf, const char *key, char *buf, size_t siz { if (strcmp(key, list->key) == 0) { - const char *value = list->value; - - if (*value == '~') - { - const char *home = getenv("HOME"); - if (home) - { - size_t src_size = strlcpy(buf, home, size); - if (src_size >= size) - return false; - - buf += src_size; - size -= src_size; - value++; - } - } - else if ((*value == ':') && -#ifdef _WIN32 - ((value[1] == '/') || (value[1] == '\\'))) -#else - (value[1] == '/')) -#endif - { - char application_dir[PATH_MAX]; - fill_pathname_application_path(application_dir, sizeof(application_dir)); - - RARCH_LOG("[Config]: Querying application path: %s.\n", application_dir); - path_basedir(application_dir); - - size_t src_size = strlcpy(buf, application_dir, size); - if (src_size >= size) - return false; - - buf += src_size; - size -= src_size; - value += 2; - } - - return strlcpy(buf, value, size) < size; + fill_pathname_expand_special(buf, list->value, size); + return true; } list = list->next; } @@ -757,6 +720,17 @@ void config_set_string(config_file_t *conf, const char *key, const char *val) conf->entries = elem; } +void config_set_path(config_file_t *conf, const char *entry, const char *val) +{ +#if defined(RARCH_CONSOLE) + config_set_string(conf, entry, val); +#else + char buf[PATH_MAX]; + fill_pathname_abbreviate_special(buf, val, sizeof(buf)); + config_set_string(conf, entry, buf); +#endif +} + void config_set_double(config_file_t *conf, const char *key, double val) { char buf[128]; diff --git a/conf/config_file.h b/conf/config_file.h index ad366e84ca..c2e074f74d 100644 --- a/conf/config_file.h +++ b/conf/config_file.h @@ -98,6 +98,7 @@ void config_set_hex(config_file_t *conf, const char *entry, unsigned val); void config_set_uint64(config_file_t *conf, const char *entry, uint64_t val); void config_set_char(config_file_t *conf, const char *entry, char val); void config_set_string(config_file_t *conf, const char *entry, const char *val); +void config_set_path(config_file_t *conf, const char *entry, const char *val); void config_set_bool(config_file_t *conf, const char *entry, bool val); // Write the current config to a file. diff --git a/file_path.c b/file_path.c index 781e8eac4d..bac62f8864 100644 --- a/file_path.c +++ b/file_path.c @@ -742,6 +742,84 @@ void fill_pathname_join(char *out_path, const char *dir, const char *path, size_ rarch_assert(strlcat(out_path, path, size) < size); } +void fill_pathname_expand_special(char *out_path, const char *in_path, size_t size) +{ +#if !defined(RARCH_CONSOLE) + if (*in_path == '~') + { + const char *home = getenv("HOME"); + if (home) + { + size_t src_size = strlcpy(out_path, home, size); + rarch_assert(src_size < size); + + out_path += src_size; + size -= src_size; + in_path++; + } + } + else if ((*in_path == ':') && +#ifdef _WIN32 + ((in_path[1] == '/') || (in_path[1] == '\\'))) +#else + (in_path[1] == '/')) +#endif + { + char application_dir[PATH_MAX]; + fill_pathname_application_path(application_dir, sizeof(application_dir)); + path_basedir(application_dir); + + size_t src_size = strlcpy(out_path, application_dir, size); + rarch_assert(src_size < size); + + out_path += src_size; + size -= src_size; + in_path += 2; + } +#endif + + rarch_assert(strlcpy(out_path, in_path, size) < size); +} + +void fill_pathname_abbreviate_special(char *out_path, const char *in_path, size_t size) +{ +#if !defined(RARCH_CONSOLE) + int i; + + const char* home = getenv("HOME"); + char application_dir[PATH_MAX]; + fill_pathname_application_path(application_dir, sizeof(application_dir)); + path_basedir(application_dir); + + // Keep application dir in front of home, moving app dir to a new location inside + // home would break otherwise. + const char *candidates[3] = { application_dir, home, 0 }; + const char *notations[3] = { ":", "~", 0 }; + + for (i = 0; candidates[i]; i ++) + { + if (strstr(in_path, candidates[i]) == in_path) + { + size_t src_size = strlcpy(out_path, notations[i], size); + rarch_assert(src_size < size); + + out_path += src_size; + size -= src_size; + in_path += strlen(candidates[i]); + + if (!path_char_is_slash(*in_path)) + { + rarch_assert(strlcpy(out_path, path_default_slash(), size) < size); + out_path ++; + size --; + } + } + } +#endif + + rarch_assert(strlcpy(out_path, in_path, size) < size); +} + #ifndef RARCH_CONSOLE void fill_pathname_application_path(char *buf, size_t size) { @@ -752,6 +830,20 @@ void fill_pathname_application_path(char *buf, size_t size) #ifdef _WIN32 DWORD ret = GetModuleFileName(GetModuleHandle(NULL), buf, size - 1); buf[ret] = '\0'; +#elif defined(__APPLE__) + CFBundleRef bundle = CFBundleGetMainBundle(); + if (bundle) + { + CFURLRef bundle_url = CFBundleCopyBundleURL(bundle); + CFStringRef bundle_path = CFURLCopyPath(bundle_url); + CFStringGetCString(bundle_path, buf, size, kCFStringEncodingUTF8); + CFRelease(bundle_path); + CFRelease(bundle_url); + + rarch_assert(strlcat(buf, "nobin", size) < size); + + return; + } #else *buf = '\0'; diff --git a/file_path.h b/file_path.h index 0b1fed1576..4dd266cbe4 100644 --- a/file_path.h +++ b/file_path.h @@ -120,6 +120,9 @@ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath, cons // Joins a directory and path together. Makes sure not to get two consecutive slashes between dir and path. void fill_pathname_join(char *out_path, const char *dir, const char *path, size_t size); +void fill_pathname_expand_special(char *out_path, const char *in_path, size_t size); +void fill_pathname_abbreviate_special(char *out_path, const char *in_path, size_t size); + #ifndef RARCH_CONSOLE void fill_pathname_application_path(char *buf, size_t size); #endif diff --git a/settings.c b/settings.c index d2f25b4c98..f250cdb158 100644 --- a/settings.c +++ b/settings.c @@ -406,24 +406,24 @@ void config_set_defaults(void) #ifdef HAVE_OVERLAY if (default_overlay_dir) { - strlcpy(g_extern.overlay_dir, default_overlay_dir, sizeof(g_extern.overlay_dir)); + fill_pathname_expand_special(g_extern.overlay_dir, default_overlay_dir, sizeof(g_extern.overlay_dir)); #if defined(__QNX__) - fill_pathname_join(g_settings.input.overlay, default_overlay_dir, "snes-landscape.cfg", sizeof(g_settings.input.overlay)); + fill_pathname_join(g_settings.input.overlay, g_extern.overlay_dir, "snes-landscape/snes-landscape.cfg", sizeof(g_settings.input.overlay)); #endif } #endif if (default_shader_dir) - strlcpy(g_settings.video.shader_dir, default_shader_dir, sizeof(g_settings.video.shader_dir)); + fill_pathname_expand_special(g_settings.video.shader_dir, default_shader_dir, sizeof(g_settings.video.shader_dir)); if (default_libretro_path) - strlcpy(g_settings.libretro, default_libretro_path, sizeof(g_settings.libretro)); + fill_pathname_expand_special(g_settings.libretro, default_libretro_path, sizeof(g_settings.libretro)); if (default_libretro_info_path) - strlcpy(g_settings.libretro_info_path, default_libretro_info_path, sizeof(g_settings.libretro_info_path)); + fill_pathname_expand_special(g_settings.libretro_info_path, default_libretro_info_path, sizeof(g_settings.libretro_info_path)); if (default_config_path) - strlcpy(g_extern.config_path, default_config_path, sizeof(g_extern.config_path)); + fill_pathname_expand_special(g_extern.config_path, default_config_path, sizeof(g_extern.config_path)); g_extern.config_save_on_exit = config_save_on_exit; @@ -1121,12 +1121,12 @@ bool config_save_file(const char *path) RARCH_LOG("Saving config at path: \"%s\"\n", path); config_set_bool(conf, "fps_show", g_settings.fps_show); - config_set_string(conf, "libretro_path", g_settings.libretro); - config_set_string(conf, "libretro_info_path", g_settings.libretro_info_path); - config_set_string(conf, "cheat_database_path", g_settings.cheat_database); + config_set_path(conf, "libretro_path", g_settings.libretro); + config_set_path(conf, "libretro_info_path", g_settings.libretro_info_path); + config_set_path(conf, "cheat_database_path", g_settings.cheat_database); config_set_bool(conf, "rewind_enable", g_settings.rewind_enable); config_set_int(conf, "rewind_granularity", g_settings.rewind_granularity); - config_set_string(conf, "video_shader", g_settings.video.shader_path); + config_set_path(conf, "video_shader", g_settings.video.shader_path); config_set_bool(conf, "video_shader_enable", g_settings.video.shader_enable); config_set_float(conf, "video_aspect_ratio", g_settings.video.aspect_ratio); config_set_float(conf, "video_xscale", g_settings.video.xscale); @@ -1146,7 +1146,7 @@ bool config_save_file(const char *path) config_set_int(conf, "video_swap_interval", g_settings.video.swap_interval); config_set_bool(conf, "video_gpu_screenshot", g_settings.video.gpu_screenshot); config_set_int(conf, "video_rotation", g_settings.video.rotation); - config_set_string(conf, "screenshot_directory", *g_settings.screenshot_directory ? g_settings.screenshot_directory : "default"); + config_set_path(conf, "screenshot_directory", *g_settings.screenshot_directory ? g_settings.screenshot_directory : "default"); config_set_int(conf, "aspect_ratio_index", g_settings.video.aspect_ratio_idx); config_set_string(conf, "audio_device", g_settings.audio.device); #ifdef HAVE_CAMERA @@ -1157,25 +1157,25 @@ bool config_save_file(const char *path) config_set_string(conf, "audio_driver", g_settings.audio.driver); config_set_int(conf, "audio_out_rate", g_settings.audio.out_rate); - config_set_string(conf, "system_directory", *g_settings.system_directory ? g_settings.system_directory : "default"); - config_set_string(conf, "savefile_directory", *g_extern.savefile_dir ? g_extern.savefile_dir : "default"); - config_set_string(conf, "savestate_directory", *g_extern.savestate_dir ? g_extern.savestate_dir : "default"); - config_set_string(conf, "video_shader_dir", *g_settings.video.shader_dir ? g_settings.video.shader_dir : "default"); + config_set_path(conf, "system_directory", *g_settings.system_directory ? g_settings.system_directory : "default"); + config_set_path(conf, "savefile_directory", *g_extern.savefile_dir ? g_extern.savefile_dir : "default"); + config_set_path(conf, "savestate_directory", *g_extern.savestate_dir ? g_extern.savestate_dir : "default"); + config_set_path(conf, "video_shader_dir", *g_settings.video.shader_dir ? g_settings.video.shader_dir : "default"); #ifdef HAVE_MENU - config_set_string(conf, "rgui_browser_directory", *g_settings.rgui_browser_directory ? g_settings.rgui_browser_directory : "default"); - config_set_string(conf, "rgui_config_directory", *g_settings.rgui_config_directory ? g_settings.rgui_config_directory : "default"); + config_set_path(conf, "rgui_browser_directory", *g_settings.rgui_browser_directory ? g_settings.rgui_browser_directory : "default"); + config_set_path(conf, "rgui_config_directory", *g_settings.rgui_config_directory ? g_settings.rgui_config_directory : "default"); config_set_bool(conf, "rgui_show_start_screen", g_settings.rgui_show_start_screen); #endif - config_set_string(conf, "game_history_path", g_settings.game_history_path); + config_set_path(conf, "game_history_path", g_settings.game_history_path); config_set_int(conf, "game_history_size", g_settings.game_history_size); - config_set_string(conf, "joypad_autoconfig_dir", g_settings.input.autoconfig_dir); + config_set_path(conf, "joypad_autoconfig_dir", g_settings.input.autoconfig_dir); config_set_bool(conf, "input_autodetect_enable", g_settings.input.autodetect_enable); #ifdef HAVE_OVERLAY - config_set_string(conf, "overlay_directory", *g_extern.overlay_dir ? g_extern.overlay_dir : "default"); - config_set_string(conf, "input_overlay", g_settings.input.overlay); + config_set_path(conf, "overlay_directory", *g_extern.overlay_dir ? g_extern.overlay_dir : "default"); + config_set_path(conf, "input_overlay", g_settings.input.overlay); config_set_float(conf, "input_overlay_opacity", g_settings.input.overlay_opacity); config_set_float(conf, "input_overlay_scale", g_settings.input.overlay_scale); #endif @@ -1208,7 +1208,7 @@ bool config_save_file(const char *path) config_set_int(conf, "custom_viewport_x", g_extern.console.screen.viewports.custom_vp.x); config_set_int(conf, "custom_viewport_y", g_extern.console.screen.viewports.custom_vp.y); #ifdef HAVE_RMENU - config_set_string(conf, "menu_texture_path", g_extern.menu_texture_path); + config_set_path(conf, "menu_texture_path", g_extern.menu_texture_path); #endif config_set_float(conf, "video_font_size", g_settings.video.font_size);