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

Annotation of sys/compat/linux/linux_file.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: linux_file.c,v 1.23 2006/09/25 07:12:57 otto Exp $    */
        !             2: /*     $NetBSD: linux_file.c,v 1.15 1996/05/20 01:59:09 fvdl Exp $     */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Frank van der Linden
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *      This product includes software developed for the NetBSD Project
        !            19:  *      by Frank van der Linden
        !            20:  * 4. The name of the author may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            33:  */
        !            34:
        !            35: #include <sys/param.h>
        !            36: #include <sys/systm.h>
        !            37: #include <sys/namei.h>
        !            38: #include <sys/proc.h>
        !            39: #include <sys/file.h>
        !            40: #include <sys/stat.h>
        !            41: #include <sys/filedesc.h>
        !            42: #include <sys/ioctl.h>
        !            43: #include <sys/kernel.h>
        !            44: #include <sys/mount.h>
        !            45: #include <sys/signalvar.h>
        !            46: #include <sys/uio.h>
        !            47: #include <sys/malloc.h>
        !            48: #include <sys/vnode.h>
        !            49: #include <sys/tty.h>
        !            50: #include <sys/conf.h>
        !            51:
        !            52: #include <sys/syscallargs.h>
        !            53:
        !            54: #include <compat/linux/linux_types.h>
        !            55: #include <compat/linux/linux_signal.h>
        !            56: #include <compat/linux/linux_syscallargs.h>
        !            57: #include <compat/linux/linux_fcntl.h>
        !            58: #include <compat/linux/linux_util.h>
        !            59:
        !            60: #include <machine/linux_machdep.h>
        !            61:
        !            62: static int linux_to_bsd_ioflags(int);
        !            63: static int bsd_to_linux_ioflags(int);
        !            64: static void bsd_to_linux_flock(struct flock *, struct linux_flock *);
        !            65: static void linux_to_bsd_flock(struct linux_flock *, struct flock *);
        !            66: static void bsd_to_linux_stat(struct stat *, struct linux_stat *);
        !            67: static int linux_stat1(struct proc *, void *, register_t *, int);
        !            68:
        !            69:
        !            70: /*
        !            71:  * Some file-related calls are handled here. The usual flag conversion
        !            72:  * an structure conversion is done, and alternate emul path searching.
        !            73:  */
        !            74:
        !            75: /*
        !            76:  * The next two functions convert between the Linux and OpenBSD values
        !            77:  * of the flags used in open(2) and fcntl(2).
        !            78:  */
        !            79: static int
        !            80: linux_to_bsd_ioflags(lflags)
        !            81:        int lflags;
        !            82: {
        !            83:        int res = 0;
        !            84:
        !            85:        res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY);
        !            86:        res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY);
        !            87:        res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR);
        !            88:        res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT);
        !            89:        res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL);
        !            90:        res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY);
        !            91:        res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC);
        !            92:        res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY);
        !            93:        res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_SYNC);
        !            94:        res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC);
        !            95:        res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND);
        !            96:
        !            97:        return res;
        !            98: }
        !            99:
        !           100: static int
        !           101: bsd_to_linux_ioflags(bflags)
        !           102:        int bflags;
        !           103: {
        !           104:        int res = 0;
        !           105:
        !           106:        res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY);
        !           107:        res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY);
        !           108:        res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR);
        !           109:        res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT);
        !           110:        res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL);
        !           111:        res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY);
        !           112:        res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC);
        !           113:        res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY);
        !           114:        res |= cvtto_linux_mask(bflags, O_SYNC, LINUX_O_SYNC);
        !           115:        res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC);
        !           116:        res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND);
        !           117:
        !           118:        return res;
        !           119: }
        !           120:
        !           121: /*
        !           122:  * creat(2) is an obsolete function, but it's present as a Linux
        !           123:  * system call, so let's deal with it.
        !           124:  *
        !           125:  * Just call open(2) with the TRUNC, CREAT and WRONLY flags.
        !           126:  */
        !           127: int
        !           128: linux_sys_creat(p, v, retval)
        !           129:        struct proc *p;
        !           130:        void *v;
        !           131:        register_t *retval;
        !           132: {
        !           133:        struct linux_sys_creat_args /* {
        !           134:                syscallarg(char *) path;
        !           135:                syscallarg(int) mode;
        !           136:        } */ *uap = v;
        !           137:        struct sys_open_args oa;
        !           138:        caddr_t sg;
        !           139:
        !           140:        sg = stackgap_init(p->p_emul);
        !           141:        LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
        !           142:
        !           143:        SCARG(&oa, path) = SCARG(uap, path);
        !           144:        SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY;
        !           145:        SCARG(&oa, mode) = SCARG(uap, mode);
        !           146:
        !           147:        return sys_open(p, &oa, retval);
        !           148: }
        !           149:
        !           150: /*
        !           151:  * open(2). Take care of the different flag values, and let the
        !           152:  * OpenBSD syscall do the real work. See if this operation
        !           153:  * gives the current process a controlling terminal.
        !           154:  * (XXX is this necessary?)
        !           155:  */
        !           156: int
        !           157: linux_sys_open(p, v, retval)
        !           158:        struct proc *p;
        !           159:        void *v;
        !           160:        register_t *retval;
        !           161: {
        !           162:        struct linux_sys_open_args /* {
        !           163:                syscallarg(char *) path;
        !           164:                syscallarg(int) flags;
        !           165:                syscallarg(int) mode;
        !           166:        } */ *uap = v;
        !           167:        int error, fl;
        !           168:        struct sys_open_args boa;
        !           169:        caddr_t sg;
        !           170:
        !           171:        sg = stackgap_init(p->p_emul);
        !           172:
        !           173:        fl = linux_to_bsd_ioflags(SCARG(uap, flags));
        !           174:
        !           175:        if (fl & O_CREAT)
        !           176:                LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
        !           177:        else
        !           178:                LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
        !           179:
        !           180:        SCARG(&boa, path) = SCARG(uap, path);
        !           181:        SCARG(&boa, flags) = fl;
        !           182:        SCARG(&boa, mode) = SCARG(uap, mode);
        !           183:
        !           184:        if ((error = sys_open(p, &boa, retval)))
        !           185:                return error;
        !           186:
        !           187:        /*
        !           188:         * this bit from sunos_misc.c (and svr4_fcntl.c).
        !           189:         * If we are a session leader, and we don't have a controlling
        !           190:         * terminal yet, and the O_NOCTTY flag is not set, try to make
        !           191:         * this the controlling terminal.
        !           192:         */
        !           193:         if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
        !           194:                 struct filedesc *fdp = p->p_fd;
        !           195:                 struct file     *fp;
        !           196:
        !           197:                if ((fp = fd_getfile(fdp, *retval)) == NULL)
        !           198:                        return (EBADF);
        !           199:                FREF(fp);
        !           200:                 if (fp->f_type == DTYPE_VNODE)
        !           201:                         (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, (caddr_t) 0, p);
        !           202:                FRELE(fp);
        !           203:         }
        !           204:        return 0;
        !           205: }
        !           206:
        !           207: /*
        !           208:  * This appears to be part of a Linux attempt to switch to 64 bits file sizes.
        !           209:  */
        !           210: int
        !           211: linux_sys_llseek(p, v, retval)
        !           212:        struct proc *p;
        !           213:        void *v;
        !           214:        register_t *retval;
        !           215: {
        !           216:        struct linux_sys_llseek_args /* {
        !           217:                syscallarg(int) fd;
        !           218:                syscallarg(uint32_t) ohigh;
        !           219:                syscallarg(uint32_t) olow;
        !           220:                syscallarg(caddr_t) res;
        !           221:                syscallarg(int) whence;
        !           222:        } */ *uap = v;
        !           223:        struct sys_lseek_args bla;
        !           224:        int error;
        !           225:        off_t off;
        !           226:
        !           227:        off = SCARG(uap, olow) | (((off_t) SCARG(uap, ohigh)) << 32);
        !           228:
        !           229:        SCARG(&bla, fd) = SCARG(uap, fd);
        !           230:        SCARG(&bla, offset) = off;
        !           231:        SCARG(&bla, whence) = SCARG(uap, whence);
        !           232:
        !           233:        if ((error = sys_lseek(p, &bla, retval)))
        !           234:                return error;
        !           235:
        !           236:        if ((error = copyout(retval, SCARG(uap, res), sizeof (off_t))))
        !           237:                return error;
        !           238:
        !           239:        retval[0] = 0;
        !           240:        return 0;
        !           241: }
        !           242:
        !           243: /*
        !           244:  * The next two functions take care of converting the flock
        !           245:  * structure back and forth between Linux and OpenBSD format.
        !           246:  * The only difference in the structures is the order of
        !           247:  * the fields, and the 'whence' value.
        !           248:  */
        !           249: static void
        !           250: bsd_to_linux_flock(bfp, lfp)
        !           251:        struct flock *bfp;
        !           252:        struct linux_flock *lfp;
        !           253: {
        !           254:
        !           255:        lfp->l_start = bfp->l_start;
        !           256:        lfp->l_len = bfp->l_len;
        !           257:        lfp->l_pid = bfp->l_pid;
        !           258:        lfp->l_whence = bfp->l_whence;
        !           259:        switch (bfp->l_type) {
        !           260:        case F_RDLCK:
        !           261:                lfp->l_type = LINUX_F_RDLCK;
        !           262:                break;
        !           263:        case F_UNLCK:
        !           264:                lfp->l_type = LINUX_F_UNLCK;
        !           265:                break;
        !           266:        case F_WRLCK:
        !           267:                lfp->l_type = LINUX_F_WRLCK;
        !           268:                break;
        !           269:        }
        !           270: }
        !           271:
        !           272: static void
        !           273: linux_to_bsd_flock(lfp, bfp)
        !           274:        struct linux_flock *lfp;
        !           275:        struct flock *bfp;
        !           276: {
        !           277:
        !           278:        bfp->l_start = lfp->l_start;
        !           279:        bfp->l_len = lfp->l_len;
        !           280:        bfp->l_pid = lfp->l_pid;
        !           281:        bfp->l_whence = lfp->l_whence;
        !           282:        switch (lfp->l_type) {
        !           283:        case LINUX_F_RDLCK:
        !           284:                bfp->l_type = F_RDLCK;
        !           285:                break;
        !           286:        case LINUX_F_UNLCK:
        !           287:                bfp->l_type = F_UNLCK;
        !           288:                break;
        !           289:        case LINUX_F_WRLCK:
        !           290:                bfp->l_type = F_WRLCK;
        !           291:                break;
        !           292:        }
        !           293: }
        !           294:
        !           295: /*
        !           296:  * Most actions in the fcntl() call are straightforward; simply
        !           297:  * pass control to the OpenBSD system call. A few commands need
        !           298:  * conversions after the actual system call has done its work,
        !           299:  * because the flag values and lock structure are different.
        !           300:  */
        !           301: int
        !           302: linux_sys_fcntl(p, v, retval)
        !           303:        struct proc *p;
        !           304:        void *v;
        !           305:        register_t *retval;
        !           306: {
        !           307:        struct linux_sys_fcntl_args /* {
        !           308:                syscallarg(int) fd;
        !           309:                syscallarg(int) cmd;
        !           310:                syscallarg(void *) arg;
        !           311:        } */ *uap = v;
        !           312:        int fd, cmd, error, val;
        !           313:        caddr_t arg, sg;
        !           314:        struct linux_flock lfl;
        !           315:        struct flock *bfp, bfl;
        !           316:        struct sys_fcntl_args fca;
        !           317:        struct filedesc *fdp;
        !           318:        struct file *fp;
        !           319:        struct vnode *vp;
        !           320:        struct vattr va;
        !           321:        long pgid;
        !           322:        struct pgrp *pgrp;
        !           323:        struct tty *tp, *(*d_tty)(dev_t);
        !           324:
        !           325:        fd = SCARG(uap, fd);
        !           326:        cmd = SCARG(uap, cmd);
        !           327:        arg = (caddr_t) SCARG(uap, arg);
        !           328:
        !           329:        switch (cmd) {
        !           330:        case LINUX_F_DUPFD:
        !           331:                cmd = F_DUPFD;
        !           332:                break;
        !           333:        case LINUX_F_GETFD:
        !           334:                cmd = F_GETFD;
        !           335:                break;
        !           336:        case LINUX_F_SETFD:
        !           337:                cmd = F_SETFD;
        !           338:                break;
        !           339:        case LINUX_F_GETFL:
        !           340:                SCARG(&fca, fd) = fd;
        !           341:                SCARG(&fca, cmd) = F_GETFL;
        !           342:                SCARG(&fca, arg) = arg;
        !           343:                if ((error = sys_fcntl(p, &fca, retval)))
        !           344:                        return error;
        !           345:                retval[0] = bsd_to_linux_ioflags(retval[0]);
        !           346:                return 0;
        !           347:        case LINUX_F_SETFL:
        !           348:                val = linux_to_bsd_ioflags((int)SCARG(uap, arg));
        !           349:                SCARG(&fca, fd) = fd;
        !           350:                SCARG(&fca, cmd) = F_SETFL;
        !           351:                SCARG(&fca, arg) = (caddr_t) val;
        !           352:                return sys_fcntl(p, &fca, retval);
        !           353:        case LINUX_F_GETLK:
        !           354:                sg = stackgap_init(p->p_emul);
        !           355:                if ((error = copyin(arg, &lfl, sizeof lfl)))
        !           356:                        return error;
        !           357:                linux_to_bsd_flock(&lfl, &bfl);
        !           358:                bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
        !           359:                SCARG(&fca, fd) = fd;
        !           360:                SCARG(&fca, cmd) = F_GETLK;
        !           361:                SCARG(&fca, arg) = bfp;
        !           362:                if ((error = copyout(&bfl, bfp, sizeof bfl)))
        !           363:                        return error;
        !           364:                if ((error = sys_fcntl(p, &fca, retval)))
        !           365:                        return error;
        !           366:                if ((error = copyin(bfp, &bfl, sizeof bfl)))
        !           367:                        return error;
        !           368:                bsd_to_linux_flock(&bfl, &lfl);
        !           369:                error = copyout(&lfl, arg, sizeof lfl);
        !           370:                return error;
        !           371:                break;
        !           372:        case LINUX_F_SETLK:
        !           373:        case LINUX_F_SETLKW:
        !           374:                cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW);
        !           375:                if ((error = copyin(arg, &lfl, sizeof lfl)))
        !           376:                        return error;
        !           377:                linux_to_bsd_flock(&lfl, &bfl);
        !           378:                sg = stackgap_init(p->p_emul);
        !           379:                bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
        !           380:                if ((error = copyout(&bfl, bfp, sizeof bfl)))
        !           381:                        return error;
        !           382:                SCARG(&fca, fd) = fd;
        !           383:                SCARG(&fca, cmd) = cmd;
        !           384:                SCARG(&fca, arg) = bfp;
        !           385:                return sys_fcntl(p, &fca, retval);
        !           386:                break;
        !           387:        case LINUX_F_SETOWN:
        !           388:        case LINUX_F_GETOWN:
        !           389:                /*
        !           390:                 * We need to route around the normal fcntl() for these calls,
        !           391:                 * since it uses TIOC{G,S}PGRP, which is too restrictive for
        !           392:                 * Linux F_{G,S}ETOWN semantics. For sockets, this problem
        !           393:                 * does not exist.
        !           394:                 */
        !           395:                fdp = p->p_fd;
        !           396:                if ((fp = fd_getfile(fdp, fd)) == NULL)
        !           397:                        return (EBADF);
        !           398:                if (fp->f_type == DTYPE_SOCKET) {
        !           399:                        cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
        !           400:                        break;
        !           401:                }
        !           402:                vp = (struct vnode *)fp->f_data;
        !           403:                if (vp->v_type != VCHR)
        !           404:                        return EINVAL;
        !           405:                FREF(fp);
        !           406:                error = VOP_GETATTR(vp, &va, p->p_ucred, p);
        !           407:                FRELE(fp);
        !           408:                if (error)
        !           409:                        return error;
        !           410:                d_tty = cdevsw[major(va.va_rdev)].d_tty;
        !           411:                if (!d_tty || (!(tp = (*d_tty)(va.va_rdev))))
        !           412:                        return EINVAL;
        !           413:                if (cmd == LINUX_F_GETOWN) {
        !           414:                        retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
        !           415:                        return 0;
        !           416:                }
        !           417:                if ((long)arg <= 0) {
        !           418:                        pgid = -(long)arg;
        !           419:                } else {
        !           420:                        struct proc *p1 = pfind((long)arg);
        !           421:                        if (p1 == 0)
        !           422:                                return (ESRCH);
        !           423:                        pgid = (long)p1->p_pgrp->pg_id;
        !           424:                }
        !           425:                pgrp = pgfind(pgid);
        !           426:                if (pgrp == NULL || pgrp->pg_session != p->p_session)
        !           427:                        return EPERM;
        !           428:                tp->t_pgrp = pgrp;
        !           429:                return 0;
        !           430:        default:
        !           431:                return EOPNOTSUPP;
        !           432:        }
        !           433:
        !           434:        SCARG(&fca, fd) = fd;
        !           435:        SCARG(&fca, cmd) = cmd;
        !           436:        SCARG(&fca, arg) = arg;
        !           437:
        !           438:        return sys_fcntl(p, &fca, retval);
        !           439: }
        !           440:
        !           441: /*
        !           442:  * Convert a OpenBSD stat structure to a Linux stat structure.
        !           443:  * Only the order of the fields and the padding in the structure
        !           444:  * is different. linux_fakedev is a machine-dependent function
        !           445:  * which optionally converts device driver major/minor numbers
        !           446:  * (XXX horrible, but what can you do against code that compares
        !           447:  * things against constant major device numbers? sigh)
        !           448:  */
        !           449: static void
        !           450: bsd_to_linux_stat(bsp, lsp)
        !           451:        struct stat *bsp;
        !           452:        struct linux_stat *lsp;
        !           453: {
        !           454:
        !           455:        lsp->lst_dev     = bsp->st_dev;
        !           456:        lsp->lst_ino     = bsp->st_ino;
        !           457:        lsp->lst_mode    = bsp->st_mode;
        !           458:        lsp->lst_nlink   = bsp->st_nlink;
        !           459:        lsp->lst_uid     = bsp->st_uid;
        !           460:        lsp->lst_gid     = bsp->st_gid;
        !           461:        lsp->lst_rdev    = linux_fakedev(bsp->st_rdev);
        !           462:        lsp->lst_size    = bsp->st_size;
        !           463:        lsp->lst_blksize = bsp->st_blksize;
        !           464:        lsp->lst_blocks  = bsp->st_blocks;
        !           465:        lsp->lst_atime   = bsp->st_atime;
        !           466:        lsp->lst_mtime   = bsp->st_mtime;
        !           467:        lsp->lst_ctime   = bsp->st_ctime;
        !           468: }
        !           469:
        !           470: /*
        !           471:  * The stat functions below are plain sailing. stat and lstat are handled
        !           472:  * by one function to avoid code duplication.
        !           473:  */
        !           474: int
        !           475: linux_sys_fstat(p, v, retval)
        !           476:        struct proc *p;
        !           477:        void *v;
        !           478:        register_t *retval;
        !           479: {
        !           480:        struct linux_sys_fstat_args /* {
        !           481:                syscallarg(int) fd;
        !           482:                syscallarg(linux_stat *) sp;
        !           483:        } */ *uap = v;
        !           484:        struct sys_fstat_args fsa;
        !           485:        struct linux_stat tmplst;
        !           486:        struct stat *st,tmpst;
        !           487:        caddr_t sg;
        !           488:        int error;
        !           489:
        !           490:        sg = stackgap_init(p->p_emul);
        !           491:
        !           492:        st = stackgap_alloc(&sg, sizeof (struct stat));
        !           493:
        !           494:        SCARG(&fsa, fd) = SCARG(uap, fd);
        !           495:        SCARG(&fsa, sb) = st;
        !           496:
        !           497:        if ((error = sys_fstat(p, &fsa, retval)))
        !           498:                return error;
        !           499:
        !           500:        if ((error = copyin(st, &tmpst, sizeof tmpst)))
        !           501:                return error;
        !           502:
        !           503:        bsd_to_linux_stat(&tmpst, &tmplst);
        !           504:
        !           505:        if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
        !           506:                return error;
        !           507:
        !           508:        return 0;
        !           509: }
        !           510:
        !           511: static int
        !           512: linux_stat1(p, v, retval, dolstat)
        !           513:        struct proc *p;
        !           514:        void *v;
        !           515:        register_t *retval;
        !           516:        int dolstat;
        !           517: {
        !           518:        struct sys_stat_args sa;
        !           519:        struct linux_stat tmplst;
        !           520:        struct stat *st, tmpst;
        !           521:        caddr_t sg;
        !           522:        int error;
        !           523:        struct linux_sys_stat_args *uap = v;
        !           524:
        !           525:        sg = stackgap_init(p->p_emul);
        !           526:
        !           527:        st = stackgap_alloc(&sg, sizeof (struct stat));
        !           528:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
        !           529:
        !           530:        SCARG(&sa, ub) = st;
        !           531:        SCARG(&sa, path) = SCARG(uap, path);
        !           532:
        !           533:        if ((error = (dolstat ? sys_lstat(p, &sa, retval) :
        !           534:                                sys_stat(p, &sa, retval))))
        !           535:                return error;
        !           536:
        !           537:        if ((error = copyin(st, &tmpst, sizeof tmpst)))
        !           538:                return error;
        !           539:
        !           540:        bsd_to_linux_stat(&tmpst, &tmplst);
        !           541:
        !           542:        if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
        !           543:                return error;
        !           544:
        !           545:        return 0;
        !           546: }
        !           547:
        !           548: int
        !           549: linux_sys_stat(p, v, retval)
        !           550:        struct proc *p;
        !           551:        void *v;
        !           552:        register_t *retval;
        !           553: {
        !           554:        struct linux_sys_stat_args /* {
        !           555:                syscallarg(char *) path;
        !           556:                syscallarg(struct linux_stat *) sp;
        !           557:        } */ *uap = v;
        !           558:
        !           559:        return linux_stat1(p, uap, retval, 0);
        !           560: }
        !           561:
        !           562: int
        !           563: linux_sys_lstat(p, v, retval)
        !           564:        struct proc *p;
        !           565:        void *v;
        !           566:        register_t *retval;
        !           567: {
        !           568:        struct linux_sys_lstat_args /* {
        !           569:                syscallarg(char *) path;
        !           570:                syscallarg(struct linux_stat *) sp;
        !           571:        } */ *uap = v;
        !           572:
        !           573:        return linux_stat1(p, uap, retval, 1);
        !           574: }
        !           575:
        !           576: /*
        !           577:  * The following syscalls are mostly here because of the alternate path check.
        !           578:  */
        !           579: int
        !           580: linux_sys_access(p, v, retval)
        !           581:        struct proc *p;
        !           582:        void *v;
        !           583:        register_t *retval;
        !           584: {
        !           585:        struct linux_sys_access_args /* {
        !           586:                syscallarg(char *) path;
        !           587:                syscallarg(int) flags;
        !           588:        } */ *uap = v;
        !           589:        caddr_t sg = stackgap_init(p->p_emul);
        !           590:
        !           591:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
        !           592:
        !           593:        return sys_access(p, uap, retval);
        !           594: }
        !           595:
        !           596: int
        !           597: linux_sys_unlink(p, v, retval)
        !           598:        struct proc *p;
        !           599:        void *v;
        !           600:        register_t *retval;
        !           601:
        !           602: {
        !           603:        struct linux_sys_unlink_args /* {
        !           604:                syscallarg(char *) path;
        !           605:        } */ *uap = v;
        !           606:        caddr_t sg = stackgap_init(p->p_emul);
        !           607:
        !           608:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
        !           609:
        !           610:        return sys_unlink(p, uap, retval);
        !           611: }
        !           612:
        !           613: int
        !           614: linux_sys_chdir(p, v, retval)
        !           615:        struct proc *p;
        !           616:        void *v;
        !           617:        register_t *retval;
        !           618: {
        !           619:        struct linux_sys_chdir_args /* {
        !           620:                syscallarg(char *) path;
        !           621:        } */ *uap = v;
        !           622:        caddr_t sg = stackgap_init(p->p_emul);
        !           623:
        !           624:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
        !           625:
        !           626:        return sys_chdir(p, uap, retval);
        !           627: }
        !           628:
        !           629: int
        !           630: linux_sys_mknod(p, v, retval)
        !           631:        struct proc *p;
        !           632:        void *v;
        !           633:        register_t *retval;
        !           634: {
        !           635:        struct linux_sys_mknod_args /* {
        !           636:                syscallarg(char *) path;
        !           637:                syscallarg(int) mode;
        !           638:                syscallarg(int) dev;
        !           639:        } */ *uap = v;
        !           640:        caddr_t sg = stackgap_init(p->p_emul);
        !           641:        struct sys_mkfifo_args bma;
        !           642:
        !           643:        LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
        !           644:
        !           645:        /*
        !           646:         * BSD handles FIFOs separately
        !           647:         */
        !           648:        if (S_ISFIFO(SCARG(uap, mode))) {
        !           649:                SCARG(&bma, path) = SCARG(uap, path);
        !           650:                SCARG(&bma, mode) = SCARG(uap, mode);
        !           651:                return sys_mkfifo(p, uap, retval);
        !           652:        } else
        !           653:                return sys_mknod(p, uap, retval);
        !           654: }
        !           655:
        !           656: int
        !           657: linux_sys_chmod(p, v, retval)
        !           658:        struct proc *p;
        !           659:        void *v;
        !           660:        register_t *retval;
        !           661: {
        !           662:        struct linux_sys_chmod_args /* {
        !           663:                syscallarg(char *) path;
        !           664:                syscallarg(int) mode;
        !           665:        } */ *uap = v;
        !           666:        caddr_t sg = stackgap_init(p->p_emul);
        !           667:
        !           668:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
        !           669:
        !           670:        return sys_chmod(p, uap, retval);
        !           671: }
        !           672:
        !           673: int
        !           674: linux_sys_chown16(p, v, retval)
        !           675:        struct proc *p;
        !           676:        void *v;
        !           677:        register_t *retval;
        !           678: {
        !           679:        struct linux_sys_chown16_args /* {
        !           680:                syscallarg(char *) path;
        !           681:                syscallarg(int) uid;
        !           682:                syscallarg(int) gid;
        !           683:        } */ *uap = v;
        !           684:        struct sys_chown_args bca;
        !           685:        caddr_t sg = stackgap_init(p->p_emul);
        !           686:
        !           687:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
        !           688:
        !           689:        SCARG(&bca, path) = SCARG(uap, path);
        !           690:        SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
        !           691:                (uid_t)-1 : SCARG(uap, uid);
        !           692:        SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
        !           693:                (gid_t)-1 : SCARG(uap, gid);
        !           694:
        !           695:        return sys_chown(p, &bca, retval);
        !           696: }
        !           697:
        !           698: int
        !           699: linux_sys_fchown16(p, v, retval)
        !           700:        struct proc *p;
        !           701:        void *v;
        !           702:        register_t *retval;
        !           703: {
        !           704:        struct linux_sys_fchown16_args /* {
        !           705:                syscallarg(int) fd;
        !           706:                syscallarg(int) uid;
        !           707:                syscallarg(int) gid;
        !           708:        } */ *uap = v;
        !           709:        struct sys_fchown_args bfa;
        !           710:
        !           711:        SCARG(&bfa, fd) = SCARG(uap, fd);
        !           712:        SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
        !           713:                (uid_t)-1 : SCARG(uap, uid);
        !           714:        SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
        !           715:                (gid_t)-1 : SCARG(uap, gid);
        !           716:
        !           717:        return sys_fchown(p, &bfa, retval);
        !           718: }
        !           719:
        !           720: int
        !           721: linux_sys_lchown16(p, v, retval)
        !           722:        struct proc *p;
        !           723:        void *v;
        !           724:        register_t *retval;
        !           725: {
        !           726:        struct linux_sys_lchown16_args /* {
        !           727:                syscallarg(char *) path;
        !           728:                syscallarg(int) uid;
        !           729:                syscallarg(int) gid;
        !           730:        } */ *uap = v;
        !           731:        struct sys_lchown_args bla;
        !           732:
        !           733:        SCARG(&bla, path) = SCARG(uap, path);
        !           734:        SCARG(&bla, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
        !           735:                (uid_t)-1 : SCARG(uap, uid);
        !           736:        SCARG(&bla, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
        !           737:                (gid_t)-1 : SCARG(uap, gid);
        !           738:
        !           739:        return sys_lchown(p, &bla, retval);
        !           740: }
        !           741:
        !           742: int
        !           743: linux_sys_rename(p, v, retval)
        !           744:        struct proc *p;
        !           745:        void *v;
        !           746:        register_t *retval;
        !           747: {
        !           748:        struct linux_sys_rename_args /* {
        !           749:                syscallarg(char *) from;
        !           750:                syscallarg(char *) to;
        !           751:        } */ *uap = v;
        !           752:        caddr_t sg = stackgap_init(p->p_emul);
        !           753:
        !           754:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from));
        !           755:        LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
        !           756:
        !           757:        return sys_rename(p, uap, retval);
        !           758: }
        !           759:
        !           760: int
        !           761: linux_sys_mkdir(p, v, retval)
        !           762:        struct proc *p;
        !           763:        void *v;
        !           764:        register_t *retval;
        !           765: {
        !           766:        struct linux_sys_mkdir_args /* {
        !           767:                syscallarg(char *) path;
        !           768:                syscallarg(int) mode;
        !           769:        } */ *uap = v;
        !           770:        caddr_t sg = stackgap_init(p->p_emul);
        !           771:
        !           772:        LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
        !           773:
        !           774:        return sys_mkdir(p, uap, retval);
        !           775: }
        !           776:
        !           777: int
        !           778: linux_sys_rmdir(p, v, retval)
        !           779:        struct proc *p;
        !           780:        void *v;
        !           781:        register_t *retval;
        !           782: {
        !           783:        struct linux_sys_rmdir_args /* {
        !           784:                syscallarg(char *) path;
        !           785:        } */ *uap = v;
        !           786:        caddr_t sg = stackgap_init(p->p_emul);
        !           787:
        !           788:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
        !           789:
        !           790:        return sys_rmdir(p, uap, retval);
        !           791: }
        !           792:
        !           793: int
        !           794: linux_sys_symlink(p, v, retval)
        !           795:        struct proc *p;
        !           796:        void *v;
        !           797:        register_t *retval;
        !           798: {
        !           799:        struct linux_sys_symlink_args /* {
        !           800:                syscallarg(char *) path;
        !           801:                syscallarg(char *) to;
        !           802:        } */ *uap = v;
        !           803:        caddr_t sg = stackgap_init(p->p_emul);
        !           804:
        !           805:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
        !           806:        LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
        !           807:
        !           808:        return sys_symlink(p, uap, retval);
        !           809: }
        !           810:
        !           811: int
        !           812: linux_sys_readlink(p, v, retval)
        !           813:        struct proc *p;
        !           814:        void *v;
        !           815:        register_t *retval;
        !           816: {
        !           817:        struct linux_sys_readlink_args /* {
        !           818:                syscallarg(char *) name;
        !           819:                syscallarg(char *) buf;
        !           820:                syscallarg(int) count;
        !           821:        } */ *uap = v;
        !           822:        caddr_t sg = stackgap_init(p->p_emul);
        !           823:
        !           824:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, name));
        !           825:
        !           826:        return sys_readlink(p, uap, retval);
        !           827: }
        !           828:
        !           829: int
        !           830: linux_sys_truncate(p, v, retval)
        !           831:        struct proc *p;
        !           832:        void *v;
        !           833:        register_t *retval;
        !           834: {
        !           835:        struct linux_sys_truncate_args /* {
        !           836:                syscallarg(char *) path;
        !           837:                syscallarg(long) length;
        !           838:        } */ *uap = v;
        !           839:        caddr_t sg = stackgap_init(p->p_emul);
        !           840:
        !           841:        LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
        !           842:
        !           843:        return compat_43_sys_truncate(p, uap, retval);
        !           844: }
        !           845:
        !           846: /*
        !           847:  * This is just fsync() for now (just as it is in the Linux kernel)
        !           848:  */
        !           849: int
        !           850: linux_sys_fdatasync(p, v, retval)
        !           851:        struct proc *p;
        !           852:        void *v;
        !           853:        register_t *retval;
        !           854: {
        !           855:        struct linux_sys_fdatasync_args /* {
        !           856:                syscallarg(int) fd;
        !           857:        } */ *uap = v;
        !           858:        return sys_fsync(p, uap, retval);
        !           859: }
        !           860:
        !           861: /*
        !           862:  * pread(2).
        !           863:  */
        !           864: int
        !           865: linux_sys_pread(p, v, retval)
        !           866:        struct proc *p;
        !           867:        void *v;
        !           868:        register_t *retval;
        !           869: {
        !           870:        struct linux_sys_pread_args /* {
        !           871:                syscallarg(int) fd;
        !           872:                syscallarg(void *) buf;
        !           873:                syscallarg(size_t) nbyte;
        !           874:                syscallarg(linux_off_t) offset;
        !           875:        } */ *uap = v;
        !           876:        struct sys_pread_args pra;
        !           877:
        !           878:        SCARG(&pra, fd) = SCARG(uap, fd);
        !           879:        SCARG(&pra, buf) = SCARG(uap, buf);
        !           880:        SCARG(&pra, nbyte) = SCARG(uap, nbyte);
        !           881:        SCARG(&pra, offset) = SCARG(uap, offset);
        !           882:
        !           883:        return sys_pread(p, &pra, retval);
        !           884: }
        !           885:
        !           886: /*
        !           887:  * pwrite(2).
        !           888:  */
        !           889: int
        !           890: linux_sys_pwrite(p, v, retval)
        !           891:        struct proc *p;
        !           892:        void *v;
        !           893:        register_t *retval;
        !           894: {
        !           895:        struct linux_sys_pwrite_args /* {
        !           896:                syscallarg(int) fd;
        !           897:                syscallarg(char *) buf;
        !           898:                syscallarg(size_t) nbyte;
        !           899:                syscallarg(linux_off_t) offset;
        !           900:        } */ *uap = v;
        !           901:        struct sys_pwrite_args pra;
        !           902:
        !           903:        SCARG(&pra, fd) = SCARG(uap, fd);
        !           904:        SCARG(&pra, buf) = SCARG(uap, buf);
        !           905:        SCARG(&pra, nbyte) = SCARG(uap, nbyte);
        !           906:        SCARG(&pra, offset) = SCARG(uap, offset);
        !           907:
        !           908:        return sys_pwrite(p, &pra, retval);
        !           909: }

CVSweb