]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/posix/readv.c
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / posix / readv.c
index 89fe1af7d3a646acc9dc6c446422f1b9962aa299..a7567d68e77ac0677b6f1d49157d10fef4f509f0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1996, 1997, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -12,9 +12,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
 
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdbool.h>
 #include <sys/param.h>
 #include <sys/uio.h>
+#include <errno.h>
+
+
+static void
+ifree (char **ptrp)
+{
+  free (*ptrp);
+}
 
 /* Read data from file descriptor FD, and put the result in the
-   buffers described by VECTOR, which is a vector of COUNT `struct iovec's.
+   buffers described by VECTOR, which is a vector of COUNT 'struct iovec's.
    The buffers are filled in the order specified.
-   Operates just like `read' (see <unistd.h>) except that data are
+   Operates just like 'read' (see <unistd.h>) except that data are
    put in VECTOR instead of a contiguous buffer.  */
 ssize_t
-__readv (fd, vector, count)
-     int fd;
-     const struct iovec *vector;
-     int count;
+__readv (int fd, const struct iovec *vector, int count)
 {
-  char *buffer;
-  char *buffer_start;
-  size_t bytes;
-  int bytes_read;
-  int i;
-  bool use_malloc = false;
-
   /* Find the total number of bytes to be read.  */
-  bytes = 0;
-  for (i = 0; i < count; ++i)
+  size_t bytes = 0;
+  for (int i = 0; i < count; ++i)
     {
       /* Check for ssize_t overflow.  */
       if (SSIZE_MAX - bytes < vector[i].iov_len)
        {
-         errno = EINVAL;
+         __set_errno (EINVAL);
          return -1;
        }
       bytes += vector[i].iov_len;
@@ -58,29 +55,26 @@ __readv (fd, vector, count)
   /* Allocate a temporary buffer to hold the data.  We should normally
      use alloca since it's faster and does not require synchronization
      with other threads.  But we cannot if the amount of memory
-     required is too large.  Use 512k as the limit.  */
-  if (bytes < 512 * 1024)
+     required is too large.  */
+  char *buffer;
+  char *malloced_buffer __attribute__ ((__cleanup__ (ifree))) = NULL;
+  if (__libc_use_alloca (bytes))
     buffer = (char *) __alloca (bytes);
   else
     {
-      buffer = (char *) malloc (bytes);
+      malloced_buffer = buffer = (char *) malloc (bytes);
       if (buffer == NULL)
-       /* XXX I don't know whether it is acceptable to try reading
-          the data in chunks.  Probably not so we just fail here.  */
        return -1;
-
-      use_malloc = true;
     }
 
   /* Read the data.  */
-  bytes_read = __read (fd, buffer, bytes);
-  if (bytes_read <= 0)
+  ssize_t bytes_read = __read (fd, buffer, bytes);
+  if (bytes_read < 0)
     return -1;
 
   /* Copy the data from BUFFER into the memory specified by VECTOR.  */
   bytes = bytes_read;
-  buffer_start = buffer;
-  for (i = 0; i < count; ++i)
+  for (int i = 0; i < count; ++i)
     {
       size_t copy = MIN (vector[i].iov_len, bytes);
 
@@ -92,11 +86,7 @@ __readv (fd, vector, count)
        break;
     }
 
-  if (use_malloc)
-    free (buffer_start);
-
   return bytes_read;
 }
-#ifndef __readv
+libc_hidden_def (__readv)
 weak_alias (__readv, readv)
-#endif