Back to index

glibc  2.9
Defines | Functions | Variables
getcwd.c File Reference
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include <strings.h>
#include <sys/param.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define __set_errno(val)   errno = (val)
#define NULL   0
#define dirent   direct
#define D_NAMLEN(d)   ((d)->d_namlen)
#define HAVE_D_NAMLEN
#define memcpy(d, s, n)   bcopy((s), (d), (n))
#define memmove   memcpy
#define MAX(a, b)   ((a) < (b) ? (b) : (a))
#define __alloca   alloca
#define PATH_MAX   1024
#define size_t   unsigned int
#define const
#define __lstat   stat
#define __getcwd   getcwd
#define GETCWD_RETURN_TYPE   char *

Functions

int bcmp ()
void bzero ()
void bcopy ()
char * malloc ()
char * realloc ()
void free ()
char * alloca ()
GETCWD_RETURN_TYPE __getcwd (char *buf, size_t size)

Variables

int errno

Define Documentation

#define __alloca   alloca

Definition at line 164 of file getcwd.c.

#define __getcwd   getcwd

Definition at line 196 of file getcwd.c.

#define __lstat   stat

Definition at line 192 of file getcwd.c.

#define __set_errno (   val)    errno = (val)

Definition at line 49 of file getcwd.c.

#define const

Definition at line 188 of file getcwd.c.

#define D_NAMLEN (   d)    ((d)->d_namlen)

Definition at line 73 of file getcwd.c.

#define dirent   direct

Definition at line 72 of file getcwd.c.

#define GETCWD_RETURN_TYPE   char *

Definition at line 200 of file getcwd.c.

#define HAVE_D_NAMLEN

Definition at line 74 of file getcwd.c.

#define MAX (   a,
  b 
)    ((a) < (b) ? (b) : (a))

Definition at line 139 of file getcwd.c.

#define memcpy (   d,
  s,
  n 
)    bcopy((s), (d), (n))

Definition at line 134 of file getcwd.c.

#define memmove   memcpy

Definition at line 135 of file getcwd.c.

#define NULL   0

Definition at line 53 of file getcwd.c.

#define PATH_MAX   1024

Definition at line 178 of file getcwd.c.

#define size_t   unsigned int

Definition at line 184 of file getcwd.c.


Function Documentation

GETCWD_RETURN_TYPE __getcwd ( char *  buf,
size_t  size 
)

Definition at line 210 of file getcwd.c.

{
  static const char dots[]
    = "../../../../../../../../../../../../../../../../../../../../../../../\
../../../../../../../../../../../../../../../../../../../../../../../../../../\
../../../../../../../../../../../../../../../../../../../../../../../../../..";
  const char *dotp = &dots[sizeof (dots)];
  const char *dotlist = dots;
  size_t dotsize = sizeof (dots) - 1;
  dev_t rootdev, thisdev;
  ino_t rootino, thisino;
  char *path;
  register char *pathp;
  struct stat st;
  int prev_errno = errno;
  size_t allocated = size;

  if (size == 0)
    {
      if (buf != NULL)
       {
         __set_errno (EINVAL);
         return NULL;
       }

      allocated = PATH_MAX + 1;
    }

  if (buf != NULL)
    path = buf;
  else
    {
      path = malloc (allocated);
      if (path == NULL)
       return NULL;
    }

  pathp = path + allocated;
  *--pathp = '\0';

  if (__lstat (".", &st) < 0)
    goto lose2;
  thisdev = st.st_dev;
  thisino = st.st_ino;

  if (__lstat ("/", &st) < 0)
    goto lose2;
  rootdev = st.st_dev;
  rootino = st.st_ino;

  while (!(thisdev == rootdev && thisino == rootino))
    {
      register DIR *dirstream;
      struct dirent *d;
      dev_t dotdev;
      ino_t dotino;
      char mount_point;

      /* Look at the parent directory.  */
      if (dotp == dotlist)
       {
         /* 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;
       }

      dotp -= 3;

      /* Figure out if this directory is a mount point.  */
      if (__lstat (dotp, &st) < 0)
       goto lose;
      dotdev = st.st_dev;
      dotino = st.st_ino;
      mount_point = dotdev != thisdev;

      /* Search for the last directory.  */
      dirstream = __opendir (dotp);
      if (dirstream == NULL)
       goto lose;
      /* Clear errno to distinguish EOF from error if readdir returns
        NULL.  */
      __set_errno (0);
      while ((d = __readdir (dirstream)) != NULL)
       {
         if (d->d_name[0] == '.' &&
             (d->d_name[1] == '\0' ||
              (d->d_name[1] == '.' && d->d_name[2] == '\0')))
           continue;
         if (mount_point || (ino_t) d->d_ino == thisino)
           {
             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 stat() 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 (__lstat (name, &st) >= 0
                && st.st_dev == thisdev && st.st_ino == thisino)
              break;
           }
       }
      if (d == NULL)
       {
         int save = errno;
         (void) __closedir (dirstream);
         if (save == 0)
           /* EOF on dirstream, which means that the current directory
              has been removed.  */
           save = ENOENT;
         __set_errno (save);
         goto lose;
       }
      else
       {
         size_t namlen = _D_EXACT_NAMLEN (d);

         if ((size_t) (pathp - path) <= namlen)
           {
             if (size != 0)
              {
                (void) __closedir (dirstream);
                __set_errno (ERANGE);
                goto lose;
              }
             else
              {
                char *tmp;
                size_t oldsize = allocated;

                allocated = 2 * MAX (allocated, namlen);
                tmp = realloc (path, allocated);
                if (tmp == NULL)
                  {
                    (void) __closedir (dirstream);
                    __set_errno (ENOMEM);/* closedir might have changed it.*/
                    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;
              }
           }
         pathp -= namlen;
         (void) memcpy (pathp, d->d_name, namlen);
         *--pathp = '/';
         (void) __closedir (dirstream);
       }

      thisdev = dotdev;
      thisino = dotino;
    }

  if (pathp == &path[allocated - 1])
    *--pathp = '/';

  if (dotlist != dots)
    free ((__ptr_t) dotlist);

  memmove (path, pathp, path + allocated - pathp);

  /* Restore errno on successful return.  */
  __set_errno (prev_errno);

  return path;

 lose:
  if (dotlist != dots)
    free ((__ptr_t) dotlist);
 lose2:
  if (buf == NULL)
    free (path);
  return NULL;
}

Here is the call graph for this function:

char* alloca ( )
int bcmp ( )
void bcopy ( )
void bzero ( )
void free ( )
char* malloc ( )
char * realloc ( )

Variable Documentation

Definition at line 22 of file sysdep.c.