[BACK]Return to linux_misc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / compat / linux / common

Annotation of src/sys/compat/linux/common/linux_misc.c, Revision 1.48

1.48    ! perry       1: /*     $NetBSD: linux_misc.c,v 1.47 1998/10/01 04:05:55 erh Exp $      */
1.47      erh         2:
                      3: /*-
                      4:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Eric Haszlakiewicz.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the NetBSD
                     21:  *     Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
1.1       fvdl       38:
                     39: /*
                     40:  * Copyright (c) 1995 Frank van der Linden
                     41:  * All rights reserved.
                     42:  *
                     43:  * Redistribution and use in source and binary forms, with or without
                     44:  * modification, are permitted provided that the following conditions
                     45:  * are met:
                     46:  * 1. Redistributions of source code must retain the above copyright
                     47:  *    notice, this list of conditions and the following disclaimer.
                     48:  * 2. Redistributions in binary form must reproduce the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer in the
                     50:  *    documentation and/or other materials provided with the distribution.
                     51:  * 3. All advertising materials mentioning features or use of this software
                     52:  *    must display the following acknowledgement:
                     53:  *      This product includes software developed for the NetBSD Project
                     54:  *      by Frank van der Linden
                     55:  * 4. The name of the author may not be used to endorse or promote products
                     56:  *    derived from this software without specific prior written permission
                     57:  *
                     58:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     59:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     60:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     61:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     62:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     63:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     64:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     65:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     66:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     67:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     68:  */
                     69:
                     70: /*
                     71:  * Linux compatibility module. Try to deal with various Linux system calls.
                     72:  */
                     73:
1.47      erh        74: /*
                     75:  * These functions have been moved to multiarch to allow
                     76:  * selection of which machines include them to be
                     77:  * determined by the individual files.linux_<arch> files.
                     78:  *
                     79:  * Function in multiarch:
                     80:  *     linux_sys_break                 : linux_break.c
                     81:  *     linux_sys_alarm                 : linux_misc_notalpha.c
                     82:  *     linux_sys_nice                  : linux_misc_notalpha.c
                     83:  *     linux_sys_readdir               : linux_misc_notalpha.c
                     84:  *     linux_sys_time                  : linux_misc_notalpha.c
                     85:  *     linux_sys_utime                 : linux_misc_notalpha.c
                     86:  *     linux_sys_waitpid               : linux_misc_notalpha.c
                     87:  *     linux_sys_old_mmap              : linux_oldmmap.c
                     88:  *     linux_sys_oldolduname           : linux_oldolduname.c
                     89:  *     linux_sys_oldselect             : linux_oldselect.c
                     90:  *     linux_sys_olduname              : linux_olduname.c
                     91:  *     linux_sys_pipe                  : linux_pipe.c
                     92:  */
                     93:
1.1       fvdl       94: #include <sys/param.h>
                     95: #include <sys/systm.h>
                     96: #include <sys/namei.h>
                     97: #include <sys/proc.h>
1.29      mycroft    98: #include <sys/dirent.h>
1.1       fvdl       99: #include <sys/file.h>
                    100: #include <sys/stat.h>
                    101: #include <sys/filedesc.h>
                    102: #include <sys/ioctl.h>
                    103: #include <sys/kernel.h>
                    104: #include <sys/malloc.h>
                    105: #include <sys/mbuf.h>
                    106: #include <sys/mman.h>
                    107: #include <sys/mount.h>
                    108: #include <sys/ptrace.h>
                    109: #include <sys/resource.h>
                    110: #include <sys/resourcevar.h>
                    111: #include <sys/signal.h>
                    112: #include <sys/signalvar.h>
                    113: #include <sys/socket.h>
                    114: #include <sys/time.h>
                    115: #include <sys/times.h>
                    116: #include <sys/vnode.h>
                    117: #include <sys/uio.h>
                    118: #include <sys/wait.h>
                    119: #include <sys/utsname.h>
                    120: #include <sys/unistd.h>
                    121:
                    122: #include <sys/syscallargs.h>
                    123:
                    124: #include <vm/vm.h>
                    125: #include <vm/vm_param.h>
                    126:
                    127: #include <compat/linux/linux_types.h>
                    128: #include <compat/linux/linux_fcntl.h>
                    129: #include <compat/linux/linux_mmap.h>
1.11      mycroft   130: #include <compat/linux/linux_signal.h>
1.47      erh       131: #include <compat/linux/linux_dirent.h>
1.1       fvdl      132: #include <compat/linux/linux_syscallargs.h>
                    133: #include <compat/linux/linux_util.h>
1.47      erh       134: #include <compat/linux/linux_misc.h>
1.1       fvdl      135:
1.47      erh       136: /* Local linux_misc.c functions: */
1.26      christos  137: static void bsd_to_linux_statfs __P((struct statfs *, struct linux_statfs *));
                    138:
1.1       fvdl      139: /*
                    140:  * The information on a terminated (or stopped) process needs
                    141:  * to be converted in order for Linux binaries to get a valid signal
                    142:  * number out of it.
                    143:  */
1.47      erh       144: void
1.1       fvdl      145: bsd_to_linux_wstat(status)
                    146:        int *status;
                    147: {
1.21      mycroft   148:
1.1       fvdl      149:        if (WIFSIGNALED(*status))
                    150:                *status = (*status & ~0177) |
1.46      mycroft   151:                    native_to_linux_sig[WTERMSIG(*status)];
1.1       fvdl      152:        else if (WIFSTOPPED(*status))
                    153:                *status = (*status & ~0xff00) |
1.46      mycroft   154:                    (native_to_linux_sig[WSTOPSIG(*status)] << 8);
1.1       fvdl      155: }
                    156:
                    157: /*
                    158:  * This is very much the same as waitpid()
                    159:  */
                    160: int
1.21      mycroft   161: linux_sys_wait4(p, v, retval)
1.1       fvdl      162:        struct proc *p;
1.20      thorpej   163:        void *v;
                    164:        register_t *retval;
                    165: {
1.21      mycroft   166:        struct linux_sys_wait4_args /* {
1.1       fvdl      167:                syscallarg(int) pid;
                    168:                syscallarg(int *) status;
                    169:                syscallarg(int) options;
                    170:                syscallarg(struct rusage *) rusage;
1.20      thorpej   171:        } */ *uap = v;
1.21      mycroft   172:        struct sys_wait4_args w4a;
1.1       fvdl      173:        int error, *status, tstat;
                    174:        caddr_t sg;
                    175:
1.16      fvdl      176:        if (SCARG(uap, status) != NULL) {
                    177:                sg = stackgap_init(p->p_emul);
                    178:                status = (int *) stackgap_alloc(&sg, sizeof status);
                    179:        } else
                    180:                status = NULL;
1.1       fvdl      181:
                    182:        SCARG(&w4a, pid) = SCARG(uap, pid);
                    183:        SCARG(&w4a, status) = status;
                    184:        SCARG(&w4a, options) = SCARG(uap, options);
                    185:        SCARG(&w4a, rusage) = SCARG(uap, rusage);
                    186:
1.21      mycroft   187:        if ((error = sys_wait4(p, &w4a, retval)))
1.1       fvdl      188:                return error;
                    189:
1.46      mycroft   190:        sigdelset(&p->p_siglist, SIGCHLD);
1.18      fvdl      191:
1.16      fvdl      192:        if (status != NULL) {
                    193:                if ((error = copyin(status, &tstat, sizeof tstat)))
                    194:                        return error;
                    195:
                    196:                bsd_to_linux_wstat(&tstat);
                    197:                return copyout(&tstat, SCARG(uap, status), sizeof tstat);
                    198:        }
1.1       fvdl      199:
1.16      fvdl      200:        return 0;
1.1       fvdl      201: }
                    202:
                    203: /*
                    204:  * Linux brk(2). The check if the new address is >= the old one is
                    205:  * done in the kernel in Linux. NetBSD does it in the library.
                    206:  */
                    207: int
1.21      mycroft   208: linux_sys_brk(p, v, retval)
1.1       fvdl      209:        struct proc *p;
1.20      thorpej   210:        void *v;
                    211:        register_t *retval;
                    212: {
1.21      mycroft   213:        struct linux_sys_brk_args /* {
1.1       fvdl      214:                syscallarg(char *) nsize;
1.20      thorpej   215:        } */ *uap = v;
1.1       fvdl      216:        char *nbrk = SCARG(uap, nsize);
1.21      mycroft   217:        struct sys_obreak_args oba;
1.1       fvdl      218:        struct vmspace *vm = p->p_vmspace;
1.26      christos  219:        caddr_t oldbrk;
1.1       fvdl      220:
                    221:        oldbrk = vm->vm_daddr + ctob(vm->vm_dsize);
                    222:        /*
                    223:         * XXX inconsistent.. Linux always returns at least the old
                    224:         * brk value, but it will be page-aligned if this fails,
                    225:         * and possibly not page aligned if it succeeds (the user
                    226:         * supplied pointer is returned).
                    227:         */
                    228:        SCARG(&oba, nsize) = nbrk;
                    229:
1.21      mycroft   230:        if ((caddr_t) nbrk > vm->vm_daddr && sys_obreak(p, &oba, retval) == 0)
                    231:                retval[0] = (register_t)nbrk;
1.1       fvdl      232:        else
1.21      mycroft   233:                retval[0] = (register_t)oldbrk;
1.1       fvdl      234:
                    235:        return 0;
                    236: }
                    237:
                    238: /*
1.2       fvdl      239:  * Convert BSD statfs structure to Linux statfs structure.
                    240:  * The Linux structure has less fields, and it also wants
                    241:  * the length of a name in a dir entry in a field, which
                    242:  * we fake (probably the wrong way).
                    243:  */
                    244: static void
                    245: bsd_to_linux_statfs(bsp, lsp)
                    246:        struct statfs *bsp;
                    247:        struct linux_statfs *lsp;
                    248: {
1.21      mycroft   249:
1.2       fvdl      250:        lsp->l_ftype = bsp->f_type;
                    251:        lsp->l_fbsize = bsp->f_bsize;
                    252:        lsp->l_fblocks = bsp->f_blocks;
                    253:        lsp->l_fbfree = bsp->f_bfree;
                    254:        lsp->l_fbavail = bsp->f_bavail;
                    255:        lsp->l_ffiles = bsp->f_files;
                    256:        lsp->l_fffree = bsp->f_ffree;
                    257:        lsp->l_ffsid.val[0] = bsp->f_fsid.val[0];
                    258:        lsp->l_ffsid.val[1] = bsp->f_fsid.val[1];
                    259:        lsp->l_fnamelen = MAXNAMLEN;    /* XXX */
                    260: }
                    261:
                    262: /*
                    263:  * Implement the fs stat functions. Straightforward.
1.1       fvdl      264:  */
                    265: int
1.21      mycroft   266: linux_sys_statfs(p, v, retval)
1.1       fvdl      267:        struct proc *p;
1.20      thorpej   268:        void *v;
                    269:        register_t *retval;
                    270: {
1.21      mycroft   271:        struct linux_sys_statfs_args /* {
1.1       fvdl      272:                syscallarg(char *) path;
                    273:                syscallarg(struct linux_statfs *) sp;
1.20      thorpej   274:        } */ *uap = v;
1.2       fvdl      275:        struct statfs btmp, *bsp;
                    276:        struct linux_statfs ltmp;
1.21      mycroft   277:        struct sys_statfs_args bsa;
1.2       fvdl      278:        caddr_t sg;
                    279:        int error;
                    280:
1.9       christos  281:        sg = stackgap_init(p->p_emul);
1.2       fvdl      282:        bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs));
                    283:
1.9       christos  284:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
1.2       fvdl      285:
                    286:        SCARG(&bsa, path) = SCARG(uap, path);
                    287:        SCARG(&bsa, buf) = bsp;
                    288:
1.21      mycroft   289:        if ((error = sys_statfs(p, &bsa, retval)))
1.2       fvdl      290:                return error;
                    291:
                    292:        if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp)))
                    293:                return error;
                    294:
                    295:        bsd_to_linux_statfs(&btmp, &ltmp);
                    296:
                    297:        return copyout((caddr_t) &ltmp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
1.1       fvdl      298: }
                    299:
                    300: int
1.21      mycroft   301: linux_sys_fstatfs(p, v, retval)
1.1       fvdl      302:        struct proc *p;
1.20      thorpej   303:        void *v;
                    304:        register_t *retval;
                    305: {
1.21      mycroft   306:        struct linux_sys_fstatfs_args /* {
1.2       fvdl      307:                syscallarg(int) fd;
1.1       fvdl      308:                syscallarg(struct linux_statfs *) sp;
1.20      thorpej   309:        } */ *uap = v;
1.2       fvdl      310:        struct statfs btmp, *bsp;
                    311:        struct linux_statfs ltmp;
1.21      mycroft   312:        struct sys_fstatfs_args bsa;
1.2       fvdl      313:        caddr_t sg;
                    314:        int error;
                    315:
1.9       christos  316:        sg = stackgap_init(p->p_emul);
1.2       fvdl      317:        bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs));
                    318:
                    319:        SCARG(&bsa, fd) = SCARG(uap, fd);
                    320:        SCARG(&bsa, buf) = bsp;
                    321:
1.21      mycroft   322:        if ((error = sys_fstatfs(p, &bsa, retval)))
1.2       fvdl      323:                return error;
                    324:
                    325:        if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp)))
                    326:                return error;
                    327:
                    328:        bsd_to_linux_statfs(&btmp, &ltmp);
                    329:
                    330:        return copyout((caddr_t) &ltmp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
1.1       fvdl      331: }
                    332:
                    333: /*
                    334:  * uname(). Just copy the info from the various strings stored in the
                    335:  * kernel, and put it in the Linux utsname structure. That structure
                    336:  * is almost the same as the NetBSD one, only it has fields 65 characters
                    337:  * long, and an extra domainname field.
                    338:  */
                    339: int
1.21      mycroft   340: linux_sys_uname(p, v, retval)
1.1       fvdl      341:        struct proc *p;
1.20      thorpej   342:        void *v;
                    343:        register_t *retval;
                    344: {
1.21      mycroft   345:        struct linux_sys_uname_args /* {
1.1       fvdl      346:                syscallarg(struct linux_utsname *) up;
1.20      thorpej   347:        } */ *uap = v;
1.15      mycroft   348:        extern char ostype[], hostname[], osrelease[], version[], machine[],
                    349:            domainname[];
                    350:        struct linux_utsname luts;
1.1       fvdl      351:        int len;
                    352:        char *cp;
                    353:
1.15      mycroft   354:        strncpy(luts.l_sysname, ostype, sizeof(luts.l_sysname));
                    355:        strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
                    356:        strncpy(luts.l_release, osrelease, sizeof(luts.l_release));
                    357:        strncpy(luts.l_version, version, sizeof(luts.l_version));
                    358:        strncpy(luts.l_machine, machine, sizeof(luts.l_machine));
                    359:        strncpy(luts.l_domainname, domainname, sizeof(luts.l_domainname));
1.1       fvdl      360:
                    361:        /* This part taken from the the uname() in libc */
1.15      mycroft   362:        len = sizeof(luts.l_version);
1.48    ! perry     363:        for (cp = luts.l_version; len--; ++cp) {
        !           364:                if (*cp == '\n' || *cp == '\t') {
1.15      mycroft   365:                        if (len > 1)
                    366:                                *cp = ' ';
                    367:                        else
                    368:                                *cp = '\0';
1.48    ! perry     369:                }
        !           370:        }
1.15      mycroft   371:
                    372:        return copyout(&luts, SCARG(uap, up), sizeof(luts));
                    373: }
                    374:
1.47      erh       375: /* Used directly on: alpha, mips, ppc, sparc, sparc64 */
                    376: /* Used indirectly on: arm, i386, m68k */
1.1       fvdl      377:
                    378: /*
1.47      erh       379:  * New type Linux mmap call.
                    380:  * Only called directly on machines with >= 6 free regs.
1.1       fvdl      381:  */
                    382: int
1.21      mycroft   383: linux_sys_mmap(p, v, retval)
1.1       fvdl      384:        struct proc *p;
1.20      thorpej   385:        void *v;
                    386:        register_t *retval;
                    387: {
1.21      mycroft   388:        struct linux_sys_mmap_args /* {
1.47      erh       389:                syscallarg(unsigned long) addr;
                    390:                syscallarg(size_t) len;
                    391:                syscallarg(int) prot;
                    392:                syscallarg(int) flags;
                    393:                syscallarg(int) fd;
                    394:                syscallarg(off_t) offset;
1.20      thorpej   395:        } */ *uap = v;
1.21      mycroft   396:        struct sys_mmap_args cma;
1.47      erh       397:        int flags;
                    398:
1.1       fvdl      399:        flags = 0;
1.47      erh       400:        flags |= cvtto_bsd_mask(SCARG(uap,flags), LINUX_MAP_SHARED, MAP_SHARED);
                    401:        flags |= cvtto_bsd_mask(SCARG(uap,flags), LINUX_MAP_PRIVATE, MAP_PRIVATE);
                    402:        flags |= cvtto_bsd_mask(SCARG(uap,flags), LINUX_MAP_FIXED, MAP_FIXED);
                    403:        flags |= cvtto_bsd_mask(SCARG(uap,flags), LINUX_MAP_ANON, MAP_ANON);
                    404:        /* XXX XAX ERH: Any other flags here?  There are more defined... */
                    405:
                    406:        SCARG(&cma,addr) = (void *)SCARG(uap, addr);
                    407:        SCARG(&cma,len) = SCARG(uap, len);
                    408:        SCARG(&cma,prot) = SCARG(uap, prot);
                    409:        if (SCARG(&cma,prot) & VM_PROT_WRITE) /* XXX */
                    410:                SCARG(&cma,prot) |= VM_PROT_READ;
1.1       fvdl      411:        SCARG(&cma,flags) = flags;
1.47      erh       412:        SCARG(&cma,fd) = SCARG(uap, fd);
1.1       fvdl      413:        SCARG(&cma,pad) = 0;
1.47      erh       414:        SCARG(&cma,pos) = SCARG(uap, offset);
1.1       fvdl      415:
1.21      mycroft   416:        return sys_mmap(p, &cma, retval);
1.34      mycroft   417: }
                    418:
                    419: int
                    420: linux_sys_mremap(p, v, retval)
                    421:        struct proc *p;
                    422:        void *v;
                    423:        register_t *retval;
                    424: {
                    425:        struct linux_sys_mremap_args /* {
                    426:                syscallarg(void *) old_address;
                    427:                syscallarg(size_t) old_size;
                    428:                syscallarg(size_t) new_size;
                    429:                syscallarg(u_long) flags;
                    430:        } */ *uap = v;
1.42      thorpej   431:        struct sys_munmap_args mua;
                    432:        size_t old_size, new_size;
                    433:        int error;
                    434:
                    435:        old_size = round_page(SCARG(uap, old_size));
                    436:        new_size = round_page(SCARG(uap, new_size));
                    437:
                    438:        /*
                    439:         * Growing mapped region.
                    440:         */
                    441:        if (new_size > old_size) {
                    442:                /*
                    443:                 * XXX Implement me.  What we probably want to do is
                    444:                 * XXX dig out the guts of the old mapping, mmap that
                    445:                 * XXX object again with the new size, then munmap
                    446:                 * XXX the old mapping.
                    447:                 */
                    448:                *retval = 0;
                    449:                return (ENOMEM);
                    450:        }
                    451:
                    452:        /*
                    453:         * Shrinking mapped region.
                    454:         */
                    455:        if (new_size < old_size) {
                    456:                SCARG(&mua, addr) = (caddr_t)SCARG(uap, old_address) +
1.43      thorpej   457:                    new_size;
1.42      thorpej   458:                SCARG(&mua, len) = old_size - new_size;
                    459:                error = sys_munmap(p, &mua, retval);
                    460:                *retval = error ? 0 : (register_t)SCARG(uap, old_address);
                    461:                return (error);
                    462:        }
1.34      mycroft   463:
1.42      thorpej   464:        /*
                    465:         * No change.
                    466:         */
                    467:        *retval = (register_t)SCARG(uap, old_address);
                    468:        return (0);
1.24      fvdl      469: }
                    470:
                    471: int
                    472: linux_sys_msync(p, v, retval)
                    473:        struct proc *p;
                    474:        void *v;
                    475:        register_t *retval;
                    476: {
                    477:        struct linux_sys_msync_args /* {
                    478:                syscallarg(caddr_t) addr;
                    479:                syscallarg(int) len;
                    480:                syscallarg(int) fl;
                    481:        } */ *uap = v;
                    482:
1.36      fvdl      483:        struct sys___msync13_args bma;
1.24      fvdl      484:
                    485:        /* flags are ignored */
                    486:        SCARG(&bma, addr) = SCARG(uap, addr);
                    487:        SCARG(&bma, len) = SCARG(uap, len);
1.36      fvdl      488:        SCARG(&bma, flags) = SCARG(uap, fl);
1.24      fvdl      489:
1.36      fvdl      490:        return sys___msync13(p, &bma, retval);
1.1       fvdl      491: }
                    492:
                    493: /*
                    494:  * This code is partly stolen from src/lib/libc/compat-43/times.c
                    495:  * XXX - CLK_TCK isn't declared in /sys, just in <time.h>, done here
                    496:  */
                    497:
                    498: #define CLK_TCK 100
                    499: #define        CONVTCK(r)      (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
                    500:
                    501: int
1.21      mycroft   502: linux_sys_times(p, v, retval)
1.1       fvdl      503:        struct proc *p;
1.20      thorpej   504:        void *v;
                    505:        register_t *retval;
                    506: {
1.21      mycroft   507:        struct linux_sys_times_args /* {
1.1       fvdl      508:                syscallarg(struct times *) tms;
1.20      thorpej   509:        } */ *uap = v;
1.1       fvdl      510:        struct timeval t;
                    511:        struct linux_tms ltms;
                    512:        struct rusage ru;
1.4       mycroft   513:        int error, s;
1.1       fvdl      514:
                    515:        calcru(p, &ru.ru_utime, &ru.ru_stime, NULL);
                    516:        ltms.ltms_utime = CONVTCK(ru.ru_utime);
                    517:        ltms.ltms_stime = CONVTCK(ru.ru_stime);
                    518:
                    519:        ltms.ltms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
                    520:        ltms.ltms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
                    521:
                    522:        if ((error = copyout(&ltms, SCARG(uap, tms), sizeof ltms)))
                    523:                return error;
                    524:
1.4       mycroft   525:        s = splclock();
                    526:        timersub(&time, &boottime, &t);
                    527:        splx(s);
1.1       fvdl      528:
                    529:        retval[0] = ((linux_clock_t)(CONVTCK(t)));
                    530:        return 0;
                    531: }
                    532:
                    533: /*
                    534:  * Linux 'readdir' call. This code is mostly taken from the
                    535:  * SunOS getdents call (see compat/sunos/sunos_misc.c), though
                    536:  * an attempt has been made to keep it a little cleaner (failing
                    537:  * miserably, because of the cruft needed if count 1 is passed).
                    538:  *
1.17      fvdl      539:  * The d_off field should contain the offset of the next valid entry,
                    540:  * but in Linux it has the offset of the entry itself. We emulate
                    541:  * that bug here.
                    542:  *
1.1       fvdl      543:  * Read in BSD-style entries, convert them, and copy them out.
                    544:  *
                    545:  * Note that this doesn't handle union-mounted filesystems.
                    546:  */
                    547: int
1.21      mycroft   548: linux_sys_getdents(p, v, retval)
1.1       fvdl      549:        struct proc *p;
1.20      thorpej   550:        void *v;
                    551:        register_t *retval;
                    552: {
1.47      erh       553:        struct linux_sys_getdents_args /* {
1.1       fvdl      554:                syscallarg(int) fd;
1.47      erh       555:                syscallarg(struct linux_dirent *) dent;
1.1       fvdl      556:                syscallarg(unsigned int) count;
1.20      thorpej   557:        } */ *uap = v;
1.1       fvdl      558:        register struct dirent *bdp;
                    559:        struct vnode *vp;
1.26      christos  560:        caddr_t inp, buf;               /* BSD-format */
                    561:        int len, reclen;                /* BSD-format */
1.47      erh       562:        struct linux_dirent *outp;      /* Linux-format */
1.26      christos  563:        int resid, linux_reclen = 0;    /* Linux-format */
1.1       fvdl      564:        struct file *fp;
                    565:        struct uio auio;
                    566:        struct iovec aiov;
                    567:        struct linux_dirent idb;
                    568:        off_t off;              /* true file offset */
1.17      fvdl      569:        int buflen, error, eofflag, nbytes, oldcall;
1.1       fvdl      570:        struct vattr va;
1.40      fvdl      571:        off_t *cookiebuf = NULL, *cookie;
1.22      mycroft   572:        int ncookies;
1.1       fvdl      573:
                    574:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
                    575:                return (error);
                    576:
                    577:        if ((fp->f_flag & FREAD) == 0)
                    578:                return (EBADF);
                    579:
1.5       mycroft   580:        vp = (struct vnode *)fp->f_data;
1.45      rvb       581:        if (vp->v_type != VDIR)
                    582:                return (EINVAL);
1.1       fvdl      583:
                    584:        if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
                    585:                return error;
                    586:
                    587:        nbytes = SCARG(uap, count);
1.17      fvdl      588:        if (nbytes == 1) {      /* emulating old, broken behaviour */
1.1       fvdl      589:                nbytes = sizeof (struct linux_dirent);
1.5       mycroft   590:                buflen = max(va.va_blocksize, nbytes);
1.17      fvdl      591:                oldcall = 1;
1.5       mycroft   592:        } else {
                    593:                buflen = min(MAXBSIZE, nbytes);
1.33      fvdl      594:                if (buflen < va.va_blocksize)
                    595:                        buflen = va.va_blocksize;
1.17      fvdl      596:                oldcall = 0;
1.1       fvdl      597:        }
                    598:        buf = malloc(buflen, M_TEMP, M_WAITOK);
1.33      fvdl      599:
1.39      fvdl      600:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.1       fvdl      601:        off = fp->f_offset;
                    602: again:
                    603:        aiov.iov_base = buf;
                    604:        aiov.iov_len = buflen;
                    605:        auio.uio_iov = &aiov;
                    606:        auio.uio_iovcnt = 1;
                    607:        auio.uio_rw = UIO_READ;
                    608:        auio.uio_segflg = UIO_SYSSPACE;
                    609:        auio.uio_procp = p;
                    610:        auio.uio_resid = buflen;
                    611:        auio.uio_offset = off;
                    612:        /*
                    613:          * First we read into the malloc'ed buffer, then
                    614:          * we massage it into user space, one record at a time.
                    615:          */
1.39      fvdl      616:        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
                    617:            &ncookies);
1.1       fvdl      618:        if (error)
                    619:                goto out;
                    620:
                    621:        inp = buf;
1.21      mycroft   622:        outp = SCARG(uap, dent);
1.1       fvdl      623:        resid = nbytes;
1.35      fvdl      624:        if ((len = buflen - auio.uio_resid) == 0)
1.1       fvdl      625:                goto eof;
                    626:
1.22      mycroft   627:        for (cookie = cookiebuf; len > 0; len -= reclen) {
1.5       mycroft   628:                bdp = (struct dirent *)inp;
                    629:                reclen = bdp->d_reclen;
1.1       fvdl      630:                if (reclen & 3)
                    631:                        panic("linux_readdir");
                    632:                if (bdp->d_fileno == 0) {
                    633:                        inp += reclen;  /* it is a hole; squish it out */
1.22      mycroft   634:                        off = *cookie++;
1.1       fvdl      635:                        continue;
                    636:                }
1.21      mycroft   637:                linux_reclen = LINUX_RECLEN(&idb, bdp->d_namlen);
                    638:                if (reclen > len || resid < linux_reclen) {
1.1       fvdl      639:                        /* entry too big for buffer, so just stop */
                    640:                        outp++;
                    641:                        break;
                    642:                }
                    643:                /*
                    644:                 * Massage in place to make a Linux-shaped dirent (otherwise
                    645:                 * we have to worry about touching user memory outside of
                    646:                 * the copyout() call).
                    647:                 */
1.22      mycroft   648:                idb.d_ino = (linux_ino_t)bdp->d_fileno;
1.17      fvdl      649:                /*
1.21      mycroft   650:                 * The old readdir() call misuses the offset and reclen fields.
1.17      fvdl      651:                 */
1.22      mycroft   652:                if (oldcall) {
                    653:                        idb.d_off = (linux_off_t)linux_reclen;
                    654:                        idb.d_reclen = (u_short)bdp->d_namlen;
                    655:                } else {
1.33      fvdl      656:                        if (sizeof (linux_off_t) < 4 && (off >> 32) != 0) {
                    657:                                compat_offseterr(vp, "linux_getdents");
                    658:                                error = EINVAL;
                    659:                                goto out;
                    660:                        }
1.22      mycroft   661:                        idb.d_off = (linux_off_t)off;
                    662:                        idb.d_reclen = (u_short)linux_reclen;
                    663:                }
1.5       mycroft   664:                strcpy(idb.d_name, bdp->d_name);
1.21      mycroft   665:                if ((error = copyout((caddr_t)&idb, outp, linux_reclen)))
1.1       fvdl      666:                        goto out;
                    667:                /* advance past this real entry */
                    668:                inp += reclen;
1.22      mycroft   669:                off = *cookie++;        /* each entry points to itself */
1.1       fvdl      670:                /* advance output past Linux-shaped entry */
1.21      mycroft   671:                outp += linux_reclen;
                    672:                resid -= linux_reclen;
1.17      fvdl      673:                if (oldcall)
1.1       fvdl      674:                        break;
                    675:        }
                    676:
                    677:        /* if we squished out the whole block, try again */
1.21      mycroft   678:        if (outp == SCARG(uap, dent))
1.1       fvdl      679:                goto again;
                    680:        fp->f_offset = off;     /* update the vnode offset */
                    681:
1.17      fvdl      682:        if (oldcall)
1.21      mycroft   683:                nbytes = resid + linux_reclen;
1.1       fvdl      684:
                    685: eof:
                    686:        *retval = nbytes - resid;
                    687: out:
1.39      fvdl      688:        VOP_UNLOCK(vp, 0);
1.40      fvdl      689:        if (cookiebuf)
                    690:                free(cookiebuf, M_TEMP);
1.1       fvdl      691:        free(buf, M_TEMP);
                    692:        return error;
                    693: }
                    694:
                    695: /*
1.17      fvdl      696:  * Even when just using registers to pass arguments to syscalls you can
                    697:  * have 5 of them on the i386. So this newer version of select() does
                    698:  * this.
1.1       fvdl      699:  */
                    700: int
1.21      mycroft   701: linux_sys_select(p, v, retval)
1.1       fvdl      702:        struct proc *p;
1.20      thorpej   703:        void *v;
                    704:        register_t *retval;
                    705: {
1.21      mycroft   706:        struct linux_sys_select_args /* {
1.17      fvdl      707:                syscallarg(int) nfds;
                    708:                syscallarg(fd_set *) readfds;
                    709:                syscallarg(fd_set *) writefds;
                    710:                syscallarg(fd_set *) exceptfds;
                    711:                syscallarg(struct timeval *) timeout;
1.20      thorpej   712:        } */ *uap = v;
                    713:
1.17      fvdl      714:        return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
                    715:            SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
                    716: }
                    717:
                    718: /*
                    719:  * Common code for the old and new versions of select(). A couple of
                    720:  * things are important:
                    721:  * 1) return the amount of time left in the 'timeout' parameter
                    722:  * 2) select never returns ERESTART on Linux, always return EINTR
                    723:  */
                    724: int
                    725: linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
                    726:        struct proc *p;
                    727:        register_t *retval;
                    728:        int nfds;
                    729:        fd_set *readfds, *writefds, *exceptfds;
                    730:        struct timeval *timeout;
                    731: {
1.21      mycroft   732:        struct sys_select_args bsa;
1.13      mycroft   733:        struct timeval tv0, tv1, utv, *tvp;
                    734:        caddr_t sg;
1.1       fvdl      735:        int error;
                    736:
1.17      fvdl      737:        SCARG(&bsa, nd) = nfds;
                    738:        SCARG(&bsa, in) = readfds;
                    739:        SCARG(&bsa, ou) = writefds;
                    740:        SCARG(&bsa, ex) = exceptfds;
                    741:        SCARG(&bsa, tv) = timeout;
1.1       fvdl      742:
1.7       fvdl      743:        /*
                    744:         * Store current time for computation of the amount of
                    745:         * time left.
                    746:         */
1.17      fvdl      747:        if (timeout) {
                    748:                if ((error = copyin(timeout, &utv, sizeof(utv))))
1.13      mycroft   749:                        return error;
                    750:                if (itimerfix(&utv)) {
                    751:                        /*
                    752:                         * The timeval was invalid.  Convert it to something
                    753:                         * valid that will act as it does under Linux.
                    754:                         */
                    755:                        sg = stackgap_init(p->p_emul);
                    756:                        tvp = stackgap_alloc(&sg, sizeof(utv));
                    757:                        utv.tv_sec += utv.tv_usec / 1000000;
                    758:                        utv.tv_usec %= 1000000;
                    759:                        if (utv.tv_usec < 0) {
                    760:                                utv.tv_sec -= 1;
                    761:                                utv.tv_usec += 1000000;
                    762:                        }
                    763:                        if (utv.tv_sec < 0)
                    764:                                timerclear(&utv);
                    765:                        if ((error = copyout(&utv, tvp, sizeof(utv))))
                    766:                                return error;
                    767:                        SCARG(&bsa, tv) = tvp;
                    768:                }
1.7       fvdl      769:                microtime(&tv0);
1.13      mycroft   770:        }
1.7       fvdl      771:
1.21      mycroft   772:        error = sys_select(p, &bsa, retval);
1.10      mycroft   773:        if (error) {
                    774:                /*
                    775:                 * See fs/select.c in the Linux kernel.  Without this,
                    776:                 * Maelstrom doesn't work.
                    777:                 */
                    778:                if (error == ERESTART)
                    779:                        error = EINTR;
1.7       fvdl      780:                return error;
1.10      mycroft   781:        }
1.7       fvdl      782:
1.17      fvdl      783:        if (timeout) {
1.14      mycroft   784:                if (*retval) {
1.7       fvdl      785:                        /*
1.13      mycroft   786:                         * Compute how much time was left of the timeout,
1.7       fvdl      787:                         * by subtracting the current time and the time
                    788:                         * before we started the call, and subtracting
                    789:                         * that result from the user-supplied value.
                    790:                         */
                    791:                        microtime(&tv1);
                    792:                        timersub(&tv1, &tv0, &tv1);
                    793:                        timersub(&utv, &tv1, &utv);
1.14      mycroft   794:                        if (utv.tv_sec < 0)
                    795:                                timerclear(&utv);
                    796:                } else
                    797:                        timerclear(&utv);
1.17      fvdl      798:                if ((error = copyout(&utv, timeout, sizeof(utv))))
1.7       fvdl      799:                        return error;
                    800:        }
1.13      mycroft   801:
1.7       fvdl      802:        return 0;
1.1       fvdl      803: }
                    804:
                    805: /*
                    806:  * Get the process group of a certain process. Look it up
                    807:  * and return the value.
                    808:  */
                    809: int
1.21      mycroft   810: linux_sys_getpgid(p, v, retval)
1.1       fvdl      811:        struct proc *p;
1.20      thorpej   812:        void *v;
                    813:        register_t *retval;
                    814: {
1.21      mycroft   815:        struct linux_sys_getpgid_args /* {
1.1       fvdl      816:                syscallarg(int) pid;
1.20      thorpej   817:        } */ *uap = v;
1.1       fvdl      818:        struct proc *targp;
                    819:
1.26      christos  820:        if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != p->p_pid) {
1.1       fvdl      821:                if ((targp = pfind(SCARG(uap, pid))) == 0)
                    822:                        return ESRCH;
1.26      christos  823:        }
1.1       fvdl      824:        else
                    825:                targp = p;
                    826:
                    827:        retval[0] = targp->p_pgid;
1.6       fvdl      828:        return 0;
                    829: }
                    830:
                    831: /*
                    832:  * Set the 'personality' (emulation mode) for the current process. Only
                    833:  * accept the Linux personality here (0). This call is needed because
                    834:  * the Linux ELF crt0 issues it in an ugly kludge to make sure that
                    835:  * ELF binaries run in Linux mode, not SVR4 mode.
                    836:  */
                    837: int
1.21      mycroft   838: linux_sys_personality(p, v, retval)
1.6       fvdl      839:        struct proc *p;
1.20      thorpej   840:        void *v;
                    841:        register_t *retval;
                    842: {
1.21      mycroft   843:        struct linux_sys_personality_args /* {
1.6       fvdl      844:                syscallarg(int) per;
1.20      thorpej   845:        } */ *uap = v;
                    846:
1.6       fvdl      847:        if (SCARG(uap, per) != 0)
                    848:                return EINVAL;
                    849:        retval[0] = 0;
1.1       fvdl      850:        return 0;
1.18      fvdl      851: }
                    852:
                    853: /*
                    854:  * The calls are here because of type conversions.
                    855:  */
                    856: int
1.21      mycroft   857: linux_sys_setreuid(p, v, retval)
1.18      fvdl      858:        struct proc *p;
1.20      thorpej   859:        void *v;
                    860:        register_t *retval;
                    861: {
1.21      mycroft   862:        struct linux_sys_setreuid_args /* {
1.18      fvdl      863:                syscallarg(int) ruid;
                    864:                syscallarg(int) euid;
1.20      thorpej   865:        } */ *uap = v;
1.28      mycroft   866:        struct sys_setreuid_args bsa;
1.18      fvdl      867:
                    868:        SCARG(&bsa, ruid) = ((linux_uid_t)SCARG(uap, ruid) == (linux_uid_t)-1) ?
                    869:                (uid_t)-1 : SCARG(uap, ruid);
                    870:        SCARG(&bsa, euid) = ((linux_uid_t)SCARG(uap, euid) == (linux_uid_t)-1) ?
                    871:                (uid_t)-1 : SCARG(uap, euid);
                    872:
1.28      mycroft   873:        return sys_setreuid(p, &bsa, retval);
1.18      fvdl      874: }
                    875:
                    876: int
1.21      mycroft   877: linux_sys_setregid(p, v, retval)
1.18      fvdl      878:        struct proc *p;
1.20      thorpej   879:        void *v;
                    880:        register_t *retval;
                    881: {
1.21      mycroft   882:        struct linux_sys_setregid_args /* {
1.18      fvdl      883:                syscallarg(int) rgid;
                    884:                syscallarg(int) egid;
1.20      thorpej   885:        } */ *uap = v;
1.28      mycroft   886:        struct sys_setregid_args bsa;
1.18      fvdl      887:
                    888:        SCARG(&bsa, rgid) = ((linux_gid_t)SCARG(uap, rgid) == (linux_gid_t)-1) ?
                    889:                (uid_t)-1 : SCARG(uap, rgid);
                    890:        SCARG(&bsa, egid) = ((linux_gid_t)SCARG(uap, egid) == (linux_gid_t)-1) ?
                    891:                (uid_t)-1 : SCARG(uap, egid);
                    892:
1.28      mycroft   893:        return sys_setregid(p, &bsa, retval);
1.27      fvdl      894: }
                    895:
                    896: int
                    897: linux_sys___sysctl(p, v, retval)
                    898:        struct proc *p;
                    899:        void *v;
                    900:        register_t *retval;
                    901: {
                    902:        struct linux_sys___sysctl_args /* {
                    903:                syscallarg(struct linux___sysctl *) lsp;
                    904:        } */ *uap = v;
                    905:        struct linux___sysctl ls;
                    906:        struct sys___sysctl_args bsa;
                    907:        int error;
                    908:
                    909:        if ((error = copyin(SCARG(uap, lsp), &ls, sizeof ls)))
                    910:                return error;
                    911:        SCARG(&bsa, name) = ls.name;
                    912:        SCARG(&bsa, namelen) = ls.namelen;
                    913:        SCARG(&bsa, old) = ls.old;
                    914:        SCARG(&bsa, oldlenp) = ls.oldlenp;
                    915:        SCARG(&bsa, new) = ls.new;
                    916:        SCARG(&bsa, newlen) = ls.newlen;
                    917:
                    918:        return sys___sysctl(p, &bsa, retval);
1.1       fvdl      919: }

CVSweb <webmaster@jp.NetBSD.org>