From e306dd8eeb97707f334ce3206d01dd5b02dde76a Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Mon, 19 Jul 2021 16:37:07 +0100 Subject: [PATCH] Automatically disable core info cache when core info directory is read-only --- core_info.c | 22 +++++++++++++++------- core_info.h | 3 ++- intl/msg_hash_us.h | 4 ++++ menu/menu_setting.c | 20 ++++++++++++++++++-- msg_hash.h | 1 + retroarch.c | 17 +++++++++++++++-- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/core_info.c b/core_info.c index 69075fe98f..ea2ab05201 100644 --- a/core_info.c +++ b/core_info.c @@ -732,17 +732,18 @@ end: return core_info_cache_list; } -static void core_info_cache_write(core_info_cache_list_t *list, const char *info_dir) +static bool core_info_cache_write(core_info_cache_list_t *list, const char *info_dir) { intfstream_t *file = NULL; rjsonwriter_t *writer = NULL; + bool success = false; char file_path[PATH_MAX_LENGTH]; size_t i, j; file_path[0] = '\0'; if (!list) - return; + return false; /* Open info cache file */ if (string_is_empty(info_dir)) @@ -763,7 +764,7 @@ static void core_info_cache_write(core_info_cache_list_t *list, const char *info if (!file) { RARCH_ERR("[Core Info] Failed to write to core info cache file: %s\n", file_path); - return; + return false; } /* Write info cache */ @@ -1068,6 +1069,7 @@ static void core_info_cache_write(core_info_cache_list_t *list, const char *info rjsonwriter_free(writer); RARCH_LOG("[Core Info] Wrote to cache file: %s\n", file_path); + success = true; /* Remove 'force refresh' file, if required */ file_path[0] = '\0'; @@ -1086,6 +1088,7 @@ end: free(file); list->refresh = false; + return success; } static void core_info_check_uninstalled(core_info_cache_list_t *list) @@ -1774,7 +1777,8 @@ static core_info_list_t *core_info_list_new(const char *path, const char *libretro_info_dir, const char *exts, bool dir_show_hidden_files, - bool enable_cache) + bool enable_cache, + bool *cache_supported) { size_t i; core_path_list_t *path_list = NULL; @@ -1906,12 +1910,14 @@ static core_info_list_t *core_info_list_new(const char *path, * a refresh) * > Write new cache to disk if updates are * required */ + *cache_supported = true; if (core_info_cache_list) { core_info_check_uninstalled(core_info_cache_list); if (core_info_cache_list->refresh) - core_info_cache_write(core_info_cache_list, info_dir); + *cache_supported = core_info_cache_write( + core_info_cache_list, info_dir); core_info_cache_list_free(core_info_cache_list); } @@ -2104,14 +2110,16 @@ void core_info_deinit_list(void) } bool core_info_init_list(const char *path_info, const char *dir_cores, - const char *exts, bool dir_show_hidden_files, bool enable_cache) + const char *exts, bool dir_show_hidden_files, + bool enable_cache, bool *cache_supported) { core_info_state_t *p_coreinfo = coreinfo_get_ptr(); if (!(p_coreinfo->curr_list = core_info_list_new(dir_cores, !string_is_empty(path_info) ? path_info : dir_cores, exts, dir_show_hidden_files, - enable_cache))) + enable_cache, + cache_supported))) return false; return true; } diff --git a/core_info.h b/core_info.h index 7cb286abff..ae9a7f28ab 100644 --- a/core_info.h +++ b/core_info.h @@ -157,7 +157,8 @@ bool core_info_get_current_core(core_info_t **core); void core_info_deinit_list(void); bool core_info_init_list(const char *path_info, const char *dir_cores, - const char *exts, bool show_hidden_files, bool enable_cache); + const char *exts, bool show_hidden_files, + bool enable_cache, bool *cache_supported); bool core_info_get_list(core_info_list_t **core); diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index c36435fc05..dc77aff722 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -12034,6 +12034,10 @@ MSG_HASH( MSG_UNSUPPORTED_VIDEO_MODE, "Unsupported video mode" ) +MSG_HASH( + MSG_CORE_INFO_CACHE_UNSUPPORTED, + "Cannot write to core info directory - core info cache will be disabled" + ) /* Lakka */ diff --git a/menu/menu_setting.c b/menu/menu_setting.c index d65711c726..bc50449ed5 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -7959,8 +7959,24 @@ static void general_write_handler(rarch_setting_t *setting) * force a cache refresh on the next * core info initialisation */ if (*setting->value.target.boolean) - core_info_cache_force_refresh(!string_is_empty(path_libretro_info) ? - path_libretro_info : dir_libretro); + if (!core_info_cache_force_refresh(!string_is_empty(path_libretro_info) ? + path_libretro_info : dir_libretro)) + { + /* core_info_cache_force_refresh() will fail + * if we cannot write to the the core_info + * directory. This will typically only happen + * on platforms where the core_info directory + * is explicitly (and intentionally) placed on + * read-only storage. In this case, core info + * caching cannot function correctly anyway, + * so we simply force-disable the feature */ + configuration_set_bool(settings, + settings->bools.core_info_cache_enable, false); + runloop_msg_queue_push( + msg_hash_to_str(MSG_CORE_INFO_CACHE_UNSUPPORTED), + 1, 100, true, + NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + } } break; default: diff --git a/msg_hash.h b/msg_hash.h index 7ae1857157..0f9f8c35df 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -491,6 +491,7 @@ enum msg_hash_enums MSG_LOCALAP_ERROR_CONFIG_PARSE, #endif MSG_UNSUPPORTED_VIDEO_MODE, + MSG_CORE_INFO_CACHE_UNSUPPORTED, MENU_LABEL(MENU_XMB_ANIMATION_HORIZONTAL_HIGHLIGHT), MENU_LABEL(MENU_XMB_ANIMATION_MOVE_UP_DOWN), diff --git a/retroarch.c b/retroarch.c index 14b126adef..15c67eeb77 100644 --- a/retroarch.c +++ b/retroarch.c @@ -14296,12 +14296,25 @@ bool command_event(enum event_command cmd, void *data) return false; if (!string_is_empty(dir_libretro)) + { + bool cache_supported = false; + core_info_init_list(path_libretro_info, dir_libretro, ext_name, show_hidden_files, - core_info_cache_enable - ); + core_info_cache_enable, + &cache_supported); + + /* If core info cache is enabled but cache + * functionality is unsupported (i.e. because + * the core info directory is on read-only + * storage), force-disable the setting to + * avoid repeated failures */ + if (core_info_cache_enable && !cache_supported) + configuration_set_bool(settings, + settings->bools.core_info_cache_enable, false); + } } break; case CMD_EVENT_CORE_DEINIT: