svn commit: r236400 - stable/9/lib/libc/stdlib
Konstantin Belousov
kib at FreeBSD.org
Fri Jun 1 14:40:16 UTC 2012
Author: kib
Date: Fri Jun 1 14:40:16 2012
New Revision: 236400
URL: http://svn.freebsd.org/changeset/base/236400
Log:
MFC r235266:
According to SUSv4, realpath(3) must fail if
[ENOENT] A component of file_name does not name an existing file or
file_name points to an empty string.
[ENOTDIR] A component of the path prefix is not a directory, or the
file_name argument contains at least one non- <slash> character
and ends with one or more trailing <slash> characters and the last
pathname component names an existing file that is neither a
directory nor a symbolic link to a directory.
Add checks for the listed conditions, and set errno accordingly.
Update the realpath(3) manpage to mention SUS behaviour. Remove the
requirement to include sys/param.h before stdlib.h.
PR: 128933
Modified:
stable/9/lib/libc/stdlib/realpath.3
stable/9/lib/libc/stdlib/realpath.c
Directory Properties:
stable/9/lib/libc/ (props changed)
Modified: stable/9/lib/libc/stdlib/realpath.3
==============================================================================
--- stable/9/lib/libc/stdlib/realpath.3 Fri Jun 1 14:29:59 2012 (r236399)
+++ stable/9/lib/libc/stdlib/realpath.3 Fri Jun 1 14:40:16 2012 (r236400)
@@ -31,7 +31,7 @@
.\" @(#)realpath.3 8.2 (Berkeley) 2/16/94
.\" $FreeBSD$
.\"
-.Dd April 19, 2010
+.Dd May 11, 2012
.Dt REALPATH 3
.Os
.Sh NAME
@@ -40,7 +40,6 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-.In sys/param.h
.In stdlib.h
.Ft "char *"
.Fn realpath "const char *pathname" "char *resolved_path"
@@ -72,11 +71,12 @@ The
function will resolve both absolute and relative paths
and return the absolute pathname corresponding to
.Fa pathname .
-All but the last component of
+All components of
.Fa pathname
must exist when
.Fn realpath
-is called.
+is called, and all but the last component must name either directories or
+symlinks pointing to the directories.
.Sh "RETURN VALUES"
The
.Fn realpath
Modified: stable/9/lib/libc/stdlib/realpath.c
==============================================================================
--- stable/9/lib/libc/stdlib/realpath.c Fri Jun 1 14:29:59 2012 (r236399)
+++ stable/9/lib/libc/stdlib/realpath.c Fri Jun 1 14:40:16 2012 (r236400)
@@ -132,8 +132,29 @@ realpath(const char * __restrict path, c
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, c
}
/*
- * 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, c
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);
More information about the svn-src-stable-9
mailing list