Replace FSF snail mail address with URLs.
[glibc.git] / sysdeps / posix / getcwd.c
blob6c41977eb0e67e52782df6a4d2c313f7f0c420ba
1 /* Copyright (C) 1991-1999,2011-2012 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 <http://www.gnu.org/licenses/>. */
18 /* Wants:
19 AC_STDC_HEADERS
20 AC_DIR_HEADER
21 AC_UNISTD_H
22 AC_MEMORY_H
23 AC_CONST
24 AC_ALLOCA
27 /* AIX requires this to be the first thing in the file. */
28 #if defined _AIX && !defined __GNUC__
29 #pragma alloca
30 #endif
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
41 #ifdef STDC_HEADERS
42 # include <stddef.h>
43 #endif
45 #if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS
46 extern int errno;
47 #endif
48 #ifndef __set_errno
49 # define __set_errno(val) errno = (val)
50 #endif
52 #ifndef NULL
53 # define NULL 0
54 #endif
56 #if defined USGr3 && !defined DIRENT
57 # define DIRENT
58 #endif /* USGr3 */
59 #if defined Xenix && !defined SYSNDIR
60 # define SYSNDIR
61 #endif /* Xenix */
63 #if defined POSIX || defined DIRENT || defined __GNU_LIBRARY__
64 # include <dirent.h>
65 # ifndef __GNU_LIBRARY__
66 # define D_NAMLEN(d) strlen((d)->d_name)
67 # else
68 # define HAVE_D_NAMLEN
69 # define D_NAMLEN(d) ((d)->d_namlen)
70 # endif
71 #else /* not POSIX or DIRENT */
72 # define dirent direct
73 # define D_NAMLEN(d) ((d)->d_namlen)
74 # define HAVE_D_NAMLEN
75 # if defined USG && !defined sgi
76 # if defined SYSNDIR
77 # include <sys/ndir.h>
78 # else /* Not SYSNDIR */
79 # include "ndir.h"
80 # endif /* SYSNDIR */
81 # else /* not USG */
82 # include <sys/dir.h>
83 # endif /* USG */
84 #endif /* POSIX or DIRENT or __GNU_LIBRARY__ */
86 #if defined HAVE_UNISTD_H || defined __GNU_LIBRARY__
87 # include <unistd.h>
88 #endif
90 #if defined STDC_HEADERS || defined __GNU_LIBRARY__ || defined POSIX
91 # include <stdlib.h>
92 # include <string.h>
93 # define ANSI_STRING
94 #else /* No standard headers. */
96 # ifdef USG
98 # include <string.h>
99 # ifdef NEED_MEMORY_H
100 # include <memory.h>
101 # endif
102 # define ANSI_STRING
104 # else /* Not USG. */
106 # ifdef NeXT
108 # include <string.h>
110 # else /* Not NeXT. */
112 # include <strings.h>
114 # ifndef bcmp
115 extern int bcmp ();
116 # endif
117 # ifndef bzero
118 extern void bzero ();
119 # endif
120 # ifndef bcopy
121 extern void bcopy ();
122 # endif
124 # endif /* NeXT. */
126 # endif /* USG. */
128 extern char *malloc (), *realloc ();
129 extern void free ();
131 #endif /* Standard headers. */
133 #ifndef ANSI_STRING
134 # define memcpy(d, s, n) bcopy((s), (d), (n))
135 # define memmove memcpy
136 #endif /* Not ANSI_STRING. */
138 #ifndef MAX
139 # define MAX(a, b) ((a) < (b) ? (b) : (a))
140 #endif
142 #ifdef _LIBC
143 # ifndef mempcpy
144 # define mempcpy __mempcpy
145 # endif
146 # define HAVE_MEMPCPY 1
147 #endif
149 #if !defined __alloca && !defined __GNU_LIBRARY__
151 # ifdef __GNUC__
152 # undef alloca
153 # define alloca(n) __builtin_alloca (n)
154 # else /* Not GCC. */
155 # if defined sparc || defined HAVE_ALLOCA_H
156 # include <alloca.h>
157 # else /* Not sparc or HAVE_ALLOCA_H. */
158 # ifndef _AIX
159 extern char *alloca ();
160 # endif /* Not _AIX. */
161 # endif /* sparc or HAVE_ALLOCA_H. */
162 # endif /* GCC. */
164 # define __alloca alloca
166 #endif
168 #if defined HAVE_LIMITS_H || defined STDC_HEADERS || defined __GNU_LIBRARY__
169 # include <limits.h>
170 #else
171 # include <sys/param.h>
172 #endif
174 #if defined _LIBC
175 # include <not-cancel.h>
176 #else
177 # define openat64_not_cancel_3(dfd, name, mode) openat64 (dfd, name, mode)
178 # define close_not_cancel_no_status(fd) close (fd)
179 #endif
181 #ifndef PATH_MAX
182 # ifdef MAXPATHLEN
183 # define PATH_MAX MAXPATHLEN
184 # else
185 # define PATH_MAX 1024
186 # endif
187 #endif
189 #if !defined STDC_HEADERS && !defined __GNU_LIBRARY__
190 # undef size_t
191 # define size_t unsigned int
192 #endif
194 #ifndef __GNU_LIBRARY__
195 # define __lstat64 stat64
196 #endif
198 #ifndef _LIBC
199 # define __getcwd getcwd
200 #endif
202 #ifndef GETCWD_RETURN_TYPE
203 # define GETCWD_RETURN_TYPE char *
204 #endif
206 #ifdef __ASSUME_ATFCTS
207 # define __have_atfcts 1
208 #elif defined NOT_IN_libc && defined IS_IN_rtld
209 static int __rtld_have_atfcts;
210 # define __have_atfcts __rtld_have_atfcts
211 #endif
213 /* Get the pathname of the current working directory, and put it in SIZE
214 bytes of BUF. Returns NULL if the directory couldn't be determined or
215 SIZE was too small. If successful, returns BUF. In GNU, if BUF is
216 NULL, an array is allocated with `malloc'; the array is SIZE bytes long,
217 unless SIZE == 0, in which case it is as big as necessary. */
219 GETCWD_RETURN_TYPE
220 __getcwd (buf, size)
221 char *buf;
222 size_t size;
224 #ifndef __ASSUME_ATFCTS
225 static const char dots[]
226 = "../../../../../../../../../../../../../../../../../../../../../../../\
227 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
228 ../../../../../../../../../../../../../../../../../../../../../../../../../..";
229 const char *dotp = &dots[sizeof (dots)];
230 const char *dotlist = dots;
231 size_t dotsize = sizeof (dots) - 1;
232 #endif
233 int prev_errno = errno;
234 DIR *dirstream = NULL;
235 bool fd_needs_closing = false;
236 int fd = AT_FDCWD;
238 char *path;
239 #ifndef NO_ALLOCATION
240 size_t allocated = size;
241 if (size == 0)
243 if (buf != NULL)
245 __set_errno (EINVAL);
246 return NULL;
249 allocated = PATH_MAX + 1;
252 if (buf == NULL)
254 path = malloc (allocated);
255 if (path == NULL)
256 return NULL;
258 else
259 #else
260 # define allocated size
261 #endif
262 path = buf;
264 char *pathp = path + allocated;
265 *--pathp = '\0';
267 struct stat64 st;
268 if (__lstat64 (".", &st) < 0)
269 goto lose;
270 dev_t thisdev = st.st_dev;
271 ino_t thisino = st.st_ino;
273 if (__lstat64 ("/", &st) < 0)
274 goto lose;
275 dev_t rootdev = st.st_dev;
276 ino_t rootino = st.st_ino;
278 while (!(thisdev == rootdev && thisino == rootino))
280 if (__have_atfcts >= 0)
282 int mode = O_RDONLY;
283 #ifdef O_CLOEXEC
284 mode |= O_CLOEXEC;
285 #endif
286 fd = openat64_not_cancel_3 (fd, "..", mode);
288 else
289 fd = -1;
290 if (fd >= 0)
292 fd_needs_closing = true;
293 if (__fstat64 (fd, &st) < 0)
294 goto lose;
296 #ifndef __ASSUME_ATFCTS
297 else if (errno == ENOSYS)
299 __have_atfcts = -1;
301 /* Look at the parent directory. */
302 if (dotp == dotlist)
304 # ifdef NO_ALLOCATION
305 __set_errno (ENOMEM);
306 goto lose;
307 # else
308 /* My, what a deep directory tree you have, Grandma. */
309 char *new;
310 if (dotlist == dots)
312 new = malloc (dotsize * 2 + 1);
313 if (new == NULL)
314 goto lose;
315 # ifdef HAVE_MEMPCPY
316 dotp = mempcpy (new, dots, dotsize);
317 # else
318 memcpy (new, dots, dotsize);
319 dotp = &new[dotsize];
320 # endif
322 else
324 new = realloc ((__ptr_t) dotlist, dotsize * 2 + 1);
325 if (new == NULL)
326 goto lose;
327 dotp = &new[dotsize];
329 # ifdef HAVE_MEMPCPY
330 *((char *) mempcpy ((char *) dotp, new, dotsize)) = '\0';
331 dotsize *= 2;
332 # else
333 memcpy ((char *) dotp, new, dotsize);
334 dotsize *= 2;
335 new[dotsize] = '\0';
336 # endif
337 dotlist = new;
338 # endif
341 dotp -= 3;
343 /* Figure out if this directory is a mount point. */
344 if (__lstat64 (dotp, &st) < 0)
345 goto lose;
347 #endif
348 else
349 goto lose;
351 if (dirstream && __closedir (dirstream) != 0)
353 dirstream = NULL;
354 goto lose;
357 dev_t dotdev = st.st_dev;
358 ino_t dotino = st.st_ino;
359 bool mount_point = dotdev != thisdev;
361 /* Search for the last directory. */
362 if (__have_atfcts >= 0)
363 dirstream = __fdopendir (fd);
364 #ifndef __ASSUME_ATFCTS
365 else
366 dirstream = __opendir (dotp);
367 #endif
368 if (dirstream == NULL)
369 goto lose;
370 fd_needs_closing = false;
372 struct dirent *d;
373 bool use_d_ino = true;
374 while (1)
376 /* Clear errno to distinguish EOF from error if readdir returns
377 NULL. */
378 __set_errno (0);
379 d = __readdir (dirstream);
380 if (d == NULL)
382 if (errno == 0)
384 /* When we've iterated through all directory entries
385 without finding one with a matching d_ino, rewind the
386 stream and consider each name again, but this time, using
387 lstat64. This is necessary in a chroot on at least one
388 system. */
389 if (use_d_ino)
391 use_d_ino = false;
392 rewinddir (dirstream);
393 continue;
396 /* EOF on dirstream, which means that the current directory
397 has been removed. */
398 __set_errno (ENOENT);
400 goto lose;
403 if (d->d_type != DT_DIR && d->d_type != DT_UNKNOWN)
404 continue;
405 if (d->d_name[0] == '.'
406 && (d->d_name[1] == '\0'
407 || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
408 continue;
409 if (use_d_ino && !mount_point && (ino_t) d->d_ino != thisino)
410 continue;
412 if (__have_atfcts >= 0)
414 /* We don't fail here if we cannot stat64() a directory entry.
415 This can happen when (network) filesystems fail. If this
416 entry is in fact the one we are looking for we will find
417 out soon as we reach the end of the directory without
418 having found anything. */
419 if (__fstatat64 (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
420 continue;
422 #ifndef __ASSUME_ATFCTS
423 else
425 char name[dotlist + dotsize - dotp + 1 + _D_ALLOC_NAMLEN (d)];
426 # ifdef HAVE_MEMPCPY
427 char *tmp = mempcpy (name, dotp, dotlist + dotsize - dotp);
428 *tmp++ = '/';
429 strcpy (tmp, d->d_name);
430 # else
431 memcpy (name, dotp, dotlist + dotsize - dotp);
432 name[dotlist + dotsize - dotp] = '/';
433 strcpy (&name[dotlist + dotsize - dotp + 1], d->d_name);
434 # endif
435 /* We don't fail here if we cannot stat64() a directory entry.
436 This can happen when (network) filesystems fail. If this
437 entry is in fact the one we are looking for we will find
438 out soon as we reach the end of the directory without
439 having found anything. */
440 if (__lstat64 (name, &st) < 0)
441 continue;
443 #endif
444 if (S_ISDIR (st.st_mode)
445 && st.st_dev == thisdev && st.st_ino == thisino)
446 break;
449 size_t namlen = _D_EXACT_NAMLEN (d);
451 if ((size_t) (pathp - path) <= namlen)
453 #ifndef NO_ALLOCATION
454 if (size == 0)
456 size_t oldsize = allocated;
458 allocated = 2 * MAX (allocated, namlen);
459 char *tmp = realloc (path, allocated);
460 if (tmp == NULL)
461 goto lose;
463 /* Move current contents up to the end of the buffer.
464 This is guaranteed to be non-overlapping. */
465 pathp = memcpy (tmp + allocated - (path + oldsize - pathp),
466 tmp + (pathp - path),
467 path + oldsize - pathp);
468 path = tmp;
470 else
471 #endif
473 __set_errno (ERANGE);
474 goto lose;
477 pathp -= namlen;
478 (void) memcpy (pathp, d->d_name, namlen);
479 *--pathp = '/';
481 thisdev = dotdev;
482 thisino = dotino;
485 if (dirstream != NULL && __closedir (dirstream) != 0)
487 dirstream = NULL;
488 goto lose;
491 if (pathp == &path[allocated - 1])
492 *--pathp = '/';
494 #ifndef __ASSUME_ATFCTS
495 if (dotlist != dots)
496 free ((__ptr_t) dotlist);
497 #endif
499 size_t used = path + allocated - pathp;
500 memmove (path, pathp, used);
502 if (size == 0)
503 /* Ensure that the buffer is only as large as necessary. */
504 buf = realloc (path, used);
506 if (buf == NULL)
507 /* Either buf was NULL all along, or `realloc' failed but
508 we still have the original string. */
509 buf = path;
511 /* Restore errno on successful return. */
512 __set_errno (prev_errno);
514 return buf;
516 lose:;
517 int save_errno = errno;
518 #ifndef __ASSUME_ATFCTS
519 if (dotlist != dots)
520 free ((__ptr_t) dotlist);
521 #endif
522 if (dirstream != NULL)
523 __closedir (dirstream);
524 if (fd_needs_closing)
525 close_not_cancel_no_status (fd);
526 #ifndef NO_ALLOCATION
527 if (buf == NULL)
528 free (path);
529 #endif
530 __set_errno (save_errno);
531 return NULL;
534 #if defined _LIBC && !defined __getcwd
535 weak_alias (__getcwd, getcwd)
536 #endif