1 /* Copyright (C) 1991-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
23 # define HAVE_OPENAT 1
24 # define D_INO_IN_DIRENT 1
25 # define HAVE_MSVC_INVALID_PARAMETER_HANDLER 0
26 # define HAVE_MINIMALLY_WORKING_GETCWD 0
30 #include <sys/types.h>
35 #include <fcntl.h> /* For AT_FDCWD on Solaris 9. */
37 /* If this host provides the openat function or if we're using the
38 gnulib replacement function with a native fdopendir, then enable
39 code below to make getcwd more efficient and robust. */
40 #if defined HAVE_OPENAT || (defined GNULIB_OPENAT && defined HAVE_FDOPENDIR)
41 # define HAVE_OPENAT_SUPPORT 1
43 # define HAVE_OPENAT_SUPPORT 0
47 # define __set_errno(val) (errno = (val))
51 #ifndef _D_EXACT_NAMLEN
52 # define _D_EXACT_NAMLEN(d) strlen ((d)->d_name)
54 #ifndef _D_ALLOC_NAMLEN
55 # define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1)
64 # define mempcpy __mempcpy
69 # define MAX(a, b) ((a) < (b) ? (b) : (a))
72 # define MIN(a, b) ((a) < (b) ? (a) : (b))
75 /* In this file, PATH_MAX only serves as a threshold for choosing among two
78 # define PATH_MAX 8192
82 # define MATCHING_INO(dp, ino) ((dp)->d_ino == (ino))
84 # define MATCHING_INO(dp, ino) true
87 #if HAVE_MSVC_INVALID_PARAMETER_HANDLER
88 # include "msvc-inval.h"
92 # define GETCWD_RETURN_TYPE char *
93 # define __close_nocancel_nostatus close
94 # define __getcwd_generic rpl_getcwd
97 # define __fstat64 fstat
98 # define __fstatat64 fstatat
99 # define __lstat64 lstat
100 # define __closedir closedir
101 # define __opendir opendir
102 # define __readdir64 readdir
103 # define __fdopendir fdopendir
104 # define __openat openat
105 # define __rewinddir rewinddir
106 # define __openat64 openat
107 # define dirent64 dirent
109 # include <not-cancel.h>
112 /* The results of opendir() in this file are not used with dirfd and fchdir,
113 and we do not leak fds to any single-threaded code that could use stdio,
114 therefore save some unnecessary recursion in fchdir.c.
115 FIXME - if the kernel ever adds support for multi-thread safety for
116 avoiding standard fds, then we should use opendir_safer and
118 #ifdef GNULIB_defined_opendir
121 #ifdef GNULIB_defined_closedir
125 #if defined _WIN32 && !defined __CYGWIN__
126 # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
128 getcwd_nothrow (char *buf
, size_t size
)
134 result
= _getcwd (buf
, size
);
146 # define getcwd_nothrow _getcwd
148 # define getcwd_system getcwd_nothrow
150 # define getcwd_system getcwd
153 /* Get the name of the current working directory, and put it in SIZE
154 bytes of BUF. Returns NULL with errno set if the directory couldn't be
155 determined or SIZE was too small. If successful, returns BUF. In GNU,
156 if BUF is NULL, an array is allocated with 'malloc'; the array is SIZE
157 bytes long, unless SIZE == 0, in which case it is as big as necessary. */
160 __getcwd_generic (char *buf
, size_t size
)
162 /* Lengths of big file name components and entire file names, and a
163 deep level of file name nesting. These numbers are not upper
164 bounds; they are merely large values suitable for initial
165 allocations, designed to be large enough for most real-world
169 BIG_FILE_NAME_COMPONENT_LENGTH
= 255,
170 BIG_FILE_NAME_LENGTH
= MIN (4095, PATH_MAX
- 1),
174 #if HAVE_OPENAT_SUPPORT
176 bool fd_needs_closing
= false;
178 char dots
[DEEP_NESTING
* sizeof ".." + BIG_FILE_NAME_COMPONENT_LENGTH
+ 1];
179 char *dotlist
= dots
;
180 size_t dotsize
= sizeof dots
;
183 DIR *dirstream
= NULL
;
184 dev_t rootdev
, thisdev
;
185 ino_t rootino
, thisino
;
189 size_t allocated
= size
;
192 #if HAVE_MINIMALLY_WORKING_GETCWD
193 /* If AT_FDCWD is not defined, the algorithm below is O(N**2) and
194 this is much slower than the system getcwd (at least on
195 GNU/Linux). So trust the system getcwd's results unless they
198 Use the system getcwd even if we have openat support, since the
199 system getcwd works even when a parent is unreadable, while the
200 openat-based approach does not.
202 But on AIX 5.1..7.1, the system getcwd is not even minimally
203 working: If the current directory name is slightly longer than
204 PATH_MAX, it omits the first directory component and returns
205 this wrong result with errno = 0. */
208 dir
= getcwd_system (buf
, size
);
209 if (dir
|| (size
&& errno
== ERANGE
))
212 /* Solaris getcwd (NULL, 0) fails with errno == EINVAL, but it has
213 internal magic that lets it work even if an ancestor directory is
214 inaccessible, which is better in many cases. So in this case try
215 again with a buffer that's almost always big enough. */
216 if (errno
== EINVAL
&& buf
== NULL
&& size
== 0)
218 char big_buffer
[BIG_FILE_NAME_LENGTH
+ 1];
219 dir
= getcwd_system (big_buffer
, sizeof big_buffer
);
224 # if HAVE_PARTLY_WORKING_GETCWD
225 /* The system getcwd works, except it sometimes fails when it
226 shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT. */
227 if (errno
!= ERANGE
&& errno
!= ENAMETOOLONG
&& errno
!= ENOENT
)
235 __set_errno (EINVAL
);
239 allocated
= BIG_FILE_NAME_LENGTH
+ 1;
244 dir
= malloc (allocated
);
251 dirp
= dir
+ allocated
;
254 if (__lstat64 (".", &st
) < 0)
259 if (__lstat64 ("/", &st
) < 0)
264 while (!(thisdev
== rootdev
&& thisino
== rootino
))
273 bool use_d_ino
= true;
275 /* Look at the parent directory. */
276 #if HAVE_OPENAT_SUPPORT
277 fd
= __openat64 (fd
, "..", O_RDONLY
);
280 fd_needs_closing
= true;
281 parent_status
= __fstat64 (fd
, &st
);
283 dotlist
[dotlen
++] = '.';
284 dotlist
[dotlen
++] = '.';
285 dotlist
[dotlen
] = '\0';
286 parent_status
= __lstat64 (dotlist
, &st
);
288 if (parent_status
!= 0)
291 if (dirstream
&& __closedir (dirstream
) != 0)
297 /* Figure out if this directory is a mount point. */
300 mount_point
= dotdev
!= thisdev
;
302 /* Search for the last directory. */
303 #if HAVE_OPENAT_SUPPORT
304 dirstream
= __fdopendir (fd
);
305 if (dirstream
== NULL
)
307 fd_needs_closing
= false;
309 dirstream
= __opendir (dotlist
);
310 if (dirstream
== NULL
)
312 dotlist
[dotlen
++] = '/';
316 /* Clear errno to distinguish EOF from error if readdir returns
319 d
= __readdir64 (dirstream
);
321 /* When we've iterated through all directory entries without finding
322 one with a matching d_ino, rewind the stream and consider each
323 name again, but this time, using lstat. This is necessary in a
324 chroot on at least one system (glibc-2.3.6 + linux 2.6.12), where
325 .., ../.., ../../.., etc. all had the same device number, yet the
326 d_ino values for entries in / did not match those obtained
328 if (d
== NULL
&& errno
== 0 && use_d_ino
)
331 __rewinddir (dirstream
);
332 d
= __readdir64 (dirstream
);
338 /* EOF on dirstream, which can mean e.g., that the current
339 directory has been removed. */
340 __set_errno (ENOENT
);
343 if (d
->d_name
[0] == '.' &&
344 (d
->d_name
[1] == '\0' ||
345 (d
->d_name
[1] == '.' && d
->d_name
[2] == '\0')))
350 bool match
= (MATCHING_INO (d
, thisino
) || mount_point
);
357 #if HAVE_OPENAT_SUPPORT
358 entry_status
= __fstatat64 (fd
, d
->d_name
, &st
, AT_SYMLINK_NOFOLLOW
);
360 /* Compute size needed for this file name, or for the file
361 name ".." in the same directory, whichever is larger.
362 Room for ".." might be needed the next time through
364 size_t name_alloc
= _D_ALLOC_NAMLEN (d
);
365 size_t filesize
= dotlen
+ MAX (sizeof "..", name_alloc
);
367 if (filesize
< dotlen
)
368 goto memory_exhausted
;
370 if (dotsize
< filesize
)
372 /* My, what a deep directory tree you have, Grandma. */
373 size_t newsize
= MAX (filesize
, dotsize
* 2);
375 if (newsize
< dotsize
)
376 goto memory_exhausted
;
379 dotlist
= malloc (newsize
);
394 memcpy (dotlist
+ dotlen
, d
->d_name
, _D_ALLOC_NAMLEN (d
));
395 entry_status
= __lstat64 (dotlist
, &st
);
397 /* We don't fail here if we cannot stat() a directory entry.
398 This can happen when (network) file systems fail. If this
399 entry is in fact the one we are looking for we will find
400 out soon as we reach the end of the directory without
401 having found anything. */
402 if (entry_status
== 0 && S_ISDIR (st
.st_mode
)
403 && st
.st_dev
== thisdev
&& st
.st_ino
== thisino
)
408 dirroom
= dirp
- dir
;
409 namlen
= _D_EXACT_NAMLEN (d
);
411 if (dirroom
<= namlen
)
415 __set_errno (ERANGE
);
421 size_t oldsize
= allocated
;
423 allocated
+= MAX (allocated
, namlen
);
424 if (allocated
< oldsize
425 || ! (tmp
= realloc (dir
, allocated
)))
426 goto memory_exhausted
;
428 /* Move current contents up to the end of the buffer.
429 This is guaranteed to be non-overlapping. */
430 dirp
= memcpy (tmp
+ allocated
- (oldsize
- dirroom
),
437 memcpy (dirp
, d
->d_name
, namlen
);
444 if (dirstream
&& __closedir (dirstream
) != 0)
450 if (dirp
== &dir
[allocated
- 1])
453 #if ! HAVE_OPENAT_SUPPORT
458 used
= dir
+ allocated
- dirp
;
459 memmove (dir
, dirp
, used
);
462 /* Ensure that the buffer is only as large as necessary. */
463 buf
= (used
< allocated
? realloc (dir
, used
) : dir
);
466 /* Either buf was NULL all along, or 'realloc' failed but
467 we still have the original string. */
473 __set_errno (ENOMEM
);
478 __closedir (dirstream
);
479 #if HAVE_OPENAT_SUPPORT
480 if (fd_needs_closing
)
481 __close_nocancel_nostatus (fd
);
493 #if defined _LIBC && !defined GETCWD_RETURN_TYPE
494 libc_hidden_def (__getcwd
)
495 weak_alias (__getcwd
, getcwd
)