diff options
Diffstat (limited to 'src/lib/libc/stdlib')
| -rw-r--r-- | src/lib/libc/stdlib/realpath.3 | 21 | ||||
| -rw-r--r-- | src/lib/libc/stdlib/realpath.c | 48 |
2 files changed, 52 insertions, 17 deletions
diff --git a/src/lib/libc/stdlib/realpath.3 b/src/lib/libc/stdlib/realpath.3 index c64fc3d637..fba88a6f6c 100644 --- a/src/lib/libc/stdlib/realpath.3 +++ b/src/lib/libc/stdlib/realpath.3 | |||
| @@ -28,9 +28,9 @@ | |||
| 28 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 28 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 29 | .\" SUCH DAMAGE. | 29 | .\" SUCH DAMAGE. |
| 30 | .\" | 30 | .\" |
| 31 | .\" $OpenBSD: realpath.3,v 1.15 2007/07/06 15:42:04 millert Exp $ | 31 | .\" $OpenBSD: realpath.3,v 1.16 2011/07/24 21:03:00 miod Exp $ |
| 32 | .\" | 32 | .\" |
| 33 | .Dd $Mdocdate: July 6 2007 $ | 33 | .Dd $Mdocdate: July 24 2011 $ |
| 34 | .Dt REALPATH 3 | 34 | .Dt REALPATH 3 |
| 35 | .Os | 35 | .Os |
| 36 | .Sh NAME | 36 | .Sh NAME |
| @@ -40,7 +40,7 @@ | |||
| 40 | .Fd #include <limits.h> | 40 | .Fd #include <limits.h> |
| 41 | .Fd #include <stdlib.h> | 41 | .Fd #include <stdlib.h> |
| 42 | .Ft "char *" | 42 | .Ft "char *" |
| 43 | .Fn realpath "const char *pathname" "char resolved[PATH_MAX]" | 43 | .Fn realpath "const char *pathname" "char *resolved" |
| 44 | .Sh DESCRIPTION | 44 | .Sh DESCRIPTION |
| 45 | The | 45 | The |
| 46 | .Fn realpath | 46 | .Fn realpath |
| @@ -60,7 +60,8 @@ argument | |||
| 60 | .Em must | 60 | .Em must |
| 61 | refer to a buffer capable of storing at least | 61 | refer to a buffer capable of storing at least |
| 62 | .Dv PATH_MAX | 62 | .Dv PATH_MAX |
| 63 | characters. | 63 | characters, or be |
| 64 | .Dv NULL . | ||
| 64 | .Pp | 65 | .Pp |
| 65 | The | 66 | The |
| 66 | .Fn realpath | 67 | .Fn realpath |
| @@ -78,6 +79,13 @@ The | |||
| 78 | function returns | 79 | function returns |
| 79 | .Fa resolved | 80 | .Fa resolved |
| 80 | on success. | 81 | on success. |
| 82 | If | ||
| 83 | .Fa resolved | ||
| 84 | is | ||
| 85 | .Dv NULL | ||
| 86 | and no error occured, then | ||
| 87 | .Fa realpath | ||
| 88 | returns a NUL-terminated string in a newly allocated buffer. | ||
| 81 | If an error occurs, | 89 | If an error occurs, |
| 82 | .Fn realpath | 90 | .Fn realpath |
| 83 | returns | 91 | returns |
| @@ -98,6 +106,11 @@ and | |||
| 98 | .Sh SEE ALSO | 106 | .Sh SEE ALSO |
| 99 | .Xr readlink 1 , | 107 | .Xr readlink 1 , |
| 100 | .Xr getcwd 3 | 108 | .Xr getcwd 3 |
| 109 | .Sh STANDARDS | ||
| 110 | The | ||
| 111 | .Fn realpath | ||
| 112 | function conforms to | ||
| 113 | .St -p1003.1-2008 . | ||
| 101 | .Sh HISTORY | 114 | .Sh HISTORY |
| 102 | The | 115 | The |
| 103 | .Fn realpath | 116 | .Fn realpath |
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 | */ |
| 45 | char * | 45 | char * |
| 46 | realpath(const char *path, char resolved[PATH_MAX]) | 46 | realpath(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 | |||
| 208 | err: | ||
| 209 | if (mem_allocated) | ||
| 210 | free(resolved); | ||
| 211 | return (NULL); | ||
| 190 | } | 212 | } |
