rumpcopy.c revision 1.9 1 /* $NetBSD: rumpcopy.c,v 1.9 2010/11/09 20:55:14 pooka Exp $ */
2
3 /*
4 * Copyright (c) 2009 Antti Kantee. All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: rumpcopy.c,v 1.9 2010/11/09 20:55:14 pooka Exp $");
30
31 #include <sys/param.h>
32 #include <sys/lwp.h>
33 #include <sys/systm.h>
34
35 #include <rump/rump.h>
36
37 #include "rump_private.h"
38
39 int
40 copyin(const void *uaddr, void *kaddr, size_t len)
41 {
42
43 if (__predict_false(uaddr == NULL && len)) {
44 return EFAULT;
45 }
46
47 if (curproc->p_vmspace == &vmspace0) {
48 memcpy(kaddr, uaddr, len);
49 } else {
50 rumpuser_sp_copyin(uaddr, kaddr, len);
51 }
52 return 0;
53 }
54
55 int
56 copyout(const void *kaddr, void *uaddr, size_t len)
57 {
58
59 if (__predict_false(uaddr == NULL && len)) {
60 return EFAULT;
61 }
62
63 if (curproc->p_vmspace == &vmspace0) {
64 memcpy(uaddr, kaddr, len);
65 } else {
66 rumpuser_sp_copyout(kaddr, uaddr, len);
67 }
68 return 0;
69 }
70
71 int
72 subyte(void *uaddr, int byte)
73 {
74
75 if (curproc->p_vmspace == &vmspace0)
76 *(char *)uaddr = byte;
77 else
78 rumpuser_sp_copyout(&byte, uaddr, 1);
79 return 0;
80 }
81
82 int
83 copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done)
84 {
85 uint8_t *to = kdaddr;
86 const uint8_t *from = kfaddr;
87 size_t actlen = 0;
88
89 while (len-- > 0 && (*to++ = *from++) != 0)
90 actlen++;
91
92 if (len+1 == 0 && *(to-1) != 0)
93 return ENAMETOOLONG;
94
95 if (done)
96 *done = actlen+1; /* + '\0' */
97 return 0;
98 }
99
100 int
101 copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
102 {
103 uint8_t *to;
104 int rv;
105
106 if (len == 0)
107 return 0;
108
109 if (curproc->p_vmspace == &vmspace0)
110 return copystr(uaddr, kaddr, len, done);
111
112 if ((rv = rumpuser_sp_copyin(uaddr, kaddr, len)) != 0)
113 return rv;
114
115 /* figure out if we got a terminated string or not */
116 to = (uint8_t *)kaddr + (len-1);
117 while (to != kaddr) {
118 if (*to == 0)
119 goto found;
120 to--;
121 }
122 return ENAMETOOLONG;
123
124 found:
125 if (done)
126 *done = strlen(kaddr)+1; /* includes termination */
127
128 return 0;
129 }
130
131 int
132 copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done)
133 {
134 size_t slen;
135
136 if (curproc->p_vmspace == &vmspace0)
137 return copystr(kaddr, uaddr, len, done);
138
139 slen = strlen(kaddr)+1;
140 if (slen > len)
141 return ENAMETOOLONG;
142
143 rumpuser_sp_copyout(kaddr, uaddr, slen);
144 if (done)
145 *done = slen;
146
147 return 0;
148 }
149
150 int
151 kcopy(const void *src, void *dst, size_t len)
152 {
153
154 memcpy(dst, src, len);
155 return 0;
156 }
157