]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/posix/readv.c
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / posix / readv.c
CommitLineData
04277e02 1/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
afd4eb37 2 This file is part of the GNU C Library.
28f540f4 3
afd4eb37 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
28f540f4 8
afd4eb37
UD
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>. */
28f540f4 17
28f540f4
RM
18#include <stdlib.h>
19#include <unistd.h>
20#include <string.h>
a204ea36
UD
21#include <limits.h>
22#include <stdbool.h>
23#include <sys/param.h>
28f540f4 24#include <sys/uio.h>
bf2cc5fb 25#include <errno.h>
28f540f4 26
2dbe6afe
UD
27
28static void
29ifree (char **ptrp)
30{
31 free (*ptrp);
32}
33
28f540f4 34/* Read data from file descriptor FD, and put the result in the
2dbe6afe 35 buffers described by VECTOR, which is a vector of COUNT 'struct iovec's.
28f540f4 36 The buffers are filled in the order specified.
2dbe6afe 37 Operates just like 'read' (see <unistd.h>) except that data are
28f540f4 38 put in VECTOR instead of a contiguous buffer. */
ebe3b3eb 39ssize_t
e19c95fd 40__readv (int fd, const struct iovec *vector, int count)
28f540f4 41{
28f540f4 42 /* Find the total number of bytes to be read. */
2dbe6afe
UD
43 size_t bytes = 0;
44 for (int i = 0; i < count; ++i)
a204ea36
UD
45 {
46 /* Check for ssize_t overflow. */
47 if (SSIZE_MAX - bytes < vector[i].iov_len)
48 {
bf2cc5fb 49 __set_errno (EINVAL);
a204ea36
UD
50 return -1;
51 }
52 bytes += vector[i].iov_len;
53 }
54
55 /* Allocate a temporary buffer to hold the data. We should normally
56 use alloca since it's faster and does not require synchronization
57 with other threads. But we cannot if the amount of memory
6166815d 58 required is too large. */
2dbe6afe
UD
59 char *buffer;
60 char *malloced_buffer __attribute__ ((__cleanup__ (ifree))) = NULL;
6166815d 61 if (__libc_use_alloca (bytes))
a204ea36
UD
62 buffer = (char *) __alloca (bytes);
63 else
64 {
2dbe6afe 65 malloced_buffer = buffer = (char *) malloc (bytes);
a204ea36 66 if (buffer == NULL)
a204ea36 67 return -1;
a204ea36 68 }
28f540f4
RM
69
70 /* Read the data. */
2dbe6afe 71 ssize_t bytes_read = __read (fd, buffer, bytes);
571ac26f 72 if (bytes_read < 0)
28f540f4
RM
73 return -1;
74
75 /* Copy the data from BUFFER into the memory specified by VECTOR. */
76 bytes = bytes_read;
2dbe6afe 77 for (int i = 0; i < count; ++i)
28f540f4 78 {
a204ea36 79 size_t copy = MIN (vector[i].iov_len, bytes);
28f540f4 80
afd4eb37 81 (void) memcpy ((void *) vector[i].iov_base, (void *) buffer, copy);
28f540f4
RM
82
83 buffer += copy;
84 bytes -= copy;
85 if (bytes == 0)
86 break;
87 }
88
89 return bytes_read;
90}
d6daff12 91libc_hidden_def (__readv)
e19c95fd 92weak_alias (__readv, readv)