summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2016-08-28 04:09:00 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2016-08-28 04:09:00 +0000
commitd2384f62b868ac27ea234d65577933862ca99188 (patch)
tree22fab5b8e9cbff000d9a368e3f402ca4505365ee /lib
parentc60a4319a91c5edb15e1427a612eb600216dd5ec (diff)
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 'lib')
-rw-r--r--lib/libc/stdlib/realpath.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/lib/libc/stdlib/realpath.c b/lib/libc/stdlib/realpath.c
index 27f1a29061d..c691252ccf5 100644
--- a/lib/libc/stdlib/realpath.c
+++ b/lib/libc/stdlib/realpath.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: realpath.c,v 1.20 2015/10/13 20:55:37 millert Exp $ */
+/* $OpenBSD: realpath.c,v 1.21 2016/08/28 04:08:59 guenther Exp $ */
/*
* Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
*
@@ -27,8 +27,6 @@
* SUCH DAMAGE.
*/
-#include <sys/stat.h>
-
#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -47,7 +45,6 @@
char *
realpath(const char *path, char *resolved)
{
- struct stat sb;
char *p, *q, *s;
size_t left_len, resolved_len;
unsigned symlinks;
@@ -148,21 +145,27 @@ realpath(const char *path, char *resolved)
errno = ENAMETOOLONG;
goto err;
}
- if (lstat(resolved, &sb) != 0) {
- if (errno == ENOENT && p == NULL) {
- errno = serrno;
- return (resolved);
+ slen = readlink(resolved, symlink, sizeof(symlink) - 1);
+ if (slen < 0) {
+ switch (errno) {
+ case EINVAL:
+ /* not a symlink, continue to next component */
+ continue;
+ case ENOENT:
+ if (p == NULL) {
+ errno = serrno;
+ return (resolved);
+ }
+ /* FALLTHROUGH */
+ default:
+ goto err;
}
- goto err;
- }
- if (S_ISLNK(sb.st_mode)) {
+ } else {
if (symlinks++ > SYMLOOP_MAX) {
errno = ELOOP;
goto err;
}
- slen = readlink(resolved, symlink, sizeof(symlink) - 1);
- if (slen < 0)
- goto err;
+
symlink[slen] = '\0';
if (symlink[0] == '/') {
resolved[1] = 0;