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