aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/posix/getcwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/posix/getcwd.c')
-rw-r--r--sysdeps/posix/getcwd.c535
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