xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 40321)
123405Smckusick /*
237741Smckusick  * Copyright (c) 1989 The Regents of the University of California.
337741Smckusick  * All rights reserved.
423405Smckusick  *
537741Smckusick  * Redistribution and use in source and binary forms are permitted
637741Smckusick  * provided that the above copyright notice and this paragraph are
737741Smckusick  * duplicated in all such forms and that any documentation,
837741Smckusick  * advertising materials, and other materials related to such
937741Smckusick  * distribution and use acknowledge that the software was developed
1037741Smckusick  * by the University of California, Berkeley.  The name of the
1137741Smckusick  * University may not be used to endorse or promote products derived
1237741Smckusick  * from this software without specific prior written permission.
1337741Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1437741Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1537741Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1637741Smckusick  *
17*40321Smckusick  *	@(#)vfs_syscalls.c	7.40 (Berkeley) 03/06/90
1823405Smckusick  */
1937Sbill 
2017101Sbloom #include "param.h"
2117101Sbloom #include "systm.h"
2237741Smckusick #include "syscontext.h"
2317101Sbloom #include "kernel.h"
2417101Sbloom #include "file.h"
2517101Sbloom #include "stat.h"
2637741Smckusick #include "vnode.h"
2737741Smckusick #include "../ufs/inode.h"
2837741Smckusick #include "mount.h"
2917101Sbloom #include "proc.h"
3017101Sbloom #include "uio.h"
3137741Smckusick #include "malloc.h"
3237Sbill 
3339797Smckusick #undef RETURN
3439797Smckusick #define RETURN(val)	{ scp->u_error = (val); if (scp->u_spare[0] != 0) panic("lock count"); return; }
3539797Smckusick 
3637741Smckusick /*
3737741Smckusick  * Virtual File System System Calls
3837741Smckusick  */
3912756Ssam 
409167Ssam /*
4137741Smckusick  * mount system call
429167Ssam  */
4338408Smckusick mount(scp)
4438408Smckusick 	register struct syscontext *scp;
456254Sroot {
4637741Smckusick 	register struct a {
4737741Smckusick 		int	type;
4837741Smckusick 		char	*dir;
4937741Smckusick 		int	flags;
5037741Smckusick 		caddr_t	data;
5138408Smckusick 	} *uap = (struct a *)scp->sc_ap;
5238408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
5339335Smckusick 	register struct vnode *vp;
5439335Smckusick 	register struct mount *mp;
5540111Smckusick 	int error, flag;
566254Sroot 
5737741Smckusick 	/*
5837741Smckusick 	 * Must be super user
5937741Smckusick 	 */
6038408Smckusick 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
6137741Smckusick 		RETURN (error);
6237741Smckusick 	/*
6337741Smckusick 	 * Get vnode to be covered
6437741Smckusick 	 */
6537741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
6637741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
6737741Smckusick 	ndp->ni_dirp = uap->dir;
6837741Smckusick 	if (error = namei(ndp))
6937741Smckusick 		RETURN (error);
7037741Smckusick 	vp = ndp->ni_vp;
7139335Smckusick 	if (uap->flags & M_UPDATE) {
7239335Smckusick 		if ((vp->v_flag & VROOT) == 0) {
7339335Smckusick 			vput(vp);
7439335Smckusick 			RETURN (EINVAL);
7539335Smckusick 		}
7639335Smckusick 		mp = vp->v_mount;
7739335Smckusick 		/*
7839335Smckusick 		 * We allow going from read-only to read-write,
7939335Smckusick 		 * but not from read-write to read-only.
8039335Smckusick 		 */
8139335Smckusick 		if ((mp->m_flag & M_RDONLY) == 0 &&
8239335Smckusick 		    (uap->flags & M_RDONLY) != 0) {
8339335Smckusick 			vput(vp);
8439335Smckusick 			RETURN (EOPNOTSUPP);	/* Needs translation */
8539335Smckusick 		}
8640111Smckusick 		flag = mp->m_flag;
8739335Smckusick 		mp->m_flag |= M_UPDATE;
8839335Smckusick 		VOP_UNLOCK(vp);
8939335Smckusick 		goto update;
9039335Smckusick 	}
9139665Smckusick 	vinvalbuf(vp, 1);
9239805Smckusick 	if (vp->v_usecount != 1) {
9337741Smckusick 		vput(vp);
9437741Smckusick 		RETURN (EBUSY);
9537741Smckusick 	}
9637741Smckusick 	if (vp->v_type != VDIR) {
9737741Smckusick 		vput(vp);
9837741Smckusick 		RETURN (ENOTDIR);
9937741Smckusick 	}
10039741Smckusick 	if ((unsigned long)uap->type > MOUNT_MAXTYPE ||
10137741Smckusick 	    vfssw[uap->type] == (struct vfsops *)0) {
10237741Smckusick 		vput(vp);
10337741Smckusick 		RETURN (ENODEV);
10437741Smckusick 	}
10537741Smckusick 
10637741Smckusick 	/*
10739335Smckusick 	 * Allocate and initialize the file system.
10837741Smckusick 	 */
10937741Smckusick 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
11037741Smckusick 		M_MOUNT, M_WAITOK);
11137741Smckusick 	mp->m_op = vfssw[uap->type];
11237741Smckusick 	mp->m_flag = 0;
11337741Smckusick 	mp->m_exroot = 0;
11439381Smckusick 	mp->m_mounth = (struct vnode *)0;
11539335Smckusick 	if (error = vfs_lock(mp)) {
11639335Smckusick 		free((caddr_t)mp, M_MOUNT);
11739335Smckusick 		vput(vp);
11839335Smckusick 		RETURN (error);
11939335Smckusick 	}
12039335Smckusick 	if (vp->v_mountedhere != (struct mount *)0) {
12139335Smckusick 		vfs_unlock(mp);
12239335Smckusick 		free((caddr_t)mp, M_MOUNT);
12339335Smckusick 		vput(vp);
12439335Smckusick 		RETURN (EBUSY);
12539335Smckusick 	}
12639335Smckusick 	vp->v_mountedhere = mp;
12739335Smckusick 	mp->m_vnodecovered = vp;
12839335Smckusick update:
12939335Smckusick 	/*
13039335Smckusick 	 * Set the mount level flags.
13139335Smckusick 	 */
13239335Smckusick 	if (uap->flags & M_RDONLY)
13339335Smckusick 		mp->m_flag |= M_RDONLY;
13439335Smckusick 	else
13539335Smckusick 		mp->m_flag &= ~M_RDONLY;
13639335Smckusick 	if (uap->flags & M_NOSUID)
13739335Smckusick 		mp->m_flag |= M_NOSUID;
13839335Smckusick 	else
13939335Smckusick 		mp->m_flag &= ~M_NOSUID;
14039335Smckusick 	if (uap->flags & M_NOEXEC)
14139335Smckusick 		mp->m_flag |= M_NOEXEC;
14239335Smckusick 	else
14339335Smckusick 		mp->m_flag &= ~M_NOEXEC;
14439335Smckusick 	if (uap->flags & M_NODEV)
14539335Smckusick 		mp->m_flag |= M_NODEV;
14639335Smckusick 	else
14739335Smckusick 		mp->m_flag &= ~M_NODEV;
14839335Smckusick 	if (uap->flags & M_SYNCHRONOUS)
14939335Smckusick 		mp->m_flag |= M_SYNCHRONOUS;
15039335Smckusick 	else
15139335Smckusick 		mp->m_flag &= ~M_SYNCHRONOUS;
15239335Smckusick 	/*
15339335Smckusick 	 * Mount the filesystem.
15439335Smckusick 	 */
15539335Smckusick 	error = VFS_MOUNT(mp, uap->dir, uap->data, ndp);
15639335Smckusick 	if (mp->m_flag & M_UPDATE) {
15739335Smckusick 		mp->m_flag &= ~M_UPDATE;
15839335Smckusick 		vrele(vp);
15940111Smckusick 		if (error)
16040111Smckusick 			mp->m_flag = flag;
16139335Smckusick 		RETURN (error);
16239335Smckusick 	}
16340110Smckusick 	/*
16440110Smckusick 	 * Put the new filesystem on the mount list after root.
16540110Smckusick 	 */
16640110Smckusick 	mp->m_next = rootfs->m_next;
16740110Smckusick 	mp->m_prev = rootfs;
16840110Smckusick 	rootfs->m_next = mp;
16940110Smckusick 	mp->m_next->m_prev = mp;
17037741Smckusick 	cache_purge(vp);
17137741Smckusick 	if (!error) {
17239335Smckusick 		VOP_UNLOCK(vp);
17337741Smckusick 		vfs_unlock(mp);
17439044Smckusick 		error = VFS_START(mp, 0);
17537741Smckusick 	} else {
17637741Smckusick 		vfs_remove(mp);
17737741Smckusick 		free((caddr_t)mp, M_MOUNT);
17839335Smckusick 		vput(vp);
17937741Smckusick 	}
18037741Smckusick 	RETURN (error);
1816254Sroot }
1826254Sroot 
1839167Ssam /*
18437741Smckusick  * Unmount system call.
18537741Smckusick  *
18637741Smckusick  * Note: unmount takes a path to the vnode mounted on as argument,
18737741Smckusick  * not special file (as before).
1889167Ssam  */
18938408Smckusick unmount(scp)
19038408Smckusick 	register struct syscontext *scp;
1916254Sroot {
19237741Smckusick 	struct a {
19337741Smckusick 		char	*pathp;
19437741Smckusick 		int	flags;
19538408Smckusick 	} *uap = (struct a *)scp->sc_ap;
19637741Smckusick 	register struct vnode *vp;
19738408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
19839356Smckusick 	struct mount *mp;
19937741Smckusick 	int error;
2006254Sroot 
20137741Smckusick 	/*
20237741Smckusick 	 * Must be super user
20337741Smckusick 	 */
20438408Smckusick 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
20537741Smckusick 		RETURN (error);
20637741Smckusick 
20737741Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
20837741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
20937741Smckusick 	ndp->ni_dirp = uap->pathp;
21037741Smckusick 	if (error = namei(ndp))
21137741Smckusick 		RETURN (error);
21237741Smckusick 	vp = ndp->ni_vp;
21337741Smckusick 	/*
21437741Smckusick 	 * Must be the root of the filesystem
21537741Smckusick 	 */
21637741Smckusick 	if ((vp->v_flag & VROOT) == 0) {
21737741Smckusick 		vput(vp);
21837741Smckusick 		RETURN (EINVAL);
21937741Smckusick 	}
22037741Smckusick 	mp = vp->v_mount;
22137741Smckusick 	vput(vp);
22239356Smckusick 	RETURN (dounmount(mp, uap->flags));
22339356Smckusick }
22439356Smckusick 
22539356Smckusick /*
22639356Smckusick  * Do an unmount.
22739356Smckusick  */
22839356Smckusick dounmount(mp, flags)
22939356Smckusick 	register struct mount *mp;
23039356Smckusick 	int flags;
23139356Smckusick {
23239356Smckusick 	struct vnode *coveredvp;
23339356Smckusick 	int error;
23439356Smckusick 
23537741Smckusick 	coveredvp = mp->m_vnodecovered;
23637741Smckusick 	if (error = vfs_lock(mp))
23739356Smckusick 		return (error);
23837741Smckusick 
23937741Smckusick 	xumount(mp);		/* remove unused sticky files from text table */
24037741Smckusick 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
24137741Smckusick 	VFS_SYNC(mp, MNT_WAIT);
24237741Smckusick 
24339356Smckusick 	error = VFS_UNMOUNT(mp, flags);
24437741Smckusick 	if (error) {
24537741Smckusick 		vfs_unlock(mp);
24637741Smckusick 	} else {
24737741Smckusick 		vrele(coveredvp);
24837741Smckusick 		vfs_remove(mp);
24937741Smckusick 		free((caddr_t)mp, M_MOUNT);
25037741Smckusick 	}
25139356Smckusick 	return (error);
2526254Sroot }
2536254Sroot 
2549167Ssam /*
25537741Smckusick  * Sync system call.
25637741Smckusick  * Sync each mounted filesystem.
2579167Ssam  */
25839491Smckusick /* ARGSUSED */
25938408Smckusick sync(scp)
26039491Smckusick 	struct syscontext *scp;
2616254Sroot {
26237741Smckusick 	register struct mount *mp;
26340110Smckusick 	struct mount *nmp;
26437741Smckusick 
26537741Smckusick 	mp = rootfs;
26637741Smckusick 	do {
26740110Smckusick 		nmp = mp->m_next;
26840110Smckusick 		if ((mp->m_flag & (M_MLOCK|M_RDONLY)) == 0)
26937741Smckusick 			VFS_SYNC(mp, MNT_NOWAIT);
27040110Smckusick 		mp = nmp;
27137741Smckusick 	} while (mp != rootfs);
27237741Smckusick }
27337741Smckusick 
27437741Smckusick /*
27537741Smckusick  * get filesystem statistics
27637741Smckusick  */
27738408Smckusick statfs(scp)
27838408Smckusick 	register struct syscontext *scp;
27937741Smckusick {
2806254Sroot 	struct a {
28137741Smckusick 		char *path;
28237741Smckusick 		struct statfs *buf;
28338408Smckusick 	} *uap = (struct a *)scp->sc_ap;
28439464Smckusick 	register struct mount *mp;
28538408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
28637741Smckusick 	struct statfs sb;
28737741Smckusick 	int error;
28837741Smckusick 
28939544Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW;
29037741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
29137741Smckusick 	ndp->ni_dirp = uap->path;
29237741Smckusick 	if (error = namei(ndp))
29337741Smckusick 		RETURN (error);
29439544Smckusick 	mp = ndp->ni_vp->v_mount;
29539544Smckusick 	vrele(ndp->ni_vp);
29639464Smckusick 	if (error = VFS_STATFS(mp, &sb))
29739544Smckusick 		RETURN (error);
29839464Smckusick 	sb.f_flags = mp->m_flag & M_VISFLAGMASK;
29939464Smckusick 	sb.f_fsid = mp->m_fsid;
30039544Smckusick 	RETURN (copyout((caddr_t)&sb, (caddr_t)uap->buf, sizeof(sb)));
30137741Smckusick }
30237741Smckusick 
30338408Smckusick fstatfs(scp)
30438408Smckusick 	register struct syscontext *scp;
30537741Smckusick {
30637741Smckusick 	struct a {
30737741Smckusick 		int fd;
30837741Smckusick 		struct statfs *buf;
30938408Smckusick 	} *uap = (struct a *)scp->sc_ap;
31037741Smckusick 	struct file *fp;
31139464Smckusick 	struct mount *mp;
31237741Smckusick 	struct statfs sb;
31337741Smckusick 	int error;
31437741Smckusick 
31538408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
31637741Smckusick 		RETURN (error);
31739464Smckusick 	mp = ((struct vnode *)fp->f_data)->v_mount;
31839464Smckusick 	if (error = VFS_STATFS(mp, &sb))
31937741Smckusick 		RETURN (error);
32039464Smckusick 	sb.f_flags = mp->m_flag & M_VISFLAGMASK;
32139464Smckusick 	sb.f_fsid = mp->m_fsid;
32237741Smckusick 	RETURN (copyout((caddr_t)&sb, (caddr_t)uap->buf, sizeof(sb)));
32337741Smckusick }
32437741Smckusick 
32537741Smckusick /*
32638270Smckusick  * get statistics on all filesystems
32738270Smckusick  */
32838408Smckusick getfsstat(scp)
32938408Smckusick 	register struct syscontext *scp;
33038270Smckusick {
33138270Smckusick 	struct a {
33238270Smckusick 		struct statfs *buf;
33338270Smckusick 		long bufsize;
33438408Smckusick 	} *uap = (struct a *)scp->sc_ap;
33538270Smckusick 	register struct mount *mp;
33639606Smckusick 	caddr_t sfsp;
33738270Smckusick 	long count, maxcount, error;
33839606Smckusick 	struct statfs sb;
33938270Smckusick 
34038270Smckusick 	maxcount = uap->bufsize / sizeof(struct statfs);
34139606Smckusick 	sfsp = (caddr_t)uap->buf;
34238270Smckusick 	mp = rootfs;
34338270Smckusick 	count = 0;
34438270Smckusick 	do {
34539606Smckusick 		if (sfsp && count < maxcount && ((mp->m_flag & M_MLOCK) == 0)) {
34639607Smckusick 			if (error = VFS_STATFS(mp, &sb)) {
34739607Smckusick 				mp = mp->m_prev;
34839607Smckusick 				continue;
34939607Smckusick 			}
35039606Smckusick 			sb.f_flags = mp->m_flag & M_VISFLAGMASK;
35139606Smckusick 			sb.f_fsid = mp->m_fsid;
35239606Smckusick 			if (error = copyout((caddr_t)&sb, sfsp, sizeof(sb)))
35339606Smckusick 				RETURN (error);
35439606Smckusick 			sfsp += sizeof(sb);
35538270Smckusick 		}
35639606Smckusick 		count++;
35738270Smckusick 		mp = mp->m_prev;
35838270Smckusick 	} while (mp != rootfs);
35938270Smckusick 	if (sfsp && count > maxcount)
36038408Smckusick 		scp->sc_retval1 = maxcount;
36138270Smckusick 	else
36238408Smckusick 		scp->sc_retval1 = count;
36338270Smckusick 	RETURN (0);
36438270Smckusick }
36538270Smckusick 
36638270Smckusick /*
36738259Smckusick  * Change current working directory to a given file descriptor.
36838259Smckusick  */
36938408Smckusick fchdir(scp)
37038408Smckusick 	register struct syscontext *scp;
37138259Smckusick {
37238259Smckusick 	struct a {
37338259Smckusick 		int	fd;
37438408Smckusick 	} *uap = (struct a *)scp->sc_ap;
37538259Smckusick 	register struct vnode *vp;
37638259Smckusick 	struct file *fp;
37738259Smckusick 	int error;
37838259Smckusick 
37938408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
38038259Smckusick 		RETURN (error);
38138259Smckusick 	vp = (struct vnode *)fp->f_data;
38238259Smckusick 	VOP_LOCK(vp);
38338259Smckusick 	if (vp->v_type != VDIR)
38438259Smckusick 		error = ENOTDIR;
38538259Smckusick 	else
38638408Smckusick 		error = VOP_ACCESS(vp, VEXEC, scp->sc_cred);
38738259Smckusick 	VOP_UNLOCK(vp);
38839860Smckusick 	if (error)
38939860Smckusick 		RETURN (error);
39039860Smckusick 	VREF(vp);
39138408Smckusick 	vrele(scp->sc_cdir);
39238408Smckusick 	scp->sc_cdir = vp;
39339860Smckusick 	RETURN (0);
39438259Smckusick }
39538259Smckusick 
39638259Smckusick /*
39737741Smckusick  * Change current working directory (``.'').
39837741Smckusick  */
39938408Smckusick chdir(scp)
40038408Smckusick 	register struct syscontext *scp;
40137741Smckusick {
40237741Smckusick 	struct a {
4036254Sroot 		char	*fname;
40438408Smckusick 	} *uap = (struct a *)scp->sc_ap;
40538408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
40637741Smckusick 	int error;
4076254Sroot 
40837741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
40916694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
41016694Smckusick 	ndp->ni_dirp = uap->fname;
41137741Smckusick 	if (error = chdirec(ndp))
41237741Smckusick 		RETURN (error);
41338408Smckusick 	vrele(scp->sc_cdir);
41438408Smckusick 	scp->sc_cdir = ndp->ni_vp;
41537741Smckusick 	RETURN (0);
41637741Smckusick }
4176254Sroot 
41837741Smckusick /*
41937741Smckusick  * Change notion of root (``/'') directory.
42037741Smckusick  */
42138408Smckusick chroot(scp)
42238408Smckusick 	register struct syscontext *scp;
42337741Smckusick {
42437741Smckusick 	struct a {
42537741Smckusick 		char	*fname;
42638408Smckusick 	} *uap = (struct a *)scp->sc_ap;
42738408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
42837741Smckusick 	int error;
42937741Smckusick 
43038408Smckusick 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
43137741Smckusick 		RETURN (error);
43237741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
43337741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
43437741Smckusick 	ndp->ni_dirp = uap->fname;
43537741Smckusick 	if (error = chdirec(ndp))
43637741Smckusick 		RETURN (error);
43739515Smckusick 	if (scp->sc_rdir != NULL)
43839515Smckusick 		vrele(scp->sc_rdir);
43938408Smckusick 	scp->sc_rdir = ndp->ni_vp;
44037741Smckusick 	RETURN (0);
4416254Sroot }
4426254Sroot 
44337Sbill /*
44437741Smckusick  * Common routine for chroot and chdir.
44537741Smckusick  */
44637741Smckusick chdirec(ndp)
44737741Smckusick 	register struct nameidata *ndp;
44837741Smckusick {
44937741Smckusick 	struct vnode *vp;
45037741Smckusick 	int error;
45137741Smckusick 
45237741Smckusick 	if (error = namei(ndp))
45337741Smckusick 		return (error);
45437741Smckusick 	vp = ndp->ni_vp;
45537741Smckusick 	if (vp->v_type != VDIR)
45637741Smckusick 		error = ENOTDIR;
45737741Smckusick 	else
45838399Smckusick 		error = VOP_ACCESS(vp, VEXEC, ndp->ni_cred);
45937741Smckusick 	VOP_UNLOCK(vp);
46037741Smckusick 	if (error)
46137741Smckusick 		vrele(vp);
46237741Smckusick 	return (error);
46337741Smckusick }
46437741Smckusick 
46537741Smckusick /*
4666254Sroot  * Open system call.
4676254Sroot  */
46838408Smckusick open(scp)
46938408Smckusick 	register struct syscontext *scp;
4706254Sroot {
47112756Ssam 	struct a {
4726254Sroot 		char	*fname;
4737701Ssam 		int	mode;
47412756Ssam 		int	crtmode;
47538408Smckusick 	} *uap = (struct a *) scp->sc_ap;
47638408Smckusick 	struct nameidata *ndp = &scp->sc_nd;
4776254Sroot 
47837741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
47937741Smckusick 	ndp->ni_dirp = uap->fname;
48038408Smckusick 	RETURN (copen(scp, uap->mode-FOPEN, uap->crtmode &~ scp->sc_cmask, ndp,
48138408Smckusick 		&scp->sc_retval1));
4826254Sroot }
4836254Sroot 
4846254Sroot /*
4856254Sroot  * Creat system call.
4866254Sroot  */
48738408Smckusick creat(scp)
48838408Smckusick 	register struct syscontext *scp;
4896254Sroot {
49012756Ssam 	struct a {
4916254Sroot 		char	*fname;
4926254Sroot 		int	fmode;
49338408Smckusick 	} *uap = (struct a *)scp->sc_ap;
49438408Smckusick 	struct nameidata *ndp = &scp->sc_nd;
4956254Sroot 
49637741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
49737741Smckusick 	ndp->ni_dirp = uap->fname;
49838408Smckusick 	RETURN (copen(scp, FWRITE|FCREAT|FTRUNC, uap->fmode &~ scp->sc_cmask,
49938408Smckusick 		ndp, &scp->sc_retval1));
5006254Sroot }
5016254Sroot 
5026254Sroot /*
5036254Sroot  * Common code for open and creat.
50412756Ssam  * Check permissions, allocate an open file structure,
50512756Ssam  * and call the device open routine if any.
5066254Sroot  */
50738408Smckusick copen(scp, fmode, cmode, ndp, resultfd)
50838408Smckusick 	register struct syscontext *scp;
50937741Smckusick 	int fmode, cmode;
51037741Smckusick 	struct nameidata *ndp;
51137741Smckusick 	int *resultfd;
51212756Ssam {
5136254Sroot 	register struct file *fp;
51437741Smckusick 	struct file *nfp;
51537741Smckusick 	int indx, error;
51637741Smckusick 	extern struct fileops vnops;
5176254Sroot 
51837741Smckusick 	if (error = falloc(&nfp, &indx))
51937741Smckusick 		return (error);
52037741Smckusick 	fp = nfp;
52138408Smckusick 	scp->sc_retval1 = indx;	/* XXX for fdopen() */
52237741Smckusick 	if (error = vn_open(ndp, fmode, (cmode & 07777) &~ ISVTX)) {
52337741Smckusick 		crfree(fp->f_cred);
52437741Smckusick 		fp->f_count--;
52539499Smckusick 		if (error == -1)	/* XXX from fdopen */
52639499Smckusick 			return (0);	/* XXX from fdopen */
52739499Smckusick 		scp->sc_ofile[indx] = NULL;
52837741Smckusick 		return (error);
52912756Ssam 	}
53037741Smckusick 	fp->f_flag = fmode & FMASK;
53137741Smckusick 	fp->f_type = DTYPE_VNODE;
53237741Smckusick 	fp->f_ops = &vnops;
53337741Smckusick 	fp->f_data = (caddr_t)ndp->ni_vp;
53437741Smckusick 	if (resultfd)
53537741Smckusick 		*resultfd = indx;
53637741Smckusick 	return (0);
5376254Sroot }
5386254Sroot 
5396254Sroot /*
5406254Sroot  * Mknod system call
5416254Sroot  */
54238408Smckusick mknod(scp)
54338408Smckusick 	register struct syscontext *scp;
5446254Sroot {
5456254Sroot 	register struct a {
5466254Sroot 		char	*fname;
5476254Sroot 		int	fmode;
5486254Sroot 		int	dev;
54938408Smckusick 	} *uap = (struct a *)scp->sc_ap;
55038408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
55137741Smckusick 	register struct vnode *vp;
55237741Smckusick 	struct vattr vattr;
55337741Smckusick 	int error;
5546254Sroot 
55538408Smckusick 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
55637741Smckusick 		RETURN (error);
55737741Smckusick 	ndp->ni_nameiop = CREATE | LOCKPARENT;
55816694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
55916694Smckusick 	ndp->ni_dirp = uap->fname;
56037741Smckusick 	if (error = namei(ndp))
56137741Smckusick 		RETURN (error);
56237741Smckusick 	vp = ndp->ni_vp;
56337741Smckusick 	if (vp != NULL) {
56437741Smckusick 		error = EEXIST;
56512756Ssam 		goto out;
5666254Sroot 	}
56737741Smckusick 	vattr_null(&vattr);
56837741Smckusick 	switch (uap->fmode & IFMT) {
56912756Ssam 
57015093Smckusick 	case IFMT:	/* used by badsect to flag bad sectors */
57137741Smckusick 		vattr.va_type = VBAD;
57237741Smckusick 		break;
57312756Ssam 	case IFCHR:
57437741Smckusick 		vattr.va_type = VCHR;
57537741Smckusick 		break;
57612756Ssam 	case IFBLK:
57737741Smckusick 		vattr.va_type = VBLK;
57837741Smckusick 		break;
57937741Smckusick 	default:
58037741Smckusick 		error = EINVAL;
58137741Smckusick 		goto out;
5826254Sroot 	}
58338408Smckusick 	vattr.va_mode = (uap->fmode & 07777) &~ scp->sc_cmask;
58437741Smckusick 	vattr.va_rdev = uap->dev;
5856254Sroot out:
58637741Smckusick 	if (error)
58737741Smckusick 		VOP_ABORTOP(ndp);
58837741Smckusick 	else
58937741Smckusick 		error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred);
59037741Smckusick 	RETURN (error);
5916254Sroot }
5926254Sroot 
5936254Sroot /*
59440285Smckusick  * Mkfifo system call
59540285Smckusick  */
59640285Smckusick mkfifo(scp)
59740285Smckusick 	register struct syscontext *scp;
59840285Smckusick {
59940285Smckusick 	register struct a {
60040285Smckusick 		char	*fname;
60140285Smckusick 		int	fmode;
60240285Smckusick 	} *uap = (struct a *)scp->sc_ap;
60340285Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
60440285Smckusick 	struct vattr vattr;
60540285Smckusick 	int error;
60640285Smckusick 
60740285Smckusick #ifndef FIFO
60840285Smckusick 	RETURN (EOPNOTSUPP);
60940285Smckusick #else
61040285Smckusick 	ndp->ni_nameiop = CREATE | LOCKPARENT;
61140285Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
61240285Smckusick 	ndp->ni_dirp = uap->fname;
61340285Smckusick 	if (error = namei(ndp))
61440285Smckusick 		RETURN (error);
61540285Smckusick 	if (ndp->ni_vp != NULL) {
61640285Smckusick 		VOP_ABORTOP(ndp);
61740285Smckusick 		RETURN (EEXIST);
61840285Smckusick 	} else {
61940285Smckusick 		vattr_null(&vattr);
62040285Smckusick 		vattr.va_type = VFIFO;
62140285Smckusick 		vattr.va_mode = (uap->fmode & 07777) &~ scp->sc_cmask;
62240285Smckusick 	}
62340285Smckusick 	RETURN (VOP_MKNOD(ndp, &vattr, ndp->ni_cred));
62440285Smckusick #endif /* FIFO */
62540285Smckusick }
62640285Smckusick 
62740285Smckusick /*
6286254Sroot  * link system call
6296254Sroot  */
63038408Smckusick link(scp)
63138408Smckusick 	register struct syscontext *scp;
6326254Sroot {
6336254Sroot 	register struct a {
6346254Sroot 		char	*target;
6356254Sroot 		char	*linkname;
63638408Smckusick 	} *uap = (struct a *)scp->sc_ap;
63738408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
63837741Smckusick 	register struct vnode *vp, *xp;
63937741Smckusick 	int error;
6406254Sroot 
64116694Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW;
64216694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
64316694Smckusick 	ndp->ni_dirp = uap->target;
64437741Smckusick 	if (error = namei(ndp))
64537741Smckusick 		RETURN (error);
64637741Smckusick 	vp = ndp->ni_vp;
64737741Smckusick 	if (vp->v_type == VDIR &&
64838408Smckusick 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
64937741Smckusick 		goto out1;
65037741Smckusick 	ndp->ni_nameiop = CREATE | LOCKPARENT;
65116694Smckusick 	ndp->ni_dirp = (caddr_t)uap->linkname;
65237741Smckusick 	if (error = namei(ndp))
65337741Smckusick 		goto out1;
65437741Smckusick 	xp = ndp->ni_vp;
6556254Sroot 	if (xp != NULL) {
65637741Smckusick 		error = EEXIST;
6576254Sroot 		goto out;
6586254Sroot 	}
65937741Smckusick 	xp = ndp->ni_dvp;
66037741Smckusick 	if (vp->v_mount != xp->v_mount)
66137741Smckusick 		error = EXDEV;
6626254Sroot out:
66337741Smckusick 	if (error)
66437741Smckusick 		VOP_ABORTOP(ndp);
66537741Smckusick 	else
66637741Smckusick 		error = VOP_LINK(vp, ndp);
66737741Smckusick out1:
66837741Smckusick 	vrele(vp);
66937741Smckusick 	RETURN (error);
6706254Sroot }
6716254Sroot 
6726254Sroot /*
6736254Sroot  * symlink -- make a symbolic link
6746254Sroot  */
67538408Smckusick symlink(scp)
67638408Smckusick 	register struct syscontext *scp;
6776254Sroot {
67837741Smckusick 	struct a {
6796254Sroot 		char	*target;
6806254Sroot 		char	*linkname;
68138408Smckusick 	} *uap = (struct a *)scp->sc_ap;
68238408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
68337741Smckusick 	register struct vnode *vp;
68437741Smckusick 	struct vattr vattr;
68537741Smckusick 	char *target;
68637741Smckusick 	int error;
6876254Sroot 
68816694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
68916694Smckusick 	ndp->ni_dirp = uap->linkname;
69037741Smckusick 	MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
69137741Smckusick 	if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
69237741Smckusick 		goto out1;
69337741Smckusick 	ndp->ni_nameiop = CREATE | LOCKPARENT;
69437741Smckusick 	if (error = namei(ndp))
69537741Smckusick 		goto out1;
69637741Smckusick 	vp = ndp->ni_vp;
69737741Smckusick 	if (vp) {
69837741Smckusick 		error = EEXIST;
69937741Smckusick 		goto out;
7006254Sroot 	}
70137741Smckusick 	vp = ndp->ni_dvp;
70237741Smckusick 	vattr_null(&vattr);
70338408Smckusick 	vattr.va_mode = 0777 &~ scp->sc_cmask;
70437741Smckusick out:
70537741Smckusick 	if (error)
70637741Smckusick 		VOP_ABORTOP(ndp);
70737741Smckusick 	else
70837741Smckusick 		error = VOP_SYMLINK(ndp, &vattr, target);
70937741Smckusick out1:
71037741Smckusick 	FREE(target, M_NAMEI);
71137741Smckusick 	RETURN (error);
7126254Sroot }
7136254Sroot 
7146254Sroot /*
7156254Sroot  * Unlink system call.
7166254Sroot  * Hard to avoid races here, especially
7176254Sroot  * in unlinking directories.
7186254Sroot  */
71938408Smckusick unlink(scp)
72038408Smckusick 	register struct syscontext *scp;
7216254Sroot {
7226254Sroot 	struct a {
7236254Sroot 		char	*fname;
72438408Smckusick 	} *uap = (struct a *)scp->sc_ap;
72538408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
72637741Smckusick 	register struct vnode *vp;
72737741Smckusick 	int error;
7286254Sroot 
72937741Smckusick 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
73016694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
73116694Smckusick 	ndp->ni_dirp = uap->fname;
73237741Smckusick 	if (error = namei(ndp))
73337741Smckusick 		RETURN (error);
73437741Smckusick 	vp = ndp->ni_vp;
73537741Smckusick 	if (vp->v_type == VDIR &&
73638408Smckusick 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
7376254Sroot 		goto out;
7386254Sroot 	/*
7396254Sroot 	 * Don't unlink a mounted file.
7406254Sroot 	 */
74137741Smckusick 	if (vp->v_flag & VROOT) {
74237741Smckusick 		error = EBUSY;
7436254Sroot 		goto out;
7446254Sroot 	}
74537741Smckusick 	if (vp->v_flag & VTEXT)
74637741Smckusick 		xrele(vp);	/* try once to free text */
7476254Sroot out:
74837741Smckusick 	if (error)
74937741Smckusick 		VOP_ABORTOP(ndp);
7507142Smckusick 	else
75137741Smckusick 		error = VOP_REMOVE(ndp);
75237741Smckusick 	RETURN (error);
7536254Sroot }
7546254Sroot 
7556254Sroot /*
7566254Sroot  * Seek system call
7576254Sroot  */
75838408Smckusick lseek(scp)
75938408Smckusick 	register struct syscontext *scp;
7606254Sroot {
7616254Sroot 	register struct file *fp;
7626254Sroot 	register struct a {
76337741Smckusick 		int	fdes;
7646254Sroot 		off_t	off;
7656254Sroot 		int	sbase;
76638408Smckusick 	} *uap = (struct a *)scp->sc_ap;
76737741Smckusick 	struct vattr vattr;
76837741Smckusick 	int error;
7696254Sroot 
77037741Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
77138408Smckusick 	    (fp = scp->sc_ofile[uap->fdes]) == NULL)
77237741Smckusick 		RETURN (EBADF);
77337741Smckusick 	if (fp->f_type != DTYPE_VNODE)
77437741Smckusick 		RETURN (ESPIPE);
77513878Ssam 	switch (uap->sbase) {
77613878Ssam 
77713878Ssam 	case L_INCR:
77813878Ssam 		fp->f_offset += uap->off;
77913878Ssam 		break;
78013878Ssam 
78113878Ssam 	case L_XTND:
78237741Smckusick 		if (error = VOP_GETATTR((struct vnode *)fp->f_data,
78338408Smckusick 		    &vattr, scp->sc_cred))
78437741Smckusick 			RETURN (error);
78537741Smckusick 		fp->f_offset = uap->off + vattr.va_size;
78613878Ssam 		break;
78713878Ssam 
78813878Ssam 	case L_SET:
78913878Ssam 		fp->f_offset = uap->off;
79013878Ssam 		break;
79113878Ssam 
79213878Ssam 	default:
79337741Smckusick 		RETURN (EINVAL);
79413878Ssam 	}
79538408Smckusick 	scp->sc_offset = fp->f_offset;
79637741Smckusick 	RETURN (0);
7976254Sroot }
7986254Sroot 
7996254Sroot /*
8006254Sroot  * Access system call
8016254Sroot  */
80238408Smckusick saccess(scp)
80338408Smckusick 	register struct syscontext *scp;
8046254Sroot {
8056254Sroot 	register struct a {
8066254Sroot 		char	*fname;
8076254Sroot 		int	fmode;
80838408Smckusick 	} *uap = (struct a *)scp->sc_ap;
80938408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
81037741Smckusick 	register struct vnode *vp;
81137741Smckusick 	int error, mode, svuid, svgid;
8126254Sroot 
81338408Smckusick 	svuid = scp->sc_uid;
81438408Smckusick 	svgid = scp->sc_gid;
81538408Smckusick 	scp->sc_uid = scp->sc_ruid;
81638408Smckusick 	scp->sc_gid = scp->sc_rgid;
81737741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
81816694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
81916694Smckusick 	ndp->ni_dirp = uap->fname;
82037741Smckusick 	if (error = namei(ndp))
82137741Smckusick 		goto out1;
82237741Smckusick 	vp = ndp->ni_vp;
82337741Smckusick 	/*
82437741Smckusick 	 * fmode == 0 means only check for exist
82537741Smckusick 	 */
82637741Smckusick 	if (uap->fmode) {
82737741Smckusick 		mode = 0;
82837741Smckusick 		if (uap->fmode & R_OK)
82937741Smckusick 			mode |= VREAD;
83037741Smckusick 		if (uap->fmode & W_OK)
83137741Smckusick 			mode |= VWRITE;
83237741Smckusick 		if (uap->fmode & X_OK)
83337741Smckusick 			mode |= VEXEC;
83439543Smckusick 		if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
83538399Smckusick 			error = VOP_ACCESS(vp, mode, ndp->ni_cred);
8366254Sroot 	}
83737741Smckusick 	vput(vp);
83837741Smckusick out1:
83938408Smckusick 	scp->sc_uid = svuid;
84038408Smckusick 	scp->sc_gid = svgid;
84137741Smckusick 	RETURN (error);
8426254Sroot }
8436254Sroot 
8446254Sroot /*
8456574Smckusic  * Stat system call.  This version follows links.
84637Sbill  */
84738408Smckusick stat(scp)
84838408Smckusick 	struct syscontext *scp;
84937Sbill {
85037Sbill 
85138408Smckusick 	stat1(scp, FOLLOW);
85237Sbill }
85337Sbill 
85437Sbill /*
8556574Smckusic  * Lstat system call.  This version does not follow links.
8565992Swnj  */
85738408Smckusick lstat(scp)
85838408Smckusick 	struct syscontext *scp;
8595992Swnj {
86012756Ssam 
86138408Smckusick 	stat1(scp, NOFOLLOW);
86212756Ssam }
86312756Ssam 
86438408Smckusick stat1(scp, follow)
86538408Smckusick 	register struct syscontext *scp;
86612756Ssam 	int follow;
86712756Ssam {
8685992Swnj 	register struct a {
8695992Swnj 		char	*fname;
87012756Ssam 		struct stat *ub;
87138408Smckusick 	} *uap = (struct a *)scp->sc_ap;
87238408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
87312756Ssam 	struct stat sb;
87437741Smckusick 	int error;
8755992Swnj 
87637741Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow;
87716694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
87816694Smckusick 	ndp->ni_dirp = uap->fname;
87937741Smckusick 	if (error = namei(ndp))
88037741Smckusick 		RETURN (error);
88137741Smckusick 	error = vn_stat(ndp->ni_vp, &sb);
88237741Smckusick 	vput(ndp->ni_vp);
88337741Smckusick 	if (error)
88437741Smckusick 		RETURN (error);
88537741Smckusick 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
88637741Smckusick 	RETURN (error);
8875992Swnj }
8885992Swnj 
8895992Swnj /*
8905992Swnj  * Return target name of a symbolic link
89137Sbill  */
89238408Smckusick readlink(scp)
89338408Smckusick 	register struct syscontext *scp;
8945992Swnj {
8955992Swnj 	register struct a {
8965992Swnj 		char	*name;
8975992Swnj 		char	*buf;
8985992Swnj 		int	count;
89938408Smckusick 	} *uap = (struct a *)scp->sc_ap;
90038408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
90137741Smckusick 	register struct vnode *vp;
90237741Smckusick 	struct iovec aiov;
90337741Smckusick 	struct uio auio;
90437741Smckusick 	int error;
9055992Swnj 
90637741Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF;
90716694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
90816694Smckusick 	ndp->ni_dirp = uap->name;
90937741Smckusick 	if (error = namei(ndp))
91037741Smckusick 		RETURN (error);
91137741Smckusick 	vp = ndp->ni_vp;
91237741Smckusick 	if (vp->v_type != VLNK) {
91337741Smckusick 		error = EINVAL;
9145992Swnj 		goto out;
9155992Swnj 	}
91637741Smckusick 	aiov.iov_base = uap->buf;
91737741Smckusick 	aiov.iov_len = uap->count;
91837741Smckusick 	auio.uio_iov = &aiov;
91937741Smckusick 	auio.uio_iovcnt = 1;
92037741Smckusick 	auio.uio_offset = 0;
92137741Smckusick 	auio.uio_rw = UIO_READ;
92237741Smckusick 	auio.uio_segflg = UIO_USERSPACE;
92337741Smckusick 	auio.uio_resid = uap->count;
92437741Smckusick 	error = VOP_READLINK(vp, &auio, ndp->ni_cred);
9255992Swnj out:
92637741Smckusick 	vput(vp);
92738408Smckusick 	scp->sc_retval1 = uap->count - auio.uio_resid;
92837741Smckusick 	RETURN (error);
9295992Swnj }
9305992Swnj 
9319167Ssam /*
93238259Smckusick  * Change flags of a file given path name.
93338259Smckusick  */
93438408Smckusick chflags(scp)
93538408Smckusick 	register struct syscontext *scp;
93638259Smckusick {
93738259Smckusick 	struct a {
93838259Smckusick 		char	*fname;
93938259Smckusick 		int	flags;
94038408Smckusick 	} *uap = (struct a *)scp->sc_ap;
94138408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
94238259Smckusick 	register struct vnode *vp;
94338259Smckusick 	struct vattr vattr;
94438259Smckusick 	int error;
94538259Smckusick 
94638259Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
94738259Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
94838259Smckusick 	ndp->ni_dirp = uap->fname;
94938259Smckusick 	vattr_null(&vattr);
95038259Smckusick 	vattr.va_flags = uap->flags;
95138259Smckusick 	if (error = namei(ndp))
95238259Smckusick 		RETURN (error);
95338259Smckusick 	vp = ndp->ni_vp;
95438259Smckusick 	if (vp->v_mount->m_flag & M_RDONLY) {
95538259Smckusick 		error = EROFS;
95638259Smckusick 		goto out;
95738259Smckusick 	}
95838259Smckusick 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
95938259Smckusick out:
96038259Smckusick 	vput(vp);
96138259Smckusick 	RETURN (error);
96238259Smckusick }
96338259Smckusick 
96438259Smckusick /*
96538259Smckusick  * Change flags of a file given a file descriptor.
96638259Smckusick  */
96738408Smckusick fchflags(scp)
96838408Smckusick 	register struct syscontext *scp;
96938259Smckusick {
97038259Smckusick 	struct a {
97138259Smckusick 		int	fd;
97238259Smckusick 		int	flags;
97338408Smckusick 	} *uap = (struct a *)scp->sc_ap;
97438259Smckusick 	struct vattr vattr;
97538259Smckusick 	struct vnode *vp;
97638259Smckusick 	struct file *fp;
97738259Smckusick 	int error;
97838259Smckusick 
97938408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
98038259Smckusick 		RETURN (error);
98138259Smckusick 	vattr_null(&vattr);
98238259Smckusick 	vattr.va_flags = uap->flags;
98338259Smckusick 	vp = (struct vnode *)fp->f_data;
98438259Smckusick 	VOP_LOCK(vp);
98538259Smckusick 	if (vp->v_mount->m_flag & M_RDONLY) {
98638259Smckusick 		error = EROFS;
98738259Smckusick 		goto out;
98838259Smckusick 	}
98938259Smckusick 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
99038259Smckusick out:
99138259Smckusick 	VOP_UNLOCK(vp);
99238259Smckusick 	RETURN (error);
99338259Smckusick }
99438259Smckusick 
99538259Smckusick /*
9969167Ssam  * Change mode of a file given path name.
9979167Ssam  */
99838408Smckusick chmod(scp)
99938408Smckusick 	register struct syscontext *scp;
10005992Swnj {
10017701Ssam 	struct a {
10026254Sroot 		char	*fname;
10036254Sroot 		int	fmode;
100438408Smckusick 	} *uap = (struct a *)scp->sc_ap;
100538408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
100637741Smckusick 	register struct vnode *vp;
100737741Smckusick 	struct vattr vattr;
100837741Smckusick 	int error;
10095992Swnj 
101037741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
101137741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
101237741Smckusick 	ndp->ni_dirp = uap->fname;
101337741Smckusick 	vattr_null(&vattr);
101437741Smckusick 	vattr.va_mode = uap->fmode & 07777;
101537741Smckusick 	if (error = namei(ndp))
101637741Smckusick 		RETURN (error);
101737741Smckusick 	vp = ndp->ni_vp;
101837741Smckusick 	if (vp->v_mount->m_flag & M_RDONLY) {
101937741Smckusick 		error = EROFS;
102037741Smckusick 		goto out;
102137741Smckusick 	}
102237741Smckusick 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
102337741Smckusick out:
102437741Smckusick 	vput(vp);
102537741Smckusick 	RETURN (error);
10267701Ssam }
10277439Sroot 
10289167Ssam /*
10299167Ssam  * Change mode of a file given a file descriptor.
10309167Ssam  */
103138408Smckusick fchmod(scp)
103238408Smckusick 	register struct syscontext *scp;
10337701Ssam {
10347701Ssam 	struct a {
10357701Ssam 		int	fd;
10367701Ssam 		int	fmode;
103738408Smckusick 	} *uap = (struct a *)scp->sc_ap;
103837741Smckusick 	struct vattr vattr;
103937741Smckusick 	struct vnode *vp;
104037741Smckusick 	struct file *fp;
104137741Smckusick 	int error;
10427701Ssam 
104338408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
104437741Smckusick 		RETURN (error);
104537741Smckusick 	vattr_null(&vattr);
104637741Smckusick 	vattr.va_mode = uap->fmode & 07777;
104737741Smckusick 	vp = (struct vnode *)fp->f_data;
104837741Smckusick 	VOP_LOCK(vp);
104937741Smckusick 	if (vp->v_mount->m_flag & M_RDONLY) {
105037741Smckusick 		error = EROFS;
105137741Smckusick 		goto out;
10527439Sroot 	}
105337741Smckusick 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
105437741Smckusick out:
105537741Smckusick 	VOP_UNLOCK(vp);
105637741Smckusick 	RETURN (error);
10575992Swnj }
10585992Swnj 
10599167Ssam /*
10609167Ssam  * Set ownership given a path name.
10619167Ssam  */
106238408Smckusick chown(scp)
106338408Smckusick 	register struct syscontext *scp;
106437Sbill {
10657701Ssam 	struct a {
10666254Sroot 		char	*fname;
10676254Sroot 		int	uid;
10686254Sroot 		int	gid;
106938408Smckusick 	} *uap = (struct a *)scp->sc_ap;
107038408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
107137741Smckusick 	register struct vnode *vp;
107237741Smckusick 	struct vattr vattr;
107337741Smckusick 	int error;
107437Sbill 
107537741Smckusick 	ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF;
107636614Sbostic 	ndp->ni_segflg = UIO_USERSPACE;
107736614Sbostic 	ndp->ni_dirp = uap->fname;
107837741Smckusick 	vattr_null(&vattr);
107937741Smckusick 	vattr.va_uid = uap->uid;
108037741Smckusick 	vattr.va_gid = uap->gid;
108137741Smckusick 	if (error = namei(ndp))
108237741Smckusick 		RETURN (error);
108337741Smckusick 	vp = ndp->ni_vp;
108437741Smckusick 	if (vp->v_mount->m_flag & M_RDONLY) {
108537741Smckusick 		error = EROFS;
108637741Smckusick 		goto out;
108737741Smckusick 	}
108837741Smckusick 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
108937741Smckusick out:
109037741Smckusick 	vput(vp);
109137741Smckusick 	RETURN (error);
10927701Ssam }
10937439Sroot 
10949167Ssam /*
10959167Ssam  * Set ownership given a file descriptor.
10969167Ssam  */
109738408Smckusick fchown(scp)
109838408Smckusick 	register struct syscontext *scp;
10997701Ssam {
11007701Ssam 	struct a {
11017701Ssam 		int	fd;
11027701Ssam 		int	uid;
11037701Ssam 		int	gid;
110438408Smckusick 	} *uap = (struct a *)scp->sc_ap;
110537741Smckusick 	struct vattr vattr;
110637741Smckusick 	struct vnode *vp;
110737741Smckusick 	struct file *fp;
110837741Smckusick 	int error;
11097701Ssam 
111038408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
111137741Smckusick 		RETURN (error);
111237741Smckusick 	vattr_null(&vattr);
111337741Smckusick 	vattr.va_uid = uap->uid;
111437741Smckusick 	vattr.va_gid = uap->gid;
111537741Smckusick 	vp = (struct vnode *)fp->f_data;
111637741Smckusick 	VOP_LOCK(vp);
111737741Smckusick 	if (vp->v_mount->m_flag & M_RDONLY) {
111837741Smckusick 		error = EROFS;
111937741Smckusick 		goto out;
112037741Smckusick 	}
112137741Smckusick 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
112237741Smckusick out:
112337741Smckusick 	VOP_UNLOCK(vp);
112437741Smckusick 	RETURN (error);
11257701Ssam }
11267701Ssam 
112738408Smckusick utimes(scp)
112838408Smckusick 	register struct syscontext *scp;
112911811Ssam {
113011811Ssam 	register struct a {
113111811Ssam 		char	*fname;
113211811Ssam 		struct	timeval *tptr;
113338408Smckusick 	} *uap = (struct a *)scp->sc_ap;
113438408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
113537741Smckusick 	register struct vnode *vp;
113611811Ssam 	struct timeval tv[2];
113737741Smckusick 	struct vattr vattr;
113837741Smckusick 	int error;
113911811Ssam 
114037741Smckusick 	if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
114137741Smckusick 		RETURN (error);
114237741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
114337741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
114437741Smckusick 	ndp->ni_dirp = uap->fname;
114537741Smckusick 	vattr_null(&vattr);
114637741Smckusick 	vattr.va_atime = tv[0];
114737741Smckusick 	vattr.va_mtime = tv[1];
114837741Smckusick 	if (error = namei(ndp))
114937741Smckusick 		RETURN (error);
115037741Smckusick 	vp = ndp->ni_vp;
115137741Smckusick 	if (vp->v_mount->m_flag & M_RDONLY) {
115237741Smckusick 		error = EROFS;
115337741Smckusick 		goto out;
115421015Smckusick 	}
115537741Smckusick 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
115637741Smckusick out:
115737741Smckusick 	vput(vp);
115837741Smckusick 	RETURN (error);
115911811Ssam }
116011811Ssam 
11619167Ssam /*
11629167Ssam  * Truncate a file given its path name.
11639167Ssam  */
116438408Smckusick truncate(scp)
116538408Smckusick 	register struct syscontext *scp;
11667701Ssam {
11677701Ssam 	struct a {
11687701Ssam 		char	*fname;
116926473Skarels 		off_t	length;
117038408Smckusick 	} *uap = (struct a *)scp->sc_ap;
117138408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
117237741Smckusick 	register struct vnode *vp;
117337741Smckusick 	struct vattr vattr;
117437741Smckusick 	int error;
11757701Ssam 
117637741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
117716694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
117816694Smckusick 	ndp->ni_dirp = uap->fname;
117937741Smckusick 	vattr_null(&vattr);
118037741Smckusick 	vattr.va_size = uap->length;
118137741Smckusick 	if (error = namei(ndp))
118237741Smckusick 		RETURN (error);
118337741Smckusick 	vp = ndp->ni_vp;
118437741Smckusick 	if (vp->v_type == VDIR) {
118537741Smckusick 		error = EISDIR;
118637741Smckusick 		goto out;
11877701Ssam 	}
118838399Smckusick 	if ((error = vn_writechk(vp)) ||
118938399Smckusick 	    (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
119037741Smckusick 		goto out;
119137741Smckusick 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
119237741Smckusick out:
119337741Smckusick 	vput(vp);
119437741Smckusick 	RETURN (error);
11957701Ssam }
11967701Ssam 
11979167Ssam /*
11989167Ssam  * Truncate a file given a file descriptor.
11999167Ssam  */
120038408Smckusick ftruncate(scp)
120138408Smckusick 	register struct syscontext *scp;
12027701Ssam {
12037701Ssam 	struct a {
12047701Ssam 		int	fd;
120526473Skarels 		off_t	length;
120638408Smckusick 	} *uap = (struct a *)scp->sc_ap;
120737741Smckusick 	struct vattr vattr;
120837741Smckusick 	struct vnode *vp;
12097701Ssam 	struct file *fp;
121037741Smckusick 	int error;
12117701Ssam 
121238408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
121337741Smckusick 		RETURN (error);
121437741Smckusick 	if ((fp->f_flag & FWRITE) == 0)
121537741Smckusick 		RETURN (EINVAL);
121637741Smckusick 	vattr_null(&vattr);
121737741Smckusick 	vattr.va_size = uap->length;
121837741Smckusick 	vp = (struct vnode *)fp->f_data;
121937741Smckusick 	VOP_LOCK(vp);
122037741Smckusick 	if (vp->v_type == VDIR) {
122137741Smckusick 		error = EISDIR;
122237741Smckusick 		goto out;
12237701Ssam 	}
122438399Smckusick 	if (error = vn_writechk(vp))
122537741Smckusick 		goto out;
122637741Smckusick 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
122737741Smckusick out:
122837741Smckusick 	VOP_UNLOCK(vp);
122937741Smckusick 	RETURN (error);
12307701Ssam }
12317701Ssam 
12329167Ssam /*
12339167Ssam  * Synch an open file.
12349167Ssam  */
123538408Smckusick fsync(scp)
123638408Smckusick 	register struct syscontext *scp;
12379167Ssam {
12389167Ssam 	struct a {
12399167Ssam 		int	fd;
124038408Smckusick 	} *uap = (struct a *)scp->sc_ap;
124139592Smckusick 	register struct vnode *vp;
12429167Ssam 	struct file *fp;
124337741Smckusick 	int error;
12449167Ssam 
124538408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
124637741Smckusick 		RETURN (error);
124739592Smckusick 	vp = (struct vnode *)fp->f_data;
124839592Smckusick 	VOP_LOCK(vp);
124939592Smckusick 	error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT);
125039592Smckusick 	VOP_UNLOCK(vp);
125137741Smckusick 	RETURN (error);
12529167Ssam }
12539167Ssam 
12549167Ssam /*
12559167Ssam  * Rename system call.
12569167Ssam  *
12579167Ssam  * Source and destination must either both be directories, or both
12589167Ssam  * not be directories.  If target is a directory, it must be empty.
12599167Ssam  */
126038408Smckusick rename(scp)
126138408Smckusick 	register struct syscontext *scp;
12627701Ssam {
12637701Ssam 	struct a {
12647701Ssam 		char	*from;
12657701Ssam 		char	*to;
126638408Smckusick 	} *uap = (struct a *)scp->sc_ap;
126737741Smckusick 	register struct vnode *tvp, *fvp, *tdvp;
126838408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
126937741Smckusick 	struct nameidata tond;
127037741Smckusick 	int error;
12717701Ssam 
127237741Smckusick 	ndp->ni_nameiop = DELETE | WANTPARENT;
127316694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
127416694Smckusick 	ndp->ni_dirp = uap->from;
127537741Smckusick 	if (error = namei(ndp))
127637741Smckusick 		RETURN (error);
127737741Smckusick 	fvp = ndp->ni_vp;
127838266Smckusick 	nddup(ndp, &tond);
127937741Smckusick 	tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
128037741Smckusick 	tond.ni_segflg = UIO_USERSPACE;
128137741Smckusick 	tond.ni_dirp = uap->to;
128237741Smckusick 	error = namei(&tond);
128337741Smckusick 	tdvp = tond.ni_dvp;
128437741Smckusick 	tvp = tond.ni_vp;
128537741Smckusick 	if (tvp != NULL) {
128637741Smckusick 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
128739242Sbostic 			error = ENOTDIR;
128837741Smckusick 			goto out;
128937741Smckusick 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
129039242Sbostic 			error = EISDIR;
129137741Smckusick 			goto out;
12929167Ssam 		}
12939167Ssam 	}
129437741Smckusick 	if (error) {
129537741Smckusick 		VOP_ABORTOP(ndp);
129637741Smckusick 		goto out1;
129737741Smckusick 	}
129837741Smckusick 	if (fvp->v_mount != tdvp->v_mount) {
129937741Smckusick 		error = EXDEV;
13009167Ssam 		goto out;
130110051Ssam 	}
130239286Smckusick 	if (fvp == tdvp)
130337741Smckusick 		error = EINVAL;
130439286Smckusick 	/*
130539286Smckusick 	 * If source is the same as the destination,
130639286Smckusick 	 * then there is nothing to do.
130739286Smckusick 	 */
130839286Smckusick 	if (fvp == tvp)
130939286Smckusick 		error = -1;
131037741Smckusick out:
131137741Smckusick 	if (error) {
131237741Smckusick 		VOP_ABORTOP(&tond);
131337741Smckusick 		VOP_ABORTOP(ndp);
13149167Ssam 	} else {
131537741Smckusick 		error = VOP_RENAME(ndp, &tond);
13169167Ssam 	}
131737741Smckusick out1:
131838266Smckusick 	ndrele(&tond);
131939286Smckusick 	if (error == -1)
132039286Smckusick 		RETURN (0);
132137741Smckusick 	RETURN (error);
13227701Ssam }
13237701Ssam 
13247535Sroot /*
132512756Ssam  * Mkdir system call
132612756Ssam  */
132738408Smckusick mkdir(scp)
132838408Smckusick 	register struct syscontext *scp;
132912756Ssam {
133012756Ssam 	struct a {
133112756Ssam 		char	*name;
133212756Ssam 		int	dmode;
133338408Smckusick 	} *uap = (struct a *)scp->sc_ap;
133438408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
133537741Smckusick 	register struct vnode *vp;
133637741Smckusick 	struct vattr vattr;
133737741Smckusick 	int error;
133812756Ssam 
133937741Smckusick 	ndp->ni_nameiop = CREATE | LOCKPARENT;
134016694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
134116694Smckusick 	ndp->ni_dirp = uap->name;
134237741Smckusick 	if (error = namei(ndp))
134337741Smckusick 		RETURN (error);
134437741Smckusick 	vp = ndp->ni_vp;
134537741Smckusick 	if (vp != NULL) {
134637741Smckusick 		VOP_ABORTOP(ndp);
134737741Smckusick 		RETURN (EEXIST);
134812756Ssam 	}
134937741Smckusick 	vattr_null(&vattr);
135037741Smckusick 	vattr.va_type = VDIR;
135138408Smckusick 	vattr.va_mode = (uap->dmode & 0777) &~ scp->sc_cmask;
135237741Smckusick 	error = VOP_MKDIR(ndp, &vattr);
135338145Smckusick 	if (!error)
135438145Smckusick 		vput(ndp->ni_vp);
135537741Smckusick 	RETURN (error);
135612756Ssam }
135712756Ssam 
135812756Ssam /*
135912756Ssam  * Rmdir system call.
136012756Ssam  */
136138408Smckusick rmdir(scp)
136238408Smckusick 	register struct syscontext *scp;
136312756Ssam {
136412756Ssam 	struct a {
136512756Ssam 		char	*name;
136638408Smckusick 	} *uap = (struct a *)scp->sc_ap;
136738408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
136837741Smckusick 	register struct vnode *vp;
136937741Smckusick 	int error;
137012756Ssam 
137137741Smckusick 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
137216694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
137316694Smckusick 	ndp->ni_dirp = uap->name;
137437741Smckusick 	if (error = namei(ndp))
137537741Smckusick 		RETURN (error);
137637741Smckusick 	vp = ndp->ni_vp;
137737741Smckusick 	if (vp->v_type != VDIR) {
137837741Smckusick 		error = ENOTDIR;
137912756Ssam 		goto out;
138012756Ssam 	}
138112756Ssam 	/*
138237741Smckusick 	 * No rmdir "." please.
138312756Ssam 	 */
138437741Smckusick 	if (ndp->ni_dvp == vp) {
138537741Smckusick 		error = EINVAL;
138612756Ssam 		goto out;
138712756Ssam 	}
138812756Ssam 	/*
138937741Smckusick 	 * Don't unlink a mounted file.
139012756Ssam 	 */
139137741Smckusick 	if (vp->v_flag & VROOT)
139237741Smckusick 		error = EBUSY;
139312756Ssam out:
139437741Smckusick 	if (error)
139537741Smckusick 		VOP_ABORTOP(ndp);
139637741Smckusick 	else
139737741Smckusick 		error = VOP_RMDIR(ndp);
139837741Smckusick 	RETURN (error);
139912756Ssam }
140012756Ssam 
140137741Smckusick /*
140237741Smckusick  * Read a block of directory entries in a file system independent format
140337741Smckusick  */
140438408Smckusick getdirentries(scp)
140538408Smckusick 	register struct syscontext *scp;
140612756Ssam {
140737741Smckusick 	register struct a {
140837741Smckusick 		int	fd;
140937741Smckusick 		char	*buf;
141037741Smckusick 		unsigned count;
141137741Smckusick 		long	*basep;
141238408Smckusick 	} *uap = (struct a *)scp->sc_ap;
141339592Smckusick 	register struct vnode *vp;
141416540Ssam 	struct file *fp;
141537741Smckusick 	struct uio auio;
141637741Smckusick 	struct iovec aiov;
141738129Smckusick 	off_t off;
1418*40321Smckusick 	int error, eofflag;
141912756Ssam 
142038408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
142137741Smckusick 		RETURN (error);
142237741Smckusick 	if ((fp->f_flag & FREAD) == 0)
142337741Smckusick 		RETURN (EBADF);
142439592Smckusick 	vp = (struct vnode *)fp->f_data;
142539592Smckusick 	if (vp->v_type != VDIR)
142639592Smckusick 		RETURN (EINVAL);
142737741Smckusick 	aiov.iov_base = uap->buf;
142837741Smckusick 	aiov.iov_len = uap->count;
142937741Smckusick 	auio.uio_iov = &aiov;
143037741Smckusick 	auio.uio_iovcnt = 1;
143137741Smckusick 	auio.uio_rw = UIO_READ;
143237741Smckusick 	auio.uio_segflg = UIO_USERSPACE;
143337741Smckusick 	auio.uio_resid = uap->count;
143439592Smckusick 	VOP_LOCK(vp);
143539592Smckusick 	auio.uio_offset = off = fp->f_offset;
1436*40321Smckusick 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag);
143739592Smckusick 	fp->f_offset = auio.uio_offset;
143839592Smckusick 	VOP_UNLOCK(vp);
143939592Smckusick 	if (error)
144037741Smckusick 		RETURN (error);
144139592Smckusick 	error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
144238408Smckusick 	scp->sc_retval1 = uap->count - auio.uio_resid;
144337741Smckusick 	RETURN (error);
144412756Ssam }
144512756Ssam 
144612756Ssam /*
144712756Ssam  * mode mask for creation of files
144812756Ssam  */
144938408Smckusick umask(scp)
145038408Smckusick 	register struct syscontext *scp;
145112756Ssam {
145212756Ssam 	register struct a {
145312756Ssam 		int	mask;
145438408Smckusick 	} *uap = (struct a *)scp->sc_ap;
145512756Ssam 
145638408Smckusick 	scp->sc_retval1 = scp->sc_cmask;
145738408Smckusick 	scp->sc_cmask = uap->mask & 07777;
145837741Smckusick 	RETURN (0);
145912756Ssam }
146037741Smckusick 
146139566Smarc /*
146239566Smarc  * Void all references to file by ripping underlying filesystem
146339566Smarc  * away from vnode.
146439566Smarc  */
146539566Smarc revoke(scp)
146639566Smarc 	register struct syscontext *scp;
146739566Smarc {
146839566Smarc 	struct a {
146939566Smarc 		char	*fname;
147039566Smarc 	} *uap = (struct a *)scp->sc_ap;
147139566Smarc 	register struct nameidata *ndp = &scp->sc_nd;
147239566Smarc 	register struct vnode *vp;
147339566Smarc 	struct vattr vattr;
147439566Smarc 	int error;
147539566Smarc 
147639566Smarc 	ndp->ni_nameiop = LOOKUP | FOLLOW;
147739566Smarc 	ndp->ni_segflg = UIO_USERSPACE;
147839566Smarc 	ndp->ni_dirp = uap->fname;
147939566Smarc 	if (error = namei(ndp))
148039566Smarc 		RETURN (error);
148139566Smarc 	vp = ndp->ni_vp;
148239566Smarc 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
148339566Smarc 		error = EINVAL;
148439566Smarc 		goto out;
148539566Smarc 	}
148639566Smarc 	if (error = VOP_GETATTR(vp, &vattr, scp->sc_cred))
148739566Smarc 		goto out;
148839566Smarc 	if (scp->sc_uid != vattr.va_uid ||
148939566Smarc 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
149039566Smarc 		goto out;
149139805Smckusick 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
149239632Smckusick 		vgoneall(vp);
149339566Smarc out:
149439566Smarc 	vrele(vp);
149539566Smarc 	RETURN (error);
149639566Smarc }
149739566Smarc 
149838408Smckusick getvnode(ofile, fdes, fpp)
149938408Smckusick 	struct file *ofile[];
150037741Smckusick 	struct file **fpp;
150137741Smckusick 	int fdes;
150237741Smckusick {
150337741Smckusick 	struct file *fp;
150437741Smckusick 
150538408Smckusick 	if ((unsigned)fdes >= NOFILE || (fp = ofile[fdes]) == NULL)
150637741Smckusick 		return (EBADF);
150737741Smckusick 	if (fp->f_type != DTYPE_VNODE)
150837741Smckusick 		return (EINVAL);
150937741Smckusick 	*fpp = fp;
151037741Smckusick 	return (0);
151137741Smckusick }
1512