1 /*
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 <lk/err.h>
9 #include <lk/debug.h>
10 #include <assert.h>
11 #include <string.h>
12 #include <sys/types.h>
13
14 #include <iovec.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) ERR_INVALID_ARGS;
24
25 size_t c = 0;
26 for (uint i = 0; i < iov_cnt; i++, iov++) {
27 c += iov->iov_len;
28 }
29 return (ssize_t) c;
30 }
31
32 /*
33 * Copy out portion of iovec started from given position
34 * into single buffer
35 */
iovec_to_membuf(uint8_t * buf,uint buf_len,const iovec_t * iov,uint iov_cnt,uint iov_pos)36 ssize_t iovec_to_membuf (uint8_t *buf, uint buf_len, const iovec_t *iov, uint iov_cnt, uint iov_pos) {
37 uint buf_pos = 0;
38
39 if (!buf || !iov)
40 return (ssize_t) ERR_INVALID_ARGS;
41
42 /* for all iovec */
43 for (uint i = 0; i < iov_cnt; i++, iov++) {
44
45 if (iov_pos >= iov->iov_len) {
46 iov_pos -= iov->iov_len; /* skip whole chunks */
47 continue;
48 }
49
50 /* calc number of bytes left in current iov */
51 size_t to_copy = (size_t) (iov->iov_len - iov_pos);
52
53 /* limit it to number of bytes left in buffer */
54 if (to_copy > buf_len)
55 to_copy = buf_len;
56
57 /* copy data out */
58 memcpy (buf + buf_pos, (uint8_t *)iov->iov_base + iov_pos, to_copy);
59
60 /* advance in buffer position */
61 buf_pos += to_copy;
62 buf_len -= to_copy;
63
64 /* check if we need to copy more data */
65 if (buf_len == 0)
66 break;
67
68 iov_pos = 0; /* it is only possible to have fully copied iovec here */
69 }
70
71 return (ssize_t) buf_pos;
72 }
73