Back to index

glibc  2.9
Defines | Functions | Variables
getcwd.c File Reference
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <sysdep.h>
#include <sys/syscall.h>
#include <bp-checks.h>
#include <kernel-features.h>
#include <sysdeps/posix/getcwd.c>

Go to the source code of this file.

Defines

#define no_syscall_getcwd   1
#define GETCWD_RETURN_TYPE   static char * internal_function
#define __getcwd   generic_getcwd

Functions

static char * generic_getcwd (char *buf, size_t size) internal_function
char * __getcwd (char *buf, size_t size)

Variables

static int have_new_dcache = 1

Define Documentation

#define __getcwd   generic_getcwd
#define GETCWD_RETURN_TYPE   static char * internal_function
#define no_syscall_getcwd   1

Definition at line 65 of file getcwd.c.


Function Documentation

char* __getcwd ( char *  buf,
size_t  size 
)

Definition at line 71 of file getcwd.c.

{
  char *path;
  int n;
  char *result;

  if (no_syscall_getcwd && !have_new_dcache)
    return generic_getcwd (buf, size);

#ifndef NO_ALLOCATION
  size_t alloc_size = size;
  if (size == 0)
    {
      if (buf != NULL)
       {
         __set_errno (EINVAL);
         return NULL;
       }

      alloc_size = MAX (PATH_MAX, __getpagesize ());
    }

  if (buf == NULL)
    {
      path = malloc (alloc_size);
      if (path == NULL)
       return NULL;
    }
  else
#else
# define alloc_size size
#endif
    path = buf;

#if defined __NR_getcwd || __LINUX_GETCWD_SYSCALL > 0
  if (!no_syscall_getcwd)
    {
      int retval;

      retval = INLINE_SYSCALL (getcwd, 2, CHECK_STRING (path), alloc_size);
      if (retval >= 0)
       {
# ifndef NO_ALLOCATION
         if (buf == NULL && size == 0)
           /* Ensure that the buffer is only as large as necessary.  */
           buf = realloc (path, (size_t) retval);

         if (buf == NULL)
           /* Either buf was NULL all along, or `realloc' failed but
              we still have the original string.  */
           buf = path;
# endif

         return buf;
       }

# if __ASSUME_GETCWD_SYSCALL
      /* It should never happen that the `getcwd' syscall failed because
        the buffer is too small if we allocated the buffer ourselves
        large enough.  */
      assert (errno != ERANGE || buf != NULL || size != 0);

#  ifndef NO_ALLOCATION
      if (buf == NULL)
       free (path);
#  endif

      return NULL;
# else
      if (errno == ENOSYS)
       {
          no_syscall_getcwd = 1;
          have_new_dcache = 1;     /* Now we will try the /proc method.  */
       }
      else if (errno != ERANGE || buf != NULL)
       {
#  ifndef NO_ALLOCATION
         if (buf == NULL)
           free (path);
#  endif
         return NULL;
       }
# endif
    }
#endif

  n = __readlink ("/proc/self/cwd", path, alloc_size - 1);
  if (n != -1)
    {
      if (path[0] == '/')
       {
         if ((size_t) n >= alloc_size - 1)
           {
#ifndef NO_ALLOCATION
             if (buf == NULL)
              free (path);
#endif
             return NULL;
           }

         path[n] = '\0';
#ifndef NO_ALLOCATION
         if (buf == NULL && size == 0)
           /* Ensure that the buffer is only as large as necessary.  */
           buf = realloc (path, (size_t) n + 1);
         if (buf == NULL)
           /* Either buf was NULL all along, or `realloc' failed but
              we still have the original string.  */
           buf = path;
#endif

         return buf;
       }
#ifndef have_new_dcache
      else
       have_new_dcache = 0;
#endif
    }

#if __ASSUME_GETCWD_SYSCALL == 0
  /* Set to have_new_dcache only if error indicates that proc doesn't
     exist.  */
  if (errno != EACCES && errno != ENAMETOOLONG)
    have_new_dcache = 0;
#endif

#ifndef NO_ALLOCATION
  /* Don't put restrictions on the length of the path unless the user does.  */
  if (size == 0)
    {
      free (path);
      path = NULL;
    }
#endif

  result = generic_getcwd (path, size);

#ifndef NO_ALLOCATION
  if (result == NULL && buf == NULL && size != 0)
    free (path);
#endif

  return result;
}

Here is the call graph for this function:

static char* generic_getcwd ( char *  buf,
size_t  size 
) [static]

Here is the caller graph for this function:


Variable Documentation

int have_new_dcache = 1 [static]

Definition at line 66 of file getcwd.c.