]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/compat/freebsd32/freebsd32_misc.c
MFC r205014,205015:
[FreeBSD/stable/8.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 #include "opt_inet.h"
32 #include "opt_inet6.h"
33
34 #define __ELF_WORD_SIZE 32
35
36 #include <sys/param.h>
37 #include <sys/bus.h>
38 #include <sys/clock.h>
39 #include <sys/exec.h>
40 #include <sys/fcntl.h>
41 #include <sys/filedesc.h>
42 #include <sys/imgact.h>
43 #include <sys/jail.h>
44 #include <sys/kernel.h>
45 #include <sys/limits.h>
46 #include <sys/lock.h>
47 #include <sys/malloc.h>
48 #include <sys/file.h>           /* Must come after sys/malloc.h */
49 #include <sys/imgact.h>
50 #include <sys/mbuf.h>
51 #include <sys/mman.h>
52 #include <sys/module.h>
53 #include <sys/mount.h>
54 #include <sys/mutex.h>
55 #include <sys/namei.h>
56 #include <sys/proc.h>
57 #include <sys/reboot.h>
58 #include <sys/resource.h>
59 #include <sys/resourcevar.h>
60 #include <sys/selinfo.h>
61 #include <sys/eventvar.h>       /* Must come after sys/selinfo.h */
62 #include <sys/pipe.h>           /* Must come after sys/selinfo.h */
63 #include <sys/signal.h>
64 #include <sys/signalvar.h>
65 #include <sys/socket.h>
66 #include <sys/socketvar.h>
67 #include <sys/stat.h>
68 #include <sys/syscall.h>
69 #include <sys/syscallsubr.h>
70 #include <sys/sysctl.h>
71 #include <sys/sysent.h>
72 #include <sys/sysproto.h>
73 #include <sys/systm.h>
74 #include <sys/thr.h>
75 #include <sys/unistd.h>
76 #include <sys/ucontext.h>
77 #include <sys/vnode.h>
78 #include <sys/wait.h>
79 #include <sys/ipc.h>
80 #include <sys/msg.h>
81 #include <sys/sem.h>
82 #include <sys/shm.h>
83
84 #ifdef INET
85 #include <netinet/in.h>
86 #endif
87
88 #include <vm/vm.h>
89 #include <vm/vm_kern.h>
90 #include <vm/vm_param.h>
91 #include <vm/pmap.h>
92 #include <vm/vm_map.h>
93 #include <vm/vm_object.h>
94 #include <vm/vm_extern.h>
95
96 #include <machine/cpu.h>
97 #include <machine/elf.h>
98
99 #include <security/audit/audit.h>
100
101 #include <compat/freebsd32/freebsd32_util.h>
102 #include <compat/freebsd32/freebsd32.h>
103 #include <compat/freebsd32/freebsd32_ipc.h>
104 #include <compat/freebsd32/freebsd32_signal.h>
105 #include <compat/freebsd32/freebsd32_proto.h>
106
107 CTASSERT(sizeof(struct timeval32) == 8);
108 CTASSERT(sizeof(struct timespec32) == 8);
109 CTASSERT(sizeof(struct itimerval32) == 16);
110 CTASSERT(sizeof(struct statfs32) == 256);
111 CTASSERT(sizeof(struct rusage32) == 72);
112 CTASSERT(sizeof(struct sigaltstack32) == 12);
113 CTASSERT(sizeof(struct kevent32) == 20);
114 CTASSERT(sizeof(struct iovec32) == 8);
115 CTASSERT(sizeof(struct msghdr32) == 28);
116 CTASSERT(sizeof(struct stat32) == 96);
117 CTASSERT(sizeof(struct sigaction32) == 24);
118
119 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
120 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
121
122 #if BYTE_ORDER == BIG_ENDIAN
123 #define PAIR32TO64(type, name) ((name ## 2) | ((type)(name ## 1) << 32))
124 #define RETVAL_HI 0     
125 #define RETVAL_LO 1     
126 #else
127 #define PAIR32TO64(type, name) ((name ## 1) | ((type)(name ## 2) << 32))
128 #define RETVAL_HI 1     
129 #define RETVAL_LO 0     
130 #endif
131
132 int
133 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
134 {
135         int error, status;
136         struct rusage32 ru32;
137         struct rusage ru, *rup;
138
139         if (uap->rusage != NULL)
140                 rup = &ru;
141         else
142                 rup = NULL;
143         error = kern_wait(td, uap->pid, &status, uap->options, rup);
144         if (error)
145                 return (error);
146         if (uap->status != NULL)
147                 error = copyout(&status, uap->status, sizeof(status));
148         if (uap->rusage != NULL && error == 0) {
149                 TV_CP(ru, ru32, ru_utime);
150                 TV_CP(ru, ru32, ru_stime);
151                 CP(ru, ru32, ru_maxrss);
152                 CP(ru, ru32, ru_ixrss);
153                 CP(ru, ru32, ru_idrss);
154                 CP(ru, ru32, ru_isrss);
155                 CP(ru, ru32, ru_minflt);
156                 CP(ru, ru32, ru_majflt);
157                 CP(ru, ru32, ru_nswap);
158                 CP(ru, ru32, ru_inblock);
159                 CP(ru, ru32, ru_oublock);
160                 CP(ru, ru32, ru_msgsnd);
161                 CP(ru, ru32, ru_msgrcv);
162                 CP(ru, ru32, ru_nsignals);
163                 CP(ru, ru32, ru_nvcsw);
164                 CP(ru, ru32, ru_nivcsw);
165                 error = copyout(&ru32, uap->rusage, sizeof(ru32));
166         }
167         return (error);
168 }
169
170 #ifdef COMPAT_FREEBSD4
171 static void
172 copy_statfs(struct statfs *in, struct statfs32 *out)
173 {
174
175         statfs_scale_blocks(in, INT32_MAX);
176         bzero(out, sizeof(*out));
177         CP(*in, *out, f_bsize);
178         out->f_iosize = MIN(in->f_iosize, INT32_MAX);
179         CP(*in, *out, f_blocks);
180         CP(*in, *out, f_bfree);
181         CP(*in, *out, f_bavail);
182         out->f_files = MIN(in->f_files, INT32_MAX);
183         out->f_ffree = MIN(in->f_ffree, INT32_MAX);
184         CP(*in, *out, f_fsid);
185         CP(*in, *out, f_owner);
186         CP(*in, *out, f_type);
187         CP(*in, *out, f_flags);
188         out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
189         out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
190         strlcpy(out->f_fstypename,
191               in->f_fstypename, MFSNAMELEN);
192         strlcpy(out->f_mntonname,
193               in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
194         out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
195         out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
196         strlcpy(out->f_mntfromname,
197               in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
198 }
199 #endif
200
201 #ifdef COMPAT_FREEBSD4
202 int
203 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
204 {
205         struct statfs *buf, *sp;
206         struct statfs32 stat32;
207         size_t count, size;
208         int error;
209
210         count = uap->bufsize / sizeof(struct statfs32);
211         size = count * sizeof(struct statfs);
212         error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
213         if (size > 0) {
214                 count = td->td_retval[0];
215                 sp = buf;
216                 while (count > 0 && error == 0) {
217                         copy_statfs(sp, &stat32);
218                         error = copyout(&stat32, uap->buf, sizeof(stat32));
219                         sp++;
220                         uap->buf++;
221                         count--;
222                 }
223                 free(buf, M_TEMP);
224         }
225         return (error);
226 }
227 #endif
228
229 int
230 freebsd32_sigaltstack(struct thread *td,
231                       struct freebsd32_sigaltstack_args *uap)
232 {
233         struct sigaltstack32 s32;
234         struct sigaltstack ss, oss, *ssp;
235         int error;
236
237         if (uap->ss != NULL) {
238                 error = copyin(uap->ss, &s32, sizeof(s32));
239                 if (error)
240                         return (error);
241                 PTRIN_CP(s32, ss, ss_sp);
242                 CP(s32, ss, ss_size);
243                 CP(s32, ss, ss_flags);
244                 ssp = &ss;
245         } else
246                 ssp = NULL;
247         error = kern_sigaltstack(td, ssp, &oss);
248         if (error == 0 && uap->oss != NULL) {
249                 PTROUT_CP(oss, s32, ss_sp);
250                 CP(oss, s32, ss_size);
251                 CP(oss, s32, ss_flags);
252                 error = copyout(&s32, uap->oss, sizeof(s32));
253         }
254         return (error);
255 }
256
257 /*
258  * Custom version of exec_copyin_args() so that we can translate
259  * the pointers.
260  */
261 static int
262 freebsd32_exec_copyin_args(struct image_args *args, char *fname,
263     enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
264 {
265         char *argp, *envp;
266         u_int32_t *p32, arg;
267         size_t length;
268         int error;
269
270         bzero(args, sizeof(*args));
271         if (argv == NULL)
272                 return (EFAULT);
273
274         /*
275          * Allocate temporary demand zeroed space for argument and
276          *      environment strings
277          */
278         args->buf = (char *) kmem_alloc_wait(exec_map,
279             PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
280         if (args->buf == NULL)
281                 return (ENOMEM);
282         args->begin_argv = args->buf;
283         args->endp = args->begin_argv;
284         args->stringspace = ARG_MAX;
285
286         /*
287          * Copy the file name.
288          */
289         if (fname != NULL) {
290                 args->fname = args->buf + ARG_MAX;
291                 error = (segflg == UIO_SYSSPACE) ?
292                     copystr(fname, args->fname, PATH_MAX, &length) :
293                     copyinstr(fname, args->fname, PATH_MAX, &length);
294                 if (error != 0)
295                         goto err_exit;
296         } else
297                 args->fname = NULL;
298
299         /*
300          * extract arguments first
301          */
302         p32 = argv;
303         for (;;) {
304                 error = copyin(p32++, &arg, sizeof(arg));
305                 if (error)
306                         goto err_exit;
307                 if (arg == 0)
308                         break;
309                 argp = PTRIN(arg);
310                 error = copyinstr(argp, args->endp, args->stringspace, &length);
311                 if (error) {
312                         if (error == ENAMETOOLONG)
313                                 error = E2BIG;
314                         goto err_exit;
315                 }
316                 args->stringspace -= length;
317                 args->endp += length;
318                 args->argc++;
319         }
320                         
321         args->begin_envv = args->endp;
322
323         /*
324          * extract environment strings
325          */
326         if (envv) {
327                 p32 = envv;
328                 for (;;) {
329                         error = copyin(p32++, &arg, sizeof(arg));
330                         if (error)
331                                 goto err_exit;
332                         if (arg == 0)
333                                 break;
334                         envp = PTRIN(arg);
335                         error = copyinstr(envp, args->endp, args->stringspace,
336                             &length);
337                         if (error) {
338                                 if (error == ENAMETOOLONG)
339                                         error = E2BIG;
340                                 goto err_exit;
341                         }
342                         args->stringspace -= length;
343                         args->endp += length;
344                         args->envc++;
345                 }
346         }
347
348         return (0);
349
350 err_exit:
351         kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
352             PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
353         args->buf = NULL;
354         return (error);
355 }
356
357 int
358 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
359 {
360         struct image_args eargs;
361         int error;
362
363         error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
364             uap->argv, uap->envv);
365         if (error == 0)
366                 error = kern_execve(td, &eargs, NULL);
367         return (error);
368 }
369
370 int
371 freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
372 {
373         struct image_args eargs;
374         int error;
375
376         error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE,
377             uap->argv, uap->envv);
378         if (error == 0) {
379                 eargs.fd = uap->fd;
380                 error = kern_execve(td, &eargs, NULL);
381         }
382         return (error);
383 }
384
385 #ifdef __ia64__
386 static int
387 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
388                        int prot, int fd, off_t pos)
389 {
390         vm_map_t map;
391         vm_map_entry_t entry;
392         int rv;
393
394         map = &td->td_proc->p_vmspace->vm_map;
395         if (fd != -1)
396                 prot |= VM_PROT_WRITE;
397
398         if (vm_map_lookup_entry(map, start, &entry)) {
399                 if ((entry->protection & prot) != prot) {
400                         rv = vm_map_protect(map,
401                                             trunc_page(start),
402                                             round_page(end),
403                                             entry->protection | prot,
404                                             FALSE);
405                         if (rv != KERN_SUCCESS)
406                                 return (EINVAL);
407                 }
408         } else {
409                 vm_offset_t addr = trunc_page(start);
410                 rv = vm_map_find(map, 0, 0,
411                                  &addr, PAGE_SIZE, FALSE, prot,
412                                  VM_PROT_ALL, 0);
413                 if (rv != KERN_SUCCESS)
414                         return (EINVAL);
415         }
416
417         if (fd != -1) {
418                 struct pread_args r;
419                 r.fd = fd;
420                 r.buf = (void *) start;
421                 r.nbyte = end - start;
422                 r.offset = pos;
423                 return (pread(td, &r));
424         } else {
425                 while (start < end) {
426                         subyte((void *) start, 0);
427                         start++;
428                 }
429                 return (0);
430         }
431 }
432 #endif
433
434 int
435 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
436 {
437         struct mmap_args ap;
438         vm_offset_t addr = (vm_offset_t) uap->addr;
439         vm_size_t len    = uap->len;
440         int prot         = uap->prot;
441         int flags        = uap->flags;
442         int fd           = uap->fd;
443         off_t pos        = PAIR32TO64(off_t,uap->pos);
444 #ifdef __ia64__
445         vm_size_t pageoff;
446         int error;
447
448         /*
449          * Attempt to handle page size hassles.
450          */
451         pageoff = (pos & PAGE_MASK);
452         if (flags & MAP_FIXED) {
453                 vm_offset_t start, end;
454                 start = addr;
455                 end = addr + len;
456
457                 if (start != trunc_page(start)) {
458                         error = freebsd32_mmap_partial(td, start,
459                                                        round_page(start), prot,
460                                                        fd, pos);
461                         if (fd != -1)
462                                 pos += round_page(start) - start;
463                         start = round_page(start);
464                 }
465                 if (end != round_page(end)) {
466                         vm_offset_t t = trunc_page(end);
467                         error = freebsd32_mmap_partial(td, t, end,
468                                                   prot, fd,
469                                                   pos + t - start);
470                         end = trunc_page(end);
471                 }
472                 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
473                         /*
474                          * We can't map this region at all. The specified
475                          * address doesn't have the same alignment as the file
476                          * position. Fake the mapping by simply reading the
477                          * entire region into memory. First we need to make
478                          * sure the region exists.
479                          */
480                         vm_map_t map;
481                         struct pread_args r;
482                         int rv;
483
484                         prot |= VM_PROT_WRITE;
485                         map = &td->td_proc->p_vmspace->vm_map;
486                         rv = vm_map_remove(map, start, end);
487                         if (rv != KERN_SUCCESS)
488                                 return (EINVAL);
489                         rv = vm_map_find(map, 0, 0,
490                                          &start, end - start, FALSE,
491                                          prot, VM_PROT_ALL, 0);
492                         if (rv != KERN_SUCCESS)
493                                 return (EINVAL);
494                         r.fd = fd;
495                         r.buf = (void *) start;
496                         r.nbyte = end - start;
497                         r.offset = pos;
498                         error = pread(td, &r);
499                         if (error)
500                                 return (error);
501
502                         td->td_retval[0] = addr;
503                         return (0);
504                 }
505                 if (end == start) {
506                         /*
507                          * After dealing with the ragged ends, there
508                          * might be none left.
509                          */
510                         td->td_retval[0] = addr;
511                         return (0);
512                 }
513                 addr = start;
514                 len = end - start;
515         }
516 #endif
517
518         ap.addr = (void *) addr;
519         ap.len = len;
520         ap.prot = prot;
521         ap.flags = flags;
522         ap.fd = fd;
523         ap.pos = pos;
524
525         return (mmap(td, &ap));
526 }
527
528 #ifdef COMPAT_FREEBSD6
529 int
530 freebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap)
531 {
532         struct freebsd32_mmap_args ap;
533
534         ap.addr = uap->addr;
535         ap.len = uap->len;
536         ap.prot = uap->prot;
537         ap.flags = uap->flags;
538         ap.fd = uap->fd;
539         ap.pos1 = uap->pos1;
540         ap.pos2 = uap->pos2;
541
542         return (freebsd32_mmap(td, &ap));
543 }
544 #endif
545
546 int
547 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
548 {
549         struct itimerval itv, oitv, *itvp;      
550         struct itimerval32 i32;
551         int error;
552
553         if (uap->itv != NULL) {
554                 error = copyin(uap->itv, &i32, sizeof(i32));
555                 if (error)
556                         return (error);
557                 TV_CP(i32, itv, it_interval);
558                 TV_CP(i32, itv, it_value);
559                 itvp = &itv;
560         } else
561                 itvp = NULL;
562         error = kern_setitimer(td, uap->which, itvp, &oitv);
563         if (error || uap->oitv == NULL)
564                 return (error);
565         TV_CP(oitv, i32, it_interval);
566         TV_CP(oitv, i32, it_value);
567         return (copyout(&i32, uap->oitv, sizeof(i32)));
568 }
569
570 int
571 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
572 {
573         struct itimerval itv;
574         struct itimerval32 i32;
575         int error;
576
577         error = kern_getitimer(td, uap->which, &itv);
578         if (error || uap->itv == NULL)
579                 return (error);
580         TV_CP(itv, i32, it_interval);
581         TV_CP(itv, i32, it_value);
582         return (copyout(&i32, uap->itv, sizeof(i32)));
583 }
584
585 int
586 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
587 {
588         struct timeval32 tv32;
589         struct timeval tv, *tvp;
590         int error;
591
592         if (uap->tv != NULL) {
593                 error = copyin(uap->tv, &tv32, sizeof(tv32));
594                 if (error)
595                         return (error);
596                 CP(tv32, tv, tv_sec);
597                 CP(tv32, tv, tv_usec);
598                 tvp = &tv;
599         } else
600                 tvp = NULL;
601         /*
602          * XXX Do pointers need PTRIN()?
603          */
604         return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
605             sizeof(int32_t) * 8));
606 }
607
608 int
609 freebsd32_pselect(struct thread *td, struct freebsd32_pselect_args *uap)
610 {
611         struct timespec32 ts32;
612         struct timespec ts;
613         struct timeval tv, *tvp;
614         sigset_t set, *uset;
615         int error;
616
617         if (uap->ts != NULL) {
618                 error = copyin(uap->ts, &ts32, sizeof(ts32));
619                 if (error != 0)
620                         return (error);
621                 CP(ts32, ts, tv_sec);
622                 CP(ts32, ts, tv_nsec);
623                 TIMESPEC_TO_TIMEVAL(&tv, &ts);
624                 tvp = &tv;
625         } else
626                 tvp = NULL;
627         if (uap->sm != NULL) {
628                 error = copyin(uap->sm, &set, sizeof(set));
629                 if (error != 0)
630                         return (error);
631                 uset = &set;
632         } else
633                 uset = NULL;
634         /*
635          * XXX Do pointers need PTRIN()?
636          */
637         error = kern_pselect(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
638             uset, sizeof(int32_t) * 8);
639         return (error);
640 }
641
642 /*
643  * Copy 'count' items into the destination list pointed to by uap->eventlist.
644  */
645 static int
646 freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
647 {
648         struct freebsd32_kevent_args *uap;
649         struct kevent32 ks32[KQ_NEVENTS];
650         int i, error = 0;
651
652         KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
653         uap = (struct freebsd32_kevent_args *)arg;
654
655         for (i = 0; i < count; i++) {
656                 CP(kevp[i], ks32[i], ident);
657                 CP(kevp[i], ks32[i], filter);
658                 CP(kevp[i], ks32[i], flags);
659                 CP(kevp[i], ks32[i], fflags);
660                 CP(kevp[i], ks32[i], data);
661                 PTROUT_CP(kevp[i], ks32[i], udata);
662         }
663         error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
664         if (error == 0)
665                 uap->eventlist += count;
666         return (error);
667 }
668
669 /*
670  * Copy 'count' items from the list pointed to by uap->changelist.
671  */
672 static int
673 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
674 {
675         struct freebsd32_kevent_args *uap;
676         struct kevent32 ks32[KQ_NEVENTS];
677         int i, error = 0;
678
679         KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
680         uap = (struct freebsd32_kevent_args *)arg;
681
682         error = copyin(uap->changelist, ks32, count * sizeof *ks32);
683         if (error)
684                 goto done;
685         uap->changelist += count;
686
687         for (i = 0; i < count; i++) {
688                 CP(ks32[i], kevp[i], ident);
689                 CP(ks32[i], kevp[i], filter);
690                 CP(ks32[i], kevp[i], flags);
691                 CP(ks32[i], kevp[i], fflags);
692                 CP(ks32[i], kevp[i], data);
693                 PTRIN_CP(ks32[i], kevp[i], udata);
694         }
695 done:
696         return (error);
697 }
698
699 int
700 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
701 {
702         struct timespec32 ts32;
703         struct timespec ts, *tsp;
704         struct kevent_copyops k_ops = { uap,
705                                         freebsd32_kevent_copyout,
706                                         freebsd32_kevent_copyin};
707         int error;
708
709
710         if (uap->timeout) {
711                 error = copyin(uap->timeout, &ts32, sizeof(ts32));
712                 if (error)
713                         return (error);
714                 CP(ts32, ts, tv_sec);
715                 CP(ts32, ts, tv_nsec);
716                 tsp = &ts;
717         } else
718                 tsp = NULL;
719         error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
720             &k_ops, tsp);
721         return (error);
722 }
723
724 int
725 freebsd32_gettimeofday(struct thread *td,
726                        struct freebsd32_gettimeofday_args *uap)
727 {
728         struct timeval atv;
729         struct timeval32 atv32;
730         struct timezone rtz;
731         int error = 0;
732
733         if (uap->tp) {
734                 microtime(&atv);
735                 CP(atv, atv32, tv_sec);
736                 CP(atv, atv32, tv_usec);
737                 error = copyout(&atv32, uap->tp, sizeof (atv32));
738         }
739         if (error == 0 && uap->tzp != NULL) {
740                 rtz.tz_minuteswest = tz_minuteswest;
741                 rtz.tz_dsttime = tz_dsttime;
742                 error = copyout(&rtz, uap->tzp, sizeof (rtz));
743         }
744         return (error);
745 }
746
747 int
748 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
749 {
750         struct rusage32 s32;
751         struct rusage s;
752         int error;
753
754         error = kern_getrusage(td, uap->who, &s);
755         if (error)
756                 return (error);
757         if (uap->rusage != NULL) {
758                 TV_CP(s, s32, ru_utime);
759                 TV_CP(s, s32, ru_stime);
760                 CP(s, s32, ru_maxrss);
761                 CP(s, s32, ru_ixrss);
762                 CP(s, s32, ru_idrss);
763                 CP(s, s32, ru_isrss);
764                 CP(s, s32, ru_minflt);
765                 CP(s, s32, ru_majflt);
766                 CP(s, s32, ru_nswap);
767                 CP(s, s32, ru_inblock);
768                 CP(s, s32, ru_oublock);
769                 CP(s, s32, ru_msgsnd);
770                 CP(s, s32, ru_msgrcv);
771                 CP(s, s32, ru_nsignals);
772                 CP(s, s32, ru_nvcsw);
773                 CP(s, s32, ru_nivcsw);
774                 error = copyout(&s32, uap->rusage, sizeof(s32));
775         }
776         return (error);
777 }
778
779 static int
780 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
781 {
782         struct iovec32 iov32;
783         struct iovec *iov;
784         struct uio *uio;
785         u_int iovlen;
786         int error, i;
787
788         *uiop = NULL;
789         if (iovcnt > UIO_MAXIOV)
790                 return (EINVAL);
791         iovlen = iovcnt * sizeof(struct iovec);
792         uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
793         iov = (struct iovec *)(uio + 1);
794         for (i = 0; i < iovcnt; i++) {
795                 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
796                 if (error) {
797                         free(uio, M_IOV);
798                         return (error);
799                 }
800                 iov[i].iov_base = PTRIN(iov32.iov_base);
801                 iov[i].iov_len = iov32.iov_len;
802         }
803         uio->uio_iov = iov;
804         uio->uio_iovcnt = iovcnt;
805         uio->uio_segflg = UIO_USERSPACE;
806         uio->uio_offset = -1;
807         uio->uio_resid = 0;
808         for (i = 0; i < iovcnt; i++) {
809                 if (iov->iov_len > INT_MAX - uio->uio_resid) {
810                         free(uio, M_IOV);
811                         return (EINVAL);
812                 }
813                 uio->uio_resid += iov->iov_len;
814                 iov++;
815         }
816         *uiop = uio;
817         return (0);
818 }
819
820 int
821 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
822 {
823         struct uio *auio;
824         int error;
825
826         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
827         if (error)
828                 return (error);
829         error = kern_readv(td, uap->fd, auio);
830         free(auio, M_IOV);
831         return (error);
832 }
833
834 int
835 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
836 {
837         struct uio *auio;
838         int error;
839
840         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
841         if (error)
842                 return (error);
843         error = kern_writev(td, uap->fd, auio);
844         free(auio, M_IOV);
845         return (error);
846 }
847
848 int
849 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
850 {
851         struct uio *auio;
852         int error;
853
854         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
855         if (error)
856                 return (error);
857         error = kern_preadv(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
858         free(auio, M_IOV);
859         return (error);
860 }
861
862 int
863 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
864 {
865         struct uio *auio;
866         int error;
867
868         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
869         if (error)
870                 return (error);
871         error = kern_pwritev(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
872         free(auio, M_IOV);
873         return (error);
874 }
875
876 static int
877 freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
878     int error)
879 {
880         struct iovec32 iov32;
881         struct iovec *iov;
882         u_int iovlen;
883         int i;
884
885         *iovp = NULL;
886         if (iovcnt > UIO_MAXIOV)
887                 return (error);
888         iovlen = iovcnt * sizeof(struct iovec);
889         iov = malloc(iovlen, M_IOV, M_WAITOK);
890         for (i = 0; i < iovcnt; i++) {
891                 error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
892                 if (error) {
893                         free(iov, M_IOV);
894                         return (error);
895                 }
896                 iov[i].iov_base = PTRIN(iov32.iov_base);
897                 iov[i].iov_len = iov32.iov_len;
898         }
899         *iovp = iov;
900         return (0);
901 }
902
903 static int
904 freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
905 {
906         struct msghdr32 m32;
907         int error;
908
909         error = copyin(msg32, &m32, sizeof(m32));
910         if (error)
911                 return (error);
912         msg->msg_name = PTRIN(m32.msg_name);
913         msg->msg_namelen = m32.msg_namelen;
914         msg->msg_iov = PTRIN(m32.msg_iov);
915         msg->msg_iovlen = m32.msg_iovlen;
916         msg->msg_control = PTRIN(m32.msg_control);
917         msg->msg_controllen = m32.msg_controllen;
918         msg->msg_flags = m32.msg_flags;
919         return (0);
920 }
921
922 static int
923 freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
924 {
925         struct msghdr32 m32;
926         int error;
927
928         m32.msg_name = PTROUT(msg->msg_name);
929         m32.msg_namelen = msg->msg_namelen;
930         m32.msg_iov = PTROUT(msg->msg_iov);
931         m32.msg_iovlen = msg->msg_iovlen;
932         m32.msg_control = PTROUT(msg->msg_control);
933         m32.msg_controllen = msg->msg_controllen;
934         m32.msg_flags = msg->msg_flags;
935         error = copyout(&m32, msg32, sizeof(m32));
936         return (error);
937 }
938
939 #define FREEBSD32_ALIGNBYTES    (sizeof(int) - 1)
940 #define FREEBSD32_ALIGN(p)      \
941         (((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
942 #define FREEBSD32_CMSG_SPACE(l) \
943         (FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
944
945 #define FREEBSD32_CMSG_DATA(cmsg)       ((unsigned char *)(cmsg) + \
946                                  FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
947 static int
948 freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
949 {
950         struct cmsghdr *cm;
951         void *data;
952         socklen_t clen, datalen;
953         int error;
954         caddr_t ctlbuf;
955         int len, maxlen, copylen;
956         struct mbuf *m;
957         error = 0;
958
959         len    = msg->msg_controllen;
960         maxlen = msg->msg_controllen;
961         msg->msg_controllen = 0;
962
963         m = control;
964         ctlbuf = msg->msg_control;
965       
966         while (m && len > 0) {
967                 cm = mtod(m, struct cmsghdr *);
968                 clen = m->m_len;
969
970                 while (cm != NULL) {
971
972                         if (sizeof(struct cmsghdr) > clen ||
973                             cm->cmsg_len > clen) {
974                                 error = EINVAL;
975                                 break;
976                         }       
977
978                         data   = CMSG_DATA(cm);
979                         datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
980
981                         /* Adjust message length */
982                         cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
983                             datalen;
984
985
986                         /* Copy cmsghdr */
987                         copylen = sizeof(struct cmsghdr);
988                         if (len < copylen) {
989                                 msg->msg_flags |= MSG_CTRUNC;
990                                 copylen = len;
991                         }
992
993                         error = copyout(cm,ctlbuf,copylen);
994                         if (error)
995                                 goto exit;
996
997                         ctlbuf += FREEBSD32_ALIGN(copylen);
998                         len    -= FREEBSD32_ALIGN(copylen);
999
1000                         if (len <= 0)
1001                                 break;
1002
1003                         /* Copy data */
1004                         copylen = datalen;
1005                         if (len < copylen) {
1006                                 msg->msg_flags |= MSG_CTRUNC;
1007                                 copylen = len;
1008                         }
1009
1010                         error = copyout(data,ctlbuf,copylen);
1011                         if (error)
1012                                 goto exit;
1013
1014                         ctlbuf += FREEBSD32_ALIGN(copylen);
1015                         len    -= FREEBSD32_ALIGN(copylen);
1016
1017                         if (CMSG_SPACE(datalen) < clen) {
1018                                 clen -= CMSG_SPACE(datalen);
1019                                 cm = (struct cmsghdr *)
1020                                         ((caddr_t)cm + CMSG_SPACE(datalen));
1021                         } else {
1022                                 clen = 0;
1023                                 cm = NULL;
1024                         }
1025                 }       
1026                 m = m->m_next;
1027         }
1028
1029         msg->msg_controllen = (len <= 0) ? maxlen :  ctlbuf - (caddr_t)msg->msg_control;
1030         
1031 exit:
1032         return (error);
1033
1034 }
1035
1036 int
1037 freebsd32_recvmsg(td, uap)
1038         struct thread *td;
1039         struct freebsd32_recvmsg_args /* {
1040                 int     s;
1041                 struct  msghdr32 *msg;
1042                 int     flags;
1043         } */ *uap;
1044 {
1045         struct msghdr msg;
1046         struct msghdr32 m32;
1047         struct iovec *uiov, *iov;
1048         struct mbuf *control = NULL;
1049         struct mbuf **controlp;
1050
1051         int error;
1052         error = copyin(uap->msg, &m32, sizeof(m32));
1053         if (error)
1054                 return (error);
1055         error = freebsd32_copyinmsghdr(uap->msg, &msg);
1056         if (error)
1057                 return (error);
1058         error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1059             EMSGSIZE);
1060         if (error)
1061                 return (error);
1062         msg.msg_flags = uap->flags;
1063         uiov = msg.msg_iov;
1064         msg.msg_iov = iov;
1065
1066         controlp = (msg.msg_control != NULL) ?  &control : NULL;
1067         error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
1068         if (error == 0) {
1069                 msg.msg_iov = uiov;
1070                 
1071                 if (control != NULL)
1072                         error = freebsd32_copy_msg_out(&msg, control);
1073                 
1074                 if (error == 0)
1075                         error = freebsd32_copyoutmsghdr(&msg, uap->msg);
1076         }
1077         free(iov, M_IOV);
1078
1079         if (control != NULL)
1080                 m_freem(control);
1081
1082         return (error);
1083 }
1084
1085
1086 static int
1087 freebsd32_convert_msg_in(struct mbuf **controlp)
1088 {
1089         struct mbuf *control = *controlp;
1090         struct cmsghdr *cm = mtod(control, struct cmsghdr *);
1091         void *data;
1092         socklen_t clen = control->m_len, datalen;
1093         int error;
1094
1095         error = 0;
1096         *controlp = NULL;
1097
1098         while (cm != NULL) {
1099                 if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
1100                         error = EINVAL;
1101                         break;
1102                 }
1103
1104                 data = FREEBSD32_CMSG_DATA(cm);
1105                 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
1106
1107                 *controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
1108                     cm->cmsg_level);
1109                 controlp = &(*controlp)->m_next;
1110
1111                 if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
1112                         clen -= FREEBSD32_CMSG_SPACE(datalen);
1113                         cm = (struct cmsghdr *)
1114                                 ((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
1115                 } else {
1116                         clen = 0;
1117                         cm = NULL;
1118                 }
1119         }
1120
1121         m_freem(control);
1122         return (error);
1123 }
1124
1125
1126 int
1127 freebsd32_sendmsg(struct thread *td,
1128                   struct freebsd32_sendmsg_args *uap)
1129 {
1130         struct msghdr msg;
1131         struct msghdr32 m32;
1132         struct iovec *iov;
1133         struct mbuf *control = NULL;
1134         struct sockaddr *to = NULL;
1135         int error;
1136
1137         error = copyin(uap->msg, &m32, sizeof(m32));
1138         if (error)
1139                 return (error);
1140         error = freebsd32_copyinmsghdr(uap->msg, &msg);
1141         if (error)
1142                 return (error);
1143         error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
1144             EMSGSIZE);
1145         if (error)
1146                 return (error);
1147         msg.msg_iov = iov;
1148         if (msg.msg_name != NULL) {
1149                 error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
1150                 if (error) {
1151                         to = NULL;
1152                         goto out;
1153                 }
1154                 msg.msg_name = to;
1155         }
1156
1157         if (msg.msg_control) {
1158                 if (msg.msg_controllen < sizeof(struct cmsghdr)) {
1159                         error = EINVAL;
1160                         goto out;
1161                 }
1162
1163                 error = sockargs(&control, msg.msg_control,
1164                     msg.msg_controllen, MT_CONTROL);
1165                 if (error)
1166                         goto out;
1167                 
1168                 error = freebsd32_convert_msg_in(&control);
1169                 if (error)
1170                         goto out;
1171         }
1172
1173         error = kern_sendit(td, uap->s, &msg, uap->flags, control,
1174             UIO_USERSPACE);
1175
1176 out:
1177         free(iov, M_IOV);
1178         if (to)
1179                 free(to, M_SONAME);
1180         return (error);
1181 }
1182
1183 int
1184 freebsd32_recvfrom(struct thread *td,
1185                    struct freebsd32_recvfrom_args *uap)
1186 {
1187         struct msghdr msg;
1188         struct iovec aiov;
1189         int error;
1190
1191         if (uap->fromlenaddr) {
1192                 error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
1193                     sizeof(msg.msg_namelen));
1194                 if (error)
1195                         return (error);
1196         } else {
1197                 msg.msg_namelen = 0;
1198         }
1199
1200         msg.msg_name = PTRIN(uap->from);
1201         msg.msg_iov = &aiov;
1202         msg.msg_iovlen = 1;
1203         aiov.iov_base = PTRIN(uap->buf);
1204         aiov.iov_len = uap->len;
1205         msg.msg_control = NULL;
1206         msg.msg_flags = uap->flags;
1207         error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
1208         if (error == 0 && uap->fromlenaddr)
1209                 error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
1210                     sizeof (msg.msg_namelen));
1211         return (error);
1212 }
1213
1214 int
1215 freebsd32_settimeofday(struct thread *td,
1216                        struct freebsd32_settimeofday_args *uap)
1217 {
1218         struct timeval32 tv32;
1219         struct timeval tv, *tvp;
1220         struct timezone tz, *tzp;
1221         int error;
1222
1223         if (uap->tv) {
1224                 error = copyin(uap->tv, &tv32, sizeof(tv32));
1225                 if (error)
1226                         return (error);
1227                 CP(tv32, tv, tv_sec);
1228                 CP(tv32, tv, tv_usec);
1229                 tvp = &tv;
1230         } else
1231                 tvp = NULL;
1232         if (uap->tzp) {
1233                 error = copyin(uap->tzp, &tz, sizeof(tz));
1234                 if (error)
1235                         return (error);
1236                 tzp = &tz;
1237         } else
1238                 tzp = NULL;
1239         return (kern_settimeofday(td, tvp, tzp));
1240 }
1241
1242 int
1243 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
1244 {
1245         struct timeval32 s32[2];
1246         struct timeval s[2], *sp;
1247         int error;
1248
1249         if (uap->tptr != NULL) {
1250                 error = copyin(uap->tptr, s32, sizeof(s32));
1251                 if (error)
1252                         return (error);
1253                 CP(s32[0], s[0], tv_sec);
1254                 CP(s32[0], s[0], tv_usec);
1255                 CP(s32[1], s[1], tv_sec);
1256                 CP(s32[1], s[1], tv_usec);
1257                 sp = s;
1258         } else
1259                 sp = NULL;
1260         return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1261 }
1262
1263 int
1264 freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
1265 {
1266         struct timeval32 s32[2];
1267         struct timeval s[2], *sp;
1268         int error;
1269
1270         if (uap->tptr != NULL) {
1271                 error = copyin(uap->tptr, s32, sizeof(s32));
1272                 if (error)
1273                         return (error);
1274                 CP(s32[0], s[0], tv_sec);
1275                 CP(s32[0], s[0], tv_usec);
1276                 CP(s32[1], s[1], tv_sec);
1277                 CP(s32[1], s[1], tv_usec);
1278                 sp = s;
1279         } else
1280                 sp = NULL;
1281         return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
1282 }
1283
1284 int
1285 freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
1286 {
1287         struct timeval32 s32[2];
1288         struct timeval s[2], *sp;
1289         int error;
1290
1291         if (uap->tptr != NULL) {
1292                 error = copyin(uap->tptr, s32, sizeof(s32));
1293                 if (error)
1294                         return (error);
1295                 CP(s32[0], s[0], tv_sec);
1296                 CP(s32[0], s[0], tv_usec);
1297                 CP(s32[1], s[1], tv_sec);
1298                 CP(s32[1], s[1], tv_usec);
1299                 sp = s;
1300         } else
1301                 sp = NULL;
1302         return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
1303 }
1304
1305 int
1306 freebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)
1307 {
1308         struct timeval32 s32[2];
1309         struct timeval s[2], *sp;
1310         int error;
1311
1312         if (uap->times != NULL) {
1313                 error = copyin(uap->times, s32, sizeof(s32));
1314                 if (error)
1315                         return (error);
1316                 CP(s32[0], s[0], tv_sec);
1317                 CP(s32[0], s[0], tv_usec);
1318                 CP(s32[1], s[1], tv_sec);
1319                 CP(s32[1], s[1], tv_usec);
1320                 sp = s;
1321         } else
1322                 sp = NULL;
1323         return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
1324                 sp, UIO_SYSSPACE));
1325 }
1326
1327 int
1328 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
1329 {
1330         struct timeval32 tv32;
1331         struct timeval delta, olddelta, *deltap;
1332         int error;
1333
1334         if (uap->delta) {
1335                 error = copyin(uap->delta, &tv32, sizeof(tv32));
1336                 if (error)
1337                         return (error);
1338                 CP(tv32, delta, tv_sec);
1339                 CP(tv32, delta, tv_usec);
1340                 deltap = &delta;
1341         } else
1342                 deltap = NULL;
1343         error = kern_adjtime(td, deltap, &olddelta);
1344         if (uap->olddelta && error == 0) {
1345                 CP(olddelta, tv32, tv_sec);
1346                 CP(olddelta, tv32, tv_usec);
1347                 error = copyout(&tv32, uap->olddelta, sizeof(tv32));
1348         }
1349         return (error);
1350 }
1351
1352 #ifdef COMPAT_FREEBSD4
1353 int
1354 freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
1355 {
1356         struct statfs32 s32;
1357         struct statfs s;
1358         int error;
1359
1360         error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
1361         if (error)
1362                 return (error);
1363         copy_statfs(&s, &s32);
1364         return (copyout(&s32, uap->buf, sizeof(s32)));
1365 }
1366 #endif
1367
1368 #ifdef COMPAT_FREEBSD4
1369 int
1370 freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
1371 {
1372         struct statfs32 s32;
1373         struct statfs s;
1374         int error;
1375
1376         error = kern_fstatfs(td, uap->fd, &s);
1377         if (error)
1378                 return (error);
1379         copy_statfs(&s, &s32);
1380         return (copyout(&s32, uap->buf, sizeof(s32)));
1381 }
1382 #endif
1383
1384 #ifdef COMPAT_FREEBSD4
1385 int
1386 freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
1387 {
1388         struct statfs32 s32;
1389         struct statfs s;
1390         fhandle_t fh;
1391         int error;
1392
1393         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
1394                 return (error);
1395         error = kern_fhstatfs(td, fh, &s);
1396         if (error)
1397                 return (error);
1398         copy_statfs(&s, &s32);
1399         return (copyout(&s32, uap->buf, sizeof(s32)));
1400 }
1401 #endif
1402
1403 #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1404     defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1405 static void
1406 freebsd32_ipcperm_old_in(struct ipc_perm32_old *ip32, struct ipc_perm *ip)
1407 {
1408
1409         CP(*ip32, *ip, cuid);
1410         CP(*ip32, *ip, cgid);
1411         CP(*ip32, *ip, uid);
1412         CP(*ip32, *ip, gid);
1413         CP(*ip32, *ip, mode);
1414         CP(*ip32, *ip, seq);
1415         CP(*ip32, *ip, key);
1416 }
1417
1418 static void
1419 freebsd32_ipcperm_old_out(struct ipc_perm *ip, struct ipc_perm32_old *ip32)
1420 {
1421
1422         CP(*ip, *ip32, cuid);
1423         CP(*ip, *ip32, cgid);
1424         CP(*ip, *ip32, uid);
1425         CP(*ip, *ip32, gid);
1426         CP(*ip, *ip32, mode);
1427         CP(*ip, *ip32, seq);
1428         CP(*ip, *ip32, key);
1429 }
1430 #endif
1431
1432 static void
1433 freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip)
1434 {
1435
1436         CP(*ip32, *ip, cuid);
1437         CP(*ip32, *ip, cgid);
1438         CP(*ip32, *ip, uid);
1439         CP(*ip32, *ip, gid);
1440         CP(*ip32, *ip, mode);
1441         CP(*ip32, *ip, seq);
1442         CP(*ip32, *ip, key);
1443 }
1444
1445 static void
1446 freebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32)
1447 {
1448
1449         CP(*ip, *ip32, cuid);
1450         CP(*ip, *ip32, cgid);
1451         CP(*ip, *ip32, uid);
1452         CP(*ip, *ip32, gid);
1453         CP(*ip, *ip32, mode);
1454         CP(*ip, *ip32, seq);
1455         CP(*ip, *ip32, key);
1456 }
1457
1458 int
1459 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
1460 {
1461
1462 #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1463     defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1464         switch (uap->which) {
1465         case 0:
1466                 return (freebsd7_freebsd32_semctl(td,
1467                     (struct freebsd7_freebsd32_semctl_args *)&uap->a2));
1468         default:
1469                 return (semsys(td, (struct semsys_args *)uap));
1470         }
1471 #else
1472         return (nosys(td, NULL));
1473 #endif
1474 }
1475
1476 #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1477     defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1478 int
1479 freebsd7_freebsd32_semctl(struct thread *td,
1480     struct freebsd7_freebsd32_semctl_args *uap)
1481 {
1482         struct semid_ds32_old dsbuf32;
1483         struct semid_ds dsbuf;
1484         union semun semun;
1485         union semun32 arg;
1486         register_t rval;
1487         int error;
1488
1489         switch (uap->cmd) {
1490         case SEM_STAT:
1491         case IPC_SET:
1492         case IPC_STAT:
1493         case GETALL:
1494         case SETVAL:
1495         case SETALL:
1496                 error = copyin(uap->arg, &arg, sizeof(arg));
1497                 if (error)
1498                         return (error);         
1499                 break;
1500         }
1501
1502         switch (uap->cmd) {
1503         case SEM_STAT:
1504         case IPC_STAT:
1505                 semun.buf = &dsbuf;
1506                 break;
1507         case IPC_SET:
1508                 error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
1509                 if (error)
1510                         return (error);
1511                 freebsd32_ipcperm_old_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
1512                 PTRIN_CP(dsbuf32, dsbuf, sem_base);
1513                 CP(dsbuf32, dsbuf, sem_nsems);
1514                 CP(dsbuf32, dsbuf, sem_otime);
1515                 CP(dsbuf32, dsbuf, sem_ctime);
1516                 semun.buf = &dsbuf;
1517                 break;
1518         case GETALL:
1519         case SETALL:
1520                 semun.array = PTRIN(arg.array);
1521                 break;
1522         case SETVAL:
1523                 semun.val = arg.val;
1524                 break;
1525         }
1526
1527         error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
1528             &rval);
1529         if (error)
1530                 return (error);
1531
1532         switch (uap->cmd) {
1533         case SEM_STAT:
1534         case IPC_STAT:
1535                 bzero(&dsbuf32, sizeof(dsbuf32));
1536                 freebsd32_ipcperm_old_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
1537                 PTROUT_CP(dsbuf, dsbuf32, sem_base);
1538                 CP(dsbuf, dsbuf32, sem_nsems);
1539                 CP(dsbuf, dsbuf32, sem_otime);
1540                 CP(dsbuf, dsbuf32, sem_ctime);
1541                 error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
1542                 break;
1543         }
1544
1545         if (error == 0)
1546                 td->td_retval[0] = rval;
1547         return (error);
1548 }
1549 #endif
1550
1551 int
1552 freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap)
1553 {
1554         struct semid_ds32 dsbuf32;
1555         struct semid_ds dsbuf;
1556         union semun semun;
1557         union semun32 arg;
1558         register_t rval;
1559         int error;
1560
1561         switch (uap->cmd) {
1562         case SEM_STAT:
1563         case IPC_SET:
1564         case IPC_STAT:
1565         case GETALL:
1566         case SETVAL:
1567         case SETALL:
1568                 error = copyin(uap->arg, &arg, sizeof(arg));
1569                 if (error)
1570                         return (error);         
1571                 break;
1572         }
1573
1574         switch (uap->cmd) {
1575         case SEM_STAT:
1576         case IPC_STAT:
1577                 semun.buf = &dsbuf;
1578                 break;
1579         case IPC_SET:
1580                 error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
1581                 if (error)
1582                         return (error);
1583                 freebsd32_ipcperm_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
1584                 PTRIN_CP(dsbuf32, dsbuf, sem_base);
1585                 CP(dsbuf32, dsbuf, sem_nsems);
1586                 CP(dsbuf32, dsbuf, sem_otime);
1587                 CP(dsbuf32, dsbuf, sem_ctime);
1588                 semun.buf = &dsbuf;
1589                 break;
1590         case GETALL:
1591         case SETALL:
1592                 semun.array = PTRIN(arg.array);
1593                 break;
1594         case SETVAL:
1595                 semun.val = arg.val;
1596                 break;          
1597         }
1598
1599         error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
1600             &rval);
1601         if (error)
1602                 return (error);
1603
1604         switch (uap->cmd) {
1605         case SEM_STAT:
1606         case IPC_STAT:
1607                 bzero(&dsbuf32, sizeof(dsbuf32));
1608                 freebsd32_ipcperm_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
1609                 PTROUT_CP(dsbuf, dsbuf32, sem_base);
1610                 CP(dsbuf, dsbuf32, sem_nsems);
1611                 CP(dsbuf, dsbuf32, sem_otime);
1612                 CP(dsbuf, dsbuf32, sem_ctime);
1613                 error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
1614                 break;
1615         }
1616
1617         if (error == 0)
1618                 td->td_retval[0] = rval;
1619         return (error);
1620 }
1621
1622 int
1623 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
1624 {
1625
1626 #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1627     defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1628         switch (uap->which) {
1629         case 0:
1630                 return (freebsd7_freebsd32_msgctl(td,
1631                     (struct freebsd7_freebsd32_msgctl_args *)&uap->a2));
1632         case 2:
1633                 return (freebsd32_msgsnd(td,
1634                     (struct freebsd32_msgsnd_args *)&uap->a2));
1635         case 3:
1636                 return (freebsd32_msgrcv(td,
1637                     (struct freebsd32_msgrcv_args *)&uap->a2));
1638         default:
1639                 return (msgsys(td, (struct msgsys_args *)uap));
1640         }
1641 #else
1642         return (nosys(td, NULL));
1643 #endif
1644 }
1645
1646 #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1647     defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1648 int
1649 freebsd7_freebsd32_msgctl(struct thread *td,
1650     struct freebsd7_freebsd32_msgctl_args *uap)
1651 {
1652         struct msqid_ds msqbuf;
1653         struct msqid_ds32_old msqbuf32;
1654         int error;
1655
1656         if (uap->cmd == IPC_SET) {
1657                 error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
1658                 if (error)
1659                         return (error);
1660                 freebsd32_ipcperm_old_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1661                 PTRIN_CP(msqbuf32, msqbuf, msg_first);
1662                 PTRIN_CP(msqbuf32, msqbuf, msg_last);
1663                 CP(msqbuf32, msqbuf, msg_cbytes);
1664                 CP(msqbuf32, msqbuf, msg_qnum);
1665                 CP(msqbuf32, msqbuf, msg_qbytes);
1666                 CP(msqbuf32, msqbuf, msg_lspid);
1667                 CP(msqbuf32, msqbuf, msg_lrpid);
1668                 CP(msqbuf32, msqbuf, msg_stime);
1669                 CP(msqbuf32, msqbuf, msg_rtime);
1670                 CP(msqbuf32, msqbuf, msg_ctime);
1671         }
1672         error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1673         if (error)
1674                 return (error);
1675         if (uap->cmd == IPC_STAT) {
1676                 bzero(&msqbuf32, sizeof(msqbuf32));
1677                 freebsd32_ipcperm_old_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1678                 PTROUT_CP(msqbuf, msqbuf32, msg_first);
1679                 PTROUT_CP(msqbuf, msqbuf32, msg_last);
1680                 CP(msqbuf, msqbuf32, msg_cbytes);
1681                 CP(msqbuf, msqbuf32, msg_qnum);
1682                 CP(msqbuf, msqbuf32, msg_qbytes);
1683                 CP(msqbuf, msqbuf32, msg_lspid);
1684                 CP(msqbuf, msqbuf32, msg_lrpid);
1685                 CP(msqbuf, msqbuf32, msg_stime);
1686                 CP(msqbuf, msqbuf32, msg_rtime);
1687                 CP(msqbuf, msqbuf32, msg_ctime);
1688                 error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
1689         }
1690         return (error);
1691 }
1692 #endif
1693
1694 int
1695 freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap)
1696 {
1697         struct msqid_ds msqbuf;
1698         struct msqid_ds32 msqbuf32;
1699         int error;
1700
1701         if (uap->cmd == IPC_SET) {
1702                 error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
1703                 if (error)
1704                         return (error);
1705                 freebsd32_ipcperm_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1706                 PTRIN_CP(msqbuf32, msqbuf, msg_first);
1707                 PTRIN_CP(msqbuf32, msqbuf, msg_last);
1708                 CP(msqbuf32, msqbuf, msg_cbytes);
1709                 CP(msqbuf32, msqbuf, msg_qnum);
1710                 CP(msqbuf32, msqbuf, msg_qbytes);
1711                 CP(msqbuf32, msqbuf, msg_lspid);
1712                 CP(msqbuf32, msqbuf, msg_lrpid);
1713                 CP(msqbuf32, msqbuf, msg_stime);
1714                 CP(msqbuf32, msqbuf, msg_rtime);
1715                 CP(msqbuf32, msqbuf, msg_ctime);
1716         }
1717         error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1718         if (error)
1719                 return (error);
1720         if (uap->cmd == IPC_STAT) {
1721                 freebsd32_ipcperm_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1722                 PTROUT_CP(msqbuf, msqbuf32, msg_first);
1723                 PTROUT_CP(msqbuf, msqbuf32, msg_last);
1724                 CP(msqbuf, msqbuf32, msg_cbytes);
1725                 CP(msqbuf, msqbuf32, msg_qnum);
1726                 CP(msqbuf, msqbuf32, msg_qbytes);
1727                 CP(msqbuf, msqbuf32, msg_lspid);
1728                 CP(msqbuf, msqbuf32, msg_lrpid);
1729                 CP(msqbuf, msqbuf32, msg_stime);
1730                 CP(msqbuf, msqbuf32, msg_rtime);
1731                 CP(msqbuf, msqbuf32, msg_ctime);
1732                 error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
1733         }
1734         return (error);
1735 }
1736
1737 int
1738 freebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap)
1739 {
1740         const void *msgp;
1741         long mtype;
1742         int32_t mtype32;
1743         int error;
1744
1745         msgp = PTRIN(uap->msgp);
1746         if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0)
1747                 return (error);
1748         mtype = mtype32;
1749         return (kern_msgsnd(td, uap->msqid,
1750             (const char *)msgp + sizeof(mtype32),
1751             uap->msgsz, uap->msgflg, mtype));
1752 }
1753
1754 int
1755 freebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap)
1756 {
1757         void *msgp;
1758         long mtype;
1759         int32_t mtype32;
1760         int error;
1761
1762         msgp = PTRIN(uap->msgp);
1763         if ((error = kern_msgrcv(td, uap->msqid,
1764             (char *)msgp + sizeof(mtype32), uap->msgsz,
1765             uap->msgtyp, uap->msgflg, &mtype)) != 0)
1766                 return (error);
1767         mtype32 = (int32_t)mtype;
1768         return (copyout(&mtype32, msgp, sizeof(mtype32)));
1769 }
1770
1771 int
1772 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
1773 {
1774
1775 #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1776     defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1777         switch (uap->which) {
1778         case 0: {       /* shmat */
1779                 struct shmat_args ap;
1780
1781                 ap.shmid = uap->a2;
1782                 ap.shmaddr = PTRIN(uap->a3);
1783                 ap.shmflg = uap->a4;
1784                 return (sysent[SYS_shmat].sy_call(td, &ap));
1785         }
1786         case 2: {       /* shmdt */
1787                 struct shmdt_args ap;
1788
1789                 ap.shmaddr = PTRIN(uap->a2);
1790                 return (sysent[SYS_shmdt].sy_call(td, &ap));
1791         }
1792         case 3: {       /* shmget */
1793                 struct shmget_args ap;
1794
1795                 ap.key = uap->a2;
1796                 ap.size = uap->a3;
1797                 ap.shmflg = uap->a4;
1798                 return (sysent[SYS_shmget].sy_call(td, &ap));
1799         }
1800         case 4: {       /* shmctl */
1801                 struct freebsd7_freebsd32_shmctl_args ap;
1802
1803                 ap.shmid = uap->a2;
1804                 ap.cmd = uap->a3;
1805                 ap.buf = PTRIN(uap->a4);
1806                 return (freebsd7_freebsd32_shmctl(td, &ap));
1807         }
1808         case 1:         /* oshmctl */
1809         default:
1810                 return (EINVAL);
1811         }
1812 #else
1813         return (nosys(td, NULL));
1814 #endif
1815 }
1816
1817 #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1818     defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1819 int
1820 freebsd7_freebsd32_shmctl(struct thread *td,
1821     struct freebsd7_freebsd32_shmctl_args *uap)
1822 {
1823         int error = 0;
1824         union {
1825                 struct shmid_ds shmid_ds;
1826                 struct shm_info shm_info;
1827                 struct shminfo shminfo;
1828         } u;
1829         union {
1830                 struct shmid_ds32_old shmid_ds32;
1831                 struct shm_info32 shm_info32;
1832                 struct shminfo32 shminfo32;
1833         } u32;
1834         size_t sz;
1835
1836         if (uap->cmd == IPC_SET) {
1837                 if ((error = copyin(uap->buf, &u32.shmid_ds32,
1838                     sizeof(u32.shmid_ds32))))
1839                         goto done;
1840                 freebsd32_ipcperm_old_in(&u32.shmid_ds32.shm_perm,
1841                     &u.shmid_ds.shm_perm);
1842                 CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1843                 CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1844                 CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1845                 CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1846                 CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1847                 CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1848                 CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1849         }
1850         
1851         error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1852         if (error)
1853                 goto done;
1854         
1855         /* Cases in which we need to copyout */
1856         switch (uap->cmd) {
1857         case IPC_INFO:
1858                 CP(u.shminfo, u32.shminfo32, shmmax);
1859                 CP(u.shminfo, u32.shminfo32, shmmin);
1860                 CP(u.shminfo, u32.shminfo32, shmmni);
1861                 CP(u.shminfo, u32.shminfo32, shmseg);
1862                 CP(u.shminfo, u32.shminfo32, shmall);
1863                 error = copyout(&u32.shminfo32, uap->buf,
1864                     sizeof(u32.shminfo32));
1865                 break;
1866         case SHM_INFO:
1867                 CP(u.shm_info, u32.shm_info32, used_ids);
1868                 CP(u.shm_info, u32.shm_info32, shm_rss);
1869                 CP(u.shm_info, u32.shm_info32, shm_tot);
1870                 CP(u.shm_info, u32.shm_info32, shm_swp);
1871                 CP(u.shm_info, u32.shm_info32, swap_attempts);
1872                 CP(u.shm_info, u32.shm_info32, swap_successes);
1873                 error = copyout(&u32.shm_info32, uap->buf,
1874                     sizeof(u32.shm_info32));
1875                 break;
1876         case SHM_STAT:
1877         case IPC_STAT:
1878                 freebsd32_ipcperm_old_out(&u.shmid_ds.shm_perm,
1879                     &u32.shmid_ds32.shm_perm);
1880                 if (u.shmid_ds.shm_segsz > INT32_MAX)
1881                         u32.shmid_ds32.shm_segsz = INT32_MAX;
1882                 else
1883                         CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1884                 CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1885                 CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1886                 CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1887                 CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1888                 CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1889                 CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1890                 u32.shmid_ds32.shm_internal = 0;
1891                 error = copyout(&u32.shmid_ds32, uap->buf,
1892                     sizeof(u32.shmid_ds32));
1893                 break;
1894         }
1895
1896 done:
1897         if (error) {
1898                 /* Invalidate the return value */
1899                 td->td_retval[0] = -1;
1900         }
1901         return (error);
1902 }
1903 #endif
1904
1905 int
1906 freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
1907 {
1908         int error = 0;
1909         union {
1910                 struct shmid_ds shmid_ds;
1911                 struct shm_info shm_info;
1912                 struct shminfo shminfo;
1913         } u;
1914         union {
1915                 struct shmid_ds32 shmid_ds32;
1916                 struct shm_info32 shm_info32;
1917                 struct shminfo32 shminfo32;
1918         } u32;
1919         size_t sz;
1920         
1921         if (uap->cmd == IPC_SET) {
1922                 if ((error = copyin(uap->buf, &u32.shmid_ds32,
1923                     sizeof(u32.shmid_ds32))))
1924                         goto done;
1925                 freebsd32_ipcperm_in(&u32.shmid_ds32.shm_perm,
1926                     &u.shmid_ds.shm_perm);
1927                 CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
1928                 CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
1929                 CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
1930                 CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
1931                 CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
1932                 CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
1933                 CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
1934         }
1935         
1936         error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
1937         if (error)
1938                 goto done;
1939         
1940         /* Cases in which we need to copyout */
1941         switch (uap->cmd) {
1942         case IPC_INFO:
1943                 CP(u.shminfo, u32.shminfo32, shmmax);
1944                 CP(u.shminfo, u32.shminfo32, shmmin);
1945                 CP(u.shminfo, u32.shminfo32, shmmni);
1946                 CP(u.shminfo, u32.shminfo32, shmseg);
1947                 CP(u.shminfo, u32.shminfo32, shmall);
1948                 error = copyout(&u32.shminfo32, uap->buf,
1949                     sizeof(u32.shminfo32));
1950                 break;
1951         case SHM_INFO:
1952                 CP(u.shm_info, u32.shm_info32, used_ids);
1953                 CP(u.shm_info, u32.shm_info32, shm_rss);
1954                 CP(u.shm_info, u32.shm_info32, shm_tot);
1955                 CP(u.shm_info, u32.shm_info32, shm_swp);
1956                 CP(u.shm_info, u32.shm_info32, swap_attempts);
1957                 CP(u.shm_info, u32.shm_info32, swap_successes);
1958                 error = copyout(&u32.shm_info32, uap->buf,
1959                     sizeof(u32.shm_info32));
1960                 break;
1961         case SHM_STAT:
1962         case IPC_STAT:
1963                 freebsd32_ipcperm_out(&u.shmid_ds.shm_perm,
1964                     &u32.shmid_ds32.shm_perm);
1965                 if (u.shmid_ds.shm_segsz > INT32_MAX)
1966                         u32.shmid_ds32.shm_segsz = INT32_MAX;
1967                 else
1968                         CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
1969                 CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
1970                 CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
1971                 CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
1972                 CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
1973                 CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
1974                 CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
1975                 error = copyout(&u32.shmid_ds32, uap->buf,
1976                     sizeof(u32.shmid_ds32));
1977                 break;
1978         }
1979
1980 done:
1981         if (error) {
1982                 /* Invalidate the return value */
1983                 td->td_retval[0] = -1;
1984         }
1985         return (error);
1986 }
1987
1988 int
1989 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
1990 {
1991         struct pread_args ap;
1992
1993         ap.fd = uap->fd;
1994         ap.buf = uap->buf;
1995         ap.nbyte = uap->nbyte;
1996         ap.offset = PAIR32TO64(off_t,uap->offset);
1997         return (pread(td, &ap));
1998 }
1999
2000 int
2001 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
2002 {
2003         struct pwrite_args ap;
2004
2005         ap.fd = uap->fd;
2006         ap.buf = uap->buf;
2007         ap.nbyte = uap->nbyte;
2008         ap.offset = PAIR32TO64(off_t,uap->offset);
2009         return (pwrite(td, &ap));
2010 }
2011
2012 int
2013 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
2014 {
2015         int error;
2016         struct lseek_args ap;
2017         off_t pos;
2018
2019         ap.fd = uap->fd;
2020         ap.offset = PAIR32TO64(off_t,uap->offset);
2021         ap.whence = uap->whence;
2022         error = lseek(td, &ap);
2023         /* Expand the quad return into two parts for eax and edx */
2024         pos = *(off_t *)(td->td_retval);
2025         td->td_retval[RETVAL_LO] = pos & 0xffffffff;    /* %eax */
2026         td->td_retval[RETVAL_HI] = pos >> 32;           /* %edx */
2027         return error;
2028 }
2029
2030 int
2031 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
2032 {
2033         struct truncate_args ap;
2034
2035         ap.path = uap->path;
2036         ap.length = PAIR32TO64(off_t,uap->length);
2037         return (truncate(td, &ap));
2038 }
2039
2040 int
2041 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
2042 {
2043         struct ftruncate_args ap;
2044
2045         ap.fd = uap->fd;
2046         ap.length = PAIR32TO64(off_t,uap->length);
2047         return (ftruncate(td, &ap));
2048 }
2049
2050 int
2051 freebsd32_getdirentries(struct thread *td,
2052     struct freebsd32_getdirentries_args *uap)
2053 {
2054         long base;
2055         int32_t base32;
2056         int error;
2057
2058         error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base);
2059         if (error)
2060                 return (error);
2061         if (uap->basep != NULL) {
2062                 base32 = base;
2063                 error = copyout(&base32, uap->basep, sizeof(int32_t));
2064         }
2065         return (error);
2066 }
2067
2068 #ifdef COMPAT_FREEBSD6
2069 /* versions with the 'int pad' argument */
2070 int
2071 freebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)
2072 {
2073         struct pread_args ap;
2074
2075         ap.fd = uap->fd;
2076         ap.buf = uap->buf;
2077         ap.nbyte = uap->nbyte;
2078         ap.offset = PAIR32TO64(off_t,uap->offset);
2079         return (pread(td, &ap));
2080 }
2081
2082 int
2083 freebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)
2084 {
2085         struct pwrite_args ap;
2086
2087         ap.fd = uap->fd;
2088         ap.buf = uap->buf;
2089         ap.nbyte = uap->nbyte;
2090         ap.offset = PAIR32TO64(off_t,uap->offset);
2091         return (pwrite(td, &ap));
2092 }
2093
2094 int
2095 freebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)
2096 {
2097         int error;
2098         struct lseek_args ap;
2099         off_t pos;
2100
2101         ap.fd = uap->fd;
2102         ap.offset = PAIR32TO64(off_t,uap->offset);
2103         ap.whence = uap->whence;
2104         error = lseek(td, &ap);
2105         /* Expand the quad return into two parts for eax and edx */
2106         pos = *(off_t *)(td->td_retval);
2107         td->td_retval[RETVAL_LO] = pos & 0xffffffff;    /* %eax */
2108         td->td_retval[RETVAL_HI] = pos >> 32;           /* %edx */
2109         return error;
2110 }
2111
2112 int
2113 freebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)
2114 {
2115         struct truncate_args ap;
2116
2117         ap.path = uap->path;
2118         ap.length = PAIR32TO64(off_t,uap->length);
2119         return (truncate(td, &ap));
2120 }
2121
2122 int
2123 freebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)
2124 {
2125         struct ftruncate_args ap;
2126
2127         ap.fd = uap->fd;
2128         ap.length = PAIR32TO64(off_t,uap->length);
2129         return (ftruncate(td, &ap));
2130 }
2131 #endif /* COMPAT_FREEBSD6 */
2132
2133 struct sf_hdtr32 {
2134         uint32_t headers;
2135         int hdr_cnt;
2136         uint32_t trailers;
2137         int trl_cnt;
2138 };
2139
2140 static int
2141 freebsd32_do_sendfile(struct thread *td,
2142     struct freebsd32_sendfile_args *uap, int compat)
2143 {
2144         struct sendfile_args ap;
2145         struct sf_hdtr32 hdtr32;
2146         struct sf_hdtr hdtr;
2147         struct uio *hdr_uio, *trl_uio;
2148         struct iovec32 *iov32;
2149         int error;
2150
2151         hdr_uio = trl_uio = NULL;
2152
2153         ap.fd = uap->fd;
2154         ap.s = uap->s;
2155         ap.offset = PAIR32TO64(off_t,uap->offset);
2156         ap.nbytes = uap->nbytes;
2157         ap.hdtr = (struct sf_hdtr *)uap->hdtr;          /* XXX not used */
2158         ap.sbytes = uap->sbytes;
2159         ap.flags = uap->flags;
2160
2161         if (uap->hdtr != NULL) {
2162                 error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
2163                 if (error)
2164                         goto out;
2165                 PTRIN_CP(hdtr32, hdtr, headers);
2166                 CP(hdtr32, hdtr, hdr_cnt);
2167                 PTRIN_CP(hdtr32, hdtr, trailers);
2168                 CP(hdtr32, hdtr, trl_cnt);
2169
2170                 if (hdtr.headers != NULL) {
2171                         iov32 = PTRIN(hdtr32.headers);
2172                         error = freebsd32_copyinuio(iov32,
2173                             hdtr32.hdr_cnt, &hdr_uio);
2174                         if (error)
2175                                 goto out;
2176                 }
2177                 if (hdtr.trailers != NULL) {
2178                         iov32 = PTRIN(hdtr32.trailers);
2179                         error = freebsd32_copyinuio(iov32,
2180                             hdtr32.trl_cnt, &trl_uio);
2181                         if (error)
2182                                 goto out;
2183                 }
2184         }
2185
2186         error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
2187 out:
2188         if (hdr_uio)
2189                 free(hdr_uio, M_IOV);
2190         if (trl_uio)
2191                 free(trl_uio, M_IOV);
2192         return (error);
2193 }
2194
2195 #ifdef COMPAT_FREEBSD4
2196 int
2197 freebsd4_freebsd32_sendfile(struct thread *td,
2198     struct freebsd4_freebsd32_sendfile_args *uap)
2199 {
2200         return (freebsd32_do_sendfile(td,
2201             (struct freebsd32_sendfile_args *)uap, 1));
2202 }
2203 #endif
2204
2205 int
2206 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
2207 {
2208
2209         return (freebsd32_do_sendfile(td, uap, 0));
2210 }
2211
2212 static void
2213 copy_stat( struct stat *in, struct stat32 *out)
2214 {
2215         CP(*in, *out, st_dev);
2216         CP(*in, *out, st_ino);
2217         CP(*in, *out, st_mode);
2218         CP(*in, *out, st_nlink);
2219         CP(*in, *out, st_uid);
2220         CP(*in, *out, st_gid);
2221         CP(*in, *out, st_rdev);
2222         TS_CP(*in, *out, st_atimespec);
2223         TS_CP(*in, *out, st_mtimespec);
2224         TS_CP(*in, *out, st_ctimespec);
2225         CP(*in, *out, st_size);
2226         CP(*in, *out, st_blocks);
2227         CP(*in, *out, st_blksize);
2228         CP(*in, *out, st_flags);
2229         CP(*in, *out, st_gen);
2230 }
2231
2232 int
2233 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
2234 {
2235         struct stat sb;
2236         struct stat32 sb32;
2237         int error;
2238
2239         error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2240         if (error)
2241                 return (error);
2242         copy_stat(&sb, &sb32);
2243         error = copyout(&sb32, uap->ub, sizeof (sb32));
2244         return (error);
2245 }
2246
2247 int
2248 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
2249 {
2250         struct stat ub;
2251         struct stat32 ub32;
2252         int error;
2253
2254         error = kern_fstat(td, uap->fd, &ub);
2255         if (error)
2256                 return (error);
2257         copy_stat(&ub, &ub32);
2258         error = copyout(&ub32, uap->ub, sizeof(ub32));
2259         return (error);
2260 }
2261
2262 int
2263 freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
2264 {
2265         struct stat ub;
2266         struct stat32 ub32;
2267         int error;
2268
2269         error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, &ub);
2270         if (error)
2271                 return (error);
2272         copy_stat(&ub, &ub32);
2273         error = copyout(&ub32, uap->buf, sizeof(ub32));
2274         return (error);
2275 }
2276
2277 int
2278 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
2279 {
2280         struct stat sb;
2281         struct stat32 sb32;
2282         int error;
2283
2284         error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2285         if (error)
2286                 return (error);
2287         copy_stat(&sb, &sb32);
2288         error = copyout(&sb32, uap->ub, sizeof (sb32));
2289         return (error);
2290 }
2291
2292 /*
2293  * MPSAFE
2294  */
2295 int
2296 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
2297 {
2298         int error, name[CTL_MAXNAME];
2299         size_t j, oldlen;
2300
2301         if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
2302                 return (EINVAL);
2303         error = copyin(uap->name, name, uap->namelen * sizeof(int));
2304         if (error)
2305                 return (error);
2306         if (uap->oldlenp)
2307                 oldlen = fuword32(uap->oldlenp);
2308         else
2309                 oldlen = 0;
2310         error = userland_sysctl(td, name, uap->namelen,
2311                 uap->old, &oldlen, 1,
2312                 uap->new, uap->newlen, &j, SCTL_MASK32);
2313         if (error && error != ENOMEM)
2314                 return (error);
2315         if (uap->oldlenp)
2316                 suword32(uap->oldlenp, j);
2317         return (0);
2318 }
2319
2320 int
2321 freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
2322 {
2323         uint32_t version;
2324         int error;
2325         struct jail j;
2326
2327         error = copyin(uap->jail, &version, sizeof(uint32_t));
2328         if (error)
2329                 return (error);
2330
2331         switch (version) {
2332         case 0:
2333         {
2334                 /* FreeBSD single IPv4 jails. */
2335                 struct jail32_v0 j32_v0;
2336
2337                 bzero(&j, sizeof(struct jail));
2338                 error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));
2339                 if (error)
2340                         return (error);
2341                 CP(j32_v0, j, version);
2342                 PTRIN_CP(j32_v0, j, path);
2343                 PTRIN_CP(j32_v0, j, hostname);
2344                 j.ip4s = j32_v0.ip_number;
2345                 break;
2346         }
2347
2348         case 1:
2349                 /*
2350                  * Version 1 was used by multi-IPv4 jail implementations
2351                  * that never made it into the official kernel.
2352                  */
2353                 return (EINVAL);
2354
2355         case 2: /* JAIL_API_VERSION */
2356         {
2357                 /* FreeBSD multi-IPv4/IPv6,noIP jails. */
2358                 struct jail32 j32;
2359
2360                 error = copyin(uap->jail, &j32, sizeof(struct jail32));
2361                 if (error)
2362                         return (error);
2363                 CP(j32, j, version);
2364                 PTRIN_CP(j32, j, path);
2365                 PTRIN_CP(j32, j, hostname);
2366                 PTRIN_CP(j32, j, jailname);
2367                 CP(j32, j, ip4s);
2368                 CP(j32, j, ip6s);
2369                 PTRIN_CP(j32, j, ip4);
2370                 PTRIN_CP(j32, j, ip6);
2371                 break;
2372         }
2373
2374         default:
2375                 /* Sci-Fi jails are not supported, sorry. */
2376                 return (EINVAL);
2377         }
2378         return (kern_jail(td, &j));
2379 }
2380
2381 int
2382 freebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
2383 {
2384         struct uio *auio;
2385         int error;
2386
2387         /* Check that we have an even number of iovecs. */
2388         if (uap->iovcnt & 1)
2389                 return (EINVAL);
2390
2391         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2392         if (error)
2393                 return (error);
2394         error = kern_jail_set(td, auio, uap->flags);
2395         free(auio, M_IOV);
2396         return (error);
2397 }
2398
2399 int
2400 freebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
2401 {
2402         struct iovec32 iov32;
2403         struct uio *auio;
2404         int error, i;
2405
2406         /* Check that we have an even number of iovecs. */
2407         if (uap->iovcnt & 1)
2408                 return (EINVAL);
2409
2410         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2411         if (error)
2412                 return (error);
2413         error = kern_jail_get(td, auio, uap->flags);
2414         if (error == 0)
2415                 for (i = 0; i < uap->iovcnt; i++) {
2416                         PTROUT_CP(auio->uio_iov[i], iov32, iov_base);
2417                         CP(auio->uio_iov[i], iov32, iov_len);
2418                         error = copyout(&iov32, uap->iovp + i, sizeof(iov32));
2419                         if (error != 0)
2420                                 break;
2421                 }
2422         free(auio, M_IOV);
2423         return (error);
2424 }
2425
2426 int
2427 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
2428 {
2429         struct sigaction32 s32;
2430         struct sigaction sa, osa, *sap;
2431         int error;
2432
2433         if (uap->act) {
2434                 error = copyin(uap->act, &s32, sizeof(s32));
2435                 if (error)
2436                         return (error);
2437                 sa.sa_handler = PTRIN(s32.sa_u);
2438                 CP(s32, sa, sa_flags);
2439                 CP(s32, sa, sa_mask);
2440                 sap = &sa;
2441         } else
2442                 sap = NULL;
2443         error = kern_sigaction(td, uap->sig, sap, &osa, 0);
2444         if (error == 0 && uap->oact != NULL) {
2445                 s32.sa_u = PTROUT(osa.sa_handler);
2446                 CP(osa, s32, sa_flags);
2447                 CP(osa, s32, sa_mask);
2448                 error = copyout(&s32, uap->oact, sizeof(s32));
2449         }
2450         return (error);
2451 }
2452
2453 #ifdef COMPAT_FREEBSD4
2454 int
2455 freebsd4_freebsd32_sigaction(struct thread *td,
2456                              struct freebsd4_freebsd32_sigaction_args *uap)
2457 {
2458         struct sigaction32 s32;
2459         struct sigaction sa, osa, *sap;
2460         int error;
2461
2462         if (uap->act) {
2463                 error = copyin(uap->act, &s32, sizeof(s32));
2464                 if (error)
2465                         return (error);
2466                 sa.sa_handler = PTRIN(s32.sa_u);
2467                 CP(s32, sa, sa_flags);
2468                 CP(s32, sa, sa_mask);
2469                 sap = &sa;
2470         } else
2471                 sap = NULL;
2472         error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
2473         if (error == 0 && uap->oact != NULL) {
2474                 s32.sa_u = PTROUT(osa.sa_handler);
2475                 CP(osa, s32, sa_flags);
2476                 CP(osa, s32, sa_mask);
2477                 error = copyout(&s32, uap->oact, sizeof(s32));
2478         }
2479         return (error);
2480 }
2481 #endif
2482
2483 #ifdef COMPAT_43
2484 struct osigaction32 {
2485         u_int32_t       sa_u;
2486         osigset_t       sa_mask;
2487         int             sa_flags;
2488 };
2489
2490 #define ONSIG   32
2491
2492 int
2493 ofreebsd32_sigaction(struct thread *td,
2494                              struct ofreebsd32_sigaction_args *uap)
2495 {
2496         struct osigaction32 s32;
2497         struct sigaction sa, osa, *sap;
2498         int error;
2499
2500         if (uap->signum <= 0 || uap->signum >= ONSIG)
2501                 return (EINVAL);
2502
2503         if (uap->nsa) {
2504                 error = copyin(uap->nsa, &s32, sizeof(s32));
2505                 if (error)
2506                         return (error);
2507                 sa.sa_handler = PTRIN(s32.sa_u);
2508                 CP(s32, sa, sa_flags);
2509                 OSIG2SIG(s32.sa_mask, sa.sa_mask);
2510                 sap = &sa;
2511         } else
2512                 sap = NULL;
2513         error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2514         if (error == 0 && uap->osa != NULL) {
2515                 s32.sa_u = PTROUT(osa.sa_handler);
2516                 CP(osa, s32, sa_flags);
2517                 SIG2OSIG(osa.sa_mask, s32.sa_mask);
2518                 error = copyout(&s32, uap->osa, sizeof(s32));
2519         }
2520         return (error);
2521 }
2522
2523 int
2524 ofreebsd32_sigprocmask(struct thread *td,
2525                                struct ofreebsd32_sigprocmask_args *uap)
2526 {
2527         sigset_t set, oset;
2528         int error;
2529
2530         OSIG2SIG(uap->mask, set);
2531         error = kern_sigprocmask(td, uap->how, &set, &oset, SIGPROCMASK_OLD);
2532         SIG2OSIG(oset, td->td_retval[0]);
2533         return (error);
2534 }
2535
2536 int
2537 ofreebsd32_sigpending(struct thread *td,
2538                               struct ofreebsd32_sigpending_args *uap)
2539 {
2540         struct proc *p = td->td_proc;
2541         sigset_t siglist;
2542
2543         PROC_LOCK(p);
2544         siglist = p->p_siglist;
2545         SIGSETOR(siglist, td->td_siglist);
2546         PROC_UNLOCK(p);
2547         SIG2OSIG(siglist, td->td_retval[0]);
2548         return (0);
2549 }
2550
2551 struct sigvec32 {
2552         u_int32_t       sv_handler;
2553         int             sv_mask;
2554         int             sv_flags;
2555 };
2556
2557 int
2558 ofreebsd32_sigvec(struct thread *td,
2559                           struct ofreebsd32_sigvec_args *uap)
2560 {
2561         struct sigvec32 vec;
2562         struct sigaction sa, osa, *sap;
2563         int error;
2564
2565         if (uap->signum <= 0 || uap->signum >= ONSIG)
2566                 return (EINVAL);
2567
2568         if (uap->nsv) {
2569                 error = copyin(uap->nsv, &vec, sizeof(vec));
2570                 if (error)
2571                         return (error);
2572                 sa.sa_handler = PTRIN(vec.sv_handler);
2573                 OSIG2SIG(vec.sv_mask, sa.sa_mask);
2574                 sa.sa_flags = vec.sv_flags;
2575                 sa.sa_flags ^= SA_RESTART;
2576                 sap = &sa;
2577         } else
2578                 sap = NULL;
2579         error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
2580         if (error == 0 && uap->osv != NULL) {
2581                 vec.sv_handler = PTROUT(osa.sa_handler);
2582                 SIG2OSIG(osa.sa_mask, vec.sv_mask);
2583                 vec.sv_flags = osa.sa_flags;
2584                 vec.sv_flags &= ~SA_NOCLDWAIT;
2585                 vec.sv_flags ^= SA_RESTART;
2586                 error = copyout(&vec, uap->osv, sizeof(vec));
2587         }
2588         return (error);
2589 }
2590
2591 int
2592 ofreebsd32_sigblock(struct thread *td,
2593                             struct ofreebsd32_sigblock_args *uap)
2594 {
2595         sigset_t set, oset;
2596
2597         OSIG2SIG(uap->mask, set);
2598         kern_sigprocmask(td, SIG_BLOCK, &set, &oset, 0);
2599         SIG2OSIG(oset, td->td_retval[0]);
2600         return (0);
2601 }
2602
2603 int
2604 ofreebsd32_sigsetmask(struct thread *td,
2605                               struct ofreebsd32_sigsetmask_args *uap)
2606 {
2607         sigset_t set, oset;
2608
2609         OSIG2SIG(uap->mask, set);
2610         kern_sigprocmask(td, SIG_SETMASK, &set, &oset, 0);
2611         SIG2OSIG(oset, td->td_retval[0]);
2612         return (0);
2613 }
2614
2615 int
2616 ofreebsd32_sigsuspend(struct thread *td,
2617                               struct ofreebsd32_sigsuspend_args *uap)
2618 {
2619         sigset_t mask;
2620
2621         OSIG2SIG(uap->mask, mask);
2622         return (kern_sigsuspend(td, mask));
2623 }
2624
2625 struct sigstack32 {
2626         u_int32_t       ss_sp;
2627         int             ss_onstack;
2628 };
2629
2630 int
2631 ofreebsd32_sigstack(struct thread *td,
2632                             struct ofreebsd32_sigstack_args *uap)
2633 {
2634         struct sigstack32 s32;
2635         struct sigstack nss, oss;
2636         int error = 0, unss;
2637
2638         if (uap->nss != NULL) {
2639                 error = copyin(uap->nss, &s32, sizeof(s32));
2640                 if (error)
2641                         return (error);
2642                 nss.ss_sp = PTRIN(s32.ss_sp);
2643                 CP(s32, nss, ss_onstack);
2644                 unss = 1;
2645         } else {
2646                 unss = 0;
2647         }
2648         oss.ss_sp = td->td_sigstk.ss_sp;
2649         oss.ss_onstack = sigonstack(cpu_getstack(td));
2650         if (unss) {
2651                 td->td_sigstk.ss_sp = nss.ss_sp;
2652                 td->td_sigstk.ss_size = 0;
2653                 td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);
2654                 td->td_pflags |= TDP_ALTSTACK;
2655         }
2656         if (uap->oss != NULL) {
2657                 s32.ss_sp = PTROUT(oss.ss_sp);
2658                 CP(oss, s32, ss_onstack);
2659                 error = copyout(&s32, uap->oss, sizeof(s32));
2660         }
2661         return (error);
2662 }
2663 #endif
2664
2665 int
2666 freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
2667 {
2668         struct timespec32 rmt32, rqt32;
2669         struct timespec rmt, rqt;
2670         int error;
2671
2672         error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
2673         if (error)
2674                 return (error);
2675
2676         CP(rqt32, rqt, tv_sec);
2677         CP(rqt32, rqt, tv_nsec);
2678
2679         if (uap->rmtp &&
2680             !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
2681                 return (EFAULT);
2682         error = kern_nanosleep(td, &rqt, &rmt);
2683         if (error && uap->rmtp) {
2684                 int error2;
2685
2686                 CP(rmt, rmt32, tv_sec);
2687                 CP(rmt, rmt32, tv_nsec);
2688
2689                 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
2690                 if (error2)
2691                         error = error2;
2692         }
2693         return (error);
2694 }
2695
2696 int
2697 freebsd32_clock_gettime(struct thread *td,
2698                         struct freebsd32_clock_gettime_args *uap)
2699 {
2700         struct timespec ats;
2701         struct timespec32 ats32;
2702         int error;
2703
2704         error = kern_clock_gettime(td, uap->clock_id, &ats);
2705         if (error == 0) {
2706                 CP(ats, ats32, tv_sec);
2707                 CP(ats, ats32, tv_nsec);
2708                 error = copyout(&ats32, uap->tp, sizeof(ats32));
2709         }
2710         return (error);
2711 }
2712
2713 int
2714 freebsd32_clock_settime(struct thread *td,
2715                         struct freebsd32_clock_settime_args *uap)
2716 {
2717         struct timespec ats;
2718         struct timespec32 ats32;
2719         int error;
2720
2721         error = copyin(uap->tp, &ats32, sizeof(ats32));
2722         if (error)
2723                 return (error);
2724         CP(ats32, ats, tv_sec);
2725         CP(ats32, ats, tv_nsec);
2726
2727         return (kern_clock_settime(td, uap->clock_id, &ats));
2728 }
2729
2730 int
2731 freebsd32_clock_getres(struct thread *td,
2732                        struct freebsd32_clock_getres_args *uap)
2733 {
2734         struct timespec ts;
2735         struct timespec32 ts32;
2736         int error;
2737
2738         if (uap->tp == NULL)
2739                 return (0);
2740         error = kern_clock_getres(td, uap->clock_id, &ts);
2741         if (error == 0) {
2742                 CP(ts, ts32, tv_sec);
2743                 CP(ts, ts32, tv_nsec);
2744                 error = copyout(&ts32, uap->tp, sizeof(ts32));
2745         }
2746         return (error);
2747 }
2748
2749 int
2750 freebsd32_thr_new(struct thread *td,
2751                   struct freebsd32_thr_new_args *uap)
2752 {
2753         struct thr_param32 param32;
2754         struct thr_param param;
2755         int error;
2756
2757         if (uap->param_size < 0 ||
2758             uap->param_size > sizeof(struct thr_param32))
2759                 return (EINVAL);
2760         bzero(&param, sizeof(struct thr_param));
2761         bzero(&param32, sizeof(struct thr_param32));
2762         error = copyin(uap->param, &param32, uap->param_size);
2763         if (error != 0)
2764                 return (error);
2765         param.start_func = PTRIN(param32.start_func);
2766         param.arg = PTRIN(param32.arg);
2767         param.stack_base = PTRIN(param32.stack_base);
2768         param.stack_size = param32.stack_size;
2769         param.tls_base = PTRIN(param32.tls_base);
2770         param.tls_size = param32.tls_size;
2771         param.child_tid = PTRIN(param32.child_tid);
2772         param.parent_tid = PTRIN(param32.parent_tid);
2773         param.flags = param32.flags;
2774         param.rtp = PTRIN(param32.rtp);
2775         param.spare[0] = PTRIN(param32.spare[0]);
2776         param.spare[1] = PTRIN(param32.spare[1]);
2777         param.spare[2] = PTRIN(param32.spare[2]);
2778
2779         return (kern_thr_new(td, &param));
2780 }
2781
2782 int
2783 freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
2784 {
2785         struct timespec32 ts32;
2786         struct timespec ts, *tsp;
2787         int error;
2788
2789         error = 0;
2790         tsp = NULL;
2791         if (uap->timeout != NULL) {
2792                 error = copyin((const void *)uap->timeout, (void *)&ts32,
2793                     sizeof(struct timespec32));
2794                 if (error != 0)
2795                         return (error);
2796                 ts.tv_sec = ts32.tv_sec;
2797                 ts.tv_nsec = ts32.tv_nsec;
2798                 tsp = &ts;
2799         }
2800         return (kern_thr_suspend(td, tsp));
2801 }
2802
2803 void
2804 siginfo_to_siginfo32(siginfo_t *src, struct siginfo32 *dst)
2805 {
2806         bzero(dst, sizeof(*dst));
2807         dst->si_signo = src->si_signo;
2808         dst->si_errno = src->si_errno;
2809         dst->si_code = src->si_code;
2810         dst->si_pid = src->si_pid;
2811         dst->si_uid = src->si_uid;
2812         dst->si_status = src->si_status;
2813         dst->si_addr = (uintptr_t)src->si_addr;
2814         dst->si_value.sigval_int = src->si_value.sival_int;
2815         dst->si_timerid = src->si_timerid;
2816         dst->si_overrun = src->si_overrun;
2817 }
2818
2819 int
2820 freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
2821 {
2822         struct timespec32 ts32;
2823         struct timespec ts;
2824         struct timespec *timeout;
2825         sigset_t set;
2826         ksiginfo_t ksi;
2827         struct siginfo32 si32;
2828         int error;
2829
2830         if (uap->timeout) {
2831                 error = copyin(uap->timeout, &ts32, sizeof(ts32));
2832                 if (error)
2833                         return (error);
2834                 ts.tv_sec = ts32.tv_sec;
2835                 ts.tv_nsec = ts32.tv_nsec;
2836                 timeout = &ts;
2837         } else
2838                 timeout = NULL;
2839
2840         error = copyin(uap->set, &set, sizeof(set));
2841         if (error)
2842                 return (error);
2843
2844         error = kern_sigtimedwait(td, set, &ksi, timeout);
2845         if (error)
2846                 return (error);
2847
2848         if (uap->info) {
2849                 siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2850                 error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2851         }
2852
2853         if (error == 0)
2854                 td->td_retval[0] = ksi.ksi_signo;
2855         return (error);
2856 }
2857
2858 /*
2859  * MPSAFE
2860  */
2861 int
2862 freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
2863 {
2864         ksiginfo_t ksi;
2865         struct siginfo32 si32;
2866         sigset_t set;
2867         int error;
2868
2869         error = copyin(uap->set, &set, sizeof(set));
2870         if (error)
2871                 return (error);
2872
2873         error = kern_sigtimedwait(td, set, &ksi, NULL);
2874         if (error)
2875                 return (error);
2876
2877         if (uap->info) {
2878                 siginfo_to_siginfo32(&ksi.ksi_info, &si32);
2879                 error = copyout(&si32, uap->info, sizeof(struct siginfo32));
2880         }       
2881         if (error == 0)
2882                 td->td_retval[0] = ksi.ksi_signo;
2883         return (error);
2884 }
2885
2886 int
2887 freebsd32_cpuset_setid(struct thread *td,
2888     struct freebsd32_cpuset_setid_args *uap)
2889 {
2890         struct cpuset_setid_args ap;
2891
2892         ap.which = uap->which;
2893         ap.id = PAIR32TO64(id_t,uap->id);
2894         ap.setid = uap->setid;
2895
2896         return (cpuset_setid(td, &ap));
2897 }
2898
2899 int
2900 freebsd32_cpuset_getid(struct thread *td,
2901     struct freebsd32_cpuset_getid_args *uap)
2902 {
2903         struct cpuset_getid_args ap;
2904
2905         ap.level = uap->level;
2906         ap.which = uap->which;
2907         ap.id = PAIR32TO64(id_t,uap->id);
2908         ap.setid = uap->setid;
2909
2910         return (cpuset_getid(td, &ap));
2911 }
2912
2913 int
2914 freebsd32_cpuset_getaffinity(struct thread *td,
2915     struct freebsd32_cpuset_getaffinity_args *uap)
2916 {
2917         struct cpuset_getaffinity_args ap;
2918
2919         ap.level = uap->level;
2920         ap.which = uap->which;
2921         ap.id = PAIR32TO64(id_t,uap->id);
2922         ap.cpusetsize = uap->cpusetsize;
2923         ap.mask = uap->mask;
2924
2925         return (cpuset_getaffinity(td, &ap));
2926 }
2927
2928 int
2929 freebsd32_cpuset_setaffinity(struct thread *td,
2930     struct freebsd32_cpuset_setaffinity_args *uap)
2931 {
2932         struct cpuset_setaffinity_args ap;
2933
2934         ap.level = uap->level;
2935         ap.which = uap->which;
2936         ap.id = PAIR32TO64(id_t,uap->id);
2937         ap.cpusetsize = uap->cpusetsize;
2938         ap.mask = uap->mask;
2939
2940         return (cpuset_setaffinity(td, &ap));
2941 }
2942
2943 int
2944 freebsd32_nmount(struct thread *td,
2945     struct freebsd32_nmount_args /* {
2946         struct iovec *iovp;
2947         unsigned int iovcnt;
2948         int flags;
2949     } */ *uap)
2950 {
2951         struct uio *auio;
2952         int error;
2953
2954         AUDIT_ARG_FFLAGS(uap->flags);
2955
2956         /*
2957          * Filter out MNT_ROOTFS.  We do not want clients of nmount() in
2958          * userspace to set this flag, but we must filter it out if we want
2959          * MNT_UPDATE on the root file system to work.
2960          * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try().
2961          */
2962         uap->flags &= ~MNT_ROOTFS;
2963
2964         /*
2965          * check that we have an even number of iovec's
2966          * and that we have at least two options.
2967          */
2968         if ((uap->iovcnt & 1) || (uap->iovcnt < 4))
2969                 return (EINVAL);
2970
2971         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
2972         if (error)
2973                 return (error);
2974         error = vfs_donmount(td, uap->flags, auio);
2975
2976         free(auio, M_IOV);
2977         return error;
2978 }
2979
2980 #if 0
2981 int
2982 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
2983 {
2984         struct yyy32 *p32, s32;
2985         struct yyy *p = NULL, s;
2986         struct xxx_arg ap;
2987         int error;
2988
2989         if (uap->zzz) {
2990                 error = copyin(uap->zzz, &s32, sizeof(s32));
2991                 if (error)
2992                         return (error);
2993                 /* translate in */
2994                 p = &s;
2995         }
2996         error = kern_xxx(td, p);
2997         if (error)
2998                 return (error);
2999         if (uap->zzz) {
3000                 /* translate out */
3001                 error = copyout(&s32, p32, sizeof(s32));
3002         }
3003         return (error);
3004 }
3005 #endif
3006
3007 int
3008 syscall32_register(int *offset, struct sysent *new_sysent,
3009     struct sysent *old_sysent)
3010 {
3011         if (*offset == NO_SYSCALL) {
3012                 int i;
3013
3014                 for (i = 1; i < SYS_MAXSYSCALL; ++i)
3015                         if (freebsd32_sysent[i].sy_call ==
3016                             (sy_call_t *)lkmnosys)
3017                                 break;
3018                 if (i == SYS_MAXSYSCALL)
3019                         return (ENFILE);
3020                 *offset = i;
3021         } else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
3022                 return (EINVAL);
3023         else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
3024             freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys)
3025                 return (EEXIST);
3026
3027         *old_sysent = freebsd32_sysent[*offset];
3028         freebsd32_sysent[*offset] = *new_sysent;
3029         return 0;
3030 }
3031
3032 int
3033 syscall32_deregister(int *offset, struct sysent *old_sysent)
3034 {
3035
3036         if (*offset)
3037                 freebsd32_sysent[*offset] = *old_sysent;
3038         return 0;
3039 }
3040
3041 int
3042 syscall32_module_handler(struct module *mod, int what, void *arg)
3043 {
3044         struct syscall_module_data *data = (struct syscall_module_data*)arg;
3045         modspecific_t ms;
3046         int error;
3047
3048         switch (what) {
3049         case MOD_LOAD:
3050                 error = syscall32_register(data->offset, data->new_sysent,
3051                     &data->old_sysent);
3052                 if (error) {
3053                         /* Leave a mark so we know to safely unload below. */
3054                         data->offset = NULL;
3055                         return error;
3056                 }
3057                 ms.intval = *data->offset;
3058                 MOD_XLOCK;
3059                 module_setspecific(mod, &ms);
3060                 MOD_XUNLOCK;
3061                 if (data->chainevh)
3062                         error = data->chainevh(mod, what, data->chainarg);
3063                 return (error);
3064         case MOD_UNLOAD:
3065                 /*
3066                  * MOD_LOAD failed, so just return without calling the
3067                  * chained handler since we didn't pass along the MOD_LOAD
3068                  * event.
3069                  */
3070                 if (data->offset == NULL)
3071                         return (0);
3072                 if (data->chainevh) {
3073                         error = data->chainevh(mod, what, data->chainarg);
3074                         if (error)
3075                                 return (error);
3076                 }
3077                 error = syscall32_deregister(data->offset, &data->old_sysent);
3078                 return (error);
3079         default:
3080                 error = EOPNOTSUPP;
3081                 if (data->chainevh)
3082                         error = data->chainevh(mod, what, data->chainarg);
3083                 return (error);
3084         }
3085 }
3086
3087 register_t *
3088 freebsd32_copyout_strings(struct image_params *imgp)
3089 {
3090         int argc, envc;
3091         u_int32_t *vectp;
3092         char *stringp, *destp;
3093         u_int32_t *stack_base;
3094         struct freebsd32_ps_strings *arginfo;
3095         size_t execpath_len;
3096         int szsigcode;
3097
3098         /*
3099          * Calculate string base and vector table pointers.
3100          * Also deal with signal trampoline code for this exec type.
3101          */
3102         if (imgp->execpath != NULL && imgp->auxargs != NULL)
3103                 execpath_len = strlen(imgp->execpath) + 1;
3104         else
3105                 execpath_len = 0;
3106         arginfo = (struct freebsd32_ps_strings *)FREEBSD32_PS_STRINGS;
3107         szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
3108         destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
3109                 roundup(execpath_len, sizeof(char *)) -
3110                 roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
3111
3112         /*
3113          * install sigcode
3114          */
3115         if (szsigcode)
3116                 copyout(imgp->proc->p_sysent->sv_sigcode,
3117                         ((caddr_t)arginfo - szsigcode), szsigcode);
3118
3119         /*
3120          * Copy the image path for the rtld.
3121          */
3122         if (execpath_len != 0) {
3123                 imgp->execpathp = (uintptr_t)arginfo - szsigcode - execpath_len;
3124                 copyout(imgp->execpath, (void *)imgp->execpathp,
3125                     execpath_len);
3126         }
3127
3128         /*
3129          * If we have a valid auxargs ptr, prepare some room
3130          * on the stack.
3131          */
3132         if (imgp->auxargs) {
3133                 /*
3134                  * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
3135                  * lower compatibility.
3136                  */
3137                 imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
3138                         : (AT_COUNT * 2);
3139                 /*
3140                  * The '+ 2' is for the null pointers at the end of each of
3141                  * the arg and env vector sets,and imgp->auxarg_size is room
3142                  * for argument of Runtime loader.
3143                  */
3144                 vectp = (u_int32_t *) (destp - (imgp->args->argc +
3145                     imgp->args->envc + 2 + imgp->auxarg_size + execpath_len) *
3146                     sizeof(u_int32_t));
3147         } else
3148                 /*
3149                  * The '+ 2' is for the null pointers at the end of each of
3150                  * the arg and env vector sets
3151                  */
3152                 vectp = (u_int32_t *)
3153                         (destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t));
3154
3155         /*
3156          * vectp also becomes our initial stack base
3157          */
3158         stack_base = vectp;
3159
3160         stringp = imgp->args->begin_argv;
3161         argc = imgp->args->argc;
3162         envc = imgp->args->envc;
3163         /*
3164          * Copy out strings - arguments and environment.
3165          */
3166         copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);
3167
3168         /*
3169          * Fill in "ps_strings" struct for ps, w, etc.
3170          */
3171         suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
3172         suword32(&arginfo->ps_nargvstr, argc);
3173
3174         /*
3175          * Fill in argument portion of vector table.
3176          */
3177         for (; argc > 0; --argc) {
3178                 suword32(vectp++, (u_int32_t)(intptr_t)destp);
3179                 while (*stringp++ != 0)
3180                         destp++;
3181                 destp++;
3182         }
3183
3184         /* a null vector table pointer separates the argp's from the envp's */
3185         suword32(vectp++, 0);
3186
3187         suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
3188         suword32(&arginfo->ps_nenvstr, envc);
3189
3190         /*
3191          * Fill in environment portion of vector table.
3192          */
3193         for (; envc > 0; --envc) {
3194                 suword32(vectp++, (u_int32_t)(intptr_t)destp);
3195                 while (*stringp++ != 0)
3196                         destp++;
3197                 destp++;
3198         }
3199
3200         /* end of vector table is a null pointer */
3201         suword32(vectp, 0);
3202
3203         return ((register_t *)stack_base);
3204 }
3205