1 /*
2 * Copyright (c) 1982, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * %sccs.include.redist.c%
11 *
12 * @(#)kern_subr.c 8.4 (Berkeley) 02/14/95
13 */
14
15 #include <sys/param.h>
16 #include <sys/systm.h>
17 #include <sys/proc.h>
18 #include <sys/malloc.h>
19 #include <sys/queue.h>
20
21 int
uiomove(cp,n,uio)22 uiomove(cp, n, uio)
23 register caddr_t cp;
24 register int n;
25 register struct uio *uio;
26 {
27 register struct iovec *iov;
28 u_int cnt;
29 int error = 0;
30
31 #ifdef DIAGNOSTIC
32 if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
33 panic("uiomove: mode");
34 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
35 panic("uiomove proc");
36 #endif
37 while (n > 0 && uio->uio_resid) {
38 iov = uio->uio_iov;
39 cnt = iov->iov_len;
40 if (cnt == 0) {
41 uio->uio_iov++;
42 uio->uio_iovcnt--;
43 continue;
44 }
45 if (cnt > n)
46 cnt = n;
47 switch (uio->uio_segflg) {
48
49 case UIO_USERSPACE:
50 case UIO_USERISPACE:
51 if (uio->uio_rw == UIO_READ)
52 error = copyout(cp, iov->iov_base, cnt);
53 else
54 error = copyin(iov->iov_base, cp, cnt);
55 if (error)
56 return (error);
57 break;
58
59 case UIO_SYSSPACE:
60 if (uio->uio_rw == UIO_READ)
61 bcopy((caddr_t)cp, iov->iov_base, cnt);
62 else
63 bcopy(iov->iov_base, (caddr_t)cp, cnt);
64 break;
65 }
66 iov->iov_base += cnt;
67 iov->iov_len -= cnt;
68 uio->uio_resid -= cnt;
69 uio->uio_offset += cnt;
70 cp += cnt;
71 n -= cnt;
72 }
73 return (error);
74 }
75
76 /*
77 * Give next character to user as result of read.
78 */
79 int
ureadc(c,uio)80 ureadc(c, uio)
81 register int c;
82 register struct uio *uio;
83 {
84 register struct iovec *iov;
85
86 if (uio->uio_resid <= 0)
87 panic("ureadc: non-positive resid");
88 again:
89 if (uio->uio_iovcnt <= 0)
90 panic("ureadc: non-positive iovcnt");
91 iov = uio->uio_iov;
92 if (iov->iov_len <= 0) {
93 uio->uio_iovcnt--;
94 uio->uio_iov++;
95 goto again;
96 }
97 switch (uio->uio_segflg) {
98
99 case UIO_USERSPACE:
100 if (subyte(iov->iov_base, c) < 0)
101 return (EFAULT);
102 break;
103
104 case UIO_SYSSPACE:
105 *iov->iov_base = c;
106 break;
107
108 case UIO_USERISPACE:
109 if (suibyte(iov->iov_base, c) < 0)
110 return (EFAULT);
111 break;
112 }
113 iov->iov_base++;
114 iov->iov_len--;
115 uio->uio_resid--;
116 uio->uio_offset++;
117 return (0);
118 }
119
120 #ifdef vax /* unused except by ct.c, other oddities XXX */
121 /*
122 * Get next character written in by user from uio.
123 */
124 int
uwritec(uio)125 uwritec(uio)
126 struct uio *uio;
127 {
128 register struct iovec *iov;
129 register int c;
130
131 if (uio->uio_resid <= 0)
132 return (-1);
133 again:
134 if (uio->uio_iovcnt <= 0)
135 panic("uwritec: non-positive iovcnt");
136 iov = uio->uio_iov;
137 if (iov->iov_len == 0) {
138 uio->uio_iov++;
139 if (--uio->uio_iovcnt == 0)
140 return (-1);
141 goto again;
142 }
143 switch (uio->uio_segflg) {
144
145 case UIO_USERSPACE:
146 c = fubyte(iov->iov_base);
147 break;
148
149 case UIO_SYSSPACE:
150 c = *(u_char *) iov->iov_base;
151 break;
152
153 case UIO_USERISPACE:
154 c = fuibyte(iov->iov_base);
155 break;
156 }
157 if (c < 0)
158 return (-1);
159 iov->iov_base++;
160 iov->iov_len--;
161 uio->uio_resid--;
162 uio->uio_offset++;
163 return (c);
164 }
165 #endif /* vax */
166
167 /*
168 * General routine to allocate a hash table.
169 */
170 void *
hashinit(elements,type,hashmask)171 hashinit(elements, type, hashmask)
172 int elements, type;
173 u_long *hashmask;
174 {
175 long hashsize;
176 LIST_HEAD(generic, generic) *hashtbl;
177 int i;
178
179 if (elements <= 0)
180 panic("hashinit: bad cnt");
181 for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
182 continue;
183 hashsize >>= 1;
184 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
185 for (i = 0; i < hashsize; i++)
186 LIST_INIT(&hashtbl[i]);
187 *hashmask = hashsize - 1;
188 return (hashtbl);
189 }
190