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