diff options
Diffstat (limited to 'src/lib/libc/stdlib/realpath.c')
-rw-r--r-- | src/lib/libc/stdlib/realpath.c | 43 |
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";*/ | 34 | static char *rcsid = "$OpenBSD: realpath.c,v 1.10 2003/08/01 21:04:59 millert Exp $"; |
39 | static 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'; | ||
83 | loop: | 82 | loop: |
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. */ |