summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/stdlib/realpath.321
-rw-r--r--src/lib/libc/stdlib/realpath.c48
2 files changed, 52 insertions, 17 deletions
diff --git a/src/lib/libc/stdlib/realpath.3 b/src/lib/libc/stdlib/realpath.3
index c64fc3d637..fba88a6f6c 100644
--- a/src/lib/libc/stdlib/realpath.3
+++ b/src/lib/libc/stdlib/realpath.3
@@ -28,9 +28,9 @@
28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29.\" SUCH DAMAGE. 29.\" SUCH DAMAGE.
30.\" 30.\"
31.\" $OpenBSD: realpath.3,v 1.15 2007/07/06 15:42:04 millert Exp $ 31.\" $OpenBSD: realpath.3,v 1.16 2011/07/24 21:03:00 miod Exp $
32.\" 32.\"
33.Dd $Mdocdate: July 6 2007 $ 33.Dd $Mdocdate: July 24 2011 $
34.Dt REALPATH 3 34.Dt REALPATH 3
35.Os 35.Os
36.Sh NAME 36.Sh NAME
@@ -40,7 +40,7 @@
40.Fd #include <limits.h> 40.Fd #include <limits.h>
41.Fd #include <stdlib.h> 41.Fd #include <stdlib.h>
42.Ft "char *" 42.Ft "char *"
43.Fn realpath "const char *pathname" "char resolved[PATH_MAX]" 43.Fn realpath "const char *pathname" "char *resolved"
44.Sh DESCRIPTION 44.Sh DESCRIPTION
45The 45The
46.Fn realpath 46.Fn realpath
@@ -60,7 +60,8 @@ argument
60.Em must 60.Em must
61refer to a buffer capable of storing at least 61refer to a buffer capable of storing at least
62.Dv PATH_MAX 62.Dv PATH_MAX
63characters. 63characters, or be
64.Dv NULL .
64.Pp 65.Pp
65The 66The
66.Fn realpath 67.Fn realpath
@@ -78,6 +79,13 @@ The
78function returns 79function returns
79.Fa resolved 80.Fa resolved
80on success. 81on success.
82If
83.Fa resolved
84is
85.Dv NULL
86and no error occured, then
87.Fa realpath
88returns a NUL-terminated string in a newly allocated buffer.
81If an error occurs, 89If an error occurs,
82.Fn realpath 90.Fn realpath
83returns 91returns
@@ -98,6 +106,11 @@ and
98.Sh SEE ALSO 106.Sh SEE ALSO
99.Xr readlink 1 , 107.Xr readlink 1 ,
100.Xr getcwd 3 108.Xr getcwd 3
109.Sh STANDARDS
110The
111.Fn realpath
112function conforms to
113.St -p1003.1-2008 .
101.Sh HISTORY 114.Sh HISTORY
102The 115The
103.Fn realpath 116.Fn realpath
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
index 4cb847b313..21af4cf005 100644
--- a/src/lib/libc/stdlib/realpath.c
+++ b/src/lib/libc/stdlib/realpath.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: realpath.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ 1/* $OpenBSD: realpath.c,v 1.14 2011/07/24 21:03:00 miod Exp $ */
2/* 2/*
3 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru> 3 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
4 * 4 *
@@ -43,16 +43,30 @@
43 * in which case the path which caused trouble is left in (resolved). 43 * in which case the path which caused trouble is left in (resolved).
44 */ 44 */
45char * 45char *
46realpath(const char *path, char resolved[PATH_MAX]) 46realpath(const char *path, char *resolved)
47{ 47{
48 struct stat sb; 48 struct stat sb;
49 char *p, *q, *s; 49 char *p, *q, *s;
50 size_t left_len, resolved_len; 50 size_t left_len, resolved_len;
51 unsigned symlinks; 51 unsigned symlinks;
52 int serrno, slen; 52 int serrno, slen, mem_allocated;
53 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; 53 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
54 54
55 if (path[0] == '\0') {
56 errno = ENOENT;
57 return (NULL);
58 }
59
55 serrno = errno; 60 serrno = errno;
61
62 if (resolved == NULL) {
63 resolved = malloc(PATH_MAX);
64 if (resolved == NULL)
65 return (NULL);
66 mem_allocated = 1;
67 } else
68 mem_allocated = 0;
69
56 symlinks = 0; 70 symlinks = 0;
57 if (path[0] == '/') { 71 if (path[0] == '/') {
58 resolved[0] = '/'; 72 resolved[0] = '/';
@@ -63,7 +77,10 @@ realpath(const char *path, char resolved[PATH_MAX])
63 left_len = strlcpy(left, path + 1, sizeof(left)); 77 left_len = strlcpy(left, path + 1, sizeof(left));
64 } else { 78 } else {
65 if (getcwd(resolved, PATH_MAX) == NULL) { 79 if (getcwd(resolved, PATH_MAX) == NULL) {
66 strlcpy(resolved, ".", PATH_MAX); 80 if (mem_allocated)
81 free(resolved);
82 else
83 strlcpy(resolved, ".", PATH_MAX);
67 return (NULL); 84 return (NULL);
68 } 85 }
69 resolved_len = strlen(resolved); 86 resolved_len = strlen(resolved);
@@ -71,7 +88,7 @@ realpath(const char *path, char resolved[PATH_MAX])
71 } 88 }
72 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { 89 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
73 errno = ENAMETOOLONG; 90 errno = ENAMETOOLONG;
74 return (NULL); 91 goto err;
75 } 92 }
76 93
77 /* 94 /*
@@ -86,7 +103,7 @@ realpath(const char *path, char resolved[PATH_MAX])
86 s = p ? p : left + left_len; 103 s = p ? p : left + left_len;
87 if (s - left >= sizeof(next_token)) { 104 if (s - left >= sizeof(next_token)) {
88 errno = ENAMETOOLONG; 105 errno = ENAMETOOLONG;
89 return (NULL); 106 goto err;
90 } 107 }
91 memcpy(next_token, left, s - left); 108 memcpy(next_token, left, s - left);
92 next_token[s - left] = '\0'; 109 next_token[s - left] = '\0';
@@ -96,7 +113,7 @@ realpath(const char *path, char resolved[PATH_MAX])
96 if (resolved[resolved_len - 1] != '/') { 113 if (resolved[resolved_len - 1] != '/') {
97 if (resolved_len + 1 >= PATH_MAX) { 114 if (resolved_len + 1 >= PATH_MAX) {
98 errno = ENAMETOOLONG; 115 errno = ENAMETOOLONG;
99 return (NULL); 116 goto err;
100 } 117 }
101 resolved[resolved_len++] = '/'; 118 resolved[resolved_len++] = '/';
102 resolved[resolved_len] = '\0'; 119 resolved[resolved_len] = '\0';
@@ -127,23 +144,23 @@ realpath(const char *path, char resolved[PATH_MAX])
127 resolved_len = strlcat(resolved, next_token, PATH_MAX); 144 resolved_len = strlcat(resolved, next_token, PATH_MAX);
128 if (resolved_len >= PATH_MAX) { 145 if (resolved_len >= PATH_MAX) {
129 errno = ENAMETOOLONG; 146 errno = ENAMETOOLONG;
130 return (NULL); 147 goto err;
131 } 148 }
132 if (lstat(resolved, &sb) != 0) { 149 if (lstat(resolved, &sb) != 0) {
133 if (errno == ENOENT && p == NULL) { 150 if (errno == ENOENT && p == NULL) {
134 errno = serrno; 151 errno = serrno;
135 return (resolved); 152 return (resolved);
136 } 153 }
137 return (NULL); 154 goto err;
138 } 155 }
139 if (S_ISLNK(sb.st_mode)) { 156 if (S_ISLNK(sb.st_mode)) {
140 if (symlinks++ > MAXSYMLINKS) { 157 if (symlinks++ > MAXSYMLINKS) {
141 errno = ELOOP; 158 errno = ELOOP;
142 return (NULL); 159 goto err;
143 } 160 }
144 slen = readlink(resolved, symlink, sizeof(symlink) - 1); 161 slen = readlink(resolved, symlink, sizeof(symlink) - 1);
145 if (slen < 0) 162 if (slen < 0)
146 return (NULL); 163 goto err;
147 symlink[slen] = '\0'; 164 symlink[slen] = '\0';
148 if (symlink[0] == '/') { 165 if (symlink[0] == '/') {
149 resolved[1] = 0; 166 resolved[1] = 0;
@@ -165,7 +182,7 @@ realpath(const char *path, char resolved[PATH_MAX])
165 if (symlink[slen - 1] != '/') { 182 if (symlink[slen - 1] != '/') {
166 if (slen + 1 >= sizeof(symlink)) { 183 if (slen + 1 >= sizeof(symlink)) {
167 errno = ENAMETOOLONG; 184 errno = ENAMETOOLONG;
168 return (NULL); 185 goto err;
169 } 186 }
170 symlink[slen] = '/'; 187 symlink[slen] = '/';
171 symlink[slen + 1] = 0; 188 symlink[slen + 1] = 0;
@@ -173,7 +190,7 @@ realpath(const char *path, char resolved[PATH_MAX])
173 left_len = strlcat(symlink, left, sizeof(left)); 190 left_len = strlcat(symlink, left, sizeof(left));
174 if (left_len >= sizeof(left)) { 191 if (left_len >= sizeof(left)) {
175 errno = ENAMETOOLONG; 192 errno = ENAMETOOLONG;
176 return (NULL); 193 goto err;
177 } 194 }
178 } 195 }
179 left_len = strlcpy(left, symlink, sizeof(left)); 196 left_len = strlcpy(left, symlink, sizeof(left));
@@ -187,4 +204,9 @@ realpath(const char *path, char resolved[PATH_MAX])
187 if (resolved_len > 1 && resolved[resolved_len - 1] == '/') 204 if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
188 resolved[resolved_len - 1] = '\0'; 205 resolved[resolved_len - 1] = '\0';
189 return (resolved); 206 return (resolved);
207
208err:
209 if (mem_allocated)
210 free(resolved);
211 return (NULL);
190} 212}