From 043be67acb94a724f96e3b18c3a09aefffd463af Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 26 Apr 2011 14:40:58 -0600 Subject: [PATCH] getcwd-lgpl: new module 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. * lib/getcwd-lgpl.c: New file. * doc/posix-functions/getcwd.texi (getcwd): Document it. * MODULES.html.sh (lacking POSIX:2008): Likewise. * modules/getcwd (configure.ac): Set C witness. * m4/getcwd.m4 (gl_FUNC_GETCWD_LGPL): New macro. Signed-off-by: Eric Blake --- ChangeLog | 8 +++ MODULES.html.sh | 1 + doc/posix-functions/getcwd.texi | 13 ++-- lib/getcwd-lgpl.c | 118 ++++++++++++++++++++++++++++++++ m4/getcwd.m4 | 29 +++++++- modules/getcwd | 1 + modules/getcwd-lgpl | 25 +++++++ 7 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 4760fedcb1..b3d036ec35 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2011-04-27 Eric Blake + 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. + * modules/getcwd (configure.ac): Set C witness. + * m4/getcwd.m4 (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 8d32a21258..a584c4ece5 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 4d00af8955..a8dba967ec 100644 --- a/doc/posix-functions/getcwd.texi +++ b/doc/posix-functions/getcwd.texi @@ -4,15 +4,20 @@ 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 +@code{getcwd-lgpl}: @itemize @item -This function is missing on some older platforms. -@item On glibc platforms, @code{getcwd (NULL, n)} allocates memory for the result. On other platforms, this call is not allowed. +@end itemize + +Portability problems fixed by Gnulib module @code{getcwd}: +@itemize +@item +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 0000000000..a5596f8869 --- /dev/null +++ b/lib/getcwd-lgpl.c @@ -0,0 +1,118 @@ +/* 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 . */ + +#include + +/* Specification */ +#include + +#include +#include + +#if GNULIB_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; + } + buf = ptr; + 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 0c7e20c2e0..55f937222b 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,29 @@ 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,13 +96,14 @@ 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, overrides LGPL 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]) diff --git a/modules/getcwd b/modules/getcwd index 108f14b28a..27ec25a458 100644 --- a/modules/getcwd +++ b/modules/getcwd @@ -20,6 +20,7 @@ strdup-posix configure.ac: gl_FUNC_GETCWD +gl_MODULE_INDICATOR([getcwd]) gl_UNISTD_MODULE_INDICATOR([getcwd]) Makefile.am: diff --git a/modules/getcwd-lgpl b/modules/getcwd-lgpl new file mode 100644 index 0000000000..1b9c87bf50 --- /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: + + +License: +LGPLv2+ + +Maintainer: +Eric Blake -- 2.30.2