[BACK]Return to linux_misc.c CVS log [TXT][DIR] Up to [local] / sys / compat / linux

Annotation of sys/compat/linux/linux_misc.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb