bug-gnulib
[Top][All Lists]
Advanced

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

Re: proposed new module careadlinkat (renamed from breadlinkat)


From: Paul Eggert
Subject: Re: proposed new module careadlinkat (renamed from breadlinkat)
Date: Tue, 05 Apr 2011 11:07:33 -0700
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110307 Fedora/3.1.9-0.39.b3pre.fc14 Thunderbird/3.1.9

Following up on Ben Pfaff's comments, I installed
the patch into gnulib, with the following further changes:

diff --git a/lib/allocator.h b/lib/allocator.h
index 54cc5ff..4ac863b 100644
--- a/lib/allocator.h
+++ b/lib/allocator.h
@@ -21,8 +21,15 @@
 
 #include <stddef.h>
 
+/* An object describing a memory allocator family.  */
+
 struct allocator
 {
+  /* Do not use GCC attributes such as __attribute__ ((malloc)) with
+     the function types pointed at by these members, because these
+     attributes do not work with pointers to functions.  See
+     <http://lists.gnu.org/archive/html/bug-gnulib/2011-04/msg00007.html>.  */
+
   /* Call MALLOC to allocate memory, like 'malloc'.  On failure MALLOC
      should return NULL, though not necessarily set errno.  When given
      a zero size it may return NULL even if successful.  */
@@ -37,8 +44,9 @@ struct allocator
   /* Call FREE to free memory, like 'free'.  */
   void (*free) (void *);
 
-  /* If nonnull, call DIE if MALLOC or REALLOC fails.  DIE should
-     not return.  */
+  /* If nonnull, call DIE if MALLOC or REALLOC fails.  DIE should not
+     return.  DIE can be used by code that detects memory overflow
+     while calculating sizes to be passed to MALLOC or REALLOC.  */
   void (*die) (void);
 };
 
diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c
index 828c050..15ffe24 100644
--- a/lib/careadlinkat.c
+++ b/lib/careadlinkat.c
@@ -57,6 +57,11 @@ careadlinkatcwd (int fd, char const *filename, char *buffer,
 }
 #endif
 
+/* A standard allocator.  For now, only careadlinkat needs this, but
+   perhaps it should be moved to the allocator module.  */
+static struct allocator const standard_allocator =
+  { malloc, realloc, free, NULL };
+
 /* Assuming the current directory is FD, get the symbolic link value
    of FILENAME as a null-terminated string and put it into a buffer.
    If FD is AT_FDCWD, FILENAME is interpreted relative to the current
@@ -88,17 +93,8 @@ careadlinkat (int fd, char const *filename,
     SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
   char stack_buf[1024];
 
-  void *(*pmalloc) (size_t) = malloc;
-  void *(*prealloc) (void *, size_t) = realloc;
-  void (*pfree) (void *) = free;
-  void (*pdie) (void) = NULL;
-  if (alloc)
-    {
-      pmalloc = alloc->malloc;
-      prealloc = alloc->realloc;
-      pfree = alloc->free;
-      pdie = alloc->die;
-    }
+  if (! alloc)
+    alloc = &standard_allocator;
 
   if (! buffer_size)
     {
@@ -127,7 +123,7 @@ careadlinkat (int fd, char const *filename,
             {
               if (buf != buffer)
                 {
-                  pfree (buf);
+                  alloc->free (buf);
                   errno = readlinkat_errno;
                 }
               return NULL;
@@ -142,16 +138,16 @@ careadlinkat (int fd, char const *filename,
 
           if (buf == stack_buf)
             {
-              char *b = (char *) pmalloc (link_size);
+              char *b = (char *) alloc->malloc (link_size);
               if (! b)
                 break;
               memcpy (b, buf, link_size);
               buf = b;
             }
-          else if (link_size < buf_size && buf != buffer && prealloc)
+          else if (link_size < buf_size && buf != buffer && alloc->realloc)
             {
               /* Shrink BUF before returning it.  */
-              char *b = (char *) prealloc (buf, link_size);
+              char *b = (char *) alloc->realloc (buf, link_size);
               if (b)
                 buf = b;
             }
@@ -160,7 +156,7 @@ careadlinkat (int fd, char const *filename,
         }
 
       if (buf != buffer)
-        pfree (buf);
+        alloc->free (buf);
 
       if (buf_size <= buf_size_max / 2)
         buf_size *= 2;
@@ -168,12 +164,12 @@ careadlinkat (int fd, char const *filename,
         buf_size = buf_size_max;
       else
         break;
-      buf = (char *) pmalloc (buf_size);
+      buf = (char *) alloc->malloc (buf_size);
     }
   while (buf);
 
-  if (pdie)
-    pdie ();
+  if (alloc->die)
+    alloc->die ();
   errno = ENOMEM;
   return NULL;
 }




reply via email to

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