From 2c3ed060512a2e90ec9f912cf1a5eb1ecd700fb9 Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Sat, 14 Nov 2009 15:57:47 +0100 Subject: realpath: SUSv4 compliant Signed-off-by: Mike Frysinger Signed-off-by: Bernhard Reutner-Fischer --- include/stdlib.h | 4 +--- libc/stdlib/realpath.c | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/include/stdlib.h b/include/stdlib.h index e462c1c93..536f81a1e 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -659,7 +659,6 @@ extern char *canonicalize_file_name (__const char *__name) __THROW __nonnull ((1)) __wur; #endif -#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED /* Return the canonical absolute name of file NAME. If RESOLVED is null, the result is malloc'd; otherwise, if the canonical name is PATH_MAX chars or more, returns null with `errno' set to @@ -667,8 +666,7 @@ extern char *canonicalize_file_name (__const char *__name) returns the name in RESOLVED. */ /* we choose to handle __resolved==NULL as crash :) */ extern char *realpath (__const char *__restrict __name, - char *__restrict __resolved) __THROW __wur __nonnull((2)); -#endif + char *__restrict __resolved) __THROW __wur; /* Shorthand for type of comparison functions. */ diff --git a/libc/stdlib/realpath.c b/libc/stdlib/realpath.c index 1a00c3112..80c25f098 100644 --- a/libc/stdlib/realpath.c +++ b/libc/stdlib/realpath.c @@ -36,19 +36,10 @@ #define MAX_READLINKS 32 -#ifdef __STDC__ char *realpath(const char *path, char got_path[]) -#else -char *realpath(path, got_path) -const char *path; -char got_path[]; -#endif { char copy_path[PATH_MAX]; - /* use user supplied buffer directly - reduces stack usage */ - /* char got_path[PATH_MAX]; */ - char *max_path; - char *new_path; + char *max_path, *new_path, *allocated_path; size_t path_len; int readlinks = 0; #ifdef S_IFLNK @@ -72,12 +63,13 @@ char got_path[]; /* Copy so that path is at the end of copy_path[] */ strcpy(copy_path + (PATH_MAX-1) - path_len, path); path = copy_path + (PATH_MAX-1) - path_len; + allocated_path = got_path ? NULL : (got_path = malloc(PATH_MAX)); max_path = got_path + PATH_MAX - 2; /* points to last non-NUL char */ new_path = got_path; if (*path != '/') { /* If it's a relative pathname use getcwd for starters. */ if (!getcwd(new_path, PATH_MAX - 1)) - return NULL; + goto err; new_path += strlen(new_path); if (new_path[-1] != '/') *new_path++ = '/'; @@ -114,6 +106,8 @@ char got_path[]; while (*path != '\0' && *path != '/') { if (new_path > max_path) { __set_errno(ENAMETOOLONG); + err: + free(allocated_path); return NULL; } *new_path++ = *path++; @@ -122,7 +116,7 @@ char got_path[]; /* Protect against infinite loops. */ if (readlinks++ > MAX_READLINKS) { __set_errno(ELOOP); - return NULL; + goto err; } path_len = strlen(path); /* See if last (so far) pathname component is a symlink. */ @@ -133,13 +127,13 @@ char got_path[]; if (link_len < 0) { /* EINVAL means the file exists but isn't a symlink. */ if (errno != EINVAL) { - return NULL; + goto err; } } else { /* Safe sex check. */ if (path_len + link_len >= PATH_MAX - 2) { __set_errno(ENAMETOOLONG); - return NULL; + goto err; } /* Note: readlink doesn't add the null byte. */ /* copy_path[link_len] = '\0'; - we don't need it too */ -- cgit v1.2.3