summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib/realpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/stdlib/realpath.c')
-rw-r--r--src/lib/libc/stdlib/realpath.c43
1 files changed, 23 insertions, 20 deletions
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
index e349b7e068..1525d0372f 100644
--- a/src/lib/libc/stdlib/realpath.c
+++ b/src/lib/libc/stdlib/realpath.c
@@ -13,11 +13,7 @@
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 16 * 3. Neither the name of the University nor the names of its contributors
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software 17 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission. 18 * without specific prior written permission.
23 * 19 *
@@ -35,8 +31,7 @@
35 */ 31 */
36 32
37#if defined(LIBC_SCCS) && !defined(lint) 33#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)realpath.c 8.1 (Berkeley) 2/16/94";*/ 34static char *rcsid = "$OpenBSD: realpath.c,v 1.10 2003/08/01 21:04:59 millert Exp $";
39static char *rcsid = "$Id: realpath.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 35#endif /* LIBC_SCCS and not lint */
41 36
42#include <sys/param.h> 37#include <sys/param.h>
@@ -61,15 +56,20 @@ realpath(path, resolved)
61 char *resolved; 56 char *resolved;
62{ 57{
63 struct stat sb; 58 struct stat sb;
64 int fd, n, rootd, serrno; 59 int fd, n, needslash, serrno;
65 char *p, *q, wbuf[MAXPATHLEN]; 60 char *p, *q, wbuf[MAXPATHLEN];
61 int symlinks = 0;
66 62
67 /* Save the starting point. */ 63 /* Save the starting point. */
68 if ((fd = open(".", O_RDONLY)) < 0) { 64 if ((fd = open(".", O_RDONLY)) < 0) {
69 (void)strcpy(resolved, "."); 65 (void)strlcpy(resolved, ".", MAXPATHLEN);
70 return (NULL); 66 return (NULL);
71 } 67 }
72 68
69 /* Convert "." -> "" to optimize away a needless lstat() and chdir() */
70 if (path[0] == '.' && path[1] == '\0')
71 path = "";
72
73 /* 73 /*
74 * Find the dirname and basename from the path to be resolved. 74 * Find the dirname and basename from the path to be resolved.
75 * Change directory to the dirname component. 75 * Change directory to the dirname component.
@@ -78,8 +78,7 @@ realpath(path, resolved)
78 * if it is a directory, then change to that directory. 78 * if it is a directory, then change to that directory.
79 * get the current directory name and append the basename. 79 * get the current directory name and append the basename.
80 */ 80 */
81 (void)strncpy(resolved, path, MAXPATHLEN - 1); 81 strlcpy(resolved, path, MAXPATHLEN);
82 resolved[MAXPATHLEN - 1] = '\0';
83loop: 82loop:
84 q = strrchr(resolved, '/'); 83 q = strrchr(resolved, '/');
85 if (q != NULL) { 84 if (q != NULL) {
@@ -99,9 +98,13 @@ loop:
99 p = resolved; 98 p = resolved;
100 99
101 /* Deal with the last component. */ 100 /* Deal with the last component. */
102 if (lstat(p, &sb) == 0) { 101 if (*p != '\0' && lstat(p, &sb) == 0) {
103 if (S_ISLNK(sb.st_mode)) { 102 if (S_ISLNK(sb.st_mode)) {
104 n = readlink(p, resolved, MAXPATHLEN); 103 if (++symlinks > MAXSYMLINKS) {
104 errno = ELOOP;
105 goto err1;
106 }
107 n = readlink(p, resolved, MAXPATHLEN-1);
105 if (n < 0) 108 if (n < 0)
106 goto err1; 109 goto err1;
107 resolved[n] = '\0'; 110 resolved[n] = '\0';
@@ -118,7 +121,7 @@ loop:
118 * Save the last component name and get the full pathname of 121 * Save the last component name and get the full pathname of
119 * the current directory. 122 * the current directory.
120 */ 123 */
121 (void)strcpy(wbuf, p); 124 (void)strlcpy(wbuf, p, sizeof wbuf);
122 if (getcwd(resolved, MAXPATHLEN) == 0) 125 if (getcwd(resolved, MAXPATHLEN) == 0)
123 goto err1; 126 goto err1;
124 127
@@ -127,18 +130,18 @@ loop:
127 * happens if the last component is empty, or the dirname is root. 130 * happens if the last component is empty, or the dirname is root.
128 */ 131 */
129 if (resolved[0] == '/' && resolved[1] == '\0') 132 if (resolved[0] == '/' && resolved[1] == '\0')
130 rootd = 1; 133 needslash = 0;
131 else 134 else
132 rootd = 0; 135 needslash = 1;
133 136
134 if (*wbuf) { 137 if (*wbuf) {
135 if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) { 138 if (strlen(resolved) + strlen(wbuf) + needslash >= MAXPATHLEN) {
136 errno = ENAMETOOLONG; 139 errno = ENAMETOOLONG;
137 goto err1; 140 goto err1;
138 } 141 }
139 if (rootd == 0) 142 if (needslash)
140 (void)strcat(resolved, "/"); 143 strlcat(resolved, "/", MAXPATHLEN);
141 (void)strcat(resolved, wbuf); 144 strlcat(resolved, wbuf, MAXPATHLEN);
142 } 145 }
143 146
144 /* Go back to where we came from. */ 147 /* Go back to where we came from. */