Use newlib's realpath

This commit is contained in:
GaryOderNichts 2020-12-25 16:25:18 +01:00
parent 162e16fd8e
commit 7b16db25f9

View File

@ -22,135 +22,66 @@ char *_getcwd (char *__buf, size_t __size)
return __buf; return __buf;
} }
/* Return the canonical absolute name of a given file. /* realpath.c - Return the canonicalized absolute pathname
Copyright (C) 1996-2018 Free Software Foundation, Inc. * Written 2000 by Werner Almesberger
This file is part of the GNU C Library. *
* Canonical name: never ends with a slash
The GNU C Library is free software; you can redistribute it and/or */
modify it under the terms of the GNU Lesser General Public static int resolve_path(char *path,char *result,char *pos)
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
char *realpath(const char *name, char *resolved)
{ {
char *rpath, *dest = NULL; if (*path == '/') {
const char *start, *end, *rpath_limit; *result = '/';
long int path_max; pos = result+1;
path++;
}
*pos = 0;
if (!*path) return 0;
while (1) {
char *slash;
struct stat st;
/* As per Single Unix Specification V2 we must return an error if slash = *path ? strchr(path,'/') : NULL;
either parameter is a null pointer. We extend this to allow if (slash) *slash = 0;
the RESOLVED parameter to be NULL in case the we are expected to if (!path[0] || (path[0] == '.' &&
allocate the room for the return value. */ (!path[1] || (path[1] == '.' && !path[2])))) {
if (!name) pos--;
return NULL; if (pos != result && path[0] && path[1])
while (*--pos != '/');
}
else {
strcpy(pos,path);
pos = strchr(result,0);
}
if (slash) {
*pos++ = '/';
path = slash+1;
}
*pos = 0;
if (!slash) break;
}
return 0;
}
/* As per Single Unix Specification V2 we must return an error if
the name argument points to an empty string. */
if (name[0] == '\0')
return NULL;
path_max = PATH_MAX; char *realpath(const char *__restrict path,char *__restrict resolved_path)
{
char cwd[PATH_MAX];
char *path_copy;
int res;
if (!resolved) if (!*path) {
{ errno = ENOENT; /* SUSv2 */
rpath = malloc(path_max);
if (!rpath)
return NULL; return NULL;
} }
else if (!_getcwd(cwd,sizeof(cwd))) return NULL;
rpath = resolved; strcpy(resolved_path,"/");
rpath_limit = rpath + path_max; if (resolve_path(cwd,resolved_path,resolved_path)) return NULL;
strcat(resolved_path,"/");
if (name[0] != '/') path_copy = strdup(path);
{ if (!path_copy) return NULL;
if (!_getcwd(rpath, path_max)) res = resolve_path(path_copy,resolved_path,strchr(resolved_path,0));
{ free(path_copy);
rpath[0] = '\0'; if (res) return NULL;
goto error; return resolved_path;
}
dest = memchr(rpath, '\0', path_max);
}
else
{
rpath[0] = '/';
dest = rpath + 1;
}
for (start = end = name; *start; start = end)
{
/* Skip sequence of multiple path-separators. */
while (*start == '/')
++start;
/* Find end of path component. */
for (end = start; *end && *end != '/'; ++end)
/* Nothing. */;
if (end - start == 0)
break;
else if (end - start == 1 && start[0] == '.')
/* nothing */;
else if (end - start == 2 && start[0] == '.' && start[1] == '.')
{
/* Back up to previous component, ignore if at root already. */
if (dest > rpath + 1)
while ((--dest)[-1] != '/')
;
}
else
{
size_t new_size;
if (dest[-1] != '/')
*dest++ = '/';
if (dest + (end - start) >= rpath_limit)
{
ptrdiff_t dest_offset = dest - rpath;
char *new_rpath;
if (resolved)
{
if (dest > rpath + 1)
dest--;
*dest = '\0';
goto error;
}
new_size = rpath_limit - rpath;
if (end - start + 1 > path_max)
new_size += end - start + 1;
else
new_size += path_max;
new_rpath = (char *)realloc(rpath, new_size);
if (!new_rpath)
goto error;
rpath = new_rpath;
rpath_limit = rpath + new_size;
dest = rpath + dest_offset;
}
dest = memcpy(dest, start, end - start);
*dest = '\0';
}
}
if (dest > rpath + 1 && dest[-1] == '/')
--dest;
*dest = '\0';
return rpath;
error:
if (!resolved)
free(rpath);
return NULL;
} }
#endif #endif