summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib/realpath.c
diff options
context:
space:
mode:
authormiod <>2011-07-24 21:03:00 +0000
committermiod <>2011-07-24 21:03:00 +0000
commitb4176721a77a9f8167bb2d29bd3992009a4cb8a3 (patch)
treec214319dae05ec7c52132c482c567999cf933e10 /src/lib/libc/stdlib/realpath.c
parentff139186f8d47a589ecba6abd896915137364e16 (diff)
downloadopenbsd-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.c48
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 */
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}