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