diff options
author | Damien Miller <djm@mindrot.org> | 2015-10-14 08:25:09 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2015-10-14 08:25:09 +1100 |
commit | 7365fe5b4859de2305e40ea132da3823830fa710 (patch) | |
tree | 1b01d108b2c88875126b6fb81246ec00dc8c265e /openbsd-compat | |
parent | e679c09cd1951f963793aa3d9748d1c3fdcf808f (diff) |
upstream commit
revision 1.14
date: 2011/07/24 21:03:00; author: miod; state: Exp; lines: +35 -13;
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 'openbsd-compat')
-rw-r--r-- | openbsd-compat/realpath.c | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c index ba4cea938..6646330ca 100644 --- a/openbsd-compat/realpath.c +++ b/openbsd-compat/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 | * |
@@ -51,16 +51,30 @@ | |||
51 | * in which case the path which caused trouble is left in (resolved). | 51 | * in which case the path which caused trouble is left in (resolved). |
52 | */ | 52 | */ |
53 | char * | 53 | char * |
54 | realpath(const char *path, char resolved[PATH_MAX]) | 54 | realpath(const char *path, char *resolved) |
55 | { | 55 | { |
56 | struct stat sb; | 56 | struct stat sb; |
57 | char *p, *q, *s; | 57 | char *p, *q, *s; |
58 | size_t left_len, resolved_len; | 58 | size_t left_len, resolved_len; |
59 | unsigned symlinks; | 59 | unsigned symlinks; |
60 | int serrno, slen; | 60 | int serrno, slen, mem_allocated; |
61 | char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; | 61 | char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; |
62 | 62 | ||
63 | if (path[0] == '\0') { | ||
64 | errno = ENOENT; | ||
65 | return (NULL); | ||
66 | } | ||
67 | |||
63 | serrno = errno; | 68 | serrno = errno; |
69 | |||
70 | if (resolved == NULL) { | ||
71 | resolved = malloc(PATH_MAX); | ||
72 | if (resolved == NULL) | ||
73 | return (NULL); | ||
74 | mem_allocated = 1; | ||
75 | } else | ||
76 | mem_allocated = 0; | ||
77 | |||
64 | symlinks = 0; | 78 | symlinks = 0; |
65 | if (path[0] == '/') { | 79 | if (path[0] == '/') { |
66 | resolved[0] = '/'; | 80 | resolved[0] = '/'; |
@@ -71,7 +85,10 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
71 | left_len = strlcpy(left, path + 1, sizeof(left)); | 85 | left_len = strlcpy(left, path + 1, sizeof(left)); |
72 | } else { | 86 | } else { |
73 | if (getcwd(resolved, PATH_MAX) == NULL) { | 87 | if (getcwd(resolved, PATH_MAX) == NULL) { |
74 | strlcpy(resolved, ".", PATH_MAX); | 88 | if (mem_allocated) |
89 | free(resolved); | ||
90 | else | ||
91 | strlcpy(resolved, ".", PATH_MAX); | ||
75 | return (NULL); | 92 | return (NULL); |
76 | } | 93 | } |
77 | resolved_len = strlen(resolved); | 94 | resolved_len = strlen(resolved); |
@@ -79,7 +96,7 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
79 | } | 96 | } |
80 | if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { | 97 | if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { |
81 | errno = ENAMETOOLONG; | 98 | errno = ENAMETOOLONG; |
82 | return (NULL); | 99 | goto err; |
83 | } | 100 | } |
84 | 101 | ||
85 | /* | 102 | /* |
@@ -94,7 +111,7 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
94 | s = p ? p : left + left_len; | 111 | s = p ? p : left + left_len; |
95 | if (s - left >= (ptrdiff_t)sizeof(next_token)) { | 112 | if (s - left >= (ptrdiff_t)sizeof(next_token)) { |
96 | errno = ENAMETOOLONG; | 113 | errno = ENAMETOOLONG; |
97 | return (NULL); | 114 | goto err; |
98 | } | 115 | } |
99 | memcpy(next_token, left, s - left); | 116 | memcpy(next_token, left, s - left); |
100 | next_token[s - left] = '\0'; | 117 | next_token[s - left] = '\0'; |
@@ -104,7 +121,7 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
104 | if (resolved[resolved_len - 1] != '/') { | 121 | if (resolved[resolved_len - 1] != '/') { |
105 | if (resolved_len + 1 >= PATH_MAX) { | 122 | if (resolved_len + 1 >= PATH_MAX) { |
106 | errno = ENAMETOOLONG; | 123 | errno = ENAMETOOLONG; |
107 | return (NULL); | 124 | goto err; |
108 | } | 125 | } |
109 | resolved[resolved_len++] = '/'; | 126 | resolved[resolved_len++] = '/'; |
110 | resolved[resolved_len] = '\0'; | 127 | resolved[resolved_len] = '\0'; |
@@ -135,23 +152,23 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
135 | resolved_len = strlcat(resolved, next_token, PATH_MAX); | 152 | resolved_len = strlcat(resolved, next_token, PATH_MAX); |
136 | if (resolved_len >= PATH_MAX) { | 153 | if (resolved_len >= PATH_MAX) { |
137 | errno = ENAMETOOLONG; | 154 | errno = ENAMETOOLONG; |
138 | return (NULL); | 155 | goto err; |
139 | } | 156 | } |
140 | if (lstat(resolved, &sb) != 0) { | 157 | if (lstat(resolved, &sb) != 0) { |
141 | if (errno == ENOENT && p == NULL) { | 158 | if (errno == ENOENT && p == NULL) { |
142 | errno = serrno; | 159 | errno = serrno; |
143 | return (resolved); | 160 | return (resolved); |
144 | } | 161 | } |
145 | return (NULL); | 162 | goto err; |
146 | } | 163 | } |
147 | if (S_ISLNK(sb.st_mode)) { | 164 | if (S_ISLNK(sb.st_mode)) { |
148 | if (symlinks++ > MAXSYMLINKS) { | 165 | if (symlinks++ > MAXSYMLINKS) { |
149 | errno = ELOOP; | 166 | errno = ELOOP; |
150 | return (NULL); | 167 | goto err; |
151 | } | 168 | } |
152 | slen = readlink(resolved, symlink, sizeof(symlink) - 1); | 169 | slen = readlink(resolved, symlink, sizeof(symlink) - 1); |
153 | if (slen < 0) | 170 | if (slen < 0) |
154 | return (NULL); | 171 | goto err; |
155 | symlink[slen] = '\0'; | 172 | symlink[slen] = '\0'; |
156 | if (symlink[0] == '/') { | 173 | if (symlink[0] == '/') { |
157 | resolved[1] = 0; | 174 | resolved[1] = 0; |
@@ -174,7 +191,7 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
174 | if (slen + 1 >= | 191 | if (slen + 1 >= |
175 | (ptrdiff_t)sizeof(symlink)) { | 192 | (ptrdiff_t)sizeof(symlink)) { |
176 | errno = ENAMETOOLONG; | 193 | errno = ENAMETOOLONG; |
177 | return (NULL); | 194 | goto err; |
178 | } | 195 | } |
179 | symlink[slen] = '/'; | 196 | symlink[slen] = '/'; |
180 | symlink[slen + 1] = 0; | 197 | symlink[slen + 1] = 0; |
@@ -182,7 +199,7 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
182 | left_len = strlcat(symlink, left, sizeof(left)); | 199 | left_len = strlcat(symlink, left, sizeof(left)); |
183 | if (left_len >= sizeof(left)) { | 200 | if (left_len >= sizeof(left)) { |
184 | errno = ENAMETOOLONG; | 201 | errno = ENAMETOOLONG; |
185 | return (NULL); | 202 | goto err; |
186 | } | 203 | } |
187 | } | 204 | } |
188 | left_len = strlcpy(left, symlink, sizeof(left)); | 205 | left_len = strlcpy(left, symlink, sizeof(left)); |
@@ -196,5 +213,10 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
196 | if (resolved_len > 1 && resolved[resolved_len - 1] == '/') | 213 | if (resolved_len > 1 && resolved[resolved_len - 1] == '/') |
197 | resolved[resolved_len - 1] = '\0'; | 214 | resolved[resolved_len - 1] = '\0'; |
198 | return (resolved); | 215 | return (resolved); |
216 | |||
217 | err: | ||
218 | if (mem_allocated) | ||
219 | free(resolved); | ||
220 | return (NULL); | ||
199 | } | 221 | } |
200 | #endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ | 222 | #endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ |