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$");
   29 
   30 #include "opt_compat.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/bus.h>
   35 #include <sys/exec.h>
   36 #include <sys/fcntl.h>
   37 #include <sys/filedesc.h>
   38 #include <sys/namei.h>
   39 #include <sys/imgact.h>
   40 #include <sys/kernel.h>
   41 #include <sys/limits.h>
   42 #include <sys/lock.h>
   43 #include <sys/malloc.h>
   44 #include <sys/file.h>           /* Must come after sys/malloc.h */
   45 #include <sys/mman.h>
   46 #include <sys/module.h>
   47 #include <sys/mount.h>
   48 #include <sys/mutex.h>
   49 #include <sys/namei.h>
   50 #include <sys/param.h>
   51 #include <sys/proc.h>
   52 #include <sys/reboot.h>
   53 #include <sys/resource.h>
   54 #include <sys/resourcevar.h>
   55 #include <sys/selinfo.h>
   56 #include <sys/eventvar.h>       /* Must come after sys/selinfo.h */
   57 #include <sys/pipe.h>           /* Must come after sys/selinfo.h */
   58 #include <sys/signal.h>
   59 #include <sys/signalvar.h>
   60 #include <sys/socket.h>
   61 #include <sys/socketvar.h>
   62 #include <sys/stat.h>
   63 #include <sys/syscallsubr.h>
   64 #include <sys/sysctl.h>
   65 #include <sys/sysent.h>
   66 #include <sys/sysproto.h>
   67 #include <sys/systm.h>
   68 #include <sys/unistd.h>
   69 #include <sys/vnode.h>
   70 #include <sys/wait.h>
   71 
   72 #include <vm/vm.h>
   73 #include <vm/vm_kern.h>
   74 #include <vm/vm_param.h>
   75 #include <vm/pmap.h>
   76 #include <vm/vm_map.h>
   77 #include <vm/vm_object.h>
   78 #include <vm/vm_extern.h>
   79 
   80 #include <compat/freebsd32/freebsd32_util.h>
   81 #include <compat/freebsd32/freebsd32.h>
   82 #include <compat/freebsd32/freebsd32_proto.h>
   83 
   84 CTASSERT(sizeof(struct timeval32) == 8);
   85 CTASSERT(sizeof(struct timespec32) == 8);
   86 CTASSERT(sizeof(struct statfs32) == 256);
   87 CTASSERT(sizeof(struct rusage32) == 72);
   88 
   89 int
   90 freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
   91 {
   92         int error, status;
   93         struct rusage32 ru32;
   94         struct rusage ru;
   95 
   96         error = kern_wait(td, uap->pid, &status, uap->options, &ru);
   97         if (error)
   98                 return (error);
   99         if (uap->status != NULL)
  100                 error = copyout(&status, uap->status, sizeof(status));
  101         if (uap->rusage != NULL && error == 0) {
  102                 TV_CP(ru, ru32, ru_utime);
  103                 TV_CP(ru, ru32, ru_stime);
  104                 CP(ru, ru32, ru_maxrss);
  105                 CP(ru, ru32, ru_ixrss);
  106                 CP(ru, ru32, ru_idrss);
  107                 CP(ru, ru32, ru_isrss);
  108                 CP(ru, ru32, ru_minflt);
  109                 CP(ru, ru32, ru_majflt);
  110                 CP(ru, ru32, ru_nswap);
  111                 CP(ru, ru32, ru_inblock);
  112                 CP(ru, ru32, ru_oublock);
  113                 CP(ru, ru32, ru_msgsnd);
  114                 CP(ru, ru32, ru_msgrcv);
  115                 CP(ru, ru32, ru_nsignals);
  116                 CP(ru, ru32, ru_nvcsw);
  117                 CP(ru, ru32, ru_nivcsw);
  118                 error = copyout(&ru32, uap->rusage, sizeof(ru32));
  119         }
  120         return (error);
  121 }
  122 
  123 #ifdef COMPAT_FREEBSD4
  124 static void
  125 copy_statfs(struct statfs *in, struct statfs32 *out)
  126 {
  127         CP(*in, *out, f_bsize);
  128         CP(*in, *out, f_iosize);
  129         CP(*in, *out, f_blocks);
  130         CP(*in, *out, f_bfree);
  131         CP(*in, *out, f_bavail);
  132         CP(*in, *out, f_files);
  133         CP(*in, *out, f_ffree);
  134         CP(*in, *out, f_fsid);
  135         CP(*in, *out, f_owner);
  136         CP(*in, *out, f_type);
  137         CP(*in, *out, f_flags);
  138         CP(*in, *out, f_flags);
  139         CP(*in, *out, f_syncwrites);
  140         CP(*in, *out, f_asyncwrites);
  141         bcopy(in->f_fstypename,
  142               out->f_fstypename, MFSNAMELEN);
  143         bcopy(in->f_mntonname,
  144               out->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
  145         CP(*in, *out, f_syncreads);
  146         CP(*in, *out, f_asyncreads);
  147         bcopy(in->f_mntfromname,
  148               out->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
  149 }
  150 #endif
  151 
  152 #ifdef COMPAT_FREEBSD4
  153 int
  154 freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
  155 {
  156         int error;
  157         caddr_t sg;
  158         struct statfs32 *sp32, stat32;
  159         struct statfs *sp = NULL, stat;
  160         int maxcount, count, i;
  161 
  162         sp32 = uap->buf;
  163         maxcount = uap->bufsize / sizeof(struct statfs32);
  164 
  165         if (sp32) {
  166                 sg = stackgap_init();
  167                 sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
  168                 uap->buf = (struct statfs32 *)sp;
  169         }
  170         error = getfsstat(td, (struct getfsstat_args *) uap);
  171         if (sp32 && !error) {
  172                 count = td->td_retval[0];
  173                 for (i = 0; i < count; i++) {
  174                         error = copyin(&sp[i], &stat, sizeof(stat));
  175                         if (error)
  176                                 return (error);
  177                         copy_statfs(&stat, &stat32);
  178                         error = copyout(&stat32, &sp32[i], sizeof(stat32));
  179                         if (error)
  180                                 return (error);
  181                 }
  182         }
  183         return (error);
  184 }
  185 #endif
  186 
  187 struct sigaltstack32 {
  188         u_int32_t       ss_sp;
  189         u_int32_t       ss_size;
  190         int             ss_flags;
  191 };
  192 
  193 CTASSERT(sizeof(struct sigaltstack32) == 12);
  194 
  195 int
  196 freebsd32_sigaltstack(struct thread *td,
  197                       struct freebsd32_sigaltstack_args *uap)
  198 {
  199         struct sigaltstack32 s32;
  200         struct sigaltstack ss, oss, *ssp;
  201         int error;
  202 
  203         if (uap->ss != NULL) {
  204                 error = copyin(uap->ss, &s32, sizeof(s32));
  205                 if (error)
  206                         return (error);
  207                 PTRIN_CP(s32, ss, ss_sp);
  208                 CP(s32, ss, ss_size);
  209                 CP(s32, ss, ss_flags);
  210                 ssp = &ss;
  211         } else
  212                 ssp = NULL;
  213         error = kern_sigaltstack(td, ssp, &oss);
  214         if (error == 0 && uap->oss != NULL) {
  215                 PTROUT_CP(oss, s32, ss_sp);
  216                 CP(oss, s32, ss_size);
  217                 CP(oss, s32, ss_flags);
  218                 error = copyout(&s32, uap->oss, sizeof(s32));
  219         }
  220         return (error);
  221 }
  222 
  223 int
  224 freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
  225 {
  226         int error;
  227         caddr_t sg;
  228         struct execve_args ap;
  229         u_int32_t *p32, arg;
  230         char **p, *p64;
  231         int count;
  232 
  233         sg = stackgap_init();
  234         ap.fname = uap->fname;
  235 
  236         if (uap->argv) {
  237                 count = 0;
  238                 p32 = uap->argv;
  239                 do {
  240                         error = copyin(p32++, &arg, sizeof(arg));
  241                         if (error)
  242                                 return error;
  243                         count++;
  244                 } while (arg != 0);
  245                 p = stackgap_alloc(&sg, count * sizeof(char *));
  246                 ap.argv = p;
  247                 p32 = uap->argv;
  248                 do {
  249                         error = copyin(p32++, &arg, sizeof(arg));
  250                         if (error)
  251                                 return error;
  252                         p64 = PTRIN(arg);
  253                         error = copyout(&p64, p++, sizeof(p64));
  254                         if (error)
  255                                 return error;
  256                 } while (arg != 0);
  257         }
  258         if (uap->envv) {
  259                 count = 0;
  260                 p32 = uap->envv;
  261                 do {
  262                         error = copyin(p32++, &arg, sizeof(arg));
  263                         if (error)
  264                                 return error;
  265                         count++;
  266                 } while (arg != 0);
  267                 p = stackgap_alloc(&sg, count * sizeof(char *));
  268                 ap.envv = p;
  269                 p32 = uap->envv;
  270                 do {
  271                         error = copyin(p32++, &arg, sizeof(arg));
  272                         if (error)
  273                                 return error;
  274                         p64 = PTRIN(arg);
  275                         error = copyout(&p64, p++, sizeof(p64));
  276                         if (error)
  277                                 return error;
  278                 } while (arg != 0);
  279         }
  280 
  281         return execve(td, &ap);
  282 }
  283 
  284 #ifdef __ia64__
  285 static int
  286 freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
  287                        int prot, int fd, off_t pos)
  288 {
  289         vm_map_t map;
  290         vm_map_entry_t entry;
  291         int rv;
  292 
  293         map = &td->td_proc->p_vmspace->vm_map;
  294         if (fd != -1)
  295                 prot |= VM_PROT_WRITE;
  296 
  297         if (vm_map_lookup_entry(map, start, &entry)) {
  298                 if ((entry->protection & prot) != prot) {
  299                         rv = vm_map_protect(map,
  300                                             trunc_page(start),
  301                                             round_page(end),
  302                                             entry->protection | prot,
  303                                             FALSE);
  304                         if (rv != KERN_SUCCESS)
  305                                 return (EINVAL);
  306                 }
  307         } else {
  308                 vm_offset_t addr = trunc_page(start);
  309                 rv = vm_map_find(map, 0, 0,
  310                                  &addr, PAGE_SIZE, FALSE, prot,
  311                                  VM_PROT_ALL, 0);
  312                 if (rv != KERN_SUCCESS)
  313                         return (EINVAL);
  314         }
  315 
  316         if (fd != -1) {
  317                 struct pread_args r;
  318                 r.fd = fd;
  319                 r.buf = (void *) start;
  320                 r.nbyte = end - start;
  321                 r.offset = pos;
  322                 return (pread(td, &r));
  323         } else {
  324                 while (start < end) {
  325                         subyte((void *) start, 0);
  326                         start++;
  327                 }
  328                 return (0);
  329         }
  330 }
  331 #endif
  332 
  333 int
  334 freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
  335 {
  336         struct mmap_args ap;
  337         vm_offset_t addr = (vm_offset_t) uap->addr;
  338         vm_size_t len    = uap->len;
  339         int prot         = uap->prot;
  340         int flags        = uap->flags;
  341         int fd           = uap->fd;
  342         off_t pos        = (uap->poslo
  343                             | ((off_t)uap->poshi << 32));
  344 #ifdef __ia64__
  345         vm_size_t pageoff;
  346         int error;
  347 
  348         /*
  349          * Attempt to handle page size hassles.
  350          */
  351         pageoff = (pos & PAGE_MASK);
  352         if (flags & MAP_FIXED) {
  353                 vm_offset_t start, end;
  354                 start = addr;
  355                 end = addr + len;
  356 
  357                 if (start != trunc_page(start)) {
  358                         error = freebsd32_mmap_partial(td, start,
  359                                                        round_page(start), prot,
  360                                                        fd, pos);
  361                         if (fd != -1)
  362                                 pos += round_page(start) - start;
  363                         start = round_page(start);
  364                 }
  365                 if (end != round_page(end)) {
  366                         vm_offset_t t = trunc_page(end);
  367                         error = freebsd32_mmap_partial(td, t, end,
  368                                                   prot, fd,
  369                                                   pos + t - start);
  370                         end = trunc_page(end);
  371                 }
  372                 if (end > start && fd != -1 && (pos & PAGE_MASK)) {
  373                         /*
  374                          * We can't map this region at all. The specified
  375                          * address doesn't have the same alignment as the file
  376                          * position. Fake the mapping by simply reading the
  377                          * entire region into memory. First we need to make
  378                          * sure the region exists.
  379                          */
  380                         vm_map_t map;
  381                         struct pread_args r;
  382                         int rv;
  383 
  384                         prot |= VM_PROT_WRITE;
  385                         map = &td->td_proc->p_vmspace->vm_map;
  386                         rv = vm_map_remove(map, start, end);
  387                         if (rv != KERN_SUCCESS)
  388                                 return (EINVAL);
  389                         rv = vm_map_find(map, 0, 0,
  390                                          &start, end - start, FALSE,
  391                                          prot, VM_PROT_ALL, 0);
  392                         if (rv != KERN_SUCCESS)
  393                                 return (EINVAL);
  394                         r.fd = fd;
  395                         r.buf = (void *) start;
  396                         r.nbyte = end - start;
  397                         r.offset = pos;
  398                         error = pread(td, &r);
  399                         if (error)
  400                                 return (error);
  401 
  402                         td->td_retval[0] = addr;
  403                         return (0);
  404                 }
  405                 if (end == start) {
  406                         /*
  407                          * After dealing with the ragged ends, there
  408                          * might be none left.
  409                          */
  410                         td->td_retval[0] = addr;
  411                         return (0);
  412                 }
  413                 addr = start;
  414                 len = end - start;
  415         }
  416 #endif
  417 
  418         ap.addr = (void *) addr;
  419         ap.len = len;
  420         ap.prot = prot;
  421         ap.flags = flags;
  422         ap.fd = fd;
  423         ap.pos = pos;
  424 
  425         return (mmap(td, &ap));
  426 }
  427 
  428 struct itimerval32 {
  429         struct timeval32 it_interval;
  430         struct timeval32 it_value;
  431 };
  432 
  433 CTASSERT(sizeof(struct itimerval32) == 16);
  434 
  435 int
  436 freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
  437 {
  438         struct itimerval itv, oitv, *itvp;      
  439         struct itimerval32 i32;
  440         int error;
  441 
  442         if (uap->itv != NULL) {
  443                 error = copyin(uap->itv, &i32, sizeof(i32));
  444                 if (error)
  445                         return (error);
  446                 TV_CP(i32, itv, it_interval);
  447                 TV_CP(i32, itv, it_value);
  448                 itvp = &itv;
  449         } else
  450                 itvp = NULL;
  451         error = kern_setitimer(td, uap->which, itvp, &oitv);
  452         if (error || uap->oitv == NULL)
  453                 return (error);
  454         TV_CP(oitv, i32, it_interval);
  455         TV_CP(oitv, i32, it_value);
  456         return (copyout(&i32, uap->oitv, sizeof(i32)));
  457 }
  458 
  459 int
  460 freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
  461 {
  462         struct itimerval itv;
  463         struct itimerval32 i32;
  464         int error;
  465 
  466         error = kern_getitimer(td, uap->which, &itv);
  467         if (error || uap->itv == NULL)
  468                 return (error);
  469         TV_CP(itv, i32, it_interval);
  470         TV_CP(itv, i32, it_value);
  471         return (copyout(&i32, uap->itv, sizeof(i32)));
  472 }
  473 
  474 int
  475 freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
  476 {
  477         struct timeval32 tv32;
  478         struct timeval tv, *tvp;
  479         int error;
  480 
  481         if (uap->tv != NULL) {
  482                 error = copyin(uap->tv, &tv32, sizeof(tv32));
  483                 if (error)
  484                         return (error);
  485                 CP(tv32, tv, tv_sec);
  486                 CP(tv32, tv, tv_usec);
  487                 tvp = &tv;
  488         } else
  489                 tvp = NULL;
  490         /*
  491          * XXX big-endian needs to convert the fd_sets too.
  492          * XXX Do pointers need PTRIN()?
  493          */
  494         return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp));
  495 }
  496 
  497 struct kevent32 {
  498         u_int32_t       ident;          /* identifier for this event */
  499         short           filter;         /* filter for event */
  500         u_short         flags;
  501         u_int           fflags;
  502         int32_t         data;
  503         u_int32_t       udata;          /* opaque user data identifier */
  504 };
  505 
  506 CTASSERT(sizeof(struct kevent32) == 20);
  507 static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
  508 static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
  509 
  510 /*
  511  * Copy 'count' items into the destination list pointed to by uap->eventlist.
  512  */
  513 static int
  514 freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
  515 {
  516         struct freebsd32_kevent_args *uap;
  517         struct kevent32 ks32[KQ_NEVENTS];
  518         int i, error = 0;
  519 
  520         KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
  521         uap = (struct freebsd32_kevent_args *)arg;
  522 
  523         for (i = 0; i < count; i++) {
  524                 CP(kevp[i], ks32[i], ident);
  525                 CP(kevp[i], ks32[i], filter);
  526                 CP(kevp[i], ks32[i], flags);
  527                 CP(kevp[i], ks32[i], fflags);
  528                 CP(kevp[i], ks32[i], data);
  529                 PTROUT_CP(kevp[i], ks32[i], udata);
  530         }
  531         error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
  532         if (error == 0)
  533                 uap->eventlist += count;
  534         return (error);
  535 }
  536 
  537 /*
  538  * Copy 'count' items from the list pointed to by uap->changelist.
  539  */
  540 static int
  541 freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
  542 {
  543         struct freebsd32_kevent_args *uap;
  544         struct kevent32 ks32[KQ_NEVENTS];
  545         int i, error = 0;
  546 
  547         KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
  548         uap = (struct freebsd32_kevent_args *)arg;
  549 
  550         error = copyin(uap->changelist, ks32, count * sizeof *ks32);
  551         if (error)
  552                 goto done;
  553         uap->changelist += count;
  554 
  555         for (i = 0; i < count; i++) {
  556                 CP(ks32[i], kevp[i], ident);
  557                 CP(ks32[i], kevp[i], filter);
  558                 CP(ks32[i], kevp[i], flags);
  559                 CP(ks32[i], kevp[i], fflags);
  560                 CP(ks32[i], kevp[i], data);
  561                 PTRIN_CP(ks32[i], kevp[i], udata);
  562         }
  563 done:
  564         return (error);
  565 }
  566 
  567 int
  568 freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
  569 {
  570         struct timespec32 ts32;
  571         struct timespec ts, *tsp;
  572         struct kevent_copyops k_ops = { uap,
  573                                         freebsd32_kevent_copyout,
  574                                         freebsd32_kevent_copyin};
  575         int error;
  576 
  577 
  578         if (uap->timeout) {
  579                 error = copyin(uap->timeout, &ts32, sizeof(ts32));
  580                 if (error)
  581                         return (error);
  582                 CP(ts32, ts, tv_sec);
  583                 CP(ts32, ts, tv_nsec);
  584                 tsp = &ts;
  585         } else
  586                 tsp = NULL;
  587         error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
  588             &k_ops, tsp);
  589         return (error);
  590 }
  591 
  592 int
  593 freebsd32_gettimeofday(struct thread *td,
  594                        struct freebsd32_gettimeofday_args *uap)
  595 {
  596         struct timeval atv;
  597         struct timeval32 atv32;
  598         struct timezone rtz;
  599         int error = 0;
  600 
  601         if (uap->tp) {
  602                 microtime(&atv);
  603                 CP(atv, atv32, tv_sec);
  604                 CP(atv, atv32, tv_usec);
  605                 error = copyout(&atv32, uap->tp, sizeof (atv32));
  606         }
  607         if (error == 0 && uap->tzp != NULL) {
  608                 rtz.tz_minuteswest = tz_minuteswest;
  609                 rtz.tz_dsttime = tz_dsttime;
  610                 error = copyout(&rtz, uap->tzp, sizeof (rtz));
  611         }
  612         return (error);
  613 }
  614 
  615 int
  616 freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
  617 {
  618         int error;
  619         caddr_t sg;
  620         struct rusage32 *p32, s32;
  621         struct rusage *p = NULL, s;
  622 
  623         p32 = uap->rusage;
  624         if (p32) {
  625                 sg = stackgap_init();
  626                 p = stackgap_alloc(&sg, sizeof(struct rusage));
  627                 uap->rusage = (struct rusage32 *)p;
  628         }
  629         error = getrusage(td, (struct getrusage_args *) uap);
  630         if (error)
  631                 return (error);
  632         if (p32) {
  633                 error = copyin(p, &s, sizeof(s));
  634                 if (error)
  635                         return (error);
  636                 TV_CP(s, s32, ru_utime);
  637                 TV_CP(s, s32, ru_stime);
  638                 CP(s, s32, ru_maxrss);
  639                 CP(s, s32, ru_ixrss);
  640                 CP(s, s32, ru_idrss);
  641                 CP(s, s32, ru_isrss);
  642                 CP(s, s32, ru_minflt);
  643                 CP(s, s32, ru_majflt);
  644                 CP(s, s32, ru_nswap);
  645                 CP(s, s32, ru_inblock);
  646                 CP(s, s32, ru_oublock);
  647                 CP(s, s32, ru_msgsnd);
  648                 CP(s, s32, ru_msgrcv);
  649                 CP(s, s32, ru_nsignals);
  650                 CP(s, s32, ru_nvcsw);
  651                 CP(s, s32, ru_nivcsw);
  652                 error = copyout(&s32, p32, sizeof(s32));
  653         }
  654         return (error);
  655 }
  656 
  657 struct iovec32 {
  658         u_int32_t iov_base;
  659         int     iov_len;
  660 };
  661 
  662 CTASSERT(sizeof(struct iovec32) == 8);
  663 
  664 static int
  665 freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
  666 {
  667         struct iovec32 iov32;
  668         struct iovec *iov;
  669         struct uio *uio;
  670         u_int iovlen;
  671         int error, i;
  672 
  673         *uiop = NULL;
  674         if (iovcnt > UIO_MAXIOV)
  675                 return (EINVAL);
  676         iovlen = iovcnt * sizeof(struct iovec);
  677         uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
  678         iov = (struct iovec *)(uio + 1);
  679         for (i = 0; i < iovcnt; i++) {
  680                 error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
  681                 if (error) {
  682                         free(uio, M_IOV);
  683                         return (error);
  684                 }
  685                 iov[i].iov_base = PTRIN(iov32.iov_base);
  686                 iov[i].iov_len = iov32.iov_len;
  687         }
  688         uio->uio_iov = iov;
  689         uio->uio_iovcnt = iovcnt;
  690         uio->uio_segflg = UIO_USERSPACE;
  691         uio->uio_offset = -1;
  692         uio->uio_resid = 0;
  693         for (i = 0; i < iovcnt; i++) {
  694                 if (iov->iov_len > INT_MAX - uio->uio_resid) {
  695                         free(uio, M_IOV);
  696                         return (EINVAL);
  697                 }
  698                 uio->uio_resid += iov->iov_len;
  699                 iov++;
  700         }
  701         *uiop = uio;
  702         return (0);
  703 }
  704 
  705 int
  706 freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
  707 {
  708         struct uio *auio;
  709         int error;
  710 
  711         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
  712         if (error)
  713                 return (error);
  714         error = kern_readv(td, uap->fd, auio);
  715         free(auio, M_IOV);
  716         return (error);
  717 }
  718 
  719 int
  720 freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
  721 {
  722         struct uio *auio;
  723         int error;
  724 
  725         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
  726         if (error)
  727                 return (error);
  728         error = kern_writev(td, uap->fd, auio);
  729         free(auio, M_IOV);
  730         return (error);
  731 }
  732 
  733 int
  734 freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
  735 {
  736         struct uio *auio;
  737         int error;
  738 
  739         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
  740         if (error)
  741                 return (error);
  742         error = kern_preadv(td, uap->fd, auio, uap->offset);
  743         free(auio, M_IOV);
  744         return (error);
  745 }
  746 
  747 int
  748 freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
  749 {
  750         struct uio *auio;
  751         int error;
  752 
  753         error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
  754         if (error)
  755                 return (error);
  756         error = kern_pwritev(td, uap->fd, auio, uap->offset);
  757         free(auio, M_IOV);
  758         return (error);
  759 }
  760 
  761 int
  762 freebsd32_settimeofday(struct thread *td,
  763                        struct freebsd32_settimeofday_args *uap)
  764 {
  765         struct timeval32 tv32;
  766         struct timeval tv, *tvp;
  767         struct timezone tz, *tzp;
  768         int error;
  769 
  770         if (uap->tv) {
  771                 error = copyin(uap->tv, &tv32, sizeof(tv32));
  772                 if (error)
  773                         return (error);
  774                 CP(tv32, tv, tv_sec);
  775                 CP(tv32, tv, tv_usec);
  776                 tvp = &tv;
  777         } else
  778                 tvp = NULL;
  779         if (uap->tzp) {
  780                 error = copyin(uap->tzp, &tz, sizeof(tz));
  781                 if (error)
  782                         return (error);
  783                 tzp = &tz;
  784         } else
  785                 tzp = NULL;
  786         return (kern_settimeofday(td, tvp, tzp));
  787 }
  788 
  789 int
  790 freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
  791 {
  792         struct timeval32 s32[2];
  793         struct timeval s[2], *sp;
  794         int error;
  795 
  796         if (uap->tptr != NULL) {
  797                 error = copyin(uap->tptr, s32, sizeof(s32));
  798                 if (error)
  799                         return (error);
  800                 CP(s32[0], s[0], tv_sec);
  801                 CP(s32[0], s[0], tv_usec);
  802                 CP(s32[1], s[1], tv_sec);
  803                 CP(s32[1], s[1], tv_usec);
  804                 sp = s;
  805         } else
  806                 sp = NULL;
  807         return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
  808 }
  809 
  810 int
  811 freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
  812 {
  813         struct timeval32 tv32;
  814         struct timeval delta, olddelta, *deltap;
  815         int error;
  816 
  817         if (uap->delta) {
  818                 error = copyin(uap->delta, &tv32, sizeof(tv32));
  819                 if (error)
  820                         return (error);
  821                 CP(tv32, delta, tv_sec);
  822                 CP(tv32, delta, tv_usec);
  823                 deltap = &delta;
  824         } else
  825                 deltap = NULL;
  826         error = kern_adjtime(td, deltap, &olddelta);
  827         if (uap->olddelta && error == 0) {
  828                 CP(olddelta, tv32, tv_sec);
  829                 CP(olddelta, tv32, tv_usec);
  830                 error = copyout(&tv32, uap->olddelta, sizeof(tv32));
  831         }
  832         return (error);
  833 }
  834 
  835 #ifdef COMPAT_FREEBSD4
  836 int
  837 freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
  838 {
  839         struct statfs32 s32;
  840         struct statfs s;
  841         int error;
  842 
  843         error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
  844         if (error)
  845                 return (error);
  846         copy_statfs(&s, &s32);
  847         return (copyout(&s32, uap->buf, sizeof(s32)));
  848 }
  849 #endif
  850 
  851 #ifdef COMPAT_FREEBSD4
  852 int
  853 freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
  854 {
  855         struct statfs32 s32;
  856         struct statfs s;
  857         int error;
  858 
  859         error = kern_fstatfs(td, uap->fd, &s);
  860         if (error)
  861                 return (error);
  862         copy_statfs(&s, &s32);
  863         return (copyout(&s32, uap->buf, sizeof(s32)));
  864 }
  865 #endif
  866 
  867 #ifdef COMPAT_FREEBSD4
  868 int
  869 freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
  870 {
  871         struct statfs32 s32;
  872         struct statfs s;
  873         fhandle_t fh;
  874         int error;
  875 
  876         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
  877                 return (error);
  878         error = kern_fhstatfs(td, fh, &s);
  879         if (error)
  880                 return (error);
  881         copy_statfs(&s, &s32);
  882         return (copyout(&s32, uap->buf, sizeof(s32)));
  883 }
  884 #endif
  885 
  886 int
  887 freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
  888 {
  889         /*
  890          * Vector through to semsys if it is loaded.
  891          */
  892         return sysent[169].sy_call(td, uap);
  893 }
  894 
  895 int
  896 freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
  897 {
  898         /*
  899          * Vector through to msgsys if it is loaded.
  900          */
  901         return sysent[170].sy_call(td, uap);
  902 }
  903 
  904 int
  905 freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
  906 {
  907         /*
  908          * Vector through to shmsys if it is loaded.
  909          */
  910         return sysent[171].sy_call(td, uap);
  911 }
  912 
  913 int
  914 freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
  915 {
  916         struct pread_args ap;
  917 
  918         ap.fd = uap->fd;
  919         ap.buf = uap->buf;
  920         ap.nbyte = uap->nbyte;
  921         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
  922         return (pread(td, &ap));
  923 }
  924 
  925 int
  926 freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
  927 {
  928         struct pwrite_args ap;
  929 
  930         ap.fd = uap->fd;
  931         ap.buf = uap->buf;
  932         ap.nbyte = uap->nbyte;
  933         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
  934         return (pwrite(td, &ap));
  935 }
  936 
  937 int
  938 freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
  939 {
  940         int error;
  941         struct lseek_args ap;
  942         off_t pos;
  943 
  944         ap.fd = uap->fd;
  945         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
  946         ap.whence = uap->whence;
  947         error = lseek(td, &ap);
  948         /* Expand the quad return into two parts for eax and edx */
  949         pos = *(off_t *)(td->td_retval);
  950         td->td_retval[0] = pos & 0xffffffff;    /* %eax */
  951         td->td_retval[1] = pos >> 32;           /* %edx */
  952         return error;
  953 }
  954 
  955 int
  956 freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
  957 {
  958         struct truncate_args ap;
  959 
  960         ap.path = uap->path;
  961         ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
  962         return (truncate(td, &ap));
  963 }
  964 
  965 int
  966 freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
  967 {
  968         struct ftruncate_args ap;
  969 
  970         ap.fd = uap->fd;
  971         ap.length = (uap->lengthlo | ((off_t)uap->lengthhi << 32));
  972         return (ftruncate(td, &ap));
  973 }
  974 
  975 #ifdef COMPAT_FREEBSD4
  976 int
  977 freebsd4_freebsd32_sendfile(struct thread *td,
  978     struct freebsd4_freebsd32_sendfile_args *uap)
  979 {
  980         struct freebsd4_sendfile_args ap;
  981 
  982         ap.fd = uap->fd;
  983         ap.s = uap->s;
  984         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
  985         ap.nbytes = uap->nbytes;        /* XXX check */
  986         ap.hdtr = uap->hdtr;            /* XXX check */
  987         ap.sbytes = uap->sbytes;        /* XXX FIXME!! */
  988         ap.flags = uap->flags;
  989         return (freebsd4_sendfile(td, &ap));
  990 }
  991 #endif
  992 
  993 int
  994 freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
  995 {
  996         struct sendfile_args ap;
  997 
  998         ap.fd = uap->fd;
  999         ap.s = uap->s;
 1000         ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32));
 1001         ap.nbytes = uap->nbytes;        /* XXX check */
 1002         ap.hdtr = uap->hdtr;            /* XXX check */
 1003         ap.sbytes = uap->sbytes;        /* XXX FIXME!! */
 1004         ap.flags = uap->flags;
 1005         return (sendfile(td, &ap));
 1006 }
 1007 
 1008 struct stat32 {
 1009         dev_t   st_dev;
 1010         ino_t   st_ino;
 1011         mode_t  st_mode;
 1012         nlink_t st_nlink;
 1013         uid_t   st_uid;
 1014         gid_t   st_gid;
 1015         dev_t   st_rdev;
 1016         struct timespec32 st_atimespec;
 1017         struct timespec32 st_mtimespec;
 1018         struct timespec32 st_ctimespec;
 1019         off_t   st_size;
 1020         int64_t st_blocks;
 1021         u_int32_t st_blksize;
 1022         u_int32_t st_flags;
 1023         u_int32_t st_gen;
 1024         struct timespec32 st_birthtimespec;
 1025         unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
 1026         unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
 1027 };
 1028 
 1029 
 1030 CTASSERT(sizeof(struct stat32) == 96);
 1031 
 1032 static void
 1033 copy_stat( struct stat *in, struct stat32 *out)
 1034 {
 1035         CP(*in, *out, st_dev);
 1036         CP(*in, *out, st_ino);
 1037         CP(*in, *out, st_mode);
 1038         CP(*in, *out, st_nlink);
 1039         CP(*in, *out, st_uid);
 1040         CP(*in, *out, st_gid);
 1041         CP(*in, *out, st_rdev);
 1042         TS_CP(*in, *out, st_atimespec);
 1043         TS_CP(*in, *out, st_mtimespec);
 1044         TS_CP(*in, *out, st_ctimespec);
 1045         CP(*in, *out, st_size);
 1046         CP(*in, *out, st_blocks);
 1047         CP(*in, *out, st_blksize);
 1048         CP(*in, *out, st_flags);
 1049         CP(*in, *out, st_gen);
 1050 }
 1051 
 1052 int
 1053 freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
 1054 {
 1055         struct stat sb;
 1056         struct stat32 sb32;
 1057         int error;
 1058 
 1059         error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
 1060         if (error)
 1061                 return (error);
 1062         copy_stat(&sb, &sb32);
 1063         error = copyout(&sb32, uap->ub, sizeof (sb32));
 1064         return (error);
 1065 }
 1066 
 1067 int
 1068 freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
 1069 {
 1070         struct stat ub;
 1071         struct stat32 ub32;
 1072         int error;
 1073 
 1074         error = kern_fstat(td, uap->fd, &ub);
 1075         if (error)
 1076                 return (error);
 1077         copy_stat(&ub, &ub32);
 1078         error = copyout(&ub32, uap->ub, sizeof(ub32));
 1079         return (error);
 1080 }
 1081 
 1082 int
 1083 freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
 1084 {
 1085         struct stat sb;
 1086         struct stat32 sb32;
 1087         int error;
 1088 
 1089         error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
 1090         if (error)
 1091                 return (error);
 1092         copy_stat(&sb, &sb32);
 1093         error = copyout(&sb32, uap->ub, sizeof (sb32));
 1094         return (error);
 1095 }
 1096 
 1097 /*
 1098  * MPSAFE
 1099  */
 1100 int
 1101 freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
 1102 {
 1103         int error, name[CTL_MAXNAME];
 1104         size_t j, oldlen;
 1105 
 1106         if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
 1107                 return (EINVAL);
 1108 
 1109         error = copyin(uap->name, &name, uap->namelen * sizeof(int));
 1110         if (error)
 1111                 return (error);
 1112 
 1113         mtx_lock(&Giant);
 1114 
 1115         if (uap->oldlenp)
 1116                 oldlen = fuword32(uap->oldlenp);
 1117         else
 1118                 oldlen = 0;
 1119         error = userland_sysctl(td, name, uap->namelen,
 1120                 uap->old, &oldlen, 1,
 1121                 uap->new, uap->newlen, &j);
 1122         if (error && error != ENOMEM)
 1123                 goto done2;
 1124         if (uap->oldlenp) {
 1125                 suword32(uap->oldlenp, j);
 1126         }
 1127 done2:
 1128         mtx_unlock(&Giant);
 1129         return (error);
 1130 }
 1131 
 1132 struct sigaction32 {
 1133         u_int32_t       sa_u;
 1134         int             sa_flags;
 1135         sigset_t        sa_mask;
 1136 };
 1137 
 1138 CTASSERT(sizeof(struct sigaction32) == 24);
 1139 
 1140 int
 1141 freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
 1142 {
 1143         struct sigaction32 s32;
 1144         struct sigaction sa, osa, *sap;
 1145         int error;
 1146 
 1147         if (uap->act) {
 1148                 error = copyin(uap->act, &s32, sizeof(s32));
 1149                 if (error)
 1150                         return (error);
 1151                 sa.sa_handler = PTRIN(s32.sa_u);
 1152                 CP(s32, sa, sa_flags);
 1153                 CP(s32, sa, sa_mask);
 1154                 sap = &sa;
 1155         } else
 1156                 sap = NULL;
 1157         error = kern_sigaction(td, uap->sig, sap, &osa, 0);
 1158         if (error == 0 && uap->oact != NULL) {
 1159                 s32.sa_u = PTROUT(osa.sa_handler);
 1160                 CP(osa, s32, sa_flags);
 1161                 CP(osa, s32, sa_mask);
 1162                 error = copyout(&s32, uap->oact, sizeof(s32));
 1163         }
 1164         return (error);
 1165 }
 1166 
 1167 #ifdef COMPAT_FREEBSD4
 1168 int
 1169 freebsd4_freebsd32_sigaction(struct thread *td,
 1170                              struct freebsd4_freebsd32_sigaction_args *uap)
 1171 {
 1172         struct sigaction32 s32;
 1173         struct sigaction sa, osa, *sap;
 1174         int error;
 1175 
 1176         if (uap->act) {
 1177                 error = copyin(uap->act, &s32, sizeof(s32));
 1178                 if (error)
 1179                         return (error);
 1180                 sa.sa_handler = PTRIN(s32.sa_u);
 1181                 CP(s32, sa, sa_flags);
 1182                 CP(s32, sa, sa_mask);
 1183                 sap = &sa;
 1184         } else
 1185                 sap = NULL;
 1186         error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
 1187         if (error == 0 && uap->oact != NULL) {
 1188                 s32.sa_u = PTROUT(osa.sa_handler);
 1189                 CP(osa, s32, sa_flags);
 1190                 CP(osa, s32, sa_mask);
 1191                 error = copyout(&s32, uap->oact, sizeof(s32));
 1192         }
 1193         return (error);
 1194 }
 1195 #endif
 1196 
 1197 int
 1198 freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
 1199 {
 1200         struct timespec32 rmt32, rqt32;
 1201         struct timespec rmt, rqt;
 1202         int error;
 1203 
 1204         error = copyin(uap->rqtp, &rqt32, sizeof(rqt));
 1205         if (error)
 1206                 return (error);
 1207 
 1208         CP(rqt32, rqt, tv_sec);
 1209         CP(rqt32, rqt, tv_nsec);
 1210 
 1211         if (uap->rmtp &&
 1212             !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
 1213                 return (EFAULT);
 1214         error = kern_nanosleep(td, &rqt, &rmt);
 1215         if (error && uap->rmtp) {
 1216                 int error2;
 1217 
 1218                 CP(rmt, rmt32, tv_sec);
 1219                 CP(rmt, rmt32, tv_nsec);
 1220 
 1221                 error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt));
 1222                 if (error2)
 1223                         error = error2;
 1224         }
 1225         return (error);
 1226 }
 1227 
 1228 #if 0
 1229 
 1230 int
 1231 freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
 1232 {
 1233         int error;
 1234         caddr_t sg;
 1235         struct yyy32 *p32, s32;
 1236         struct yyy *p = NULL, s;
 1237 
 1238         p32 = uap->zzz;
 1239         if (p32) {
 1240                 sg = stackgap_init();
 1241                 p = stackgap_alloc(&sg, sizeof(struct yyy));
 1242                 uap->zzz = (struct yyy32 *)p;
 1243                 error = copyin(p32, &s32, sizeof(s32));
 1244                 if (error)
 1245                         return (error);
 1246                 /* translate in */
 1247                 error = copyout(&s, p, sizeof(s));
 1248                 if (error)
 1249                         return (error);
 1250         }
 1251         error = xxx(td, (struct xxx_args *) uap);
 1252         if (error)
 1253                 return (error);
 1254         if (p32) {
 1255                 error = copyin(p, &s, sizeof(s));
 1256                 if (error)
 1257                         return (error);
 1258                 /* translate out */
 1259                 error = copyout(&s32, p32, sizeof(s32));
 1260         }
 1261         return (error);
 1262 }
 1263 
 1264 #endif

Cache object: e5c87458cd144cef2b48446af5a4982e


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