1
/* Copyright (C) 1991-1999, 2004-2010 Free Software Foundation, Inc.
2
This file is part of the GNU C Library.
4
This program is free software: you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 3 of the License, or
7
(at your option) any later version.
9
This program 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
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program. If not, see <http://www.gnu.org/licenses/>. */
23
#include <sys/types.h>
28
#include <fcntl.h> /* For AT_FDCWD on Solaris 9. */
30
/* If this host provides the openat function, then enable
31
code below to make getcwd more efficient and robust. */
33
# define HAVE_OPENAT_SUPPORT 1
35
# define HAVE_OPENAT_SUPPORT 0
39
# define __set_errno(val) (errno = (val))
43
#ifndef _D_EXACT_NAMLEN
44
# define _D_EXACT_NAMLEN(d) strlen ((d)->d_name)
46
#ifndef _D_ALLOC_NAMLEN
47
# define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1)
56
# define mempcpy __mempcpy
63
# define MAX(a, b) ((a) < (b) ? (b) : (a))
66
# define MIN(a, b) ((a) < (b) ? (a) : (b))
71
# define PATH_MAX MAXPATHLEN
73
# define PATH_MAX 1024
78
# define MATCHING_INO(dp, ino) ((dp)->d_ino == (ino))
80
# define MATCHING_INO(dp, ino) true
84
# define __getcwd rpl_getcwd
85
# define __lstat lstat
86
# define __closedir closedir
87
# define __opendir opendir
88
# define __readdir readdir
91
/* The results of opendir() in this file are not used with dirfd and fchdir,
92
and we do not leak fds to any single-threaded code that could use stdio,
93
therefore save some unnecessary recursion in fchdir.c.
94
FIXME - if the kernel ever adds support for multi-thread safety for
95
avoiding standard fds, then we should use opendir_safer and
100
/* Get the name of the current working directory, and put it in SIZE
101
bytes of BUF. Returns NULL if the directory couldn't be determined or
102
SIZE was too small. If successful, returns BUF. In GNU, if BUF is
103
NULL, an array is allocated with `malloc'; the array is SIZE bytes long,
104
unless SIZE == 0, in which case it is as big as necessary. */
107
__getcwd (char *buf, size_t size)
109
/* Lengths of big file name components and entire file names, and a
110
deep level of file name nesting. These numbers are not upper
111
bounds; they are merely large values suitable for initial
112
allocations, designed to be large enough for most real-world
116
BIG_FILE_NAME_COMPONENT_LENGTH = 255,
117
BIG_FILE_NAME_LENGTH = MIN (4095, PATH_MAX - 1),
121
#if HAVE_OPENAT_SUPPORT
123
bool fd_needs_closing = false;
125
char dots[DEEP_NESTING * sizeof ".." + BIG_FILE_NAME_COMPONENT_LENGTH + 1];
126
char *dotlist = dots;
127
size_t dotsize = sizeof dots;
130
DIR *dirstream = NULL;
131
dev_t rootdev, thisdev;
132
ino_t rootino, thisino;
136
size_t allocated = size;
139
#if HAVE_PARTLY_WORKING_GETCWD
140
/* The system getcwd works, except it sometimes fails when it
141
shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT. If
142
AT_FDCWD is not defined, the algorithm below is O(N**2) and this
143
is much slower than the system getcwd (at least on GNU/Linux).
144
So trust the system getcwd's results unless they look
147
Use the system getcwd even if we have openat support, since the
148
system getcwd works even when a parent is unreadable, while the
149
openat-based approach does not. */
152
dir = getcwd (buf, size);
153
if (dir || (errno != ERANGE && errno != ENAMETOOLONG && errno != ENOENT))
161
__set_errno (EINVAL);
165
allocated = BIG_FILE_NAME_LENGTH + 1;
170
dir = malloc (allocated);
177
dirp = dir + allocated;
180
if (__lstat (".", &st) < 0)
185
if (__lstat ("/", &st) < 0)
190
while (!(thisdev == rootdev && thisino == rootino))
199
bool use_d_ino = true;
201
/* Look at the parent directory. */
202
#if HAVE_OPENAT_SUPPORT
203
fd = openat (fd, "..", O_RDONLY);
206
fd_needs_closing = true;
207
parent_status = fstat (fd, &st);
209
dotlist[dotlen++] = '.';
210
dotlist[dotlen++] = '.';
211
dotlist[dotlen] = '\0';
212
parent_status = __lstat (dotlist, &st);
214
if (parent_status != 0)
217
if (dirstream && __closedir (dirstream) != 0)
223
/* Figure out if this directory is a mount point. */
226
mount_point = dotdev != thisdev;
228
/* Search for the last directory. */
229
#if HAVE_OPENAT_SUPPORT
230
dirstream = fdopendir (fd);
231
if (dirstream == NULL)
233
/* Reset fd. It may have been closed by fdopendir. */
234
fd = dirfd (dirstream);
235
fd_needs_closing = false;
237
dirstream = __opendir (dotlist);
238
if (dirstream == NULL)
240
dotlist[dotlen++] = '/';
244
/* Clear errno to distinguish EOF from error if readdir returns
247
d = __readdir (dirstream);
249
/* When we've iterated through all directory entries without finding
250
one with a matching d_ino, rewind the stream and consider each
251
name again, but this time, using lstat. This is necessary in a
252
chroot on at least one system (glibc-2.3.6 + linux 2.6.12), where
253
.., ../.., ../../.., etc. all had the same device number, yet the
254
d_ino values for entries in / did not match those obtained
256
if (d == NULL && errno == 0 && use_d_ino)
259
rewinddir (dirstream);
260
d = __readdir (dirstream);
266
/* EOF on dirstream, which can mean e.g., that the current
267
directory has been removed. */
268
__set_errno (ENOENT);
271
if (d->d_name[0] == '.' &&
272
(d->d_name[1] == '\0' ||
273
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
278
bool match = (MATCHING_INO (d, thisino) || mount_point);
285
#if HAVE_OPENAT_SUPPORT
286
entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
288
/* Compute size needed for this file name, or for the file
289
name ".." in the same directory, whichever is larger.
290
Room for ".." might be needed the next time through
292
size_t name_alloc = _D_ALLOC_NAMLEN (d);
293
size_t filesize = dotlen + MAX (sizeof "..", name_alloc);
295
if (filesize < dotlen)
296
goto memory_exhausted;
298
if (dotsize < filesize)
300
/* My, what a deep directory tree you have, Grandma. */
301
size_t newsize = MAX (filesize, dotsize * 2);
303
if (newsize < dotsize)
304
goto memory_exhausted;
307
dotlist = malloc (newsize);
322
memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
323
entry_status = __lstat (dotlist, &st);
325
/* We don't fail here if we cannot stat() a directory entry.
326
This can happen when (network) file systems fail. If this
327
entry is in fact the one we are looking for we will find
328
out soon as we reach the end of the directory without
329
having found anything. */
330
if (entry_status == 0 && S_ISDIR (st.st_mode)
331
&& st.st_dev == thisdev && st.st_ino == thisino)
336
dirroom = dirp - dir;
337
namlen = _D_EXACT_NAMLEN (d);
339
if (dirroom <= namlen)
343
__set_errno (ERANGE);
349
size_t oldsize = allocated;
351
allocated += MAX (allocated, namlen);
352
if (allocated < oldsize
353
|| ! (tmp = realloc (dir, allocated)))
354
goto memory_exhausted;
356
/* Move current contents up to the end of the buffer.
357
This is guaranteed to be non-overlapping. */
358
dirp = memcpy (tmp + allocated - (oldsize - dirroom),
365
memcpy (dirp, d->d_name, namlen);
372
if (dirstream && __closedir (dirstream) != 0)
378
if (dirp == &dir[allocated - 1])
381
#if ! HAVE_OPENAT_SUPPORT
386
used = dir + allocated - dirp;
387
memmove (dir, dirp, used);
390
/* Ensure that the buffer is only as large as necessary. */
391
buf = realloc (dir, used);
394
/* Either buf was NULL all along, or `realloc' failed but
395
we still have the original string. */
401
__set_errno (ENOMEM);
406
__closedir (dirstream);
407
#if HAVE_OPENAT_SUPPORT
408
if (fd_needs_closing)
422
weak_alias (__getcwd, getcwd)