1 /* Copyright (C) 1991-1999, 2004-2014 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
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.
8
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.
13
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/>. */
16
17 #if !_LIBC
18 # include <config.h>
19 # include <unistd.h>
20 #endif
21
22 #include <errno.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <stdbool.h>
26 #include <stddef.h>
27
28 #include <fcntl.h> /* For AT_FDCWD on Solaris 9. */
29
30 /* If this host provides the openat function or if we're using the
31 gnulib replacement function with a native fdopendir, then enable
32 code below to make getcwd more efficient and robust. */
33 #if defined HAVE_OPENAT || (defined GNULIB_OPENAT && defined HAVE_FDOPENDIR)
34 # define HAVE_OPENAT_SUPPORT 1
35 #else
36 # define HAVE_OPENAT_SUPPORT 0
37 #endif
38
39 #ifndef __set_errno
40 # define __set_errno(val) (errno = (val))
41 #endif
42
43 #include <dirent.h>
44 #ifndef _D_EXACT_NAMLEN
45 # define _D_EXACT_NAMLEN(d) strlen ((d)->d_name)
46 #endif
47 #ifndef _D_ALLOC_NAMLEN
48 # define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1)
49 #endif
50
51 #include <unistd.h>
52 #include <stdlib.h>
53 #include <string.h>
54
55 #if _LIBC
56 # ifndef mempcpy
57 # define mempcpy __mempcpy
58 # endif
59 #endif
60
61 #ifndef MAX
62 # define MAX(a, b) ((a) < (b) ? (b) : (a))
63 #endif
64 #ifndef MIN
65 # define MIN(a, b) ((a) < (b) ? (a) : (b))
66 #endif
67
68 #include "pathmax.h"
69
70 /* In this file, PATH_MAX only serves as a threshold for choosing among two
71 algorithms. */
72 #ifndef PATH_MAX
73 # define PATH_MAX 8192
74 #endif
75
76 #if D_INO_IN_DIRENT
77 # define MATCHING_INO(dp, ino) ((dp)->d_ino == (ino))
78 #else
79 # define MATCHING_INO(dp, ino) true
80 #endif
81
82 #if !_LIBC
83 # define __getcwd rpl_getcwd
84 # define __lstat lstat
85 # define __closedir closedir
86 # define __opendir opendir
87 # define __readdir readdir
88 #endif
89
90 /* The results of opendir() in this file are not used with dirfd and fchdir,
91 and we do not leak fds to any single-threaded code that could use stdio,
92 therefore save some unnecessary recursion in fchdir.c.
93 FIXME - if the kernel ever adds support for multi-thread safety for
94 avoiding standard fds, then we should use opendir_safer and
95 openat_safer. */
96 #undef opendir
97 #undef closedir
98
99 /* Get the name of the current working directory, and put it in SIZE
100 bytes of BUF. Returns NULL if the directory couldn't be determined or
101 SIZE was too small. If successful, returns BUF. In GNU, if BUF is
102 NULL, an array is allocated with 'malloc'; the array is SIZE bytes long,
103 unless SIZE == 0, in which case it is as big as necessary. */
104
105 char *
__getcwd(char * buf,size_t size)106 __getcwd (char *buf, size_t size)
107 {
108 /* Lengths of big file name components and entire file names, and a
109 deep level of file name nesting. These numbers are not upper
110 bounds; they are merely large values suitable for initial
111 allocations, designed to be large enough for most real-world
112 uses. */
113 enum
114 {
115 BIG_FILE_NAME_COMPONENT_LENGTH = 255,
116 BIG_FILE_NAME_LENGTH = MIN (4095, PATH_MAX - 1),
117 DEEP_NESTING = 100
118 };
119
120 #if HAVE_OPENAT_SUPPORT
121 int fd = AT_FDCWD;
122 bool fd_needs_closing = false;
123 #else
124 char dots[DEEP_NESTING * sizeof ".." + BIG_FILE_NAME_COMPONENT_LENGTH + 1];
125 char *dotlist = dots;
126 size_t dotsize = sizeof dots;
127 size_t dotlen = 0;
128 #endif
129 DIR *dirstream = NULL;
130 dev_t rootdev, thisdev;
131 ino_t rootino, thisino;
132 char *dir;
133 register char *dirp;
134 struct stat st;
135 size_t allocated = size;
136 size_t used;
137
138 #if HAVE_MINIMALLY_WORKING_GETCWD
139 /* If AT_FDCWD is not defined, the algorithm below is O(N**2) and
140 this is much slower than the system getcwd (at least on
141 GNU/Linux). So trust the system getcwd's results unless they
142 look suspicious.
143
144 Use the system getcwd even if we have openat support, since the
145 system getcwd works even when a parent is unreadable, while the
146 openat-based approach does not.
147
148 But on AIX 5.1..7.1, the system getcwd is not even minimally
149 working: If the current directory name is slightly longer than
150 PATH_MAX, it omits the first directory component and returns
151 this wrong result with errno = 0. */
152
153 # undef getcwd
154 dir = getcwd (buf, size);
155 if (dir || (size && errno == ERANGE))
156 return dir;
157
158 /* Solaris getcwd (NULL, 0) fails with errno == EINVAL, but it has
159 internal magic that lets it work even if an ancestor directory is
160 inaccessible, which is better in many cases. So in this case try
161 again with a buffer that's almost always big enough. */
162 if (errno == EINVAL && buf == NULL && size == 0)
163 {
164 char big_buffer[BIG_FILE_NAME_LENGTH + 1];
165 dir = getcwd (big_buffer, sizeof big_buffer);
166 if (dir)
167 return strdup (dir);
168 }
169
170 # if HAVE_PARTLY_WORKING_GETCWD
171 /* The system getcwd works, except it sometimes fails when it
172 shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT. */
173 if (errno != ERANGE && errno != ENAMETOOLONG && errno != ENOENT)
174 return NULL;
175 # endif
176 #endif
177
178 if (size == 0)
179 {
180 if (buf != NULL)
181 {
182 __set_errno (EINVAL);
183 return NULL;
184 }
185
186 allocated = BIG_FILE_NAME_LENGTH + 1;
187 }
188
189 if (buf == NULL)
190 {
191 dir = malloc (allocated);
192 if (dir == NULL)
193 return NULL;
194 }
195 else
196 dir = buf;
197
198 dirp = dir + allocated;
199 *--dirp = '\0';
200
201 if (__lstat (".", &st) < 0)
202 goto lose;
203 thisdev = st.st_dev;
204 thisino = st.st_ino;
205
206 if (__lstat ("/", &st) < 0)
207 goto lose;
208 rootdev = st.st_dev;
209 rootino = st.st_ino;
210
211 while (!(thisdev == rootdev && thisino == rootino))
212 {
213 struct dirent *d;
214 dev_t dotdev;
215 ino_t dotino;
216 bool mount_point;
217 int parent_status;
218 size_t dirroom;
219 size_t namlen;
220 bool use_d_ino = true;
221
222 /* Look at the parent directory. */
223 #if HAVE_OPENAT_SUPPORT
224 fd = openat (fd, "..", O_RDONLY);
225 if (fd < 0)
226 goto lose;
227 fd_needs_closing = true;
228 parent_status = fstat (fd, &st);
229 #else
230 dotlist[dotlen++] = '.';
231 dotlist[dotlen++] = '.';
232 dotlist[dotlen] = '\0';
233 parent_status = __lstat (dotlist, &st);
234 #endif
235 if (parent_status != 0)
236 goto lose;
237
238 if (dirstream && __closedir (dirstream) != 0)
239 {
240 dirstream = NULL;
241 goto lose;
242 }
243
244 /* Figure out if this directory is a mount point. */
245 dotdev = st.st_dev;
246 dotino = st.st_ino;
247 mount_point = dotdev != thisdev;
248
249 /* Search for the last directory. */
250 #if HAVE_OPENAT_SUPPORT
251 dirstream = fdopendir (fd);
252 if (dirstream == NULL)
253 goto lose;
254 fd_needs_closing = false;
255 #else
256 dirstream = __opendir (dotlist);
257 if (dirstream == NULL)
258 goto lose;
259 dotlist[dotlen++] = '/';
260 #endif
261 for (;;)
262 {
263 /* Clear errno to distinguish EOF from error if readdir returns
264 NULL. */
265 __set_errno (0);
266 d = __readdir (dirstream);
267
268 /* When we've iterated through all directory entries without finding
269 one with a matching d_ino, rewind the stream and consider each
270 name again, but this time, using lstat. This is necessary in a
271 chroot on at least one system (glibc-2.3.6 + linux 2.6.12), where
272 .., ../.., ../../.., etc. all had the same device number, yet the
273 d_ino values for entries in / did not match those obtained
274 via lstat. */
275 if (d == NULL && errno == 0 && use_d_ino)
276 {
277 use_d_ino = false;
278 rewinddir (dirstream);
279 d = __readdir (dirstream);
280 }
281
282 if (d == NULL)
283 {
284 if (errno == 0)
285 /* EOF on dirstream, which can mean e.g., that the current
286 directory has been removed. */
287 __set_errno (ENOENT);
288 goto lose;
289 }
290 if (d->d_name[0] == '.' &&
291 (d->d_name[1] == '\0' ||
292 (d->d_name[1] == '.' && d->d_name[2] == '\0')))
293 continue;
294
295 if (use_d_ino)
296 {
297 bool match = (MATCHING_INO (d, thisino) || mount_point);
298 if (! match)
299 continue;
300 }
301
302 {
303 int entry_status;
304 #if HAVE_OPENAT_SUPPORT
305 entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
306 #else
307 /* Compute size needed for this file name, or for the file
308 name ".." in the same directory, whichever is larger.
309 Room for ".." might be needed the next time through
310 the outer loop. */
311 size_t name_alloc = _D_ALLOC_NAMLEN (d);
312 size_t filesize = dotlen + MAX (sizeof "..", name_alloc);
313
314 if (filesize < dotlen)
315 goto memory_exhausted;
316
317 if (dotsize < filesize)
318 {
319 /* My, what a deep directory tree you have, Grandma. */
320 size_t newsize = MAX (filesize, dotsize * 2);
321 size_t i;
322 if (newsize < dotsize)
323 goto memory_exhausted;
324 if (dotlist != dots)
325 free (dotlist);
326 dotlist = malloc (newsize);
327 if (dotlist == NULL)
328 goto lose;
329 dotsize = newsize;
330
331 i = 0;
332 do
333 {
334 dotlist[i++] = '.';
335 dotlist[i++] = '.';
336 dotlist[i++] = '/';
337 }
338 while (i < dotlen);
339 }
340
341 memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
342 entry_status = __lstat (dotlist, &st);
343 #endif
344 /* We don't fail here if we cannot stat() a directory entry.
345 This can happen when (network) file systems fail. If this
346 entry is in fact the one we are looking for we will find
347 out soon as we reach the end of the directory without
348 having found anything. */
349 if (entry_status == 0 && S_ISDIR (st.st_mode)
350 && st.st_dev == thisdev && st.st_ino == thisino)
351 break;
352 }
353 }
354
355 dirroom = dirp - dir;
356 namlen = _D_EXACT_NAMLEN (d);
357
358 if (dirroom <= namlen)
359 {
360 if (size != 0)
361 {
362 __set_errno (ERANGE);
363 goto lose;
364 }
365 else
366 {
367 char *tmp;
368 size_t oldsize = allocated;
369
370 allocated += MAX (allocated, namlen);
371 if (allocated < oldsize
372 || ! (tmp = realloc (dir, allocated)))
373 goto memory_exhausted;
374
375 /* Move current contents up to the end of the buffer.
376 This is guaranteed to be non-overlapping. */
377 dirp = memcpy (tmp + allocated - (oldsize - dirroom),
378 tmp + dirroom,
379 oldsize - dirroom);
380 dir = tmp;
381 }
382 }
383 dirp -= namlen;
384 memcpy (dirp, d->d_name, namlen);
385 *--dirp = '/';
386
387 thisdev = dotdev;
388 thisino = dotino;
389 }
390
391 if (dirstream && __closedir (dirstream) != 0)
392 {
393 dirstream = NULL;
394 goto lose;
395 }
396
397 if (dirp == &dir[allocated - 1])
398 *--dirp = '/';
399
400 #if ! HAVE_OPENAT_SUPPORT
401 if (dotlist != dots)
402 free (dotlist);
403 #endif
404
405 used = dir + allocated - dirp;
406 memmove (dir, dirp, used);
407
408 if (size == 0)
409 /* Ensure that the buffer is only as large as necessary. */
410 buf = realloc (dir, used);
411
412 if (buf == NULL)
413 /* Either buf was NULL all along, or 'realloc' failed but
414 we still have the original string. */
415 buf = dir;
416
417 return buf;
418
419 memory_exhausted:
420 __set_errno (ENOMEM);
421 lose:
422 {
423 int save = errno;
424 if (dirstream)
425 __closedir (dirstream);
426 #if HAVE_OPENAT_SUPPORT
427 if (fd_needs_closing)
428 close (fd);
429 #else
430 if (dotlist != dots)
431 free (dotlist);
432 #endif
433 if (buf == NULL)
434 free (dir);
435 __set_errno (save);
436 }
437 return NULL;
438 }
439
440 #ifdef weak_alias
441 weak_alias (__getcwd, getcwd)
442 #endif
443