xref: /csrg-svn/sys/kern/kern_subr.c (revision 56517)
123375Smckusick /*
247540Skarels  * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
352497Storek  * All rights reserved.
423375Smckusick  *
547540Skarels  * %sccs.include.redist.c%
647540Skarels  *
7*56517Sbostic  *	@(#)kern_subr.c	7.11 (Berkeley) 10/11/92
823375Smckusick  */
912792Ssam 
10*56517Sbostic #include <sys/param.h>
11*56517Sbostic #include <sys/systm.h>
12*56517Sbostic #include <sys/proc.h>
13*56517Sbostic #include <sys/malloc.h>
1412792Ssam 
1537728Smckusick uiomove(cp, n, uio)
1612792Ssam 	register caddr_t cp;
1712792Ssam 	register int n;
1812792Ssam 	register struct uio *uio;
1912792Ssam {
2012792Ssam 	register struct iovec *iov;
2112792Ssam 	u_int cnt;
2212792Ssam 	int error = 0;
2312792Ssam 
2448016Smckusick #ifdef DIAGNOSTIC
2537728Smckusick 	if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
2637728Smckusick 		panic("uiomove: mode");
2748016Smckusick 	if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
2848016Smckusick 		panic("uiomove proc");
2948016Smckusick #endif
3012792Ssam 	while (n > 0 && uio->uio_resid) {
3112792Ssam 		iov = uio->uio_iov;
3212792Ssam 		cnt = iov->iov_len;
3312792Ssam 		if (cnt == 0) {
3412792Ssam 			uio->uio_iov++;
3512792Ssam 			uio->uio_iovcnt--;
3612792Ssam 			continue;
3712792Ssam 		}
3812792Ssam 		if (cnt > n)
3912792Ssam 			cnt = n;
4012792Ssam 		switch (uio->uio_segflg) {
4112792Ssam 
4216704Smckusick 		case UIO_USERSPACE:
4316704Smckusick 		case UIO_USERISPACE:
4437728Smckusick 			if (uio->uio_rw == UIO_READ)
4512792Ssam 				error = copyout(cp, iov->iov_base, cnt);
4612792Ssam 			else
4712792Ssam 				error = copyin(iov->iov_base, cp, cnt);
4812792Ssam 			if (error)
4912792Ssam 				return (error);
5012792Ssam 			break;
5112792Ssam 
5216704Smckusick 		case UIO_SYSSPACE:
5337728Smckusick 			if (uio->uio_rw == UIO_READ)
5412792Ssam 				bcopy((caddr_t)cp, iov->iov_base, cnt);
5512792Ssam 			else
5612792Ssam 				bcopy(iov->iov_base, (caddr_t)cp, cnt);
5712792Ssam 			break;
5812792Ssam 		}
5912792Ssam 		iov->iov_base += cnt;
6012792Ssam 		iov->iov_len -= cnt;
6112792Ssam 		uio->uio_resid -= cnt;
6212792Ssam 		uio->uio_offset += cnt;
6312792Ssam 		cp += cnt;
6412792Ssam 		n -= cnt;
6512792Ssam 	}
6612792Ssam 	return (error);
6712792Ssam }
6812792Ssam 
6912792Ssam /*
7012792Ssam  * Give next character to user as result of read.
7112792Ssam  */
7212792Ssam ureadc(c, uio)
7312792Ssam 	register int c;
7412792Ssam 	register struct uio *uio;
7512792Ssam {
7612792Ssam 	register struct iovec *iov;
7712792Ssam 
7812792Ssam again:
7912792Ssam 	if (uio->uio_iovcnt == 0)
8012792Ssam 		panic("ureadc");
8112792Ssam 	iov = uio->uio_iov;
8212792Ssam 	if (iov->iov_len <= 0 || uio->uio_resid <= 0) {
8312792Ssam 		uio->uio_iovcnt--;
8412792Ssam 		uio->uio_iov++;
8512792Ssam 		goto again;
8612792Ssam 	}
8712792Ssam 	switch (uio->uio_segflg) {
8812792Ssam 
8916704Smckusick 	case UIO_USERSPACE:
9012792Ssam 		if (subyte(iov->iov_base, c) < 0)
9112792Ssam 			return (EFAULT);
9212792Ssam 		break;
9312792Ssam 
9416704Smckusick 	case UIO_SYSSPACE:
9512792Ssam 		*iov->iov_base = c;
9612792Ssam 		break;
9712792Ssam 
9816704Smckusick 	case UIO_USERISPACE:
9912792Ssam 		if (suibyte(iov->iov_base, c) < 0)
10012792Ssam 			return (EFAULT);
10112792Ssam 		break;
10212792Ssam 	}
10312792Ssam 	iov->iov_base++;
10412792Ssam 	iov->iov_len--;
10512792Ssam 	uio->uio_resid--;
10612792Ssam 	uio->uio_offset++;
10712792Ssam 	return (0);
10812792Ssam }
10912792Ssam 
11052497Storek #ifdef vax	/* unused except by ct.c, other oddities XXX */
11112792Ssam /*
11212792Ssam  * Get next character written in by user from uio.
11312792Ssam  */
11412792Ssam uwritec(uio)
11512792Ssam 	struct uio *uio;
11612792Ssam {
11712792Ssam 	register struct iovec *iov;
11812792Ssam 	register int c;
11912792Ssam 
12027235Skarels 	if (uio->uio_resid <= 0)
12127235Skarels 		return (-1);
12212792Ssam again:
12327235Skarels 	if (uio->uio_iovcnt <= 0)
12412792Ssam 		panic("uwritec");
12512792Ssam 	iov = uio->uio_iov;
12612792Ssam 	if (iov->iov_len == 0) {
12712792Ssam 		uio->uio_iov++;
12827235Skarels 		if (--uio->uio_iovcnt == 0)
12927235Skarels 			return (-1);
13012792Ssam 		goto again;
13112792Ssam 	}
13212792Ssam 	switch (uio->uio_segflg) {
13312792Ssam 
13416704Smckusick 	case UIO_USERSPACE:
13512792Ssam 		c = fubyte(iov->iov_base);
13612792Ssam 		break;
13712792Ssam 
13816704Smckusick 	case UIO_SYSSPACE:
13947540Skarels 		c = *(u_char *) iov->iov_base;
14012792Ssam 		break;
14112792Ssam 
14216704Smckusick 	case UIO_USERISPACE:
14312792Ssam 		c = fuibyte(iov->iov_base);
14412792Ssam 		break;
14512792Ssam 	}
14612792Ssam 	if (c < 0)
14712792Ssam 		return (-1);
14812792Ssam 	iov->iov_base++;
14912792Ssam 	iov->iov_len--;
15012792Ssam 	uio->uio_resid--;
15112792Ssam 	uio->uio_offset++;
15247540Skarels 	return (c);
15312792Ssam }
15452497Storek #endif /* vax */
15555404Smckusick 
15655404Smckusick /*
15755404Smckusick  * General routine to allocate a hash table.
15855404Smckusick  */
15955404Smckusick void *
16055404Smckusick hashinit(elements, type, hashmask)
16155404Smckusick 	int elements, type;
16255404Smckusick 	u_long *hashmask;
16355404Smckusick {
16455404Smckusick 	long hashsize;
16555404Smckusick 	void *hashtbl;
16655404Smckusick 
16755404Smckusick 	if (elements <= 0)
16855404Smckusick 		panic("hashinit: bad cnt");
16955404Smckusick 	for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
17055404Smckusick 		continue;
17155404Smckusick 	hashsize >>= 1;
17255404Smckusick 	hashtbl = malloc((u_long)hashsize * sizeof(void *), type, M_WAITOK);
17355404Smckusick 	bzero(hashtbl, hashsize * sizeof(void *));
17455404Smckusick 	*hashmask = hashsize - 1;
17555404Smckusick 	return (hashtbl);
17655404Smckusick }
177