Blame sysdeps/posix/getcwd.c

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