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