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 <err.h>
9#include <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 */
21ssize_t iovec_size (const iovec_t *iov, uint iov_cnt)
22{
23    if (!iov)
24        return (ssize_t) ZX_ERR_INVALID_ARGS;
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 */
37ssize_t iovec_to_membuf (uint8_t *buf, uint buf_len, const iovec_t *iov, uint iov_cnt, uint iov_pos)
38{
39    uint buf_pos = 0;
40
41    if (!buf || !iov)
42        return (ssize_t) ZX_ERR_INVALID_ARGS;
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        /* copy data out */
60        memcpy (buf + buf_pos, (uint8_t *)iov->iov_base + iov_pos, to_copy);
61
62        /* advance in buffer position */
63        buf_pos += to_copy;
64        buf_len -= to_copy;
65
66        /* check if we need to copy more data */
67        if (buf_len == 0)
68            break;
69
70        iov_pos  = 0; /* it is only possible to have fully copied iovec here */
71    }
72
73    return (ssize_t) buf_pos;
74}
75