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

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;
1.1.1.2 ! root      603:        if (!mp)
        !           604:                return (EBADF);
1.1       root      605:        sp = &mp->mnt_stat;
                    606:        if (error = VFS_STATFS(mp, sp, p))
                    607:                return (error);
                    608:        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
                    609:        return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
                    610: }
                    611: 
                    612: /*
                    613:  * Get statistics on all filesystems.
                    614:  */
                    615: struct getfsstat_args {
                    616:        struct statfs *buf;
                    617:        long bufsize;
                    618:        int flags;
                    619: };
                    620: int
                    621: getfsstat(p, uap, retval)
                    622:        struct proc *p;
                    623:        register struct getfsstat_args *uap;
                    624:        register_t *retval;
                    625: {
                    626:        register struct mount *mp, *nmp;
                    627:        register struct statfs *sp;
                    628:        caddr_t sfsp;
                    629:        long count, maxcount, error;
                    630: 
                    631:        maxcount = uap->bufsize / sizeof(struct statfs);
                    632:        sfsp = (caddr_t)uap->buf;
                    633:        count = 0;
                    634:        simple_lock(&mountlist_slock);
                    635:        for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
                    636:                if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
                    637:                        nmp = mp->mnt_list.cqe_next;
                    638:                        continue;
                    639:                }
                    640:                if (sfsp && count < maxcount) {
                    641:                        sp = &mp->mnt_stat;
                    642:                        /*
                    643:                         * If MNT_NOWAIT is specified, do not refresh the
                    644:                         * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
                    645:                         */
                    646:                        if (((uap->flags & MNT_NOWAIT) == 0 ||
                    647:                            (uap->flags & MNT_WAIT)) &&
                    648:                            (error = VFS_STATFS(mp, sp, p))) {
                    649:                                simple_lock(&mountlist_slock);
                    650:                                nmp = mp->mnt_list.cqe_next;
                    651:                                vfs_unbusy(mp, p);
                    652:                                continue;
                    653:                        }
                    654:                        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
                    655:                        if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
                    656:                                return (error);
                    657:                        sfsp += sizeof(*sp);
                    658:                }
                    659:                count++;
                    660:                simple_lock(&mountlist_slock);
                    661:                nmp = mp->mnt_list.cqe_next;
                    662:                vfs_unbusy(mp, p);
                    663:        }
                    664:        simple_unlock(&mountlist_slock);
                    665:        if (sfsp && count > maxcount)
                    666:                *retval = maxcount;
                    667:        else
                    668:                *retval = count;
                    669:        return (0);
                    670: }
                    671: 
                    672: /*
                    673:  * Change current working directory to a given file descriptor.
                    674:  */
                    675: struct fchdir_args {
                    676:        int     fd;
                    677: };
                    678: /* ARGSUSED */
                    679: int
                    680: fchdir(p, uap, retval)
                    681:        struct proc *p;
                    682:        struct fchdir_args *uap;
                    683:        register_t *retval;
                    684: {
                    685:        register struct filedesc *fdp = p->p_fd;
                    686:        struct vnode *vp, *tdp;
                    687:        struct mount *mp;
                    688:        struct file *fp;
                    689:        int error;
                    690: 
                    691:        if (error = getvnode(p, uap->fd, &fp))
                    692:                return (error);
                    693:        vp = (struct vnode *)fp->f_data;
                    694:        VREF(vp);
                    695:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                    696:        if (vp->v_type != VDIR)
                    697:                error = ENOTDIR;
                    698:        else
                    699:                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
                    700:        while (!error && (mp = vp->v_mountedhere) != NULL) {
                    701:                if (vfs_busy(mp, 0, 0, p))
                    702:                        continue;
                    703:                error = VFS_ROOT(mp, &tdp);
                    704:                vfs_unbusy(mp, p);
                    705:                if (error)
                    706:                        break;
                    707:                vput(vp);
                    708:                vp = tdp;
                    709:        }
                    710:        if (error) {
                    711:                vput(vp);
                    712:                return (error);
                    713:        }
                    714:        VOP_UNLOCK(vp, 0, p);
                    715:        vrele(fdp->fd_cdir);
                    716:        fdp->fd_cdir = vp;
                    717:        return (0);
                    718: }
                    719: 
                    720: /*
                    721:  * Change current working directory (``.'').
                    722:  */
                    723: struct chdir_args {
                    724:        char    *path;
                    725: };
                    726: /* ARGSUSED */
                    727: int
                    728: chdir(p, uap, retval)
                    729:        struct proc *p;
                    730:        struct chdir_args *uap;
                    731:        register_t *retval;
                    732: {
                    733:        register struct filedesc *fdp = p->p_fd;
                    734:        int error;
                    735:        struct nameidata nd;
                    736: 
                    737:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                    738:            uap->path, p);
                    739:        if (error = change_dir(&nd, p))
                    740:                return (error);
                    741:        vrele(fdp->fd_cdir);
                    742:        fdp->fd_cdir = nd.ni_vp;
                    743:        return (0);
                    744: }
                    745: 
                    746: /*
                    747:  * Change notion of root (``/'') directory.
                    748:  */
                    749: struct chroot_args {
                    750:        char    *path;
                    751: };
                    752: /* ARGSUSED */
                    753: int
                    754: chroot(p, uap, retval)
                    755:        struct proc *p;
                    756:        struct chroot_args *uap;
                    757:        register_t *retval;
                    758: {
                    759:        register struct filedesc *fdp = p->p_fd;
                    760:        int error;
                    761:        struct nameidata nd;
                    762: 
                    763:        if (error = suser(p->p_ucred, &p->p_acflag))
                    764:                return (error);
                    765:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                    766:            uap->path, p);
                    767:        if (error = change_dir(&nd, p))
                    768:                return (error);
                    769:        if (fdp->fd_rdir != NULL)
                    770:                vrele(fdp->fd_rdir);
                    771:        fdp->fd_rdir = nd.ni_vp;
                    772:        return (0);
                    773: }
                    774: 
                    775: /*
                    776:  * Common routine for chroot and chdir.
                    777:  */
                    778: static int
                    779: change_dir(ndp, p)
                    780:        register struct nameidata *ndp;
                    781:        struct proc *p;
                    782: {
                    783:        struct vnode *vp;
                    784:        int error;
                    785: 
                    786:        if (error = namei(ndp))
                    787:                return (error);
                    788:        vp = ndp->ni_vp;
                    789:        if (vp->v_type != VDIR)
                    790:                error = ENOTDIR;
                    791:        else
                    792:                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
                    793:        if (error)
                    794:                vput(vp);
                    795:        else
                    796:                VOP_UNLOCK(vp, 0, p);
                    797:        return (error);
                    798: }
                    799: 
                    800: /*
                    801:  * Check permissions, allocate an open file structure,
                    802:  * and call the device open routine if any.
                    803:  */
                    804: struct open_args {
                    805:        char    *path;
                    806:        int     flags;
                    807:        int     mode;
                    808: };
                    809: int
                    810: open(p, uap, retval)
                    811:        struct proc *p;
                    812:        register struct open_args *uap;
                    813:        register_t *retval;
                    814: {
                    815:        register struct filedesc *fdp = p->p_fd;
                    816:        register struct file *fp;
                    817:        register struct vnode *vp;
                    818:        int flags, cmode;
                    819:        struct file *nfp;
                    820:        int type, indx, error;
                    821:        struct flock lf;
                    822:        struct nameidata nd;
                    823:        extern struct fileops vnops;
                    824: 
                    825:        /* CERT advisory patch applied from FreeBSD */
                    826:        /* Refer to Radar#2262895 A. Ramesh */
                    827:        flags = FFLAGS(uap->flags);
                    828:        if ((flags & (FREAD | FWRITE))==0)
                    829:                return(EINVAL);
                    830:        if (error = falloc(p, &nfp, &indx))
                    831:                return (error);
                    832:        fp = nfp;
                    833:        cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
                    834:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
                    835:        p->p_dupfd = -indx - 1;                 /* XXX check for fdopen */
                    836:        if (error = vn_open(&nd, flags, cmode)) {
                    837:                ffree(fp);
                    838:                if ((error == ENODEV || error == ENXIO) &&
                    839:                    p->p_dupfd >= 0 &&                  /* XXX from fdopen */
                    840:                    (error =
                    841:                        dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
                    842:                        *retval = indx;
                    843:                        return (0);
                    844:                }
                    845:                if (error == ERESTART)
                    846:                        error = EINTR;
                    847:                fdrelse(p, indx);
                    848:                return (error);
                    849:        }
                    850:        p->p_dupfd = 0;
                    851:        vp = nd.ni_vp;
                    852:        fp->f_flag = flags & FMASK;
                    853:        fp->f_type = DTYPE_VNODE;
                    854:        fp->f_ops = &vnops;
                    855:        fp->f_data = (caddr_t)vp;
                    856:        if (flags & (O_EXLOCK | O_SHLOCK)) {
                    857:                lf.l_whence = SEEK_SET;
                    858:                lf.l_start = 0;
                    859:                lf.l_len = 0;
                    860:                if (flags & O_EXLOCK)
                    861:                        lf.l_type = F_WRLCK;
                    862:                else
                    863:                        lf.l_type = F_RDLCK;
                    864:                type = F_FLOCK;
                    865:                if ((flags & FNONBLOCK) == 0)
                    866:                        type |= F_WAIT;
                    867:                VOP_UNLOCK(vp, 0, p);
                    868:                if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
                    869:                        (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
                    870:                        ffree(fp);
                    871:                        fdrelse(p, indx);
                    872:                        return (error);
                    873:                }
                    874:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                    875:                fp->f_flag |= FHASLOCK;
                    876:        }
                    877:        VOP_UNLOCK(vp, 0, p);
                    878:        *fdflags(p, indx) &= ~UF_RESERVED;
                    879:        *retval = indx;
                    880:        return (0);
                    881: }
                    882: 
                    883: #if COMPAT_43
                    884: /*
                    885:  * Create a file.
                    886:  */
                    887: struct ocreat_args {
                    888:        char    *path;
                    889:        int     mode;
                    890: };
                    891: int
                    892: ocreat(p, uap, retval)
                    893:        struct proc *p;
                    894:        register struct ocreat_args *uap;
                    895:        register_t *retval;
                    896: {
                    897:        struct open_args nuap;
                    898: 
                    899:        nuap.path = uap->path;
                    900:        nuap.mode = uap->mode;
                    901:        nuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
                    902:        return (open(p, &nuap, retval));
                    903: }
                    904: #endif /* COMPAT_43 */
                    905: 
                    906: /*
                    907:  * Create a special file.
                    908:  */
                    909: struct mknod_args {
                    910:        char    *path;
                    911:        int     mode;
                    912:        int     dev;
                    913: };
                    914: /* ARGSUSED */
                    915: int
                    916: mknod(p, uap, retval)
                    917:        struct proc *p;
                    918:        register struct mknod_args *uap;
                    919:        register_t *retval;
                    920: {
                    921:        register struct vnode *vp;
                    922:        struct vattr vattr;
                    923:        int error;
                    924:        int whiteout;
                    925:        struct nameidata nd;
                    926: 
                    927:        if (error = suser(p->p_ucred, &p->p_acflag))
                    928:                return (error);
                    929:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
                    930:        if (error = namei(&nd))
                    931:                return (error);
                    932:        vp = nd.ni_vp;
                    933:        if (vp != NULL)
                    934:                error = EEXIST;
                    935:        else {
                    936:                VATTR_NULL(&vattr);
                    937:                vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
                    938:                vattr.va_rdev = uap->dev;
                    939:                whiteout = 0;
                    940: 
                    941:                switch (uap->mode & S_IFMT) {
                    942:                case S_IFMT:    /* used by badsect to flag bad sectors */
                    943:                        vattr.va_type = VBAD;
                    944:                        break;
                    945:                case S_IFCHR:
                    946:                        vattr.va_type = VCHR;
                    947:                        break;
                    948:                case S_IFBLK:
                    949:                        vattr.va_type = VBLK;
                    950:                        break;
                    951:                case S_IFWHT:
                    952:                        whiteout = 1;
                    953:                        break;
                    954:                default:
                    955:                        error = EINVAL;
                    956:                        break;
                    957:                }
                    958:        }
                    959:        if (!error) {
                    960:                VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
                    961:                if (whiteout) {
                    962:                        error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
                    963:                        if (error)
                    964:                                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                    965:                        vput(nd.ni_dvp);
                    966:                } else {
                    967:                        error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
                    968:                                                &nd.ni_cnd, &vattr);
                    969:                }
                    970:        } else {
                    971:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                    972:                if (nd.ni_dvp == vp)
                    973:                        vrele(nd.ni_dvp);
                    974:                else
                    975:                        vput(nd.ni_dvp);
                    976:                if (vp)
                    977:                        vrele(vp);
                    978:        }
                    979:        return (error);
                    980: }
                    981: 
                    982: /*
                    983:  * Create a named pipe.
                    984:  */
                    985: struct mkfifo_args {
                    986:        char    *path;
                    987:        int     mode;
                    988: };
                    989: /* ARGSUSED */
                    990: int
                    991: mkfifo(p, uap, retval)
                    992:        struct proc *p;
                    993:        register struct mkfifo_args *uap;
                    994:        register_t *retval;
                    995: {
                    996:        struct vattr vattr;
                    997:        int error;
                    998:        struct nameidata nd;
                    999: 
                   1000: #if !FIFO 
                   1001:        return (EOPNOTSUPP);
                   1002: #else
                   1003:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
                   1004:        if (error = namei(&nd))
                   1005:                return (error);
                   1006:        if (nd.ni_vp != NULL) {
                   1007:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1008:                if (nd.ni_dvp == nd.ni_vp)
                   1009:                        vrele(nd.ni_dvp);
                   1010:                else
                   1011:                        vput(nd.ni_dvp);
                   1012:                vrele(nd.ni_vp);
                   1013:                return (EEXIST);
                   1014:        }
                   1015:        VATTR_NULL(&vattr);
                   1016:        vattr.va_type = VFIFO;
                   1017:        vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
                   1018:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
                   1019:        return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
                   1020: #endif /* FIFO */
                   1021: }
                   1022: 
                   1023: /*
                   1024:  * Make a hard file link.
                   1025:  */
                   1026: struct link_args {
                   1027:        char    *path;
                   1028:        char    *link;
                   1029: };
                   1030: /* ARGSUSED */
                   1031: int
                   1032: link(p, uap, retval)
                   1033:        struct proc *p;
                   1034:        register struct link_args *uap;
                   1035:        register_t *retval;
                   1036: {
                   1037:        register struct vnode *vp;
                   1038:        struct nameidata nd;
                   1039:        int error;
                   1040: 
                   1041:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
                   1042:        if (error = namei(&nd))
                   1043:                return (error);
                   1044:        vp = nd.ni_vp;
                   1045:        if (vp->v_type == VDIR)
                   1046:                error = EPERM;   /* POSIX */
                   1047:        else {
                   1048:                nd.ni_cnd.cn_nameiop = CREATE;
                   1049:                nd.ni_cnd.cn_flags = LOCKPARENT;
                   1050:                nd.ni_dirp = uap->link;
                   1051:                if ((error = namei(&nd)) == 0) {
                   1052:                        if (nd.ni_vp != NULL)
                   1053:                                error = EEXIST;
                   1054:                        if (!error) {
                   1055:                                VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
                   1056:                                    LEASE_WRITE);
                   1057:                                VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1058:                                error = VOP_LINK(vp, nd.ni_dvp, &nd.ni_cnd);
                   1059:                        } else {
                   1060:                                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1061:                                if (nd.ni_dvp == nd.ni_vp)
                   1062:                                        vrele(nd.ni_dvp);
                   1063:                                else
                   1064:                                        vput(nd.ni_dvp);
                   1065:                                if (nd.ni_vp)
                   1066:                                        vrele(nd.ni_vp);
                   1067:                        }
                   1068:                }
                   1069:        }
                   1070:        vrele(vp);
                   1071:        return (error);
                   1072: }
                   1073: 
                   1074: /*
                   1075:  * Make a symbolic link.
                   1076:  */
                   1077: struct symlink_args {
                   1078:        char    *path;
                   1079:        char    *link;
                   1080: };
                   1081: /* ARGSUSED */
                   1082: int
                   1083: symlink(p, uap, retval)
                   1084:        struct proc *p;
                   1085:        register struct symlink_args *uap;
                   1086:        register_t *retval;
                   1087: {
                   1088:        struct vattr vattr;
                   1089:        char *path;
                   1090:        int error;
                   1091:        struct nameidata nd;
                   1092: 
                   1093:        MALLOC_ZONE(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
                   1094:        if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL))
                   1095:                goto out;
                   1096:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
                   1097:        if (error = namei(&nd))
                   1098:                goto out;
                   1099:        if (nd.ni_vp) {
                   1100:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1101:                if (nd.ni_dvp == nd.ni_vp)
                   1102:                        vrele(nd.ni_dvp);
                   1103:                else
                   1104:                        vput(nd.ni_dvp);
                   1105:                vrele(nd.ni_vp);
                   1106:                error = EEXIST;
                   1107:                goto out;
                   1108:        }
                   1109:        VATTR_NULL(&vattr);
                   1110:        vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
                   1111:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
                   1112:        error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
                   1113: out:
                   1114:        FREE_ZONE(path, MAXPATHLEN, M_NAMEI);
                   1115:        return (error);
                   1116: }
                   1117: 
                   1118: /*
                   1119:  * Delete a whiteout from the filesystem.
                   1120:  */
                   1121: struct undelete_args {
                   1122:        char    *path;
                   1123: };
                   1124: /* ARGSUSED */
                   1125: int
                   1126: undelete(p, uap, retval)
                   1127:        struct proc *p;
                   1128:        register struct undelete_args *uap;
                   1129:        register_t *retval;
                   1130: {
                   1131:        int error;
                   1132:        struct nameidata nd;
                   1133: 
                   1134:        NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
                   1135:            uap->path, p);
                   1136:        error = namei(&nd);
                   1137:        if (error)
                   1138:                return (error);
                   1139: 
                   1140:        if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
                   1141:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1142:                if (nd.ni_dvp == nd.ni_vp)
                   1143:                        vrele(nd.ni_dvp);
                   1144:                else
                   1145:                        vput(nd.ni_dvp);
                   1146:                if (nd.ni_vp)
                   1147:                        vrele(nd.ni_vp);
                   1148:                return (EEXIST);
                   1149:        }
                   1150: 
                   1151:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
                   1152:        if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE))
                   1153:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1154:        vput(nd.ni_dvp);
                   1155:        return (error);
                   1156: }
                   1157: 
                   1158: /*
                   1159:  * Delete a name from the filesystem.
                   1160:  */
                   1161: struct unlink_args {
                   1162:        char    *path;
                   1163: };
                   1164: /* ARGSUSED */
                   1165: int
                   1166: unlink(p, uap, retval)
                   1167:        struct proc *p;
                   1168:        struct unlink_args *uap;
                   1169:        register_t *retval;
                   1170: {
                   1171:        register struct vnode *vp;
                   1172:        int error;
                   1173:        struct nameidata nd;
                   1174: 
                   1175:        NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
                   1176:        if (error = namei(&nd))
                   1177:                return (error);
                   1178:        vp = nd.ni_vp;
                   1179:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1180:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   1181: 
                   1182:        if (vp->v_type == VDIR)
                   1183:                error = EPERM;  /* POSIX */
                   1184:        else {
                   1185:                /*
                   1186:                 * The root of a mounted filesystem cannot be deleted.
                   1187:                 *
                   1188:                 * XXX: can this only be a VDIR case?
                   1189:                 */
                   1190:                if (vp->v_flag & VROOT)
                   1191:                        error = EBUSY;
                   1192:                else
                   1193:                        (void) vnode_uncache(vp);
                   1194:        }
                   1195: 
                   1196:        if (!error) {
                   1197:                VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
                   1198:                error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
                   1199:        } else {
                   1200:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1201:                if (nd.ni_dvp == vp)
                   1202:                        vrele(nd.ni_dvp);
                   1203:                else
                   1204:                        vput(nd.ni_dvp);
                   1205:                if (vp != NULLVP)
                   1206:                        vput(vp);
                   1207:        }
                   1208:        return (error);
                   1209: }
                   1210: 
                   1211: /*
                   1212:  * Reposition read/write file offset.
                   1213:  */
                   1214: struct lseek_args {
                   1215:        int     fd;
                   1216: #ifdef DOUBLE_ALIGN_PARAMS
                   1217:        int pad;
                   1218: #endif
                   1219:        off_t   offset;
                   1220:        int     whence;
                   1221: };
                   1222: int
                   1223: lseek(p, uap, retval)
                   1224:        struct proc *p;
                   1225:        register struct lseek_args *uap;
                   1226:        register_t *retval;
                   1227: {
                   1228:        struct ucred *cred = p->p_ucred;
                   1229:        struct file *fp;
                   1230:        struct vattr vattr;
                   1231:        int error;
                   1232: 
                   1233:        if (error = fdgetf(p, uap->fd, &fp))
                   1234:                return (error);
                   1235:        if (fp->f_type != DTYPE_VNODE)
                   1236:                return (ESPIPE);
                   1237:        switch (uap->whence) {
                   1238:        case L_INCR:
                   1239:                fp->f_offset += uap->offset;
                   1240:                break;
                   1241:        case L_XTND:
                   1242:                if (error =
                   1243:                    VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p))
                   1244:                        return (error);
                   1245:                fp->f_offset = uap->offset + vattr.va_size;
                   1246:                break;
                   1247:        case L_SET:
                   1248:                fp->f_offset = uap->offset;
                   1249:                break;
                   1250:        default:
                   1251:                return (EINVAL);
                   1252:        }
                   1253:        *(off_t *)retval = fp->f_offset;
                   1254:        return (0);
                   1255: }
                   1256: 
                   1257: #if COMPAT_43
                   1258: /*
                   1259:  * Reposition read/write file offset.
                   1260:  */
                   1261: struct olseek_args {
                   1262:        int     fd;
                   1263:        long    offset;
                   1264:        int     whence;
                   1265: };
                   1266: int
                   1267: olseek(p, uap, retval)
                   1268:        struct proc *p;
                   1269:        register struct olseek_args *uap;
                   1270:        register_t *retval;
                   1271: {
                   1272:        struct lseek_args /* {
                   1273:                syscallarg(int) fd;
                   1274: #ifdef DOUBLE_ALIGN_PARAMS
                   1275:         syscallarg(int) pad;
                   1276: #endif
                   1277:                syscallarg(off_t) offset;
                   1278:                syscallarg(int) whence;
                   1279:        } */ nuap;
                   1280:        off_t qret;
                   1281:        int error;
                   1282: 
                   1283:        nuap.fd = uap->fd;
                   1284:        nuap.offset = uap->offset;
                   1285:        nuap.whence = uap->whence;
                   1286:        error = lseek(p, &nuap, &qret);
                   1287:        *(long *)retval = qret;
                   1288:        return (error);
                   1289: }
                   1290: #endif /* COMPAT_43 */
                   1291: 
                   1292: /*
                   1293:  * Check access permissions.
                   1294:  */
                   1295: struct access_args {
                   1296:        char    *path;
                   1297:        int     flags;
                   1298: };
                   1299: int
                   1300: access(p, uap, retval)
                   1301:        struct proc *p;
                   1302:        register struct access_args *uap;
                   1303:        register_t *retval;
                   1304: {
                   1305:        register struct ucred *cred = p->p_ucred;
                   1306:        register struct vnode *vp;
                   1307:        int error, flags, t_gid, t_uid;
                   1308:        struct nameidata nd;
                   1309: 
                   1310:        t_uid = cred->cr_uid;
                   1311:        t_gid = cred->cr_groups[0];
                   1312:        cred->cr_uid = p->p_cred->p_ruid;
                   1313:        cred->cr_groups[0] = p->p_cred->p_rgid;
                   1314:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                   1315:            uap->path, p);
                   1316:        if (error = namei(&nd))
                   1317:                goto out1;
                   1318:        vp = nd.ni_vp;
                   1319: 
                   1320:        /* Flags == 0 means only check for existence. */
                   1321:        if (uap->flags) {
                   1322:                flags = 0;
                   1323:                if (uap->flags & R_OK)
                   1324:                        flags |= VREAD;
                   1325:                if (uap->flags & W_OK)
                   1326:                        flags |= VWRITE;
                   1327:                if (uap->flags & X_OK)
                   1328:                        flags |= VEXEC;
                   1329:                if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
                   1330:                        error = VOP_ACCESS(vp, flags, cred, p);
                   1331:        }
                   1332:        vput(vp);
                   1333: out1:
                   1334:        cred->cr_uid = t_uid;
                   1335:        cred->cr_groups[0] = t_gid;
                   1336:        return (error);
                   1337: }
                   1338: 
                   1339: #if COMPAT_43
                   1340: /*
                   1341:  * Get file status; this version follows links.
                   1342:  */
                   1343: struct ostat_args {
                   1344:        char    *path;
                   1345:        struct ostat *ub;
                   1346: };
                   1347: /* ARGSUSED */
                   1348: int
                   1349: ostat(p, uap, retval)
                   1350:        struct proc *p;
                   1351:        register struct ostat_args *uap;
                   1352:        register_t *retval;
                   1353: {
                   1354:        struct stat sb;
                   1355:        struct ostat osb;
                   1356:        int error;
                   1357:        struct nameidata nd;
                   1358: 
                   1359:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                   1360:            uap->path, p);
                   1361:        if (error = namei(&nd))
                   1362:                return (error);
                   1363:        error = vn_stat(nd.ni_vp, &sb, p);
                   1364:        vput(nd.ni_vp);
                   1365:        if (error)
                   1366:                return (error);
                   1367:        cvtstat(&sb, &osb);
                   1368:        error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
                   1369:        return (error);
                   1370: }
                   1371: 
                   1372: /*
                   1373:  * Get file status; this version does not follow links.
                   1374:  */
                   1375: struct olstat_args {
                   1376:        char    *path;
                   1377:        struct ostat *ub;
                   1378: };
                   1379: /* ARGSUSED */
                   1380: int
                   1381: olstat(p, uap, retval)
                   1382:        struct proc *p;
                   1383:        register struct olstat_args *uap;
                   1384:        register_t *retval;
                   1385: {
                   1386:        struct vnode *vp, *dvp;
                   1387:        struct stat sb, sb1;
                   1388:        struct ostat osb;
                   1389:        int error;
                   1390:        struct nameidata nd;
                   1391: 
                   1392:        NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
                   1393:            uap->path, p);
                   1394:        if (error = namei(&nd))
                   1395:                return (error);
                   1396:        /*
                   1397:         * For symbolic links, always return the attributes of its
                   1398:         * containing directory, except for mode, size, and links.
                   1399:         */
                   1400:        vp = nd.ni_vp;
                   1401:        dvp = nd.ni_dvp;
                   1402:        if (vp->v_type != VLNK) {
                   1403:                if (dvp == vp)
                   1404:                        vrele(dvp);
                   1405:                else
                   1406:                        vput(dvp);
                   1407:                error = vn_stat(vp, &sb, p);
                   1408:                vput(vp);
                   1409:                if (error)
                   1410:                        return (error);
                   1411:        } else {
                   1412:                error = vn_stat(dvp, &sb, p);
                   1413:                vput(dvp);
                   1414:                if (error) {
                   1415:                        vput(vp);
                   1416:                        return (error);
                   1417:                }
                   1418:                error = vn_stat(vp, &sb1, p);
                   1419:                vput(vp);
                   1420:                if (error)
                   1421:                        return (error);
                   1422:                sb.st_mode &= ~S_IFDIR;
                   1423:                sb.st_mode |= S_IFLNK;
                   1424:                sb.st_nlink = sb1.st_nlink;
                   1425:                sb.st_size = sb1.st_size;
                   1426:                sb.st_blocks = sb1.st_blocks;
                   1427:        }
                   1428:        cvtstat(&sb, &osb);
                   1429:        error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
                   1430:        return (error);
                   1431: }
                   1432: 
                   1433: /*
                   1434:  * Convert from an old to a new stat structure.
                   1435:  */
                   1436: void
                   1437: cvtstat(st, ost)
                   1438:        struct stat *st;
                   1439:        struct ostat *ost;
                   1440: {
                   1441: 
                   1442:        ost->st_dev = st->st_dev;
                   1443:        ost->st_ino = st->st_ino;
                   1444:        ost->st_mode = st->st_mode;
                   1445:        ost->st_nlink = st->st_nlink;
                   1446:        ost->st_uid = st->st_uid;
                   1447:        ost->st_gid = st->st_gid;
                   1448:        ost->st_rdev = st->st_rdev;
                   1449:        if (st->st_size < (quad_t)1 << 32)
                   1450:                ost->st_size = st->st_size;
                   1451:        else
                   1452:                ost->st_size = -2;
                   1453:        ost->st_atime = st->st_atime;
                   1454:        ost->st_mtime = st->st_mtime;
                   1455:        ost->st_ctime = st->st_ctime;
                   1456:        ost->st_blksize = st->st_blksize;
                   1457:        ost->st_blocks = st->st_blocks;
                   1458:        ost->st_flags = st->st_flags;
                   1459:        ost->st_gen = st->st_gen;
                   1460: }
                   1461: #endif /* COMPAT_43 */
                   1462: 
                   1463: /*
                   1464:  * Get file status; this version follows links.
                   1465:  */
                   1466: struct stat_args {
                   1467:        char    *path;
                   1468:        struct stat *ub;
                   1469: };
                   1470: /* ARGSUSED */
                   1471: int
                   1472: stat(p, uap, retval)
                   1473:        struct proc *p;
                   1474:        register struct stat_args *uap;
                   1475:        register_t *retval;
                   1476: {
                   1477:        struct stat sb;
                   1478:        int error;
                   1479:        struct nameidata nd;
                   1480: 
                   1481:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                   1482:            uap->path, p);
                   1483:        if (error = namei(&nd))
                   1484:                return (error);
                   1485:        error = vn_stat(nd.ni_vp, &sb, p);
                   1486:        vput(nd.ni_vp);
                   1487:        if (error)
                   1488:                return (error);
                   1489:        error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
                   1490:        return (error);
                   1491: }
                   1492: 
                   1493: /*
                   1494:  * Get file status; this version does not follow links.
                   1495:  */
                   1496: struct lstat_args {
                   1497:        char    *path;
                   1498:        struct stat *ub;
                   1499: };
                   1500: /* ARGSUSED */
                   1501: int
                   1502: lstat(p, uap, retval)
                   1503:        struct proc *p;
                   1504:        register struct lstat_args *uap;
                   1505:        register_t *retval;
                   1506: {
                   1507:        int error;
                   1508:        struct vnode *vp, *dvp;
                   1509:        struct stat sb, sb1;
                   1510:        struct nameidata nd;
                   1511: 
                   1512:        NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
                   1513:            uap->path, p);
                   1514:        if (error = namei(&nd))
                   1515:                return (error);
                   1516:        /*
                   1517:         * For symbolic links, always return the attributes of its containing
                   1518:         * directory, except for mode, size, inode number, and links.
                   1519:         */
                   1520:        vp = nd.ni_vp;
                   1521:        dvp = nd.ni_dvp;
                   1522:        if ((vp->v_type != VLNK) || ((vp->v_type == VLNK) && (vp->v_tag == VT_NFS))) {
                   1523:                if (dvp == vp)
                   1524:                        vrele(dvp);
                   1525:                else
                   1526:                        vput(dvp);
                   1527:                error = vn_stat(vp, &sb, p);
                   1528:                vput(vp);
                   1529:                if (error)
                   1530:                        return (error);
                   1531:                if (vp->v_type == VLNK)
                   1532:                sb.st_mode |= S_IFLNK;
                   1533:        } else {
                   1534:                error = vn_stat(dvp, &sb, p);
                   1535:                vput(dvp);
                   1536:                if (error) {
                   1537:                        vput(vp);
                   1538:                        return (error);
                   1539:                }
                   1540:                error = vn_stat(vp, &sb1, p);
                   1541:                vput(vp);
                   1542:                if (error)
                   1543:                        return (error);
                   1544:                sb.st_mode &= ~S_IFDIR;
                   1545:                sb.st_mode |= S_IFLNK;
                   1546:                sb.st_nlink = sb1.st_nlink;
                   1547:                sb.st_size = sb1.st_size;
                   1548:                sb.st_blocks = sb1.st_blocks;
                   1549:                sb.st_ino = sb1.st_ino;
                   1550:        }
                   1551:        error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
                   1552:        return (error);
                   1553: }
                   1554: 
                   1555: /*
                   1556:  * Get configurable pathname variables.
                   1557:  */
                   1558: struct pathconf_args {
                   1559:        char    *path;
                   1560:        int     name;
                   1561: };
                   1562: /* ARGSUSED */
                   1563: int
                   1564: pathconf(p, uap, retval)
                   1565:        struct proc *p;
                   1566:        register struct pathconf_args *uap;
                   1567:        register_t *retval;
                   1568: {
                   1569:        int error;
                   1570:        struct nameidata nd;
                   1571: 
                   1572:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                   1573:            uap->path, p);
                   1574:        if (error = namei(&nd))
                   1575:                return (error);
                   1576:        error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
                   1577:        vput(nd.ni_vp);
                   1578:        return (error);
                   1579: }
                   1580: 
                   1581: /*
                   1582:  * Return target name of a symbolic link.
                   1583:  */
                   1584: struct readlink_args {
                   1585:        char    *path;
                   1586:        char    *buf;
                   1587:        int     count;
                   1588: };
                   1589: /* ARGSUSED */
                   1590: int
                   1591: readlink(p, uap, retval)
                   1592:        struct proc *p;
                   1593:        register struct readlink_args *uap;
                   1594:        register_t *retval;
                   1595: {
                   1596:        register struct vnode *vp;
                   1597:        struct iovec aiov;
                   1598:        struct uio auio;
                   1599:        int error;
                   1600:        struct nameidata nd;
                   1601: 
                   1602:        NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
                   1603:            uap->path, p);
                   1604:        if (error = namei(&nd))
                   1605:                return (error);
                   1606:        vp = nd.ni_vp;
                   1607:        if (vp->v_type != VLNK)
                   1608:                error = EINVAL;
                   1609:        else {
                   1610:                aiov.iov_base = uap->buf;
                   1611:                aiov.iov_len = uap->count;
                   1612:                auio.uio_iov = &aiov;
                   1613:                auio.uio_iovcnt = 1;
                   1614:                auio.uio_offset = 0;
                   1615:                auio.uio_rw = UIO_READ;
                   1616:                auio.uio_segflg = UIO_USERSPACE;
                   1617:                auio.uio_procp = p;
                   1618:                auio.uio_resid = uap->count;
                   1619:                error = VOP_READLINK(vp, &auio, p->p_ucred);
                   1620:        }
                   1621:        vput(vp);
                   1622:        *retval = uap->count - auio.uio_resid;
                   1623:        return (error);
                   1624: }
                   1625: 
                   1626: /*
                   1627:  * Change flags of a file given a path name.
                   1628:  */
                   1629: struct chflags_args {
                   1630:        char    *path;
                   1631:        int     flags;
                   1632: };
                   1633: /* ARGSUSED */
                   1634: int
                   1635: chflags(p, uap, retval)
                   1636:        struct proc *p;
                   1637:        register struct chflags_args *uap;
                   1638:        register_t *retval;
                   1639: {
                   1640:        register struct vnode *vp;
                   1641:        struct vattr vattr;
                   1642:        int error;
                   1643:        struct nameidata nd;
                   1644: 
                   1645:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
                   1646:        if (error = namei(&nd))
                   1647:                return (error);
                   1648:        vp = nd.ni_vp;
                   1649:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1650:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   1651:        VATTR_NULL(&vattr);
                   1652:        vattr.va_flags = uap->flags;
                   1653:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1654:        vput(vp);
                   1655:        return (error);
                   1656: }
                   1657: 
                   1658: /*
                   1659:  * Change flags of a file given a file descriptor.
                   1660:  */
                   1661: struct fchflags_args {
                   1662:        int     fd;
                   1663:        int     flags;
                   1664: };
                   1665: /* ARGSUSED */
                   1666: int
                   1667: fchflags(p, uap, retval)
                   1668:        struct proc *p;
                   1669:        register struct fchflags_args *uap;
                   1670:        register_t *retval;
                   1671: {
                   1672:        struct vattr vattr;
                   1673:        struct vnode *vp;
                   1674:        struct file *fp;
                   1675:        int error;
                   1676: 
                   1677:        if (error = getvnode(p, uap->fd, &fp))
                   1678:                return (error);
                   1679:        vp = (struct vnode *)fp->f_data;
                   1680:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1681:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   1682:        VATTR_NULL(&vattr);
                   1683:        vattr.va_flags = uap->flags;
                   1684:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1685:        VOP_UNLOCK(vp, 0, p);
                   1686:        return (error);
                   1687: }
                   1688: 
                   1689: /*
                   1690:  * Change mode of a file given path name.
                   1691:  */
                   1692: struct chmod_args {
                   1693:        char    *path;
                   1694:        int     mode;
                   1695: };
                   1696: /* ARGSUSED */
                   1697: int
                   1698: chmod(p, uap, retval)
                   1699:        struct proc *p;
                   1700:        register struct chmod_args *uap;
                   1701:        register_t *retval;
                   1702: {
                   1703:        register struct vnode *vp;
                   1704:        struct vattr vattr;
                   1705:        int error;
                   1706:        struct nameidata nd;
                   1707: 
                   1708:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
                   1709:        if (error = namei(&nd))
                   1710:                return (error);
                   1711:        vp = nd.ni_vp;
                   1712:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1713:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   1714:        VATTR_NULL(&vattr);
                   1715:        vattr.va_mode = uap->mode & ALLPERMS;
                   1716:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1717:        vput(vp);
                   1718:        return (error);
                   1719: }
                   1720: 
                   1721: /*
                   1722:  * Change mode of a file given a file descriptor.
                   1723:  */
                   1724: struct fchmod_args {
                   1725:        int     fd;
                   1726:        int     mode;
                   1727: };
                   1728: /* ARGSUSED */
                   1729: int
                   1730: fchmod(p, uap, retval)
                   1731:        struct proc *p;
                   1732:        register struct fchmod_args *uap;
                   1733:        register_t *retval;
                   1734: {
                   1735:        struct vattr vattr;
                   1736:        struct vnode *vp;
                   1737:        struct file *fp;
                   1738:        int error;
                   1739: 
                   1740:        if (error = getvnode(p, uap->fd, &fp))
                   1741:                return (error);
                   1742:        vp = (struct vnode *)fp->f_data;
                   1743:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1744:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   1745:        VATTR_NULL(&vattr);
                   1746:        vattr.va_mode = uap->mode & ALLPERMS;
                   1747:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1748:        VOP_UNLOCK(vp, 0, p);
                   1749:        return (error);
                   1750: }
                   1751: 
                   1752: /*
                   1753:  * Set ownership given a path name.
                   1754:  */
                   1755: struct chown_args {
                   1756:        char    *path;
                   1757:        int     uid;
                   1758:        int     gid;
                   1759: };
                   1760: /* ARGSUSED */
                   1761: int
                   1762: chown(p, uap, retval)
                   1763:        struct proc *p;
                   1764:        register struct chown_args *uap;
                   1765:        register_t *retval;
                   1766: {
                   1767:        register struct vnode *vp;
                   1768:        struct vattr vattr;
                   1769:        int error;
                   1770:        struct nameidata nd;
                   1771: 
                   1772:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
                   1773:        if (error = namei(&nd))
                   1774:                return (error);
                   1775:        vp = nd.ni_vp;
                   1776:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1777:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   1778:        VATTR_NULL(&vattr);
                   1779:        vattr.va_uid = uap->uid;
                   1780:        vattr.va_gid = uap->gid;
                   1781:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1782:        vput(vp);
                   1783:        return (error);
                   1784: }
                   1785: 
                   1786: /*
                   1787:  * Set ownership given a file descriptor.
                   1788:  */
                   1789: struct fchown_args {
                   1790:        int     fd;
                   1791:        int     uid;
                   1792:        int     gid;
                   1793: };
                   1794: /* ARGSUSED */
                   1795: int
                   1796: fchown(p, uap, retval)
                   1797:        struct proc *p;
                   1798:        register struct fchown_args *uap;
                   1799:        register_t *retval;
                   1800: {
                   1801:        struct vattr vattr;
                   1802:        struct vnode *vp;
                   1803:        struct file *fp;
                   1804:        int error;
                   1805: 
                   1806:        if (error = getvnode(p, uap->fd, &fp))
                   1807:                return (error);
                   1808:        vp = (struct vnode *)fp->f_data;
                   1809:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1810:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   1811:        VATTR_NULL(&vattr);
                   1812:        vattr.va_uid = uap->uid;
                   1813:        vattr.va_gid = uap->gid;
                   1814:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1815:        VOP_UNLOCK(vp, 0, p);
                   1816:        return (error);
                   1817: }
                   1818: 
                   1819: /*
                   1820:  * Set the access and modification times of a file.
                   1821:  */
                   1822: struct utimes_args {
                   1823:        char    *path;
                   1824:        struct  timeval *tptr;
                   1825: };
                   1826: /* ARGSUSED */
                   1827: int
                   1828: utimes(p, uap, retval)
                   1829:        struct proc *p;
                   1830:        register struct utimes_args *uap;
                   1831:        register_t *retval;
                   1832: {
                   1833:        register struct vnode *vp;
                   1834:        struct timeval tv[2];
                   1835:        struct vattr vattr;
                   1836:        int error;
                   1837:        struct nameidata nd;
                   1838: 
                   1839:        VATTR_NULL(&vattr);
                   1840:        if (uap->tptr == NULL) {
                   1841:                microtime(&tv[0]);
                   1842:                tv[1] = tv[0];
                   1843:                vattr.va_vaflags |= VA_UTIMES_NULL;
                   1844:        } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv,
                   1845:            sizeof (tv)))
                   1846:                return (error);
                   1847:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
                   1848:        if (error = namei(&nd))
                   1849:                return (error);
                   1850:        vp = nd.ni_vp;
                   1851:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1852:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   1853:        vattr.va_atime.tv_sec = tv[0].tv_sec;
                   1854:        vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
                   1855:        vattr.va_mtime.tv_sec = tv[1].tv_sec;
                   1856:        vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
                   1857:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1858:        vput(vp);
                   1859:        return (error);
                   1860: }
                   1861: 
                   1862: /*
                   1863:  * Truncate a file given its path name.
                   1864:  */
                   1865: struct truncate_args {
                   1866:        char    *path;
                   1867: #ifdef DOUBLE_ALIGN_PARAMS
                   1868:        int     pad;
                   1869: #endif
                   1870:        off_t   length;
                   1871: };
                   1872: /* ARGSUSED */
                   1873: int
                   1874: truncate(p, uap, retval)
                   1875:        struct proc *p;
                   1876:        register struct truncate_args *uap;
                   1877:        register_t *retval;
                   1878: {
                   1879:        register struct vnode *vp;
                   1880:        struct vattr vattr;
                   1881:        int error;
                   1882:        struct nameidata nd;
                   1883: 
                   1884:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
                   1885:        if (error = namei(&nd))
                   1886:                return (error);
                   1887:        vp = nd.ni_vp;
                   1888:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1889:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   1890:        if (vp->v_type == VDIR)
                   1891:                error = EISDIR;
                   1892:        else if ((error = vn_writechk(vp)) == 0 &&
                   1893:            (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
                   1894:                VATTR_NULL(&vattr);
                   1895:                vattr.va_size = uap->length;
                   1896:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   1897:        }
                   1898:        vput(vp);
                   1899:        return (error);
                   1900: }
                   1901: 
                   1902: /*
                   1903:  * Truncate a file given a file descriptor.
                   1904:  */
                   1905: struct ftruncate_args {
                   1906:        int     fd;
                   1907: #ifdef DOUBLE_ALIGN_PARAMS
                   1908:        int     pad;
                   1909: #endif
                   1910:        off_t   length;
                   1911: };
                   1912: /* ARGSUSED */
                   1913: int
                   1914: ftruncate(p, uap, retval)
                   1915:        struct proc *p;
                   1916:        register struct ftruncate_args *uap;
                   1917:        register_t *retval;
                   1918: {
                   1919:        struct vattr vattr;
                   1920:        struct vnode *vp;
                   1921:        struct file *fp;
                   1922:        int error;
                   1923: 
                   1924:        if (error = getvnode(p, uap->fd, &fp))
                   1925:                return (error);
                   1926:        if ((fp->f_flag & FWRITE) == 0)
                   1927:                return (EINVAL);
                   1928:        vp = (struct vnode *)fp->f_data;
                   1929:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1930:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   1931:        if (vp->v_type == VDIR)
                   1932:                error = EISDIR;
                   1933:        else if ((error = vn_writechk(vp)) == 0) {
                   1934:                VATTR_NULL(&vattr);
                   1935:                vattr.va_size = uap->length;
                   1936:                error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
                   1937:        }
                   1938:        VOP_UNLOCK(vp, 0, p);
                   1939:        return (error);
                   1940: }
                   1941: 
                   1942: #if COMPAT_43
                   1943: /*
                   1944:  * Truncate a file given its path name.
                   1945:  */
                   1946: struct otruncate_args {
                   1947:        char    *path;
                   1948:        long    length;
                   1949: };
                   1950: /* ARGSUSED */
                   1951: int
                   1952: otruncate(p, uap, retval)
                   1953:        struct proc *p;
                   1954:        register struct otruncate_args *uap;
                   1955:        register_t *retval;
                   1956: {
                   1957:        struct truncate_args /* {
                   1958:                syscallarg(char *) path;
                   1959: #ifdef DOUBLE_ALIGN_PARAMS
                   1960:                syscallarg(int) pad;
                   1961: #endif
                   1962:                syscallarg(off_t) length;
                   1963:        } */ nuap;
                   1964: 
                   1965:        nuap.path = uap->path;
                   1966:        nuap.length = uap->length;
                   1967:        return (truncate(p, &nuap, retval));
                   1968: }
                   1969: 
                   1970: /*
                   1971:  * Truncate a file given a file descriptor.
                   1972:  */
                   1973: struct oftruncate_args {
                   1974:        int     fd;
                   1975:        long    length;
                   1976: };
                   1977: /* ARGSUSED */
                   1978: int
                   1979: oftruncate(p, uap, retval)
                   1980:        struct proc *p;
                   1981:        register struct oftruncate_args *uap;
                   1982:        register_t *retval;
                   1983: {
                   1984:        struct ftruncate_args /* {
                   1985:                syscallarg(int) fd;
                   1986: #ifdef DOUBLE_ALIGN_PARAMS
                   1987:                syscallarg(int) pad;
                   1988: #endif
                   1989:                syscallarg(off_t) length;
                   1990:        } */ nuap;
                   1991: 
                   1992:        nuap.fd = uap->fd;
                   1993:        nuap.length = uap->length;
                   1994:        return (ftruncate(p, &nuap, retval));
                   1995: }
                   1996: #endif /* COMPAT_43 */
                   1997: 
                   1998: /*
                   1999:  * Sync an open file.
                   2000:  */
                   2001: struct fsync_args {
                   2002:        int     fd;
                   2003: };
                   2004: /* ARGSUSED */
                   2005: int
                   2006: fsync(p, uap, retval)
                   2007:        struct proc *p;
                   2008:        struct fsync_args *uap;
                   2009:        register_t *retval;
                   2010: {
                   2011:        register struct vnode *vp;
                   2012:        struct file *fp;
                   2013:        int error;
                   2014: 
                   2015:        if (error = getvnode(p, uap->fd, &fp))
                   2016:                return (error);
                   2017:        vp = (struct vnode *)fp->f_data;
                   2018: #if MACH_NBC
                   2019:        mapfs_fsync(vp);
                   2020: #endif
                   2021:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   2022:        error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
                   2023:        VOP_UNLOCK(vp, 0, p);
                   2024:        return (error);
                   2025: }
                   2026: 
                   2027: /*
                   2028:  * Rename files.  Source and destination must either both be directories,
                   2029:  * or both not be directories.  If target is a directory, it must be empty.
                   2030:  */
                   2031: struct rename_args {
                   2032:        char    *from;
                   2033:        char    *to;
                   2034: };
                   2035: /* ARGSUSED */
                   2036: int
                   2037: rename(p, uap, retval)
                   2038:        struct proc *p;
                   2039:        register struct rename_args *uap;
                   2040:        register_t *retval;
                   2041: {
                   2042:        register struct vnode *tvp, *fvp, *tdvp;
                   2043:        struct nameidata fromnd, tond;
                   2044:        int error;
                   2045: 
                   2046:        NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
                   2047:            uap->from, p);
                   2048:        if (error = namei(&fromnd))
                   2049:                return (error);
                   2050:        fvp = fromnd.ni_vp;
                   2051:        NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
                   2052:            UIO_USERSPACE, uap->to, p);
                   2053:        if (error = namei(&tond)) {
                   2054:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
                   2055:                vrele(fromnd.ni_dvp);
                   2056:                vrele(fvp);
                   2057:                goto out1;
                   2058:        }
                   2059:        tdvp = tond.ni_dvp;
                   2060:        tvp = tond.ni_vp;
                   2061:        if (tvp != NULL) {
                   2062:                if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
                   2063:                        error = ENOTDIR;
                   2064:                        goto out;
                   2065:                } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
                   2066:                        error = EISDIR;
                   2067:                        goto out;
                   2068:                }
                   2069:        }
                   2070:        if (fvp == tdvp)
                   2071:                error = EINVAL;
                   2072:        /*
                   2073:         * If source is the same as the destination (that is the
                   2074:         * same inode number) then there is nothing to do.
                   2075:         * (fixed to have POSIX semantics - CSM 3/2/98)
                   2076:         */
                   2077:        if (fvp == tvp)
                   2078:                error = -1;
                   2079: out:
                   2080:        if (!error) {
                   2081:                VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
                   2082:                if (fromnd.ni_dvp != tdvp)
                   2083:                        VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
                   2084:                if (tvp)
                   2085:                        VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
                   2086:                error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
                   2087:                                   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
                   2088:        } else {
                   2089:                VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
                   2090:                if (tdvp == tvp)
                   2091:                        vrele(tdvp);
                   2092:                else
                   2093:                        vput(tdvp);
                   2094:                if (tvp)
                   2095:                        vput(tvp);
                   2096:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
                   2097:                vrele(fromnd.ni_dvp);
                   2098:                vrele(fvp);
                   2099:        }
                   2100:        vrele(tond.ni_startdir);
                   2101:        FREE_ZONE(tond.ni_cnd.cn_pnbuf, tond.ni_cnd.cn_pnlen, M_NAMEI);
                   2102: out1:
                   2103:        if (fromnd.ni_startdir)
                   2104:                vrele(fromnd.ni_startdir);
                   2105:        FREE_ZONE(fromnd.ni_cnd.cn_pnbuf, fromnd.ni_cnd.cn_pnlen, M_NAMEI);
                   2106:        if (error == -1)
                   2107:                return (0);
                   2108:        return (error);
                   2109: }
                   2110: 
                   2111: /*
                   2112:  * Make a directory file.
                   2113:  */
                   2114: struct mkdir_args {
                   2115:        char    *path;
                   2116:        int     mode;
                   2117: };
                   2118: /* ARGSUSED */
                   2119: int
                   2120: mkdir(p, uap, retval)
                   2121:        struct proc *p;
                   2122:        register struct mkdir_args *uap;
                   2123:        register_t *retval;
                   2124: {
                   2125:        register struct vnode *vp;
                   2126:        struct vattr vattr;
                   2127:        int error;
                   2128:        struct nameidata nd;
                   2129: 
                   2130:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
                   2131:        if (error = namei(&nd))
                   2132:                return (error);
                   2133:        vp = nd.ni_vp;
                   2134:        if (vp != NULL) {
                   2135:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   2136:                if (nd.ni_dvp == vp)
                   2137:                        vrele(nd.ni_dvp);
                   2138:                else
                   2139:                        vput(nd.ni_dvp);
                   2140:                vrele(vp);
                   2141:                return (EEXIST);
                   2142:        }
                   2143:        VATTR_NULL(&vattr);
                   2144:        vattr.va_type = VDIR;
                   2145:        vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
                   2146:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
                   2147:        error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
                   2148:        if (!error)
                   2149:                vput(nd.ni_vp);
                   2150:        return (error);
                   2151: }
                   2152: 
                   2153: /*
                   2154:  * Remove a directory file.
                   2155:  */
                   2156: struct rmdir_args {
                   2157:        char    *path;
                   2158: };
                   2159: /* ARGSUSED */
                   2160: int
                   2161: rmdir(p, uap, retval)
                   2162:        struct proc *p;
                   2163:        struct rmdir_args *uap;
                   2164:        register_t *retval;
                   2165: {
                   2166:        register struct vnode *vp;
                   2167:        int error;
                   2168:        struct nameidata nd;
                   2169: 
                   2170:        NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
                   2171:            uap->path, p);
                   2172:        if (error = namei(&nd))
                   2173:                return (error);
                   2174:        vp = nd.ni_vp;
                   2175:        if (vp->v_type != VDIR) {
                   2176:                error = ENOTDIR;
                   2177:                goto out;
                   2178:        }
                   2179:        /*
                   2180:         * No rmdir "." please.
                   2181:         */
                   2182:        if (nd.ni_dvp == vp) {
                   2183:                error = EINVAL;
                   2184:                goto out;
                   2185:        }
                   2186:        /*
                   2187:         * The root of a mounted filesystem cannot be deleted.
                   2188:         */
                   2189:        if (vp->v_flag & VROOT)
                   2190:                error = EBUSY;
                   2191: out:
                   2192:        if (!error) {
                   2193:                VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
                   2194:                VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   2195:                error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
                   2196:        } else {
                   2197:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   2198:                if (nd.ni_dvp == vp)
                   2199:                        vrele(nd.ni_dvp);
                   2200:                else
                   2201:                        vput(nd.ni_dvp);
                   2202:                vput(vp);
                   2203:        }
                   2204:        return (error);
                   2205: }
                   2206: 
                   2207: #if COMPAT_43
                   2208: /*
                   2209:  * Read a block of directory entries in a file system independent format.
                   2210:  */
                   2211: struct ogetdirentries_args {
                   2212:        int     fd;
                   2213:        char    *buf;
                   2214:        u_int   count;
                   2215:        long    *basep;
                   2216: };
                   2217: int
                   2218: ogetdirentries(p, uap, retval)
                   2219:        struct proc *p;
                   2220:        register struct ogetdirentries_args *uap;
                   2221:        register_t *retval;
                   2222: {
                   2223:        register struct vnode *vp;
                   2224:        struct file *fp;
                   2225:        struct uio auio, kuio;
                   2226:        struct iovec aiov, kiov;
                   2227:        struct dirent *dp, *edp;
                   2228:        caddr_t dirbuf;
                   2229:        int error, eofflag, readcnt;
                   2230:        long loff;
                   2231: 
                   2232:        if (error = getvnode(p, uap->fd, &fp))
                   2233:                return (error);
                   2234:        if ((fp->f_flag & FREAD) == 0)
                   2235:                return (EBADF);
                   2236:        vp = (struct vnode *)fp->f_data;
                   2237: unionread:
                   2238:        if (vp->v_type != VDIR)
                   2239:                return (EINVAL);
                   2240:        aiov.iov_base = uap->buf;
                   2241:        aiov.iov_len = uap->count;
                   2242:        auio.uio_iov = &aiov;
                   2243:        auio.uio_iovcnt = 1;
                   2244:        auio.uio_rw = UIO_READ;
                   2245:        auio.uio_segflg = UIO_USERSPACE;
                   2246:        auio.uio_procp = p;
                   2247:        auio.uio_resid = uap->count;
                   2248:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   2249:        loff = auio.uio_offset = fp->f_offset;
                   2250: #      if (BYTE_ORDER != LITTLE_ENDIAN)
                   2251:                if (vp->v_mount->mnt_maxsymlinklen <= 0) {
                   2252:                        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
                   2253:                            (int *)0, (u_long *)0);
                   2254:                        fp->f_offset = auio.uio_offset;
                   2255:                } else
                   2256: #      endif
                   2257:        {
                   2258:                kuio = auio;
                   2259:                kuio.uio_iov = &kiov;
                   2260:                kuio.uio_segflg = UIO_SYSSPACE;
                   2261:                kiov.iov_len = uap->count;
                   2262:                MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
                   2263:                kiov.iov_base = dirbuf;
                   2264:                error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
                   2265:                            (int *)0, (u_long *)0);
                   2266:                fp->f_offset = kuio.uio_offset;
                   2267:                if (error == 0) {
                   2268:                        readcnt = uap->count - kuio.uio_resid;
                   2269:                        edp = (struct dirent *)&dirbuf[readcnt];
                   2270:                        for (dp = (struct dirent *)dirbuf; dp < edp; ) {
                   2271: #                              if (BYTE_ORDER == LITTLE_ENDIAN)
                   2272:                                        /*
                   2273:                                         * The expected low byte of
                   2274:                                         * dp->d_namlen is our dp->d_type.
                   2275:                                         * The high MBZ byte of dp->d_namlen
                   2276:                                         * is our dp->d_namlen.
                   2277:                                         */
                   2278:                                        dp->d_type = dp->d_namlen;
                   2279:                                        dp->d_namlen = 0;
                   2280: #                              else
                   2281:                                        /*
                   2282:                                         * The dp->d_type is the high byte
                   2283:                                         * of the expected dp->d_namlen,
                   2284:                                         * so must be zero'ed.
                   2285:                                         */
                   2286:                                        dp->d_type = 0;
                   2287: #                              endif
                   2288:                                if (dp->d_reclen > 0) {
                   2289:                                        dp = (struct dirent *)
                   2290:                                            ((char *)dp + dp->d_reclen);
                   2291:                                } else {
                   2292:                                        error = EIO;
                   2293:                                        break;
                   2294:                                }
                   2295:                        }
                   2296:                        if (dp >= edp)
                   2297:                                error = uiomove(dirbuf, readcnt, &auio);
                   2298:                }
                   2299:                FREE(dirbuf, M_TEMP);
                   2300:        }
                   2301:        VOP_UNLOCK(vp, 0, p);
                   2302:        if (error)
                   2303:                return (error);
                   2304: 
                   2305: #if UNION
                   2306: {
                   2307:        extern int (**union_vnodeop_p)();
                   2308:        extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
                   2309: 
                   2310:        if ((uap->count == auio.uio_resid) &&
                   2311:            (vp->v_op == union_vnodeop_p)) {
                   2312:                struct vnode *lvp;
                   2313: 
                   2314:                lvp = union_dircache(vp, p);
                   2315:                if (lvp != NULLVP) {
                   2316:                        struct vattr va;
                   2317: 
                   2318:                        /*
                   2319:                         * If the directory is opaque,
                   2320:                         * then don't show lower entries
                   2321:                         */
                   2322:                        error = VOP_GETATTR(vp, &va, fp->f_cred, p);
                   2323:                        if (va.va_flags & OPAQUE) {
                   2324:                                vput(lvp);
                   2325:                                lvp = NULL;
                   2326:                        }
                   2327:                }
                   2328:                
                   2329:                if (lvp != NULLVP) {
                   2330:                        error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
                   2331:                        if (error) {
                   2332:                                vput(lvp);
                   2333:                                return (error);
                   2334:                        }
                   2335:                        VOP_UNLOCK(lvp, 0, p);
                   2336:                        fp->f_data = (caddr_t) lvp;
                   2337:                        fp->f_offset = 0;
                   2338:                        error = vn_close(vp, FREAD, fp->f_cred, p);
                   2339:                        if (error)
                   2340:                                return (error);
                   2341:                        vp = lvp;
                   2342:                        goto unionread;
                   2343:                }
                   2344:        }
                   2345: }
                   2346: #endif /* UNION */
                   2347: 
                   2348:        if ((uap->count == auio.uio_resid) &&
                   2349:            (vp->v_flag & VROOT) &&
                   2350:            (vp->v_mount->mnt_flag & MNT_UNION)) {
                   2351:                struct vnode *tvp = vp;
                   2352:                vp = vp->v_mount->mnt_vnodecovered;
                   2353:                VREF(vp);
                   2354:                fp->f_data = (caddr_t) vp;
                   2355:                fp->f_offset = 0;
                   2356:                vrele(tvp);
                   2357:                goto unionread;
                   2358:        }
                   2359:        error = copyout((caddr_t)&loff, (caddr_t)uap->basep,
                   2360:            sizeof(long));
                   2361:        *retval = uap->count - auio.uio_resid;
                   2362:        return (error);
                   2363: }
                   2364: #endif /* COMPAT_43 */
                   2365: 
                   2366: /*
                   2367:  * Read a block of directory entries in a file system independent format.
                   2368:  */
                   2369: struct getdirentries_args {
                   2370:        int     fd;
                   2371:        char    *buf;
                   2372:        u_int   count;
                   2373:        long    *basep;
                   2374: };
                   2375: int
                   2376: getdirentries(p, uap, retval)
                   2377:        struct proc *p;
                   2378:        register struct getdirentries_args *uap;
                   2379:        register_t *retval;
                   2380: {
                   2381:        register struct vnode *vp;
                   2382:        struct file *fp;
                   2383:        struct uio auio;
                   2384:        struct iovec aiov;
                   2385:        long loff;
                   2386:        int error, eofflag;
                   2387: 
                   2388:        if (error = getvnode(p, uap->fd, &fp))
                   2389:                return (error);
                   2390:        if ((fp->f_flag & FREAD) == 0)
                   2391:                return (EBADF);
                   2392:        vp = (struct vnode *)fp->f_data;
                   2393: unionread:
                   2394:        if (vp->v_type != VDIR)
                   2395:                return (EINVAL);
                   2396:        aiov.iov_base = uap->buf;
                   2397:        aiov.iov_len = uap->count;
                   2398:        auio.uio_iov = &aiov;
                   2399:        auio.uio_iovcnt = 1;
                   2400:        auio.uio_rw = UIO_READ;
                   2401:        auio.uio_segflg = UIO_USERSPACE;
                   2402:        auio.uio_procp = p;
                   2403:        auio.uio_resid = uap->count;
                   2404:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   2405:        loff = auio.uio_offset = fp->f_offset;
                   2406:        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
                   2407:                            (int *)0, (u_long *)0);
                   2408:        fp->f_offset = auio.uio_offset;
                   2409:        VOP_UNLOCK(vp, 0, p);
                   2410:        if (error)
                   2411:                return (error);
                   2412: 
                   2413: #if UNION
                   2414: {
                   2415:        extern int (**union_vnodeop_p)();
                   2416:        extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
                   2417: 
                   2418:        if ((uap->count == auio.uio_resid) &&
                   2419:            (vp->v_op == union_vnodeop_p)) {
                   2420:                struct vnode *lvp;
                   2421: 
                   2422:                lvp = union_dircache(vp, p);
                   2423:                if (lvp != NULLVP) {
                   2424:                        struct vattr va;
                   2425: 
                   2426:                        /*
                   2427:                         * If the directory is opaque,
                   2428:                         * then don't show lower entries
                   2429:                         */
                   2430:                        error = VOP_GETATTR(vp, &va, fp->f_cred, p);
                   2431:                        if (va.va_flags & OPAQUE) {
                   2432:                                vput(lvp);
                   2433:                                lvp = NULL;
                   2434:                        }
                   2435:                }
                   2436: 
                   2437:                if (lvp != NULLVP) {
                   2438:                        error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
                   2439:                        if (error) {
                   2440:                                vput(lvp);
                   2441:                                return (error);
                   2442:                        }
                   2443:                        VOP_UNLOCK(lvp, 0, p);
                   2444:                        fp->f_data = (caddr_t) lvp;
                   2445:                        fp->f_offset = 0;
                   2446:                        error = vn_close(vp, FREAD, fp->f_cred, p);
                   2447:                        if (error)
                   2448:                                return (error);
                   2449:                        vp = lvp;
                   2450:                        goto unionread;
                   2451:                }
                   2452:        }
                   2453: }
                   2454: #endif /* UNION */
                   2455: 
                   2456:        if ((uap->count == auio.uio_resid) &&
                   2457:            (vp->v_flag & VROOT) &&
                   2458:            (vp->v_mount->mnt_flag & MNT_UNION)) {
                   2459:                struct vnode *tvp = vp;
                   2460:                vp = vp->v_mount->mnt_vnodecovered;
                   2461:                VREF(vp);
                   2462:                fp->f_data = (caddr_t) vp;
                   2463:                fp->f_offset = 0;
                   2464:                vrele(tvp);
                   2465:                goto unionread;
                   2466:        }
                   2467:        error = copyout((caddr_t)&loff, (caddr_t)uap->basep,
                   2468:            sizeof(long));
                   2469:        *retval = uap->count - auio.uio_resid;
                   2470:        return (error);
                   2471: }
                   2472: 
                   2473: /*
                   2474:  * Set the mode mask for creation of filesystem nodes.
                   2475:  */
                   2476: struct umask_args {
                   2477:        int     newmask;
                   2478: };
                   2479: int
                   2480: umask(p, uap, retval)
                   2481:        struct proc *p;
                   2482:        struct umask_args *uap;
                   2483:        register_t *retval;
                   2484: {
                   2485:        register struct filedesc *fdp;
                   2486: 
                   2487:        fdp = p->p_fd;
                   2488:        *retval = fdp->fd_cmask;
                   2489:        fdp->fd_cmask = uap->newmask & ALLPERMS;
                   2490:        return (0);
                   2491: }
                   2492: 
                   2493: /*
                   2494:  * Void all references to file by ripping underlying filesystem
                   2495:  * away from vnode.
                   2496:  */
                   2497: struct revoke_args {
                   2498:        char    *path;
                   2499: };
                   2500: /* ARGSUSED */
                   2501: int
                   2502: revoke(p, uap, retval)
                   2503:        struct proc *p;
                   2504:        register struct revoke_args *uap;
                   2505:        register_t *retval;
                   2506: {
                   2507:        register struct vnode *vp;
                   2508:        struct vattr vattr;
                   2509:        int error;
                   2510:        struct nameidata nd;
                   2511: 
                   2512:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
                   2513:        if (error = namei(&nd))
                   2514:                return (error);
                   2515:        vp = nd.ni_vp;
                   2516:        if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
                   2517:                goto out;
                   2518:        if (p->p_ucred->cr_uid != vattr.va_uid &&
                   2519:            (error = suser(p->p_ucred, &p->p_acflag)))
                   2520:                goto out;
                   2521:        if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
                   2522:                VOP_REVOKE(vp, REVOKEALL);
                   2523: out:
                   2524:        vrele(vp);
                   2525:        return (error);
                   2526: }
                   2527: 
                   2528: /*
                   2529:  * Convert a user file descriptor to a kernel file entry.
                   2530:  */
                   2531: int
                   2532: getvnode(p, fd, fpp)
                   2533:        struct proc *p;
                   2534:        int fd;
                   2535:        struct file **fpp;
                   2536: {
                   2537:        struct file *fp;
                   2538:        int error;
                   2539: 
                   2540:        if (error = fdgetf(p, fd, &fp))
                   2541:                return (error);
                   2542:        if (fp->f_type != DTYPE_VNODE)
                   2543:                return (EINVAL);
                   2544:        *fpp = fp;
                   2545:        return (0);
                   2546: }
                   2547: /*
                   2548:  *  HFS/HFS PlUS SPECIFIC SYSTEM CALLS
                   2549:  *  The following 10 system calls are designed to support features
                   2550:  *  which are specific to the HFS & HFS Plus volume formats
                   2551:  */
                   2552: 
                   2553: 
                   2554: /*
                   2555:  * Make a complex file.  A complex file is one with multiple forks (data streams)
                   2556:  */
                   2557: struct mkcomplex_args {
                   2558:         const char *path;      /* pathname of the file to be created */
                   2559:        mode_t mode;            /* access mode for the newly created file */
                   2560:         u_long type;           /* format of the complex file */
                   2561: };
                   2562: /* ARGSUSED */
                   2563: int
                   2564: mkcomplex(p,uap,retval)
                   2565:        struct proc *p;
                   2566:         register struct mkcomplex_args *uap;
                   2567:         register_t *retval;
                   2568:                        
                   2569: {
                   2570:        struct vnode *vp;
                   2571:         struct vattr vattr;
                   2572:         int error;
                   2573:         struct nameidata nd;
                   2574: 
                   2575:        /* mkcomplex wants the directory vnode locked so do that here */
                   2576: 
                   2577:         NDINIT(&nd, CREATE, FOLLOW | LOCKPARENT, UIO_USERSPACE, uap->path, p);
                   2578:         if (error = namei(&nd))
                   2579:                 return (error);
                   2580: 
                   2581:        /*  Set the attributes as specified by the user */
                   2582: 
                   2583:         VATTR_NULL(&vattr);
                   2584:         vattr.va_mode = (uap->mode & ACCESSPERMS);
                   2585:         error = VOP_MKCOMPLEX(nd.ni_dvp, &vp, &nd.ni_cnd, &vattr, uap->type);
                   2586: 
                   2587:        /*  The mkcomplex call promises to release the parent vnode pointer
                   2588:         *  even an an error case so don't do it here unless the operation
                   2589:         *  is not supported.  In that case, there isn't anyone to unlock the parent
                   2590:         *  The vnode pointer to the file will also be released.
                   2591:         */
                   2592: 
                   2593:         if (error)
                   2594:                {
                   2595:                        if (error == EOPNOTSUPP)
                   2596:                        vput(nd.ni_dvp);
                   2597:                 return (error);
                   2598:                }
                   2599: 
                   2600:         return (0);
                   2601: 
                   2602: } /* end of mkcomplex system call */
                   2603: 
                   2604: 
                   2605: 
                   2606: /*
                   2607:  * Extended stat call which returns volumeid and vnodeid as well as other info
                   2608:  */
                   2609: struct statv_args {
                   2610:         const char *path;      /* pathname of the target file       */
                   2611:         struct vstat *vsb;     /* vstat structure for returned info */
                   2612: };
                   2613: /* ARGSUSED */
                   2614: int
                   2615: statv(p,uap,retval)
                   2616:         struct proc *p;
                   2617:         register struct statv_args *uap;
                   2618:         register_t *retval;
                   2619: 
                   2620: {
                   2621:        return (EOPNOTSUPP);    /*  We'll just return an error for now */
                   2622: 
                   2623: } /* end of statv system call */
                   2624: 
                   2625: 
                   2626: 
                   2627: /*
                   2628: * Extended lstat call which returns volumeid and vnodeid as well as other info
                   2629: */
                   2630: struct lstatv_args {
                   2631:        const char *path;       /* pathname of the target file       */
                   2632:        struct vstat *vsb;      /* vstat structure for returned info */
                   2633: };
                   2634: /* ARGSUSED */
                   2635: int
                   2636: lstatv(p,uap,retval)
                   2637:        struct proc *p;
                   2638:        register struct lstatv_args *uap;
                   2639:        register_t *retval;
                   2640: 
                   2641: {
                   2642:        return (EOPNOTSUPP);    /*  We'll just return an error for now */
                   2643: } /* end of lstatv system call */
                   2644: 
                   2645: 
                   2646: 
                   2647: /*
                   2648: * Extended fstat call which returns volumeid and vnodeid as well as other info
                   2649: */
                   2650: struct fstatv_args {
                   2651:        int fd;                 /* file descriptor of the target file */
                   2652:        struct vstat *vsb;      /* vstat structure for returned info  */
                   2653: };
                   2654: /* ARGSUSED */
                   2655: int
                   2656: fstatv(p,uap,retval)
                   2657:        struct proc *p;
                   2658:        register struct fstatv_args *uap;
                   2659:        register_t *retval;
                   2660: 
                   2661: {
                   2662:        return (EOPNOTSUPP);    /*  We'll just return an error for now */
                   2663: } /* end of fstatv system call */
                   2664: 
                   2665: 
                   2666: 
                   2667: /*
                   2668: * Obtain attribute information about a file system object
                   2669: */
                   2670: 
                   2671: struct getattrlist_args {
                   2672:        const char *path;       /* pathname of the target object */
                   2673:        struct attrlist * alist; /* Attributes desired by the user */
                   2674:        void * attributeBuffer;         /* buffer to hold returned attributes */
                   2675:        size_t bufferSize;      /* size of the return buffer */
                   2676: };
                   2677: /* ARGSUSED */
                   2678: int
                   2679: getattrlist (p,uap,retval)
                   2680:        struct proc *p;
                   2681:        register struct getattrlist_args *uap;
                   2682:        register_t *retval;
                   2683: 
                   2684: {
                   2685:         int error;
                   2686:         struct nameidata nd;   
                   2687:        struct iovec aiov;
                   2688:        struct uio auio;
                   2689:         struct attrlist attributelist; 
                   2690: 
                   2691:        /* Get the attributes desire and do our parameter checking */
                   2692: 
                   2693:        if (error = copyin((caddr_t)uap->alist, (caddr_t) &attributelist,
                   2694:                  sizeof (attributelist)))
                   2695:                {
                   2696:                return(error);
                   2697:                }
                   2698: 
                   2699:        if (attributelist.bitmapcount != ATTR_BIT_MAP_COUNT
                   2700: #if 0
                   2701:            ||  attributelist.commonattr & ~ATTR_CMN_VALIDMASK ||
                   2702:                attributelist.volattr & ~ATTR_VOL_VALIDMASK ||
                   2703:                attributelist.dirattr & ~ATTR_DIR_VALIDMASK ||
                   2704:                attributelist.fileattr & ~ATTR_FILE_VALIDMASK ||
                   2705:                attributelist.forkattr & ~ATTR_FORK_VALIDMASK
                   2706: #endif
                   2707:        )
                   2708:                {
                   2709:                return (EINVAL);
                   2710:                }
                   2711: 
                   2712:        /* Get the vnode for the file we are getting info on.  */
                   2713:         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
                   2714: 
                   2715:         if (error = namei(&nd))
                   2716:                 return (error);
                   2717: 
                   2718:        /* Set up the UIO structure for use by the vfs routine */
                   2719: 
                   2720:        
                   2721:        aiov.iov_base = uap->attributeBuffer;
                   2722:         aiov.iov_len = uap->bufferSize;  
                   2723:        auio.uio_iov = &aiov;
                   2724:        auio.uio_iovcnt = 1;
                   2725:         auio.uio_offset = 0;
                   2726:         auio.uio_rw = UIO_READ;
                   2727:         auio.uio_segflg = UIO_USERSPACE;
                   2728:         auio.uio_procp = p;
                   2729:         auio.uio_resid = uap->bufferSize;
                   2730: 
                   2731: 
                   2732:         error = VOP_GETATTRLIST(nd.ni_vp, &attributelist, &auio, p->p_ucred, p);
                   2733: 
                   2734:        /* Unlock and release the vnode which will have been locked by namei */
                   2735: 
                   2736:         vput(nd.ni_vp);
                   2737: 
                   2738:         /* return the effort if we got one, otherwise return success */
                   2739: 
                   2740:         if (error)
                   2741:             {
                   2742:             return (error);
                   2743:             }
                   2744: 
                   2745:         return(0);
                   2746: 
                   2747: } /* end of getattrlist system call */
                   2748: 
                   2749: 
                   2750: 
                   2751: /*
                   2752: * Set attribute information about a file system object
                   2753: */
                   2754: 
                   2755: struct setattrlist_args {
                   2756:       const char *path;                /* pathname of the target object          */
                   2757:       struct attrlist * alist;  /* Attributes being set  by the user     */
                   2758:       void * attributeBuffer;  /* buffer with attribute values to be set */
                   2759:       size_t bufferSize;       /* size of the return buffer              */
                   2760: };
                   2761: /* ARGSUSED */
                   2762: int
                   2763: setattrlist (p,uap,retval)
                   2764:       struct proc *p;
                   2765:       register struct setattrlist_args *uap;
                   2766:       register_t *retval;
                   2767: 
                   2768: {
                   2769:        int error;
                   2770:        struct nameidata nd;    
                   2771:        struct iovec aiov;
                   2772:        struct uio auio;
                   2773:        struct attrlist attributelist;
                   2774: 
                   2775:        /* Get the attributes desire and do our parameter checking */
                   2776: 
                   2777:        if (error = copyin((caddr_t)uap->alist, (caddr_t) &attributelist,
                   2778:                 sizeof (attributelist)))
                   2779:                {
                   2780:                 return(error);
                   2781:                 }
                   2782: 
                   2783:        if (attributelist.bitmapcount != ATTR_BIT_MAP_COUNT
                   2784: #if 0
                   2785:            ||  attributelist.commonattr & ~ATTR_CMN_VALIDMASK ||
                   2786:                attributelist.volattr & ~ATTR_VOL_VALIDMASK ||
                   2787:                attributelist.dirattr & ~ATTR_DIR_VALIDMASK ||
                   2788:                attributelist.fileattr & ~ATTR_FILE_VALIDMASK ||
                   2789:                attributelist.forkattr & ~ATTR_FORK_VALIDMASK
                   2790: #endif
                   2791:        )
                   2792:                 {
                   2793:                 return (EINVAL);
                   2794:                 }
                   2795: 
                   2796:        /* Get the vnode for the file we are getting info on.  */
                   2797:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
                   2798: 
                   2799:        if (error = namei(&nd))
                   2800:                return (error);
                   2801: 
                   2802:       /* Set up the UIO structure for use by the vfs routine */
                   2803:       
                   2804:        aiov.iov_base = uap->attributeBuffer;
                   2805:        aiov.iov_len = uap->bufferSize;
                   2806:        auio.uio_iov = &aiov;
                   2807:        auio.uio_iovcnt = 1;
                   2808:        auio.uio_offset = 0;
                   2809:        auio.uio_rw = UIO_WRITE;
                   2810:        auio.uio_segflg = UIO_USERSPACE;
                   2811:        auio.uio_procp = p;
                   2812:        auio.uio_resid = uap->bufferSize;
                   2813: 
                   2814: 
                   2815:        error = VOP_SETATTRLIST(nd.ni_vp,&attributelist, &auio, p->p_ucred, p);
                   2816:        
                   2817:        /* Unlock and release the vnode which will have been locked by namei */
                   2818: 
                   2819:        vput(nd.ni_vp);
                   2820: 
                   2821:        /* return the error if we got one, otherwise return success */
                   2822: 
                   2823:        if (error)
                   2824:           {
                   2825:           return (error);
                   2826:            }
                   2827:    
                   2828:        return(0);
                   2829: 
                   2830: } /* end of setattrlist system call */
                   2831: 
                   2832: 
                   2833: /*
                   2834: * Obtain attribute information on objects in a directory while enumerating
                   2835:   the directory.  This call does not yet support union mounted directories.  
                   2836: */
                   2837: 
                   2838: struct getdirentryattr_args {
                   2839:       int fd;                  /* file descriptor */
                   2840:       int *index;              /* Cookie from the user */
                   2841:       struct attrlist *alist;   /* bit map of requested attributes */
                   2842:       void *attributebuffer;   /* buffer to hold returned attribute info */
                   2843:       size_t buffersize;       /* size of the return buffer */
                   2844: };
                   2845: /* ARGSUSED */
                   2846: int
                   2847: getdirentryattr (p,uap,retval)
                   2848:       struct proc *p;
                   2849:       register struct getdirentryattr_args *uap;
                   2850:       register_t *retval;
                   2851: 
                   2852: {
                   2853:         register struct vnode *vp;
                   2854:         struct file *fp;
                   2855:         struct uio auio;
                   2856:         struct iovec aiov;
                   2857:         int index;
                   2858:         int error, eofflag;
                   2859:         struct attrlist attributelist;
                   2860: 
                   2861:         /* Get the attributes desired and do our parameter checking */
                   2862: 
                   2863:         if (error = copyin((caddr_t)uap->alist, (caddr_t) &attributelist,
                   2864:                  sizeof (attributelist)))
                   2865:                  {
                   2866:                  return(error);
                   2867:                  }
                   2868: 
                   2869:         if (attributelist.bitmapcount != ATTR_BIT_MAP_COUNT)
                   2870:                  {
                   2871:                  return (EINVAL);
                   2872:                  }
                   2873: 
                   2874:         if (error = getvnode(p, uap->fd, &fp))
                   2875:                 return (error);
                   2876: 
                   2877:         if ((fp->f_flag & FREAD) == 0)
                   2878:                {               
                   2879:                 return(EBADF);
                   2880:                }
                   2881: 
                   2882:         vp = (struct vnode *)fp->f_data;
                   2883: 
                   2884:         if (vp->v_type != VDIR)
                   2885:                {
                   2886:                 return(EINVAL);
                   2887:                }
                   2888: 
                   2889:        if (error = copyin((caddr_t) uap->index, (caddr_t) &index, sizeof(index)))
                   2890:                return(error);
                   2891: 
                   2892:        /* set up the uio structure which will contain the users return buffer */
                   2893: 
                   2894:         aiov.iov_base = uap->attributebuffer;
                   2895:         aiov.iov_len = uap->buffersize;
                   2896:         auio.uio_iov = &aiov;
                   2897:         auio.uio_iovcnt = 1;
                   2898:         auio.uio_rw = UIO_READ;
                   2899:         auio.uio_segflg = UIO_USERSPACE;
                   2900:         auio.uio_procp = p;
                   2901:         auio.uio_resid = uap->buffersize;
                   2902: 
                   2903:         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                   2904:         error = VOP_READDIRATTR (vp, &attributelist, &auio, &index, &eofflag,((u_long*)0), ((u_long **)0),fp->f_cred);
                   2905:         fp->f_offset = auio.uio_offset;
                   2906: 
                   2907:        if (error)
                   2908:                 return (error);
                   2909: 
                   2910:         VOP_UNLOCK(vp, 0, p);
                   2911: 
                   2912:        if (error = copyout((caddr_t) &index, (caddr_t) uap->index, sizeof(index)))
                   2913:                return(error);
                   2914: 
                   2915:         return (0);
                   2916: 
                   2917: } /* end of getdirentryattr system call */
                   2918: 
                   2919: /*
                   2920: * Exchange data between two files
                   2921: */
                   2922: 
                   2923: struct exchangedata_args {
                   2924:       const char *path1;       /* pathname of the first swapee  */
                   2925:       const char *path2;       /* pathname of the second swapee */
                   2926: };
                   2927: /* ARGSUSED */
                   2928: int
                   2929: exchangedata (p,uap,retval)
                   2930:       struct proc *p;
                   2931:       register struct exchangedata_args *uap;
                   2932:       register_t *retval;
                   2933: 
                   2934: {
                   2935: 
                   2936:        struct nameidata fnd, snd;
                   2937:        struct vnode *fvp, *svp;
                   2938:         int error;
                   2939: 
                   2940:                /* Global lock, to prevent race condition, only one exchange at a time */
                   2941:         lockmgr(&exchangelock, LK_EXCLUSIVE , (struct slock *)0, p);
                   2942: 
                   2943:         NDINIT(&fnd, LOOKUP,FOLLOW, UIO_USERSPACE, uap->path1, p);
                   2944: 
                   2945:         if (error = namei(&fnd))
                   2946:                 goto out2;
                   2947: 
                   2948:         fvp = fnd.ni_vp;
                   2949: 
                   2950:         NDINIT(&snd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path2, p);
                   2951: 
                   2952:         if (error = namei(&snd)) {
                   2953:                        vrele(fvp);
                   2954:             goto out2;
                   2955:                }
                   2956: 
                   2957:        svp = snd.ni_vp;
                   2958: 
                   2959:        /* if the files are the same, return an inval error */
                   2960:        if (svp == fvp) {
                   2961:                vrele(fvp);
                   2962:                vrele(svp);
                   2963:         error = EINVAL;
                   2964:                goto out2;
                   2965:         } 
                   2966: 
                   2967:     vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p);
                   2968:     vn_lock(svp, LK_EXCLUSIVE | LK_RETRY, p);
                   2969: 
                   2970:        error = VOP_ACCESS(fvp, VWRITE, p->p_ucred, p);
                   2971:        if (error) goto out;
                   2972: 
                   2973:        error = VOP_ACCESS(svp, VWRITE, p->p_ucred, p);
                   2974:        if (error) goto out;
                   2975: 
                   2976:        /* Ok, make the call */
                   2977:        error = VOP_EXCHANGE (fvp, svp, p->p_ucred, p);
                   2978: 
                   2979: out:
                   2980:     vput (svp);
                   2981:        vput (fvp);
                   2982: 
                   2983: out2:
                   2984:     lockmgr(&exchangelock, LK_RELEASE, (struct slock *)0, p);
                   2985: 
                   2986:        if (error) {
                   2987:         return (error);
                   2988:                }
                   2989:        
                   2990:        return (0);
                   2991: 
                   2992: } /* end of exchangedata system call */
                   2993: 
                   2994: /*
                   2995: * Check users access to a file 
                   2996: */
                   2997: 
                   2998: struct checkuseraccess_args {
                   2999:      const char *path;         /* pathname of the target file   */
                   3000:      uid_t userid;             /* user for whom we are checking access */
                   3001:      gid_t *groups;            /* Group that we are checking for */
                   3002:      int ngroups;              /* Number of groups being checked */
                   3003:      int accessrequired;       /* needed access to the file */
                   3004: };
                   3005: 
                   3006: /* ARGSUSED */
                   3007: int
                   3008: checkuseraccess (p,uap,retval)
                   3009:      struct proc *p;
                   3010:      register struct checkuseraccess_args *uap;
                   3011:      register_t *retval;
                   3012: 
                   3013: {
                   3014:        register struct vnode *vp;
                   3015:        int error;
                   3016:        struct nameidata nd;
                   3017:        struct ucred cred;
                   3018:        int flags;              /*what will actually get passed to access*/
                   3019: 
                   3020:        /* Make sure that the number of groups is correct before we do anything */
                   3021: 
                   3022:        if (uap->ngroups > NGROUPS)
                   3023:                return (EINVAL);
                   3024: 
                   3025:        /* Verify that the caller is root */
                   3026:        
                   3027:        if (error = suser(p->p_ucred, &p->p_acflag))
                   3028:                return(error);
                   3029: 
                   3030:        /* Fill in the credential structure */
                   3031: 
                   3032:        cred.cr_ref = 0;
                   3033:        cred.cr_uid = uap->userid;
                   3034:        cred.cr_ngroups = uap->ngroups;
                   3035:        if (error = copyin((caddr_t) uap->groups, (caddr_t) &(cred.cr_groups), (sizeof(gid_t))*uap->ngroups))
                   3036:                return (error);
                   3037: 
                   3038:        /* Get our hands on the file */
                   3039: 
                   3040:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
                   3041: 
                   3042:        if (error = namei(&nd))
                   3043:                         return (error);
                   3044:        vp = nd.ni_vp;
                   3045:        
                   3046:        /* Flags == 0 means only check for existence. */
                   3047: 
                   3048:        flags = 0;
                   3049: 
                   3050:        if (uap->accessrequired) {
                   3051:                if (uap->accessrequired & R_OK)
                   3052:                        flags |= VREAD;
                   3053:                if (uap->accessrequired & W_OK)
                   3054:                        flags |= VWRITE;
                   3055:                if (uap->accessrequired & X_OK)
                   3056:                        flags |= VEXEC;
                   3057:                }
                   3058:        error = VOP_ACCESS(vp, flags, &cred, p);
                   3059:                        
                   3060:        vput(vp);
                   3061: 
                   3062:        if (error) 
                   3063:                return (error);
                   3064:        
                   3065:        return (0); 
                   3066: 
                   3067: } /* end of checkuseraccess system call */
                   3068: 
                   3069: 
                   3070: struct searchfs_args {
                   3071:        const char *path;
                   3072:        struct fssearchblock *searchblock; 
                   3073:        u_long *nummatches;
                   3074:        u_long scriptcode;
                   3075:        u_long options;
                   3076:        struct searchstate *state; 
                   3077:        };
                   3078: /* ARGSUSED */
                   3079: 
                   3080: int
                   3081: searchfs (p,uap,retval)
                   3082:        struct proc *p;
                   3083:        register struct searchfs_args *uap;
                   3084:        register_t *retval;
                   3085: 
                   3086: {
                   3087:        register struct vnode *vp;
                   3088:        int error=0;
                   3089:        int fserror = 0;
                   3090:        struct nameidata nd;
                   3091:        struct fssearchblock searchblock;
                   3092:        struct searchstate *state;
                   3093:        struct attrlist *returnattrs;
                   3094:        void *searchparams1,*searchparams2;
                   3095:        struct iovec aiov;
                   3096:        struct uio auio;
                   3097:        u_long nummatches;
                   3098:        int mallocsize;
                   3099:        
                   3100: 
                   3101:        /* Start by copying in fsearchblock paramater list */
                   3102: 
                   3103:        if (error = copyin((caddr_t) uap->searchblock, (caddr_t) &searchblock,sizeof(struct fssearchblock)))
                   3104:                return(error);
                   3105: 
                   3106:        /* Now malloc a big bunch of space to hold the search parameters, the attrlists and the search state. */
                   3107:        /* It all has to do into local memory and it's not that big so we might as well  put it all together. */
                   3108:        /* Searchparams1 shall be first so we might as well use that to hold the base address of the allocated*/
                   3109:        /* block.                                                                                             */
                   3110:        
                   3111:        mallocsize = searchblock.sizeofsearchparams1+searchblock.sizeofsearchparams2 +
                   3112:                      sizeof(struct attrlist) + sizeof(struct searchstate);
                   3113: 
                   3114:        MALLOC(searchparams1, void *, mallocsize, M_TEMP, M_WAITOK);
                   3115: 
                   3116:        /* Now set up the various pointers to the correct place in our newly allocated memory */
                   3117: 
                   3118:        searchparams2 = (void *) (((caddr_t) searchparams1) + searchblock.sizeofsearchparams1);
                   3119:        returnattrs = (struct attrlist *) (((caddr_t) searchparams2) + searchblock.sizeofsearchparams2);
                   3120:        state = (struct searchstate *) (((caddr_t) returnattrs) + sizeof (struct attrlist));
                   3121: 
                   3122:        /* Now copy in the stuff given our local variables. */
                   3123: 
                   3124:        if (error = copyin((caddr_t) searchblock.searchparams1, searchparams1,searchblock.sizeofsearchparams1))
                   3125:                goto freeandexit;
                   3126: 
                   3127:        if (error = copyin((caddr_t) searchblock.searchparams2, searchparams2,searchblock.sizeofsearchparams2))
                   3128:                goto freeandexit;
                   3129: 
                   3130:        if (error = copyin((caddr_t) searchblock.returnattrs, (caddr_t) returnattrs, sizeof(struct attrlist)))
                   3131:                goto freeandexit;
                   3132:                
                   3133:        if (error = copyin((caddr_t) uap->state, (caddr_t) state, sizeof(struct searchstate)))
                   3134:                goto freeandexit;
                   3135:        
                   3136:        /* set up the uio structure which will contain the users return buffer */
                   3137: 
                   3138:        aiov.iov_base = searchblock.returnbuffer;
                   3139:        aiov.iov_len = searchblock.returnbuffersize;
                   3140:        auio.uio_iov = &aiov;
                   3141:        auio.uio_iovcnt = 1;
                   3142:        auio.uio_rw = UIO_READ;
                   3143:        auio.uio_segflg = UIO_USERSPACE;
                   3144:        auio.uio_procp = p;
                   3145:        auio.uio_resid = searchblock.returnbuffersize;
                   3146: 
                   3147: 
                   3148:        NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF, UIO_USERSPACE, uap->path, p);
                   3149: 
                   3150:        if (error = namei(&nd))
                   3151:                goto freeandexit;
                   3152: 
                   3153:        vp = nd.ni_vp; 
                   3154: 
                   3155:        /*
                   3156:           Allright, we have everything we need, so lets make that call.
                   3157:           
                   3158:           We keep special track of the return value from the file system:
                   3159:           EAGAIN is an acceptable error condition that shouldn't keep us
                   3160:           from copying out any results...
                   3161:         */
                   3162: 
                   3163:        fserror = VOP_SEARCHFS(vp,
                   3164:                                                        searchparams1,
                   3165:                                                        searchparams2,
                   3166:                                                        &searchblock.searchattrs,
                   3167:                                                        searchblock.maxmatches,
                   3168:                                                        &searchblock.timelimit,
                   3169:                                                        returnattrs,
                   3170:                                                        &nummatches,
                   3171:                                                        uap->scriptcode,
                   3172:                                                        uap->options,
                   3173:                                                        &auio,
                   3174:                                                        state);
                   3175:                
                   3176:        vput(vp);
                   3177: 
                   3178:        /* Now copy out the stuff that needs copying out. That means the number of matches, the
                   3179:           search state.  Everything was already put into he return buffer by the vop call. */
                   3180: 
                   3181:        if (error = copyout((caddr_t) state, (caddr_t) uap->state, sizeof(struct searchstate)))
                   3182:                goto freeandexit;
                   3183: 
                   3184:        if (error = copyout((caddr_t) &nummatches, (caddr_t) uap->nummatches, sizeof(u_long)))
                   3185:                goto freeandexit;
                   3186:        
                   3187:        error = fserror;
                   3188: 
                   3189: freeandexit:
                   3190: 
                   3191:        FREE(searchparams1,M_TEMP);
                   3192: 
                   3193:        return(error);
                   3194: 
                   3195: 
                   3196: } /* end of searchfs system call */
                   3197: 
                   3198: 

unix.superglobalmegacorp.com

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