mirror of
https://github.com/libretro/RetroArch
synced 2025-04-18 14:42:30 +00:00
Merge pull request #9137 from LazyBumHorse/realpath
replace realpath() by custom code which does not resolve symlinks
This commit is contained in:
commit
52ef1af14e
@ -53,7 +53,7 @@ bool glslang_read_shader_file(const char *path, vector<string> *output, bool roo
|
|||||||
include_path[0] = tmp[0] = '\0';
|
include_path[0] = tmp[0] = '\0';
|
||||||
|
|
||||||
strlcpy(tmp_path, path, path_size);
|
strlcpy(tmp_path, path, path_size);
|
||||||
path_resolve_realpath(tmp_path, path_size);
|
path_resolve_realpath(tmp_path, path_size, false);
|
||||||
|
|
||||||
if (!path_is_valid(tmp_path))
|
if (!path_is_valid(tmp_path))
|
||||||
strlcpy(tmp_path, path, path_size);
|
strlcpy(tmp_path, path, path_size);
|
||||||
|
@ -756,7 +756,7 @@ void video_shader_write_conf_preset(config_file_t *conf,
|
|||||||
strlcpy(tmp_base, preset_path, tmp_size);
|
strlcpy(tmp_base, preset_path, tmp_size);
|
||||||
|
|
||||||
/* ensure we use a clean base like the shader passes and texture paths do */
|
/* ensure we use a clean base like the shader passes and texture paths do */
|
||||||
path_resolve_realpath(tmp_base, tmp_size);
|
path_resolve_realpath(tmp_base, tmp_size, false);
|
||||||
path_basedir(tmp_base);
|
path_basedir(tmp_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,35 +756,135 @@ bool path_is_absolute(const char *path)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* path_resolve_realpath:
|
* path_resolve_realpath:
|
||||||
* @buf : buffer for path
|
* @buf : input and output buffer for path
|
||||||
* @size : size of buffer
|
* @size : size of buffer
|
||||||
|
* @resolve_symlinks : whether to resolve symlinks or not
|
||||||
*
|
*
|
||||||
* Turns relative paths into absolute paths and
|
* Resolves use of ".", "..", multiple slashes etc in absolute paths.
|
||||||
* resolves use of "." and ".." in absolute paths.
|
*
|
||||||
* If relative, rebases on current working dir.
|
* Relative paths are rebased on the current working dir.
|
||||||
|
*
|
||||||
|
* Returns: @buf if successful, NULL otherwise.
|
||||||
|
* Note: Not implemented on consoles
|
||||||
|
* Note: Symlinks are only resolved on Unix-likes
|
||||||
|
* Note: The current working dir might not be what you expect,
|
||||||
|
* e.g. on Android it is "/"
|
||||||
|
* Use of fill_pathname_resolve_relative() should be prefered
|
||||||
**/
|
**/
|
||||||
void path_resolve_realpath(char *buf, size_t size)
|
char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks)
|
||||||
{
|
{
|
||||||
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
||||||
char tmp[PATH_MAX_LENGTH];
|
char tmp[PATH_MAX_LENGTH];
|
||||||
|
|
||||||
tmp[0] = '\0';
|
|
||||||
|
|
||||||
strlcpy(tmp, buf, sizeof(tmp));
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
strlcpy(tmp, buf, sizeof(tmp));
|
||||||
if (!_fullpath(buf, tmp, size))
|
if (!_fullpath(buf, tmp, size))
|
||||||
|
{
|
||||||
strlcpy(buf, tmp, size);
|
strlcpy(buf, tmp, size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
#else
|
#else
|
||||||
|
size_t t;
|
||||||
|
char *p;
|
||||||
|
const char *next;
|
||||||
|
const char *buf_end;
|
||||||
|
|
||||||
/* NOTE: realpath() expects at least PATH_MAX_LENGTH bytes in buf.
|
if (resolve_symlinks)
|
||||||
* Technically, PATH_MAX_LENGTH needn't be defined, but we rely on it anyways.
|
{
|
||||||
* POSIX 2008 can automatically allocate for you,
|
strlcpy(tmp, buf, sizeof(tmp));
|
||||||
* but don't rely on that. */
|
|
||||||
if (!realpath(tmp, buf))
|
/* NOTE: realpath() expects at least PATH_MAX_LENGTH bytes in buf.
|
||||||
strlcpy(buf, tmp, size);
|
* Technically, PATH_MAX_LENGTH needn't be defined, but we rely on it anyways.
|
||||||
|
* POSIX 2008 can automatically allocate for you,
|
||||||
|
* but don't rely on that. */
|
||||||
|
if (!realpath(tmp, buf))
|
||||||
|
{
|
||||||
|
strlcpy(buf, tmp, size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
t = 0; /* length of output */
|
||||||
|
buf_end = buf + strlen(buf);
|
||||||
|
|
||||||
|
if (!path_is_absolute(buf))
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
/* rebase on working directory */
|
||||||
|
if (!getcwd(tmp, PATH_MAX_LENGTH-1))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
len = strlen(tmp);
|
||||||
|
t += len;
|
||||||
|
|
||||||
|
if (tmp[len-1] != '/')
|
||||||
|
tmp[t++] = '/';
|
||||||
|
|
||||||
|
if (string_is_empty(buf))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* UNIX paths can start with multiple '/', copy those */
|
||||||
|
for (p = buf; *p == '/'; p++)
|
||||||
|
tmp[t++] = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* p points to just after a slash while 'next' points to the next slash
|
||||||
|
* if there are no slashes, they point relative to where one would be */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
next = strchr(p, '/');
|
||||||
|
if (!next)
|
||||||
|
next = buf_end;
|
||||||
|
|
||||||
|
if ((next - p == 2 && p[0] == '.' && p[1] == '.'))
|
||||||
|
{
|
||||||
|
p += 3;
|
||||||
|
|
||||||
|
/* fail for illegal /.., //.. etc */
|
||||||
|
if (t == 1 || tmp[t-2] == '/')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* delete previous segment in tmp by adjusting size t
|
||||||
|
* tmp[t-1] == '/', find '/' before that */
|
||||||
|
t = t-2;
|
||||||
|
while (tmp[t] != '/')
|
||||||
|
t--;
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
else if (next - p == 1 && p[0] == '.')
|
||||||
|
{
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
else if (next - p == 0)
|
||||||
|
{
|
||||||
|
p += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* fail when truncating */
|
||||||
|
if (t + next-p+1 > PATH_MAX_LENGTH-1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (p <= next)
|
||||||
|
tmp[t++] = *p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while (next < buf_end);
|
||||||
|
|
||||||
|
end:
|
||||||
|
tmp[t] = '\0';
|
||||||
|
strlcpy(buf, tmp, size);
|
||||||
|
return buf;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -855,7 +955,7 @@ void fill_pathname_resolve_relative(char *out_path,
|
|||||||
|
|
||||||
fill_pathname_basedir(out_path, in_refpath, size);
|
fill_pathname_basedir(out_path, in_refpath, size);
|
||||||
strlcat(out_path, in_path, size);
|
strlcat(out_path, in_path, size);
|
||||||
path_resolve_realpath(out_path, size);
|
path_resolve_realpath(out_path, size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,14 +147,22 @@ void path_parent_dir(char *path);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* path_resolve_realpath:
|
* path_resolve_realpath:
|
||||||
* @buf : buffer for path
|
* @buf : input and output buffer for path
|
||||||
* @size : size of buffer
|
* @size : size of buffer
|
||||||
|
* @resolve_symlinks : whether to resolve symlinks or not
|
||||||
*
|
*
|
||||||
* Turns relative paths into absolute paths and
|
* Resolves use of ".", "..", multiple slashes etc in absolute paths.
|
||||||
* resolves use of "." and ".." in absolute paths.
|
*
|
||||||
* If relative, rebases on current working dir.
|
* Relative paths are rebased on the current working dir.
|
||||||
|
*
|
||||||
|
* Returns: @buf if successful, NULL otherwise.
|
||||||
|
* Note: Not implemented on consoles
|
||||||
|
* Note: Symlinks are only resolved on Unix-likes
|
||||||
|
* Note: The current working dir might not be what you expect,
|
||||||
|
* e.g. on Android it is "/"
|
||||||
|
* Use of fill_pathname_resolve_relative() should be prefered
|
||||||
**/
|
**/
|
||||||
void path_resolve_realpath(char *buf, size_t size);
|
char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* path_relative_to:
|
* path_relative_to:
|
||||||
|
58
playlist.c
58
playlist.c
@ -104,7 +104,7 @@ static bool playlist_path_equal(const char *real_path, const char *entry_path)
|
|||||||
|
|
||||||
/* Get entry 'real' path */
|
/* Get entry 'real' path */
|
||||||
strlcpy(entry_real_path, entry_path, sizeof(entry_real_path));
|
strlcpy(entry_real_path, entry_path, sizeof(entry_real_path));
|
||||||
path_resolve_realpath(entry_real_path, sizeof(entry_real_path));
|
path_resolve_realpath(entry_real_path, sizeof(entry_real_path), true);
|
||||||
|
|
||||||
if (string_is_empty(entry_real_path))
|
if (string_is_empty(entry_real_path))
|
||||||
return false;
|
return false;
|
||||||
@ -193,7 +193,7 @@ static bool playlist_core_path_equal(const char *real_core_path, const char *ent
|
|||||||
/* Get entry 'real' core path */
|
/* Get entry 'real' core path */
|
||||||
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_str(FILE_PATH_DETECT)))
|
if (!string_is_equal(entry_real_core_path, file_path_str(FILE_PATH_DETECT)))
|
||||||
path_resolve_realpath(entry_real_core_path, sizeof(entry_real_core_path));
|
path_resolve_realpath(entry_real_core_path, sizeof(entry_real_core_path), true);
|
||||||
|
|
||||||
if (string_is_empty(entry_real_core_path))
|
if (string_is_empty(entry_real_core_path))
|
||||||
return false;
|
return false;
|
||||||
@ -279,7 +279,7 @@ void playlist_get_index_by_path(playlist_t *playlist,
|
|||||||
|
|
||||||
/* Get 'real' search path */
|
/* Get 'real' search path */
|
||||||
strlcpy(real_search_path, search_path, sizeof(real_search_path));
|
strlcpy(real_search_path, search_path, sizeof(real_search_path));
|
||||||
path_resolve_realpath(real_search_path, sizeof(real_search_path));
|
path_resolve_realpath(real_search_path, sizeof(real_search_path), true);
|
||||||
|
|
||||||
for (i = 0; i < playlist->size; i++)
|
for (i = 0; i < playlist->size; i++)
|
||||||
{
|
{
|
||||||
@ -306,7 +306,7 @@ bool playlist_entry_exists(playlist_t *playlist,
|
|||||||
|
|
||||||
/* Get 'real' search path */
|
/* Get 'real' search path */
|
||||||
strlcpy(real_search_path, path, sizeof(real_search_path));
|
strlcpy(real_search_path, path, sizeof(real_search_path));
|
||||||
path_resolve_realpath(real_search_path, sizeof(real_search_path));
|
path_resolve_realpath(real_search_path, sizeof(real_search_path), true);
|
||||||
|
|
||||||
for (i = 0; i < playlist->size; i++)
|
for (i = 0; i < playlist->size; i++)
|
||||||
if (playlist_path_equal(real_search_path, playlist->entries[i].path))
|
if (playlist_path_equal(real_search_path, playlist->entries[i].path))
|
||||||
@ -539,13 +539,13 @@ 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));
|
path_resolve_realpath(real_path, sizeof(real_path), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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_str(FILE_PATH_DETECT)))
|
if (!string_is_equal(real_core_path, file_path_str(FILE_PATH_DETECT)))
|
||||||
path_resolve_realpath(real_core_path, sizeof(real_core_path));
|
path_resolve_realpath(real_core_path, sizeof(real_core_path), true);
|
||||||
|
|
||||||
if (string_is_empty(real_core_path))
|
if (string_is_empty(real_core_path))
|
||||||
{
|
{
|
||||||
@ -628,7 +628,7 @@ success:
|
|||||||
/**
|
/**
|
||||||
* playlist_resolve_path:
|
* playlist_resolve_path:
|
||||||
* @mode : PLAYLIST_LOAD or PLAYLIST_SAVE
|
* @mode : PLAYLIST_LOAD or PLAYLIST_SAVE
|
||||||
* @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
|
||||||
* appropriate for saving or loading depending on the @mode parameter
|
* appropriate for saving or loading depending on the @mode parameter
|
||||||
@ -640,32 +640,26 @@ success:
|
|||||||
void playlist_resolve_path(enum playlist_file_mode mode,
|
void playlist_resolve_path(enum playlist_file_mode mode,
|
||||||
char *path, size_t size)
|
char *path, size_t size)
|
||||||
{
|
{
|
||||||
char tmp[PATH_MAX_LENGTH];
|
|
||||||
tmp[0] = '\0';
|
|
||||||
#ifdef HAVE_COCOATOUCH
|
#ifdef HAVE_COCOATOUCH
|
||||||
char resolved_path[PATH_MAX_LENGTH] = {0};
|
char tmp[PATH_MAX_LENGTH];
|
||||||
strlcpy(tmp, path, sizeof(tmp));
|
|
||||||
if ( mode == PLAYLIST_LOAD )
|
|
||||||
{
|
|
||||||
strlcpy(resolved_path, tmp, sizeof(resolved_path));
|
|
||||||
fill_pathname_expand_special(tmp, resolved_path, sizeof(tmp));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* iOS needs to call realpath here since the call
|
|
||||||
* above fails due to possibly buffer related issues. */
|
|
||||||
realpath(tmp, resolved_path);
|
|
||||||
fill_pathname_abbreviate_special(tmp, resolved_path, sizeof(tmp));
|
|
||||||
}
|
|
||||||
strlcpy(path, tmp, size);
|
|
||||||
return;
|
|
||||||
#else
|
|
||||||
if ( mode == PLAYLIST_LOAD)
|
|
||||||
return;
|
|
||||||
|
|
||||||
strlcpy(tmp, path, sizeof(tmp));
|
if (mode == PLAYLIST_LOAD)
|
||||||
path_resolve_realpath(tmp, sizeof(tmp));
|
{
|
||||||
strlcpy(path, tmp, size);
|
fill_pathname_expand_special(tmp, path, sizeof(tmp));
|
||||||
|
strlcpy(path, tmp, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* iOS needs to call realpath here since the call
|
||||||
|
* above fails due to possibly buffer related issues. */
|
||||||
|
realpath(path, tmp);
|
||||||
|
fill_pathname_abbreviate_special(path, tmp, size);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (mode == PLAYLIST_LOAD)
|
||||||
|
return;
|
||||||
|
|
||||||
|
path_resolve_realpath(path, size, true);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,7 +781,7 @@ bool playlist_push(playlist_t *playlist,
|
|||||||
if (!string_is_empty(entry->subsystem_roms->elems[j].data))
|
if (!string_is_empty(entry->subsystem_roms->elems[j].data))
|
||||||
{
|
{
|
||||||
strlcpy(real_rom_path, entry->subsystem_roms->elems[j].data, sizeof(real_rom_path));
|
strlcpy(real_rom_path, entry->subsystem_roms->elems[j].data, sizeof(real_rom_path));
|
||||||
path_resolve_realpath(real_rom_path, sizeof(real_rom_path));
|
path_resolve_realpath(real_rom_path, sizeof(real_rom_path), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!playlist_path_equal(real_rom_path, roms->elems[j].data))
|
if (!playlist_path_equal(real_rom_path, roms->elems[j].data))
|
||||||
|
@ -7529,7 +7529,7 @@ static bool load_dynamic_core(const char *path, char *buf, size_t size)
|
|||||||
/* 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);
|
path_resolve_realpath(buf, size, true);
|
||||||
if ((lib_handle = dylib_load(path)))
|
if ((lib_handle = dylib_load(path)))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -1349,7 +1349,7 @@ static void task_push_to_history_list(
|
|||||||
/* Path can be relative here.
|
/* Path can be relative here.
|
||||||
* Ensure we're pushing absolute path. */
|
* Ensure we're pushing absolute path. */
|
||||||
if (!launched_from_menu && !string_is_empty(tmp))
|
if (!launched_from_menu && !string_is_empty(tmp))
|
||||||
path_resolve_realpath(tmp, tmp_size);
|
path_resolve_realpath(tmp, tmp_size, true);
|
||||||
|
|
||||||
#ifdef HAVE_MENU
|
#ifdef HAVE_MENU
|
||||||
/* Push quick menu onto menu stack */
|
/* Push quick menu onto menu stack */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user