bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 04/13] careadlinkat: use walloc


From: Paul Eggert
Subject: [PATCH 04/13] careadlinkat: use walloc
Date: Sun, 4 Jun 2017 23:45:54 -0700

* NEWS: Mention ptrdiff_t.
* lib/careadlinkat.c: Include stdint.h, intprops.h, minmax.h, walloc.h.
(SSIZE_MAX): Use TYPE_MAXIMUM.
(careadlinkat): Accept ptrdiff_t, not size_t.
Use wallocmore instead of rolling our own allocator.
* lib/careadlinkat.h (careadlinkat): Accept ptrdiff_t, not size_t.
* modules/careadlinkat (Depends-on): Add intprops, minmax, stdint,
walloc.  Remove allocator.
---
 ChangeLog            | 10 ++++++++
 NEWS                 |  4 ++++
 lib/careadlinkat.c   | 64 +++++++++++++++++++---------------------------------
 lib/careadlinkat.h   |  2 +-
 modules/careadlinkat |  5 +++-
 5 files changed, 42 insertions(+), 43 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5aae016..d7e6afc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2017-06-04  Paul Eggert  <address@hidden>
 
+       careadlinkat: use walloc
+       * NEWS: Mention ptrdiff_t.
+       * lib/careadlinkat.c: Include stdint.h, intprops.h, minmax.h, walloc.h.
+       (SSIZE_MAX): Use TYPE_MAXIMUM.
+       (careadlinkat): Accept ptrdiff_t, not size_t.
+       Use wallocmore instead of rolling our own allocator.
+       * lib/careadlinkat.h (careadlinkat): Accept ptrdiff_t, not size_t.
+       * modules/careadlinkat (Depends-on): Add intprops, minmax, stdint,
+       walloc.  Remove allocator.
+
        allocator: allow reasons other than size overflow
        * lib/allocator.h: Adjust comment to allow reasons other
        than size overflow to result in SIZE_MAX.
diff --git a/NEWS b/NEWS
index b75ca01..ff60817 100644
--- a/NEWS
+++ b/NEWS
@@ -42,6 +42,10 @@ User visible incompatible changes
 
 Date        Modules         Changes
 
+2017-06-04  careadlinkat    careadlinkat now takes
+                            ptrdiff_t instead of size_t arguments for object
+                            and byte counts.
+
 2017-05-19  closeout        close_stdout longer closes stderr when addresses
                             are being sanitized, as the sanitizer outputs to
                             stderr afterwards.
diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c
index 455e00e..f939b0f 100644
--- a/lib/careadlinkat.c
+++ b/lib/careadlinkat.c
@@ -24,19 +24,18 @@
 
 #include <errno.h>
 #include <limits.h>
+#include <stdint.h>
 #include <string.h>
 #include <unistd.h>
 
-/* Define this independently so that stdint.h is not a prerequisite.  */
-#ifndef SIZE_MAX
-# define SIZE_MAX ((size_t) -1)
-#endif
-
 #ifndef SSIZE_MAX
-# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
+# define SSIZE_MAX TYPE_MAXIMUM (ssize_t)
 #endif
 
 #include "allocator.h"
+#include "intprops.h"
+#include "minmax.h"
+#include "walloc.h"
 
 /* Assuming the current directory is FD, get the symbolic link value
    of FILENAME as a null-terminated string and put it into a buffer.
@@ -49,8 +48,7 @@
 
    If the link is not small, put it into a dynamically allocated
    buffer managed by ALLOC.  It is the caller's responsibility to free
-   the returned value if it is nonnull and is not BUFFER.  A null
-   ALLOC stands for the standard allocator.
+   the returned value if it is nonnull and is not BUFFER.
 
    The PREADLINKAT function specifies how to read links.  It operates
    like POSIX readlinkat()
@@ -62,19 +60,15 @@
 
 char *
 careadlinkat (int fd, char const *filename,
-              char *buffer, size_t buffer_size,
+              char *buffer, ptrdiff_t buffer_size,
               struct allocator const *alloc,
               ssize_t (*preadlinkat) (int, char const *, char *, size_t))
 {
   char *buf;
-  size_t buf_size;
-  size_t buf_size_max =
-    SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
+  ptrdiff_t buf_size;
+  ptrdiff_t buf_size_max = MIN (PTRDIFF_MAX, SSIZE_MAX);
   char stack_buf[1024];
 
-  if (! alloc)
-    alloc = &stdlib_allocator;
-
   if (! buffer_size)
     {
       /* Allocate the initial buffer on the stack.  This way, in the
@@ -92,7 +86,6 @@ careadlinkat (int fd, char const *filename,
     {
       /* Attempt to read the link into the current buffer.  */
       ssize_t link_length = preadlinkat (fd, filename, buf, buf_size);
-      size_t link_size;
       if (link_length < 0)
         {
           /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1
@@ -108,26 +101,27 @@ careadlinkat (int fd, char const *filename,
               return NULL;
             }
         }
-
-      link_size = link_length;
-
-      if (link_size < buf_size)
+      else if (link_length < buf_size)
         {
-          buf[link_size++] = '\0';
+          buf[link_length++] = '\0';
 
           if (buf == stack_buf)
             {
-              char *b = (char *) alloc->allocate (link_size);
-              buf_size = link_size;
+              char *b = alloc->allocate (link_length);
               if (! b)
-                break;
-              memcpy (b, buf, link_size);
+                {
+                  if (alloc->die)
+                    alloc->die (link_length);
+                  break;
+                }
+              memcpy (b, buf, link_length);
               buf = b;
+              buf_size = link_length;
             }
-          else if (link_size < buf_size && buf != buffer && alloc->reallocate)
+          else if (buf != buffer)
             {
               /* Shrink BUF before returning it.  */
-              char *b = (char *) alloc->reallocate (buf, link_size);
+              char *b = alloc->reallocate (buf, link_length);
               if (b)
                 buf = b;
             }
@@ -138,23 +132,11 @@ careadlinkat (int fd, char const *filename,
       if (buf != buffer)
         alloc->free (buf);
 
-      if (buf_size <= buf_size_max / 2)
-        buf_size *= 2;
-      else if (buf_size < buf_size_max)
-        buf_size = buf_size_max;
-      else if (buf_size_max < SIZE_MAX)
-        {
-          errno = ENAMETOOLONG;
-          return NULL;
-        }
-      else
-        break;
-      buf = (char *) alloc->allocate (buf_size);
+      /* BUF_SIZE was not big enough; try again with a larger value.  */
+      buf = wallocmore (NULL, &buf_size, 1, buf_size_max, sizeof *buf, alloc);
     }
   while (buf);
 
-  if (alloc->die)
-    alloc->die (buf_size);
   errno = ENOMEM;
   return NULL;
 }
diff --git a/lib/careadlinkat.h b/lib/careadlinkat.h
index 528a828..b66e4bd 100644
--- a/lib/careadlinkat.h
+++ b/lib/careadlinkat.h
@@ -47,7 +47,7 @@ struct allocator;
    set errno.  */
 
 char *careadlinkat (int fd, char const *filename,
-                    char *buffer, size_t buffer_size,
+                    char *buffer, ptrdiff_t buffer_size,
                     struct allocator const *alloc,
                     ssize_t (*preadlinkat) (int, char const *,
                                             char *, size_t));
diff --git a/modules/careadlinkat b/modules/careadlinkat
index 9dd7471..5079429 100644
--- a/modules/careadlinkat
+++ b/modules/careadlinkat
@@ -6,9 +6,12 @@ lib/careadlinkat.c
 lib/careadlinkat.h
 
 Depends-on:
-allocator
+intprops
+minmax
 ssize_t
+stdint
 unistd
+walloc
 
 configure.ac:
 AC_CHECK_FUNCS_ONCE([readlinkat])
-- 
2.9.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]