[Top][All Lists]
[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
[PATCHv2 2/9] getcwd-lgpl: new module,
Eric Blake <=
[PATCHv2 5/9] dirent-safer: drop unused link dependency, Eric Blake, 2011/04/26
[PATCHv2 6/9] tests: reduce dependencies, Eric Blake, 2011/04/26
[PATCHv2 3/9] getcwd: enhance tests, Eric Blake, 2011/04/26
[PATCHv2 7/9] linkat, renameat: add missing dependency, Eric Blake, 2011/04/26