The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/freebsd32/freebsd32_misc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 3a1da2150384879a000c4af7ddb32252


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.