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 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 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 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 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