xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 54620)
123405Smckusick /*
237741Smckusick  * Copyright (c) 1989 The Regents of the University of California.
337741Smckusick  * All rights reserved.
423405Smckusick  *
544459Sbostic  * %sccs.include.redist.c%
637741Smckusick  *
7*54620Smckusick  *	@(#)vfs_syscalls.c	7.89 (Berkeley) 07/02/92
823405Smckusick  */
937Sbill 
1017101Sbloom #include "param.h"
1117101Sbloom #include "systm.h"
1247540Skarels #include "namei.h"
1345914Smckusick #include "filedesc.h"
1417101Sbloom #include "kernel.h"
1517101Sbloom #include "file.h"
1617101Sbloom #include "stat.h"
1737741Smckusick #include "vnode.h"
1837741Smckusick #include "mount.h"
1917101Sbloom #include "proc.h"
2017101Sbloom #include "uio.h"
2137741Smckusick #include "malloc.h"
22*54620Smckusick #include "dirent.h"
2353468Smckusick #include <vm/vm.h>
2437Sbill 
2537741Smckusick /*
2637741Smckusick  * Virtual File System System Calls
2737741Smckusick  */
2812756Ssam 
299167Ssam /*
3049365Smckusick  * Mount system call.
319167Ssam  */
3242441Smckusick /* ARGSUSED */
3342441Smckusick mount(p, uap, retval)
3445914Smckusick 	struct proc *p;
3542441Smckusick 	register struct args {
3637741Smckusick 		int	type;
3737741Smckusick 		char	*dir;
3837741Smckusick 		int	flags;
3937741Smckusick 		caddr_t	data;
4042441Smckusick 	} *uap;
4142441Smckusick 	int *retval;
4242441Smckusick {
4353548Sheideman 	USES_VOP_UNLOCK;
4439335Smckusick 	register struct vnode *vp;
4539335Smckusick 	register struct mount *mp;
4640111Smckusick 	int error, flag;
4747540Skarels 	struct nameidata nd;
486254Sroot 
4937741Smckusick 	/*
5037741Smckusick 	 * Must be super user
5137741Smckusick 	 */
5247540Skarels 	if (error = suser(p->p_ucred, &p->p_acflag))
5347540Skarels 		return (error);
5437741Smckusick 	/*
5537741Smckusick 	 * Get vnode to be covered
5637741Smckusick 	 */
5752322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->dir, p);
5852322Smckusick 	if (error = namei(&nd))
5947540Skarels 		return (error);
6052322Smckusick 	vp = nd.ni_vp;
6141400Smckusick 	if (uap->flags & MNT_UPDATE) {
6239335Smckusick 		if ((vp->v_flag & VROOT) == 0) {
6339335Smckusick 			vput(vp);
6447540Skarels 			return (EINVAL);
6539335Smckusick 		}
6639335Smckusick 		mp = vp->v_mount;
6739335Smckusick 		/*
6839335Smckusick 		 * We allow going from read-only to read-write,
6939335Smckusick 		 * but not from read-write to read-only.
7039335Smckusick 		 */
7141400Smckusick 		if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
7241400Smckusick 		    (uap->flags & MNT_RDONLY) != 0) {
7339335Smckusick 			vput(vp);
7447540Skarels 			return (EOPNOTSUPP);	/* Needs translation */
7539335Smckusick 		}
7641400Smckusick 		flag = mp->mnt_flag;
7741400Smckusick 		mp->mnt_flag |= MNT_UPDATE;
7839335Smckusick 		VOP_UNLOCK(vp);
7939335Smckusick 		goto update;
8039335Smckusick 	}
8139805Smckusick 	if (vp->v_usecount != 1) {
8237741Smckusick 		vput(vp);
8347540Skarels 		return (EBUSY);
8437741Smckusick 	}
8554441Smckusick 	if (error = vinvalbuf(vp, 1, p->p_ucred, p))
8654441Smckusick 		return (error);
8737741Smckusick 	if (vp->v_type != VDIR) {
8837741Smckusick 		vput(vp);
8947540Skarels 		return (ENOTDIR);
9037741Smckusick 	}
9139741Smckusick 	if ((unsigned long)uap->type > MOUNT_MAXTYPE ||
9237741Smckusick 	    vfssw[uap->type] == (struct vfsops *)0) {
9337741Smckusick 		vput(vp);
9447540Skarels 		return (ENODEV);
9537741Smckusick 	}
9637741Smckusick 
9737741Smckusick 	/*
9839335Smckusick 	 * Allocate and initialize the file system.
9937741Smckusick 	 */
10037741Smckusick 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
10137741Smckusick 		M_MOUNT, M_WAITOK);
10254172Smckusick 	bzero((char *)mp, (u_long)sizeof(struct mount));
10341400Smckusick 	mp->mnt_op = vfssw[uap->type];
10439335Smckusick 	if (error = vfs_lock(mp)) {
10539335Smckusick 		free((caddr_t)mp, M_MOUNT);
10639335Smckusick 		vput(vp);
10747540Skarels 		return (error);
10839335Smckusick 	}
10939335Smckusick 	if (vp->v_mountedhere != (struct mount *)0) {
11039335Smckusick 		vfs_unlock(mp);
11139335Smckusick 		free((caddr_t)mp, M_MOUNT);
11239335Smckusick 		vput(vp);
11347540Skarels 		return (EBUSY);
11439335Smckusick 	}
11539335Smckusick 	vp->v_mountedhere = mp;
11641400Smckusick 	mp->mnt_vnodecovered = vp;
11739335Smckusick update:
11839335Smckusick 	/*
11939335Smckusick 	 * Set the mount level flags.
12039335Smckusick 	 */
12141400Smckusick 	if (uap->flags & MNT_RDONLY)
12241400Smckusick 		mp->mnt_flag |= MNT_RDONLY;
12339335Smckusick 	else
12441400Smckusick 		mp->mnt_flag &= ~MNT_RDONLY;
12541400Smckusick 	if (uap->flags & MNT_NOSUID)
12641400Smckusick 		mp->mnt_flag |= MNT_NOSUID;
12739335Smckusick 	else
12841400Smckusick 		mp->mnt_flag &= ~MNT_NOSUID;
12941400Smckusick 	if (uap->flags & MNT_NOEXEC)
13041400Smckusick 		mp->mnt_flag |= MNT_NOEXEC;
13139335Smckusick 	else
13241400Smckusick 		mp->mnt_flag &= ~MNT_NOEXEC;
13341400Smckusick 	if (uap->flags & MNT_NODEV)
13441400Smckusick 		mp->mnt_flag |= MNT_NODEV;
13539335Smckusick 	else
13641400Smckusick 		mp->mnt_flag &= ~MNT_NODEV;
13741400Smckusick 	if (uap->flags & MNT_SYNCHRONOUS)
13841400Smckusick 		mp->mnt_flag |= MNT_SYNCHRONOUS;
13939335Smckusick 	else
14041400Smckusick 		mp->mnt_flag &= ~MNT_SYNCHRONOUS;
14139335Smckusick 	/*
14239335Smckusick 	 * Mount the filesystem.
14339335Smckusick 	 */
14452322Smckusick 	error = VFS_MOUNT(mp, uap->dir, uap->data, &nd, p);
14541400Smckusick 	if (mp->mnt_flag & MNT_UPDATE) {
14641400Smckusick 		mp->mnt_flag &= ~MNT_UPDATE;
14739335Smckusick 		vrele(vp);
14840111Smckusick 		if (error)
14941400Smckusick 			mp->mnt_flag = flag;
15047540Skarels 		return (error);
15139335Smckusick 	}
15240110Smckusick 	/*
15340110Smckusick 	 * Put the new filesystem on the mount list after root.
15440110Smckusick 	 */
15541400Smckusick 	mp->mnt_next = rootfs->mnt_next;
15641400Smckusick 	mp->mnt_prev = rootfs;
15741400Smckusick 	rootfs->mnt_next = mp;
15841400Smckusick 	mp->mnt_next->mnt_prev = mp;
15937741Smckusick 	cache_purge(vp);
16037741Smckusick 	if (!error) {
16139335Smckusick 		VOP_UNLOCK(vp);
16237741Smckusick 		vfs_unlock(mp);
16348026Smckusick 		error = VFS_START(mp, 0, p);
16437741Smckusick 	} else {
16537741Smckusick 		vfs_remove(mp);
16637741Smckusick 		free((caddr_t)mp, M_MOUNT);
16739335Smckusick 		vput(vp);
16837741Smckusick 	}
16947540Skarels 	return (error);
1706254Sroot }
1716254Sroot 
1729167Ssam /*
17337741Smckusick  * Unmount system call.
17437741Smckusick  *
17537741Smckusick  * Note: unmount takes a path to the vnode mounted on as argument,
17637741Smckusick  * not special file (as before).
1779167Ssam  */
17842441Smckusick /* ARGSUSED */
17942441Smckusick unmount(p, uap, retval)
18045914Smckusick 	struct proc *p;
18142441Smckusick 	register struct args {
18237741Smckusick 		char	*pathp;
18337741Smckusick 		int	flags;
18442441Smckusick 	} *uap;
18542441Smckusick 	int *retval;
18642441Smckusick {
18737741Smckusick 	register struct vnode *vp;
18839356Smckusick 	struct mount *mp;
18937741Smckusick 	int error;
19047540Skarels 	struct nameidata nd;
1916254Sroot 
19237741Smckusick 	/*
19337741Smckusick 	 * Must be super user
19437741Smckusick 	 */
19547540Skarels 	if (error = suser(p->p_ucred, &p->p_acflag))
19647540Skarels 		return (error);
19737741Smckusick 
19852322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->pathp, p);
19952322Smckusick 	if (error = namei(&nd))
20047540Skarels 		return (error);
20152322Smckusick 	vp = nd.ni_vp;
20237741Smckusick 	/*
20337741Smckusick 	 * Must be the root of the filesystem
20437741Smckusick 	 */
20537741Smckusick 	if ((vp->v_flag & VROOT) == 0) {
20637741Smckusick 		vput(vp);
20747540Skarels 		return (EINVAL);
20837741Smckusick 	}
20937741Smckusick 	mp = vp->v_mount;
21037741Smckusick 	vput(vp);
21148026Smckusick 	return (dounmount(mp, uap->flags, p));
21239356Smckusick }
21339356Smckusick 
21439356Smckusick /*
21539356Smckusick  * Do an unmount.
21639356Smckusick  */
21748026Smckusick dounmount(mp, flags, p)
21839356Smckusick 	register struct mount *mp;
21939356Smckusick 	int flags;
22048026Smckusick 	struct proc *p;
22139356Smckusick {
22239356Smckusick 	struct vnode *coveredvp;
22339356Smckusick 	int error;
22439356Smckusick 
22541400Smckusick 	coveredvp = mp->mnt_vnodecovered;
22641298Smckusick 	if (vfs_busy(mp))
22741298Smckusick 		return (EBUSY);
22841400Smckusick 	mp->mnt_flag |= MNT_UNMOUNT;
22937741Smckusick 	if (error = vfs_lock(mp))
23039356Smckusick 		return (error);
23137741Smckusick 
23245738Smckusick 	vnode_pager_umount(mp);	/* release cached vnodes */
23337741Smckusick 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
23454441Smckusick 	if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
23554441Smckusick 	    (flags & MNT_FORCE))
23648026Smckusick 		error = VFS_UNMOUNT(mp, flags, p);
23741400Smckusick 	mp->mnt_flag &= ~MNT_UNMOUNT;
23841298Smckusick 	vfs_unbusy(mp);
23937741Smckusick 	if (error) {
24037741Smckusick 		vfs_unlock(mp);
24137741Smckusick 	} else {
24237741Smckusick 		vrele(coveredvp);
24337741Smckusick 		vfs_remove(mp);
24452287Smckusick 		if (mp->mnt_mounth != NULL)
24552287Smckusick 			panic("unmount: dangling vnode");
24637741Smckusick 		free((caddr_t)mp, M_MOUNT);
24737741Smckusick 	}
24839356Smckusick 	return (error);
2496254Sroot }
2506254Sroot 
2519167Ssam /*
25237741Smckusick  * Sync system call.
25337741Smckusick  * Sync each mounted filesystem.
2549167Ssam  */
25539491Smckusick /* ARGSUSED */
25642441Smckusick sync(p, uap, retval)
25745914Smckusick 	struct proc *p;
25847540Skarels 	void *uap;
25942441Smckusick 	int *retval;
2606254Sroot {
26137741Smckusick 	register struct mount *mp;
26241298Smckusick 	struct mount *omp;
26337741Smckusick 
26437741Smckusick 	mp = rootfs;
26537741Smckusick 	do {
26640343Smckusick 		/*
26740343Smckusick 		 * The lock check below is to avoid races with mount
26840343Smckusick 		 * and unmount.
26940343Smckusick 		 */
27041400Smckusick 		if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
27141298Smckusick 		    !vfs_busy(mp)) {
27254441Smckusick 			VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
27341298Smckusick 			omp = mp;
27441400Smckusick 			mp = mp->mnt_next;
27541298Smckusick 			vfs_unbusy(omp);
27641298Smckusick 		} else
27741400Smckusick 			mp = mp->mnt_next;
27837741Smckusick 	} while (mp != rootfs);
27947688Skarels 	return (0);
28037741Smckusick }
28137741Smckusick 
28237741Smckusick /*
28349365Smckusick  * Operate on filesystem quotas.
28441298Smckusick  */
28542441Smckusick /* ARGSUSED */
28642441Smckusick quotactl(p, uap, retval)
28745914Smckusick 	struct proc *p;
28842441Smckusick 	register struct args {
28941298Smckusick 		char *path;
29041298Smckusick 		int cmd;
29141298Smckusick 		int uid;
29241298Smckusick 		caddr_t arg;
29342441Smckusick 	} *uap;
29442441Smckusick 	int *retval;
29542441Smckusick {
29641298Smckusick 	register struct mount *mp;
29741298Smckusick 	int error;
29847540Skarels 	struct nameidata nd;
29941298Smckusick 
30052322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
30152322Smckusick 	if (error = namei(&nd))
30247540Skarels 		return (error);
30352322Smckusick 	mp = nd.ni_vp->v_mount;
30452322Smckusick 	vrele(nd.ni_vp);
30548026Smckusick 	return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
30641298Smckusick }
30741298Smckusick 
30841298Smckusick /*
30949365Smckusick  * Get filesystem statistics.
31037741Smckusick  */
31142441Smckusick /* ARGSUSED */
31242441Smckusick statfs(p, uap, retval)
31345914Smckusick 	struct proc *p;
31442441Smckusick 	register struct args {
31537741Smckusick 		char *path;
31637741Smckusick 		struct statfs *buf;
31742441Smckusick 	} *uap;
31842441Smckusick 	int *retval;
31942441Smckusick {
32039464Smckusick 	register struct mount *mp;
32140343Smckusick 	register struct statfs *sp;
32237741Smckusick 	int error;
32347540Skarels 	struct nameidata nd;
32437741Smckusick 
32552322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
32652322Smckusick 	if (error = namei(&nd))
32747540Skarels 		return (error);
32852322Smckusick 	mp = nd.ni_vp->v_mount;
32941400Smckusick 	sp = &mp->mnt_stat;
33052322Smckusick 	vrele(nd.ni_vp);
33148026Smckusick 	if (error = VFS_STATFS(mp, sp, p))
33247540Skarels 		return (error);
33341400Smckusick 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
33447540Skarels 	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
33537741Smckusick }
33637741Smckusick 
33742441Smckusick /*
33849365Smckusick  * Get filesystem statistics.
33942441Smckusick  */
34042441Smckusick /* ARGSUSED */
34142441Smckusick fstatfs(p, uap, retval)
34245914Smckusick 	struct proc *p;
34342441Smckusick 	register struct args {
34437741Smckusick 		int fd;
34537741Smckusick 		struct statfs *buf;
34642441Smckusick 	} *uap;
34742441Smckusick 	int *retval;
34842441Smckusick {
34937741Smckusick 	struct file *fp;
35039464Smckusick 	struct mount *mp;
35140343Smckusick 	register struct statfs *sp;
35237741Smckusick 	int error;
35337741Smckusick 
35445914Smckusick 	if (error = getvnode(p->p_fd, uap->fd, &fp))
35547540Skarels 		return (error);
35639464Smckusick 	mp = ((struct vnode *)fp->f_data)->v_mount;
35741400Smckusick 	sp = &mp->mnt_stat;
35848026Smckusick 	if (error = VFS_STATFS(mp, sp, p))
35947540Skarels 		return (error);
36041400Smckusick 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
36147540Skarels 	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
36237741Smckusick }
36337741Smckusick 
36437741Smckusick /*
36549365Smckusick  * Get statistics on all filesystems.
36638270Smckusick  */
36742441Smckusick getfsstat(p, uap, retval)
36845914Smckusick 	struct proc *p;
36942441Smckusick 	register struct args {
37038270Smckusick 		struct statfs *buf;
37138270Smckusick 		long bufsize;
37240343Smckusick 		int flags;
37342441Smckusick 	} *uap;
37442441Smckusick 	int *retval;
37542441Smckusick {
37638270Smckusick 	register struct mount *mp;
37740343Smckusick 	register struct statfs *sp;
37839606Smckusick 	caddr_t sfsp;
37938270Smckusick 	long count, maxcount, error;
38038270Smckusick 
38138270Smckusick 	maxcount = uap->bufsize / sizeof(struct statfs);
38239606Smckusick 	sfsp = (caddr_t)uap->buf;
38338270Smckusick 	mp = rootfs;
38438270Smckusick 	count = 0;
38538270Smckusick 	do {
38641400Smckusick 		if (sfsp && count < maxcount &&
38741400Smckusick 		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
38841400Smckusick 			sp = &mp->mnt_stat;
38940343Smckusick 			/*
39040343Smckusick 			 * If MNT_NOWAIT is specified, do not refresh the
39140343Smckusick 			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
39240343Smckusick 			 */
39340343Smckusick 			if (((uap->flags & MNT_NOWAIT) == 0 ||
39440343Smckusick 			    (uap->flags & MNT_WAIT)) &&
39548026Smckusick 			    (error = VFS_STATFS(mp, sp, p))) {
39641400Smckusick 				mp = mp->mnt_prev;
39739607Smckusick 				continue;
39839607Smckusick 			}
39941400Smckusick 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
40040343Smckusick 			if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
40147540Skarels 				return (error);
40240343Smckusick 			sfsp += sizeof(*sp);
40338270Smckusick 		}
40439606Smckusick 		count++;
40541400Smckusick 		mp = mp->mnt_prev;
40638270Smckusick 	} while (mp != rootfs);
40738270Smckusick 	if (sfsp && count > maxcount)
40842441Smckusick 		*retval = maxcount;
40938270Smckusick 	else
41042441Smckusick 		*retval = count;
41147540Skarels 	return (0);
41238270Smckusick }
41338270Smckusick 
41438270Smckusick /*
41538259Smckusick  * Change current working directory to a given file descriptor.
41638259Smckusick  */
41742441Smckusick /* ARGSUSED */
41842441Smckusick fchdir(p, uap, retval)
41945914Smckusick 	struct proc *p;
42042441Smckusick 	struct args {
42142441Smckusick 		int	fd;
42242441Smckusick 	} *uap;
42342441Smckusick 	int *retval;
42438259Smckusick {
42553548Sheideman 	USES_VOP_ACCESS;
42653548Sheideman 	USES_VOP_LOCK;
42753548Sheideman 	USES_VOP_UNLOCK;
42845914Smckusick 	register struct filedesc *fdp = p->p_fd;
42938259Smckusick 	register struct vnode *vp;
43038259Smckusick 	struct file *fp;
43138259Smckusick 	int error;
43238259Smckusick 
43345914Smckusick 	if (error = getvnode(fdp, uap->fd, &fp))
43447540Skarels 		return (error);
43538259Smckusick 	vp = (struct vnode *)fp->f_data;
43638259Smckusick 	VOP_LOCK(vp);
43738259Smckusick 	if (vp->v_type != VDIR)
43838259Smckusick 		error = ENOTDIR;
43938259Smckusick 	else
44048026Smckusick 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
44138259Smckusick 	VOP_UNLOCK(vp);
44239860Smckusick 	if (error)
44347540Skarels 		return (error);
44439860Smckusick 	VREF(vp);
44545914Smckusick 	vrele(fdp->fd_cdir);
44645914Smckusick 	fdp->fd_cdir = vp;
44747540Skarels 	return (0);
44838259Smckusick }
44938259Smckusick 
45038259Smckusick /*
45137741Smckusick  * Change current working directory (``.'').
45237741Smckusick  */
45342441Smckusick /* ARGSUSED */
45442441Smckusick chdir(p, uap, retval)
45545914Smckusick 	struct proc *p;
45642441Smckusick 	struct args {
45742441Smckusick 		char	*fname;
45842441Smckusick 	} *uap;
45942441Smckusick 	int *retval;
46037741Smckusick {
46145914Smckusick 	register struct filedesc *fdp = p->p_fd;
46237741Smckusick 	int error;
46347540Skarels 	struct nameidata nd;
4646254Sroot 
46552322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
46652781Sralph 	if (error = chdirec(&nd, p))
46747540Skarels 		return (error);
46845914Smckusick 	vrele(fdp->fd_cdir);
46952322Smckusick 	fdp->fd_cdir = nd.ni_vp;
47047540Skarels 	return (0);
47137741Smckusick }
4726254Sroot 
47337741Smckusick /*
47437741Smckusick  * Change notion of root (``/'') directory.
47537741Smckusick  */
47642441Smckusick /* ARGSUSED */
47742441Smckusick chroot(p, uap, retval)
47845914Smckusick 	struct proc *p;
47942441Smckusick 	struct args {
48042441Smckusick 		char	*fname;
48142441Smckusick 	} *uap;
48242441Smckusick 	int *retval;
48337741Smckusick {
48445914Smckusick 	register struct filedesc *fdp = p->p_fd;
48537741Smckusick 	int error;
48647540Skarels 	struct nameidata nd;
48737741Smckusick 
48847540Skarels 	if (error = suser(p->p_ucred, &p->p_acflag))
48947540Skarels 		return (error);
49052322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
49152781Sralph 	if (error = chdirec(&nd, p))
49247540Skarels 		return (error);
49345914Smckusick 	if (fdp->fd_rdir != NULL)
49445914Smckusick 		vrele(fdp->fd_rdir);
49552322Smckusick 	fdp->fd_rdir = nd.ni_vp;
49647540Skarels 	return (0);
4976254Sroot }
4986254Sroot 
49937Sbill /*
50037741Smckusick  * Common routine for chroot and chdir.
50137741Smckusick  */
50247540Skarels chdirec(ndp, p)
50352322Smckusick 	register struct nameidata *ndp;
50447540Skarels 	struct proc *p;
50537741Smckusick {
50653548Sheideman 	USES_VOP_ACCESS;
50753548Sheideman 	USES_VOP_UNLOCK;
50837741Smckusick 	struct vnode *vp;
50937741Smckusick 	int error;
51037741Smckusick 
51152322Smckusick 	if (error = namei(ndp))
51237741Smckusick 		return (error);
51337741Smckusick 	vp = ndp->ni_vp;
51437741Smckusick 	if (vp->v_type != VDIR)
51537741Smckusick 		error = ENOTDIR;
51637741Smckusick 	else
51748026Smckusick 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
51837741Smckusick 	VOP_UNLOCK(vp);
51937741Smckusick 	if (error)
52037741Smckusick 		vrele(vp);
52137741Smckusick 	return (error);
52237741Smckusick }
52337741Smckusick 
52437741Smckusick /*
5256254Sroot  * Open system call.
52642441Smckusick  * Check permissions, allocate an open file structure,
52742441Smckusick  * and call the device open routine if any.
5286254Sroot  */
52942441Smckusick open(p, uap, retval)
53045914Smckusick 	struct proc *p;
53142441Smckusick 	register struct args {
5326254Sroot 		char	*fname;
5337701Ssam 		int	mode;
53412756Ssam 		int	crtmode;
53542441Smckusick 	} *uap;
53642441Smckusick 	int *retval;
5376254Sroot {
53853548Sheideman 	USES_VOP_ADVLOCK;
53953548Sheideman 	USES_VOP_UNLOCK;
54045914Smckusick 	register struct filedesc *fdp = p->p_fd;
54142441Smckusick 	register struct file *fp;
54250111Smckusick 	register struct vnode *vp;
54337741Smckusick 	int fmode, cmode;
54437741Smckusick 	struct file *nfp;
54549945Smckusick 	int type, indx, error;
54649945Smckusick 	struct flock lf;
54747540Skarels 	struct nameidata nd;
54837741Smckusick 	extern struct fileops vnops;
5496254Sroot 
55045914Smckusick 	if (error = falloc(p, &nfp, &indx))
55147540Skarels 		return (error);
55237741Smckusick 	fp = nfp;
55346553Skarels 	fmode = FFLAGS(uap->mode);
55445914Smckusick 	cmode = ((uap->crtmode &~ fdp->fd_cmask) & 07777) &~ S_ISVTX;
55552322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
55645202Smckusick 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
55752322Smckusick 	if (error = vn_open(&nd, fmode, cmode)) {
55853828Spendry 		int dfd = p->p_dupfd;
55953828Spendry 		p->p_dupfd = 0;
56049980Smckusick 		ffree(fp);
56153828Spendry 		if ((error == ENODEV || error == ENXIO) && /* XXX from fdopen */
56253828Spendry 		    dfd >= 0 &&
56353828Spendry 		    (error = dupfdopen(fdp, indx, p->p_dupfd,
56453828Spendry 					fmode, error)) == 0) {
56542441Smckusick 			*retval = indx;
56647540Skarels 			return (0);
56742441Smckusick 		}
56840884Smckusick 		if (error == ERESTART)
56940884Smckusick 			error = EINTR;
57047688Skarels 		fdp->fd_ofiles[indx] = NULL;
57147540Skarels 		return (error);
57212756Ssam 	}
57353828Spendry 	p->p_dupfd = 0;
57452322Smckusick 	vp = nd.ni_vp;
57549949Smckusick 	fp->f_flag = fmode & FMASK;
57654348Smckusick 	fp->f_type = DTYPE_VNODE;
57754348Smckusick 	fp->f_ops = &vnops;
57854348Smckusick 	fp->f_data = (caddr_t)vp;
57949945Smckusick 	if (fmode & (O_EXLOCK | O_SHLOCK)) {
58049945Smckusick 		lf.l_whence = SEEK_SET;
58149945Smckusick 		lf.l_start = 0;
58249945Smckusick 		lf.l_len = 0;
58349945Smckusick 		if (fmode & O_EXLOCK)
58449945Smckusick 			lf.l_type = F_WRLCK;
58549945Smckusick 		else
58649945Smckusick 			lf.l_type = F_RDLCK;
58749945Smckusick 		type = F_FLOCK;
58849945Smckusick 		if ((fmode & FNONBLOCK) == 0)
58949945Smckusick 			type |= F_WAIT;
59050111Smckusick 		if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
59150111Smckusick 			VOP_UNLOCK(vp);
59250111Smckusick 			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
59349980Smckusick 			ffree(fp);
59449945Smckusick 			fdp->fd_ofiles[indx] = NULL;
59549945Smckusick 			return (error);
59649945Smckusick 		}
59749949Smckusick 		fp->f_flag |= FHASLOCK;
59849945Smckusick 	}
59950111Smckusick 	VOP_UNLOCK(vp);
60042441Smckusick 	*retval = indx;
60147540Skarels 	return (0);
6026254Sroot }
6036254Sroot 
60442955Smckusick #ifdef COMPAT_43
6056254Sroot /*
60642441Smckusick  * Creat system call.
6076254Sroot  */
60842955Smckusick ocreat(p, uap, retval)
60942441Smckusick 	struct proc *p;
61042441Smckusick 	register struct args {
61142441Smckusick 		char	*fname;
61242441Smckusick 		int	fmode;
61342441Smckusick 	} *uap;
61442441Smckusick 	int *retval;
6156254Sroot {
616*54620Smckusick 	struct nargs {
6176254Sroot 		char	*fname;
61842441Smckusick 		int	mode;
61942441Smckusick 		int	crtmode;
62042441Smckusick 	} openuap;
62142441Smckusick 
62242441Smckusick 	openuap.fname = uap->fname;
62342441Smckusick 	openuap.crtmode = uap->fmode;
62442441Smckusick 	openuap.mode = O_WRONLY | O_CREAT | O_TRUNC;
62547540Skarels 	return (open(p, &openuap, retval));
62642441Smckusick }
62742955Smckusick #endif /* COMPAT_43 */
62842441Smckusick 
62942441Smckusick /*
63049365Smckusick  * Mknod system call.
63142441Smckusick  */
63242441Smckusick /* ARGSUSED */
63342441Smckusick mknod(p, uap, retval)
63445914Smckusick 	struct proc *p;
63542441Smckusick 	register struct args {
63642441Smckusick 		char	*fname;
6376254Sroot 		int	fmode;
6386254Sroot 		int	dev;
63942441Smckusick 	} *uap;
64042441Smckusick 	int *retval;
64142441Smckusick {
64253548Sheideman 	USES_VOP_ABORTOP;
64353548Sheideman 	USES_VOP_MKNOD;
64437741Smckusick 	register struct vnode *vp;
64537741Smckusick 	struct vattr vattr;
64637741Smckusick 	int error;
64747540Skarels 	struct nameidata nd;
6486254Sroot 
64947540Skarels 	if (error = suser(p->p_ucred, &p->p_acflag))
65047540Skarels 		return (error);
65152322Smckusick 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->fname, p);
65252322Smckusick 	if (error = namei(&nd))
65347540Skarels 		return (error);
65452322Smckusick 	vp = nd.ni_vp;
65537741Smckusick 	if (vp != NULL) {
65637741Smckusick 		error = EEXIST;
65712756Ssam 		goto out;
6586254Sroot 	}
65941362Smckusick 	VATTR_NULL(&vattr);
66040635Smckusick 	switch (uap->fmode & S_IFMT) {
66112756Ssam 
66240635Smckusick 	case S_IFMT:	/* used by badsect to flag bad sectors */
66337741Smckusick 		vattr.va_type = VBAD;
66437741Smckusick 		break;
66540635Smckusick 	case S_IFCHR:
66637741Smckusick 		vattr.va_type = VCHR;
66737741Smckusick 		break;
66840635Smckusick 	case S_IFBLK:
66937741Smckusick 		vattr.va_type = VBLK;
67037741Smckusick 		break;
67137741Smckusick 	default:
67237741Smckusick 		error = EINVAL;
67337741Smckusick 		goto out;
6746254Sroot 	}
67545914Smckusick 	vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask;
67637741Smckusick 	vattr.va_rdev = uap->dev;
6776254Sroot out:
67842465Smckusick 	if (!error) {
67952322Smckusick 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
68052322Smckusick 		error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
68142465Smckusick 	} else {
68252322Smckusick 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
68352322Smckusick 		if (nd.ni_dvp == vp)
68452322Smckusick 			vrele(nd.ni_dvp);
68543344Smckusick 		else
68652322Smckusick 			vput(nd.ni_dvp);
68742465Smckusick 		if (vp)
68842465Smckusick 			vrele(vp);
68942465Smckusick 	}
69047540Skarels 	return (error);
6916254Sroot }
6926254Sroot 
6936254Sroot /*
69449365Smckusick  * Mkfifo system call.
69540285Smckusick  */
69642441Smckusick /* ARGSUSED */
69742441Smckusick mkfifo(p, uap, retval)
69845914Smckusick 	struct proc *p;
69942441Smckusick 	register struct args {
70040285Smckusick 		char	*fname;
70140285Smckusick 		int	fmode;
70242441Smckusick 	} *uap;
70342441Smckusick 	int *retval;
70442441Smckusick {
70553548Sheideman 	USES_VOP_ABORTOP;
70653548Sheideman 	USES_VOP_MKNOD;
70740285Smckusick 	struct vattr vattr;
70840285Smckusick 	int error;
70947540Skarels 	struct nameidata nd;
71040285Smckusick 
71140285Smckusick #ifndef FIFO
71247540Skarels 	return (EOPNOTSUPP);
71340285Smckusick #else
71452322Smckusick 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->fname, p);
71552322Smckusick 	if (error = namei(&nd))
71647540Skarels 		return (error);
71752322Smckusick 	if (nd.ni_vp != NULL) {
71852322Smckusick 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
71952322Smckusick 		if (nd.ni_dvp == nd.ni_vp)
72052322Smckusick 			vrele(nd.ni_dvp);
72143344Smckusick 		else
72252322Smckusick 			vput(nd.ni_dvp);
72352322Smckusick 		vrele(nd.ni_vp);
72447540Skarels 		return (EEXIST);
72540285Smckusick 	}
72645785Sbostic 	VATTR_NULL(&vattr);
72745785Sbostic 	vattr.va_type = VFIFO;
72845914Smckusick 	vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask;
72952322Smckusick 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
73052322Smckusick 	return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
73140285Smckusick #endif /* FIFO */
73240285Smckusick }
73340285Smckusick 
73440285Smckusick /*
73549365Smckusick  * Link system call.
7366254Sroot  */
73742441Smckusick /* ARGSUSED */
73842441Smckusick link(p, uap, retval)
73945914Smckusick 	struct proc *p;
74042441Smckusick 	register struct args {
7416254Sroot 		char	*target;
7426254Sroot 		char	*linkname;
74342441Smckusick 	} *uap;
74442441Smckusick 	int *retval;
74542441Smckusick {
74653548Sheideman 	USES_VOP_ABORTOP;
74753548Sheideman 	USES_VOP_LINK;
74837741Smckusick 	register struct vnode *vp, *xp;
74937741Smckusick 	int error;
75047540Skarels 	struct nameidata nd;
7516254Sroot 
75252322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->target, p);
75352322Smckusick 	if (error = namei(&nd))
75447540Skarels 		return (error);
75552322Smckusick 	vp = nd.ni_vp;
75637741Smckusick 	if (vp->v_type == VDIR &&
75747540Skarels 	    (error = suser(p->p_ucred, &p->p_acflag)))
75837741Smckusick 		goto out1;
75952322Smckusick 	nd.ni_cnd.cn_nameiop = CREATE;
76052322Smckusick 	nd.ni_cnd.cn_flags = LOCKPARENT;
76152322Smckusick 	nd.ni_dirp = (caddr_t)uap->linkname;
76252322Smckusick 	if (error = namei(&nd))
76337741Smckusick 		goto out1;
76452322Smckusick 	xp = nd.ni_vp;
7656254Sroot 	if (xp != NULL) {
76637741Smckusick 		error = EEXIST;
7676254Sroot 		goto out;
7686254Sroot 	}
76952322Smckusick 	xp = nd.ni_dvp;
7706254Sroot out:
77142465Smckusick 	if (!error) {
77252192Smckusick 		LEASE_CHECK(xp, p, p->p_ucred, LEASE_WRITE);
77352192Smckusick 		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
77452821Smckusick 		error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
77542465Smckusick 	} else {
77652322Smckusick 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
77752322Smckusick 		if (nd.ni_dvp == nd.ni_vp)
77852322Smckusick 			vrele(nd.ni_dvp);
77943344Smckusick 		else
78052322Smckusick 			vput(nd.ni_dvp);
78152322Smckusick 		if (nd.ni_vp)
78252322Smckusick 			vrele(nd.ni_vp);
78342465Smckusick 	}
78437741Smckusick out1:
78537741Smckusick 	vrele(vp);
78647540Skarels 	return (error);
7876254Sroot }
7886254Sroot 
7896254Sroot /*
79049365Smckusick  * Make a symbolic link.
7916254Sroot  */
79242441Smckusick /* ARGSUSED */
79342441Smckusick symlink(p, uap, retval)
79445914Smckusick 	struct proc *p;
79542441Smckusick 	register struct args {
7966254Sroot 		char	*target;
7976254Sroot 		char	*linkname;
79842441Smckusick 	} *uap;
79942441Smckusick 	int *retval;
80042441Smckusick {
80153548Sheideman 	USES_VOP_ABORTOP;
80253548Sheideman 	USES_VOP_SYMLINK;
80337741Smckusick 	struct vattr vattr;
80437741Smckusick 	char *target;
80537741Smckusick 	int error;
80647540Skarels 	struct nameidata nd;
8076254Sroot 
80837741Smckusick 	MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
80937741Smckusick 	if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
81042465Smckusick 		goto out;
81152322Smckusick 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->linkname, p);
81252322Smckusick 	if (error = namei(&nd))
81342465Smckusick 		goto out;
81452322Smckusick 	if (nd.ni_vp) {
81552322Smckusick 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
81652322Smckusick 		if (nd.ni_dvp == nd.ni_vp)
81752322Smckusick 			vrele(nd.ni_dvp);
81843344Smckusick 		else
81952322Smckusick 			vput(nd.ni_dvp);
82052322Smckusick 		vrele(nd.ni_vp);
82137741Smckusick 		error = EEXIST;
82237741Smckusick 		goto out;
8236254Sroot 	}
82441362Smckusick 	VATTR_NULL(&vattr);
82545914Smckusick 	vattr.va_mode = 0777 &~ p->p_fd->fd_cmask;
82652322Smckusick 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
82752322Smckusick 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, target);
82837741Smckusick out:
82937741Smckusick 	FREE(target, M_NAMEI);
83047540Skarels 	return (error);
8316254Sroot }
8326254Sroot 
8336254Sroot /*
83449365Smckusick  * Delete a name from the filesystem.
8356254Sroot  */
83642441Smckusick /* ARGSUSED */
83742441Smckusick unlink(p, uap, retval)
83845914Smckusick 	struct proc *p;
83942441Smckusick 	struct args {
84052322Smckusick 		char	*name;
84142441Smckusick 	} *uap;
84242441Smckusick 	int *retval;
8436254Sroot {
84453548Sheideman 	USES_VOP_ABORTOP;
84553548Sheideman 	USES_VOP_REMOVE;
84637741Smckusick 	register struct vnode *vp;
84737741Smckusick 	int error;
84847540Skarels 	struct nameidata nd;
8496254Sroot 
85052322Smckusick 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p);
85152322Smckusick 	if (error = namei(&nd))
85247540Skarels 		return (error);
85352322Smckusick 	vp = nd.ni_vp;
85437741Smckusick 	if (vp->v_type == VDIR &&
85547540Skarels 	    (error = suser(p->p_ucred, &p->p_acflag)))
8566254Sroot 		goto out;
8576254Sroot 	/*
85849365Smckusick 	 * The root of a mounted filesystem cannot be deleted.
8596254Sroot 	 */
86037741Smckusick 	if (vp->v_flag & VROOT) {
86137741Smckusick 		error = EBUSY;
8626254Sroot 		goto out;
8636254Sroot 	}
86445738Smckusick 	(void) vnode_pager_uncache(vp);
8656254Sroot out:
86642465Smckusick 	if (!error) {
86752322Smckusick 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
86852192Smckusick 		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
86952322Smckusick 		error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
87042465Smckusick 	} else {
87152322Smckusick 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
87252322Smckusick 		if (nd.ni_dvp == vp)
87352322Smckusick 			vrele(nd.ni_dvp);
87443344Smckusick 		else
87552322Smckusick 			vput(nd.ni_dvp);
87642465Smckusick 		vput(vp);
87742465Smckusick 	}
87847540Skarels 	return (error);
8796254Sroot }
8806254Sroot 
88154348Smckusick #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
8826254Sroot /*
88349365Smckusick  * Seek system call.
8846254Sroot  */
88542441Smckusick lseek(p, uap, retval)
88645914Smckusick 	struct proc *p;
88742441Smckusick 	register struct args {
88837741Smckusick 		int	fdes;
88953468Smckusick 		long	off;
89053468Smckusick 		int	sbase;
89153468Smckusick 	} *uap;
89253468Smckusick 	long *retval;
89353468Smckusick {
89453468Smckusick 	struct nargs {
89553468Smckusick 		int	fdes;
8966254Sroot 		off_t	off;
8976254Sroot 		int	sbase;
89853468Smckusick 	} nuap;
89953468Smckusick 	quad_t qret;
90053468Smckusick 	int error;
90153468Smckusick 
90253468Smckusick 	nuap.fdes = uap->fdes;
90353468Smckusick 	nuap.off = uap->off;
90453468Smckusick 	nuap.sbase = uap->sbase;
90553759Smckusick 	error = __lseek(p, &nuap, &qret);
90653468Smckusick 	*retval = qret;
90753468Smckusick 	return (error);
90853468Smckusick }
90954348Smckusick #endif /* COMPAT_43 || COMPAT_SUNOS */
91053468Smckusick 
91153468Smckusick /*
91253468Smckusick  * Seek system call.
91353468Smckusick  */
91453759Smckusick __lseek(p, uap, retval)
91553468Smckusick 	struct proc *p;
91653468Smckusick 	register struct args {
91753468Smckusick 		int	fdes;
91853468Smckusick 		off_t	off;
91953468Smckusick 		int	sbase;
92042441Smckusick 	} *uap;
92142441Smckusick 	off_t *retval;
92242441Smckusick {
92353548Sheideman 	USES_VOP_GETATTR;
92447540Skarels 	struct ucred *cred = p->p_ucred;
92545914Smckusick 	register struct filedesc *fdp = p->p_fd;
92642441Smckusick 	register struct file *fp;
92737741Smckusick 	struct vattr vattr;
92837741Smckusick 	int error;
9296254Sroot 
93047540Skarels 	if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
93147688Skarels 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
93247540Skarels 		return (EBADF);
93337741Smckusick 	if (fp->f_type != DTYPE_VNODE)
93447540Skarels 		return (ESPIPE);
93513878Ssam 	switch (uap->sbase) {
93613878Ssam 
93713878Ssam 	case L_INCR:
93813878Ssam 		fp->f_offset += uap->off;
93913878Ssam 		break;
94013878Ssam 
94113878Ssam 	case L_XTND:
94237741Smckusick 		if (error = VOP_GETATTR((struct vnode *)fp->f_data,
94348026Smckusick 		    &vattr, cred, p))
94447540Skarels 			return (error);
94537741Smckusick 		fp->f_offset = uap->off + vattr.va_size;
94613878Ssam 		break;
94713878Ssam 
94813878Ssam 	case L_SET:
94913878Ssam 		fp->f_offset = uap->off;
95013878Ssam 		break;
95113878Ssam 
95213878Ssam 	default:
95347540Skarels 		return (EINVAL);
95413878Ssam 	}
95542441Smckusick 	*retval = fp->f_offset;
95647540Skarels 	return (0);
9576254Sroot }
9586254Sroot 
9596254Sroot /*
96049365Smckusick  * Check access permissions.
9616254Sroot  */
96242441Smckusick /* ARGSUSED */
96342441Smckusick saccess(p, uap, retval)
96445914Smckusick 	struct proc *p;
96542441Smckusick 	register struct args {
9666254Sroot 		char	*fname;
9676254Sroot 		int	fmode;
96842441Smckusick 	} *uap;
96942441Smckusick 	int *retval;
97042441Smckusick {
97153548Sheideman 	USES_VOP_ACCESS;
97247540Skarels 	register struct ucred *cred = p->p_ucred;
97337741Smckusick 	register struct vnode *vp;
97437741Smckusick 	int error, mode, svuid, svgid;
97547540Skarels 	struct nameidata nd;
9766254Sroot 
97742441Smckusick 	svuid = cred->cr_uid;
97842441Smckusick 	svgid = cred->cr_groups[0];
97947540Skarels 	cred->cr_uid = p->p_cred->p_ruid;
98047540Skarels 	cred->cr_groups[0] = p->p_cred->p_rgid;
98152322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
98252322Smckusick 	if (error = namei(&nd))
98337741Smckusick 		goto out1;
98452322Smckusick 	vp = nd.ni_vp;
98537741Smckusick 	/*
98637741Smckusick 	 * fmode == 0 means only check for exist
98737741Smckusick 	 */
98837741Smckusick 	if (uap->fmode) {
98937741Smckusick 		mode = 0;
99037741Smckusick 		if (uap->fmode & R_OK)
99137741Smckusick 			mode |= VREAD;
99237741Smckusick 		if (uap->fmode & W_OK)
99337741Smckusick 			mode |= VWRITE;
99437741Smckusick 		if (uap->fmode & X_OK)
99537741Smckusick 			mode |= VEXEC;
99639543Smckusick 		if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
99748026Smckusick 			error = VOP_ACCESS(vp, mode, cred, p);
9986254Sroot 	}
99937741Smckusick 	vput(vp);
100037741Smckusick out1:
100142441Smckusick 	cred->cr_uid = svuid;
100242441Smckusick 	cred->cr_groups[0] = svgid;
100347540Skarels 	return (error);
10046254Sroot }
10056254Sroot 
100654348Smckusick #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
10076254Sroot /*
100849365Smckusick  * Stat system call.
100949365Smckusick  * This version follows links.
101037Sbill  */
101142441Smckusick /* ARGSUSED */
101253759Smckusick ostat(p, uap, retval)
101345914Smckusick 	struct proc *p;
101442441Smckusick 	register struct args {
101542441Smckusick 		char	*fname;
101653468Smckusick 		struct ostat *ub;
101753468Smckusick 	} *uap;
101853468Smckusick 	int *retval;
101953468Smckusick {
102053468Smckusick 	struct stat sb;
102153468Smckusick 	struct ostat osb;
102253468Smckusick 	int error;
102353468Smckusick 	struct nameidata nd;
102453468Smckusick 
102553468Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
102653468Smckusick 	if (error = namei(&nd))
102753468Smckusick 		return (error);
102853468Smckusick 	error = vn_stat(nd.ni_vp, &sb, p);
102953468Smckusick 	vput(nd.ni_vp);
103053468Smckusick 	if (error)
103153468Smckusick 		return (error);
103253468Smckusick 	cvtstat(&sb, &osb);
103353468Smckusick 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
103453468Smckusick 	return (error);
103553468Smckusick }
103653468Smckusick 
103753468Smckusick /*
103853468Smckusick  * Lstat system call.
103953468Smckusick  * This version does not follow links.
104053468Smckusick  */
104153468Smckusick /* ARGSUSED */
104253759Smckusick olstat(p, uap, retval)
104353468Smckusick 	struct proc *p;
104453468Smckusick 	register struct args {
104553468Smckusick 		char	*fname;
104653468Smckusick 		struct ostat *ub;
104753468Smckusick 	} *uap;
104853468Smckusick 	int *retval;
104953468Smckusick {
105053468Smckusick 	struct stat sb;
105153468Smckusick 	struct ostat osb;
105253468Smckusick 	int error;
105353468Smckusick 	struct nameidata nd;
105453468Smckusick 
105553468Smckusick 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
105653468Smckusick 	if (error = namei(&nd))
105753468Smckusick 		return (error);
105853468Smckusick 	error = vn_stat(nd.ni_vp, &sb, p);
105953468Smckusick 	vput(nd.ni_vp);
106053468Smckusick 	if (error)
106153468Smckusick 		return (error);
106253468Smckusick 	cvtstat(&sb, &osb);
106353468Smckusick 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
106453468Smckusick 	return (error);
106553468Smckusick }
106653468Smckusick 
106753468Smckusick /*
106853468Smckusick  * convert from an old to a new stat structure.
106953468Smckusick  */
107053468Smckusick cvtstat(st, ost)
107153468Smckusick 	struct stat *st;
107253468Smckusick 	struct ostat *ost;
107353468Smckusick {
107453468Smckusick 
107553468Smckusick 	ost->st_dev = st->st_dev;
107653468Smckusick 	ost->st_ino = st->st_ino;
107753468Smckusick 	ost->st_mode = st->st_mode;
107853468Smckusick 	ost->st_nlink = st->st_nlink;
107953468Smckusick 	ost->st_uid = st->st_uid;
108053468Smckusick 	ost->st_gid = st->st_gid;
108153468Smckusick 	ost->st_rdev = st->st_rdev;
108253468Smckusick 	if (st->st_size < (quad_t)1 << 32)
108353468Smckusick 		ost->st_size = st->st_size;
108453468Smckusick 	else
108553468Smckusick 		ost->st_size = -2;
108653468Smckusick 	ost->st_atime = st->st_atime;
108753468Smckusick 	ost->st_mtime = st->st_mtime;
108853468Smckusick 	ost->st_ctime = st->st_ctime;
108953468Smckusick 	ost->st_blksize = st->st_blksize;
109053468Smckusick 	ost->st_blocks = st->st_blocks;
109153468Smckusick 	ost->st_flags = st->st_flags;
109253468Smckusick 	ost->st_gen = st->st_gen;
109353468Smckusick }
109454348Smckusick #endif /* COMPAT_43 || COMPAT_SUNOS */
109553468Smckusick 
109653468Smckusick /*
109753468Smckusick  * Stat system call.
109853468Smckusick  * This version follows links.
109953468Smckusick  */
110053468Smckusick /* ARGSUSED */
110153759Smckusick stat(p, uap, retval)
110253468Smckusick 	struct proc *p;
110353468Smckusick 	register struct args {
110453468Smckusick 		char	*fname;
110542441Smckusick 		struct stat *ub;
110642441Smckusick 	} *uap;
110742441Smckusick 	int *retval;
110837Sbill {
110942441Smckusick 	struct stat sb;
111042441Smckusick 	int error;
111147540Skarels 	struct nameidata nd;
111237Sbill 
111352322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
111452322Smckusick 	if (error = namei(&nd))
111547540Skarels 		return (error);
111652322Smckusick 	error = vn_stat(nd.ni_vp, &sb, p);
111752322Smckusick 	vput(nd.ni_vp);
111842441Smckusick 	if (error)
111947540Skarels 		return (error);
112042441Smckusick 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
112147540Skarels 	return (error);
112237Sbill }
112337Sbill 
112437Sbill /*
112549365Smckusick  * Lstat system call.
112649365Smckusick  * This version does not follow links.
11275992Swnj  */
112842441Smckusick /* ARGSUSED */
112953759Smckusick lstat(p, uap, retval)
113045914Smckusick 	struct proc *p;
113142441Smckusick 	register struct args {
11325992Swnj 		char	*fname;
113312756Ssam 		struct stat *ub;
113442441Smckusick 	} *uap;
113542441Smckusick 	int *retval;
113642441Smckusick {
113712756Ssam 	struct stat sb;
113837741Smckusick 	int error;
113947540Skarels 	struct nameidata nd;
11405992Swnj 
114152322Smckusick 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
114252322Smckusick 	if (error = namei(&nd))
114347540Skarels 		return (error);
114452322Smckusick 	error = vn_stat(nd.ni_vp, &sb, p);
114552322Smckusick 	vput(nd.ni_vp);
114637741Smckusick 	if (error)
114747540Skarels 		return (error);
114837741Smckusick 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
114947540Skarels 	return (error);
11505992Swnj }
11515992Swnj 
11525992Swnj /*
115349365Smckusick  * Return target name of a symbolic link.
115437Sbill  */
115542441Smckusick /* ARGSUSED */
115642441Smckusick readlink(p, uap, retval)
115745914Smckusick 	struct proc *p;
115842441Smckusick 	register struct args {
11595992Swnj 		char	*name;
11605992Swnj 		char	*buf;
11615992Swnj 		int	count;
116242441Smckusick 	} *uap;
116342441Smckusick 	int *retval;
116442441Smckusick {
116553548Sheideman 	USES_VOP_READLINK;
116637741Smckusick 	register struct vnode *vp;
116737741Smckusick 	struct iovec aiov;
116837741Smckusick 	struct uio auio;
116937741Smckusick 	int error;
117047540Skarels 	struct nameidata nd;
11715992Swnj 
117252322Smckusick 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->name, p);
117352322Smckusick 	if (error = namei(&nd))
117447540Skarels 		return (error);
117552322Smckusick 	vp = nd.ni_vp;
117637741Smckusick 	if (vp->v_type != VLNK) {
117737741Smckusick 		error = EINVAL;
11785992Swnj 		goto out;
11795992Swnj 	}
118037741Smckusick 	aiov.iov_base = uap->buf;
118137741Smckusick 	aiov.iov_len = uap->count;
118237741Smckusick 	auio.uio_iov = &aiov;
118337741Smckusick 	auio.uio_iovcnt = 1;
118437741Smckusick 	auio.uio_offset = 0;
118537741Smckusick 	auio.uio_rw = UIO_READ;
118637741Smckusick 	auio.uio_segflg = UIO_USERSPACE;
118748026Smckusick 	auio.uio_procp = p;
118837741Smckusick 	auio.uio_resid = uap->count;
118947540Skarels 	error = VOP_READLINK(vp, &auio, p->p_ucred);
11905992Swnj out:
119137741Smckusick 	vput(vp);
119242441Smckusick 	*retval = uap->count - auio.uio_resid;
119347540Skarels 	return (error);
11945992Swnj }
11955992Swnj 
11969167Ssam /*
119738259Smckusick  * Change flags of a file given path name.
119838259Smckusick  */
119942441Smckusick /* ARGSUSED */
120042441Smckusick chflags(p, uap, retval)
120145914Smckusick 	struct proc *p;
120242441Smckusick 	register struct args {
120338259Smckusick 		char	*fname;
120438259Smckusick 		int	flags;
120542441Smckusick 	} *uap;
120642441Smckusick 	int *retval;
120742441Smckusick {
120853548Sheideman 	USES_VOP_SETATTR;
120938259Smckusick 	register struct vnode *vp;
121038259Smckusick 	struct vattr vattr;
121138259Smckusick 	int error;
121247540Skarels 	struct nameidata nd;
121338259Smckusick 
121452322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
121552322Smckusick 	if (error = namei(&nd))
121647540Skarels 		return (error);
121752322Smckusick 	vp = nd.ni_vp;
121841400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
121938259Smckusick 		error = EROFS;
122038259Smckusick 		goto out;
122138259Smckusick 	}
122245785Sbostic 	VATTR_NULL(&vattr);
122345785Sbostic 	vattr.va_flags = uap->flags;
122452192Smckusick 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
122548026Smckusick 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
122638259Smckusick out:
122738259Smckusick 	vput(vp);
122847540Skarels 	return (error);
122938259Smckusick }
123038259Smckusick 
123138259Smckusick /*
123238259Smckusick  * Change flags of a file given a file descriptor.
123338259Smckusick  */
123442441Smckusick /* ARGSUSED */
123542441Smckusick fchflags(p, uap, retval)
123645914Smckusick 	struct proc *p;
123742441Smckusick 	register struct args {
123838259Smckusick 		int	fd;
123938259Smckusick 		int	flags;
124042441Smckusick 	} *uap;
124142441Smckusick 	int *retval;
124242441Smckusick {
124353548Sheideman 	USES_VOP_LOCK;
124453548Sheideman 	USES_VOP_SETATTR;
124553548Sheideman 	USES_VOP_UNLOCK;
124638259Smckusick 	struct vattr vattr;
124738259Smckusick 	struct vnode *vp;
124838259Smckusick 	struct file *fp;
124938259Smckusick 	int error;
125038259Smckusick 
125145914Smckusick 	if (error = getvnode(p->p_fd, uap->fd, &fp))
125247540Skarels 		return (error);
125338259Smckusick 	vp = (struct vnode *)fp->f_data;
125438259Smckusick 	VOP_LOCK(vp);
125541400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
125638259Smckusick 		error = EROFS;
125738259Smckusick 		goto out;
125838259Smckusick 	}
125945785Sbostic 	VATTR_NULL(&vattr);
126045785Sbostic 	vattr.va_flags = uap->flags;
126152192Smckusick 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
126248026Smckusick 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
126338259Smckusick out:
126438259Smckusick 	VOP_UNLOCK(vp);
126547540Skarels 	return (error);
126638259Smckusick }
126738259Smckusick 
126838259Smckusick /*
12699167Ssam  * Change mode of a file given path name.
12709167Ssam  */
127142441Smckusick /* ARGSUSED */
127242441Smckusick chmod(p, uap, retval)
127345914Smckusick 	struct proc *p;
127442441Smckusick 	register struct args {
12756254Sroot 		char	*fname;
12766254Sroot 		int	fmode;
127742441Smckusick 	} *uap;
127842441Smckusick 	int *retval;
127942441Smckusick {
128053548Sheideman 	USES_VOP_SETATTR;
128137741Smckusick 	register struct vnode *vp;
128237741Smckusick 	struct vattr vattr;
128337741Smckusick 	int error;
128447540Skarels 	struct nameidata nd;
12855992Swnj 
128652322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
128752322Smckusick 	if (error = namei(&nd))
128847540Skarels 		return (error);
128952322Smckusick 	vp = nd.ni_vp;
129041400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
129137741Smckusick 		error = EROFS;
129237741Smckusick 		goto out;
129337741Smckusick 	}
129445785Sbostic 	VATTR_NULL(&vattr);
129545785Sbostic 	vattr.va_mode = uap->fmode & 07777;
129652192Smckusick 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
129748026Smckusick 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
129837741Smckusick out:
129937741Smckusick 	vput(vp);
130047540Skarels 	return (error);
13017701Ssam }
13027439Sroot 
13039167Ssam /*
13049167Ssam  * Change mode of a file given a file descriptor.
13059167Ssam  */
130642441Smckusick /* ARGSUSED */
130742441Smckusick fchmod(p, uap, retval)
130845914Smckusick 	struct proc *p;
130942441Smckusick 	register struct args {
13107701Ssam 		int	fd;
13117701Ssam 		int	fmode;
131242441Smckusick 	} *uap;
131342441Smckusick 	int *retval;
131442441Smckusick {
131553548Sheideman 	USES_VOP_LOCK;
131653548Sheideman 	USES_VOP_SETATTR;
131753548Sheideman 	USES_VOP_UNLOCK;
131837741Smckusick 	struct vattr vattr;
131937741Smckusick 	struct vnode *vp;
132037741Smckusick 	struct file *fp;
132137741Smckusick 	int error;
13227701Ssam 
132345914Smckusick 	if (error = getvnode(p->p_fd, uap->fd, &fp))
132447540Skarels 		return (error);
132537741Smckusick 	vp = (struct vnode *)fp->f_data;
132637741Smckusick 	VOP_LOCK(vp);
132741400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
132837741Smckusick 		error = EROFS;
132937741Smckusick 		goto out;
13307439Sroot 	}
133145785Sbostic 	VATTR_NULL(&vattr);
133245785Sbostic 	vattr.va_mode = uap->fmode & 07777;
133352192Smckusick 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
133448026Smckusick 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
133537741Smckusick out:
133637741Smckusick 	VOP_UNLOCK(vp);
133747540Skarels 	return (error);
13385992Swnj }
13395992Swnj 
13409167Ssam /*
13419167Ssam  * Set ownership given a path name.
13429167Ssam  */
134342441Smckusick /* ARGSUSED */
134442441Smckusick chown(p, uap, retval)
134545914Smckusick 	struct proc *p;
134642441Smckusick 	register struct args {
13476254Sroot 		char	*fname;
13486254Sroot 		int	uid;
13496254Sroot 		int	gid;
135042441Smckusick 	} *uap;
135142441Smckusick 	int *retval;
135242441Smckusick {
135353548Sheideman 	USES_VOP_SETATTR;
135437741Smckusick 	register struct vnode *vp;
135537741Smckusick 	struct vattr vattr;
135637741Smckusick 	int error;
135747540Skarels 	struct nameidata nd;
135837Sbill 
135952322Smckusick 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
136052322Smckusick 	if (error = namei(&nd))
136147540Skarels 		return (error);
136252322Smckusick 	vp = nd.ni_vp;
136341400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
136437741Smckusick 		error = EROFS;
136537741Smckusick 		goto out;
136637741Smckusick 	}
136745785Sbostic 	VATTR_NULL(&vattr);
136845785Sbostic 	vattr.va_uid = uap->uid;
136945785Sbostic 	vattr.va_gid = uap->gid;
137052192Smckusick 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
137148026Smckusick 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
137237741Smckusick out:
137337741Smckusick 	vput(vp);
137447540Skarels 	return (error);
13757701Ssam }
13767439Sroot 
13779167Ssam /*
13789167Ssam  * Set ownership given a file descriptor.
13799167Ssam  */
138042441Smckusick /* ARGSUSED */
138142441Smckusick fchown(p, uap, retval)
138245914Smckusick 	struct proc *p;
138342441Smckusick 	register struct args {
13847701Ssam 		int	fd;
13857701Ssam 		int	uid;
13867701Ssam 		int	gid;
138742441Smckusick 	} *uap;
138842441Smckusick 	int *retval;
138942441Smckusick {
139053548Sheideman 	USES_VOP_LOCK;
139153548Sheideman 	USES_VOP_SETATTR;
139253548Sheideman 	USES_VOP_UNLOCK;
139337741Smckusick 	struct vattr vattr;
139437741Smckusick 	struct vnode *vp;
139537741Smckusick 	struct file *fp;
139637741Smckusick 	int error;
13977701Ssam 
139845914Smckusick 	if (error = getvnode(p->p_fd, uap->fd, &fp))
139947540Skarels 		return (error);
140037741Smckusick 	vp = (struct vnode *)fp->f_data;
140137741Smckusick 	VOP_LOCK(vp);
140241400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
140337741Smckusick 		error = EROFS;
140437741Smckusick 		goto out;
140537741Smckusick 	}
140645785Sbostic 	VATTR_NULL(&vattr);
140745785Sbostic 	vattr.va_uid = uap->uid;
140845785Sbostic 	vattr.va_gid = uap->gid;
140952192Smckusick 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
141048026Smckusick 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
141137741Smckusick out:
141237741Smckusick 	VOP_UNLOCK(vp);
141347540Skarels 	return (error);
14147701Ssam }
14157701Ssam 
141642441Smckusick /*
141742441Smckusick  * Set the access and modification times of a file.
141842441Smckusick  */
141942441Smckusick /* ARGSUSED */
142042441Smckusick utimes(p, uap, retval)
142145914Smckusick 	struct proc *p;
142242441Smckusick 	register struct args {
142311811Ssam 		char	*fname;
142411811Ssam 		struct	timeval *tptr;
142542441Smckusick 	} *uap;
142642441Smckusick 	int *retval;
142742441Smckusick {
142853548Sheideman 	USES_VOP_SETATTR;
142937741Smckusick 	register struct vnode *vp;
143011811Ssam 	struct timeval tv[2];
143137741Smckusick 	struct vattr vattr;
143237741Smckusick 	int error;
143347540Skarels 	struct nameidata nd;
143411811Ssam 
143537741Smckusick 	if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
143647540Skarels 		return (error);
143752322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
143852322Smckusick 	if (error = namei(&nd))
143947540Skarels 		return (error);
144052322Smckusick 	vp = nd.ni_vp;
144141400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
144237741Smckusick 		error = EROFS;
144337741Smckusick 		goto out;
144421015Smckusick 	}
144545785Sbostic 	VATTR_NULL(&vattr);
144654100Smckusick 	vattr.va_atime.ts_sec = tv[0].tv_sec;
144754100Smckusick 	vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
144854100Smckusick 	vattr.va_mtime.ts_sec = tv[1].tv_sec;
144954100Smckusick 	vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
145052192Smckusick 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
145148026Smckusick 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
145237741Smckusick out:
145337741Smckusick 	vput(vp);
145447540Skarels 	return (error);
145511811Ssam }
145611811Ssam 
145754348Smckusick #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
14589167Ssam /*
14599167Ssam  * Truncate a file given its path name.
14609167Ssam  */
146142441Smckusick /* ARGSUSED */
146242441Smckusick truncate(p, uap, retval)
146345914Smckusick 	struct proc *p;
146442441Smckusick 	register struct args {
14657701Ssam 		char	*fname;
146653468Smckusick 		long	length;
146753468Smckusick 	} *uap;
146853468Smckusick 	int *retval;
146953468Smckusick {
147053468Smckusick 	struct nargs {
147153468Smckusick 		char	*fname;
147226473Skarels 		off_t	length;
147353468Smckusick 	} nuap;
147453468Smckusick 
147553468Smckusick 	nuap.fname = uap->fname;
147653468Smckusick 	nuap.length = uap->length;
147753759Smckusick 	return (__truncate(p, &nuap, retval));
147853468Smckusick }
147953468Smckusick 
148053468Smckusick /*
148153468Smckusick  * Truncate a file given a file descriptor.
148253468Smckusick  */
148353468Smckusick /* ARGSUSED */
148453468Smckusick ftruncate(p, uap, retval)
148553468Smckusick 	struct proc *p;
148653468Smckusick 	register struct args {
148753468Smckusick 		int	fd;
148853468Smckusick 		long	length;
148942441Smckusick 	} *uap;
149042441Smckusick 	int *retval;
149142441Smckusick {
149253468Smckusick 	struct nargs {
149353468Smckusick 		int	fd;
149453468Smckusick 		off_t	length;
149553468Smckusick 	} nuap;
149653468Smckusick 
149753468Smckusick 	nuap.fd = uap->fd;
149853468Smckusick 	nuap.length = uap->length;
149953759Smckusick 	return (__ftruncate(p, &nuap, retval));
150053468Smckusick }
150154348Smckusick #endif /* COMPAT_43 || COMPAT_SUNOS */
150253468Smckusick 
150353468Smckusick /*
150453468Smckusick  * Truncate a file given its path name.
150553468Smckusick  */
150653468Smckusick /* ARGSUSED */
150753759Smckusick __truncate(p, uap, retval)
150853468Smckusick 	struct proc *p;
150953468Smckusick 	register struct args {
151053468Smckusick 		char	*fname;
151153468Smckusick 		off_t	length;
151253468Smckusick 	} *uap;
151353468Smckusick 	int *retval;
151453468Smckusick {
151553548Sheideman 	USES_VOP_ACCESS;
151653548Sheideman 	USES_VOP_SETATTR;
151737741Smckusick 	register struct vnode *vp;
151837741Smckusick 	struct vattr vattr;
151937741Smckusick 	int error;
152047540Skarels 	struct nameidata nd;
15217701Ssam 
152252322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
152352322Smckusick 	if (error = namei(&nd))
152447540Skarels 		return (error);
152552322Smckusick 	vp = nd.ni_vp;
152637741Smckusick 	if (vp->v_type == VDIR) {
152737741Smckusick 		error = EISDIR;
152837741Smckusick 		goto out;
15297701Ssam 	}
153038399Smckusick 	if ((error = vn_writechk(vp)) ||
153148026Smckusick 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)))
153237741Smckusick 		goto out;
153345785Sbostic 	VATTR_NULL(&vattr);
153445785Sbostic 	vattr.va_size = uap->length;
153552192Smckusick 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
153648026Smckusick 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
153737741Smckusick out:
153837741Smckusick 	vput(vp);
153947540Skarels 	return (error);
15407701Ssam }
15417701Ssam 
15429167Ssam /*
15439167Ssam  * Truncate a file given a file descriptor.
15449167Ssam  */
154542441Smckusick /* ARGSUSED */
154653759Smckusick __ftruncate(p, uap, retval)
154745914Smckusick 	struct proc *p;
154842441Smckusick 	register struct args {
15497701Ssam 		int	fd;
155026473Skarels 		off_t	length;
155142441Smckusick 	} *uap;
155242441Smckusick 	int *retval;
155342441Smckusick {
155453548Sheideman 	USES_VOP_LOCK;
155553548Sheideman 	USES_VOP_SETATTR;
155653548Sheideman 	USES_VOP_UNLOCK;
155737741Smckusick 	struct vattr vattr;
155837741Smckusick 	struct vnode *vp;
15597701Ssam 	struct file *fp;
156037741Smckusick 	int error;
15617701Ssam 
156245914Smckusick 	if (error = getvnode(p->p_fd, uap->fd, &fp))
156347540Skarels 		return (error);
156437741Smckusick 	if ((fp->f_flag & FWRITE) == 0)
156547540Skarels 		return (EINVAL);
156637741Smckusick 	vp = (struct vnode *)fp->f_data;
156737741Smckusick 	VOP_LOCK(vp);
156837741Smckusick 	if (vp->v_type == VDIR) {
156937741Smckusick 		error = EISDIR;
157037741Smckusick 		goto out;
15717701Ssam 	}
157238399Smckusick 	if (error = vn_writechk(vp))
157337741Smckusick 		goto out;
157445785Sbostic 	VATTR_NULL(&vattr);
157545785Sbostic 	vattr.va_size = uap->length;
157652192Smckusick 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
157748026Smckusick 	error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
157837741Smckusick out:
157937741Smckusick 	VOP_UNLOCK(vp);
158047540Skarels 	return (error);
15817701Ssam }
15827701Ssam 
15839167Ssam /*
15849167Ssam  * Synch an open file.
15859167Ssam  */
158642441Smckusick /* ARGSUSED */
158742441Smckusick fsync(p, uap, retval)
158845914Smckusick 	struct proc *p;
158942441Smckusick 	struct args {
159042441Smckusick 		int	fd;
159142441Smckusick 	} *uap;
159242441Smckusick 	int *retval;
15939167Ssam {
159453548Sheideman 	USES_VOP_FSYNC;
159553548Sheideman 	USES_VOP_LOCK;
159653548Sheideman 	USES_VOP_UNLOCK;
159739592Smckusick 	register struct vnode *vp;
15989167Ssam 	struct file *fp;
159937741Smckusick 	int error;
16009167Ssam 
160145914Smckusick 	if (error = getvnode(p->p_fd, uap->fd, &fp))
160247540Skarels 		return (error);
160339592Smckusick 	vp = (struct vnode *)fp->f_data;
160439592Smckusick 	VOP_LOCK(vp);
160554441Smckusick 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
160639592Smckusick 	VOP_UNLOCK(vp);
160747540Skarels 	return (error);
16089167Ssam }
16099167Ssam 
16109167Ssam /*
16119167Ssam  * Rename system call.
16129167Ssam  *
16139167Ssam  * Source and destination must either both be directories, or both
16149167Ssam  * not be directories.  If target is a directory, it must be empty.
16159167Ssam  */
161642441Smckusick /* ARGSUSED */
161742441Smckusick rename(p, uap, retval)
161845914Smckusick 	struct proc *p;
161942441Smckusick 	register struct args {
16207701Ssam 		char	*from;
16217701Ssam 		char	*to;
162242441Smckusick 	} *uap;
162342441Smckusick 	int *retval;
162442441Smckusick {
162553548Sheideman 	USES_VOP_ABORTOP;
162653548Sheideman 	USES_VOP_RENAME;
162737741Smckusick 	register struct vnode *tvp, *fvp, *tdvp;
162849735Smckusick 	struct nameidata fromnd, tond;
162937741Smckusick 	int error;
16307701Ssam 
163152322Smckusick 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
163252322Smckusick 		uap->from, p);
163352322Smckusick 	if (error = namei(&fromnd))
163447540Skarels 		return (error);
163549735Smckusick 	fvp = fromnd.ni_vp;
163652322Smckusick 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
163752322Smckusick 		UIO_USERSPACE, uap->to, p);
163852322Smckusick 	if (error = namei(&tond)) {
163952230Sheideman 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
164049735Smckusick 		vrele(fromnd.ni_dvp);
164142465Smckusick 		vrele(fvp);
164242465Smckusick 		goto out1;
164342465Smckusick 	}
164437741Smckusick 	tdvp = tond.ni_dvp;
164537741Smckusick 	tvp = tond.ni_vp;
164637741Smckusick 	if (tvp != NULL) {
164737741Smckusick 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
164839242Sbostic 			error = ENOTDIR;
164937741Smckusick 			goto out;
165037741Smckusick 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
165139242Sbostic 			error = EISDIR;
165237741Smckusick 			goto out;
16539167Ssam 		}
16549167Ssam 	}
165539286Smckusick 	if (fvp == tdvp)
165637741Smckusick 		error = EINVAL;
165739286Smckusick 	/*
165849735Smckusick 	 * If source is the same as the destination (that is the
165949735Smckusick 	 * same inode number with the same name in the same directory),
166039286Smckusick 	 * then there is nothing to do.
166139286Smckusick 	 */
166249735Smckusick 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
166352322Smckusick 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
166452322Smckusick 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
166552322Smckusick 	      fromnd.ni_cnd.cn_namelen))
166639286Smckusick 		error = -1;
166737741Smckusick out:
166842465Smckusick 	if (!error) {
166952192Smckusick 		LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
167052192Smckusick 		if (fromnd.ni_dvp != tdvp)
167152192Smckusick 			LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
167252192Smckusick 		if (tvp)
167352192Smckusick 			LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
167452230Sheideman 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
167552230Sheideman 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
167642465Smckusick 	} else {
167752230Sheideman 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
167843344Smckusick 		if (tdvp == tvp)
167943344Smckusick 			vrele(tdvp);
168043344Smckusick 		else
168143344Smckusick 			vput(tdvp);
168242465Smckusick 		if (tvp)
168342465Smckusick 			vput(tvp);
168452230Sheideman 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
168549735Smckusick 		vrele(fromnd.ni_dvp);
168642465Smckusick 		vrele(fvp);
16879167Ssam 	}
168849735Smckusick 	vrele(tond.ni_startdir);
168952322Smckusick 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
169037741Smckusick out1:
169149735Smckusick 	vrele(fromnd.ni_startdir);
169252322Smckusick 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
169339286Smckusick 	if (error == -1)
169447540Skarels 		return (0);
169547540Skarels 	return (error);
16967701Ssam }
16977701Ssam 
16987535Sroot /*
169949365Smckusick  * Mkdir system call.
170012756Ssam  */
170142441Smckusick /* ARGSUSED */
170242441Smckusick mkdir(p, uap, retval)
170345914Smckusick 	struct proc *p;
170442441Smckusick 	register struct args {
170512756Ssam 		char	*name;
170612756Ssam 		int	dmode;
170742441Smckusick 	} *uap;
170842441Smckusick 	int *retval;
170942441Smckusick {
171053548Sheideman 	USES_VOP_ABORTOP;
171153548Sheideman 	USES_VOP_MKDIR;
171237741Smckusick 	register struct vnode *vp;
171337741Smckusick 	struct vattr vattr;
171437741Smckusick 	int error;
171547540Skarels 	struct nameidata nd;
171612756Ssam 
171752322Smckusick 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->name, p);
171852322Smckusick 	if (error = namei(&nd))
171947540Skarels 		return (error);
172052322Smckusick 	vp = nd.ni_vp;
172137741Smckusick 	if (vp != NULL) {
172252322Smckusick 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
172352322Smckusick 		if (nd.ni_dvp == vp)
172452322Smckusick 			vrele(nd.ni_dvp);
172543344Smckusick 		else
172652322Smckusick 			vput(nd.ni_dvp);
172742465Smckusick 		vrele(vp);
172847540Skarels 		return (EEXIST);
172912756Ssam 	}
173041362Smckusick 	VATTR_NULL(&vattr);
173137741Smckusick 	vattr.va_type = VDIR;
173245914Smckusick 	vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask;
173352322Smckusick 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
173452322Smckusick 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
173538145Smckusick 	if (!error)
173652322Smckusick 		vput(nd.ni_vp);
173747540Skarels 	return (error);
173812756Ssam }
173912756Ssam 
174012756Ssam /*
174112756Ssam  * Rmdir system call.
174212756Ssam  */
174342441Smckusick /* ARGSUSED */
174442441Smckusick rmdir(p, uap, retval)
174545914Smckusick 	struct proc *p;
174642441Smckusick 	struct args {
174742441Smckusick 		char	*name;
174842441Smckusick 	} *uap;
174942441Smckusick 	int *retval;
175012756Ssam {
175153548Sheideman 	USES_VOP_ABORTOP;
175253548Sheideman 	USES_VOP_RMDIR;
175337741Smckusick 	register struct vnode *vp;
175437741Smckusick 	int error;
175547540Skarels 	struct nameidata nd;
175612756Ssam 
175752322Smckusick 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p);
175852322Smckusick 	if (error = namei(&nd))
175947540Skarels 		return (error);
176052322Smckusick 	vp = nd.ni_vp;
176137741Smckusick 	if (vp->v_type != VDIR) {
176237741Smckusick 		error = ENOTDIR;
176312756Ssam 		goto out;
176412756Ssam 	}
176512756Ssam 	/*
176637741Smckusick 	 * No rmdir "." please.
176712756Ssam 	 */
176852322Smckusick 	if (nd.ni_dvp == vp) {
176937741Smckusick 		error = EINVAL;
177012756Ssam 		goto out;
177112756Ssam 	}
177212756Ssam 	/*
177349365Smckusick 	 * The root of a mounted filesystem cannot be deleted.
177412756Ssam 	 */
177537741Smckusick 	if (vp->v_flag & VROOT)
177637741Smckusick 		error = EBUSY;
177712756Ssam out:
177842465Smckusick 	if (!error) {
177952322Smckusick 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
178052192Smckusick 		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
178152322Smckusick 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
178242465Smckusick 	} else {
178352322Smckusick 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
178452322Smckusick 		if (nd.ni_dvp == vp)
178552322Smckusick 			vrele(nd.ni_dvp);
178643344Smckusick 		else
178752322Smckusick 			vput(nd.ni_dvp);
178842465Smckusick 		vput(vp);
178942465Smckusick 	}
179047540Skarels 	return (error);
179112756Ssam }
179212756Ssam 
1793*54620Smckusick #ifdef COMPAT_43
179437741Smckusick /*
179549365Smckusick  * Read a block of directory entries in a file system independent format.
179637741Smckusick  */
1797*54620Smckusick ogetdirentries(p, uap, retval)
1798*54620Smckusick 	struct proc *p;
1799*54620Smckusick 	register struct args {
1800*54620Smckusick 		int	fd;
1801*54620Smckusick 		char	*buf;
1802*54620Smckusick 		unsigned count;
1803*54620Smckusick 		long	*basep;
1804*54620Smckusick 	} *uap;
1805*54620Smckusick 	int *retval;
1806*54620Smckusick {
1807*54620Smckusick 	USES_VOP_LOCK;
1808*54620Smckusick 	USES_VOP_READDIR;
1809*54620Smckusick 	USES_VOP_UNLOCK;
1810*54620Smckusick 	register struct vnode *vp;
1811*54620Smckusick 	struct file *fp;
1812*54620Smckusick 	struct uio auio, kuio;
1813*54620Smckusick 	struct iovec aiov, kiov;
1814*54620Smckusick 	struct dirent *dp, *edp;
1815*54620Smckusick 	caddr_t dirbuf;
1816*54620Smckusick 	int error, readcnt;
1817*54620Smckusick 	off_t off;
1818*54620Smckusick 
1819*54620Smckusick 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1820*54620Smckusick 		return (error);
1821*54620Smckusick 	if ((fp->f_flag & FREAD) == 0)
1822*54620Smckusick 		return (EBADF);
1823*54620Smckusick 	vp = (struct vnode *)fp->f_data;
1824*54620Smckusick 	if (vp->v_type != VDIR)
1825*54620Smckusick 		return (EINVAL);
1826*54620Smckusick 	aiov.iov_base = uap->buf;
1827*54620Smckusick 	aiov.iov_len = uap->count;
1828*54620Smckusick 	auio.uio_iov = &aiov;
1829*54620Smckusick 	auio.uio_iovcnt = 1;
1830*54620Smckusick 	auio.uio_rw = UIO_READ;
1831*54620Smckusick 	auio.uio_segflg = UIO_USERSPACE;
1832*54620Smckusick 	auio.uio_procp = p;
1833*54620Smckusick 	auio.uio_resid = uap->count;
1834*54620Smckusick 	VOP_LOCK(vp);
1835*54620Smckusick 	auio.uio_offset = off = fp->f_offset;
1836*54620Smckusick #	if (BYTE_ORDER != LITTLE_ENDIAN)
1837*54620Smckusick 		if (vp->v_mount->mnt_maxsymlinklen <= 0)
1838*54620Smckusick 			error = VOP_READDIR(vp, &auio, fp->f_cred);
1839*54620Smckusick 		else
1840*54620Smckusick #	endif
1841*54620Smckusick 	{
1842*54620Smckusick 		kuio = auio;
1843*54620Smckusick 		kuio.uio_iov = &kiov;
1844*54620Smckusick 		kuio.uio_segflg = UIO_SYSSPACE;
1845*54620Smckusick 		kiov.iov_len = uap->count;
1846*54620Smckusick 		MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
1847*54620Smckusick 		kiov.iov_base = dirbuf;
1848*54620Smckusick 		error = VOP_READDIR(vp, &kuio, fp->f_cred);
1849*54620Smckusick 		if (error == 0) {
1850*54620Smckusick 			readcnt = uap->count - kuio.uio_resid;
1851*54620Smckusick 			edp = (struct dirent *)&dirbuf[readcnt];
1852*54620Smckusick 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1853*54620Smckusick 				dp->d_type = 0;
1854*54620Smckusick #				if (BYTE_ORDER == LITTLE_ENDIAN)
1855*54620Smckusick 					{ u_char tmp = dp->d_namlen;
1856*54620Smckusick 					dp->d_namlen = dp->d_type;
1857*54620Smckusick 					dp->d_type = tmp; }
1858*54620Smckusick #				endif
1859*54620Smckusick 				if (dp->d_reclen > 0) {
1860*54620Smckusick 					dp = (struct dirent *)
1861*54620Smckusick 					    ((char *)dp + dp->d_reclen);
1862*54620Smckusick 				} else {
1863*54620Smckusick 					error = EIO;
1864*54620Smckusick 					break;
1865*54620Smckusick 				}
1866*54620Smckusick 			}
1867*54620Smckusick 			if (dp >= edp)
1868*54620Smckusick 				error = uiomove(dirbuf, readcnt, &auio);
1869*54620Smckusick 		}
1870*54620Smckusick 		FREE(dirbuf, M_TEMP);
1871*54620Smckusick 	}
1872*54620Smckusick 	fp->f_offset = auio.uio_offset;
1873*54620Smckusick 	VOP_UNLOCK(vp);
1874*54620Smckusick 	if (error)
1875*54620Smckusick 		return (error);
1876*54620Smckusick 	error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
1877*54620Smckusick 	*retval = uap->count - auio.uio_resid;
1878*54620Smckusick 	return (error);
1879*54620Smckusick }
1880*54620Smckusick #endif
1881*54620Smckusick 
1882*54620Smckusick /*
1883*54620Smckusick  * Read a block of directory entries in a file system independent format.
1884*54620Smckusick  */
188542441Smckusick getdirentries(p, uap, retval)
188645914Smckusick 	struct proc *p;
188742441Smckusick 	register struct args {
188837741Smckusick 		int	fd;
188937741Smckusick 		char	*buf;
189037741Smckusick 		unsigned count;
189137741Smckusick 		long	*basep;
189242441Smckusick 	} *uap;
189342441Smckusick 	int *retval;
189442441Smckusick {
189553548Sheideman 	USES_VOP_LOCK;
189653548Sheideman 	USES_VOP_READDIR;
189753548Sheideman 	USES_VOP_UNLOCK;
189839592Smckusick 	register struct vnode *vp;
189916540Ssam 	struct file *fp;
190037741Smckusick 	struct uio auio;
190137741Smckusick 	struct iovec aiov;
190238129Smckusick 	off_t off;
190354441Smckusick 	int error;
190412756Ssam 
190545914Smckusick 	if (error = getvnode(p->p_fd, uap->fd, &fp))
190647540Skarels 		return (error);
190737741Smckusick 	if ((fp->f_flag & FREAD) == 0)
190847540Skarels 		return (EBADF);
190939592Smckusick 	vp = (struct vnode *)fp->f_data;
191039592Smckusick 	if (vp->v_type != VDIR)
191147540Skarels 		return (EINVAL);
191237741Smckusick 	aiov.iov_base = uap->buf;
191337741Smckusick 	aiov.iov_len = uap->count;
191437741Smckusick 	auio.uio_iov = &aiov;
191537741Smckusick 	auio.uio_iovcnt = 1;
191637741Smckusick 	auio.uio_rw = UIO_READ;
191737741Smckusick 	auio.uio_segflg = UIO_USERSPACE;
191848026Smckusick 	auio.uio_procp = p;
191937741Smckusick 	auio.uio_resid = uap->count;
192039592Smckusick 	VOP_LOCK(vp);
192139592Smckusick 	auio.uio_offset = off = fp->f_offset;
192254441Smckusick 	error = VOP_READDIR(vp, &auio, fp->f_cred);
192339592Smckusick 	fp->f_offset = auio.uio_offset;
192439592Smckusick 	VOP_UNLOCK(vp);
192539592Smckusick 	if (error)
192647540Skarels 		return (error);
192739592Smckusick 	error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
192842441Smckusick 	*retval = uap->count - auio.uio_resid;
192947540Skarels 	return (error);
193012756Ssam }
193112756Ssam 
193212756Ssam /*
193349365Smckusick  * Set the mode mask for creation of filesystem nodes.
193412756Ssam  */
193542441Smckusick mode_t
193642441Smckusick umask(p, uap, retval)
193745914Smckusick 	struct proc *p;
193842441Smckusick 	struct args {
193942441Smckusick 		int	mask;
194042441Smckusick 	} *uap;
194142441Smckusick 	int *retval;
194212756Ssam {
194345914Smckusick 	register struct filedesc *fdp = p->p_fd;
194412756Ssam 
194545914Smckusick 	*retval = fdp->fd_cmask;
194645914Smckusick 	fdp->fd_cmask = uap->mask & 07777;
194747540Skarels 	return (0);
194812756Ssam }
194937741Smckusick 
195039566Smarc /*
195139566Smarc  * Void all references to file by ripping underlying filesystem
195239566Smarc  * away from vnode.
195339566Smarc  */
195442441Smckusick /* ARGSUSED */
195542441Smckusick revoke(p, uap, retval)
195645914Smckusick 	struct proc *p;
195742441Smckusick 	register struct args {
195839566Smarc 		char	*fname;
195942441Smckusick 	} *uap;
196042441Smckusick 	int *retval;
196142441Smckusick {
196253548Sheideman 	USES_VOP_GETATTR;
196339566Smarc 	register struct vnode *vp;
196439566Smarc 	struct vattr vattr;
196539566Smarc 	int error;
196647540Skarels 	struct nameidata nd;
196739566Smarc 
196852322Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
196952322Smckusick 	if (error = namei(&nd))
197047540Skarels 		return (error);
197152322Smckusick 	vp = nd.ni_vp;
197239566Smarc 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
197339566Smarc 		error = EINVAL;
197439566Smarc 		goto out;
197539566Smarc 	}
197648026Smckusick 	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
197739566Smarc 		goto out;
197847540Skarels 	if (p->p_ucred->cr_uid != vattr.va_uid &&
197947540Skarels 	    (error = suser(p->p_ucred, &p->p_acflag)))
198039566Smarc 		goto out;
198139805Smckusick 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
198239632Smckusick 		vgoneall(vp);
198339566Smarc out:
198439566Smarc 	vrele(vp);
198547540Skarels 	return (error);
198639566Smarc }
198739566Smarc 
198849365Smckusick /*
198949365Smckusick  * Convert a user file descriptor to a kernel file entry.
199049365Smckusick  */
199145914Smckusick getvnode(fdp, fdes, fpp)
199245914Smckusick 	struct filedesc *fdp;
199337741Smckusick 	struct file **fpp;
199437741Smckusick 	int fdes;
199537741Smckusick {
199637741Smckusick 	struct file *fp;
199737741Smckusick 
199847540Skarels 	if ((unsigned)fdes >= fdp->fd_nfiles ||
199947688Skarels 	    (fp = fdp->fd_ofiles[fdes]) == NULL)
200037741Smckusick 		return (EBADF);
200137741Smckusick 	if (fp->f_type != DTYPE_VNODE)
200237741Smckusick 		return (EINVAL);
200337741Smckusick 	*fpp = fp;
200437741Smckusick 	return (0);
200537741Smckusick }
2006