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