(Android) Play Store builds: Do not resolve symlinks when handling core paths

This commit is contained in:
jdgleaver 2020-08-31 12:12:09 +01:00
parent 201f119c51
commit 20230ec625
6 changed files with 138 additions and 37 deletions

View File

@ -273,6 +273,7 @@ bool core_updater_list_get_core(
const char *local_core_path, const char *local_core_path,
const core_updater_list_entry_t **entry) const core_updater_list_entry_t **entry)
{ {
bool resolve_symlinks;
size_t num_entries; size_t num_entries;
size_t i; size_t i;
char real_core_path[PATH_MAX_LENGTH]; char real_core_path[PATH_MAX_LENGTH];
@ -289,7 +290,14 @@ bool core_updater_list_get_core(
/* Resolve absolute pathname of local_core_path */ /* Resolve absolute pathname of local_core_path */
strlcpy(real_core_path, local_core_path, sizeof(real_core_path)); strlcpy(real_core_path, local_core_path, sizeof(real_core_path));
path_resolve_realpath(real_core_path, sizeof(real_core_path), true); /* Can't resolve symlinks when dealing with cores
* installed via play feature delivery, because the
* source files have non-standard file names (which
* will not be recognised by regular core handling
* routines) */
resolve_symlinks = (core_list->type != CORE_UPDATER_LIST_TYPE_PFD);
path_resolve_realpath(real_core_path, sizeof(real_core_path),
resolve_symlinks);
if (string_is_empty(real_core_path)) if (string_is_empty(real_core_path))
return false; return false;
@ -391,10 +399,16 @@ static bool core_updater_list_set_paths(
{ {
char *last_underscore = NULL; char *last_underscore = NULL;
char *tmp_url = NULL; char *tmp_url = NULL;
bool is_archive = true;
/* Can't resolve symlinks when dealing with cores
* installed via play feature delivery, because the
* source files have non-standard file names (which
* will not be recognised by regular core handling
* routines) */
bool resolve_symlinks = (list_type != CORE_UPDATER_LIST_TYPE_PFD);
char remote_core_path[PATH_MAX_LENGTH]; char remote_core_path[PATH_MAX_LENGTH];
char local_core_path[PATH_MAX_LENGTH]; char local_core_path[PATH_MAX_LENGTH];
char local_info_path[PATH_MAX_LENGTH]; char local_info_path[PATH_MAX_LENGTH];
bool is_archive;
remote_core_path[0] = '\0'; remote_core_path[0] = '\0';
local_core_path[0] = '\0'; local_core_path[0] = '\0';
@ -460,7 +474,8 @@ static bool core_updater_list_set_paths(
if (is_archive) if (is_archive)
path_remove_extension(local_core_path); path_remove_extension(local_core_path);
path_resolve_realpath(local_core_path, sizeof(local_core_path), true); path_resolve_realpath(local_core_path, sizeof(local_core_path),
resolve_symlinks);
if (entry->local_core_path) if (entry->local_core_path)
{ {

View File

@ -2168,7 +2168,7 @@ static int action_ok_playlist_entry_collection(const char *path,
if (!string_is_empty(entry->path)) if (!string_is_empty(entry->path))
{ {
strlcpy(content_path, entry->path, sizeof(content_path)); strlcpy(content_path, entry->path, sizeof(content_path));
playlist_resolve_path(PLAYLIST_LOAD, content_path, sizeof(content_path)); playlist_resolve_path(PLAYLIST_LOAD, false, content_path, sizeof(content_path));
} }
/* Cache entry label */ /* Cache entry label */
@ -2239,7 +2239,7 @@ static int action_ok_playlist_entry_collection(const char *path,
/* Core path is invalid - just copy what we have /* Core path is invalid - just copy what we have
* and hope for the best... */ * and hope for the best... */
strlcpy(core_path, entry->core_path, sizeof(core_path)); strlcpy(core_path, entry->core_path, sizeof(core_path));
playlist_resolve_path(PLAYLIST_LOAD, core_path, sizeof(core_path)); playlist_resolve_path(PLAYLIST_LOAD, true, core_path, sizeof(core_path));
} }
} }
} }
@ -3284,7 +3284,7 @@ static int action_ok_core_deferred_set(const char *new_core_path,
true); true);
strlcpy(resolved_core_path, new_core_path, sizeof(resolved_core_path)); strlcpy(resolved_core_path, new_core_path, sizeof(resolved_core_path));
playlist_resolve_path(PLAYLIST_SAVE, resolved_core_path, sizeof(resolved_core_path)); playlist_resolve_path(PLAYLIST_SAVE, true, resolved_core_path, sizeof(resolved_core_path));
/* the update function reads our entry /* the update function reads our entry
* as const, so these casts are safe */ * as const, so these casts are safe */

View File

@ -44,22 +44,28 @@
typedef struct typedef struct
{ {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
slock_t *lock; slock_t *enabled_lock;
slock_t *status_lock;
#endif #endif
unsigned download_progress; unsigned download_progress;
enum play_feature_delivery_install_status last_status; enum play_feature_delivery_install_status last_status;
char last_core_name[256]; char last_core_name[256];
bool enabled;
bool enabled_set;
bool active; bool active;
} play_feature_delivery_state_t; } play_feature_delivery_state_t;
static play_feature_delivery_state_t play_feature_delivery_state = { static play_feature_delivery_state_t play_feature_delivery_state = {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
NULL, /* lock */ NULL, /* enabled_lock */
NULL, /* status_lock */
#endif #endif
0, /* download_progress */ 0, /* download_progress */
PLAY_FEATURE_DELIVERY_IDLE, /* last_status */ PLAY_FEATURE_DELIVERY_IDLE, /* last_status */
{'\0'}, /* last_core_name */ {'\0'}, /* last_core_name */
false, /* enabled */
false, /* enabled_set */
false, /* active */ false, /* active */
}; };
@ -85,7 +91,7 @@ JNIEXPORT void JNICALL Java_com_retroarch_browser_retroactivity_RetroActivityCom
/* Lock mutex */ /* Lock mutex */
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
slock_lock(state->lock); slock_lock(state->status_lock);
#endif #endif
/* Only update status if an install is active */ /* Only update status if an install is active */
@ -114,7 +120,7 @@ JNIEXPORT void JNICALL Java_com_retroarch_browser_retroactivity_RetroActivityCom
/* Unlock mutex */ /* Unlock mutex */
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
slock_unlock(state->lock); slock_unlock(state->status_lock);
#endif #endif
} }
@ -130,7 +136,7 @@ JNIEXPORT void JNICALL Java_com_retroarch_browser_retroactivity_RetroActivityCom
/* Lock mutex */ /* Lock mutex */
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
slock_lock(state->lock); slock_lock(state->status_lock);
#endif #endif
/* Only update status if an install is active */ /* Only update status if an install is active */
@ -184,7 +190,7 @@ JNIEXPORT void JNICALL Java_com_retroarch_browser_retroactivity_RetroActivityCom
/* Unlock mutex */ /* Unlock mutex */
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
slock_unlock(state->lock); slock_unlock(state->status_lock);
#endif #endif
} }
@ -198,12 +204,23 @@ void play_feature_delivery_init(void)
play_feature_delivery_state_t* state = play_feature_delivery_get_state(); play_feature_delivery_state_t* state = play_feature_delivery_get_state();
play_feature_delivery_deinit(); play_feature_delivery_deinit();
#ifdef HAVE_THREADS
if (!state->lock)
state->lock = slock_new();
retro_assert(state->lock); #ifdef HAVE_THREADS
if (!state->enabled_lock)
state->enabled_lock = slock_new();
retro_assert(state->enabled_lock);
if (!state->status_lock)
state->status_lock = slock_new();
retro_assert(state->status_lock);
#endif #endif
/* Note: Would like to cache whether this
* is a Play Store build here, but
* play_feature_delivery_init() is called
* too early in the startup sequence... */
} }
/* Must be called upon program termination */ /* Must be called upon program termination */
@ -212,10 +229,16 @@ void play_feature_delivery_deinit(void)
play_feature_delivery_state_t* state = play_feature_delivery_get_state(); play_feature_delivery_state_t* state = play_feature_delivery_get_state();
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
if (state->lock) if (state->enabled_lock)
{ {
slock_free(state->lock); slock_free(state->enabled_lock);
state->lock = NULL; state->enabled_lock = NULL;
}
if (state->status_lock)
{
slock_free(state->status_lock);
state->status_lock = NULL;
} }
#endif #endif
} }
@ -251,8 +274,10 @@ static bool play_feature_delivery_get_core_name(
} }
/* Returns true if current build utilises /* Returns true if current build utilises
* play feature delivery */ * play feature delivery
bool play_feature_delivery_enabled(void) * > Relies on a Java function call, and is
* therefore slow */
static bool play_feature_delivery_enabled_internal(void)
{ {
JNIEnv *env = jni_thread_getenv(); JNIEnv *env = jni_thread_getenv();
struct android_app *app = (struct android_app*)g_android; struct android_app *app = (struct android_app*)g_android;
@ -269,6 +294,39 @@ bool play_feature_delivery_enabled(void)
return enabled; return enabled;
} }
/* Returns true if current build utilises
* play feature delivery */
bool play_feature_delivery_enabled(void)
{
play_feature_delivery_state_t* state = play_feature_delivery_get_state();
bool enabled;
/* Lock mutex */
#ifdef HAVE_THREADS
slock_lock(state->enabled_lock);
#endif
/* Calling Java functions is slow. We need to
* check Play Store build status frequently,
* often in loops, so rely on a cached global
* status flag instead dealing with Java
* interfaces */
if (!state->enabled_set)
{
state->enabled = play_feature_delivery_enabled_internal();
state->enabled_set = true;
}
enabled = state->enabled;
/* Unlock mutex */
#ifdef HAVE_THREADS
slock_unlock(state->enabled_lock);
#endif
return enabled;
}
/* Returns a list of cores currently available /* Returns a list of cores currently available
* via play feature delivery. * via play feature delivery.
* Returns a new string_list on success, or * Returns a new string_list on success, or
@ -408,7 +466,7 @@ bool play_feature_delivery_download_status(
/* Lock mutex */ /* Lock mutex */
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
slock_lock(state->lock); slock_lock(state->status_lock);
#endif #endif
/* Copy status parameters */ /* Copy status parameters */
@ -422,7 +480,7 @@ bool play_feature_delivery_download_status(
/* Unlock mutex */ /* Unlock mutex */
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
slock_unlock(state->lock); slock_unlock(state->status_lock);
#endif #endif
return active; return active;
@ -459,7 +517,7 @@ bool play_feature_delivery_download(const char *core_file)
/* Lock mutex */ /* Lock mutex */
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
slock_lock(state->lock); slock_lock(state->status_lock);
#endif #endif
/* We only support one download at a time */ /* We only support one download at a time */
@ -487,7 +545,7 @@ bool play_feature_delivery_download(const char *core_file)
/* Unlock mutex */ /* Unlock mutex */
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
slock_unlock(state->lock); slock_unlock(state->status_lock);
#endif #endif
return success; return success;

View File

@ -334,7 +334,8 @@ static bool playlist_core_path_equal(const char *real_core_path, const char *ent
strlcpy(entry_real_core_path, entry_core_path, sizeof(entry_real_core_path)); strlcpy(entry_real_core_path, entry_core_path, sizeof(entry_real_core_path));
if (!string_is_equal(entry_real_core_path, FILE_PATH_DETECT) && if (!string_is_equal(entry_real_core_path, FILE_PATH_DETECT) &&
!string_is_equal(entry_real_core_path, FILE_PATH_BUILTIN)) !string_is_equal(entry_real_core_path, FILE_PATH_BUILTIN))
path_resolve_realpath(entry_real_core_path, sizeof(entry_real_core_path), true); playlist_resolve_path(PLAYLIST_SAVE, true, entry_real_core_path,
sizeof(entry_real_core_path));
if (string_is_empty(entry_real_core_path)) if (string_is_empty(entry_real_core_path))
return false; return false;
@ -764,14 +765,15 @@ bool playlist_push_runtime(playlist_t *playlist,
if (!string_is_empty(entry->path)) if (!string_is_empty(entry->path))
{ {
strlcpy(real_path, entry->path, sizeof(real_path)); strlcpy(real_path, entry->path, sizeof(real_path));
path_resolve_realpath(real_path, sizeof(real_path), true); playlist_resolve_path(PLAYLIST_SAVE, false, real_path, sizeof(real_path));
} }
/* Get 'real' core path */ /* Get 'real' core path */
strlcpy(real_core_path, entry->core_path, sizeof(real_core_path)); strlcpy(real_core_path, entry->core_path, sizeof(real_core_path));
if (!string_is_equal(real_core_path, FILE_PATH_DETECT) && if (!string_is_equal(real_core_path, FILE_PATH_DETECT) &&
!string_is_equal(real_core_path, FILE_PATH_BUILTIN)) !string_is_equal(real_core_path, FILE_PATH_BUILTIN))
path_resolve_realpath(real_core_path, sizeof(real_core_path), true); playlist_resolve_path(PLAYLIST_SAVE, true, real_core_path,
sizeof(real_core_path));
if (string_is_empty(real_core_path)) if (string_is_empty(real_core_path))
{ {
@ -869,6 +871,7 @@ success:
/** /**
* playlist_resolve_path: * playlist_resolve_path:
* @mode : PLAYLIST_LOAD or PLAYLIST_SAVE * @mode : PLAYLIST_LOAD or PLAYLIST_SAVE
* @is_core : Set true if path to be resolved is a core file
* @path : The path to be modified * @path : The path to be modified
* *
* Resolves the path of an item, such as the content path or path to the core, to a format * Resolves the path of an item, such as the content path or path to the core, to a format
@ -879,7 +882,7 @@ success:
* install (iOS) * install (iOS)
**/ **/
void playlist_resolve_path(enum playlist_file_mode mode, void playlist_resolve_path(enum playlist_file_mode mode,
char *path, size_t len) bool is_core, char *path, size_t len)
{ {
#ifdef HAVE_COCOATOUCH #ifdef HAVE_COCOATOUCH
char tmp[PATH_MAX_LENGTH]; char tmp[PATH_MAX_LENGTH];
@ -903,10 +906,22 @@ void playlist_resolve_path(enum playlist_file_mode mode,
fill_pathname_abbreviate_special(path, tmp2, len); fill_pathname_abbreviate_special(path, tmp2, len);
} }
#else #else
bool resolve_symlinks = true;
if (mode == PLAYLIST_LOAD) if (mode == PLAYLIST_LOAD)
return; return;
path_resolve_realpath(path, len, true); #if defined(ANDROID)
/* Can't resolve symlinks when dealing with cores
* installed via play feature delivery, because the
* source files have non-standard file names (which
* will not be recognised by regular core handling
* routines) */
if (is_core)
resolve_symlinks = !play_feature_delivery_enabled();
#endif
path_resolve_realpath(path, len, resolve_symlinks);
#endif #endif
} }
@ -941,14 +956,14 @@ bool playlist_push(playlist_t *playlist,
if (!string_is_empty(entry->path)) if (!string_is_empty(entry->path))
{ {
strlcpy(real_path, entry->path, sizeof(real_path)); strlcpy(real_path, entry->path, sizeof(real_path));
playlist_resolve_path(PLAYLIST_SAVE, real_path, sizeof(real_path)); playlist_resolve_path(PLAYLIST_SAVE, false, real_path, sizeof(real_path));
} }
/* Get 'real' core path */ /* Get 'real' core path */
strlcpy(real_core_path, entry->core_path, sizeof(real_core_path)); strlcpy(real_core_path, entry->core_path, sizeof(real_core_path));
if (!string_is_equal(real_core_path, FILE_PATH_DETECT) && if (!string_is_equal(real_core_path, FILE_PATH_DETECT) &&
!string_is_equal(real_core_path, FILE_PATH_BUILTIN)) !string_is_equal(real_core_path, FILE_PATH_BUILTIN))
playlist_resolve_path(PLAYLIST_SAVE, real_core_path, playlist_resolve_path(PLAYLIST_SAVE, true, real_core_path,
sizeof(real_core_path)); sizeof(real_core_path));
if (string_is_empty(real_core_path)) if (string_is_empty(real_core_path))
@ -2976,7 +2991,8 @@ bool playlist_entries_are_equal(
strlcpy(real_core_path_a, entry_a->core_path, sizeof(real_core_path_a)); strlcpy(real_core_path_a, entry_a->core_path, sizeof(real_core_path_a));
if (!string_is_equal(real_core_path_a, FILE_PATH_DETECT) && if (!string_is_equal(real_core_path_a, FILE_PATH_DETECT) &&
!string_is_equal(real_core_path_a, FILE_PATH_BUILTIN)) !string_is_equal(real_core_path_a, FILE_PATH_BUILTIN))
path_resolve_realpath(real_core_path_a, sizeof(real_core_path_a), true); playlist_resolve_path(PLAYLIST_SAVE, true,
real_core_path_a, sizeof(real_core_path_a));
} }
return playlist_core_path_equal(real_core_path_a, entry_b->core_path, config); return playlist_core_path_equal(real_core_path_a, entry_b->core_path, config);
@ -3076,7 +3092,7 @@ void playlist_set_default_core_path(playlist_t *playlist, const char *core_path)
strlcpy(real_core_path, core_path, sizeof(real_core_path)); strlcpy(real_core_path, core_path, sizeof(real_core_path));
if (!string_is_equal(real_core_path, FILE_PATH_DETECT) && if (!string_is_equal(real_core_path, FILE_PATH_DETECT) &&
!string_is_equal(real_core_path, FILE_PATH_BUILTIN)) !string_is_equal(real_core_path, FILE_PATH_BUILTIN))
playlist_resolve_path(PLAYLIST_SAVE, playlist_resolve_path(PLAYLIST_SAVE, true,
real_core_path, sizeof(real_core_path)); real_core_path, sizeof(real_core_path));
if (string_is_empty(real_core_path)) if (string_is_empty(real_core_path))

View File

@ -223,7 +223,8 @@ void playlist_delete_by_path(playlist_t *playlist,
/** /**
* playlist_resolve_path: * playlist_resolve_path:
* @mode : PLAYLIST_LOAD or PLAYLIST_SAVE * @mode : PLAYLIST_LOAD or PLAYLIST_SAVE
* @path : The path to be modified * @is_core : Set true if path to be resolved is a core file
* @path : The path to be modified
* *
* Resolves the path of an item, such as the content path or path to the core, to a format * Resolves the path of an item, such as the content path or path to the core, to a format
* appropriate for saving or loading depending on the @mode parameter * appropriate for saving or loading depending on the @mode parameter
@ -233,7 +234,7 @@ void playlist_delete_by_path(playlist_t *playlist,
* install (iOS) * install (iOS)
**/ **/
void playlist_resolve_path(enum playlist_file_mode mode, void playlist_resolve_path(enum playlist_file_mode mode,
char *path, size_t len); bool is_core, char *path, size_t len);
/** /**
* playlist_push: * playlist_push:

View File

@ -20305,6 +20305,17 @@ static bool load_dynamic_core(
struct rarch_state *p_rarch, struct rarch_state *p_rarch,
const char *path, char *buf, size_t size) const char *path, char *buf, size_t size)
{ {
#if defined(ANDROID)
/* Can't resolve symlinks when dealing with cores
* installed via play feature delivery, because the
* source files have non-standard file names (which
* will not be recognised by regular core handling
* routines) */
bool resolve_symlinks = !play_feature_delivery_enabled();
#else
bool resolve_symlinks = true;
#endif
/* Can't lookup symbols in itself on UWP */ /* Can't lookup symbols in itself on UWP */
#if !(defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) #if !(defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
if (dylib_proc(NULL, "retro_init")) if (dylib_proc(NULL, "retro_init"))
@ -20323,7 +20334,7 @@ static bool load_dynamic_core(
/* Need to use absolute path for this setting. It can be /* Need to use absolute path for this setting. It can be
* saved to content history, and a relative path would * saved to content history, and a relative path would
* break in that scenario. */ * break in that scenario. */
path_resolve_realpath(buf, size, true); path_resolve_realpath(buf, size, resolve_symlinks);
if ((p_rarch->lib_handle = dylib_load(path))) if ((p_rarch->lib_handle = dylib_load(path)))
return true; return true;
return false; return false;