From 2331f968556c6b5d8617a3d420e5cf9a2b61b4f5 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 1 Mar 2007 00:07:34 +0000 Subject: [PATCH] Add the xreadlink module from GNU gettext (based on code from Jim Meyering). --- ChangeLog | 7 +++ MODULES.html.sh | 1 + lib/xreadlink.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/xreadlink.h | 15 +++++- modules/xreadlink | 26 +++++++++++ 5 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 lib/xreadlink.c create mode 100644 modules/xreadlink diff --git a/ChangeLog b/ChangeLog index 26d7289e4..2e3930a3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2007-02-28 Bruno Haible + * MODULES.html.sh (File system functions): Add xreadlink-with-size. + + * modules/xreadlink: New file, from GNU gettext with modifications. + * lib/xreadlink.c: New file, from GNU gettext. + * lib/xreadlink.h: Add comments. + (xreadlink): New declaration. + * modules/xreadlink-with-size: Renamed from modules/xreadlink. (Files): Remove m4/xreadlink.m4. Replace lib/xreadlink.c with lib/xreadlink-with-size.c. diff --git a/MODULES.html.sh b/MODULES.html.sh index e187e3e18..b7001db70 100755 --- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -2074,6 +2074,7 @@ func_all_modules () func_module utimens func_module xgetcwd func_module xreadlink + func_module xreadlink-with-size func_end_table element="File descriptor based Input/Output" diff --git a/lib/xreadlink.c b/lib/xreadlink.c new file mode 100644 index 000000000..51714cd57 --- /dev/null +++ b/lib/xreadlink.c @@ -0,0 +1,133 @@ +/* xreadlink.c -- readlink wrapper to return the link name in malloc'd storage + + Copyright (C) 2001, 2003-2007 Free Software Foundation, Inc. + + 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 2, 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; see the file COPYING. + If not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Jim Meyering + and Bruno Haible . */ + +#include + +/* Specification. */ +#include "xreadlink.h" + +#include +#include +#include +#include +#include +#include +#if HAVE_UNISTD_H +# include +#endif + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif + +#ifdef NO_XMALLOC +# define xmalloc malloc +#else +# include "xalloc.h" +#endif + +/* Call readlink to get the symbolic link value of FILENAME. + Return a pointer to that NUL-terminated string in malloc'd storage. + If readlink fails, return NULL (caller may use errno to diagnose). + If realloc fails, or if the link value is longer than SIZE_MAX :-), + give a diagnostic and exit. */ + +char * +xreadlink (char const *filename) +{ + /* The initial buffer size for the link value. A power of 2 + detects arithmetic overflow earlier, but is not required. */ +#define INITIAL_BUF_SIZE 1024 + + /* Allocate the initial buffer on the stack. This way, in the common + case of a symlink of small size, we get away with a single small malloc() + instead of a big malloc() followed by a shrinking realloc(). */ + char initial_buf[INITIAL_BUF_SIZE]; + + char *buffer = initial_buf; + size_t buf_size = sizeof (initial_buf); + + while (1) + { + /* Attempt to read the link into the current buffer. */ + ssize_t link_length = readlink (filename, buffer, buf_size); + + /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1 + with errno == ERANGE if the buffer is too small. */ + if (link_length < 0 && errno != ERANGE) + { + if (buffer != initial_buf) + { + int saved_errno = errno; + free (buffer); + errno = saved_errno; + } + return NULL; + } + + if ((size_t) link_length < buf_size) + { + buffer[link_length++] = '\0'; + + /* Return it in a chunk of memory as small as possible. */ + if (buffer == initial_buf) + { + buffer = (char *) xmalloc (link_length); +#ifdef NO_XMALLOC + if (buffer == NULL) + return NULL; +#endif + memcpy (buffer, initial_buf, link_length); + } + else + { + /* Shrink buffer before returning it. */ + if ((size_t) link_length < buf_size) + { + char *smaller_buffer = (char *) realloc (buffer, link_length); + + if (smaller_buffer != NULL) + buffer = smaller_buffer; + } + } + return buffer; + } + + if (buffer != initial_buf) + free (buffer); + buf_size *= 2; + if (SSIZE_MAX < buf_size || (SIZE_MAX / 2 < SSIZE_MAX && buf_size == 0)) +#ifdef NO_XMALLOC + return NULL; +#else + xalloc_die (); +#endif + buffer = (char *) xmalloc (buf_size); +#ifdef NO_XMALLOC + if (buffer == NULL) + return NULL; +#endif + } +} diff --git a/lib/xreadlink.h b/lib/xreadlink.h index 401f98058..6d93fe6c3 100644 --- a/lib/xreadlink.h +++ b/lib/xreadlink.h @@ -1,4 +1,4 @@ -/* readlink wrapper to return the link name in malloc'd storage +/* Reading symbolic links without size limitation. Copyright (C) 2001, 2003, 2004, 2007 Free Software Foundation, Inc. @@ -20,4 +20,15 @@ /* Written by Jim Meyering */ #include -char *xreadlink_with_size (char const *, size_t); + +/* Call readlink to get the symbolic link value of FILENAME. + Return a pointer to that NUL-terminated string in malloc'd storage. + If readlink fails, return NULL and set errno. */ +extern char *xreadlink (char const *filename); + +/* Call readlink to get the symbolic link value of FILENAME. + SIZE_HINT is a hint as to how long the link is expected to be; + typically it is taken from st_size. It need not be correct. + Return a pointer to that NUL-terminated string in malloc'd storage. + If readlink fails, return NULL and set errno. */ +extern char *xreadlink_with_size (char const *filename, size_t size_hint); diff --git a/modules/xreadlink b/modules/xreadlink new file mode 100644 index 000000000..29f0959df --- /dev/null +++ b/modules/xreadlink @@ -0,0 +1,26 @@ +Description: +Reading symbolic links without size limitation. + +Files: +lib/xreadlink.h +lib/xreadlink.c + +Depends-on: +readlink +ssize_t +xalloc + +configure.ac: + +Makefile.am: +lib_SOURCES += xreadlink.c + +Include: +"xreadlink.h" + +License: +GPL + +Maintainer: +Bruno Haible + -- 2.11.0