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

Cache object: 8a868365b3e6425544fa87b2e4354f65


[ 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.