xref: /original-bsd/sys/kern/kern_subr.c (revision 333da485)
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.3 (Berkeley) 01/21/94
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 uiomove(cp, n, uio)
22 	register caddr_t cp;
23 	register int n;
24 	register struct uio *uio;
25 {
26 	register struct iovec *iov;
27 	u_int cnt;
28 	int error = 0;
29 
30 #ifdef DIAGNOSTIC
31 	if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
32 		panic("uiomove: mode");
33 	if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
34 		panic("uiomove proc");
35 #endif
36 	while (n > 0 && uio->uio_resid) {
37 		iov = uio->uio_iov;
38 		cnt = iov->iov_len;
39 		if (cnt == 0) {
40 			uio->uio_iov++;
41 			uio->uio_iovcnt--;
42 			continue;
43 		}
44 		if (cnt > n)
45 			cnt = n;
46 		switch (uio->uio_segflg) {
47 
48 		case UIO_USERSPACE:
49 		case UIO_USERISPACE:
50 			if (uio->uio_rw == UIO_READ)
51 				error = copyout(cp, iov->iov_base, cnt);
52 			else
53 				error = copyin(iov->iov_base, cp, cnt);
54 			if (error)
55 				return (error);
56 			break;
57 
58 		case UIO_SYSSPACE:
59 			if (uio->uio_rw == UIO_READ)
60 				bcopy((caddr_t)cp, iov->iov_base, cnt);
61 			else
62 				bcopy(iov->iov_base, (caddr_t)cp, cnt);
63 			break;
64 		}
65 		iov->iov_base += cnt;
66 		iov->iov_len -= cnt;
67 		uio->uio_resid -= cnt;
68 		uio->uio_offset += cnt;
69 		cp += cnt;
70 		n -= cnt;
71 	}
72 	return (error);
73 }
74 
75 /*
76  * Give next character to user as result of read.
77  */
78 ureadc(c, uio)
79 	register int c;
80 	register struct uio *uio;
81 {
82 	register struct iovec *iov;
83 
84 again:
85 	if (uio->uio_iovcnt == 0 || uio->uio_resid == 0)
86 		panic("ureadc");
87 	iov = uio->uio_iov;
88 	if (iov->iov_len == 0) {
89 		uio->uio_iovcnt--;
90 		uio->uio_iov++;
91 		goto again;
92 	}
93 	switch (uio->uio_segflg) {
94 
95 	case UIO_USERSPACE:
96 		if (subyte(iov->iov_base, c) < 0)
97 			return (EFAULT);
98 		break;
99 
100 	case UIO_SYSSPACE:
101 		*iov->iov_base = c;
102 		break;
103 
104 	case UIO_USERISPACE:
105 		if (suibyte(iov->iov_base, c) < 0)
106 			return (EFAULT);
107 		break;
108 	}
109 	iov->iov_base++;
110 	iov->iov_len--;
111 	uio->uio_resid--;
112 	uio->uio_offset++;
113 	return (0);
114 }
115 
116 #ifdef vax	/* unused except by ct.c, other oddities XXX */
117 /*
118  * Get next character written in by user from uio.
119  */
120 uwritec(uio)
121 	struct uio *uio;
122 {
123 	register struct iovec *iov;
124 	register int c;
125 
126 	if (uio->uio_resid <= 0)
127 		return (-1);
128 again:
129 	if (uio->uio_iovcnt <= 0)
130 		panic("uwritec");
131 	iov = uio->uio_iov;
132 	if (iov->iov_len == 0) {
133 		uio->uio_iov++;
134 		if (--uio->uio_iovcnt == 0)
135 			return (-1);
136 		goto again;
137 	}
138 	switch (uio->uio_segflg) {
139 
140 	case UIO_USERSPACE:
141 		c = fubyte(iov->iov_base);
142 		break;
143 
144 	case UIO_SYSSPACE:
145 		c = *(u_char *) iov->iov_base;
146 		break;
147 
148 	case UIO_USERISPACE:
149 		c = fuibyte(iov->iov_base);
150 		break;
151 	}
152 	if (c < 0)
153 		return (-1);
154 	iov->iov_base++;
155 	iov->iov_len--;
156 	uio->uio_resid--;
157 	uio->uio_offset++;
158 	return (c);
159 }
160 #endif /* vax */
161 
162 /*
163  * General routine to allocate a hash table.
164  */
165 void *
166 hashinit(elements, type, hashmask)
167 	int elements, type;
168 	u_long *hashmask;
169 {
170 	long hashsize;
171 	LIST_HEAD(generic, generic) *hashtbl;
172 	int i;
173 
174 	if (elements <= 0)
175 		panic("hashinit: bad cnt");
176 	for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
177 		continue;
178 	hashsize >>= 1;
179 	hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
180 	for (i = 0; i < hashsize; i++)
181 		LIST_INIT(&hashtbl[i]);
182 	*hashmask = hashsize - 1;
183 	return (hashtbl);
184 }
185