]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/posix/writev.c
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / posix / writev.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>
9710f75d
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
34
28f540f4 35/* Write data pointed by the buffers described by VECTOR, which
2dbe6afe 36 is a vector of COUNT 'struct iovec's, to file descriptor FD.
28f540f4 37 The data is written in the order specified.
2dbe6afe 38 Operates just like 'write' (see <unistd.h>) except that the data
28f540f4 39 are taken from VECTOR instead of a contiguous buffer. */
ebe3b3eb 40ssize_t
e19c95fd 41__writev (int fd, const struct iovec *vector, int count)
28f540f4 42{
28f540f4 43 /* Find the total number of bytes to be written. */
2dbe6afe
UD
44 size_t bytes = 0;
45 for (int i = 0; i < count; ++i)
9710f75d
UD
46 {
47 /* Check for ssize_t overflow. */
48 if (SSIZE_MAX - bytes < vector[i].iov_len)
49 {
bf2cc5fb 50 __set_errno (EINVAL);
9710f75d
UD
51 return -1;
52 }
53 bytes += vector[i].iov_len;
54 }
28f540f4 55
9710f75d
UD
56 /* Allocate a temporary buffer to hold the data. We should normally
57 use alloca since it's faster and does not require synchronization
58 with other threads. But we cannot if the amount of memory
6166815d 59 required is too large. */
2dbe6afe
UD
60 char *buffer;
61 char *malloced_buffer __attribute__ ((__cleanup__ (ifree))) = NULL;
6166815d 62 if (__libc_use_alloca (bytes))
9710f75d
UD
63 buffer = (char *) __alloca (bytes);
64 else
65 {
2dbe6afe 66 malloced_buffer = buffer = (char *) malloc (bytes);
9710f75d
UD
67 if (buffer == NULL)
68 /* XXX I don't know whether it is acceptable to try writing
69 the data in chunks. Probably not so we just fail here. */
70 return -1;
9710f75d 71 }
28f540f4
RM
72
73 /* Copy the data into BUFFER. */
2dbe6afe
UD
74 size_t to_copy = bytes;
75 char *bp = buffer;
76 for (int i = 0; i < count; ++i)
28f540f4 77 {
9710f75d 78 size_t copy = MIN (vector[i].iov_len, to_copy);
28f540f4 79
86187531 80 bp = __mempcpy ((void *) bp, (void *) vector[i].iov_base, copy);
28f540f4 81
28f540f4 82 to_copy -= copy;
86187531 83 if (to_copy == 0)
28f540f4
RM
84 break;
85 }
86
2dbe6afe 87 ssize_t bytes_written = __write (fd, buffer, bytes);
9710f75d
UD
88
89 return bytes_written;
28f540f4 90}
d6daff12 91libc_hidden_def (__writev)
e19c95fd 92weak_alias (__writev, writev)