root/compat/linux/linux_misc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bsd_to_linux_wstat
  2. linux_sys_waitpid
  3. linux_sys_wait4
  4. linux_sys_setresgid16
  5. linux_sys_getresgid16
  6. linux_sys_setresuid16
  7. linux_sys_getresuid16
  8. linux_sys_break
  9. linux_sys_brk
  10. linux_sys_time
  11. bsd_to_linux_statfs
  12. linux_sys_statfs
  13. linux_sys_fstatfs
  14. linux_sys_uname
  15. linux_sys_olduname
  16. linux_sys_oldolduname
  17. linux_sys_mmap
  18. linux_sys_mmap2
  19. linux_to_bsd_mmap_args
  20. linux_sys_mremap
  21. linux_sys_times
  22. linux_sys_pipe
  23. linux_sys_alarm
  24. linux_sys_utime
  25. linux_sys_readdir
  26. linux_readdir_callback
  27. linux_sys_getdents64
  28. linux_sys_getdents
  29. getdents_common
  30. linux_sys_oldselect
  31. linux_sys_select
  32. linux_select1
  33. linux_sys_getpgid
  34. linux_sys_personality
  35. linux_sys_setreuid16
  36. linux_sys_setregid16
  37. linux_sys_getsid
  38. linux_sys___sysctl
  39. linux_sys_setfsuid
  40. linux_sys_getfsuid
  41. linux_sys_nice
  42. linux_sys_stime
  43. linux_sys_getpid
  44. linux_sys_getuid
  45. linux_sys_getgid
  46. linux_sys_sysinfo

    1 /*      $OpenBSD: linux_misc.c,v 1.60 2007/02/06 18:42:37 art Exp $     */
    2 /*      $NetBSD: linux_misc.c,v 1.27 1996/05/20 01:59:21 fvdl Exp $     */
    3 
    4 /*-
    5  * Copyright (c) 1995, 1998, 1999 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Frank van der Linden and Eric Haszlakiewicz; by Jason R. Thorpe
   10  * of the Numerical Aerospace Simulation Facility, NASA Ames Research Center.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the NetBSD
   23  *      Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * Linux compatibility module. Try to deal with various Linux system calls.
   43  */
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/namei.h>
   48 #include <sys/proc.h>
   49 #include <sys/dirent.h>
   50 #include <sys/file.h>
   51 #include <sys/stat.h>
   52 #include <sys/filedesc.h>
   53 #include <sys/ioctl.h>
   54 #include <sys/kernel.h>
   55 #include <sys/malloc.h>
   56 #include <sys/mbuf.h>
   57 #include <sys/mman.h>
   58 #include <sys/mount.h>
   59 #include <sys/ptrace.h>
   60 #include <sys/resource.h>
   61 #include <sys/resourcevar.h>
   62 #include <sys/signal.h>
   63 #include <sys/signalvar.h>
   64 #include <sys/socket.h>
   65 #include <sys/time.h>
   66 #include <sys/times.h>
   67 #include <sys/vnode.h>
   68 #include <sys/uio.h>
   69 #include <sys/wait.h>
   70 #include <sys/utsname.h>
   71 #include <sys/unistd.h>
   72 
   73 #include <sys/syscallargs.h>
   74 
   75 #include <uvm/uvm_extern.h>
   76 
   77 #include <compat/linux/linux_types.h>
   78 #include <compat/linux/linux_fcntl.h>
   79 #include <compat/linux/linux_misc.h>
   80 #include <compat/linux/linux_mmap.h>
   81 #include <compat/linux/linux_sched.h>
   82 #include <compat/linux/linux_signal.h>
   83 #include <compat/linux/linux_syscallargs.h>
   84 #include <compat/linux/linux_util.h>
   85 #include <compat/linux/linux_dirent.h>
   86 #include <compat/linux/linux_emuldata.h>
   87 
   88 #include <compat/common/compat_dir.h>
   89 
   90 /* linux_misc.c */
   91 static void bsd_to_linux_statfs(struct statfs *, struct linux_statfs *);
   92 int     linux_select1(struct proc *, register_t *, int, fd_set *,
   93      fd_set *, fd_set *, struct timeval *);
   94 static int getdents_common(struct proc *, void *, register_t *, int);
   95 static void linux_to_bsd_mmap_args(struct sys_mmap_args *,
   96     const struct linux_sys_mmap2_args *);
   97 
   98 /*
   99  * The information on a terminated (or stopped) process needs
  100  * to be converted in order for Linux binaries to get a valid signal
  101  * number out of it.
  102  */
  103 void
  104 bsd_to_linux_wstat(status)
  105         int *status;
  106 {
  107 
  108         if (WIFSIGNALED(*status))
  109                 *status = (*status & ~0177) |
  110                     bsd_to_linux_sig[WTERMSIG(*status)];
  111         else if (WIFSTOPPED(*status))
  112                 *status = (*status & ~0xff00) |
  113                     (bsd_to_linux_sig[WSTOPSIG(*status)] << 8);
  114 }
  115 
  116 /*
  117  * waitpid(2). Just forward on to linux_sys_wait4 with a NULL rusage.
  118  */
  119 int
  120 linux_sys_waitpid(p, v, retval)
  121         struct proc *p;
  122         void *v;
  123         register_t *retval;
  124 {
  125         struct linux_sys_waitpid_args /* {
  126                 syscallarg(int) pid;
  127                 syscallarg(int *) status;
  128                 syscallarg(int) options;
  129         } */ *uap = v;
  130         struct sys_wait4_args linux_w4a;
  131 
  132         SCARG(&linux_w4a, pid) = SCARG(uap, pid);
  133         SCARG(&linux_w4a, status) = SCARG(uap, status);
  134         SCARG(&linux_w4a, options) = SCARG(uap, options);
  135         SCARG(&linux_w4a, rusage) = NULL;
  136 
  137         return (linux_sys_wait4(p, &linux_w4a, retval));
  138 }
  139 
  140 /*
  141  * wait4(2). Passed on to the OpenBSD call, surrounded by code to reserve
  142  * some space for an OpenBSD-style wait status, and converting it to what
  143  * Linux wants.
  144  */
  145 int
  146 linux_sys_wait4(p, v, retval)
  147         struct proc *p;
  148         void *v;
  149         register_t *retval;
  150 {
  151         struct linux_sys_wait4_args /* {
  152                 syscallarg(int) pid;
  153                 syscallarg(int *) status;
  154                 syscallarg(int) options;
  155                 syscallarg(struct rusage *) rusage;
  156         } */ *uap = v;
  157         struct sys_wait4_args w4a;
  158         int error, *status, tstat, linux_options, options;
  159         caddr_t sg;
  160 
  161         if (SCARG(uap, status) != NULL) {
  162                 sg = stackgap_init(p->p_emul);
  163                 status = (int *) stackgap_alloc(&sg, sizeof status);
  164         } else
  165                 status = NULL;
  166 
  167         linux_options = SCARG(uap, options);
  168         options = 0;
  169         if (linux_options &
  170             ~(LINUX_WAIT4_WNOHANG|LINUX_WAIT4_WUNTRACED|LINUX_WAIT4_WCLONE))
  171                 return (EINVAL);
  172 
  173         if (linux_options & LINUX_WAIT4_WNOHANG)
  174                 options |= WNOHANG;
  175         if (linux_options & LINUX_WAIT4_WUNTRACED)
  176                 options |= WUNTRACED;
  177         if (linux_options & LINUX_WAIT4_WCLONE)
  178                 options |= WALTSIG;
  179 
  180         SCARG(&w4a, pid) = SCARG(uap, pid);
  181         SCARG(&w4a, status) = status;
  182         SCARG(&w4a, options) = options;
  183         SCARG(&w4a, rusage) = SCARG(uap, rusage);
  184 
  185         if ((error = sys_wait4(p, &w4a, retval)))
  186                 return error;
  187 
  188         atomic_clearbits_int(&p->p_siglist, sigmask(SIGCHLD));
  189 
  190         if (status != NULL) {
  191                 if ((error = copyin(status, &tstat, sizeof tstat)))
  192                         return error;
  193 
  194                 bsd_to_linux_wstat(&tstat);
  195                 return copyout(&tstat, SCARG(uap, status), sizeof tstat);
  196         }
  197 
  198         return 0;
  199 }
  200 
  201 int
  202 linux_sys_setresgid16(p, v, retval)
  203         struct proc *p;
  204         void *v;
  205         register_t *retval;
  206 {
  207         struct linux_sys_setresgid16_args /* {
  208                 syscallarg(u_int16_t) rgid;
  209                 syscallarg(u_int16_t) egid;
  210                 syscallarg(u_int16_t) sgid;
  211         } */ *uap = v;
  212         struct sys_setresgid_args nuap;
  213         u_int16_t rgid, egid, sgid;
  214 
  215         rgid = SCARG(uap, rgid);
  216         SCARG(&nuap, rgid) = (rgid == (u_int16_t)-1) ? (gid_t)-1 : rgid;
  217         egid = SCARG(uap, egid);
  218         SCARG(&nuap, egid) = (egid == (u_int16_t)-1) ? (gid_t)-1 : egid;
  219         sgid = SCARG(uap, sgid);
  220         SCARG(&nuap, sgid) = (sgid == (u_int16_t)-1) ? (gid_t)-1 : sgid;
  221 
  222         return sys_setresgid(p, &nuap, retval);
  223 }
  224 
  225 int
  226 linux_sys_getresgid16(p, v, retval)
  227         struct proc *p;
  228         void *v;
  229         register_t *retval;
  230 {
  231         struct linux_sys_getresgid16_args /* {
  232                 syscallarg(u_int16_t *) rgid;
  233                 syscallarg(u_int16_t *) egid;
  234                 syscallarg(u_int16_t *) sgid;
  235         } */ *uap = v;
  236         struct sys_getresgid_args nuap;
  237 
  238         SCARG(&nuap, rgid) = (gid_t *)SCARG(uap, rgid);
  239         SCARG(&nuap, egid) = (gid_t *)SCARG(uap, egid);
  240         SCARG(&nuap, sgid) = (gid_t *)SCARG(uap, sgid);
  241 
  242         return sys_getresgid(p, &nuap, retval);
  243 }
  244 
  245 int
  246 linux_sys_setresuid16(p, v, retval)
  247         struct proc *p;
  248         void *v;
  249         register_t *retval;
  250 {
  251         struct linux_sys_setresuid16_args /* {
  252                 syscallarg(u_int16_t) ruid;
  253                 syscallarg(u_int16_t) euid;
  254                 syscallarg(u_int16_t) suid;
  255         } */ *uap = v;
  256         struct sys_setresuid_args nuap;
  257         u_int16_t ruid, euid, suid;
  258 
  259         ruid = SCARG(uap, ruid);
  260         SCARG(&nuap, ruid) = (ruid == (u_int16_t)-1) ? (uid_t)-1 : ruid;
  261         euid = SCARG(uap, euid);
  262         SCARG(&nuap, euid) = (euid == (u_int16_t)-1) ? (uid_t)-1 : euid;
  263         suid = SCARG(uap, suid);
  264         SCARG(&nuap, suid) = (suid == (u_int16_t)-1) ? (uid_t)-1 : suid;
  265 
  266         return sys_setresuid(p, &nuap, retval);
  267 }
  268 
  269 int
  270 linux_sys_getresuid16(p, v, retval)
  271         struct proc *p;
  272         void *v;
  273         register_t *retval;
  274 {
  275         struct linux_sys_getresuid16_args /* {
  276                 syscallarg(u_int16_t *) ruid;
  277                 syscallarg(u_int16_t *) euid;
  278                 syscallarg(u_int16_t *) suid;
  279         } */ *uap = v;
  280         struct sys_getresuid_args nuap;
  281 
  282         SCARG(&nuap, ruid) = (uid_t *)SCARG(uap, ruid);
  283         SCARG(&nuap, euid) = (uid_t *)SCARG(uap, euid);
  284         SCARG(&nuap, suid) = (uid_t *)SCARG(uap, suid);
  285 
  286         return sys_getresuid(p, &nuap, retval);
  287 }
  288 
  289 /*
  290  * This is the old brk(2) call. I don't think anything in the Linux
  291  * world uses this anymore
  292  */
  293 int
  294 linux_sys_break(p, v, retval)
  295         struct proc *p;
  296         void *v;
  297         register_t *retval;
  298 {
  299 #if 0
  300         struct linux_sys_brk_args /* {
  301                 syscallarg(char *) nsize;
  302         } */ *uap = v;
  303 #endif
  304 
  305         return ENOSYS;
  306 }
  307 
  308 /*
  309  * Linux brk(2). The check if the new address is >= the old one is
  310  * done in the kernel in Linux. OpenBSD does it in the library.
  311  */
  312 int
  313 linux_sys_brk(p, v, retval)
  314         struct proc *p;
  315         void *v;
  316         register_t *retval;
  317 {
  318         struct linux_sys_brk_args /* {
  319                 syscallarg(char *) nsize;
  320         } */ *uap = v;
  321         char *nbrk = SCARG(uap, nsize);
  322         struct sys_obreak_args oba;
  323         struct vmspace *vm = p->p_vmspace;
  324         struct linux_emuldata *ed = (struct linux_emuldata*)p->p_emuldata;
  325 
  326         SCARG(&oba, nsize) = nbrk;
  327 
  328         if ((caddr_t) nbrk > vm->vm_daddr && sys_obreak(p, &oba, retval) == 0)
  329                 ed->p_break = (char*)nbrk;
  330         else
  331                 nbrk = ed->p_break;
  332 
  333         retval[0] = (register_t)nbrk;
  334 
  335         return 0;
  336 }
  337 
  338 /*
  339  * I wonder why Linux has gettimeofday() _and_ time().. Still, we
  340  * need to deal with it.
  341  */
  342 int
  343 linux_sys_time(p, v, retval)
  344         struct proc *p;
  345         void *v;
  346         register_t *retval;
  347 {
  348         struct linux_sys_time_args /* {
  349                 linux_time_t *t;
  350         } */ *uap = v;
  351         struct timeval atv;
  352         linux_time_t tt;
  353         int error;
  354 
  355         microtime(&atv);
  356 
  357         tt = atv.tv_sec;
  358         if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt)))
  359                 return error;
  360 
  361         retval[0] = tt;
  362         return 0;
  363 }
  364 
  365 /*
  366  * Convert BSD statfs structure to Linux statfs structure.
  367  * The Linux structure has less fields, and it also wants
  368  * the length of a name in a dir entry in a field, which
  369  * we fake (probably the wrong way).
  370  */
  371 static void
  372 bsd_to_linux_statfs(bsp, lsp)
  373         struct statfs *bsp;
  374         struct linux_statfs *lsp;
  375 {
  376 
  377         /*
  378          * Convert BSD filesystem names to Linux filesystem type numbers
  379          * where possible.  Linux statfs uses a value of -1 to indicate
  380          * an unsupported field.
  381          */
  382         if (!strcmp(bsp->f_fstypename, MOUNT_FFS) ||
  383             !strcmp(bsp->f_fstypename, MOUNT_MFS))
  384                 lsp->l_ftype = 0x11954;
  385         else if (!strcmp(bsp->f_fstypename, MOUNT_NFS))
  386                 lsp->l_ftype = 0x6969;
  387         else if (!strcmp(bsp->f_fstypename, MOUNT_MSDOS))
  388                 lsp->l_ftype = 0x4d44;
  389         else if (!strcmp(bsp->f_fstypename, MOUNT_PROCFS))
  390                 lsp->l_ftype = 0x9fa0;
  391         else if (!strcmp(bsp->f_fstypename, MOUNT_EXT2FS))
  392                 lsp->l_ftype = 0xef53;
  393         else if (!strcmp(bsp->f_fstypename, MOUNT_CD9660))
  394                 lsp->l_ftype = 0x9660;
  395         else if (!strcmp(bsp->f_fstypename, MOUNT_NCPFS))
  396                 lsp->l_ftype = 0x6969;
  397         else
  398                 lsp->l_ftype = -1;
  399 
  400         lsp->l_fbsize = bsp->f_bsize;
  401         lsp->l_fblocks = bsp->f_blocks;
  402         lsp->l_fbfree = bsp->f_bfree;
  403         lsp->l_fbavail = bsp->f_bavail;
  404         lsp->l_ffiles = bsp->f_files;
  405         lsp->l_fffree = bsp->f_ffree;
  406         lsp->l_ffsid.val[0] = bsp->f_fsid.val[0];
  407         lsp->l_ffsid.val[1] = bsp->f_fsid.val[1];
  408         lsp->l_fnamelen = MAXNAMLEN;    /* XXX */
  409 }
  410 
  411 /*
  412  * Implement the fs stat functions. Straightforward.
  413  */
  414 int
  415 linux_sys_statfs(p, v, retval)
  416         struct proc *p;
  417         void *v;
  418         register_t *retval;
  419 {
  420         struct linux_sys_statfs_args /* {
  421                 syscallarg(char *) path;
  422                 syscallarg(struct linux_statfs *) sp;
  423         } */ *uap = v;
  424         struct statfs btmp, *bsp;
  425         struct linux_statfs ltmp;
  426         struct sys_statfs_args bsa;
  427         caddr_t sg;
  428         int error;
  429 
  430         sg = stackgap_init(p->p_emul);
  431         bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs));
  432 
  433         LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  434 
  435         SCARG(&bsa, path) = SCARG(uap, path);
  436         SCARG(&bsa, buf) = bsp;
  437 
  438         if ((error = sys_statfs(p, &bsa, retval)))
  439                 return error;
  440 
  441         if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp)))
  442                 return error;
  443 
  444         bsd_to_linux_statfs(&btmp, &ltmp);
  445 
  446         return copyout((caddr_t) &ltmp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
  447 }
  448 
  449 int
  450 linux_sys_fstatfs(p, v, retval)
  451         struct proc *p;
  452         void *v;
  453         register_t *retval;
  454 {
  455         struct linux_sys_fstatfs_args /* {
  456                 syscallarg(int) fd;
  457                 syscallarg(struct linux_statfs *) sp;
  458         } */ *uap = v;
  459         struct statfs btmp, *bsp;
  460         struct linux_statfs ltmp;
  461         struct sys_fstatfs_args bsa;
  462         caddr_t sg;
  463         int error;
  464 
  465         sg = stackgap_init(p->p_emul);
  466         bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs));
  467 
  468         SCARG(&bsa, fd) = SCARG(uap, fd);
  469         SCARG(&bsa, buf) = bsp;
  470 
  471         if ((error = sys_fstatfs(p, &bsa, retval)))
  472                 return error;
  473 
  474         if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp)))
  475                 return error;
  476 
  477         bsd_to_linux_statfs(&btmp, &ltmp);
  478 
  479         return copyout((caddr_t) &ltmp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
  480 }
  481 
  482 /*
  483  * uname(). Just copy the info from the various strings stored in the
  484  * kernel, and put it in the Linux utsname structure. That structure
  485  * is almost the same as the OpenBSD one, only it has fields 65 characters
  486  * long, and an extra domainname field.
  487  */
  488 int
  489 linux_sys_uname(p, v, retval)
  490         struct proc *p;
  491         void *v;
  492         register_t *retval;
  493 {
  494         struct linux_sys_uname_args /* {
  495                 syscallarg(struct linux_utsname *) up;
  496         } */ *uap = v;
  497         extern char hostname[], machine[], domainname[];
  498         struct linux_utsname luts;
  499         int len;
  500         char *cp;
  501 
  502         strlcpy(luts.l_sysname, ostype, sizeof(luts.l_sysname));
  503         strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
  504         strlcpy(luts.l_release, osrelease, sizeof(luts.l_release));
  505         strlcpy(luts.l_version, version, sizeof(luts.l_version));
  506         strlcpy(luts.l_machine, machine, sizeof(luts.l_machine));
  507         strlcpy(luts.l_domainname, domainname, sizeof(luts.l_domainname));
  508 
  509         /* This part taken from the uname() in libc */
  510         len = sizeof(luts.l_version);
  511         for (cp = luts.l_version; len--; ++cp)
  512                 if (*cp == '\n' || *cp == '\t')
  513                         *cp = (len > 1) ? ' ' : '\0';
  514 
  515         return copyout(&luts, SCARG(uap, up), sizeof(luts));
  516 }
  517 
  518 int
  519 linux_sys_olduname(p, v, retval)
  520         struct proc *p;
  521         void *v;
  522         register_t *retval;
  523 {
  524         struct linux_sys_uname_args /* {
  525                 syscallarg(struct linux_oldutsname *) up;
  526         } */ *uap = v;
  527         extern char hostname[], machine[];
  528         struct linux_oldutsname luts;
  529         int len;
  530         char *cp;
  531 
  532         strlcpy(luts.l_sysname, ostype, sizeof(luts.l_sysname));
  533         strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
  534         strlcpy(luts.l_release, osrelease, sizeof(luts.l_release));
  535         strlcpy(luts.l_version, version, sizeof(luts.l_version));
  536         strlcpy(luts.l_machine, machine, sizeof(luts.l_machine));
  537 
  538         /* This part taken from the uname() in libc */
  539         len = sizeof(luts.l_version);
  540         for (cp = luts.l_version; len--; ++cp)
  541                 if (*cp == '\n' || *cp == '\t')
  542                         *cp = (len > 1) ? ' ' : '\0';
  543 
  544         return copyout(&luts, SCARG(uap, up), sizeof(luts));
  545 }
  546 
  547 int
  548 linux_sys_oldolduname(p, v, retval)
  549         struct proc *p;
  550         void *v;
  551         register_t *retval;
  552 {
  553         struct linux_sys_uname_args /* {
  554                 syscallarg(struct linux_oldoldutsname *) up;
  555         } */ *uap = v;
  556         extern char hostname[], machine[];
  557         struct linux_oldoldutsname luts;
  558         int len;
  559         char *cp;
  560 
  561         strlcpy(luts.l_sysname, ostype, sizeof(luts.l_sysname));
  562         strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
  563         strlcpy(luts.l_release, osrelease, sizeof(luts.l_release));
  564         strlcpy(luts.l_version, version, sizeof(luts.l_version));
  565         strlcpy(luts.l_machine, machine, sizeof(luts.l_machine));
  566 
  567         /* This part taken from the uname() in libc */
  568         len = sizeof(luts.l_version);
  569         for (cp = luts.l_version; len--; ++cp)
  570                 if (*cp == '\n' || *cp == '\t')
  571                         *cp = (len > 1) ? ' ' : '\0';
  572 
  573         return copyout(&luts, SCARG(uap, up), sizeof(luts));
  574 }
  575 
  576 /*
  577  * Linux wants to pass everything to a syscall in registers. However,
  578  * mmap() has 6 of them. Oops: out of register error. They just pass
  579  * everything in a structure.
  580  */
  581 int
  582 linux_sys_mmap(p, v, retval)
  583         struct proc *p;
  584         void *v;
  585         register_t *retval;
  586 {
  587         struct linux_sys_mmap_args /* {
  588                 syscallarg(struct linux_mmap *) lmp;
  589         } */ *uap = v;
  590         struct linux_mmap lmap;
  591         struct linux_sys_mmap2_args nlmap;
  592         struct sys_mmap_args cma;
  593         int error;
  594 
  595         if ((error = copyin(SCARG(uap, lmp), &lmap, sizeof lmap)))
  596                 return error;
  597 
  598         if (lmap.lm_pos & PAGE_MASK)
  599                 return EINVAL;
  600 
  601         /* repackage into something sane */
  602         SCARG(&nlmap,addr) = (unsigned long)lmap.lm_addr;
  603         SCARG(&nlmap,len) = lmap.lm_len;
  604         SCARG(&nlmap,prot) = lmap.lm_prot;
  605         SCARG(&nlmap,flags) = lmap.lm_flags;
  606         SCARG(&nlmap,fd) = lmap.lm_fd;
  607         SCARG(&nlmap,offset) = (unsigned)lmap.lm_pos;
  608 
  609         linux_to_bsd_mmap_args(&cma, &nlmap);
  610         SCARG(&cma, pos) = (off_t)SCARG(&nlmap, offset);
  611 
  612         return sys_mmap(p, &cma, retval);
  613 }
  614 
  615 /*
  616  * Guts of most architectures' mmap64() implementations.  This shares
  617  * its list of arguments with linux_sys_mmap().
  618  *
  619  * The difference in linux_sys_mmap2() is that "offset" is actually
  620  * (offset / pagesize), not an absolute byte count.  This translation
  621  * to pagesize offsets is done inside glibc between the mmap64() call
  622  * point, and the actual syscall.
  623  */
  624 int
  625 linux_sys_mmap2(p, v, retval)
  626         struct proc *p;
  627         void *v;
  628         register_t *retval;
  629 {
  630         struct linux_sys_mmap2_args /* {
  631                 syscallarg(unsigned long) addr;
  632                 syscallarg(size_t) len;
  633                 syscallarg(int) prot;
  634                 syscallarg(int) flags;
  635                 syscallarg(int) fd;
  636                 syscallarg(linux_off_t) offset;
  637         } */ *uap = v;
  638         struct sys_mmap_args cma;
  639 
  640         linux_to_bsd_mmap_args(&cma, uap);
  641         SCARG(&cma, pos) = ((off_t)SCARG(uap, offset)) << PAGE_SHIFT;
  642 
  643         return sys_mmap(p, &cma, retval);
  644 }
  645 
  646 static void
  647 linux_to_bsd_mmap_args(cma, uap)
  648         struct sys_mmap_args *cma;
  649         const struct linux_sys_mmap2_args *uap;
  650 {
  651         int flags = MAP_TRYFIXED, fl = SCARG(uap, flags);
  652         
  653         flags |= cvtto_bsd_mask(fl, LINUX_MAP_SHARED, MAP_SHARED);
  654         flags |= cvtto_bsd_mask(fl, LINUX_MAP_PRIVATE, MAP_PRIVATE);
  655         flags |= cvtto_bsd_mask(fl, LINUX_MAP_FIXED, MAP_FIXED);
  656         flags |= cvtto_bsd_mask(fl, LINUX_MAP_ANON, MAP_ANON);
  657         /* XXX XAX ERH: Any other flags here?  There are more defined... */
  658 
  659         SCARG(cma, addr) = (void *)SCARG(uap, addr);
  660         SCARG(cma, len) = SCARG(uap, len);
  661         SCARG(cma, prot) = SCARG(uap, prot);
  662         if (SCARG(cma, prot) & VM_PROT_WRITE) /* XXX */
  663                 SCARG(cma, prot) |= VM_PROT_READ;
  664         SCARG(cma, flags) = flags;
  665         SCARG(cma, fd) = flags & MAP_ANON ? -1 : SCARG(uap, fd);
  666         SCARG(cma, pad) = 0;
  667 }
  668 
  669 int
  670 linux_sys_mremap(p, v, retval)
  671         struct proc *p;
  672         void *v;
  673         register_t *retval;
  674 {
  675 
  676         struct linux_sys_mremap_args /* {
  677                 syscallarg(void *) old_address;
  678                 syscallarg(size_t) old_size;
  679                 syscallarg(size_t) new_size;
  680                 syscallarg(u_long) flags;
  681         } */ *uap = v;
  682         struct sys_munmap_args mua;
  683         size_t old_size, new_size;
  684         int error;
  685  
  686         old_size = round_page(SCARG(uap, old_size));
  687         new_size = round_page(SCARG(uap, new_size));
  688  
  689         /*
  690          * Growing mapped region.
  691          */
  692         if (new_size > old_size) {
  693                 /*
  694                  * XXX Implement me.  What we probably want to do is
  695                  * XXX dig out the guts of the old mapping, mmap that
  696                  * XXX object again with the new size, then munmap
  697                  * XXX the old mapping.
  698                  */
  699                 *retval = 0;
  700                 return (ENOMEM);
  701         }
  702         /*
  703          * Shrinking mapped region.
  704          */
  705         if (new_size < old_size) {
  706                 SCARG(&mua, addr) = (caddr_t)SCARG(uap, old_address) + new_size;
  707                 SCARG(&mua, len) = old_size - new_size;
  708                 error = sys_munmap(p, &mua, retval);
  709                 *retval = error ? 0 : (register_t)SCARG(uap, old_address);
  710                 return (error);
  711         }
  712  
  713         /*
  714          * No change.
  715          */
  716         *retval = (register_t)SCARG(uap, old_address);
  717         return (0);
  718 
  719 }
  720 
  721 /*
  722  * This code is partly stolen from src/lib/libc/gen/times.c
  723  * XXX - CLK_TCK isn't declared in /sys, just in <time.h>, done here
  724  */
  725 
  726 #define CLK_TCK 100
  727 #define CONVTCK(r)      (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
  728 
  729 int
  730 linux_sys_times(p, v, retval)
  731         struct proc *p;
  732         void *v;
  733         register_t *retval;
  734 {
  735         struct linux_sys_times_args /* {
  736                 syscallarg(struct times *) tms;
  737         } */ *uap = v;
  738         struct timeval t;
  739         struct linux_tms ltms;
  740         struct rusage ru;
  741         int error;
  742 
  743         calcru(p, &ru.ru_utime, &ru.ru_stime, NULL);
  744         ltms.ltms_utime = CONVTCK(ru.ru_utime);
  745         ltms.ltms_stime = CONVTCK(ru.ru_stime);
  746 
  747         ltms.ltms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
  748         ltms.ltms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
  749 
  750         if ((error = copyout(&ltms, SCARG(uap, tms), sizeof ltms)))
  751                 return error;
  752 
  753         microuptime(&t);
  754 
  755         retval[0] = ((linux_clock_t)(CONVTCK(t)));
  756         return 0;
  757 }
  758 
  759 /*
  760  * OpenBSD passes fd[0] in retval[0], and fd[1] in retval[1].
  761  * Linux directly passes the pointer.
  762  */
  763 int
  764 linux_sys_pipe(p, v, retval)
  765         struct proc *p;
  766         void *v;
  767         register_t *retval;
  768 {
  769         struct linux_sys_pipe_args /* {
  770                 syscallarg(int *) pfds;
  771         } */ *uap = v;
  772         int error;
  773         int pfds[2];
  774 #ifdef __i386__
  775         int reg_edx = retval[1];
  776 #endif /* __i386__ */
  777 
  778         if ((error = sys_opipe(p, 0, retval))) {
  779 #ifdef __i386__
  780                 retval[1] = reg_edx;
  781 #endif /* __i386__ */
  782                 return error;
  783         }
  784 
  785         /* Assumes register_t is an int */
  786 
  787         pfds[0] = retval[0];
  788         pfds[1] = retval[1];
  789         if ((error = copyout(pfds, SCARG(uap, pfds), 2 * sizeof (int)))) {
  790 #ifdef __i386__
  791                 retval[1] = reg_edx;
  792 #endif /* __i386__ */
  793                 fdrelease(p, retval[0]);
  794                 fdrelease(p, retval[1]);
  795                 return error;
  796         }
  797 
  798         retval[0] = 0;
  799 #ifdef __i386__
  800         retval[1] = reg_edx;
  801 #endif /* __i386__ */
  802         return 0;
  803 }
  804 
  805 /*
  806  * Alarm. This is a libc call which uses setitimer(2) in OpenBSD.
  807  * Fiddle with the timers to make it work.
  808  */
  809 int
  810 linux_sys_alarm(p, v, retval)
  811         struct proc *p;
  812         void *v;
  813         register_t *retval;
  814 {
  815         struct linux_sys_alarm_args /* {
  816                 syscallarg(unsigned int) secs;
  817         } */ *uap = v;
  818         int s;
  819         struct itimerval *itp, it;
  820         struct timeval tv;
  821         int timo;
  822 
  823         itp = &p->p_realtimer;
  824         s = splclock();
  825         /*
  826          * Clear any pending timer alarms.
  827          */
  828         getmicrouptime(&tv);
  829         timeout_del(&p->p_realit_to);
  830         timerclear(&itp->it_interval);
  831         if (timerisset(&itp->it_value) &&
  832             timercmp(&itp->it_value, &tv, >))
  833                 timersub(&itp->it_value, &tv, &itp->it_value);
  834         /*
  835          * Return how many seconds were left (rounded up)
  836          */
  837         retval[0] = itp->it_value.tv_sec;
  838         if (itp->it_value.tv_usec)
  839                 retval[0]++;
  840 
  841         /*
  842          * alarm(0) just resets the timer.
  843          */
  844         if (SCARG(uap, secs) == 0) {
  845                 timerclear(&itp->it_value);
  846                 splx(s);
  847                 return 0;
  848         }
  849 
  850         /*
  851          * Check the new alarm time for sanity, and set it.
  852          */
  853         timerclear(&it.it_interval);
  854         it.it_value.tv_sec = SCARG(uap, secs);
  855         it.it_value.tv_usec = 0;
  856         if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) {
  857                 splx(s);
  858                 return (EINVAL);
  859         }
  860 
  861         if (timerisset(&it.it_value)) {
  862                 timo = tvtohz(&it.it_value);
  863                 timeradd(&it.it_value, &tv, &it.it_value);
  864                 timeout_add(&p->p_realit_to, timo);
  865         }
  866         p->p_realtimer = it;
  867         splx(s);
  868 
  869         return 0;
  870 }
  871 
  872 /*
  873  * utime(). Do conversion to things that utimes() understands, 
  874  * and pass it on.
  875  */
  876 int
  877 linux_sys_utime(p, v, retval)
  878         struct proc *p;
  879         void *v;
  880         register_t *retval;
  881 {
  882         struct linux_sys_utime_args /* {
  883                 syscallarg(char *) path;
  884                 syscallarg(struct linux_utimbuf *)times;
  885         } */ *uap = v;
  886         caddr_t sg;
  887         int error;
  888         struct sys_utimes_args ua;
  889         struct timeval tv[2], *tvp;
  890         struct linux_utimbuf lut;
  891 
  892         sg = stackgap_init(p->p_emul);
  893         tvp = (struct timeval *) stackgap_alloc(&sg, sizeof(tv));
  894         LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  895 
  896         SCARG(&ua, path) = SCARG(uap, path);
  897 
  898         if (SCARG(uap, times) != NULL) {
  899                 if ((error = copyin(SCARG(uap, times), &lut, sizeof lut)))
  900                         return error;
  901                 tv[0].tv_usec = tv[1].tv_usec = 0;
  902                 tv[0].tv_sec = lut.l_actime;
  903                 tv[1].tv_sec = lut.l_modtime;
  904                 if ((error = copyout(tv, tvp, sizeof tv)))
  905                         return error;
  906                 SCARG(&ua, tptr) = tvp;
  907         }
  908         else
  909                 SCARG(&ua, tptr) = NULL;
  910 
  911         return sys_utimes(p, &ua, retval);
  912 }
  913 
  914 /*
  915  * The old Linux readdir was only able to read one entry at a time,
  916  * even though it had a 'count' argument. In fact, the emulation
  917  * of the old call was better than the original, because it did handle
  918  * the count arg properly. Don't bother with it anymore now, and use
  919  * it to distinguish between old and new. The difference is that the
  920  * newer one actually does multiple entries, and the reclen field
  921  * really is the reclen, not the namelength.
  922  */
  923 int
  924 linux_sys_readdir(p, v, retval)
  925         struct proc *p;
  926         void *v;
  927         register_t *retval;
  928 {
  929         struct linux_sys_readdir_args /* {
  930                 syscallarg(int) fd;
  931                 syscallarg(struct linux_dirent *) dent;
  932                 syscallarg(unsigned int) count;
  933         } */ *uap = v;
  934 
  935         SCARG(uap, count) = 1;
  936 
  937         return linux_sys_getdents(p, uap, retval);
  938 }
  939 
  940 /*
  941  * Linux 'readdir' call. This code is mostly taken from the
  942  * SunOS getdents call (see compat/sunos/sunos_misc.c), though
  943  * an attempt has been made to keep it a little cleaner (failing
  944  * miserably, because of the cruft needed if count 1 is passed).
  945  *
  946  * The d_off field should contain the offset of the next valid entry,
  947  * but in Linux it has the offset of the entry itself. We emulate
  948  * that bug here.
  949  *
  950  * Read in BSD-style entries, convert them, and copy them out.
  951  *
  952  * Note that this doesn't handle union-mounted filesystems.
  953  */
  954 int linux_readdir_callback(void *, struct dirent *, off_t);
  955 
  956 struct linux_readdir_callback_args {
  957         caddr_t outp;
  958         int     resid;
  959         int     oldcall;
  960         int     is64bit;
  961 };
  962 
  963 int
  964 linux_readdir_callback(arg, bdp, cookie)
  965         void *arg;
  966         struct dirent *bdp;
  967         off_t cookie;
  968 {
  969         struct linux_dirent64 idb64;
  970         struct linux_dirent idb;
  971         struct linux_readdir_callback_args *cb = arg;
  972         int linux_reclen;
  973         int error;
  974 
  975         if (cb->oldcall == 2) 
  976                 return (ENOMEM);
  977 
  978         linux_reclen = (cb->is64bit) ?
  979              LINUX_RECLEN(&idb64, bdp->d_namlen) :
  980              LINUX_RECLEN(&idb, bdp->d_namlen);
  981 
  982         if (cb->resid < linux_reclen)
  983                 return (ENOMEM);
  984 
  985         if (cb->is64bit) {
  986                 idb64.d_ino = (linux_ino64_t)bdp->d_fileno;
  987                 idb64.d_off = (linux_off64_t)cookie;
  988                 idb64.d_reclen = (u_short)linux_reclen;
  989                 idb64.d_type = bdp->d_type;
  990                 strlcpy(idb64.d_name, bdp->d_name, sizeof(idb64.d_name));
  991                 error = copyout((caddr_t)&idb64, cb->outp, linux_reclen);
  992         } else {
  993                 idb.d_ino = (linux_ino_t)bdp->d_fileno;
  994                 if (cb->oldcall) {
  995                         /*
  996                          * The old readdir() call misuses the offset
  997                          * and reclen fields.
  998                          */
  999                         idb.d_off = (linux_off_t)linux_reclen;
 1000                         idb.d_reclen = (u_short)bdp->d_namlen;
 1001                 } else {
 1002                         idb.d_off = (linux_off_t)cookie;
 1003                         idb.d_reclen = (u_short)linux_reclen;
 1004                 }
 1005                 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
 1006                 error = copyout((caddr_t)&idb, cb->outp, linux_reclen);
 1007         }
 1008         if (error)
 1009                 return (error);
 1010 
 1011         /* advance output past Linux-shaped entry */
 1012         cb->outp += linux_reclen;
 1013         cb->resid -= linux_reclen;
 1014 
 1015         if (cb->oldcall == 1)
 1016                 ++cb->oldcall;
 1017         
 1018         return (0);
 1019 }
 1020 
 1021 int
 1022 linux_sys_getdents64(p, v, retval)
 1023         struct proc *p;
 1024         void *v;
 1025         register_t *retval;
 1026 {
 1027         return getdents_common(p, v, retval, 1);
 1028 }
 1029 
 1030 int
 1031 linux_sys_getdents(p, v, retval)
 1032         struct proc *p;
 1033         void *v;
 1034         register_t *retval;
 1035 {
 1036         return getdents_common(p, v, retval, 0);
 1037 }
 1038 
 1039 static int
 1040 getdents_common(p, v, retval, is64bit)
 1041         struct proc *p;
 1042         void *v;
 1043         register_t *retval;
 1044         int is64bit;
 1045 {
 1046         struct linux_sys_getdents_args /* {
 1047                 syscallarg(int) fd;
 1048                 syscallarg(void *) dirent;
 1049                 syscallarg(unsigned) count;
 1050         } */ *uap = v;
 1051         struct linux_readdir_callback_args args;
 1052         struct file *fp;
 1053         int error;
 1054         int nbytes = SCARG(uap, count);
 1055 
 1056         if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 1057                 return (error);
 1058 
 1059         if (nbytes == 1) {      /* emulating old, broken behaviour */
 1060                 /* readdir(2) case. Always struct dirent. */
 1061                 if (is64bit) {
 1062                         FRELE(fp);
 1063                         return (EINVAL);
 1064                 }
 1065                 nbytes = sizeof(struct linux_dirent);
 1066                 args.oldcall = 1;
 1067         } else {
 1068                 args.oldcall = 0;
 1069         }
 1070 
 1071         args.resid = nbytes;
 1072         args.outp = (caddr_t)SCARG(uap, dirent);
 1073         args.is64bit = is64bit;
 1074 
 1075         if ((error = readdir_with_callback(fp, &fp->f_offset, nbytes,
 1076             linux_readdir_callback, &args)) != 0)
 1077                 goto exit;
 1078 
 1079         *retval = nbytes - args.resid;
 1080 
 1081  exit:
 1082         FRELE(fp);
 1083         return (error);
 1084 }
 1085 
 1086 /*
 1087  * Not sure why the arguments to this older version of select() were put
 1088  * into a structure, because there are 5, and that can all be handled
 1089  * in registers on the i386 like Linux wants to.
 1090  */
 1091 int
 1092 linux_sys_oldselect(p, v, retval)
 1093         struct proc *p;
 1094         void *v;
 1095         register_t *retval;
 1096 {
 1097         struct linux_sys_oldselect_args /* {
 1098                 syscallarg(struct linux_select *) lsp;
 1099         } */ *uap = v;
 1100         struct linux_select ls;
 1101         int error;
 1102 
 1103         if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
 1104                 return error;
 1105 
 1106         return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
 1107             ls.exceptfds, ls.timeout);
 1108 }
 1109 
 1110 /*
 1111  * Even when just using registers to pass arguments to syscalls you can
 1112  * have 5 of them on the i386. So this newer version of select() does
 1113  * this.
 1114  */
 1115 int
 1116 linux_sys_select(p, v, retval)
 1117         struct proc *p;
 1118         void *v;
 1119         register_t *retval;
 1120 {
 1121         struct linux_sys_select_args /* {
 1122                 syscallarg(int) nfds;
 1123                 syscallarg(fd_set *) readfds;
 1124                 syscallarg(fd_set *) writefds;
 1125                 syscallarg(fd_set *) exceptfds;
 1126                 syscallarg(struct timeval *) timeout;
 1127         } */ *uap = v;
 1128 
 1129         return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
 1130             SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
 1131 }
 1132 
 1133 /*
 1134  * Common code for the old and new versions of select(). A couple of
 1135  * things are important:
 1136  * 1) return the amount of time left in the 'timeout' parameter
 1137  * 2) select never returns ERESTART on Linux, always return EINTR
 1138  */
 1139 int
 1140 linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
 1141         struct proc *p;
 1142         register_t *retval;
 1143         int nfds;
 1144         fd_set *readfds, *writefds, *exceptfds;
 1145         struct timeval *timeout;
 1146 {
 1147         struct sys_select_args bsa;
 1148         struct timeval tv0, tv1, utv, *tvp;
 1149         caddr_t sg;
 1150         int error;
 1151 
 1152         SCARG(&bsa, nd) = nfds;
 1153         SCARG(&bsa, in) = readfds;
 1154         SCARG(&bsa, ou) = writefds;
 1155         SCARG(&bsa, ex) = exceptfds;
 1156         SCARG(&bsa, tv) = timeout;
 1157 
 1158         /*
 1159          * Store current time for computation of the amount of
 1160          * time left.
 1161          */
 1162         if (timeout) {
 1163                 if ((error = copyin(timeout, &utv, sizeof(utv))))
 1164                         return error;
 1165                 if (itimerfix(&utv)) {
 1166                         /*
 1167                          * The timeval was invalid.  Convert it to something
 1168                          * valid that will act as it does under Linux.
 1169                          */
 1170                         sg = stackgap_init(p->p_emul);
 1171                         tvp = stackgap_alloc(&sg, sizeof(utv));
 1172                         utv.tv_sec += utv.tv_usec / 1000000;
 1173                         utv.tv_usec %= 1000000;
 1174                         if (utv.tv_usec < 0) {
 1175                                 utv.tv_sec -= 1;
 1176                                 utv.tv_usec += 1000000;
 1177                         }
 1178                         if (utv.tv_sec < 0)
 1179                                 timerclear(&utv);
 1180                         if ((error = copyout(&utv, tvp, sizeof(utv))))
 1181                                 return error;
 1182                         SCARG(&bsa, tv) = tvp;
 1183                 }
 1184                 microtime(&tv0);
 1185         }
 1186 
 1187         error = sys_select(p, &bsa, retval);
 1188         if (error) {
 1189                 /*
 1190                  * See fs/select.c in the Linux kernel.  Without this,
 1191                  * Maelstrom doesn't work.
 1192                  */
 1193                 if (error == ERESTART)
 1194                         error = EINTR;
 1195                 return error;
 1196         }
 1197 
 1198         if (timeout) {
 1199                 if (*retval) {
 1200                         /*
 1201                          * Compute how much time was left of the timeout,
 1202                          * by subtracting the current time and the time
 1203                          * before we started the call, and subtracting
 1204                          * that result from the user-supplied value.
 1205                          */
 1206                         microtime(&tv1);
 1207                         timersub(&tv1, &tv0, &tv1);
 1208                         timersub(&utv, &tv1, &utv);
 1209                         if (utv.tv_sec < 0)
 1210                                 timerclear(&utv);
 1211                 } else
 1212                         timerclear(&utv);
 1213                 if ((error = copyout(&utv, timeout, sizeof(utv))))
 1214                         return error;
 1215         }
 1216 
 1217         return 0;
 1218 }
 1219 
 1220 /*
 1221  * Get the process group of a certain process. Look it up
 1222  * and return the value.
 1223  */
 1224 int
 1225 linux_sys_getpgid(p, v, retval)
 1226         struct proc *p;
 1227         void *v;
 1228         register_t *retval;
 1229 {
 1230         struct linux_sys_getpgid_args /* {
 1231                 syscallarg(int) pid;
 1232         } */ *uap = v;
 1233         struct proc *targp;
 1234 
 1235         if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != p->p_pid) {
 1236                 if ((targp = pfind(SCARG(uap, pid))) == 0)
 1237                         return ESRCH;
 1238         }
 1239         else
 1240                 targp = p;
 1241 
 1242         retval[0] = targp->p_pgid;
 1243         return 0;
 1244 }
 1245 
 1246 /*
 1247  * Set the 'personality' (emulation mode) for the current process. Only
 1248  * accept the Linux personality here (0). This call is needed because
 1249  * the Linux ELF crt0 issues it in an ugly kludge to make sure that
 1250  * ELF binaries run in Linux mode, not SVR4 mode.
 1251  */
 1252 int
 1253 linux_sys_personality(p, v, retval)
 1254         struct proc *p;
 1255         void *v;
 1256         register_t *retval;
 1257 {
 1258         struct linux_sys_personality_args /* {
 1259                 syscallarg(int) per;
 1260         } */ *uap = v;
 1261 
 1262         if (SCARG(uap, per) != 0)
 1263                 return EINVAL;
 1264         retval[0] = 0;
 1265         return 0;
 1266 }
 1267 
 1268 /*
 1269  * The calls are here because of type conversions.
 1270  */
 1271 int
 1272 linux_sys_setreuid16(p, v, retval)
 1273         struct proc *p;
 1274         void *v;
 1275         register_t *retval;
 1276 {
 1277         struct linux_sys_setreuid16_args /* {
 1278                 syscallarg(int) ruid;
 1279                 syscallarg(int) euid;
 1280         } */ *uap = v;
 1281         struct sys_setreuid_args bsa;
 1282         
 1283         SCARG(&bsa, ruid) = ((linux_uid_t)SCARG(uap, ruid) == (linux_uid_t)-1) ?
 1284                 (uid_t)-1 : SCARG(uap, ruid);
 1285         SCARG(&bsa, euid) = ((linux_uid_t)SCARG(uap, euid) == (linux_uid_t)-1) ?
 1286                 (uid_t)-1 : SCARG(uap, euid);
 1287 
 1288         return sys_setreuid(p, &bsa, retval);
 1289 }
 1290 
 1291 int
 1292 linux_sys_setregid16(p, v, retval)
 1293         struct proc *p;
 1294         void *v;
 1295         register_t *retval;
 1296 {
 1297         struct linux_sys_setregid16_args /* {
 1298                 syscallarg(int) rgid;
 1299                 syscallarg(int) egid;
 1300         } */ *uap = v;
 1301         struct sys_setregid_args bsa;
 1302         
 1303         SCARG(&bsa, rgid) = ((linux_gid_t)SCARG(uap, rgid) == (linux_gid_t)-1) ?
 1304                 (uid_t)-1 : SCARG(uap, rgid);
 1305         SCARG(&bsa, egid) = ((linux_gid_t)SCARG(uap, egid) == (linux_gid_t)-1) ?
 1306                 (uid_t)-1 : SCARG(uap, egid);
 1307 
 1308         return sys_setregid(p, &bsa, retval);
 1309 }
 1310 
 1311 int
 1312 linux_sys_getsid(p, v, retval)
 1313         struct proc *p;
 1314         void *v;
 1315         register_t *retval;
 1316 {
 1317         struct linux_sys_getsid_args /* {
 1318                 syscallarg(int) pid;
 1319         } */ *uap = v;
 1320         struct proc *p1;
 1321         pid_t pid;
 1322 
 1323         pid = (pid_t)SCARG(uap, pid);
 1324 
 1325         if (pid == 0) {
 1326                 retval[0] = (int)p->p_session;  /* XXX Oh well */
 1327                 return 0;
 1328         }
 1329 
 1330         p1 = pfind((int)pid);
 1331         if (p1 == NULL)
 1332                 return ESRCH;
 1333 
 1334         retval[0] = (int)p1->p_session;
 1335         return 0;
 1336 }
 1337 
 1338 int
 1339 linux_sys___sysctl(p, v, retval)
 1340         struct proc *p;
 1341         void *v;
 1342         register_t *retval;
 1343 {
 1344         struct linux_sys___sysctl_args /* {
 1345                 syscallarg(struct linux___sysctl *) lsp;
 1346         } */ *uap = v;
 1347         struct linux___sysctl ls;
 1348         struct sys___sysctl_args bsa;
 1349         int error;
 1350 
 1351         if ((error = copyin(SCARG(uap, lsp), &ls, sizeof ls)))
 1352                 return error;
 1353         SCARG(&bsa, name) = ls.name;
 1354         SCARG(&bsa, namelen) = ls.namelen;
 1355         SCARG(&bsa, old) = ls.old;
 1356         SCARG(&bsa, oldlenp) = ls.oldlenp;
 1357         SCARG(&bsa, new) = ls.new;
 1358         SCARG(&bsa, newlen) = ls.newlen;
 1359 
 1360         return sys___sysctl(p, &bsa, retval);
 1361 }
 1362 
 1363 /*
 1364  * We have nonexistent fsuid equal to uid.
 1365  * If modification is requested, refuse.
 1366  */
 1367 int
 1368 linux_sys_setfsuid(p, v, retval)
 1369          struct proc *p;
 1370          void *v;
 1371          register_t *retval;
 1372 {
 1373          struct linux_sys_setfsuid_args /* {
 1374                  syscallarg(uid_t) uid;
 1375          } */ *uap = v;
 1376          uid_t uid;
 1377 
 1378          uid = SCARG(uap, uid);
 1379          if (p->p_cred->p_ruid != uid)
 1380                  return sys_nosys(p, v, retval);
 1381          else
 1382                  return (0);
 1383 }
 1384 
 1385 int
 1386 linux_sys_getfsuid(p, v, retval)
 1387         struct proc *p;
 1388         void *v;
 1389         register_t *retval;
 1390 {
 1391         return sys_getuid(p, v, retval);
 1392 }
 1393 
 1394 
 1395 int
 1396 linux_sys_nice(p, v, retval)
 1397         struct proc *p;
 1398         void *v;
 1399         register_t *retval;
 1400 {
 1401         struct linux_sys_nice_args /* {
 1402                 syscallarg(int) incr;
 1403         } */ *uap = v;
 1404         struct sys_setpriority_args bsa;
 1405 
 1406         SCARG(&bsa, which) = PRIO_PROCESS;
 1407         SCARG(&bsa, who) = 0;
 1408         SCARG(&bsa, prio) = SCARG(uap, incr);
 1409         return sys_setpriority(p, &bsa, retval);
 1410 }
 1411 
 1412 int
 1413 linux_sys_stime(p, v, retval)
 1414         struct proc *p;
 1415         void *v;
 1416         register_t *retval;
 1417 {
 1418         struct linux_sys_time_args /* {
 1419                 linux_time_t *t;
 1420         } */ *uap = v;
 1421         struct timespec ats;
 1422         linux_time_t tt;
 1423         int error;
 1424 
 1425         if ((error = suser(p, 0)) != 0)
 1426                 return (error);
 1427 
 1428         if ((error = copyin(SCARG(uap, t), &tt, sizeof(tt))) != 0)
 1429                 return (error);
 1430 
 1431         ats.tv_sec = tt;
 1432         ats.tv_nsec = 0;
 1433 
 1434         error = settime(&ats);
 1435 
 1436         return (error);
 1437 }
 1438 
 1439 int
 1440 linux_sys_getpid(p, v, retval)
 1441         struct proc *p;
 1442         void *v;
 1443         register_t *retval;
 1444 {
 1445 
 1446         *retval = p->p_pid;
 1447         return (0);
 1448 }
 1449 
 1450 int
 1451 linux_sys_getuid(p, v, retval)
 1452         struct proc *p;
 1453         void *v;
 1454         register_t *retval;
 1455 {
 1456 
 1457         *retval = p->p_cred->p_ruid;
 1458         return (0);
 1459 }
 1460 
 1461 int
 1462 linux_sys_getgid(p, v, retval)
 1463         struct proc *p;
 1464         void *v;
 1465         register_t *retval;
 1466 {
 1467 
 1468         *retval = p->p_cred->p_rgid;
 1469         return (0);
 1470 }
 1471 
 1472 
 1473 /*
 1474  * sysinfo()
 1475  */
 1476 /* ARGSUSED */
 1477 int
 1478 linux_sys_sysinfo(p, v, retval)
 1479         struct proc *p;
 1480         void *v;
 1481         register_t *retval;
 1482 {
 1483         struct linux_sys_sysinfo_args /* {
 1484                 syscallarg(struct linux_sysinfo *) sysinfo;
 1485         } */ *uap = v;
 1486         struct linux_sysinfo si;
 1487         struct loadavg *la;
 1488         extern int bufpages;
 1489         struct timeval tv;
 1490 
 1491         getmicrouptime(&tv);
 1492         si.uptime = tv.tv_sec;
 1493         la = &averunnable;
 1494         si.loads[0] = la->ldavg[0] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
 1495         si.loads[1] = la->ldavg[1] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
 1496         si.loads[2] = la->ldavg[2] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
 1497         si.totalram = ctob(physmem);
 1498         si.freeram = uvmexp.free * uvmexp.pagesize;
 1499         si.sharedram = 0;/* XXX */
 1500         si.bufferram = bufpages * PAGE_SIZE;
 1501         si.totalswap = uvmexp.swpages * PAGE_SIZE;
 1502         si.freeswap = (uvmexp.swpages - uvmexp.swpginuse) * PAGE_SIZE;
 1503         si.procs = nprocs;
 1504         /* The following are only present in newer Linux kernels. */
 1505         si.totalbig = 0;
 1506         si.freebig = 0;
 1507         si.mem_unit = 1;
 1508 
 1509         return (copyout(&si, SCARG(uap, sysinfo), sizeof(si)));
 1510 }

/* [<][>][^][v][top][bottom][index][help] */