summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdlib/realpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/stdlib/realpath.c')
-rw-r--r--lib/libc/stdlib/realpath.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/lib/libc/stdlib/realpath.c b/lib/libc/stdlib/realpath.c
index 2c9562e..ffbf8ec 100644
--- a/lib/libc/stdlib/realpath.c
+++ b/lib/libc/stdlib/realpath.c
@@ -132,8 +132,29 @@ realpath(const char * __restrict path, char * __restrict resolved)
resolved[resolved_len++] = '/';
resolved[resolved_len] = '\0';
}
- if (next_token[0] == '\0')
+ if (next_token[0] == '\0') {
+ /*
+ * Handle consequential slashes. The path
+ * before slash shall point to a directory.
+ *
+ * Only the trailing slashes are not covered
+ * by other checks in the loop, but we verify
+ * the prefix for any (rare) "//" or "/\0"
+ * occurence to not implement lookahead.
+ */
+ if (lstat(resolved, &sb) != 0) {
+ if (m)
+ free(resolved);
+ return (NULL);
+ }
+ if (!S_ISDIR(sb.st_mode)) {
+ if (m)
+ free(resolved);
+ errno = ENOTDIR;
+ return (NULL);
+ }
continue;
+ }
else if (strcmp(next_token, ".") == 0)
continue;
else if (strcmp(next_token, "..") == 0) {
@@ -151,9 +172,7 @@ realpath(const char * __restrict path, char * __restrict resolved)
}
/*
- * Append the next path component and lstat() it. If
- * lstat() fails we still can return successfully if
- * there are no more path components left.
+ * Append the next path component and lstat() it.
*/
resolved_len = strlcat(resolved, next_token, PATH_MAX);
if (resolved_len >= PATH_MAX) {
@@ -163,10 +182,8 @@ realpath(const char * __restrict path, char * __restrict resolved)
return (NULL);
}
if (lstat(resolved, &sb) != 0) {
- if (errno == ENOENT && p == NULL) {
- errno = serrno;
- return (resolved);
- }
+ if (errno != ENOENT || p != NULL)
+ errno = ENOTDIR;
if (m)
free(resolved);
return (NULL);
OpenPOWER on IntegriCloud