Browse Source

Don't call lstat() before readlink() just to see if it's a symlink,

as readlink() will tell you that more cheaply.
ok millert@
OPENBSD_6_1
guenther 8 years ago
parent
commit
4c8fdca0ed
1 changed files with 17 additions and 14 deletions
  1. +17
    -14
      src/lib/libc/stdlib/realpath.c

+ 17
- 14
src/lib/libc/stdlib/realpath.c View File

@ -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> * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
* *
@ -27,8 +27,6 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -47,7 +45,6 @@
char * char *
realpath(const char *path, char *resolved) realpath(const char *path, char *resolved)
{ {
struct stat sb;
char *p, *q, *s; char *p, *q, *s;
size_t left_len, resolved_len; size_t left_len, resolved_len;
unsigned symlinks; unsigned symlinks;
@ -148,21 +145,27 @@ realpath(const char *path, char *resolved)
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
goto err; 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) { if (symlinks++ > SYMLOOP_MAX) {
errno = ELOOP; errno = ELOOP;
goto err; goto err;
} }
slen = readlink(resolved, symlink, sizeof(symlink) - 1);
if (slen < 0)
goto err;
symlink[slen] = '\0'; symlink[slen] = '\0';
if (symlink[0] == '/') { if (symlink[0] == '/') {
resolved[1] = 0; resolved[1] = 0;


Loading…
Cancel
Save