Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * Samba system utilities
4 : * Copyright (C) Volker Lendecke 2014
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation; either version 3 of the License, or
9 : * (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License
17 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "replace.h"
21 : #include "system/filesys.h"
22 : #include "iov_buf.h"
23 : #include <talloc.h>
24 :
25 1613307 : ssize_t iov_buflen(const struct iovec *iov, int iovcnt)
26 : {
27 1613307 : return iov_buf(iov, iovcnt, NULL, 0);
28 : }
29 :
30 2023510 : ssize_t iov_buf(const struct iovec *iov, int iovcnt,
31 : uint8_t *buf, size_t buflen)
32 : {
33 2023510 : size_t needed = 0;
34 2023510 : uint8_t *p = buf;
35 : int i;
36 :
37 9054463 : for (i=0; i<iovcnt; i++) {
38 7030953 : size_t thislen = iov[i].iov_len;
39 : size_t tmp;
40 :
41 7030953 : tmp = needed + thislen;
42 :
43 7030953 : if (tmp < needed) {
44 : /* wrap */
45 0 : return -1;
46 : }
47 7030953 : needed = tmp;
48 :
49 7030953 : if ((p != NULL) && needed <= buflen && thislen > 0) {
50 1488014 : memcpy(p, iov[i].iov_base, thislen);
51 1488014 : p += thislen;
52 : }
53 : }
54 :
55 2023510 : return needed;
56 : }
57 :
58 17502035 : bool iov_advance(struct iovec **iov, int *iovcnt, size_t n)
59 : {
60 17502035 : struct iovec *v = *iov;
61 17502035 : int cnt = *iovcnt;
62 :
63 46085693 : while (n > 0) {
64 22599829 : if (cnt == 0) {
65 0 : return false;
66 : }
67 22599829 : if (n < v->iov_len) {
68 8791616 : v->iov_base = (char *)v->iov_base + n;
69 8791616 : v->iov_len -= n;
70 8791616 : break;
71 : }
72 13808213 : n -= v->iov_len;
73 13808213 : v += 1;
74 13808213 : cnt -= 1;
75 : }
76 :
77 : /*
78 : * Skip 0-length iovec's
79 : *
80 : * There might be empty buffers at the end of iov. Next time we do a
81 : * readv/writev based on this iov would give 0 transferred bytes, also
82 : * known as EPIPE. So we need to be careful discarding them.
83 : */
84 :
85 32657833 : while ((cnt > 0) && (v->iov_len == 0)) {
86 380353 : v += 1;
87 380353 : cnt -= 1;
88 : }
89 :
90 17502035 : *iov = v;
91 17502035 : *iovcnt = cnt;
92 17502035 : return true;
93 : }
94 :
95 408757 : uint8_t *iov_concat(TALLOC_CTX *mem_ctx, const struct iovec *iov, int count)
96 : {
97 : ssize_t buflen;
98 : uint8_t *buf;
99 :
100 408757 : buflen = iov_buflen(iov, count);
101 408757 : if (buflen == -1) {
102 0 : return NULL;
103 : }
104 :
105 408757 : buf = talloc_array(mem_ctx, uint8_t, buflen);
106 408757 : if (buf == NULL) {
107 0 : return NULL;
108 : }
109 :
110 408757 : iov_buf(iov, count, buf, buflen);
111 :
112 408757 : return buf;
113 : }
|