Deleted Added
full compact
freebsd32_misc.c (113859) freebsd32_misc.c (114987)
1/*-
2 * Copyright (c) 2002 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 2002 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 113859 2003-04-22 18:23:49Z jhb $
26 * $FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 114987 2003-05-14 04:10:49Z peter $
27 */
28
29#include "opt_compat.h"
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/bus.h>
34#include <sys/exec.h>
35#include <sys/fcntl.h>
36#include <sys/filedesc.h>
37#include <sys/imgact.h>
38#include <sys/kernel.h>
39#include <sys/lock.h>
40#include <sys/malloc.h>
41#include <sys/file.h> /* Must come after sys/malloc.h */
42#include <sys/mman.h>
43#include <sys/module.h>
44#include <sys/mount.h>
45#include <sys/mutex.h>
46#include <sys/namei.h>
47#include <sys/param.h>
48#include <sys/proc.h>
49#include <sys/reboot.h>
50#include <sys/resource.h>
51#include <sys/resourcevar.h>
52#include <sys/selinfo.h>
53#include <sys/pipe.h> /* Must come after sys/selinfo.h */
54#include <sys/signal.h>
55#include <sys/signalvar.h>
56#include <sys/socket.h>
57#include <sys/socketvar.h>
58#include <sys/stat.h>
59#include <sys/syscallsubr.h>
60#include <sys/sysctl.h>
61#include <sys/sysent.h>
62#include <sys/sysproto.h>
63#include <sys/systm.h>
64#include <sys/unistd.h>
65#include <sys/user.h>
66#include <sys/utsname.h>
67#include <sys/vnode.h>
68
69#include <vm/vm.h>
70#include <vm/vm_kern.h>
71#include <vm/vm_param.h>
72#include <vm/pmap.h>
73#include <vm/vm_map.h>
74#include <vm/vm_object.h>
75#include <vm/vm_extern.h>
76
27 */
28
29#include "opt_compat.h"
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/bus.h>
34#include <sys/exec.h>
35#include <sys/fcntl.h>
36#include <sys/filedesc.h>
37#include <sys/imgact.h>
38#include <sys/kernel.h>
39#include <sys/lock.h>
40#include <sys/malloc.h>
41#include <sys/file.h> /* Must come after sys/malloc.h */
42#include <sys/mman.h>
43#include <sys/module.h>
44#include <sys/mount.h>
45#include <sys/mutex.h>
46#include <sys/namei.h>
47#include <sys/param.h>
48#include <sys/proc.h>
49#include <sys/reboot.h>
50#include <sys/resource.h>
51#include <sys/resourcevar.h>
52#include <sys/selinfo.h>
53#include <sys/pipe.h> /* Must come after sys/selinfo.h */
54#include <sys/signal.h>
55#include <sys/signalvar.h>
56#include <sys/socket.h>
57#include <sys/socketvar.h>
58#include <sys/stat.h>
59#include <sys/syscallsubr.h>
60#include <sys/sysctl.h>
61#include <sys/sysent.h>
62#include <sys/sysproto.h>
63#include <sys/systm.h>
64#include <sys/unistd.h>
65#include <sys/user.h>
66#include <sys/utsname.h>
67#include <sys/vnode.h>
68
69#include <vm/vm.h>
70#include <vm/vm_kern.h>
71#include <vm/vm_param.h>
72#include <vm/pmap.h>
73#include <vm/vm_map.h>
74#include <vm/vm_object.h>
75#include <vm/vm_extern.h>
76
77#include <ia64/ia32/ia32_util.h>
78#include <ia64/ia32/ia32.h>
79#include <ia64/ia32/ia32_proto.h>
77#include <amd64/ia32/ia32_util.h>
78#include <amd64/ia32/ia32.h>
79#include <amd64/ia32/ia32_proto.h>
80
81static const char ia32_emul_path[] = "/compat/ia32";
82/*
83 * [ taken from the linux emulator ]
84 * Search an alternate path before passing pathname arguments on
85 * to system calls. Useful for keeping a separate 'emulation tree'.
86 *
87 * If cflag is set, we check if an attempt can be made to create
88 * the named file, i.e. we check if the directory it should
89 * be in exists.
90 */
91int
92ia32_emul_find(td, sgp, prefix, path, pbuf, cflag)
93 struct thread *td;
94 caddr_t *sgp; /* Pointer to stackgap memory */
95 const char *prefix;
96 char *path;
97 char **pbuf;
98 int cflag;
99{
100 int error;
101 size_t len, sz;
102 char *buf, *cp, *ptr;
103 struct ucred *ucred;
104 struct nameidata nd;
105 struct nameidata ndroot;
106 struct vattr vat;
107 struct vattr vatroot;
108
109 buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
110 *pbuf = path;
111
112 for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
113 continue;
114
115 sz = MAXPATHLEN - (ptr - buf);
116
117 /*
118 * If sgp is not given then the path is already in kernel space
119 */
120 if (sgp == NULL)
121 error = copystr(path, ptr, sz, &len);
122 else
123 error = copyinstr(path, ptr, sz, &len);
124
125 if (error) {
126 free(buf, M_TEMP);
127 return error;
128 }
129
130 if (*ptr != '/') {
131 free(buf, M_TEMP);
132 return EINVAL;
133 }
134
135 /*
136 * We know that there is a / somewhere in this pathname.
137 * Search backwards for it, to find the file's parent dir
138 * to see if it exists in the alternate tree. If it does,
139 * and we want to create a file (cflag is set). We don't
140 * need to worry about the root comparison in this case.
141 */
142
143 if (cflag) {
144 for (cp = &ptr[len] - 1; *cp != '/'; cp--)
145 ;
146 *cp = '\0';
147
148 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
149
150 if ((error = namei(&nd)) != 0) {
151 free(buf, M_TEMP);
152 return error;
153 }
154
155 *cp = '/';
156 } else {
157 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
158
159 if ((error = namei(&nd)) != 0) {
160 free(buf, M_TEMP);
161 return error;
162 }
163
164 /*
165 * We now compare the vnode of the ia32_root to the one
166 * vnode asked. If they resolve to be the same, then we
167 * ignore the match so that the real root gets used.
168 * This avoids the problem of traversing "../.." to find the
169 * root directory and never finding it, because "/" resolves
170 * to the emulation root directory. This is expensive :-(
171 */
172 NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path,
173 td);
174
175 if ((error = namei(&ndroot)) != 0) {
176 /* Cannot happen! */
177 free(buf, M_TEMP);
178 vrele(nd.ni_vp);
179 return error;
180 }
181
182 ucred = td->td_ucred;
183 if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
184 goto bad;
185 }
186
187 if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
188 td)) != 0) {
189 goto bad;
190 }
191
192 if (vat.va_fsid == vatroot.va_fsid &&
193 vat.va_fileid == vatroot.va_fileid) {
194 error = ENOENT;
195 goto bad;
196 }
197
198 }
199 if (sgp == NULL)
200 *pbuf = buf;
201 else {
202 sz = &ptr[len] - buf;
203 *pbuf = stackgap_alloc(sgp, sz + 1);
204 error = copyout(buf, *pbuf, sz);
205 free(buf, M_TEMP);
206 }
207
208 vrele(nd.ni_vp);
209 if (!cflag)
210 vrele(ndroot.ni_vp);
211
212 return error;
213
214bad:
215 vrele(ndroot.ni_vp);
216 vrele(nd.ni_vp);
217 free(buf, M_TEMP);
218 return error;
219}
220
221int
222ia32_open(struct thread *td, struct ia32_open_args *uap)
223{
224 caddr_t sg;
225
226 sg = stackgap_init();
227 CHECKALTEXIST(td, &sg, uap->path);
228
229 return open(td, (struct open_args *) uap);
230}
231
232int
233ia32_wait4(struct thread *td, struct ia32_wait4_args *uap)
234{
235 int error;
236 caddr_t sg;
237 struct rusage32 *rusage32, ru32;
238 struct rusage *rusage = NULL, ru;
239
240 rusage32 = uap->rusage;
241 if (rusage32) {
242 sg = stackgap_init();
243 rusage = stackgap_alloc(&sg, sizeof(struct rusage));
244 uap->rusage = (struct rusage32 *)rusage;
245 }
246 error = wait4(td, (struct wait_args *)uap);
247 if (error)
248 return (error);
249 if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
250 TV_CP(ru, ru32, ru_utime);
251 TV_CP(ru, ru32, ru_stime);
252 CP(ru, ru32, ru_maxrss);
253 CP(ru, ru32, ru_ixrss);
254 CP(ru, ru32, ru_idrss);
255 CP(ru, ru32, ru_isrss);
256 CP(ru, ru32, ru_minflt);
257 CP(ru, ru32, ru_majflt);
258 CP(ru, ru32, ru_nswap);
259 CP(ru, ru32, ru_inblock);
260 CP(ru, ru32, ru_oublock);
261 CP(ru, ru32, ru_msgsnd);
262 CP(ru, ru32, ru_msgrcv);
263 CP(ru, ru32, ru_nsignals);
264 CP(ru, ru32, ru_nvcsw);
265 CP(ru, ru32, ru_nivcsw);
266 error = copyout(&ru32, rusage32, sizeof(ru32));
267 }
268 return (error);
269}
270
271static void
272copy_statfs(struct statfs *in, struct statfs32 *out)
273{
274 CP(*in, *out, f_bsize);
275 CP(*in, *out, f_iosize);
276 CP(*in, *out, f_blocks);
277 CP(*in, *out, f_bfree);
278 CP(*in, *out, f_bavail);
279 CP(*in, *out, f_files);
280 CP(*in, *out, f_ffree);
281 CP(*in, *out, f_fsid);
282 CP(*in, *out, f_owner);
283 CP(*in, *out, f_type);
284 CP(*in, *out, f_flags);
285 CP(*in, *out, f_flags);
286 CP(*in, *out, f_syncwrites);
287 CP(*in, *out, f_asyncwrites);
288 bcopy(in->f_fstypename,
289 out->f_fstypename, MFSNAMELEN);
290 bcopy(in->f_mntonname,
291 out->f_mntonname, MNAMELEN);
292 CP(*in, *out, f_syncreads);
293 CP(*in, *out, f_asyncreads);
294 bcopy(in->f_mntfromname,
295 out->f_mntfromname, MNAMELEN);
296}
297
298int
299ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap)
300{
301 int error;
302 caddr_t sg;
303 struct statfs32 *sp32, stat32;
304 struct statfs *sp = NULL, stat;
305 int maxcount, count, i;
306
307 sp32 = uap->buf;
308 maxcount = uap->bufsize / sizeof(struct statfs32);
309
310 if (sp32) {
311 sg = stackgap_init();
312 sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
313 uap->buf = (struct statfs32 *)sp;
314 }
315 error = getfsstat(td, (struct getfsstat_args *) uap);
316 if (sp32 && !error) {
317 count = td->td_retval[0];
318 for (i = 0; i < count; i++) {
319 error = copyin(&sp[i], &stat, sizeof(stat));
320 if (error)
321 return (error);
322 copy_statfs(&stat, &stat32);
323 error = copyout(&stat32, &sp32[i], sizeof(stat32));
324 if (error)
325 return (error);
326 }
327 }
328 return (error);
329}
330
331int
332ia32_access(struct thread *td, struct ia32_access_args *uap)
333{
334 caddr_t sg;
335
336 sg = stackgap_init();
337 CHECKALTEXIST(td, &sg, uap->path);
338
339 return access(td, (struct access_args *)uap);
340}
341
342int
343ia32_chflags(struct thread *td, struct ia32_chflags_args *uap)
344{
345 caddr_t sg;
346
347 sg = stackgap_init();
348 CHECKALTEXIST(td, &sg, uap->path);
349
350 return chflags(td, (struct chflags_args *)uap);
351}
352
353struct sigaltstack32 {
354 u_int32_t ss_sp;
355 u_int32_t ss_size;
356 int ss_flags;
357};
358
359int
360ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap)
361{
362 struct sigaltstack32 s32;
363 struct sigaltstack ss, oss, *ssp;
364 int error;
365
366 if (uap->ss != NULL) {
367 error = copyin(uap->ss, &s32, sizeof(s32));
368 if (error)
369 return (error);
370 PTRIN_CP(s32, ss, ss_sp);
371 CP(s32, ss, ss_size);
372 CP(s32, ss, ss_flags);
373 ssp = &ss;
374 } else
375 ssp = NULL;
376 error = kern_sigaltstack(td, ssp, &oss);
377 if (error == 0 && uap->oss != NULL) {
378 PTROUT_CP(oss, s32, ss_sp);
379 CP(oss, s32, ss_size);
380 CP(oss, s32, ss_flags);
381 error = copyout(&s32, uap->oss, sizeof(s32));
382 }
383 return (error);
384}
385
386int
387ia32_execve(struct thread *td, struct ia32_execve_args *uap)
388{
389 int error;
390 caddr_t sg;
391 struct execve_args ap;
392 u_int32_t *p32, arg;
393 char **p;
394 int count;
395
396 sg = stackgap_init();
397 CHECKALTEXIST(td, &sg, uap->fname);
398 ap.fname = uap->fname;
399
400 if (uap->argv) {
401 count = 0;
402 p32 = uap->argv;
403 do {
404 error = copyin(p32++, &arg, sizeof(arg));
405 if (error)
406 return error;
407 count++;
408 } while (arg != 0);
409 p = stackgap_alloc(&sg, count * sizeof(char *));
410 ap.argv = p;
411 p32 = uap->argv;
412 do {
413 error = copyin(p32++, &arg, sizeof(arg));
414 if (error)
415 return error;
416 *p++ = PTRIN(arg);
417 } while (arg != 0);
418 }
419 if (uap->envv) {
420 count = 0;
421 p32 = uap->envv;
422 do {
423 error = copyin(p32++, &arg, sizeof(arg));
424 if (error)
425 return error;
426 count++;
427 } while (arg != 0);
428 p = stackgap_alloc(&sg, count * sizeof(char *));
429 ap.envv = p;
430 p32 = uap->envv;
431 do {
432 error = copyin(p32++, &arg, sizeof(arg));
433 if (error)
434 return error;
435 *p++ = PTRIN(arg);
436 } while (arg != 0);
437 }
438
439 return execve(td, &ap);
440}
441
80
81static const char ia32_emul_path[] = "/compat/ia32";
82/*
83 * [ taken from the linux emulator ]
84 * Search an alternate path before passing pathname arguments on
85 * to system calls. Useful for keeping a separate 'emulation tree'.
86 *
87 * If cflag is set, we check if an attempt can be made to create
88 * the named file, i.e. we check if the directory it should
89 * be in exists.
90 */
91int
92ia32_emul_find(td, sgp, prefix, path, pbuf, cflag)
93 struct thread *td;
94 caddr_t *sgp; /* Pointer to stackgap memory */
95 const char *prefix;
96 char *path;
97 char **pbuf;
98 int cflag;
99{
100 int error;
101 size_t len, sz;
102 char *buf, *cp, *ptr;
103 struct ucred *ucred;
104 struct nameidata nd;
105 struct nameidata ndroot;
106 struct vattr vat;
107 struct vattr vatroot;
108
109 buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
110 *pbuf = path;
111
112 for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
113 continue;
114
115 sz = MAXPATHLEN - (ptr - buf);
116
117 /*
118 * If sgp is not given then the path is already in kernel space
119 */
120 if (sgp == NULL)
121 error = copystr(path, ptr, sz, &len);
122 else
123 error = copyinstr(path, ptr, sz, &len);
124
125 if (error) {
126 free(buf, M_TEMP);
127 return error;
128 }
129
130 if (*ptr != '/') {
131 free(buf, M_TEMP);
132 return EINVAL;
133 }
134
135 /*
136 * We know that there is a / somewhere in this pathname.
137 * Search backwards for it, to find the file's parent dir
138 * to see if it exists in the alternate tree. If it does,
139 * and we want to create a file (cflag is set). We don't
140 * need to worry about the root comparison in this case.
141 */
142
143 if (cflag) {
144 for (cp = &ptr[len] - 1; *cp != '/'; cp--)
145 ;
146 *cp = '\0';
147
148 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
149
150 if ((error = namei(&nd)) != 0) {
151 free(buf, M_TEMP);
152 return error;
153 }
154
155 *cp = '/';
156 } else {
157 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
158
159 if ((error = namei(&nd)) != 0) {
160 free(buf, M_TEMP);
161 return error;
162 }
163
164 /*
165 * We now compare the vnode of the ia32_root to the one
166 * vnode asked. If they resolve to be the same, then we
167 * ignore the match so that the real root gets used.
168 * This avoids the problem of traversing "../.." to find the
169 * root directory and never finding it, because "/" resolves
170 * to the emulation root directory. This is expensive :-(
171 */
172 NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path,
173 td);
174
175 if ((error = namei(&ndroot)) != 0) {
176 /* Cannot happen! */
177 free(buf, M_TEMP);
178 vrele(nd.ni_vp);
179 return error;
180 }
181
182 ucred = td->td_ucred;
183 if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
184 goto bad;
185 }
186
187 if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
188 td)) != 0) {
189 goto bad;
190 }
191
192 if (vat.va_fsid == vatroot.va_fsid &&
193 vat.va_fileid == vatroot.va_fileid) {
194 error = ENOENT;
195 goto bad;
196 }
197
198 }
199 if (sgp == NULL)
200 *pbuf = buf;
201 else {
202 sz = &ptr[len] - buf;
203 *pbuf = stackgap_alloc(sgp, sz + 1);
204 error = copyout(buf, *pbuf, sz);
205 free(buf, M_TEMP);
206 }
207
208 vrele(nd.ni_vp);
209 if (!cflag)
210 vrele(ndroot.ni_vp);
211
212 return error;
213
214bad:
215 vrele(ndroot.ni_vp);
216 vrele(nd.ni_vp);
217 free(buf, M_TEMP);
218 return error;
219}
220
221int
222ia32_open(struct thread *td, struct ia32_open_args *uap)
223{
224 caddr_t sg;
225
226 sg = stackgap_init();
227 CHECKALTEXIST(td, &sg, uap->path);
228
229 return open(td, (struct open_args *) uap);
230}
231
232int
233ia32_wait4(struct thread *td, struct ia32_wait4_args *uap)
234{
235 int error;
236 caddr_t sg;
237 struct rusage32 *rusage32, ru32;
238 struct rusage *rusage = NULL, ru;
239
240 rusage32 = uap->rusage;
241 if (rusage32) {
242 sg = stackgap_init();
243 rusage = stackgap_alloc(&sg, sizeof(struct rusage));
244 uap->rusage = (struct rusage32 *)rusage;
245 }
246 error = wait4(td, (struct wait_args *)uap);
247 if (error)
248 return (error);
249 if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
250 TV_CP(ru, ru32, ru_utime);
251 TV_CP(ru, ru32, ru_stime);
252 CP(ru, ru32, ru_maxrss);
253 CP(ru, ru32, ru_ixrss);
254 CP(ru, ru32, ru_idrss);
255 CP(ru, ru32, ru_isrss);
256 CP(ru, ru32, ru_minflt);
257 CP(ru, ru32, ru_majflt);
258 CP(ru, ru32, ru_nswap);
259 CP(ru, ru32, ru_inblock);
260 CP(ru, ru32, ru_oublock);
261 CP(ru, ru32, ru_msgsnd);
262 CP(ru, ru32, ru_msgrcv);
263 CP(ru, ru32, ru_nsignals);
264 CP(ru, ru32, ru_nvcsw);
265 CP(ru, ru32, ru_nivcsw);
266 error = copyout(&ru32, rusage32, sizeof(ru32));
267 }
268 return (error);
269}
270
271static void
272copy_statfs(struct statfs *in, struct statfs32 *out)
273{
274 CP(*in, *out, f_bsize);
275 CP(*in, *out, f_iosize);
276 CP(*in, *out, f_blocks);
277 CP(*in, *out, f_bfree);
278 CP(*in, *out, f_bavail);
279 CP(*in, *out, f_files);
280 CP(*in, *out, f_ffree);
281 CP(*in, *out, f_fsid);
282 CP(*in, *out, f_owner);
283 CP(*in, *out, f_type);
284 CP(*in, *out, f_flags);
285 CP(*in, *out, f_flags);
286 CP(*in, *out, f_syncwrites);
287 CP(*in, *out, f_asyncwrites);
288 bcopy(in->f_fstypename,
289 out->f_fstypename, MFSNAMELEN);
290 bcopy(in->f_mntonname,
291 out->f_mntonname, MNAMELEN);
292 CP(*in, *out, f_syncreads);
293 CP(*in, *out, f_asyncreads);
294 bcopy(in->f_mntfromname,
295 out->f_mntfromname, MNAMELEN);
296}
297
298int
299ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap)
300{
301 int error;
302 caddr_t sg;
303 struct statfs32 *sp32, stat32;
304 struct statfs *sp = NULL, stat;
305 int maxcount, count, i;
306
307 sp32 = uap->buf;
308 maxcount = uap->bufsize / sizeof(struct statfs32);
309
310 if (sp32) {
311 sg = stackgap_init();
312 sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
313 uap->buf = (struct statfs32 *)sp;
314 }
315 error = getfsstat(td, (struct getfsstat_args *) uap);
316 if (sp32 && !error) {
317 count = td->td_retval[0];
318 for (i = 0; i < count; i++) {
319 error = copyin(&sp[i], &stat, sizeof(stat));
320 if (error)
321 return (error);
322 copy_statfs(&stat, &stat32);
323 error = copyout(&stat32, &sp32[i], sizeof(stat32));
324 if (error)
325 return (error);
326 }
327 }
328 return (error);
329}
330
331int
332ia32_access(struct thread *td, struct ia32_access_args *uap)
333{
334 caddr_t sg;
335
336 sg = stackgap_init();
337 CHECKALTEXIST(td, &sg, uap->path);
338
339 return access(td, (struct access_args *)uap);
340}
341
342int
343ia32_chflags(struct thread *td, struct ia32_chflags_args *uap)
344{
345 caddr_t sg;
346
347 sg = stackgap_init();
348 CHECKALTEXIST(td, &sg, uap->path);
349
350 return chflags(td, (struct chflags_args *)uap);
351}
352
353struct sigaltstack32 {
354 u_int32_t ss_sp;
355 u_int32_t ss_size;
356 int ss_flags;
357};
358
359int
360ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap)
361{
362 struct sigaltstack32 s32;
363 struct sigaltstack ss, oss, *ssp;
364 int error;
365
366 if (uap->ss != NULL) {
367 error = copyin(uap->ss, &s32, sizeof(s32));
368 if (error)
369 return (error);
370 PTRIN_CP(s32, ss, ss_sp);
371 CP(s32, ss, ss_size);
372 CP(s32, ss, ss_flags);
373 ssp = &ss;
374 } else
375 ssp = NULL;
376 error = kern_sigaltstack(td, ssp, &oss);
377 if (error == 0 && uap->oss != NULL) {
378 PTROUT_CP(oss, s32, ss_sp);
379 CP(oss, s32, ss_size);
380 CP(oss, s32, ss_flags);
381 error = copyout(&s32, uap->oss, sizeof(s32));
382 }
383 return (error);
384}
385
386int
387ia32_execve(struct thread *td, struct ia32_execve_args *uap)
388{
389 int error;
390 caddr_t sg;
391 struct execve_args ap;
392 u_int32_t *p32, arg;
393 char **p;
394 int count;
395
396 sg = stackgap_init();
397 CHECKALTEXIST(td, &sg, uap->fname);
398 ap.fname = uap->fname;
399
400 if (uap->argv) {
401 count = 0;
402 p32 = uap->argv;
403 do {
404 error = copyin(p32++, &arg, sizeof(arg));
405 if (error)
406 return error;
407 count++;
408 } while (arg != 0);
409 p = stackgap_alloc(&sg, count * sizeof(char *));
410 ap.argv = p;
411 p32 = uap->argv;
412 do {
413 error = copyin(p32++, &arg, sizeof(arg));
414 if (error)
415 return error;
416 *p++ = PTRIN(arg);
417 } while (arg != 0);
418 }
419 if (uap->envv) {
420 count = 0;
421 p32 = uap->envv;
422 do {
423 error = copyin(p32++, &arg, sizeof(arg));
424 if (error)
425 return error;
426 count++;
427 } while (arg != 0);
428 p = stackgap_alloc(&sg, count * sizeof(char *));
429 ap.envv = p;
430 p32 = uap->envv;
431 do {
432 error = copyin(p32++, &arg, sizeof(arg));
433 if (error)
434 return error;
435 *p++ = PTRIN(arg);
436 } while (arg != 0);
437 }
438
439 return execve(td, &ap);
440}
441
442#ifdef __ia64__
442static int
443ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
444 int prot, int fd, off_t pos)
445{
446 vm_map_t map;
447 vm_map_entry_t entry;
448 int rv;
449
450 map = &td->td_proc->p_vmspace->vm_map;
451 if (fd != -1)
452 prot |= VM_PROT_WRITE;
453
454 if (vm_map_lookup_entry(map, start, &entry)) {
455 if ((entry->protection & prot) != prot) {
456 rv = vm_map_protect(map,
457 trunc_page(start),
458 round_page(end),
459 entry->protection | prot,
460 FALSE);
461 if (rv != KERN_SUCCESS)
462 return (EINVAL);
463 }
464 } else {
465 vm_offset_t addr = trunc_page(start);
466 rv = vm_map_find(map, 0, 0,
467 &addr, PAGE_SIZE, FALSE, prot,
468 VM_PROT_ALL, 0);
469 if (rv != KERN_SUCCESS)
470 return (EINVAL);
471 }
472
473 if (fd != -1) {
474 struct pread_args r;
475 r.fd = fd;
476 r.buf = (void *) start;
477 r.nbyte = end - start;
478 r.offset = pos;
479 return (pread(td, &r));
480 } else {
481 while (start < end) {
482 subyte((void *) start, 0);
483 start++;
484 }
485 return (0);
486 }
487}
443static int
444ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
445 int prot, int fd, off_t pos)
446{
447 vm_map_t map;
448 vm_map_entry_t entry;
449 int rv;
450
451 map = &td->td_proc->p_vmspace->vm_map;
452 if (fd != -1)
453 prot |= VM_PROT_WRITE;
454
455 if (vm_map_lookup_entry(map, start, &entry)) {
456 if ((entry->protection & prot) != prot) {
457 rv = vm_map_protect(map,
458 trunc_page(start),
459 round_page(end),
460 entry->protection | prot,
461 FALSE);
462 if (rv != KERN_SUCCESS)
463 return (EINVAL);
464 }
465 } else {
466 vm_offset_t addr = trunc_page(start);
467 rv = vm_map_find(map, 0, 0,
468 &addr, PAGE_SIZE, FALSE, prot,
469 VM_PROT_ALL, 0);
470 if (rv != KERN_SUCCESS)
471 return (EINVAL);
472 }
473
474 if (fd != -1) {
475 struct pread_args r;
476 r.fd = fd;
477 r.buf = (void *) start;
478 r.nbyte = end - start;
479 r.offset = pos;
480 return (pread(td, &r));
481 } else {
482 while (start < end) {
483 subyte((void *) start, 0);
484 start++;
485 }
486 return (0);
487 }
488}
489#endif
488
489int
490ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
491{
492 struct mmap_args ap;
493 vm_offset_t addr = (vm_offset_t) uap->addr;
494 vm_size_t len = uap->len;
495 int prot = uap->prot;
496 int flags = uap->flags;
497 int fd = uap->fd;
498 off_t pos = (uap->poslo
499 | ((off_t)uap->poshi << 32));
490
491int
492ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
493{
494 struct mmap_args ap;
495 vm_offset_t addr = (vm_offset_t) uap->addr;
496 vm_size_t len = uap->len;
497 int prot = uap->prot;
498 int flags = uap->flags;
499 int fd = uap->fd;
500 off_t pos = (uap->poslo
501 | ((off_t)uap->poshi << 32));
502#ifdef __ia64__
500 vm_size_t pageoff;
501 int error;
502
503 /*
504 * Attempt to handle page size hassles.
505 */
506 pageoff = (pos & PAGE_MASK);
507 if (flags & MAP_FIXED) {
508 vm_offset_t start, end;
509 start = addr;
510 end = addr + len;
511
512 if (start != trunc_page(start)) {
513 error = ia32_mmap_partial(td, start, round_page(start),
514 prot, fd, pos);
515 if (fd != -1)
516 pos += round_page(start) - start;
517 start = round_page(start);
518 }
519 if (end != round_page(end)) {
520 vm_offset_t t = trunc_page(end);
521 error = ia32_mmap_partial(td, t, end,
522 prot, fd,
523 pos + t - start);
524 end = trunc_page(end);
525 }
526 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
527 /*
528 * We can't map this region at all. The specified
529 * address doesn't have the same alignment as the file
530 * position. Fake the mapping by simply reading the
531 * entire region into memory. First we need to make
532 * sure the region exists.
533 */
534 vm_map_t map;
535 struct pread_args r;
536 int rv;
537
538 prot |= VM_PROT_WRITE;
539 map = &td->td_proc->p_vmspace->vm_map;
540 rv = vm_map_remove(map, start, end);
541 if (rv != KERN_SUCCESS)
542 return (EINVAL);
543 rv = vm_map_find(map, 0, 0,
544 &start, end - start, FALSE,
545 prot, VM_PROT_ALL, 0);
546 if (rv != KERN_SUCCESS)
547 return (EINVAL);
548 r.fd = fd;
549 r.buf = (void *) start;
550 r.nbyte = end - start;
551 r.offset = pos;
552 error = pread(td, &r);
553 if (error)
554 return (error);
555
556 td->td_retval[0] = addr;
557 return (0);
558 }
559 if (end == start) {
560 /*
561 * After dealing with the ragged ends, there
562 * might be none left.
563 */
564 td->td_retval[0] = addr;
565 return (0);
566 }
567 addr = start;
568 len = end - start;
569 }
503 vm_size_t pageoff;
504 int error;
505
506 /*
507 * Attempt to handle page size hassles.
508 */
509 pageoff = (pos & PAGE_MASK);
510 if (flags & MAP_FIXED) {
511 vm_offset_t start, end;
512 start = addr;
513 end = addr + len;
514
515 if (start != trunc_page(start)) {
516 error = ia32_mmap_partial(td, start, round_page(start),
517 prot, fd, pos);
518 if (fd != -1)
519 pos += round_page(start) - start;
520 start = round_page(start);
521 }
522 if (end != round_page(end)) {
523 vm_offset_t t = trunc_page(end);
524 error = ia32_mmap_partial(td, t, end,
525 prot, fd,
526 pos + t - start);
527 end = trunc_page(end);
528 }
529 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
530 /*
531 * We can't map this region at all. The specified
532 * address doesn't have the same alignment as the file
533 * position. Fake the mapping by simply reading the
534 * entire region into memory. First we need to make
535 * sure the region exists.
536 */
537 vm_map_t map;
538 struct pread_args r;
539 int rv;
540
541 prot |= VM_PROT_WRITE;
542 map = &td->td_proc->p_vmspace->vm_map;
543 rv = vm_map_remove(map, start, end);
544 if (rv != KERN_SUCCESS)
545 return (EINVAL);
546 rv = vm_map_find(map, 0, 0,
547 &start, end - start, FALSE,
548 prot, VM_PROT_ALL, 0);
549 if (rv != KERN_SUCCESS)
550 return (EINVAL);
551 r.fd = fd;
552 r.buf = (void *) start;
553 r.nbyte = end - start;
554 r.offset = pos;
555 error = pread(td, &r);
556 if (error)
557 return (error);
558
559 td->td_retval[0] = addr;
560 return (0);
561 }
562 if (end == start) {
563 /*
564 * After dealing with the ragged ends, there
565 * might be none left.
566 */
567 td->td_retval[0] = addr;
568 return (0);
569 }
570 addr = start;
571 len = end - start;
572 }
573#endif
570
571 ap.addr = (void *) addr;
572 ap.len = len;
573 ap.prot = prot;
574 ap.flags = flags;
575 ap.fd = fd;
576 ap.pos = pos;
577
578 return (mmap(td, &ap));
579}
580
581struct itimerval32 {
582 struct timeval32 it_interval;
583 struct timeval32 it_value;
584};
585
586int
587ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
588{
589 int error;
590 caddr_t sg;
591 struct itimerval32 *p32, *op32, s32;
592 struct itimerval *p = NULL, *op = NULL, s;
593
594 p32 = uap->itv;
595 if (p32) {
596 sg = stackgap_init();
597 p = stackgap_alloc(&sg, sizeof(struct itimerval));
598 uap->itv = (struct itimerval32 *)p;
599 error = copyin(p32, &s32, sizeof(s32));
600 if (error)
601 return (error);
602 TV_CP(s32, s, it_interval);
603 TV_CP(s32, s, it_value);
604 error = copyout(&s, p, sizeof(s));
605 if (error)
606 return (error);
607 }
608 op32 = uap->oitv;
609 if (op32) {
610 sg = stackgap_init();
611 op = stackgap_alloc(&sg, sizeof(struct itimerval));
612 uap->oitv = (struct itimerval32 *)op;
613 }
614 error = setitimer(td, (struct setitimer_args *) uap);
615 if (error)
616 return (error);
617 if (op32) {
618 error = copyin(op, &s, sizeof(s));
619 if (error)
620 return (error);
621 TV_CP(s, s32, it_interval);
622 TV_CP(s, s32, it_value);
623 error = copyout(&s32, op32, sizeof(s32));
624 }
625 return (error);
626}
627
628int
629ia32_select(struct thread *td, struct ia32_select_args *uap)
630{
631 int error;
632 caddr_t sg;
633 struct timeval32 *p32, s32;
634 struct timeval *p = NULL, s;
635
636 p32 = uap->tv;
637 if (p32) {
638 sg = stackgap_init();
639 p = stackgap_alloc(&sg, sizeof(struct timeval));
640 uap->tv = (struct timeval32 *)p;
641 error = copyin(p32, &s32, sizeof(s32));
642 if (error)
643 return (error);
644 CP(s32, s, tv_sec);
645 CP(s32, s, tv_usec);
646 error = copyout(&s, p, sizeof(s));
647 if (error)
648 return (error);
649 }
650 /*
651 * XXX big-endian needs to convert the fd_sets too.
652 */
653 return (select(td, (struct select_args *) uap));
654}
655
574
575 ap.addr = (void *) addr;
576 ap.len = len;
577 ap.prot = prot;
578 ap.flags = flags;
579 ap.fd = fd;
580 ap.pos = pos;
581
582 return (mmap(td, &ap));
583}
584
585struct itimerval32 {
586 struct timeval32 it_interval;
587 struct timeval32 it_value;
588};
589
590int
591ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
592{
593 int error;
594 caddr_t sg;
595 struct itimerval32 *p32, *op32, s32;
596 struct itimerval *p = NULL, *op = NULL, s;
597
598 p32 = uap->itv;
599 if (p32) {
600 sg = stackgap_init();
601 p = stackgap_alloc(&sg, sizeof(struct itimerval));
602 uap->itv = (struct itimerval32 *)p;
603 error = copyin(p32, &s32, sizeof(s32));
604 if (error)
605 return (error);
606 TV_CP(s32, s, it_interval);
607 TV_CP(s32, s, it_value);
608 error = copyout(&s, p, sizeof(s));
609 if (error)
610 return (error);
611 }
612 op32 = uap->oitv;
613 if (op32) {
614 sg = stackgap_init();
615 op = stackgap_alloc(&sg, sizeof(struct itimerval));
616 uap->oitv = (struct itimerval32 *)op;
617 }
618 error = setitimer(td, (struct setitimer_args *) uap);
619 if (error)
620 return (error);
621 if (op32) {
622 error = copyin(op, &s, sizeof(s));
623 if (error)
624 return (error);
625 TV_CP(s, s32, it_interval);
626 TV_CP(s, s32, it_value);
627 error = copyout(&s32, op32, sizeof(s32));
628 }
629 return (error);
630}
631
632int
633ia32_select(struct thread *td, struct ia32_select_args *uap)
634{
635 int error;
636 caddr_t sg;
637 struct timeval32 *p32, s32;
638 struct timeval *p = NULL, s;
639
640 p32 = uap->tv;
641 if (p32) {
642 sg = stackgap_init();
643 p = stackgap_alloc(&sg, sizeof(struct timeval));
644 uap->tv = (struct timeval32 *)p;
645 error = copyin(p32, &s32, sizeof(s32));
646 if (error)
647 return (error);
648 CP(s32, s, tv_sec);
649 CP(s32, s, tv_usec);
650 error = copyout(&s, p, sizeof(s));
651 if (error)
652 return (error);
653 }
654 /*
655 * XXX big-endian needs to convert the fd_sets too.
656 */
657 return (select(td, (struct select_args *) uap));
658}
659
660struct kevent32 {
661 u_int32_t ident; /* identifier for this event */
662 short filter; /* filter for event */
663 u_short flags;
664 u_int fflags;
665 int32_t data;
666 u_int32_t udata; /* opaque user data identifier */
667};
668
656int
669int
670ia32_kevent(struct thread *td, struct ia32_kevent_args *uap)
671{
672 int error;
673 caddr_t sg;
674 struct timespec32 ts32;
675 struct timespec ts;
676 struct kevent32 ks32;
677 struct kevent *ks;
678 struct kevent_args a;
679 int i;
680
681 sg = stackgap_init();
682
683 a.fd = uap->fd;
684 a.changelist = uap->changelist;
685 a.nchanges = uap->nchanges;
686 a.eventlist = uap->eventlist;
687 a.nevents = uap->nevents;
688 a.timeout = NULL;
689
690 if (uap->timeout) {
691 a.timeout = stackgap_alloc(&sg, sizeof(struct timespec));
692 error = copyin(uap->timeout, &ts32, sizeof(ts32));
693 if (error)
694 return (error);
695 CP(ts32, ts, tv_sec);
696 CP(ts32, ts, tv_nsec);
697 error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts));
698 if (error)
699 return (error);
700 }
701 if (uap->changelist) {
702 a.changelist = (struct kevent *)stackgap_alloc(&sg, uap->nchanges * sizeof(struct kevent));
703 for (i = 0; i < uap->nchanges; i++) {
704 error = copyin(&uap->changelist[i], &ks32, sizeof(ks32));
705 if (error)
706 return (error);
707 ks = (struct kevent *)(uintptr_t)&a.changelist[i];
708 CP(ks32, *ks, ident);
709 CP(ks32, *ks, filter);
710 CP(ks32, *ks, flags);
711 CP(ks32, *ks, fflags);
712 CP(ks32, *ks, data);
713 PTRIN_CP(ks32, *ks, udata);
714 }
715 }
716 if (uap->eventlist) {
717 a.eventlist = stackgap_alloc(&sg, uap->nevents * sizeof(struct kevent));
718 }
719 error = kevent(td, &a);
720 if (uap->eventlist && error > 0) {
721 for (i = 0; i < error; i++) {
722 ks = &a.eventlist[i];
723 CP(*ks, ks32, ident);
724 CP(*ks, ks32, filter);
725 CP(*ks, ks32, flags);
726 CP(*ks, ks32, fflags);
727 CP(*ks, ks32, data);
728 PTROUT_CP(*ks, ks32, udata);
729 error = copyout(&ks32, &uap->eventlist[i], sizeof(ks32));
730 if (error)
731 return (error);
732 }
733 }
734 return error;
735}
736
737int
657ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
658{
659 int error;
660 caddr_t sg;
661 struct timeval32 *p32, s32;
662 struct timeval *p = NULL, s;
663
664 p32 = uap->tp;
665 if (p32) {
666 sg = stackgap_init();
667 p = stackgap_alloc(&sg, sizeof(struct timeval));
668 uap->tp = (struct timeval32 *)p;
669 }
670 error = gettimeofday(td, (struct gettimeofday_args *) uap);
671 if (error)
672 return (error);
673 if (p32) {
674 error = copyin(p, &s, sizeof(s));
675 if (error)
676 return (error);
677 CP(s, s32, tv_sec);
678 CP(s, s32, tv_usec);
679 error = copyout(&s32, p32, sizeof(s32));
680 if (error)
681 return (error);
682 }
683 return (error);
684}
685
686int
687ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
688{
689 int error;
690 caddr_t sg;
691 struct rusage32 *p32, s32;
692 struct rusage *p = NULL, s;
693
694 p32 = uap->rusage;
695 if (p32) {
696 sg = stackgap_init();
697 p = stackgap_alloc(&sg, sizeof(struct rusage));
698 uap->rusage = (struct rusage32 *)p;
699 }
700 error = getrusage(td, (struct getrusage_args *) uap);
701 if (error)
702 return (error);
703 if (p32) {
704 error = copyin(p, &s, sizeof(s));
705 if (error)
706 return (error);
707 TV_CP(s, s32, ru_utime);
708 TV_CP(s, s32, ru_stime);
709 CP(s, s32, ru_maxrss);
710 CP(s, s32, ru_ixrss);
711 CP(s, s32, ru_idrss);
712 CP(s, s32, ru_isrss);
713 CP(s, s32, ru_minflt);
714 CP(s, s32, ru_majflt);
715 CP(s, s32, ru_nswap);
716 CP(s, s32, ru_inblock);
717 CP(s, s32, ru_oublock);
718 CP(s, s32, ru_msgsnd);
719 CP(s, s32, ru_msgrcv);
720 CP(s, s32, ru_nsignals);
721 CP(s, s32, ru_nvcsw);
722 CP(s, s32, ru_nivcsw);
723 error = copyout(&s32, p32, sizeof(s32));
724 }
725 return (error);
726}
727
728struct iovec32 {
729 u_int32_t iov_base;
730 int iov_len;
731};
732#define STACKGAPLEN 400
733
734int
735ia32_readv(struct thread *td, struct ia32_readv_args *uap)
736{
737 int error, osize, nsize, i;
738 caddr_t sg;
739 struct readv_args /* {
740 syscallarg(int) fd;
741 syscallarg(struct iovec *) iovp;
742 syscallarg(u_int) iovcnt;
743 } */ a;
744 struct iovec32 *oio;
745 struct iovec *nio;
746
747 sg = stackgap_init();
748
749 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
750 return (EINVAL);
751
752 osize = uap->iovcnt * sizeof (struct iovec32);
753 nsize = uap->iovcnt * sizeof (struct iovec);
754
755 oio = malloc(osize, M_TEMP, M_WAITOK);
756 nio = malloc(nsize, M_TEMP, M_WAITOK);
757
758 error = 0;
759 if ((error = copyin(uap->iovp, oio, osize)))
760 goto punt;
761 for (i = 0; i < uap->iovcnt; i++) {
762 nio[i].iov_base = PTRIN(oio[i].iov_base);
763 nio[i].iov_len = oio[i].iov_len;
764 }
765
766 a.fd = uap->fd;
767 a.iovp = stackgap_alloc(&sg, nsize);
768 a.iovcnt = uap->iovcnt;
769
770 if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
771 goto punt;
772 error = readv(td, &a);
773
774punt:
775 free(oio, M_TEMP);
776 free(nio, M_TEMP);
777 return (error);
778}
779
780int
781ia32_writev(struct thread *td, struct ia32_writev_args *uap)
782{
783 int error, i, nsize, osize;
784 caddr_t sg;
785 struct writev_args /* {
786 syscallarg(int) fd;
787 syscallarg(struct iovec *) iovp;
788 syscallarg(u_int) iovcnt;
789 } */ a;
790 struct iovec32 *oio;
791 struct iovec *nio;
792
793 sg = stackgap_init();
794
795 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
796 return (EINVAL);
797
798 osize = uap->iovcnt * sizeof (struct iovec32);
799 nsize = uap->iovcnt * sizeof (struct iovec);
800
801 oio = malloc(osize, M_TEMP, M_WAITOK);
802 nio = malloc(nsize, M_TEMP, M_WAITOK);
803
804 error = 0;
805 if ((error = copyin(uap->iovp, oio, osize)))
806 goto punt;
807 for (i = 0; i < uap->iovcnt; i++) {
808 nio[i].iov_base = PTRIN(oio[i].iov_base);
809 nio[i].iov_len = oio[i].iov_len;
810 }
811
812 a.fd = uap->fd;
813 a.iovp = stackgap_alloc(&sg, nsize);
814 a.iovcnt = uap->iovcnt;
815
816 if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
817 goto punt;
818 error = writev(td, &a);
819
820punt:
821 free(oio, M_TEMP);
822 free(nio, M_TEMP);
823 return (error);
824}
825
826int
827ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
828{
829 int error;
830 caddr_t sg;
831 struct timeval32 *p32, s32;
832 struct timeval *p = NULL, s;
833
834 p32 = uap->tv;
835 if (p32) {
836 sg = stackgap_init();
837 p = stackgap_alloc(&sg, sizeof(struct timeval));
838 uap->tv = (struct timeval32 *)p;
839 error = copyin(p32, &s32, sizeof(s32));
840 if (error)
841 return (error);
842 CP(s32, s, tv_sec);
843 CP(s32, s, tv_usec);
844 error = copyout(&s, p, sizeof(s));
845 if (error)
846 return (error);
847 }
848 return (settimeofday(td, (struct settimeofday_args *) uap));
849}
850
851int
852ia32_utimes(struct thread *td, struct ia32_utimes_args *uap)
853{
854 int error;
855 caddr_t sg;
856 struct timeval32 *p32, s32[2];
857 struct timeval *p = NULL, s[2];
858
859 p32 = uap->tptr;
860 if (p32) {
861 sg = stackgap_init();
862 p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
863 uap->tptr = (struct timeval32 *)p;
864 error = copyin(p32, s32, sizeof(s32));
865 if (error)
866 return (error);
867 CP(s32[0], s[0], tv_sec);
868 CP(s32[0], s[0], tv_usec);
869 CP(s32[1], s[1], tv_sec);
870 CP(s32[1], s[1], tv_usec);
871 error = copyout(s, p, sizeof(s));
872 if (error)
873 return (error);
874 }
875 return (utimes(td, (struct utimes_args *) uap));
876}
877
878int
879ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
880{
881 int error;
882 caddr_t sg;
883 struct timeval32 *p32, *op32, s32;
884 struct timeval *p = NULL, *op = NULL, s;
885
886 p32 = uap->delta;
887 if (p32) {
888 sg = stackgap_init();
889 p = stackgap_alloc(&sg, sizeof(struct timeval));
890 uap->delta = (struct timeval32 *)p;
891 error = copyin(p32, &s32, sizeof(s32));
892 if (error)
893 return (error);
894 CP(s32, s, tv_sec);
895 CP(s32, s, tv_usec);
896 error = copyout(&s, p, sizeof(s));
897 if (error)
898 return (error);
899 }
900 op32 = uap->olddelta;
901 if (op32) {
902 sg = stackgap_init();
903 op = stackgap_alloc(&sg, sizeof(struct timeval));
904 uap->olddelta = (struct timeval32 *)op;
905 }
906 error = utimes(td, (struct utimes_args *) uap);
907 if (error)
908 return error;
909 if (op32) {
910 error = copyin(op, &s, sizeof(s));
911 if (error)
912 return (error);
913 CP(s, s32, tv_sec);
914 CP(s, s32, tv_usec);
915 error = copyout(&s32, op32, sizeof(s32));
916 }
917 return (error);
918}
919
920int
921ia32_statfs(struct thread *td, struct ia32_statfs_args *uap)
922{
923 int error;
924 caddr_t sg;
925 struct statfs32 *p32, s32;
926 struct statfs *p = NULL, s;
927
928 p32 = uap->buf;
929 if (p32) {
930 sg = stackgap_init();
931 p = stackgap_alloc(&sg, sizeof(struct statfs));
932 uap->buf = (struct statfs32 *)p;
933 }
934 error = statfs(td, (struct statfs_args *) uap);
935 if (error)
936 return (error);
937 if (p32) {
938 error = copyin(p, &s, sizeof(s));
939 if (error)
940 return (error);
941 copy_statfs(&s, &s32);
942 error = copyout(&s32, p32, sizeof(s32));
943 }
944 return (error);
945}
946
947int
948ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
949{
950 int error;
951 caddr_t sg;
952 struct statfs32 *p32, s32;
953 struct statfs *p = NULL, s;
954
955 p32 = uap->buf;
956 if (p32) {
957 sg = stackgap_init();
958 p = stackgap_alloc(&sg, sizeof(struct statfs));
959 uap->buf = (struct statfs32 *)p;
960 }
961 error = fstatfs(td, (struct fstatfs_args *) uap);
962 if (error)
963 return (error);
964 if (p32) {
965 error = copyin(p, &s, sizeof(s));
966 if (error)
967 return (error);
968 copy_statfs(&s, &s32);
969 error = copyout(&s32, p32, sizeof(s32));
970 }
971 return (error);
972}
973
974int
975ia32_semsys(struct thread *td, struct ia32_semsys_args *uap)
976{
977 /*
978 * Vector through to semsys if it is loaded.
979 */
980 return sysent[169].sy_call(td, uap);
981}
982
983int
984ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
985{
986 /*
987 * Vector through to msgsys if it is loaded.
988 */
989 return sysent[170].sy_call(td, uap);
990}
991
992int
993ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
994{
995 /*
996 * Vector through to shmsys if it is loaded.
997 */
998 return sysent[171].sy_call(td, uap);
999}
1000
1001int
1002ia32_pread(struct thread *td, struct ia32_pread_args *uap)
1003{
1004 struct pread_args ap;
1005
1006 ap.fd = uap->fd;
1007 ap.buf = uap->buf;
1008 ap.nbyte = uap->nbyte;
1009 ap.offset = (uap->offsetlo
1010 | ((off_t)uap->offsethi << 32));
1011 return (pread(td, &ap));
1012}
1013
1014int
1015ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
1016{
1017 struct pwrite_args ap;
1018
1019 ap.fd = uap->fd;
1020 ap.buf = uap->buf;
1021 ap.nbyte = uap->nbyte;
1022 ap.offset = (uap->offsetlo
1023 | ((off_t)uap->offsethi << 32));
1024 return (pwrite(td, &ap));
1025}
1026
1027int
1028ia32_lseek(struct thread *td, struct ia32_lseek_args *uap)
1029{
1030 int error;
1031 struct lseek_args ap;
1032 off_t pos;
1033
1034 ap.fd = uap->fd;
1035 ap.offset = (uap->offsetlo
1036 | ((off_t)uap->offsethi << 32));
1037 ap.whence = uap->whence;
1038 error = lseek(td, &ap);
1039 /* Expand the quad return into two parts for eax and edx */
1040 pos = *(off_t *)(td->td_retval);
1041 td->td_retval[0] = pos & 0xffffffff; /* %eax */
1042 td->td_retval[1] = pos >> 32; /* %edx */
1043 return error;
1044}
1045
1046int
1047ia32_truncate(struct thread *td, struct ia32_truncate_args *uap)
1048{
1049 struct truncate_args ap;
1050
1051 ap.path = uap->path;
1052 ap.length = (uap->lengthlo
1053 | ((off_t)uap->lengthhi << 32));
1054 return (truncate(td, &ap));
1055}
1056
1057int
1058ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
1059{
1060 struct ftruncate_args ap;
1061
1062 ap.fd = uap->fd;
1063 ap.length = (uap->lengthlo
1064 | ((off_t)uap->lengthhi << 32));
1065 return (ftruncate(td, &ap));
1066}
1067
1068#ifdef COMPAT_FREEBSD4
1069int
1070freebsd4_ia32_sendfile(struct thread *td,
1071 struct freebsd4_ia32_sendfile_args *uap)
1072{
1073 struct freebsd4_sendfile_args ap;
1074
1075 ap.fd = uap->fd;
1076 ap.s = uap->s;
1077 ap.offset = (uap->offsetlo
1078 | ((off_t)uap->offsethi << 32));
1079 ap.nbytes = uap->nbytes; /* XXX check */
1080 ap.hdtr = uap->hdtr; /* XXX check */
1081 ap.sbytes = uap->sbytes; /* XXX FIXME!! */
1082 ap.flags = uap->flags;
1083 return (freebsd4_sendfile(td, &ap));
1084}
1085#endif
1086
1087int
1088ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
1089{
1090 struct sendfile_args ap;
1091
1092 ap.fd = uap->fd;
1093 ap.s = uap->s;
1094 ap.offset = (uap->offsetlo
1095 | ((off_t)uap->offsethi << 32));
1096 ap.nbytes = uap->nbytes; /* XXX check */
1097 ap.hdtr = uap->hdtr; /* XXX check */
1098 ap.sbytes = uap->sbytes; /* XXX FIXME!! */
1099 ap.flags = uap->flags;
1100 return (sendfile(td, &ap));
1101}
1102
1103struct stat32 {
1104 udev_t st_dev;
1105 ino_t st_ino;
1106 mode_t st_mode;
1107 nlink_t st_nlink;
1108 uid_t st_uid;
1109 gid_t st_gid;
1110 udev_t st_rdev;
1111 struct timespec32 st_atimespec;
1112 struct timespec32 st_mtimespec;
1113 struct timespec32 st_ctimespec;
1114 off_t st_size;
1115 int64_t st_blocks;
1116 u_int32_t st_blksize;
1117 u_int32_t st_flags;
1118 u_int32_t st_gen;
1119};
1120
1121static void
1122copy_stat( struct stat *in, struct stat32 *out)
1123{
1124 CP(*in, *out, st_dev);
1125 CP(*in, *out, st_ino);
1126 CP(*in, *out, st_mode);
1127 CP(*in, *out, st_nlink);
1128 CP(*in, *out, st_uid);
1129 CP(*in, *out, st_gid);
1130 CP(*in, *out, st_rdev);
1131 TS_CP(*in, *out, st_atimespec);
1132 TS_CP(*in, *out, st_mtimespec);
1133 TS_CP(*in, *out, st_ctimespec);
1134 CP(*in, *out, st_size);
1135 CP(*in, *out, st_blocks);
1136 CP(*in, *out, st_blksize);
1137 CP(*in, *out, st_flags);
1138 CP(*in, *out, st_gen);
1139}
1140
1141int
1142ia32_stat(struct thread *td, struct ia32_stat_args *uap)
1143{
1144 int error;
1145 caddr_t sg;
1146 struct stat32 *p32, s32;
1147 struct stat *p = NULL, s;
1148
1149 p32 = uap->ub;
1150 if (p32) {
1151 sg = stackgap_init();
1152 p = stackgap_alloc(&sg, sizeof(struct stat));
1153 uap->ub = (struct stat32 *)p;
1154 }
1155 error = stat(td, (struct stat_args *) uap);
1156 if (error)
1157 return (error);
1158 if (p32) {
1159 error = copyin(p, &s, sizeof(s));
1160 if (error)
1161 return (error);
1162 copy_stat(&s, &s32);
1163 error = copyout(&s32, p32, sizeof(s32));
1164 }
1165 return (error);
1166}
1167
1168int
1169ia32_fstat(struct thread *td, struct ia32_fstat_args *uap)
1170{
1171 int error;
1172 caddr_t sg;
1173 struct stat32 *p32, s32;
1174 struct stat *p = NULL, s;
1175
1176 p32 = uap->ub;
1177 if (p32) {
1178 sg = stackgap_init();
1179 p = stackgap_alloc(&sg, sizeof(struct stat));
1180 uap->ub = (struct stat32 *)p;
1181 }
1182 error = fstat(td, (struct fstat_args *) uap);
1183 if (error)
1184 return (error);
1185 if (p32) {
1186 error = copyin(p, &s, sizeof(s));
1187 if (error)
1188 return (error);
1189 copy_stat(&s, &s32);
1190 error = copyout(&s32, p32, sizeof(s32));
1191 }
1192 return (error);
1193}
1194
1195int
1196ia32_lstat(struct thread *td, struct ia32_lstat_args *uap)
1197{
1198 int error;
1199 caddr_t sg;
1200 struct stat32 *p32, s32;
1201 struct stat *p = NULL, s;
1202
1203 p32 = uap->ub;
1204 if (p32) {
1205 sg = stackgap_init();
1206 p = stackgap_alloc(&sg, sizeof(struct stat));
1207 uap->ub = (struct stat32 *)p;
1208 }
1209 error = lstat(td, (struct lstat_args *) uap);
1210 if (error)
1211 return (error);
1212 if (p32) {
1213 error = copyin(p, &s, sizeof(s));
1214 if (error)
1215 return (error);
1216 copy_stat(&s, &s32);
1217 error = copyout(&s32, p32, sizeof(s32));
1218 }
1219 return (error);
1220}
1221
1222/*
1223 * MPSAFE
1224 */
1225int
1226ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
1227{
1228 int error, name[CTL_MAXNAME];
1229 size_t j, oldlen;
1230
1231 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1232 return (EINVAL);
1233
1234 error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1235 if (error)
1236 return (error);
1237
1238 mtx_lock(&Giant);
1239
1240 if (uap->oldlenp)
1241 oldlen = fuword32(uap->oldlenp);
1242 else
1243 oldlen = 0;
1244 error = userland_sysctl(td, name, uap->namelen,
1245 uap->old, &oldlen, 1,
1246 uap->new, uap->newlen, &j);
1247 if (error && error != ENOMEM)
1248 goto done2;
1249 if (uap->oldlenp) {
1250 suword32(uap->oldlenp, j);
1251 }
1252done2:
1253 mtx_unlock(&Giant);
1254 return (error);
1255}
1256
1257struct sigaction32 {
1258 u_int32_t sa_u;
1259 int sa_flags;
1260 sigset_t sa_mask;
1261};
1262
1263int
1264ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
1265{
1266 struct sigaction32 s32;
1267 struct sigaction sa, osa, *sap;
1268 int error;
1269
1270 if (uap->act) {
1271 error = copyin(uap->act, &s32, sizeof(s32));
1272 if (error)
1273 return (error);
1274 sa.sa_handler = PTRIN(s32.sa_u);
1275 CP(s32, sa, sa_flags);
1276 CP(s32, sa, sa_mask);
1277 sap = &sa;
1278 } else
1279 sap = NULL;
1280 error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1281 if (error != 0 && uap->oact != NULL) {
1282 s32.sa_u = PTROUT(osa.sa_handler);
1283 CP(osa, s32, sa_flags);
1284 CP(osa, s32, sa_mask);
1285 error = copyout(&s32, uap->oact, sizeof(s32));
1286 }
1287 return (error);
1288}
1289
738ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
739{
740 int error;
741 caddr_t sg;
742 struct timeval32 *p32, s32;
743 struct timeval *p = NULL, s;
744
745 p32 = uap->tp;
746 if (p32) {
747 sg = stackgap_init();
748 p = stackgap_alloc(&sg, sizeof(struct timeval));
749 uap->tp = (struct timeval32 *)p;
750 }
751 error = gettimeofday(td, (struct gettimeofday_args *) uap);
752 if (error)
753 return (error);
754 if (p32) {
755 error = copyin(p, &s, sizeof(s));
756 if (error)
757 return (error);
758 CP(s, s32, tv_sec);
759 CP(s, s32, tv_usec);
760 error = copyout(&s32, p32, sizeof(s32));
761 if (error)
762 return (error);
763 }
764 return (error);
765}
766
767int
768ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
769{
770 int error;
771 caddr_t sg;
772 struct rusage32 *p32, s32;
773 struct rusage *p = NULL, s;
774
775 p32 = uap->rusage;
776 if (p32) {
777 sg = stackgap_init();
778 p = stackgap_alloc(&sg, sizeof(struct rusage));
779 uap->rusage = (struct rusage32 *)p;
780 }
781 error = getrusage(td, (struct getrusage_args *) uap);
782 if (error)
783 return (error);
784 if (p32) {
785 error = copyin(p, &s, sizeof(s));
786 if (error)
787 return (error);
788 TV_CP(s, s32, ru_utime);
789 TV_CP(s, s32, ru_stime);
790 CP(s, s32, ru_maxrss);
791 CP(s, s32, ru_ixrss);
792 CP(s, s32, ru_idrss);
793 CP(s, s32, ru_isrss);
794 CP(s, s32, ru_minflt);
795 CP(s, s32, ru_majflt);
796 CP(s, s32, ru_nswap);
797 CP(s, s32, ru_inblock);
798 CP(s, s32, ru_oublock);
799 CP(s, s32, ru_msgsnd);
800 CP(s, s32, ru_msgrcv);
801 CP(s, s32, ru_nsignals);
802 CP(s, s32, ru_nvcsw);
803 CP(s, s32, ru_nivcsw);
804 error = copyout(&s32, p32, sizeof(s32));
805 }
806 return (error);
807}
808
809struct iovec32 {
810 u_int32_t iov_base;
811 int iov_len;
812};
813#define STACKGAPLEN 400
814
815int
816ia32_readv(struct thread *td, struct ia32_readv_args *uap)
817{
818 int error, osize, nsize, i;
819 caddr_t sg;
820 struct readv_args /* {
821 syscallarg(int) fd;
822 syscallarg(struct iovec *) iovp;
823 syscallarg(u_int) iovcnt;
824 } */ a;
825 struct iovec32 *oio;
826 struct iovec *nio;
827
828 sg = stackgap_init();
829
830 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
831 return (EINVAL);
832
833 osize = uap->iovcnt * sizeof (struct iovec32);
834 nsize = uap->iovcnt * sizeof (struct iovec);
835
836 oio = malloc(osize, M_TEMP, M_WAITOK);
837 nio = malloc(nsize, M_TEMP, M_WAITOK);
838
839 error = 0;
840 if ((error = copyin(uap->iovp, oio, osize)))
841 goto punt;
842 for (i = 0; i < uap->iovcnt; i++) {
843 nio[i].iov_base = PTRIN(oio[i].iov_base);
844 nio[i].iov_len = oio[i].iov_len;
845 }
846
847 a.fd = uap->fd;
848 a.iovp = stackgap_alloc(&sg, nsize);
849 a.iovcnt = uap->iovcnt;
850
851 if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
852 goto punt;
853 error = readv(td, &a);
854
855punt:
856 free(oio, M_TEMP);
857 free(nio, M_TEMP);
858 return (error);
859}
860
861int
862ia32_writev(struct thread *td, struct ia32_writev_args *uap)
863{
864 int error, i, nsize, osize;
865 caddr_t sg;
866 struct writev_args /* {
867 syscallarg(int) fd;
868 syscallarg(struct iovec *) iovp;
869 syscallarg(u_int) iovcnt;
870 } */ a;
871 struct iovec32 *oio;
872 struct iovec *nio;
873
874 sg = stackgap_init();
875
876 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
877 return (EINVAL);
878
879 osize = uap->iovcnt * sizeof (struct iovec32);
880 nsize = uap->iovcnt * sizeof (struct iovec);
881
882 oio = malloc(osize, M_TEMP, M_WAITOK);
883 nio = malloc(nsize, M_TEMP, M_WAITOK);
884
885 error = 0;
886 if ((error = copyin(uap->iovp, oio, osize)))
887 goto punt;
888 for (i = 0; i < uap->iovcnt; i++) {
889 nio[i].iov_base = PTRIN(oio[i].iov_base);
890 nio[i].iov_len = oio[i].iov_len;
891 }
892
893 a.fd = uap->fd;
894 a.iovp = stackgap_alloc(&sg, nsize);
895 a.iovcnt = uap->iovcnt;
896
897 if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
898 goto punt;
899 error = writev(td, &a);
900
901punt:
902 free(oio, M_TEMP);
903 free(nio, M_TEMP);
904 return (error);
905}
906
907int
908ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
909{
910 int error;
911 caddr_t sg;
912 struct timeval32 *p32, s32;
913 struct timeval *p = NULL, s;
914
915 p32 = uap->tv;
916 if (p32) {
917 sg = stackgap_init();
918 p = stackgap_alloc(&sg, sizeof(struct timeval));
919 uap->tv = (struct timeval32 *)p;
920 error = copyin(p32, &s32, sizeof(s32));
921 if (error)
922 return (error);
923 CP(s32, s, tv_sec);
924 CP(s32, s, tv_usec);
925 error = copyout(&s, p, sizeof(s));
926 if (error)
927 return (error);
928 }
929 return (settimeofday(td, (struct settimeofday_args *) uap));
930}
931
932int
933ia32_utimes(struct thread *td, struct ia32_utimes_args *uap)
934{
935 int error;
936 caddr_t sg;
937 struct timeval32 *p32, s32[2];
938 struct timeval *p = NULL, s[2];
939
940 p32 = uap->tptr;
941 if (p32) {
942 sg = stackgap_init();
943 p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
944 uap->tptr = (struct timeval32 *)p;
945 error = copyin(p32, s32, sizeof(s32));
946 if (error)
947 return (error);
948 CP(s32[0], s[0], tv_sec);
949 CP(s32[0], s[0], tv_usec);
950 CP(s32[1], s[1], tv_sec);
951 CP(s32[1], s[1], tv_usec);
952 error = copyout(s, p, sizeof(s));
953 if (error)
954 return (error);
955 }
956 return (utimes(td, (struct utimes_args *) uap));
957}
958
959int
960ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
961{
962 int error;
963 caddr_t sg;
964 struct timeval32 *p32, *op32, s32;
965 struct timeval *p = NULL, *op = NULL, s;
966
967 p32 = uap->delta;
968 if (p32) {
969 sg = stackgap_init();
970 p = stackgap_alloc(&sg, sizeof(struct timeval));
971 uap->delta = (struct timeval32 *)p;
972 error = copyin(p32, &s32, sizeof(s32));
973 if (error)
974 return (error);
975 CP(s32, s, tv_sec);
976 CP(s32, s, tv_usec);
977 error = copyout(&s, p, sizeof(s));
978 if (error)
979 return (error);
980 }
981 op32 = uap->olddelta;
982 if (op32) {
983 sg = stackgap_init();
984 op = stackgap_alloc(&sg, sizeof(struct timeval));
985 uap->olddelta = (struct timeval32 *)op;
986 }
987 error = utimes(td, (struct utimes_args *) uap);
988 if (error)
989 return error;
990 if (op32) {
991 error = copyin(op, &s, sizeof(s));
992 if (error)
993 return (error);
994 CP(s, s32, tv_sec);
995 CP(s, s32, tv_usec);
996 error = copyout(&s32, op32, sizeof(s32));
997 }
998 return (error);
999}
1000
1001int
1002ia32_statfs(struct thread *td, struct ia32_statfs_args *uap)
1003{
1004 int error;
1005 caddr_t sg;
1006 struct statfs32 *p32, s32;
1007 struct statfs *p = NULL, s;
1008
1009 p32 = uap->buf;
1010 if (p32) {
1011 sg = stackgap_init();
1012 p = stackgap_alloc(&sg, sizeof(struct statfs));
1013 uap->buf = (struct statfs32 *)p;
1014 }
1015 error = statfs(td, (struct statfs_args *) uap);
1016 if (error)
1017 return (error);
1018 if (p32) {
1019 error = copyin(p, &s, sizeof(s));
1020 if (error)
1021 return (error);
1022 copy_statfs(&s, &s32);
1023 error = copyout(&s32, p32, sizeof(s32));
1024 }
1025 return (error);
1026}
1027
1028int
1029ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
1030{
1031 int error;
1032 caddr_t sg;
1033 struct statfs32 *p32, s32;
1034 struct statfs *p = NULL, s;
1035
1036 p32 = uap->buf;
1037 if (p32) {
1038 sg = stackgap_init();
1039 p = stackgap_alloc(&sg, sizeof(struct statfs));
1040 uap->buf = (struct statfs32 *)p;
1041 }
1042 error = fstatfs(td, (struct fstatfs_args *) uap);
1043 if (error)
1044 return (error);
1045 if (p32) {
1046 error = copyin(p, &s, sizeof(s));
1047 if (error)
1048 return (error);
1049 copy_statfs(&s, &s32);
1050 error = copyout(&s32, p32, sizeof(s32));
1051 }
1052 return (error);
1053}
1054
1055int
1056ia32_semsys(struct thread *td, struct ia32_semsys_args *uap)
1057{
1058 /*
1059 * Vector through to semsys if it is loaded.
1060 */
1061 return sysent[169].sy_call(td, uap);
1062}
1063
1064int
1065ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
1066{
1067 /*
1068 * Vector through to msgsys if it is loaded.
1069 */
1070 return sysent[170].sy_call(td, uap);
1071}
1072
1073int
1074ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
1075{
1076 /*
1077 * Vector through to shmsys if it is loaded.
1078 */
1079 return sysent[171].sy_call(td, uap);
1080}
1081
1082int
1083ia32_pread(struct thread *td, struct ia32_pread_args *uap)
1084{
1085 struct pread_args ap;
1086
1087 ap.fd = uap->fd;
1088 ap.buf = uap->buf;
1089 ap.nbyte = uap->nbyte;
1090 ap.offset = (uap->offsetlo
1091 | ((off_t)uap->offsethi << 32));
1092 return (pread(td, &ap));
1093}
1094
1095int
1096ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
1097{
1098 struct pwrite_args ap;
1099
1100 ap.fd = uap->fd;
1101 ap.buf = uap->buf;
1102 ap.nbyte = uap->nbyte;
1103 ap.offset = (uap->offsetlo
1104 | ((off_t)uap->offsethi << 32));
1105 return (pwrite(td, &ap));
1106}
1107
1108int
1109ia32_lseek(struct thread *td, struct ia32_lseek_args *uap)
1110{
1111 int error;
1112 struct lseek_args ap;
1113 off_t pos;
1114
1115 ap.fd = uap->fd;
1116 ap.offset = (uap->offsetlo
1117 | ((off_t)uap->offsethi << 32));
1118 ap.whence = uap->whence;
1119 error = lseek(td, &ap);
1120 /* Expand the quad return into two parts for eax and edx */
1121 pos = *(off_t *)(td->td_retval);
1122 td->td_retval[0] = pos & 0xffffffff; /* %eax */
1123 td->td_retval[1] = pos >> 32; /* %edx */
1124 return error;
1125}
1126
1127int
1128ia32_truncate(struct thread *td, struct ia32_truncate_args *uap)
1129{
1130 struct truncate_args ap;
1131
1132 ap.path = uap->path;
1133 ap.length = (uap->lengthlo
1134 | ((off_t)uap->lengthhi << 32));
1135 return (truncate(td, &ap));
1136}
1137
1138int
1139ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
1140{
1141 struct ftruncate_args ap;
1142
1143 ap.fd = uap->fd;
1144 ap.length = (uap->lengthlo
1145 | ((off_t)uap->lengthhi << 32));
1146 return (ftruncate(td, &ap));
1147}
1148
1149#ifdef COMPAT_FREEBSD4
1150int
1151freebsd4_ia32_sendfile(struct thread *td,
1152 struct freebsd4_ia32_sendfile_args *uap)
1153{
1154 struct freebsd4_sendfile_args ap;
1155
1156 ap.fd = uap->fd;
1157 ap.s = uap->s;
1158 ap.offset = (uap->offsetlo
1159 | ((off_t)uap->offsethi << 32));
1160 ap.nbytes = uap->nbytes; /* XXX check */
1161 ap.hdtr = uap->hdtr; /* XXX check */
1162 ap.sbytes = uap->sbytes; /* XXX FIXME!! */
1163 ap.flags = uap->flags;
1164 return (freebsd4_sendfile(td, &ap));
1165}
1166#endif
1167
1168int
1169ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
1170{
1171 struct sendfile_args ap;
1172
1173 ap.fd = uap->fd;
1174 ap.s = uap->s;
1175 ap.offset = (uap->offsetlo
1176 | ((off_t)uap->offsethi << 32));
1177 ap.nbytes = uap->nbytes; /* XXX check */
1178 ap.hdtr = uap->hdtr; /* XXX check */
1179 ap.sbytes = uap->sbytes; /* XXX FIXME!! */
1180 ap.flags = uap->flags;
1181 return (sendfile(td, &ap));
1182}
1183
1184struct stat32 {
1185 udev_t st_dev;
1186 ino_t st_ino;
1187 mode_t st_mode;
1188 nlink_t st_nlink;
1189 uid_t st_uid;
1190 gid_t st_gid;
1191 udev_t st_rdev;
1192 struct timespec32 st_atimespec;
1193 struct timespec32 st_mtimespec;
1194 struct timespec32 st_ctimespec;
1195 off_t st_size;
1196 int64_t st_blocks;
1197 u_int32_t st_blksize;
1198 u_int32_t st_flags;
1199 u_int32_t st_gen;
1200};
1201
1202static void
1203copy_stat( struct stat *in, struct stat32 *out)
1204{
1205 CP(*in, *out, st_dev);
1206 CP(*in, *out, st_ino);
1207 CP(*in, *out, st_mode);
1208 CP(*in, *out, st_nlink);
1209 CP(*in, *out, st_uid);
1210 CP(*in, *out, st_gid);
1211 CP(*in, *out, st_rdev);
1212 TS_CP(*in, *out, st_atimespec);
1213 TS_CP(*in, *out, st_mtimespec);
1214 TS_CP(*in, *out, st_ctimespec);
1215 CP(*in, *out, st_size);
1216 CP(*in, *out, st_blocks);
1217 CP(*in, *out, st_blksize);
1218 CP(*in, *out, st_flags);
1219 CP(*in, *out, st_gen);
1220}
1221
1222int
1223ia32_stat(struct thread *td, struct ia32_stat_args *uap)
1224{
1225 int error;
1226 caddr_t sg;
1227 struct stat32 *p32, s32;
1228 struct stat *p = NULL, s;
1229
1230 p32 = uap->ub;
1231 if (p32) {
1232 sg = stackgap_init();
1233 p = stackgap_alloc(&sg, sizeof(struct stat));
1234 uap->ub = (struct stat32 *)p;
1235 }
1236 error = stat(td, (struct stat_args *) uap);
1237 if (error)
1238 return (error);
1239 if (p32) {
1240 error = copyin(p, &s, sizeof(s));
1241 if (error)
1242 return (error);
1243 copy_stat(&s, &s32);
1244 error = copyout(&s32, p32, sizeof(s32));
1245 }
1246 return (error);
1247}
1248
1249int
1250ia32_fstat(struct thread *td, struct ia32_fstat_args *uap)
1251{
1252 int error;
1253 caddr_t sg;
1254 struct stat32 *p32, s32;
1255 struct stat *p = NULL, s;
1256
1257 p32 = uap->ub;
1258 if (p32) {
1259 sg = stackgap_init();
1260 p = stackgap_alloc(&sg, sizeof(struct stat));
1261 uap->ub = (struct stat32 *)p;
1262 }
1263 error = fstat(td, (struct fstat_args *) uap);
1264 if (error)
1265 return (error);
1266 if (p32) {
1267 error = copyin(p, &s, sizeof(s));
1268 if (error)
1269 return (error);
1270 copy_stat(&s, &s32);
1271 error = copyout(&s32, p32, sizeof(s32));
1272 }
1273 return (error);
1274}
1275
1276int
1277ia32_lstat(struct thread *td, struct ia32_lstat_args *uap)
1278{
1279 int error;
1280 caddr_t sg;
1281 struct stat32 *p32, s32;
1282 struct stat *p = NULL, s;
1283
1284 p32 = uap->ub;
1285 if (p32) {
1286 sg = stackgap_init();
1287 p = stackgap_alloc(&sg, sizeof(struct stat));
1288 uap->ub = (struct stat32 *)p;
1289 }
1290 error = lstat(td, (struct lstat_args *) uap);
1291 if (error)
1292 return (error);
1293 if (p32) {
1294 error = copyin(p, &s, sizeof(s));
1295 if (error)
1296 return (error);
1297 copy_stat(&s, &s32);
1298 error = copyout(&s32, p32, sizeof(s32));
1299 }
1300 return (error);
1301}
1302
1303/*
1304 * MPSAFE
1305 */
1306int
1307ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
1308{
1309 int error, name[CTL_MAXNAME];
1310 size_t j, oldlen;
1311
1312 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1313 return (EINVAL);
1314
1315 error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1316 if (error)
1317 return (error);
1318
1319 mtx_lock(&Giant);
1320
1321 if (uap->oldlenp)
1322 oldlen = fuword32(uap->oldlenp);
1323 else
1324 oldlen = 0;
1325 error = userland_sysctl(td, name, uap->namelen,
1326 uap->old, &oldlen, 1,
1327 uap->new, uap->newlen, &j);
1328 if (error && error != ENOMEM)
1329 goto done2;
1330 if (uap->oldlenp) {
1331 suword32(uap->oldlenp, j);
1332 }
1333done2:
1334 mtx_unlock(&Giant);
1335 return (error);
1336}
1337
1338struct sigaction32 {
1339 u_int32_t sa_u;
1340 int sa_flags;
1341 sigset_t sa_mask;
1342};
1343
1344int
1345ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
1346{
1347 struct sigaction32 s32;
1348 struct sigaction sa, osa, *sap;
1349 int error;
1350
1351 if (uap->act) {
1352 error = copyin(uap->act, &s32, sizeof(s32));
1353 if (error)
1354 return (error);
1355 sa.sa_handler = PTRIN(s32.sa_u);
1356 CP(s32, sa, sa_flags);
1357 CP(s32, sa, sa_mask);
1358 sap = &sa;
1359 } else
1360 sap = NULL;
1361 error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1362 if (error != 0 && uap->oact != NULL) {
1363 s32.sa_u = PTROUT(osa.sa_handler);
1364 CP(osa, s32, sa_flags);
1365 CP(osa, s32, sa_mask);
1366 error = copyout(&s32, uap->oact, sizeof(s32));
1367 }
1368 return (error);
1369}
1370
1371#ifdef COMPAT_FREEBSD4
1372int
1373freebsd4_ia32_sigaction(struct thread *td, struct freebsd4_ia32_sigaction_args *uap)
1374{
1375 struct sigaction32 s32;
1376 struct sigaction sa, osa, *sap;
1377 int error;
1378
1379 if (uap->act) {
1380 error = copyin(uap->act, &s32, sizeof(s32));
1381 if (error)
1382 return (error);
1383 sa.sa_handler = PTRIN(s32.sa_u);
1384 CP(s32, sa, sa_flags);
1385 CP(s32, sa, sa_mask);
1386 sap = &sa;
1387 } else
1388 sap = NULL;
1389 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1390 if (error != 0 && uap->oact != NULL) {
1391 s32.sa_u = PTROUT(osa.sa_handler);
1392 CP(osa, s32, sa_flags);
1393 CP(osa, s32, sa_mask);
1394 error = copyout(&s32, uap->oact, sizeof(s32));
1395 }
1396 return (error);
1397}
1398#endif
1399
1290#if 0
1291
1292int
1293ia32_xxx(struct thread *td, struct ia32_xxx_args *uap)
1294{
1295 int error;
1296 caddr_t sg;
1297 struct yyy32 *p32, s32;
1298 struct yyy *p = NULL, s;
1299
1300 p32 = uap->zzz;
1301 if (p32) {
1302 sg = stackgap_init();
1303 p = stackgap_alloc(&sg, sizeof(struct yyy));
1304 uap->zzz = (struct yyy32 *)p;
1305 error = copyin(p32, &s32, sizeof(s32));
1306 if (error)
1307 return (error);
1308 /* translate in */
1309 error = copyout(&s, p, sizeof(s));
1310 if (error)
1311 return (error);
1312 }
1313 error = xxx(td, (struct xxx_args *) uap);
1314 if (error)
1315 return (error);
1316 if (p32) {
1317 error = copyin(p, &s, sizeof(s));
1318 if (error)
1319 return (error);
1320 /* translate out */
1321 error = copyout(&s32, p32, sizeof(s32));
1322 }
1323 return (error);
1324}
1325
1326#endif
1400#if 0
1401
1402int
1403ia32_xxx(struct thread *td, struct ia32_xxx_args *uap)
1404{
1405 int error;
1406 caddr_t sg;
1407 struct yyy32 *p32, s32;
1408 struct yyy *p = NULL, s;
1409
1410 p32 = uap->zzz;
1411 if (p32) {
1412 sg = stackgap_init();
1413 p = stackgap_alloc(&sg, sizeof(struct yyy));
1414 uap->zzz = (struct yyy32 *)p;
1415 error = copyin(p32, &s32, sizeof(s32));
1416 if (error)
1417 return (error);
1418 /* translate in */
1419 error = copyout(&s, p, sizeof(s));
1420 if (error)
1421 return (error);
1422 }
1423 error = xxx(td, (struct xxx_args *) uap);
1424 if (error)
1425 return (error);
1426 if (p32) {
1427 error = copyin(p, &s, sizeof(s));
1428 if (error)
1429 return (error);
1430 /* translate out */
1431 error = copyout(&s32, p32, sizeof(s32));
1432 }
1433 return (error);
1434}
1435
1436#endif