bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCHv2 2/9] getcwd-lgpl: new module


From: Eric Blake
Subject: [PATCHv2 2/9] getcwd-lgpl: new module
Date: Tue, 26 Apr 2011 17:35:24 -0600

For programs that aren't worried about being invoked from an
current working directory longer than PATH_MAX (perhaps because
the program always does chdir to a sane location first), the
getcwd module is overkill, given that all modern portability
targets have a getcwd that works on short names.

* modules/getcwd-lgpl: New module.
* doc/posix-functions/getcwd.texi (getcwd): Document it.
* MODULES.html.sh (lacking POSIX:2008): Likewise.
* m4/getcwd.m4 (gl_PREREQ_GETCWD): Define extra witness.
(gl_FUNC_GETCWD_LGPL): New macro.
* lib/getcwd.c (rpl_getcwd): Provide alternate LGPL
implementation.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog                       |    8 +++
 MODULES.html.sh                 |    1 +
 doc/posix-functions/getcwd.texi |   13 +++-
 lib/getcwd-lgpl.c               |  117 +++++++++++++++++++++++++++++++++++++++
 m4/getcwd.m4                    |   31 ++++++++++-
 modules/getcwd-lgpl             |   25 ++++++++
 6 files changed, 189 insertions(+), 6 deletions(-)
 create mode 100644 lib/getcwd-lgpl.c
 create mode 100644 modules/getcwd-lgpl

diff --git a/ChangeLog b/ChangeLog
index 4c4b944..40f863a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2011-04-26  Eric Blake  <address@hidden>

+       getcwd-lgpl: new module
+       * modules/getcwd-lgpl: New module.
+       * lib/getcwd-lgpl.c: New file.
+       * doc/posix-functions/getcwd.texi (getcwd): Document it.
+       * MODULES.html.sh (lacking POSIX:2008): Likewise.
+       * m4/getcwd.m4 (gl_PREREQ_GETCWD): Define extra witness.
+       (gl_FUNC_GETCWD_LGPL): New macro.
+
        getcwd: tweak comments
        * m4/getcwd-abort-bug.m4: Fix comments.
        * m4/getcwd-path-max.m4: Likewise.
diff --git a/MODULES.html.sh b/MODULES.html.sh
index 8d32a21..a584c4e 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -2353,6 +2353,7 @@ func_all_modules ()
   func_module futimens
   func_module getaddrinfo
   func_module getcwd
+  func_module getcwd-lgpl
   func_module getgroups
   func_module gethostname
   func_module getlogin
diff --git a/doc/posix-functions/getcwd.texi b/doc/posix-functions/getcwd.texi
index 4d00af8..a8dba96 100644
--- a/doc/posix-functions/getcwd.texi
+++ b/doc/posix-functions/getcwd.texi
@@ -4,15 +4,20 @@ getcwd

 POSIX specification:@* 
@url{http://www.opengroup.org/onlinepubs/9699919799/functions/getcwd.html}

-Gnulib module: getcwd
+Gnulib module: getcwd or getcwd-lgpl

-Portability problems fixed by Gnulib:
+Portability problems fixed by either Gnulib module @code{getcwd} or
address@hidden:
 @itemize
 @item
-This function is missing on some older platforms.
address@hidden
 On glibc platforms, @code{getcwd (NULL, n)} allocates memory for the result.
 On other platforms, this call is not allowed.
address@hidden itemize
+
+Portability problems fixed by Gnulib module @code{getcwd}:
address@hidden
address@hidden
+This function is missing on some older platforms.
 @item
 This function does not handle long file names (greater than @code{PATH_MAX})
 correctly on some platforms.
diff --git a/lib/getcwd-lgpl.c b/lib/getcwd-lgpl.c
new file mode 100644
index 0000000..1fcf9f3
--- /dev/null
+++ b/lib/getcwd-lgpl.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+   This file is part of gnulib.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification */
+#include <unistd.h>
+
+#include <errno.h>
+#include <string.h>
+
+#if USE_GPL_GETCWD
+/* Favor GPL getcwd.c if both getcwd and getcwd-lgpl modules are in use.  */
+typedef int dummy;
+#else
+
+/* 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
+   (perhaps because the absolute name was longer than PATH_MAX, or
+   because of missing read/search permissions on parent directories)
+   or SIZE was too small.  If successful, returns BUF.  If BUF is
+   NULL, an array is allocated with `malloc'; the array is SIZE bytes
+   long, unless SIZE == 0, in which case it is as big as
+   necessary.  */
+
+# undef getcwd
+char *
+rpl_getcwd (char *buf, size_t size)
+{
+  char *ptr;
+  char *result;
+
+  /* Handle single size operations.  */
+  if (buf)
+    return getcwd (buf, size);
+
+  if (size)
+    {
+      buf = malloc (size);
+      if (!buf)
+        {
+          errno = ENOMEM;
+          return -1;
+        }
+      result = getcwd (buf, size);
+      if (!result)
+        {
+          int saved_errno = errno;
+          free (buf);
+          errno = saved_errno;
+        }
+      return result;
+    }
+
+  /* Flexible sizing requested.  Avoid over-allocation for the common
+     case of a name that fits within a 4k page, minus some space for
+     local variables, to be sure we don't skip over a guard page.  */
+  {
+    char tmp[4032];
+    size = sizeof tmp;
+    ptr = getcwd (tmp, size);
+    if (ptr)
+      {
+        result = strdup (ptr);
+        if (!result)
+          errno = ENOMEM;
+        return result;
+      }
+    if (errno != ERANGE)
+      return NULL;
+  }
+
+  /* My what a large directory name we have.  */
+  do
+    {
+      size <<= 1;
+      ptr = realloc (buf, size);
+      if (ptr == NULL)
+        {
+          free (buf);
+          errno = ENOMEM;
+          return NULL;
+        }
+      result = getcwd (buf, size);
+    }
+  while (!result && errno == ERANGE);
+
+  if (!result)
+    {
+      int saved_errno = errno;
+      free (buf);
+      errno = saved_errno;
+    }
+  else
+    {
+      /* Trim to fit, if possible.  */
+      result = realloc (buf, strlen (buf) + 1);
+      if (!result)
+        result = buf;
+    }
+  return result;
+}
+
+#endif
diff --git a/m4/getcwd.m4 b/m4/getcwd.m4
index 0c7e20c..8cbfbe2 100644
--- a/m4/getcwd.m4
+++ b/m4/getcwd.m4
@@ -6,10 +6,11 @@
 # with or without modifications, as long as this notice is preserved.

 # Written by Paul Eggert.
-# serial 4
+# serial 5

 AC_DEFUN([gl_FUNC_GETCWD_NULL],
   [
+   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
    AC_CACHE_CHECK([whether getcwd (NULL, 0) allocates memory for result],
      [gl_cv_func_getcwd_null],
      [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
@@ -52,6 +53,28 @@ AC_DEFUN([gl_FUNC_GETCWD_NULL],
         ]])])
 ])

+
+dnl Guarantee that getcwd will malloc with a NULL first argument.  Assumes
+dnl that either the system getcwd is robust, or that calling code is okay
+dnl with spurious failures when run from a directory with an absolute name
+dnl larger than 4k bytes.
+dnl
+dnl Assumes that getcwd exists; if you are worried about obsolete
+dnl platforms that lacked getcwd(), then you need to use the GPL module.
+AC_DEFUN([gl_FUNC_GETCWD_LGPL],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([gl_FUNC_GETCWD_NULL])
+
+  case $gl_cv_func_getcwd_null in
+  *yes) ;;
+  *)
+    dnl Minimal replacement
+    REPLACE_GETCWD=1
+    AC_LIBOBJ([getcwd-lgpl])
+  esac
+])
+
 dnl Check for all known getcwd bugs; useful for a program likely to be
 dnl executed from an arbitrary location.
 AC_DEFUN([gl_FUNC_GETCWD],
@@ -72,16 +95,20 @@ AC_DEFUN([gl_FUNC_GETCWD],
   case $gl_cv_func_getcwd_null,$gl_cv_func_getcwd_path_max,$gl_abort_bug in
   *yes,yes,no) ;;
   *)
+    dnl Full replacement.
     REPLACE_GETCWD=1
     AC_LIBOBJ([getcwd])
     gl_PREREQ_GETCWD;;
   esac
 ])

-# Prerequisites of lib/getcwd.c.
+# Prerequisites of lib/getcwd.c, when full replacement is in effect.
 AC_DEFUN([gl_PREREQ_GETCWD],
 [
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
   AC_REQUIRE([gl_CHECK_TYPE_STRUCT_DIRENT_D_INO])
+  AC_DEFINE([USE_GPL_GETCWD], [1],
+      [Define to 1 if GPL code should be used to attempt to work around
+       native getcwd failures.])
   :
 ])
diff --git a/modules/getcwd-lgpl b/modules/getcwd-lgpl
new file mode 100644
index 0000000..ffb4be5
--- /dev/null
+++ b/modules/getcwd-lgpl
@@ -0,0 +1,25 @@
+Description:
+Ensure getcwd(NULL, 0) returns a buffer allocated by malloc().
+
+Files:
+lib/getcwd-lgpl.c
+m4/getcwd.m4
+
+Depends-on:
+strdup
+unistd
+
+configure.ac:
+gl_FUNC_GETCWD_LGPL
+gl_UNISTD_MODULE_INDICATOR([getcwd])
+
+Makefile.am:
+
+Include:
+<unistd.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+Eric Blake
-- 
1.7.4.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]