Line data Source code
1 : /* $OpenBSD: criov.c,v 1.20 2015/03/14 03:38:46 jsg 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/errno.h>
31 : #include <sys/kernel.h>
32 : #include <sys/mbuf.h>
33 :
34 : void
35 0 : cuio_copydata(struct uio *uio, int off, int len, caddr_t cp)
36 : {
37 0 : struct iovec *iov = uio->uio_iov;
38 0 : int iol = uio->uio_iovcnt;
39 : unsigned count;
40 :
41 0 : if (off < 0)
42 0 : panic("cuio_copydata: off %d < 0", off);
43 0 : if (len < 0)
44 0 : panic("cuio_copydata: len %d < 0", len);
45 0 : while (off > 0) {
46 0 : if (iol == 0)
47 0 : panic("iov_copydata: empty in skip");
48 0 : if (off < iov->iov_len)
49 : break;
50 0 : off -= iov->iov_len;
51 0 : iol--;
52 0 : iov++;
53 : }
54 0 : while (len > 0) {
55 0 : if (iol == 0)
56 0 : panic("cuio_copydata: empty");
57 0 : count = min(iov->iov_len - off, len);
58 0 : bcopy(((caddr_t)iov->iov_base) + off, cp, count);
59 0 : len -= count;
60 0 : cp += count;
61 : off = 0;
62 0 : iol--;
63 0 : iov++;
64 : }
65 0 : }
66 :
67 : void
68 0 : cuio_copyback(struct uio *uio, int off, int len, const void *_cp)
69 : {
70 0 : struct iovec *iov = uio->uio_iov;
71 0 : int iol = uio->uio_iovcnt;
72 : unsigned count;
73 : caddr_t cp = (caddr_t)_cp;
74 :
75 0 : if (off < 0)
76 0 : panic("cuio_copyback: off %d < 0", off);
77 0 : if (len < 0)
78 0 : panic("cuio_copyback: len %d < 0", len);
79 0 : while (off > 0) {
80 0 : if (iol == 0)
81 0 : panic("cuio_copyback: empty in skip");
82 0 : if (off < iov->iov_len)
83 : break;
84 0 : off -= iov->iov_len;
85 0 : iol--;
86 0 : iov++;
87 : }
88 0 : while (len > 0) {
89 0 : if (iol == 0)
90 0 : panic("uio_copyback: empty");
91 0 : count = min(iov->iov_len - off, len);
92 0 : bcopy(cp, ((caddr_t)iov->iov_base) + off, count);
93 0 : len -= count;
94 0 : cp += count;
95 : off = 0;
96 0 : iol--;
97 0 : iov++;
98 : }
99 0 : }
100 :
101 : int
102 0 : cuio_getptr(struct uio *uio, int loc, int *off)
103 : {
104 : int ind, len;
105 :
106 : ind = 0;
107 0 : while (loc >= 0 && ind < uio->uio_iovcnt) {
108 0 : len = uio->uio_iov[ind].iov_len;
109 0 : if (len > loc) {
110 0 : *off = loc;
111 0 : return (ind);
112 : }
113 0 : loc -= len;
114 0 : ind++;
115 : }
116 :
117 0 : if (ind > 0 && loc == 0) {
118 0 : ind--;
119 0 : *off = uio->uio_iov[ind].iov_len;
120 0 : return (ind);
121 : }
122 :
123 0 : return (-1);
124 0 : }
125 :
126 : int
127 0 : cuio_apply(struct uio *uio, int off, int len,
128 : int (*f)(caddr_t, caddr_t, unsigned int), caddr_t fstate)
129 : {
130 : int rval, ind, uiolen;
131 : unsigned int count;
132 :
133 0 : if (len < 0)
134 0 : panic("cuio_apply: len %d < 0", len);
135 0 : if (off < 0)
136 0 : panic("cuio_apply: off %d < 0", off);
137 :
138 : ind = 0;
139 0 : while (off > 0) {
140 0 : if (ind >= uio->uio_iovcnt)
141 0 : panic("cuio_apply: ind %d >= uio_iovcnt %d for off",
142 : ind, uio->uio_iovcnt);
143 0 : uiolen = uio->uio_iov[ind].iov_len;
144 0 : if (off < uiolen)
145 : break;
146 0 : off -= uiolen;
147 0 : ind++;
148 : }
149 0 : while (len > 0) {
150 0 : if (ind >= uio->uio_iovcnt)
151 0 : panic("cuio_apply: ind %d >= uio_iovcnt %d for len",
152 : ind, uio->uio_iovcnt);
153 0 : count = min(uio->uio_iov[ind].iov_len - off, len);
154 :
155 0 : rval = f(fstate, (char *)uio->uio_iov[ind].iov_base + off,
156 : count);
157 0 : if (rval)
158 0 : return (rval);
159 :
160 0 : len -= count;
161 : off = 0;
162 0 : ind++;
163 : }
164 :
165 0 : return (0);
166 0 : }
|