Date: Fri, 1 Jun 2012 14:40:16 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r236400 - stable/9/lib/libc/stdlib Message-ID: <201206011440.q51EeGII024908@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206011440.q51EeGII024908>