svn commit: r207599 - in stable/8: include lib/libc/stdlib
Konstantin Belousov
kib at FreeBSD.org
Tue May 4 05:34:18 UTC 2010
Author: kib
Date: Tue May 4 05:34:18 2010
New Revision: 207599
URL: http://svn.freebsd.org/changeset/base/207599
Log:
MFC r206893:
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().
MFC r206898:
Free() is not allowed to modify errno, remove safety brackets around it.
Add small optimization, do not copy a string to the buffer that is
to be freed immediately after.
MFC r206997:
Move realpath(3) prototype to a POSIX section.
MFC r206998:
Add standards section, improve wording, taking into account the handling
of NULL and changed type in declaration.
Modified:
stable/8/include/stdlib.h
stable/8/lib/libc/stdlib/realpath.3
stable/8/lib/libc/stdlib/realpath.c
Directory Properties:
stable/8/include/ (props changed)
stable/8/lib/libc/ (props changed)
stable/8/lib/libc/stdtime/ (props changed)
Modified: stable/8/include/stdlib.h
==============================================================================
--- stable/8/include/stdlib.h Tue May 4 05:25:48 2010 (r207598)
+++ stable/8/include/stdlib.h Tue May 4 05:34:18 2010 (r207599)
@@ -159,6 +159,7 @@ void _Exit(int) __dead2;
#if __POSIX_VISIBLE /* >= ??? */
int posix_memalign(void **, size_t, size_t); /* (ADV) */
int rand_r(unsigned *); /* (TSF) */
+char *realpath(const char * __restrict, char * __restrict);
int setenv(const char *, const char *, int);
int unsetenv(const char *);
#endif
@@ -205,7 +206,6 @@ int posix_openpt(int);
char *ptsname(int);
int putenv(char *);
long random(void);
-char *realpath(const char *, char resolved_path[]);
unsigned short
*seed48(unsigned short[3]);
#ifndef _SETKEY_DECLARED
Modified: stable/8/lib/libc/stdlib/realpath.3
==============================================================================
--- stable/8/lib/libc/stdlib/realpath.3 Tue May 4 05:25:48 2010 (r207598)
+++ stable/8/lib/libc/stdlib/realpath.3 Tue May 4 05:34:18 2010 (r207599)
@@ -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,13 +83,22 @@ 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
.Dv NULL ,
-and
+and if
.Fa resolved_path
-contains the pathname which caused the problem.
+is not
+.Dv NULL ,
+the array that it points to contains the pathname which caused the problem.
.Sh ERRORS
The function
.Fn realpath
@@ -113,6 +123,11 @@ when given a relative
.Fa pathname .
.Sh "SEE ALSO"
.Xr getcwd 3
+.Sh STANDARDS
+The
+.Fn realpath
+function conforms to
+.St -p1003.1-2001 .
.Sh HISTORY
The
.Fn realpath
Modified: stable/8/lib/libc/stdlib/realpath.c
==============================================================================
--- stable/8/lib/libc/stdlib/realpath.c Tue May 4 05:25:48 2010 (r207598)
+++ stable/8/lib/libc/stdlib/realpath.c Tue May 4 05:34:18 2010 (r207599)
@@ -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] = '/';
@@ -70,13 +84,18 @@ realpath(const char *path, char resolved
left_len = strlcpy(left, path + 1, sizeof(left));
} else {
if (getcwd(resolved, PATH_MAX) == NULL) {
- strlcpy(resolved, ".", PATH_MAX);
+ if (m)
+ free(resolved);
+ else
+ strlcpy(resolved, ".", PATH_MAX);
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 +111,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 +123,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 +156,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 +166,23 @@ realpath(const char *path, char resolved
errno = serrno;
return (resolved);
}
+ if (m)
+ free(resolved);
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)
+ free(resolved);
return (NULL);
+ }
symlink[slen] = '\0';
if (symlink[0] == '/') {
resolved[1] = 0;
@@ -171,6 +203,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 +213,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);
}
More information about the svn-src-stable
mailing list