From 4c8fdca0edf7a3da7e0a85aa746f0e6687d53fdd Mon Sep 17 00:00:00 2001 From: guenther <> Date: Sun, 28 Aug 2016 04:08:59 +0000 Subject: [PATCH] Don't call lstat() before readlink() just to see if it's a symlink, as readlink() will tell you that more cheaply. ok millert@ --- src/lib/libc/stdlib/realpath.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c index 27f1a290..c691252c 100644 --- a/src/lib/libc/stdlib/realpath.c +++ b/src/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 * @@ -27,8 +27,6 @@ * SUCH DAMAGE. */ -#include - #include #include #include @@ -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;