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