1 // Copyright 2016 The Fuchsia Authors
2 // Copyright (c) 2014 Travis Geiselbrecht
3 //
4 // Use of this source code is governed by a MIT-style
5 // license that can be found in the LICENSE file or at
6 // https://opensource.org/licenses/MIT
7
8 #include <iovec.h>
9
10 #include <assert.h>
11 #include <debug.h>
12 #include <err.h>
13 #include <string.h>
14 #include <sys/types.h>
15
16 #define LOCAL_TRACE 0
17
18 /*
19 * Calc total size of iovec buffers
20 */
iovec_size(const iovec_t * iov,uint iov_cnt)21 ssize_t iovec_size(const iovec_t* iov, uint iov_cnt) {
22 if (!iov) {
23 return (ssize_t)ZX_ERR_INVALID_ARGS;
24 }
25
26 size_t c = 0;
27 for (uint i = 0; i < iov_cnt; i++, iov++) {
28 c += iov->iov_len;
29 }
30 return (ssize_t)c;
31 }
32
33 /*
34 * Copy out portion of iovec started from given position
35 * into single buffer
36 */
iovec_to_membuf(uint8_t * buf,uint buf_len,const iovec_t * iov,uint iov_cnt,uint iov_pos)37 ssize_t iovec_to_membuf(uint8_t* buf, uint buf_len, const iovec_t* iov, uint iov_cnt, uint iov_pos) {
38 uint buf_pos = 0;
39
40 if (!buf || !iov) {
41 return (ssize_t)ZX_ERR_INVALID_ARGS;
42 }
43
44 /* for all iovec */
45 for (uint i = 0; i < iov_cnt; i++, iov++) {
46
47 if (iov_pos >= iov->iov_len) {
48 iov_pos -= iov->iov_len; /* skip whole chunks */
49 continue;
50 }
51
52 /* calc number of bytes left in current iov */
53 size_t to_copy = (size_t)(iov->iov_len - iov_pos);
54
55 /* limit it to number of bytes left in buffer */
56 if (to_copy > buf_len) {
57 to_copy = buf_len;
58 }
59
60 /* copy data out */
61 memcpy(buf + buf_pos, (uint8_t*)iov->iov_base + iov_pos, to_copy);
62
63 /* advance in buffer position */
64 buf_pos += to_copy;
65 buf_len -= to_copy;
66
67 /* check if we need to copy more data */
68 if (buf_len == 0) {
69 break;
70 }
71
72 iov_pos = 0; /* it is only possible to have fully copied iovec here */
73 }
74
75 return (ssize_t)buf_pos;
76 }
77