diff options
author | guenther <> | 2016-08-28 04:08:59 +0000 |
---|---|---|
committer | guenther <> | 2016-08-28 04:08:59 +0000 |
commit | 1250d78eeed22bd3e5b5389e26f447d9d5f5969b (patch) | |
tree | 97bebb52af146194335c40817dca433f00de8f64 /src | |
parent | 9304d31ee77186647e4a011b65ec5bc5f7aaa6b2 (diff) | |
download | openbsd-1250d78eeed22bd3e5b5389e26f447d9d5f5969b.tar.gz openbsd-1250d78eeed22bd3e5b5389e26f447d9d5f5969b.tar.bz2 openbsd-1250d78eeed22bd3e5b5389e26f447d9d5f5969b.zip |
Don't call lstat() before readlink() just to see if it's a symlink,
as readlink() will tell you that more cheaply.
ok millert@
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libc/stdlib/realpath.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c index 27f1a29061..c691252ccf 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.20 2015/10/13 20:55:37 millert Exp $ */ | 1 | /* $OpenBSD: realpath.c,v 1.21 2016/08/28 04:08:59 guenther 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 | * |
@@ -27,8 +27,6 @@ | |||
27 | * SUCH DAMAGE. | 27 | * SUCH DAMAGE. |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <sys/stat.h> | ||
31 | |||
32 | #include <errno.h> | 30 | #include <errno.h> |
33 | #include <stdlib.h> | 31 | #include <stdlib.h> |
34 | #include <string.h> | 32 | #include <string.h> |
@@ -47,7 +45,6 @@ | |||
47 | char * | 45 | char * |
48 | realpath(const char *path, char *resolved) | 46 | realpath(const char *path, char *resolved) |
49 | { | 47 | { |
50 | struct stat sb; | ||
51 | char *p, *q, *s; | 48 | char *p, *q, *s; |
52 | size_t left_len, resolved_len; | 49 | size_t left_len, resolved_len; |
53 | unsigned symlinks; | 50 | unsigned symlinks; |
@@ -148,21 +145,27 @@ realpath(const char *path, char *resolved) | |||
148 | errno = ENAMETOOLONG; | 145 | errno = ENAMETOOLONG; |
149 | goto err; | 146 | goto err; |
150 | } | 147 | } |
151 | if (lstat(resolved, &sb) != 0) { | 148 | slen = readlink(resolved, symlink, sizeof(symlink) - 1); |
152 | if (errno == ENOENT && p == NULL) { | 149 | if (slen < 0) { |
153 | errno = serrno; | 150 | switch (errno) { |
154 | return (resolved); | 151 | case EINVAL: |
152 | /* not a symlink, continue to next component */ | ||
153 | continue; | ||
154 | case ENOENT: | ||
155 | if (p == NULL) { | ||
156 | errno = serrno; | ||
157 | return (resolved); | ||
158 | } | ||
159 | /* FALLTHROUGH */ | ||
160 | default: | ||
161 | goto err; | ||
155 | } | 162 | } |
156 | goto err; | 163 | } else { |
157 | } | ||
158 | if (S_ISLNK(sb.st_mode)) { | ||
159 | if (symlinks++ > SYMLOOP_MAX) { | 164 | if (symlinks++ > SYMLOOP_MAX) { |
160 | errno = ELOOP; | 165 | errno = ELOOP; |
161 | goto err; | 166 | goto err; |
162 | } | 167 | } |
163 | slen = readlink(resolved, symlink, sizeof(symlink) - 1); | 168 | |
164 | if (slen < 0) | ||
165 | goto err; | ||
166 | symlink[slen] = '\0'; | 169 | symlink[slen] = '\0'; |
167 | if (symlink[0] == '/') { | 170 | if (symlink[0] == '/') { |
168 | resolved[1] = 0; | 171 | resolved[1] = 0; |