summaryrefslogtreecommitdiff
path: root/openbsd-compat
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2005-02-02 10:43:59 +1100
committerDarren Tucker <dtucker@zip.com.au>2005-02-02 10:43:59 +1100
commitad7646a59ab05ed9d6c156ba952725f44c02de7d (patch)
treed3a3d9665222fd63ddf530362fef4324992cb785 /openbsd-compat
parent9dca099aec9ce1a5c67e2c0f737871c1e3126b90 (diff)
- (dtucker) [configure.ac openbsd-compat/realpath.c] Sync up with realpath
rev 1.11 from OpenBSD and make it use fchdir if available. ok djm@
Diffstat (limited to 'openbsd-compat')
-rw-r--r--openbsd-compat/realpath.c69
1 files changed, 51 insertions, 18 deletions
diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c
index 218fbecb2..7f73bd998 100644
--- a/openbsd-compat/realpath.c
+++ b/openbsd-compat/realpath.c
@@ -37,7 +37,7 @@
37#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) 37#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH)
38 38
39#if defined(LIBC_SCCS) && !defined(lint) 39#if defined(LIBC_SCCS) && !defined(lint)
40static char *rcsid = "$OpenBSD: realpath.c,v 1.10 2003/08/01 21:04:59 millert Exp $"; 40static char *rcsid = "$OpenBSD: realpath.c,v 1.11 2004/11/30 15:12:59 millert Exp $";
41#endif /* LIBC_SCCS and not lint */ 41#endif /* LIBC_SCCS and not lint */
42 42
43#include <sys/param.h> 43#include <sys/param.h>
@@ -67,17 +67,25 @@ char *
67realpath(const char *path, char *resolved) 67realpath(const char *path, char *resolved)
68{ 68{
69 struct stat sb; 69 struct stat sb;
70 int fd, n, needslash, serrno = 0; 70 int fd, n, needslash, serrno;
71 char *p, *q, wbuf[MAXPATHLEN], start[MAXPATHLEN]; 71 char *p, *q, wbuf[MAXPATHLEN];
72 int symlinks = 0; 72 int symlinks = 0;
73 73
74 /* Save the starting point. */ 74 /* Save the starting point. */
75 getcwd(start,MAXPATHLEN); 75#ifndef HAVE_FCHDIR
76 char start[MAXPATHLEN];
77 /* this is potentially racy but without fchdir we have no option */
78 if (getcwd(start, sizeof(start)) == NULL) {
79 resolved[0] = '.';
80 resolved[1] = '\0';
81 return (NULL);
82 }
83#endif
76 if ((fd = open(".", O_RDONLY)) < 0) { 84 if ((fd = open(".", O_RDONLY)) < 0) {
77 (void)strlcpy(resolved, ".", MAXPATHLEN); 85 resolved[0] = '.';
86 resolved[1] = '\0';
78 return (NULL); 87 return (NULL);
79 } 88 }
80 close(fd);
81 89
82 /* Convert "." -> "" to optimize away a needless lstat() and chdir() */ 90 /* Convert "." -> "" to optimize away a needless lstat() and chdir() */
83 if (path[0] == '.' && path[1] == '\0') 91 if (path[0] == '.' && path[1] == '\0')
@@ -91,7 +99,10 @@ realpath(const char *path, char *resolved)
91 * if it is a directory, then change to that directory. 99 * if it is a directory, then change to that directory.
92 * get the current directory name and append the basename. 100 * get the current directory name and append the basename.
93 */ 101 */
94 strlcpy(resolved, path, MAXPATHLEN); 102 if (strlcpy(resolved, path, MAXPATHLEN) >= MAXPATHLEN) {
103 serrno = ENAMETOOLONG;
104 goto err2;
105 }
95loop: 106loop:
96 q = strrchr(resolved, '/'); 107 q = strrchr(resolved, '/');
97 if (q != NULL) { 108 if (q != NULL) {
@@ -114,11 +125,10 @@ loop:
114 if (*p != '\0' && lstat(p, &sb) == 0) { 125 if (*p != '\0' && lstat(p, &sb) == 0) {
115 if (S_ISLNK(sb.st_mode)) { 126 if (S_ISLNK(sb.st_mode)) {
116 if (++symlinks > MAXSYMLINKS) { 127 if (++symlinks > MAXSYMLINKS) {
117 serrno = ELOOP; 128 errno = ELOOP;
118 goto err1; 129 goto err1;
119 } 130 }
120 n = readlink(p, resolved, MAXPATHLEN-1); 131 if ((n = readlink(p, resolved, MAXPATHLEN-1)) < 0)
121 if (n < 0)
122 goto err1; 132 goto err1;
123 resolved[n] = '\0'; 133 resolved[n] = '\0';
124 goto loop; 134 goto loop;
@@ -134,8 +144,11 @@ loop:
134 * Save the last component name and get the full pathname of 144 * Save the last component name and get the full pathname of
135 * the current directory. 145 * the current directory.
136 */ 146 */
137 (void)strlcpy(wbuf, p, sizeof wbuf); 147 if (strlcpy(wbuf, p, sizeof(wbuf)) >= sizeof(wbuf)) {
138 if (getcwd(resolved, MAXPATHLEN) == 0) 148 errno = ENAMETOOLONG;
149 goto err1;
150 }
151 if (getcwd(resolved, MAXPATHLEN) == NULL)
139 goto err1; 152 goto err1;
140 153
141 /* 154 /*
@@ -149,23 +162,43 @@ loop:
149 162
150 if (*wbuf) { 163 if (*wbuf) {
151 if (strlen(resolved) + strlen(wbuf) + needslash >= MAXPATHLEN) { 164 if (strlen(resolved) + strlen(wbuf) + needslash >= MAXPATHLEN) {
152 serrno = ENAMETOOLONG; 165 errno = ENAMETOOLONG;
166 goto err1;
167 }
168 if (needslash) {
169 if (strlcat(resolved, "/", MAXPATHLEN) >= MAXPATHLEN) {
170 errno = ENAMETOOLONG;
171 goto err1;
172 }
173 }
174 if (strlcat(resolved, wbuf, MAXPATHLEN) >= MAXPATHLEN) {
175 errno = ENAMETOOLONG;
153 goto err1; 176 goto err1;
154 } 177 }
155 if (needslash)
156 strlcat(resolved, "/", MAXPATHLEN);
157 strlcat(resolved, wbuf, MAXPATHLEN);
158 } 178 }
159 179
160 /* Go back to where we came from. */ 180 /* Go back to where we came from. */
181#ifdef HAVE_FCHDIR
182 if (fchdir(fd) < 0) {
183#else
161 if (chdir(start) < 0) { 184 if (chdir(start) < 0) {
185#endif
162 serrno = errno; 186 serrno = errno;
163 goto err2; 187 goto err2;
164 } 188 }
189
190 /* It's okay if the close fails, what's an fd more or less? */
191 (void)close(fd);
165 return (resolved); 192 return (resolved);
166 193
167err1: chdir(start); 194err1: serrno = errno;
168err2: errno = serrno; 195#ifdef HAVE_FCHDIR
196 (void)fchdir(fd);
197#else
198 chdir(start);
199#endif
200err2: (void)close(fd);
201 errno = serrno;
169 return (NULL); 202 return (NULL);
170} 203}
171#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ 204#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */