diff options
author | miod <> | 2011-07-24 21:03:00 +0000 |
---|---|---|
committer | miod <> | 2011-07-24 21:03:00 +0000 |
commit | b4176721a77a9f8167bb2d29bd3992009a4cb8a3 (patch) | |
tree | c214319dae05ec7c52132c482c567999cf933e10 /src | |
parent | ff139186f8d47a589ecba6abd896915137364e16 (diff) | |
download | openbsd-b4176721a77a9f8167bb2d29bd3992009a4cb8a3.tar.gz openbsd-b4176721a77a9f8167bb2d29bd3992009a4cb8a3.tar.bz2 openbsd-b4176721a77a9f8167bb2d29bd3992009a4cb8a3.zip |
Recent Single Unix will malloc memory if the second argument of realpath()
is NULL, and third-party software is starting to rely upon this.
Adapted from FreeBSD via Jona Joachim (jaj ; hcl-club , .lu), with minor
tweaks from nicm@ and yours truly.
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libc/stdlib/realpath.3 | 21 | ||||
-rw-r--r-- | src/lib/libc/stdlib/realpath.c | 48 |
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 |
45 | The | 45 | The |
46 | .Fn realpath | 46 | .Fn realpath |
@@ -60,7 +60,8 @@ argument | |||
60 | .Em must | 60 | .Em must |
61 | refer to a buffer capable of storing at least | 61 | refer to a buffer capable of storing at least |
62 | .Dv PATH_MAX | 62 | .Dv PATH_MAX |
63 | characters. | 63 | characters, or be |
64 | .Dv NULL . | ||
64 | .Pp | 65 | .Pp |
65 | The | 66 | The |
66 | .Fn realpath | 67 | .Fn realpath |
@@ -78,6 +79,13 @@ The | |||
78 | function returns | 79 | function returns |
79 | .Fa resolved | 80 | .Fa resolved |
80 | on success. | 81 | on success. |
82 | If | ||
83 | .Fa resolved | ||
84 | is | ||
85 | .Dv NULL | ||
86 | and no error occured, then | ||
87 | .Fa realpath | ||
88 | returns a NUL-terminated string in a newly allocated buffer. | ||
81 | If an error occurs, | 89 | If an error occurs, |
82 | .Fn realpath | 90 | .Fn realpath |
83 | returns | 91 | returns |
@@ -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 | ||
110 | The | ||
111 | .Fn realpath | ||
112 | function conforms to | ||
113 | .St -p1003.1-2008 . | ||
101 | .Sh HISTORY | 114 | .Sh HISTORY |
102 | The | 115 | The |
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 | */ |
45 | char * | 45 | char * |
46 | realpath(const char *path, char resolved[PATH_MAX]) | 46 | realpath(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 | |||
208 | err: | ||
209 | if (mem_allocated) | ||
210 | free(resolved); | ||
211 | return (NULL); | ||
190 | } | 212 | } |