]> Savannah Git Hosting - gnulib.git/commitdiff
areadlink-with-size: avoid realloc when size==0
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 7 Jul 2019 02:25:24 +0000 (19:25 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 7 Jul 2019 02:25:55 +0000 (19:25 -0700)
* lib/areadlink-with-size.c (areadlink_with_size):
* lib/areadlinkat-with-size.c (areadlinkat_with_size):
Reallocate at the end to the actual size, to avoid memory waste,
as suggested by Bruno Haible.  But when the guessed size is zero -
useful when the size is unknown - do the initial small readlink
into the stack, to avoid that realloc in the usual case.

ChangeLog
lib/areadlink-with-size.c
lib/areadlinkat-with-size.c

index 0b061317cf62b479a3c2ff6f1111fae2cbcb85fa..f7e031d9bf31920befd5da6e7a1ecebd02bf55a0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2019-07-06  Paul Eggert  <eggert@cs.ucla.edu>
+
+       areadlink-with-size: avoid realloc when size==0
+       * lib/areadlink-with-size.c (areadlink_with_size):
+       * lib/areadlinkat-with-size.c (areadlinkat_with_size):
+       Reallocate at the end to the actual size, to avoid memory waste,
+       as suggested by Bruno Haible.  But when the guessed size is zero -
+       useful when the size is unknown - do the initial small readlink
+       into the stack, to avoid that realloc in the usual case.
+
 2019-07-06  Pádraig Brady  <P@draigBrady.com>
 
        areadlink-with-size: guess a buffer size with 0 size
index b9cd05cba6fcf4a10c33a69f5c32e98ee26e0ea9..ae3c782a4efd7993df1ba9bfd738be5b7a10aebf 100644 (file)
@@ -60,19 +60,28 @@ areadlink_with_size (char const *file, size_t size)
                           ? symlink_max + 1
                           : INITIAL_LIMIT_BOUND);
 
+  enum { stackbuf_size = 128 };
+
   /* The initial buffer size for the link value.  */
-  size_t buf_size = (size == 0 ? 128
+  size_t buf_size = (size == 0 ? stackbuf_size
                      : size < initial_limit ? size + 1 : initial_limit);
 
   while (1)
     {
       ssize_t r;
       size_t link_length;
-      char *buffer = malloc (buf_size);
+      char stackbuf[stackbuf_size];
+      char *buf = stackbuf;
+      char *buffer = NULL;
+
+      if (! (size == 0 && buf_size == stackbuf_size))
+        {
+          buf = buffer = malloc (buf_size);
+          if (!buffer)
+            return NULL;
+        }
 
-      if (buffer == NULL)
-        return NULL;
-      r = readlink (file, buffer, buf_size);
+      r = readlink (file, buf, buf_size);
       link_length = r;
 
       /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1
@@ -87,10 +96,16 @@ areadlink_with_size (char const *file, size_t size)
 
       if (link_length < buf_size)
         {
-          buffer[link_length] = 0;
-          /* Shrink BUFFER before returning it.  */
-          if (link_length + 1 < buf_size)
+          buf[link_length] = 0;
+          if (!buffer)
+            {
+              buffer = malloc (link_length + 1);
+              if (buffer)
+                return memcpy (buffer, buf, link_length + 1);
+            }
+          else if (link_length + 1 < buf_size)
             {
+              /* Shrink BUFFER before returning it.  */
               char *shrinked_buffer = realloc (buffer, link_length + 1);
               if (shrinked_buffer != NULL)
                 buffer = shrinked_buffer;
index d39096f2bc04684c67a16eead8022612500ee1cc..ed46d59110bcd909bd980f7072b791186978d4e4 100644 (file)
@@ -65,19 +65,28 @@ areadlinkat_with_size (int fd, char const *file, size_t size)
                           ? symlink_max + 1
                           : INITIAL_LIMIT_BOUND);
 
+  enum { stackbuf_size = 128 };
+
   /* The initial buffer size for the link value.  */
-  size_t buf_size = (size == 0 ? 128
+  size_t buf_size = (size == 0 ? stackbuf_size
                      : size < initial_limit ? size + 1 : initial_limit);
 
   while (1)
     {
       ssize_t r;
       size_t link_length;
-      char *buffer = malloc (buf_size);
+      char stackbuf[stackbuf_size];
+      char *buf = stackbuf;
+      char *buffer = NULL;
+
+      if (! (size == 0 && buf_size == stackbuf_size))
+        {
+          buf = buffer = malloc (buf_size);
+          if (!buffer)
+            return NULL;
+        }
 
-      if (buffer == NULL)
-        return NULL;
-      r = readlinkat (fd, file, buffer, buf_size);
+      r = readlinkat (fd, file, buf, buf_size);
       link_length = r;
 
       /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1
@@ -92,10 +101,16 @@ areadlinkat_with_size (int fd, char const *file, size_t size)
 
       if (link_length < buf_size)
         {
-          buffer[link_length] = 0;
-          /* Shrink BUFFER before returning it.  */
-          if (link_length + 1 < buf_size)
+          buf[link_length] = 0;
+          if (!buffer)
+            {
+              buffer = malloc (link_length + 1);
+              if (buffer)
+                return memcpy (buffer, buf, link_length + 1);
+            }
+          else if (link_length + 1 < buf_size)
             {
+              /* Shrink BUFFER before returning it.  */
               char *shrinked_buffer = realloc (buffer, link_length + 1);
               if (shrinked_buffer != NULL)
                 buffer = shrinked_buffer;