11 #include <sys/param.h>
15 #define VECTORIO_READ 1
16 #define VECTORIO_WRITE 2
19 __weak_alias(writev
, _writev
)
20 __weak_alias(readv
, _readv
)
23 static ssize_t
vectorio_buffer(int fildes
, const struct iovec
*iov
,
24 int iovcnt
, int readwrite
, ssize_t totallen
)
27 int iovidx
, errno_saved
;
28 ssize_t copied
, len
, r
;
31 buffer
= (char *) malloc(totallen
);
35 /* perform the actual read/write for the entire buffer */
39 /* first read, then copy buffers (only part read) */
40 r
= read(fildes
, buffer
, totallen
);
46 assert(iovidx
< iovcnt
);
47 len
= MIN(r
- copied
, iov
[iovidx
].iov_len
);
48 memcpy(iov
[iovidx
++].iov_base
, buffer
+ copied
, len
);
51 assert(r
< 0 || r
== copied
);
55 /* first copy buffers, then write */
57 for (iovidx
= 0; iovidx
< iovcnt
; iovidx
++)
59 memcpy(buffer
+ copied
, iov
[iovidx
].iov_base
,
61 copied
+= iov
[iovidx
].iov_len
;
63 assert(copied
== totallen
);
65 r
= write(fildes
, buffer
, totallen
);
74 /* free the buffer, keeping errno unchanged */
82 static ssize_t
vectorio(int fildes
, const struct iovec
*iov
,
83 int iovcnt
, int readwrite
)
88 /* parameter sanity checks */
96 for (i
= 0; i
< iovcnt
; i
++)
98 /* don't read/write anything in case of possible overflow */
99 if ((ssize_t
) (totallen
+ iov
[i
].iov_len
) < totallen
)
104 totallen
+= iov
[i
].iov_len
;
106 /* report on NULL pointers */
107 if (iov
[i
].iov_len
&& !iov
[i
].iov_base
)
114 /* anything to do? */
119 * there aught to be a system call here; instead we use an intermediate
120 * buffer; this is preferred over multiple read/write calls because
121 * this function has to be atomic
123 return vectorio_buffer(fildes
, iov
, iovcnt
, readwrite
, totallen
);
126 ssize_t
readv(int fildes
, const struct iovec
*iov
, int iovcnt
)
128 return vectorio(fildes
, iov
, iovcnt
, VECTORIO_READ
);
131 ssize_t
writev(int fildes
, const struct iovec
*iov
, int iovcnt
)
133 return vectorio(fildes
, iov
, iovcnt
, VECTORIO_WRITE
);