summaryrefslogtreecommitdiff
path: root/openbsd-compat/realpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsd-compat/realpath.c')
-rw-r--r--openbsd-compat/realpath.c61
1 files changed, 45 insertions, 16 deletions
diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c
index ba4cea938..a2f090e55 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.20 2015/10/13 20:55:37 millert 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 *
@@ -42,6 +42,13 @@
42#include <stddef.h> 42#include <stddef.h>
43#include <string.h> 43#include <string.h>
44#include <unistd.h> 44#include <unistd.h>
45#include <limits.h>
46
47#ifndef SYMLOOP_MAX
48# define SYMLOOP_MAX 32
49#endif
50
51/* A slightly modified copy of this file exists in libexec/ld.so */
45 52
46/* 53/*
47 * char *realpath(const char *path, char resolved[PATH_MAX]); 54 * char *realpath(const char *path, char resolved[PATH_MAX]);
@@ -51,16 +58,30 @@
51 * in which case the path which caused trouble is left in (resolved). 58 * in which case the path which caused trouble is left in (resolved).
52 */ 59 */
53char * 60char *
54realpath(const char *path, char resolved[PATH_MAX]) 61realpath(const char *path, char *resolved)
55{ 62{
56 struct stat sb; 63 struct stat sb;
57 char *p, *q, *s; 64 char *p, *q, *s;
58 size_t left_len, resolved_len; 65 size_t left_len, resolved_len;
59 unsigned symlinks; 66 unsigned symlinks;
60 int serrno, slen; 67 int serrno, slen, mem_allocated;
61 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; 68 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
62 69
70 if (path[0] == '\0') {
71 errno = ENOENT;
72 return (NULL);
73 }
74
63 serrno = errno; 75 serrno = errno;
76
77 if (resolved == NULL) {
78 resolved = malloc(PATH_MAX);
79 if (resolved == NULL)
80 return (NULL);
81 mem_allocated = 1;
82 } else
83 mem_allocated = 0;
84
64 symlinks = 0; 85 symlinks = 0;
65 if (path[0] == '/') { 86 if (path[0] == '/') {
66 resolved[0] = '/'; 87 resolved[0] = '/';
@@ -71,7 +92,10 @@ realpath(const char *path, char resolved[PATH_MAX])
71 left_len = strlcpy(left, path + 1, sizeof(left)); 92 left_len = strlcpy(left, path + 1, sizeof(left));
72 } else { 93 } else {
73 if (getcwd(resolved, PATH_MAX) == NULL) { 94 if (getcwd(resolved, PATH_MAX) == NULL) {
74 strlcpy(resolved, ".", PATH_MAX); 95 if (mem_allocated)
96 free(resolved);
97 else
98 strlcpy(resolved, ".", PATH_MAX);
75 return (NULL); 99 return (NULL);
76 } 100 }
77 resolved_len = strlen(resolved); 101 resolved_len = strlen(resolved);
@@ -79,7 +103,7 @@ realpath(const char *path, char resolved[PATH_MAX])
79 } 103 }
80 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { 104 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
81 errno = ENAMETOOLONG; 105 errno = ENAMETOOLONG;
82 return (NULL); 106 goto err;
83 } 107 }
84 108
85 /* 109 /*
@@ -94,7 +118,7 @@ realpath(const char *path, char resolved[PATH_MAX])
94 s = p ? p : left + left_len; 118 s = p ? p : left + left_len;
95 if (s - left >= (ptrdiff_t)sizeof(next_token)) { 119 if (s - left >= (ptrdiff_t)sizeof(next_token)) {
96 errno = ENAMETOOLONG; 120 errno = ENAMETOOLONG;
97 return (NULL); 121 goto err;
98 } 122 }
99 memcpy(next_token, left, s - left); 123 memcpy(next_token, left, s - left);
100 next_token[s - left] = '\0'; 124 next_token[s - left] = '\0';
@@ -104,7 +128,7 @@ realpath(const char *path, char resolved[PATH_MAX])
104 if (resolved[resolved_len - 1] != '/') { 128 if (resolved[resolved_len - 1] != '/') {
105 if (resolved_len + 1 >= PATH_MAX) { 129 if (resolved_len + 1 >= PATH_MAX) {
106 errno = ENAMETOOLONG; 130 errno = ENAMETOOLONG;
107 return (NULL); 131 goto err;
108 } 132 }
109 resolved[resolved_len++] = '/'; 133 resolved[resolved_len++] = '/';
110 resolved[resolved_len] = '\0'; 134 resolved[resolved_len] = '\0';
@@ -135,23 +159,23 @@ realpath(const char *path, char resolved[PATH_MAX])
135 resolved_len = strlcat(resolved, next_token, PATH_MAX); 159 resolved_len = strlcat(resolved, next_token, PATH_MAX);
136 if (resolved_len >= PATH_MAX) { 160 if (resolved_len >= PATH_MAX) {
137 errno = ENAMETOOLONG; 161 errno = ENAMETOOLONG;
138 return (NULL); 162 goto err;
139 } 163 }
140 if (lstat(resolved, &sb) != 0) { 164 if (lstat(resolved, &sb) != 0) {
141 if (errno == ENOENT && p == NULL) { 165 if (errno == ENOENT && p == NULL) {
142 errno = serrno; 166 errno = serrno;
143 return (resolved); 167 return (resolved);
144 } 168 }
145 return (NULL); 169 goto err;
146 } 170 }
147 if (S_ISLNK(sb.st_mode)) { 171 if (S_ISLNK(sb.st_mode)) {
148 if (symlinks++ > MAXSYMLINKS) { 172 if (symlinks++ > SYMLOOP_MAX) {
149 errno = ELOOP; 173 errno = ELOOP;
150 return (NULL); 174 goto err;
151 } 175 }
152 slen = readlink(resolved, symlink, sizeof(symlink) - 1); 176 slen = readlink(resolved, symlink, sizeof(symlink) - 1);
153 if (slen < 0) 177 if (slen < 0)
154 return (NULL); 178 goto err;
155 symlink[slen] = '\0'; 179 symlink[slen] = '\0';
156 if (symlink[0] == '/') { 180 if (symlink[0] == '/') {
157 resolved[1] = 0; 181 resolved[1] = 0;
@@ -174,15 +198,15 @@ realpath(const char *path, char resolved[PATH_MAX])
174 if (slen + 1 >= 198 if (slen + 1 >=
175 (ptrdiff_t)sizeof(symlink)) { 199 (ptrdiff_t)sizeof(symlink)) {
176 errno = ENAMETOOLONG; 200 errno = ENAMETOOLONG;
177 return (NULL); 201 goto err;
178 } 202 }
179 symlink[slen] = '/'; 203 symlink[slen] = '/';
180 symlink[slen + 1] = 0; 204 symlink[slen + 1] = 0;
181 } 205 }
182 left_len = strlcat(symlink, left, sizeof(left)); 206 left_len = strlcat(symlink, left, sizeof(symlink));
183 if (left_len >= sizeof(left)) { 207 if (left_len >= sizeof(symlink)) {
184 errno = ENAMETOOLONG; 208 errno = ENAMETOOLONG;
185 return (NULL); 209 goto err;
186 } 210 }
187 } 211 }
188 left_len = strlcpy(left, symlink, sizeof(left)); 212 left_len = strlcpy(left, symlink, sizeof(left));
@@ -196,5 +220,10 @@ realpath(const char *path, char resolved[PATH_MAX])
196 if (resolved_len > 1 && resolved[resolved_len - 1] == '/') 220 if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
197 resolved[resolved_len - 1] = '\0'; 221 resolved[resolved_len - 1] = '\0';
198 return (resolved); 222 return (resolved);
223
224err:
225 if (mem_allocated)
226 free(resolved);
227 return (NULL);
199} 228}
200#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ 229#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */