diff options
Diffstat (limited to 'sysdeps/posix/getcwd.c')
-rw-r--r-- | sysdeps/posix/getcwd.c | 535 |
1 files changed, 0 insertions, 535 deletions
diff --git a/sysdeps/posix/getcwd.c b/sysdeps/posix/getcwd.c deleted file mode 100644 index eb1706aa5c..0000000000 --- a/sysdeps/posix/getcwd.c +++ /dev/null @@ -1,535 +0,0 @@ -/* Copyright (C) 1991-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -/* Wants: - AC_STDC_HEADERS - AC_DIR_HEADER - AC_UNISTD_H - AC_MEMORY_H - AC_CONST - AC_ALLOCA - */ - -/* AIX requires this to be the first thing in the file. */ -#if defined _AIX && !defined __GNUC__ - #pragma alloca -#endif - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <errno.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> - -#ifdef STDC_HEADERS -# include <stddef.h> -#endif - -#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS -extern int errno; -#endif -#ifndef __set_errno -# define __set_errno(val) errno = (val) -#endif - -#ifndef NULL -# define NULL 0 -#endif - -#if defined USGr3 && !defined DIRENT -# define DIRENT -#endif /* USGr3 */ -#if defined Xenix && !defined SYSNDIR -# define SYSNDIR -#endif /* Xenix */ - -#if defined POSIX || defined DIRENT || defined __GNU_LIBRARY__ -# include <dirent.h> -# ifndef __GNU_LIBRARY__ -# define D_NAMLEN(d) strlen((d)->d_name) -# else -# define HAVE_D_NAMLEN -# define D_NAMLEN(d) ((d)->d_namlen) -# endif -#else /* not POSIX or DIRENT */ -# define dirent direct -# define D_NAMLEN(d) ((d)->d_namlen) -# define HAVE_D_NAMLEN -# if defined USG && !defined sgi -# if defined SYSNDIR -# include <sys/ndir.h> -# else /* Not SYSNDIR */ -# include "ndir.h" -# endif /* SYSNDIR */ -# else /* not USG */ -# include <sys/dir.h> -# endif /* USG */ -#endif /* POSIX or DIRENT or __GNU_LIBRARY__ */ - -#if defined HAVE_UNISTD_H || defined __GNU_LIBRARY__ -# include <unistd.h> -#endif - -#if defined STDC_HEADERS || defined __GNU_LIBRARY__ || defined POSIX -# include <stdlib.h> -# include <string.h> -# define ANSI_STRING -#else /* No standard headers. */ - -# ifdef USG - -# include <string.h> -# ifdef NEED_MEMORY_H -# include <memory.h> -# endif -# define ANSI_STRING - -# else /* Not USG. */ - -# ifdef NeXT - -# include <string.h> - -# else /* Not NeXT. */ - -# include <strings.h> - -# ifndef bcmp -extern int bcmp (); -# endif -# ifndef bzero -extern void bzero (); -# endif -# ifndef bcopy -extern void bcopy (); -# endif - -# endif /* NeXT. */ - -# endif /* USG. */ - -extern char *malloc (), *realloc (); -extern void free (); - -#endif /* Standard headers. */ - -#ifndef ANSI_STRING -# define memcpy(d, s, n) bcopy((s), (d), (n)) -# define memmove memcpy -#endif /* Not ANSI_STRING. */ - -#ifndef MAX -# define MAX(a, b) ((a) < (b) ? (b) : (a)) -#endif - -#ifdef _LIBC -# ifndef mempcpy -# define mempcpy __mempcpy -# endif -# define HAVE_MEMPCPY 1 -#endif - -#if !defined __alloca && !defined __GNU_LIBRARY__ - -# ifdef __GNUC__ -# undef alloca -# define alloca(n) __builtin_alloca (n) -# else /* Not GCC. */ -# if defined sparc || defined HAVE_ALLOCA_H -# include <alloca.h> -# else /* Not sparc or HAVE_ALLOCA_H. */ -# ifndef _AIX -extern char *alloca (); -# endif /* Not _AIX. */ -# endif /* sparc or HAVE_ALLOCA_H. */ -# endif /* GCC. */ - -# define __alloca alloca - -#endif - -#if defined HAVE_LIMITS_H || defined STDC_HEADERS || defined __GNU_LIBRARY__ -# include <limits.h> -#else -# include <sys/param.h> -#endif - -#if defined _LIBC -# include <not-cancel.h> -# include <kernel-features.h> -#else -# define openat64_not_cancel_3(dfd, name, mode) openat64 (dfd, name, mode) -# define close_not_cancel_no_status(fd) close (fd) -#endif - -#ifndef PATH_MAX -# ifdef MAXPATHLEN -# define PATH_MAX MAXPATHLEN -# else -# define PATH_MAX 1024 -# endif -#endif - -#if !defined STDC_HEADERS && !defined __GNU_LIBRARY__ -# undef size_t -# define size_t unsigned int -#endif - -#ifndef __GNU_LIBRARY__ -# define __lstat64 stat64 -#endif - -#ifndef _LIBC -# define __rewinddir rewinddir -#endif - -#ifndef _LIBC -# define __getcwd getcwd -#endif - -#ifndef GETCWD_RETURN_TYPE -# define GETCWD_RETURN_TYPE char * -#endif - -#ifdef __ASSUME_ATFCTS -# define __have_atfcts 1 -#elif IS_IN (rtld) -static int __rtld_have_atfcts; -# define __have_atfcts __rtld_have_atfcts -#endif - -/* Get the pathname of the current working directory, and put it in SIZE - bytes of BUF. Returns NULL if the directory couldn't be determined or - SIZE was too small. If successful, returns BUF. In GNU, if BUF is - NULL, an array is allocated with `malloc'; the array is SIZE bytes long, - unless SIZE == 0, in which case it is as big as necessary. */ - -GETCWD_RETURN_TYPE -__getcwd (char *buf, size_t size) -{ -#ifndef __ASSUME_ATFCTS - static const char dots[] - = "../../../../../../../../../../../../../../../../../../../../../../../\ -../../../../../../../../../../../../../../../../../../../../../../../../../../\ -../../../../../../../../../../../../../../../../../../../../../../../../../.."; - const char *dotp = &dots[sizeof (dots)]; - const char *dotlist = dots; - size_t dotsize = sizeof (dots) - 1; -#endif - int prev_errno = errno; - DIR *dirstream = NULL; - bool fd_needs_closing = false; - int fd = AT_FDCWD; - - char *path; -#ifndef NO_ALLOCATION - size_t allocated = size; - if (size == 0) - { - if (buf != NULL) - { - __set_errno (EINVAL); - return NULL; - } - - allocated = PATH_MAX + 1; - } - - if (buf == NULL) - { - path = malloc (allocated); - if (path == NULL) - return NULL; - } - else -#else -# define allocated size -#endif - path = buf; - - char *pathp = path + allocated; - *--pathp = '\0'; - - struct stat64 st; - if (__lstat64 (".", &st) < 0) - goto lose; - dev_t thisdev = st.st_dev; - ino_t thisino = st.st_ino; - - if (__lstat64 ("/", &st) < 0) - goto lose; - dev_t rootdev = st.st_dev; - ino_t rootino = st.st_ino; - - while (!(thisdev == rootdev && thisino == rootino)) - { - if (__have_atfcts >= 0) - fd = openat64_not_cancel_3 (fd, "..", O_RDONLY | O_CLOEXEC); - else - fd = -1; - if (fd >= 0) - { - fd_needs_closing = true; - if (__fstat64 (fd, &st) < 0) - goto lose; - } -#ifndef __ASSUME_ATFCTS - else if (errno == ENOSYS) - { - __have_atfcts = -1; - - /* Look at the parent directory. */ - if (dotp == dotlist) - { -# ifdef NO_ALLOCATION - __set_errno (ENOMEM); - goto lose; -# else - /* My, what a deep directory tree you have, Grandma. */ - char *new; - if (dotlist == dots) - { - new = malloc (dotsize * 2 + 1); - if (new == NULL) - goto lose; -# ifdef HAVE_MEMPCPY - dotp = mempcpy (new, dots, dotsize); -# else - memcpy (new, dots, dotsize); - dotp = &new[dotsize]; -# endif - } - else - { - new = realloc ((__ptr_t) dotlist, dotsize * 2 + 1); - if (new == NULL) - goto lose; - dotp = &new[dotsize]; - } -# ifdef HAVE_MEMPCPY - *((char *) mempcpy ((char *) dotp, new, dotsize)) = '\0'; - dotsize *= 2; -# else - memcpy ((char *) dotp, new, dotsize); - dotsize *= 2; - new[dotsize] = '\0'; -# endif - dotlist = new; -# endif - } - - dotp -= 3; - - /* Figure out if this directory is a mount point. */ - if (__lstat64 (dotp, &st) < 0) - goto lose; - } -#endif - else - goto lose; - - if (dirstream && __closedir (dirstream) != 0) - { - dirstream = NULL; - goto lose; - } - - dev_t dotdev = st.st_dev; - ino_t dotino = st.st_ino; - bool mount_point = dotdev != thisdev; - - /* Search for the last directory. */ - if (__have_atfcts >= 0) - dirstream = __fdopendir (fd); -#ifndef __ASSUME_ATFCTS - else - dirstream = __opendir (dotp); -#endif - if (dirstream == NULL) - goto lose; - fd_needs_closing = false; - - struct dirent *d; - bool use_d_ino = true; - while (1) - { - /* Clear errno to distinguish EOF from error if readdir returns - NULL. */ - __set_errno (0); - d = __readdir (dirstream); - if (d == NULL) - { - if (errno == 0) - { - /* When we've iterated through all directory entries - without finding one with a matching d_ino, rewind the - stream and consider each name again, but this time, using - lstat64. This is necessary in a chroot on at least one - system. */ - if (use_d_ino) - { - use_d_ino = false; - __rewinddir (dirstream); - continue; - } - - /* EOF on dirstream, which means that the current directory - has been removed. */ - __set_errno (ENOENT); - } - goto lose; - } - -#ifdef _DIRENT_HAVE_D_TYPE - if (d->d_type != DT_DIR && d->d_type != DT_UNKNOWN) - continue; -#endif - if (d->d_name[0] == '.' - && (d->d_name[1] == '\0' - || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) - continue; - if (use_d_ino && !mount_point && (ino_t) d->d_ino != thisino) - continue; - - if (__have_atfcts >= 0) - { - /* We don't fail here if we cannot stat64() a directory entry. - This can happen when (network) filesystems fail. If this - entry is in fact the one we are looking for we will find - out soon as we reach the end of the directory without - having found anything. */ - if (__fstatat64 (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) - continue; - } -#ifndef __ASSUME_ATFCTS - else - { - char name[dotlist + dotsize - dotp + 1 + _D_ALLOC_NAMLEN (d)]; -# ifdef HAVE_MEMPCPY - char *tmp = mempcpy (name, dotp, dotlist + dotsize - dotp); - *tmp++ = '/'; - strcpy (tmp, d->d_name); -# else - memcpy (name, dotp, dotlist + dotsize - dotp); - name[dotlist + dotsize - dotp] = '/'; - strcpy (&name[dotlist + dotsize - dotp + 1], d->d_name); -# endif - /* We don't fail here if we cannot stat64() a directory entry. - This can happen when (network) filesystems fail. If this - entry is in fact the one we are looking for we will find - out soon as we reach the end of the directory without - having found anything. */ - if (__lstat64 (name, &st) < 0) - continue; - } -#endif - if (S_ISDIR (st.st_mode) - && st.st_dev == thisdev && st.st_ino == thisino) - break; - } - - size_t namlen = _D_EXACT_NAMLEN (d); - - if ((size_t) (pathp - path) <= namlen) - { -#ifndef NO_ALLOCATION - if (size == 0) - { - size_t oldsize = allocated; - - allocated = 2 * MAX (allocated, namlen); - char *tmp = realloc (path, allocated); - if (tmp == NULL) - goto lose; - - /* Move current contents up to the end of the buffer. - This is guaranteed to be non-overlapping. */ - pathp = memcpy (tmp + allocated - (path + oldsize - pathp), - tmp + (pathp - path), - path + oldsize - pathp); - path = tmp; - } - else -#endif - { - __set_errno (ERANGE); - goto lose; - } - } - pathp -= namlen; - (void) memcpy (pathp, d->d_name, namlen); - *--pathp = '/'; - - thisdev = dotdev; - thisino = dotino; - } - - if (dirstream != NULL && __closedir (dirstream) != 0) - { - dirstream = NULL; - goto lose; - } - - if (pathp == &path[allocated - 1]) - *--pathp = '/'; - -#ifndef __ASSUME_ATFCTS - if (dotlist != dots) - free ((__ptr_t) dotlist); -#endif - - size_t used = path + allocated - pathp; - memmove (path, pathp, used); - - if (size == 0) - /* Ensure that the buffer is only as large as necessary. */ - buf = realloc (path, used); - - if (buf == NULL) - /* Either buf was NULL all along, or `realloc' failed but - we still have the original string. */ - buf = path; - - /* Restore errno on successful return. */ - __set_errno (prev_errno); - - return buf; - - lose:; - int save_errno = errno; -#ifndef __ASSUME_ATFCTS - if (dotlist != dots) - free ((__ptr_t) dotlist); -#endif - if (dirstream != NULL) - __closedir (dirstream); - if (fd_needs_closing) - close_not_cancel_no_status (fd); -#ifndef NO_ALLOCATION - if (buf == NULL) - free (path); -#endif - __set_errno (save_errno); - return NULL; -} - -#if defined _LIBC && !defined __getcwd -weak_alias (__getcwd, getcwd) -#endif |