From owner-svn-src-head@FreeBSD.ORG Tue Oct 13 20:58:23 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4FD421065679; Tue, 13 Oct 2009 20:58:23 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 3DBF58FC1B; Tue, 13 Oct 2009 20:58:23 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n9DKwMdt016463; Tue, 13 Oct 2009 20:58:22 GMT (envelope-from jilles@svn.freebsd.org) Received: (from jilles@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n9DKwMoW016461; Tue, 13 Oct 2009 20:58:22 GMT (envelope-from jilles@svn.freebsd.org) Message-Id: <200910132058.n9DKwMoW016461@svn.freebsd.org> From: Jilles Tjoelker Date: Tue, 13 Oct 2009 20:58:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r198053 - head/lib/libc/gen X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 13 Oct 2009 20:58:23 -0000 Author: jilles Date: Tue Oct 13 20:58:22 2009 New Revision: 198053 URL: http://svn.freebsd.org/changeset/base/198053 Log: Make getcwd(3) faster, simpler and more compliant using *at syscalls. It is no longer necessary to construct long paths consisting of repeated "../" which may be slow to process and may exceed PATH_MAX. Modified: head/lib/libc/gen/getcwd.c Modified: head/lib/libc/gen/getcwd.c ============================================================================== --- head/lib/libc/gen/getcwd.c Tue Oct 13 20:48:05 2009 (r198052) +++ head/lib/libc/gen/getcwd.c Tue Oct 13 20:58:22 2009 (r198053) @@ -62,13 +62,14 @@ getcwd(pt, size) dev_t dev; ino_t ino; int first; - char *bpt, *bup; + char *bpt; struct stat s; dev_t root_dev; ino_t root_ino; - size_t ptsize, upsize; + size_t ptsize; int save_errno; - char *ept, *eup, *up, c; + char *ept, c; + int fd; /* * If no buffer specified by the user, allocate one as necessary. @@ -106,18 +107,6 @@ getcwd(pt, size) bpt = ept - 1; *bpt = '\0'; - /* - * Allocate 1024 bytes for the string of "../"'s. - * Should always be enough. If it's not, allocate - * as necessary. Special case the first stat, it's ".", not "..". - */ - if ((up = malloc(upsize = 1024)) == NULL) - goto err; - eup = up + upsize; - bup = up; - up[0] = '.'; - up[1] = '\0'; - /* Save root values, so know when to stop. */ if (stat("/", &s)) goto err; @@ -128,7 +117,7 @@ getcwd(pt, size) for (first = 1;; first = 0) { /* Stat the current level. */ - if (lstat(up, &s)) + if (dir != NULL ? _fstat(dirfd(dir), &s) : lstat(".", &s)) goto err; /* Save current node values. */ @@ -144,32 +133,22 @@ getcwd(pt, size) * been that way and stuff would probably break. */ bcopy(bpt, pt, ept - bpt); - free(up); + if (dir) + (void) closedir(dir); return (pt); } - /* - * Build pointer to the parent directory, allocating memory - * as necessary. Max length is 3 for "../", the largest - * possible component name, plus a trailing NUL. - */ - while (bup + 3 + MAXNAMLEN + 1 >= eup) { - if ((up = reallocf(up, upsize *= 2)) == NULL) - goto err; - bup = up; - eup = up + upsize; - } - *bup++ = '.'; - *bup++ = '.'; - *bup = '\0'; - /* Open and stat parent directory. */ - if (!(dir = opendir(up)) || _fstat(dirfd(dir), &s)) + fd = _openat(dir != NULL ? dirfd(dir) : AT_FDCWD, + "..", O_RDONLY); + if (fd == -1) goto err; - - /* Add trailing slash for next directory. */ - *bup++ = '/'; - *bup = '\0'; + if (dir) + (void) closedir(dir); + if (!(dir = fdopendir(fd)) || _fstat(dirfd(dir), &s)) { + _close(fd); + goto err; + } /* * If it's a mount point, have to stat each element because @@ -190,10 +169,10 @@ getcwd(pt, size) goto notfound; if (ISDOT(dp)) continue; - bcopy(dp->d_name, bup, dp->d_namlen + 1); /* Save the first error for later. */ - if (lstat(up, &s)) { + if (fstatat(dirfd(dir), dp->d_name, &s, + AT_SYMLINK_NOFOLLOW)) { if (!save_errno) save_errno = errno; errno = 0; @@ -227,11 +206,6 @@ getcwd(pt, size) *--bpt = '/'; bpt -= dp->d_namlen; bcopy(dp->d_name, bpt, dp->d_namlen); - (void) closedir(dir); - dir = NULL; - - /* Truncate any file name. */ - *bup = '\0'; } notfound: @@ -250,7 +224,6 @@ err: free(pt); if (dir) (void) closedir(dir); - free(up); errno = save_errno; return (NULL);