- (dtucker) [configure.ac openbsd-compat/realpath.c] Sync up with realpath

rev 1.11 from OpenBSD and make it use fchdir if available.  ok djm@
This commit is contained in:
Darren Tucker 2005-02-02 10:43:59 +11:00
parent 9dca099aec
commit ad7646a59a
3 changed files with 61 additions and 24 deletions

View File

@ -1,3 +1,7 @@
20050202
- (dtucker) [configure.ac openbsd-compat/realpath.c] Sync up with realpath
rev 1.11 from OpenBSD and make it use fchdir if available. ok djm@
20050201 20050201
- (dtucker) [log.c] Bug #973: force log_init() to open syslog, since on some - (dtucker) [log.c] Bug #973: force log_init() to open syslog, since on some
platforms syslog will revert to its default values. This may result in platforms syslog will revert to its default values. This may result in
@ -2051,4 +2055,4 @@
- (djm) Trim deprecated options from INSTALL. Mention UsePAM - (djm) Trim deprecated options from INSTALL. Mention UsePAM
- (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
$Id: ChangeLog,v 1.3628 2005/02/01 08:16:45 dtucker Exp $ $Id: ChangeLog,v 1.3629 2005/02/01 23:43:59 dtucker Exp $

View File

@ -1,4 +1,4 @@
# $Id: configure.ac,v 1.235 2005/01/18 01:05:18 dtucker Exp $ # $Id: configure.ac,v 1.236 2005/02/01 23:44:00 dtucker Exp $
# #
# Copyright (c) 1999-2004 Damien Miller # Copyright (c) 1999-2004 Damien Miller
# #
@ -877,9 +877,9 @@ AC_ARG_WITH(libedit,
dnl Checks for library functions. Please keep in alphabetical order dnl Checks for library functions. Please keep in alphabetical order
AC_CHECK_FUNCS(\ AC_CHECK_FUNCS(\
arc4random __b64_ntop b64_ntop __b64_pton b64_pton bcopy \ arc4random __b64_ntop b64_ntop __b64_pton b64_pton bcopy \
bindresvport_sa clock closefrom dirfd fchmod fchown freeaddrinfo \ bindresvport_sa clock closefrom dirfd fchdir fchmod fchown \
futimes getaddrinfo getcwd getgrouplist getnameinfo getopt \ freeaddrinfo futimes getaddrinfo getcwd getgrouplist getnameinfo \
getpeereid _getpty getrlimit getttyent glob inet_aton \ getopt getpeereid _getpty getrlimit getttyent glob inet_aton \
inet_ntoa inet_ntop innetgr login_getcapbool md5_crypt memmove \ inet_ntoa inet_ntop innetgr login_getcapbool md5_crypt memmove \
mkdtemp mmap ngetaddrinfo nsleep ogetaddrinfo openlog_r openpty \ mkdtemp mmap ngetaddrinfo nsleep ogetaddrinfo openlog_r openpty \
pstat prctl readpassphrase realpath recvmsg rresvport_af sendmsg \ pstat prctl readpassphrase realpath recvmsg rresvport_af sendmsg \

View File

@ -37,7 +37,7 @@
#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) #if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH)
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
static char *rcsid = "$OpenBSD: realpath.c,v 1.10 2003/08/01 21:04:59 millert Exp $"; static char *rcsid = "$OpenBSD: realpath.c,v 1.11 2004/11/30 15:12:59 millert Exp $";
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#include <sys/param.h> #include <sys/param.h>
@ -67,17 +67,25 @@ char *
realpath(const char *path, char *resolved) realpath(const char *path, char *resolved)
{ {
struct stat sb; struct stat sb;
int fd, n, needslash, serrno = 0; int fd, n, needslash, serrno;
char *p, *q, wbuf[MAXPATHLEN], start[MAXPATHLEN]; char *p, *q, wbuf[MAXPATHLEN];
int symlinks = 0; int symlinks = 0;
/* Save the starting point. */ /* Save the starting point. */
getcwd(start,MAXPATHLEN); #ifndef HAVE_FCHDIR
if ((fd = open(".", O_RDONLY)) < 0) { char start[MAXPATHLEN];
(void)strlcpy(resolved, ".", MAXPATHLEN); /* this is potentially racy but without fchdir we have no option */
if (getcwd(start, sizeof(start)) == NULL) {
resolved[0] = '.';
resolved[1] = '\0';
return (NULL);
}
#endif
if ((fd = open(".", O_RDONLY)) < 0) {
resolved[0] = '.';
resolved[1] = '\0';
return (NULL); return (NULL);
} }
close(fd);
/* Convert "." -> "" to optimize away a needless lstat() and chdir() */ /* Convert "." -> "" to optimize away a needless lstat() and chdir() */
if (path[0] == '.' && path[1] == '\0') if (path[0] == '.' && path[1] == '\0')
@ -91,7 +99,10 @@ realpath(const char *path, char *resolved)
* if it is a directory, then change to that directory. * if it is a directory, then change to that directory.
* get the current directory name and append the basename. * get the current directory name and append the basename.
*/ */
strlcpy(resolved, path, MAXPATHLEN); if (strlcpy(resolved, path, MAXPATHLEN) >= MAXPATHLEN) {
serrno = ENAMETOOLONG;
goto err2;
}
loop: loop:
q = strrchr(resolved, '/'); q = strrchr(resolved, '/');
if (q != NULL) { if (q != NULL) {
@ -114,11 +125,10 @@ loop:
if (*p != '\0' && lstat(p, &sb) == 0) { if (*p != '\0' && lstat(p, &sb) == 0) {
if (S_ISLNK(sb.st_mode)) { if (S_ISLNK(sb.st_mode)) {
if (++symlinks > MAXSYMLINKS) { if (++symlinks > MAXSYMLINKS) {
serrno = ELOOP; errno = ELOOP;
goto err1; goto err1;
} }
n = readlink(p, resolved, MAXPATHLEN-1); if ((n = readlink(p, resolved, MAXPATHLEN-1)) < 0)
if (n < 0)
goto err1; goto err1;
resolved[n] = '\0'; resolved[n] = '\0';
goto loop; goto loop;
@ -134,8 +144,11 @@ loop:
* Save the last component name and get the full pathname of * Save the last component name and get the full pathname of
* the current directory. * the current directory.
*/ */
(void)strlcpy(wbuf, p, sizeof wbuf); if (strlcpy(wbuf, p, sizeof(wbuf)) >= sizeof(wbuf)) {
if (getcwd(resolved, MAXPATHLEN) == 0) errno = ENAMETOOLONG;
goto err1;
}
if (getcwd(resolved, MAXPATHLEN) == NULL)
goto err1; goto err1;
/* /*
@ -149,23 +162,43 @@ loop:
if (*wbuf) { if (*wbuf) {
if (strlen(resolved) + strlen(wbuf) + needslash >= MAXPATHLEN) { if (strlen(resolved) + strlen(wbuf) + needslash >= MAXPATHLEN) {
serrno = ENAMETOOLONG; errno = ENAMETOOLONG;
goto err1;
}
if (needslash) {
if (strlcat(resolved, "/", MAXPATHLEN) >= MAXPATHLEN) {
errno = ENAMETOOLONG;
goto err1;
}
}
if (strlcat(resolved, wbuf, MAXPATHLEN) >= MAXPATHLEN) {
errno = ENAMETOOLONG;
goto err1; goto err1;
} }
if (needslash)
strlcat(resolved, "/", MAXPATHLEN);
strlcat(resolved, wbuf, MAXPATHLEN);
} }
/* Go back to where we came from. */ /* Go back to where we came from. */
#ifdef HAVE_FCHDIR
if (fchdir(fd) < 0) {
#else
if (chdir(start) < 0) { if (chdir(start) < 0) {
#endif
serrno = errno; serrno = errno;
goto err2; goto err2;
} }
/* It's okay if the close fails, what's an fd more or less? */
(void)close(fd);
return (resolved); return (resolved);
err1: chdir(start); err1: serrno = errno;
err2: errno = serrno; #ifdef HAVE_FCHDIR
(void)fchdir(fd);
#else
chdir(start);
#endif
err2: (void)close(fd);
errno = serrno;
return (NULL); return (NULL);
} }
#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ #endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */