Annotation of Net2/kern/vfs_syscalls.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * Copyright (c) 1989 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by the University of
                     16:  *     California, Berkeley and its contributors.
                     17:  * 4. Neither the name of the University nor the names of its contributors
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
1.1.1.3 ! root       33:  *     from: @(#)vfs_syscalls.c        7.74 (Berkeley) 6/21/91
        !            34:  *     vfs_syscalls.c,v 1.4.2.1 1993/08/02 23:51:21 cgd Exp
1.1       root       35:  */
                     36: 
                     37: #include "param.h"
                     38: #include "systm.h"
                     39: #include "namei.h"
                     40: #include "filedesc.h"
                     41: #include "kernel.h"
                     42: #include "file.h"
                     43: #include "stat.h"
                     44: #include "vnode.h"
                     45: #include "mount.h"
                     46: #include "proc.h"
                     47: #include "uio.h"
                     48: #include "malloc.h"
                     49: 
                     50: /*
                     51:  * Virtual File System System Calls
                     52:  */
                     53: 
                     54: /*
                     55:  * Mount system call.
                     56:  */
1.1.1.3 ! root       57: 
        !            58: struct mount_args {
        !            59:        int     type;
        !            60:        char    *dir;
        !            61:        int     flags;
        !            62:        caddr_t data;
        !            63: };
        !            64: 
1.1       root       65: /* ARGSUSED */
                     66: mount(p, uap, retval)
                     67:        struct proc *p;
1.1.1.3 ! root       68:        register struct mount_args *uap;
1.1       root       69:        int *retval;
                     70: {
                     71:        register struct nameidata *ndp;
                     72:        register struct vnode *vp;
                     73:        register struct mount *mp;
                     74:        int error, flag;
                     75:        struct nameidata nd;
                     76: 
                     77:        /*
                     78:         * Must be super user
                     79:         */
                     80:        if (error = suser(p->p_ucred, &p->p_acflag))
                     81:                return (error);
                     82:        /*
                     83:         * Get vnode to be covered
                     84:         */
                     85:        ndp = &nd;
                     86:        ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
                     87:        ndp->ni_segflg = UIO_USERSPACE;
                     88:        ndp->ni_dirp = uap->dir;
                     89:        if (error = namei(ndp, p))
                     90:                return (error);
                     91:        vp = ndp->ni_vp;
                     92:        if (uap->flags & MNT_UPDATE) {
                     93:                if ((vp->v_flag & VROOT) == 0) {
                     94:                        vput(vp);
                     95:                        return (EINVAL);
                     96:                }
                     97:                mp = vp->v_mount;
                     98:                /*
                     99:                 * We allow going from read-only to read-write,
                    100:                 * but not from read-write to read-only.
                    101:                 */
                    102:                if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
                    103:                    (uap->flags & MNT_RDONLY) != 0) {
                    104:                        vput(vp);
                    105:                        return (EOPNOTSUPP);    /* Needs translation */
                    106:                }
                    107:                flag = mp->mnt_flag;
                    108:                mp->mnt_flag |= MNT_UPDATE;
                    109:                VOP_UNLOCK(vp);
                    110:                goto update;
                    111:        }
                    112:        vinvalbuf(vp, 1);
                    113:        if (vp->v_usecount != 1) {
                    114:                vput(vp);
                    115:                return (EBUSY);
                    116:        }
                    117:        if (vp->v_type != VDIR) {
                    118:                vput(vp);
                    119:                return (ENOTDIR);
                    120:        }
                    121:        if ((unsigned long)uap->type > MOUNT_MAXTYPE ||
                    122:            vfssw[uap->type] == (struct vfsops *)0) {
                    123:                vput(vp);
                    124:                return (ENODEV);
                    125:        }
                    126: 
                    127:        /*
                    128:         * Allocate and initialize the file system.
                    129:         */
                    130:        mp = (struct mount *)malloc((u_long)sizeof(struct mount),
                    131:                M_MOUNT, M_WAITOK);
                    132:        mp->mnt_op = vfssw[uap->type];
                    133:        mp->mnt_flag = 0;
                    134:        mp->mnt_exroot = 0;
                    135:        mp->mnt_mounth = NULLVP;
                    136:        if (error = vfs_lock(mp)) {
                    137:                free((caddr_t)mp, M_MOUNT);
                    138:                vput(vp);
                    139:                return (error);
                    140:        }
                    141:        if (vp->v_mountedhere != (struct mount *)0) {
                    142:                vfs_unlock(mp);
                    143:                free((caddr_t)mp, M_MOUNT);
                    144:                vput(vp);
                    145:                return (EBUSY);
                    146:        }
                    147:        vp->v_mountedhere = mp;
                    148:        mp->mnt_vnodecovered = vp;
                    149: update:
                    150:        /*
                    151:         * Set the mount level flags.
                    152:         */
                    153:        if (uap->flags & MNT_RDONLY)
                    154:                mp->mnt_flag |= MNT_RDONLY;
                    155:        else
                    156:                mp->mnt_flag &= ~MNT_RDONLY;
                    157:        if (uap->flags & MNT_NOSUID)
                    158:                mp->mnt_flag |= MNT_NOSUID;
                    159:        else
                    160:                mp->mnt_flag &= ~MNT_NOSUID;
                    161:        if (uap->flags & MNT_NOEXEC)
                    162:                mp->mnt_flag |= MNT_NOEXEC;
                    163:        else
                    164:                mp->mnt_flag &= ~MNT_NOEXEC;
                    165:        if (uap->flags & MNT_NODEV)
                    166:                mp->mnt_flag |= MNT_NODEV;
                    167:        else
                    168:                mp->mnt_flag &= ~MNT_NODEV;
                    169:        if (uap->flags & MNT_SYNCHRONOUS)
                    170:                mp->mnt_flag |= MNT_SYNCHRONOUS;
                    171:        else
                    172:                mp->mnt_flag &= ~MNT_SYNCHRONOUS;
                    173:        /*
                    174:         * Mount the filesystem.
                    175:         */
                    176:        error = VFS_MOUNT(mp, uap->dir, uap->data, ndp, p);
                    177:        if (mp->mnt_flag & MNT_UPDATE) {
                    178:                mp->mnt_flag &= ~MNT_UPDATE;
                    179:                vrele(vp);
                    180:                if (error)
                    181:                        mp->mnt_flag = flag;
                    182:                return (error);
                    183:        }
                    184:        /*
                    185:         * Put the new filesystem on the mount list after root.
                    186:         */
                    187:        mp->mnt_next = rootfs->mnt_next;
                    188:        mp->mnt_prev = rootfs;
                    189:        rootfs->mnt_next = mp;
                    190:        mp->mnt_next->mnt_prev = mp;
                    191:        cache_purge(vp);
                    192:        if (!error) {
                    193:                VOP_UNLOCK(vp);
                    194:                vfs_unlock(mp);
                    195:                error = VFS_START(mp, 0, p);
                    196:        } else {
                    197:                vfs_remove(mp);
                    198:                free((caddr_t)mp, M_MOUNT);
                    199:                vput(vp);
                    200:        }
                    201:        return (error);
                    202: }
                    203: 
                    204: /*
                    205:  * Unmount system call.
                    206:  *
                    207:  * Note: unmount takes a path to the vnode mounted on as argument,
                    208:  * not special file (as before).
                    209:  */
1.1.1.3 ! root      210: 
        !           211: struct umount_args {
        !           212:        char    *pathp;
        !           213:        int     flags;
        !           214: };
        !           215: 
1.1       root      216: /* ARGSUSED */
                    217: unmount(p, uap, retval)
                    218:        struct proc *p;
1.1.1.3 ! root      219:        register struct umount_args *uap;
1.1       root      220:        int *retval;
                    221: {
                    222:        register struct vnode *vp;
                    223:        register struct nameidata *ndp;
                    224:        struct mount *mp;
                    225:        int error;
                    226:        struct nameidata nd;
                    227: 
                    228:        /*
                    229:         * Must be super user
                    230:         */
                    231:        if (error = suser(p->p_ucred, &p->p_acflag))
                    232:                return (error);
                    233: 
                    234:        ndp = &nd;
                    235:        ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
                    236:        ndp->ni_segflg = UIO_USERSPACE;
                    237:        ndp->ni_dirp = uap->pathp;
                    238:        if (error = namei(ndp, p))
                    239:                return (error);
                    240:        vp = ndp->ni_vp;
                    241:        /*
                    242:         * Must be the root of the filesystem
                    243:         */
                    244:        if ((vp->v_flag & VROOT) == 0) {
                    245:                vput(vp);
                    246:                return (EINVAL);
                    247:        }
                    248:        mp = vp->v_mount;
                    249:        vput(vp);
                    250:        return (dounmount(mp, uap->flags, p));
                    251: }
                    252: 
                    253: /*
                    254:  * Do an unmount.
                    255:  */
                    256: dounmount(mp, flags, p)
                    257:        register struct mount *mp;
                    258:        int flags;
                    259:        struct proc *p;
                    260: {
                    261:        struct vnode *coveredvp;
                    262:        int error;
                    263: 
                    264:        coveredvp = mp->mnt_vnodecovered;
                    265:        if (vfs_busy(mp))
                    266:                return (EBUSY);
                    267:        mp->mnt_flag |= MNT_UNMOUNT;
                    268:        if (error = vfs_lock(mp))
                    269:                return (error);
                    270: 
                    271:        vnode_pager_umount(mp); /* release cached vnodes */
                    272:        cache_purgevfs(mp);     /* remove cache entries for this file sys */
                    273:        if ((error = VFS_SYNC(mp, MNT_WAIT)) == 0 || (flags & MNT_FORCE))
                    274:                error = VFS_UNMOUNT(mp, flags, p);
                    275:        mp->mnt_flag &= ~MNT_UNMOUNT;
                    276:        vfs_unbusy(mp);
                    277:        if (error) {
                    278:                vfs_unlock(mp);
                    279:        } else {
                    280:                vrele(coveredvp);
                    281:                vfs_remove(mp);
                    282:                free((caddr_t)mp, M_MOUNT);
                    283:        }
                    284:        return (error);
                    285: }
                    286: 
                    287: /*
                    288:  * Sync system call.
                    289:  * Sync each mounted filesystem.
                    290:  */
                    291: /* ARGSUSED */
                    292: sync(p, uap, retval)
                    293:        struct proc *p;
                    294:        void *uap;
                    295:        int *retval;
                    296: {
                    297:        register struct mount *mp;
                    298:        struct mount *omp;
                    299: 
                    300:        mp = rootfs;
                    301:        do {
                    302:                /*
                    303:                 * The lock check below is to avoid races with mount
                    304:                 * and unmount.
                    305:                 */
                    306:                if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
                    307:                    !vfs_busy(mp)) {
                    308:                        VFS_SYNC(mp, MNT_NOWAIT);
                    309:                        omp = mp;
                    310:                        mp = mp->mnt_next;
                    311:                        vfs_unbusy(omp);
                    312:                } else
                    313:                        mp = mp->mnt_next;
                    314:        } while (mp != rootfs);
                    315:        return (0);
                    316: }
                    317: 
                    318: /*
                    319:  * Operate on filesystem quotas.
                    320:  */
1.1.1.3 ! root      321: 
        !           322: struct quotactl_args {
        !           323:        char *path;
        !           324:        int cmd;
        !           325:        int uid;
        !           326:        caddr_t arg;
        !           327: };
        !           328: 
1.1       root      329: /* ARGSUSED */
                    330: quotactl(p, uap, retval)
                    331:        struct proc *p;
1.1.1.3 ! root      332:        register struct quotactl_args *uap;
1.1       root      333:        int *retval;
                    334: {
                    335:        register struct mount *mp;
                    336:        register struct nameidata *ndp;
                    337:        int error;
                    338:        struct nameidata nd;
                    339: 
                    340:        ndp = &nd;
                    341:        ndp->ni_nameiop = LOOKUP | FOLLOW;
                    342:        ndp->ni_segflg = UIO_USERSPACE;
                    343:        ndp->ni_dirp = uap->path;
                    344:        if (error = namei(ndp, p))
                    345:                return (error);
                    346:        mp = ndp->ni_vp->v_mount;
                    347:        vrele(ndp->ni_vp);
                    348:        return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
                    349: }
                    350: 
                    351: /*
                    352:  * Get filesystem statistics.
                    353:  */
1.1.1.3 ! root      354: 
        !           355: struct statfs_args {
        !           356:        char *path;
        !           357:        struct statfs *buf;
        !           358: };
        !           359: 
1.1       root      360: /* ARGSUSED */
                    361: statfs(p, uap, retval)
                    362:        struct proc *p;
1.1.1.3 ! root      363:        register struct statfs_args *uap;
1.1       root      364:        int *retval;
                    365: {
                    366:        register struct mount *mp;
                    367:        register struct nameidata *ndp;
                    368:        register struct statfs *sp;
                    369:        int error;
                    370:        struct nameidata nd;
                    371: 
                    372:        ndp = &nd;
                    373:        ndp->ni_nameiop = LOOKUP | FOLLOW;
                    374:        ndp->ni_segflg = UIO_USERSPACE;
                    375:        ndp->ni_dirp = uap->path;
                    376:        if (error = namei(ndp, p))
                    377:                return (error);
                    378:        mp = ndp->ni_vp->v_mount;
                    379:        sp = &mp->mnt_stat;
                    380:        vrele(ndp->ni_vp);
                    381:        if (error = VFS_STATFS(mp, sp, p))
                    382:                return (error);
                    383:        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
                    384:        return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
                    385: }
                    386: 
                    387: /*
                    388:  * Get filesystem statistics.
                    389:  */
1.1.1.3 ! root      390: 
        !           391: struct fstatfs_args {
        !           392:        int fd;
        !           393:        struct statfs *buf;
        !           394: };
        !           395: 
1.1       root      396: /* ARGSUSED */
                    397: fstatfs(p, uap, retval)
                    398:        struct proc *p;
1.1.1.3 ! root      399:        register struct fstatfs_args *uap;
1.1       root      400:        int *retval;
                    401: {
                    402:        struct file *fp;
                    403:        struct mount *mp;
                    404:        register struct statfs *sp;
                    405:        int error;
                    406: 
                    407:        if (error = getvnode(p->p_fd, uap->fd, &fp))
                    408:                return (error);
                    409:        mp = ((struct vnode *)fp->f_data)->v_mount;
                    410:        sp = &mp->mnt_stat;
                    411:        if (error = VFS_STATFS(mp, sp, p))
                    412:                return (error);
                    413:        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
                    414:        return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
                    415: }
                    416: 
                    417: /*
                    418:  * Get statistics on all filesystems.
                    419:  */
1.1.1.3 ! root      420: 
        !           421: struct getfsstat_args {
        !           422:        struct statfs *buf;
        !           423:        long bufsize;
        !           424:        int flags;
        !           425: };
        !           426: 
1.1       root      427: getfsstat(p, uap, retval)
                    428:        struct proc *p;
1.1.1.3 ! root      429:        register struct getfsstat_args *uap;
1.1       root      430:        int *retval;
                    431: {
                    432:        register struct mount *mp;
                    433:        register struct statfs *sp;
                    434:        caddr_t sfsp;
                    435:        long count, maxcount, error;
                    436: 
                    437:        maxcount = uap->bufsize / sizeof(struct statfs);
                    438:        sfsp = (caddr_t)uap->buf;
                    439:        mp = rootfs;
                    440:        count = 0;
                    441:        do {
                    442:                if (sfsp && count < maxcount &&
                    443:                    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
                    444:                        sp = &mp->mnt_stat;
                    445:                        /*
                    446:                         * If MNT_NOWAIT is specified, do not refresh the
                    447:                         * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
                    448:                         */
                    449:                        if (((uap->flags & MNT_NOWAIT) == 0 ||
                    450:                            (uap->flags & MNT_WAIT)) &&
                    451:                            (error = VFS_STATFS(mp, sp, p))) {
                    452:                                mp = mp->mnt_prev;
                    453:                                continue;
                    454:                        }
                    455:                        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
                    456:                        if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
                    457:                                return (error);
                    458:                        sfsp += sizeof(*sp);
                    459:                }
                    460:                count++;
                    461:                mp = mp->mnt_prev;
                    462:        } while (mp != rootfs);
                    463:        if (sfsp && count > maxcount)
                    464:                *retval = maxcount;
                    465:        else
                    466:                *retval = count;
                    467:        return (0);
                    468: }
                    469: 
                    470: /*
                    471:  * Change current working directory to a given file descriptor.
                    472:  */
1.1.1.3 ! root      473: 
        !           474: struct fchdir_args {
        !           475:        int     fd;
        !           476: };
        !           477: 
1.1       root      478: /* ARGSUSED */
                    479: fchdir(p, uap, retval)
                    480:        struct proc *p;
1.1.1.3 ! root      481:        struct fchdir_args *uap;
1.1       root      482:        int *retval;
                    483: {
                    484:        register struct filedesc *fdp = p->p_fd;
                    485:        register struct vnode *vp;
                    486:        struct file *fp;
                    487:        int error;
                    488: 
                    489:        if (error = getvnode(fdp, uap->fd, &fp))
                    490:                return (error);
                    491:        vp = (struct vnode *)fp->f_data;
                    492:        VOP_LOCK(vp);
                    493:        if (vp->v_type != VDIR)
                    494:                error = ENOTDIR;
                    495:        else
                    496:                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
                    497:        VOP_UNLOCK(vp);
                    498:        if (error)
                    499:                return (error);
                    500:        VREF(vp);
                    501:        vrele(fdp->fd_cdir);
                    502:        fdp->fd_cdir = vp;
                    503:        return (0);
                    504: }
                    505: 
                    506: /*
                    507:  * Change current working directory (``.'').
                    508:  */
1.1.1.3 ! root      509: 
        !           510: struct chdir_args {
        !           511:        char    *fname;
        !           512: };
        !           513: 
1.1       root      514: /* ARGSUSED */
                    515: chdir(p, uap, retval)
                    516:        struct proc *p;
1.1.1.3 ! root      517:        struct chdir_args *uap;
1.1       root      518:        int *retval;
                    519: {
                    520:        register struct nameidata *ndp;
                    521:        register struct filedesc *fdp = p->p_fd;
                    522:        int error;
                    523:        struct nameidata nd;
                    524: 
                    525:        ndp = &nd;
                    526:        ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
                    527:        ndp->ni_segflg = UIO_USERSPACE;
                    528:        ndp->ni_dirp = uap->fname;
                    529:        if (error = chdirec(ndp, p))
                    530:                return (error);
                    531:        vrele(fdp->fd_cdir);
                    532:        fdp->fd_cdir = ndp->ni_vp;
                    533:        return (0);
                    534: }
                    535: 
                    536: /*
                    537:  * Change notion of root (``/'') directory.
                    538:  */
1.1.1.3 ! root      539: 
        !           540: struct chroot_args {
        !           541:        char    *fname;
        !           542: };
        !           543: 
1.1       root      544: /* ARGSUSED */
                    545: chroot(p, uap, retval)
                    546:        struct proc *p;
1.1.1.3 ! root      547:        struct chroot_args *uap;
1.1       root      548:        int *retval;
                    549: {
                    550:        register struct nameidata *ndp;
                    551:        register struct filedesc *fdp = p->p_fd;
                    552:        int error;
                    553:        struct nameidata nd;
                    554: 
                    555:        if (error = suser(p->p_ucred, &p->p_acflag))
                    556:                return (error);
                    557:        ndp = &nd;
                    558:        ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
                    559:        ndp->ni_segflg = UIO_USERSPACE;
                    560:        ndp->ni_dirp = uap->fname;
                    561:        if (error = chdirec(ndp, p))
                    562:                return (error);
                    563:        if (fdp->fd_rdir != NULL)
                    564:                vrele(fdp->fd_rdir);
                    565:        fdp->fd_rdir = ndp->ni_vp;
                    566:        return (0);
                    567: }
                    568: 
                    569: /*
                    570:  * Common routine for chroot and chdir.
                    571:  */
                    572: chdirec(ndp, p)
                    573:        struct nameidata *ndp;
                    574:        struct proc *p;
                    575: {
                    576:        struct vnode *vp;
                    577:        int error;
                    578: 
                    579:        if (error = namei(ndp, p))
                    580:                return (error);
                    581:        vp = ndp->ni_vp;
                    582:        if (vp->v_type != VDIR)
                    583:                error = ENOTDIR;
                    584:        else
                    585:                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
                    586:        VOP_UNLOCK(vp);
                    587:        if (error)
                    588:                vrele(vp);
                    589:        return (error);
                    590: }
                    591: 
                    592: /*
                    593:  * Open system call.
                    594:  * Check permissions, allocate an open file structure,
                    595:  * and call the device open routine if any.
                    596:  */
1.1.1.3 ! root      597: 
        !           598: struct open_args {
        !           599:        char    *fname;
        !           600:        int     mode;
        !           601:        int     crtmode;
        !           602: };
        !           603: 
1.1       root      604: open(p, uap, retval)
                    605:        struct proc *p;
1.1.1.3 ! root      606:        register struct open_args *uap;
1.1       root      607:        int *retval;
                    608: {
                    609:        struct nameidata *ndp;
                    610:        register struct filedesc *fdp = p->p_fd;
                    611:        register struct file *fp;
                    612:        register struct vnode *vp;
                    613:        int fmode, cmode;
                    614:        struct file *nfp;
                    615:        int type, indx, error;
                    616:        struct flock lf;
                    617:        struct nameidata nd;
                    618:        extern struct fileops vnops;
                    619: 
                    620:        if (error = falloc(p, &nfp, &indx))
                    621:                return (error);
                    622:        fp = nfp;
                    623:        fmode = FFLAGS(uap->mode);
                    624:        cmode = ((uap->crtmode &~ fdp->fd_cmask) & 07777) &~ S_ISVTX;
                    625:        ndp = &nd;
                    626:        ndp->ni_segflg = UIO_USERSPACE;
                    627:        ndp->ni_dirp = uap->fname;
                    628:        p->p_dupfd = -indx - 1;                 /* XXX check for fdopen */
                    629:        if (error = vn_open(ndp, p, fmode, cmode)) {
                    630:                ffree(fp);
                    631:                if (error == ENODEV &&          /* XXX from fdopen */
1.1.1.3 ! root      632:                    ((short) p->p_dupfd) >= 0 &&
1.1       root      633:                    (error = dupfdopen(fdp, indx, p->p_dupfd, fmode)) == 0) {
                    634:                        *retval = indx;
                    635:                        return (0);
                    636:                }
                    637:                if (error == ERESTART)
                    638:                        error = EINTR;
                    639:                fdp->fd_ofiles[indx] = NULL;
                    640:                return (error);
                    641:        }
                    642:        vp = ndp->ni_vp;
1.1.1.3 ! root      643:        VOP_UNLOCK(vp);
1.1       root      644:        fp->f_flag = fmode & FMASK;
                    645:        if (fmode & (O_EXLOCK | O_SHLOCK)) {
                    646:                lf.l_whence = SEEK_SET;
                    647:                lf.l_start = 0;
                    648:                lf.l_len = 0;
                    649:                if (fmode & O_EXLOCK)
                    650:                        lf.l_type = F_WRLCK;
                    651:                else
                    652:                        lf.l_type = F_RDLCK;
                    653:                type = F_FLOCK;
                    654:                if ((fmode & FNONBLOCK) == 0)
                    655:                        type |= F_WAIT;
                    656:                if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
                    657:                        (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
                    658:                        ffree(fp);
                    659:                        fdp->fd_ofiles[indx] = NULL;
                    660:                        return (error);
                    661:                }
                    662:                fp->f_flag |= FHASLOCK;
                    663:        }
                    664:        fp->f_type = DTYPE_VNODE;
                    665:        fp->f_ops = &vnops;
                    666:        fp->f_data = (caddr_t)vp;
                    667:        *retval = indx;
                    668:        return (0);
                    669: }
                    670: 
                    671: #ifdef COMPAT_43
                    672: /*
                    673:  * Creat system call.
                    674:  */
1.1.1.3 ! root      675: 
        !           676: struct ocreat_args {
        !           677:        char    *fname;
        !           678:        int     fmode;
        !           679: };
        !           680: 
1.1       root      681: ocreat(p, uap, retval)
                    682:        struct proc *p;
1.1.1.3 ! root      683:        register struct ocreat_args *uap;
1.1       root      684:        int *retval;
                    685: {
1.1.1.3 ! root      686:        struct open_args openuap;
1.1       root      687: 
                    688:        openuap.fname = uap->fname;
                    689:        openuap.crtmode = uap->fmode;
                    690:        openuap.mode = O_WRONLY | O_CREAT | O_TRUNC;
1.1.1.2   root      691:        return (open(p, (struct args *)&openuap, retval));
1.1       root      692: }
                    693: #endif /* COMPAT_43 */
                    694: 
                    695: /*
                    696:  * Mknod system call.
                    697:  */
1.1.1.3 ! root      698: 
        !           699: struct mknod_args {
        !           700:        char    *fname;
        !           701:        int     fmode;
        !           702:        int     dev;
        !           703: };
        !           704: 
1.1       root      705: /* ARGSUSED */
                    706: mknod(p, uap, retval)
                    707:        struct proc *p;
1.1.1.3 ! root      708:        register struct mknod_args *uap;
1.1       root      709:        int *retval;
                    710: {
                    711:        register struct nameidata *ndp;
                    712:        register struct vnode *vp;
                    713:        struct vattr vattr;
                    714:        int error;
                    715:        struct nameidata nd;
                    716: 
                    717:        if (error = suser(p->p_ucred, &p->p_acflag))
                    718:                return (error);
                    719:        ndp = &nd;
                    720:        ndp->ni_nameiop = CREATE | LOCKPARENT;
                    721:        ndp->ni_segflg = UIO_USERSPACE;
                    722:        ndp->ni_dirp = uap->fname;
                    723:        if (error = namei(ndp, p))
                    724:                return (error);
                    725:        vp = ndp->ni_vp;
                    726:        if (vp != NULL) {
                    727:                error = EEXIST;
                    728:                goto out;
                    729:        }
                    730:        VATTR_NULL(&vattr);
                    731:        switch (uap->fmode & S_IFMT) {
                    732: 
                    733:        case S_IFMT:    /* used by badsect to flag bad sectors */
                    734:                vattr.va_type = VBAD;
                    735:                break;
                    736:        case S_IFCHR:
                    737:                vattr.va_type = VCHR;
                    738:                break;
                    739:        case S_IFBLK:
                    740:                vattr.va_type = VBLK;
                    741:                break;
                    742:        default:
                    743:                error = EINVAL;
                    744:                goto out;
                    745:        }
                    746:        vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask;
                    747:        vattr.va_rdev = uap->dev;
                    748: out:
                    749:        if (!error) {
                    750:                error = VOP_MKNOD(ndp, &vattr, p->p_ucred, p);
                    751:        } else {
                    752:                VOP_ABORTOP(ndp);
                    753:                if (ndp->ni_dvp == vp)
                    754:                        vrele(ndp->ni_dvp);
                    755:                else
                    756:                        vput(ndp->ni_dvp);
                    757:                if (vp)
                    758:                        vrele(vp);
                    759:        }
                    760:        return (error);
                    761: }
                    762: 
                    763: /*
                    764:  * Mkfifo system call.
                    765:  */
1.1.1.3 ! root      766: 
        !           767: struct mkfifo_args {
        !           768:        char    *fname;
        !           769:        int     fmode;
        !           770: };
        !           771: 
1.1       root      772: /* ARGSUSED */
                    773: mkfifo(p, uap, retval)
                    774:        struct proc *p;
1.1.1.3 ! root      775:        register struct mkfifo_args *uap;
1.1       root      776:        int *retval;
                    777: {
                    778:        register struct nameidata *ndp;
                    779:        struct vattr vattr;
                    780:        int error;
                    781:        struct nameidata nd;
                    782: 
                    783: #ifndef FIFO
                    784:        return (EOPNOTSUPP);
                    785: #else
                    786:        ndp = &nd;
                    787:        ndp->ni_nameiop = CREATE | LOCKPARENT;
                    788:        ndp->ni_segflg = UIO_USERSPACE;
                    789:        ndp->ni_dirp = uap->fname;
                    790:        if (error = namei(ndp, p))
                    791:                return (error);
                    792:        if (ndp->ni_vp != NULL) {
                    793:                VOP_ABORTOP(ndp);
                    794:                if (ndp->ni_dvp == ndp->ni_vp)
                    795:                        vrele(ndp->ni_dvp);
                    796:                else
                    797:                        vput(ndp->ni_dvp);
                    798:                vrele(ndp->ni_vp);
                    799:                return (EEXIST);
                    800:        }
                    801:        VATTR_NULL(&vattr);
                    802:        vattr.va_type = VFIFO;
                    803:        vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask;
                    804:        return (VOP_MKNOD(ndp, &vattr, p->p_ucred, p));
                    805: #endif /* FIFO */
                    806: }
                    807: 
                    808: /*
                    809:  * Link system call.
                    810:  */
1.1.1.3 ! root      811: 
        !           812: struct link_args {
        !           813:        char    *target;
        !           814:        char    *linkname;
        !           815: };
        !           816: 
1.1       root      817: /* ARGSUSED */
                    818: link(p, uap, retval)
                    819:        struct proc *p;
1.1.1.3 ! root      820:        register struct link_args *uap;
1.1       root      821:        int *retval;
                    822: {
                    823:        register struct nameidata *ndp;
                    824:        register struct vnode *vp, *xp;
                    825:        int error;
                    826:        struct nameidata nd;
                    827: 
                    828:        ndp = &nd;
                    829:        ndp->ni_nameiop = LOOKUP | FOLLOW;
                    830:        ndp->ni_segflg = UIO_USERSPACE;
                    831:        ndp->ni_dirp = uap->target;
                    832:        if (error = namei(ndp, p))
                    833:                return (error);
                    834:        vp = ndp->ni_vp;
                    835:        if (vp->v_type == VDIR &&
                    836:            (error = suser(p->p_ucred, &p->p_acflag)))
                    837:                goto out1;
                    838:        ndp->ni_nameiop = CREATE | LOCKPARENT;
                    839:        ndp->ni_dirp = (caddr_t)uap->linkname;
                    840:        if (error = namei(ndp, p))
                    841:                goto out1;
                    842:        xp = ndp->ni_vp;
                    843:        if (xp != NULL) {
                    844:                error = EEXIST;
                    845:                goto out;
                    846:        }
                    847:        xp = ndp->ni_dvp;
                    848:        if (vp->v_mount != xp->v_mount)
                    849:                error = EXDEV;
                    850: out:
                    851:        if (!error) {
                    852:                error = VOP_LINK(vp, ndp, p);
                    853:        } else {
                    854:                VOP_ABORTOP(ndp);
                    855:                if (ndp->ni_dvp == ndp->ni_vp)
                    856:                        vrele(ndp->ni_dvp);
                    857:                else
                    858:                        vput(ndp->ni_dvp);
                    859:                if (ndp->ni_vp)
                    860:                        vrele(ndp->ni_vp);
                    861:        }
                    862: out1:
                    863:        vrele(vp);
                    864:        return (error);
                    865: }
                    866: 
                    867: /*
                    868:  * Make a symbolic link.
                    869:  */
1.1.1.3 ! root      870: 
        !           871: struct symlink_args {
        !           872:        char    *target;
        !           873:        char    *linkname;
        !           874: };
        !           875: 
1.1       root      876: /* ARGSUSED */
                    877: symlink(p, uap, retval)
                    878:        struct proc *p;
1.1.1.3 ! root      879:        register struct symlink_args *uap;
1.1       root      880:        int *retval;
                    881: {
                    882:        register struct nameidata *ndp;
                    883:        struct vattr vattr;
                    884:        char *target;
                    885:        int error;
                    886:        struct nameidata nd;
                    887: 
                    888:        ndp = &nd;
                    889:        ndp->ni_segflg = UIO_USERSPACE;
                    890:        ndp->ni_dirp = uap->linkname;
                    891:        MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
                    892:        if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
                    893:                goto out;
                    894:        ndp->ni_nameiop = CREATE | LOCKPARENT;
                    895:        if (error = namei(ndp, p))
                    896:                goto out;
                    897:        if (ndp->ni_vp) {
                    898:                VOP_ABORTOP(ndp);
                    899:                if (ndp->ni_dvp == ndp->ni_vp)
                    900:                        vrele(ndp->ni_dvp);
                    901:                else
                    902:                        vput(ndp->ni_dvp);
                    903:                vrele(ndp->ni_vp);
                    904:                error = EEXIST;
                    905:                goto out;
                    906:        }
                    907:        VATTR_NULL(&vattr);
                    908:        vattr.va_mode = 0777 &~ p->p_fd->fd_cmask;
                    909:        error = VOP_SYMLINK(ndp, &vattr, target, p);
                    910: out:
                    911:        FREE(target, M_NAMEI);
                    912:        return (error);
                    913: }
                    914: 
                    915: /*
                    916:  * Delete a name from the filesystem.
                    917:  */
1.1.1.3 ! root      918: 
        !           919: struct unlink_args {
        !           920:        char    *fname;
        !           921: };
        !           922: 
1.1       root      923: /* ARGSUSED */
                    924: unlink(p, uap, retval)
                    925:        struct proc *p;
1.1.1.3 ! root      926:        struct unlink_args *uap;
1.1       root      927:        int *retval;
                    928: {
                    929:        register struct nameidata *ndp;
                    930:        register struct vnode *vp;
                    931:        int error;
                    932:        struct nameidata nd;
                    933: 
                    934:        ndp = &nd;
                    935:        ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
                    936:        ndp->ni_segflg = UIO_USERSPACE;
                    937:        ndp->ni_dirp = uap->fname;
                    938:        if (error = namei(ndp, p))
                    939:                return (error);
                    940:        vp = ndp->ni_vp;
                    941:        if (vp->v_type == VDIR &&
                    942:            (error = suser(p->p_ucred, &p->p_acflag)))
                    943:                goto out;
                    944:        /*
                    945:         * The root of a mounted filesystem cannot be deleted.
                    946:         */
                    947:        if (vp->v_flag & VROOT) {
                    948:                error = EBUSY;
                    949:                goto out;
                    950:        }
                    951:        (void) vnode_pager_uncache(vp);
                    952: out:
                    953:        if (!error) {
                    954:                error = VOP_REMOVE(ndp, p);
                    955:        } else {
                    956:                VOP_ABORTOP(ndp);
                    957:                if (ndp->ni_dvp == vp)
                    958:                        vrele(ndp->ni_dvp);
                    959:                else
                    960:                        vput(ndp->ni_dvp);
                    961:                vput(vp);
                    962:        }
                    963:        return (error);
                    964: }
                    965: 
                    966: /*
                    967:  * Seek system call.
                    968:  */
1.1.1.3 ! root      969: 
        !           970: struct lseek_args {
        !           971:        int     fdes;
        !           972:        off_t   off;
        !           973:        int     sbase;
        !           974: };
        !           975: 
1.1       root      976: lseek(p, uap, retval)
                    977:        struct proc *p;
1.1.1.3 ! root      978:        register struct lseek_args *uap;
1.1       root      979:        off_t *retval;
                    980: {
                    981:        struct ucred *cred = p->p_ucred;
                    982:        register struct filedesc *fdp = p->p_fd;
                    983:        register struct file *fp;
                    984:        struct vattr vattr;
                    985:        int error;
                    986: 
                    987:        if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
                    988:            (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
                    989:                return (EBADF);
                    990:        if (fp->f_type != DTYPE_VNODE)
                    991:                return (ESPIPE);
                    992:        switch (uap->sbase) {
                    993: 
                    994:        case L_INCR:
                    995:                fp->f_offset += uap->off;
                    996:                break;
                    997: 
                    998:        case L_XTND:
                    999:                if (error = VOP_GETATTR((struct vnode *)fp->f_data,
                   1000:                    &vattr, cred, p))
                   1001:                        return (error);
                   1002:                fp->f_offset = uap->off + vattr.va_size;
                   1003:                break;
                   1004: 
                   1005:        case L_SET:
                   1006:                fp->f_offset = uap->off;
                   1007:                break;
                   1008: 
                   1009:        default:
                   1010:                return (EINVAL);
                   1011:        }
                   1012:        *retval = fp->f_offset;
                   1013:        return (0);
                   1014: }
                   1015: 
                   1016: /*
                   1017:  * Check access permissions.
                   1018:  */
1.1.1.3 ! root     1019: 
        !          1020: struct saccess_args {
        !          1021:        char    *fname;
        !          1022:        int     fmode;
        !          1023: };
        !          1024: 
1.1       root     1025: /* ARGSUSED */
                   1026: saccess(p, uap, retval)
                   1027:        struct proc *p;
1.1.1.3 ! root     1028:        register struct saccess_args *uap;
1.1       root     1029:        int *retval;
                   1030: {
                   1031:        register struct nameidata *ndp;
                   1032:        register struct ucred *cred = p->p_ucred;
                   1033:        register struct vnode *vp;
                   1034:        int error, mode, svuid, svgid;
                   1035:        struct nameidata nd;
                   1036: 
                   1037:        ndp = &nd;
                   1038:        svuid = cred->cr_uid;
                   1039:        svgid = cred->cr_groups[0];
                   1040:        cred->cr_uid = p->p_cred->p_ruid;
                   1041:        cred->cr_groups[0] = p->p_cred->p_rgid;
                   1042:        ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
                   1043:        ndp->ni_segflg = UIO_USERSPACE;
                   1044:        ndp->ni_dirp = uap->fname;
                   1045:        if (error = namei(ndp, p))
                   1046:                goto out1;
                   1047:        vp = ndp->ni_vp;
                   1048:        /*
                   1049:         * fmode == 0 means only check for exist
                   1050:         */
                   1051:        if (uap->fmode) {
                   1052:                mode = 0;
                   1053:                if (uap->fmode & R_OK)
                   1054:                        mode |= VREAD;
                   1055:                if (uap->fmode & W_OK)
                   1056:                        mode |= VWRITE;
                   1057:                if (uap->fmode & X_OK)
                   1058:                        mode |= VEXEC;
                   1059:                if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
                   1060:                        error = VOP_ACCESS(vp, mode, cred, p);
                   1061:        }
                   1062:        vput(vp);
                   1063: out1:
                   1064:        cred->cr_uid = svuid;
                   1065:        cred->cr_groups[0] = svgid;
                   1066:        return (error);
                   1067: }
                   1068: 
                   1069: /*
                   1070:  * Stat system call.
                   1071:  * This version follows links.
                   1072:  */
1.1.1.3 ! root     1073: 
        !          1074: struct stat_args {
        !          1075:        char    *fname;
        !          1076:        struct stat *ub;
        !          1077: };
        !          1078: 
1.1       root     1079: /* ARGSUSED */
                   1080: stat(p, uap, retval)
                   1081:        struct proc *p;
1.1.1.3 ! root     1082:        register struct stat_args *uap;
1.1       root     1083:        int *retval;
                   1084: {
                   1085:        register struct nameidata *ndp;
                   1086:        struct stat sb;
                   1087:        int error;
                   1088:        struct nameidata nd;
                   1089: 
                   1090:        ndp = &nd;
                   1091:        ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
                   1092:        ndp->ni_segflg = UIO_USERSPACE;
                   1093:        ndp->ni_dirp = uap->fname;
                   1094:        if (error = namei(ndp, p))
                   1095:                return (error);
                   1096:        error = vn_stat(ndp->ni_vp, &sb, p);
                   1097:        vput(ndp->ni_vp);
                   1098:        if (error)
                   1099:                return (error);
                   1100:        error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
                   1101:        return (error);
                   1102: }
                   1103: 
                   1104: /*
                   1105:  * Lstat system call.
                   1106:  * This version does not follow links.
                   1107:  */
1.1.1.3 ! root     1108: 
        !          1109: struct lstat_args {
        !          1110:        char    *fname;
        !          1111:        struct stat *ub;
        !          1112: };
        !          1113: 
1.1       root     1114: /* ARGSUSED */
                   1115: lstat(p, uap, retval)
                   1116:        struct proc *p;
1.1.1.3 ! root     1117:        register struct lstat_args *uap;
1.1       root     1118:        int *retval;
                   1119: {
                   1120:        register struct nameidata *ndp;
                   1121:        struct stat sb;
                   1122:        int error;
                   1123:        struct nameidata nd;
                   1124: 
                   1125:        ndp = &nd;
                   1126:        ndp->ni_nameiop = LOOKUP | LOCKLEAF | NOFOLLOW;
                   1127:        ndp->ni_segflg = UIO_USERSPACE;
                   1128:        ndp->ni_dirp = uap->fname;
                   1129:        if (error = namei(ndp, p))
                   1130:                return (error);
                   1131:        error = vn_stat(ndp->ni_vp, &sb, p);
                   1132:        vput(ndp->ni_vp);
                   1133:        if (error)
                   1134:                return (error);
                   1135:        error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
                   1136:        return (error);
                   1137: }
                   1138: 
                   1139: /*
                   1140:  * Return target name of a symbolic link.
                   1141:  */
1.1.1.3 ! root     1142: 
        !          1143: struct readlink_args {
        !          1144:        char    *name;
        !          1145:        char    *buf;
        !          1146:        int     count;
        !          1147: };
        !          1148: 
1.1       root     1149: /* ARGSUSED */
                   1150: readlink(p, uap, retval)
                   1151:        struct proc *p;
1.1.1.3 ! root     1152:        register struct readlink_args *uap;
1.1       root     1153:        int *retval;
                   1154: {
                   1155:        register struct nameidata *ndp;
                   1156:        register struct vnode *vp;
                   1157:        struct iovec aiov;
                   1158:        struct uio auio;
                   1159:        int error;
                   1160:        struct nameidata nd;
                   1161: 
                   1162:        ndp = &nd;
                   1163:        ndp->ni_nameiop = LOOKUP | LOCKLEAF;
                   1164:        ndp->ni_segflg = UIO_USERSPACE;
                   1165:        ndp->ni_dirp = uap->name;
                   1166:        if (error = namei(ndp, p))
                   1167:                return (error);
                   1168:        vp = ndp->ni_vp;
                   1169:        if (vp->v_type != VLNK) {
                   1170:                error = EINVAL;
                   1171:                goto out;
                   1172:        }
                   1173:        aiov.iov_base = uap->buf;
                   1174:        aiov.iov_len = uap->count;
                   1175:        auio.uio_iov = &aiov;
                   1176:        auio.uio_iovcnt = 1;
                   1177:        auio.uio_offset = 0;
                   1178:        auio.uio_rw = UIO_READ;
                   1179:        auio.uio_segflg = UIO_USERSPACE;
                   1180:        auio.uio_procp = p;
                   1181:        auio.uio_resid = uap->count;
                   1182:        error = VOP_READLINK(vp, &auio, p->p_ucred);
                   1183: out:
                   1184:        vput(vp);
                   1185:        *retval = uap->count - auio.uio_resid;
                   1186:        return (error);
                   1187: }
                   1188: 
                   1189: /*
                   1190:  * Change flags of a file given path name.
                   1191:  */
1.1.1.3 ! root     1192: 
        !          1193: struct chflags_args {
        !          1194:        char    *fname;
        !          1195:        int     flags;
        !          1196: };
        !          1197: 
1.1       root     1198: /* ARGSUSED */
                   1199: chflags(p, uap, retval)
                   1200:        struct proc *p;
1.1.1.3 ! root     1201:        register struct chflags_args *uap;
1.1       root     1202:        int *retval;
                   1203: {
                   1204:        register struct nameidata *ndp;
                   1205:        register struct vnode *vp;
                   1206:        struct vattr vattr;
                   1207:        int error;
                   1208:        struct nameidata nd;
                   1209: 
                   1210:        ndp = &nd;
                   1211:        ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
                   1212:        ndp->ni_segflg = UIO_USERSPACE;
                   1213:        ndp->ni_dirp = uap->fname;
                   1214:        if (error = namei(ndp, p))
                   1215:                return (error);
                   1216:        vp = ndp->ni_vp;
                   1217:        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                   1218:                error = EROFS;
                   1219:                goto out;
                   1220:        }
                   1221:        VATTR_NULL(&vattr);
                   1222:        vattr.va_flags = uap->flags;
                   1223:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1224: out:
                   1225:        vput(vp);
                   1226:        return (error);
                   1227: }
                   1228: 
                   1229: /*
                   1230:  * Change flags of a file given a file descriptor.
                   1231:  */
1.1.1.3 ! root     1232: 
        !          1233: struct fdchflags_args {
        !          1234:        int     fd;
        !          1235:        int     flags;
        !          1236: };
        !          1237: 
1.1       root     1238: /* ARGSUSED */
                   1239: fchflags(p, uap, retval)
                   1240:        struct proc *p;
1.1.1.3 ! root     1241:        register struct fdchflags_args *uap;
1.1       root     1242:        int *retval;
                   1243: {
                   1244:        struct vattr vattr;
                   1245:        struct vnode *vp;
                   1246:        struct file *fp;
                   1247:        int error;
                   1248: 
                   1249:        if (error = getvnode(p->p_fd, uap->fd, &fp))
                   1250:                return (error);
                   1251:        vp = (struct vnode *)fp->f_data;
                   1252:        VOP_LOCK(vp);
                   1253:        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                   1254:                error = EROFS;
                   1255:                goto out;
                   1256:        }
                   1257:        VATTR_NULL(&vattr);
                   1258:        vattr.va_flags = uap->flags;
                   1259:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1260: out:
                   1261:        VOP_UNLOCK(vp);
                   1262:        return (error);
                   1263: }
                   1264: 
                   1265: /*
                   1266:  * Change mode of a file given path name.
                   1267:  */
1.1.1.3 ! root     1268: 
        !          1269: struct chmod_args {
        !          1270:        char    *fname;
        !          1271:        int     fmode;
        !          1272: };
        !          1273: 
1.1       root     1274: /* ARGSUSED */
                   1275: chmod(p, uap, retval)
                   1276:        struct proc *p;
1.1.1.3 ! root     1277:        register struct chmod_args *uap;
1.1       root     1278:        int *retval;
                   1279: {
                   1280:        register struct nameidata *ndp;
                   1281:        register struct vnode *vp;
                   1282:        struct vattr vattr;
                   1283:        int error;
                   1284:        struct nameidata nd;
                   1285: 
                   1286:        ndp = &nd;
                   1287:        ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
                   1288:        ndp->ni_segflg = UIO_USERSPACE;
                   1289:        ndp->ni_dirp = uap->fname;
                   1290:        if (error = namei(ndp, p))
                   1291:                return (error);
                   1292:        vp = ndp->ni_vp;
                   1293:        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                   1294:                error = EROFS;
                   1295:                goto out;
                   1296:        }
                   1297:        VATTR_NULL(&vattr);
                   1298:        vattr.va_mode = uap->fmode & 07777;
                   1299:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1300: out:
                   1301:        vput(vp);
                   1302:        return (error);
                   1303: }
                   1304: 
                   1305: /*
                   1306:  * Change mode of a file given a file descriptor.
                   1307:  */
1.1.1.3 ! root     1308: 
        !          1309: struct fchmod_args {
        !          1310:        int     fd;
        !          1311:        int     fmode;
        !          1312: };
        !          1313: 
1.1       root     1314: /* ARGSUSED */
                   1315: fchmod(p, uap, retval)
                   1316:        struct proc *p;
1.1.1.3 ! root     1317:        register struct fchmod_args *uap;
1.1       root     1318:        int *retval;
                   1319: {
                   1320:        struct vattr vattr;
                   1321:        struct vnode *vp;
                   1322:        struct file *fp;
                   1323:        int error;
                   1324: 
                   1325:        if (error = getvnode(p->p_fd, uap->fd, &fp))
                   1326:                return (error);
                   1327:        vp = (struct vnode *)fp->f_data;
                   1328:        VOP_LOCK(vp);
                   1329:        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                   1330:                error = EROFS;
                   1331:                goto out;
                   1332:        }
                   1333:        VATTR_NULL(&vattr);
                   1334:        vattr.va_mode = uap->fmode & 07777;
                   1335:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1336: out:
                   1337:        VOP_UNLOCK(vp);
                   1338:        return (error);
                   1339: }
                   1340: 
                   1341: /*
                   1342:  * Set ownership given a path name.
                   1343:  */
1.1.1.3 ! root     1344: 
        !          1345: struct chown_args {
        !          1346:        char    *fname;
        !          1347:        int     uid;
        !          1348:        int     gid;
        !          1349: };
        !          1350: 
1.1       root     1351: /* ARGSUSED */
                   1352: chown(p, uap, retval)
                   1353:        struct proc *p;
1.1.1.3 ! root     1354:        register struct chown_args *uap;
1.1       root     1355:        int *retval;
                   1356: {
                   1357:        register struct nameidata *ndp;
                   1358:        register struct vnode *vp;
                   1359:        struct vattr vattr;
                   1360:        int error;
                   1361:        struct nameidata nd;
                   1362: 
                   1363:        ndp = &nd;
                   1364:        ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF;
                   1365:        ndp->ni_segflg = UIO_USERSPACE;
                   1366:        ndp->ni_dirp = uap->fname;
                   1367:        if (error = namei(ndp, p))
                   1368:                return (error);
                   1369:        vp = ndp->ni_vp;
                   1370:        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                   1371:                error = EROFS;
                   1372:                goto out;
                   1373:        }
                   1374:        VATTR_NULL(&vattr);
                   1375:        vattr.va_uid = uap->uid;
                   1376:        vattr.va_gid = uap->gid;
                   1377:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1378: out:
                   1379:        vput(vp);
                   1380:        return (error);
                   1381: }
                   1382: 
                   1383: /*
                   1384:  * Set ownership given a file descriptor.
                   1385:  */
1.1.1.3 ! root     1386: 
        !          1387: struct fchown_args {
        !          1388:        int     fd;
        !          1389:        int     uid;
        !          1390:        int     gid;
        !          1391: };
        !          1392: 
1.1       root     1393: /* ARGSUSED */
                   1394: fchown(p, uap, retval)
                   1395:        struct proc *p;
1.1.1.3 ! root     1396:        register struct fchown_args *uap;
1.1       root     1397:        int *retval;
                   1398: {
                   1399:        struct vattr vattr;
                   1400:        struct vnode *vp;
                   1401:        struct file *fp;
                   1402:        int error;
                   1403: 
                   1404:        if (error = getvnode(p->p_fd, uap->fd, &fp))
                   1405:                return (error);
                   1406:        vp = (struct vnode *)fp->f_data;
                   1407:        VOP_LOCK(vp);
                   1408:        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                   1409:                error = EROFS;
                   1410:                goto out;
                   1411:        }
                   1412:        VATTR_NULL(&vattr);
                   1413:        vattr.va_uid = uap->uid;
                   1414:        vattr.va_gid = uap->gid;
                   1415:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1416: out:
                   1417:        VOP_UNLOCK(vp);
                   1418:        return (error);
                   1419: }
                   1420: 
                   1421: /*
                   1422:  * Set the access and modification times of a file.
                   1423:  */
1.1.1.3 ! root     1424: 
        !          1425: struct utimes_args {
        !          1426:        char    *fname;
        !          1427:        struct  timeval *tptr;
        !          1428: };
        !          1429: 
1.1       root     1430: /* ARGSUSED */
                   1431: utimes(p, uap, retval)
                   1432:        struct proc *p;
1.1.1.3 ! root     1433:        register struct utimes_args *uap;
1.1       root     1434:        int *retval;
                   1435: {
                   1436:        register struct nameidata *ndp;
                   1437:        register struct vnode *vp;
                   1438:        struct timeval tv[2];
                   1439:        struct vattr vattr;
                   1440:        int error;
                   1441:        struct nameidata nd;
                   1442: 
                   1443:        if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
                   1444:                return (error);
                   1445:        ndp = &nd;
                   1446:        ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
                   1447:        ndp->ni_segflg = UIO_USERSPACE;
                   1448:        ndp->ni_dirp = uap->fname;
                   1449:        if (error = namei(ndp, p))
                   1450:                return (error);
                   1451:        vp = ndp->ni_vp;
                   1452:        if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                   1453:                error = EROFS;
                   1454:                goto out;
                   1455:        }
                   1456:        VATTR_NULL(&vattr);
                   1457:        vattr.va_atime = tv[0];
                   1458:        vattr.va_mtime = tv[1];
                   1459:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1460: out:
                   1461:        vput(vp);
                   1462:        return (error);
                   1463: }
                   1464: 
                   1465: /*
                   1466:  * Truncate a file given its path name.
                   1467:  */
1.1.1.3 ! root     1468: 
        !          1469: struct truncate_args {
        !          1470:        char    *fname;
        !          1471:        off_t   length;
        !          1472: };
        !          1473: 
1.1       root     1474: /* ARGSUSED */
                   1475: truncate(p, uap, retval)
                   1476:        struct proc *p;
1.1.1.3 ! root     1477:        register struct truncate_args *uap;
1.1       root     1478:        int *retval;
                   1479: {
                   1480:        register struct nameidata *ndp;
                   1481:        register struct vnode *vp;
                   1482:        struct vattr vattr;
                   1483:        int error;
                   1484:        struct nameidata nd;
                   1485: 
                   1486:        ndp = &nd;
                   1487:        ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
                   1488:        ndp->ni_segflg = UIO_USERSPACE;
                   1489:        ndp->ni_dirp = uap->fname;
                   1490:        if (error = namei(ndp, p))
                   1491:                return (error);
                   1492:        vp = ndp->ni_vp;
                   1493:        if (vp->v_type == VDIR) {
                   1494:                error = EISDIR;
                   1495:                goto out;
                   1496:        }
                   1497:        if ((error = vn_writechk(vp)) ||
                   1498:            (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)))
                   1499:                goto out;
                   1500:        VATTR_NULL(&vattr);
                   1501:        vattr.va_size = uap->length;
                   1502:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1503: out:
                   1504:        vput(vp);
                   1505:        return (error);
                   1506: }
                   1507: 
                   1508: /*
                   1509:  * Truncate a file given a file descriptor.
                   1510:  */
1.1.1.3 ! root     1511: 
        !          1512: struct ftruncate_args {
        !          1513:        int     fd;
        !          1514:        off_t   length;
        !          1515: };
        !          1516: 
1.1       root     1517: /* ARGSUSED */
                   1518: ftruncate(p, uap, retval)
                   1519:        struct proc *p;
1.1.1.3 ! root     1520:        register struct ftruncate_args *uap;
1.1       root     1521:        int *retval;
                   1522: {
                   1523:        struct vattr vattr;
                   1524:        struct vnode *vp;
                   1525:        struct file *fp;
                   1526:        int error;
                   1527: 
                   1528:        if (error = getvnode(p->p_fd, uap->fd, &fp))
                   1529:                return (error);
                   1530:        if ((fp->f_flag & FWRITE) == 0)
                   1531:                return (EINVAL);
                   1532:        vp = (struct vnode *)fp->f_data;
                   1533:        VOP_LOCK(vp);
                   1534:        if (vp->v_type == VDIR) {
                   1535:                error = EISDIR;
                   1536:                goto out;
                   1537:        }
                   1538:        if (error = vn_writechk(vp))
                   1539:                goto out;
                   1540:        VATTR_NULL(&vattr);
                   1541:        vattr.va_size = uap->length;
                   1542:        error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
                   1543: out:
                   1544:        VOP_UNLOCK(vp);
                   1545:        return (error);
                   1546: }
                   1547: 
                   1548: /*
                   1549:  * Synch an open file.
                   1550:  */
1.1.1.3 ! root     1551: 
        !          1552: struct fsync_args {
        !          1553:        int     fd;
        !          1554: };
        !          1555: 
1.1       root     1556: /* ARGSUSED */
                   1557: fsync(p, uap, retval)
                   1558:        struct proc *p;
1.1.1.3 ! root     1559:        struct fsync_args *uap;
1.1       root     1560:        int *retval;
                   1561: {
                   1562:        register struct vnode *vp;
                   1563:        struct file *fp;
                   1564:        int error;
                   1565: 
                   1566:        if (error = getvnode(p->p_fd, uap->fd, &fp))
                   1567:                return (error);
                   1568:        vp = (struct vnode *)fp->f_data;
                   1569:        VOP_LOCK(vp);
                   1570:        error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT, p);
                   1571:        VOP_UNLOCK(vp);
                   1572:        return (error);
                   1573: }
                   1574: 
                   1575: /*
                   1576:  * Rename system call.
                   1577:  *
                   1578:  * Source and destination must either both be directories, or both
                   1579:  * not be directories.  If target is a directory, it must be empty.
                   1580:  */
1.1.1.3 ! root     1581: 
        !          1582: struct rename_args {
        !          1583:        char    *from;
        !          1584:        char    *to;
        !          1585: };
        !          1586: 
1.1       root     1587: /* ARGSUSED */
                   1588: rename(p, uap, retval)
                   1589:        struct proc *p;
1.1.1.3 ! root     1590:        register struct rename_args *uap;
1.1       root     1591:        int *retval;
                   1592: {
                   1593:        register struct vnode *tvp, *fvp, *tdvp;
                   1594:        struct nameidata fromnd, tond;
                   1595:        int error;
                   1596: 
                   1597:        fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART;
                   1598:        fromnd.ni_segflg = UIO_USERSPACE;
                   1599:        fromnd.ni_dirp = uap->from;
                   1600:        if (error = namei(&fromnd, p))
                   1601:                return (error);
                   1602:        fvp = fromnd.ni_vp;
                   1603:        tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
                   1604:        tond.ni_segflg = UIO_USERSPACE;
                   1605:        tond.ni_dirp = uap->to;
                   1606:        if (error = namei(&tond, p)) {
                   1607:                VOP_ABORTOP(&fromnd);
                   1608:                vrele(fromnd.ni_dvp);
                   1609:                vrele(fvp);
                   1610:                goto out1;
                   1611:        }
                   1612:        tdvp = tond.ni_dvp;
                   1613:        tvp = tond.ni_vp;
                   1614:        if (tvp != NULL) {
                   1615:                if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
                   1616:                        error = ENOTDIR;
                   1617:                        goto out;
                   1618:                } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
                   1619:                        error = EISDIR;
                   1620:                        goto out;
                   1621:                }
                   1622:                if (fvp->v_mount != tvp->v_mount) {
                   1623:                        error = EXDEV;
                   1624:                        goto out;
                   1625:                }
                   1626:        }
                   1627:        if (fvp->v_mount != tdvp->v_mount) {
                   1628:                error = EXDEV;
                   1629:                goto out;
                   1630:        }
                   1631:        if (fvp == tdvp)
                   1632:                error = EINVAL;
                   1633:        /*
                   1634:         * If source is the same as the destination (that is the
                   1635:         * same inode number with the same name in the same directory),
                   1636:         * then there is nothing to do.
                   1637:         */
                   1638:        if (fvp == tvp && fromnd.ni_dvp == tdvp &&
                   1639:            fromnd.ni_namelen == tond.ni_namelen &&
                   1640:            !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen))
                   1641:                error = -1;
                   1642: out:
                   1643:        if (!error) {
                   1644:                error = VOP_RENAME(&fromnd, &tond, p);
                   1645:        } else {
                   1646:                VOP_ABORTOP(&tond);
                   1647:                if (tdvp == tvp)
                   1648:                        vrele(tdvp);
                   1649:                else
                   1650:                        vput(tdvp);
                   1651:                if (tvp)
                   1652:                        vput(tvp);
                   1653:                VOP_ABORTOP(&fromnd);
                   1654:                vrele(fromnd.ni_dvp);
                   1655:                vrele(fvp);
                   1656:        }
                   1657:        vrele(tond.ni_startdir);
                   1658:        FREE(tond.ni_pnbuf, M_NAMEI);
                   1659: out1:
                   1660:        vrele(fromnd.ni_startdir);
                   1661:        FREE(fromnd.ni_pnbuf, M_NAMEI);
                   1662:        if (error == -1)
                   1663:                return (0);
                   1664:        return (error);
                   1665: }
                   1666: 
                   1667: /*
                   1668:  * Mkdir system call.
                   1669:  */
1.1.1.3 ! root     1670: 
        !          1671: struct mkdir_args {
        !          1672:        char    *name;
        !          1673:        int     dmode;
        !          1674: };
        !          1675: 
1.1       root     1676: /* ARGSUSED */
                   1677: mkdir(p, uap, retval)
                   1678:        struct proc *p;
1.1.1.3 ! root     1679:        register struct mkdir_args *uap;
1.1       root     1680:        int *retval;
                   1681: {
                   1682:        register struct nameidata *ndp;
                   1683:        register struct vnode *vp;
                   1684:        struct vattr vattr;
                   1685:        int error;
                   1686:        struct nameidata nd;
                   1687: 
                   1688:        ndp = &nd;
                   1689:        ndp->ni_nameiop = CREATE | LOCKPARENT;
                   1690:        ndp->ni_segflg = UIO_USERSPACE;
                   1691:        ndp->ni_dirp = uap->name;
                   1692:        if (error = namei(ndp, p))
                   1693:                return (error);
                   1694:        vp = ndp->ni_vp;
                   1695:        if (vp != NULL) {
                   1696:                VOP_ABORTOP(ndp);
                   1697:                if (ndp->ni_dvp == vp)
                   1698:                        vrele(ndp->ni_dvp);
                   1699:                else
                   1700:                        vput(ndp->ni_dvp);
                   1701:                vrele(vp);
                   1702:                return (EEXIST);
                   1703:        }
                   1704:        VATTR_NULL(&vattr);
                   1705:        vattr.va_type = VDIR;
                   1706:        vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask;
                   1707:        error = VOP_MKDIR(ndp, &vattr, p);
                   1708:        if (!error)
                   1709:                vput(ndp->ni_vp);
                   1710:        return (error);
                   1711: }
                   1712: 
                   1713: /*
                   1714:  * Rmdir system call.
                   1715:  */
1.1.1.3 ! root     1716: 
        !          1717: struct rmdir_args {
        !          1718:        char    *name;
        !          1719: };
        !          1720: 
1.1       root     1721: /* ARGSUSED */
                   1722: rmdir(p, uap, retval)
                   1723:        struct proc *p;
1.1.1.3 ! root     1724:        struct rmdir_args *uap;
1.1       root     1725:        int *retval;
                   1726: {
                   1727:        register struct nameidata *ndp;
                   1728:        register struct vnode *vp;
                   1729:        int error;
                   1730:        struct nameidata nd;
                   1731: 
                   1732:        ndp = &nd;
                   1733:        ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
                   1734:        ndp->ni_segflg = UIO_USERSPACE;
                   1735:        ndp->ni_dirp = uap->name;
                   1736:        if (error = namei(ndp, p))
                   1737:                return (error);
                   1738:        vp = ndp->ni_vp;
                   1739:        if (vp->v_type != VDIR) {
                   1740:                error = ENOTDIR;
                   1741:                goto out;
                   1742:        }
                   1743:        /*
                   1744:         * No rmdir "." please.
                   1745:         */
                   1746:        if (ndp->ni_dvp == vp) {
                   1747:                error = EINVAL;
                   1748:                goto out;
                   1749:        }
                   1750:        /*
                   1751:         * The root of a mounted filesystem cannot be deleted.
                   1752:         */
                   1753:        if (vp->v_flag & VROOT)
                   1754:                error = EBUSY;
                   1755: out:
                   1756:        if (!error) {
                   1757:                error = VOP_RMDIR(ndp, p);
                   1758:        } else {
                   1759:                VOP_ABORTOP(ndp);
                   1760:                if (ndp->ni_dvp == vp)
                   1761:                        vrele(ndp->ni_dvp);
                   1762:                else
                   1763:                        vput(ndp->ni_dvp);
                   1764:                vput(vp);
                   1765:        }
                   1766:        return (error);
                   1767: }
                   1768: 
                   1769: /*
                   1770:  * Read a block of directory entries in a file system independent format.
                   1771:  */
1.1.1.3 ! root     1772: 
        !          1773: struct getdirentries_args {
        !          1774:        int     fd;
        !          1775:        char    *buf;
        !          1776:        unsigned count;
        !          1777:        long    *basep;
        !          1778: };
        !          1779: 
1.1       root     1780: getdirentries(p, uap, retval)
                   1781:        struct proc *p;
1.1.1.3 ! root     1782:        register struct getdirentries_args *uap;
1.1       root     1783:        int *retval;
                   1784: {
                   1785:        register struct vnode *vp;
                   1786:        struct file *fp;
                   1787:        struct uio auio;
                   1788:        struct iovec aiov;
                   1789:        off_t off;
                   1790:        int error, eofflag;
                   1791: 
                   1792:        if (error = getvnode(p->p_fd, uap->fd, &fp))
                   1793:                return (error);
                   1794:        if ((fp->f_flag & FREAD) == 0)
                   1795:                return (EBADF);
                   1796:        vp = (struct vnode *)fp->f_data;
                   1797:        if (vp->v_type != VDIR)
                   1798:                return (EINVAL);
                   1799:        aiov.iov_base = uap->buf;
                   1800:        aiov.iov_len = uap->count;
                   1801:        auio.uio_iov = &aiov;
                   1802:        auio.uio_iovcnt = 1;
                   1803:        auio.uio_rw = UIO_READ;
                   1804:        auio.uio_segflg = UIO_USERSPACE;
                   1805:        auio.uio_procp = p;
                   1806:        auio.uio_resid = uap->count;
                   1807:        VOP_LOCK(vp);
                   1808:        auio.uio_offset = off = fp->f_offset;
                   1809:        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag);
                   1810:        fp->f_offset = auio.uio_offset;
                   1811:        VOP_UNLOCK(vp);
                   1812:        if (error)
                   1813:                return (error);
                   1814:        error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
                   1815:        *retval = uap->count - auio.uio_resid;
                   1816:        return (error);
                   1817: }
                   1818: 
                   1819: /*
                   1820:  * Set the mode mask for creation of filesystem nodes.
                   1821:  */
1.1.1.3 ! root     1822: 
        !          1823: struct umask_args {
        !          1824:        int     mask;
        !          1825: };
        !          1826: 
1.1       root     1827: mode_t
                   1828: umask(p, uap, retval)
                   1829:        struct proc *p;
1.1.1.3 ! root     1830:        struct umask_args *uap;
1.1       root     1831:        int *retval;
                   1832: {
                   1833:        register struct filedesc *fdp = p->p_fd;
                   1834: 
                   1835:        *retval = fdp->fd_cmask;
                   1836:        fdp->fd_cmask = uap->mask & 07777;
                   1837:        return (0);
                   1838: }
                   1839: 
                   1840: /*
                   1841:  * Void all references to file by ripping underlying filesystem
                   1842:  * away from vnode.
                   1843:  */
1.1.1.3 ! root     1844: 
        !          1845: struct revoke_args {
        !          1846:        char    *fname;
        !          1847: };
        !          1848: 
1.1       root     1849: /* ARGSUSED */
                   1850: revoke(p, uap, retval)
                   1851:        struct proc *p;
1.1.1.3 ! root     1852:        register struct revoke_args *uap;
1.1       root     1853:        int *retval;
                   1854: {
                   1855:        register struct nameidata *ndp;
                   1856:        register struct vnode *vp;
                   1857:        struct vattr vattr;
                   1858:        int error;
                   1859:        struct nameidata nd;
                   1860: 
                   1861:        ndp = &nd;
                   1862:        ndp->ni_nameiop = LOOKUP | FOLLOW;
                   1863:        ndp->ni_segflg = UIO_USERSPACE;
                   1864:        ndp->ni_dirp = uap->fname;
                   1865:        if (error = namei(ndp, p))
                   1866:                return (error);
                   1867:        vp = ndp->ni_vp;
                   1868:        if (vp->v_type != VCHR && vp->v_type != VBLK) {
                   1869:                error = EINVAL;
                   1870:                goto out;
                   1871:        }
                   1872:        if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
                   1873:                goto out;
                   1874:        if (p->p_ucred->cr_uid != vattr.va_uid &&
                   1875:            (error = suser(p->p_ucred, &p->p_acflag)))
                   1876:                goto out;
                   1877:        if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
                   1878:                vgoneall(vp);
                   1879: out:
                   1880:        vrele(vp);
                   1881:        return (error);
                   1882: }
                   1883: 
                   1884: /*
                   1885:  * Convert a user file descriptor to a kernel file entry.
                   1886:  */
                   1887: getvnode(fdp, fdes, fpp)
                   1888:        struct filedesc *fdp;
                   1889:        struct file **fpp;
                   1890:        int fdes;
                   1891: {
                   1892:        struct file *fp;
                   1893: 
                   1894:        if ((unsigned)fdes >= fdp->fd_nfiles ||
                   1895:            (fp = fdp->fd_ofiles[fdes]) == NULL)
                   1896:                return (EBADF);
                   1897:        if (fp->f_type != DTYPE_VNODE)
                   1898:                return (EINVAL);
                   1899:        *fpp = fp;
                   1900:        return (0);
                   1901: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.