Fix sem_* tdelete, tfind, tsearch, twalk namespace (bug 18536).
[glibc.git] / sysdeps / posix / getcwd.c
blobafe696767a7904dcf1aeb9b6faf50fb9b7a14dc5
1 /* Copyright (C) 1991-2015 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 # include <kernel-features.h>
177 #else
178 # define openat64_not_cancel_3(dfd, name, mode) openat64 (dfd, name, mode)
179 # define close_not_cancel_no_status(fd) close (fd)
180 #endif
182 #ifndef PATH_MAX
183 # ifdef MAXPATHLEN
184 # define PATH_MAX MAXPATHLEN
185 # else
186 # define PATH_MAX 1024
187 # endif
188 #endif
190 #if !defined STDC_HEADERS && !defined __GNU_LIBRARY__
191 # undef size_t
192 # define size_t unsigned int
193 #endif
195 #ifndef __GNU_LIBRARY__
196 # define __lstat64 stat64
197 #endif
199 #ifndef _LIBC
200 # define __rewinddir rewinddir
201 #endif
203 #ifndef _LIBC
204 # define __getcwd getcwd
205 #endif
207 #ifndef GETCWD_RETURN_TYPE
208 # define GETCWD_RETURN_TYPE char *
209 #endif
211 #ifdef __ASSUME_ATFCTS
212 # define __have_atfcts 1
213 #elif IS_IN (rtld)
214 static int __rtld_have_atfcts;
215 # define __have_atfcts __rtld_have_atfcts
216 #endif
218 /* Get the pathname of the current working directory, and put it in SIZE
219 bytes of BUF. Returns NULL if the directory couldn't be determined or
220 SIZE was too small. If successful, returns BUF. In GNU, if BUF is
221 NULL, an array is allocated with `malloc'; the array is SIZE bytes long,
222 unless SIZE == 0, in which case it is as big as necessary. */
224 GETCWD_RETURN_TYPE
225 __getcwd (buf, size)
226 char *buf;
227 size_t size;
229 #ifndef __ASSUME_ATFCTS
230 static const char dots[]
231 = "../../../../../../../../../../../../../../../../../../../../../../../\
232 ../../../../../../../../../../../../../../../../../../../../../../../../../../\
233 ../../../../../../../../../../../../../../../../../../../../../../../../../..";
234 const char *dotp = &dots[sizeof (dots)];
235 const char *dotlist = dots;
236 size_t dotsize = sizeof (dots) - 1;
237 #endif
238 int prev_errno = errno;
239 DIR *dirstream = NULL;
240 bool fd_needs_closing = false;
241 int fd = AT_FDCWD;
243 char *path;
244 #ifndef NO_ALLOCATION
245 size_t allocated = size;
246 if (size == 0)
248 if (buf != NULL)
250 __set_errno (EINVAL);
251 return NULL;
254 allocated = PATH_MAX + 1;
257 if (buf == NULL)
259 path = malloc (allocated);
260 if (path == NULL)
261 return NULL;
263 else
264 #else
265 # define allocated size
266 #endif
267 path = buf;
269 char *pathp = path + allocated;
270 *--pathp = '\0';
272 struct stat64 st;
273 if (__lstat64 (".", &st) < 0)
274 goto lose;
275 dev_t thisdev = st.st_dev;
276 ino_t thisino = st.st_ino;
278 if (__lstat64 ("/", &st) < 0)
279 goto lose;
280 dev_t rootdev = st.st_dev;
281 ino_t rootino = st.st_ino;
283 while (!(thisdev == rootdev && thisino == rootino))
285 if (__have_atfcts >= 0)
287 int mode = O_RDONLY;
288 #ifdef O_CLOEXEC
289 mode |= O_CLOEXEC;
290 #endif
291 fd = openat64_not_cancel_3 (fd, "..", mode);
293 else
294 fd = -1;
295 if (fd >= 0)
297 fd_needs_closing = true;
298 if (__fstat64 (fd, &st) < 0)
299 goto lose;
301 #ifndef __ASSUME_ATFCTS
302 else if (errno == ENOSYS)
304 __have_atfcts = -1;
306 /* Look at the parent directory. */
307 if (dotp == dotlist)
309 # ifdef NO_ALLOCATION
310 __set_errno (ENOMEM);
311 goto lose;
312 # else
313 /* My, what a deep directory tree you have, Grandma. */
314 char *new;
315 if (dotlist == dots)
317 new = malloc (dotsize * 2 + 1);
318 if (new == NULL)
319 goto lose;
320 # ifdef HAVE_MEMPCPY
321 dotp = mempcpy (new, dots, dotsize);
322 # else
323 memcpy (new, dots, dotsize);
324 dotp = &new[dotsize];
325 # endif
327 else
329 new = realloc ((__ptr_t) dotlist, dotsize * 2 + 1);
330 if (new == NULL)
331 goto lose;
332 dotp = &new[dotsize];
334 # ifdef HAVE_MEMPCPY
335 *((char *) mempcpy ((char *) dotp, new, dotsize)) = '\0';
336 dotsize *= 2;
337 # else
338 memcpy ((char *) dotp, new, dotsize);
339 dotsize *= 2;
340 new[dotsize] = '\0';
341 # endif
342 dotlist = new;
343 # endif
346 dotp -= 3;
348 /* Figure out if this directory is a mount point. */
349 if (__lstat64 (dotp, &st) < 0)
350 goto lose;
352 #endif
353 else
354 goto lose;
356 if (dirstream && __closedir (dirstream) != 0)
358 dirstream = NULL;
359 goto lose;
362 dev_t dotdev = st.st_dev;
363 ino_t dotino = st.st_ino;
364 bool mount_point = dotdev != thisdev;
366 /* Search for the last directory. */
367 if (__have_atfcts >= 0)
368 dirstream = __fdopendir (fd);
369 #ifndef __ASSUME_ATFCTS
370 else
371 dirstream = __opendir (dotp);
372 #endif
373 if (dirstream == NULL)
374 goto lose;
375 fd_needs_closing = false;
377 struct dirent *d;
378 bool use_d_ino = true;
379 while (1)
381 /* Clear errno to distinguish EOF from error if readdir returns
382 NULL. */
383 __set_errno (0);
384 d = __readdir (dirstream);
385 if (d == NULL)
387 if (errno == 0)
389 /* When we've iterated through all directory entries
390 without finding one with a matching d_ino, rewind the
391 stream and consider each name again, but this time, using
392 lstat64. This is necessary in a chroot on at least one
393 system. */
394 if (use_d_ino)
396 use_d_ino = false;
397 __rewinddir (dirstream);
398 continue;
401 /* EOF on dirstream, which means that the current directory
402 has been removed. */
403 __set_errno (ENOENT);
405 goto lose;
408 #ifdef _DIRENT_HAVE_D_TYPE
409 if (d->d_type != DT_DIR && d->d_type != DT_UNKNOWN)
410 continue;
411 #endif
412 if (d->d_name[0] == '.'
413 && (d->d_name[1] == '\0'
414 || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
415 continue;
416 if (use_d_ino && !mount_point && (ino_t) d->d_ino != thisino)
417 continue;
419 if (__have_atfcts >= 0)
421 /* We don't fail here if we cannot stat64() a directory entry.
422 This can happen when (network) filesystems fail. If this
423 entry is in fact the one we are looking for we will find
424 out soon as we reach the end of the directory without
425 having found anything. */
426 if (__fstatat64 (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
427 continue;
429 #ifndef __ASSUME_ATFCTS
430 else
432 char name[dotlist + dotsize - dotp + 1 + _D_ALLOC_NAMLEN (d)];
433 # ifdef HAVE_MEMPCPY
434 char *tmp = mempcpy (name, dotp, dotlist + dotsize - dotp);
435 *tmp++ = '/';
436 strcpy (tmp, d->d_name);
437 # else
438 memcpy (name, dotp, dotlist + dotsize - dotp);
439 name[dotlist + dotsize - dotp] = '/';
440 strcpy (&name[dotlist + dotsize - dotp + 1], d->d_name);
441 # endif
442 /* We don't fail here if we cannot stat64() a directory entry.
443 This can happen when (network) filesystems fail. If this
444 entry is in fact the one we are looking for we will find
445 out soon as we reach the end of the directory without
446 having found anything. */
447 if (__lstat64 (name, &st) < 0)
448 continue;
450 #endif
451 if (S_ISDIR (st.st_mode)
452 && st.st_dev == thisdev && st.st_ino == thisino)
453 break;
456 size_t namlen = _D_EXACT_NAMLEN (d);
458 if ((size_t) (pathp - path) <= namlen)
460 #ifndef NO_ALLOCATION
461 if (size == 0)
463 size_t oldsize = allocated;
465 allocated = 2 * MAX (allocated, namlen);
466 char *tmp = realloc (path, allocated);
467 if (tmp == NULL)
468 goto lose;
470 /* Move current contents up to the end of the buffer.
471 This is guaranteed to be non-overlapping. */
472 pathp = memcpy (tmp + allocated - (path + oldsize - pathp),
473 tmp + (pathp - path),
474 path + oldsize - pathp);
475 path = tmp;
477 else
478 #endif
480 __set_errno (ERANGE);
481 goto lose;
484 pathp -= namlen;
485 (void) memcpy (pathp, d->d_name, namlen);
486 *--pathp = '/';
488 thisdev = dotdev;
489 thisino = dotino;
492 if (dirstream != NULL && __closedir (dirstream) != 0)
494 dirstream = NULL;
495 goto lose;
498 if (pathp == &path[allocated - 1])
499 *--pathp = '/';
501 #ifndef __ASSUME_ATFCTS
502 if (dotlist != dots)
503 free ((__ptr_t) dotlist);
504 #endif
506 size_t used = path + allocated - pathp;
507 memmove (path, pathp, used);
509 if (size == 0)
510 /* Ensure that the buffer is only as large as necessary. */
511 buf = realloc (path, used);
513 if (buf == NULL)
514 /* Either buf was NULL all along, or `realloc' failed but
515 we still have the original string. */
516 buf = path;
518 /* Restore errno on successful return. */
519 __set_errno (prev_errno);
521 return buf;
523 lose:;
524 int save_errno = errno;
525 #ifndef __ASSUME_ATFCTS
526 if (dotlist != dots)
527 free ((__ptr_t) dotlist);
528 #endif
529 if (dirstream != NULL)
530 __closedir (dirstream);
531 if (fd_needs_closing)
532 close_not_cancel_no_status (fd);
533 #ifndef NO_ALLOCATION
534 if (buf == NULL)
535 free (path);
536 #endif
537 __set_errno (save_errno);
538 return NULL;
541 #if defined _LIBC && !defined __getcwd
542 weak_alias (__getcwd, getcwd)
543 #endif