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

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

unix.superglobalmegacorp.com

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