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

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

unix.superglobalmegacorp.com

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