diff --git a/ChangeLog b/ChangeLog index 301921de1..eb897ec41 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 - (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 @@ -2051,4 +2055,4 @@ - (djm) Trim deprecated options from INSTALL. Mention UsePAM - (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 $ diff --git a/configure.ac b/configure.ac index d4151feb0..94d6b1e78 100644 --- a/configure.ac +++ b/configure.ac @@ -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 # @@ -877,9 +877,9 @@ AC_ARG_WITH(libedit, dnl Checks for library functions. Please keep in alphabetical order AC_CHECK_FUNCS(\ arc4random __b64_ntop b64_ntop __b64_pton b64_pton bcopy \ - bindresvport_sa clock closefrom dirfd fchmod fchown freeaddrinfo \ - futimes getaddrinfo getcwd getgrouplist getnameinfo getopt \ - getpeereid _getpty getrlimit getttyent glob inet_aton \ + bindresvport_sa clock closefrom dirfd fchdir fchmod fchown \ + freeaddrinfo futimes getaddrinfo getcwd getgrouplist getnameinfo \ + getopt getpeereid _getpty getrlimit getttyent glob inet_aton \ inet_ntoa inet_ntop innetgr login_getcapbool md5_crypt memmove \ mkdtemp mmap ngetaddrinfo nsleep ogetaddrinfo openlog_r openpty \ pstat prctl readpassphrase realpath recvmsg rresvport_af sendmsg \ diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c index 218fbecb2..7f73bd998 100644 --- a/openbsd-compat/realpath.c +++ b/openbsd-compat/realpath.c @@ -37,7 +37,7 @@ #if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) #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 */ #include @@ -67,17 +67,25 @@ char * realpath(const char *path, char *resolved) { struct stat sb; - int fd, n, needslash, serrno = 0; - char *p, *q, wbuf[MAXPATHLEN], start[MAXPATHLEN]; + int fd, n, needslash, serrno; + char *p, *q, wbuf[MAXPATHLEN]; int symlinks = 0; /* Save the starting point. */ - getcwd(start,MAXPATHLEN); - if ((fd = open(".", O_RDONLY)) < 0) { - (void)strlcpy(resolved, ".", MAXPATHLEN); +#ifndef HAVE_FCHDIR + char start[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); } - close(fd); /* Convert "." -> "" to optimize away a needless lstat() and chdir() */ 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. * get the current directory name and append the basename. */ - strlcpy(resolved, path, MAXPATHLEN); + if (strlcpy(resolved, path, MAXPATHLEN) >= MAXPATHLEN) { + serrno = ENAMETOOLONG; + goto err2; + } loop: q = strrchr(resolved, '/'); if (q != NULL) { @@ -114,11 +125,10 @@ loop: if (*p != '\0' && lstat(p, &sb) == 0) { if (S_ISLNK(sb.st_mode)) { if (++symlinks > MAXSYMLINKS) { - serrno = ELOOP; + errno = ELOOP; goto err1; } - n = readlink(p, resolved, MAXPATHLEN-1); - if (n < 0) + if ((n = readlink(p, resolved, MAXPATHLEN-1)) < 0) goto err1; resolved[n] = '\0'; goto loop; @@ -134,8 +144,11 @@ loop: * Save the last component name and get the full pathname of * the current directory. */ - (void)strlcpy(wbuf, p, sizeof wbuf); - if (getcwd(resolved, MAXPATHLEN) == 0) + if (strlcpy(wbuf, p, sizeof(wbuf)) >= sizeof(wbuf)) { + errno = ENAMETOOLONG; + goto err1; + } + if (getcwd(resolved, MAXPATHLEN) == NULL) goto err1; /* @@ -149,23 +162,43 @@ loop: if (*wbuf) { 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; } - if (needslash) - strlcat(resolved, "/", MAXPATHLEN); - strlcat(resolved, wbuf, MAXPATHLEN); } /* Go back to where we came from. */ +#ifdef HAVE_FCHDIR + if (fchdir(fd) < 0) { +#else if (chdir(start) < 0) { +#endif serrno = errno; goto err2; } + + /* It's okay if the close fails, what's an fd more or less? */ + (void)close(fd); return (resolved); -err1: chdir(start); -err2: errno = serrno; +err1: serrno = errno; +#ifdef HAVE_FCHDIR + (void)fchdir(fd); +#else + chdir(start); +#endif +err2: (void)close(fd); + errno = serrno; return (NULL); } #endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */