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