xref: /illumos-gate/usr/src/lib/libfakekernel/common/uio.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
14  */
15 
16 #include <sys/types.h>
17 #include <sys/sysmacros.h>
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/uio.h>
21 #include <sys/errno.h>
22 
23 /*
24  * Move "n" bytes at byte address "p"; "rw" indicates the direction
25  * of the move, and the I/O parameters are provided in "uio", which is
26  * update to reflect the data which was moved.  Returns 0 on success or
27  * a non-zero errno on failure.
28  */
29 int
30 uiomove(void *p, size_t n, enum uio_rw rw, struct uio *uio)
31 {
32 	struct iovec *iov;
33 	ulong_t cnt;
34 
35 	while (n && uio->uio_resid) {
36 		iov = uio->uio_iov;
37 		cnt = MIN(iov->iov_len, n);
38 		if (cnt == 0L) {
39 			uio->uio_iov++;
40 			uio->uio_iovcnt--;
41 			continue;
42 		}
43 		switch (uio->uio_segflg) {
44 
45 		case UIO_USERISPACE:
46 			return (EINVAL);
47 
48 		case UIO_USERSPACE:
49 		case UIO_SYSSPACE:
50 			if (rw == UIO_READ)
51 				bcopy(p, iov->iov_base, cnt);
52 			else
53 				bcopy(iov->iov_base, p, cnt);
54 			break;
55 		}
56 		iov->iov_base += cnt;
57 		iov->iov_len -= cnt;
58 		uio->uio_resid -= cnt;
59 		uio->uio_loffset += cnt;
60 		p = (caddr_t)p + cnt;
61 		n -= cnt;
62 	}
63 	return (0);
64 }
65 
66 /*
67  * Drop the next n chars out of *uiop.
68  */
69 void
70 uioskip(uio_t *uiop, size_t n)
71 {
72 	if (n > uiop->uio_resid)
73 		return;
74 	while (n != 0) {
75 		iovec_t	*iovp = uiop->uio_iov;
76 		size_t	niovb = MIN(iovp->iov_len, n);
77 
78 		if (niovb == 0) {
79 			uiop->uio_iov++;
80 			uiop->uio_iovcnt--;
81 			continue;
82 		}
83 		iovp->iov_base += niovb;
84 		uiop->uio_loffset += niovb;
85 		iovp->iov_len -= niovb;
86 		uiop->uio_resid -= niovb;
87 		n -= niovb;
88 	}
89 }
90