xref: /original-bsd/sys/kern/kern_subr.c (revision 27393bdf)
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
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
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
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 *
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