kern/121897: commit references a PR

dfilter service dfilter at FreeBSD.ORG
Tue Apr 20 10:20:07 UTC 2010


The following reply was made to PR kern/121897; it has been noted by GNATS.

From: dfilter at FreeBSD.ORG (dfilter service)
To: bug-followup at FreeBSD.org
Cc:  
Subject: Re: kern/121897: commit references a PR
Date: Tue, 20 Apr 2010 10:16:58 +0000 (UTC)

 Author: kib
 Date: Tue Apr 20 10:16:44 2010
 New Revision: 206893
 URL: http://svn.freebsd.org/changeset/base/206893
 
 Log:
   Slightly modernize realpath(3).
   
   SUSv4 requires that implementation returns EINVAL if supplied path is NULL,
   and ENOENT if path is empty string [1].
   Bring prototype in conformance with SUSv4, adding restrict keywords.
   Allow the resolved path buffer pointer be NULL, in which case realpath(3)
   allocates storage with malloc().
   
   PR:	kern/121897 [1]
   MFC after:	2 weeks
 
 Modified:
   head/include/stdlib.h
   head/lib/libc/stdlib/realpath.3
   head/lib/libc/stdlib/realpath.c
 
 Modified: head/include/stdlib.h
 ==============================================================================
 --- head/include/stdlib.h	Tue Apr 20 08:51:21 2010	(r206892)
 +++ head/include/stdlib.h	Tue Apr 20 10:16:44 2010	(r206893)
 @@ -201,7 +201,7 @@ int	 posix_openpt(int);
  char	*ptsname(int);
  int	 putenv(char *);
  long	 random(void);
 -char	*realpath(const char *, char resolved_path[]);
 +char	*realpath(const char * __restrict, char * __restrict);
  unsigned short
  	*seed48(unsigned short[3]);
  #ifndef _SETKEY_DECLARED
 
 Modified: head/lib/libc/stdlib/realpath.3
 ==============================================================================
 --- head/lib/libc/stdlib/realpath.3	Tue Apr 20 08:51:21 2010	(r206892)
 +++ head/lib/libc/stdlib/realpath.3	Tue Apr 20 10:16:44 2010	(r206893)
 @@ -31,7 +31,7 @@
  .\"     @(#)realpath.3	8.2 (Berkeley) 2/16/94
  .\" $FreeBSD$
  .\"
 -.Dd February 16, 1994
 +.Dd April 19, 2010
  .Dt REALPATH 3
  .Os
  .Sh NAME
 @@ -43,7 +43,7 @@
  .In sys/param.h
  .In stdlib.h
  .Ft "char *"
 -.Fn realpath "const char *pathname" "char resolved_path[PATH_MAX]"
 +.Fn realpath "const char *pathname" "char *resolved_path"
  .Sh DESCRIPTION
  The
  .Fn realpath
 @@ -64,7 +64,8 @@ argument
  .Em must
  refer to a buffer capable of storing at least
  .Dv PATH_MAX
 -characters.
 +characters, or be
 +.Dv NULL .
  .Pp
  The
  .Fn realpath
 @@ -82,6 +83,13 @@ The
  function returns
  .Fa resolved_path
  on success.
 +If the function was supplied
 +.Dv NULL
 +as
 +.Fa resolved_path ,
 +and operation did not cause errors, the returned value is
 +a null-terminated string in a buffer allocated by a call to
 +.Fn malloc 3 .
  If an error occurs,
  .Fn realpath
  returns
 @@ -89,6 +97,11 @@ returns
  and
  .Fa resolved_path
  contains the pathname which caused the problem.
 +If
 +.Fa resolved_path
 +was
 +.Dv NULL ,
 +then information of the failed pathname component is lost.
  .Sh ERRORS
  The function
  .Fn realpath
 
 Modified: head/lib/libc/stdlib/realpath.c
 ==============================================================================
 --- head/lib/libc/stdlib/realpath.c	Tue Apr 20 08:51:21 2010	(r206892)
 +++ head/lib/libc/stdlib/realpath.c	Tue Apr 20 10:16:44 2010	(r206893)
 @@ -43,23 +43,37 @@ __FBSDID("$FreeBSD$");
  #include "un-namespace.h"
  
  /*
 - * char *realpath(const char *path, char resolved[PATH_MAX]);
 - *
   * Find the real name of path, by removing all ".", ".." and symlink
   * components.  Returns (resolved) on success, or (NULL) on failure,
   * in which case the path which caused trouble is left in (resolved).
   */
  char *
 -realpath(const char *path, char resolved[PATH_MAX])
 +realpath(const char * __restrict path, char * __restrict resolved)
  {
  	struct stat sb;
  	char *p, *q, *s;
  	size_t left_len, resolved_len;
  	unsigned symlinks;
 -	int serrno, slen;
 +	int serrno, slen, m;
  	char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
  
 +	if (path == NULL) {
 +		errno = EINVAL;
 +		return (NULL);
 +	}
 +	if (path[0] == '\0') {
 +		errno = ENOENT;
 +		return (NULL);
 +	}
  	serrno = errno;
 +	if (resolved == NULL) {
 +		resolved = malloc(PATH_MAX);
 +		if (resolved == NULL)
 +			return (NULL);
 +		m = 1;
 +	} else
 +		m = 0;
 +
  	symlinks = 0;
  	if (path[0] == '/') {
  		resolved[0] = '/';
 @@ -71,12 +85,19 @@ realpath(const char *path, char resolved
  	} else {
  		if (getcwd(resolved, PATH_MAX) == NULL) {
  			strlcpy(resolved, ".", PATH_MAX);
 +			if (m) {
 +				serrno = errno;
 +				free(resolved);
 +				errno = serrno;
 +			}
  			return (NULL);
  		}
  		resolved_len = strlen(resolved);
  		left_len = strlcpy(left, path, sizeof(left));
  	}
  	if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
 +		if (m)
 +			free(resolved);
  		errno = ENAMETOOLONG;
  		return (NULL);
  	}
 @@ -92,6 +113,8 @@ realpath(const char *path, char resolved
  		p = strchr(left, '/');
  		s = p ? p : left + left_len;
  		if (s - left >= sizeof(next_token)) {
 +			if (m)
 +				free(resolved);
  			errno = ENAMETOOLONG;
  			return (NULL);
  		}
 @@ -102,6 +125,8 @@ realpath(const char *path, char resolved
  			memmove(left, s + 1, left_len + 1);
  		if (resolved[resolved_len - 1] != '/') {
  			if (resolved_len + 1 >= PATH_MAX) {
 +				if (m)
 +					free(resolved);
  				errno = ENAMETOOLONG;
  				return (NULL);
  			}
 @@ -133,6 +158,8 @@ realpath(const char *path, char resolved
  		 */
  		resolved_len = strlcat(resolved, next_token, PATH_MAX);
  		if (resolved_len >= PATH_MAX) {
 +			if (m)
 +				free(resolved);
  			errno = ENAMETOOLONG;
  			return (NULL);
  		}
 @@ -141,16 +168,29 @@ realpath(const char *path, char resolved
  				errno = serrno;
  				return (resolved);
  			}
 +			if (m) {
 +				serrno = errno;
 +				free(resolved);
 +				errno = serrno;
 +			}
  			return (NULL);
  		}
  		if (S_ISLNK(sb.st_mode)) {
  			if (symlinks++ > MAXSYMLINKS) {
 +				if (m)
 +					free(resolved);
  				errno = ELOOP;
  				return (NULL);
  			}
  			slen = readlink(resolved, symlink, sizeof(symlink) - 1);
 -			if (slen < 0)
 +			if (slen < 0) {
 +				if (m) {
 +					serrno = errno;
 +					free(resolved);
 +					errno = serrno;
 +				}
  				return (NULL);
 +			}
  			symlink[slen] = '\0';
  			if (symlink[0] == '/') {
  				resolved[1] = 0;
 @@ -171,6 +211,8 @@ realpath(const char *path, char resolved
  			if (p != NULL) {
  				if (symlink[slen - 1] != '/') {
  					if (slen + 1 >= sizeof(symlink)) {
 +						if (m)
 +							free(resolved);
  						errno = ENAMETOOLONG;
  						return (NULL);
  					}
 @@ -179,6 +221,8 @@ realpath(const char *path, char resolved
  				}
  				left_len = strlcat(symlink, left, sizeof(left));
  				if (left_len >= sizeof(left)) {
 +					if (m)
 +						free(resolved);
  					errno = ENAMETOOLONG;
  					return (NULL);
  				}
 _______________________________________________
 svn-src-all at freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
 


More information about the freebsd-bugs mailing list