diff options
| author | Carmelo Amoroso <carmelo.amoroso@st.com> | 2008-07-09 16:47:01 +0000 |
|---|---|---|
| committer | Carmelo Amoroso <carmelo.amoroso@st.com> | 2008-07-09 16:47:01 +0000 |
| commit | 62a21af8006ab04282fdc354c5b4dc765f56d058 (patch) | |
| tree | 568761d58289238aa14cced3f0010809d4d28c00 /libc/stdlib/realpath.c | |
| parent | ef250238dc1572caf859c2b64652f9cdfb0d9e42 (diff) | |
| download | uClibc-alpine-62a21af8006ab04282fdc354c5b4dc765f56d058.tar.bz2 uClibc-alpine-62a21af8006ab04282fdc354c5b4dc765f56d058.tar.xz | |
BIG BIG commit: all left files merged from trunk [rev 22714]. Currenntly NPTL sh4 port build and work fine. All committed to allow Khem Ray working on a working branch to integrate the ARM nptl port. MIPS nptl port not tested but should still building and working fine. There are some other part non yet merged with trunk (misc/internals and some headers file that need some more work). Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
Diffstat (limited to 'libc/stdlib/realpath.c')
| -rw-r--r-- | libc/stdlib/realpath.c | 100 |
1 files changed, 53 insertions, 47 deletions
diff --git a/libc/stdlib/realpath.c b/libc/stdlib/realpath.c index b28d6f07e..e9eabdfaa 100644 --- a/libc/stdlib/realpath.c +++ b/libc/stdlib/realpath.c @@ -21,9 +21,9 @@ #include <sys/stat.h> /* for S_IFLNK */ -libc_hidden_proto(strcat) -libc_hidden_proto(strcpy) -libc_hidden_proto(strlen) +/* Experimentally off - libc_hidden_proto(strcat) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ libc_hidden_proto(readlink) libc_hidden_proto(getcwd) @@ -42,20 +42,23 @@ libc_hidden_proto(getcwd) #define MAX_READLINKS 32 #ifdef __STDC__ -char *realpath(const char *path, char resolved_path[]) +char *realpath(const char *path, char got_path[]) #else -char *realpath(path, resolved_path) +char *realpath(path, got_path) const char *path; -char resolved_path[]; +char got_path[]; #endif { char copy_path[PATH_MAX]; - char link_path[PATH_MAX]; - char got_path[PATH_MAX]; - char *new_path = got_path; + /* use user supplied buffer directly - reduces stack usage */ + /* char got_path[PATH_MAX]; */ char *max_path; + char *new_path; + size_t path_len; int readlinks = 0; - int n; +#ifdef S_IFLNK + int link_len; +#endif if (path == NULL) { __set_errno(EINVAL); @@ -66,17 +69,20 @@ char resolved_path[]; return NULL; } /* Make a copy of the source path since we may need to modify it. */ - if (strlen(path) >= PATH_MAX - 2) { + path_len = strlen(path); + if (path_len >= PATH_MAX - 2) { __set_errno(ENAMETOOLONG); return NULL; } - strcpy(copy_path, path); - path = copy_path; - max_path = copy_path + PATH_MAX - 2; - /* If it's a relative pathname use getcwd for starters. */ + /* 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; + max_path = got_path + PATH_MAX - 2; /* points to last non-NUL char */ + new_path = got_path; if (*path != '/') { - /* Ohoo... */ - getcwd(new_path, PATH_MAX - 1); + /* If it's a relative pathname use getcwd for starters. */ + if (!getcwd(new_path, PATH_MAX - 1)) + return NULL; new_path += strlen(new_path); if (new_path[-1] != '/') *new_path++ = '/'; @@ -111,7 +117,7 @@ char resolved_path[]; } /* Safely copy the next pathname component. */ while (*path != '\0' && *path != '/') { - if (path > max_path) { + if (new_path > max_path) { __set_errno(ENAMETOOLONG); return NULL; } @@ -123,35 +129,36 @@ char resolved_path[]; __set_errno(ELOOP); return NULL; } - /* See if latest pathname component is a symlink. */ + path_len = strlen(path); + /* See if last (so far) pathname component is a symlink. */ *new_path = '\0'; - n = readlink(got_path, link_path, PATH_MAX - 1); - if (n < 0) { - /* EINVAL means the file exists but isn't a symlink. */ - if (errno != EINVAL) { - /* Make sure it's null terminated. */ - *new_path = '\0'; - strcpy(resolved_path, got_path); - return NULL; - } - } else { - /* Note: readlink doesn't add the null byte. */ - link_path[n] = '\0'; - if (*link_path == '/') - /* Start over for an absolute symlink. */ - new_path = got_path; - else - /* Otherwise back up over this component. */ - while (*(--new_path) != '/'); - /* Safe sex check. */ - if (strlen(path) + n >= PATH_MAX - 2) { - __set_errno(ENAMETOOLONG); - return NULL; + { + int sv_errno = errno; + link_len = readlink(got_path, copy_path, PATH_MAX - 1); + if (link_len < 0) { + /* EINVAL means the file exists but isn't a symlink. */ + if (errno != EINVAL) { + return NULL; + } + } else { + /* Safe sex check. */ + if (path_len + link_len >= PATH_MAX - 2) { + __set_errno(ENAMETOOLONG); + return NULL; + } + /* Note: readlink doesn't add the null byte. */ + /* copy_path[link_len] = '\0'; - we don't need it too */ + if (*copy_path == '/') + /* Start over for an absolute symlink. */ + new_path = got_path; + else + /* Otherwise back up over this component. */ + while (*(--new_path) != '/'); + /* Prepend symlink contents to path. */ + memmove(copy_path + (PATH_MAX-1) - link_len - path_len, copy_path, link_len); + path = copy_path + (PATH_MAX-1) - link_len - path_len; } - /* Insert symlink contents into path. */ - strcat(link_path, path); - strcpy(copy_path, link_path); - path = copy_path; + __set_errno(sv_errno); } #endif /* S_IFLNK */ *new_path++ = '/'; @@ -161,6 +168,5 @@ char resolved_path[]; new_path--; /* Make sure it's null terminated. */ *new_path = '\0'; - strcpy(resolved_path, got_path); - return resolved_path; + return got_path; } |
