xref: /csrg-svn/sys/kern/kern_subr.c (revision 65771)
123375Smckusick /*
263176Sbostic  * Copyright (c) 1982, 1986, 1991, 1993
363176Sbostic  *	The Regents of the University of California.  All rights reserved.
4*65771Sbostic  * (c) UNIX System Laboratories, Inc.
5*65771Sbostic  * All or some portions of this file are derived from material licensed
6*65771Sbostic  * to the University of California by American Telephone and Telegraph
7*65771Sbostic  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8*65771Sbostic  * the permission of UNIX System Laboratories, Inc.
923375Smckusick  *
1047540Skarels  * %sccs.include.redist.c%
1147540Skarels  *
12*65771Sbostic  *	@(#)kern_subr.c	8.3 (Berkeley) 01/21/94
1323375Smckusick  */
1412792Ssam 
1556517Sbostic #include <sys/param.h>
1656517Sbostic #include <sys/systm.h>
1756517Sbostic #include <sys/proc.h>
1856517Sbostic #include <sys/malloc.h>
1965257Smckusick #include <sys/queue.h>
2012792Ssam 
2137728Smckusick uiomove(cp, n, uio)
2212792Ssam 	register caddr_t cp;
2312792Ssam 	register int n;
2412792Ssam 	register struct uio *uio;
2512792Ssam {
2612792Ssam 	register struct iovec *iov;
2712792Ssam 	u_int cnt;
2812792Ssam 	int error = 0;
2912792Ssam 
3048016Smckusick #ifdef DIAGNOSTIC
3137728Smckusick 	if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
3237728Smckusick 		panic("uiomove: mode");
3348016Smckusick 	if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
3448016Smckusick 		panic("uiomove proc");
3548016Smckusick #endif
3612792Ssam 	while (n > 0 && uio->uio_resid) {
3712792Ssam 		iov = uio->uio_iov;
3812792Ssam 		cnt = iov->iov_len;
3912792Ssam 		if (cnt == 0) {
4012792Ssam 			uio->uio_iov++;
4112792Ssam 			uio->uio_iovcnt--;
4212792Ssam 			continue;
4312792Ssam 		}
4412792Ssam 		if (cnt > n)
4512792Ssam 			cnt = n;
4612792Ssam 		switch (uio->uio_segflg) {
4712792Ssam 
4816704Smckusick 		case UIO_USERSPACE:
4916704Smckusick 		case UIO_USERISPACE:
5037728Smckusick 			if (uio->uio_rw == UIO_READ)
5112792Ssam 				error = copyout(cp, iov->iov_base, cnt);
5212792Ssam 			else
5312792Ssam 				error = copyin(iov->iov_base, cp, cnt);
5412792Ssam 			if (error)
5512792Ssam 				return (error);
5612792Ssam 			break;
5712792Ssam 
5816704Smckusick 		case UIO_SYSSPACE:
5937728Smckusick 			if (uio->uio_rw == UIO_READ)
6012792Ssam 				bcopy((caddr_t)cp, iov->iov_base, cnt);
6112792Ssam 			else
6212792Ssam 				bcopy(iov->iov_base, (caddr_t)cp, cnt);
6312792Ssam 			break;
6412792Ssam 		}
6512792Ssam 		iov->iov_base += cnt;
6612792Ssam 		iov->iov_len -= cnt;
6712792Ssam 		uio->uio_resid -= cnt;
6812792Ssam 		uio->uio_offset += cnt;
6912792Ssam 		cp += cnt;
7012792Ssam 		n -= cnt;
7112792Ssam 	}
7212792Ssam 	return (error);
7312792Ssam }
7412792Ssam 
7512792Ssam /*
7612792Ssam  * Give next character to user as result of read.
7712792Ssam  */
7812792Ssam ureadc(c, uio)
7912792Ssam 	register int c;
8012792Ssam 	register struct uio *uio;
8112792Ssam {
8212792Ssam 	register struct iovec *iov;
8312792Ssam 
8412792Ssam again:
8557729Smckusick 	if (uio->uio_iovcnt == 0 || uio->uio_resid == 0)
8612792Ssam 		panic("ureadc");
8712792Ssam 	iov = uio->uio_iov;
8857729Smckusick 	if (iov->iov_len == 0) {
8912792Ssam 		uio->uio_iovcnt--;
9012792Ssam 		uio->uio_iov++;
9112792Ssam 		goto again;
9212792Ssam 	}
9312792Ssam 	switch (uio->uio_segflg) {
9412792Ssam 
9516704Smckusick 	case UIO_USERSPACE:
9612792Ssam 		if (subyte(iov->iov_base, c) < 0)
9712792Ssam 			return (EFAULT);
9812792Ssam 		break;
9912792Ssam 
10016704Smckusick 	case UIO_SYSSPACE:
10112792Ssam 		*iov->iov_base = c;
10212792Ssam 		break;
10312792Ssam 
10416704Smckusick 	case UIO_USERISPACE:
10512792Ssam 		if (suibyte(iov->iov_base, c) < 0)
10612792Ssam 			return (EFAULT);
10712792Ssam 		break;
10812792Ssam 	}
10912792Ssam 	iov->iov_base++;
11012792Ssam 	iov->iov_len--;
11112792Ssam 	uio->uio_resid--;
11212792Ssam 	uio->uio_offset++;
11312792Ssam 	return (0);
11412792Ssam }
11512792Ssam 
11652497Storek #ifdef vax	/* unused except by ct.c, other oddities XXX */
11712792Ssam /*
11812792Ssam  * Get next character written in by user from uio.
11912792Ssam  */
12012792Ssam uwritec(uio)
12112792Ssam 	struct uio *uio;
12212792Ssam {
12312792Ssam 	register struct iovec *iov;
12412792Ssam 	register int c;
12512792Ssam 
12627235Skarels 	if (uio->uio_resid <= 0)
12727235Skarels 		return (-1);
12812792Ssam again:
12927235Skarels 	if (uio->uio_iovcnt <= 0)
13012792Ssam 		panic("uwritec");
13112792Ssam 	iov = uio->uio_iov;
13212792Ssam 	if (iov->iov_len == 0) {
13312792Ssam 		uio->uio_iov++;
13427235Skarels 		if (--uio->uio_iovcnt == 0)
13527235Skarels 			return (-1);
13612792Ssam 		goto again;
13712792Ssam 	}
13812792Ssam 	switch (uio->uio_segflg) {
13912792Ssam 
14016704Smckusick 	case UIO_USERSPACE:
14112792Ssam 		c = fubyte(iov->iov_base);
14212792Ssam 		break;
14312792Ssam 
14416704Smckusick 	case UIO_SYSSPACE:
14547540Skarels 		c = *(u_char *) iov->iov_base;
14612792Ssam 		break;
14712792Ssam 
14816704Smckusick 	case UIO_USERISPACE:
14912792Ssam 		c = fuibyte(iov->iov_base);
15012792Ssam 		break;
15112792Ssam 	}
15212792Ssam 	if (c < 0)
15312792Ssam 		return (-1);
15412792Ssam 	iov->iov_base++;
15512792Ssam 	iov->iov_len--;
15612792Ssam 	uio->uio_resid--;
15712792Ssam 	uio->uio_offset++;
15847540Skarels 	return (c);
15912792Ssam }
16052497Storek #endif /* vax */
16155404Smckusick 
16255404Smckusick /*
16355404Smckusick  * General routine to allocate a hash table.
16455404Smckusick  */
16555404Smckusick void *
16655404Smckusick hashinit(elements, type, hashmask)
16755404Smckusick 	int elements, type;
16855404Smckusick 	u_long *hashmask;
16955404Smckusick {
17055404Smckusick 	long hashsize;
17165257Smckusick 	LIST_HEAD(generic, generic) *hashtbl;
17265257Smckusick 	int i;
17355404Smckusick 
17455404Smckusick 	if (elements <= 0)
17555404Smckusick 		panic("hashinit: bad cnt");
17655404Smckusick 	for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
17755404Smckusick 		continue;
17855404Smckusick 	hashsize >>= 1;
17965257Smckusick 	hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
18065257Smckusick 	for (i = 0; i < hashsize; i++)
18165257Smckusick 		LIST_INIT(&hashtbl[i]);
18255404Smckusick 	*hashmask = hashsize - 1;
18355404Smckusick 	return (hashtbl);
18455404Smckusick }
185