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