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/5.2/sys/compat/freebsd32/freebsd32_misc.c 122253 2003-11-07 21:27:13Z peter $");
   29 
   30 #include "opt_compat.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/bus.h>
   35 #include <sys/exec.h>
   36 #include <sys/fcntl.h>
   37 #include <sys/filedesc.h>
   38 #include <sys/imgact.h>
   39 #include <sys/kernel.h>
   40 #include <sys/lock.h>
   41 #include <sys/malloc.h>
   42 #include <sys/file.h>           /* Must come after sys/malloc.h */
   43 #include <sys/mman.h>
   44 #include <sys/module.h>
   45 #include <sys/mount.h>
   46 #include <sys/mutex.h>
   47 #include <sys/namei.h>
   48 #include <sys/param.h>
   49 #include <sys/proc.h>
   50 #include <sys/reboot.h>
   51 #include <sys/resource.h>
   52 #include <sys/resourcevar.h>
   53 #include <sys/selinfo.h>
   54 #include <sys/pipe.h>           /* Must come after sys/selinfo.h */
   55 #include <sys/signal.h>
   56 #include <sys/signalvar.h>
   57 #include <sys/socket.h>
   58 #include <sys/socketvar.h>
   59 #include <sys/stat.h>
   60 #include <sys/syscallsubr.h>
   61 #include <sys/sysctl.h>
   62 #include <sys/sysent.h>
   63 #include <sys/sysproto.h>
   64 #include <sys/systm.h>
   65 #include <sys/unistd.h>
   66 #include <sys/user.h>
   67 #include <sys/utsname.h>
   68 #include <sys/vnode.h>
   69 
   70 #include <vm/vm.h>
   71 #include <vm/vm_kern.h>
   72 #include <vm/vm_param.h>
   73 #include <vm/pmap.h>
   74 #include <vm/vm_map.h>
   75 #include <vm/vm_object.h>
   76 #include <vm/vm_extern.h>
   77 
   78 #include <compat/freebsd32/freebsd32_util.h>
   79 #include <compat/freebsd32/freebsd32.h>
   80 #include <compat/freebsd32/freebsd32_proto.h>
   81 
   82 CTASSERT(sizeof(struct timeval32) == 8);
   83 CTASSERT(sizeof(struct timespec32) == 8);
   84 CTASSERT(sizeof(struct statfs32) == 256);
   85 CTASSERT(sizeof(struct rusage32) == 72);
   86 
   87 /*
   88  * [ taken from the linux emulator ]
   89  * Search an alternate path before passing pathname arguments on
   90  * to system calls. Useful for keeping a separate 'emulation tree'.
   91  *
   92  * If cflag is set, we check if an attempt can be made to create
   93  * the named file, i.e. we check if the directory it should
   94  * be in exists.
   95  */
   96 int
   97 freebsd32_emul_find(td, sgp, prefix, path, pbuf, cflag)
   98         struct thread   *td;
   99         caddr_t         *sgp;           /* Pointer to stackgap memory */
  100         const char      *prefix;
  101         char            *path;
  102         char            **pbuf;
  103         int             cflag;
  104 {
  105         int                     error;
  106         size_t                  len, sz;
  107         char                    *buf, *cp, *ptr;
  108         struct ucred            *ucred;
  109         struct nameidata        nd;
  110         struct nameidata        ndroot;
  111         struct vattr            vat;
  112         struct vattr            vatroot;
  113 
  114         buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  115         *pbuf = path;
  116 
  117         for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
  118                 continue;
  119 
  120         sz = MAXPATHLEN - (ptr - buf);
  121 
  122         /*
  123          * If sgp is not given then the path is already in kernel space
  124          */
  125         if (sgp == NULL)
  126                 error = copystr(path, ptr, sz, &len);
  127         else
  128                 error = copyinstr(path, ptr, sz, &len);
  129 
  130         if (error) {
  131                 free(buf, M_TEMP);
  132                 return error;
  133         }
  134 
  135         if (*ptr != '/') {
  136                 free(buf, M_TEMP);
  137                 return EINVAL;
  138         }
  139 
  140         /*
  141          *  We know that there is a / somewhere in this pathname.
  142          *  Search backwards for it, to find the file's parent dir
  143          *  to see if it exists in the alternate tree. If it does,
  144          *  and we want to create a file (cflag is set). We don't
  145          *  need to worry about the root comparison in this case.
  146          */
  147 
  148         if (cflag) {
  149                 for (cp = &ptr[len] - 1; *cp != '/'; cp--)
  150                         ;
  151                 *cp = '\0';
  152 
  153                 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
  154 
  155                 if ((error = namei(&nd)) != 0) {
  156                         free(buf, M_TEMP);
  157                         return error;
  158                 }
  159 
  160                 *cp = '/';
  161         } else {
  162                 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
  163 
  164                 if ((error = namei(&nd)) != 0) {
  165                         free(buf, M_TEMP);
  166                         return error;
  167                 }
  168 
  169                 /*
  170                  * We now compare the vnode of the freebsd32_root to the one
  171                  * vnode asked. If they resolve to be the same, then we
  172                  * ignore the match so that the real root gets used.
  173                  * This avoids the problem of traversing "../.." to find the
  174                  * root directory and never finding it, because "/" resolves
  175                  * to the emulation root directory. This is expensive :-(
  176                  */
  177                 NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE,
  178                     freebsd32_emul_path, td);
  179 
  180                 if ((error = namei(&ndroot)) != 0) {
  181                         /* Cannot happen! */
  182                         free(buf, M_TEMP);
  183                         vrele(nd.ni_vp);
  184                         return error;
  185                 }
  186 
  187                 ucred = td->td_ucred;
  188                 if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
  189                         goto bad;
  190                 }
  191 
  192                 if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
  193                     td)) != 0) {
  194                         goto bad;
  195                 }
  196 
  197                 if (vat.va_fsid == vatroot.va_fsid &&
  198                     vat.va_fileid == vatroot.va_fileid) {
  199                         error = ENOENT;
  200                         goto bad;
  201                 }
  202 
  203         }
  204         if (sgp == NULL)
  205                 *pbuf = buf;
  206         else {
  207                 sz = &ptr[len] - buf;
  208                 *pbuf = stackgap_alloc(sgp, sz + 1);
  209                 error = copyout(buf, *pbuf, sz);
  210                 free(buf, M_TEMP);
  211         }
  212 
  213         vrele(nd.ni_vp);
  214         if (!cflag)
  215                 vrele(ndroot.ni_vp);
  216 
  217         return error;
  218 
  219 bad:
  220         vrele(ndroot.ni_vp);
  221         vrele(nd.ni_vp);
  222         free(buf, M_TEMP);
  223         return error;
  224 }
  225 
  226 int
  227 freebsd32_open(struct thread *td, struct freebsd32_open_args *uap)
  228 {
  229         caddr_t sg;
  230 
  231         sg = stackgap_init();
  232         CHECKALTEXIST(td, &sg, uap->path);
  233 
  234         return open(td, (struct open_args *) uap);
  235 }
  236 
  237 int
  238 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
  239 {
  240         int error;
  241         caddr_t sg;
  242         struct rusage32 *rusage32, ru32;
  243         struct rusage *rusage = NULL, ru;
  244 
  245         rusage32 = uap->rusage;
  246         if (rusage32) {
  247                 sg = stackgap_init();
  248                 rusage = stackgap_alloc(&sg, sizeof(struct rusage));
  249                 uap->rusage = (struct rusage32 *)rusage;
  250         }
  251         error = wait4(td, (struct wait_args *)uap);
  252         if (error)
  253                 return (error);
  254         if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
  255                 TV_CP(ru, ru32, ru_utime);
  256                 TV_CP(ru, ru32, ru_stime);
  257                 CP(ru, ru32, ru_maxrss);
  258                 CP(ru, ru32, ru_ixrss);
  259                 CP(ru, ru32, ru_idrss);
  260                 CP(ru, ru32, ru_isrss);
  261                 CP(ru, ru32, ru_minflt);
  262                 CP(ru, ru32, ru_majflt);
  263                 CP(ru, ru32, ru_nswap);
  264                 CP(ru, ru32, ru_inblock);
  265                 CP(ru, ru32, ru_oublock);
  266                 CP(ru, ru32, ru_msgsnd);
  267                 CP(ru, ru32, ru_msgrcv);
  268                 CP(ru, ru32, ru_nsignals);
  269                 CP(ru, ru32, ru_nvcsw);
  270                 CP(ru, ru32, ru_nivcsw);
  271                 error = copyout(&ru32, rusage32, sizeof(ru32));
  272         }
  273         return (error);
  274 }
  275 
  276 static void
  277 copy_statfs(struct statfs *in, struct statfs32 *out)
  278 {
  279         CP(*in, *out, f_bsize);
  280         CP(*in, *out, f_iosize);
  281         CP(*in, *out, f_blocks);
  282         CP(*in, *out, f_bfree);
  283         CP(*in, *out, f_bavail);
  284         CP(*in, *out, f_files);
  285         CP(*in, *out, f_ffree);
  286         CP(*in, *out, f_fsid);
  287         CP(*in, *out, f_owner);
  288         CP(*in, *out, f_type);
  289         CP(*in, *out, f_flags);
  290         CP(*in, *out, f_flags);
  291         CP(*in, *out, f_syncwrites);
  292         CP(*in, *out, f_asyncwrites);
  293         bcopy(in->f_fstypename,
  294               out->f_fstypename, MFSNAMELEN);
  295         bcopy(in->f_mntonname,
  296               out->f_mntonname, MNAMELEN);
  297         CP(*in, *out, f_syncreads);
  298         CP(*in, *out, f_asyncreads);
  299         bcopy(in->f_mntfromname,
  300               out->f_mntfromname, MNAMELEN);
  301 }
  302 
  303 int
  304 freebsd32_getfsstat(struct thread *td, struct freebsd32_getfsstat_args *uap)
  305 {
  306         int error;
  307         caddr_t sg;
  308         struct statfs32 *sp32, stat32;
  309         struct statfs *sp = NULL, stat;
  310         int maxcount, count, i;
  311 
  312         sp32 = uap->buf;
  313         maxcount = uap->bufsize / sizeof(struct statfs32);
  314 
  315         if (sp32) {
  316                 sg = stackgap_init();
  317                 sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
  318                 uap->buf = (struct statfs32 *)sp;
  319         }
  320         error = getfsstat(td, (struct getfsstat_args *) uap);
  321         if (sp32 && !error) {
  322                 count = td->td_retval[0];
  323                 for (i = 0; i < count; i++) {
  324                         error = copyin(&sp[i], &stat, sizeof(stat));
  325                         if (error)
  326                                 return (error);
  327                         copy_statfs(&stat, &stat32);
  328                         error = copyout(&stat32, &sp32[i], sizeof(stat32));
  329                         if (error)
  330                                 return (error);
  331                 }
  332         }
  333         return (error);
  334 }
  335 
  336 int
  337 freebsd32_access(struct thread *td, struct freebsd32_access_args *uap)
  338 {
  339         caddr_t sg;
  340 
  341         sg = stackgap_init();
  342         CHECKALTEXIST(td, &sg, uap->path);
  343 
  344         return access(td, (struct access_args *)uap);
  345 }
  346 
  347 int
  348 freebsd32_chflags(struct thread *td, struct freebsd32_chflags_args *uap)
  349 {
  350         caddr_t sg;
  351 
  352         sg = stackgap_init();
  353         CHECKALTEXIST(td, &sg, uap->path);
  354 
  355         return chflags(td, (struct chflags_args *)uap);
  356 }
  357 
  358 struct sigaltstack32 {
  359         u_int32_t       ss_sp;
  360         u_int32_t       ss_size;
  361         int             ss_flags;
  362 };
  363 
  364 CTASSERT(sizeof(struct sigaltstack32) == 12);
  365 
  366 int
  367 freebsd32_sigaltstack(struct thread *td,
  368                       struct freebsd32_sigaltstack_args *uap)
  369 {
  370         struct sigaltstack32 s32;
  371         struct sigaltstack ss, oss, *ssp;
  372         int error;
  373 
  374         if (uap->ss != NULL) {
  375                 error = copyin(uap->ss, &s32, sizeof(s32));
  376                 if (error)
  377                         return (error);
  378                 PTRIN_CP(s32, ss, ss_sp);
  379                 CP(s32, ss, ss_size);
  380                 CP(s32, ss, ss_flags);
  381                 ssp = &ss;
  382         } else
  383                 ssp = NULL;
  384         error = kern_sigaltstack(td, ssp, &oss);
  385         if (error == 0 && uap->oss != NULL) {
  386                 PTROUT_CP(oss, s32, ss_sp);
  387                 CP(oss, s32, ss_size);
  388                 CP(oss, s32, ss_flags);
  389                 error = copyout(&s32, uap->oss, sizeof(s32));
  390         }
  391         return (error);
  392 }
  393 
  394 int
  395 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
  396 {
  397         int error;
  398         caddr_t sg;
  399         struct execve_args ap;
  400         u_int32_t *p32, arg;
  401         char **p, *p64;
  402         int count;
  403 
  404         sg = stackgap_init();
  405         CHECKALTEXIST(td, &sg, uap->fname);
  406         ap.fname = uap->fname;
  407 
  408         if (uap->argv) {
  409                 count = 0;
  410                 p32 = uap->argv;
  411                 do {
  412                         error = copyin(p32++, &arg, sizeof(arg));
  413                         if (error)
  414                                 return error;
  415                         count++;
  416                 } while (arg != 0);
  417                 p = stackgap_alloc(&sg, count * sizeof(char *));
  418                 ap.argv = p;
  419                 p32 = uap->argv;
  420                 do {
  421                         error = copyin(p32++, &arg, sizeof(arg));
  422                         if (error)
  423                                 return error;
  424                         p64 = PTRIN(arg);
  425                         error = copyout(&p64, p++, sizeof(p64));
  426                         if (error)
  427                                 return error;
  428                 } while (arg != 0);
  429         }
  430         if (uap->envv) {
  431                 count = 0;
  432                 p32 = uap->envv;
  433                 do {
  434                         error = copyin(p32++, &arg, sizeof(arg));
  435                         if (error)
  436                                 return error;
  437                         count++;
  438                 } while (arg != 0);
  439                 p = stackgap_alloc(&sg, count * sizeof(char *));
  440                 ap.envv = p;
  441                 p32 = uap->envv;
  442                 do {
  443                         error = copyin(p32++, &arg, sizeof(arg));
  444                         if (error)
  445                                 return error;
  446                         p64 = PTRIN(arg);
  447                         error = copyout(&p64, p++, sizeof(p64));
  448                         if (error)
  449                                 return error;
  450                 } while (arg != 0);
  451         }
  452 
  453         return execve(td, &ap);
  454 }
  455 
  456 #ifdef __ia64__
  457 static int
  458 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
  459                        int prot, int fd, off_t pos)
  460 {
  461         vm_map_t map;
  462         vm_map_entry_t entry;
  463         int rv;
  464 
  465         map = &td->td_proc->p_vmspace->vm_map;
  466         if (fd != -1)
  467                 prot |= VM_PROT_WRITE;
  468 
  469         if (vm_map_lookup_entry(map, start, &entry)) {
  470                 if ((entry->protection & prot) != prot) {
  471                         rv = vm_map_protect(map,
  472                                             trunc_page(start),
  473                                             round_page(end),
  474                                             entry->protection | prot,
  475                                             FALSE);
  476                         if (rv != KERN_SUCCESS)
  477                                 return (EINVAL);
  478                 }
  479         } else {
  480                 vm_offset_t addr = trunc_page(start);
  481                 rv = vm_map_find(map, 0, 0,
  482                                  &addr, PAGE_SIZE, FALSE, prot,
  483                                  VM_PROT_ALL, 0);
  484                 if (rv != KERN_SUCCESS)
  485                         return (EINVAL);
  486         }
  487 
  488         if (fd != -1) {
  489                 struct pread_args r;
  490                 r.fd = fd;
  491                 r.buf = (void *) start;
  492                 r.nbyte = end - start;
  493                 r.offset = pos;
  494                 return (pread(td, &r));
  495         } else {
  496                 while (start < end) {
  497                         subyte((void *) start, 0);
  498                         start++;
  499                 }
  500                 return (0);
  501         }
  502 }
  503 #endif
  504 
  505 int
  506 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
  507 {
  508         struct mmap_args ap;
  509         vm_offset_t addr = (vm_offset_t) uap->addr;
  510         vm_size_t len    = uap->len;
  511         int prot         = uap->prot;
  512         int flags        = uap->flags;
  513         int fd           = uap->fd;
  514         off_t pos        = (uap->poslo
  515                             | ((off_t)uap->poshi << 32));
  516 #ifdef __ia64__
  517         vm_size_t pageoff;
  518         int error;
  519 
  520         /*
  521          * Attempt to handle page size hassles.
  522          */
  523         pageoff = (pos & PAGE_MASK);
  524         if (flags & MAP_FIXED) {
  525                 vm_offset_t start, end;
  526                 start = addr;
  527                 end = addr + len;
  528 
  529                 if (start != trunc_page(start)) {
  530                         error = freebsd32_mmap_partial(td, start,
  531                                                        round_page(start), prot,
  532                                                        fd, pos);
  533                         if (fd != -1)
  534                                 pos += round_page(start) - start;
  535                         start = round_page(start);
  536                 }
  537                 if (end != round_page(end)) {
  538                         vm_offset_t t = trunc_page(end);
  539                         error = freebsd32_mmap_partial(td, t, end,
  540                                                   prot, fd,
  541                                                   pos + t - start);
  542                         end = trunc_page(end);
  543                 }
  544                 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
  545                         /*
  546                          * We can't map this region at all. The specified
  547                          * address doesn't have the same alignment as the file
  548                          * position. Fake the mapping by simply reading the
  549                          * entire region into memory. First we need to make
  550                          * sure the region exists.
  551                          */
  552                         vm_map_t map;
  553                         struct pread_args r;
  554                         int rv;
  555 
  556                         prot |= VM_PROT_WRITE;
  557                         map = &td->td_proc->p_vmspace->vm_map;
  558                         rv = vm_map_remove(map, start, end);
  559                         if (rv != KERN_SUCCESS)
  560                                 return (EINVAL);
  561                         rv = vm_map_find(map, 0, 0,
  562                                          &start, end - start, FALSE,
  563                                          prot, VM_PROT_ALL, 0);
  564                         if (rv != KERN_SUCCESS)
  565                                 return (EINVAL);
  566                         r.fd = fd;
  567                         r.buf = (void *) start;
  568                         r.nbyte = end - start;
  569                         r.offset = pos;
  570                         error = pread(td, &r);
  571                         if (error)
  572                                 return (error);
  573 
  574                         td->td_retval[0] = addr;
  575                         return (0);
  576                 }
  577                 if (end == start) {
  578                         /*
  579                          * After dealing with the ragged ends, there
  580                          * might be none left.
  581                          */
  582                         td->td_retval[0] = addr;
  583                         return (0);
  584                 }
  585                 addr = start;
  586                 len = end - start;
  587         }
  588 #endif
  589 
  590         ap.addr = (void *) addr;
  591         ap.len = len;
  592         ap.prot = prot;
  593         ap.flags = flags;
  594         ap.fd = fd;
  595         ap.pos = pos;
  596 
  597         return (mmap(td, &ap));
  598 }
  599 
  600 struct itimerval32 {
  601         struct timeval32 it_interval;
  602         struct timeval32 it_value;
  603 };
  604 
  605 CTASSERT(sizeof(struct itimerval32) == 16);
  606 
  607 int
  608 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
  609 {
  610         int error;
  611         caddr_t sg;
  612         struct itimerval32 *p32, *op32, s32;
  613         struct itimerval *p = NULL, *op = NULL, s;
  614 
  615         p32 = uap->itv;
  616         if (p32) {
  617                 sg = stackgap_init();
  618                 p = stackgap_alloc(&sg, sizeof(struct itimerval));
  619                 uap->itv = (struct itimerval32 *)p;
  620                 error = copyin(p32, &s32, sizeof(s32));
  621                 if (error)
  622                         return (error);
  623                 TV_CP(s32, s, it_interval);
  624                 TV_CP(s32, s, it_value);
  625                 error = copyout(&s, p, sizeof(s));
  626                 if (error)
  627                         return (error);
  628         }
  629         op32 = uap->oitv;
  630         if (op32) {
  631                 sg = stackgap_init();
  632                 op = stackgap_alloc(&sg, sizeof(struct itimerval));
  633                 uap->oitv = (struct itimerval32 *)op;
  634         }
  635         error = setitimer(td, (struct setitimer_args *) uap);
  636         if (error)
  637                 return (error);
  638         if (op32) {
  639                 error = copyin(op, &s, sizeof(s));
  640                 if (error)
  641                         return (error);
  642                 TV_CP(s, s32, it_interval);
  643                 TV_CP(s, s32, it_value);
  644                 error = copyout(&s32, op32, sizeof(s32));
  645         }
  646         return (error);
  647 }
  648 
  649 int
  650 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
  651 {
  652         int error;
  653         caddr_t sg;
  654         struct timeval32 *p32, s32;
  655         struct timeval *p = NULL, s;
  656 
  657         p32 = uap->tv;
  658         if (p32) {
  659                 sg = stackgap_init();
  660                 p = stackgap_alloc(&sg, sizeof(struct timeval));
  661                 uap->tv = (struct timeval32 *)p;
  662                 error = copyin(p32, &s32, sizeof(s32));
  663                 if (error)
  664                         return (error);
  665                 CP(s32, s, tv_sec);
  666                 CP(s32, s, tv_usec);
  667                 error = copyout(&s, p, sizeof(s));
  668                 if (error)
  669                         return (error);
  670         }
  671         /*
  672          * XXX big-endian needs to convert the fd_sets too.
  673          */
  674         return (select(td, (struct select_args *) uap));
  675 }
  676 
  677 struct kevent32 {
  678         u_int32_t       ident;          /* identifier for this event */
  679         short           filter;         /* filter for event */
  680         u_short         flags;
  681         u_int           fflags;
  682         int32_t         data;
  683         u_int32_t       udata;          /* opaque user data identifier */
  684 };
  685 
  686 CTASSERT(sizeof(struct kevent32) == 20);
  687 
  688 int
  689 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
  690 {
  691         int error;
  692         caddr_t sg;
  693         struct timespec32 ts32;
  694         struct timespec ts;
  695         struct kevent32 ks32;
  696         struct kevent *ks;
  697         struct kevent_args a;
  698         int i;
  699 
  700         sg = stackgap_init();
  701 
  702         a.fd = uap->fd;
  703         a.changelist = uap->changelist;
  704         a.nchanges = uap->nchanges;
  705         a.eventlist = uap->eventlist;
  706         a.nevents = uap->nevents;
  707         a.timeout = NULL;
  708 
  709         if (uap->timeout) {
  710                 a.timeout = stackgap_alloc(&sg, sizeof(struct timespec));
  711                 error = copyin(uap->timeout, &ts32, sizeof(ts32));
  712                 if (error)
  713                         return (error);
  714                 CP(ts32, ts, tv_sec);
  715                 CP(ts32, ts, tv_nsec);
  716                 error = copyout(&ts, (void *)(uintptr_t)a.timeout, sizeof(ts));
  717                 if (error)
  718                         return (error);
  719         }
  720         if (uap->changelist) {
  721                 a.changelist = (struct kevent *)stackgap_alloc(&sg,
  722                     uap->nchanges * sizeof(struct kevent));
  723                 for (i = 0; i < uap->nchanges; i++) {
  724                         error = copyin(&uap->changelist[i], &ks32,
  725                             sizeof(ks32));
  726                         if (error)
  727                                 return (error);
  728                         ks = (struct kevent *)(uintptr_t)&a.changelist[i];
  729                         CP(ks32, *ks, ident);
  730                         CP(ks32, *ks, filter);
  731                         CP(ks32, *ks, flags);
  732                         CP(ks32, *ks, fflags);
  733                         CP(ks32, *ks, data);
  734                         PTRIN_CP(ks32, *ks, udata);
  735                 }
  736         }
  737         if (uap->eventlist) {
  738                 a.eventlist = stackgap_alloc(&sg,
  739                     uap->nevents * sizeof(struct kevent));
  740         }
  741         error = kevent(td, &a);
  742         if (uap->eventlist && error > 0) {
  743                 for (i = 0; i < error; i++) {
  744                         ks = &a.eventlist[i];
  745                         CP(*ks, ks32, ident);
  746                         CP(*ks, ks32, filter);
  747                         CP(*ks, ks32, flags);
  748                         CP(*ks, ks32, fflags);
  749                         CP(*ks, ks32, data);
  750                         PTROUT_CP(*ks, ks32, udata);
  751                         error = copyout(&ks32, &uap->eventlist[i],
  752                             sizeof(ks32));
  753                         if (error)
  754                                 return (error);
  755                 }
  756         }
  757         return error;
  758 }
  759 
  760 int
  761 freebsd32_gettimeofday(struct thread *td,
  762                        struct freebsd32_gettimeofday_args *uap)
  763 {
  764         int error;
  765         caddr_t sg;
  766         struct timeval32 *p32, s32;
  767         struct timeval *p = NULL, s;
  768 
  769         p32 = uap->tp;
  770         if (p32) {
  771                 sg = stackgap_init();
  772                 p = stackgap_alloc(&sg, sizeof(struct timeval));
  773                 uap->tp = (struct timeval32 *)p;
  774         }
  775         error = gettimeofday(td, (struct gettimeofday_args *) uap);
  776         if (error)
  777                 return (error);
  778         if (p32) {
  779                 error = copyin(p, &s, sizeof(s));
  780                 if (error)
  781                         return (error);
  782                 CP(s, s32, tv_sec);
  783                 CP(s, s32, tv_usec);
  784                 error = copyout(&s32, p32, sizeof(s32));
  785                 if (error)
  786                         return (error);
  787         }
  788         return (error);
  789 }
  790 
  791 int
  792 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
  793 {
  794         int error;
  795         caddr_t sg;
  796         struct rusage32 *p32, s32;
  797         struct rusage *p = NULL, s;
  798 
  799         p32 = uap->rusage;
  800         if (p32) {
  801                 sg = stackgap_init();
  802                 p = stackgap_alloc(&sg, sizeof(struct rusage));
  803                 uap->rusage = (struct rusage32 *)p;
  804         }
  805         error = getrusage(td, (struct getrusage_args *) uap);
  806         if (error)
  807                 return (error);
  808         if (p32) {
  809                 error = copyin(p, &s, sizeof(s));
  810                 if (error)
  811                         return (error);
  812                 TV_CP(s, s32, ru_utime);
  813                 TV_CP(s, s32, ru_stime);
  814                 CP(s, s32, ru_maxrss);
  815                 CP(s, s32, ru_ixrss);
  816                 CP(s, s32, ru_idrss);
  817                 CP(s, s32, ru_isrss);
  818                 CP(s, s32, ru_minflt);
  819                 CP(s, s32, ru_majflt);
  820                 CP(s, s32, ru_nswap);
  821                 CP(s, s32, ru_inblock);
  822                 CP(s, s32, ru_oublock);
  823                 CP(s, s32, ru_msgsnd);
  824                 CP(s, s32, ru_msgrcv);
  825                 CP(s, s32, ru_nsignals);
  826                 CP(s, s32, ru_nvcsw);
  827                 CP(s, s32, ru_nivcsw);
  828                 error = copyout(&s32, p32, sizeof(s32));
  829         }
  830         return (error);
  831 }
  832 
  833 struct iovec32 {
  834         u_int32_t iov_base;
  835         int     iov_len;
  836 };
  837 #define STACKGAPLEN     400
  838 
  839 CTASSERT(sizeof(struct iovec32) == 8);
  840 
  841 int
  842 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
  843 {
  844         int error, osize, nsize, i;
  845         caddr_t sg;
  846         struct readv_args /* {
  847                 syscallarg(int) fd;
  848                 syscallarg(struct iovec *) iovp;
  849                 syscallarg(u_int) iovcnt;
  850         } */ a;
  851         struct iovec32 *oio;
  852         struct iovec *nio;
  853 
  854         sg = stackgap_init();
  855 
  856         if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
  857                 return (EINVAL);
  858 
  859         osize = uap->iovcnt * sizeof (struct iovec32);
  860         nsize = uap->iovcnt * sizeof (struct iovec);
  861 
  862         oio = malloc(osize, M_TEMP, M_WAITOK);
  863         nio = malloc(nsize, M_TEMP, M_WAITOK);
  864 
  865         error = 0;
  866         if ((error = copyin(uap->iovp, oio, osize)))
  867                 goto punt;
  868         for (i = 0; i < uap->iovcnt; i++) {
  869                 nio[i].iov_base = PTRIN(oio[i].iov_base);
  870                 nio[i].iov_len = oio[i].iov_len;
  871         }
  872 
  873         a.fd = uap->fd;
  874         a.iovp = stackgap_alloc(&sg, nsize);
  875         a.iovcnt = uap->iovcnt;
  876 
  877         if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
  878                 goto punt;
  879         error = readv(td, &a);
  880 
  881 punt:
  882         free(oio, M_TEMP);
  883         free(nio, M_TEMP);
  884         return (error);
  885 }
  886 
  887 int
  888 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
  889 {
  890         int error, i, nsize, osize;
  891         caddr_t sg;
  892         struct writev_args /* {
  893                 syscallarg(int) fd;
  894                 syscallarg(struct iovec *) iovp;
  895                 syscallarg(u_int) iovcnt;
  896         } */ a;
  897         struct iovec32 *oio;
  898         struct iovec *nio;
  899 
  900         sg = stackgap_init();
  901 
  902         if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec)))
  903                 return (EINVAL);
  904 
  905         osize = uap->iovcnt * sizeof (struct iovec32);
  906         nsize = uap->iovcnt * sizeof (struct iovec);
  907 
  908         oio = malloc(osize, M_TEMP, M_WAITOK);
  909         nio = malloc(nsize, M_TEMP, M_WAITOK);
  910 
  911         error = 0;
  912         if ((error = copyin(uap->iovp, oio, osize)))
  913                 goto punt;
  914         for (i = 0; i < uap->iovcnt; i++) {
  915                 nio[i].iov_base = PTRIN(oio[i].iov_base);
  916                 nio[i].iov_len = oio[i].iov_len;
  917         }
  918 
  919         a.fd = uap->fd;
  920         a.iovp = stackgap_alloc(&sg, nsize);
  921         a.iovcnt = uap->iovcnt;
  922 
  923         if ((error = copyout(nio, (caddr_t)a.iovp, nsize)))
  924                 goto punt;
  925         error = writev(td, &a);
  926 
  927 punt:
  928         free(oio, M_TEMP);
  929         free(nio, M_TEMP);
  930         return (error);
  931 }
  932 
  933 int
  934 freebsd32_settimeofday(struct thread *td,
  935                        struct freebsd32_settimeofday_args *uap)
  936 {
  937         int error;
  938         caddr_t sg;
  939         struct timeval32 *p32, s32;
  940         struct timeval *p = NULL, s;
  941 
  942         p32 = uap->tv;
  943         if (p32) {
  944                 sg = stackgap_init();
  945                 p = stackgap_alloc(&sg, sizeof(struct timeval));
  946                 uap->tv = (struct timeval32 *)p;
  947                 error = copyin(p32, &s32, sizeof(s32));
  948                 if (error)
  949                         return (error);
  950                 CP(s32, s, tv_sec);
  951                 CP(s32, s, tv_usec);
  952                 error = copyout(&s, p, sizeof(s));
  953                 if (error)
  954                         return (error);
  955         }
  956         return (settimeofday(td, (struct settimeofday_args *) uap));
  957 }
  958 
  959 int
  960 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
  961 {
  962         int error;
  963         caddr_t sg;
  964         struct timeval32 *p32, s32[2];
  965         struct timeval *p = NULL, s[2];
  966 
  967         p32 = uap->tptr;
  968         if (p32) {
  969                 sg = stackgap_init();
  970                 p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
  971                 uap->tptr = (struct timeval32 *)p;
  972                 error = copyin(p32, s32, sizeof(s32));
  973                 if (error)
  974                         return (error);
  975                 CP(s32[0], s[0], tv_sec);
  976                 CP(s32[0], s[0], tv_usec);
  977                 CP(s32[1], s[1], tv_sec);
  978                 CP(s32[1], s[1], tv_usec);
  979                 error = copyout(s, p, sizeof(s));
  980                 if (error)
  981                         return (error);
  982         }
  983         return (utimes(td, (struct utimes_args *) uap));
  984 }
  985 
  986 int
  987 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
  988 {
  989         int error;
  990         caddr_t sg;
  991         struct timeval32 *p32, *op32, s32;
  992         struct timeval *p = NULL, *op = NULL, s;
  993 
  994         p32 = uap->delta;
  995         if (p32) {
  996                 sg = stackgap_init();
  997                 p = stackgap_alloc(&sg, sizeof(struct timeval));
  998                 uap->delta = (struct timeval32 *)p;
  999                 error = copyin(p32, &s32, sizeof(s32));
 1000                 if (error)
 1001                         return (error);
 1002                 CP(s32, s, tv_sec);
 1003                 CP(s32, s, tv_usec);
 1004                 error = copyout(&s, p, sizeof(s));
 1005                 if (error)
 1006                         return (error);
 1007         }
 1008         op32 = uap->olddelta;
 1009         if (op32) {
 1010                 sg = stackgap_init();
 1011                 op = stackgap_alloc(&sg, sizeof(struct timeval));
 1012                 uap->olddelta = (struct timeval32 *)op;
 1013         }
 1014         error = utimes(td, (struct utimes_args *) uap);
 1015         if (error)
 1016                 return error;
 1017         if (op32) {
 1018                 error = copyin(op, &s, sizeof(s));
 1019                 if (error)
 1020                         return (error);
 1021                 CP(s, s32, tv_sec);
 1022                 CP(s, s32, tv_usec);
 1023                 error = copyout(&s32, op32, sizeof(s32));
 1024         }
 1025         return (error);
 1026 }
 1027 
 1028 int
 1029 freebsd32_statfs(struct thread *td, struct freebsd32_statfs_args *uap)
 1030 {
 1031         int error;
 1032         caddr_t sg;
 1033         struct statfs32 *p32, s32;
 1034         struct statfs *p = NULL, s;
 1035 
 1036         p32 = uap->buf;
 1037         if (p32) {
 1038                 sg = stackgap_init();
 1039                 p = stackgap_alloc(&sg, sizeof(struct statfs));
 1040                 uap->buf = (struct statfs32 *)p;
 1041         }
 1042         error = statfs(td, (struct statfs_args *) uap);
 1043         if (error)
 1044                 return (error);
 1045         if (p32) {
 1046                 error = copyin(p, &s, sizeof(s));
 1047                 if (error)
 1048                         return (error);
 1049                 copy_statfs(&s, &s32);
 1050                 error = copyout(&s32, p32, sizeof(s32));
 1051         }
 1052         return (error);
 1053 }
 1054 
 1055 int
 1056 freebsd32_fstatfs(struct thread *td, struct freebsd32_fstatfs_args *uap)
 1057 {
 1058         int error;
 1059         caddr_t sg;
 1060         struct statfs32 *p32, s32;
 1061         struct statfs *p = NULL, s;
 1062 
 1063         p32 = uap->buf;
 1064         if (p32) {
 1065                 sg = stackgap_init();
 1066                 p = stackgap_alloc(&sg, sizeof(struct statfs));
 1067                 uap->buf = (struct statfs32 *)p;
 1068         }
 1069         error = fstatfs(td, (struct fstatfs_args *) uap);
 1070         if (error)
 1071                 return (error);
 1072         if (p32) {
 1073                 error = copyin(p, &s, sizeof(s));
 1074                 if (error)
 1075                         return (error);
 1076                 copy_statfs(&s, &s32);
 1077                 error = copyout(&s32, p32, sizeof(s32));
 1078         }
 1079         return (error);
 1080 }
 1081 
 1082 int
 1083 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
 1084 {
 1085         /*
 1086          * Vector through to semsys if it is loaded.
 1087          */
 1088         return sysent[169].sy_call(td, uap);
 1089 }
 1090 
 1091 int
 1092 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
 1093 {
 1094         /*
 1095          * Vector through to msgsys if it is loaded.
 1096          */
 1097         return sysent[170].sy_call(td, uap);
 1098 }
 1099 
 1100 int
 1101 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
 1102 {
 1103         /*
 1104          * Vector through to shmsys if it is loaded.
 1105          */
 1106         return sysent[171].sy_call(td, uap);
 1107 }
 1108 
 1109 int
 1110 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
 1111 {
 1112         struct pread_args ap;
 1113 
 1114         ap.fd = uap->fd;
 1115         ap.buf = uap->buf;
 1116         ap.nbyte = uap->nbyte;
 1117         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
 1118         return (pread(td, &ap));
 1119 }
 1120 
 1121 int
 1122 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
 1123 {
 1124         struct pwrite_args ap;
 1125 
 1126         ap.fd = uap->fd;
 1127         ap.buf = uap->buf;
 1128         ap.nbyte = uap->nbyte;
 1129         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
 1130         return (pwrite(td, &ap));
 1131 }
 1132 
 1133 int
 1134 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
 1135 {
 1136         int error;
 1137         struct lseek_args ap;
 1138         off_t pos;
 1139 
 1140         ap.fd = uap->fd;
 1141         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
 1142         ap.whence = uap->whence;
 1143         error = lseek(td, &ap);
 1144         /* Expand the quad return into two parts for eax and edx */
 1145         pos = *(off_t *)(td->td_retval);
 1146         td->td_retval[0] = pos & 0xffffffff;    /* %eax */
 1147         td->td_retval[1] = pos >> 32;           /* %edx */
 1148         return error;
 1149 }
 1150 
 1151 int
 1152 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
 1153 {
 1154         struct truncate_args ap;
 1155 
 1156         ap.path = uap->path;
 1157         ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
 1158         return (truncate(td, &ap));
 1159 }
 1160 
 1161 int
 1162 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
 1163 {
 1164         struct ftruncate_args ap;
 1165 
 1166         ap.fd = uap->fd;
 1167         ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
 1168         return (ftruncate(td, &ap));
 1169 }
 1170 
 1171 #ifdef COMPAT_FREEBSD4
 1172 int
 1173 freebsd4_freebsd32_sendfile(struct thread *td,
 1174     struct freebsd4_freebsd32_sendfile_args *uap)
 1175 {
 1176         struct freebsd4_sendfile_args ap;
 1177 
 1178         ap.fd = uap->fd;
 1179         ap.s = uap->s;
 1180         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
 1181         ap.nbytes = uap->nbytes;        /* XXX check */
 1182         ap.hdtr = uap->hdtr;            /* XXX check */
 1183         ap.sbytes = uap->sbytes;        /* XXX FIXME!! */
 1184         ap.flags = uap->flags;
 1185         return (freebsd4_sendfile(td, &ap));
 1186 }
 1187 #endif
 1188 
 1189 int
 1190 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
 1191 {
 1192         struct sendfile_args ap;
 1193 
 1194         ap.fd = uap->fd;
 1195         ap.s = uap->s;
 1196         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
 1197         ap.nbytes = uap->nbytes;        /* XXX check */
 1198         ap.hdtr = uap->hdtr;            /* XXX check */
 1199         ap.sbytes = uap->sbytes;        /* XXX FIXME!! */
 1200         ap.flags = uap->flags;
 1201         return (sendfile(td, &ap));
 1202 }
 1203 
 1204 struct stat32 {
 1205         udev_t  st_dev;
 1206         ino_t   st_ino;
 1207         mode_t  st_mode;
 1208         nlink_t st_nlink;
 1209         uid_t   st_uid;
 1210         gid_t   st_gid;
 1211         udev_t  st_rdev;
 1212         struct timespec32 st_atimespec;
 1213         struct timespec32 st_mtimespec;
 1214         struct timespec32 st_ctimespec;
 1215         off_t   st_size;
 1216         int64_t st_blocks;
 1217         u_int32_t st_blksize;
 1218         u_int32_t st_flags;
 1219         u_int32_t st_gen;
 1220         struct timespec32 st_birthtimespec;
 1221         unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
 1222         unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
 1223 };
 1224 
 1225 
 1226 CTASSERT(sizeof(struct stat32) == 96);
 1227 
 1228 static void
 1229 copy_stat( struct stat *in, struct stat32 *out)
 1230 {
 1231         CP(*in, *out, st_dev);
 1232         CP(*in, *out, st_ino);
 1233         CP(*in, *out, st_mode);
 1234         CP(*in, *out, st_nlink);
 1235         CP(*in, *out, st_uid);
 1236         CP(*in, *out, st_gid);
 1237         CP(*in, *out, st_rdev);
 1238         TS_CP(*in, *out, st_atimespec);
 1239         TS_CP(*in, *out, st_mtimespec);
 1240         TS_CP(*in, *out, st_ctimespec);
 1241         CP(*in, *out, st_size);
 1242         CP(*in, *out, st_blocks);
 1243         CP(*in, *out, st_blksize);
 1244         CP(*in, *out, st_flags);
 1245         CP(*in, *out, st_gen);
 1246 }
 1247 
 1248 int
 1249 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
 1250 {
 1251         int error;
 1252         caddr_t sg;
 1253         struct stat32 *p32, s32;
 1254         struct stat *p = NULL, s;
 1255 
 1256         p32 = uap->ub;
 1257         if (p32) {
 1258                 sg = stackgap_init();
 1259                 p = stackgap_alloc(&sg, sizeof(struct stat));
 1260                 uap->ub = (struct stat32 *)p;
 1261         }
 1262         error = stat(td, (struct stat_args *) uap);
 1263         if (error)
 1264                 return (error);
 1265         if (p32) {
 1266                 error = copyin(p, &s, sizeof(s));
 1267                 if (error)
 1268                         return (error);
 1269                 copy_stat(&s, &s32);
 1270                 error = copyout(&s32, p32, sizeof(s32));
 1271         }
 1272         return (error);
 1273 }
 1274 
 1275 int
 1276 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
 1277 {
 1278         int error;
 1279         caddr_t sg;
 1280         struct stat32 *p32, s32;
 1281         struct stat *p = NULL, s;
 1282 
 1283         p32 = uap->ub;
 1284         if (p32) {
 1285                 sg = stackgap_init();
 1286                 p = stackgap_alloc(&sg, sizeof(struct stat));
 1287                 uap->ub = (struct stat32 *)p;
 1288         }
 1289         error = fstat(td, (struct fstat_args *) uap);
 1290         if (error)
 1291                 return (error);
 1292         if (p32) {
 1293                 error = copyin(p, &s, sizeof(s));
 1294                 if (error)
 1295                         return (error);
 1296                 copy_stat(&s, &s32);
 1297                 error = copyout(&s32, p32, sizeof(s32));
 1298         }
 1299         return (error);
 1300 }
 1301 
 1302 int
 1303 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
 1304 {
 1305         int error;
 1306         caddr_t sg;
 1307         struct stat32 *p32, s32;
 1308         struct stat *p = NULL, s;
 1309 
 1310         p32 = uap->ub;
 1311         if (p32) {
 1312                 sg = stackgap_init();
 1313                 p = stackgap_alloc(&sg, sizeof(struct stat));
 1314                 uap->ub = (struct stat32 *)p;
 1315         }
 1316         error = lstat(td, (struct lstat_args *) uap);
 1317         if (error)
 1318                 return (error);
 1319         if (p32) {
 1320                 error = copyin(p, &s, sizeof(s));
 1321                 if (error)
 1322                         return (error);
 1323                 copy_stat(&s, &s32);
 1324                 error = copyout(&s32, p32, sizeof(s32));
 1325         }
 1326         return (error);
 1327 }
 1328 
 1329 /*
 1330  * MPSAFE
 1331  */
 1332 int
 1333 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
 1334 {
 1335         int error, name[CTL_MAXNAME];
 1336         size_t j, oldlen;
 1337 
 1338         if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
 1339                 return (EINVAL);
 1340 
 1341         error = copyin(uap->name, &name, uap->namelen * sizeof(int));
 1342         if (error)
 1343                 return (error);
 1344 
 1345         mtx_lock(&Giant);
 1346 
 1347         if (uap->oldlenp)
 1348                 oldlen = fuword32(uap->oldlenp);
 1349         else
 1350                 oldlen = 0;
 1351         error = userland_sysctl(td, name, uap->namelen,
 1352                 uap->old, &oldlen, 1,
 1353                 uap->new, uap->newlen, &j);
 1354         if (error && error != ENOMEM)
 1355                 goto done2;
 1356         if (uap->oldlenp) {
 1357                 suword32(uap->oldlenp, j);
 1358         }
 1359 done2:
 1360         mtx_unlock(&Giant);
 1361         return (error);
 1362 }
 1363 
 1364 struct sigaction32 {
 1365         u_int32_t       sa_u;
 1366         int             sa_flags;
 1367         sigset_t        sa_mask;
 1368 };
 1369 
 1370 CTASSERT(sizeof(struct sigaction32) == 24);
 1371 
 1372 int
 1373 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
 1374 {
 1375         struct sigaction32 s32;
 1376         struct sigaction sa, osa, *sap;
 1377         int error;
 1378 
 1379         if (uap->act) {
 1380                 error = copyin(uap->act, &s32, sizeof(s32));
 1381                 if (error)
 1382                         return (error);
 1383                 sa.sa_handler = PTRIN(s32.sa_u);
 1384                 CP(s32, sa, sa_flags);
 1385                 CP(s32, sa, sa_mask);
 1386                 sap = &sa;
 1387         } else
 1388                 sap = NULL;
 1389         error = kern_sigaction(td, uap->sig, sap, &osa, 0);
 1390         if (error != 0 && uap->oact != NULL) {
 1391                 s32.sa_u = PTROUT(osa.sa_handler);
 1392                 CP(osa, s32, sa_flags);
 1393                 CP(osa, s32, sa_mask);
 1394                 error = copyout(&s32, uap->oact, sizeof(s32));
 1395         }
 1396         return (error);
 1397 }
 1398 
 1399 #ifdef COMPAT_FREEBSD4
 1400 int
 1401 freebsd4_freebsd32_sigaction(struct thread *td,
 1402                              struct freebsd4_freebsd32_sigaction_args *uap)
 1403 {
 1404         struct sigaction32 s32;
 1405         struct sigaction sa, osa, *sap;
 1406         int error;
 1407 
 1408         if (uap->act) {
 1409                 error = copyin(uap->act, &s32, sizeof(s32));
 1410                 if (error)
 1411                         return (error);
 1412                 sa.sa_handler = PTRIN(s32.sa_u);
 1413                 CP(s32, sa, sa_flags);
 1414                 CP(s32, sa, sa_mask);
 1415                 sap = &sa;
 1416         } else
 1417                 sap = NULL;
 1418         error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
 1419         if (error != 0 && uap->oact != NULL) {
 1420                 s32.sa_u = PTROUT(osa.sa_handler);
 1421                 CP(osa, s32, sa_flags);
 1422                 CP(osa, s32, sa_mask);
 1423                 error = copyout(&s32, uap->oact, sizeof(s32));
 1424         }
 1425         return (error);
 1426 }
 1427 #endif
 1428 
 1429 #if 0
 1430 
 1431 int
 1432 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
 1433 {
 1434         int error;
 1435         caddr_t sg;
 1436         struct yyy32 *p32, s32;
 1437         struct yyy *p = NULL, s;
 1438 
 1439         p32 = uap->zzz;
 1440         if (p32) {
 1441                 sg = stackgap_init();
 1442                 p = stackgap_alloc(&sg, sizeof(struct yyy));
 1443                 uap->zzz = (struct yyy32 *)p;
 1444                 error = copyin(p32, &s32, sizeof(s32));
 1445                 if (error)
 1446                         return (error);
 1447                 /* translate in */
 1448                 error = copyout(&s, p, sizeof(s));
 1449                 if (error)
 1450                         return (error);
 1451         }
 1452         error = xxx(td, (struct xxx_args *) uap);
 1453         if (error)
 1454                 return (error);
 1455         if (p32) {
 1456                 error = copyin(p, &s, sizeof(s));
 1457                 if (error)
 1458                         return (error);
 1459                 /* translate out */
 1460                 error = copyout(&s32, p32, sizeof(s32));
 1461         }
 1462         return (error);
 1463 }
 1464 
 1465 #endif

Cache object: c7548777aba3ed25f60d74694daafc77


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