]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/compat/freebsd32/freebsd32_misc.c
This commit was generated by cvs2svn to compensate for changes in r167612,
[FreeBSD/FreeBSD.git] / sys / compat / freebsd32 / freebsd32_misc.c
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$");
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/clock.h>
36 #include <sys/exec.h>
37 #include <sys/fcntl.h>
38 #include <sys/filedesc.h>
39 #include <sys/namei.h>
40 #include <sys/imgact.h>
41 #include <sys/kernel.h>
42 #include <sys/limits.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/file.h>           /* Must come after sys/malloc.h */
46 #include <sys/mbuf.h>
47 #include <sys/mman.h>
48 #include <sys/module.h>
49 #include <sys/mount.h>
50 #include <sys/mutex.h>
51 #include <sys/namei.h>
52 #include <sys/param.h>
53 #include <sys/proc.h>
54 #include <sys/reboot.h>
55 #include <sys/resource.h>
56 #include <sys/resourcevar.h>
57 #include <sys/selinfo.h>
58 #include <sys/eventvar.h>       /* Must come after sys/selinfo.h */
59 #include <sys/pipe.h>           /* Must come after sys/selinfo.h */
60 #include <sys/signal.h>
61 #include <sys/signalvar.h>
62 #include <sys/socket.h>
63 #include <sys/socketvar.h>
64 #include <sys/stat.h>
65 #include <sys/syscall.h>
66 #include <sys/syscallsubr.h>
67 #include <sys/sysctl.h>
68 #include <sys/sysent.h>
69 #include <sys/sysproto.h>
70 #include <sys/systm.h>
71 #include <sys/thr.h>
72 #include <sys/unistd.h>
73 #include <sys/ucontext.h>
74 #include <sys/vnode.h>
75 #include <sys/wait.h>
76 #include <sys/ipc.h>
77 #include <sys/shm.h>
78
79 #include <vm/vm.h>
80 #include <vm/vm_kern.h>
81 #include <vm/vm_param.h>
82 #include <vm/pmap.h>
83 #include <vm/vm_map.h>
84 #include <vm/vm_object.h>
85 #include <vm/vm_extern.h>
86
87 #include <machine/cpu.h>
88
89 #include <compat/freebsd32/freebsd32_util.h>
90 #include <compat/freebsd32/freebsd32.h>
91 #include <compat/freebsd32/freebsd32_signal.h>
92 #include <compat/freebsd32/freebsd32_proto.h>
93
94 CTASSERT(sizeof(struct timeval32) == 8);
95 CTASSERT(sizeof(struct timespec32) == 8);
96 CTASSERT(sizeof(struct statfs32) == 256);
97 CTASSERT(sizeof(struct rusage32) == 72);
98
99 int
100 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
101 {
102         int error, status;
103         struct rusage32 ru32;
104         struct rusage ru, *rup;
105
106         if (uap->rusage != NULL)
107                 rup = &ru;
108         else
109                 rup = NULL;
110         error = kern_wait(td, uap->pid, &status, uap->options, rup);
111         if (error)
112                 return (error);
113         if (uap->status != NULL)
114                 error = copyout(&status, uap->status, sizeof(status));
115         if (uap->rusage != NULL && error == 0) {
116                 TV_CP(ru, ru32, ru_utime);
117                 TV_CP(ru, ru32, ru_stime);
118                 CP(ru, ru32, ru_maxrss);
119                 CP(ru, ru32, ru_ixrss);
120                 CP(ru, ru32, ru_idrss);
121                 CP(ru, ru32, ru_isrss);
122                 CP(ru, ru32, ru_minflt);
123                 CP(ru, ru32, ru_majflt);
124                 CP(ru, ru32, ru_nswap);
125                 CP(ru, ru32, ru_inblock);
126                 CP(ru, ru32, ru_oublock);
127                 CP(ru, ru32, ru_msgsnd);
128                 CP(ru, ru32, ru_msgrcv);
129                 CP(ru, ru32, ru_nsignals);
130                 CP(ru, ru32, ru_nvcsw);
131                 CP(ru, ru32, ru_nivcsw);
132                 error = copyout(&ru32, uap->rusage, sizeof(ru32));
133         }
134         return (error);
135 }
136
137 #ifdef COMPAT_FREEBSD4
138 static void
139 copy_statfs(struct statfs *in, struct statfs32 *out)
140 {
141         
142         bzero(out, sizeof(*out));
143         CP(*in, *out, f_bsize);
144         CP(*in, *out, f_iosize);
145         CP(*in, *out, f_blocks);
146         CP(*in, *out, f_bfree);
147         CP(*in, *out, f_bavail);
148         CP(*in, *out, f_files);
149         CP(*in, *out, f_ffree);
150         CP(*in, *out, f_fsid);
151         CP(*in, *out, f_owner);
152         CP(*in, *out, f_type);
153         CP(*in, *out, f_flags);
154         CP(*in, *out, f_flags);
155         CP(*in, *out, f_syncwrites);
156         CP(*in, *out, f_asyncwrites);
157         strlcpy(out->f_fstypename,
158               in->f_fstypename, MFSNAMELEN);
159         strlcpy(out->f_mntonname,
160               in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
161         CP(*in, *out, f_syncreads);
162         CP(*in, *out, f_asyncreads);
163         strlcpy(out->f_mntfromname,
164               in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
165 }
166 #endif
167
168 #ifdef COMPAT_FREEBSD4
169 int
170 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
171 {
172         struct statfs *buf, *sp;
173         struct statfs32 stat32;
174         size_t count, size;
175         int error;
176
177         count = uap->bufsize / sizeof(struct statfs32);
178         size = count * sizeof(struct statfs);
179         error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
180         if (size > 0) {
181                 count = td->td_retval[0];
182                 sp = buf;
183                 while (count > 0 && error == 0) {
184                         copy_statfs(sp, &stat32);
185                         error = copyout(&stat32, uap->buf, sizeof(stat32));
186                         sp++;
187                         uap->buf++;
188                         count--;
189                 }
190                 free(buf, M_TEMP);
191         }
192         return (error);
193 }
194 #endif
195
196 CTASSERT(sizeof(struct sigaltstack32) == 12);
197
198 int
199 freebsd32_sigaltstack(struct thread *td,
200                       struct freebsd32_sigaltstack_args *uap)
201 {
202         struct sigaltstack32 s32;
203         struct sigaltstack ss, oss, *ssp;
204         int error;
205
206         if (uap->ss != NULL) {
207                 error = copyin(uap->ss, &s32, sizeof(s32));
208                 if (error)
209                         return (error);
210                 PTRIN_CP(s32, ss, ss_sp);
211                 CP(s32, ss, ss_size);
212                 CP(s32, ss, ss_flags);
213                 ssp = &ss;
214         } else
215                 ssp = NULL;
216         error = kern_sigaltstack(td, ssp, &oss);
217         if (error == 0 && uap->oss != NULL) {
218                 PTROUT_CP(oss, s32, ss_sp);
219                 CP(oss, s32, ss_size);
220                 CP(oss, s32, ss_flags);
221                 error = copyout(&s32, uap->oss, sizeof(s32));
222         }
223         return (error);
224 }
225
226 /*
227  * Custom version of exec_copyin_args() so that we can translate
228  * the pointers.
229  */
230 static int
231 freebsd32_exec_copyin_args(struct image_args *args, char *fname,
232     enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
233 {
234         char *argp, *envp;
235         u_int32_t *p32, arg;
236         size_t length;
237         int error;
238
239         bzero(args, sizeof(*args));
240         if (argv == NULL)
241                 return (EFAULT);
242
243         /*
244          * Allocate temporary demand zeroed space for argument and
245          *      environment strings
246          */
247         args->buf = (char *) kmem_alloc_wait(exec_map,
248             PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
249         if (args->buf == NULL)
250                 return (ENOMEM);
251         args->begin_argv = args->buf;
252         args->endp = args->begin_argv;
253         args->stringspace = ARG_MAX;
254
255         args->fname = args->buf + ARG_MAX;
256
257         /*
258          * Copy the file name.
259          */
260         error = (segflg == UIO_SYSSPACE) ?
261             copystr(fname, args->fname, PATH_MAX, &length) :
262             copyinstr(fname, args->fname, PATH_MAX, &length);
263         if (error != 0)
264                 goto err_exit;
265
266         /*
267          * extract arguments first
268          */
269         p32 = argv;
270         for (;;) {
271                 error = copyin(p32++, &arg, sizeof(arg));
272                 if (error)
273                         goto err_exit;
274                 if (arg == 0)
275                         break;
276                 argp = PTRIN(arg);
277                 error = copyinstr(argp, args->endp, args->stringspace, &length);
278                 if (error) {
279                         if (error == ENAMETOOLONG)
280                                 error = E2BIG;
281                         goto err_exit;
282                 }
283                 args->stringspace -= length;
284                 args->endp += length;
285                 args->argc++;
286         }
287                         
288         args->begin_envv = args->endp;
289
290         /*
291          * extract environment strings
292          */
293         if (envv) {
294                 p32 = envv;
295                 for (;;) {
296                         error = copyin(p32++, &arg, sizeof(arg));
297                         if (error)
298                                 goto err_exit;
299                         if (arg == 0)
300                                 break;
301                         envp = PTRIN(arg);
302                         error = copyinstr(envp, args->endp, args->stringspace,
303                             &length);
304                         if (error) {
305                                 if (error == ENAMETOOLONG)
306                                         error = E2BIG;
307                                 goto err_exit;
308                         }
309                         args->stringspace -= length;
310                         args->endp += length;
311                         args->envc++;
312                 }
313         }
314
315         return (0);
316
317 err_exit:
318         kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
319             PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
320         args->buf = NULL;
321         return (error);
322 }
323
324 int
325 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
326 {
327         struct image_args eargs;
328         int error;
329
330         error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
331             uap->argv, uap->envv);
332         if (error == 0)
333                 error = kern_execve(td, &eargs, NULL);
334         return (error);
335 }
336
337 #ifdef __ia64__
338 static int
339 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
340                        int prot, int fd, off_t pos)
341 {
342         vm_map_t map;
343         vm_map_entry_t entry;
344         int rv;
345
346         map = &td->td_proc->p_vmspace->vm_map;
347         if (fd != -1)
348                 prot |= VM_PROT_WRITE;
349
350         if (vm_map_lookup_entry(map, start, &entry)) {
351                 if ((entry->protection & prot) != prot) {
352                         rv = vm_map_protect(map,
353                                             trunc_page(start),
354                                             round_page(end),
355                                             entry->protection | prot,
356                                             FALSE);
357                         if (rv != KERN_SUCCESS)
358                                 return (EINVAL);
359                 }
360         } else {
361                 vm_offset_t addr = trunc_page(start);
362                 rv = vm_map_find(map, 0, 0,
363                                  &addr, PAGE_SIZE, FALSE, prot,
364                                  VM_PROT_ALL, 0);
365                 if (rv != KERN_SUCCESS)
366                         return (EINVAL);
367         }
368
369         if (fd != -1) {
370                 struct pread_args r;
371                 r.fd = fd;
372                 r.buf = (void *) start;
373                 r.nbyte = end - start;
374                 r.offset = pos;
375                 return (pread(td, &r));
376         } else {
377                 while (start < end) {
378                         subyte((void *) start, 0);
379                         start++;
380                 }
381                 return (0);
382         }
383 }
384 #endif
385
386 int
387 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
388 {
389         struct mmap_args ap;
390         vm_offset_t addr = (vm_offset_t) uap->addr;
391         vm_size_t len    = uap->len;
392         int prot         = uap->prot;
393         int flags        = uap->flags;
394         int fd           = uap->fd;
395         off_t pos        = (uap->poslo
396                             | ((off_t)uap->poshi << 32));
397 #ifdef __ia64__
398         vm_size_t pageoff;
399         int error;
400
401         /*
402          * Attempt to handle page size hassles.
403          */
404         pageoff = (pos & PAGE_MASK);
405         if (flags & MAP_FIXED) {
406                 vm_offset_t start, end;
407                 start = addr;
408                 end = addr + len;
409
410                 mtx_lock(&Giant);
411                 if (start != trunc_page(start)) {
412                         error = freebsd32_mmap_partial(td, start,
413                                                        round_page(start), prot,
414                                                        fd, pos);
415                         if (fd != -1)
416                                 pos += round_page(start) - start;
417                         start = round_page(start);
418                 }
419                 if (end != round_page(end)) {
420                         vm_offset_t t = trunc_page(end);
421                         error = freebsd32_mmap_partial(td, t, end,
422                                                   prot, fd,
423                                                   pos + t - start);
424                         end = trunc_page(end);
425                 }
426                 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
427                         /*
428                          * We can't map this region at all. The specified
429                          * address doesn't have the same alignment as the file
430                          * position. Fake the mapping by simply reading the
431                          * entire region into memory. First we need to make
432                          * sure the region exists.
433                          */
434                         vm_map_t map;
435                         struct pread_args r;
436                         int rv;
437
438                         prot |= VM_PROT_WRITE;
439                         map = &td->td_proc->p_vmspace->vm_map;
440                         rv = vm_map_remove(map, start, end);
441                         if (rv != KERN_SUCCESS) {
442                                 mtx_unlock(&Giant);
443                                 return (EINVAL);
444                         }
445                         rv = vm_map_find(map, 0, 0,
446                                          &start, end - start, FALSE,
447                                          prot, VM_PROT_ALL, 0);
448                         mtx_unlock(&Giant);
449                         if (rv != KERN_SUCCESS)
450                                 return (EINVAL);
451                         r.fd = fd;
452                         r.buf = (void *) start;
453                         r.nbyte = end - start;
454                         r.offset = pos;
455                         error = pread(td, &r);
456                         if (error)
457                                 return (error);
458
459                         td->td_retval[0] = addr;
460                         return (0);
461                 }
462                 mtx_unlock(&Giant);
463                 if (end == start) {
464                         /*
465                          * After dealing with the ragged ends, there
466                          * might be none left.
467                          */
468                         td->td_retval[0] = addr;
469                         return (0);
470                 }
471                 addr = start;
472                 len = end - start;
473         }
474 #endif
475
476         ap.addr = (void *) addr;
477         ap.len = len;
478         ap.prot = prot;
479         ap.flags = flags;
480         ap.fd = fd;
481         ap.pos = pos;
482
483         return (mmap(td, &ap));
484 }
485
486 struct itimerval32 {
487         struct timeval32 it_interval;
488         struct timeval32 it_value;
489 };
490
491 CTASSERT(sizeof(struct itimerval32) == 16);
492
493 int
494 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
495 {
496         struct itimerval itv, oitv, *itvp;      
497         struct itimerval32 i32;
498         int error;
499
500         if (uap->itv != NULL) {
501                 error = copyin(uap->itv, &i32, sizeof(i32));
502                 if (error)
503                         return (error);
504                 TV_CP(i32, itv, it_interval);
505                 TV_CP(i32, itv, it_value);
506                 itvp = &itv;
507         } else
508                 itvp = NULL;
509         error = kern_setitimer(td, uap->which, itvp, &oitv);
510         if (error || uap->oitv == NULL)
511                 return (error);
512         TV_CP(oitv, i32, it_interval);
513         TV_CP(oitv, i32, it_value);
514         return (copyout(&i32, uap->oitv, sizeof(i32)));
515 }
516
517 int
518 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
519 {
520         struct itimerval itv;
521         struct itimerval32 i32;
522         int error;
523
524         error = kern_getitimer(td, uap->which, &itv);
525         if (error || uap->itv == NULL)
526                 return (error);
527         TV_CP(itv, i32, it_interval);
528         TV_CP(itv, i32, it_value);
529         return (copyout(&i32, uap->itv, sizeof(i32)));
530 }
531
532 int
533 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
534 {
535         struct timeval32 tv32;
536         struct timeval tv, *tvp;
537         int error;
538
539         if (uap->tv != NULL) {
540                 error = copyin(uap->tv, &tv32, sizeof(tv32));
541                 if (error)
542                         return (error);
543                 CP(tv32, tv, tv_sec);
544                 CP(tv32, tv, tv_usec);
545                 tvp = &tv;
546         } else
547                 tvp = NULL;
548         /*
549          * XXX big-endian needs to convert the fd_sets too.
550          * XXX Do pointers need PTRIN()?
551          */
552         return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
553 }
554
555 struct kevent32 {
556         u_int32_t       ident;          /* identifier for this event */
557         short           filter;         /* filter for event */
558         u_short         flags;
559         u_int           fflags;
560         int32_t         data;
561         u_int32_t       udata;          /* opaque user data identifier */
562 };
563
564 CTASSERT(sizeof(struct kevent32) == 20);
565 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
566 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
567
568 /*
569  * Copy 'count' items into the destination list pointed to by uap->eventlist.
570  */
571 static int
572 freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
573 {
574         struct freebsd32_kevent_args *uap;
575         struct kevent32 ks32[KQ_NEVENTS];
576         int i, error = 0;
577
578         KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
579         uap = (struct freebsd32_kevent_args *)arg;
580
581         for (i = 0; i < count; i++) {
582                 CP(kevp[i], ks32[i], ident);
583                 CP(kevp[i], ks32[i], filter);
584                 CP(kevp[i], ks32[i], flags);
585                 CP(kevp[i], ks32[i], fflags);
586                 CP(kevp[i], ks32[i], data);
587                 PTROUT_CP(kevp[i], ks32[i], udata);
588         }
589         error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
590         if (error == 0)
591                 uap->eventlist += count;
592         return (error);
593 }
594
595 /*
596  * Copy 'count' items from the list pointed to by uap->changelist.
597  */
598 static int
599 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
600 {
601         struct freebsd32_kevent_args *uap;
602         struct kevent32 ks32[KQ_NEVENTS];
603         int i, error = 0;
604
605         KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
606         uap = (struct freebsd32_kevent_args *)arg;
607
608         error = copyin(uap->changelist, ks32, count * sizeof *ks32);
609         if (error)
610                 goto done;
611         uap->changelist += count;
612
613         for (i = 0; i < count; i++) {
614                 CP(ks32[i], kevp[i], ident);
615                 CP(ks32[i], kevp[i], filter);
616                 CP(ks32[i], kevp[i], flags);
617                 CP(ks32[i], kevp[i], fflags);
618                 CP(ks32[i], kevp[i], data);
619                 PTRIN_CP(ks32[i], kevp[i], udata);
620         }
621 done:
622         return (error);
623 }
624
625 int
626 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
627 {
628         struct timespec32 ts32;
629         struct timespec ts, *tsp;
630         struct kevent_copyops k_ops = { uap,
631                                         freebsd32_kevent_copyout,
632                                         freebsd32_kevent_copyin};
633         int error;
634
635
636         if (uap->timeout) {
637                 error = copyin(uap->timeout, &ts32, sizeof(ts32));
638                 if (error)
639                         return (error);
640                 CP(ts32, ts, tv_sec);
641                 CP(ts32, ts, tv_nsec);
642                 tsp = &ts;
643         } else
644                 tsp = NULL;
645         error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
646             &k_ops, tsp);
647         return (error);
648 }
649
650 int
651 freebsd32_gettimeofday(struct thread *td,
652                        struct freebsd32_gettimeofday_args *uap)
653 {
654         struct timeval atv;
655         struct timeval32 atv32;
656         struct timezone rtz;
657         int error = 0;
658
659         if (uap->tp) {
660                 microtime(&atv);
661                 CP(atv, atv32, tv_sec);
662                 CP(atv, atv32, tv_usec);
663                 error = copyout(&atv32, uap->tp, sizeof (atv32));
664         }
665         if (error == 0 && uap->tzp != NULL) {
666                 rtz.tz_minuteswest = tz_minuteswest;
667                 rtz.tz_dsttime = tz_dsttime;
668                 error = copyout(&rtz, uap->tzp, sizeof (rtz));
669         }
670         return (error);
671 }
672
673 int
674 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
675 {
676         struct rusage32 s32;
677         struct rusage s;
678         int error;
679
680         error = kern_getrusage(td, uap->who, &s);
681         if (error)
682                 return (error);
683         if (uap->rusage != NULL) {
684                 TV_CP(s, s32, ru_utime);
685                 TV_CP(s, s32, ru_stime);
686                 CP(s, s32, ru_maxrss);
687                 CP(s, s32, ru_ixrss);
688                 CP(s, s32, ru_idrss);
689                 CP(s, s32, ru_isrss);
690                 CP(s, s32, ru_minflt);
691                 CP(s, s32, ru_majflt);
692                 CP(s, s32, ru_nswap);
693                 CP(s, s32, ru_inblock);
694                 CP(s, s32, ru_oublock);
695                 CP(s, s32, ru_msgsnd);
696                 CP(s, s32, ru_msgrcv);
697                 CP(s, s32, ru_nsignals);
698                 CP(s, s32, ru_nvcsw);
699                 CP(s, s32, ru_nivcsw);
700                 error = copyout(&s32, uap->rusage, sizeof(s32));
701         }
702         return (error);
703 }
704
705 struct iovec32 {
706         u_int32_t iov_base;
707         int     iov_len;
708 };
709
710 CTASSERT(sizeof(struct iovec32) == 8);
711
712 static int
713 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
714 {
715         struct iovec32 iov32;
716         struct iovec *iov;
717         struct uio *uio;
718         u_int iovlen;
719         int error, i;
720
721         *uiop = NULL;
722         if (iovcnt > UIO_MAXIOV)
723                 return (EINVAL);
724         iovlen = iovcnt * sizeof(struct iovec);
725         uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
726         iov = (struct iovec *)(uio + 1);
727         for (i = 0; i < iovcnt; i++) {
728                 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
729                 if (error) {
730                         free(uio, M_IOV);
731                         return (error);
732                 }
733                 iov[i].iov_base = PTRIN(iov32.iov_base);
734                 iov[i].iov_len = iov32.iov_len;
735         }
736         uio->uio_iov = iov;
737         uio->uio_iovcnt = iovcnt;
738         uio->uio_segflg = UIO_USERSPACE;
739         uio->uio_offset = -1;
740         uio->uio_resid = 0;
741         for (i = 0; i < iovcnt; i++) {
742                 if (iov->iov_len > INT_MAX - uio->uio_resid) {
743                         free(uio, M_IOV);
744                         return (EINVAL);
745                 }
746                 uio->uio_resid += iov->iov_len;
747                 iov++;
748         }
749         *uiop = uio;
750         return (0);
751 }
752
753 int
754 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
755 {
756         struct uio *auio;
757         int error;
758
759         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
760         if (error)
761                 return (error);
762         error = kern_readv(td, uap->fd, auio);
763         free(auio, M_IOV);
764         return (error);
765 }
766
767 int
768 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
769 {
770         struct uio *auio;
771         int error;
772
773         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
774         if (error)
775                 return (error);
776         error = kern_writev(td, uap->fd, auio);
777         free(auio, M_IOV);
778         return (error);
779 }
780
781 int
782 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
783 {
784         struct uio *auio;
785         int error;
786
787         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
788         if (error)
789                 return (error);
790         error = kern_preadv(td, uap->fd, auio, uap->offset);
791         free(auio, M_IOV);
792         return (error);
793 }
794
795 int
796 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
797 {
798         struct uio *auio;
799         int error;
800
801         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
802         if (error)
803                 return (error);
804         error = kern_pwritev(td, uap->fd, auio, uap->offset);
805         free(auio, M_IOV);
806         return (error);
807 }
808
809 static int
810 freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
811     int error)
812 {
813         struct iovec32 iov32;
814         struct iovec *iov;
815         u_int iovlen;
816         int i;
817
818         *iovp = NULL;
819         if (iovcnt > UIO_MAXIOV)
820                 return (error);
821         iovlen = iovcnt * sizeof(struct iovec);
822         iov = malloc(iovlen, M_IOV, M_WAITOK);
823         for (i = 0; i < iovcnt; i++) {
824                 error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
825                 if (error) {
826                         free(iov, M_IOV);
827                         return (error);
828                 }
829                 iov[i].iov_base = PTRIN(iov32.iov_base);
830                 iov[i].iov_len = iov32.iov_len;
831         }
832         *iovp = iov;
833         return (0);
834 }
835
836 struct msghdr32 {
837         u_int32_t        msg_name;
838         socklen_t        msg_namelen;
839         u_int32_t        msg_iov;
840         int              msg_iovlen;
841         u_int32_t        msg_control;
842         socklen_t        msg_controllen;
843         int              msg_flags;
844 };
845 CTASSERT(sizeof(struct msghdr32) == 28);
846
847 static int
848 freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
849 {
850         struct msghdr32 m32;
851         int error;
852
853         error = copyin(msg32, &m32, sizeof(m32));
854         if (error)
855                 return (error);
856         msg->msg_name = PTRIN(m32.msg_name);
857         msg->msg_namelen = m32.msg_namelen;
858         msg->msg_iov = PTRIN(m32.msg_iov);
859         msg->msg_iovlen = m32.msg_iovlen;
860         msg->msg_control = PTRIN(m32.msg_control);
861         msg->msg_controllen = m32.msg_controllen;
862         msg->msg_flags = m32.msg_flags;
863         return (0);
864 }
865
866 static int
867 freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
868 {
869         struct msghdr32 m32;
870         int error;
871
872         m32.msg_name = PTROUT(msg->msg_name);
873         m32.msg_namelen = msg->msg_namelen;
874         m32.msg_iov = PTROUT(msg->msg_iov);
875         m32.msg_iovlen = msg->msg_iovlen;
876         m32.msg_control = PTROUT(msg->msg_control);
877         m32.msg_controllen = msg->msg_controllen;
878         m32.msg_flags = msg->msg_flags;
879         error = copyout(&m32, msg32, sizeof(m32));
880         return (error);
881 }
882
883 #define FREEBSD32_ALIGNBYTES    (sizeof(int) - 1)
884 #define FREEBSD32_ALIGN(p)      \
885         (((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
886 #define FREEBSD32_CMSG_SPACE(l) \
887         (FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
888
889 #define FREEBSD32_CMSG_DATA(cmsg)       ((unsigned char *)(cmsg) + \
890                                  FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
891 static int
892 freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
893 {
894         struct cmsghdr *cm;
895         void *data;
896         socklen_t clen, datalen;
897         int error;
898         caddr_t ctlbuf;
899         int len, maxlen, copylen;
900         struct mbuf *m;
901         error = 0;
902
903         len    = msg->msg_controllen;
904         maxlen = msg->msg_controllen;
905         msg->msg_controllen = 0;
906
907         m = control;
908         ctlbuf = msg->msg_control;
909       
910         while (m && len > 0) {
911                 cm = mtod(m, struct cmsghdr *);
912                 clen = m->m_len;
913
914                 while (cm != NULL) {
915
916                         if (sizeof(struct cmsghdr) > clen ||
917                             cm->cmsg_len > clen) {
918                                 error = EINVAL;
919                                 break;
920                         }       
921
922                         data   = CMSG_DATA(cm);
923                         datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
924
925                         /* Adjust message length */
926                         cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
927                             datalen;
928
929
930                         /* Copy cmsghdr */
931                         copylen = sizeof(struct cmsghdr);
932                         if (len < copylen) {
933                                 msg->msg_flags |= MSG_CTRUNC;
934                                 copylen = len;
935                         }
936
937                         error = copyout(cm,ctlbuf,copylen);
938                         if (error)
939                                 goto exit;
940
941                         ctlbuf += FREEBSD32_ALIGN(copylen);
942                         len    -= FREEBSD32_ALIGN(copylen);
943
944                         if (len <= 0)
945                                 break;
946
947                         /* Copy data */
948                         copylen = datalen;
949                         if (len < copylen) {
950                                 msg->msg_flags |= MSG_CTRUNC;
951                                 copylen = len;
952                         }
953
954                         error = copyout(data,ctlbuf,copylen);
955                         if (error)
956                                 goto exit;
957
958                         ctlbuf += FREEBSD32_ALIGN(copylen);
959                         len    -= FREEBSD32_ALIGN(copylen);
960
961                         if (CMSG_SPACE(datalen) < clen) {
962                                 clen -= CMSG_SPACE(datalen);
963                                 cm = (struct cmsghdr *)
964                                         ((caddr_t)cm + CMSG_SPACE(datalen));
965                         } else {
966                                 clen = 0;
967                                 cm = NULL;
968                         }
969                 }       
970                 m = m->m_next;
971         }
972
973         msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
974         
975 exit:
976         return (error);
977
978 }
979
980 int
981 freebsd32_recvmsg(td, uap)
982         struct thread *td;
983         struct freebsd32_recvmsg_args /* {
984                 int     s;
985                 struct  msghdr32 *msg;
986                 int     flags;
987         } */ *uap;
988 {
989         struct msghdr msg;
990         struct msghdr32 m32;
991         struct iovec *uiov, *iov;
992         struct mbuf *control = NULL;
993         struct mbuf **controlp;
994
995         int error;
996         error = copyin(uap->msg, &m32, sizeof(m32));
997         if (error)
998                 return (error);
999         error = freebsd32_copyinmsghdr(uap->msg, &msg);
1000         if (error)
1001                 return (error);
1002         error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1003             EMSGSIZE);
1004         if (error)
1005                 return (error);
1006         msg.msg_flags = uap->flags;
1007         uiov = msg.msg_iov;
1008         msg.msg_iov = iov;
1009
1010         controlp = (msg.msg_control != NULL) ?  &control : NULL;
1011         error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
1012         if (error == 0) {
1013                 msg.msg_iov = uiov;
1014                 
1015                 if (control != NULL)
1016                         error = freebsd32_copy_msg_out(&msg, control);
1017                 
1018                 if (error == 0)
1019                         error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1020         }
1021         free(iov, M_IOV);
1022
1023         if (control != NULL)
1024                 m_freem(control);
1025
1026         return (error);
1027 }
1028
1029
1030 static int
1031 freebsd32_convert_msg_in(struct mbuf **controlp)
1032 {
1033         struct mbuf *control = *controlp;
1034         struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1035         void *data;
1036         socklen_t clen = control->m_len, datalen;
1037         int error;
1038
1039         error = 0;
1040         *controlp = NULL;
1041
1042         while (cm != NULL) {
1043                 if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1044                         error = EINVAL;
1045                         break;
1046                 }
1047
1048                 data = FREEBSD32_CMSG_DATA(cm);
1049                 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1050
1051                 *controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1052                     cm->cmsg_level);
1053                 controlp = &(*controlp)->m_next;
1054
1055                 if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1056                         clen -= FREEBSD32_CMSG_SPACE(datalen);
1057                         cm = (struct cmsghdr *)
1058                                 ((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1059                 } else {
1060                         clen = 0;
1061                         cm = NULL;
1062                 }
1063         }
1064
1065         m_freem(control);
1066         return (error);
1067 }
1068
1069
1070 int
1071 freebsd32_sendmsg(struct thread *td,
1072                   struct freebsd32_sendmsg_args *uap)
1073 {
1074         struct msghdr msg;
1075         struct msghdr32 m32;
1076         struct iovec *iov;
1077         struct mbuf *control = NULL;
1078         struct sockaddr *to = NULL;
1079         int error;
1080
1081         error = copyin(uap->msg, &m32, sizeof(m32));
1082         if (error)
1083                 return (error);
1084         error = freebsd32_copyinmsghdr(uap->msg, &msg);
1085         if (error)
1086                 return (error);
1087         error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1088             EMSGSIZE);
1089         if (error)
1090                 return (error);
1091         msg.msg_iov = iov;
1092         if (msg.msg_name != NULL) {
1093                 error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1094                 if (error) {
1095                         to = NULL;
1096                         goto out;
1097                 }
1098                 msg.msg_name = to;
1099         }
1100
1101         if (msg.msg_control) {
1102                 if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1103                         error = EINVAL;
1104                         goto out;
1105                 }
1106
1107                 error = sockargs(&control, msg.msg_control,
1108                     msg.msg_controllen, MT_CONTROL);
1109                 if (error)
1110                         goto out;
1111                 
1112                 error = freebsd32_convert_msg_in(&control);
1113                 if (error)
1114                         goto out;
1115         }
1116
1117         error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1118             UIO_USERSPACE);
1119
1120 out:
1121         free(iov, M_IOV);
1122         if (to)
1123                 free(to, M_SONAME);
1124         return (error);
1125 }
1126
1127 int
1128 freebsd32_recvfrom(struct thread *td,
1129                    struct freebsd32_recvfrom_args *uap)
1130 {
1131         struct msghdr msg;
1132         struct iovec aiov;
1133         int error;
1134
1135         if (uap->fromlenaddr) {
1136                 error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
1137                     sizeof(msg.msg_namelen));
1138                 if (error)
1139                         return (error);
1140         } else {
1141                 msg.msg_namelen = 0;
1142         }
1143
1144         msg.msg_name = PTRIN(uap->from);
1145         msg.msg_iov = &aiov;
1146         msg.msg_iovlen = 1;
1147         aiov.iov_base = PTRIN(uap->buf);
1148         aiov.iov_len = uap->len;
1149         msg.msg_control = NULL;
1150         msg.msg_flags = uap->flags;
1151         error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
1152         if (error == 0 && uap->fromlenaddr)
1153                 error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
1154                     sizeof (msg.msg_namelen));
1155         return (error);
1156 }
1157
1158 int
1159 freebsd32_settimeofday(struct thread *td,
1160                        struct freebsd32_settimeofday_args *uap)
1161 {
1162         struct timeval32 tv32;
1163         struct timeval tv, *tvp;
1164         struct timezone tz, *tzp;
1165         int error;
1166
1167         if (uap->tv) {
1168                 error = copyin(uap->tv, &tv32, sizeof(tv32));
1169                 if (error)
1170                         return (error);
1171                 CP(tv32, tv, tv_sec);
1172                 CP(tv32, tv, tv_usec);
1173                 tvp = &tv;
1174         } else
1175                 tvp = NULL;
1176         if (uap->tzp) {
1177                 error = copyin(uap->tzp, &tz, sizeof(tz));
1178                 if (error)
1179                         return (error);
1180                 tzp = &tz;
1181         } else
1182                 tzp = NULL;
1183         return (kern_settimeofday(td, tvp, tzp));
1184 }
1185
1186 int
1187 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1188 {
1189         struct timeval32 s32[2];
1190         struct timeval s[2], *sp;
1191         int error;
1192
1193         if (uap->tptr != NULL) {
1194                 error = copyin(uap->tptr, s32, sizeof(s32));
1195                 if (error)
1196                         return (error);
1197                 CP(s32[0], s[0], tv_sec);
1198                 CP(s32[0], s[0], tv_usec);
1199                 CP(s32[1], s[1], tv_sec);
1200                 CP(s32[1], s[1], tv_usec);
1201                 sp = s;
1202         } else
1203                 sp = NULL;
1204         return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1205 }
1206
1207 int
1208 freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1209 {
1210         struct timeval32 s32[2];
1211         struct timeval s[2], *sp;
1212         int error;
1213
1214         if (uap->tptr != NULL) {
1215                 error = copyin(uap->tptr, s32, sizeof(s32));
1216                 if (error)
1217                         return (error);
1218                 CP(s32[0], s[0], tv_sec);
1219                 CP(s32[0], s[0], tv_usec);
1220                 CP(s32[1], s[1], tv_sec);
1221                 CP(s32[1], s[1], tv_usec);
1222                 sp = s;
1223         } else
1224                 sp = NULL;
1225         return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1226 }
1227
1228 int
1229 freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1230 {
1231         struct timeval32 s32[2];
1232         struct timeval s[2], *sp;
1233         int error;
1234
1235         if (uap->tptr != NULL) {
1236                 error = copyin(uap->tptr, s32, sizeof(s32));
1237                 if (error)
1238                         return (error);
1239                 CP(s32[0], s[0], tv_sec);
1240                 CP(s32[0], s[0], tv_usec);
1241                 CP(s32[1], s[1], tv_sec);
1242                 CP(s32[1], s[1], tv_usec);
1243                 sp = s;
1244         } else
1245                 sp = NULL;
1246         return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1247 }
1248
1249
1250 int
1251 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1252 {
1253         struct timeval32 tv32;
1254         struct timeval delta, olddelta, *deltap;
1255         int error;
1256
1257         if (uap->delta) {
1258                 error = copyin(uap->delta, &tv32, sizeof(tv32));
1259                 if (error)
1260                         return (error);
1261                 CP(tv32, delta, tv_sec);
1262                 CP(tv32, delta, tv_usec);
1263                 deltap = &delta;
1264         } else
1265                 deltap = NULL;
1266         error = kern_adjtime(td, deltap, &olddelta);
1267         if (uap->olddelta && error == 0) {
1268                 CP(olddelta, tv32, tv_sec);
1269                 CP(olddelta, tv32, tv_usec);
1270                 error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1271         }
1272         return (error);
1273 }
1274
1275 #ifdef COMPAT_FREEBSD4
1276 int
1277 freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1278 {
1279         struct statfs32 s32;
1280         struct statfs s;
1281         int error;
1282
1283         error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1284         if (error)
1285                 return (error);
1286         copy_statfs(&s, &s32);
1287         return (copyout(&s32, uap->buf, sizeof(s32)));
1288 }
1289 #endif
1290
1291 #ifdef COMPAT_FREEBSD4
1292 int
1293 freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1294 {
1295         struct statfs32 s32;
1296         struct statfs s;
1297         int error;
1298
1299         error = kern_fstatfs(td, uap->fd, &s);
1300         if (error)
1301                 return (error);
1302         copy_statfs(&s, &s32);
1303         return (copyout(&s32, uap->buf, sizeof(s32)));
1304 }
1305 #endif
1306
1307 #ifdef COMPAT_FREEBSD4
1308 int
1309 freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1310 {
1311         struct statfs32 s32;
1312         struct statfs s;
1313         fhandle_t fh;
1314         int error;
1315
1316         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1317                 return (error);
1318         error = kern_fhstatfs(td, fh, &s);
1319         if (error)
1320                 return (error);
1321         copy_statfs(&s, &s32);
1322         return (copyout(&s32, uap->buf, sizeof(s32)));
1323 }
1324 #endif
1325
1326 int
1327 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1328 {
1329         /*
1330          * Vector through to semsys if it is loaded.
1331          */
1332         return sysent[SYS_semsys].sy_call(td, uap);
1333 }
1334
1335 int
1336 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1337 {
1338         switch (uap->which) {
1339         case 2:
1340                 return (freebsd32_msgsnd(td,
1341                     (struct freebsd32_msgsnd_args *)&uap->a2));
1342                 break;
1343         case 3:
1344                 return (freebsd32_msgrcv(td,
1345                     (struct freebsd32_msgrcv_args *)&uap->a2));
1346                 break;
1347         default:
1348                 /*
1349                  * Vector through to msgsys if it is loaded.
1350                  */
1351                 return (sysent[SYS_msgsys].sy_call(td, uap));
1352                 break;
1353         }
1354 }
1355
1356 int
1357 freebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap)
1358 {
1359         const void *msgp;
1360         long mtype;
1361         int32_t mtype32;
1362         int error;
1363
1364         if (!SYSCALL_MODULE_PRESENT(msgsnd))
1365                 return (nosys(td, (struct nosys_args *)uap));
1366
1367         msgp = PTRIN(uap->msgp);
1368         if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0)
1369                 return (error);
1370         mtype = mtype32;
1371         return (kern_msgsnd(td, uap->msqid,
1372             (const char *)msgp + sizeof(mtype32),
1373             uap->msgsz, uap->msgflg, mtype));
1374 }
1375
1376 int
1377 freebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap)
1378 {
1379         void *msgp;
1380         long mtype;
1381         int32_t mtype32;
1382         int error;
1383
1384         if (!SYSCALL_MODULE_PRESENT(msgrcv))
1385                 return (nosys(td, (struct nosys_args *)uap));
1386
1387         msgp = PTRIN(uap->msgp);
1388         if ((error = kern_msgrcv(td, uap->msqid,
1389             (char *)msgp + sizeof(mtype32), uap->msgsz,
1390             uap->msgtyp, uap->msgflg, &mtype)) != 0)
1391                 return (error);
1392         mtype32 = (int32_t)mtype;
1393         return (copyout(&mtype32, msgp, sizeof(mtype32)));
1394 }
1395
1396 int
1397 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1398 {
1399
1400         switch (uap->which) {
1401         case 0: {       /* shmat */
1402                 struct shmat_args ap;
1403
1404                 ap.shmid = uap->a2;
1405                 ap.shmaddr = PTRIN(uap->a3);
1406                 ap.shmflg = uap->a4;
1407                 return (sysent[SYS_shmat].sy_call(td, &ap));
1408         }
1409         case 2: {       /* shmdt */
1410                 struct shmdt_args ap;
1411
1412                 ap.shmaddr = PTRIN(uap->a2);
1413                 return (sysent[SYS_shmdt].sy_call(td, &ap));
1414         }
1415         case 3: {       /* shmget */
1416                 struct shmget_args ap;
1417
1418                 ap.key = uap->a2;
1419                 ap.size = uap->a3;
1420                 ap.shmflg = uap->a4;
1421                 return (sysent[SYS_shmget].sy_call(td, &ap));
1422         }
1423         case 4: {       /* shmctl */
1424                 struct freebsd32_shmctl_args ap;
1425
1426                 ap.shmid = uap->a2;
1427                 ap.cmd = uap->a3;
1428                 ap.buf = PTRIN(uap->a4);
1429                 return (freebsd32_shmctl(td, &ap));
1430         }
1431         case 1:         /* oshmctl */
1432         default:
1433                 return (EINVAL);
1434         }
1435 }
1436
1437 struct ipc_perm32 {
1438         uint16_t        cuid;
1439         uint16_t        cgid;
1440         uint16_t        uid;
1441         uint16_t        gid;
1442         uint16_t        mode;
1443         uint16_t        seq;
1444         uint32_t        key;
1445 };
1446 struct shmid_ds32 {
1447         struct ipc_perm32 shm_perm;
1448         int32_t         shm_segsz;
1449         int32_t         shm_lpid;
1450         int32_t         shm_cpid;
1451         int16_t         shm_nattch;
1452         int32_t         shm_atime;
1453         int32_t         shm_dtime;
1454         int32_t         shm_ctime;
1455         uint32_t        shm_internal;
1456 };
1457 struct shm_info32 {
1458         int32_t         used_ids;
1459         uint32_t        shm_tot;
1460         uint32_t        shm_rss;
1461         uint32_t        shm_swp;
1462         uint32_t        swap_attempts;
1463         uint32_t        swap_successes;
1464 };
1465 struct shminfo32 {
1466         uint32_t        shmmax;
1467         uint32_t        shmmin;
1468         uint32_t        shmmni;
1469         uint32_t        shmseg;
1470         uint32_t        shmall;
1471 };
1472
1473 int
1474 freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
1475 {
1476         int error = 0;
1477         union {
1478                 struct shmid_ds shmid_ds;
1479                 struct shm_info shm_info;
1480                 struct shminfo shminfo;
1481         } u;
1482         union {
1483                 struct shmid_ds32 shmid_ds32;
1484                 struct shm_info32 shm_info32;
1485                 struct shminfo32 shminfo32;
1486         } u32;
1487         size_t sz;
1488         
1489         if (uap->cmd == IPC_SET) {
1490                 if ((error = copyin(uap->buf, &u32.shmid_ds32,
1491                     sizeof(u32.shmid_ds32))))
1492                         goto done;
1493                 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cuid);
1494                 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.cgid);
1495                 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.uid);
1496                 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.gid);
1497                 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.mode);
1498                 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.seq);
1499                 CP(u32.shmid_ds32, u.shmid_ds, shm_perm.key);
1500                 CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1501                 CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1502                 CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1503                 CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1504                 CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1505                 CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1506                 CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1507                 PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal);
1508         }
1509         
1510         error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1511         if (error)
1512                 goto done;
1513         
1514         /* Cases in which we need to copyout */
1515         switch (uap->cmd) {
1516         case IPC_INFO:
1517                 CP(u.shminfo, u32.shminfo32, shmmax);
1518                 CP(u.shminfo, u32.shminfo32, shmmin);
1519                 CP(u.shminfo, u32.shminfo32, shmmni);
1520                 CP(u.shminfo, u32.shminfo32, shmseg);
1521                 CP(u.shminfo, u32.shminfo32, shmall);
1522                 error = copyout(&u32.shminfo32, uap->buf,
1523                     sizeof(u32.shminfo32));
1524                 break;
1525         case SHM_INFO:
1526                 CP(u.shm_info, u32.shm_info32, used_ids);
1527                 CP(u.shm_info, u32.shm_info32, shm_rss);
1528                 CP(u.shm_info, u32.shm_info32, shm_tot);
1529                 CP(u.shm_info, u32.shm_info32, shm_swp);
1530                 CP(u.shm_info, u32.shm_info32, swap_attempts);
1531                 CP(u.shm_info, u32.shm_info32, swap_successes);
1532                 error = copyout(&u32.shm_info32, uap->buf,
1533                     sizeof(u32.shm_info32));
1534                 break;
1535         case SHM_STAT:
1536         case IPC_STAT:
1537                 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cuid);
1538                 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.cgid);
1539                 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.uid);
1540                 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.gid);
1541                 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.mode);
1542                 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.seq);
1543                 CP(u.shmid_ds, u32.shmid_ds32, shm_perm.key);
1544                 CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1545                 CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1546                 CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1547                 CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1548                 CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1549                 CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1550                 CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1551                 PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal);
1552                 error = copyout(&u32.shmid_ds32, uap->buf,
1553                     sizeof(u32.shmid_ds32));
1554                 break;
1555         }
1556
1557 done:
1558         if (error) {
1559                 /* Invalidate the return value */
1560                 td->td_retval[0] = -1;
1561         }
1562         return (error);
1563 }
1564
1565 int
1566 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1567 {
1568         struct pread_args ap;
1569
1570         ap.fd = uap->fd;
1571         ap.buf = uap->buf;
1572         ap.nbyte = uap->nbyte;
1573         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1574         return (pread(td, &ap));
1575 }
1576
1577 int
1578 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
1579 {
1580         struct pwrite_args ap;
1581
1582         ap.fd = uap->fd;
1583         ap.buf = uap->buf;
1584         ap.nbyte = uap->nbyte;
1585         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1586         return (pwrite(td, &ap));
1587 }
1588
1589 int
1590 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
1591 {
1592         int error;
1593         struct lseek_args ap;
1594         off_t pos;
1595
1596         ap.fd = uap->fd;
1597         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1598         ap.whence = uap->whence;
1599         error = lseek(td, &ap);
1600         /* Expand the quad return into two parts for eax and edx */
1601         pos = *(off_t *)(td->td_retval);
1602         td->td_retval[0] = pos & 0xffffffff;    /* %eax */
1603         td->td_retval[1] = pos >> 32;           /* %edx */
1604         return error;
1605 }
1606
1607 int
1608 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
1609 {
1610         struct truncate_args ap;
1611
1612         ap.path = uap->path;
1613         ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1614         return (truncate(td, &ap));
1615 }
1616
1617 int
1618 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
1619 {
1620         struct ftruncate_args ap;
1621
1622         ap.fd = uap->fd;
1623         ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
1624         return (ftruncate(td, &ap));
1625 }
1626
1627 struct sf_hdtr32 {
1628         uint32_t headers;
1629         int hdr_cnt;
1630         uint32_t trailers;
1631         int trl_cnt;
1632 };
1633
1634 static int
1635 freebsd32_do_sendfile(struct thread *td,
1636     struct freebsd32_sendfile_args *uap, int compat)
1637 {
1638         struct sendfile_args ap;
1639         struct sf_hdtr32 hdtr32;
1640         struct sf_hdtr hdtr;
1641         struct uio *hdr_uio, *trl_uio;
1642         struct iovec32 *iov32;
1643         int error;
1644
1645         hdr_uio = trl_uio = NULL;
1646
1647         ap.fd = uap->fd;
1648         ap.s = uap->s;
1649         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
1650         ap.nbytes = uap->nbytes;
1651         ap.hdtr = (struct sf_hdtr *)uap->hdtr;          /* XXX not used */
1652         ap.sbytes = uap->sbytes;
1653         ap.flags = uap->flags;
1654
1655         if (uap->hdtr != NULL) {
1656                 error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
1657                 if (error)
1658                         goto out;
1659                 PTRIN_CP(hdtr32, hdtr, headers);
1660                 CP(hdtr32, hdtr, hdr_cnt);
1661                 PTRIN_CP(hdtr32, hdtr, trailers);
1662                 CP(hdtr32, hdtr, trl_cnt);
1663
1664                 if (hdtr.headers != NULL) {
1665                         iov32 = PTRIN(hdtr32.headers);
1666                         error = freebsd32_copyinuio(iov32,
1667                             hdtr32.hdr_cnt, &hdr_uio);
1668                         if (error)
1669                                 goto out;
1670                 }
1671                 if (hdtr.trailers != NULL) {
1672                         iov32 = PTRIN(hdtr32.trailers);
1673                         error = freebsd32_copyinuio(iov32,
1674                             hdtr32.trl_cnt, &trl_uio);
1675                         if (error)
1676                                 goto out;
1677                 }
1678         }
1679
1680         error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
1681 out:
1682         if (hdr_uio)
1683                 free(hdr_uio, M_IOV);
1684         if (trl_uio)
1685                 free(trl_uio, M_IOV);
1686         return (error);
1687 }
1688
1689 #ifdef COMPAT_FREEBSD4
1690 int
1691 freebsd4_freebsd32_sendfile(struct thread *td,
1692     struct freebsd4_freebsd32_sendfile_args *uap)
1693 {
1694         return (freebsd32_do_sendfile(td,
1695             (struct freebsd32_sendfile_args *)uap, 1));
1696 }
1697 #endif
1698
1699 int
1700 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
1701 {
1702
1703         return (freebsd32_do_sendfile(td, uap, 0));
1704 }
1705
1706 struct stat32 {
1707         dev_t   st_dev;
1708         ino_t   st_ino;
1709         mode_t  st_mode;
1710         nlink_t st_nlink;
1711         uid_t   st_uid;
1712         gid_t   st_gid;
1713         dev_t   st_rdev;
1714         struct timespec32 st_atimespec;
1715         struct timespec32 st_mtimespec;
1716         struct timespec32 st_ctimespec;
1717         off_t   st_size;
1718         int64_t st_blocks;
1719         u_int32_t st_blksize;
1720         u_int32_t st_flags;
1721         u_int32_t st_gen;
1722         struct timespec32 st_birthtimespec;
1723         unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1724         unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
1725 };
1726
1727
1728 CTASSERT(sizeof(struct stat32) == 96);
1729
1730 static void
1731 copy_stat( struct stat *in, struct stat32 *out)
1732 {
1733         CP(*in, *out, st_dev);
1734         CP(*in, *out, st_ino);
1735         CP(*in, *out, st_mode);
1736         CP(*in, *out, st_nlink);
1737         CP(*in, *out, st_uid);
1738         CP(*in, *out, st_gid);
1739         CP(*in, *out, st_rdev);
1740         TS_CP(*in, *out, st_atimespec);
1741         TS_CP(*in, *out, st_mtimespec);
1742         TS_CP(*in, *out, st_ctimespec);
1743         CP(*in, *out, st_size);
1744         CP(*in, *out, st_blocks);
1745         CP(*in, *out, st_blksize);
1746         CP(*in, *out, st_flags);
1747         CP(*in, *out, st_gen);
1748 }
1749
1750 int
1751 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
1752 {
1753         struct stat sb;
1754         struct stat32 sb32;
1755         int error;
1756
1757         error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1758         if (error)
1759                 return (error);
1760         copy_stat(&sb, &sb32);
1761         error = copyout(&sb32, uap->ub, sizeof (sb32));
1762         return (error);
1763 }
1764
1765 int
1766 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
1767 {
1768         struct stat ub;
1769         struct stat32 ub32;
1770         int error;
1771
1772         error = kern_fstat(td, uap->fd, &ub);
1773         if (error)
1774                 return (error);
1775         copy_stat(&ub, &ub32);
1776         error = copyout(&ub32, uap->ub, sizeof(ub32));
1777         return (error);
1778 }
1779
1780 int
1781 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
1782 {
1783         struct stat sb;
1784         struct stat32 sb32;
1785         int error;
1786
1787         error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
1788         if (error)
1789                 return (error);
1790         copy_stat(&sb, &sb32);
1791         error = copyout(&sb32, uap->ub, sizeof (sb32));
1792         return (error);
1793 }
1794
1795 /*
1796  * MPSAFE
1797  */
1798 int
1799 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
1800 {
1801         int error, name[CTL_MAXNAME];
1802         size_t j, oldlen;
1803
1804         if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1805                 return (EINVAL);
1806         error = copyin(uap->name, name, uap->namelen * sizeof(int));
1807         if (error)
1808                 return (error);
1809         mtx_lock(&Giant);
1810         if (uap->oldlenp)
1811                 oldlen = fuword32(uap->oldlenp);
1812         else
1813                 oldlen = 0;
1814         error = userland_sysctl(td, name, uap->namelen,
1815                 uap->old, &oldlen, 1,
1816                 uap->new, uap->newlen, &j, SCTL_MASK32);
1817         if (error && error != ENOMEM)
1818                 goto done2;
1819         if (uap->oldlenp)
1820                 suword32(uap->oldlenp, j);
1821 done2:
1822         mtx_unlock(&Giant);
1823         return (error);
1824 }
1825
1826 struct sigaction32 {
1827         u_int32_t       sa_u;
1828         int             sa_flags;
1829         sigset_t        sa_mask;
1830 };
1831
1832 CTASSERT(sizeof(struct sigaction32) == 24);
1833
1834 int
1835 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
1836 {
1837         struct sigaction32 s32;
1838         struct sigaction sa, osa, *sap;
1839         int error;
1840
1841         if (uap->act) {
1842                 error = copyin(uap->act, &s32, sizeof(s32));
1843                 if (error)
1844                         return (error);
1845                 sa.sa_handler = PTRIN(s32.sa_u);
1846                 CP(s32, sa, sa_flags);
1847                 CP(s32, sa, sa_mask);
1848                 sap = &sa;
1849         } else
1850                 sap = NULL;
1851         error = kern_sigaction(td, uap->sig, sap, &osa, 0);
1852         if (error == 0 && uap->oact != NULL) {
1853                 s32.sa_u = PTROUT(osa.sa_handler);
1854                 CP(osa, s32, sa_flags);
1855                 CP(osa, s32, sa_mask);
1856                 error = copyout(&s32, uap->oact, sizeof(s32));
1857         }
1858         return (error);
1859 }
1860
1861 #ifdef COMPAT_FREEBSD4
1862 int
1863 freebsd4_freebsd32_sigaction(struct thread *td,
1864                              struct freebsd4_freebsd32_sigaction_args *uap)
1865 {
1866         struct sigaction32 s32;
1867         struct sigaction sa, osa, *sap;
1868         int error;
1869
1870         if (uap->act) {
1871                 error = copyin(uap->act, &s32, sizeof(s32));
1872                 if (error)
1873                         return (error);
1874                 sa.sa_handler = PTRIN(s32.sa_u);
1875                 CP(s32, sa, sa_flags);
1876                 CP(s32, sa, sa_mask);
1877                 sap = &sa;
1878         } else
1879                 sap = NULL;
1880         error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
1881         if (error == 0 && uap->oact != NULL) {
1882                 s32.sa_u = PTROUT(osa.sa_handler);
1883                 CP(osa, s32, sa_flags);
1884                 CP(osa, s32, sa_mask);
1885                 error = copyout(&s32, uap->oact, sizeof(s32));
1886         }
1887         return (error);
1888 }
1889 #endif
1890
1891 #ifdef COMPAT_43
1892 struct osigaction32 {
1893         u_int32_t       sa_u;
1894         osigset_t       sa_mask;
1895         int             sa_flags;
1896 };
1897
1898 #define ONSIG   32
1899
1900 int
1901 ofreebsd32_sigaction(struct thread *td,
1902                              struct ofreebsd32_sigaction_args *uap)
1903 {
1904         struct osigaction32 s32;
1905         struct sigaction sa, osa, *sap;
1906         int error;
1907
1908         if (uap->signum <= 0 || uap->signum >= ONSIG)
1909                 return (EINVAL);
1910
1911         if (uap->nsa) {
1912                 error = copyin(uap->nsa, &s32, sizeof(s32));
1913                 if (error)
1914                         return (error);
1915                 sa.sa_handler = PTRIN(s32.sa_u);
1916                 CP(s32, sa, sa_flags);
1917                 OSIG2SIG(s32.sa_mask, sa.sa_mask);
1918                 sap = &sa;
1919         } else
1920                 sap = NULL;
1921         error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1922         if (error == 0 && uap->osa != NULL) {
1923                 s32.sa_u = PTROUT(osa.sa_handler);
1924                 CP(osa, s32, sa_flags);
1925                 SIG2OSIG(osa.sa_mask, s32.sa_mask);
1926                 error = copyout(&s32, uap->osa, sizeof(s32));
1927         }
1928         return (error);
1929 }
1930
1931 int
1932 ofreebsd32_sigprocmask(struct thread *td,
1933                                struct ofreebsd32_sigprocmask_args *uap)
1934 {
1935         sigset_t set, oset;
1936         int error;
1937
1938         OSIG2SIG(uap->mask, set);
1939         error = kern_sigprocmask(td, uap->how, &set, &oset, 1);
1940         SIG2OSIG(oset, td->td_retval[0]);
1941         return (error);
1942 }
1943
1944 int
1945 ofreebsd32_sigpending(struct thread *td,
1946                               struct ofreebsd32_sigpending_args *uap)
1947 {
1948         struct proc *p = td->td_proc;
1949         sigset_t siglist;
1950
1951         PROC_LOCK(p);
1952         siglist = p->p_siglist;
1953         SIGSETOR(siglist, td->td_siglist);
1954         PROC_UNLOCK(p);
1955         SIG2OSIG(siglist, td->td_retval[0]);
1956         return (0);
1957 }
1958
1959 struct sigvec32 {
1960         u_int32_t       sv_handler;
1961         int             sv_mask;
1962         int             sv_flags;
1963 };
1964
1965 int
1966 ofreebsd32_sigvec(struct thread *td,
1967                           struct ofreebsd32_sigvec_args *uap)
1968 {
1969         struct sigvec32 vec;
1970         struct sigaction sa, osa, *sap;
1971         int error;
1972
1973         if (uap->signum <= 0 || uap->signum >= ONSIG)
1974                 return (EINVAL);
1975
1976         if (uap->nsv) {
1977                 error = copyin(uap->nsv, &vec, sizeof(vec));
1978                 if (error)
1979                         return (error);
1980                 sa.sa_handler = PTRIN(vec.sv_handler);
1981                 OSIG2SIG(vec.sv_mask, sa.sa_mask);
1982                 sa.sa_flags = vec.sv_flags;
1983                 sa.sa_flags ^= SA_RESTART;
1984                 sap = &sa;
1985         } else
1986                 sap = NULL;
1987         error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
1988         if (error == 0 && uap->osv != NULL) {
1989                 vec.sv_handler = PTROUT(osa.sa_handler);
1990                 SIG2OSIG(osa.sa_mask, vec.sv_mask);
1991                 vec.sv_flags = osa.sa_flags;
1992                 vec.sv_flags &= ~SA_NOCLDWAIT;
1993                 vec.sv_flags ^= SA_RESTART;
1994                 error = copyout(&vec, uap->osv, sizeof(vec));
1995         }
1996         return (error);
1997 }
1998
1999 int
2000 ofreebsd32_sigblock(struct thread *td,
2001                             struct ofreebsd32_sigblock_args *uap)
2002 {
2003         struct proc *p = td->td_proc;
2004         sigset_t set;
2005
2006         OSIG2SIG(uap->mask, set);
2007         SIG_CANTMASK(set);
2008         PROC_LOCK(p);
2009         SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2010         SIGSETOR(td->td_sigmask, set);
2011         PROC_UNLOCK(p);
2012         return (0);
2013 }
2014
2015 int
2016 ofreebsd32_sigsetmask(struct thread *td,
2017                               struct ofreebsd32_sigsetmask_args *uap)
2018 {
2019         struct proc *p = td->td_proc;
2020         sigset_t set;
2021
2022         OSIG2SIG(uap->mask, set);
2023         SIG_CANTMASK(set);
2024         PROC_LOCK(p);
2025         SIG2OSIG(td->td_sigmask, td->td_retval[0]);
2026         SIGSETLO(td->td_sigmask, set);
2027         signotify(td);
2028         PROC_UNLOCK(p);
2029         return (0);
2030 }
2031
2032 int
2033 ofreebsd32_sigsuspend(struct thread *td,
2034                               struct ofreebsd32_sigsuspend_args *uap)
2035 {
2036         struct proc *p = td->td_proc;
2037         sigset_t mask;
2038
2039         PROC_LOCK(p);
2040         td->td_oldsigmask = td->td_sigmask;
2041         td->td_pflags |= TDP_OLDMASK;
2042         OSIG2SIG(uap->mask, mask);
2043         SIG_CANTMASK(mask);
2044         SIGSETLO(td->td_sigmask, mask);
2045         signotify(td);
2046         while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
2047                 /* void */;
2048         PROC_UNLOCK(p);
2049         /* always return EINTR rather than ERESTART... */
2050         return (EINTR);
2051 }
2052
2053 struct sigstack32 {
2054         u_int32_t       ss_sp;
2055         int             ss_onstack;
2056 };
2057
2058 int
2059 ofreebsd32_sigstack(struct thread *td,
2060                             struct ofreebsd32_sigstack_args *uap)
2061 {
2062         struct sigstack32 s32;
2063         struct sigstack nss, oss;
2064         int error = 0;
2065
2066         if (uap->nss != NULL) {
2067                 error = copyin(uap->nss, &s32, sizeof(s32));
2068                 if (error)
2069                         return (error);
2070                 nss.ss_sp = PTRIN(s32.ss_sp);
2071                 CP(s32, nss, ss_onstack);
2072         }
2073         oss.ss_sp = td->td_sigstk.ss_sp;
2074         oss.ss_onstack = sigonstack(cpu_getstack(td));
2075         if (uap->nss != NULL) {
2076                 td->td_sigstk.ss_sp = nss.ss_sp;
2077                 td->td_sigstk.ss_size = 0;
2078                 td->td_sigstk.ss_flags |= nss.ss_onstack & SS_ONSTACK;
2079                 td->td_pflags |= TDP_ALTSTACK;
2080         }
2081         if (uap->oss != NULL) {
2082                 s32.ss_sp = PTROUT(oss.ss_sp);
2083                 CP(oss, s32, ss_onstack);
2084                 error = copyout(&s32, uap->oss, sizeof(s32));
2085         }
2086         return (error);
2087 }
2088 #endif
2089
2090 int
2091 freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2092 {
2093         struct timespec32 rmt32, rqt32;
2094         struct timespec rmt, rqt;
2095         int error;
2096
2097         error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2098         if (error)
2099                 return (error);
2100
2101         CP(rqt32, rqt, tv_sec);
2102         CP(rqt32, rqt, tv_nsec);
2103
2104         if (uap->rmtp &&
2105             !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2106                 return (EFAULT);
2107         error = kern_nanosleep(td, &rqt, &rmt);
2108         if (error && uap->rmtp) {
2109                 int error2;
2110
2111                 CP(rmt, rmt32, tv_sec);
2112                 CP(rmt, rmt32, tv_nsec);
2113
2114                 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2115                 if (error2)
2116                         error = error2;
2117         }
2118         return (error);
2119 }
2120
2121 int
2122 freebsd32_clock_gettime(struct thread *td,
2123                         struct freebsd32_clock_gettime_args *uap)
2124 {
2125         struct timespec ats;
2126         struct timespec32 ats32;
2127         int error;
2128
2129         error = kern_clock_gettime(td, uap->clock_id, &ats);
2130         if (error == 0) {
2131                 CP(ats, ats32, tv_sec);
2132                 CP(ats, ats32, tv_nsec);
2133                 error = copyout(&ats32, uap->tp, sizeof(ats32));
2134         }
2135         return (error);
2136 }
2137
2138 int
2139 freebsd32_clock_settime(struct thread *td,
2140                         struct freebsd32_clock_settime_args *uap)
2141 {
2142         struct timespec ats;
2143         struct timespec32 ats32;
2144         int error;
2145
2146         error = copyin(uap->tp, &ats32, sizeof(ats32));
2147         if (error)
2148                 return (error);
2149         CP(ats32, ats, tv_sec);
2150         CP(ats32, ats, tv_nsec);
2151
2152         return (kern_clock_settime(td, uap->clock_id, &ats));
2153 }
2154
2155 int
2156 freebsd32_clock_getres(struct thread *td,
2157                        struct freebsd32_clock_getres_args *uap)
2158 {
2159         struct timespec ts;
2160         struct timespec32 ts32;
2161         int error;
2162
2163         if (uap->tp == NULL)
2164                 return (0);
2165         error = kern_clock_getres(td, uap->clock_id, &ts);
2166         if (error == 0) {
2167                 CP(ts, ts32, tv_sec);
2168                 CP(ts, ts32, tv_nsec);
2169                 error = copyout(&ts32, uap->tp, sizeof(ts32));
2170         }
2171         return (error);
2172 }
2173
2174 int
2175 freebsd32_thr_new(struct thread *td,
2176                   struct freebsd32_thr_new_args *uap)
2177 {
2178         struct thr_param32 param32;
2179         struct thr_param param;
2180         int error;
2181
2182         if (uap->param_size < 0 ||
2183             uap->param_size > sizeof(struct thr_param32))
2184                 return (EINVAL);
2185         bzero(&param, sizeof(struct thr_param));
2186         bzero(&param32, sizeof(struct thr_param32));
2187         error = copyin(uap->param, &param32, uap->param_size);
2188         if (error != 0)
2189                 return (error);
2190         param.start_func = PTRIN(param32.start_func);
2191         param.arg = PTRIN(param32.arg);
2192         param.stack_base = PTRIN(param32.stack_base);
2193         param.stack_size = param32.stack_size;
2194         param.tls_base = PTRIN(param32.tls_base);
2195         param.tls_size = param32.tls_size;
2196         param.child_tid = PTRIN(param32.child_tid);
2197         param.parent_tid = PTRIN(param32.parent_tid);
2198         param.flags = param32.flags;
2199         param.rtp = PTRIN(param32.rtp);
2200         param.spare[0] = PTRIN(param32.spare[0]);
2201         param.spare[1] = PTRIN(param32.spare[1]);
2202         param.spare[2] = PTRIN(param32.spare[2]);
2203
2204         return (kern_thr_new(td, &param));
2205 }
2206
2207 int
2208 freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2209 {
2210         struct timespec32 ts32;
2211         struct timespec ts, *tsp;
2212         int error;
2213
2214         error = 0;
2215         tsp = NULL;
2216         if (uap->timeout != NULL) {
2217                 error = copyin((const void *)uap->timeout, (void *)&ts32,
2218                     sizeof(struct timespec32));
2219                 if (error != 0)
2220                         return (error);
2221                 ts.tv_sec = ts32.tv_sec;
2222                 ts.tv_nsec = ts32.tv_nsec;
2223                 tsp = &ts;
2224         }
2225         return (kern_thr_suspend(td, tsp));
2226 }
2227
2228 void
2229 siginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst)
2230 {
2231         bzero(dst, sizeof(*dst));
2232         dst->si_signo = src->si_signo;
2233         dst->si_errno = src->si_errno;
2234         dst->si_code = src->si_code;
2235         dst->si_pid = src->si_pid;
2236         dst->si_uid = src->si_uid;
2237         dst->si_status = src->si_status;
2238         dst->si_addr = dst->si_addr;
2239         dst->si_value.sigval_int = src->si_value.sival_int;
2240         dst->si_timerid = src->si_timerid;
2241         dst->si_overrun = src->si_overrun;
2242 }
2243
2244 int
2245 freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
2246 {
2247         struct timespec32 ts32;
2248         struct timespec ts;
2249         struct timespec *timeout;
2250         sigset_t set;
2251         ksiginfo_t ksi;
2252         struct siginfo32 si32;
2253         int error;
2254
2255         if (uap->timeout) {
2256                 error = copyin(uap->timeout, &ts32, sizeof(ts32));
2257                 if (error)
2258                         return (error);
2259                 ts.tv_sec = ts32.tv_sec;
2260                 ts.tv_nsec = ts32.tv_nsec;
2261                 timeout = &ts;
2262         } else
2263                 timeout = NULL;
2264
2265         error = copyin(uap->set, &set, sizeof(set));
2266         if (error)
2267                 return (error);
2268
2269         error = kern_sigtimedwait(td, set, &ksi, timeout);
2270         if (error)
2271                 return (error);
2272
2273         if (uap->info) {
2274                 siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2275                 error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2276         }
2277
2278         if (error == 0)
2279                 td->td_retval[0] = ksi.ksi_signo;
2280         return (error);
2281 }
2282
2283 /*
2284  * MPSAFE
2285  */
2286 int
2287 freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
2288 {
2289         ksiginfo_t ksi;
2290         struct siginfo32 si32;
2291         sigset_t set;
2292         int error;
2293
2294         error = copyin(uap->set, &set, sizeof(set));
2295         if (error)
2296                 return (error);
2297
2298         error = kern_sigtimedwait(td, set, &ksi, NULL);
2299         if (error)
2300                 return (error);
2301
2302         if (uap->info) {
2303                 siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2304                 error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2305         }       
2306         if (error == 0)
2307                 td->td_retval[0] = ksi.ksi_signo;
2308         return (error);
2309 }
2310
2311 #if 0
2312
2313 int
2314 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2315 {
2316         int error;
2317         struct yyy32 *p32, s32;
2318         struct yyy *p = NULL, s;
2319
2320         if (uap->zzz) {
2321                 error = copyin(uap->zzz, &s32, sizeof(s32));
2322                 if (error)
2323                         return (error);
2324                 /* translate in */
2325                 p = &s;
2326         }
2327         error = kern_xxx(td, p);
2328         if (error)
2329                 return (error);
2330         if (uap->zzz) {
2331                 /* translate out */
2332                 error = copyout(&s32, p32, sizeof(s32));
2333         }
2334         return (error);
2335 }
2336
2337 #endif