Deleted Added
full compact
freebsd32_misc.c (147964) freebsd32_misc.c (150883)
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
27#include <sys/cdefs.h>
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
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 147964 2005-07-13 15:12:19Z jhb $");
28__FBSDID("$FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 150883 2005-10-03 18:34:17Z jhb $");
29
30#include "opt_compat.h"
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/exec.h>
36#include <sys/fcntl.h>
37#include <sys/filedesc.h>
38#include <sys/namei.h>
39#include <sys/imgact.h>
40#include <sys/kernel.h>
41#include <sys/lock.h>
42#include <sys/malloc.h>
43#include <sys/file.h> /* Must come after sys/malloc.h */
44#include <sys/mman.h>
45#include <sys/module.h>
46#include <sys/mount.h>
47#include <sys/mutex.h>
48#include <sys/namei.h>
49#include <sys/param.h>
50#include <sys/proc.h>
51#include <sys/reboot.h>
52#include <sys/resource.h>
53#include <sys/resourcevar.h>
54#include <sys/selinfo.h>
55#include <sys/eventvar.h> /* Must come after sys/selinfo.h */
56#include <sys/pipe.h> /* Must come after sys/selinfo.h */
57#include <sys/signal.h>
58#include <sys/signalvar.h>
59#include <sys/socket.h>
60#include <sys/socketvar.h>
61#include <sys/stat.h>
29
30#include "opt_compat.h"
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/exec.h>
36#include <sys/fcntl.h>
37#include <sys/filedesc.h>
38#include <sys/namei.h>
39#include <sys/imgact.h>
40#include <sys/kernel.h>
41#include <sys/lock.h>
42#include <sys/malloc.h>
43#include <sys/file.h> /* Must come after sys/malloc.h */
44#include <sys/mman.h>
45#include <sys/module.h>
46#include <sys/mount.h>
47#include <sys/mutex.h>
48#include <sys/namei.h>
49#include <sys/param.h>
50#include <sys/proc.h>
51#include <sys/reboot.h>
52#include <sys/resource.h>
53#include <sys/resourcevar.h>
54#include <sys/selinfo.h>
55#include <sys/eventvar.h> /* Must come after sys/selinfo.h */
56#include <sys/pipe.h> /* Must come after sys/selinfo.h */
57#include <sys/signal.h>
58#include <sys/signalvar.h>
59#include <sys/socket.h>
60#include <sys/socketvar.h>
61#include <sys/stat.h>
62#include <sys/syscall.h>
62#include <sys/syscallsubr.h>
63#include <sys/sysctl.h>
64#include <sys/sysent.h>
65#include <sys/sysproto.h>
66#include <sys/systm.h>
67#include <sys/unistd.h>
68#include <sys/vnode.h>
69#include <sys/wait.h>
70
71#include <vm/vm.h>
72#include <vm/vm_kern.h>
73#include <vm/vm_param.h>
74#include <vm/pmap.h>
75#include <vm/vm_map.h>
76#include <vm/vm_object.h>
77#include <vm/vm_extern.h>
78
79#include <compat/freebsd32/freebsd32_util.h>
80#include <compat/freebsd32/freebsd32.h>
81#include <compat/freebsd32/freebsd32_proto.h>
82
83CTASSERT(sizeof(struct timeval32) == 8);
84CTASSERT(sizeof(struct timespec32) == 8);
85CTASSERT(sizeof(struct statfs32) == 256);
86CTASSERT(sizeof(struct rusage32) == 72);
87
88int
89freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
90{
91 int error, status;
92 struct rusage32 ru32;
93 struct rusage ru, *rup;
94
95 if (uap->rusage != NULL)
96 rup = &ru;
97 else
98 rup = NULL;
99 error = kern_wait(td, uap->pid, &status, uap->options, rup);
100 if (error)
101 return (error);
102 if (uap->status != NULL)
103 error = copyout(&status, uap->status, sizeof(status));
104 if (uap->rusage != NULL && error == 0) {
105 TV_CP(ru, ru32, ru_utime);
106 TV_CP(ru, ru32, ru_stime);
107 CP(ru, ru32, ru_maxrss);
108 CP(ru, ru32, ru_ixrss);
109 CP(ru, ru32, ru_idrss);
110 CP(ru, ru32, ru_isrss);
111 CP(ru, ru32, ru_minflt);
112 CP(ru, ru32, ru_majflt);
113 CP(ru, ru32, ru_nswap);
114 CP(ru, ru32, ru_inblock);
115 CP(ru, ru32, ru_oublock);
116 CP(ru, ru32, ru_msgsnd);
117 CP(ru, ru32, ru_msgrcv);
118 CP(ru, ru32, ru_nsignals);
119 CP(ru, ru32, ru_nvcsw);
120 CP(ru, ru32, ru_nivcsw);
121 error = copyout(&ru32, uap->rusage, sizeof(ru32));
122 }
123 return (error);
124}
125
126#ifdef COMPAT_FREEBSD4
127static void
128copy_statfs(struct statfs *in, struct statfs32 *out)
129{
130 CP(*in, *out, f_bsize);
131 CP(*in, *out, f_iosize);
132 CP(*in, *out, f_blocks);
133 CP(*in, *out, f_bfree);
134 CP(*in, *out, f_bavail);
135 CP(*in, *out, f_files);
136 CP(*in, *out, f_ffree);
137 CP(*in, *out, f_fsid);
138 CP(*in, *out, f_owner);
139 CP(*in, *out, f_type);
140 CP(*in, *out, f_flags);
141 CP(*in, *out, f_flags);
142 CP(*in, *out, f_syncwrites);
143 CP(*in, *out, f_asyncwrites);
144 bcopy(in->f_fstypename,
145 out->f_fstypename, MFSNAMELEN);
146 bcopy(in->f_mntonname,
147 out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
148 CP(*in, *out, f_syncreads);
149 CP(*in, *out, f_asyncreads);
150 bcopy(in->f_mntfromname,
151 out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
152}
153#endif
154
155#ifdef COMPAT_FREEBSD4
156int
157freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
158{
159 struct statfs *buf, *sp;
160 struct statfs32 stat32;
161 size_t count, size;
162 int error;
163
164 count = uap->bufsize / sizeof(struct statfs32);
165 size = count * sizeof(struct statfs);
166 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
167 if (size > 0) {
168 count = td->td_retval[0];
169 sp = buf;
170 while (count > 0 && error == 0) {
171 copy_statfs(sp, &stat32);
172 error = copyout(&stat32, uap->buf, sizeof(stat32));
173 sp++;
174 uap->buf++;
175 count--;
176 }
177 free(buf, M_TEMP);
178 }
179 return (error);
180}
181#endif
182
183struct sigaltstack32 {
184 u_int32_t ss_sp;
185 u_int32_t ss_size;
186 int ss_flags;
187};
188
189CTASSERT(sizeof(struct sigaltstack32) == 12);
190
191int
192freebsd32_sigaltstack(struct thread *td,
193 struct freebsd32_sigaltstack_args *uap)
194{
195 struct sigaltstack32 s32;
196 struct sigaltstack ss, oss, *ssp;
197 int error;
198
199 if (uap->ss != NULL) {
200 error = copyin(uap->ss, &s32, sizeof(s32));
201 if (error)
202 return (error);
203 PTRIN_CP(s32, ss, ss_sp);
204 CP(s32, ss, ss_size);
205 CP(s32, ss, ss_flags);
206 ssp = &ss;
207 } else
208 ssp = NULL;
209 error = kern_sigaltstack(td, ssp, &oss);
210 if (error == 0 && uap->oss != NULL) {
211 PTROUT_CP(oss, s32, ss_sp);
212 CP(oss, s32, ss_size);
213 CP(oss, s32, ss_flags);
214 error = copyout(&s32, uap->oss, sizeof(s32));
215 }
216 return (error);
217}
218
219/*
220 * Custom version of exec_copyin_args() so that we can translate
221 * the pointers.
222 */
223static int
224freebsd32_exec_copyin_args(struct image_args *args, char *fname,
225 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
226{
227 char *argp, *envp;
228 u_int32_t *p32, arg;
229 size_t length;
230 int error;
231
232 bzero(args, sizeof(*args));
233 if (argv == NULL)
234 return (EFAULT);
235
236 /*
237 * Allocate temporary demand zeroed space for argument and
238 * environment strings
239 */
240 args->buf = (char *) kmem_alloc_wait(exec_map,
241 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
242 if (args->buf == NULL)
243 return (ENOMEM);
244 args->begin_argv = args->buf;
245 args->endp = args->begin_argv;
246 args->stringspace = ARG_MAX;
247
248 args->fname = args->buf + ARG_MAX;
249
250 /*
251 * Copy the file name.
252 */
253 error = (segflg == UIO_SYSSPACE) ?
254 copystr(fname, args->fname, PATH_MAX, &length) :
255 copyinstr(fname, args->fname, PATH_MAX, &length);
256 if (error != 0)
257 return (error);
258
259 /*
260 * extract arguments first
261 */
262 p32 = argv;
263 for (;;) {
264 error = copyin(p32++, &arg, sizeof(arg));
265 if (error)
266 return (error);
267 if (arg == 0)
268 break;
269 argp = PTRIN(arg);
270 error = copyinstr(argp, args->endp, args->stringspace, &length);
271 if (error) {
272 if (error == ENAMETOOLONG)
273 return (E2BIG);
274 else
275 return (error);
276 }
277 args->stringspace -= length;
278 args->endp += length;
279 args->argc++;
280 }
281
282 args->begin_envv = args->endp;
283
284 /*
285 * extract environment strings
286 */
287 if (envv) {
288 p32 = envv;
289 for (;;) {
290 error = copyin(p32++, &arg, sizeof(arg));
291 if (error)
292 return (error);
293 if (arg == 0)
294 break;
295 envp = PTRIN(arg);
296 error = copyinstr(envp, args->endp, args->stringspace,
297 &length);
298 if (error) {
299 if (error == ENAMETOOLONG)
300 return (E2BIG);
301 else
302 return (error);
303 }
304 args->stringspace -= length;
305 args->endp += length;
306 args->envc++;
307 }
308 }
309
310 return (0);
311}
312
313int
314freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
315{
316 struct image_args eargs;
317 int error;
318
319 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
320 uap->argv, uap->envv);
321 if (error == 0)
322 error = kern_execve(td, &eargs, NULL);
323 exec_free_args(&eargs);
324 return (error);
325}
326
327#ifdef __ia64__
328static int
329freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
330 int prot, int fd, off_t pos)
331{
332 vm_map_t map;
333 vm_map_entry_t entry;
334 int rv;
335
336 map = &td->td_proc->p_vmspace->vm_map;
337 if (fd != -1)
338 prot |= VM_PROT_WRITE;
339
340 if (vm_map_lookup_entry(map, start, &entry)) {
341 if ((entry->protection & prot) != prot) {
342 rv = vm_map_protect(map,
343 trunc_page(start),
344 round_page(end),
345 entry->protection | prot,
346 FALSE);
347 if (rv != KERN_SUCCESS)
348 return (EINVAL);
349 }
350 } else {
351 vm_offset_t addr = trunc_page(start);
352 rv = vm_map_find(map, 0, 0,
353 &addr, PAGE_SIZE, FALSE, prot,
354 VM_PROT_ALL, 0);
355 if (rv != KERN_SUCCESS)
356 return (EINVAL);
357 }
358
359 if (fd != -1) {
360 struct pread_args r;
361 r.fd = fd;
362 r.buf = (void *) start;
363 r.nbyte = end - start;
364 r.offset = pos;
365 return (pread(td, &r));
366 } else {
367 while (start < end) {
368 subyte((void *) start, 0);
369 start++;
370 }
371 return (0);
372 }
373}
374#endif
375
376int
377freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
378{
379 struct mmap_args ap;
380 vm_offset_t addr = (vm_offset_t) uap->addr;
381 vm_size_t len = uap->len;
382 int prot = uap->prot;
383 int flags = uap->flags;
384 int fd = uap->fd;
385 off_t pos = (uap->poslo
386 | ((off_t)uap->poshi << 32));
387#ifdef __ia64__
388 vm_size_t pageoff;
389 int error;
390
391 /*
392 * Attempt to handle page size hassles.
393 */
394 pageoff = (pos & PAGE_MASK);
395 if (flags & MAP_FIXED) {
396 vm_offset_t start, end;
397 start = addr;
398 end = addr + len;
399
400 mtx_lock(&Giant);
401 if (start != trunc_page(start)) {
402 error = freebsd32_mmap_partial(td, start,
403 round_page(start), prot,
404 fd, pos);
405 if (fd != -1)
406 pos += round_page(start) - start;
407 start = round_page(start);
408 }
409 if (end != round_page(end)) {
410 vm_offset_t t = trunc_page(end);
411 error = freebsd32_mmap_partial(td, t, end,
412 prot, fd,
413 pos + t - start);
414 end = trunc_page(end);
415 }
416 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
417 /*
418 * We can't map this region at all. The specified
419 * address doesn't have the same alignment as the file
420 * position. Fake the mapping by simply reading the
421 * entire region into memory. First we need to make
422 * sure the region exists.
423 */
424 vm_map_t map;
425 struct pread_args r;
426 int rv;
427
428 prot |= VM_PROT_WRITE;
429 map = &td->td_proc->p_vmspace->vm_map;
430 rv = vm_map_remove(map, start, end);
431 if (rv != KERN_SUCCESS) {
432 mtx_unlock(&Giant);
433 return (EINVAL);
434 }
435 rv = vm_map_find(map, 0, 0,
436 &start, end - start, FALSE,
437 prot, VM_PROT_ALL, 0);
438 mtx_unlock(&Giant);
439 if (rv != KERN_SUCCESS)
440 return (EINVAL);
441 r.fd = fd;
442 r.buf = (void *) start;
443 r.nbyte = end - start;
444 r.offset = pos;
445 error = pread(td, &r);
446 if (error)
447 return (error);
448
449 td->td_retval[0] = addr;
450 return (0);
451 }
452 mtx_unlock(&Giant);
453 if (end == start) {
454 /*
455 * After dealing with the ragged ends, there
456 * might be none left.
457 */
458 td->td_retval[0] = addr;
459 return (0);
460 }
461 addr = start;
462 len = end - start;
463 }
464#endif
465
466 ap.addr = (void *) addr;
467 ap.len = len;
468 ap.prot = prot;
469 ap.flags = flags;
470 ap.fd = fd;
471 ap.pos = pos;
472
473 return (mmap(td, &ap));
474}
475
476struct itimerval32 {
477 struct timeval32 it_interval;
478 struct timeval32 it_value;
479};
480
481CTASSERT(sizeof(struct itimerval32) == 16);
482
483int
484freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
485{
486 struct itimerval itv, oitv, *itvp;
487 struct itimerval32 i32;
488 int error;
489
490 if (uap->itv != NULL) {
491 error = copyin(uap->itv, &i32, sizeof(i32));
492 if (error)
493 return (error);
494 TV_CP(i32, itv, it_interval);
495 TV_CP(i32, itv, it_value);
496 itvp = &itv;
497 } else
498 itvp = NULL;
499 error = kern_setitimer(td, uap->which, itvp, &oitv);
500 if (error || uap->oitv == NULL)
501 return (error);
502 TV_CP(oitv, i32, it_interval);
503 TV_CP(oitv, i32, it_value);
504 return (copyout(&i32, uap->oitv, sizeof(i32)));
505}
506
507int
508freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
509{
510 struct itimerval itv;
511 struct itimerval32 i32;
512 int error;
513
514 error = kern_getitimer(td, uap->which, &itv);
515 if (error || uap->itv == NULL)
516 return (error);
517 TV_CP(itv, i32, it_interval);
518 TV_CP(itv, i32, it_value);
519 return (copyout(&i32, uap->itv, sizeof(i32)));
520}
521
522int
523freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
524{
525 struct timeval32 tv32;
526 struct timeval tv, *tvp;
527 int error;
528
529 if (uap->tv != NULL) {
530 error = copyin(uap->tv, &tv32, sizeof(tv32));
531 if (error)
532 return (error);
533 CP(tv32, tv, tv_sec);
534 CP(tv32, tv, tv_usec);
535 tvp = &tv;
536 } else
537 tvp = NULL;
538 /*
539 * XXX big-endian needs to convert the fd_sets too.
540 * XXX Do pointers need PTRIN()?
541 */
542 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
543}
544
545struct kevent32 {
546 u_int32_t ident; /* identifier for this event */
547 short filter; /* filter for event */
548 u_short flags;
549 u_int fflags;
550 int32_t data;
551 u_int32_t udata; /* opaque user data identifier */
552};
553
554CTASSERT(sizeof(struct kevent32) == 20);
555static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
556static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
557
558/*
559 * Copy 'count' items into the destination list pointed to by uap->eventlist.
560 */
561static int
562freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
563{
564 struct freebsd32_kevent_args *uap;
565 struct kevent32 ks32[KQ_NEVENTS];
566 int i, error = 0;
567
568 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
569 uap = (struct freebsd32_kevent_args *)arg;
570
571 for (i = 0; i < count; i++) {
572 CP(kevp[i], ks32[i], ident);
573 CP(kevp[i], ks32[i], filter);
574 CP(kevp[i], ks32[i], flags);
575 CP(kevp[i], ks32[i], fflags);
576 CP(kevp[i], ks32[i], data);
577 PTROUT_CP(kevp[i], ks32[i], udata);
578 }
579 error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
580 if (error == 0)
581 uap->eventlist += count;
582 return (error);
583}
584
585/*
586 * Copy 'count' items from the list pointed to by uap->changelist.
587 */
588static int
589freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
590{
591 struct freebsd32_kevent_args *uap;
592 struct kevent32 ks32[KQ_NEVENTS];
593 int i, error = 0;
594
595 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
596 uap = (struct freebsd32_kevent_args *)arg;
597
598 error = copyin(uap->changelist, ks32, count * sizeof *ks32);
599 if (error)
600 goto done;
601 uap->changelist += count;
602
603 for (i = 0; i < count; i++) {
604 CP(ks32[i], kevp[i], ident);
605 CP(ks32[i], kevp[i], filter);
606 CP(ks32[i], kevp[i], flags);
607 CP(ks32[i], kevp[i], fflags);
608 CP(ks32[i], kevp[i], data);
609 PTRIN_CP(ks32[i], kevp[i], udata);
610 }
611done:
612 return (error);
613}
614
615int
616freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
617{
618 struct timespec32 ts32;
619 struct timespec ts, *tsp;
620 struct kevent_copyops k_ops = { uap,
621 freebsd32_kevent_copyout,
622 freebsd32_kevent_copyin};
623 int error;
624
625
626 if (uap->timeout) {
627 error = copyin(uap->timeout, &ts32, sizeof(ts32));
628 if (error)
629 return (error);
630 CP(ts32, ts, tv_sec);
631 CP(ts32, ts, tv_nsec);
632 tsp = &ts;
633 } else
634 tsp = NULL;
635 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
636 &k_ops, tsp);
637 return (error);
638}
639
640int
641freebsd32_gettimeofday(struct thread *td,
642 struct freebsd32_gettimeofday_args *uap)
643{
644 struct timeval atv;
645 struct timeval32 atv32;
646 struct timezone rtz;
647 int error = 0;
648
649 if (uap->tp) {
650 microtime(&atv);
651 CP(atv, atv32, tv_sec);
652 CP(atv, atv32, tv_usec);
653 error = copyout(&atv32, uap->tp, sizeof (atv32));
654 }
655 if (error == 0 && uap->tzp != NULL) {
656 rtz.tz_minuteswest = tz_minuteswest;
657 rtz.tz_dsttime = tz_dsttime;
658 error = copyout(&rtz, uap->tzp, sizeof (rtz));
659 }
660 return (error);
661}
662
663int
664freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
665{
666 struct rusage32 s32;
667 struct rusage s;
668 int error;
669
670 error = kern_getrusage(td, uap->who, &s);
671 if (error)
672 return (error);
673 if (uap->rusage != NULL) {
674 TV_CP(s, s32, ru_utime);
675 TV_CP(s, s32, ru_stime);
676 CP(s, s32, ru_maxrss);
677 CP(s, s32, ru_ixrss);
678 CP(s, s32, ru_idrss);
679 CP(s, s32, ru_isrss);
680 CP(s, s32, ru_minflt);
681 CP(s, s32, ru_majflt);
682 CP(s, s32, ru_nswap);
683 CP(s, s32, ru_inblock);
684 CP(s, s32, ru_oublock);
685 CP(s, s32, ru_msgsnd);
686 CP(s, s32, ru_msgrcv);
687 CP(s, s32, ru_nsignals);
688 CP(s, s32, ru_nvcsw);
689 CP(s, s32, ru_nivcsw);
690 error = copyout(&s32, uap->rusage, sizeof(s32));
691 }
692 return (error);
693}
694
695struct iovec32 {
696 u_int32_t iov_base;
697 int iov_len;
698};
699
700CTASSERT(sizeof(struct iovec32) == 8);
701
702static int
703freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
704{
705 struct iovec32 iov32;
706 struct iovec *iov;
707 struct uio *uio;
708 u_int iovlen;
709 int error, i;
710
711 *uiop = NULL;
712 if (iovcnt > UIO_MAXIOV)
713 return (EINVAL);
714 iovlen = iovcnt * sizeof(struct iovec);
715 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
716 iov = (struct iovec *)(uio + 1);
717 for (i = 0; i < iovcnt; i++) {
718 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
719 if (error) {
720 free(uio, M_IOV);
721 return (error);
722 }
723 iov[i].iov_base = PTRIN(iov32.iov_base);
724 iov[i].iov_len = iov32.iov_len;
725 }
726 uio->uio_iov = iov;
727 uio->uio_iovcnt = iovcnt;
728 uio->uio_segflg = UIO_USERSPACE;
729 uio->uio_offset = -1;
730 uio->uio_resid = 0;
731 for (i = 0; i < iovcnt; i++) {
732 if (iov->iov_len > INT_MAX - uio->uio_resid) {
733 free(uio, M_IOV);
734 return (EINVAL);
735 }
736 uio->uio_resid += iov->iov_len;
737 iov++;
738 }
739 *uiop = uio;
740 return (0);
741}
742
743int
744freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
745{
746 struct uio *auio;
747 int error;
748
749 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
750 if (error)
751 return (error);
752 error = kern_readv(td, uap->fd, auio);
753 free(auio, M_IOV);
754 return (error);
755}
756
757int
758freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
759{
760 struct uio *auio;
761 int error;
762
763 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
764 if (error)
765 return (error);
766 error = kern_writev(td, uap->fd, auio);
767 free(auio, M_IOV);
768 return (error);
769}
770
771int
772freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
773{
774 struct uio *auio;
775 int error;
776
777 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
778 if (error)
779 return (error);
780 error = kern_preadv(td, uap->fd, auio, uap->offset);
781 free(auio, M_IOV);
782 return (error);
783}
784
785int
786freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
787{
788 struct uio *auio;
789 int error;
790
791 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
792 if (error)
793 return (error);
794 error = kern_pwritev(td, uap->fd, auio, uap->offset);
795 free(auio, M_IOV);
796 return (error);
797}
798
799int
800freebsd32_settimeofday(struct thread *td,
801 struct freebsd32_settimeofday_args *uap)
802{
803 struct timeval32 tv32;
804 struct timeval tv, *tvp;
805 struct timezone tz, *tzp;
806 int error;
807
808 if (uap->tv) {
809 error = copyin(uap->tv, &tv32, sizeof(tv32));
810 if (error)
811 return (error);
812 CP(tv32, tv, tv_sec);
813 CP(tv32, tv, tv_usec);
814 tvp = &tv;
815 } else
816 tvp = NULL;
817 if (uap->tzp) {
818 error = copyin(uap->tzp, &tz, sizeof(tz));
819 if (error)
820 return (error);
821 tzp = &tz;
822 } else
823 tzp = NULL;
824 return (kern_settimeofday(td, tvp, tzp));
825}
826
827int
828freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
829{
830 struct timeval32 s32[2];
831 struct timeval s[2], *sp;
832 int error;
833
834 if (uap->tptr != NULL) {
835 error = copyin(uap->tptr, s32, sizeof(s32));
836 if (error)
837 return (error);
838 CP(s32[0], s[0], tv_sec);
839 CP(s32[0], s[0], tv_usec);
840 CP(s32[1], s[1], tv_sec);
841 CP(s32[1], s[1], tv_usec);
842 sp = s;
843 } else
844 sp = NULL;
845 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
846}
847
848int
849freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
850{
851 struct timeval32 tv32;
852 struct timeval delta, olddelta, *deltap;
853 int error;
854
855 if (uap->delta) {
856 error = copyin(uap->delta, &tv32, sizeof(tv32));
857 if (error)
858 return (error);
859 CP(tv32, delta, tv_sec);
860 CP(tv32, delta, tv_usec);
861 deltap = &delta;
862 } else
863 deltap = NULL;
864 error = kern_adjtime(td, deltap, &olddelta);
865 if (uap->olddelta && error == 0) {
866 CP(olddelta, tv32, tv_sec);
867 CP(olddelta, tv32, tv_usec);
868 error = copyout(&tv32, uap->olddelta, sizeof(tv32));
869 }
870 return (error);
871}
872
873#ifdef COMPAT_FREEBSD4
874int
875freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
876{
877 struct statfs32 s32;
878 struct statfs s;
879 int error;
880
881 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
882 if (error)
883 return (error);
884 copy_statfs(&s, &s32);
885 return (copyout(&s32, uap->buf, sizeof(s32)));
886}
887#endif
888
889#ifdef COMPAT_FREEBSD4
890int
891freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
892{
893 struct statfs32 s32;
894 struct statfs s;
895 int error;
896
897 error = kern_fstatfs(td, uap->fd, &s);
898 if (error)
899 return (error);
900 copy_statfs(&s, &s32);
901 return (copyout(&s32, uap->buf, sizeof(s32)));
902}
903#endif
904
905#ifdef COMPAT_FREEBSD4
906int
907freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
908{
909 struct statfs32 s32;
910 struct statfs s;
911 fhandle_t fh;
912 int error;
913
914 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
915 return (error);
916 error = kern_fhstatfs(td, fh, &s);
917 if (error)
918 return (error);
919 copy_statfs(&s, &s32);
920 return (copyout(&s32, uap->buf, sizeof(s32)));
921}
922#endif
923
924int
925freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
926{
927 /*
928 * Vector through to semsys if it is loaded.
929 */
63#include <sys/syscallsubr.h>
64#include <sys/sysctl.h>
65#include <sys/sysent.h>
66#include <sys/sysproto.h>
67#include <sys/systm.h>
68#include <sys/unistd.h>
69#include <sys/vnode.h>
70#include <sys/wait.h>
71
72#include <vm/vm.h>
73#include <vm/vm_kern.h>
74#include <vm/vm_param.h>
75#include <vm/pmap.h>
76#include <vm/vm_map.h>
77#include <vm/vm_object.h>
78#include <vm/vm_extern.h>
79
80#include <compat/freebsd32/freebsd32_util.h>
81#include <compat/freebsd32/freebsd32.h>
82#include <compat/freebsd32/freebsd32_proto.h>
83
84CTASSERT(sizeof(struct timeval32) == 8);
85CTASSERT(sizeof(struct timespec32) == 8);
86CTASSERT(sizeof(struct statfs32) == 256);
87CTASSERT(sizeof(struct rusage32) == 72);
88
89int
90freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
91{
92 int error, status;
93 struct rusage32 ru32;
94 struct rusage ru, *rup;
95
96 if (uap->rusage != NULL)
97 rup = &ru;
98 else
99 rup = NULL;
100 error = kern_wait(td, uap->pid, &status, uap->options, rup);
101 if (error)
102 return (error);
103 if (uap->status != NULL)
104 error = copyout(&status, uap->status, sizeof(status));
105 if (uap->rusage != NULL && error == 0) {
106 TV_CP(ru, ru32, ru_utime);
107 TV_CP(ru, ru32, ru_stime);
108 CP(ru, ru32, ru_maxrss);
109 CP(ru, ru32, ru_ixrss);
110 CP(ru, ru32, ru_idrss);
111 CP(ru, ru32, ru_isrss);
112 CP(ru, ru32, ru_minflt);
113 CP(ru, ru32, ru_majflt);
114 CP(ru, ru32, ru_nswap);
115 CP(ru, ru32, ru_inblock);
116 CP(ru, ru32, ru_oublock);
117 CP(ru, ru32, ru_msgsnd);
118 CP(ru, ru32, ru_msgrcv);
119 CP(ru, ru32, ru_nsignals);
120 CP(ru, ru32, ru_nvcsw);
121 CP(ru, ru32, ru_nivcsw);
122 error = copyout(&ru32, uap->rusage, sizeof(ru32));
123 }
124 return (error);
125}
126
127#ifdef COMPAT_FREEBSD4
128static void
129copy_statfs(struct statfs *in, struct statfs32 *out)
130{
131 CP(*in, *out, f_bsize);
132 CP(*in, *out, f_iosize);
133 CP(*in, *out, f_blocks);
134 CP(*in, *out, f_bfree);
135 CP(*in, *out, f_bavail);
136 CP(*in, *out, f_files);
137 CP(*in, *out, f_ffree);
138 CP(*in, *out, f_fsid);
139 CP(*in, *out, f_owner);
140 CP(*in, *out, f_type);
141 CP(*in, *out, f_flags);
142 CP(*in, *out, f_flags);
143 CP(*in, *out, f_syncwrites);
144 CP(*in, *out, f_asyncwrites);
145 bcopy(in->f_fstypename,
146 out->f_fstypename, MFSNAMELEN);
147 bcopy(in->f_mntonname,
148 out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
149 CP(*in, *out, f_syncreads);
150 CP(*in, *out, f_asyncreads);
151 bcopy(in->f_mntfromname,
152 out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
153}
154#endif
155
156#ifdef COMPAT_FREEBSD4
157int
158freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
159{
160 struct statfs *buf, *sp;
161 struct statfs32 stat32;
162 size_t count, size;
163 int error;
164
165 count = uap->bufsize / sizeof(struct statfs32);
166 size = count * sizeof(struct statfs);
167 error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
168 if (size > 0) {
169 count = td->td_retval[0];
170 sp = buf;
171 while (count > 0 && error == 0) {
172 copy_statfs(sp, &stat32);
173 error = copyout(&stat32, uap->buf, sizeof(stat32));
174 sp++;
175 uap->buf++;
176 count--;
177 }
178 free(buf, M_TEMP);
179 }
180 return (error);
181}
182#endif
183
184struct sigaltstack32 {
185 u_int32_t ss_sp;
186 u_int32_t ss_size;
187 int ss_flags;
188};
189
190CTASSERT(sizeof(struct sigaltstack32) == 12);
191
192int
193freebsd32_sigaltstack(struct thread *td,
194 struct freebsd32_sigaltstack_args *uap)
195{
196 struct sigaltstack32 s32;
197 struct sigaltstack ss, oss, *ssp;
198 int error;
199
200 if (uap->ss != NULL) {
201 error = copyin(uap->ss, &s32, sizeof(s32));
202 if (error)
203 return (error);
204 PTRIN_CP(s32, ss, ss_sp);
205 CP(s32, ss, ss_size);
206 CP(s32, ss, ss_flags);
207 ssp = &ss;
208 } else
209 ssp = NULL;
210 error = kern_sigaltstack(td, ssp, &oss);
211 if (error == 0 && uap->oss != NULL) {
212 PTROUT_CP(oss, s32, ss_sp);
213 CP(oss, s32, ss_size);
214 CP(oss, s32, ss_flags);
215 error = copyout(&s32, uap->oss, sizeof(s32));
216 }
217 return (error);
218}
219
220/*
221 * Custom version of exec_copyin_args() so that we can translate
222 * the pointers.
223 */
224static int
225freebsd32_exec_copyin_args(struct image_args *args, char *fname,
226 enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
227{
228 char *argp, *envp;
229 u_int32_t *p32, arg;
230 size_t length;
231 int error;
232
233 bzero(args, sizeof(*args));
234 if (argv == NULL)
235 return (EFAULT);
236
237 /*
238 * Allocate temporary demand zeroed space for argument and
239 * environment strings
240 */
241 args->buf = (char *) kmem_alloc_wait(exec_map,
242 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
243 if (args->buf == NULL)
244 return (ENOMEM);
245 args->begin_argv = args->buf;
246 args->endp = args->begin_argv;
247 args->stringspace = ARG_MAX;
248
249 args->fname = args->buf + ARG_MAX;
250
251 /*
252 * Copy the file name.
253 */
254 error = (segflg == UIO_SYSSPACE) ?
255 copystr(fname, args->fname, PATH_MAX, &length) :
256 copyinstr(fname, args->fname, PATH_MAX, &length);
257 if (error != 0)
258 return (error);
259
260 /*
261 * extract arguments first
262 */
263 p32 = argv;
264 for (;;) {
265 error = copyin(p32++, &arg, sizeof(arg));
266 if (error)
267 return (error);
268 if (arg == 0)
269 break;
270 argp = PTRIN(arg);
271 error = copyinstr(argp, args->endp, args->stringspace, &length);
272 if (error) {
273 if (error == ENAMETOOLONG)
274 return (E2BIG);
275 else
276 return (error);
277 }
278 args->stringspace -= length;
279 args->endp += length;
280 args->argc++;
281 }
282
283 args->begin_envv = args->endp;
284
285 /*
286 * extract environment strings
287 */
288 if (envv) {
289 p32 = envv;
290 for (;;) {
291 error = copyin(p32++, &arg, sizeof(arg));
292 if (error)
293 return (error);
294 if (arg == 0)
295 break;
296 envp = PTRIN(arg);
297 error = copyinstr(envp, args->endp, args->stringspace,
298 &length);
299 if (error) {
300 if (error == ENAMETOOLONG)
301 return (E2BIG);
302 else
303 return (error);
304 }
305 args->stringspace -= length;
306 args->endp += length;
307 args->envc++;
308 }
309 }
310
311 return (0);
312}
313
314int
315freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
316{
317 struct image_args eargs;
318 int error;
319
320 error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
321 uap->argv, uap->envv);
322 if (error == 0)
323 error = kern_execve(td, &eargs, NULL);
324 exec_free_args(&eargs);
325 return (error);
326}
327
328#ifdef __ia64__
329static int
330freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
331 int prot, int fd, off_t pos)
332{
333 vm_map_t map;
334 vm_map_entry_t entry;
335 int rv;
336
337 map = &td->td_proc->p_vmspace->vm_map;
338 if (fd != -1)
339 prot |= VM_PROT_WRITE;
340
341 if (vm_map_lookup_entry(map, start, &entry)) {
342 if ((entry->protection & prot) != prot) {
343 rv = vm_map_protect(map,
344 trunc_page(start),
345 round_page(end),
346 entry->protection | prot,
347 FALSE);
348 if (rv != KERN_SUCCESS)
349 return (EINVAL);
350 }
351 } else {
352 vm_offset_t addr = trunc_page(start);
353 rv = vm_map_find(map, 0, 0,
354 &addr, PAGE_SIZE, FALSE, prot,
355 VM_PROT_ALL, 0);
356 if (rv != KERN_SUCCESS)
357 return (EINVAL);
358 }
359
360 if (fd != -1) {
361 struct pread_args r;
362 r.fd = fd;
363 r.buf = (void *) start;
364 r.nbyte = end - start;
365 r.offset = pos;
366 return (pread(td, &r));
367 } else {
368 while (start < end) {
369 subyte((void *) start, 0);
370 start++;
371 }
372 return (0);
373 }
374}
375#endif
376
377int
378freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
379{
380 struct mmap_args ap;
381 vm_offset_t addr = (vm_offset_t) uap->addr;
382 vm_size_t len = uap->len;
383 int prot = uap->prot;
384 int flags = uap->flags;
385 int fd = uap->fd;
386 off_t pos = (uap->poslo
387 | ((off_t)uap->poshi << 32));
388#ifdef __ia64__
389 vm_size_t pageoff;
390 int error;
391
392 /*
393 * Attempt to handle page size hassles.
394 */
395 pageoff = (pos & PAGE_MASK);
396 if (flags & MAP_FIXED) {
397 vm_offset_t start, end;
398 start = addr;
399 end = addr + len;
400
401 mtx_lock(&Giant);
402 if (start != trunc_page(start)) {
403 error = freebsd32_mmap_partial(td, start,
404 round_page(start), prot,
405 fd, pos);
406 if (fd != -1)
407 pos += round_page(start) - start;
408 start = round_page(start);
409 }
410 if (end != round_page(end)) {
411 vm_offset_t t = trunc_page(end);
412 error = freebsd32_mmap_partial(td, t, end,
413 prot, fd,
414 pos + t - start);
415 end = trunc_page(end);
416 }
417 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
418 /*
419 * We can't map this region at all. The specified
420 * address doesn't have the same alignment as the file
421 * position. Fake the mapping by simply reading the
422 * entire region into memory. First we need to make
423 * sure the region exists.
424 */
425 vm_map_t map;
426 struct pread_args r;
427 int rv;
428
429 prot |= VM_PROT_WRITE;
430 map = &td->td_proc->p_vmspace->vm_map;
431 rv = vm_map_remove(map, start, end);
432 if (rv != KERN_SUCCESS) {
433 mtx_unlock(&Giant);
434 return (EINVAL);
435 }
436 rv = vm_map_find(map, 0, 0,
437 &start, end - start, FALSE,
438 prot, VM_PROT_ALL, 0);
439 mtx_unlock(&Giant);
440 if (rv != KERN_SUCCESS)
441 return (EINVAL);
442 r.fd = fd;
443 r.buf = (void *) start;
444 r.nbyte = end - start;
445 r.offset = pos;
446 error = pread(td, &r);
447 if (error)
448 return (error);
449
450 td->td_retval[0] = addr;
451 return (0);
452 }
453 mtx_unlock(&Giant);
454 if (end == start) {
455 /*
456 * After dealing with the ragged ends, there
457 * might be none left.
458 */
459 td->td_retval[0] = addr;
460 return (0);
461 }
462 addr = start;
463 len = end - start;
464 }
465#endif
466
467 ap.addr = (void *) addr;
468 ap.len = len;
469 ap.prot = prot;
470 ap.flags = flags;
471 ap.fd = fd;
472 ap.pos = pos;
473
474 return (mmap(td, &ap));
475}
476
477struct itimerval32 {
478 struct timeval32 it_interval;
479 struct timeval32 it_value;
480};
481
482CTASSERT(sizeof(struct itimerval32) == 16);
483
484int
485freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
486{
487 struct itimerval itv, oitv, *itvp;
488 struct itimerval32 i32;
489 int error;
490
491 if (uap->itv != NULL) {
492 error = copyin(uap->itv, &i32, sizeof(i32));
493 if (error)
494 return (error);
495 TV_CP(i32, itv, it_interval);
496 TV_CP(i32, itv, it_value);
497 itvp = &itv;
498 } else
499 itvp = NULL;
500 error = kern_setitimer(td, uap->which, itvp, &oitv);
501 if (error || uap->oitv == NULL)
502 return (error);
503 TV_CP(oitv, i32, it_interval);
504 TV_CP(oitv, i32, it_value);
505 return (copyout(&i32, uap->oitv, sizeof(i32)));
506}
507
508int
509freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
510{
511 struct itimerval itv;
512 struct itimerval32 i32;
513 int error;
514
515 error = kern_getitimer(td, uap->which, &itv);
516 if (error || uap->itv == NULL)
517 return (error);
518 TV_CP(itv, i32, it_interval);
519 TV_CP(itv, i32, it_value);
520 return (copyout(&i32, uap->itv, sizeof(i32)));
521}
522
523int
524freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
525{
526 struct timeval32 tv32;
527 struct timeval tv, *tvp;
528 int error;
529
530 if (uap->tv != NULL) {
531 error = copyin(uap->tv, &tv32, sizeof(tv32));
532 if (error)
533 return (error);
534 CP(tv32, tv, tv_sec);
535 CP(tv32, tv, tv_usec);
536 tvp = &tv;
537 } else
538 tvp = NULL;
539 /*
540 * XXX big-endian needs to convert the fd_sets too.
541 * XXX Do pointers need PTRIN()?
542 */
543 return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
544}
545
546struct kevent32 {
547 u_int32_t ident; /* identifier for this event */
548 short filter; /* filter for event */
549 u_short flags;
550 u_int fflags;
551 int32_t data;
552 u_int32_t udata; /* opaque user data identifier */
553};
554
555CTASSERT(sizeof(struct kevent32) == 20);
556static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
557static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
558
559/*
560 * Copy 'count' items into the destination list pointed to by uap->eventlist.
561 */
562static int
563freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
564{
565 struct freebsd32_kevent_args *uap;
566 struct kevent32 ks32[KQ_NEVENTS];
567 int i, error = 0;
568
569 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
570 uap = (struct freebsd32_kevent_args *)arg;
571
572 for (i = 0; i < count; i++) {
573 CP(kevp[i], ks32[i], ident);
574 CP(kevp[i], ks32[i], filter);
575 CP(kevp[i], ks32[i], flags);
576 CP(kevp[i], ks32[i], fflags);
577 CP(kevp[i], ks32[i], data);
578 PTROUT_CP(kevp[i], ks32[i], udata);
579 }
580 error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
581 if (error == 0)
582 uap->eventlist += count;
583 return (error);
584}
585
586/*
587 * Copy 'count' items from the list pointed to by uap->changelist.
588 */
589static int
590freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
591{
592 struct freebsd32_kevent_args *uap;
593 struct kevent32 ks32[KQ_NEVENTS];
594 int i, error = 0;
595
596 KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
597 uap = (struct freebsd32_kevent_args *)arg;
598
599 error = copyin(uap->changelist, ks32, count * sizeof *ks32);
600 if (error)
601 goto done;
602 uap->changelist += count;
603
604 for (i = 0; i < count; i++) {
605 CP(ks32[i], kevp[i], ident);
606 CP(ks32[i], kevp[i], filter);
607 CP(ks32[i], kevp[i], flags);
608 CP(ks32[i], kevp[i], fflags);
609 CP(ks32[i], kevp[i], data);
610 PTRIN_CP(ks32[i], kevp[i], udata);
611 }
612done:
613 return (error);
614}
615
616int
617freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
618{
619 struct timespec32 ts32;
620 struct timespec ts, *tsp;
621 struct kevent_copyops k_ops = { uap,
622 freebsd32_kevent_copyout,
623 freebsd32_kevent_copyin};
624 int error;
625
626
627 if (uap->timeout) {
628 error = copyin(uap->timeout, &ts32, sizeof(ts32));
629 if (error)
630 return (error);
631 CP(ts32, ts, tv_sec);
632 CP(ts32, ts, tv_nsec);
633 tsp = &ts;
634 } else
635 tsp = NULL;
636 error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
637 &k_ops, tsp);
638 return (error);
639}
640
641int
642freebsd32_gettimeofday(struct thread *td,
643 struct freebsd32_gettimeofday_args *uap)
644{
645 struct timeval atv;
646 struct timeval32 atv32;
647 struct timezone rtz;
648 int error = 0;
649
650 if (uap->tp) {
651 microtime(&atv);
652 CP(atv, atv32, tv_sec);
653 CP(atv, atv32, tv_usec);
654 error = copyout(&atv32, uap->tp, sizeof (atv32));
655 }
656 if (error == 0 && uap->tzp != NULL) {
657 rtz.tz_minuteswest = tz_minuteswest;
658 rtz.tz_dsttime = tz_dsttime;
659 error = copyout(&rtz, uap->tzp, sizeof (rtz));
660 }
661 return (error);
662}
663
664int
665freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
666{
667 struct rusage32 s32;
668 struct rusage s;
669 int error;
670
671 error = kern_getrusage(td, uap->who, &s);
672 if (error)
673 return (error);
674 if (uap->rusage != NULL) {
675 TV_CP(s, s32, ru_utime);
676 TV_CP(s, s32, ru_stime);
677 CP(s, s32, ru_maxrss);
678 CP(s, s32, ru_ixrss);
679 CP(s, s32, ru_idrss);
680 CP(s, s32, ru_isrss);
681 CP(s, s32, ru_minflt);
682 CP(s, s32, ru_majflt);
683 CP(s, s32, ru_nswap);
684 CP(s, s32, ru_inblock);
685 CP(s, s32, ru_oublock);
686 CP(s, s32, ru_msgsnd);
687 CP(s, s32, ru_msgrcv);
688 CP(s, s32, ru_nsignals);
689 CP(s, s32, ru_nvcsw);
690 CP(s, s32, ru_nivcsw);
691 error = copyout(&s32, uap->rusage, sizeof(s32));
692 }
693 return (error);
694}
695
696struct iovec32 {
697 u_int32_t iov_base;
698 int iov_len;
699};
700
701CTASSERT(sizeof(struct iovec32) == 8);
702
703static int
704freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
705{
706 struct iovec32 iov32;
707 struct iovec *iov;
708 struct uio *uio;
709 u_int iovlen;
710 int error, i;
711
712 *uiop = NULL;
713 if (iovcnt > UIO_MAXIOV)
714 return (EINVAL);
715 iovlen = iovcnt * sizeof(struct iovec);
716 uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
717 iov = (struct iovec *)(uio + 1);
718 for (i = 0; i < iovcnt; i++) {
719 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
720 if (error) {
721 free(uio, M_IOV);
722 return (error);
723 }
724 iov[i].iov_base = PTRIN(iov32.iov_base);
725 iov[i].iov_len = iov32.iov_len;
726 }
727 uio->uio_iov = iov;
728 uio->uio_iovcnt = iovcnt;
729 uio->uio_segflg = UIO_USERSPACE;
730 uio->uio_offset = -1;
731 uio->uio_resid = 0;
732 for (i = 0; i < iovcnt; i++) {
733 if (iov->iov_len > INT_MAX - uio->uio_resid) {
734 free(uio, M_IOV);
735 return (EINVAL);
736 }
737 uio->uio_resid += iov->iov_len;
738 iov++;
739 }
740 *uiop = uio;
741 return (0);
742}
743
744int
745freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
746{
747 struct uio *auio;
748 int error;
749
750 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
751 if (error)
752 return (error);
753 error = kern_readv(td, uap->fd, auio);
754 free(auio, M_IOV);
755 return (error);
756}
757
758int
759freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
760{
761 struct uio *auio;
762 int error;
763
764 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
765 if (error)
766 return (error);
767 error = kern_writev(td, uap->fd, auio);
768 free(auio, M_IOV);
769 return (error);
770}
771
772int
773freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
774{
775 struct uio *auio;
776 int error;
777
778 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
779 if (error)
780 return (error);
781 error = kern_preadv(td, uap->fd, auio, uap->offset);
782 free(auio, M_IOV);
783 return (error);
784}
785
786int
787freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
788{
789 struct uio *auio;
790 int error;
791
792 error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
793 if (error)
794 return (error);
795 error = kern_pwritev(td, uap->fd, auio, uap->offset);
796 free(auio, M_IOV);
797 return (error);
798}
799
800int
801freebsd32_settimeofday(struct thread *td,
802 struct freebsd32_settimeofday_args *uap)
803{
804 struct timeval32 tv32;
805 struct timeval tv, *tvp;
806 struct timezone tz, *tzp;
807 int error;
808
809 if (uap->tv) {
810 error = copyin(uap->tv, &tv32, sizeof(tv32));
811 if (error)
812 return (error);
813 CP(tv32, tv, tv_sec);
814 CP(tv32, tv, tv_usec);
815 tvp = &tv;
816 } else
817 tvp = NULL;
818 if (uap->tzp) {
819 error = copyin(uap->tzp, &tz, sizeof(tz));
820 if (error)
821 return (error);
822 tzp = &tz;
823 } else
824 tzp = NULL;
825 return (kern_settimeofday(td, tvp, tzp));
826}
827
828int
829freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
830{
831 struct timeval32 s32[2];
832 struct timeval s[2], *sp;
833 int error;
834
835 if (uap->tptr != NULL) {
836 error = copyin(uap->tptr, s32, sizeof(s32));
837 if (error)
838 return (error);
839 CP(s32[0], s[0], tv_sec);
840 CP(s32[0], s[0], tv_usec);
841 CP(s32[1], s[1], tv_sec);
842 CP(s32[1], s[1], tv_usec);
843 sp = s;
844 } else
845 sp = NULL;
846 return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
847}
848
849int
850freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
851{
852 struct timeval32 tv32;
853 struct timeval delta, olddelta, *deltap;
854 int error;
855
856 if (uap->delta) {
857 error = copyin(uap->delta, &tv32, sizeof(tv32));
858 if (error)
859 return (error);
860 CP(tv32, delta, tv_sec);
861 CP(tv32, delta, tv_usec);
862 deltap = &delta;
863 } else
864 deltap = NULL;
865 error = kern_adjtime(td, deltap, &olddelta);
866 if (uap->olddelta && error == 0) {
867 CP(olddelta, tv32, tv_sec);
868 CP(olddelta, tv32, tv_usec);
869 error = copyout(&tv32, uap->olddelta, sizeof(tv32));
870 }
871 return (error);
872}
873
874#ifdef COMPAT_FREEBSD4
875int
876freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
877{
878 struct statfs32 s32;
879 struct statfs s;
880 int error;
881
882 error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
883 if (error)
884 return (error);
885 copy_statfs(&s, &s32);
886 return (copyout(&s32, uap->buf, sizeof(s32)));
887}
888#endif
889
890#ifdef COMPAT_FREEBSD4
891int
892freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
893{
894 struct statfs32 s32;
895 struct statfs s;
896 int error;
897
898 error = kern_fstatfs(td, uap->fd, &s);
899 if (error)
900 return (error);
901 copy_statfs(&s, &s32);
902 return (copyout(&s32, uap->buf, sizeof(s32)));
903}
904#endif
905
906#ifdef COMPAT_FREEBSD4
907int
908freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
909{
910 struct statfs32 s32;
911 struct statfs s;
912 fhandle_t fh;
913 int error;
914
915 if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
916 return (error);
917 error = kern_fhstatfs(td, fh, &s);
918 if (error)
919 return (error);
920 copy_statfs(&s, &s32);
921 return (copyout(&s32, uap->buf, sizeof(s32)));
922}
923#endif
924
925int
926freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
927{
928 /*
929 * Vector through to semsys if it is loaded.
930 */
930 return sysent[169].sy_call(td, uap);
931 return sysent[SYS_semsys].sy_call(td, uap);
931}
932
933int
934freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
935{
936 /*
937 * Vector through to msgsys if it is loaded.
938 */
932}
933
934int
935freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
936{
937 /*
938 * Vector through to msgsys if it is loaded.
939 */
939 return sysent[170].sy_call(td, uap);
940 return sysent[SYS_msgsys].sy_call(td, uap);
940}
941
942int
943freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
944{
945 /*
946 * Vector through to shmsys if it is loaded.
947 */
941}
942
943int
944freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
945{
946 /*
947 * Vector through to shmsys if it is loaded.
948 */
948 return sysent[171].sy_call(td, uap);
949 return sysent[SYS_shmsys].sy_call(td, uap);
949}
950
951int
952freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
953{
954 struct pread_args ap;
955
956 ap.fd = uap->fd;
957 ap.buf = uap->buf;
958 ap.nbyte = uap->nbyte;
959 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
960 return (pread(td, &ap));
961}
962
963int
964freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
965{
966 struct pwrite_args ap;
967
968 ap.fd = uap->fd;
969 ap.buf = uap->buf;
970 ap.nbyte = uap->nbyte;
971 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
972 return (pwrite(td, &ap));
973}
974
975int
976freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
977{
978 int error;
979 struct lseek_args ap;
980 off_t pos;
981
982 ap.fd = uap->fd;
983 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
984 ap.whence = uap->whence;
985 error = lseek(td, &ap);
986 /* Expand the quad return into two parts for eax and edx */
987 pos = *(off_t *)(td->td_retval);
988 td->td_retval[0] = pos & 0xffffffff; /* %eax */
989 td->td_retval[1] = pos >> 32; /* %edx */
990 return error;
991}
992
993int
994freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
995{
996 struct truncate_args ap;
997
998 ap.path = uap->path;
999 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1000 return (truncate(td, &ap));
1001}
1002
1003int
1004freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1005{
1006 struct ftruncate_args ap;
1007
1008 ap.fd = uap->fd;
1009 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1010 return (ftruncate(td, &ap));
1011}
1012
1013#ifdef COMPAT_FREEBSD4
1014int
1015freebsd4_freebsd32_sendfile(struct thread *td,
1016 struct freebsd4_freebsd32_sendfile_args *uap)
1017{
1018 struct freebsd4_sendfile_args ap;
1019
1020 ap.fd = uap->fd;
1021 ap.s = uap->s;
1022 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1023 ap.nbytes = uap->nbytes; /* XXX check */
1024 ap.hdtr = uap->hdtr; /* XXX check */
1025 ap.sbytes = uap->sbytes; /* XXX FIXME!! */
1026 ap.flags = uap->flags;
1027 return (freebsd4_sendfile(td, &ap));
1028}
1029#endif
1030
1031int
1032freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1033{
1034 struct sendfile_args ap;
1035
1036 ap.fd = uap->fd;
1037 ap.s = uap->s;
1038 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1039 ap.nbytes = uap->nbytes; /* XXX check */
1040 ap.hdtr = uap->hdtr; /* XXX check */
1041 ap.sbytes = uap->sbytes; /* XXX FIXME!! */
1042 ap.flags = uap->flags;
1043 return (sendfile(td, &ap));
1044}
1045
1046struct stat32 {
1047 dev_t st_dev;
1048 ino_t st_ino;
1049 mode_t st_mode;
1050 nlink_t st_nlink;
1051 uid_t st_uid;
1052 gid_t st_gid;
1053 dev_t st_rdev;
1054 struct timespec32 st_atimespec;
1055 struct timespec32 st_mtimespec;
1056 struct timespec32 st_ctimespec;
1057 off_t st_size;
1058 int64_t st_blocks;
1059 u_int32_t st_blksize;
1060 u_int32_t st_flags;
1061 u_int32_t st_gen;
1062 struct timespec32 st_birthtimespec;
1063 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1064 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1065};
1066
1067
1068CTASSERT(sizeof(struct stat32) == 96);
1069
1070static void
1071copy_stat( struct stat *in, struct stat32 *out)
1072{
1073 CP(*in, *out, st_dev);
1074 CP(*in, *out, st_ino);
1075 CP(*in, *out, st_mode);
1076 CP(*in, *out, st_nlink);
1077 CP(*in, *out, st_uid);
1078 CP(*in, *out, st_gid);
1079 CP(*in, *out, st_rdev);
1080 TS_CP(*in, *out, st_atimespec);
1081 TS_CP(*in, *out, st_mtimespec);
1082 TS_CP(*in, *out, st_ctimespec);
1083 CP(*in, *out, st_size);
1084 CP(*in, *out, st_blocks);
1085 CP(*in, *out, st_blksize);
1086 CP(*in, *out, st_flags);
1087 CP(*in, *out, st_gen);
1088}
1089
1090int
1091freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1092{
1093 struct stat sb;
1094 struct stat32 sb32;
1095 int error;
1096
1097 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1098 if (error)
1099 return (error);
1100 copy_stat(&sb, &sb32);
1101 error = copyout(&sb32, uap->ub, sizeof (sb32));
1102 return (error);
1103}
1104
1105int
1106freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1107{
1108 struct stat ub;
1109 struct stat32 ub32;
1110 int error;
1111
1112 error = kern_fstat(td, uap->fd, &ub);
1113 if (error)
1114 return (error);
1115 copy_stat(&ub, &ub32);
1116 error = copyout(&ub32, uap->ub, sizeof(ub32));
1117 return (error);
1118}
1119
1120int
1121freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1122{
1123 struct stat sb;
1124 struct stat32 sb32;
1125 int error;
1126
1127 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1128 if (error)
1129 return (error);
1130 copy_stat(&sb, &sb32);
1131 error = copyout(&sb32, uap->ub, sizeof (sb32));
1132 return (error);
1133}
1134
1135/*
1136 * MPSAFE
1137 */
1138int
1139freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1140{
1141 int error, name[CTL_MAXNAME];
1142 size_t j, oldlen;
1143
1144 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1145 return (EINVAL);
1146 error = copyin(uap->name, name, uap->namelen * sizeof(int));
1147 if (error)
1148 return (error);
1149 mtx_lock(&Giant);
1150 if (uap->oldlenp)
1151 oldlen = fuword32(uap->oldlenp);
1152 else
1153 oldlen = 0;
1154 error = userland_sysctl(td, name, uap->namelen,
1155 uap->old, &oldlen, 1,
1156 uap->new, uap->newlen, &j, SCTL_MASK32);
1157 if (error && error != ENOMEM)
1158 goto done2;
1159 if (uap->oldlenp)
1160 suword32(uap->oldlenp, j);
1161done2:
1162 mtx_unlock(&Giant);
1163 return (error);
1164}
1165
1166struct sigaction32 {
1167 u_int32_t sa_u;
1168 int sa_flags;
1169 sigset_t sa_mask;
1170};
1171
1172CTASSERT(sizeof(struct sigaction32) == 24);
1173
1174int
1175freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1176{
1177 struct sigaction32 s32;
1178 struct sigaction sa, osa, *sap;
1179 int error;
1180
1181 if (uap->act) {
1182 error = copyin(uap->act, &s32, sizeof(s32));
1183 if (error)
1184 return (error);
1185 sa.sa_handler = PTRIN(s32.sa_u);
1186 CP(s32, sa, sa_flags);
1187 CP(s32, sa, sa_mask);
1188 sap = &sa;
1189 } else
1190 sap = NULL;
1191 error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1192 if (error == 0 && uap->oact != NULL) {
1193 s32.sa_u = PTROUT(osa.sa_handler);
1194 CP(osa, s32, sa_flags);
1195 CP(osa, s32, sa_mask);
1196 error = copyout(&s32, uap->oact, sizeof(s32));
1197 }
1198 return (error);
1199}
1200
1201#ifdef COMPAT_FREEBSD4
1202int
1203freebsd4_freebsd32_sigaction(struct thread *td,
1204 struct freebsd4_freebsd32_sigaction_args *uap)
1205{
1206 struct sigaction32 s32;
1207 struct sigaction sa, osa, *sap;
1208 int error;
1209
1210 if (uap->act) {
1211 error = copyin(uap->act, &s32, sizeof(s32));
1212 if (error)
1213 return (error);
1214 sa.sa_handler = PTRIN(s32.sa_u);
1215 CP(s32, sa, sa_flags);
1216 CP(s32, sa, sa_mask);
1217 sap = &sa;
1218 } else
1219 sap = NULL;
1220 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1221 if (error == 0 && uap->oact != NULL) {
1222 s32.sa_u = PTROUT(osa.sa_handler);
1223 CP(osa, s32, sa_flags);
1224 CP(osa, s32, sa_mask);
1225 error = copyout(&s32, uap->oact, sizeof(s32));
1226 }
1227 return (error);
1228}
1229#endif
1230
1231int
1232freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1233{
1234 struct timespec32 rmt32, rqt32;
1235 struct timespec rmt, rqt;
1236 int error;
1237
1238 error = copyin(uap->rqtp, &rqt32, sizeof(rqt));
1239 if (error)
1240 return (error);
1241
1242 CP(rqt32, rqt, tv_sec);
1243 CP(rqt32, rqt, tv_nsec);
1244
1245 if (uap->rmtp &&
1246 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1247 return (EFAULT);
1248 error = kern_nanosleep(td, &rqt, &rmt);
1249 if (error && uap->rmtp) {
1250 int error2;
1251
1252 CP(rmt, rmt32, tv_sec);
1253 CP(rmt, rmt32, tv_nsec);
1254
1255 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt));
1256 if (error2)
1257 error = error2;
1258 }
1259 return (error);
1260}
1261
1262#if 0
1263
1264int
1265freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1266{
1267 int error;
1268 struct yyy32 *p32, s32;
1269 struct yyy *p = NULL, s;
1270
1271 if (uap->zzz) {
1272 error = copyin(uap->zzz, &s32, sizeof(s32));
1273 if (error)
1274 return (error);
1275 /* translate in */
1276 p = &s;
1277 }
1278 error = kern_xxx(td, p);
1279 if (error)
1280 return (error);
1281 if (uap->zzz) {
1282 /* translate out */
1283 error = copyout(&s32, p32, sizeof(s32));
1284 }
1285 return (error);
1286}
1287
1288#endif
950}
951
952int
953freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
954{
955 struct pread_args ap;
956
957 ap.fd = uap->fd;
958 ap.buf = uap->buf;
959 ap.nbyte = uap->nbyte;
960 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
961 return (pread(td, &ap));
962}
963
964int
965freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
966{
967 struct pwrite_args ap;
968
969 ap.fd = uap->fd;
970 ap.buf = uap->buf;
971 ap.nbyte = uap->nbyte;
972 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
973 return (pwrite(td, &ap));
974}
975
976int
977freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
978{
979 int error;
980 struct lseek_args ap;
981 off_t pos;
982
983 ap.fd = uap->fd;
984 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
985 ap.whence = uap->whence;
986 error = lseek(td, &ap);
987 /* Expand the quad return into two parts for eax and edx */
988 pos = *(off_t *)(td->td_retval);
989 td->td_retval[0] = pos & 0xffffffff; /* %eax */
990 td->td_retval[1] = pos >> 32; /* %edx */
991 return error;
992}
993
994int
995freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
996{
997 struct truncate_args ap;
998
999 ap.path = uap->path;
1000 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1001 return (truncate(td, &ap));
1002}
1003
1004int
1005freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1006{
1007 struct ftruncate_args ap;
1008
1009 ap.fd = uap->fd;
1010 ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1011 return (ftruncate(td, &ap));
1012}
1013
1014#ifdef COMPAT_FREEBSD4
1015int
1016freebsd4_freebsd32_sendfile(struct thread *td,
1017 struct freebsd4_freebsd32_sendfile_args *uap)
1018{
1019 struct freebsd4_sendfile_args ap;
1020
1021 ap.fd = uap->fd;
1022 ap.s = uap->s;
1023 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1024 ap.nbytes = uap->nbytes; /* XXX check */
1025 ap.hdtr = uap->hdtr; /* XXX check */
1026 ap.sbytes = uap->sbytes; /* XXX FIXME!! */
1027 ap.flags = uap->flags;
1028 return (freebsd4_sendfile(td, &ap));
1029}
1030#endif
1031
1032int
1033freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1034{
1035 struct sendfile_args ap;
1036
1037 ap.fd = uap->fd;
1038 ap.s = uap->s;
1039 ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1040 ap.nbytes = uap->nbytes; /* XXX check */
1041 ap.hdtr = uap->hdtr; /* XXX check */
1042 ap.sbytes = uap->sbytes; /* XXX FIXME!! */
1043 ap.flags = uap->flags;
1044 return (sendfile(td, &ap));
1045}
1046
1047struct stat32 {
1048 dev_t st_dev;
1049 ino_t st_ino;
1050 mode_t st_mode;
1051 nlink_t st_nlink;
1052 uid_t st_uid;
1053 gid_t st_gid;
1054 dev_t st_rdev;
1055 struct timespec32 st_atimespec;
1056 struct timespec32 st_mtimespec;
1057 struct timespec32 st_ctimespec;
1058 off_t st_size;
1059 int64_t st_blocks;
1060 u_int32_t st_blksize;
1061 u_int32_t st_flags;
1062 u_int32_t st_gen;
1063 struct timespec32 st_birthtimespec;
1064 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1065 unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1066};
1067
1068
1069CTASSERT(sizeof(struct stat32) == 96);
1070
1071static void
1072copy_stat( struct stat *in, struct stat32 *out)
1073{
1074 CP(*in, *out, st_dev);
1075 CP(*in, *out, st_ino);
1076 CP(*in, *out, st_mode);
1077 CP(*in, *out, st_nlink);
1078 CP(*in, *out, st_uid);
1079 CP(*in, *out, st_gid);
1080 CP(*in, *out, st_rdev);
1081 TS_CP(*in, *out, st_atimespec);
1082 TS_CP(*in, *out, st_mtimespec);
1083 TS_CP(*in, *out, st_ctimespec);
1084 CP(*in, *out, st_size);
1085 CP(*in, *out, st_blocks);
1086 CP(*in, *out, st_blksize);
1087 CP(*in, *out, st_flags);
1088 CP(*in, *out, st_gen);
1089}
1090
1091int
1092freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1093{
1094 struct stat sb;
1095 struct stat32 sb32;
1096 int error;
1097
1098 error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1099 if (error)
1100 return (error);
1101 copy_stat(&sb, &sb32);
1102 error = copyout(&sb32, uap->ub, sizeof (sb32));
1103 return (error);
1104}
1105
1106int
1107freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1108{
1109 struct stat ub;
1110 struct stat32 ub32;
1111 int error;
1112
1113 error = kern_fstat(td, uap->fd, &ub);
1114 if (error)
1115 return (error);
1116 copy_stat(&ub, &ub32);
1117 error = copyout(&ub32, uap->ub, sizeof(ub32));
1118 return (error);
1119}
1120
1121int
1122freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1123{
1124 struct stat sb;
1125 struct stat32 sb32;
1126 int error;
1127
1128 error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1129 if (error)
1130 return (error);
1131 copy_stat(&sb, &sb32);
1132 error = copyout(&sb32, uap->ub, sizeof (sb32));
1133 return (error);
1134}
1135
1136/*
1137 * MPSAFE
1138 */
1139int
1140freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1141{
1142 int error, name[CTL_MAXNAME];
1143 size_t j, oldlen;
1144
1145 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1146 return (EINVAL);
1147 error = copyin(uap->name, name, uap->namelen * sizeof(int));
1148 if (error)
1149 return (error);
1150 mtx_lock(&Giant);
1151 if (uap->oldlenp)
1152 oldlen = fuword32(uap->oldlenp);
1153 else
1154 oldlen = 0;
1155 error = userland_sysctl(td, name, uap->namelen,
1156 uap->old, &oldlen, 1,
1157 uap->new, uap->newlen, &j, SCTL_MASK32);
1158 if (error && error != ENOMEM)
1159 goto done2;
1160 if (uap->oldlenp)
1161 suword32(uap->oldlenp, j);
1162done2:
1163 mtx_unlock(&Giant);
1164 return (error);
1165}
1166
1167struct sigaction32 {
1168 u_int32_t sa_u;
1169 int sa_flags;
1170 sigset_t sa_mask;
1171};
1172
1173CTASSERT(sizeof(struct sigaction32) == 24);
1174
1175int
1176freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1177{
1178 struct sigaction32 s32;
1179 struct sigaction sa, osa, *sap;
1180 int error;
1181
1182 if (uap->act) {
1183 error = copyin(uap->act, &s32, sizeof(s32));
1184 if (error)
1185 return (error);
1186 sa.sa_handler = PTRIN(s32.sa_u);
1187 CP(s32, sa, sa_flags);
1188 CP(s32, sa, sa_mask);
1189 sap = &sa;
1190 } else
1191 sap = NULL;
1192 error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1193 if (error == 0 && uap->oact != NULL) {
1194 s32.sa_u = PTROUT(osa.sa_handler);
1195 CP(osa, s32, sa_flags);
1196 CP(osa, s32, sa_mask);
1197 error = copyout(&s32, uap->oact, sizeof(s32));
1198 }
1199 return (error);
1200}
1201
1202#ifdef COMPAT_FREEBSD4
1203int
1204freebsd4_freebsd32_sigaction(struct thread *td,
1205 struct freebsd4_freebsd32_sigaction_args *uap)
1206{
1207 struct sigaction32 s32;
1208 struct sigaction sa, osa, *sap;
1209 int error;
1210
1211 if (uap->act) {
1212 error = copyin(uap->act, &s32, sizeof(s32));
1213 if (error)
1214 return (error);
1215 sa.sa_handler = PTRIN(s32.sa_u);
1216 CP(s32, sa, sa_flags);
1217 CP(s32, sa, sa_mask);
1218 sap = &sa;
1219 } else
1220 sap = NULL;
1221 error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1222 if (error == 0 && uap->oact != NULL) {
1223 s32.sa_u = PTROUT(osa.sa_handler);
1224 CP(osa, s32, sa_flags);
1225 CP(osa, s32, sa_mask);
1226 error = copyout(&s32, uap->oact, sizeof(s32));
1227 }
1228 return (error);
1229}
1230#endif
1231
1232int
1233freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
1234{
1235 struct timespec32 rmt32, rqt32;
1236 struct timespec rmt, rqt;
1237 int error;
1238
1239 error = copyin(uap->rqtp, &rqt32, sizeof(rqt));
1240 if (error)
1241 return (error);
1242
1243 CP(rqt32, rqt, tv_sec);
1244 CP(rqt32, rqt, tv_nsec);
1245
1246 if (uap->rmtp &&
1247 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
1248 return (EFAULT);
1249 error = kern_nanosleep(td, &rqt, &rmt);
1250 if (error && uap->rmtp) {
1251 int error2;
1252
1253 CP(rmt, rmt32, tv_sec);
1254 CP(rmt, rmt32, tv_nsec);
1255
1256 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt));
1257 if (error2)
1258 error = error2;
1259 }
1260 return (error);
1261}
1262
1263#if 0
1264
1265int
1266freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
1267{
1268 int error;
1269 struct yyy32 *p32, s32;
1270 struct yyy *p = NULL, s;
1271
1272 if (uap->zzz) {
1273 error = copyin(uap->zzz, &s32, sizeof(s32));
1274 if (error)
1275 return (error);
1276 /* translate in */
1277 p = &s;
1278 }
1279 error = kern_xxx(td, p);
1280 if (error)
1281 return (error);
1282 if (uap->zzz) {
1283 /* translate out */
1284 error = copyout(&s32, p32, sizeof(s32));
1285 }
1286 return (error);
1287}
1288
1289#endif