Annotation of XNU/bsd/vfs/vfs_syscalls.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /* Copyright (c) 1995-1999 Apple Computer, Inc. All Rights Reserved */
        !            23: /*
        !            24:  * Copyright (c) 1989, 1993
        !            25:  *     The Regents of the University of California.  All rights reserved.
        !            26:  * (c) UNIX System Laboratories, Inc.
        !            27:  * All or some portions of this file are derived from material licensed
        !            28:  * to the University of California by American Telephone and Telegraph
        !            29:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
        !            30:  * the permission of UNIX System Laboratories, Inc.
        !            31:  *
        !            32:  * Redistribution and use in source and binary forms, with or without
        !            33:  * modification, are permitted provided that the following conditions
        !            34:  * are met:
        !            35:  * 1. Redistributions of source code must retain the above copyright
        !            36:  *    notice, this list of conditions and the following disclaimer.
        !            37:  * 2. Redistributions in binary form must reproduce the above copyright
        !            38:  *    notice, this list of conditions and the following disclaimer in the
        !            39:  *    documentation and/or other materials provided with the distribution.
        !            40:  * 3. All advertising materials mentioning features or use of this software
        !            41:  *    must display the following acknowledgement:
        !            42:  *     This product includes software developed by the University of
        !            43:  *     California, Berkeley and its contributors.
        !            44:  * 4. Neither the name of the University nor the names of its contributors
        !            45:  *    may be used to endorse or promote products derived from this software
        !            46:  *    without specific prior written permission.
        !            47:  *
        !            48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            58:  * SUCH DAMAGE.
        !            59:  *
        !            60:  *     @(#)vfs_syscalls.c      8.41 (Berkeley) 6/15/95
        !            61:  */
        !            62: 
        !            63: #include <mach_nbc.h>
        !            64: #include <sys/param.h>
        !            65: #include <sys/systm.h>
        !            66: #include <sys/namei.h>
        !            67: #include <sys/filedesc.h>
        !            68: #include <sys/kernel.h>
        !            69: #include <sys/file.h>
        !            70: #include <sys/stat.h>
        !            71: #include <sys/vnode.h>
        !            72: #include <sys/mount.h>
        !            73: #include <sys/proc.h>
        !            74: #include <sys/uio.h>
        !            75: #include <sys/malloc.h>
        !            76: #include <sys/dirent.h>
        !            77: #include <sys/attr.h>
        !            78: #include <sys/sysctl.h>
        !            79: #include <kern/mapfs.h>
        !            80: 
        !            81: struct lock__bsd__     exchangelock;
        !            82: 
        !            83: static int change_dir __P((struct nameidata *ndp, struct proc *p));
        !            84: static void checkdirs __P((struct vnode *olddp));
        !            85: 
        !            86: #ifdef NeXT
        !            87: unsigned int vfs_nummntops=0;  /* counts number of mount and unmount operations */
        !            88: #endif
        !            89: 
        !            90: /*
        !            91:  * Virtual File System System Calls
        !            92:  */
        !            93: 
        !            94: /*
        !            95:  * Mount a file system.
        !            96:  */
        !            97: struct mount_args {
        !            98:        char    *type;
        !            99:        char    *path;
        !           100:        int     flags;
        !           101:        caddr_t data;
        !           102: };
        !           103: /* ARGSUSED */
        !           104: int
        !           105: mount(p, uap, retval)
        !           106:        struct proc *p;
        !           107:        register struct mount_args *uap;
        !           108:        register_t *retval;
        !           109: {
        !           110:        struct vnode *vp;
        !           111:        struct mount *mp;
        !           112:        struct vfsconf *vfsp;
        !           113:        int error, flag;
        !           114:        struct vattr va;
        !           115:        u_long fstypenum;
        !           116:        struct nameidata nd;
        !           117:        char fstypename[MFSNAMELEN];
        !           118:        size_t dummy=0;
        !           119:        /*
        !           120:         * Get vnode to be covered
        !           121:         */
        !           122:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !           123:            uap->path, p);
        !           124:        if (error = namei(&nd))
        !           125:                return (error);
        !           126:        vp = nd.ni_vp;
        !           127:        
        !           128:        if ((vp->v_flag & VROOT) &&
        !           129:                (vp->v_mount->mnt_flag & MNT_ROOTFS)) uap->flags |= MNT_UPDATE;
        !           130:        
        !           131:        if (uap->flags & MNT_UPDATE) {
        !           132:                if ((vp->v_flag & VROOT) == 0) {
        !           133:                        vput(vp);
        !           134:                        return (EINVAL);
        !           135:                }
        !           136:                mp = vp->v_mount;
        !           137:                flag = mp->mnt_flag;
        !           138:                /*
        !           139:                 * We only allow the filesystem to be reloaded if it
        !           140:                 * is currently mounted read-only.
        !           141:                 */
        !           142:                if ((uap->flags & MNT_RELOAD) &&
        !           143:                    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
        !           144:                        vput(vp);
        !           145:                        return (EOPNOTSUPP);    /* Needs translation */
        !           146:                }
        !           147:                mp->mnt_flag |=
        !           148:                    uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
        !           149:                /*
        !           150:                 * Only root, or the user that did the original mount is
        !           151:                 * permitted to update it.
        !           152:                 */
        !           153:                if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
        !           154:                    (error = suser(p->p_ucred, &p->p_acflag))) {
        !           155:                        vput(vp);
        !           156:                        return (error);
        !           157:                }
        !           158:                /*
        !           159:                 * Do not allow NFS export by non-root users. FOr non-root
        !           160:                 * users, silently enforce MNT_NOSUID and MNT_NODEV, and
        !           161:                 * MNT_NOEXEC if mount point is already MNT_NOEXEC.
        !           162:                 */
        !           163:                if (p->p_ucred->cr_uid != 0) {
        !           164:                        if (uap->flags & MNT_EXPORTED) {
        !           165:                                vput(vp);
        !           166:                                return (EPERM);
        !           167:                        }
        !           168:                        uap->flags |= MNT_NOSUID | MNT_NODEV;
        !           169:                        if (flag & MNT_NOEXEC)
        !           170:                                uap->flags |= MNT_NOEXEC;
        !           171:                }
        !           172:                if (vfs_busy(mp, LK_NOWAIT, 0, p)) {
        !           173:                        vput(vp);
        !           174:                        return (EBUSY);
        !           175:                }
        !           176:                VOP_UNLOCK(vp, 0, p);
        !           177:                goto update;
        !           178:        }
        !           179:        /*
        !           180:         * If the user is not root, ensure that they own the directory
        !           181:         * onto which we are attempting to mount.
        !           182:         */
        !           183:        if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
        !           184:            (va.va_uid != p->p_ucred->cr_uid &&
        !           185:             (error = suser(p->p_ucred, &p->p_acflag)))) {
        !           186:                vput(vp);
        !           187:                return (error);
        !           188:        }
        !           189:        /*
        !           190:         * Do not allow NFS export by non-root users. FOr non-root
        !           191:         * users, silently enforce MNT_NOSUID and MNT_NODEV, and
        !           192:         * MNT_NOEXEC if mount point is already MNT_NOEXEC.
        !           193:         */
        !           194:        if (p->p_ucred->cr_uid != 0) {
        !           195:                if (uap->flags & MNT_EXPORTED) {
        !           196:                        vput(vp);
        !           197:                        return (EPERM);
        !           198:                }
        !           199:                uap->flags |= MNT_NOSUID | MNT_NODEV;
        !           200:                if (vp->v_mount->mnt_flag & MNT_NOEXEC)
        !           201:                        uap->flags |= MNT_NOEXEC;
        !           202:        }
        !           203:        if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) {
        !           204:                vput(vp);
        !           205:                return (error);
        !           206:        }
        !           207:        if (vp->v_type != VDIR) {
        !           208:                vput(vp);
        !           209:                return (ENOTDIR);
        !           210:        }
        !           211: #if COMPAT_43
        !           212:        /*
        !           213:         * Historically filesystem types were identified by number. If we
        !           214:         * get an integer for the filesystem type instead of a string, we
        !           215:         * check to see if it matches one of the historic filesystem types.
        !           216:         */
        !           217:        fstypenum = (u_long)uap->type;
        !           218:        if (fstypenum < maxvfsconf) {
        !           219:                for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
        !           220:                        if (vfsp->vfc_typenum == fstypenum)
        !           221:                                break;
        !           222:                if (vfsp == NULL) {
        !           223:                        vput(vp);
        !           224:                        return (ENODEV);
        !           225:                }
        !           226:                strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
        !           227:        } else
        !           228: #endif /* COMPAT_43 */
        !           229:        if (error = copyinstr(uap->type, fstypename, MFSNAMELEN, &dummy)) {
        !           230:                vput(vp);
        !           231:                return (error);
        !           232:        }
        !           233:        for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
        !           234:                if (!strcmp(vfsp->vfc_name, fstypename))
        !           235:                        break;
        !           236:        if (vfsp == NULL) {
        !           237:                vput(vp);
        !           238:                return (ENODEV);
        !           239:        }
        !           240:        if (vp->v_mountedhere != NULL) {
        !           241:                vput(vp);
        !           242:                return (EBUSY);
        !           243:        }
        !           244: 
        !           245:        /*
        !           246:         * Allocate and initialize the filesystem.
        !           247:         */
        !           248:        mp = (struct mount *)_MALLOC_ZONE((u_long)sizeof(struct mount),
        !           249:                M_MOUNT, M_WAITOK);
        !           250:        bzero((char *)mp, (u_long)sizeof(struct mount));
        !           251:        lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
        !           252:        (void)vfs_busy(mp, LK_NOWAIT, 0, p);
        !           253:        mp->mnt_op = vfsp->vfc_vfsops;
        !           254:        mp->mnt_vfc = vfsp;
        !           255:        vfsp->vfc_refcount++;
        !           256:        mp->mnt_stat.f_type = vfsp->vfc_typenum;
        !           257:        mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
        !           258:        strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
        !           259:        vp->v_mountedhere = mp;
        !           260:        mp->mnt_vnodecovered = vp;
        !           261:        mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
        !           262: update:
        !           263:        /*
        !           264:         * Set the mount level flags.
        !           265:         */
        !           266:        if (uap->flags & MNT_RDONLY)
        !           267:                mp->mnt_flag |= MNT_RDONLY;
        !           268:        else if (mp->mnt_flag & MNT_RDONLY)
        !           269:                mp->mnt_flag |= MNT_WANTRDWR;
        !           270:        mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
        !           271:            MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
        !           272:        mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC |
        !           273:            MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
        !           274:        /*
        !           275:         * Mount the filesystem.
        !           276:         */
        !           277:        error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p);
        !           278:        if (mp->mnt_flag & MNT_UPDATE) {
        !           279:                vrele(vp);
        !           280:                if (mp->mnt_flag & MNT_WANTRDWR)
        !           281:                        mp->mnt_flag &= ~MNT_RDONLY;
        !           282:                mp->mnt_flag &=~
        !           283:                    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
        !           284:                if (error)
        !           285:                        mp->mnt_flag = flag;
        !           286:                vfs_unbusy(mp, p);
        !           287:                return (error);
        !           288:        }
        !           289:        /*
        !           290:         * Put the new filesystem on the mount list after root.
        !           291:         */
        !           292:        cache_purge(vp);
        !           293:        if (!error) {
        !           294:                simple_lock(&mountlist_slock);
        !           295:                CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
        !           296:                simple_unlock(&mountlist_slock);
        !           297:                checkdirs(vp);
        !           298:                VOP_UNLOCK(vp, 0, p);
        !           299:                vfs_unbusy(mp, p);
        !           300:                if (error = VFS_START(mp, 0, p))
        !           301:                        vrele(vp);
        !           302: #ifdef NeXT
        !           303:                /* increment the operations count */
        !           304:                if (!error) vfs_nummntops++;
        !           305: #endif
        !           306:        } else {
        !           307:                mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
        !           308:                mp->mnt_vfc->vfc_refcount--;
        !           309:                vfs_unbusy(mp, p);
        !           310:                _FREE_ZONE((caddr_t)mp, sizeof (struct mount), M_MOUNT);
        !           311:                vput(vp);
        !           312:        }
        !           313:        return (error);
        !           314: }
        !           315: 
        !           316: /*
        !           317:  * Scan all active processes to see if any of them have a current
        !           318:  * or root directory onto which the new filesystem has just been
        !           319:  * mounted. If so, replace them with the new mount point.
        !           320:  */
        !           321: static void
        !           322: checkdirs(olddp)
        !           323:        struct vnode *olddp;
        !           324: {
        !           325:        struct filedesc *fdp;
        !           326:        struct vnode *newdp;
        !           327:        struct proc *p;
        !           328: 
        !           329:        if (olddp->v_usecount == 1)
        !           330:                return;
        !           331:        if (VFS_ROOT(olddp->v_mountedhere, &newdp))
        !           332:                panic("mount: lost mount");
        !           333:        for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
        !           334:                fdp = p->p_fd;
        !           335:                if (fdp->fd_cdir == olddp) {
        !           336:                        vrele(fdp->fd_cdir);
        !           337:                        VREF(newdp);
        !           338:                        fdp->fd_cdir = newdp;
        !           339:                }
        !           340:                if (fdp->fd_rdir == olddp) {
        !           341:                        vrele(fdp->fd_rdir);
        !           342:                        VREF(newdp);
        !           343:                        fdp->fd_rdir = newdp;
        !           344:                }
        !           345:        }
        !           346:        if (rootvnode == olddp) {
        !           347:                vrele(rootvnode);
        !           348:                VREF(newdp);
        !           349:                rootvnode = newdp;
        !           350:        }
        !           351:        vput(newdp);
        !           352: }
        !           353: 
        !           354: /*
        !           355:  * Unmount a file system.
        !           356:  *
        !           357:  * Note: unmount takes a path to the vnode mounted on as argument,
        !           358:  * not special file (as before).
        !           359:  */
        !           360: struct unmount_args {
        !           361:        char    *path;
        !           362:        int     flags;
        !           363: };
        !           364: /* ARGSUSED */
        !           365: int
        !           366: unmount(p, uap, retval)
        !           367:        struct proc *p;
        !           368:        register struct unmount_args *uap;
        !           369:        register_t *retval;
        !           370: {
        !           371:        register struct vnode *vp;
        !           372:        struct mount *mp;
        !           373:        int error;
        !           374:        struct nameidata nd;
        !           375: 
        !           376:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !           377:            uap->path, p);
        !           378:        if (error = namei(&nd))
        !           379:                return (error);
        !           380:        vp = nd.ni_vp;
        !           381:        mp = vp->v_mount;
        !           382: 
        !           383:        /*
        !           384:         * Only root, or the user that did the original mount is
        !           385:         * permitted to unmount this filesystem.
        !           386:         */
        !           387:        if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
        !           388:            (error = suser(p->p_ucred, &p->p_acflag))) {
        !           389:                vput(vp);
        !           390:                return (error);
        !           391:        }
        !           392: 
        !           393:        /*
        !           394:         * Don't allow unmounting the root file system.
        !           395:         */
        !           396:        if (mp->mnt_flag & MNT_ROOTFS) {
        !           397:                vput(vp);
        !           398:                return (EINVAL);
        !           399:        }
        !           400: 
        !           401:        /*
        !           402:         * Must be the root of the filesystem
        !           403:         */
        !           404:        if ((vp->v_flag & VROOT) == 0) {
        !           405:                vput(vp);
        !           406:                return (EINVAL);
        !           407:        }
        !           408:        vput(vp);
        !           409:        return (dounmount(mp, uap->flags, p));
        !           410: }
        !           411: 
        !           412: /*
        !           413:  * Do the actual file system unmount.
        !           414:  */
        !           415: int
        !           416: dounmount(mp, flags, p)
        !           417:        register struct mount *mp;
        !           418:        int flags;
        !           419:        struct proc *p;
        !           420: {
        !           421:        struct vnode *coveredvp;
        !           422:        int error;
        !           423: 
        !           424:        simple_lock(&mountlist_slock);
        !           425:        mp->mnt_flag |= MNT_UNMOUNT;
        !           426:        lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p);
        !           427:        mp->mnt_flag &=~ MNT_ASYNC;
        !           428: #if MACH_NBC
        !           429:        mapfs_cache_clear();
        !           430: #endif
        !           431:        vnode_pager_umount(mp); /* release cached vnodes */
        !           432: #if MACH_NBC
        !           433:        vm_object_cache_clear();        /* clear the object cache */
        !           434: #endif /* MACH_NBC */
        !           435:        cache_purgevfs(mp);     /* remove cache entries for this file sys */
        !           436:        if (((mp->mnt_flag & MNT_RDONLY) ||
        !           437:             (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
        !           438:            (flags & MNT_FORCE))
        !           439:                error = VFS_UNMOUNT(mp, flags, p);
        !           440:        simple_lock(&mountlist_slock);
        !           441:        if (error) {
        !           442:                mp->mnt_flag &= ~MNT_UNMOUNT;
        !           443:                lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
        !           444:                    &mountlist_slock, p);
        !           445:                goto out;
        !           446:        }
        !           447: #ifdef NeXT
        !           448:        /* increment the operations count */
        !           449:        if (!error) vfs_nummntops++;
        !           450: #endif
        !           451:        CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
        !           452:        if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
        !           453:                coveredvp->v_mountedhere = (struct mount *)0;
        !           454:                simple_unlock(&mountlist_slock);
        !           455:                vrele(coveredvp);
        !           456:                simple_lock(&mountlist_slock);
        !           457:        }
        !           458:        mp->mnt_vfc->vfc_refcount--;
        !           459:        if (mp->mnt_vnodelist.lh_first != NULL)
        !           460:                panic("unmount: dangling vnode");
        !           461:        lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
        !           462: out:
        !           463:        if (mp->mnt_flag & MNT_MWAIT)
        !           464:                wakeup((caddr_t)mp);
        !           465:        if (!error)
        !           466:                _FREE_ZONE((caddr_t)mp, sizeof (struct mount), M_MOUNT);
        !           467:        return (error);
        !           468: }
        !           469: 
        !           470: /*
        !           471:  * Sync each mounted filesystem.
        !           472:  */
        !           473: #if DIAGNOSTIC
        !           474: int syncprt = 0;
        !           475: struct ctldebug debug0 = { "syncprt", &syncprt };
        !           476: #endif
        !           477: 
        !           478: struct sync_args {
        !           479:        int     dummy;
        !           480: };
        !           481: /* ARGSUSED */
        !           482: int
        !           483: sync(p, uap, retval)
        !           484:        struct proc *p;
        !           485:        struct sync_args *uap;
        !           486:        register_t *retval;
        !           487: {
        !           488:        register struct mount *mp, *nmp;
        !           489:        int asyncflag;
        !           490: 
        !           491: #if    MACH_NBC
        !           492: #if DIAGNOSTIC
        !           493:        {
        !           494:                int error = 0;
        !           495:                error = mapfs_sync();
        !           496:                if (error)
        !           497:                        panic("sync: mapfs_sync %d", error);
        !           498:        }
        !           499: #else
        !           500:        (void)mapfs_sync(); /* Ignore errors! */
        !           501: #endif /* DIAGNOSTIC */
        !           502: #endif /* MACH_NBC */
        !           503: 
        !           504:        simple_lock(&mountlist_slock);
        !           505:        for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
        !           506:                if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
        !           507:                        nmp = mp->mnt_list.cqe_next;
        !           508:                        continue;
        !           509:                }
        !           510:                if ((mp->mnt_flag & MNT_RDONLY) == 0) {
        !           511:                        asyncflag = mp->mnt_flag & MNT_ASYNC;
        !           512:                        mp->mnt_flag &= ~MNT_ASYNC;
        !           513:                        VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
        !           514:                        if (asyncflag)
        !           515:                                mp->mnt_flag |= MNT_ASYNC;
        !           516:                }
        !           517:                simple_lock(&mountlist_slock);
        !           518:                nmp = mp->mnt_list.cqe_next;
        !           519:                vfs_unbusy(mp, p);
        !           520:        }
        !           521:        simple_unlock(&mountlist_slock);
        !           522: #if DIAGNOSTIC
        !           523:        if (syncprt)
        !           524:                vfs_bufstats();
        !           525: #endif /* DIAGNOSTIC */
        !           526:        return (0);
        !           527: }
        !           528: 
        !           529: /*
        !           530:  * Change filesystem quotas.
        !           531:  */
        !           532: struct quotactl_args {
        !           533:        char *path;
        !           534:        int cmd;
        !           535:        int uid;
        !           536:        caddr_t arg;
        !           537: };
        !           538: /* ARGSUSED */
        !           539: int
        !           540: quotactl(p, uap, retval)
        !           541:        struct proc *p;
        !           542:        register struct quotactl_args *uap;
        !           543:        register_t *retval;
        !           544: {
        !           545:        register struct mount *mp;
        !           546:        int error;
        !           547:        struct nameidata nd;
        !           548: 
        !           549:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
        !           550:        if (error = namei(&nd))
        !           551:                return (error);
        !           552:        mp = nd.ni_vp->v_mount;
        !           553:        vrele(nd.ni_vp);
        !           554:        return (VFS_QUOTACTL(mp, uap->cmd, uap->uid,
        !           555:            uap->arg, p));
        !           556: }
        !           557: 
        !           558: /*
        !           559:  * Get filesystem statistics.
        !           560:  */
        !           561: struct statfs_args {
        !           562:        char *path;
        !           563:        struct statfs *buf;
        !           564: };
        !           565: /* ARGSUSED */
        !           566: int
        !           567: statfs(p, uap, retval)
        !           568:        struct proc *p;
        !           569:        register struct statfs_args *uap;
        !           570:        register_t *retval;
        !           571: {
        !           572:        register struct mount *mp;
        !           573:        register struct statfs *sp;
        !           574:        int error;
        !           575:        struct nameidata nd;
        !           576: 
        !           577:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
        !           578:        if (error = namei(&nd))
        !           579:                return (error);
        !           580:        mp = nd.ni_vp->v_mount;
        !           581:        sp = &mp->mnt_stat;
        !           582:        vrele(nd.ni_vp);
        !           583:        if (error = VFS_STATFS(mp, sp, p))
        !           584:                return (error);
        !           585:        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
        !           586:        return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
        !           587: }
        !           588: 
        !           589: /*
        !           590:  * Get filesystem statistics.
        !           591:  */
        !           592: struct fstatfs_args {
        !           593:        int fd;
        !           594:        struct statfs *buf;
        !           595: };
        !           596: /* ARGSUSED */
        !           597: int
        !           598: fstatfs(p, uap, retval)
        !           599:        struct proc *p;
        !           600:        register struct fstatfs_args *uap;
        !           601:        register_t *retval;
        !           602: {
        !           603:        struct file *fp;
        !           604:        struct mount *mp;
        !           605:        register struct statfs *sp;
        !           606:        int error;
        !           607: 
        !           608:        if (error = getvnode(p, uap->fd, &fp))
        !           609:                return (error);
        !           610:        mp = ((struct vnode *)fp->f_data)->v_mount;
        !           611:        if (!mp)
        !           612:                return (EBADF);
        !           613:        sp = &mp->mnt_stat;
        !           614:        if (error = VFS_STATFS(mp, sp, p))
        !           615:                return (error);
        !           616:        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
        !           617:        return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
        !           618: }
        !           619: 
        !           620: /*
        !           621:  * Get statistics on all filesystems.
        !           622:  */
        !           623: struct getfsstat_args {
        !           624:        struct statfs *buf;
        !           625:        long bufsize;
        !           626:        int flags;
        !           627: };
        !           628: int
        !           629: getfsstat(p, uap, retval)
        !           630:        struct proc *p;
        !           631:        register struct getfsstat_args *uap;
        !           632:        register_t *retval;
        !           633: {
        !           634:        register struct mount *mp, *nmp;
        !           635:        register struct statfs *sp;
        !           636:        caddr_t sfsp;
        !           637:        long count, maxcount, error;
        !           638: 
        !           639:        maxcount = uap->bufsize / sizeof(struct statfs);
        !           640:        sfsp = (caddr_t)uap->buf;
        !           641:        count = 0;
        !           642:        simple_lock(&mountlist_slock);
        !           643:        for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
        !           644:                if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
        !           645:                        nmp = mp->mnt_list.cqe_next;
        !           646:                        continue;
        !           647:                }
        !           648:                if (sfsp && count < maxcount) {
        !           649:                        sp = &mp->mnt_stat;
        !           650:                        /*
        !           651:                         * If MNT_NOWAIT is specified, do not refresh the
        !           652:                         * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
        !           653:                         */
        !           654:                        if (((uap->flags & MNT_NOWAIT) == 0 ||
        !           655:                            (uap->flags & MNT_WAIT)) &&
        !           656:                            (error = VFS_STATFS(mp, sp, p))) {
        !           657:                                simple_lock(&mountlist_slock);
        !           658:                                nmp = mp->mnt_list.cqe_next;
        !           659:                                vfs_unbusy(mp, p);
        !           660:                                continue;
        !           661:                        }
        !           662:                        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
        !           663:                        if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
        !           664:                                return (error);
        !           665:                        sfsp += sizeof(*sp);
        !           666:                }
        !           667:                count++;
        !           668:                simple_lock(&mountlist_slock);
        !           669:                nmp = mp->mnt_list.cqe_next;
        !           670:                vfs_unbusy(mp, p);
        !           671:        }
        !           672:        simple_unlock(&mountlist_slock);
        !           673:        if (sfsp && count > maxcount)
        !           674:                *retval = maxcount;
        !           675:        else
        !           676:                *retval = count;
        !           677:        return (0);
        !           678: }
        !           679: 
        !           680: /*
        !           681:  * Change current working directory to a given file descriptor.
        !           682:  */
        !           683: struct fchdir_args {
        !           684:        int     fd;
        !           685: };
        !           686: /* ARGSUSED */
        !           687: int
        !           688: fchdir(p, uap, retval)
        !           689:        struct proc *p;
        !           690:        struct fchdir_args *uap;
        !           691:        register_t *retval;
        !           692: {
        !           693:        register struct filedesc *fdp = p->p_fd;
        !           694:        struct vnode *vp, *tdp;
        !           695:        struct mount *mp;
        !           696:        struct file *fp;
        !           697:        int error;
        !           698: 
        !           699:        if (error = getvnode(p, uap->fd, &fp))
        !           700:                return (error);
        !           701:        vp = (struct vnode *)fp->f_data;
        !           702:        VREF(vp);
        !           703:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !           704:        if (vp->v_type != VDIR)
        !           705:                error = ENOTDIR;
        !           706:        else
        !           707:                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
        !           708:        while (!error && (mp = vp->v_mountedhere) != NULL) {
        !           709:                if (vfs_busy(mp, 0, 0, p))
        !           710:                        continue;
        !           711:                error = VFS_ROOT(mp, &tdp);
        !           712:                vfs_unbusy(mp, p);
        !           713:                if (error)
        !           714:                        break;
        !           715:                vput(vp);
        !           716:                vp = tdp;
        !           717:        }
        !           718:        if (error) {
        !           719:                vput(vp);
        !           720:                return (error);
        !           721:        }
        !           722:        VOP_UNLOCK(vp, 0, p);
        !           723:        vrele(fdp->fd_cdir);
        !           724:        fdp->fd_cdir = vp;
        !           725:        return (0);
        !           726: }
        !           727: 
        !           728: /*
        !           729:  * Change current working directory (``.'').
        !           730:  */
        !           731: struct chdir_args {
        !           732:        char    *path;
        !           733: };
        !           734: /* ARGSUSED */
        !           735: int
        !           736: chdir(p, uap, retval)
        !           737:        struct proc *p;
        !           738:        struct chdir_args *uap;
        !           739:        register_t *retval;
        !           740: {
        !           741:        register struct filedesc *fdp = p->p_fd;
        !           742:        int error;
        !           743:        struct nameidata nd;
        !           744: 
        !           745:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !           746:            uap->path, p);
        !           747:        if (error = change_dir(&nd, p))
        !           748:                return (error);
        !           749:        vrele(fdp->fd_cdir);
        !           750:        fdp->fd_cdir = nd.ni_vp;
        !           751:        return (0);
        !           752: }
        !           753: 
        !           754: /*
        !           755:  * Change notion of root (``/'') directory.
        !           756:  */
        !           757: struct chroot_args {
        !           758:        char    *path;
        !           759: };
        !           760: /* ARGSUSED */
        !           761: int
        !           762: chroot(p, uap, retval)
        !           763:        struct proc *p;
        !           764:        struct chroot_args *uap;
        !           765:        register_t *retval;
        !           766: {
        !           767:        register struct filedesc *fdp = p->p_fd;
        !           768:        int error;
        !           769:        struct nameidata nd;
        !           770: 
        !           771:        if (error = suser(p->p_ucred, &p->p_acflag))
        !           772:                return (error);
        !           773:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !           774:            uap->path, p);
        !           775:        if (error = change_dir(&nd, p))
        !           776:                return (error);
        !           777:        if (fdp->fd_rdir != NULL)
        !           778:                vrele(fdp->fd_rdir);
        !           779:        fdp->fd_rdir = nd.ni_vp;
        !           780:        return (0);
        !           781: }
        !           782: 
        !           783: /*
        !           784:  * Common routine for chroot and chdir.
        !           785:  */
        !           786: static int
        !           787: change_dir(ndp, p)
        !           788:        register struct nameidata *ndp;
        !           789:        struct proc *p;
        !           790: {
        !           791:        struct vnode *vp;
        !           792:        int error;
        !           793: 
        !           794:        if (error = namei(ndp))
        !           795:                return (error);
        !           796:        vp = ndp->ni_vp;
        !           797:        if (vp->v_type != VDIR)
        !           798:                error = ENOTDIR;
        !           799:        else
        !           800:                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
        !           801:        if (error)
        !           802:                vput(vp);
        !           803:        else
        !           804:                VOP_UNLOCK(vp, 0, p);
        !           805:        return (error);
        !           806: }
        !           807: 
        !           808: /*
        !           809:  * Check permissions, allocate an open file structure,
        !           810:  * and call the device open routine if any.
        !           811:  */
        !           812: struct open_args {
        !           813:        char    *path;
        !           814:        int     flags;
        !           815:        int     mode;
        !           816: };
        !           817: int
        !           818: open(p, uap, retval)
        !           819:        struct proc *p;
        !           820:        register struct open_args *uap;
        !           821:        register_t *retval;
        !           822: {
        !           823:        register struct filedesc *fdp = p->p_fd;
        !           824:        register struct file *fp;
        !           825:        register struct vnode *vp;
        !           826:        int flags, cmode;
        !           827:        struct file *nfp;
        !           828:        int type, indx, error;
        !           829:        struct flock lf;
        !           830:        struct nameidata nd;
        !           831:        extern struct fileops vnops;
        !           832: 
        !           833:        /* CERT advisory patch applied from FreeBSD */
        !           834:        /* Refer to Radar#2262895 A. Ramesh */
        !           835:        flags = FFLAGS(uap->flags);
        !           836:        if ((flags & (FREAD | FWRITE))==0)
        !           837:                return(EINVAL);
        !           838:        if (error = falloc(p, &nfp, &indx))
        !           839:                return (error);
        !           840:        fp = nfp;
        !           841:        cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
        !           842:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
        !           843:        p->p_dupfd = -indx - 1;                 /* XXX check for fdopen */
        !           844:        if (error = vn_open(&nd, flags, cmode)) {
        !           845:                ffree(fp);
        !           846:                if ((error == ENODEV || error == ENXIO) &&
        !           847:                    p->p_dupfd >= 0 &&                  /* XXX from fdopen */
        !           848:                    (error =
        !           849:                        dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
        !           850:                        *retval = indx;
        !           851:                        return (0);
        !           852:                }
        !           853:                if (error == ERESTART)
        !           854:                        error = EINTR;
        !           855:                fdrelse(p, indx);
        !           856:                return (error);
        !           857:        }
        !           858:        p->p_dupfd = 0;
        !           859:        vp = nd.ni_vp;
        !           860:        fp->f_flag = flags & FMASK;
        !           861:        fp->f_type = DTYPE_VNODE;
        !           862:        fp->f_ops = &vnops;
        !           863:        fp->f_data = (caddr_t)vp;
        !           864:        if (flags & (O_EXLOCK | O_SHLOCK)) {
        !           865:                lf.l_whence = SEEK_SET;
        !           866:                lf.l_start = 0;
        !           867:                lf.l_len = 0;
        !           868:                if (flags & O_EXLOCK)
        !           869:                        lf.l_type = F_WRLCK;
        !           870:                else
        !           871:                        lf.l_type = F_RDLCK;
        !           872:                type = F_FLOCK;
        !           873:                if ((flags & FNONBLOCK) == 0)
        !           874:                        type |= F_WAIT;
        !           875:                VOP_UNLOCK(vp, 0, p);
        !           876:                if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
        !           877:                        (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
        !           878:                        ffree(fp);
        !           879:                        fdrelse(p, indx);
        !           880:                        return (error);
        !           881:                }
        !           882:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !           883:                fp->f_flag |= FHASLOCK;
        !           884:        }
        !           885:        VOP_UNLOCK(vp, 0, p);
        !           886:        *fdflags(p, indx) &= ~UF_RESERVED;
        !           887:        *retval = indx;
        !           888:        return (0);
        !           889: }
        !           890: 
        !           891: #if COMPAT_43
        !           892: /*
        !           893:  * Create a file.
        !           894:  */
        !           895: struct ocreat_args {
        !           896:        char    *path;
        !           897:        int     mode;
        !           898: };
        !           899: int
        !           900: ocreat(p, uap, retval)
        !           901:        struct proc *p;
        !           902:        register struct ocreat_args *uap;
        !           903:        register_t *retval;
        !           904: {
        !           905:        struct open_args nuap;
        !           906: 
        !           907:        nuap.path = uap->path;
        !           908:        nuap.mode = uap->mode;
        !           909:        nuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
        !           910:        return (open(p, &nuap, retval));
        !           911: }
        !           912: #endif /* COMPAT_43 */
        !           913: 
        !           914: /*
        !           915:  * Create a special file.
        !           916:  */
        !           917: struct mknod_args {
        !           918:        char    *path;
        !           919:        int     mode;
        !           920:        int     dev;
        !           921: };
        !           922: /* ARGSUSED */
        !           923: int
        !           924: mknod(p, uap, retval)
        !           925:        struct proc *p;
        !           926:        register struct mknod_args *uap;
        !           927:        register_t *retval;
        !           928: {
        !           929:        register struct vnode *vp;
        !           930:        struct vattr vattr;
        !           931:        int error;
        !           932:        int whiteout;
        !           933:        struct nameidata nd;
        !           934: 
        !           935:        if (error = suser(p->p_ucred, &p->p_acflag))
        !           936:                return (error);
        !           937:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
        !           938:        if (error = namei(&nd))
        !           939:                return (error);
        !           940:        vp = nd.ni_vp;
        !           941:        if (vp != NULL)
        !           942:                error = EEXIST;
        !           943:        else {
        !           944:                VATTR_NULL(&vattr);
        !           945:                vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
        !           946:                vattr.va_rdev = uap->dev;
        !           947:                whiteout = 0;
        !           948: 
        !           949:                switch (uap->mode & S_IFMT) {
        !           950:                case S_IFMT:    /* used by badsect to flag bad sectors */
        !           951:                        vattr.va_type = VBAD;
        !           952:                        break;
        !           953:                case S_IFCHR:
        !           954:                        vattr.va_type = VCHR;
        !           955:                        break;
        !           956:                case S_IFBLK:
        !           957:                        vattr.va_type = VBLK;
        !           958:                        break;
        !           959:                case S_IFWHT:
        !           960:                        whiteout = 1;
        !           961:                        break;
        !           962:                default:
        !           963:                        error = EINVAL;
        !           964:                        break;
        !           965:                }
        !           966:        }
        !           967:        if (!error) {
        !           968:                VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
        !           969:                if (whiteout) {
        !           970:                        error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
        !           971:                        if (error)
        !           972:                                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !           973:                        vput(nd.ni_dvp);
        !           974:                } else {
        !           975:                        error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
        !           976:                                                &nd.ni_cnd, &vattr);
        !           977:                }
        !           978:        } else {
        !           979:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !           980:                if (nd.ni_dvp == vp)
        !           981:                        vrele(nd.ni_dvp);
        !           982:                else
        !           983:                        vput(nd.ni_dvp);
        !           984:                if (vp)
        !           985:                        vrele(vp);
        !           986:        }
        !           987:        return (error);
        !           988: }
        !           989: 
        !           990: /*
        !           991:  * Create a named pipe.
        !           992:  */
        !           993: struct mkfifo_args {
        !           994:        char    *path;
        !           995:        int     mode;
        !           996: };
        !           997: /* ARGSUSED */
        !           998: int
        !           999: mkfifo(p, uap, retval)
        !          1000:        struct proc *p;
        !          1001:        register struct mkfifo_args *uap;
        !          1002:        register_t *retval;
        !          1003: {
        !          1004:        struct vattr vattr;
        !          1005:        int error;
        !          1006:        struct nameidata nd;
        !          1007: 
        !          1008: #if !FIFO 
        !          1009:        return (EOPNOTSUPP);
        !          1010: #else
        !          1011:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
        !          1012:        if (error = namei(&nd))
        !          1013:                return (error);
        !          1014:        if (nd.ni_vp != NULL) {
        !          1015:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          1016:                if (nd.ni_dvp == nd.ni_vp)
        !          1017:                        vrele(nd.ni_dvp);
        !          1018:                else
        !          1019:                        vput(nd.ni_dvp);
        !          1020:                vrele(nd.ni_vp);
        !          1021:                return (EEXIST);
        !          1022:        }
        !          1023:        VATTR_NULL(&vattr);
        !          1024:        vattr.va_type = VFIFO;
        !          1025:        vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
        !          1026:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
        !          1027:        return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
        !          1028: #endif /* FIFO */
        !          1029: }
        !          1030: 
        !          1031: /*
        !          1032:  * Make a hard file link.
        !          1033:  */
        !          1034: struct link_args {
        !          1035:        char    *path;
        !          1036:        char    *link;
        !          1037: };
        !          1038: /* ARGSUSED */
        !          1039: int
        !          1040: link(p, uap, retval)
        !          1041:        struct proc *p;
        !          1042:        register struct link_args *uap;
        !          1043:        register_t *retval;
        !          1044: {
        !          1045:        register struct vnode *vp;
        !          1046:        struct nameidata nd;
        !          1047:        int error;
        !          1048: 
        !          1049:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
        !          1050:        if (error = namei(&nd))
        !          1051:                return (error);
        !          1052:        vp = nd.ni_vp;
        !          1053:        if (vp->v_type == VDIR)
        !          1054:                error = EPERM;   /* POSIX */
        !          1055:        else {
        !          1056:                nd.ni_cnd.cn_nameiop = CREATE;
        !          1057:                nd.ni_cnd.cn_flags = LOCKPARENT;
        !          1058:                nd.ni_dirp = uap->link;
        !          1059:                if ((error = namei(&nd)) == 0) {
        !          1060:                        if (nd.ni_vp != NULL)
        !          1061:                                error = EEXIST;
        !          1062:                        if (!error) {
        !          1063:                                VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
        !          1064:                                    LEASE_WRITE);
        !          1065:                                VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          1066:                                error = VOP_LINK(vp, nd.ni_dvp, &nd.ni_cnd);
        !          1067:                        } else {
        !          1068:                                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          1069:                                if (nd.ni_dvp == nd.ni_vp)
        !          1070:                                        vrele(nd.ni_dvp);
        !          1071:                                else
        !          1072:                                        vput(nd.ni_dvp);
        !          1073:                                if (nd.ni_vp)
        !          1074:                                        vrele(nd.ni_vp);
        !          1075:                        }
        !          1076:                }
        !          1077:        }
        !          1078:        vrele(vp);
        !          1079:        return (error);
        !          1080: }
        !          1081: 
        !          1082: /*
        !          1083:  * Make a symbolic link.
        !          1084:  */
        !          1085: struct symlink_args {
        !          1086:        char    *path;
        !          1087:        char    *link;
        !          1088: };
        !          1089: /* ARGSUSED */
        !          1090: int
        !          1091: symlink(p, uap, retval)
        !          1092:        struct proc *p;
        !          1093:        register struct symlink_args *uap;
        !          1094:        register_t *retval;
        !          1095: {
        !          1096:        struct vattr vattr;
        !          1097:        char *path;
        !          1098:        int error;
        !          1099:        struct nameidata nd;
        !          1100:        size_t dummy=0;
        !          1101:        MALLOC_ZONE(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
        !          1102:        if (error = copyinstr(uap->path, path, MAXPATHLEN, &dummy))
        !          1103:                goto out;
        !          1104:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
        !          1105:        if (error = namei(&nd))
        !          1106:                goto out;
        !          1107:        if (nd.ni_vp) {
        !          1108:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          1109:                if (nd.ni_dvp == nd.ni_vp)
        !          1110:                        vrele(nd.ni_dvp);
        !          1111:                else
        !          1112:                        vput(nd.ni_dvp);
        !          1113:                vrele(nd.ni_vp);
        !          1114:                error = EEXIST;
        !          1115:                goto out;
        !          1116:        }
        !          1117:        VATTR_NULL(&vattr);
        !          1118:        vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
        !          1119:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
        !          1120:        error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
        !          1121: out:
        !          1122:        FREE_ZONE(path, MAXPATHLEN, M_NAMEI);
        !          1123:        return (error);
        !          1124: }
        !          1125: 
        !          1126: /*
        !          1127:  * Delete a whiteout from the filesystem.
        !          1128:  */
        !          1129: struct undelete_args {
        !          1130:        char    *path;
        !          1131: };
        !          1132: /* ARGSUSED */
        !          1133: int
        !          1134: undelete(p, uap, retval)
        !          1135:        struct proc *p;
        !          1136:        register struct undelete_args *uap;
        !          1137:        register_t *retval;
        !          1138: {
        !          1139:        int error;
        !          1140:        struct nameidata nd;
        !          1141: 
        !          1142:        NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
        !          1143:            uap->path, p);
        !          1144:        error = namei(&nd);
        !          1145:        if (error)
        !          1146:                return (error);
        !          1147: 
        !          1148:        if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
        !          1149:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          1150:                if (nd.ni_dvp == nd.ni_vp)
        !          1151:                        vrele(nd.ni_dvp);
        !          1152:                else
        !          1153:                        vput(nd.ni_dvp);
        !          1154:                if (nd.ni_vp)
        !          1155:                        vrele(nd.ni_vp);
        !          1156:                return (EEXIST);
        !          1157:        }
        !          1158: 
        !          1159:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
        !          1160:        if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE))
        !          1161:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          1162:        vput(nd.ni_dvp);
        !          1163:        return (error);
        !          1164: }
        !          1165: 
        !          1166: /*
        !          1167:  * Delete a name from the filesystem.
        !          1168:  */
        !          1169: struct unlink_args {
        !          1170:        char    *path;
        !          1171: };
        !          1172: /* ARGSUSED */
        !          1173: static int
        !          1174: _unlink(p, uap, retval, nodelbusy)
        !          1175:        struct proc *p;
        !          1176:        struct unlink_args *uap;
        !          1177:        register_t *retval;
        !          1178:        int nodelbusy;
        !          1179: {
        !          1180:        register struct vnode *vp;
        !          1181:        int error;
        !          1182:        struct nameidata nd;
        !          1183: 
        !          1184:        NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
        !          1185:        /* with hfs semantics, busy files cannot be deleted */
        !          1186:        if (nodelbusy)
        !          1187:                nd.ni_cnd.cn_flags |= NODELETEBUSY;
        !          1188:        if (error = namei(&nd))
        !          1189:                return (error);
        !          1190:        vp = nd.ni_vp;
        !          1191:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          1192:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1193: 
        !          1194:        if (vp->v_type == VDIR)
        !          1195:                error = EPERM;  /* POSIX */
        !          1196:        else {
        !          1197:                /*
        !          1198:                 * The root of a mounted filesystem cannot be deleted.
        !          1199:                 *
        !          1200:                 * XXX: can this only be a VDIR case?
        !          1201:                 */
        !          1202:                if (vp->v_flag & VROOT)
        !          1203:                        error = EBUSY;
        !          1204:                else {
        !          1205:                        (void) vnode_uncache(vp);
        !          1206:                        if (ISMAPPEDFILE(vp)) {
        !          1207:                                ubc_unlink(vp);
        !          1208:                        }
        !          1209:                }
        !          1210:        }
        !          1211: 
        !          1212:        if (!error) {
        !          1213:                VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
        !          1214:                error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
        !          1215:        } else {
        !          1216:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          1217:                if (nd.ni_dvp == vp)
        !          1218:                        vrele(nd.ni_dvp);
        !          1219:                else
        !          1220:                        vput(nd.ni_dvp);
        !          1221:                if (vp != NULLVP)
        !          1222:                        vput(vp);
        !          1223:        }
        !          1224:        return (error);
        !          1225: }
        !          1226: 
        !          1227: /*
        !          1228:  * Delete a name from the filesystem using POSIX semantics.
        !          1229:  */
        !          1230: int
        !          1231: unlink(p, uap, retval)
        !          1232:        struct proc *p;
        !          1233:        struct unlink_args *uap;
        !          1234:        register_t *retval;
        !          1235: {
        !          1236:        return _unlink(p, uap, retval, 0);
        !          1237: }
        !          1238: 
        !          1239: /*
        !          1240:  * Delete a name from the filesystem using HFS semantics.
        !          1241:  */
        !          1242: int
        !          1243: delete(p, uap, retval)
        !          1244:        struct proc *p;
        !          1245:        struct unlink_args *uap;
        !          1246:        register_t *retval;
        !          1247: {
        !          1248:        return _unlink(p, uap, retval, 1);
        !          1249: }
        !          1250: 
        !          1251: /*
        !          1252:  * Reposition read/write file offset.
        !          1253:  */
        !          1254: struct lseek_args {
        !          1255:        int     fd;
        !          1256: #ifdef DOUBLE_ALIGN_PARAMS
        !          1257:        int pad;
        !          1258: #endif
        !          1259:        off_t   offset;
        !          1260:        int     whence;
        !          1261: };
        !          1262: int
        !          1263: lseek(p, uap, retval)
        !          1264:        struct proc *p;
        !          1265:        register struct lseek_args *uap;
        !          1266:        register_t *retval;
        !          1267: {
        !          1268:        struct ucred *cred = p->p_ucred;
        !          1269:        struct file *fp;
        !          1270:        struct vattr vattr;
        !          1271:        int error;
        !          1272: 
        !          1273:        if (error = fdgetf(p, uap->fd, &fp))
        !          1274:                return (error);
        !          1275:        if (fp->f_type != DTYPE_VNODE)
        !          1276:                return (ESPIPE);
        !          1277:        switch (uap->whence) {
        !          1278:        case L_INCR:
        !          1279:                fp->f_offset += uap->offset;
        !          1280:                break;
        !          1281:        case L_XTND:
        !          1282:                if (error =
        !          1283:                    VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p))
        !          1284:                        return (error);
        !          1285:                fp->f_offset = uap->offset + vattr.va_size;
        !          1286:                break;
        !          1287:        case L_SET:
        !          1288:                fp->f_offset = uap->offset;
        !          1289:                break;
        !          1290:        default:
        !          1291:                return (EINVAL);
        !          1292:        }
        !          1293:        *(off_t *)retval = fp->f_offset;
        !          1294:        return (0);
        !          1295: }
        !          1296: 
        !          1297: #if COMPAT_43
        !          1298: /*
        !          1299:  * Reposition read/write file offset.
        !          1300:  */
        !          1301: struct olseek_args {
        !          1302:        int     fd;
        !          1303:        long    offset;
        !          1304:        int     whence;
        !          1305: };
        !          1306: int
        !          1307: olseek(p, uap, retval)
        !          1308:        struct proc *p;
        !          1309:        register struct olseek_args *uap;
        !          1310:        register_t *retval;
        !          1311: {
        !          1312:        struct lseek_args /* {
        !          1313:                syscallarg(int) fd;
        !          1314: #ifdef DOUBLE_ALIGN_PARAMS
        !          1315:         syscallarg(int) pad;
        !          1316: #endif
        !          1317:                syscallarg(off_t) offset;
        !          1318:                syscallarg(int) whence;
        !          1319:        } */ nuap;
        !          1320:        off_t qret;
        !          1321:        int error;
        !          1322: 
        !          1323:        nuap.fd = uap->fd;
        !          1324:        nuap.offset = uap->offset;
        !          1325:        nuap.whence = uap->whence;
        !          1326:        error = lseek(p, &nuap, &qret);
        !          1327:        *(long *)retval = qret;
        !          1328:        return (error);
        !          1329: }
        !          1330: #endif /* COMPAT_43 */
        !          1331: 
        !          1332: /*
        !          1333:  * Check access permissions.
        !          1334:  */
        !          1335: struct access_args {
        !          1336:        char    *path;
        !          1337:        int     flags;
        !          1338: };
        !          1339: int
        !          1340: access(p, uap, retval)
        !          1341:        struct proc *p;
        !          1342:        register struct access_args *uap;
        !          1343:        register_t *retval;
        !          1344: {
        !          1345:        register struct ucred *cred = p->p_ucred;
        !          1346:        register struct vnode *vp;
        !          1347:        int error, flags, t_gid, t_uid;
        !          1348:        struct nameidata nd;
        !          1349: 
        !          1350:        t_uid = cred->cr_uid;
        !          1351:        t_gid = cred->cr_groups[0];
        !          1352:        cred->cr_uid = p->p_cred->p_ruid;
        !          1353:        cred->cr_groups[0] = p->p_cred->p_rgid;
        !          1354:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !          1355:            uap->path, p);
        !          1356:        if (error = namei(&nd))
        !          1357:                goto out1;
        !          1358:        vp = nd.ni_vp;
        !          1359: 
        !          1360:        /* Flags == 0 means only check for existence. */
        !          1361:        if (uap->flags) {
        !          1362:                flags = 0;
        !          1363:                if (uap->flags & R_OK)
        !          1364:                        flags |= VREAD;
        !          1365:                if (uap->flags & W_OK)
        !          1366:                        flags |= VWRITE;
        !          1367:                if (uap->flags & X_OK)
        !          1368:                        flags |= VEXEC;
        !          1369:                if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
        !          1370:                        error = VOP_ACCESS(vp, flags, cred, p);
        !          1371:        }
        !          1372:        vput(vp);
        !          1373: out1:
        !          1374:        cred->cr_uid = t_uid;
        !          1375:        cred->cr_groups[0] = t_gid;
        !          1376:        return (error);
        !          1377: }
        !          1378: 
        !          1379: #if COMPAT_43
        !          1380: /*
        !          1381:  * Get file status; this version follows links.
        !          1382:  */
        !          1383: struct ostat_args {
        !          1384:        char    *path;
        !          1385:        struct ostat *ub;
        !          1386: };
        !          1387: /* ARGSUSED */
        !          1388: int
        !          1389: ostat(p, uap, retval)
        !          1390:        struct proc *p;
        !          1391:        register struct ostat_args *uap;
        !          1392:        register_t *retval;
        !          1393: {
        !          1394:        struct stat sb;
        !          1395:        struct ostat osb;
        !          1396:        int error;
        !          1397:        struct nameidata nd;
        !          1398: 
        !          1399:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !          1400:            uap->path, p);
        !          1401:        if (error = namei(&nd))
        !          1402:                return (error);
        !          1403:        error = vn_stat(nd.ni_vp, &sb, p);
        !          1404:        vput(nd.ni_vp);
        !          1405:        if (error)
        !          1406:                return (error);
        !          1407:        cvtstat(&sb, &osb);
        !          1408:        error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
        !          1409:        return (error);
        !          1410: }
        !          1411: 
        !          1412: /*
        !          1413:  * Get file status; this version does not follow links.
        !          1414:  */
        !          1415: struct olstat_args {
        !          1416:        char    *path;
        !          1417:        struct ostat *ub;
        !          1418: };
        !          1419: /* ARGSUSED */
        !          1420: int
        !          1421: olstat(p, uap, retval)
        !          1422:        struct proc *p;
        !          1423:        register struct olstat_args *uap;
        !          1424:        register_t *retval;
        !          1425: {
        !          1426:        struct vnode *vp, *dvp;
        !          1427:        struct stat sb, sb1;
        !          1428:        struct ostat osb;
        !          1429:        int error;
        !          1430:        struct nameidata nd;
        !          1431: 
        !          1432:        NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
        !          1433:            uap->path, p);
        !          1434:        if (error = namei(&nd))
        !          1435:                return (error);
        !          1436:        /*
        !          1437:         * For symbolic links, always return the attributes of its
        !          1438:         * containing directory, except for mode, size, and links.
        !          1439:         */
        !          1440:        vp = nd.ni_vp;
        !          1441:        dvp = nd.ni_dvp;
        !          1442:        if (vp->v_type != VLNK) {
        !          1443:                if (dvp == vp)
        !          1444:                        vrele(dvp);
        !          1445:                else
        !          1446:                        vput(dvp);
        !          1447:                error = vn_stat(vp, &sb, p);
        !          1448:                vput(vp);
        !          1449:                if (error)
        !          1450:                        return (error);
        !          1451:        } else {
        !          1452:                error = vn_stat(dvp, &sb, p);
        !          1453:                vput(dvp);
        !          1454:                if (error) {
        !          1455:                        vput(vp);
        !          1456:                        return (error);
        !          1457:                }
        !          1458:                error = vn_stat(vp, &sb1, p);
        !          1459:                vput(vp);
        !          1460:                if (error)
        !          1461:                        return (error);
        !          1462:                sb.st_mode &= ~S_IFDIR;
        !          1463:                sb.st_mode |= S_IFLNK;
        !          1464:                sb.st_nlink = sb1.st_nlink;
        !          1465:                sb.st_size = sb1.st_size;
        !          1466:                sb.st_blocks = sb1.st_blocks;
        !          1467:        }
        !          1468:        cvtstat(&sb, &osb);
        !          1469:        error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
        !          1470:        return (error);
        !          1471: }
        !          1472: 
        !          1473: /*
        !          1474:  * Convert from an old to a new stat structure.
        !          1475:  */
        !          1476: void
        !          1477: cvtstat(st, ost)
        !          1478:        struct stat *st;
        !          1479:        struct ostat *ost;
        !          1480: {
        !          1481: 
        !          1482:        ost->st_dev = st->st_dev;
        !          1483:        ost->st_ino = st->st_ino;
        !          1484:        ost->st_mode = st->st_mode;
        !          1485:        ost->st_nlink = st->st_nlink;
        !          1486:        ost->st_uid = st->st_uid;
        !          1487:        ost->st_gid = st->st_gid;
        !          1488:        ost->st_rdev = st->st_rdev;
        !          1489:        if (st->st_size < (quad_t)1 << 32)
        !          1490:                ost->st_size = st->st_size;
        !          1491:        else
        !          1492:                ost->st_size = -2;
        !          1493:        ost->st_atime = st->st_atime;
        !          1494:        ost->st_mtime = st->st_mtime;
        !          1495:        ost->st_ctime = st->st_ctime;
        !          1496:        ost->st_blksize = st->st_blksize;
        !          1497:        ost->st_blocks = st->st_blocks;
        !          1498:        ost->st_flags = st->st_flags;
        !          1499:        ost->st_gen = st->st_gen;
        !          1500: }
        !          1501: #endif /* COMPAT_43 */
        !          1502: 
        !          1503: /*
        !          1504:  * Get file status; this version follows links.
        !          1505:  */
        !          1506: struct stat_args {
        !          1507:        char    *path;
        !          1508:        struct stat *ub;
        !          1509: };
        !          1510: /* ARGSUSED */
        !          1511: int
        !          1512: stat(p, uap, retval)
        !          1513:        struct proc *p;
        !          1514:        register struct stat_args *uap;
        !          1515:        register_t *retval;
        !          1516: {
        !          1517:        struct stat sb;
        !          1518:        int error;
        !          1519:        struct nameidata nd;
        !          1520: 
        !          1521:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !          1522:            uap->path, p);
        !          1523:        if (error = namei(&nd))
        !          1524:                return (error);
        !          1525:        error = vn_stat(nd.ni_vp, &sb, p);
        !          1526:        vput(nd.ni_vp);
        !          1527:        if (error)
        !          1528:                return (error);
        !          1529:        error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
        !          1530:        return (error);
        !          1531: }
        !          1532: 
        !          1533: /*
        !          1534:  * Get file status; this version does not follow links.
        !          1535:  */
        !          1536: struct lstat_args {
        !          1537:        char    *path;
        !          1538:        struct stat *ub;
        !          1539: };
        !          1540: /* ARGSUSED */
        !          1541: int
        !          1542: lstat(p, uap, retval)
        !          1543:        struct proc *p;
        !          1544:        register struct lstat_args *uap;
        !          1545:        register_t *retval;
        !          1546: {
        !          1547:        int error;
        !          1548:        struct vnode *vp, *dvp;
        !          1549:        struct stat sb, sb1;
        !          1550:        struct nameidata nd;
        !          1551: 
        !          1552:        NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
        !          1553:            uap->path, p);
        !          1554:        if (error = namei(&nd))
        !          1555:                return (error);
        !          1556:        /*
        !          1557:         * For symbolic links, always return the attributes of its containing
        !          1558:         * directory, except for mode, size, inode number, and links.
        !          1559:         */
        !          1560:        vp = nd.ni_vp;
        !          1561:        dvp = nd.ni_dvp;
        !          1562:        if ((vp->v_type != VLNK) || ((vp->v_type == VLNK) && (vp->v_tag == VT_NFS))) {
        !          1563:                if (dvp == vp)
        !          1564:                        vrele(dvp);
        !          1565:                else
        !          1566:                        vput(dvp);
        !          1567:                error = vn_stat(vp, &sb, p);
        !          1568:                vput(vp);
        !          1569:                if (error)
        !          1570:                        return (error);
        !          1571:                if (vp->v_type == VLNK)
        !          1572:                sb.st_mode |= S_IFLNK;
        !          1573:        } else {
        !          1574:                error = vn_stat(dvp, &sb, p);
        !          1575:                vput(dvp);
        !          1576:                if (error) {
        !          1577:                        vput(vp);
        !          1578:                        return (error);
        !          1579:                }
        !          1580:                error = vn_stat(vp, &sb1, p);
        !          1581:                vput(vp);
        !          1582:                if (error)
        !          1583:                        return (error);
        !          1584:                sb.st_mode &= ~S_IFDIR;
        !          1585:                sb.st_mode |= S_IFLNK;
        !          1586:                sb.st_nlink = sb1.st_nlink;
        !          1587:                sb.st_size = sb1.st_size;
        !          1588:                sb.st_blocks = sb1.st_blocks;
        !          1589:                sb.st_ino = sb1.st_ino;
        !          1590:        }
        !          1591:        error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
        !          1592:        return (error);
        !          1593: }
        !          1594: 
        !          1595: /*
        !          1596:  * Get configurable pathname variables.
        !          1597:  */
        !          1598: struct pathconf_args {
        !          1599:        char    *path;
        !          1600:        int     name;
        !          1601: };
        !          1602: /* ARGSUSED */
        !          1603: int
        !          1604: pathconf(p, uap, retval)
        !          1605:        struct proc *p;
        !          1606:        register struct pathconf_args *uap;
        !          1607:        register_t *retval;
        !          1608: {
        !          1609:        int error;
        !          1610:        struct nameidata nd;
        !          1611: 
        !          1612:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !          1613:            uap->path, p);
        !          1614:        if (error = namei(&nd))
        !          1615:                return (error);
        !          1616:        error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
        !          1617:        vput(nd.ni_vp);
        !          1618:        return (error);
        !          1619: }
        !          1620: 
        !          1621: /*
        !          1622:  * Return target name of a symbolic link.
        !          1623:  */
        !          1624: struct readlink_args {
        !          1625:        char    *path;
        !          1626:        char    *buf;
        !          1627:        int     count;
        !          1628: };
        !          1629: /* ARGSUSED */
        !          1630: int
        !          1631: readlink(p, uap, retval)
        !          1632:        struct proc *p;
        !          1633:        register struct readlink_args *uap;
        !          1634:        register_t *retval;
        !          1635: {
        !          1636:        register struct vnode *vp;
        !          1637:        struct iovec aiov;
        !          1638:        struct uio auio;
        !          1639:        int error;
        !          1640:        struct nameidata nd;
        !          1641: 
        !          1642:        NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
        !          1643:            uap->path, p);
        !          1644:        if (error = namei(&nd))
        !          1645:                return (error);
        !          1646:        vp = nd.ni_vp;
        !          1647:        if (vp->v_type != VLNK)
        !          1648:                error = EINVAL;
        !          1649:        else {
        !          1650:                aiov.iov_base = uap->buf;
        !          1651:                aiov.iov_len = uap->count;
        !          1652:                auio.uio_iov = &aiov;
        !          1653:                auio.uio_iovcnt = 1;
        !          1654:                auio.uio_offset = 0;
        !          1655:                auio.uio_rw = UIO_READ;
        !          1656:                auio.uio_segflg = UIO_USERSPACE;
        !          1657:                auio.uio_procp = p;
        !          1658:                auio.uio_resid = uap->count;
        !          1659:                error = VOP_READLINK(vp, &auio, p->p_ucred);
        !          1660:        }
        !          1661:        vput(vp);
        !          1662:        *retval = uap->count - auio.uio_resid;
        !          1663:        return (error);
        !          1664: }
        !          1665: 
        !          1666: /*
        !          1667:  * Change flags of a file given a path name.
        !          1668:  */
        !          1669: struct chflags_args {
        !          1670:        char    *path;
        !          1671:        int     flags;
        !          1672: };
        !          1673: /* ARGSUSED */
        !          1674: int
        !          1675: chflags(p, uap, retval)
        !          1676:        struct proc *p;
        !          1677:        register struct chflags_args *uap;
        !          1678:        register_t *retval;
        !          1679: {
        !          1680:        register struct vnode *vp;
        !          1681:        struct vattr vattr;
        !          1682:        int error;
        !          1683:        struct nameidata nd;
        !          1684: 
        !          1685:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
        !          1686:        if (error = namei(&nd))
        !          1687:                return (error);
        !          1688:        vp = nd.ni_vp;
        !          1689:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          1690:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1691:        VATTR_NULL(&vattr);
        !          1692:        vattr.va_flags = uap->flags;
        !          1693:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1694:        vput(vp);
        !          1695:        return (error);
        !          1696: }
        !          1697: 
        !          1698: /*
        !          1699:  * Change flags of a file given a file descriptor.
        !          1700:  */
        !          1701: struct fchflags_args {
        !          1702:        int     fd;
        !          1703:        int     flags;
        !          1704: };
        !          1705: /* ARGSUSED */
        !          1706: int
        !          1707: fchflags(p, uap, retval)
        !          1708:        struct proc *p;
        !          1709:        register struct fchflags_args *uap;
        !          1710:        register_t *retval;
        !          1711: {
        !          1712:        struct vattr vattr;
        !          1713:        struct vnode *vp;
        !          1714:        struct file *fp;
        !          1715:        int error;
        !          1716: 
        !          1717:        if (error = getvnode(p, uap->fd, &fp))
        !          1718:                return (error);
        !          1719:        vp = (struct vnode *)fp->f_data;
        !          1720:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          1721:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1722:        VATTR_NULL(&vattr);
        !          1723:        vattr.va_flags = uap->flags;
        !          1724:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1725:        VOP_UNLOCK(vp, 0, p);
        !          1726:        return (error);
        !          1727: }
        !          1728: 
        !          1729: /*
        !          1730:  * Change mode of a file given path name.
        !          1731:  */
        !          1732: struct chmod_args {
        !          1733:        char    *path;
        !          1734:        int     mode;
        !          1735: };
        !          1736: /* ARGSUSED */
        !          1737: int
        !          1738: chmod(p, uap, retval)
        !          1739:        struct proc *p;
        !          1740:        register struct chmod_args *uap;
        !          1741:        register_t *retval;
        !          1742: {
        !          1743:        register struct vnode *vp;
        !          1744:        struct vattr vattr;
        !          1745:        int error;
        !          1746:        struct nameidata nd;
        !          1747: 
        !          1748:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
        !          1749:        if (error = namei(&nd))
        !          1750:                return (error);
        !          1751:        vp = nd.ni_vp;
        !          1752:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          1753:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1754:        VATTR_NULL(&vattr);
        !          1755:        vattr.va_mode = uap->mode & ALLPERMS;
        !          1756:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1757:        vput(vp);
        !          1758:        return (error);
        !          1759: }
        !          1760: 
        !          1761: /*
        !          1762:  * Change mode of a file given a file descriptor.
        !          1763:  */
        !          1764: struct fchmod_args {
        !          1765:        int     fd;
        !          1766:        int     mode;
        !          1767: };
        !          1768: /* ARGSUSED */
        !          1769: int
        !          1770: fchmod(p, uap, retval)
        !          1771:        struct proc *p;
        !          1772:        register struct fchmod_args *uap;
        !          1773:        register_t *retval;
        !          1774: {
        !          1775:        struct vattr vattr;
        !          1776:        struct vnode *vp;
        !          1777:        struct file *fp;
        !          1778:        int error;
        !          1779: 
        !          1780:        if (error = getvnode(p, uap->fd, &fp))
        !          1781:                return (error);
        !          1782:        vp = (struct vnode *)fp->f_data;
        !          1783:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          1784:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1785:        VATTR_NULL(&vattr);
        !          1786:        vattr.va_mode = uap->mode & ALLPERMS;
        !          1787:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1788:        VOP_UNLOCK(vp, 0, p);
        !          1789:        return (error);
        !          1790: }
        !          1791: 
        !          1792: /*
        !          1793:  * Set ownership given a path name.
        !          1794:  */
        !          1795: struct chown_args {
        !          1796:        char    *path;
        !          1797:        int     uid;
        !          1798:        int     gid;
        !          1799: };
        !          1800: /* ARGSUSED */
        !          1801: int
        !          1802: chown(p, uap, retval)
        !          1803:        struct proc *p;
        !          1804:        register struct chown_args *uap;
        !          1805:        register_t *retval;
        !          1806: {
        !          1807:        register struct vnode *vp;
        !          1808:        struct vattr vattr;
        !          1809:        int error;
        !          1810:        struct nameidata nd;
        !          1811: 
        !          1812:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
        !          1813:        if (error = namei(&nd))
        !          1814:                return (error);
        !          1815:        vp = nd.ni_vp;
        !          1816:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          1817:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1818:        VATTR_NULL(&vattr);
        !          1819:        vattr.va_uid = uap->uid;
        !          1820:        vattr.va_gid = uap->gid;
        !          1821:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1822:        vput(vp);
        !          1823:        return (error);
        !          1824: }
        !          1825: 
        !          1826: /*
        !          1827:  * Set ownership given a file descriptor.
        !          1828:  */
        !          1829: struct fchown_args {
        !          1830:        int     fd;
        !          1831:        int     uid;
        !          1832:        int     gid;
        !          1833: };
        !          1834: /* ARGSUSED */
        !          1835: int
        !          1836: fchown(p, uap, retval)
        !          1837:        struct proc *p;
        !          1838:        register struct fchown_args *uap;
        !          1839:        register_t *retval;
        !          1840: {
        !          1841:        struct vattr vattr;
        !          1842:        struct vnode *vp;
        !          1843:        struct file *fp;
        !          1844:        int error;
        !          1845: 
        !          1846:        if (error = getvnode(p, uap->fd, &fp))
        !          1847:                return (error);
        !          1848:        vp = (struct vnode *)fp->f_data;
        !          1849:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          1850:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1851:        VATTR_NULL(&vattr);
        !          1852:        vattr.va_uid = uap->uid;
        !          1853:        vattr.va_gid = uap->gid;
        !          1854:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1855:        VOP_UNLOCK(vp, 0, p);
        !          1856:        return (error);
        !          1857: }
        !          1858: 
        !          1859: /*
        !          1860:  * Set the access and modification times of a file.
        !          1861:  */
        !          1862: struct utimes_args {
        !          1863:        char    *path;
        !          1864:        struct  timeval *tptr;
        !          1865: };
        !          1866: /* ARGSUSED */
        !          1867: int
        !          1868: utimes(p, uap, retval)
        !          1869:        struct proc *p;
        !          1870:        register struct utimes_args *uap;
        !          1871:        register_t *retval;
        !          1872: {
        !          1873:        register struct vnode *vp;
        !          1874:        struct timeval tv[2];
        !          1875:        struct vattr vattr;
        !          1876:        int error;
        !          1877:        struct nameidata nd;
        !          1878: 
        !          1879:        VATTR_NULL(&vattr);
        !          1880:        if (uap->tptr == NULL) {
        !          1881:                microtime(&tv[0]);
        !          1882:                tv[1] = tv[0];
        !          1883:                vattr.va_vaflags |= VA_UTIMES_NULL;
        !          1884:        } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv,
        !          1885:            sizeof (tv)))
        !          1886:                return (error);
        !          1887:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
        !          1888:        if (error = namei(&nd))
        !          1889:                return (error);
        !          1890:        vp = nd.ni_vp;
        !          1891:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          1892:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1893:        vattr.va_atime.tv_sec = tv[0].tv_sec;
        !          1894:        vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
        !          1895:        vattr.va_mtime.tv_sec = tv[1].tv_sec;
        !          1896:        vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
        !          1897:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1898:        vput(vp);
        !          1899:        return (error);
        !          1900: }
        !          1901: 
        !          1902: /*
        !          1903:  * Truncate a file given its path name.
        !          1904:  */
        !          1905: struct truncate_args {
        !          1906:        char    *path;
        !          1907: #ifdef DOUBLE_ALIGN_PARAMS
        !          1908:        int     pad;
        !          1909: #endif
        !          1910:        off_t   length;
        !          1911: };
        !          1912: /* ARGSUSED */
        !          1913: int
        !          1914: truncate(p, uap, retval)
        !          1915:        struct proc *p;
        !          1916:        register struct truncate_args *uap;
        !          1917:        register_t *retval;
        !          1918: {
        !          1919:        register struct vnode *vp;
        !          1920:        struct vattr vattr;
        !          1921:        int error;
        !          1922:        struct nameidata nd;
        !          1923: 
        !          1924:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
        !          1925:        if (error = namei(&nd))
        !          1926:                return (error);
        !          1927:        vp = nd.ni_vp;
        !          1928:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          1929:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1930:        if (vp->v_type == VDIR)
        !          1931:                error = EISDIR;
        !          1932:        else if ((error = vn_writechk(vp)) == 0 &&
        !          1933:            (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
        !          1934:                VATTR_NULL(&vattr);
        !          1935:                vattr.va_size = uap->length;
        !          1936:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
        !          1937:        }
        !          1938:        vput(vp);
        !          1939:        return (error);
        !          1940: }
        !          1941: 
        !          1942: /*
        !          1943:  * Truncate a file given a file descriptor.
        !          1944:  */
        !          1945: struct ftruncate_args {
        !          1946:        int     fd;
        !          1947: #ifdef DOUBLE_ALIGN_PARAMS
        !          1948:        int     pad;
        !          1949: #endif
        !          1950:        off_t   length;
        !          1951: };
        !          1952: /* ARGSUSED */
        !          1953: int
        !          1954: ftruncate(p, uap, retval)
        !          1955:        struct proc *p;
        !          1956:        register struct ftruncate_args *uap;
        !          1957:        register_t *retval;
        !          1958: {
        !          1959:        struct vattr vattr;
        !          1960:        struct vnode *vp;
        !          1961:        struct file *fp;
        !          1962:        int error;
        !          1963: 
        !          1964:        if (error = fdgetf(p, uap->fd, &fp))
        !          1965:                return (error);
        !          1966: 
        !          1967:        if (fp->f_type == DTYPE_PSXSHM) {
        !          1968:                return(pshm_truncate(p, fp, uap->fd, uap->length, retval));
        !          1969:        }
        !          1970:        if (fp->f_type != DTYPE_VNODE) 
        !          1971:                return (EINVAL);
        !          1972: 
        !          1973:        
        !          1974:        if ((fp->f_flag & FWRITE) == 0)
        !          1975:                return (EINVAL);
        !          1976:        vp = (struct vnode *)fp->f_data;
        !          1977:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          1978:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          1979:        if (vp->v_type == VDIR)
        !          1980:                error = EISDIR;
        !          1981:        else if ((error = vn_writechk(vp)) == 0) {
        !          1982:                VATTR_NULL(&vattr);
        !          1983:                vattr.va_size = uap->length;
        !          1984:                error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
        !          1985:        }
        !          1986:        VOP_UNLOCK(vp, 0, p);
        !          1987:        return (error);
        !          1988: }
        !          1989: 
        !          1990: #if COMPAT_43
        !          1991: /*
        !          1992:  * Truncate a file given its path name.
        !          1993:  */
        !          1994: struct otruncate_args {
        !          1995:        char    *path;
        !          1996:        long    length;
        !          1997: };
        !          1998: /* ARGSUSED */
        !          1999: int
        !          2000: otruncate(p, uap, retval)
        !          2001:        struct proc *p;
        !          2002:        register struct otruncate_args *uap;
        !          2003:        register_t *retval;
        !          2004: {
        !          2005:        struct truncate_args /* {
        !          2006:                syscallarg(char *) path;
        !          2007: #ifdef DOUBLE_ALIGN_PARAMS
        !          2008:                syscallarg(int) pad;
        !          2009: #endif
        !          2010:                syscallarg(off_t) length;
        !          2011:        } */ nuap;
        !          2012: 
        !          2013:        nuap.path = uap->path;
        !          2014:        nuap.length = uap->length;
        !          2015:        return (truncate(p, &nuap, retval));
        !          2016: }
        !          2017: 
        !          2018: /*
        !          2019:  * Truncate a file given a file descriptor.
        !          2020:  */
        !          2021: struct oftruncate_args {
        !          2022:        int     fd;
        !          2023:        long    length;
        !          2024: };
        !          2025: /* ARGSUSED */
        !          2026: int
        !          2027: oftruncate(p, uap, retval)
        !          2028:        struct proc *p;
        !          2029:        register struct oftruncate_args *uap;
        !          2030:        register_t *retval;
        !          2031: {
        !          2032:        struct ftruncate_args /* {
        !          2033:                syscallarg(int) fd;
        !          2034: #ifdef DOUBLE_ALIGN_PARAMS
        !          2035:                syscallarg(int) pad;
        !          2036: #endif
        !          2037:                syscallarg(off_t) length;
        !          2038:        } */ nuap;
        !          2039: 
        !          2040:        nuap.fd = uap->fd;
        !          2041:        nuap.length = uap->length;
        !          2042:        return (ftruncate(p, &nuap, retval));
        !          2043: }
        !          2044: #endif /* COMPAT_43 */
        !          2045: 
        !          2046: /*
        !          2047:  * Sync an open file.
        !          2048:  */
        !          2049: struct fsync_args {
        !          2050:        int     fd;
        !          2051: };
        !          2052: /* ARGSUSED */
        !          2053: int
        !          2054: fsync(p, uap, retval)
        !          2055:        struct proc *p;
        !          2056:        struct fsync_args *uap;
        !          2057:        register_t *retval;
        !          2058: {
        !          2059:        register struct vnode *vp;
        !          2060:        struct file *fp;
        !          2061:        int error;
        !          2062: 
        !          2063:        if (error = getvnode(p, uap->fd, &fp))
        !          2064:                return (error);
        !          2065:        vp = (struct vnode *)fp->f_data;
        !          2066: #if MACH_NBC
        !          2067:        mapfs_fsync(vp);
        !          2068: #endif
        !          2069:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          2070:        error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
        !          2071:        VOP_UNLOCK(vp, 0, p);
        !          2072:        return (error);
        !          2073: }
        !          2074: 
        !          2075: /*
        !          2076:  * Duplicate files.  Source must be a file, target must be a file or 
        !          2077:  * must not exist.
        !          2078:  */
        !          2079: 
        !          2080: struct copyfile_args {
        !          2081:        char    *from;
        !          2082:        char    *to;
        !          2083:         int    mode;
        !          2084:         int    flags;
        !          2085: };
        !          2086: /* ARGSUSED */
        !          2087: int
        !          2088: copyfile(p, uap, retval)
        !          2089:        struct proc *p;
        !          2090:        register struct copyfile_args *uap;
        !          2091:        register_t *retval;
        !          2092: {
        !          2093:        register struct vnode *tvp, *fvp, *tdvp;
        !          2094:         register struct ucred *cred = p->p_ucred;
        !          2095:        struct nameidata fromnd, tond;
        !          2096:        int error;
        !          2097:         
        !          2098:         /* Check that the flags are valid.  
        !          2099:          */
        !          2100: 
        !          2101:        if (uap->flags & ~CPF_MASK) {
        !          2102:            return(EINVAL);
        !          2103:         }
        !          2104: 
        !          2105:        NDINIT(&fromnd, LOOKUP, SAVESTART, UIO_USERSPACE,
        !          2106:            uap->from, p);
        !          2107:        if (error = namei(&fromnd))
        !          2108:                return (error);
        !          2109:        fvp = fromnd.ni_vp;
        !          2110: 
        !          2111:        NDINIT(&tond, CREATE,  LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
        !          2112:            UIO_USERSPACE, uap->to, p);
        !          2113:        if (error = namei(&tond)) {
        !          2114:                vrele(fvp);
        !          2115:                goto out1;
        !          2116:        }
        !          2117:        tdvp = tond.ni_dvp;
        !          2118:        tvp = tond.ni_vp;
        !          2119:        if (tvp != NULL) {
        !          2120:                if (!(uap->flags & CPF_OVERWRITE)) {
        !          2121:                        error = EEXIST;
        !          2122:                        goto out;
        !          2123:                }
        !          2124:        }
        !          2125: 
        !          2126:        if (fvp->v_type == VDIR || (tvp && tvp->v_type == VDIR)) {
        !          2127:                error = EISDIR;
        !          2128:                goto out;
        !          2129:        }
        !          2130: 
        !          2131:         if (error = VOP_ACCESS(tdvp, VWRITE, cred, p))         
        !          2132:                goto out;
        !          2133: 
        !          2134:        if (fvp == tdvp)
        !          2135:                error = EINVAL;
        !          2136:        /*
        !          2137:         * If source is the same as the destination (that is the
        !          2138:         * same inode number) then there is nothing to do.
        !          2139:         * (fixed to have POSIX semantics - CSM 3/2/98)
        !          2140:         */
        !          2141:        if (fvp == tvp)
        !          2142:                error = -1;
        !          2143: out:
        !          2144:        if (!error) {
        !          2145:                error = VOP_COPYFILE(fvp,tdvp,tvp,&tond.ni_cnd,uap->mode,uap->flags);
        !          2146:        } else {
        !          2147:                VOP_ABORTOP(tdvp, &tond.ni_cnd);
        !          2148:                if (tdvp == tvp)
        !          2149:                        vrele(tdvp);
        !          2150:                else
        !          2151:                        vput(tdvp);
        !          2152:                if (tvp)
        !          2153:                        vput(tvp);
        !          2154:                vrele(fvp);
        !          2155:        }
        !          2156:        vrele(tond.ni_startdir);
        !          2157:        FREE_ZONE(tond.ni_cnd.cn_pnbuf, tond.ni_cnd.cn_pnlen, M_NAMEI);
        !          2158: out1:
        !          2159:        if (fromnd.ni_startdir)
        !          2160:                vrele(fromnd.ni_startdir);
        !          2161:        FREE_ZONE(fromnd.ni_cnd.cn_pnbuf, fromnd.ni_cnd.cn_pnlen, M_NAMEI);
        !          2162:        if (error == -1)
        !          2163:                return (0);
        !          2164:        return (error);
        !          2165: }
        !          2166: 
        !          2167: /*
        !          2168: /*
        !          2169:  * Rename files.  Source and destination must either both be directories,
        !          2170:  * or both not be directories.  If target is a directory, it must be empty.
        !          2171:  */
        !          2172: struct rename_args {
        !          2173:        char    *from;
        !          2174:        char    *to;
        !          2175: };
        !          2176: /* ARGSUSED */
        !          2177: int
        !          2178: rename(p, uap, retval)
        !          2179:        struct proc *p;
        !          2180:        register struct rename_args *uap;
        !          2181:        register_t *retval;
        !          2182: {
        !          2183:        register struct vnode *tvp, *fvp, *tdvp;
        !          2184:        struct nameidata fromnd, tond;
        !          2185:        int error;
        !          2186: 
        !          2187:        NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
        !          2188:            uap->from, p);
        !          2189:        if (error = namei(&fromnd))
        !          2190:                return (error);
        !          2191:        fvp = fromnd.ni_vp;
        !          2192:        NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
        !          2193:            UIO_USERSPACE, uap->to, p);
        !          2194:        if (error = namei(&tond)) {
        !          2195:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
        !          2196:                vrele(fromnd.ni_dvp);
        !          2197:                vrele(fvp);
        !          2198:                goto out1;
        !          2199:        }
        !          2200:        tdvp = tond.ni_dvp;
        !          2201:        tvp = tond.ni_vp;
        !          2202:        if (tvp != NULL) {
        !          2203:                if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
        !          2204:                        error = ENOTDIR;
        !          2205:                        goto out;
        !          2206:                } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
        !          2207:                        error = EISDIR;
        !          2208:                        goto out;
        !          2209:                }
        !          2210:        }
        !          2211:        if (fvp == tdvp)
        !          2212:                error = EINVAL;
        !          2213:        /*
        !          2214:         * If source is the same as the destination (that is the
        !          2215:         * same inode number) then there is nothing to do.
        !          2216:         * (fixed to have POSIX semantics - CSM 3/2/98)
        !          2217:         */
        !          2218:        if (fvp == tvp)
        !          2219:                error = -1;
        !          2220: out:
        !          2221:        if (!error) {
        !          2222:                VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
        !          2223:                if (fromnd.ni_dvp != tdvp)
        !          2224:                        VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
        !          2225:                if (tvp)
        !          2226:                        VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
        !          2227:                error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
        !          2228:                                   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
        !          2229:        } else {
        !          2230:                VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
        !          2231:                if (tdvp == tvp)
        !          2232:                        vrele(tdvp);
        !          2233:                else
        !          2234:                        vput(tdvp);
        !          2235:                if (tvp)
        !          2236:                        vput(tvp);
        !          2237:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
        !          2238:                vrele(fromnd.ni_dvp);
        !          2239:                vrele(fvp);
        !          2240:        }
        !          2241:        vrele(tond.ni_startdir);
        !          2242:        FREE_ZONE(tond.ni_cnd.cn_pnbuf, tond.ni_cnd.cn_pnlen, M_NAMEI);
        !          2243: out1:
        !          2244:        if (fromnd.ni_startdir)
        !          2245:                vrele(fromnd.ni_startdir);
        !          2246:        FREE_ZONE(fromnd.ni_cnd.cn_pnbuf, fromnd.ni_cnd.cn_pnlen, M_NAMEI);
        !          2247:        if (error == -1)
        !          2248:                return (0);
        !          2249:        return (error);
        !          2250: }
        !          2251: 
        !          2252: /*
        !          2253:  * Make a directory file.
        !          2254:  */
        !          2255: struct mkdir_args {
        !          2256:        char    *path;
        !          2257:        int     mode;
        !          2258: };
        !          2259: /* ARGSUSED */
        !          2260: int
        !          2261: mkdir(p, uap, retval)
        !          2262:        struct proc *p;
        !          2263:        register struct mkdir_args *uap;
        !          2264:        register_t *retval;
        !          2265: {
        !          2266:        register struct vnode *vp;
        !          2267:        struct vattr vattr;
        !          2268:        int error;
        !          2269:        struct nameidata nd;
        !          2270: 
        !          2271:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
        !          2272:        if (error = namei(&nd))
        !          2273:                return (error);
        !          2274:        vp = nd.ni_vp;
        !          2275:        if (vp != NULL) {
        !          2276:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          2277:                if (nd.ni_dvp == vp)
        !          2278:                        vrele(nd.ni_dvp);
        !          2279:                else
        !          2280:                        vput(nd.ni_dvp);
        !          2281:                vrele(vp);
        !          2282:                return (EEXIST);
        !          2283:        }
        !          2284:        VATTR_NULL(&vattr);
        !          2285:        vattr.va_type = VDIR;
        !          2286:        vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
        !          2287:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
        !          2288:        error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
        !          2289:        if (!error)
        !          2290:                vput(nd.ni_vp);
        !          2291:        return (error);
        !          2292: }
        !          2293: 
        !          2294: /*
        !          2295:  * Remove a directory file.
        !          2296:  */
        !          2297: struct rmdir_args {
        !          2298:        char    *path;
        !          2299: };
        !          2300: /* ARGSUSED */
        !          2301: int
        !          2302: rmdir(p, uap, retval)
        !          2303:        struct proc *p;
        !          2304:        struct rmdir_args *uap;
        !          2305:        register_t *retval;
        !          2306: {
        !          2307:        register struct vnode *vp;
        !          2308:        int error;
        !          2309:        struct nameidata nd;
        !          2310: 
        !          2311:        NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
        !          2312:            uap->path, p);
        !          2313:        if (error = namei(&nd))
        !          2314:                return (error);
        !          2315:        vp = nd.ni_vp;
        !          2316:        if (vp->v_type != VDIR) {
        !          2317:                error = ENOTDIR;
        !          2318:                goto out;
        !          2319:        }
        !          2320:        /*
        !          2321:         * No rmdir "." please.
        !          2322:         */
        !          2323:        if (nd.ni_dvp == vp) {
        !          2324:                error = EINVAL;
        !          2325:                goto out;
        !          2326:        }
        !          2327:        /*
        !          2328:         * The root of a mounted filesystem cannot be deleted.
        !          2329:         */
        !          2330:        if (vp->v_flag & VROOT)
        !          2331:                error = EBUSY;
        !          2332: out:
        !          2333:        if (!error) {
        !          2334:                VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
        !          2335:                VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
        !          2336:                error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
        !          2337:        } else {
        !          2338:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
        !          2339:                if (nd.ni_dvp == vp)
        !          2340:                        vrele(nd.ni_dvp);
        !          2341:                else
        !          2342:                        vput(nd.ni_dvp);
        !          2343:                vput(vp);
        !          2344:        }
        !          2345:        return (error);
        !          2346: }
        !          2347: 
        !          2348: #if COMPAT_43
        !          2349: /*
        !          2350:  * Read a block of directory entries in a file system independent format.
        !          2351:  */
        !          2352: struct ogetdirentries_args {
        !          2353:        int     fd;
        !          2354:        char    *buf;
        !          2355:        u_int   count;
        !          2356:        long    *basep;
        !          2357: };
        !          2358: int
        !          2359: ogetdirentries(p, uap, retval)
        !          2360:        struct proc *p;
        !          2361:        register struct ogetdirentries_args *uap;
        !          2362:        register_t *retval;
        !          2363: {
        !          2364:        register struct vnode *vp;
        !          2365:        struct file *fp;
        !          2366:        struct uio auio, kuio;
        !          2367:        struct iovec aiov, kiov;
        !          2368:        struct dirent *dp, *edp;
        !          2369:        caddr_t dirbuf;
        !          2370:        int error, eofflag, readcnt;
        !          2371:        long loff;
        !          2372: 
        !          2373:        if (error = getvnode(p, uap->fd, &fp))
        !          2374:                return (error);
        !          2375:        if ((fp->f_flag & FREAD) == 0)
        !          2376:                return (EBADF);
        !          2377:        vp = (struct vnode *)fp->f_data;
        !          2378: unionread:
        !          2379:        if (vp->v_type != VDIR)
        !          2380:                return (EINVAL);
        !          2381:        aiov.iov_base = uap->buf;
        !          2382:        aiov.iov_len = uap->count;
        !          2383:        auio.uio_iov = &aiov;
        !          2384:        auio.uio_iovcnt = 1;
        !          2385:        auio.uio_rw = UIO_READ;
        !          2386:        auio.uio_segflg = UIO_USERSPACE;
        !          2387:        auio.uio_procp = p;
        !          2388:        auio.uio_resid = uap->count;
        !          2389:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          2390:        loff = auio.uio_offset = fp->f_offset;
        !          2391: #      if (BYTE_ORDER != LITTLE_ENDIAN)
        !          2392:                if (vp->v_mount->mnt_maxsymlinklen <= 0) {
        !          2393:                        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
        !          2394:                            (int *)0, (u_long *)0);
        !          2395:                        fp->f_offset = auio.uio_offset;
        !          2396:                } else
        !          2397: #      endif
        !          2398:        {
        !          2399:                kuio = auio;
        !          2400:                kuio.uio_iov = &kiov;
        !          2401:                kuio.uio_segflg = UIO_SYSSPACE;
        !          2402:                kiov.iov_len = uap->count;
        !          2403:                MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
        !          2404:                kiov.iov_base = dirbuf;
        !          2405:                error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
        !          2406:                            (int *)0, (u_long *)0);
        !          2407:                fp->f_offset = kuio.uio_offset;
        !          2408:                if (error == 0) {
        !          2409:                        readcnt = uap->count - kuio.uio_resid;
        !          2410:                        edp = (struct dirent *)&dirbuf[readcnt];
        !          2411:                        for (dp = (struct dirent *)dirbuf; dp < edp; ) {
        !          2412: #                              if (BYTE_ORDER == LITTLE_ENDIAN)
        !          2413:                                        /*
        !          2414:                                         * The expected low byte of
        !          2415:                                         * dp->d_namlen is our dp->d_type.
        !          2416:                                         * The high MBZ byte of dp->d_namlen
        !          2417:                                         * is our dp->d_namlen.
        !          2418:                                         */
        !          2419:                                        dp->d_type = dp->d_namlen;
        !          2420:                                        dp->d_namlen = 0;
        !          2421: #                              else
        !          2422:                                        /*
        !          2423:                                         * The dp->d_type is the high byte
        !          2424:                                         * of the expected dp->d_namlen,
        !          2425:                                         * so must be zero'ed.
        !          2426:                                         */
        !          2427:                                        dp->d_type = 0;
        !          2428: #                              endif
        !          2429:                                if (dp->d_reclen > 0) {
        !          2430:                                        dp = (struct dirent *)
        !          2431:                                            ((char *)dp + dp->d_reclen);
        !          2432:                                } else {
        !          2433:                                        error = EIO;
        !          2434:                                        break;
        !          2435:                                }
        !          2436:                        }
        !          2437:                        if (dp >= edp)
        !          2438:                                error = uiomove(dirbuf, readcnt, &auio);
        !          2439:                }
        !          2440:                FREE(dirbuf, M_TEMP);
        !          2441:        }
        !          2442:        VOP_UNLOCK(vp, 0, p);
        !          2443:        if (error)
        !          2444:                return (error);
        !          2445: 
        !          2446: #if UNION
        !          2447: {
        !          2448:        extern int (**union_vnodeop_p)();
        !          2449:        extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
        !          2450: 
        !          2451:        if ((uap->count == auio.uio_resid) &&
        !          2452:            (vp->v_op == union_vnodeop_p)) {
        !          2453:                struct vnode *lvp;
        !          2454: 
        !          2455:                lvp = union_dircache(vp, p);
        !          2456:                if (lvp != NULLVP) {
        !          2457:                        struct vattr va;
        !          2458: 
        !          2459:                        /*
        !          2460:                         * If the directory is opaque,
        !          2461:                         * then don't show lower entries
        !          2462:                         */
        !          2463:                        error = VOP_GETATTR(vp, &va, fp->f_cred, p);
        !          2464:                        if (va.va_flags & OPAQUE) {
        !          2465:                                vput(lvp);
        !          2466:                                lvp = NULL;
        !          2467:                        }
        !          2468:                }
        !          2469:                
        !          2470:                if (lvp != NULLVP) {
        !          2471:                        error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
        !          2472:                        if (error) {
        !          2473:                                vput(lvp);
        !          2474:                                return (error);
        !          2475:                        }
        !          2476:                        VOP_UNLOCK(lvp, 0, p);
        !          2477:                        fp->f_data = (caddr_t) lvp;
        !          2478:                        fp->f_offset = 0;
        !          2479:                        error = vn_close(vp, FREAD, fp->f_cred, p);
        !          2480:                        if (error)
        !          2481:                                return (error);
        !          2482:                        vp = lvp;
        !          2483:                        goto unionread;
        !          2484:                }
        !          2485:        }
        !          2486: }
        !          2487: #endif /* UNION */
        !          2488: 
        !          2489:        if ((uap->count == auio.uio_resid) &&
        !          2490:            (vp->v_flag & VROOT) &&
        !          2491:            (vp->v_mount->mnt_flag & MNT_UNION)) {
        !          2492:                struct vnode *tvp = vp;
        !          2493:                vp = vp->v_mount->mnt_vnodecovered;
        !          2494:                VREF(vp);
        !          2495:                fp->f_data = (caddr_t) vp;
        !          2496:                fp->f_offset = 0;
        !          2497:                vrele(tvp);
        !          2498:                goto unionread;
        !          2499:        }
        !          2500:        error = copyout((caddr_t)&loff, (caddr_t)uap->basep,
        !          2501:            sizeof(long));
        !          2502:        *retval = uap->count - auio.uio_resid;
        !          2503:        return (error);
        !          2504: }
        !          2505: #endif /* COMPAT_43 */
        !          2506: 
        !          2507: /*
        !          2508:  * Read a block of directory entries in a file system independent format.
        !          2509:  */
        !          2510: struct getdirentries_args {
        !          2511:        int     fd;
        !          2512:        char    *buf;
        !          2513:        u_int   count;
        !          2514:        long    *basep;
        !          2515: };
        !          2516: int
        !          2517: getdirentries(p, uap, retval)
        !          2518:        struct proc *p;
        !          2519:        register struct getdirentries_args *uap;
        !          2520:        register_t *retval;
        !          2521: {
        !          2522:        register struct vnode *vp;
        !          2523:        struct file *fp;
        !          2524:        struct uio auio;
        !          2525:        struct iovec aiov;
        !          2526:        long loff;
        !          2527:        int error, eofflag;
        !          2528: 
        !          2529:        if (error = getvnode(p, uap->fd, &fp))
        !          2530:                return (error);
        !          2531:        if ((fp->f_flag & FREAD) == 0)
        !          2532:                return (EBADF);
        !          2533:        vp = (struct vnode *)fp->f_data;
        !          2534: unionread:
        !          2535:        if (vp->v_type != VDIR)
        !          2536:                return (EINVAL);
        !          2537:        aiov.iov_base = uap->buf;
        !          2538:        aiov.iov_len = uap->count;
        !          2539:        auio.uio_iov = &aiov;
        !          2540:        auio.uio_iovcnt = 1;
        !          2541:        auio.uio_rw = UIO_READ;
        !          2542:        auio.uio_segflg = UIO_USERSPACE;
        !          2543:        auio.uio_procp = p;
        !          2544:        auio.uio_resid = uap->count;
        !          2545:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          2546:        loff = auio.uio_offset = fp->f_offset;
        !          2547:        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
        !          2548:                            (int *)0, (u_long *)0);
        !          2549:        fp->f_offset = auio.uio_offset;
        !          2550:        VOP_UNLOCK(vp, 0, p);
        !          2551:        if (error)
        !          2552:                return (error);
        !          2553: 
        !          2554: #if UNION
        !          2555: {
        !          2556:        extern int (**union_vnodeop_p)();
        !          2557:        extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
        !          2558: 
        !          2559:        if ((uap->count == auio.uio_resid) &&
        !          2560:            (vp->v_op == union_vnodeop_p)) {
        !          2561:                struct vnode *lvp;
        !          2562: 
        !          2563:                lvp = union_dircache(vp, p);
        !          2564:                if (lvp != NULLVP) {
        !          2565:                        struct vattr va;
        !          2566: 
        !          2567:                        /*
        !          2568:                         * If the directory is opaque,
        !          2569:                         * then don't show lower entries
        !          2570:                         */
        !          2571:                        error = VOP_GETATTR(vp, &va, fp->f_cred, p);
        !          2572:                        if (va.va_flags & OPAQUE) {
        !          2573:                                vput(lvp);
        !          2574:                                lvp = NULL;
        !          2575:                        }
        !          2576:                }
        !          2577: 
        !          2578:                if (lvp != NULLVP) {
        !          2579:                        error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
        !          2580:                        if (error) {
        !          2581:                                vput(lvp);
        !          2582:                                return (error);
        !          2583:                        }
        !          2584:                        VOP_UNLOCK(lvp, 0, p);
        !          2585:                        fp->f_data = (caddr_t) lvp;
        !          2586:                        fp->f_offset = 0;
        !          2587:                        error = vn_close(vp, FREAD, fp->f_cred, p);
        !          2588:                        if (error)
        !          2589:                                return (error);
        !          2590:                        vp = lvp;
        !          2591:                        goto unionread;
        !          2592:                }
        !          2593:        }
        !          2594: }
        !          2595: #endif /* UNION */
        !          2596: 
        !          2597:        if ((uap->count == auio.uio_resid) &&
        !          2598:            (vp->v_flag & VROOT) &&
        !          2599:            (vp->v_mount->mnt_flag & MNT_UNION)) {
        !          2600:                struct vnode *tvp = vp;
        !          2601:                vp = vp->v_mount->mnt_vnodecovered;
        !          2602:                VREF(vp);
        !          2603:                fp->f_data = (caddr_t) vp;
        !          2604:                fp->f_offset = 0;
        !          2605:                vrele(tvp);
        !          2606:                goto unionread;
        !          2607:        }
        !          2608:        error = copyout((caddr_t)&loff, (caddr_t)uap->basep,
        !          2609:            sizeof(long));
        !          2610:        *retval = uap->count - auio.uio_resid;
        !          2611:        return (error);
        !          2612: }
        !          2613: 
        !          2614: /*
        !          2615:  * Set the mode mask for creation of filesystem nodes.
        !          2616:  */
        !          2617: struct umask_args {
        !          2618:        int     newmask;
        !          2619: };
        !          2620: int
        !          2621: umask(p, uap, retval)
        !          2622:        struct proc *p;
        !          2623:        struct umask_args *uap;
        !          2624:        register_t *retval;
        !          2625: {
        !          2626:        register struct filedesc *fdp;
        !          2627: 
        !          2628:        fdp = p->p_fd;
        !          2629:        *retval = fdp->fd_cmask;
        !          2630:        fdp->fd_cmask = uap->newmask & ALLPERMS;
        !          2631:        return (0);
        !          2632: }
        !          2633: 
        !          2634: /*
        !          2635:  * Void all references to file by ripping underlying filesystem
        !          2636:  * away from vnode.
        !          2637:  */
        !          2638: struct revoke_args {
        !          2639:        char    *path;
        !          2640: };
        !          2641: /* ARGSUSED */
        !          2642: int
        !          2643: revoke(p, uap, retval)
        !          2644:        struct proc *p;
        !          2645:        register struct revoke_args *uap;
        !          2646:        register_t *retval;
        !          2647: {
        !          2648:        register struct vnode *vp;
        !          2649:        struct vattr vattr;
        !          2650:        int error;
        !          2651:        struct nameidata nd;
        !          2652: 
        !          2653:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
        !          2654:        if (error = namei(&nd))
        !          2655:                return (error);
        !          2656:        vp = nd.ni_vp;
        !          2657:        if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
        !          2658:                goto out;
        !          2659:        if (p->p_ucred->cr_uid != vattr.va_uid &&
        !          2660:            (error = suser(p->p_ucred, &p->p_acflag)))
        !          2661:                goto out;
        !          2662:        if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
        !          2663:                VOP_REVOKE(vp, REVOKEALL);
        !          2664: out:
        !          2665:        vrele(vp);
        !          2666:        return (error);
        !          2667: }
        !          2668: 
        !          2669: /*
        !          2670:  * Convert a user file descriptor to a kernel file entry.
        !          2671:  */
        !          2672: int
        !          2673: getvnode(p, fd, fpp)
        !          2674:        struct proc *p;
        !          2675:        int fd;
        !          2676:        struct file **fpp;
        !          2677: {
        !          2678:        struct file *fp;
        !          2679:        int error;
        !          2680: 
        !          2681:        if (error = fdgetf(p, fd, &fp))
        !          2682:                return (error);
        !          2683:        if (fp->f_type != DTYPE_VNODE)
        !          2684:                return (EINVAL);
        !          2685:        *fpp = fp;
        !          2686:        return (0);
        !          2687: }
        !          2688: /*
        !          2689:  *  HFS/HFS PlUS SPECIFIC SYSTEM CALLS
        !          2690:  *  The following 10 system calls are designed to support features
        !          2691:  *  which are specific to the HFS & HFS Plus volume formats
        !          2692:  */
        !          2693: 
        !          2694: 
        !          2695: /*
        !          2696:  * Make a complex file.  A complex file is one with multiple forks (data streams)
        !          2697:  */
        !          2698: struct mkcomplex_args {
        !          2699:         const char *path;      /* pathname of the file to be created */
        !          2700:        mode_t mode;            /* access mode for the newly created file */
        !          2701:         u_long type;           /* format of the complex file */
        !          2702: };
        !          2703: /* ARGSUSED */
        !          2704: int
        !          2705: mkcomplex(p,uap,retval)
        !          2706:        struct proc *p;
        !          2707:         register struct mkcomplex_args *uap;
        !          2708:         register_t *retval;
        !          2709:                        
        !          2710: {
        !          2711:        struct vnode *vp;
        !          2712:         struct vattr vattr;
        !          2713:         int error;
        !          2714:         struct nameidata nd;
        !          2715: 
        !          2716:        /* mkcomplex wants the directory vnode locked so do that here */
        !          2717: 
        !          2718:         NDINIT(&nd, CREATE, FOLLOW | LOCKPARENT, UIO_USERSPACE, uap->path, p);
        !          2719:         if (error = namei(&nd))
        !          2720:                 return (error);
        !          2721: 
        !          2722:        /*  Set the attributes as specified by the user */
        !          2723: 
        !          2724:         VATTR_NULL(&vattr);
        !          2725:         vattr.va_mode = (uap->mode & ACCESSPERMS);
        !          2726:         error = VOP_MKCOMPLEX(nd.ni_dvp, &vp, &nd.ni_cnd, &vattr, uap->type);
        !          2727: 
        !          2728:        /*  The mkcomplex call promises to release the parent vnode pointer
        !          2729:         *  even an an error case so don't do it here unless the operation
        !          2730:         *  is not supported.  In that case, there isn't anyone to unlock the parent
        !          2731:         *  The vnode pointer to the file will also be released.
        !          2732:         */
        !          2733: 
        !          2734:         if (error)
        !          2735:                {
        !          2736:                        if (error == EOPNOTSUPP)
        !          2737:                        vput(nd.ni_dvp);
        !          2738:                 return (error);
        !          2739:                }
        !          2740: 
        !          2741:         return (0);
        !          2742: 
        !          2743: } /* end of mkcomplex system call */
        !          2744: 
        !          2745: 
        !          2746: 
        !          2747: /*
        !          2748:  * Extended stat call which returns volumeid and vnodeid as well as other info
        !          2749:  */
        !          2750: struct statv_args {
        !          2751:         const char *path;      /* pathname of the target file       */
        !          2752:         struct vstat *vsb;     /* vstat structure for returned info */
        !          2753: };
        !          2754: /* ARGSUSED */
        !          2755: int
        !          2756: statv(p,uap,retval)
        !          2757:         struct proc *p;
        !          2758:         register struct statv_args *uap;
        !          2759:         register_t *retval;
        !          2760: 
        !          2761: {
        !          2762:        return (EOPNOTSUPP);    /*  We'll just return an error for now */
        !          2763: 
        !          2764: } /* end of statv system call */
        !          2765: 
        !          2766: 
        !          2767: 
        !          2768: /*
        !          2769: * Extended lstat call which returns volumeid and vnodeid as well as other info
        !          2770: */
        !          2771: struct lstatv_args {
        !          2772:        const char *path;       /* pathname of the target file       */
        !          2773:        struct vstat *vsb;      /* vstat structure for returned info */
        !          2774: };
        !          2775: /* ARGSUSED */
        !          2776: int
        !          2777: lstatv(p,uap,retval)
        !          2778:        struct proc *p;
        !          2779:        register struct lstatv_args *uap;
        !          2780:        register_t *retval;
        !          2781: 
        !          2782: {
        !          2783:        return (EOPNOTSUPP);    /*  We'll just return an error for now */
        !          2784: } /* end of lstatv system call */
        !          2785: 
        !          2786: 
        !          2787: 
        !          2788: /*
        !          2789: * Extended fstat call which returns volumeid and vnodeid as well as other info
        !          2790: */
        !          2791: struct fstatv_args {
        !          2792:        int fd;                 /* file descriptor of the target file */
        !          2793:        struct vstat *vsb;      /* vstat structure for returned info  */
        !          2794: };
        !          2795: /* ARGSUSED */
        !          2796: int
        !          2797: fstatv(p,uap,retval)
        !          2798:        struct proc *p;
        !          2799:        register struct fstatv_args *uap;
        !          2800:        register_t *retval;
        !          2801: 
        !          2802: {
        !          2803:        return (EOPNOTSUPP);    /*  We'll just return an error for now */
        !          2804: } /* end of fstatv system call */
        !          2805: 
        !          2806: 
        !          2807: 
        !          2808: /*
        !          2809: * Obtain attribute information about a file system object
        !          2810: */
        !          2811: 
        !          2812: struct getattrlist_args {
        !          2813:        const char *path;       /* pathname of the target object */
        !          2814:        struct attrlist * alist; /* Attributes desired by the user */
        !          2815:        void * attributeBuffer;         /* buffer to hold returned attributes */
        !          2816:        size_t bufferSize;      /* size of the return buffer */
        !          2817:        unsigned long options;   /* options (follow/don't follow) */
        !          2818: };
        !          2819: /* ARGSUSED */
        !          2820: int
        !          2821: getattrlist (p,uap,retval)
        !          2822:        struct proc *p;
        !          2823:        register struct getattrlist_args *uap;
        !          2824:        register_t *retval;
        !          2825: 
        !          2826: {
        !          2827:         int error;
        !          2828:         struct nameidata nd;   
        !          2829:        struct iovec aiov;
        !          2830:        struct uio auio;
        !          2831:         struct attrlist attributelist;
        !          2832:        u_long nameiflags;
        !          2833: 
        !          2834:        /* Get the attributes desire and do our parameter checking */
        !          2835: 
        !          2836:        if (error = copyin((caddr_t)uap->alist, (caddr_t) &attributelist,
        !          2837:                  sizeof (attributelist)))
        !          2838:                {
        !          2839:                return(error);
        !          2840:                }
        !          2841: 
        !          2842:        if (attributelist.bitmapcount != ATTR_BIT_MAP_COUNT
        !          2843: #if 0
        !          2844:            ||  attributelist.commonattr & ~ATTR_CMN_VALIDMASK ||
        !          2845:                attributelist.volattr & ~ATTR_VOL_VALIDMASK ||
        !          2846:                attributelist.dirattr & ~ATTR_DIR_VALIDMASK ||
        !          2847:                attributelist.fileattr & ~ATTR_FILE_VALIDMASK ||
        !          2848:                attributelist.forkattr & ~ATTR_FORK_VALIDMASK
        !          2849: #endif
        !          2850:        )
        !          2851:                {
        !          2852:                return (EINVAL);
        !          2853:                }
        !          2854: 
        !          2855:        /* Get the vnode for the file we are getting info on.  */
        !          2856:        nameiflags = LOCKLEAF;
        !          2857:        if ((uap->options & FSOPT_NOFOLLOW) == 0) nameiflags |= FOLLOW;
        !          2858:         NDINIT(&nd, LOOKUP, nameiflags, UIO_USERSPACE, uap->path, p);
        !          2859: 
        !          2860:         if (error = namei(&nd))
        !          2861:                 return (error);
        !          2862: 
        !          2863:        /* Set up the UIO structure for use by the vfs routine */
        !          2864: 
        !          2865:        
        !          2866:        aiov.iov_base = uap->attributeBuffer;
        !          2867:         aiov.iov_len = uap->bufferSize;  
        !          2868:        auio.uio_iov = &aiov;
        !          2869:        auio.uio_iovcnt = 1;
        !          2870:         auio.uio_offset = 0;
        !          2871:         auio.uio_rw = UIO_READ;
        !          2872:         auio.uio_segflg = UIO_USERSPACE;
        !          2873:         auio.uio_procp = p;
        !          2874:         auio.uio_resid = uap->bufferSize;
        !          2875: 
        !          2876: 
        !          2877:         error = VOP_GETATTRLIST(nd.ni_vp, &attributelist, &auio, p->p_ucred, p);
        !          2878: 
        !          2879:        /* Unlock and release the vnode which will have been locked by namei */
        !          2880: 
        !          2881:         vput(nd.ni_vp);
        !          2882: 
        !          2883:         /* return the effort if we got one, otherwise return success */
        !          2884: 
        !          2885:         if (error)
        !          2886:             {
        !          2887:             return (error);
        !          2888:             }
        !          2889: 
        !          2890:         return(0);
        !          2891: 
        !          2892: } /* end of getattrlist system call */
        !          2893: 
        !          2894: 
        !          2895: 
        !          2896: /*
        !          2897: * Set attribute information about a file system object
        !          2898: */
        !          2899: 
        !          2900: struct setattrlist_args {
        !          2901:       const char *path;                /* pathname of the target object          */
        !          2902:       struct attrlist * alist;  /* Attributes being set  by the user     */
        !          2903:       void * attributeBuffer;  /* buffer with attribute values to be set */
        !          2904:       size_t bufferSize;       /* size of the return buffer              */
        !          2905:       unsigned long options;    /* options (follow/don't follow) */
        !          2906: };
        !          2907: /* ARGSUSED */
        !          2908: int
        !          2909: setattrlist (p,uap,retval)
        !          2910:       struct proc *p;
        !          2911:       register struct setattrlist_args *uap;
        !          2912:       register_t *retval;
        !          2913: 
        !          2914: {
        !          2915:        int error;
        !          2916:        struct nameidata nd;    
        !          2917:        struct iovec aiov;
        !          2918:        struct uio auio;
        !          2919:        struct attrlist attributelist;
        !          2920:        u_long nameiflags;
        !          2921: 
        !          2922:        /* Get the attributes desired and do our parameter checking */
        !          2923: 
        !          2924:        if (error = copyin((caddr_t)uap->alist, (caddr_t) &attributelist,
        !          2925:                 sizeof (attributelist)))
        !          2926:                {
        !          2927:                 return(error);
        !          2928:                 }
        !          2929: 
        !          2930:        if (attributelist.bitmapcount != ATTR_BIT_MAP_COUNT
        !          2931: #if 0
        !          2932:            ||  attributelist.commonattr & ~ATTR_CMN_VALIDMASK ||
        !          2933:                attributelist.volattr & ~ATTR_VOL_VALIDMASK ||
        !          2934:                attributelist.dirattr & ~ATTR_DIR_VALIDMASK ||
        !          2935:                attributelist.fileattr & ~ATTR_FILE_VALIDMASK ||
        !          2936:                attributelist.forkattr & ~ATTR_FORK_VALIDMASK
        !          2937: #endif
        !          2938:        )
        !          2939:                 {
        !          2940:                 return (EINVAL);
        !          2941:                 }
        !          2942: 
        !          2943:        /* Get the vnode for the file we are getting info on.  */
        !          2944:        nameiflags = LOCKLEAF;
        !          2945:        if ((uap->options & FSOPT_NOFOLLOW) == 0) nameiflags |= FOLLOW;
        !          2946:        NDINIT(&nd, LOOKUP, nameiflags, UIO_USERSPACE, uap->path, p);
        !          2947: 
        !          2948:        if (error = namei(&nd))
        !          2949:                return (error);
        !          2950: 
        !          2951:       /* Set up the UIO structure for use by the vfs routine */
        !          2952:       
        !          2953:        aiov.iov_base = uap->attributeBuffer;
        !          2954:        aiov.iov_len = uap->bufferSize;
        !          2955:        auio.uio_iov = &aiov;
        !          2956:        auio.uio_iovcnt = 1;
        !          2957:        auio.uio_offset = 0;
        !          2958:        auio.uio_rw = UIO_WRITE;
        !          2959:        auio.uio_segflg = UIO_USERSPACE;
        !          2960:        auio.uio_procp = p;
        !          2961:        auio.uio_resid = uap->bufferSize;
        !          2962: 
        !          2963: 
        !          2964:        error = VOP_SETATTRLIST(nd.ni_vp,&attributelist, &auio, p->p_ucred, p);
        !          2965:        
        !          2966:        /* Unlock and release the vnode which will have been locked by namei */
        !          2967: 
        !          2968:        vput(nd.ni_vp);
        !          2969: 
        !          2970:        /* return the error if we got one, otherwise return success */
        !          2971: 
        !          2972:        if (error)
        !          2973:           {
        !          2974:           return (error);
        !          2975:            }
        !          2976:    
        !          2977:        return(0);
        !          2978: 
        !          2979: } /* end of setattrlist system call */
        !          2980: 
        !          2981: 
        !          2982: /*
        !          2983: * Obtain attribute information on objects in a directory while enumerating
        !          2984: * the directory.  This call does not yet support union mounted directories.
        !          2985: * TO DO
        !          2986: *  1.union mounted directories.
        !          2987: */
        !          2988: 
        !          2989: struct getdirentriesattr_args {
        !          2990:       int fd;                  /* file descriptor */
        !          2991:       struct attrlist *alist;   /* bit map of requested attributes */
        !          2992:       void *buffer;            /* buffer to hold returned attribute info */
        !          2993:       size_t buffersize;       /* size of the return buffer */
        !          2994:       u_long *count;           /* the count of entries requested/returned */
        !          2995:       u_long *basep;           /* the offset of where we are leaving off in buffer */
        !          2996:       u_long *newstate;                /* a flag to inform of changes in directory */
        !          2997:       u_long options;          /* maybe unused for now */
        !          2998: };
        !          2999: /* ARGSUSED */
        !          3000: int
        !          3001: getdirentriesattr (p,uap,retval)
        !          3002:       struct proc *p;
        !          3003:       register struct getdirentriesattr_args *uap;
        !          3004:       register_t *retval;
        !          3005: 
        !          3006: {
        !          3007:         register struct vnode *vp;
        !          3008:         struct file *fp;
        !          3009:         struct uio auio;
        !          3010:         struct iovec aiov;
        !          3011:         u_long actualcount;
        !          3012:         u_long newstate;
        !          3013:         int error, eofflag;
        !          3014:         long loff;
        !          3015:         struct attrlist attributelist; 
        !          3016: 
        !          3017:         /* Get the attributes into kernel space */
        !          3018:         if (error = copyin((caddr_t)uap->alist, (caddr_t) &attributelist, sizeof (attributelist)))
        !          3019:            return(error);
        !          3020:         if (error = copyin((caddr_t)uap->count, (caddr_t) &actualcount, sizeof (u_long)))
        !          3021:            return(error);
        !          3022: 
        !          3023:         if (error = getvnode(p, uap->fd, &fp))
        !          3024:                 return (error);
        !          3025:         if ((fp->f_flag & FREAD) == 0)
        !          3026:                 return(EBADF);
        !          3027:         vp = (struct vnode *)fp->f_data;
        !          3028: 
        !          3029:         if (vp->v_type != VDIR)
        !          3030:             return(EINVAL);
        !          3031: 
        !          3032:        /* set up the uio structure which will contain the users return buffer */
        !          3033:         aiov.iov_base = uap->buffer;
        !          3034:         aiov.iov_len = uap->buffersize;
        !          3035:         auio.uio_iov = &aiov;
        !          3036:         auio.uio_iovcnt = 1;
        !          3037:         auio.uio_rw = UIO_READ;
        !          3038:         auio.uio_segflg = UIO_USERSPACE;
        !          3039:         auio.uio_procp = p;
        !          3040:         auio.uio_resid = uap->buffersize;
        !          3041:         
        !          3042:         loff = auio.uio_offset = fp->f_offset;
        !          3043:         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        !          3044:         error = VOP_READDIRATTR (vp, &attributelist, &auio,
        !          3045:                    actualcount, uap->options, &newstate, &eofflag,
        !          3046:                    &actualcount, ((u_long **)0), p->p_cred);
        !          3047: 
        !          3048:         VOP_UNLOCK(vp, 0, p);
        !          3049:         if (error) return (error);
        !          3050:         fp->f_offset = auio.uio_offset; /* should be multiple of dirent, not variable */
        !          3051: 
        !          3052:         if (error = copyout((caddr_t) &actualcount, (caddr_t) uap->count, sizeof(u_long)))
        !          3053:             return (error);
        !          3054:         if (error = copyout((caddr_t) &newstate, (caddr_t) uap->newstate, sizeof(u_long)))
        !          3055:             return (error);
        !          3056:         if (error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long)))
        !          3057:             return (error);
        !          3058: 
        !          3059:        *retval = eofflag;  /* similar to getdirentries */
        !          3060:         return (0); /* return error earlier, an retval of 0 or 1 now */
        !          3061: 
        !          3062: } /* end of getdirentryattr system call */
        !          3063: 
        !          3064: /*
        !          3065: * Exchange data between two files
        !          3066: */
        !          3067: 
        !          3068: struct exchangedata_args {
        !          3069:       const char *path1;       /* pathname of the first swapee  */
        !          3070:       const char *path2;       /* pathname of the second swapee */
        !          3071:       unsigned long options;    /* options */
        !          3072: };
        !          3073: /* ARGSUSED */
        !          3074: int
        !          3075: exchangedata (p,uap,retval)
        !          3076:       struct proc *p;
        !          3077:       register struct exchangedata_args *uap;
        !          3078:       register_t *retval;
        !          3079: 
        !          3080: {
        !          3081: 
        !          3082:        struct nameidata fnd, snd;
        !          3083:        struct vnode *fvp, *svp;
        !          3084:         int error;
        !          3085:        u_long nameiflags;
        !          3086: 
        !          3087:        nameiflags = 0;
        !          3088:        if ((uap->options & FSOPT_NOFOLLOW) == 0) nameiflags |= FOLLOW;
        !          3089: 
        !          3090:                /* Global lock, to prevent race condition, only one exchange at a time */
        !          3091:         lockmgr(&exchangelock, LK_EXCLUSIVE , (struct slock *)0, p);
        !          3092: 
        !          3093:         NDINIT(&fnd, LOOKUP, nameiflags, UIO_USERSPACE, uap->path1, p);
        !          3094: 
        !          3095:         if (error = namei(&fnd))
        !          3096:                 goto out2;
        !          3097: 
        !          3098:         fvp = fnd.ni_vp;
        !          3099: 
        !          3100:         NDINIT(&snd, LOOKUP, nameiflags, UIO_USERSPACE, uap->path2, p);
        !          3101: 
        !          3102:         if (error = namei(&snd)) {
        !          3103:                        vrele(fvp);
        !          3104:             goto out2;
        !          3105:                }
        !          3106: 
        !          3107:        svp = snd.ni_vp;
        !          3108: 
        !          3109:        /* if the files are the same, return an inval error */
        !          3110:        if (svp == fvp) {
        !          3111:                vrele(fvp);
        !          3112:                vrele(svp);
        !          3113:         error = EINVAL;
        !          3114:                goto out2;
        !          3115:         } 
        !          3116: 
        !          3117:     vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p);
        !          3118:     vn_lock(svp, LK_EXCLUSIVE | LK_RETRY, p);
        !          3119: 
        !          3120:        error = VOP_ACCESS(fvp, VWRITE, p->p_ucred, p);
        !          3121:        if (error) goto out;
        !          3122: 
        !          3123:        error = VOP_ACCESS(svp, VWRITE, p->p_ucred, p);
        !          3124:        if (error) goto out;
        !          3125: 
        !          3126:        /* Ok, make the call */
        !          3127:        error = VOP_EXCHANGE (fvp, svp, p->p_ucred, p);
        !          3128: 
        !          3129: out:
        !          3130:     vput (svp);
        !          3131:        vput (fvp);
        !          3132: 
        !          3133: out2:
        !          3134:     lockmgr(&exchangelock, LK_RELEASE, (struct slock *)0, p);
        !          3135: 
        !          3136:        if (error) {
        !          3137:         return (error);
        !          3138:                }
        !          3139:        
        !          3140:        return (0);
        !          3141: 
        !          3142: } /* end of exchangedata system call */
        !          3143: 
        !          3144: /*
        !          3145: * Check users access to a file 
        !          3146: */
        !          3147: 
        !          3148: struct checkuseraccess_args {
        !          3149:      const char *path;         /* pathname of the target file   */
        !          3150:      uid_t userid;             /* user for whom we are checking access */
        !          3151:      gid_t *groups;            /* Group that we are checking for */
        !          3152:      int ngroups;              /* Number of groups being checked */
        !          3153:      int accessrequired;       /* needed access to the file */
        !          3154:      unsigned long options;     /* options */
        !          3155: };
        !          3156: 
        !          3157: /* ARGSUSED */
        !          3158: int
        !          3159: checkuseraccess (p,uap,retval)
        !          3160:      struct proc *p;
        !          3161:      register struct checkuseraccess_args *uap;
        !          3162:      register_t *retval;
        !          3163: 
        !          3164: {
        !          3165:        register struct vnode *vp;
        !          3166:        int error;
        !          3167:        struct nameidata nd;
        !          3168:        struct ucred cred;
        !          3169:        int flags;              /*what will actually get passed to access*/
        !          3170:        u_long nameiflags;
        !          3171: 
        !          3172:        /* Make sure that the number of groups is correct before we do anything */
        !          3173: 
        !          3174:        if (uap->ngroups > NGROUPS)
        !          3175:                return (EINVAL);
        !          3176: 
        !          3177:        /* Verify that the caller is root */
        !          3178:        
        !          3179:        if (error = suser(p->p_ucred, &p->p_acflag))
        !          3180:                return(error);
        !          3181: 
        !          3182:        /* Fill in the credential structure */
        !          3183: 
        !          3184:        cred.cr_ref = 0;
        !          3185:        cred.cr_uid = uap->userid;
        !          3186:        cred.cr_ngroups = uap->ngroups;
        !          3187:        if (error = copyin((caddr_t) uap->groups, (caddr_t) &(cred.cr_groups), (sizeof(gid_t))*uap->ngroups))
        !          3188:                return (error);
        !          3189: 
        !          3190:        /* Get our hands on the file */
        !          3191: 
        !          3192:        nameiflags = LOCKLEAF;
        !          3193:        if ((uap->options & FSOPT_NOFOLLOW) == 0) nameiflags |= FOLLOW;
        !          3194:        NDINIT(&nd, LOOKUP, nameiflags, UIO_USERSPACE, uap->path, p);
        !          3195: 
        !          3196:        if (error = namei(&nd))
        !          3197:                         return (error);
        !          3198:        vp = nd.ni_vp;
        !          3199:        
        !          3200:        /* Flags == 0 means only check for existence. */
        !          3201: 
        !          3202:        flags = 0;
        !          3203: 
        !          3204:        if (uap->accessrequired) {
        !          3205:                if (uap->accessrequired & R_OK)
        !          3206:                        flags |= VREAD;
        !          3207:                if (uap->accessrequired & W_OK)
        !          3208:                        flags |= VWRITE;
        !          3209:                if (uap->accessrequired & X_OK)
        !          3210:                        flags |= VEXEC;
        !          3211:                }
        !          3212:        error = VOP_ACCESS(vp, flags, &cred, p);
        !          3213:                        
        !          3214:        vput(vp);
        !          3215: 
        !          3216:        if (error) 
        !          3217:                return (error);
        !          3218:        
        !          3219:        return (0); 
        !          3220: 
        !          3221: } /* end of checkuseraccess system call */
        !          3222: 
        !          3223: 
        !          3224: struct searchfs_args {
        !          3225:        const char *path;
        !          3226:        struct fssearchblock *searchblock; 
        !          3227:        u_long *nummatches;
        !          3228:        u_long scriptcode;
        !          3229:        u_long options;
        !          3230:        struct searchstate *state; 
        !          3231:        };
        !          3232: /* ARGSUSED */
        !          3233: 
        !          3234: int
        !          3235: searchfs (p,uap,retval)
        !          3236:        struct proc *p;
        !          3237:        register struct searchfs_args *uap;
        !          3238:        register_t *retval;
        !          3239: 
        !          3240: {
        !          3241:        register struct vnode *vp;
        !          3242:        int error=0;
        !          3243:        int fserror = 0;
        !          3244:        struct nameidata nd;
        !          3245:        struct fssearchblock searchblock;
        !          3246:        struct searchstate *state;
        !          3247:        struct attrlist *returnattrs;
        !          3248:        void *searchparams1,*searchparams2;
        !          3249:        struct iovec aiov;
        !          3250:        struct uio auio;
        !          3251:        u_long nummatches;
        !          3252:        int mallocsize;
        !          3253:        u_long nameiflags;
        !          3254:        
        !          3255: 
        !          3256:        /* Start by copying in fsearchblock paramater list */
        !          3257: 
        !          3258:        if (error = copyin((caddr_t) uap->searchblock, (caddr_t) &searchblock,sizeof(struct fssearchblock)))
        !          3259:                return(error);
        !          3260: 
        !          3261:        /* Now malloc a big bunch of space to hold the search parameters, the attrlists and the search state. */
        !          3262:        /* It all has to do into local memory and it's not that big so we might as well  put it all together. */
        !          3263:        /* Searchparams1 shall be first so we might as well use that to hold the base address of the allocated*/
        !          3264:        /* block.                                                                                             */
        !          3265:        
        !          3266:        mallocsize = searchblock.sizeofsearchparams1+searchblock.sizeofsearchparams2 +
        !          3267:                      sizeof(struct attrlist) + sizeof(struct searchstate);
        !          3268: 
        !          3269:        MALLOC(searchparams1, void *, mallocsize, M_TEMP, M_WAITOK);
        !          3270: 
        !          3271:        /* Now set up the various pointers to the correct place in our newly allocated memory */
        !          3272: 
        !          3273:        searchparams2 = (void *) (((caddr_t) searchparams1) + searchblock.sizeofsearchparams1);
        !          3274:        returnattrs = (struct attrlist *) (((caddr_t) searchparams2) + searchblock.sizeofsearchparams2);
        !          3275:        state = (struct searchstate *) (((caddr_t) returnattrs) + sizeof (struct attrlist));
        !          3276: 
        !          3277:        /* Now copy in the stuff given our local variables. */
        !          3278: 
        !          3279:        if (error = copyin((caddr_t) searchblock.searchparams1, searchparams1,searchblock.sizeofsearchparams1))
        !          3280:                goto freeandexit;
        !          3281: 
        !          3282:        if (error = copyin((caddr_t) searchblock.searchparams2, searchparams2,searchblock.sizeofsearchparams2))
        !          3283:                goto freeandexit;
        !          3284: 
        !          3285:        if (error = copyin((caddr_t) searchblock.returnattrs, (caddr_t) returnattrs, sizeof(struct attrlist)))
        !          3286:                goto freeandexit;
        !          3287:                
        !          3288:        if (error = copyin((caddr_t) uap->state, (caddr_t) state, sizeof(struct searchstate)))
        !          3289:                goto freeandexit;
        !          3290:        
        !          3291:        /* set up the uio structure which will contain the users return buffer */
        !          3292: 
        !          3293:        aiov.iov_base = searchblock.returnbuffer;
        !          3294:        aiov.iov_len = searchblock.returnbuffersize;
        !          3295:        auio.uio_iov = &aiov;
        !          3296:        auio.uio_iovcnt = 1;
        !          3297:        auio.uio_rw = UIO_READ;
        !          3298:        auio.uio_segflg = UIO_USERSPACE;
        !          3299:        auio.uio_procp = p;
        !          3300:        auio.uio_resid = searchblock.returnbuffersize;
        !          3301: 
        !          3302:        nameiflags = LOCKLEAF;
        !          3303:        if ((uap->options & FSOPT_NOFOLLOW) == 0) nameiflags |= FOLLOW;
        !          3304:        NDINIT(&nd, LOOKUP, nameiflags, UIO_USERSPACE, uap->path, p);
        !          3305: 
        !          3306:        if (error = namei(&nd))
        !          3307:                goto freeandexit;
        !          3308: 
        !          3309:        vp = nd.ni_vp; 
        !          3310: 
        !          3311:        /*
        !          3312:           Allright, we have everything we need, so lets make that call.
        !          3313:           
        !          3314:           We keep special track of the return value from the file system:
        !          3315:           EAGAIN is an acceptable error condition that shouldn't keep us
        !          3316:           from copying out any results...
        !          3317:         */
        !          3318: 
        !          3319:        fserror = VOP_SEARCHFS(vp,
        !          3320:                                                        searchparams1,
        !          3321:                                                        searchparams2,
        !          3322:                                                        &searchblock.searchattrs,
        !          3323:                                                        searchblock.maxmatches,
        !          3324:                                                        &searchblock.timelimit,
        !          3325:                                                        returnattrs,
        !          3326:                                                        &nummatches,
        !          3327:                                                        uap->scriptcode,
        !          3328:                                                        uap->options,
        !          3329:                                                        &auio,
        !          3330:                                                        state);
        !          3331:                
        !          3332:        vput(vp);
        !          3333: 
        !          3334:        /* Now copy out the stuff that needs copying out. That means the number of matches, the
        !          3335:           search state.  Everything was already put into he return buffer by the vop call. */
        !          3336: 
        !          3337:        if (error = copyout((caddr_t) state, (caddr_t) uap->state, sizeof(struct searchstate)))
        !          3338:                goto freeandexit;
        !          3339: 
        !          3340:        if (error = copyout((caddr_t) &nummatches, (caddr_t) uap->nummatches, sizeof(u_long)))
        !          3341:                goto freeandexit;
        !          3342:        
        !          3343:        error = fserror;
        !          3344: 
        !          3345: freeandexit:
        !          3346: 
        !          3347:        FREE(searchparams1,M_TEMP);
        !          3348: 
        !          3349:        return(error);
        !          3350: 
        !          3351: 
        !          3352: } /* end of searchfs system call */
        !          3353: 
        !          3354: 
        !          3355: /*
        !          3356:  * Make a filesystem-specific control call:
        !          3357:  */
        !          3358: struct fsctl_args {
        !          3359:        const char *path;       /* pathname of the target object */
        !          3360:        u_long cmd;             /* cmd (also encodes size/direction of arguments a la ioctl) */
        !          3361:        caddr_t data;           /* pointer to argument buffer */
        !          3362:        u_long options;         /* options for fsctl processing */
        !          3363: };
        !          3364: /* ARGSUSED */
        !          3365: int
        !          3366: fsctl (p,uap,retval)
        !          3367:        struct proc *p;
        !          3368:        struct fsctl_args *uap;
        !          3369:        register_t *retval;
        !          3370: 
        !          3371: {
        !          3372:        int error;
        !          3373:        struct nameidata nd;    
        !          3374:        u_long nameiflags;
        !          3375:        u_long cmd = uap->cmd;
        !          3376:        register u_int size;
        !          3377: #define STK_PARAMS 128
        !          3378:        char stkbuf[STK_PARAMS];
        !          3379:        caddr_t data, memp;
        !          3380: 
        !          3381:        size = IOCPARM_LEN(cmd);
        !          3382:        if (size > IOCPARM_MAX) return (EINVAL);
        !          3383: 
        !          3384:        memp = NULL;
        !          3385:        if (size > sizeof (stkbuf)) {
        !          3386:                if ((memp = (caddr_t)kalloc(size)) == 0) return ENOMEM;
        !          3387:                data = memp;
        !          3388:        } else {
        !          3389:                data = stkbuf;
        !          3390:        };
        !          3391:        
        !          3392:        if (cmd & IOC_IN) {
        !          3393:                if (size) {
        !          3394:                        error = copyin(uap->data, data, (u_int)size);
        !          3395:                        if (error) goto FSCtl_Exit;
        !          3396:                } else {
        !          3397:                        *(caddr_t *)data = uap->data;
        !          3398:                };
        !          3399:        } else if ((cmd & IOC_OUT) && size) {
        !          3400:                /*
        !          3401:                 * Zero the buffer so the user always
        !          3402:                 * gets back something deterministic.
        !          3403:                 */
        !          3404:                bzero(data, size);
        !          3405:        } else if (cmd & IOC_VOID)
        !          3406:                *(caddr_t *)data = uap->data;
        !          3407: 
        !          3408:        /* Get the vnode for the file we are getting info on:  */
        !          3409:        nameiflags = LOCKLEAF;
        !          3410:        if ((uap->options & FSOPT_NOFOLLOW) == 0) nameiflags |= FOLLOW;
        !          3411:        NDINIT(&nd, LOOKUP, nameiflags, UIO_USERSPACE, uap->path, p);
        !          3412:        if (error = namei(&nd)) goto FSCtl_Exit;
        !          3413:        
        !          3414:        /* Invoke the filesystem-specific code */
        !          3415:        error = VOP_IOCTL(nd.ni_vp, IOCBASECMD(cmd), data, uap->options, p->p_ucred, p);
        !          3416:        
        !          3417:        vput(nd.ni_vp);
        !          3418:        
        !          3419:        /*
        !          3420:         * Copy any data to user, size was
        !          3421:         * already set and checked above.
        !          3422:         */
        !          3423:        if (error == 0 && (cmd & IOC_OUT) && size) error = copyout(data, uap->data, (u_int)size);
        !          3424:        
        !          3425: FSCtl_Exit:
        !          3426:        if (memp) kfree(memp, size);
        !          3427:        
        !          3428:        return error;
        !          3429: }
        !          3430: /* end of fsctl system call */

unix.superglobalmegacorp.com

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