replace realpath() by custom code which does not resolve symlinks

This commit is contained in:
LazyBumHorse 2019-07-19 22:59:29 +02:00
parent 25a7f9f535
commit 7006764c12
2 changed files with 105 additions and 21 deletions

View file

@ -756,35 +756,113 @@ bool path_is_absolute(const char *path)
/**
* path_resolve_realpath:
* @buf : buffer for path
* @buf : input and output buffer for path
* @size : size of buffer
*
* Turns relative paths into absolute paths and
* resolves use of "." and ".." in absolute paths.
* If relative, rebases on current working dir.
* Resolves use of ".", "..", multiple slashes etc in absolute paths.
*
* Relative paths are rebased on the current working dir.
*
* Returns: @buf if successful, NULL otherwise.
* Note: Not implemented on consoles
* 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)
{
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
char tmp[PATH_MAX_LENGTH];
tmp[0] = '\0';
strlcpy(tmp, buf, sizeof(tmp));
#ifdef _WIN32
strlcpy(tmp, buf, sizeof(tmp));
if (!_fullpath(buf, tmp, size))
{
strlcpy(buf, tmp, size);
return NULL;
}
return buf;
#else
size_t t = 0; /* length of output */
char *p;
const char *next;
const char *buf_end = buf + strlen(buf);
/* NOTE: realpath() expects at least PATH_MAX_LENGTH bytes in buf.
* 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);
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
return NULL;
}
/**

View file

@ -147,14 +147,20 @@ void path_parent_dir(char *path);
/**
* path_resolve_realpath:
* @buf : buffer for path
* @buf : input and output buffer for path
* @size : size of buffer
*
* Turns relative paths into absolute paths and
* resolves use of "." and ".." in absolute paths.
* If relative, rebases on current working dir.
* Resolves use of ".", "..", multiple slashes etc in absolute paths.
*
* Relative paths are rebased on the current working dir.
*
* Returns: @buf if successful, NULL otherwise.
* Note: Not implemented on consoles
* 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);
/**
* path_relative_to: