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