1 /*
2 * this code is taken from Michael - the qemu code is GPLv2 so I don't want
3 * to reuse it.
4 * I've adapted it to handle offsets and callback
5 */
6
7 //
8 // iovec.c
9 //
10 // Scatter/gather utility routines
11 //
12 // Copyright (C) 2002 Michael Ringgaard. All rights reserved.
13 //
14 // Redistribution and use in source and binary forms, with or without
15 // modification, are permitted provided that the following conditions
16 // are met:
17 //
18 // 1. Redistributions of source code must retain the above copyright
19 // notice, this list of conditions and the following disclaimer.
20 // 2. Redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 // 3. Neither the name of the project nor the names of its contributors
24 // may be used to endorse or promote products derived from this software
25 // without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
28 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
31 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 // SUCH DAMAGE.
38 //
39
40 #include <assert.h>
41 #include <string.h>
42 #include "vrend_iov.h"
43
vrend_get_iovec_size(const struct iovec * iov,int iovlen)44 size_t vrend_get_iovec_size(const struct iovec *iov, int iovlen) {
45 size_t size = 0;
46
47 while (iovlen > 0) {
48 size += iov->iov_len;
49 iov++;
50 iovlen--;
51 }
52
53 return size;
54 }
55
vrend_read_from_iovec(const struct iovec * iov,int iovlen,size_t offset,char * buf,size_t count)56 size_t vrend_read_from_iovec(const struct iovec *iov, int iovlen,
57 size_t offset,
58 char *buf, size_t count)
59 {
60 size_t read = 0;
61 size_t len;
62
63 while (count > 0 && iovlen > 0) {
64 if (iov->iov_len > offset) {
65 len = iov->iov_len - offset;
66
67 if (count < len) len = count;
68
69 memcpy(buf, (char*)iov->iov_base + offset, len);
70 read += len;
71
72 buf += len;
73 count -= len;
74 offset = 0;
75 } else {
76 offset -= iov->iov_len;
77 }
78
79 iov++;
80 iovlen--;
81 }
82 assert(offset == 0);
83 return read;
84 }
85
vrend_write_to_iovec(const struct iovec * iov,int iovlen,size_t offset,const char * buf,size_t count)86 size_t vrend_write_to_iovec(const struct iovec *iov, int iovlen,
87 size_t offset, const char *buf, size_t count)
88 {
89 size_t written = 0;
90 size_t len;
91
92 while (count > 0 && iovlen > 0) {
93 if (iov->iov_len > offset) {
94 len = iov->iov_len - offset;
95
96 if (count < len) len = count;
97
98 memcpy((char*)iov->iov_base + offset, buf, len);
99 written += len;
100
101 offset = 0;
102 buf += len;
103 count -= len;
104 } else {
105 offset -= iov->iov_len;
106 }
107 iov++;
108 iovlen--;
109 }
110 assert(offset == 0);
111 return written;
112 }
113
vrend_read_from_iovec_cb(const struct iovec * iov,int iovlen,size_t offset,size_t count,iov_cb iocb,void * cookie)114 size_t vrend_read_from_iovec_cb(const struct iovec *iov, int iovlen,
115 size_t offset, size_t count,
116 iov_cb iocb, void *cookie)
117 {
118 size_t read = 0;
119 size_t len;
120
121 while (count > 0 && iovlen > 0) {
122 if (iov->iov_len > offset) {
123 len = iov->iov_len - offset;
124
125 if (count < len) len = count;
126
127 (*iocb)(cookie, read, (char*)iov->iov_base + offset, len);
128 read += len;
129
130 count -= len;
131 offset = 0;
132 } else {
133 offset -= iov->iov_len;
134 }
135 iov++;
136 iovlen--;
137 }
138 assert(offset == 0);
139 return read;
140
141
142 }
143