1 /* $OpenBSD: criov.c,v 1.12 2003/06/03 15:51:28 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1999 Theo de Raadt 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/proc.h> 31 #include <sys/errno.h> 32 #include <sys/malloc.h> 33 #include <sys/kernel.h> 34 #include <sys/mbuf.h> 35 36 #include <uvm/uvm_extern.h> 37 38 #include <crypto/cryptodev.h> 39 40 void 41 cuio_copydata(uio, off, len, cp) 42 struct uio *uio; 43 int off, len; 44 caddr_t cp; 45 { 46 struct iovec *iov = uio->uio_iov; 47 int iol = uio->uio_iovcnt; 48 unsigned count; 49 50 if (off < 0) 51 panic("cuio_copydata: off %d < 0", off); 52 if (len < 0) 53 panic("cuio_copydata: len %d < 0", len); 54 while (off > 0) { 55 if (iol == 0) 56 panic("iov_copydata: empty in skip"); 57 if (off < iov->iov_len) 58 break; 59 off -= iov->iov_len; 60 iol--; 61 iov++; 62 } 63 while (len > 0) { 64 if (iol == 0) 65 panic("cuio_copydata: empty"); 66 count = min(iov->iov_len - off, len); 67 bcopy(((caddr_t)iov->iov_base) + off, cp, count); 68 len -= count; 69 cp += count; 70 off = 0; 71 iol--; 72 iov++; 73 } 74 } 75 76 void 77 cuio_copyback(uio, off, len, cp) 78 struct uio *uio; 79 int off, len; 80 caddr_t cp; 81 { 82 struct iovec *iov = uio->uio_iov; 83 int iol = uio->uio_iovcnt; 84 unsigned count; 85 86 if (off < 0) 87 panic("cuio_copyback: off %d < 0", off); 88 if (len < 0) 89 panic("cuio_copyback: len %d < 0", len); 90 while (off > 0) { 91 if (iol == 0) 92 panic("cuio_copyback: empty in skip"); 93 if (off < iov->iov_len) 94 break; 95 off -= iov->iov_len; 96 iol--; 97 iov++; 98 } 99 while (len > 0) { 100 if (iol == 0) 101 panic("uio_copyback: empty"); 102 count = min(iov->iov_len - off, len); 103 bcopy(cp, ((caddr_t)iov->iov_base) + off, count); 104 len -= count; 105 cp += count; 106 off = 0; 107 iol--; 108 iov++; 109 } 110 } 111 112 int 113 cuio_getptr(struct uio *uio, int loc, int *off) 114 { 115 int ind, len; 116 117 ind = 0; 118 while (loc >= 0 && ind < uio->uio_iovcnt) { 119 len = uio->uio_iov[ind].iov_len; 120 if (len > loc) { 121 *off = loc; 122 return (ind); 123 } 124 loc -= len; 125 ind++; 126 } 127 128 if (ind > 0 && loc == 0) { 129 ind--; 130 *off = uio->uio_iov[ind].iov_len; 131 return (ind); 132 } 133 134 return (-1); 135 } 136 137 int 138 cuio_apply(struct uio *uio, int off, int len, 139 int (*f)(caddr_t, caddr_t, unsigned int), caddr_t fstate) 140 { 141 int rval, ind, uiolen; 142 unsigned int count; 143 144 if (len < 0) 145 panic("%s: len %d < 0", __func__, len); 146 if (off < 0) 147 panic("%s: off %d < 0", __func__, off); 148 149 ind = 0; 150 while (off > 0) { 151 if (ind >= uio->uio_iovcnt) 152 panic("m_apply: null mbuf in skip"); 153 uiolen = uio->uio_iov[ind].iov_len; 154 if (off < uiolen) 155 break; 156 off -= uiolen; 157 ind++; 158 } 159 while (len > 0) { 160 if (ind >= uio->uio_iovcnt) 161 panic("m_apply: null mbuf"); 162 count = min(uio->uio_iov[ind].iov_len - off, len); 163 164 rval = f(fstate, uio->uio_iov[ind].iov_base + off, count); 165 if (rval) 166 return (rval); 167 168 len -= count; 169 off = 0; 170 ind++; 171 } 172 173 return (0); 174 } 175