Home | History | Annotate | Line # | Download | only in kern
vfs_syscalls.c revision 1.1.1.2
      1 /*
      2  * Copyright (c) 1989, 1993
      3  *	The Regents of the University of California.  All rights reserved.
      4  * (c) UNIX System Laboratories, Inc.
      5  * All or some portions of this file are derived from material licensed
      6  * to the University of California by American Telephone and Telegraph
      7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
      8  * the permission of UNIX System Laboratories, Inc.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the University of
     21  *	California, Berkeley and its contributors.
     22  * 4. Neither the name of the University nor the names of its contributors
     23  *    may be used to endorse or promote products derived from this software
     24  *    without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     36  * SUCH DAMAGE.
     37  *
     38  *	@(#)vfs_syscalls.c	8.13 (Berkeley) 4/15/94
     39  */
     40 
     41 #include <sys/param.h>
     42 #include <sys/systm.h>
     43 #include <sys/namei.h>
     44 #include <sys/filedesc.h>
     45 #include <sys/kernel.h>
     46 #include <sys/file.h>
     47 #include <sys/stat.h>
     48 #include <sys/vnode.h>
     49 #include <sys/mount.h>
     50 #include <sys/proc.h>
     51 #include <sys/uio.h>
     52 #include <sys/malloc.h>
     53 #include <sys/dirent.h>
     54 
     55 #include <vm/vm.h>
     56 #include <sys/sysctl.h>
     57 
     58 static int change_dir __P((struct nameidata *ndp, struct proc *p));
     59 
     60 /*
     61  * Virtual File System System Calls
     62  */
     63 
     64 /*
     65  * Mount a file system.
     66  */
     67 struct mount_args {
     68 	int	type;
     69 	char	*path;
     70 	int	flags;
     71 	caddr_t	data;
     72 };
     73 /* ARGSUSED */
     74 mount(p, uap, retval)
     75 	struct proc *p;
     76 	register struct mount_args *uap;
     77 	int *retval;
     78 {
     79 	register struct vnode *vp;
     80 	register struct mount *mp;
     81 	int error, flag;
     82 	struct nameidata nd;
     83 
     84 	/*
     85 	 * Must be super user
     86 	 */
     87 	if (error = suser(p->p_ucred, &p->p_acflag))
     88 		return (error);
     89 	/*
     90 	 * Get vnode to be covered
     91 	 */
     92 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
     93 	if (error = namei(&nd))
     94 		return (error);
     95 	vp = nd.ni_vp;
     96 	if (uap->flags & MNT_UPDATE) {
     97 		if ((vp->v_flag & VROOT) == 0) {
     98 			vput(vp);
     99 			return (EINVAL);
    100 		}
    101 		mp = vp->v_mount;
    102 		flag = mp->mnt_flag;
    103 		/*
    104 		 * We only allow the filesystem to be reloaded if it
    105 		 * is currently mounted read-only.
    106 		 */
    107 		if ((uap->flags & MNT_RELOAD) &&
    108 		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
    109 			vput(vp);
    110 			return (EOPNOTSUPP);	/* Needs translation */
    111 		}
    112 		mp->mnt_flag |=
    113 		    uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
    114 		VOP_UNLOCK(vp);
    115 		goto update;
    116 	}
    117 	if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
    118 		return (error);
    119 	if (vp->v_type != VDIR) {
    120 		vput(vp);
    121 		return (ENOTDIR);
    122 	}
    123 	if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) {
    124 		vput(vp);
    125 		return (ENODEV);
    126 	}
    127 
    128 	/*
    129 	 * Allocate and initialize the file system.
    130 	 */
    131 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
    132 		M_MOUNT, M_WAITOK);
    133 	bzero((char *)mp, (u_long)sizeof(struct mount));
    134 	mp->mnt_op = vfssw[uap->type];
    135 	if (error = vfs_lock(mp)) {
    136 		free((caddr_t)mp, M_MOUNT);
    137 		vput(vp);
    138 		return (error);
    139 	}
    140 	if (vp->v_mountedhere != NULL) {
    141 		vfs_unlock(mp);
    142 		free((caddr_t)mp, M_MOUNT);
    143 		vput(vp);
    144 		return (EBUSY);
    145 	}
    146 	vp->v_mountedhere = mp;
    147 	mp->mnt_vnodecovered = vp;
    148 update:
    149 	/*
    150 	 * Set the mount level flags.
    151 	 */
    152 	if (uap->flags & MNT_RDONLY)
    153 		mp->mnt_flag |= MNT_RDONLY;
    154 	else if (mp->mnt_flag & MNT_RDONLY)
    155 		mp->mnt_flag |= MNT_WANTRDWR;
    156 	mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
    157 	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
    158 	mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
    159 	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
    160 	/*
    161 	 * Mount the filesystem.
    162 	 */
    163 	error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p);
    164 	if (mp->mnt_flag & MNT_UPDATE) {
    165 		vrele(vp);
    166 		if (mp->mnt_flag & MNT_WANTRDWR)
    167 			mp->mnt_flag &= ~MNT_RDONLY;
    168 		mp->mnt_flag &=~
    169 		    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
    170 		if (error)
    171 			mp->mnt_flag = flag;
    172 		return (error);
    173 	}
    174 	/*
    175 	 * Put the new filesystem on the mount list after root.
    176 	 */
    177 	cache_purge(vp);
    178 	if (!error) {
    179 		TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
    180 		VOP_UNLOCK(vp);
    181 		vfs_unlock(mp);
    182 		error = VFS_START(mp, 0, p);
    183 	} else {
    184 		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
    185 		vfs_unlock(mp);
    186 		free((caddr_t)mp, M_MOUNT);
    187 		vput(vp);
    188 	}
    189 	return (error);
    190 }
    191 
    192 /*
    193  * Unmount a file system.
    194  *
    195  * Note: unmount takes a path to the vnode mounted on as argument,
    196  * not special file (as before).
    197  */
    198 struct unmount_args {
    199 	char	*path;
    200 	int	flags;
    201 };
    202 /* ARGSUSED */
    203 unmount(p, uap, retval)
    204 	struct proc *p;
    205 	register struct unmount_args *uap;
    206 	int *retval;
    207 {
    208 	register struct vnode *vp;
    209 	struct mount *mp;
    210 	int error;
    211 	struct nameidata nd;
    212 
    213 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
    214 	if (error = namei(&nd))
    215 		return (error);
    216 	vp = nd.ni_vp;
    217 
    218 	/*
    219 	 * Unless this is a user mount, then must
    220 	 * have suser privilege.
    221 	 */
    222 	if (((vp->v_mount->mnt_flag & MNT_USER) == 0) &&
    223 	    (error = suser(p->p_ucred, &p->p_acflag))) {
    224 		vput(vp);
    225 		return (error);
    226 	}
    227 
    228 	/*
    229 	 * Must be the root of the filesystem
    230 	 */
    231 	if ((vp->v_flag & VROOT) == 0) {
    232 		vput(vp);
    233 		return (EINVAL);
    234 	}
    235 	mp = vp->v_mount;
    236 	vput(vp);
    237 	return (dounmount(mp, uap->flags, p));
    238 }
    239 
    240 /*
    241  * Do the actual file system unmount.
    242  */
    243 dounmount(mp, flags, p)
    244 	register struct mount *mp;
    245 	int flags;
    246 	struct proc *p;
    247 {
    248 	struct vnode *coveredvp;
    249 	int error;
    250 
    251 	coveredvp = mp->mnt_vnodecovered;
    252 	if (vfs_busy(mp))
    253 		return (EBUSY);
    254 	mp->mnt_flag |= MNT_UNMOUNT;
    255 	if (error = vfs_lock(mp))
    256 		return (error);
    257 
    258 	mp->mnt_flag &=~ MNT_ASYNC;
    259 	vnode_pager_umount(mp);	/* release cached vnodes */
    260 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
    261 	if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
    262 	    (flags & MNT_FORCE))
    263 		error = VFS_UNMOUNT(mp, flags, p);
    264 	mp->mnt_flag &= ~MNT_UNMOUNT;
    265 	vfs_unbusy(mp);
    266 	if (error) {
    267 		vfs_unlock(mp);
    268 	} else {
    269 		vrele(coveredvp);
    270 		TAILQ_REMOVE(&mountlist, mp, mnt_list);
    271 		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
    272 		vfs_unlock(mp);
    273 		if (mp->mnt_vnodelist.lh_first != NULL)
    274 			panic("unmount: dangling vnode");
    275 		free((caddr_t)mp, M_MOUNT);
    276 	}
    277 	return (error);
    278 }
    279 
    280 /*
    281  * Sync each mounted filesystem.
    282  */
    283 #ifdef DIAGNOSTIC
    284 int syncprt = 0;
    285 struct ctldebug debug0 = { "syncprt", &syncprt };
    286 #endif
    287 
    288 struct sync_args {
    289 	int	dummy;
    290 };
    291 /* ARGSUSED */
    292 sync(p, uap, retval)
    293 	struct proc *p;
    294 	struct sync_args *uap;
    295 	int *retval;
    296 {
    297 	register struct mount *mp, *nmp;
    298 	int asyncflag;
    299 
    300 	for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
    301 		nmp = mp->mnt_list.tqe_next;
    302 		/*
    303 		 * The lock check below is to avoid races with mount
    304 		 * and unmount.
    305 		 */
    306 		if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
    307 		    !vfs_busy(mp)) {
    308 			asyncflag = mp->mnt_flag & MNT_ASYNC;
    309 			mp->mnt_flag &= ~MNT_ASYNC;
    310 			VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
    311 			if (asyncflag)
    312 				mp->mnt_flag |= MNT_ASYNC;
    313 			vfs_unbusy(mp);
    314 		}
    315 	}
    316 #ifdef DIAGNOSTIC
    317 	if (syncprt)
    318 		vfs_bufstats();
    319 #endif /* DIAGNOSTIC */
    320 	return (0);
    321 }
    322 
    323 /*
    324  * Change filesystem quotas.
    325  */
    326 struct quotactl_args {
    327 	char *path;
    328 	int cmd;
    329 	int uid;
    330 	caddr_t arg;
    331 };
    332 /* ARGSUSED */
    333 quotactl(p, uap, retval)
    334 	struct proc *p;
    335 	register struct quotactl_args *uap;
    336 	int *retval;
    337 {
    338 	register struct mount *mp;
    339 	int error;
    340 	struct nameidata nd;
    341 
    342 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
    343 	if (error = namei(&nd))
    344 		return (error);
    345 	mp = nd.ni_vp->v_mount;
    346 	vrele(nd.ni_vp);
    347 	return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
    348 }
    349 
    350 /*
    351  * Get filesystem statistics.
    352  */
    353 struct statfs_args {
    354 	char *path;
    355 	struct statfs *buf;
    356 };
    357 /* ARGSUSED */
    358 statfs(p, uap, retval)
    359 	struct proc *p;
    360 	register struct statfs_args *uap;
    361 	int *retval;
    362 {
    363 	register struct mount *mp;
    364 	register struct statfs *sp;
    365 	int error;
    366 	struct nameidata nd;
    367 
    368 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
    369 	if (error = namei(&nd))
    370 		return (error);
    371 	mp = nd.ni_vp->v_mount;
    372 	sp = &mp->mnt_stat;
    373 	vrele(nd.ni_vp);
    374 	if (error = VFS_STATFS(mp, sp, p))
    375 		return (error);
    376 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
    377 	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
    378 }
    379 
    380 /*
    381  * Get filesystem statistics.
    382  */
    383 struct fstatfs_args {
    384 	int fd;
    385 	struct statfs *buf;
    386 };
    387 /* ARGSUSED */
    388 fstatfs(p, uap, retval)
    389 	struct proc *p;
    390 	register struct fstatfs_args *uap;
    391 	int *retval;
    392 {
    393 	struct file *fp;
    394 	struct mount *mp;
    395 	register struct statfs *sp;
    396 	int error;
    397 
    398 	if (error = getvnode(p->p_fd, uap->fd, &fp))
    399 		return (error);
    400 	mp = ((struct vnode *)fp->f_data)->v_mount;
    401 	sp = &mp->mnt_stat;
    402 	if (error = VFS_STATFS(mp, sp, p))
    403 		return (error);
    404 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
    405 	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
    406 }
    407 
    408 /*
    409  * Get statistics on all filesystems.
    410  */
    411 struct getfsstat_args {
    412 	struct statfs *buf;
    413 	long bufsize;
    414 	int flags;
    415 };
    416 getfsstat(p, uap, retval)
    417 	struct proc *p;
    418 	register struct getfsstat_args *uap;
    419 	int *retval;
    420 {
    421 	register struct mount *mp, *nmp;
    422 	register struct statfs *sp;
    423 	caddr_t sfsp;
    424 	long count, maxcount, error;
    425 
    426 	maxcount = uap->bufsize / sizeof(struct statfs);
    427 	sfsp = (caddr_t)uap->buf;
    428 	for (count = 0, mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
    429 		nmp = mp->mnt_list.tqe_next;
    430 		if (sfsp && count < maxcount &&
    431 		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
    432 			sp = &mp->mnt_stat;
    433 			/*
    434 			 * If MNT_NOWAIT is specified, do not refresh the
    435 			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
    436 			 */
    437 			if (((uap->flags & MNT_NOWAIT) == 0 ||
    438 			    (uap->flags & MNT_WAIT)) &&
    439 			    (error = VFS_STATFS(mp, sp, p)))
    440 				continue;
    441 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
    442 			if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
    443 				return (error);
    444 			sfsp += sizeof(*sp);
    445 		}
    446 		count++;
    447 	}
    448 	if (sfsp && count > maxcount)
    449 		*retval = maxcount;
    450 	else
    451 		*retval = count;
    452 	return (0);
    453 }
    454 
    455 /*
    456  * Change current working directory to a given file descriptor.
    457  */
    458 struct fchdir_args {
    459 	int	fd;
    460 };
    461 /* ARGSUSED */
    462 fchdir(p, uap, retval)
    463 	struct proc *p;
    464 	struct fchdir_args *uap;
    465 	int *retval;
    466 {
    467 	register struct filedesc *fdp = p->p_fd;
    468 	register struct vnode *vp;
    469 	struct file *fp;
    470 	int error;
    471 
    472 	if (error = getvnode(fdp, uap->fd, &fp))
    473 		return (error);
    474 	vp = (struct vnode *)fp->f_data;
    475 	VOP_LOCK(vp);
    476 	if (vp->v_type != VDIR)
    477 		error = ENOTDIR;
    478 	else
    479 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
    480 	VOP_UNLOCK(vp);
    481 	if (error)
    482 		return (error);
    483 	VREF(vp);
    484 	vrele(fdp->fd_cdir);
    485 	fdp->fd_cdir = vp;
    486 	return (0);
    487 }
    488 
    489 /*
    490  * Change current working directory (``.'').
    491  */
    492 struct chdir_args {
    493 	char	*path;
    494 };
    495 /* ARGSUSED */
    496 chdir(p, uap, retval)
    497 	struct proc *p;
    498 	struct chdir_args *uap;
    499 	int *retval;
    500 {
    501 	register struct filedesc *fdp = p->p_fd;
    502 	int error;
    503 	struct nameidata nd;
    504 
    505 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
    506 	if (error = change_dir(&nd, p))
    507 		return (error);
    508 	vrele(fdp->fd_cdir);
    509 	fdp->fd_cdir = nd.ni_vp;
    510 	return (0);
    511 }
    512 
    513 /*
    514  * Change notion of root (``/'') directory.
    515  */
    516 struct chroot_args {
    517 	char	*path;
    518 };
    519 /* ARGSUSED */
    520 chroot(p, uap, retval)
    521 	struct proc *p;
    522 	struct chroot_args *uap;
    523 	int *retval;
    524 {
    525 	register struct filedesc *fdp = p->p_fd;
    526 	int error;
    527 	struct nameidata nd;
    528 
    529 	if (error = suser(p->p_ucred, &p->p_acflag))
    530 		return (error);
    531 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
    532 	if (error = change_dir(&nd, p))
    533 		return (error);
    534 	if (fdp->fd_rdir != NULL)
    535 		vrele(fdp->fd_rdir);
    536 	fdp->fd_rdir = nd.ni_vp;
    537 	return (0);
    538 }
    539 
    540 /*
    541  * Common routine for chroot and chdir.
    542  */
    543 static int
    544 change_dir(ndp, p)
    545 	register struct nameidata *ndp;
    546 	struct proc *p;
    547 {
    548 	struct vnode *vp;
    549 	int error;
    550 
    551 	if (error = namei(ndp))
    552 		return (error);
    553 	vp = ndp->ni_vp;
    554 	if (vp->v_type != VDIR)
    555 		error = ENOTDIR;
    556 	else
    557 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
    558 	VOP_UNLOCK(vp);
    559 	if (error)
    560 		vrele(vp);
    561 	return (error);
    562 }
    563 
    564 /*
    565  * Check permissions, allocate an open file structure,
    566  * and call the device open routine if any.
    567  */
    568 struct open_args {
    569 	char	*path;
    570 	int	flags;
    571 	int	mode;
    572 };
    573 open(p, uap, retval)
    574 	struct proc *p;
    575 	register struct open_args *uap;
    576 	int *retval;
    577 {
    578 	register struct filedesc *fdp = p->p_fd;
    579 	register struct file *fp;
    580 	register struct vnode *vp;
    581 	int flags, cmode;
    582 	struct file *nfp;
    583 	int type, indx, error;
    584 	struct flock lf;
    585 	struct nameidata nd;
    586 	extern struct fileops vnops;
    587 
    588 	if (error = falloc(p, &nfp, &indx))
    589 		return (error);
    590 	fp = nfp;
    591 	flags = FFLAGS(uap->flags);
    592 	cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
    593 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
    594 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
    595 	if (error = vn_open(&nd, flags, cmode)) {
    596 		ffree(fp);
    597 		if ((error == ENODEV || error == ENXIO) &&
    598 		    p->p_dupfd >= 0 && 			/* XXX from fdopen */
    599 		    (error =
    600 		        dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
    601 			*retval = indx;
    602 			return (0);
    603 		}
    604 		if (error == ERESTART)
    605 			error = EINTR;
    606 		fdp->fd_ofiles[indx] = NULL;
    607 		return (error);
    608 	}
    609 	p->p_dupfd = 0;
    610 	vp = nd.ni_vp;
    611 	fp->f_flag = flags & FMASK;
    612 	fp->f_type = DTYPE_VNODE;
    613 	fp->f_ops = &vnops;
    614 	fp->f_data = (caddr_t)vp;
    615 	if (flags & (O_EXLOCK | O_SHLOCK)) {
    616 		lf.l_whence = SEEK_SET;
    617 		lf.l_start = 0;
    618 		lf.l_len = 0;
    619 		if (flags & O_EXLOCK)
    620 			lf.l_type = F_WRLCK;
    621 		else
    622 			lf.l_type = F_RDLCK;
    623 		type = F_FLOCK;
    624 		if ((flags & FNONBLOCK) == 0)
    625 			type |= F_WAIT;
    626 		VOP_UNLOCK(vp);
    627 		if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
    628 			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
    629 			ffree(fp);
    630 			fdp->fd_ofiles[indx] = NULL;
    631 			return (error);
    632 		}
    633 		VOP_LOCK(vp);
    634 		fp->f_flag |= FHASLOCK;
    635 	}
    636 	VOP_UNLOCK(vp);
    637 	*retval = indx;
    638 	return (0);
    639 }
    640 
    641 #ifdef COMPAT_43
    642 /*
    643  * Create a file.
    644  */
    645 struct ocreat_args {
    646 	char	*path;
    647 	int	mode;
    648 };
    649 ocreat(p, uap, retval)
    650 	struct proc *p;
    651 	register struct ocreat_args *uap;
    652 	int *retval;
    653 {
    654 	struct open_args openuap;
    655 
    656 	openuap.path = uap->path;
    657 	openuap.mode = uap->mode;
    658 	openuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
    659 	return (open(p, &openuap, retval));
    660 }
    661 #endif /* COMPAT_43 */
    662 
    663 /*
    664  * Create a special file.
    665  */
    666 struct mknod_args {
    667 	char	*path;
    668 	int	mode;
    669 	int	dev;
    670 };
    671 /* ARGSUSED */
    672 mknod(p, uap, retval)
    673 	struct proc *p;
    674 	register struct mknod_args *uap;
    675 	int *retval;
    676 {
    677 	register struct vnode *vp;
    678 	struct vattr vattr;
    679 	int error;
    680 	struct nameidata nd;
    681 
    682 	if (error = suser(p->p_ucred, &p->p_acflag))
    683 		return (error);
    684 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
    685 	if (error = namei(&nd))
    686 		return (error);
    687 	vp = nd.ni_vp;
    688 	if (vp != NULL)
    689 		error = EEXIST;
    690 	else {
    691 		VATTR_NULL(&vattr);
    692 		vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
    693 		vattr.va_rdev = uap->dev;
    694 
    695 		switch (uap->mode & S_IFMT) {
    696 		case S_IFMT:	/* used by badsect to flag bad sectors */
    697 			vattr.va_type = VBAD;
    698 			break;
    699 		case S_IFCHR:
    700 			vattr.va_type = VCHR;
    701 			break;
    702 		case S_IFBLK:
    703 			vattr.va_type = VBLK;
    704 			break;
    705 		default:
    706 			error = EINVAL;
    707 			break;
    708 		}
    709 	}
    710 	if (!error) {
    711 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
    712 		error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
    713 	} else {
    714 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    715 		if (nd.ni_dvp == vp)
    716 			vrele(nd.ni_dvp);
    717 		else
    718 			vput(nd.ni_dvp);
    719 		if (vp)
    720 			vrele(vp);
    721 	}
    722 	return (error);
    723 }
    724 
    725 /*
    726  * Create named pipe.
    727  */
    728 struct mkfifo_args {
    729 	char	*path;
    730 	int	mode;
    731 };
    732 /* ARGSUSED */
    733 mkfifo(p, uap, retval)
    734 	struct proc *p;
    735 	register struct mkfifo_args *uap;
    736 	int *retval;
    737 {
    738 	struct vattr vattr;
    739 	int error;
    740 	struct nameidata nd;
    741 
    742 #ifndef FIFO
    743 	return (EOPNOTSUPP);
    744 #else
    745 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
    746 	if (error = namei(&nd))
    747 		return (error);
    748 	if (nd.ni_vp != NULL) {
    749 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    750 		if (nd.ni_dvp == nd.ni_vp)
    751 			vrele(nd.ni_dvp);
    752 		else
    753 			vput(nd.ni_dvp);
    754 		vrele(nd.ni_vp);
    755 		return (EEXIST);
    756 	}
    757 	VATTR_NULL(&vattr);
    758 	vattr.va_type = VFIFO;
    759 	vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
    760 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
    761 	return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
    762 #endif /* FIFO */
    763 }
    764 
    765 /*
    766  * Make a hard file link.
    767  */
    768 struct link_args {
    769 	char	*path;
    770 	char	*link;
    771 };
    772 /* ARGSUSED */
    773 link(p, uap, retval)
    774 	struct proc *p;
    775 	register struct link_args *uap;
    776 	int *retval;
    777 {
    778 	register struct vnode *vp;
    779 	struct nameidata nd;
    780 	int error;
    781 
    782 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
    783 	if (error = namei(&nd))
    784 		return (error);
    785 	vp = nd.ni_vp;
    786 	if (vp->v_type != VDIR ||
    787 	    (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
    788 		nd.ni_cnd.cn_nameiop = CREATE;
    789 		nd.ni_cnd.cn_flags = LOCKPARENT;
    790 		nd.ni_dirp = uap->link;
    791 		if ((error = namei(&nd)) == 0) {
    792 			if (nd.ni_vp != NULL)
    793 				error = EEXIST;
    794 			if (!error) {
    795 				LEASE_CHECK(nd.ni_dvp,
    796 				    p, p->p_ucred, LEASE_WRITE);
    797 				LEASE_CHECK(vp,
    798 				    p, p->p_ucred, LEASE_WRITE);
    799 				error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
    800 			} else {
    801 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    802 				if (nd.ni_dvp == nd.ni_vp)
    803 					vrele(nd.ni_dvp);
    804 				else
    805 					vput(nd.ni_dvp);
    806 				if (nd.ni_vp)
    807 					vrele(nd.ni_vp);
    808 			}
    809 		}
    810 	}
    811 	vrele(vp);
    812 	return (error);
    813 }
    814 
    815 /*
    816  * Make a symbolic link.
    817  */
    818 struct symlink_args {
    819 	char	*path;
    820 	char	*link;
    821 };
    822 /* ARGSUSED */
    823 symlink(p, uap, retval)
    824 	struct proc *p;
    825 	register struct symlink_args *uap;
    826 	int *retval;
    827 {
    828 	struct vattr vattr;
    829 	char *path;
    830 	int error;
    831 	struct nameidata nd;
    832 
    833 	MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
    834 	if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL))
    835 		goto out;
    836 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
    837 	if (error = namei(&nd))
    838 		goto out;
    839 	if (nd.ni_vp) {
    840 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    841 		if (nd.ni_dvp == nd.ni_vp)
    842 			vrele(nd.ni_dvp);
    843 		else
    844 			vput(nd.ni_dvp);
    845 		vrele(nd.ni_vp);
    846 		error = EEXIST;
    847 		goto out;
    848 	}
    849 	VATTR_NULL(&vattr);
    850 	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
    851 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
    852 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
    853 out:
    854 	FREE(path, M_NAMEI);
    855 	return (error);
    856 }
    857 
    858 /*
    859  * Delete a name from the filesystem.
    860  */
    861 struct unlink_args {
    862 	char	*path;
    863 };
    864 /* ARGSUSED */
    865 unlink(p, uap, retval)
    866 	struct proc *p;
    867 	struct unlink_args *uap;
    868 	int *retval;
    869 {
    870 	register struct vnode *vp;
    871 	int error;
    872 	struct nameidata nd;
    873 
    874 	NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
    875 	if (error = namei(&nd))
    876 		return (error);
    877 	vp = nd.ni_vp;
    878 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
    879 	VOP_LOCK(vp);
    880 
    881 	if (vp->v_type != VDIR ||
    882 	    (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
    883 		/*
    884 		 * The root of a mounted filesystem cannot be deleted.
    885 		 */
    886 		if (vp->v_flag & VROOT)
    887 			error = EBUSY;
    888 		else
    889 			(void)vnode_pager_uncache(vp);
    890 	}
    891 
    892 	if (!error) {
    893 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
    894 		error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
    895 	} else {
    896 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
    897 		if (nd.ni_dvp == vp)
    898 			vrele(nd.ni_dvp);
    899 		else
    900 			vput(nd.ni_dvp);
    901 		vput(vp);
    902 	}
    903 	return (error);
    904 }
    905 
    906 /*
    907  * Reposition read/write file offset.
    908  */
    909 struct lseek_args {
    910 	int	fd;
    911 	int	pad;
    912 	off_t	offset;
    913 	int	whence;
    914 };
    915 lseek(p, uap, retval)
    916 	struct proc *p;
    917 	register struct lseek_args *uap;
    918 	int *retval;
    919 {
    920 	struct ucred *cred = p->p_ucred;
    921 	register struct filedesc *fdp = p->p_fd;
    922 	register struct file *fp;
    923 	struct vattr vattr;
    924 	int error;
    925 
    926 	if ((u_int)uap->fd >= fdp->fd_nfiles ||
    927 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
    928 		return (EBADF);
    929 	if (fp->f_type != DTYPE_VNODE)
    930 		return (ESPIPE);
    931 	switch (uap->whence) {
    932 	case L_INCR:
    933 		fp->f_offset += uap->offset;
    934 		break;
    935 	case L_XTND:
    936 		if (error =
    937 		    VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p))
    938 			return (error);
    939 		fp->f_offset = uap->offset + vattr.va_size;
    940 		break;
    941 	case L_SET:
    942 		fp->f_offset = uap->offset;
    943 		break;
    944 	default:
    945 		return (EINVAL);
    946 	}
    947 	*(off_t *)retval = fp->f_offset;
    948 	return (0);
    949 }
    950 
    951 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
    952 /*
    953  * Reposition read/write file offset.
    954  */
    955 struct olseek_args {
    956 	int	fd;
    957 	long	offset;
    958 	int	whence;
    959 };
    960 olseek(p, uap, retval)
    961 	struct proc *p;
    962 	register struct olseek_args *uap;
    963 	int *retval;
    964 {
    965 	struct lseek_args nuap;
    966 	off_t qret;
    967 	int error;
    968 
    969 	nuap.fd = uap->fd;
    970 	nuap.offset = uap->offset;
    971 	nuap.whence = uap->whence;
    972 	error = lseek(p, &nuap, &qret);
    973 	*(long *)retval = qret;
    974 	return (error);
    975 }
    976 #endif /* COMPAT_43 */
    977 
    978 /*
    979  * Check access permissions.
    980  */
    981 struct access_args {
    982 	char	*path;
    983 	int	flags;
    984 };
    985 access(p, uap, retval)
    986 	struct proc *p;
    987 	register struct access_args *uap;
    988 	int *retval;
    989 {
    990 	register struct ucred *cred = p->p_ucred;
    991 	register struct vnode *vp;
    992 	int error, flags, t_gid, t_uid;
    993 	struct nameidata nd;
    994 
    995 	t_uid = cred->cr_uid;
    996 	t_gid = cred->cr_groups[0];
    997 	cred->cr_uid = p->p_cred->p_ruid;
    998 	cred->cr_groups[0] = p->p_cred->p_rgid;
    999 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
   1000 	if (error = namei(&nd))
   1001 		goto out1;
   1002 	vp = nd.ni_vp;
   1003 
   1004 	/* Flags == 0 means only check for existence. */
   1005 	if (uap->flags) {
   1006 		flags = 0;
   1007 		if (uap->flags & R_OK)
   1008 			flags |= VREAD;
   1009 		if (uap->flags & W_OK)
   1010 			flags |= VWRITE;
   1011 		if (uap->flags & X_OK)
   1012 			flags |= VEXEC;
   1013 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
   1014 			error = VOP_ACCESS(vp, flags, cred, p);
   1015 	}
   1016 	vput(vp);
   1017 out1:
   1018 	cred->cr_uid = t_uid;
   1019 	cred->cr_groups[0] = t_gid;
   1020 	return (error);
   1021 }
   1022 
   1023 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
   1024 /*
   1025  * Get file status; this version follows links.
   1026  */
   1027 struct ostat_args {
   1028 	char	*path;
   1029 	struct ostat *ub;
   1030 };
   1031 /* ARGSUSED */
   1032 ostat(p, uap, retval)
   1033 	struct proc *p;
   1034 	register struct ostat_args *uap;
   1035 	int *retval;
   1036 {
   1037 	struct stat sb;
   1038 	struct ostat osb;
   1039 	int error;
   1040 	struct nameidata nd;
   1041 
   1042 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
   1043 	if (error = namei(&nd))
   1044 		return (error);
   1045 	error = vn_stat(nd.ni_vp, &sb, p);
   1046 	vput(nd.ni_vp);
   1047 	if (error)
   1048 		return (error);
   1049 	cvtstat(&sb, &osb);
   1050 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
   1051 	return (error);
   1052 }
   1053 
   1054 /*
   1055  * Get file status; this version does not follow links.
   1056  */
   1057 struct olstat_args {
   1058 	char	*path;
   1059 	struct ostat *ub;
   1060 };
   1061 /* ARGSUSED */
   1062 olstat(p, uap, retval)
   1063 	struct proc *p;
   1064 	register struct olstat_args *uap;
   1065 	int *retval;
   1066 {
   1067 	struct stat sb;
   1068 	struct ostat osb;
   1069 	int error;
   1070 	struct nameidata nd;
   1071 
   1072 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
   1073 	if (error = namei(&nd))
   1074 		return (error);
   1075 	error = vn_stat(nd.ni_vp, &sb, p);
   1076 	vput(nd.ni_vp);
   1077 	if (error)
   1078 		return (error);
   1079 	cvtstat(&sb, &osb);
   1080 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
   1081 	return (error);
   1082 }
   1083 
   1084 /*
   1085  * Convert from an old to a new stat structure.
   1086  */
   1087 cvtstat(st, ost)
   1088 	struct stat *st;
   1089 	struct ostat *ost;
   1090 {
   1091 
   1092 	ost->st_dev = st->st_dev;
   1093 	ost->st_ino = st->st_ino;
   1094 	ost->st_mode = st->st_mode;
   1095 	ost->st_nlink = st->st_nlink;
   1096 	ost->st_uid = st->st_uid;
   1097 	ost->st_gid = st->st_gid;
   1098 	ost->st_rdev = st->st_rdev;
   1099 	if (st->st_size < (quad_t)1 << 32)
   1100 		ost->st_size = st->st_size;
   1101 	else
   1102 		ost->st_size = -2;
   1103 	ost->st_atime = st->st_atime;
   1104 	ost->st_mtime = st->st_mtime;
   1105 	ost->st_ctime = st->st_ctime;
   1106 	ost->st_blksize = st->st_blksize;
   1107 	ost->st_blocks = st->st_blocks;
   1108 	ost->st_flags = st->st_flags;
   1109 	ost->st_gen = st->st_gen;
   1110 }
   1111 #endif /* COMPAT_43 || COMPAT_SUNOS */
   1112 
   1113 /*
   1114  * Get file status; this version follows links.
   1115  */
   1116 struct stat_args {
   1117 	char	*path;
   1118 	struct stat *ub;
   1119 };
   1120 /* ARGSUSED */
   1121 stat(p, uap, retval)
   1122 	struct proc *p;
   1123 	register struct stat_args *uap;
   1124 	int *retval;
   1125 {
   1126 	struct stat sb;
   1127 	int error;
   1128 	struct nameidata nd;
   1129 
   1130 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
   1131 	if (error = namei(&nd))
   1132 		return (error);
   1133 	error = vn_stat(nd.ni_vp, &sb, p);
   1134 	vput(nd.ni_vp);
   1135 	if (error)
   1136 		return (error);
   1137 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
   1138 	return (error);
   1139 }
   1140 
   1141 /*
   1142  * Get file status; this version does not follow links.
   1143  */
   1144 struct lstat_args {
   1145 	char	*path;
   1146 	struct stat *ub;
   1147 };
   1148 /* ARGSUSED */
   1149 lstat(p, uap, retval)
   1150 	struct proc *p;
   1151 	register struct lstat_args *uap;
   1152 	int *retval;
   1153 {
   1154 	int error;
   1155 	struct vnode *vp, *dvp;
   1156 	struct stat sb, sb1;
   1157 	struct nameidata nd;
   1158 
   1159 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
   1160 	    uap->path, p);
   1161 	if (error = namei(&nd))
   1162 		return (error);
   1163 	/*
   1164 	 * For symbolic links, always return the attributes of its
   1165 	 * containing directory, except for mode, size, and links.
   1166 	 */
   1167 	vp = nd.ni_vp;
   1168 	dvp = nd.ni_dvp;
   1169 	if (vp->v_type != VLNK) {
   1170 		if (dvp == vp)
   1171 			vrele(dvp);
   1172 		else
   1173 			vput(dvp);
   1174 		error = vn_stat(vp, &sb, p);
   1175 		vput(vp);
   1176 		if (error)
   1177 			return (error);
   1178 	} else {
   1179 		error = vn_stat(dvp, &sb, p);
   1180 		vput(dvp);
   1181 		if (error) {
   1182 			vput(vp);
   1183 			return (error);
   1184 		}
   1185 		error = vn_stat(vp, &sb1, p);
   1186 		vput(vp);
   1187 		if (error)
   1188 			return (error);
   1189 		sb.st_mode &= ~S_IFDIR;
   1190 		sb.st_mode |= S_IFLNK;
   1191 		sb.st_nlink = sb1.st_nlink;
   1192 		sb.st_size = sb1.st_size;
   1193 		sb.st_blocks = sb1.st_blocks;
   1194 	}
   1195 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
   1196 	return (error);
   1197 }
   1198 
   1199 /*
   1200  * Get configurable pathname variables.
   1201  */
   1202 struct pathconf_args {
   1203 	char	*path;
   1204 	int	name;
   1205 };
   1206 /* ARGSUSED */
   1207 pathconf(p, uap, retval)
   1208 	struct proc *p;
   1209 	register struct pathconf_args *uap;
   1210 	int *retval;
   1211 {
   1212 	int error;
   1213 	struct nameidata nd;
   1214 
   1215 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
   1216 	if (error = namei(&nd))
   1217 		return (error);
   1218 	error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
   1219 	vput(nd.ni_vp);
   1220 	return (error);
   1221 }
   1222 
   1223 /*
   1224  * Return target name of a symbolic link.
   1225  */
   1226 struct readlink_args {
   1227 	char	*path;
   1228 	char	*buf;
   1229 	int	count;
   1230 };
   1231 /* ARGSUSED */
   1232 readlink(p, uap, retval)
   1233 	struct proc *p;
   1234 	register struct readlink_args *uap;
   1235 	int *retval;
   1236 {
   1237 	register struct vnode *vp;
   1238 	struct iovec aiov;
   1239 	struct uio auio;
   1240 	int error;
   1241 	struct nameidata nd;
   1242 
   1243 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
   1244 	if (error = namei(&nd))
   1245 		return (error);
   1246 	vp = nd.ni_vp;
   1247 	if (vp->v_type != VLNK)
   1248 		error = EINVAL;
   1249 	else {
   1250 		aiov.iov_base = uap->buf;
   1251 		aiov.iov_len = uap->count;
   1252 		auio.uio_iov = &aiov;
   1253 		auio.uio_iovcnt = 1;
   1254 		auio.uio_offset = 0;
   1255 		auio.uio_rw = UIO_READ;
   1256 		auio.uio_segflg = UIO_USERSPACE;
   1257 		auio.uio_procp = p;
   1258 		auio.uio_resid = uap->count;
   1259 		error = VOP_READLINK(vp, &auio, p->p_ucred);
   1260 	}
   1261 	vput(vp);
   1262 	*retval = uap->count - auio.uio_resid;
   1263 	return (error);
   1264 }
   1265 
   1266 /*
   1267  * Change flags of a file given a path name.
   1268  */
   1269 struct chflags_args {
   1270 	char	*path;
   1271 	int	flags;
   1272 };
   1273 /* ARGSUSED */
   1274 chflags(p, uap, retval)
   1275 	struct proc *p;
   1276 	register struct chflags_args *uap;
   1277 	int *retval;
   1278 {
   1279 	register struct vnode *vp;
   1280 	struct vattr vattr;
   1281 	int error;
   1282 	struct nameidata nd;
   1283 
   1284 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
   1285 	if (error = namei(&nd))
   1286 		return (error);
   1287 	vp = nd.ni_vp;
   1288 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
   1289 	VOP_LOCK(vp);
   1290 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
   1291 		error = EROFS;
   1292 	else {
   1293 		VATTR_NULL(&vattr);
   1294 		vattr.va_flags = uap->flags;
   1295 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
   1296 	}
   1297 	vput(vp);
   1298 	return (error);
   1299 }
   1300 
   1301 /*
   1302  * Change flags of a file given a file descriptor.
   1303  */
   1304 struct fchflags_args {
   1305 	int	fd;
   1306 	int	flags;
   1307 };
   1308 /* ARGSUSED */
   1309 fchflags(p, uap, retval)
   1310 	struct proc *p;
   1311 	register struct fchflags_args *uap;
   1312 	int *retval;
   1313 {
   1314 	struct vattr vattr;
   1315 	struct vnode *vp;
   1316 	struct file *fp;
   1317 	int error;
   1318 
   1319 	if (error = getvnode(p->p_fd, uap->fd, &fp))
   1320 		return (error);
   1321 	vp = (struct vnode *)fp->f_data;
   1322 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
   1323 	VOP_LOCK(vp);
   1324 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
   1325 		error = EROFS;
   1326 	else {
   1327 		VATTR_NULL(&vattr);
   1328 		vattr.va_flags = uap->flags;
   1329 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
   1330 	}
   1331 	VOP_UNLOCK(vp);
   1332 	return (error);
   1333 }
   1334 
   1335 /*
   1336  * Change mode of a file given path name.
   1337  */
   1338 struct chmod_args {
   1339 	char	*path;
   1340 	int	mode;
   1341 };
   1342 /* ARGSUSED */
   1343 chmod(p, uap, retval)
   1344 	struct proc *p;
   1345 	register struct chmod_args *uap;
   1346 	int *retval;
   1347 {
   1348 	register struct vnode *vp;
   1349 	struct vattr vattr;
   1350 	int error;
   1351 	struct nameidata nd;
   1352 
   1353 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
   1354 	if (error = namei(&nd))
   1355 		return (error);
   1356 	vp = nd.ni_vp;
   1357 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
   1358 	VOP_LOCK(vp);
   1359 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
   1360 		error = EROFS;
   1361 	else {
   1362 		VATTR_NULL(&vattr);
   1363 		vattr.va_mode = uap->mode & ALLPERMS;
   1364 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
   1365 	}
   1366 	vput(vp);
   1367 	return (error);
   1368 }
   1369 
   1370 /*
   1371  * Change mode of a file given a file descriptor.
   1372  */
   1373 struct fchmod_args {
   1374 	int	fd;
   1375 	int	mode;
   1376 };
   1377 /* ARGSUSED */
   1378 fchmod(p, uap, retval)
   1379 	struct proc *p;
   1380 	register struct fchmod_args *uap;
   1381 	int *retval;
   1382 {
   1383 	struct vattr vattr;
   1384 	struct vnode *vp;
   1385 	struct file *fp;
   1386 	int error;
   1387 
   1388 	if (error = getvnode(p->p_fd, uap->fd, &fp))
   1389 		return (error);
   1390 	vp = (struct vnode *)fp->f_data;
   1391 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
   1392 	VOP_LOCK(vp);
   1393 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
   1394 		error = EROFS;
   1395 	else {
   1396 		VATTR_NULL(&vattr);
   1397 		vattr.va_mode = uap->mode & ALLPERMS;
   1398 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
   1399 	}
   1400 	VOP_UNLOCK(vp);
   1401 	return (error);
   1402 }
   1403 
   1404 /*
   1405  * Set ownership given a path name.
   1406  */
   1407 struct chown_args {
   1408 	char	*path;
   1409 	int	uid;
   1410 	int	gid;
   1411 };
   1412 /* ARGSUSED */
   1413 chown(p, uap, retval)
   1414 	struct proc *p;
   1415 	register struct chown_args *uap;
   1416 	int *retval;
   1417 {
   1418 	register struct vnode *vp;
   1419 	struct vattr vattr;
   1420 	int error;
   1421 	struct nameidata nd;
   1422 
   1423 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
   1424 	if (error = namei(&nd))
   1425 		return (error);
   1426 	vp = nd.ni_vp;
   1427 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
   1428 	VOP_LOCK(vp);
   1429 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
   1430 		error = EROFS;
   1431 	else {
   1432 		VATTR_NULL(&vattr);
   1433 		vattr.va_uid = uap->uid;
   1434 		vattr.va_gid = uap->gid;
   1435 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
   1436 	}
   1437 	vput(vp);
   1438 	return (error);
   1439 }
   1440 
   1441 /*
   1442  * Set ownership given a file descriptor.
   1443  */
   1444 struct fchown_args {
   1445 	int	fd;
   1446 	int	uid;
   1447 	int	gid;
   1448 };
   1449 /* ARGSUSED */
   1450 fchown(p, uap, retval)
   1451 	struct proc *p;
   1452 	register struct fchown_args *uap;
   1453 	int *retval;
   1454 {
   1455 	struct vattr vattr;
   1456 	struct vnode *vp;
   1457 	struct file *fp;
   1458 	int error;
   1459 
   1460 	if (error = getvnode(p->p_fd, uap->fd, &fp))
   1461 		return (error);
   1462 	vp = (struct vnode *)fp->f_data;
   1463 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
   1464 	VOP_LOCK(vp);
   1465 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
   1466 		error = EROFS;
   1467 	else {
   1468 		VATTR_NULL(&vattr);
   1469 		vattr.va_uid = uap->uid;
   1470 		vattr.va_gid = uap->gid;
   1471 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
   1472 	}
   1473 	VOP_UNLOCK(vp);
   1474 	return (error);
   1475 }
   1476 
   1477 /*
   1478  * Set the access and modification times of a file.
   1479  */
   1480 struct utimes_args {
   1481 	char	*path;
   1482 	struct	timeval *tptr;
   1483 };
   1484 /* ARGSUSED */
   1485 utimes(p, uap, retval)
   1486 	struct proc *p;
   1487 	register struct utimes_args *uap;
   1488 	int *retval;
   1489 {
   1490 	register struct vnode *vp;
   1491 	struct timeval tv[2];
   1492 	struct vattr vattr;
   1493 	int error;
   1494 	struct nameidata nd;
   1495 
   1496 	VATTR_NULL(&vattr);
   1497 	if (uap->tptr == NULL) {
   1498 		microtime(&tv[0]);
   1499 		tv[1] = tv[0];
   1500 		vattr.va_vaflags |= VA_UTIMES_NULL;
   1501 	} else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
   1502   		return (error);
   1503 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
   1504 	if (error = namei(&nd))
   1505 		return (error);
   1506 	vp = nd.ni_vp;
   1507 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
   1508 	VOP_LOCK(vp);
   1509 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
   1510 		error = EROFS;
   1511 	else {
   1512 		vattr.va_atime.ts_sec = tv[0].tv_sec;
   1513 		vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
   1514 		vattr.va_mtime.ts_sec = tv[1].tv_sec;
   1515 		vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
   1516 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
   1517 	}
   1518 	vput(vp);
   1519 	return (error);
   1520 }
   1521 
   1522 /*
   1523  * Truncate a file given its path name.
   1524  */
   1525 struct truncate_args {
   1526 	char	*path;
   1527 	int	pad;
   1528 	off_t	length;
   1529 };
   1530 /* ARGSUSED */
   1531 truncate(p, uap, retval)
   1532 	struct proc *p;
   1533 	register struct truncate_args *uap;
   1534 	int *retval;
   1535 {
   1536 	register struct vnode *vp;
   1537 	struct vattr vattr;
   1538 	int error;
   1539 	struct nameidata nd;
   1540 
   1541 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
   1542 	if (error = namei(&nd))
   1543 		return (error);
   1544 	vp = nd.ni_vp;
   1545 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
   1546 	VOP_LOCK(vp);
   1547 	if (vp->v_type == VDIR)
   1548 		error = EISDIR;
   1549 	else if ((error = vn_writechk(vp)) == 0 &&
   1550 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
   1551 		VATTR_NULL(&vattr);
   1552 		vattr.va_size = uap->length;
   1553 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
   1554 	}
   1555 	vput(vp);
   1556 	return (error);
   1557 }
   1558 
   1559 /*
   1560  * Truncate a file given a file descriptor.
   1561  */
   1562 struct ftruncate_args {
   1563 	int	fd;
   1564 	int	pad;
   1565 	off_t	length;
   1566 };
   1567 /* ARGSUSED */
   1568 ftruncate(p, uap, retval)
   1569 	struct proc *p;
   1570 	register struct ftruncate_args *uap;
   1571 	int *retval;
   1572 {
   1573 	struct vattr vattr;
   1574 	struct vnode *vp;
   1575 	struct file *fp;
   1576 	int error;
   1577 
   1578 	if (error = getvnode(p->p_fd, uap->fd, &fp))
   1579 		return (error);
   1580 	if ((fp->f_flag & FWRITE) == 0)
   1581 		return (EINVAL);
   1582 	vp = (struct vnode *)fp->f_data;
   1583 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
   1584 	VOP_LOCK(vp);
   1585 	if (vp->v_type == VDIR)
   1586 		error = EISDIR;
   1587 	else if ((error = vn_writechk(vp)) == 0) {
   1588 		VATTR_NULL(&vattr);
   1589 		vattr.va_size = uap->length;
   1590 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
   1591 	}
   1592 	VOP_UNLOCK(vp);
   1593 	return (error);
   1594 }
   1595 
   1596 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
   1597 /*
   1598  * Truncate a file given its path name.
   1599  */
   1600 struct otruncate_args {
   1601 	char	*path;
   1602 	long	length;
   1603 };
   1604 /* ARGSUSED */
   1605 otruncate(p, uap, retval)
   1606 	struct proc *p;
   1607 	register struct otruncate_args *uap;
   1608 	int *retval;
   1609 {
   1610 	struct truncate_args nuap;
   1611 
   1612 	nuap.path = uap->path;
   1613 	nuap.length = uap->length;
   1614 	return (truncate(p, &nuap, retval));
   1615 }
   1616 
   1617 /*
   1618  * Truncate a file given a file descriptor.
   1619  */
   1620 struct oftruncate_args {
   1621 	int	fd;
   1622 	long	length;
   1623 };
   1624 /* ARGSUSED */
   1625 oftruncate(p, uap, retval)
   1626 	struct proc *p;
   1627 	register struct oftruncate_args *uap;
   1628 	int *retval;
   1629 {
   1630 	struct ftruncate_args nuap;
   1631 
   1632 	nuap.fd = uap->fd;
   1633 	nuap.length = uap->length;
   1634 	return (ftruncate(p, &nuap, retval));
   1635 }
   1636 #endif /* COMPAT_43 || COMPAT_SUNOS */
   1637 
   1638 /*
   1639  * Sync an open file.
   1640  */
   1641 struct fsync_args {
   1642 	int	fd;
   1643 };
   1644 /* ARGSUSED */
   1645 fsync(p, uap, retval)
   1646 	struct proc *p;
   1647 	struct fsync_args *uap;
   1648 	int *retval;
   1649 {
   1650 	register struct vnode *vp;
   1651 	struct file *fp;
   1652 	int error;
   1653 
   1654 	if (error = getvnode(p->p_fd, uap->fd, &fp))
   1655 		return (error);
   1656 	vp = (struct vnode *)fp->f_data;
   1657 	VOP_LOCK(vp);
   1658 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
   1659 	VOP_UNLOCK(vp);
   1660 	return (error);
   1661 }
   1662 
   1663 /*
   1664  * Rename files.  Source and destination must either both be directories,
   1665  * or both not be directories.  If target is a directory, it must be empty.
   1666  */
   1667 struct rename_args {
   1668 	char	*from;
   1669 	char	*to;
   1670 };
   1671 /* ARGSUSED */
   1672 rename(p, uap, retval)
   1673 	struct proc *p;
   1674 	register struct rename_args *uap;
   1675 	int *retval;
   1676 {
   1677 	register struct vnode *tvp, *fvp, *tdvp;
   1678 	struct nameidata fromnd, tond;
   1679 	int error;
   1680 
   1681 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
   1682 		uap->from, p);
   1683 	if (error = namei(&fromnd))
   1684 		return (error);
   1685 	fvp = fromnd.ni_vp;
   1686 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
   1687 		UIO_USERSPACE, uap->to, p);
   1688 	if (error = namei(&tond)) {
   1689 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
   1690 		vrele(fromnd.ni_dvp);
   1691 		vrele(fvp);
   1692 		goto out1;
   1693 	}
   1694 	tdvp = tond.ni_dvp;
   1695 	tvp = tond.ni_vp;
   1696 	if (tvp != NULL) {
   1697 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
   1698 			error = ENOTDIR;
   1699 			goto out;
   1700 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
   1701 			error = EISDIR;
   1702 			goto out;
   1703 		}
   1704 	}
   1705 	if (fvp == tdvp)
   1706 		error = EINVAL;
   1707 	/*
   1708 	 * If source is the same as the destination (that is the
   1709 	 * same inode number with the same name in the same directory),
   1710 	 * then there is nothing to do.
   1711 	 */
   1712 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
   1713 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
   1714 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
   1715 	      fromnd.ni_cnd.cn_namelen))
   1716 		error = -1;
   1717 out:
   1718 	if (!error) {
   1719 		LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
   1720 		if (fromnd.ni_dvp != tdvp)
   1721 			LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
   1722 		if (tvp)
   1723 			LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
   1724 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
   1725 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
   1726 	} else {
   1727 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
   1728 		if (tdvp == tvp)
   1729 			vrele(tdvp);
   1730 		else
   1731 			vput(tdvp);
   1732 		if (tvp)
   1733 			vput(tvp);
   1734 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
   1735 		vrele(fromnd.ni_dvp);
   1736 		vrele(fvp);
   1737 	}
   1738 	vrele(tond.ni_startdir);
   1739 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
   1740 out1:
   1741 	if (fromnd.ni_startdir)
   1742 		vrele(fromnd.ni_startdir);
   1743 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
   1744 	if (error == -1)
   1745 		return (0);
   1746 	return (error);
   1747 }
   1748 
   1749 /*
   1750  * Make a directory file.
   1751  */
   1752 struct mkdir_args {
   1753 	char	*path;
   1754 	int	mode;
   1755 };
   1756 /* ARGSUSED */
   1757 mkdir(p, uap, retval)
   1758 	struct proc *p;
   1759 	register struct mkdir_args *uap;
   1760 	int *retval;
   1761 {
   1762 	register struct vnode *vp;
   1763 	struct vattr vattr;
   1764 	int error;
   1765 	struct nameidata nd;
   1766 
   1767 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
   1768 	if (error = namei(&nd))
   1769 		return (error);
   1770 	vp = nd.ni_vp;
   1771 	if (vp != NULL) {
   1772 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1773 		if (nd.ni_dvp == vp)
   1774 			vrele(nd.ni_dvp);
   1775 		else
   1776 			vput(nd.ni_dvp);
   1777 		vrele(vp);
   1778 		return (EEXIST);
   1779 	}
   1780 	VATTR_NULL(&vattr);
   1781 	vattr.va_type = VDIR;
   1782 	vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
   1783 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
   1784 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
   1785 	if (!error)
   1786 		vput(nd.ni_vp);
   1787 	return (error);
   1788 }
   1789 
   1790 /*
   1791  * Remove a directory file.
   1792  */
   1793 struct rmdir_args {
   1794 	char	*path;
   1795 };
   1796 /* ARGSUSED */
   1797 rmdir(p, uap, retval)
   1798 	struct proc *p;
   1799 	struct rmdir_args *uap;
   1800 	int *retval;
   1801 {
   1802 	register struct vnode *vp;
   1803 	int error;
   1804 	struct nameidata nd;
   1805 
   1806 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p);
   1807 	if (error = namei(&nd))
   1808 		return (error);
   1809 	vp = nd.ni_vp;
   1810 	if (vp->v_type != VDIR) {
   1811 		error = ENOTDIR;
   1812 		goto out;
   1813 	}
   1814 	/*
   1815 	 * No rmdir "." please.
   1816 	 */
   1817 	if (nd.ni_dvp == vp) {
   1818 		error = EINVAL;
   1819 		goto out;
   1820 	}
   1821 	/*
   1822 	 * The root of a mounted filesystem cannot be deleted.
   1823 	 */
   1824 	if (vp->v_flag & VROOT)
   1825 		error = EBUSY;
   1826 out:
   1827 	if (!error) {
   1828 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
   1829 		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
   1830 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
   1831 	} else {
   1832 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1833 		if (nd.ni_dvp == vp)
   1834 			vrele(nd.ni_dvp);
   1835 		else
   1836 			vput(nd.ni_dvp);
   1837 		vput(vp);
   1838 	}
   1839 	return (error);
   1840 }
   1841 
   1842 #ifdef COMPAT_43
   1843 /*
   1844  * Read a block of directory entries in a file system independent format.
   1845  */
   1846 struct ogetdirentries_args {
   1847 	int	fd;
   1848 	char	*buf;
   1849 	u_int	count;
   1850 	long	*basep;
   1851 };
   1852 ogetdirentries(p, uap, retval)
   1853 	struct proc *p;
   1854 	register struct ogetdirentries_args *uap;
   1855 	int *retval;
   1856 {
   1857 	register struct vnode *vp;
   1858 	struct file *fp;
   1859 	struct uio auio, kuio;
   1860 	struct iovec aiov, kiov;
   1861 	struct dirent *dp, *edp;
   1862 	caddr_t dirbuf;
   1863 	int error, readcnt;
   1864 	long loff;
   1865 
   1866 	if (error = getvnode(p->p_fd, uap->fd, &fp))
   1867 		return (error);
   1868 	if ((fp->f_flag & FREAD) == 0)
   1869 		return (EBADF);
   1870 	vp = (struct vnode *)fp->f_data;
   1871 	if (vp->v_type != VDIR)
   1872 		return (EINVAL);
   1873 	aiov.iov_base = uap->buf;
   1874 	aiov.iov_len = uap->count;
   1875 	auio.uio_iov = &aiov;
   1876 	auio.uio_iovcnt = 1;
   1877 	auio.uio_rw = UIO_READ;
   1878 	auio.uio_segflg = UIO_USERSPACE;
   1879 	auio.uio_procp = p;
   1880 	auio.uio_resid = uap->count;
   1881 	VOP_LOCK(vp);
   1882 	loff = auio.uio_offset = fp->f_offset;
   1883 #	if (BYTE_ORDER != LITTLE_ENDIAN)
   1884 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
   1885 			error = VOP_READDIR(vp, &auio, fp->f_cred);
   1886 			fp->f_offset = auio.uio_offset;
   1887 		} else
   1888 #	endif
   1889 	{
   1890 		kuio = auio;
   1891 		kuio.uio_iov = &kiov;
   1892 		kuio.uio_segflg = UIO_SYSSPACE;
   1893 		kiov.iov_len = uap->count;
   1894 		MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
   1895 		kiov.iov_base = dirbuf;
   1896 		error = VOP_READDIR(vp, &kuio, fp->f_cred);
   1897 		fp->f_offset = kuio.uio_offset;
   1898 		if (error == 0) {
   1899 			readcnt = uap->count - kuio.uio_resid;
   1900 			edp = (struct dirent *)&dirbuf[readcnt];
   1901 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
   1902 #				if (BYTE_ORDER == LITTLE_ENDIAN)
   1903 					/*
   1904 					 * The expected low byte of
   1905 					 * dp->d_namlen is our dp->d_type.
   1906 					 * The high MBZ byte of dp->d_namlen
   1907 					 * is our dp->d_namlen.
   1908 					 */
   1909 					dp->d_type = dp->d_namlen;
   1910 					dp->d_namlen = 0;
   1911 #				else
   1912 					/*
   1913 					 * The dp->d_type is the high byte
   1914 					 * of the expected dp->d_namlen,
   1915 					 * so must be zero'ed.
   1916 					 */
   1917 					dp->d_type = 0;
   1918 #				endif
   1919 				if (dp->d_reclen > 0) {
   1920 					dp = (struct dirent *)
   1921 					    ((char *)dp + dp->d_reclen);
   1922 				} else {
   1923 					error = EIO;
   1924 					break;
   1925 				}
   1926 			}
   1927 			if (dp >= edp)
   1928 				error = uiomove(dirbuf, readcnt, &auio);
   1929 		}
   1930 		FREE(dirbuf, M_TEMP);
   1931 	}
   1932 	VOP_UNLOCK(vp);
   1933 	if (error)
   1934 		return (error);
   1935 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
   1936 	*retval = uap->count - auio.uio_resid;
   1937 	return (error);
   1938 }
   1939 #endif
   1940 
   1941 /*
   1942  * Read a block of directory entries in a file system independent format.
   1943  */
   1944 struct getdirentries_args {
   1945 	int	fd;
   1946 	char	*buf;
   1947 	u_int	count;
   1948 	long	*basep;
   1949 };
   1950 getdirentries(p, uap, retval)
   1951 	struct proc *p;
   1952 	register struct getdirentries_args *uap;
   1953 	int *retval;
   1954 {
   1955 	register struct vnode *vp;
   1956 	struct file *fp;
   1957 	struct uio auio;
   1958 	struct iovec aiov;
   1959 	long loff;
   1960 	int error;
   1961 
   1962 	if (error = getvnode(p->p_fd, uap->fd, &fp))
   1963 		return (error);
   1964 	if ((fp->f_flag & FREAD) == 0)
   1965 		return (EBADF);
   1966 	vp = (struct vnode *)fp->f_data;
   1967 unionread:
   1968 	if (vp->v_type != VDIR)
   1969 		return (EINVAL);
   1970 	aiov.iov_base = uap->buf;
   1971 	aiov.iov_len = uap->count;
   1972 	auio.uio_iov = &aiov;
   1973 	auio.uio_iovcnt = 1;
   1974 	auio.uio_rw = UIO_READ;
   1975 	auio.uio_segflg = UIO_USERSPACE;
   1976 	auio.uio_procp = p;
   1977 	auio.uio_resid = uap->count;
   1978 	VOP_LOCK(vp);
   1979 	loff = auio.uio_offset = fp->f_offset;
   1980 	error = VOP_READDIR(vp, &auio, fp->f_cred);
   1981 	fp->f_offset = auio.uio_offset;
   1982 	VOP_UNLOCK(vp);
   1983 	if (error)
   1984 		return (error);
   1985 
   1986 #ifdef UNION
   1987 {
   1988 	extern int (**union_vnodeop_p)();
   1989 	extern struct vnode *union_lowervp __P((struct vnode *));
   1990 
   1991 	if ((uap->count == auio.uio_resid) &&
   1992 	    (vp->v_op == union_vnodeop_p)) {
   1993 		struct vnode *tvp = vp;
   1994 
   1995 		vp = union_lowervp(vp);
   1996 		if (vp != NULLVP) {
   1997 			VOP_LOCK(vp);
   1998 			error = VOP_OPEN(vp, FREAD);
   1999 			VOP_UNLOCK(vp);
   2000 
   2001 			if (error) {
   2002 				vrele(vp);
   2003 				return (error);
   2004 			}
   2005 			fp->f_data = (caddr_t) vp;
   2006 			fp->f_offset = 0;
   2007 			error = vn_close(tvp, FREAD, fp->f_cred, p);
   2008 			if (error)
   2009 				return (error);
   2010 			goto unionread;
   2011 		}
   2012 	}
   2013 }
   2014 #endif
   2015 
   2016 	if ((uap->count == auio.uio_resid) &&
   2017 	    (vp->v_flag & VROOT) &&
   2018 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
   2019 		struct vnode *tvp = vp;
   2020 		vp = vp->v_mount->mnt_vnodecovered;
   2021 		VREF(vp);
   2022 		fp->f_data = (caddr_t) vp;
   2023 		fp->f_offset = 0;
   2024 		vrele(tvp);
   2025 		goto unionread;
   2026 	}
   2027 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
   2028 	*retval = uap->count - auio.uio_resid;
   2029 	return (error);
   2030 }
   2031 
   2032 /*
   2033  * Set the mode mask for creation of filesystem nodes.
   2034  */
   2035 struct umask_args {
   2036 	int	newmask;
   2037 };
   2038 mode_t				/* XXX */
   2039 umask(p, uap, retval)
   2040 	struct proc *p;
   2041 	struct umask_args *uap;
   2042 	int *retval;
   2043 {
   2044 	register struct filedesc *fdp;
   2045 
   2046 	fdp = p->p_fd;
   2047 	*retval = fdp->fd_cmask;
   2048 	fdp->fd_cmask = uap->newmask & ALLPERMS;
   2049 	return (0);
   2050 }
   2051 
   2052 /*
   2053  * Void all references to file by ripping underlying filesystem
   2054  * away from vnode.
   2055  */
   2056 struct revoke_args {
   2057 	char	*path;
   2058 };
   2059 /* ARGSUSED */
   2060 revoke(p, uap, retval)
   2061 	struct proc *p;
   2062 	register struct revoke_args *uap;
   2063 	int *retval;
   2064 {
   2065 	register struct vnode *vp;
   2066 	struct vattr vattr;
   2067 	int error;
   2068 	struct nameidata nd;
   2069 
   2070 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
   2071 	if (error = namei(&nd))
   2072 		return (error);
   2073 	vp = nd.ni_vp;
   2074 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
   2075 		error = EINVAL;
   2076 		goto out;
   2077 	}
   2078 	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
   2079 		goto out;
   2080 	if (p->p_ucred->cr_uid != vattr.va_uid &&
   2081 	    (error = suser(p->p_ucred, &p->p_acflag)))
   2082 		goto out;
   2083 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
   2084 		vgoneall(vp);
   2085 out:
   2086 	vrele(vp);
   2087 	return (error);
   2088 }
   2089 
   2090 /*
   2091  * Convert a user file descriptor to a kernel file entry.
   2092  */
   2093 getvnode(fdp, fd, fpp)
   2094 	struct filedesc *fdp;
   2095 	struct file **fpp;
   2096 	int fd;
   2097 {
   2098 	struct file *fp;
   2099 
   2100 	if ((u_int)fd >= fdp->fd_nfiles ||
   2101 	    (fp = fdp->fd_ofiles[fd]) == NULL)
   2102 		return (EBADF);
   2103 	if (fp->f_type != DTYPE_VNODE)
   2104 		return (EINVAL);
   2105 	*fpp = fp;
   2106 	return (0);
   2107 }
   2108