xref: /csrg-svn/sys/kern/kern_subr.c (revision 27235)
123375Smckusick /*
223375Smckusick  * Copyright (c) 1982 Regents of the University of California.
323375Smckusick  * All rights reserved.  The Berkeley software License Agreement
423375Smckusick  * specifies the terms and conditions for redistribution.
523375Smckusick  *
6*27235Skarels  *	@(#)kern_subr.c	6.5 (Berkeley) 04/21/86
723375Smckusick  */
812792Ssam 
917093Sbloom #include "param.h"
1017093Sbloom #include "systm.h"
1117093Sbloom #include "dir.h"
1217093Sbloom #include "user.h"
1317093Sbloom #include "uio.h"
1412792Ssam 
1512792Ssam uiomove(cp, n, rw, uio)
1612792Ssam 	register caddr_t cp;
1712792Ssam 	register int n;
1812792Ssam 	enum uio_rw rw;
1912792Ssam 	register struct uio *uio;
2012792Ssam {
2112792Ssam 	register struct iovec *iov;
2212792Ssam 	u_int cnt;
2312792Ssam 	int error = 0;
2412792Ssam 
2512792Ssam 	while (n > 0 && uio->uio_resid) {
2612792Ssam 		iov = uio->uio_iov;
2712792Ssam 		cnt = iov->iov_len;
2812792Ssam 		if (cnt == 0) {
2912792Ssam 			uio->uio_iov++;
3012792Ssam 			uio->uio_iovcnt--;
3112792Ssam 			continue;
3212792Ssam 		}
3312792Ssam 		if (cnt > n)
3412792Ssam 			cnt = n;
3512792Ssam 		switch (uio->uio_segflg) {
3612792Ssam 
3716704Smckusick 		case UIO_USERSPACE:
3816704Smckusick 		case UIO_USERISPACE:
3912792Ssam 			if (rw == UIO_READ)
4012792Ssam 				error = copyout(cp, iov->iov_base, cnt);
4112792Ssam 			else
4212792Ssam 				error = copyin(iov->iov_base, cp, cnt);
4312792Ssam 			if (error)
4412792Ssam 				return (error);
4512792Ssam 			break;
4612792Ssam 
4716704Smckusick 		case UIO_SYSSPACE:
4812792Ssam 			if (rw == UIO_READ)
4912792Ssam 				bcopy((caddr_t)cp, iov->iov_base, cnt);
5012792Ssam 			else
5112792Ssam 				bcopy(iov->iov_base, (caddr_t)cp, cnt);
5212792Ssam 			break;
5312792Ssam 		}
5412792Ssam 		iov->iov_base += cnt;
5512792Ssam 		iov->iov_len -= cnt;
5612792Ssam 		uio->uio_resid -= cnt;
5712792Ssam 		uio->uio_offset += cnt;
5812792Ssam 		cp += cnt;
5912792Ssam 		n -= cnt;
6012792Ssam 	}
6112792Ssam 	return (error);
6212792Ssam }
6312792Ssam 
6412792Ssam /*
6512792Ssam  * Give next character to user as result of read.
6612792Ssam  */
6712792Ssam ureadc(c, uio)
6812792Ssam 	register int c;
6912792Ssam 	register struct uio *uio;
7012792Ssam {
7112792Ssam 	register struct iovec *iov;
7212792Ssam 
7312792Ssam again:
7412792Ssam 	if (uio->uio_iovcnt == 0)
7512792Ssam 		panic("ureadc");
7612792Ssam 	iov = uio->uio_iov;
7712792Ssam 	if (iov->iov_len <= 0 || uio->uio_resid <= 0) {
7812792Ssam 		uio->uio_iovcnt--;
7912792Ssam 		uio->uio_iov++;
8012792Ssam 		goto again;
8112792Ssam 	}
8212792Ssam 	switch (uio->uio_segflg) {
8312792Ssam 
8416704Smckusick 	case UIO_USERSPACE:
8512792Ssam 		if (subyte(iov->iov_base, c) < 0)
8612792Ssam 			return (EFAULT);
8712792Ssam 		break;
8812792Ssam 
8916704Smckusick 	case UIO_SYSSPACE:
9012792Ssam 		*iov->iov_base = c;
9112792Ssam 		break;
9212792Ssam 
9316704Smckusick 	case UIO_USERISPACE:
9412792Ssam 		if (suibyte(iov->iov_base, c) < 0)
9512792Ssam 			return (EFAULT);
9612792Ssam 		break;
9712792Ssam 	}
9812792Ssam 	iov->iov_base++;
9912792Ssam 	iov->iov_len--;
10012792Ssam 	uio->uio_resid--;
10112792Ssam 	uio->uio_offset++;
10212792Ssam 	return (0);
10312792Ssam }
10412792Ssam 
10512792Ssam /*
10612792Ssam  * Get next character written in by user from uio.
10712792Ssam  */
10812792Ssam uwritec(uio)
10912792Ssam 	struct uio *uio;
11012792Ssam {
11112792Ssam 	register struct iovec *iov;
11212792Ssam 	register int c;
11312792Ssam 
114*27235Skarels 	if (uio->uio_resid <= 0)
115*27235Skarels 		return (-1);
11612792Ssam again:
117*27235Skarels 	if (uio->uio_iovcnt <= 0)
11812792Ssam 		panic("uwritec");
11912792Ssam 	iov = uio->uio_iov;
12012792Ssam 	if (iov->iov_len == 0) {
12112792Ssam 		uio->uio_iov++;
122*27235Skarels 		if (--uio->uio_iovcnt == 0)
123*27235Skarels 			return (-1);
12412792Ssam 		goto again;
12512792Ssam 	}
12612792Ssam 	switch (uio->uio_segflg) {
12712792Ssam 
12816704Smckusick 	case UIO_USERSPACE:
12912792Ssam 		c = fubyte(iov->iov_base);
13012792Ssam 		break;
13112792Ssam 
13216704Smckusick 	case UIO_SYSSPACE:
13312792Ssam 		c = *iov->iov_base & 0377;
13412792Ssam 		break;
13512792Ssam 
13616704Smckusick 	case UIO_USERISPACE:
13712792Ssam 		c = fuibyte(iov->iov_base);
13812792Ssam 		break;
13912792Ssam 	}
14012792Ssam 	if (c < 0)
14112792Ssam 		return (-1);
14212792Ssam 	iov->iov_base++;
14312792Ssam 	iov->iov_len--;
14412792Ssam 	uio->uio_resid--;
14512792Ssam 	uio->uio_offset++;
14612792Ssam 	return (c & 0377);
14712792Ssam }
148