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/lib/libc/stdlib/realpath.c | |
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/lib/libc/stdlib/realpath.c')
-rw-r--r-- | src/lib/libc/stdlib/realpath.c | 48 |
1 files changed, 35 insertions, 13 deletions
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 | } |