]> code.delx.au - gnu-emacs/blobdiff - lib/careadlinkat.c
Update ps-mode.el from upstream
[gnu-emacs] / lib / careadlinkat.c
index 828c0508db74134639816fea0606eb8552be4a96..e2c19d1c1f1749d77d44ca54c1ce595ba7b621e4 100644 (file)
@@ -1,6 +1,6 @@
 /* Read symbolic links into a buffer without size limitation, relative to fd.
 
-   Copyright (C) 2001, 2003-2004, 2007, 2009-2011 Free Software Foundation,
+   Copyright (C) 2001, 2003-2004, 2007, 2009-2013 Free Software Foundation,
    Inc.
 
    This program is free software: you can redistribute it and/or modify
 
 #include "careadlinkat.h"
 
-#include "allocator.h"
-
 #include <errno.h>
 #include <limits.h>
-#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-/* Use the system functions, not the gnulib overrides, because this
-   module does not depend on GNU or POSIX semantics.  */
-#undef malloc
-#undef realloc
-
 /* Define this independently so that stdint.h is not a prerequisite.  */
 #ifndef SIZE_MAX
 # define SIZE_MAX ((size_t) -1)
 # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
 #endif
 
-#if ! HAVE_READLINKAT
-/* Ignore FD.  Get the symbolic link value of FILENAME and put it into
-   BUFFER, with size BUFFER_SIZE.  This function acts like readlink
-   but has readlinkat's signature.  */
-ssize_t
-careadlinkatcwd (int fd, char const *filename, char *buffer,
-                 size_t buffer_size)
-{
-  (void) fd;
-  return readlink (filename, buffer, buffer_size);
-}
-#endif
+#include "allocator.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.
@@ -71,7 +52,10 @@ careadlinkatcwd (int fd, char const *filename, char *buffer,
    the returned value if it is nonnull and is not BUFFER.  A null
    ALLOC stands for the standard allocator.
 
-   The PREADLINKAT function specifies how to read links.
+   The PREADLINKAT function specifies how to read links.  It operates
+   like POSIX readlinkat()
+   <http://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>
+   but can assume that its first argument is the same as FD.
 
    If successful, return the buffer address; otherwise return NULL and
    set errno.  */
@@ -88,17 +72,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 = &stdlib_allocator;
 
   if (! buffer_size)
     {
@@ -127,7 +102,7 @@ careadlinkat (int fd, char const *filename,
             {
               if (buf != buffer)
                 {
-                  pfree (buf);
+                  alloc->free (buf);
                   errno = readlinkat_errno;
                 }
               return NULL;
@@ -142,16 +117,17 @@ careadlinkat (int fd, char const *filename,
 
           if (buf == stack_buf)
             {
-              char *b = (char *) pmalloc (link_size);
+              char *b = (char *) alloc->allocate (link_size);
+              buf_size = 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->reallocate)
             {
               /* Shrink BUF before returning it.  */
-              char *b = (char *) prealloc (buf, link_size);
+              char *b = (char *) alloc->reallocate (buf, link_size);
               if (b)
                 buf = b;
             }
@@ -160,20 +136,25 @@ careadlinkat (int fd, char const *filename,
         }
 
       if (buf != buffer)
-        pfree (buf);
+        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 *) pmalloc (buf_size);
+      buf = (char *) alloc->allocate (buf_size);
     }
   while (buf);
 
-  if (pdie)
-    pdie ();
+  if (alloc->die)
+    alloc->die (buf_size);
   errno = ENOMEM;
   return NULL;
 }