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

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

unix.superglobalmegacorp.com

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