[BACK]Return to vfs_syscalls.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/vfs_syscalls.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: vfs_syscalls.c,v 1.141 2007/08/06 16:58:26 millert Exp $      */
        !             2: /*     $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $        */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1989, 1993
        !             6:  *     The Regents of the University of California.  All rights reserved.
        !             7:  * (c) UNIX System Laboratories, Inc.
        !             8:  * All or some portions of this file are derived from material licensed
        !             9:  * to the University of California by American Telephone and Telegraph
        !            10:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
        !            11:  * the permission of UNIX System Laboratories, Inc.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer.
        !            18:  * 2. Redistributions in binary form must reproduce the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer in the
        !            20:  *    documentation and/or other materials provided with the distribution.
        !            21:  * 3. Neither the name of the University nor the names of its contributors
        !            22:  *    may be used to endorse or promote products derived from this software
        !            23:  *    without specific prior written permission.
        !            24:  *
        !            25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            35:  * SUCH DAMAGE.
        !            36:  *
        !            37:  *     @(#)vfs_syscalls.c      8.28 (Berkeley) 12/10/94
        !            38:  */
        !            39:
        !            40: #include <sys/param.h>
        !            41: #include <sys/systm.h>
        !            42: #include <sys/namei.h>
        !            43: #include <sys/filedesc.h>
        !            44: #include <sys/kernel.h>
        !            45: #include <sys/file.h>
        !            46: #include <sys/stat.h>
        !            47: #include <sys/vnode.h>
        !            48: #include <sys/mount.h>
        !            49: #include <sys/proc.h>
        !            50: #include <sys/uio.h>
        !            51: #include <sys/malloc.h>
        !            52: #include <sys/pool.h>
        !            53: #include <sys/dirent.h>
        !            54: #include <sys/dkio.h>
        !            55: #include <sys/disklabel.h>
        !            56:
        !            57: #include <sys/syscallargs.h>
        !            58:
        !            59: #include <uvm/uvm_extern.h>
        !            60: #include <sys/sysctl.h>
        !            61:
        !            62: extern int suid_clear;
        !            63: int    usermount = 0;          /* sysctl: by default, users may not mount */
        !            64:
        !            65: static int change_dir(struct nameidata *, struct proc *);
        !            66:
        !            67: void checkdirs(struct vnode *);
        !            68:
        !            69: int copyout_statfs(struct statfs *, void *, struct proc *);
        !            70:
        !            71: /*
        !            72:  * Virtual File System System Calls
        !            73:  */
        !            74:
        !            75: /*
        !            76:  * Mount a file system.
        !            77:  */
        !            78: /* ARGSUSED */
        !            79: int
        !            80: sys_mount(struct proc *p, void *v, register_t *retval)
        !            81: {
        !            82:        struct sys_mount_args /* {
        !            83:                syscallarg(const char *) type;
        !            84:                syscallarg(const char *) path;
        !            85:                syscallarg(int) flags;
        !            86:                syscallarg(void *) data;
        !            87:        } */ *uap = v;
        !            88:        struct vnode *vp;
        !            89:        struct mount *mp;
        !            90:        int error, flag = 0;
        !            91: #ifdef COMPAT_43
        !            92:        u_long fstypenum = 0;
        !            93: #endif
        !            94:        char fstypename[MFSNAMELEN];
        !            95:        char fspath[MNAMELEN];
        !            96:        struct vattr va;
        !            97:        struct nameidata nd;
        !            98:        struct vfsconf *vfsp;
        !            99:
        !           100:        if (usermount == 0 && (error = suser(p, 0)))
        !           101:                return (error);
        !           102:
        !           103:        /*
        !           104:         * Mount points must fit in MNAMELEN, not MAXPATHLEN.
        !           105:         */
        !           106:        error = copyinstr(SCARG(uap, path), fspath, MNAMELEN, NULL);
        !           107:        if (error)
        !           108:                return(error);
        !           109:
        !           110:        /*
        !           111:         * Get vnode to be covered
        !           112:         */
        !           113:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, p);
        !           114:        if ((error = namei(&nd)) != 0)
        !           115:                return (error);
        !           116:        vp = nd.ni_vp;
        !           117:        if (SCARG(uap, flags) & MNT_UPDATE) {
        !           118:                if ((vp->v_flag & VROOT) == 0) {
        !           119:                        vput(vp);
        !           120:                        return (EINVAL);
        !           121:                }
        !           122:                mp = vp->v_mount;
        !           123:                flag = mp->mnt_flag;
        !           124:                /*
        !           125:                 * We only allow the filesystem to be reloaded if it
        !           126:                 * is currently mounted read-only.
        !           127:                 */
        !           128:                if ((SCARG(uap, flags) & MNT_RELOAD) &&
        !           129:                    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
        !           130:                        vput(vp);
        !           131:                        return (EOPNOTSUPP);    /* Needs translation */
        !           132:                }
        !           133:
        !           134:                /*
        !           135:                 * Only root, or the user that did the original mount is
        !           136:                 * permitted to update it.
        !           137:                 */
        !           138:                if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
        !           139:                    (error = suser(p, 0))) {
        !           140:                        vput(vp);
        !           141:                        return (error);
        !           142:                }
        !           143:                /*
        !           144:                 * Do not allow NFS export by non-root users. Silently
        !           145:                 * enforce MNT_NOSUID and MNT_NODEV for non-root users, and
        !           146:                 * inherit MNT_NOEXEC from the mount point.
        !           147:                 */
        !           148:                if (p->p_ucred->cr_uid != 0) {
        !           149:                        if (SCARG(uap, flags) & MNT_EXPORTED) {
        !           150:                                vput(vp);
        !           151:                                return (EPERM);
        !           152:                        }
        !           153:                        SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
        !           154:                        if (flag & MNT_NOEXEC)
        !           155:                                SCARG(uap, flags) |= MNT_NOEXEC;
        !           156:                }
        !           157:                if ((error = vfs_busy(mp, VB_READ|VB_NOWAIT)) != 0) {
        !           158:                        vput(vp);
        !           159:                        return (error);
        !           160:                }
        !           161:                VOP_UNLOCK(vp, 0, p);
        !           162:                mp->mnt_flag |= SCARG(uap, flags) & (MNT_RELOAD | MNT_UPDATE);
        !           163:                goto update;
        !           164:        }
        !           165:        /*
        !           166:         * If the user is not root, ensure that they own the directory
        !           167:         * onto which we are attempting to mount.
        !           168:         */
        !           169:        if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
        !           170:            (va.va_uid != p->p_ucred->cr_uid &&
        !           171:            (error = suser(p, 0)))) {
        !           172:                vput(vp);
        !           173:                return (error);
        !           174:        }
        !           175:        /*
        !           176:         * Do not allow NFS export by non-root users. Silently
        !           177:         * enforce MNT_NOSUID and MNT_NODEV for non-root users, and inherit
        !           178:         * MNT_NOEXEC from the mount point.
        !           179:         */
        !           180:        if (p->p_ucred->cr_uid != 0) {
        !           181:                if (SCARG(uap, flags) & MNT_EXPORTED) {
        !           182:                        vput(vp);
        !           183:                        return (EPERM);
        !           184:                }
        !           185:                SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
        !           186:                if (vp->v_mount->mnt_flag & MNT_NOEXEC)
        !           187:                        SCARG(uap, flags) |= MNT_NOEXEC;
        !           188:        }
        !           189:        if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) {
        !           190:                vput(vp);
        !           191:                return (error);
        !           192:        }
        !           193:        if (vp->v_type != VDIR) {
        !           194:                vput(vp);
        !           195:                return (ENOTDIR);
        !           196:        }
        !           197:        error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL);
        !           198:        if (error) {
        !           199: #ifdef COMPAT_43
        !           200:                /*
        !           201:                 * Historically filesystem types were identified by number.
        !           202:                 * If we get an integer for the filesystem type instead of a
        !           203:                 * string, we check to see if it matches one of the historic
        !           204:                 * filesystem types.
        !           205:                 */
        !           206:                fstypenum = (u_long)SCARG(uap, type);
        !           207:
        !           208:                for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
        !           209:                        if (vfsp->vfc_typenum == fstypenum)
        !           210:                                break;
        !           211:                if (vfsp == NULL) {
        !           212:                        vput(vp);
        !           213:                        return (ENODEV);
        !           214:                }
        !           215:                strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
        !           216:
        !           217: #else
        !           218:                vput(vp);
        !           219:                return (error);
        !           220: #endif
        !           221:        }
        !           222:        for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
        !           223:                if (!strcmp(vfsp->vfc_name, fstypename))
        !           224:                        break;
        !           225:        }
        !           226:
        !           227:        if (vfsp == NULL) {
        !           228:                vput(vp);
        !           229:                return (EOPNOTSUPP);
        !           230:        }
        !           231:
        !           232:        if (vp->v_mountedhere != NULL) {
        !           233:                vput(vp);
        !           234:                return (EBUSY);
        !           235:        }
        !           236:
        !           237:        /*
        !           238:         * Allocate and initialize the file system.
        !           239:         */
        !           240:        mp = (struct mount *)malloc((u_long)sizeof(struct mount),
        !           241:                M_MOUNT, M_WAITOK);
        !           242:        bzero((char *)mp, (u_long)sizeof(struct mount));
        !           243:        (void) vfs_busy(mp, VB_READ|VB_NOWAIT);
        !           244:        mp->mnt_op = vfsp->vfc_vfsops;
        !           245:        mp->mnt_vfc = vfsp;
        !           246:        mp->mnt_flag |= (vfsp->vfc_flags & MNT_VISFLAGMASK);
        !           247:        strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
        !           248:        mp->mnt_vnodecovered = vp;
        !           249:        mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
        !           250: update:
        !           251:        /*
        !           252:         * Set the mount level flags.
        !           253:         */
        !           254:        if (SCARG(uap, flags) & MNT_RDONLY)
        !           255:                mp->mnt_flag |= MNT_RDONLY;
        !           256:        else if (mp->mnt_flag & MNT_RDONLY)
        !           257:                mp->mnt_flag |= MNT_WANTRDWR;
        !           258:        mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
        !           259:            MNT_SYNCHRONOUS | MNT_ASYNC | MNT_SOFTDEP | MNT_NOATIME |
        !           260:            MNT_FORCE);
        !           261:        mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
        !           262:            MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_SOFTDEP |
        !           263:            MNT_NOATIME | MNT_FORCE);
        !           264:        /*
        !           265:         * Mount the filesystem.
        !           266:         */
        !           267:        error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
        !           268:        if (!error) {
        !           269:                mp->mnt_stat.f_ctime = time_second;
        !           270:        }
        !           271:        if (mp->mnt_flag & MNT_UPDATE) {
        !           272:                vrele(vp);
        !           273:                if (mp->mnt_flag & MNT_WANTRDWR)
        !           274:                        mp->mnt_flag &= ~MNT_RDONLY;
        !           275:                mp->mnt_flag &=~
        !           276:                    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
        !           277:                if (error)
        !           278:                        mp->mnt_flag = flag;
        !           279:
        !           280:                if ((mp->mnt_flag & MNT_RDONLY) == 0) {
        !           281:                        if (mp->mnt_syncer == NULL)
        !           282:                                error = vfs_allocate_syncvnode(mp);
        !           283:                } else {
        !           284:                        if (mp->mnt_syncer != NULL)
        !           285:                                vgone(mp->mnt_syncer);
        !           286:                        mp->mnt_syncer = NULL;
        !           287:                }
        !           288:
        !           289:                vfs_unbusy(mp);
        !           290:                return (error);
        !           291:        }
        !           292:
        !           293:        vp->v_mountedhere = mp;
        !           294:
        !           295:        /*
        !           296:         * Put the new filesystem on the mount list after root.
        !           297:         */
        !           298:        cache_purge(vp);
        !           299:        if (!error) {
        !           300:                vfsp->vfc_refcount++;
        !           301:                CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
        !           302:                checkdirs(vp);
        !           303:                VOP_UNLOCK(vp, 0, p);
        !           304:                if ((mp->mnt_flag & MNT_RDONLY) == 0)
        !           305:                        error = vfs_allocate_syncvnode(mp);
        !           306:                vfs_unbusy(mp);
        !           307:                (void) VFS_STATFS(mp, &mp->mnt_stat, p);
        !           308:                if ((error = VFS_START(mp, 0, p)) != 0)
        !           309:                        vrele(vp);
        !           310:        } else {
        !           311:                mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
        !           312:                vfs_unbusy(mp);
        !           313:                free(mp, M_MOUNT);
        !           314:                vput(vp);
        !           315:        }
        !           316:        return (error);
        !           317: }
        !           318:
        !           319: /*
        !           320:  * Scan all active processes to see if any of them have a current
        !           321:  * or root directory onto which the new filesystem has just been
        !           322:  * mounted. If so, replace them with the new mount point.
        !           323:  */
        !           324: void
        !           325: checkdirs(struct vnode *olddp)
        !           326: {
        !           327:        struct filedesc *fdp;
        !           328:        struct vnode *newdp;
        !           329:        struct proc *p;
        !           330:
        !           331:        if (olddp->v_usecount == 1)
        !           332:                return;
        !           333:        if (VFS_ROOT(olddp->v_mountedhere, &newdp))
        !           334:                panic("mount: lost mount");
        !           335:        for (p = LIST_FIRST(&allproc); p != 0; p = LIST_NEXT(p, p_list)) {
        !           336:                fdp = p->p_fd;
        !           337:                if (fdp->fd_cdir == olddp) {
        !           338:                        vrele(fdp->fd_cdir);
        !           339:                        VREF(newdp);
        !           340:                        fdp->fd_cdir = newdp;
        !           341:                }
        !           342:                if (fdp->fd_rdir == olddp) {
        !           343:                        vrele(fdp->fd_rdir);
        !           344:                        VREF(newdp);
        !           345:                        fdp->fd_rdir = newdp;
        !           346:                }
        !           347:        }
        !           348:        if (rootvnode == olddp) {
        !           349:                vrele(rootvnode);
        !           350:                VREF(newdp);
        !           351:                rootvnode = newdp;
        !           352:        }
        !           353:        vput(newdp);
        !           354: }
        !           355:
        !           356: /*
        !           357:  * Unmount a file system.
        !           358:  *
        !           359:  * Note: unmount takes a path to the vnode mounted on as argument,
        !           360:  * not special file (as before).
        !           361:  */
        !           362: /* ARGSUSED */
        !           363: int
        !           364: sys_unmount(struct proc *p, void *v, register_t *retval)
        !           365: {
        !           366:        struct sys_unmount_args /* {
        !           367:                syscallarg(const char *) path;
        !           368:                syscallarg(int) flags;
        !           369:        } */ *uap = v;
        !           370:        struct vnode *vp;
        !           371:        struct mount *mp;
        !           372:        int error;
        !           373:        struct nameidata nd;
        !           374:
        !           375:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !           376:            SCARG(uap, path), p);
        !           377:        if ((error = namei(&nd)) != 0)
        !           378:                return (error);
        !           379:        vp = nd.ni_vp;
        !           380:        mp = vp->v_mount;
        !           381:
        !           382:        /*
        !           383:         * Only root, or the user that did the original mount is
        !           384:         * permitted to unmount this filesystem.
        !           385:         */
        !           386:        if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
        !           387:            (error = suser(p, 0))) {
        !           388:                vput(vp);
        !           389:                return (error);
        !           390:        }
        !           391:
        !           392:        /*
        !           393:         * Don't allow unmounting the root file system.
        !           394:         */
        !           395:        if (mp->mnt_flag & MNT_ROOTFS) {
        !           396:                vput(vp);
        !           397:                return (EINVAL);
        !           398:        }
        !           399:
        !           400:        /*
        !           401:         * Must be the root of the filesystem
        !           402:         */
        !           403:        if ((vp->v_flag & VROOT) == 0) {
        !           404:                vput(vp);
        !           405:                return (EINVAL);
        !           406:        }
        !           407:        vput(vp);
        !           408:
        !           409:        if (vfs_busy(mp, VB_WRITE|VB_WAIT))
        !           410:                return (EBUSY);
        !           411:
        !           412:        return (dounmount(mp, SCARG(uap, flags), p, vp));
        !           413: }
        !           414:
        !           415: /*
        !           416:  * Do the actual file system unmount.
        !           417:  */
        !           418: int
        !           419: dounmount(struct mount *mp, int flags, struct proc *p, struct vnode *olddp)
        !           420: {
        !           421:        struct vnode *coveredvp;
        !           422:        int error;
        !           423:        int hadsyncer = 0;
        !           424:
        !           425:        mp->mnt_flag &=~ MNT_ASYNC;
        !           426:        cache_purgevfs(mp);     /* remove cache entries for this file sys */
        !           427:        if (mp->mnt_syncer != NULL) {
        !           428:                hadsyncer = 1;
        !           429:                vgone(mp->mnt_syncer);
        !           430:                mp->mnt_syncer = NULL;
        !           431:        }
        !           432:        if (((mp->mnt_flag & MNT_RDONLY) ||
        !           433:            (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
        !           434:            (flags & MNT_FORCE))
        !           435:                error = VFS_UNMOUNT(mp, flags, p);
        !           436:
        !           437:        if (error && error != EIO && !(flags & MNT_DOOMED)) {
        !           438:                if ((mp->mnt_flag & MNT_RDONLY) == 0 && hadsyncer)
        !           439:                        (void) vfs_allocate_syncvnode(mp);
        !           440:                vfs_unbusy(mp);
        !           441:                return (error);
        !           442:        }
        !           443:
        !           444:        CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
        !           445:        if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
        !           446:                coveredvp->v_mountedhere = NULL;
        !           447:                vrele(coveredvp);
        !           448:        }
        !           449:
        !           450:        mp->mnt_vfc->vfc_refcount--;
        !           451:
        !           452:        if (!LIST_EMPTY(&mp->mnt_vnodelist))
        !           453:                panic("unmount: dangling vnode");
        !           454:
        !           455:        vfs_unbusy(mp);
        !           456:        free(mp, M_MOUNT);
        !           457:
        !           458:        return (0);
        !           459: }
        !           460:
        !           461: /*
        !           462:  * Sync each mounted filesystem.
        !           463:  */
        !           464: #ifdef DEBUG
        !           465: int syncprt = 0;
        !           466: struct ctldebug debug0 = { "syncprt", &syncprt };
        !           467: #endif
        !           468:
        !           469: /* ARGSUSED */
        !           470: int
        !           471: sys_sync(struct proc *p, void *v, register_t *retval)
        !           472: {
        !           473:        struct mount *mp, *nmp;
        !           474:        int asyncflag;
        !           475:
        !           476:        for (mp = CIRCLEQ_LAST(&mountlist); mp != CIRCLEQ_END(&mountlist);
        !           477:            mp = nmp) {
        !           478:                if (vfs_busy(mp, VB_READ|VB_NOWAIT)) {
        !           479:                        nmp = CIRCLEQ_PREV(mp, mnt_list);
        !           480:                        continue;
        !           481:                }
        !           482:                if ((mp->mnt_flag & MNT_RDONLY) == 0) {
        !           483:                        asyncflag = mp->mnt_flag & MNT_ASYNC;
        !           484:                        mp->mnt_flag &= ~MNT_ASYNC;
        !           485:                        uvm_vnp_sync(mp);
        !           486:                        VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
        !           487:                        if (asyncflag)
        !           488:                                mp->mnt_flag |= MNT_ASYNC;
        !           489:                }
        !           490:                nmp = CIRCLEQ_PREV(mp, mnt_list);
        !           491:                vfs_unbusy(mp);
        !           492:        }
        !           493:
        !           494: #ifdef DEBUG
        !           495:        if (syncprt)
        !           496:                vfs_bufstats();
        !           497: #endif /* DEBUG */
        !           498:        return (0);
        !           499: }
        !           500:
        !           501: /*
        !           502:  * Change filesystem quotas.
        !           503:  */
        !           504: /* ARGSUSED */
        !           505: int
        !           506: sys_quotactl(struct proc *p, void *v, register_t *retval)
        !           507: {
        !           508:        struct sys_quotactl_args /* {
        !           509:                syscallarg(const char *) path;
        !           510:                syscallarg(int) cmd;
        !           511:                syscallarg(int) uid;
        !           512:                syscallarg(char *) arg;
        !           513:        } */ *uap = v;
        !           514:        struct mount *mp;
        !           515:        int error;
        !           516:        struct nameidata nd;
        !           517:
        !           518:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
        !           519:        if ((error = namei(&nd)) != 0)
        !           520:                return (error);
        !           521:        mp = nd.ni_vp->v_mount;
        !           522:        vrele(nd.ni_vp);
        !           523:        return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
        !           524:            SCARG(uap, arg), p));
        !           525: }
        !           526:
        !           527: int
        !           528: copyout_statfs(struct statfs *sp, void *uaddr, struct proc *p)
        !           529: {
        !           530:        size_t co_sz1 = offsetof(struct statfs, f_fsid);
        !           531:        size_t co_off2 = co_sz1 + sizeof(fsid_t);
        !           532:        size_t co_sz2 = sizeof(struct statfs) - co_off2;
        !           533:        char *s, *d;
        !           534:        int error;
        !           535:
        !           536:        /* Don't let non-root see filesystem id (for NFS security) */
        !           537:        if (suser(p, 0)) {
        !           538:                fsid_t fsid;
        !           539:
        !           540:                s = (char *)sp;
        !           541:                d = (char *)uaddr;
        !           542:
        !           543:                memset(&fsid, 0, sizeof(fsid));
        !           544:
        !           545:                if ((error = copyout(s, d, co_sz1)) != 0)
        !           546:                        return (error);
        !           547:                if ((error = copyout(&fsid, d + co_sz1, sizeof(fsid))) != 0)
        !           548:                        return (error);
        !           549:                return (copyout(s + co_off2, d + co_off2, co_sz2));
        !           550:        }
        !           551:
        !           552:        return (copyout(sp, uaddr, sizeof(*sp)));
        !           553: }
        !           554:
        !           555: /*
        !           556:  * Get filesystem statistics.
        !           557:  */
        !           558: /* ARGSUSED */
        !           559: int
        !           560: sys_statfs(struct proc *p, void *v, register_t *retval)
        !           561: {
        !           562:        struct sys_statfs_args /* {
        !           563:                syscallarg(const char *) path;
        !           564:                syscallarg(struct statfs *) buf;
        !           565:        } */ *uap = v;
        !           566:        struct mount *mp;
        !           567:        struct statfs *sp;
        !           568:        int error;
        !           569:        struct nameidata nd;
        !           570:
        !           571:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
        !           572:        if ((error = namei(&nd)) != 0)
        !           573:                return (error);
        !           574:        mp = nd.ni_vp->v_mount;
        !           575:        sp = &mp->mnt_stat;
        !           576:        vrele(nd.ni_vp);
        !           577:        if ((error = VFS_STATFS(mp, sp, p)) != 0)
        !           578:                return (error);
        !           579:        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
        !           580: #if notyet
        !           581:        if (mp->mnt_flag & MNT_SOFTDEP)
        !           582:                sp->f_eflags = STATFS_SOFTUPD;
        !           583: #endif
        !           584:        return (copyout_statfs(sp, SCARG(uap, buf), p));
        !           585: }
        !           586:
        !           587: /*
        !           588:  * Get filesystem statistics.
        !           589:  */
        !           590: /* ARGSUSED */
        !           591: int
        !           592: sys_fstatfs(struct proc *p, void *v, register_t *retval)
        !           593: {
        !           594:        struct sys_fstatfs_args /* {
        !           595:                syscallarg(int) fd;
        !           596:                syscallarg(struct statfs *) buf;
        !           597:        } */ *uap = v;
        !           598:        struct file *fp;
        !           599:        struct mount *mp;
        !           600:        struct statfs *sp;
        !           601:        int error;
        !           602:
        !           603:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
        !           604:                return (error);
        !           605:        mp = ((struct vnode *)fp->f_data)->v_mount;
        !           606:        if (!mp) {
        !           607:                FRELE(fp);
        !           608:                return (ENOENT);
        !           609:        }
        !           610:        sp = &mp->mnt_stat;
        !           611:        error = VFS_STATFS(mp, sp, p);
        !           612:        FRELE(fp);
        !           613:        if (error)
        !           614:                return (error);
        !           615:        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
        !           616: #if notyet
        !           617:        if (mp->mnt_flag & MNT_SOFTDEP)
        !           618:                sp->f_eflags = STATFS_SOFTUPD;
        !           619: #endif
        !           620:        return (copyout_statfs(sp, SCARG(uap, buf), p));
        !           621: }
        !           622:
        !           623: /*
        !           624:  * Get statistics on all filesystems.
        !           625:  */
        !           626: int
        !           627: sys_getfsstat(struct proc *p, void *v, register_t *retval)
        !           628: {
        !           629:        struct sys_getfsstat_args /* {
        !           630:                syscallarg(struct statfs *) buf;
        !           631:                syscallarg(size_t) bufsize;
        !           632:                syscallarg(int) flags;
        !           633:        } */ *uap = v;
        !           634:        struct mount *mp, *nmp;
        !           635:        struct statfs *sp;
        !           636:        struct statfs *sfsp;
        !           637:        size_t count, maxcount;
        !           638:        int error, flags = SCARG(uap, flags);
        !           639:
        !           640:        maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
        !           641:        sfsp = SCARG(uap, buf);
        !           642:        count = 0;
        !           643:
        !           644:        for (mp = CIRCLEQ_FIRST(&mountlist); mp != CIRCLEQ_END(&mountlist);
        !           645:            mp = nmp) {
        !           646:                if (vfs_busy(mp, VB_READ|VB_NOWAIT)) {
        !           647:                        nmp = CIRCLEQ_NEXT(mp, mnt_list);
        !           648:                        continue;
        !           649:                }
        !           650:                if (sfsp && count < maxcount) {
        !           651:                        sp = &mp->mnt_stat;
        !           652:
        !           653:                        /* Refresh stats unless MNT_NOWAIT is specified */
        !           654:                        if (flags != MNT_NOWAIT &&
        !           655:                            flags != MNT_LAZY &&
        !           656:                            (flags == MNT_WAIT ||
        !           657:                            flags == 0) &&
        !           658:                            (error = VFS_STATFS(mp, sp, p))) {
        !           659:                                nmp = CIRCLEQ_NEXT(mp, mnt_list);
        !           660:                                vfs_unbusy(mp);
        !           661:                                continue;
        !           662:                        }
        !           663:
        !           664:                        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
        !           665: #if notyet
        !           666:                        if (mp->mnt_flag & MNT_SOFTDEP)
        !           667:                                sp->f_eflags = STATFS_SOFTUPD;
        !           668: #endif
        !           669:                        error = (copyout_statfs(sp, sfsp, p));
        !           670:                        if (error) {
        !           671:                                vfs_unbusy(mp);
        !           672:                                return (error);
        !           673:                        }
        !           674:                        sfsp++;
        !           675:                }
        !           676:                count++;
        !           677:                nmp = CIRCLEQ_NEXT(mp, mnt_list);
        !           678:                vfs_unbusy(mp);
        !           679:        }
        !           680:
        !           681:        if (sfsp && count > maxcount)
        !           682:                *retval = maxcount;
        !           683:        else
        !           684:                *retval = count;
        !           685:
        !           686:        return (0);
        !           687: }
        !           688:
        !           689: /*
        !           690:  * Change current working directory to a given file descriptor.
        !           691:  */
        !           692: /* ARGSUSED */
        !           693: int
        !           694: sys_fchdir(struct proc *p, void *v, register_t *retval)
        !           695: {
        !           696:        struct sys_fchdir_args /* {
        !           697:                syscallarg(int) fd;
        !           698:        } */ *uap = v;
        !           699:        struct filedesc *fdp = p->p_fd;
        !           700:        struct vnode *vp, *tdp;
        !           701:        struct mount *mp;
        !           702:        struct file *fp;
        !           703:        int error;
        !           704:
        !           705:        if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
        !           706:                return (error);
        !           707:        vp = (struct vnode *)fp->f_data;
        !           708:        VREF(vp);
        !           709:        FRELE(fp);
        !           710:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !           711:        if (vp->v_type != VDIR)
        !           712:                error = ENOTDIR;
        !           713:        else
        !           714:                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
        !           715:
        !           716:        while (!error && (mp = vp->v_mountedhere) != NULL) {
        !           717:                if (vfs_busy(mp, VB_READ|VB_WAIT))
        !           718:                        continue;
        !           719:                error = VFS_ROOT(mp, &tdp);
        !           720:                vfs_unbusy(mp);
        !           721:                if (error)
        !           722:                        break;
        !           723:                vput(vp);
        !           724:                vp = tdp;
        !           725:        }
        !           726:        if (error) {
        !           727:                vput(vp);
        !           728:                return (error);
        !           729:        }
        !           730:        VOP_UNLOCK(vp, 0, p);
        !           731:        vrele(fdp->fd_cdir);
        !           732:        fdp->fd_cdir = vp;
        !           733:        return (0);
        !           734: }
        !           735:
        !           736: /*
        !           737:  * Change current working directory (``.'').
        !           738:  */
        !           739: /* ARGSUSED */
        !           740: int
        !           741: sys_chdir(struct proc *p, void *v, register_t *retval)
        !           742: {
        !           743:        struct sys_chdir_args /* {
        !           744:                syscallarg(const char *) path;
        !           745:        } */ *uap = v;
        !           746:        struct filedesc *fdp = p->p_fd;
        !           747:        int error;
        !           748:        struct nameidata nd;
        !           749:
        !           750:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !           751:            SCARG(uap, path), p);
        !           752:        if ((error = change_dir(&nd, p)) != 0)
        !           753:                return (error);
        !           754:        vrele(fdp->fd_cdir);
        !           755:        fdp->fd_cdir = nd.ni_vp;
        !           756:        return (0);
        !           757: }
        !           758:
        !           759: /*
        !           760:  * Change notion of root (``/'') directory.
        !           761:  */
        !           762: /* ARGSUSED */
        !           763: int
        !           764: sys_chroot(struct proc *p, void *v, register_t *retval)
        !           765: {
        !           766:        struct sys_chroot_args /* {
        !           767:                syscallarg(const char *) path;
        !           768:        } */ *uap = v;
        !           769:        struct filedesc *fdp = p->p_fd;
        !           770:        int error;
        !           771:        struct nameidata nd;
        !           772:
        !           773:        if ((error = suser(p, 0)) != 0)
        !           774:                return (error);
        !           775:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !           776:            SCARG(uap, path), p);
        !           777:        if ((error = change_dir(&nd, p)) != 0)
        !           778:                return (error);
        !           779:        if (fdp->fd_rdir != NULL) {
        !           780:                /*
        !           781:                 * A chroot() done inside a changed root environment does
        !           782:                 * an automatic chdir to avoid the out-of-tree experience.
        !           783:                 */
        !           784:                vrele(fdp->fd_rdir);
        !           785:                vrele(fdp->fd_cdir);
        !           786:                VREF(nd.ni_vp);
        !           787:                fdp->fd_cdir = nd.ni_vp;
        !           788:        }
        !           789:        fdp->fd_rdir = nd.ni_vp;
        !           790:        return (0);
        !           791: }
        !           792:
        !           793: /*
        !           794:  * Common routine for chroot and chdir.
        !           795:  */
        !           796: static int
        !           797: change_dir(struct nameidata *ndp, struct proc *p)
        !           798: {
        !           799:        struct vnode *vp;
        !           800:        int error;
        !           801:
        !           802:        if ((error = namei(ndp)) != 0)
        !           803:                return (error);
        !           804:        vp = ndp->ni_vp;
        !           805:        if (vp->v_type != VDIR)
        !           806:                error = ENOTDIR;
        !           807:        else
        !           808:                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
        !           809:        if (error)
        !           810:                vput(vp);
        !           811:        else
        !           812:                VOP_UNLOCK(vp, 0, p);
        !           813:        return (error);
        !           814: }
        !           815:
        !           816: /*
        !           817:  * Check permissions, allocate an open file structure,
        !           818:  * and call the device open routine if any.
        !           819:  */
        !           820: int
        !           821: sys_open(struct proc *p, void *v, register_t *retval)
        !           822: {
        !           823:        struct sys_open_args /* {
        !           824:                syscallarg(const char *) path;
        !           825:                syscallarg(int) flags;
        !           826:                syscallarg(mode_t) mode;
        !           827:        } */ *uap = v;
        !           828:        struct filedesc *fdp = p->p_fd;
        !           829:        struct file *fp;
        !           830:        struct vnode *vp;
        !           831:        struct vattr vattr;
        !           832:        int flags, cmode;
        !           833:        int type, indx, error, localtrunc = 0;
        !           834:        struct flock lf;
        !           835:        struct nameidata nd;
        !           836:
        !           837:        fdplock(fdp);
        !           838:
        !           839:        if ((error = falloc(p, &fp, &indx)) != 0)
        !           840:                goto out;
        !           841:
        !           842:        flags = FFLAGS(SCARG(uap, flags));
        !           843:        cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
        !           844:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
        !           845:        p->p_dupfd = -1;                        /* XXX check for fdopen */
        !           846:        if ((flags & O_TRUNC) && (flags & (O_EXLOCK | O_SHLOCK))) {
        !           847:                localtrunc = 1;
        !           848:                flags &= ~O_TRUNC;      /* Must do truncate ourselves */
        !           849:        }
        !           850:        if ((error = vn_open(&nd, flags, cmode)) != 0) {
        !           851:                if ((error == ENODEV || error == ENXIO) &&
        !           852:                    p->p_dupfd >= 0 &&                  /* XXX from fdopen */
        !           853:                    (error =
        !           854:                        dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
        !           855:                        closef(fp, p);
        !           856:                        *retval = indx;
        !           857:                        goto out;
        !           858:                }
        !           859:                if (error == ERESTART)
        !           860:                        error = EINTR;
        !           861:                fdremove(fdp, indx);
        !           862:                closef(fp, p);
        !           863:                goto out;
        !           864:        }
        !           865:        p->p_dupfd = 0;
        !           866:        vp = nd.ni_vp;
        !           867:        fp->f_flag = flags & FMASK;
        !           868:        fp->f_type = DTYPE_VNODE;
        !           869:        fp->f_ops = &vnops;
        !           870:        fp->f_data = vp;
        !           871:        if (flags & (O_EXLOCK | O_SHLOCK)) {
        !           872:                lf.l_whence = SEEK_SET;
        !           873:                lf.l_start = 0;
        !           874:                lf.l_len = 0;
        !           875:                if (flags & O_EXLOCK)
        !           876:                        lf.l_type = F_WRLCK;
        !           877:                else
        !           878:                        lf.l_type = F_RDLCK;
        !           879:                type = F_FLOCK;
        !           880:                if ((flags & FNONBLOCK) == 0)
        !           881:                        type |= F_WAIT;
        !           882:                VOP_UNLOCK(vp, 0, p);
        !           883:                error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
        !           884:                if (error) {
        !           885:                        /* closef will vn_close the file for us. */
        !           886:                        fdremove(fdp, indx);
        !           887:                        closef(fp, p);
        !           888:                        goto out;
        !           889:                }
        !           890:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !           891:                fp->f_flag |= FHASLOCK;
        !           892:        }
        !           893:        if (localtrunc) {
        !           894:                if ((fp->f_flag & FWRITE) == 0)
        !           895:                        error = EACCES;
        !           896:                else if (vp->v_mount->mnt_flag & MNT_RDONLY)
        !           897:                        error = EROFS;
        !           898:                else if (vp->v_type == VDIR)
        !           899:                        error = EISDIR;
        !           900:                else if ((error = vn_writechk(vp)) == 0) {
        !           901:                        VATTR_NULL(&vattr);
        !           902:                        vattr.va_size = 0;
        !           903:                        error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
        !           904:                }
        !           905:                if (error) {
        !           906:                        VOP_UNLOCK(vp, 0, p);
        !           907:                        /* closef will close the file for us. */
        !           908:                        fdremove(fdp, indx);
        !           909:                        closef(fp, p);
        !           910:                        goto out;
        !           911:                }
        !           912:        }
        !           913:        VOP_UNLOCK(vp, 0, p);
        !           914:        *retval = indx;
        !           915:        FILE_SET_MATURE(fp);
        !           916: out:
        !           917:        fdpunlock(fdp);
        !           918:        return (error);
        !           919: }
        !           920:
        !           921: /*
        !           922:  * Get file handle system call
        !           923:  */
        !           924: int
        !           925: sys_getfh(struct proc *p, void *v, register_t *retval)
        !           926: {
        !           927:        struct sys_getfh_args /* {
        !           928:                syscallarg(const char *) fname;
        !           929:                syscallarg(fhandle_t *) fhp;
        !           930:        } */ *uap = v;
        !           931:        struct vnode *vp;
        !           932:        fhandle_t fh;
        !           933:        int error;
        !           934:        struct nameidata nd;
        !           935:
        !           936:        /*
        !           937:         * Must be super user
        !           938:         */
        !           939:        error = suser(p, 0);
        !           940:        if (error)
        !           941:                return (error);
        !           942:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !           943:            SCARG(uap, fname), p);
        !           944:        error = namei(&nd);
        !           945:        if (error)
        !           946:                return (error);
        !           947:        vp = nd.ni_vp;
        !           948:        bzero(&fh, sizeof(fh));
        !           949:        fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
        !           950:        error = VFS_VPTOFH(vp, &fh.fh_fid);
        !           951:        vput(vp);
        !           952:        if (error)
        !           953:                return (error);
        !           954:        error = copyout(&fh, SCARG(uap, fhp), sizeof(fh));
        !           955:        return (error);
        !           956: }
        !           957:
        !           958: /*
        !           959:  * Open a file given a file handle.
        !           960:  *
        !           961:  * Check permissions, allocate an open file structure,
        !           962:  * and call the device open routine if any.
        !           963:  */
        !           964: int
        !           965: sys_fhopen(struct proc *p, void *v, register_t *retval)
        !           966: {
        !           967:        struct sys_fhopen_args /* {
        !           968:                syscallarg(const fhandle_t *) fhp;
        !           969:                syscallarg(int) flags;
        !           970:        } */ *uap = v;
        !           971:        struct filedesc *fdp = p->p_fd;
        !           972:        struct file *fp;
        !           973:        struct vnode *vp = NULL;
        !           974:        struct mount *mp;
        !           975:        struct ucred *cred = p->p_ucred;
        !           976:        int flags;
        !           977:        int type, indx, error=0;
        !           978:        struct flock lf;
        !           979:        struct vattr va;
        !           980:        fhandle_t fh;
        !           981:
        !           982:        /*
        !           983:         * Must be super user
        !           984:         */
        !           985:        if ((error = suser(p, 0)))
        !           986:                return (error);
        !           987:
        !           988:        flags = FFLAGS(SCARG(uap, flags));
        !           989:        if ((flags & (FREAD | FWRITE)) == 0)
        !           990:                return (EINVAL);
        !           991:        if ((flags & O_CREAT))
        !           992:                return (EINVAL);
        !           993:
        !           994:        fdplock(fdp);
        !           995:        if ((error = falloc(p, &fp, &indx)) != 0) {
        !           996:                fp = NULL;
        !           997:                goto bad;
        !           998:        }
        !           999:
        !          1000:        if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
        !          1001:                goto bad;
        !          1002:
        !          1003:        if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
        !          1004:                error = ESTALE;
        !          1005:                goto bad;
        !          1006:        }
        !          1007:
        !          1008:        if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)) != 0) {
        !          1009:                vp = NULL;      /* most likely unnecessary sanity for bad: */
        !          1010:                goto bad;
        !          1011:        }
        !          1012:
        !          1013:        /* Now do an effective vn_open */
        !          1014:
        !          1015:        if (vp->v_type == VSOCK) {
        !          1016:                error = EOPNOTSUPP;
        !          1017:                goto bad;
        !          1018:        }
        !          1019:        if (flags & FREAD) {
        !          1020:                if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0)
        !          1021:                        goto bad;
        !          1022:        }
        !          1023:        if (flags & (FWRITE | O_TRUNC)) {
        !          1024:                if (vp->v_type == VDIR) {
        !          1025:                        error = EISDIR;
        !          1026:                        goto bad;
        !          1027:                }
        !          1028:                if ((error = vn_writechk(vp)) != 0 ||
        !          1029:                    (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
        !          1030:                        goto bad;
        !          1031:        }
        !          1032:        if (flags & O_TRUNC) {
        !          1033:                VATTR_NULL(&va);
        !          1034:                va.va_size = 0;
        !          1035:                if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
        !          1036:                        goto bad;
        !          1037:        }
        !          1038:        if ((error = VOP_OPEN(vp, flags, cred, p)) != 0)
        !          1039:                goto bad;
        !          1040:        if (flags & FWRITE)
        !          1041:                vp->v_writecount++;
        !          1042:
        !          1043:        /* done with modified vn_open, now finish what sys_open does. */
        !          1044:
        !          1045:        fp->f_flag = flags & FMASK;
        !          1046:        fp->f_type = DTYPE_VNODE;
        !          1047:        fp->f_ops = &vnops;
        !          1048:        fp->f_data = vp;
        !          1049:        if (flags & (O_EXLOCK | O_SHLOCK)) {
        !          1050:                lf.l_whence = SEEK_SET;
        !          1051:                lf.l_start = 0;
        !          1052:                lf.l_len = 0;
        !          1053:                if (flags & O_EXLOCK)
        !          1054:                        lf.l_type = F_WRLCK;
        !          1055:                else
        !          1056:                        lf.l_type = F_RDLCK;
        !          1057:                type = F_FLOCK;
        !          1058:                if ((flags & FNONBLOCK) == 0)
        !          1059:                        type |= F_WAIT;
        !          1060:                VOP_UNLOCK(vp, 0, p);
        !          1061:                error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
        !          1062:                if (error)
        !          1063:                        goto bad;
        !          1064:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1065:                fp->f_flag |= FHASLOCK;
        !          1066:        }
        !          1067:        VOP_UNLOCK(vp, 0, p);
        !          1068:        *retval = indx;
        !          1069:        FILE_SET_MATURE(fp);
        !          1070:
        !          1071:        fdpunlock(fdp);
        !          1072:        return (0);
        !          1073:
        !          1074: bad:
        !          1075:        if (fp) {
        !          1076:                fdremove(fdp, indx);
        !          1077:                closef(fp, p);
        !          1078:                if (vp != NULL)
        !          1079:                        vput(vp);
        !          1080:        }
        !          1081:        fdpunlock(fdp);
        !          1082:        return (error);
        !          1083: }
        !          1084:
        !          1085: /* ARGSUSED */
        !          1086: int
        !          1087: sys_fhstat(struct proc *p, void *v, register_t *retval)
        !          1088: {
        !          1089:        struct sys_fhstat_args /* {
        !          1090:                syscallarg(const fhandle_t *) fhp;
        !          1091:                syscallarg(struct stat *) sb;
        !          1092:        } */ *uap = v;
        !          1093:        struct stat sb;
        !          1094:        int error;
        !          1095:        fhandle_t fh;
        !          1096:        struct mount *mp;
        !          1097:        struct vnode *vp;
        !          1098:
        !          1099:        /*
        !          1100:         * Must be super user
        !          1101:         */
        !          1102:        if ((error = suser(p, 0)))
        !          1103:                return (error);
        !          1104:
        !          1105:        if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
        !          1106:                return (error);
        !          1107:
        !          1108:        if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
        !          1109:                return (ESTALE);
        !          1110:        if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
        !          1111:                return (error);
        !          1112:        error = vn_stat(vp, &sb, p);
        !          1113:        vput(vp);
        !          1114:        if (error)
        !          1115:                return (error);
        !          1116:        error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
        !          1117:        return (error);
        !          1118: }
        !          1119:
        !          1120: /* ARGSUSED */
        !          1121: int
        !          1122: sys_fhstatfs(struct proc *p, void *v, register_t *retval)
        !          1123: {
        !          1124:        struct sys_fhstatfs_args /*
        !          1125:                syscallarg(const fhandle_t *) fhp;
        !          1126:                syscallarg(struct statfs *) buf;
        !          1127:        } */ *uap = v;
        !          1128:        struct statfs *sp;
        !          1129:        fhandle_t fh;
        !          1130:        struct mount *mp;
        !          1131:        struct vnode *vp;
        !          1132:        int error;
        !          1133:
        !          1134:        /*
        !          1135:         * Must be super user
        !          1136:         */
        !          1137:        if ((error = suser(p, 0)))
        !          1138:                return (error);
        !          1139:
        !          1140:        if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
        !          1141:                return (error);
        !          1142:
        !          1143:        if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
        !          1144:                return (ESTALE);
        !          1145:        if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
        !          1146:                return (error);
        !          1147:        mp = vp->v_mount;
        !          1148:        sp = &mp->mnt_stat;
        !          1149:        vput(vp);
        !          1150:        if ((error = VFS_STATFS(mp, sp, p)) != 0)
        !          1151:                return (error);
        !          1152:        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
        !          1153:        return (copyout(sp, SCARG(uap, buf), sizeof(sp)));
        !          1154: }
        !          1155:
        !          1156: /*
        !          1157:  * Create a special file.
        !          1158:  */
        !          1159: /* ARGSUSED */
        !          1160: int
        !          1161: sys_mknod(struct proc *p, void *v, register_t *retval)
        !          1162: {
        !          1163:        struct sys_mknod_args /* {
        !          1164:                syscallarg(const char *) path;
        !          1165:                syscallarg(mode_t) mode;
        !          1166:                syscallarg(int) dev;
        !          1167:        } */ *uap = v;
        !          1168:        struct vnode *vp;
        !          1169:        struct vattr vattr;
        !          1170:        int error;
        !          1171:        struct nameidata nd;
        !          1172:
        !          1173:        if ((error = suser(p, 0)) != 0)
        !          1174:                return (error);
        !          1175:        if (p->p_fd->fd_rdir)
        !          1176:                return (EINVAL);
        !          1177:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
        !          1178:        if ((error = namei(&nd)) != 0)
        !          1179:                return (error);
        !          1180:        vp = nd.ni_vp;
        !          1181:        if (vp != NULL)
        !          1182:                error = EEXIST;
        !          1183:        else {
        !          1184:                VATTR_NULL(&vattr);
        !          1185:                vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
        !          1186:                vattr.va_rdev = SCARG(uap, dev);
        !          1187:
        !          1188:                switch (SCARG(uap, mode) & S_IFMT) {
        !          1189:                case S_IFMT:    /* used by badsect to flag bad sectors */
        !          1190:                        vattr.va_type = VBAD;
        !          1191:                        break;
        !          1192:                case S_IFCHR:
        !          1193:                        vattr.va_type = VCHR;
        !          1194:                        break;
        !          1195:                case S_IFBLK:
        !          1196:                        vattr.va_type = VBLK;
        !          1197:                        break;
        !          1198:                default:
        !          1199:                        error = EINVAL;
        !          1200:                        break;
        !          1201:                }
        !          1202:        }
        !          1203:        if (!error) {
        !          1204:                error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
        !          1205:        } else {
        !          1206:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          1207:                if (nd.ni_dvp == vp)
        !          1208:                        vrele(nd.ni_dvp);
        !          1209:                else
        !          1210:                        vput(nd.ni_dvp);
        !          1211:                if (vp)
        !          1212:                        vrele(vp);
        !          1213:        }
        !          1214:        return (error);
        !          1215: }
        !          1216:
        !          1217: /*
        !          1218:  * Create a named pipe.
        !          1219:  */
        !          1220: /* ARGSUSED */
        !          1221: int
        !          1222: sys_mkfifo(struct proc *p, void *v, register_t *retval)
        !          1223: {
        !          1224: #ifndef FIFO
        !          1225:        return (EOPNOTSUPP);
        !          1226: #else
        !          1227:        struct sys_mkfifo_args /* {
        !          1228:                syscallarg(const char *) path;
        !          1229:                syscallarg(mode_t) mode;
        !          1230:        } */ *uap = v;
        !          1231:        struct vattr vattr;
        !          1232:        int error;
        !          1233:        struct nameidata nd;
        !          1234:
        !          1235:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
        !          1236:        if ((error = namei(&nd)) != 0)
        !          1237:                return (error);
        !          1238:        if (nd.ni_vp != NULL) {
        !          1239:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          1240:                if (nd.ni_dvp == nd.ni_vp)
        !          1241:                        vrele(nd.ni_dvp);
        !          1242:                else
        !          1243:                        vput(nd.ni_dvp);
        !          1244:                vrele(nd.ni_vp);
        !          1245:                return (EEXIST);
        !          1246:        }
        !          1247:        VATTR_NULL(&vattr);
        !          1248:        vattr.va_type = VFIFO;
        !          1249:        vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
        !          1250:        return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
        !          1251: #endif /* FIFO */
        !          1252: }
        !          1253:
        !          1254: /*
        !          1255:  * Make a hard file link.
        !          1256:  */
        !          1257: /* ARGSUSED */
        !          1258: int
        !          1259: sys_link(struct proc *p, void *v, register_t *retval)
        !          1260: {
        !          1261:        struct sys_link_args /* {
        !          1262:                syscallarg(const char *) path;
        !          1263:                syscallarg(const char *) link;
        !          1264:        } */ *uap = v;
        !          1265:        struct vnode *vp;
        !          1266:        struct nameidata nd;
        !          1267:        int error;
        !          1268:        int flags;
        !          1269:
        !          1270:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
        !          1271:        if ((error = namei(&nd)) != 0)
        !          1272:                return (error);
        !          1273:        vp = nd.ni_vp;
        !          1274:
        !          1275:        flags = LOCKPARENT;
        !          1276:        if (vp->v_type == VDIR) {
        !          1277:                flags |= STRIPSLASHES;
        !          1278:        }
        !          1279:
        !          1280:        NDINIT(&nd, CREATE, flags, UIO_USERSPACE, SCARG(uap, link), p);
        !          1281:        if ((error = namei(&nd)) != 0)
        !          1282:                goto out;
        !          1283:        if (nd.ni_vp) {
        !          1284:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          1285:                if (nd.ni_dvp == nd.ni_vp)
        !          1286:                        vrele(nd.ni_dvp);
        !          1287:                else
        !          1288:                        vput(nd.ni_dvp);
        !          1289:                vrele(nd.ni_vp);
        !          1290:                error = EEXIST;
        !          1291:                goto out;
        !          1292:        }
        !          1293:        error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
        !          1294: out:
        !          1295:        vrele(vp);
        !          1296:        return (error);
        !          1297: }
        !          1298:
        !          1299: /*
        !          1300:  * Make a symbolic link.
        !          1301:  */
        !          1302: /* ARGSUSED */
        !          1303: int
        !          1304: sys_symlink(struct proc *p, void *v, register_t *retval)
        !          1305: {
        !          1306:        struct sys_symlink_args /* {
        !          1307:                syscallarg(const char *) path;
        !          1308:                syscallarg(const char *) link;
        !          1309:        } */ *uap = v;
        !          1310:        struct vattr vattr;
        !          1311:        char *path;
        !          1312:        int error;
        !          1313:        struct nameidata nd;
        !          1314:
        !          1315:        path = pool_get(&namei_pool, PR_WAITOK);
        !          1316:        error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL);
        !          1317:        if (error)
        !          1318:                goto out;
        !          1319:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
        !          1320:        if ((error = namei(&nd)) != 0)
        !          1321:                goto out;
        !          1322:        if (nd.ni_vp) {
        !          1323:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          1324:                if (nd.ni_dvp == nd.ni_vp)
        !          1325:                        vrele(nd.ni_dvp);
        !          1326:                else
        !          1327:                        vput(nd.ni_dvp);
        !          1328:                vrele(nd.ni_vp);
        !          1329:                error = EEXIST;
        !          1330:                goto out;
        !          1331:        }
        !          1332:        VATTR_NULL(&vattr);
        !          1333:        vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
        !          1334:        error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
        !          1335: out:
        !          1336:        pool_put(&namei_pool, path);
        !          1337:        return (error);
        !          1338: }
        !          1339:
        !          1340: /*
        !          1341:  * Delete a name from the filesystem.
        !          1342:  */
        !          1343: /* ARGSUSED */
        !          1344: int
        !          1345: sys_unlink(struct proc *p, void *v, register_t *retval)
        !          1346: {
        !          1347:        struct sys_unlink_args /* {
        !          1348:                syscallarg(const char *) path;
        !          1349:        } */ *uap = v;
        !          1350:        struct vnode *vp;
        !          1351:        int error;
        !          1352:        struct nameidata nd;
        !          1353:
        !          1354:        NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
        !          1355:            SCARG(uap, path), p);
        !          1356:        if ((error = namei(&nd)) != 0)
        !          1357:                return (error);
        !          1358:        vp = nd.ni_vp;
        !          1359:
        !          1360:        /*
        !          1361:         * The root of a mounted filesystem cannot be deleted.
        !          1362:         */
        !          1363:        if (vp->v_flag & VROOT) {
        !          1364:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          1365:                if (nd.ni_dvp == vp)
        !          1366:                        vrele(nd.ni_dvp);
        !          1367:                else
        !          1368:                        vput(nd.ni_dvp);
        !          1369:                vput(vp);
        !          1370:                error = EBUSY;
        !          1371:                goto out;
        !          1372:        }
        !          1373:
        !          1374:        (void)uvm_vnp_uncache(vp);
        !          1375:
        !          1376:        error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
        !          1377: out:
        !          1378:        return (error);
        !          1379: }
        !          1380:
        !          1381: /*
        !          1382:  * Reposition read/write file offset.
        !          1383:  */
        !          1384: int
        !          1385: sys_lseek(struct proc *p, void *v, register_t *retval)
        !          1386: {
        !          1387:        struct sys_lseek_args /* {
        !          1388:                syscallarg(int) fd;
        !          1389:                syscallarg(int) pad;
        !          1390:                syscallarg(off_t) offset;
        !          1391:                syscallarg(int) whence;
        !          1392:        } */ *uap = v;
        !          1393:        struct ucred *cred = p->p_ucred;
        !          1394:        struct filedesc *fdp = p->p_fd;
        !          1395:        struct file *fp;
        !          1396:        struct vattr vattr;
        !          1397:        struct vnode *vp;
        !          1398:        off_t offarg, newoff;
        !          1399:        int error, special;
        !          1400:
        !          1401:        if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
        !          1402:                return (EBADF);
        !          1403:        if (fp->f_type != DTYPE_VNODE)
        !          1404:                return (ESPIPE);
        !          1405:        vp = (struct vnode *)fp->f_data;
        !          1406:        if (vp->v_type == VFIFO)
        !          1407:                return (ESPIPE);
        !          1408:        if (vp->v_type == VCHR)
        !          1409:                special = 1;
        !          1410:        else
        !          1411:                special = 0;
        !          1412:        offarg = SCARG(uap, offset);
        !          1413:
        !          1414:        switch (SCARG(uap, whence)) {
        !          1415:        case SEEK_CUR:
        !          1416:                newoff = fp->f_offset + offarg;;
        !          1417:                break;
        !          1418:        case SEEK_END:
        !          1419:                error = VOP_GETATTR((struct vnode *)fp->f_data, &vattr,
        !          1420:                                    cred, p);
        !          1421:                if (error)
        !          1422:                        return (error);
        !          1423:                newoff = offarg + (off_t)vattr.va_size;
        !          1424:                break;
        !          1425:        case SEEK_SET:
        !          1426:                newoff = offarg;
        !          1427:                break;
        !          1428:        default:
        !          1429:                return (EINVAL);
        !          1430:        }
        !          1431:        if (!special) {
        !          1432:                if (newoff < 0)
        !          1433:                        return (EINVAL);
        !          1434:        } else {
        !          1435:                /*
        !          1436:                 * Make sure the user don't seek beyond the end of the
        !          1437:                 * partition.
        !          1438:                 */
        !          1439:                struct partinfo dpart;
        !          1440:                error = vn_ioctl(fp, DIOCGPART, (void *)&dpart, p);
        !          1441:                if (!error) {
        !          1442:                        if (newoff >= DL_GETPSIZE(dpart.part) *
        !          1443:                            dpart.disklab->d_secsize)
        !          1444:                                        return (EINVAL);
        !          1445:                }
        !          1446:        }
        !          1447:        *(off_t *)retval = fp->f_offset = newoff;
        !          1448:        fp->f_seek++;
        !          1449:        return (0);
        !          1450: }
        !          1451:
        !          1452: /*
        !          1453:  * Check access permissions.
        !          1454:  */
        !          1455: int
        !          1456: sys_access(struct proc *p, void *v, register_t *retval)
        !          1457: {
        !          1458:        struct sys_access_args /* {
        !          1459:                syscallarg(const char *) path;
        !          1460:                syscallarg(int) flags;
        !          1461:        } */ *uap = v;
        !          1462:        struct ucred *cred = p->p_ucred;
        !          1463:        struct vnode *vp;
        !          1464:        int error, flags, t_gid, t_uid;
        !          1465:        struct nameidata nd;
        !          1466:
        !          1467:        if (SCARG(uap, flags) & ~(R_OK | W_OK | X_OK))
        !          1468:                return (EINVAL);
        !          1469:        t_uid = cred->cr_uid;
        !          1470:        t_gid = cred->cr_gid;
        !          1471:        cred->cr_uid = p->p_cred->p_ruid;
        !          1472:        cred->cr_gid = p->p_cred->p_rgid;
        !          1473:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !          1474:            SCARG(uap, path), p);
        !          1475:        if ((error = namei(&nd)) != 0)
        !          1476:                goto out1;
        !          1477:        vp = nd.ni_vp;
        !          1478:
        !          1479:        /* Flags == 0 means only check for existence. */
        !          1480:        if (SCARG(uap, flags)) {
        !          1481:                flags = 0;
        !          1482:                if (SCARG(uap, flags) & R_OK)
        !          1483:                        flags |= VREAD;
        !          1484:                if (SCARG(uap, flags) & W_OK)
        !          1485:                        flags |= VWRITE;
        !          1486:                if (SCARG(uap, flags) & X_OK)
        !          1487:                        flags |= VEXEC;
        !          1488:                if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
        !          1489:                        error = VOP_ACCESS(vp, flags, cred, p);
        !          1490:        }
        !          1491:        vput(vp);
        !          1492: out1:
        !          1493:        cred->cr_uid = t_uid;
        !          1494:        cred->cr_gid = t_gid;
        !          1495:        return (error);
        !          1496: }
        !          1497:
        !          1498: /*
        !          1499:  * Get file status; this version follows links.
        !          1500:  */
        !          1501: /* ARGSUSED */
        !          1502: int
        !          1503: sys_stat(struct proc *p, void *v, register_t *retval)
        !          1504: {
        !          1505:        struct sys_stat_args /* {
        !          1506:                syscallarg(const char *) path;
        !          1507:                syscallarg(struct stat *) ub;
        !          1508:        } */ *uap = v;
        !          1509:        struct stat sb;
        !          1510:        int error;
        !          1511:        struct nameidata nd;
        !          1512:
        !          1513:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !          1514:            SCARG(uap, path), p);
        !          1515:        if ((error = namei(&nd)) != 0)
        !          1516:                return (error);
        !          1517:        error = vn_stat(nd.ni_vp, &sb, p);
        !          1518:        vput(nd.ni_vp);
        !          1519:        if (error)
        !          1520:                return (error);
        !          1521:        /* Don't let non-root see generation numbers (for NFS security) */
        !          1522:        if (suser(p, 0))
        !          1523:                sb.st_gen = 0;
        !          1524:        error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
        !          1525:        return (error);
        !          1526: }
        !          1527:
        !          1528: /*
        !          1529:  * Get file status; this version does not follow links.
        !          1530:  */
        !          1531: /* ARGSUSED */
        !          1532: int
        !          1533: sys_lstat(struct proc *p, void *v, register_t *retval)
        !          1534: {
        !          1535:        struct sys_lstat_args /* {
        !          1536:                syscallarg(const char *) path;
        !          1537:                syscallarg(struct stat *) ub;
        !          1538:        } */ *uap = v;
        !          1539:        struct stat sb;
        !          1540:        int error;
        !          1541:        struct nameidata nd;
        !          1542:
        !          1543:        NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
        !          1544:            SCARG(uap, path), p);
        !          1545:        if ((error = namei(&nd)) != 0)
        !          1546:                return (error);
        !          1547:        error = vn_stat(nd.ni_vp, &sb, p);
        !          1548:        vput(nd.ni_vp);
        !          1549:        if (error)
        !          1550:                return (error);
        !          1551:        /* Don't let non-root see generation numbers (for NFS security) */
        !          1552:        if (suser(p, 0))
        !          1553:                sb.st_gen = 0;
        !          1554:        error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
        !          1555:        return (error);
        !          1556: }
        !          1557:
        !          1558: /*
        !          1559:  * Get configurable pathname variables.
        !          1560:  */
        !          1561: /* ARGSUSED */
        !          1562: int
        !          1563: sys_pathconf(struct proc *p, void *v, register_t *retval)
        !          1564: {
        !          1565:        struct sys_pathconf_args /* {
        !          1566:                syscallarg(const char *) path;
        !          1567:                syscallarg(int) name;
        !          1568:        } */ *uap = v;
        !          1569:        int error;
        !          1570:        struct nameidata nd;
        !          1571:
        !          1572:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !          1573:            SCARG(uap, path), p);
        !          1574:        if ((error = namei(&nd)) != 0)
        !          1575:                return (error);
        !          1576:        error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
        !          1577:        vput(nd.ni_vp);
        !          1578:        return (error);
        !          1579: }
        !          1580:
        !          1581: /*
        !          1582:  * Return target name of a symbolic link.
        !          1583:  */
        !          1584: /* ARGSUSED */
        !          1585: int
        !          1586: sys_readlink(struct proc *p, void *v, register_t *retval)
        !          1587: {
        !          1588:        struct sys_readlink_args /* {
        !          1589:                syscallarg(const char *) path;
        !          1590:                syscallarg(char *) buf;
        !          1591:                syscallarg(size_t) count;
        !          1592:        } */ *uap = v;
        !          1593:        struct vnode *vp;
        !          1594:        struct iovec aiov;
        !          1595:        struct uio auio;
        !          1596:        int error;
        !          1597:        struct nameidata nd;
        !          1598:
        !          1599:        NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
        !          1600:            SCARG(uap, path), p);
        !          1601:        if ((error = namei(&nd)) != 0)
        !          1602:                return (error);
        !          1603:        vp = nd.ni_vp;
        !          1604:        if (vp->v_type != VLNK)
        !          1605:                error = EINVAL;
        !          1606:        else {
        !          1607:                aiov.iov_base = SCARG(uap, buf);
        !          1608:                aiov.iov_len = SCARG(uap, count);
        !          1609:                auio.uio_iov = &aiov;
        !          1610:                auio.uio_iovcnt = 1;
        !          1611:                auio.uio_offset = 0;
        !          1612:                auio.uio_rw = UIO_READ;
        !          1613:                auio.uio_segflg = UIO_USERSPACE;
        !          1614:                auio.uio_procp = p;
        !          1615:                auio.uio_resid = SCARG(uap, count);
        !          1616:                error = VOP_READLINK(vp, &auio, p->p_ucred);
        !          1617:        }
        !          1618:        vput(vp);
        !          1619:        *retval = SCARG(uap, count) - auio.uio_resid;
        !          1620:        return (error);
        !          1621: }
        !          1622:
        !          1623: /*
        !          1624:  * Change flags of a file given a path name.
        !          1625:  */
        !          1626: /* ARGSUSED */
        !          1627: int
        !          1628: sys_chflags(struct proc *p, void *v, register_t *retval)
        !          1629: {
        !          1630:        struct sys_chflags_args /* {
        !          1631:                syscallarg(const char *) path;
        !          1632:                syscallarg(u_int) flags;
        !          1633:        } */ *uap = v;
        !          1634:        struct vnode *vp;
        !          1635:        struct vattr vattr;
        !          1636:        int error;
        !          1637:        struct nameidata nd;
        !          1638:
        !          1639:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
        !          1640:        if ((error = namei(&nd)) != 0)
        !          1641:                return (error);
        !          1642:        vp = nd.ni_vp;
        !          1643:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1644:        if (vp->v_mount->mnt_flag & MNT_RDONLY)
        !          1645:                error = EROFS;
        !          1646:        else if (SCARG(uap, flags) == VNOVAL)
        !          1647:                error = EINVAL;
        !          1648:        else {
        !          1649:                if (suser(p, 0)) {
        !          1650:                        if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
        !          1651:                                goto out;
        !          1652:                        if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
        !          1653:                                error = EINVAL;
        !          1654:                                goto out;
        !          1655:                        }
        !          1656:                }
        !          1657:                VATTR_NULL(&vattr);
        !          1658:                vattr.va_flags = SCARG(uap, flags);
        !          1659:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1660:        }
        !          1661: out:
        !          1662:        vput(vp);
        !          1663:        return (error);
        !          1664: }
        !          1665:
        !          1666: /*
        !          1667:  * Change flags of a file given a file descriptor.
        !          1668:  */
        !          1669: /* ARGSUSED */
        !          1670: int
        !          1671: sys_fchflags(struct proc *p, void *v, register_t *retval)
        !          1672: {
        !          1673:        struct sys_fchflags_args /* {
        !          1674:                syscallarg(int) fd;
        !          1675:                syscallarg(u_int) flags;
        !          1676:        } */ *uap = v;
        !          1677:        struct vattr vattr;
        !          1678:        struct vnode *vp;
        !          1679:        struct file *fp;
        !          1680:        int error;
        !          1681:
        !          1682:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
        !          1683:                return (error);
        !          1684:        vp = (struct vnode *)fp->f_data;
        !          1685:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1686:        if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY)
        !          1687:                error = EROFS;
        !          1688:        else if (SCARG(uap, flags) == VNOVAL)
        !          1689:                error = EINVAL;
        !          1690:        else {
        !          1691:                if (suser(p, 0)) {
        !          1692:                        if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
        !          1693:                            != 0)
        !          1694:                                goto out;
        !          1695:                        if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
        !          1696:                                error = EINVAL;
        !          1697:                                goto out;
        !          1698:                        }
        !          1699:                }
        !          1700:                VATTR_NULL(&vattr);
        !          1701:                vattr.va_flags = SCARG(uap, flags);
        !          1702:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1703:        }
        !          1704: out:
        !          1705:        VOP_UNLOCK(vp, 0, p);
        !          1706:        FRELE(fp);
        !          1707:        return (error);
        !          1708: }
        !          1709:
        !          1710: /*
        !          1711:  * Change mode of a file given path name.
        !          1712:  */
        !          1713: /* ARGSUSED */
        !          1714: int
        !          1715: sys_chmod(struct proc *p, void *v, register_t *retval)
        !          1716: {
        !          1717:        struct sys_chmod_args /* {
        !          1718:                syscallarg(const char *) path;
        !          1719:                syscallarg(mode_t) mode;
        !          1720:        } */ *uap = v;
        !          1721:        struct vnode *vp;
        !          1722:        struct vattr vattr;
        !          1723:        int error;
        !          1724:        struct nameidata nd;
        !          1725:
        !          1726:        if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
        !          1727:                return (EINVAL);
        !          1728:
        !          1729:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
        !          1730:        if ((error = namei(&nd)) != 0)
        !          1731:                return (error);
        !          1732:        vp = nd.ni_vp;
        !          1733:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1734:        if (vp->v_mount->mnt_flag & MNT_RDONLY)
        !          1735:                error = EROFS;
        !          1736:        else {
        !          1737:                VATTR_NULL(&vattr);
        !          1738:                vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
        !          1739:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1740:        }
        !          1741:        vput(vp);
        !          1742:        return (error);
        !          1743: }
        !          1744:
        !          1745: /*
        !          1746:  * Change mode of a file given a file descriptor.
        !          1747:  */
        !          1748: /* ARGSUSED */
        !          1749: int
        !          1750: sys_fchmod(struct proc *p, void *v, register_t *retval)
        !          1751: {
        !          1752:        struct sys_fchmod_args /* {
        !          1753:                syscallarg(int) fd;
        !          1754:                syscallarg(mode_t) mode;
        !          1755:        } */ *uap = v;
        !          1756:        struct vattr vattr;
        !          1757:        struct vnode *vp;
        !          1758:        struct file *fp;
        !          1759:        int error;
        !          1760:
        !          1761:        if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
        !          1762:                return (EINVAL);
        !          1763:
        !          1764:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
        !          1765:                return (error);
        !          1766:        vp = (struct vnode *)fp->f_data;
        !          1767:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1768:        if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY)
        !          1769:                error = EROFS;
        !          1770:        else {
        !          1771:                VATTR_NULL(&vattr);
        !          1772:                vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
        !          1773:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1774:        }
        !          1775:        VOP_UNLOCK(vp, 0, p);
        !          1776:        FRELE(fp);
        !          1777:        return (error);
        !          1778: }
        !          1779:
        !          1780: /*
        !          1781:  * Set ownership given a path name.
        !          1782:  */
        !          1783: /* ARGSUSED */
        !          1784: int
        !          1785: sys_chown(struct proc *p, void *v, register_t *retval)
        !          1786: {
        !          1787:        struct sys_chown_args /* {
        !          1788:                syscallarg(const char *) path;
        !          1789:                syscallarg(uid_t) uid;
        !          1790:                syscallarg(gid_t) gid;
        !          1791:        } */ *uap = v;
        !          1792:        struct vnode *vp;
        !          1793:        struct vattr vattr;
        !          1794:        int error;
        !          1795:        struct nameidata nd;
        !          1796:        mode_t mode;
        !          1797:
        !          1798:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
        !          1799:        if ((error = namei(&nd)) != 0)
        !          1800:                return (error);
        !          1801:        vp = nd.ni_vp;
        !          1802:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1803:        if (vp->v_mount->mnt_flag & MNT_RDONLY)
        !          1804:                error = EROFS;
        !          1805:        else {
        !          1806:                if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
        !          1807:                    (suser(p, 0) || suid_clear)) {
        !          1808:                        error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
        !          1809:                        if (error)
        !          1810:                                goto out;
        !          1811:                        mode = vattr.va_mode & ~(VSUID | VSGID);
        !          1812:                        if (mode == vattr.va_mode)
        !          1813:                                mode = VNOVAL;
        !          1814:                }
        !          1815:                else
        !          1816:                        mode = VNOVAL;
        !          1817:                VATTR_NULL(&vattr);
        !          1818:                vattr.va_uid = SCARG(uap, uid);
        !          1819:                vattr.va_gid = SCARG(uap, gid);
        !          1820:                vattr.va_mode = mode;
        !          1821:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1822:        }
        !          1823: out:
        !          1824:        vput(vp);
        !          1825:        return (error);
        !          1826: }
        !          1827:
        !          1828: /*
        !          1829:  * Set ownership given a path name, without following links.
        !          1830:  */
        !          1831: /* ARGSUSED */
        !          1832: int
        !          1833: sys_lchown(struct proc *p, void *v, register_t *retval)
        !          1834: {
        !          1835:        struct sys_lchown_args /* {
        !          1836:                syscallarg(const char *) path;
        !          1837:                syscallarg(uid_t) uid;
        !          1838:                syscallarg(gid_t) gid;
        !          1839:        } */ *uap = v;
        !          1840:        struct vnode *vp;
        !          1841:        struct vattr vattr;
        !          1842:        int error;
        !          1843:        struct nameidata nd;
        !          1844:        mode_t mode;
        !          1845:
        !          1846:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
        !          1847:        if ((error = namei(&nd)) != 0)
        !          1848:                return (error);
        !          1849:        vp = nd.ni_vp;
        !          1850:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1851:        if (vp->v_mount->mnt_flag & MNT_RDONLY)
        !          1852:                error = EROFS;
        !          1853:        else {
        !          1854:                if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
        !          1855:                    (suser(p, 0) || suid_clear)) {
        !          1856:                        error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
        !          1857:                        if (error)
        !          1858:                                goto out;
        !          1859:                        mode = vattr.va_mode & ~(VSUID | VSGID);
        !          1860:                        if (mode == vattr.va_mode)
        !          1861:                                mode = VNOVAL;
        !          1862:                }
        !          1863:                else
        !          1864:                        mode = VNOVAL;
        !          1865:                VATTR_NULL(&vattr);
        !          1866:                vattr.va_uid = SCARG(uap, uid);
        !          1867:                vattr.va_gid = SCARG(uap, gid);
        !          1868:                vattr.va_mode = mode;
        !          1869:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1870:        }
        !          1871: out:
        !          1872:        vput(vp);
        !          1873:        return (error);
        !          1874: }
        !          1875:
        !          1876: /*
        !          1877:  * Set ownership given a file descriptor.
        !          1878:  */
        !          1879: /* ARGSUSED */
        !          1880: int
        !          1881: sys_fchown(struct proc *p, void *v, register_t *retval)
        !          1882: {
        !          1883:        struct sys_fchown_args /* {
        !          1884:                syscallarg(int) fd;
        !          1885:                syscallarg(uid_t) uid;
        !          1886:                syscallarg(gid_t) gid;
        !          1887:        } */ *uap = v;
        !          1888:        struct vnode *vp;
        !          1889:        struct vattr vattr;
        !          1890:        int error;
        !          1891:        struct file *fp;
        !          1892:        mode_t mode;
        !          1893:
        !          1894:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
        !          1895:                return (error);
        !          1896:        vp = (struct vnode *)fp->f_data;
        !          1897:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1898:        if (vp->v_mount->mnt_flag & MNT_RDONLY)
        !          1899:                error = EROFS;
        !          1900:        else {
        !          1901:                if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
        !          1902:                    (suser(p, 0) || suid_clear)) {
        !          1903:                        error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
        !          1904:                        if (error)
        !          1905:                                goto out;
        !          1906:                        mode = vattr.va_mode & ~(VSUID | VSGID);
        !          1907:                        if (mode == vattr.va_mode)
        !          1908:                                mode = VNOVAL;
        !          1909:                } else
        !          1910:                        mode = VNOVAL;
        !          1911:                VATTR_NULL(&vattr);
        !          1912:                vattr.va_uid = SCARG(uap, uid);
        !          1913:                vattr.va_gid = SCARG(uap, gid);
        !          1914:                vattr.va_mode = mode;
        !          1915:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1916:        }
        !          1917: out:
        !          1918:        VOP_UNLOCK(vp, 0, p);
        !          1919:        FRELE(fp);
        !          1920:        return (error);
        !          1921: }
        !          1922:
        !          1923: /*
        !          1924:  * Set the access and modification times given a path name.
        !          1925:  */
        !          1926: /* ARGSUSED */
        !          1927: int
        !          1928: sys_utimes(struct proc *p, void *v, register_t *retval)
        !          1929: {
        !          1930:        struct sys_utimes_args /* {
        !          1931:                syscallarg(const char *) path;
        !          1932:                syscallarg(const struct timeval *) tptr;
        !          1933:        } */ *uap = v;
        !          1934:        struct vnode *vp;
        !          1935:        struct timeval tv[2];
        !          1936:        struct vattr vattr;
        !          1937:        int error;
        !          1938:        struct nameidata nd;
        !          1939:
        !          1940:        VATTR_NULL(&vattr);
        !          1941:        if (SCARG(uap, tptr) == NULL) {
        !          1942:                microtime(&tv[0]);
        !          1943:                tv[1] = tv[0];
        !          1944:                vattr.va_vaflags |= VA_UTIMES_NULL;
        !          1945:        } else {
        !          1946:                error = copyin(SCARG(uap, tptr), tv,
        !          1947:                    sizeof(tv));
        !          1948:                if (error)
        !          1949:                        return (error);
        !          1950:                /* XXX workaround timeval matching the VFS constant VNOVAL */
        !          1951:                if (tv[0].tv_sec == VNOVAL)
        !          1952:                        tv[0].tv_sec = VNOVAL - 1;
        !          1953:                if (tv[1].tv_sec == VNOVAL)
        !          1954:                        tv[1].tv_sec = VNOVAL - 1;
        !          1955:        }
        !          1956:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
        !          1957:        if ((error = namei(&nd)) != 0)
        !          1958:                return (error);
        !          1959:        vp = nd.ni_vp;
        !          1960:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1961:        if (vp->v_mount->mnt_flag & MNT_RDONLY)
        !          1962:                error = EROFS;
        !          1963:        else {
        !          1964:                vattr.va_atime.tv_sec = tv[0].tv_sec;
        !          1965:                vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
        !          1966:                vattr.va_mtime.tv_sec = tv[1].tv_sec;
        !          1967:                vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
        !          1968:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1969:        }
        !          1970:        vput(vp);
        !          1971:        return (error);
        !          1972: }
        !          1973:
        !          1974: /*
        !          1975:  * Set the access and modification times given a file descriptor.
        !          1976:  */
        !          1977: /* ARGSUSED */
        !          1978: int
        !          1979: sys_futimes(struct proc *p, void *v, register_t *retval)
        !          1980: {
        !          1981:        struct sys_futimes_args /* {
        !          1982:                syscallarg(int) fd;
        !          1983:                syscallarg(const struct timeval *) tptr;
        !          1984:        } */ *uap = v;
        !          1985:        struct vnode *vp;
        !          1986:        struct timeval tv[2];
        !          1987:        struct vattr vattr;
        !          1988:        int error;
        !          1989:        struct file *fp;
        !          1990:
        !          1991:        VATTR_NULL(&vattr);
        !          1992:        if (SCARG(uap, tptr) == NULL) {
        !          1993:                microtime(&tv[0]);
        !          1994:                tv[1] = tv[0];
        !          1995:                vattr.va_vaflags |= VA_UTIMES_NULL;
        !          1996:        } else {
        !          1997:                error = copyin(SCARG(uap, tptr), tv,
        !          1998:                    sizeof(tv));
        !          1999:                if (error)
        !          2000:                        return (error);
        !          2001:                /* XXX workaround timeval matching the VFS constant VNOVAL */
        !          2002:                if (tv[0].tv_sec == VNOVAL)
        !          2003:                        tv[0].tv_sec = VNOVAL - 1;
        !          2004:                if (tv[1].tv_sec == VNOVAL)
        !          2005:                        tv[1].tv_sec = VNOVAL - 1;
        !          2006:        }
        !          2007:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
        !          2008:                return (error);
        !          2009:        vp = (struct vnode *)fp->f_data;
        !          2010:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          2011:        if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY)
        !          2012:                error = EROFS;
        !          2013:        else {
        !          2014:                vattr.va_atime.tv_sec = tv[0].tv_sec;
        !          2015:                vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
        !          2016:                vattr.va_mtime.tv_sec = tv[1].tv_sec;
        !          2017:                vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
        !          2018:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          2019:        }
        !          2020:        VOP_UNLOCK(vp, 0, p);
        !          2021:        FRELE(fp);
        !          2022:        return (error);
        !          2023: }
        !          2024:
        !          2025: /*
        !          2026:  * Truncate a file given its path name.
        !          2027:  */
        !          2028: /* ARGSUSED */
        !          2029: int
        !          2030: sys_truncate(struct proc *p, void *v, register_t *retval)
        !          2031: {
        !          2032:        struct sys_truncate_args /* {
        !          2033:                syscallarg(const char *) path;
        !          2034:                syscallarg(int) pad;
        !          2035:                syscallarg(off_t) length;
        !          2036:        } */ *uap = v;
        !          2037:        struct vnode *vp;
        !          2038:        struct vattr vattr;
        !          2039:        int error;
        !          2040:        struct nameidata nd;
        !          2041:
        !          2042:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
        !          2043:        if ((error = namei(&nd)) != 0)
        !          2044:                return (error);
        !          2045:        vp = nd.ni_vp;
        !          2046:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          2047:        if (vp->v_type == VDIR)
        !          2048:                error = EISDIR;
        !          2049:        else if ((error = vn_writechk(vp)) == 0 &&
        !          2050:            (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
        !          2051:                VATTR_NULL(&vattr);
        !          2052:                vattr.va_size = SCARG(uap, length);
        !          2053:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          2054:        }
        !          2055:        vput(vp);
        !          2056:        return (error);
        !          2057: }
        !          2058:
        !          2059: /*
        !          2060:  * Truncate a file given a file descriptor.
        !          2061:  */
        !          2062: /* ARGSUSED */
        !          2063: int
        !          2064: sys_ftruncate(struct proc *p, void *v, register_t *retval)
        !          2065: {
        !          2066:        struct sys_ftruncate_args /* {
        !          2067:                syscallarg(int) fd;
        !          2068:                syscallarg(int) pad;
        !          2069:                syscallarg(off_t) length;
        !          2070:        } */ *uap = v;
        !          2071:        struct vattr vattr;
        !          2072:        struct vnode *vp;
        !          2073:        struct file *fp;
        !          2074:        off_t len;
        !          2075:        int error;
        !          2076:
        !          2077:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
        !          2078:                return (error);
        !          2079:        len = SCARG(uap, length);
        !          2080:        if ((fp->f_flag & FWRITE) == 0 || len < 0) {
        !          2081:                error = EINVAL;
        !          2082:                goto bad;
        !          2083:        }
        !          2084:        vp = (struct vnode *)fp->f_data;
        !          2085:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          2086:        if (vp->v_type == VDIR)
        !          2087:                error = EISDIR;
        !          2088:        else if ((error = vn_writechk(vp)) == 0) {
        !          2089:                VATTR_NULL(&vattr);
        !          2090:                vattr.va_size = len;
        !          2091:                error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
        !          2092:        }
        !          2093:        VOP_UNLOCK(vp, 0, p);
        !          2094: bad:
        !          2095:        FRELE(fp);
        !          2096:        return (error);
        !          2097: }
        !          2098:
        !          2099: /*
        !          2100:  * Sync an open file.
        !          2101:  */
        !          2102: /* ARGSUSED */
        !          2103: int
        !          2104: sys_fsync(struct proc *p, void *v, register_t *retval)
        !          2105: {
        !          2106:        struct sys_fsync_args /* {
        !          2107:                syscallarg(int) fd;
        !          2108:        } */ *uap = v;
        !          2109:        struct vnode *vp;
        !          2110:        struct file *fp;
        !          2111:        int error;
        !          2112:
        !          2113:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
        !          2114:                return (error);
        !          2115:        vp = (struct vnode *)fp->f_data;
        !          2116:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          2117:        error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
        !          2118: #ifdef FFS_SOFTUPDATES
        !          2119:        if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
        !          2120:                error = softdep_fsync(vp);
        !          2121: #endif
        !          2122:
        !          2123:        VOP_UNLOCK(vp, 0, p);
        !          2124:        FRELE(fp);
        !          2125:        return (error);
        !          2126: }
        !          2127:
        !          2128: /*
        !          2129:  * Rename files.  Source and destination must either both be directories,
        !          2130:  * or both not be directories.  If target is a directory, it must be empty.
        !          2131:  */
        !          2132: /* ARGSUSED */
        !          2133: int
        !          2134: sys_rename(struct proc *p, void *v, register_t *retval)
        !          2135: {
        !          2136:        struct sys_rename_args /* {
        !          2137:                syscallarg(const char *) from;
        !          2138:                syscallarg(const char *) to;
        !          2139:        } */ *uap = v;
        !          2140:        struct vnode *tvp, *fvp, *tdvp;
        !          2141:        struct nameidata fromnd, tond;
        !          2142:        int error;
        !          2143:        int flags;
        !          2144:
        !          2145:        NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
        !          2146:            SCARG(uap, from), p);
        !          2147:        if ((error = namei(&fromnd)) != 0)
        !          2148:                return (error);
        !          2149:        fvp = fromnd.ni_vp;
        !          2150:
        !          2151:        flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
        !          2152:        /*
        !          2153:         * rename("foo/", "bar/");  is  OK
        !          2154:         */
        !          2155:        if (fvp->v_type == VDIR)
        !          2156:                flags |= STRIPSLASHES;
        !          2157:
        !          2158:        NDINIT(&tond, RENAME, flags,
        !          2159:            UIO_USERSPACE, SCARG(uap, to), p);
        !          2160:        if ((error = namei(&tond)) != 0) {
        !          2161:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
        !          2162:                vrele(fromnd.ni_dvp);
        !          2163:                vrele(fvp);
        !          2164:                goto out1;
        !          2165:        }
        !          2166:        tdvp = tond.ni_dvp;
        !          2167:        tvp = tond.ni_vp;
        !          2168:        if (tvp != NULL) {
        !          2169:                if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
        !          2170:                        error = ENOTDIR;
        !          2171:                        goto out;
        !          2172:                } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
        !          2173:                        error = EISDIR;
        !          2174:                        goto out;
        !          2175:                }
        !          2176:        }
        !          2177:        if (fvp == tdvp)
        !          2178:                error = EINVAL;
        !          2179:        /*
        !          2180:         * If source is the same as the destination (that is the
        !          2181:         * same inode number)
        !          2182:         */
        !          2183:        if (fvp == tvp)
        !          2184:                error = -1;
        !          2185: out:
        !          2186:        if (!error) {
        !          2187:                if (tvp) {
        !          2188:                        (void)uvm_vnp_uncache(tvp);
        !          2189:                }
        !          2190:                error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
        !          2191:                                   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
        !          2192:        } else {
        !          2193:                VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
        !          2194:                if (tdvp == tvp)
        !          2195:                        vrele(tdvp);
        !          2196:                else
        !          2197:                        vput(tdvp);
        !          2198:                if (tvp)
        !          2199:                        vput(tvp);
        !          2200:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
        !          2201:                vrele(fromnd.ni_dvp);
        !          2202:                vrele(fvp);
        !          2203:        }
        !          2204:        vrele(tond.ni_startdir);
        !          2205:        pool_put(&namei_pool, tond.ni_cnd.cn_pnbuf);
        !          2206: out1:
        !          2207:        if (fromnd.ni_startdir)
        !          2208:                vrele(fromnd.ni_startdir);
        !          2209:        pool_put(&namei_pool, fromnd.ni_cnd.cn_pnbuf);
        !          2210:        if (error == -1)
        !          2211:                return (0);
        !          2212:        return (error);
        !          2213: }
        !          2214:
        !          2215: /*
        !          2216:  * Make a directory file.
        !          2217:  */
        !          2218: /* ARGSUSED */
        !          2219: int
        !          2220: sys_mkdir(struct proc *p, void *v, register_t *retval)
        !          2221: {
        !          2222:        struct sys_mkdir_args /* {
        !          2223:                syscallarg(const char *) path;
        !          2224:                syscallarg(mode_t) mode;
        !          2225:        } */ *uap = v;
        !          2226:        struct vnode *vp;
        !          2227:        struct vattr vattr;
        !          2228:        int error;
        !          2229:        struct nameidata nd;
        !          2230:
        !          2231:        NDINIT(&nd, CREATE, LOCKPARENT | STRIPSLASHES,
        !          2232:            UIO_USERSPACE, SCARG(uap, path), p);
        !          2233:        if ((error = namei(&nd)) != 0)
        !          2234:                return (error);
        !          2235:        vp = nd.ni_vp;
        !          2236:        if (vp != NULL) {
        !          2237:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          2238:                if (nd.ni_dvp == vp)
        !          2239:                        vrele(nd.ni_dvp);
        !          2240:                else
        !          2241:                        vput(nd.ni_dvp);
        !          2242:                vrele(vp);
        !          2243:                return (EEXIST);
        !          2244:        }
        !          2245:        VATTR_NULL(&vattr);
        !          2246:        vattr.va_type = VDIR;
        !          2247:        vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
        !          2248:        error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
        !          2249:        if (!error)
        !          2250:                vput(nd.ni_vp);
        !          2251:        return (error);
        !          2252: }
        !          2253:
        !          2254: /*
        !          2255:  * Remove a directory file.
        !          2256:  */
        !          2257: /* ARGSUSED */
        !          2258: int
        !          2259: sys_rmdir(struct proc *p, void *v, register_t *retval)
        !          2260: {
        !          2261:        struct sys_rmdir_args /* {
        !          2262:                syscallarg(const char *) path;
        !          2263:        } */ *uap = v;
        !          2264:        struct vnode *vp;
        !          2265:        int error;
        !          2266:        struct nameidata nd;
        !          2267:
        !          2268:        NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
        !          2269:            SCARG(uap, path), p);
        !          2270:        if ((error = namei(&nd)) != 0)
        !          2271:                return (error);
        !          2272:        vp = nd.ni_vp;
        !          2273:        if (vp->v_type != VDIR) {
        !          2274:                error = ENOTDIR;
        !          2275:                goto out;
        !          2276:        }
        !          2277:        /*
        !          2278:         * No rmdir "." please.
        !          2279:         */
        !          2280:        if (nd.ni_dvp == vp) {
        !          2281:                error = EBUSY;
        !          2282:                goto out;
        !          2283:        }
        !          2284:        /*
        !          2285:         * The root of a mounted filesystem cannot be deleted.
        !          2286:         */
        !          2287:        if (vp->v_flag & VROOT)
        !          2288:                error = EBUSY;
        !          2289: out:
        !          2290:        if (!error) {
        !          2291:                error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
        !          2292:        } else {
        !          2293:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          2294:                if (nd.ni_dvp == vp)
        !          2295:                        vrele(nd.ni_dvp);
        !          2296:                else
        !          2297:                        vput(nd.ni_dvp);
        !          2298:                vput(vp);
        !          2299:        }
        !          2300:        return (error);
        !          2301: }
        !          2302:
        !          2303: /*
        !          2304:  * Read a block of directory entries in a file system independent format.
        !          2305:  */
        !          2306: int
        !          2307: sys_getdirentries(struct proc *p, void *v, register_t *retval)
        !          2308: {
        !          2309:        struct sys_getdirentries_args /* {
        !          2310:                syscallarg(int) fd;
        !          2311:                syscallarg(char *) buf;
        !          2312:                syscallarg(int) count;
        !          2313:                syscallarg(long *) basep;
        !          2314:        } */ *uap = v;
        !          2315:        struct vnode *vp;
        !          2316:        struct file *fp;
        !          2317:        struct uio auio;
        !          2318:        struct iovec aiov;
        !          2319:        long loff;
        !          2320:        int error, eofflag;
        !          2321:
        !          2322:        if (SCARG(uap, count) < 0)
        !          2323:                return EINVAL;
        !          2324:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
        !          2325:                return (error);
        !          2326:        if ((fp->f_flag & FREAD) == 0) {
        !          2327:                error = EBADF;
        !          2328:                goto bad;
        !          2329:        }
        !          2330:        vp = (struct vnode *)fp->f_data;
        !          2331:        if (vp->v_type != VDIR) {
        !          2332:                error = EINVAL;
        !          2333:                goto bad;
        !          2334:        }
        !          2335:        aiov.iov_base = SCARG(uap, buf);
        !          2336:        aiov.iov_len = SCARG(uap, count);
        !          2337:        auio.uio_iov = &aiov;
        !          2338:        auio.uio_iovcnt = 1;
        !          2339:        auio.uio_rw = UIO_READ;
        !          2340:        auio.uio_segflg = UIO_USERSPACE;
        !          2341:        auio.uio_procp = p;
        !          2342:        auio.uio_resid = SCARG(uap, count);
        !          2343:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          2344:        loff = auio.uio_offset = fp->f_offset;
        !          2345:        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 0, 0);
        !          2346:        fp->f_offset = auio.uio_offset;
        !          2347:        VOP_UNLOCK(vp, 0, p);
        !          2348:        if (error)
        !          2349:                goto bad;
        !          2350:        error = copyout(&loff, SCARG(uap, basep),
        !          2351:            sizeof(long));
        !          2352:        *retval = SCARG(uap, count) - auio.uio_resid;
        !          2353: bad:
        !          2354:        FRELE(fp);
        !          2355:        return (error);
        !          2356: }
        !          2357:
        !          2358: /*
        !          2359:  * Set the mode mask for creation of filesystem nodes.
        !          2360:  */
        !          2361: int
        !          2362: sys_umask(struct proc *p, void *v, register_t *retval)
        !          2363: {
        !          2364:        struct sys_umask_args /* {
        !          2365:                syscallarg(mode_t) newmask;
        !          2366:        } */ *uap = v;
        !          2367:        struct filedesc *fdp;
        !          2368:
        !          2369:        fdp = p->p_fd;
        !          2370:        *retval = fdp->fd_cmask;
        !          2371:        fdp->fd_cmask = SCARG(uap, newmask) & ACCESSPERMS;
        !          2372:        return (0);
        !          2373: }
        !          2374:
        !          2375: /*
        !          2376:  * Void all references to file by ripping underlying filesystem
        !          2377:  * away from vnode.
        !          2378:  */
        !          2379: /* ARGSUSED */
        !          2380: int
        !          2381: sys_revoke(struct proc *p, void *v, register_t *retval)
        !          2382: {
        !          2383:        struct sys_revoke_args /* {
        !          2384:                syscallarg(const char *) path;
        !          2385:        } */ *uap = v;
        !          2386:        struct vnode *vp;
        !          2387:        struct vattr vattr;
        !          2388:        int error;
        !          2389:        struct nameidata nd;
        !          2390:
        !          2391:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
        !          2392:        if ((error = namei(&nd)) != 0)
        !          2393:                return (error);
        !          2394:        vp = nd.ni_vp;
        !          2395:        if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
        !          2396:                goto out;
        !          2397:        if (p->p_ucred->cr_uid != vattr.va_uid &&
        !          2398:            (error = suser(p, 0)))
        !          2399:                goto out;
        !          2400:        if (vp->v_usecount > 1 || (vp->v_flag & (VALIASED)))
        !          2401:                VOP_REVOKE(vp, REVOKEALL);
        !          2402: out:
        !          2403:        vrele(vp);
        !          2404:        return (error);
        !          2405: }
        !          2406:
        !          2407: /*
        !          2408:  * Convert a user file descriptor to a kernel file entry.
        !          2409:  *
        !          2410:  * On return *fpp is FREF:ed.
        !          2411:  */
        !          2412: int
        !          2413: getvnode(struct filedesc *fdp, int fd, struct file **fpp)
        !          2414: {
        !          2415:        struct file *fp;
        !          2416:        struct vnode *vp;
        !          2417:
        !          2418:        if ((fp = fd_getfile(fdp, fd)) == NULL)
        !          2419:                return (EBADF);
        !          2420:
        !          2421:        if (fp->f_type != DTYPE_VNODE)
        !          2422:                return (EINVAL);
        !          2423:
        !          2424:        vp = (struct vnode *)fp->f_data;
        !          2425:        if (vp->v_type == VBAD)
        !          2426:                return (EBADF);
        !          2427:
        !          2428:        FREF(fp);
        !          2429:        *fpp = fp;
        !          2430:
        !          2431:        return (0);
        !          2432: }
        !          2433:
        !          2434: /*
        !          2435:  * Positional read system call.
        !          2436:  */
        !          2437: int
        !          2438: sys_pread(struct proc *p, void *v, register_t *retval)
        !          2439: {
        !          2440:        struct sys_pread_args /* {
        !          2441:                syscallarg(int) fd;
        !          2442:                syscallarg(void *) buf;
        !          2443:                syscallarg(size_t) nbyte;
        !          2444:                syscallarg(int) pad;
        !          2445:                syscallarg(off_t) offset;
        !          2446:        } */ *uap = v;
        !          2447:        struct filedesc *fdp = p->p_fd;
        !          2448:        struct file *fp;
        !          2449:        struct vnode *vp;
        !          2450:        off_t offset;
        !          2451:        int fd = SCARG(uap, fd);
        !          2452:
        !          2453:        if ((fp = fd_getfile(fdp, fd)) == NULL)
        !          2454:                return (EBADF);
        !          2455:        if ((fp->f_flag & FREAD) == 0)
        !          2456:                return (EBADF);
        !          2457:
        !          2458:        vp = (struct vnode *)fp->f_data;
        !          2459:        if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
        !          2460:                return (ESPIPE);
        !          2461:        }
        !          2462:
        !          2463:        offset = SCARG(uap, offset);
        !          2464:
        !          2465:        FREF(fp);
        !          2466:
        !          2467:        /* dofileread() will FRELE the descriptor for us */
        !          2468:        return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
        !          2469:            &offset, retval));
        !          2470: }
        !          2471:
        !          2472: /*
        !          2473:  * Positional scatter read system call.
        !          2474:  */
        !          2475: int
        !          2476: sys_preadv(struct proc *p, void *v, register_t *retval)
        !          2477: {
        !          2478:        struct sys_preadv_args /* {
        !          2479:                syscallarg(int) fd;
        !          2480:                syscallarg(const struct iovec *) iovp;
        !          2481:                syscallarg(int) iovcnt;
        !          2482:                syscallarg(int) pad;
        !          2483:                syscallarg(off_t) offset;
        !          2484:        } */ *uap = v;
        !          2485:        struct filedesc *fdp = p->p_fd;
        !          2486:        struct file *fp;
        !          2487:        struct vnode *vp;
        !          2488:        off_t offset;
        !          2489:        int fd = SCARG(uap, fd);
        !          2490:
        !          2491:        if ((fp = fd_getfile(fdp, fd)) == NULL)
        !          2492:                return (EBADF);
        !          2493:        if ((fp->f_flag & FREAD) == 0)
        !          2494:                return (EBADF);
        !          2495:
        !          2496:        vp = (struct vnode *)fp->f_data;
        !          2497:        if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
        !          2498:                return (ESPIPE);
        !          2499:        }
        !          2500:
        !          2501:        FREF(fp);
        !          2502:
        !          2503:        offset = SCARG(uap, offset);
        !          2504:
        !          2505:        /* dofilereadv() will FRELE the descriptor for us */
        !          2506:        return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
        !          2507:            &offset, retval));
        !          2508: }
        !          2509:
        !          2510: /*
        !          2511:  * Positional write system call.
        !          2512:  */
        !          2513: int
        !          2514: sys_pwrite(struct proc *p, void *v, register_t *retval)
        !          2515: {
        !          2516:        struct sys_pwrite_args /* {
        !          2517:                syscallarg(int) fd;
        !          2518:                syscallarg(const void *) buf;
        !          2519:                syscallarg(size_t) nbyte;
        !          2520:                syscallarg(int) pad;
        !          2521:                syscallarg(off_t) offset;
        !          2522:        } */ *uap = v;
        !          2523:        struct filedesc *fdp = p->p_fd;
        !          2524:        struct file *fp;
        !          2525:        struct vnode *vp;
        !          2526:        off_t offset;
        !          2527:        int fd = SCARG(uap, fd);
        !          2528:
        !          2529:        if ((fp = fd_getfile(fdp, fd)) == NULL)
        !          2530:                return (EBADF);
        !          2531:        if ((fp->f_flag & FWRITE) == 0)
        !          2532:                return (EBADF);
        !          2533:
        !          2534:        vp = (struct vnode *)fp->f_data;
        !          2535:        if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
        !          2536:                return (ESPIPE);
        !          2537:        }
        !          2538:
        !          2539:        FREF(fp);
        !          2540:
        !          2541:        offset = SCARG(uap, offset);
        !          2542:
        !          2543:        /* dofilewrite() will FRELE the descriptor for us */
        !          2544:        return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
        !          2545:            &offset, retval));
        !          2546: }
        !          2547:
        !          2548: /*
        !          2549:  * Positional gather write system call.
        !          2550:  */
        !          2551: int
        !          2552: sys_pwritev(struct proc *p, void *v, register_t *retval)
        !          2553: {
        !          2554:        struct sys_pwritev_args /* {
        !          2555:                syscallarg(int) fd;
        !          2556:                syscallarg(const struct iovec *) iovp;
        !          2557:                syscallarg(int) iovcnt;
        !          2558:                syscallarg(int) pad;
        !          2559:                syscallarg(off_t) offset;
        !          2560:        } */ *uap = v;
        !          2561:        struct filedesc *fdp = p->p_fd;
        !          2562:        struct file *fp;
        !          2563:        struct vnode *vp;
        !          2564:        off_t offset;
        !          2565:        int fd = SCARG(uap, fd);
        !          2566:
        !          2567:        if ((fp = fd_getfile(fdp, fd)) == NULL)
        !          2568:                return (EBADF);
        !          2569:        if ((fp->f_flag & FWRITE) == 0)
        !          2570:                return (EBADF);
        !          2571:
        !          2572:        vp = (struct vnode *)fp->f_data;
        !          2573:        if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
        !          2574:                return (ESPIPE);
        !          2575:        }
        !          2576:
        !          2577:        FREF(fp);
        !          2578:
        !          2579:        offset = SCARG(uap, offset);
        !          2580:
        !          2581:        /* dofilewritev() will FRELE the descriptor for us */
        !          2582:        return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
        !          2583:            &offset, retval));
        !          2584: }

CVSweb