diff --git a/conf/config_file.c b/conf/config_file.c index ced76f2b5e..304cf27917 100644 --- a/conf/config_file.c +++ b/conf/config_file.c @@ -563,7 +563,7 @@ bool config_get_array(config_file_t *conf, const char *key, char *buf, size_t si bool config_get_path(config_file_t *conf, const char *key, char *buf, size_t size) { -#if defined(_WIN32) || defined(RARCH_CONSOLE) +#if defined(RARCH_CONSOLE) return config_get_array(conf, key, buf, size); #else struct config_entry_list *list = conf->entries; @@ -573,6 +573,7 @@ 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"); @@ -587,6 +588,27 @@ bool config_get_path(config_file_t *conf, const char *key, char *buf, size_t siz 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; } diff --git a/file.h b/file.h index e0d6f2f75e..4aa6876a6e 100644 --- a/file.h +++ b/file.h @@ -131,6 +131,10 @@ 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); +#ifndef RARCH_CONSOLE +void fill_pathname_application_path(char *buf, size_t size); +#endif + size_t convert_char_to_wchar(wchar_t *out_wchar, const char *in_char, size_t size); size_t convert_wchar_to_char(char *out_char, const wchar_t *in_wchar, size_t size); diff --git a/file_path.c b/file_path.c index 38600c2921..9346a2fa7c 100644 --- a/file_path.c +++ b/file_path.c @@ -45,6 +45,7 @@ #include #include #include +#include #endif void string_list_free(struct string_list *list) @@ -536,6 +537,37 @@ void fill_pathname_join(char *out_path, const char *dir, const char *path, size_ rarch_assert(strlcat(out_path, path, size) < size); } +#ifndef RARCH_CONSOLE +void fill_pathname_application_path(char *buf, size_t size) +{ + if (!size) + return; + +#ifdef _WIN32 + DWORD ret = GetModuleFileName(GetModuleHandle(NULL), buf, size - 1); + buf[ret] = '\0'; +#else + + *buf = '\0'; + pid_t pid = getpid(); + char link_path[PATH_MAX]; + static const char *exts[] = { "exe", "file", "path/a.out" }; // Linux, BSD and Solaris paths. Not standardized. + for (unsigned i = 0; i < ARRAY_SIZE(exts); i++) + { + snprintf(link_path, sizeof(link_path), "/proc/%u/%s", (unsigned)pid, exts[i]); + ssize_t ret = readlink(link_path, buf, size - 1); + if (ret >= 0) + { + buf[ret] = '\0'; + return; + } + } + + RARCH_ERR("Cannot resolve application path! This should not happen.\n"); +#endif +} +#endif + size_t convert_char_to_wchar(wchar_t *out_wchar, const char *in_char, size_t size) { return mbstowcs(out_wchar, in_char, size / sizeof(wchar_t)); diff --git a/frontend/frontend.c b/frontend/frontend.c index 5edcaeeb3f..c940082388 100644 --- a/frontend/frontend.c +++ b/frontend/frontend.c @@ -15,6 +15,8 @@ */ #include "../general.h" +#include "conf/config_file.h" +#include "../file.h" #ifdef HAVE_RGUI #include "../frontend/menu/rgui.h" @@ -33,6 +35,7 @@ int main(int argc, char *argv[]) // Consoles use the higher level API. return rarch_main(argc, argv); #else + rarch_init_msg_queue(); int init_ret;