X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fgetcwd.c;h=23b35de679d1e50f97d0b49cdd8932b4a9b2a3c4;hb=024eeefda59f214eeaac745db9f3e982b9a726c3;hp=292bc19a333a67cd970acd1f5846925aa8f08959;hpb=0632e115747ff96e93330c88f536d7354a7ce507;p=gnulib.git diff --git a/lib/getcwd.c b/lib/getcwd.c index 292bc19a3..23b35de67 100644 --- a/lib/getcwd.c +++ b/lib/getcwd.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,92,93,94,95,96,97,98,99,2004,2005,2006 Free Software +/* Copyright (C) 1991,92,93,94,95,96,97,98,99,2004,2005,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -18,7 +18,8 @@ #if !_LIBC # include -# include "getcwd.h" +# include +# include "dirfd.h" #endif #include @@ -49,8 +50,6 @@ # ifndef mempcpy # define mempcpy __mempcpy # endif -#else -# include "mempcpy.h" #endif #include @@ -97,6 +96,11 @@ # define __opendir opendir # define __readdir readdir #endif + +/* The results of opendir() in this file are not used with dirfd and fchdir, + therefore save some unnecessary recursion in fchdir.c. */ +#undef opendir +#undef closedir /* Get the name of the current working directory, and put it in SIZE bytes of BUF. Returns NULL if the directory couldn't be determined or @@ -137,13 +141,18 @@ __getcwd (char *buf, size_t size) size_t allocated = size; size_t used; -#if HAVE_PARTLY_WORKING_GETCWD && !defined AT_FDCWD +#if HAVE_PARTLY_WORKING_GETCWD /* The system getcwd works, except it sometimes fails when it shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT. If AT_FDCWD is not defined, the algorithm below is O(N**2) and this is much slower than the system getcwd (at least on GNU/Linux). So trust the system getcwd's results unless they look - suspicious. */ + suspicious. + + Use the system getcwd even if we have openat support, since the + system getcwd works even when a parent is unreadable, while the + openat-based approach does not. */ + # undef getcwd dir = getcwd (buf, size); if (dir || (errno != ERANGE && !is_ENAMETOOLONG (errno) && errno != ENOENT)) @@ -226,6 +235,8 @@ __getcwd (char *buf, size_t size) dirstream = fdopendir (fd); if (dirstream == NULL) goto lose; + /* Reset fd. It may have been closed by fdopendir. */ + fd = dirfd (dirstream); fd_needs_closing = false; #else dirstream = __opendir (dotlist); @@ -380,7 +391,7 @@ __getcwd (char *buf, size_t size) used = dir + allocated - dirp; memmove (dir, dirp, used); - if (buf == NULL && size == 0) + if (size == 0) /* Ensure that the buffer is only as large as necessary. */ buf = realloc (dir, used);