From owner-svn-src-stable@FreeBSD.ORG Fri Jun 1 14:40:16 2012 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 98B031065674; Fri, 1 Jun 2012 14:40:16 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 81E578FC1C; Fri, 1 Jun 2012 14:40:16 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q51EeGtD024911; Fri, 1 Jun 2012 14:40:16 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q51EeGII024908; Fri, 1 Jun 2012 14:40:16 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201206011440.q51EeGII024908@svn.freebsd.org> From: Konstantin Belousov Date: Fri, 1 Jun 2012 14:40:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r236400 - stable/9/lib/libc/stdlib X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 01 Jun 2012 14:40:16 -0000 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- character and ends with one or more trailing 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);