-/* Copyright (C) 1991,92,93,94,95,96,97,98,99,2004 Free Software Foundation,
- Inc.
+/* Copyright (C) 1991,92,93,94,95,96,97,98,99,2004,2005,2006 Free Software
+ Foundation, Inc.
This file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify
with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
+#ifdef HAVE_CONFIG_H
+# include <config.h>
#endif
#if !_LIBC
#include <stdbool.h>
#include <stddef.h>
-#if HAVE_FCNTL_H
-# include <fcntl.h> /* For AT_FDCWD on Solaris 9. */
-#endif
+#include <fcntl.h> /* For AT_FDCWD on Solaris 9. */
#ifndef __set_errno
# define __set_errno(val) (errno = (val))
# define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1)
#endif
-#if HAVE_UNISTD_H || _LIBC
-# include <unistd.h>
-#endif
-
+#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its
+ value exceeds INT_MAX, so its use as an int doesn't conform to the
+ C standard, and GCC and Sun C complain in some cases. */
+#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553
+# undef AT_FDCWD
+# define AT_FDCWD (-3041965)
+#endif
+
#ifdef ENAMETOOLONG
# define is_ENAMETOOLONG(x) ((x) == ENAMETOOLONG)
#else
# define __readdir readdir
#endif
\f
-/* Get the pathname of the current working directory, and put it in SIZE
+/* Get the name 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,
DIR *dirstream = NULL;
dev_t rootdev, thisdev;
ino_t rootino, thisino;
- char *path;
- register char *pathp;
+ char *dir;
+ register char *dirp;
struct stat st;
size_t allocated = size;
size_t used;
So trust the system getcwd's results unless they look
suspicious. */
# undef getcwd
- path = getcwd (buf, size);
- if (path || (errno != ERANGE && !is_ENAMETOOLONG (errno) && errno != ENOENT))
- return path;
+ dir = getcwd (buf, size);
+ if (dir || (errno != ERANGE && !is_ENAMETOOLONG (errno) && errno != ENOENT))
+ return dir;
#endif
if (size == 0)
if (buf == NULL)
{
- path = malloc (allocated);
- if (path == NULL)
+ dir = malloc (allocated);
+ if (dir == NULL)
return NULL;
}
else
- path = buf;
+ dir = buf;
- pathp = path + allocated;
- *--pathp = '\0';
+ dirp = dir + allocated;
+ *--dirp = '\0';
if (__lstat (".", &st) < 0)
goto lose;
ino_t dotino;
bool mount_point;
int parent_status;
+ size_t dirroom;
+ size_t namlen;
/* Look at the parent directory. */
#ifdef AT_FDCWD
goto lose;
dotlist[dotlen++] = '/';
#endif
- /* Clear errno to distinguish EOF from error if readdir returns
- NULL. */
- __set_errno (0);
- while ((d = __readdir (dirstream)) != NULL)
+ for (;;)
{
+ /* Clear errno to distinguish EOF from error if readdir returns
+ NULL. */
+ __set_errno (0);
+ d = __readdir (dirstream);
+ if (d == NULL)
+ {
+ if (errno == 0)
+ /* EOF on dirstream, which means that the current directory
+ has been removed. */
+ __set_errno (ENOENT);
+ goto lose;
+ }
if (d->d_name[0] == '.' &&
(d->d_name[1] == '\0' ||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
break;
}
}
- if (d == NULL)
- {
- if (errno == 0)
- /* EOF on dirstream, which means that the current directory
- has been removed. */
- __set_errno (ENOENT);
- goto lose;
- }
- else
- {
- size_t pathroom = pathp - path;
- size_t namlen = _D_EXACT_NAMLEN (d);
- if (pathroom <= namlen)
+ dirroom = dirp - dir;
+ namlen = _D_EXACT_NAMLEN (d);
+
+ if (dirroom <= namlen)
+ {
+ if (size != 0)
{
- if (size != 0)
- {
- __set_errno (ERANGE);
- goto lose;
- }
- else
- {
- char *tmp;
- size_t oldsize = allocated;
+ __set_errno (ERANGE);
+ goto lose;
+ }
+ else
+ {
+ char *tmp;
+ size_t oldsize = allocated;
- allocated += MAX (allocated, namlen);
- if (allocated < oldsize
- || ! (tmp = realloc (path, allocated)))
- goto memory_exhausted;
+ allocated += MAX (allocated, namlen);
+ if (allocated < oldsize
+ || ! (tmp = realloc (dir, allocated)))
+ goto memory_exhausted;
- /* Move current contents up to the end of the buffer.
- This is guaranteed to be non-overlapping. */
- pathp = memcpy (tmp + allocated - (oldsize - pathroom),
- tmp + pathroom,
- oldsize - pathroom);
- path = tmp;
- }
+ /* Move current contents up to the end of the buffer.
+ This is guaranteed to be non-overlapping. */
+ dirp = memcpy (tmp + allocated - (oldsize - dirroom),
+ tmp + dirroom,
+ oldsize - dirroom);
+ dir = tmp;
}
- pathp -= namlen;
- memcpy (pathp, d->d_name, namlen);
- *--pathp = '/';
}
+ dirp -= namlen;
+ memcpy (dirp, d->d_name, namlen);
+ *--dirp = '/';
thisdev = dotdev;
thisino = dotino;
goto lose;
}
- if (pathp == &path[allocated - 1])
- *--pathp = '/';
+ if (dirp == &dir[allocated - 1])
+ *--dirp = '/';
#ifndef AT_FDCWD
if (dotlist != dots)
free (dotlist);
#endif
- used = path + allocated - pathp;
- memmove (path, pathp, used);
+ used = dir + allocated - dirp;
+ memmove (dir, dirp, used);
if (buf == NULL && size == 0)
/* Ensure that the buffer is only as large as necessary. */
- buf = realloc (path, used);
+ buf = realloc (dir, used);
if (buf == NULL)
/* Either buf was NULL all along, or `realloc' failed but
we still have the original string. */
- buf = path;
+ buf = dir;
return buf;
free (dotlist);
#endif
if (buf == NULL)
- free (path);
+ free (dir);
__set_errno (save);
}
return NULL;