summaryrefslogtreecommitdiff
path: root/lib/xreadlink.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2004-11-02 20:17:37 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2004-11-02 20:17:37 +0000
commit3bd23802ad65a4379e0c97d736dc6c2ab2d37f1d (patch)
treedc8e1c28f6b4170a0813b14a0163d1fede51cf2a /lib/xreadlink.c
parentea6305f7467ea99eac90af5717e190bdffd664ce (diff)
downloadgnulib-3bd23802ad65a4379e0c97d736dc6c2ab2d37f1d.tar.gz
(MAXSIZE): New macro.
(xreadlink): Use it instead of SSIZE_MAX. Ensure initial buffer size does not exceed MAXSIZE. Avoid cast. As suggested by Mark D. Baushke in <http://lists.gnu.org/archive/html/bug-gnulib/2004-11/msg00009.html>, if readlink fails with buffer size just under MAXSIZE, try again with MAXSIZE.
Diffstat (limited to 'lib/xreadlink.c')
-rw-r--r--lib/xreadlink.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/lib/xreadlink.c b/lib/xreadlink.c
index 2e66c07f24..c38e2d3aad 100644
--- a/lib/xreadlink.c
+++ b/lib/xreadlink.c
@@ -41,6 +41,8 @@
# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
#endif
+#define MAXSIZE (SIZE_MAX < SSIZE_MAX ? SIZE_MAX : SSIZE_MAX)
+
#include "xalloc.h"
/* Call readlink to get the symbolic link value of FILENAME.
@@ -56,14 +58,15 @@ xreadlink (char const *filename, size_t size)
{
/* The initial buffer size for the link value. A power of 2
detects arithmetic overflow earlier, but is not required. */
- size_t buf_size = size + 1;
+ size_t buf_size = size < MAXSIZE ? size + 1 : MAXSIZE;
while (1)
{
char *buffer = xmalloc (buf_size);
- ssize_t link_length = readlink (filename, buffer, buf_size);
+ ssize_t r = readlink (filename, buffer, buf_size);
+ size_t link_length = r;
- if (link_length < 0)
+ if (r < 0)
{
int saved_errno = errno;
free (buffer);
@@ -71,15 +74,18 @@ xreadlink (char const *filename, size_t size)
return NULL;
}
- if ((size_t) link_length < buf_size)
+ if (link_length < buf_size)
{
buffer[link_length] = 0;
return buffer;
}
free (buffer);
- buf_size *= 2;
- if (! (0 < buf_size && buf_size <= SSIZE_MAX))
+ if (buf_size <= MAXSIZE / 2)
+ buf_size *= 2;
+ else if (buf_size < MAXSIZE)
+ buf_size = MAXSIZE;
+ else
xalloc_die ();
}
}