Blame lib/getcwd-lgpl.c

Packit 709fb3
/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
Packit 709fb3
   This file is part of gnulib.
Packit 709fb3
Packit 709fb3
   This program is free software: you can redistribute it and/or modify
Packit 709fb3
   it under the terms of the GNU General Public License as published by
Packit 709fb3
   the Free Software Foundation; either version 3 of the License, or
Packit 709fb3
   (at your option) any later version.
Packit 709fb3
Packit 709fb3
   This program is distributed in the hope that it will be useful,
Packit 709fb3
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 709fb3
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 709fb3
   GNU General Public License for more details.
Packit 709fb3
Packit 709fb3
   You should have received a copy of the GNU General Public License
Packit 709fb3
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 709fb3
Packit 709fb3
#include <config.h>
Packit 709fb3
Packit 709fb3
/* Specification */
Packit 709fb3
#include <unistd.h>
Packit 709fb3
Packit 709fb3
#include <errno.h>
Packit 709fb3
#include <stdlib.h>
Packit 709fb3
#include <string.h>
Packit 709fb3
Packit 709fb3
#if GNULIB_GETCWD
Packit 709fb3
/* Favor GPL getcwd.c if both getcwd and getcwd-lgpl modules are in use.  */
Packit 709fb3
typedef int dummy;
Packit 709fb3
#else
Packit 709fb3
Packit 709fb3
/* Get the name of the current working directory, and put it in SIZE
Packit 709fb3
   bytes of BUF.  Returns NULL if the directory couldn't be determined
Packit 709fb3
   (perhaps because the absolute name was longer than PATH_MAX, or
Packit 709fb3
   because of missing read/search permissions on parent directories)
Packit 709fb3
   or SIZE was too small.  If successful, returns BUF.  If BUF is
Packit 709fb3
   NULL, an array is allocated with 'malloc'; the array is SIZE bytes
Packit 709fb3
   long, unless SIZE == 0, in which case it is as big as
Packit 709fb3
   necessary.  */
Packit 709fb3
Packit 709fb3
# undef getcwd
Packit 709fb3
char *
Packit 709fb3
rpl_getcwd (char *buf, size_t size)
Packit 709fb3
{
Packit 709fb3
  char *ptr;
Packit 709fb3
  char *result;
Packit 709fb3
Packit 709fb3
  /* Handle single size operations.  */
Packit 709fb3
  if (buf)
Packit 709fb3
    {
Packit 709fb3
      if (!size)
Packit 709fb3
        {
Packit 709fb3
          errno = EINVAL;
Packit 709fb3
          return NULL;
Packit 709fb3
        }
Packit 709fb3
      return getcwd (buf, size);
Packit 709fb3
    }
Packit 709fb3
Packit 709fb3
  if (size)
Packit 709fb3
    {
Packit 709fb3
      buf = malloc (size);
Packit 709fb3
      if (!buf)
Packit 709fb3
        {
Packit 709fb3
          errno = ENOMEM;
Packit 709fb3
          return NULL;
Packit 709fb3
        }
Packit 709fb3
      result = getcwd (buf, size);
Packit 709fb3
      if (!result)
Packit 709fb3
        {
Packit 709fb3
          int saved_errno = errno;
Packit 709fb3
          free (buf);
Packit 709fb3
          errno = saved_errno;
Packit 709fb3
        }
Packit 709fb3
      return result;
Packit 709fb3
    }
Packit 709fb3
Packit 709fb3
  /* Flexible sizing requested.  Avoid over-allocation for the common
Packit 709fb3
     case of a name that fits within a 4k page, minus some space for
Packit 709fb3
     local variables, to be sure we don't skip over a guard page.  */
Packit 709fb3
  {
Packit 709fb3
    char tmp[4032];
Packit 709fb3
    size = sizeof tmp;
Packit 709fb3
    ptr = getcwd (tmp, size);
Packit 709fb3
    if (ptr)
Packit 709fb3
      {
Packit 709fb3
        result = strdup (ptr);
Packit 709fb3
        if (!result)
Packit 709fb3
          errno = ENOMEM;
Packit 709fb3
        return result;
Packit 709fb3
      }
Packit 709fb3
    if (errno != ERANGE)
Packit 709fb3
      return NULL;
Packit 709fb3
  }
Packit 709fb3
Packit 709fb3
  /* My what a large directory name we have.  */
Packit 709fb3
  do
Packit 709fb3
    {
Packit 709fb3
      size <<= 1;
Packit 709fb3
      ptr = realloc (buf, size);
Packit 709fb3
      if (ptr == NULL)
Packit 709fb3
        {
Packit 709fb3
          free (buf);
Packit 709fb3
          errno = ENOMEM;
Packit 709fb3
          return NULL;
Packit 709fb3
        }
Packit 709fb3
      buf = ptr;
Packit 709fb3
      result = getcwd (buf, size);
Packit 709fb3
    }
Packit 709fb3
  while (!result && errno == ERANGE);
Packit 709fb3
Packit 709fb3
  if (!result)
Packit 709fb3
    {
Packit 709fb3
      int saved_errno = errno;
Packit 709fb3
      free (buf);
Packit 709fb3
      errno = saved_errno;
Packit 709fb3
    }
Packit 709fb3
  else
Packit 709fb3
    {
Packit 709fb3
      /* Trim to fit, if possible.  */
Packit 709fb3
      result = realloc (buf, strlen (buf) + 1);
Packit 709fb3
      if (!result)
Packit 709fb3
        result = buf;
Packit 709fb3
    }
Packit 709fb3
  return result;
Packit 709fb3
}
Packit 709fb3
Packit 709fb3
#endif