xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 41676)
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*41676Smckusick  *	@(#)vfs_syscalls.c	7.47 (Berkeley) 05/11/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 "mount.h"
2817101Sbloom #include "proc.h"
2917101Sbloom #include "uio.h"
3037741Smckusick #include "malloc.h"
3137Sbill 
3239797Smckusick #undef RETURN
3339797Smckusick #define RETURN(val)	{ scp->u_error = (val); if (scp->u_spare[0] != 0) panic("lock count"); return; }
3439797Smckusick 
3537741Smckusick /*
3637741Smckusick  * Virtual File System System Calls
3737741Smckusick  */
3812756Ssam 
399167Ssam /*
4037741Smckusick  * mount system call
419167Ssam  */
4238408Smckusick mount(scp)
4338408Smckusick 	register struct syscontext *scp;
446254Sroot {
4537741Smckusick 	register struct a {
4637741Smckusick 		int	type;
4737741Smckusick 		char	*dir;
4837741Smckusick 		int	flags;
4937741Smckusick 		caddr_t	data;
5038408Smckusick 	} *uap = (struct a *)scp->sc_ap;
5138408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
5239335Smckusick 	register struct vnode *vp;
5339335Smckusick 	register struct mount *mp;
5440111Smckusick 	int error, flag;
556254Sroot 
5637741Smckusick 	/*
5737741Smckusick 	 * Must be super user
5837741Smckusick 	 */
5938408Smckusick 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
6037741Smckusick 		RETURN (error);
6137741Smckusick 	/*
6237741Smckusick 	 * Get vnode to be covered
6337741Smckusick 	 */
6437741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
6537741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
6637741Smckusick 	ndp->ni_dirp = uap->dir;
6737741Smckusick 	if (error = namei(ndp))
6837741Smckusick 		RETURN (error);
6937741Smckusick 	vp = ndp->ni_vp;
7041400Smckusick 	if (uap->flags & MNT_UPDATE) {
7139335Smckusick 		if ((vp->v_flag & VROOT) == 0) {
7239335Smckusick 			vput(vp);
7339335Smckusick 			RETURN (EINVAL);
7439335Smckusick 		}
7539335Smckusick 		mp = vp->v_mount;
7639335Smckusick 		/*
7739335Smckusick 		 * We allow going from read-only to read-write,
7839335Smckusick 		 * but not from read-write to read-only.
7939335Smckusick 		 */
8041400Smckusick 		if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
8141400Smckusick 		    (uap->flags & MNT_RDONLY) != 0) {
8239335Smckusick 			vput(vp);
8339335Smckusick 			RETURN (EOPNOTSUPP);	/* Needs translation */
8439335Smckusick 		}
8541400Smckusick 		flag = mp->mnt_flag;
8641400Smckusick 		mp->mnt_flag |= MNT_UPDATE;
8739335Smckusick 		VOP_UNLOCK(vp);
8839335Smckusick 		goto update;
8939335Smckusick 	}
9039665Smckusick 	vinvalbuf(vp, 1);
9139805Smckusick 	if (vp->v_usecount != 1) {
9237741Smckusick 		vput(vp);
9337741Smckusick 		RETURN (EBUSY);
9437741Smckusick 	}
9537741Smckusick 	if (vp->v_type != VDIR) {
9637741Smckusick 		vput(vp);
9737741Smckusick 		RETURN (ENOTDIR);
9837741Smckusick 	}
9939741Smckusick 	if ((unsigned long)uap->type > MOUNT_MAXTYPE ||
10037741Smckusick 	    vfssw[uap->type] == (struct vfsops *)0) {
10137741Smckusick 		vput(vp);
10237741Smckusick 		RETURN (ENODEV);
10337741Smckusick 	}
10437741Smckusick 
10537741Smckusick 	/*
10639335Smckusick 	 * Allocate and initialize the file system.
10737741Smckusick 	 */
10837741Smckusick 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
10937741Smckusick 		M_MOUNT, M_WAITOK);
11041400Smckusick 	mp->mnt_op = vfssw[uap->type];
11141400Smckusick 	mp->mnt_flag = 0;
11241400Smckusick 	mp->mnt_exroot = 0;
11341400Smckusick 	mp->mnt_mounth = NULLVP;
11439335Smckusick 	if (error = vfs_lock(mp)) {
11539335Smckusick 		free((caddr_t)mp, M_MOUNT);
11639335Smckusick 		vput(vp);
11739335Smckusick 		RETURN (error);
11839335Smckusick 	}
11939335Smckusick 	if (vp->v_mountedhere != (struct mount *)0) {
12039335Smckusick 		vfs_unlock(mp);
12139335Smckusick 		free((caddr_t)mp, M_MOUNT);
12239335Smckusick 		vput(vp);
12339335Smckusick 		RETURN (EBUSY);
12439335Smckusick 	}
12539335Smckusick 	vp->v_mountedhere = mp;
12641400Smckusick 	mp->mnt_vnodecovered = vp;
12739335Smckusick update:
12839335Smckusick 	/*
12939335Smckusick 	 * Set the mount level flags.
13039335Smckusick 	 */
13141400Smckusick 	if (uap->flags & MNT_RDONLY)
13241400Smckusick 		mp->mnt_flag |= MNT_RDONLY;
13339335Smckusick 	else
13441400Smckusick 		mp->mnt_flag &= ~MNT_RDONLY;
13541400Smckusick 	if (uap->flags & MNT_NOSUID)
13641400Smckusick 		mp->mnt_flag |= MNT_NOSUID;
13739335Smckusick 	else
13841400Smckusick 		mp->mnt_flag &= ~MNT_NOSUID;
13941400Smckusick 	if (uap->flags & MNT_NOEXEC)
14041400Smckusick 		mp->mnt_flag |= MNT_NOEXEC;
14139335Smckusick 	else
14241400Smckusick 		mp->mnt_flag &= ~MNT_NOEXEC;
14341400Smckusick 	if (uap->flags & MNT_NODEV)
14441400Smckusick 		mp->mnt_flag |= MNT_NODEV;
14539335Smckusick 	else
14641400Smckusick 		mp->mnt_flag &= ~MNT_NODEV;
14741400Smckusick 	if (uap->flags & MNT_SYNCHRONOUS)
14841400Smckusick 		mp->mnt_flag |= MNT_SYNCHRONOUS;
14939335Smckusick 	else
15041400Smckusick 		mp->mnt_flag &= ~MNT_SYNCHRONOUS;
15139335Smckusick 	/*
15239335Smckusick 	 * Mount the filesystem.
15339335Smckusick 	 */
15439335Smckusick 	error = VFS_MOUNT(mp, uap->dir, uap->data, ndp);
15541400Smckusick 	if (mp->mnt_flag & MNT_UPDATE) {
15641400Smckusick 		mp->mnt_flag &= ~MNT_UPDATE;
15739335Smckusick 		vrele(vp);
15840111Smckusick 		if (error)
15941400Smckusick 			mp->mnt_flag = flag;
16039335Smckusick 		RETURN (error);
16139335Smckusick 	}
16240110Smckusick 	/*
16340110Smckusick 	 * Put the new filesystem on the mount list after root.
16440110Smckusick 	 */
16541400Smckusick 	mp->mnt_next = rootfs->mnt_next;
16641400Smckusick 	mp->mnt_prev = rootfs;
16741400Smckusick 	rootfs->mnt_next = mp;
16841400Smckusick 	mp->mnt_next->mnt_prev = mp;
16937741Smckusick 	cache_purge(vp);
17037741Smckusick 	if (!error) {
17139335Smckusick 		VOP_UNLOCK(vp);
17237741Smckusick 		vfs_unlock(mp);
17339044Smckusick 		error = VFS_START(mp, 0);
17437741Smckusick 	} else {
17537741Smckusick 		vfs_remove(mp);
17637741Smckusick 		free((caddr_t)mp, M_MOUNT);
17739335Smckusick 		vput(vp);
17837741Smckusick 	}
17937741Smckusick 	RETURN (error);
1806254Sroot }
1816254Sroot 
1829167Ssam /*
18337741Smckusick  * Unmount system call.
18437741Smckusick  *
18537741Smckusick  * Note: unmount takes a path to the vnode mounted on as argument,
18637741Smckusick  * not special file (as before).
1879167Ssam  */
18838408Smckusick unmount(scp)
18938408Smckusick 	register struct syscontext *scp;
1906254Sroot {
19137741Smckusick 	struct a {
19237741Smckusick 		char	*pathp;
19337741Smckusick 		int	flags;
19438408Smckusick 	} *uap = (struct a *)scp->sc_ap;
19537741Smckusick 	register struct vnode *vp;
19638408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
19739356Smckusick 	struct mount *mp;
19837741Smckusick 	int error;
1996254Sroot 
20037741Smckusick 	/*
20137741Smckusick 	 * Must be super user
20237741Smckusick 	 */
20338408Smckusick 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
20437741Smckusick 		RETURN (error);
20537741Smckusick 
20637741Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
20737741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
20837741Smckusick 	ndp->ni_dirp = uap->pathp;
20937741Smckusick 	if (error = namei(ndp))
21037741Smckusick 		RETURN (error);
21137741Smckusick 	vp = ndp->ni_vp;
21237741Smckusick 	/*
21337741Smckusick 	 * Must be the root of the filesystem
21437741Smckusick 	 */
21537741Smckusick 	if ((vp->v_flag & VROOT) == 0) {
21637741Smckusick 		vput(vp);
21737741Smckusick 		RETURN (EINVAL);
21837741Smckusick 	}
21937741Smckusick 	mp = vp->v_mount;
22037741Smckusick 	vput(vp);
22139356Smckusick 	RETURN (dounmount(mp, uap->flags));
22239356Smckusick }
22339356Smckusick 
22439356Smckusick /*
22539356Smckusick  * Do an unmount.
22639356Smckusick  */
22739356Smckusick dounmount(mp, flags)
22839356Smckusick 	register struct mount *mp;
22939356Smckusick 	int flags;
23039356Smckusick {
23139356Smckusick 	struct vnode *coveredvp;
23239356Smckusick 	int error;
23339356Smckusick 
23441400Smckusick 	coveredvp = mp->mnt_vnodecovered;
23541298Smckusick 	if (vfs_busy(mp))
23641298Smckusick 		return (EBUSY);
23741400Smckusick 	mp->mnt_flag |= MNT_UNMOUNT;
23837741Smckusick 	if (error = vfs_lock(mp))
23939356Smckusick 		return (error);
24037741Smckusick 
24137741Smckusick 	xumount(mp);		/* remove unused sticky files from text table */
24237741Smckusick 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
243*41676Smckusick 	if ((error = VFS_SYNC(mp, MNT_WAIT)) == 0 || (flags & MNT_FORCE))
244*41676Smckusick 		error = VFS_UNMOUNT(mp, flags);
24541400Smckusick 	mp->mnt_flag &= ~MNT_UNMOUNT;
24641298Smckusick 	vfs_unbusy(mp);
24737741Smckusick 	if (error) {
24837741Smckusick 		vfs_unlock(mp);
24937741Smckusick 	} else {
25037741Smckusick 		vrele(coveredvp);
25137741Smckusick 		vfs_remove(mp);
25237741Smckusick 		free((caddr_t)mp, M_MOUNT);
25337741Smckusick 	}
25439356Smckusick 	return (error);
2556254Sroot }
2566254Sroot 
2579167Ssam /*
25837741Smckusick  * Sync system call.
25937741Smckusick  * Sync each mounted filesystem.
2609167Ssam  */
26139491Smckusick /* ARGSUSED */
26238408Smckusick sync(scp)
26339491Smckusick 	struct syscontext *scp;
2646254Sroot {
26537741Smckusick 	register struct mount *mp;
26641298Smckusick 	struct mount *omp;
26737741Smckusick 
26837741Smckusick 	mp = rootfs;
26937741Smckusick 	do {
27040343Smckusick 		/*
27140343Smckusick 		 * The lock check below is to avoid races with mount
27240343Smckusick 		 * and unmount.
27340343Smckusick 		 */
27441400Smckusick 		if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
27541298Smckusick 		    !vfs_busy(mp)) {
27637741Smckusick 			VFS_SYNC(mp, MNT_NOWAIT);
27741298Smckusick 			omp = mp;
27841400Smckusick 			mp = mp->mnt_next;
27941298Smckusick 			vfs_unbusy(omp);
28041298Smckusick 		} else
28141400Smckusick 			mp = mp->mnt_next;
28237741Smckusick 	} while (mp != rootfs);
28337741Smckusick }
28437741Smckusick 
28537741Smckusick /*
28641298Smckusick  * operate on filesystem quotas
28741298Smckusick  */
28841298Smckusick quotactl(scp)
28941298Smckusick 	register struct syscontext *scp;
29041298Smckusick {
29141298Smckusick 	struct a {
29241298Smckusick 		char *path;
29341298Smckusick 		int cmd;
29441298Smckusick 		int uid;
29541298Smckusick 		caddr_t arg;
29641298Smckusick 	} *uap = (struct a *)scp->sc_ap;
29741298Smckusick 	register struct mount *mp;
29841298Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
29941298Smckusick 	int error;
30041298Smckusick 
30141298Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW;
30241298Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
30341298Smckusick 	ndp->ni_dirp = uap->path;
30441298Smckusick 	if (error = namei(ndp))
30541298Smckusick 		RETURN (error);
30641298Smckusick 	mp = ndp->ni_vp->v_mount;
30741298Smckusick 	vrele(ndp->ni_vp);
30841298Smckusick 	RETURN (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg));
30941298Smckusick }
31041298Smckusick 
31141298Smckusick /*
31237741Smckusick  * get filesystem statistics
31337741Smckusick  */
31438408Smckusick statfs(scp)
31538408Smckusick 	register struct syscontext *scp;
31637741Smckusick {
3176254Sroot 	struct a {
31837741Smckusick 		char *path;
31937741Smckusick 		struct statfs *buf;
32038408Smckusick 	} *uap = (struct a *)scp->sc_ap;
32139464Smckusick 	register struct mount *mp;
32238408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
32340343Smckusick 	register struct statfs *sp;
32437741Smckusick 	int error;
32537741Smckusick 
32639544Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW;
32737741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
32837741Smckusick 	ndp->ni_dirp = uap->path;
32937741Smckusick 	if (error = namei(ndp))
33037741Smckusick 		RETURN (error);
33139544Smckusick 	mp = ndp->ni_vp->v_mount;
33241400Smckusick 	sp = &mp->mnt_stat;
33339544Smckusick 	vrele(ndp->ni_vp);
33440343Smckusick 	if (error = VFS_STATFS(mp, sp))
33539544Smckusick 		RETURN (error);
33641400Smckusick 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
33740343Smckusick 	RETURN (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
33837741Smckusick }
33937741Smckusick 
34038408Smckusick fstatfs(scp)
34138408Smckusick 	register struct syscontext *scp;
34237741Smckusick {
34337741Smckusick 	struct a {
34437741Smckusick 		int fd;
34537741Smckusick 		struct statfs *buf;
34638408Smckusick 	} *uap = (struct a *)scp->sc_ap;
34737741Smckusick 	struct file *fp;
34839464Smckusick 	struct mount *mp;
34940343Smckusick 	register struct statfs *sp;
35037741Smckusick 	int error;
35137741Smckusick 
35238408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
35337741Smckusick 		RETURN (error);
35439464Smckusick 	mp = ((struct vnode *)fp->f_data)->v_mount;
35541400Smckusick 	sp = &mp->mnt_stat;
35640343Smckusick 	if (error = VFS_STATFS(mp, sp))
35737741Smckusick 		RETURN (error);
35841400Smckusick 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
35940343Smckusick 	RETURN (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
36037741Smckusick }
36137741Smckusick 
36237741Smckusick /*
36338270Smckusick  * get statistics on all filesystems
36438270Smckusick  */
36538408Smckusick getfsstat(scp)
36638408Smckusick 	register struct syscontext *scp;
36738270Smckusick {
36838270Smckusick 	struct a {
36938270Smckusick 		struct statfs *buf;
37038270Smckusick 		long bufsize;
37140343Smckusick 		int flags;
37238408Smckusick 	} *uap = (struct a *)scp->sc_ap;
37338270Smckusick 	register struct mount *mp;
37440343Smckusick 	register struct statfs *sp;
37539606Smckusick 	caddr_t sfsp;
37638270Smckusick 	long count, maxcount, error;
37738270Smckusick 
37838270Smckusick 	maxcount = uap->bufsize / sizeof(struct statfs);
37939606Smckusick 	sfsp = (caddr_t)uap->buf;
38038270Smckusick 	mp = rootfs;
38138270Smckusick 	count = 0;
38238270Smckusick 	do {
38341400Smckusick 		if (sfsp && count < maxcount &&
38441400Smckusick 		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
38541400Smckusick 			sp = &mp->mnt_stat;
38640343Smckusick 			/*
38740343Smckusick 			 * If MNT_NOWAIT is specified, do not refresh the
38840343Smckusick 			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
38940343Smckusick 			 */
39040343Smckusick 			if (((uap->flags & MNT_NOWAIT) == 0 ||
39140343Smckusick 			    (uap->flags & MNT_WAIT)) &&
39240343Smckusick 			    (error = VFS_STATFS(mp, sp))) {
39341400Smckusick 				mp = mp->mnt_prev;
39439607Smckusick 				continue;
39539607Smckusick 			}
39641400Smckusick 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
39740343Smckusick 			if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
39839606Smckusick 				RETURN (error);
39940343Smckusick 			sfsp += sizeof(*sp);
40038270Smckusick 		}
40139606Smckusick 		count++;
40241400Smckusick 		mp = mp->mnt_prev;
40338270Smckusick 	} while (mp != rootfs);
40438270Smckusick 	if (sfsp && count > maxcount)
40538408Smckusick 		scp->sc_retval1 = maxcount;
40638270Smckusick 	else
40738408Smckusick 		scp->sc_retval1 = count;
40838270Smckusick 	RETURN (0);
40938270Smckusick }
41038270Smckusick 
41138270Smckusick /*
41238259Smckusick  * Change current working directory to a given file descriptor.
41338259Smckusick  */
41438408Smckusick fchdir(scp)
41538408Smckusick 	register struct syscontext *scp;
41638259Smckusick {
41738259Smckusick 	struct a {
41838259Smckusick 		int	fd;
41938408Smckusick 	} *uap = (struct a *)scp->sc_ap;
42038259Smckusick 	register struct vnode *vp;
42138259Smckusick 	struct file *fp;
42238259Smckusick 	int error;
42338259Smckusick 
42438408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
42538259Smckusick 		RETURN (error);
42638259Smckusick 	vp = (struct vnode *)fp->f_data;
42738259Smckusick 	VOP_LOCK(vp);
42838259Smckusick 	if (vp->v_type != VDIR)
42938259Smckusick 		error = ENOTDIR;
43038259Smckusick 	else
43138408Smckusick 		error = VOP_ACCESS(vp, VEXEC, scp->sc_cred);
43238259Smckusick 	VOP_UNLOCK(vp);
43339860Smckusick 	if (error)
43439860Smckusick 		RETURN (error);
43539860Smckusick 	VREF(vp);
43638408Smckusick 	vrele(scp->sc_cdir);
43738408Smckusick 	scp->sc_cdir = vp;
43839860Smckusick 	RETURN (0);
43938259Smckusick }
44038259Smckusick 
44138259Smckusick /*
44237741Smckusick  * Change current working directory (``.'').
44337741Smckusick  */
44438408Smckusick chdir(scp)
44538408Smckusick 	register struct syscontext *scp;
44637741Smckusick {
44737741Smckusick 	struct a {
4486254Sroot 		char	*fname;
44938408Smckusick 	} *uap = (struct a *)scp->sc_ap;
45038408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
45137741Smckusick 	int error;
4526254Sroot 
45337741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
45416694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
45516694Smckusick 	ndp->ni_dirp = uap->fname;
45637741Smckusick 	if (error = chdirec(ndp))
45737741Smckusick 		RETURN (error);
45838408Smckusick 	vrele(scp->sc_cdir);
45938408Smckusick 	scp->sc_cdir = ndp->ni_vp;
46037741Smckusick 	RETURN (0);
46137741Smckusick }
4626254Sroot 
46337741Smckusick /*
46437741Smckusick  * Change notion of root (``/'') directory.
46537741Smckusick  */
46638408Smckusick chroot(scp)
46738408Smckusick 	register struct syscontext *scp;
46837741Smckusick {
46937741Smckusick 	struct a {
47037741Smckusick 		char	*fname;
47138408Smckusick 	} *uap = (struct a *)scp->sc_ap;
47238408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
47337741Smckusick 	int error;
47437741Smckusick 
47538408Smckusick 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
47637741Smckusick 		RETURN (error);
47737741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
47837741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
47937741Smckusick 	ndp->ni_dirp = uap->fname;
48037741Smckusick 	if (error = chdirec(ndp))
48137741Smckusick 		RETURN (error);
48239515Smckusick 	if (scp->sc_rdir != NULL)
48339515Smckusick 		vrele(scp->sc_rdir);
48438408Smckusick 	scp->sc_rdir = ndp->ni_vp;
48537741Smckusick 	RETURN (0);
4866254Sroot }
4876254Sroot 
48837Sbill /*
48937741Smckusick  * Common routine for chroot and chdir.
49037741Smckusick  */
49137741Smckusick chdirec(ndp)
49237741Smckusick 	register struct nameidata *ndp;
49337741Smckusick {
49437741Smckusick 	struct vnode *vp;
49537741Smckusick 	int error;
49637741Smckusick 
49737741Smckusick 	if (error = namei(ndp))
49837741Smckusick 		return (error);
49937741Smckusick 	vp = ndp->ni_vp;
50037741Smckusick 	if (vp->v_type != VDIR)
50137741Smckusick 		error = ENOTDIR;
50237741Smckusick 	else
50338399Smckusick 		error = VOP_ACCESS(vp, VEXEC, ndp->ni_cred);
50437741Smckusick 	VOP_UNLOCK(vp);
50537741Smckusick 	if (error)
50637741Smckusick 		vrele(vp);
50737741Smckusick 	return (error);
50837741Smckusick }
50937741Smckusick 
51037741Smckusick /*
5116254Sroot  * Open system call.
5126254Sroot  */
51338408Smckusick open(scp)
51438408Smckusick 	register struct syscontext *scp;
5156254Sroot {
51612756Ssam 	struct a {
5176254Sroot 		char	*fname;
5187701Ssam 		int	mode;
51912756Ssam 		int	crtmode;
52038408Smckusick 	} *uap = (struct a *) scp->sc_ap;
52138408Smckusick 	struct nameidata *ndp = &scp->sc_nd;
5226254Sroot 
52337741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
52437741Smckusick 	ndp->ni_dirp = uap->fname;
52538408Smckusick 	RETURN (copen(scp, uap->mode-FOPEN, uap->crtmode &~ scp->sc_cmask, ndp,
52638408Smckusick 		&scp->sc_retval1));
5276254Sroot }
5286254Sroot 
5296254Sroot /*
5306254Sroot  * Creat system call.
5316254Sroot  */
53238408Smckusick creat(scp)
53338408Smckusick 	register struct syscontext *scp;
5346254Sroot {
53512756Ssam 	struct a {
5366254Sroot 		char	*fname;
5376254Sroot 		int	fmode;
53838408Smckusick 	} *uap = (struct a *)scp->sc_ap;
53938408Smckusick 	struct nameidata *ndp = &scp->sc_nd;
5406254Sroot 
54137741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
54237741Smckusick 	ndp->ni_dirp = uap->fname;
54338408Smckusick 	RETURN (copen(scp, FWRITE|FCREAT|FTRUNC, uap->fmode &~ scp->sc_cmask,
54438408Smckusick 		ndp, &scp->sc_retval1));
5456254Sroot }
5466254Sroot 
5476254Sroot /*
5486254Sroot  * Common code for open and creat.
54912756Ssam  * Check permissions, allocate an open file structure,
55012756Ssam  * and call the device open routine if any.
5516254Sroot  */
55238408Smckusick copen(scp, fmode, cmode, ndp, resultfd)
55338408Smckusick 	register struct syscontext *scp;
55437741Smckusick 	int fmode, cmode;
55537741Smckusick 	struct nameidata *ndp;
55637741Smckusick 	int *resultfd;
55712756Ssam {
5586254Sroot 	register struct file *fp;
55937741Smckusick 	struct file *nfp;
56037741Smckusick 	int indx, error;
56137741Smckusick 	extern struct fileops vnops;
5626254Sroot 
56337741Smckusick 	if (error = falloc(&nfp, &indx))
56437741Smckusick 		return (error);
56537741Smckusick 	fp = nfp;
56638408Smckusick 	scp->sc_retval1 = indx;	/* XXX for fdopen() */
56740635Smckusick 	if (error = vn_open(ndp, fmode, (cmode & 07777) &~ S_ISVTX)) {
56837741Smckusick 		crfree(fp->f_cred);
56937741Smckusick 		fp->f_count--;
57040884Smckusick 		if (error == EJUSTRETURN)	/* XXX from fdopen */
57140884Smckusick 			return (0);		/* XXX from fdopen */
57240884Smckusick 		if (error == ERESTART)
57340884Smckusick 			error = EINTR;
57439499Smckusick 		scp->sc_ofile[indx] = NULL;
57537741Smckusick 		return (error);
57612756Ssam 	}
57737741Smckusick 	fp->f_flag = fmode & FMASK;
57837741Smckusick 	fp->f_type = DTYPE_VNODE;
57937741Smckusick 	fp->f_ops = &vnops;
58037741Smckusick 	fp->f_data = (caddr_t)ndp->ni_vp;
58137741Smckusick 	if (resultfd)
58237741Smckusick 		*resultfd = indx;
58337741Smckusick 	return (0);
5846254Sroot }
5856254Sroot 
5866254Sroot /*
5876254Sroot  * Mknod system call
5886254Sroot  */
58938408Smckusick mknod(scp)
59038408Smckusick 	register struct syscontext *scp;
5916254Sroot {
5926254Sroot 	register struct a {
5936254Sroot 		char	*fname;
5946254Sroot 		int	fmode;
5956254Sroot 		int	dev;
59638408Smckusick 	} *uap = (struct a *)scp->sc_ap;
59738408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
59837741Smckusick 	register struct vnode *vp;
59937741Smckusick 	struct vattr vattr;
60037741Smckusick 	int error;
6016254Sroot 
60238408Smckusick 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
60337741Smckusick 		RETURN (error);
60437741Smckusick 	ndp->ni_nameiop = CREATE | LOCKPARENT;
60516694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
60616694Smckusick 	ndp->ni_dirp = uap->fname;
60737741Smckusick 	if (error = namei(ndp))
60837741Smckusick 		RETURN (error);
60937741Smckusick 	vp = ndp->ni_vp;
61037741Smckusick 	if (vp != NULL) {
61137741Smckusick 		error = EEXIST;
61212756Ssam 		goto out;
6136254Sroot 	}
61441362Smckusick 	VATTR_NULL(&vattr);
61540635Smckusick 	switch (uap->fmode & S_IFMT) {
61612756Ssam 
61740635Smckusick 	case S_IFMT:	/* used by badsect to flag bad sectors */
61837741Smckusick 		vattr.va_type = VBAD;
61937741Smckusick 		break;
62040635Smckusick 	case S_IFCHR:
62137741Smckusick 		vattr.va_type = VCHR;
62237741Smckusick 		break;
62340635Smckusick 	case S_IFBLK:
62437741Smckusick 		vattr.va_type = VBLK;
62537741Smckusick 		break;
62637741Smckusick 	default:
62737741Smckusick 		error = EINVAL;
62837741Smckusick 		goto out;
6296254Sroot 	}
63038408Smckusick 	vattr.va_mode = (uap->fmode & 07777) &~ scp->sc_cmask;
63137741Smckusick 	vattr.va_rdev = uap->dev;
6326254Sroot out:
63337741Smckusick 	if (error)
63437741Smckusick 		VOP_ABORTOP(ndp);
63537741Smckusick 	else
63637741Smckusick 		error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred);
63737741Smckusick 	RETURN (error);
6386254Sroot }
6396254Sroot 
6406254Sroot /*
64140285Smckusick  * Mkfifo system call
64240285Smckusick  */
64340285Smckusick mkfifo(scp)
64440285Smckusick 	register struct syscontext *scp;
64540285Smckusick {
64640285Smckusick 	register struct a {
64740285Smckusick 		char	*fname;
64840285Smckusick 		int	fmode;
64940285Smckusick 	} *uap = (struct a *)scp->sc_ap;
65040285Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
65140285Smckusick 	struct vattr vattr;
65240285Smckusick 	int error;
65340285Smckusick 
65440285Smckusick #ifndef FIFO
65540285Smckusick 	RETURN (EOPNOTSUPP);
65640285Smckusick #else
65740285Smckusick 	ndp->ni_nameiop = CREATE | LOCKPARENT;
65840285Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
65940285Smckusick 	ndp->ni_dirp = uap->fname;
66040285Smckusick 	if (error = namei(ndp))
66140285Smckusick 		RETURN (error);
66240285Smckusick 	if (ndp->ni_vp != NULL) {
66340285Smckusick 		VOP_ABORTOP(ndp);
66440285Smckusick 		RETURN (EEXIST);
66540285Smckusick 	} else {
66641362Smckusick 		VATTR_NULL(&vattr);
66740285Smckusick 		vattr.va_type = VFIFO;
66840285Smckusick 		vattr.va_mode = (uap->fmode & 07777) &~ scp->sc_cmask;
66940285Smckusick 	}
67040285Smckusick 	RETURN (VOP_MKNOD(ndp, &vattr, ndp->ni_cred));
67140285Smckusick #endif /* FIFO */
67240285Smckusick }
67340285Smckusick 
67440285Smckusick /*
6756254Sroot  * link system call
6766254Sroot  */
67738408Smckusick link(scp)
67838408Smckusick 	register struct syscontext *scp;
6796254Sroot {
6806254Sroot 	register struct a {
6816254Sroot 		char	*target;
6826254Sroot 		char	*linkname;
68338408Smckusick 	} *uap = (struct a *)scp->sc_ap;
68438408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
68537741Smckusick 	register struct vnode *vp, *xp;
68637741Smckusick 	int error;
6876254Sroot 
68816694Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW;
68916694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
69016694Smckusick 	ndp->ni_dirp = uap->target;
69137741Smckusick 	if (error = namei(ndp))
69237741Smckusick 		RETURN (error);
69337741Smckusick 	vp = ndp->ni_vp;
69437741Smckusick 	if (vp->v_type == VDIR &&
69538408Smckusick 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
69637741Smckusick 		goto out1;
69737741Smckusick 	ndp->ni_nameiop = CREATE | LOCKPARENT;
69816694Smckusick 	ndp->ni_dirp = (caddr_t)uap->linkname;
69937741Smckusick 	if (error = namei(ndp))
70037741Smckusick 		goto out1;
70137741Smckusick 	xp = ndp->ni_vp;
7026254Sroot 	if (xp != NULL) {
70337741Smckusick 		error = EEXIST;
7046254Sroot 		goto out;
7056254Sroot 	}
70637741Smckusick 	xp = ndp->ni_dvp;
70737741Smckusick 	if (vp->v_mount != xp->v_mount)
70837741Smckusick 		error = EXDEV;
7096254Sroot out:
71037741Smckusick 	if (error)
71137741Smckusick 		VOP_ABORTOP(ndp);
71237741Smckusick 	else
71337741Smckusick 		error = VOP_LINK(vp, ndp);
71437741Smckusick out1:
71537741Smckusick 	vrele(vp);
71637741Smckusick 	RETURN (error);
7176254Sroot }
7186254Sroot 
7196254Sroot /*
7206254Sroot  * symlink -- make a symbolic link
7216254Sroot  */
72238408Smckusick symlink(scp)
72338408Smckusick 	register struct syscontext *scp;
7246254Sroot {
72537741Smckusick 	struct a {
7266254Sroot 		char	*target;
7276254Sroot 		char	*linkname;
72838408Smckusick 	} *uap = (struct a *)scp->sc_ap;
72938408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
73037741Smckusick 	register struct vnode *vp;
73137741Smckusick 	struct vattr vattr;
73237741Smckusick 	char *target;
73337741Smckusick 	int error;
7346254Sroot 
73516694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
73616694Smckusick 	ndp->ni_dirp = uap->linkname;
73737741Smckusick 	MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
73837741Smckusick 	if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
73937741Smckusick 		goto out1;
74037741Smckusick 	ndp->ni_nameiop = CREATE | LOCKPARENT;
74137741Smckusick 	if (error = namei(ndp))
74237741Smckusick 		goto out1;
74337741Smckusick 	vp = ndp->ni_vp;
74437741Smckusick 	if (vp) {
74537741Smckusick 		error = EEXIST;
74637741Smckusick 		goto out;
7476254Sroot 	}
74837741Smckusick 	vp = ndp->ni_dvp;
74941362Smckusick 	VATTR_NULL(&vattr);
75038408Smckusick 	vattr.va_mode = 0777 &~ scp->sc_cmask;
75137741Smckusick out:
75237741Smckusick 	if (error)
75337741Smckusick 		VOP_ABORTOP(ndp);
75437741Smckusick 	else
75537741Smckusick 		error = VOP_SYMLINK(ndp, &vattr, target);
75637741Smckusick out1:
75737741Smckusick 	FREE(target, M_NAMEI);
75837741Smckusick 	RETURN (error);
7596254Sroot }
7606254Sroot 
7616254Sroot /*
7626254Sroot  * Unlink system call.
7636254Sroot  * Hard to avoid races here, especially
7646254Sroot  * in unlinking directories.
7656254Sroot  */
76638408Smckusick unlink(scp)
76738408Smckusick 	register struct syscontext *scp;
7686254Sroot {
7696254Sroot 	struct a {
7706254Sroot 		char	*fname;
77138408Smckusick 	} *uap = (struct a *)scp->sc_ap;
77238408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
77337741Smckusick 	register struct vnode *vp;
77437741Smckusick 	int error;
7756254Sroot 
77637741Smckusick 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
77716694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
77816694Smckusick 	ndp->ni_dirp = uap->fname;
77937741Smckusick 	if (error = namei(ndp))
78037741Smckusick 		RETURN (error);
78137741Smckusick 	vp = ndp->ni_vp;
78237741Smckusick 	if (vp->v_type == VDIR &&
78338408Smckusick 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
7846254Sroot 		goto out;
7856254Sroot 	/*
7866254Sroot 	 * Don't unlink a mounted file.
7876254Sroot 	 */
78837741Smckusick 	if (vp->v_flag & VROOT) {
78937741Smckusick 		error = EBUSY;
7906254Sroot 		goto out;
7916254Sroot 	}
79237741Smckusick 	if (vp->v_flag & VTEXT)
79337741Smckusick 		xrele(vp);	/* try once to free text */
7946254Sroot out:
79537741Smckusick 	if (error)
79637741Smckusick 		VOP_ABORTOP(ndp);
7977142Smckusick 	else
79837741Smckusick 		error = VOP_REMOVE(ndp);
79937741Smckusick 	RETURN (error);
8006254Sroot }
8016254Sroot 
8026254Sroot /*
8036254Sroot  * Seek system call
8046254Sroot  */
80538408Smckusick lseek(scp)
80638408Smckusick 	register struct syscontext *scp;
8076254Sroot {
8086254Sroot 	register struct file *fp;
8096254Sroot 	register struct a {
81037741Smckusick 		int	fdes;
8116254Sroot 		off_t	off;
8126254Sroot 		int	sbase;
81338408Smckusick 	} *uap = (struct a *)scp->sc_ap;
81437741Smckusick 	struct vattr vattr;
81537741Smckusick 	int error;
8166254Sroot 
81737741Smckusick 	if ((unsigned)uap->fdes >= NOFILE ||
81838408Smckusick 	    (fp = scp->sc_ofile[uap->fdes]) == NULL)
81937741Smckusick 		RETURN (EBADF);
82037741Smckusick 	if (fp->f_type != DTYPE_VNODE)
82137741Smckusick 		RETURN (ESPIPE);
82213878Ssam 	switch (uap->sbase) {
82313878Ssam 
82413878Ssam 	case L_INCR:
82513878Ssam 		fp->f_offset += uap->off;
82613878Ssam 		break;
82713878Ssam 
82813878Ssam 	case L_XTND:
82937741Smckusick 		if (error = VOP_GETATTR((struct vnode *)fp->f_data,
83038408Smckusick 		    &vattr, scp->sc_cred))
83137741Smckusick 			RETURN (error);
83237741Smckusick 		fp->f_offset = uap->off + vattr.va_size;
83313878Ssam 		break;
83413878Ssam 
83513878Ssam 	case L_SET:
83613878Ssam 		fp->f_offset = uap->off;
83713878Ssam 		break;
83813878Ssam 
83913878Ssam 	default:
84037741Smckusick 		RETURN (EINVAL);
84113878Ssam 	}
84238408Smckusick 	scp->sc_offset = fp->f_offset;
84337741Smckusick 	RETURN (0);
8446254Sroot }
8456254Sroot 
8466254Sroot /*
8476254Sroot  * Access system call
8486254Sroot  */
84938408Smckusick saccess(scp)
85038408Smckusick 	register struct syscontext *scp;
8516254Sroot {
8526254Sroot 	register struct a {
8536254Sroot 		char	*fname;
8546254Sroot 		int	fmode;
85538408Smckusick 	} *uap = (struct a *)scp->sc_ap;
85638408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
85737741Smckusick 	register struct vnode *vp;
85837741Smckusick 	int error, mode, svuid, svgid;
8596254Sroot 
86038408Smckusick 	svuid = scp->sc_uid;
86138408Smckusick 	svgid = scp->sc_gid;
86238408Smckusick 	scp->sc_uid = scp->sc_ruid;
86338408Smckusick 	scp->sc_gid = scp->sc_rgid;
86437741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
86516694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
86616694Smckusick 	ndp->ni_dirp = uap->fname;
86737741Smckusick 	if (error = namei(ndp))
86837741Smckusick 		goto out1;
86937741Smckusick 	vp = ndp->ni_vp;
87037741Smckusick 	/*
87137741Smckusick 	 * fmode == 0 means only check for exist
87237741Smckusick 	 */
87337741Smckusick 	if (uap->fmode) {
87437741Smckusick 		mode = 0;
87537741Smckusick 		if (uap->fmode & R_OK)
87637741Smckusick 			mode |= VREAD;
87737741Smckusick 		if (uap->fmode & W_OK)
87837741Smckusick 			mode |= VWRITE;
87937741Smckusick 		if (uap->fmode & X_OK)
88037741Smckusick 			mode |= VEXEC;
88139543Smckusick 		if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
88238399Smckusick 			error = VOP_ACCESS(vp, mode, ndp->ni_cred);
8836254Sroot 	}
88437741Smckusick 	vput(vp);
88537741Smckusick out1:
88638408Smckusick 	scp->sc_uid = svuid;
88738408Smckusick 	scp->sc_gid = svgid;
88837741Smckusick 	RETURN (error);
8896254Sroot }
8906254Sroot 
8916254Sroot /*
8926574Smckusic  * Stat system call.  This version follows links.
89337Sbill  */
89438408Smckusick stat(scp)
89538408Smckusick 	struct syscontext *scp;
89637Sbill {
89737Sbill 
89838408Smckusick 	stat1(scp, FOLLOW);
89937Sbill }
90037Sbill 
90137Sbill /*
9026574Smckusic  * Lstat system call.  This version does not follow links.
9035992Swnj  */
90438408Smckusick lstat(scp)
90538408Smckusick 	struct syscontext *scp;
9065992Swnj {
90712756Ssam 
90838408Smckusick 	stat1(scp, NOFOLLOW);
90912756Ssam }
91012756Ssam 
91138408Smckusick stat1(scp, follow)
91238408Smckusick 	register struct syscontext *scp;
91312756Ssam 	int follow;
91412756Ssam {
9155992Swnj 	register struct a {
9165992Swnj 		char	*fname;
91712756Ssam 		struct stat *ub;
91838408Smckusick 	} *uap = (struct a *)scp->sc_ap;
91938408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
92012756Ssam 	struct stat sb;
92137741Smckusick 	int error;
9225992Swnj 
92337741Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow;
92416694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
92516694Smckusick 	ndp->ni_dirp = uap->fname;
92637741Smckusick 	if (error = namei(ndp))
92737741Smckusick 		RETURN (error);
92837741Smckusick 	error = vn_stat(ndp->ni_vp, &sb);
92937741Smckusick 	vput(ndp->ni_vp);
93037741Smckusick 	if (error)
93137741Smckusick 		RETURN (error);
93237741Smckusick 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
93337741Smckusick 	RETURN (error);
9345992Swnj }
9355992Swnj 
9365992Swnj /*
9375992Swnj  * Return target name of a symbolic link
93837Sbill  */
93938408Smckusick readlink(scp)
94038408Smckusick 	register struct syscontext *scp;
9415992Swnj {
9425992Swnj 	register struct a {
9435992Swnj 		char	*name;
9445992Swnj 		char	*buf;
9455992Swnj 		int	count;
94638408Smckusick 	} *uap = (struct a *)scp->sc_ap;
94738408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
94837741Smckusick 	register struct vnode *vp;
94937741Smckusick 	struct iovec aiov;
95037741Smckusick 	struct uio auio;
95137741Smckusick 	int error;
9525992Swnj 
95337741Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF;
95416694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
95516694Smckusick 	ndp->ni_dirp = uap->name;
95637741Smckusick 	if (error = namei(ndp))
95737741Smckusick 		RETURN (error);
95837741Smckusick 	vp = ndp->ni_vp;
95937741Smckusick 	if (vp->v_type != VLNK) {
96037741Smckusick 		error = EINVAL;
9615992Swnj 		goto out;
9625992Swnj 	}
96337741Smckusick 	aiov.iov_base = uap->buf;
96437741Smckusick 	aiov.iov_len = uap->count;
96537741Smckusick 	auio.uio_iov = &aiov;
96637741Smckusick 	auio.uio_iovcnt = 1;
96737741Smckusick 	auio.uio_offset = 0;
96837741Smckusick 	auio.uio_rw = UIO_READ;
96937741Smckusick 	auio.uio_segflg = UIO_USERSPACE;
97037741Smckusick 	auio.uio_resid = uap->count;
97137741Smckusick 	error = VOP_READLINK(vp, &auio, ndp->ni_cred);
9725992Swnj out:
97337741Smckusick 	vput(vp);
97438408Smckusick 	scp->sc_retval1 = uap->count - auio.uio_resid;
97537741Smckusick 	RETURN (error);
9765992Swnj }
9775992Swnj 
9789167Ssam /*
97938259Smckusick  * Change flags of a file given path name.
98038259Smckusick  */
98138408Smckusick chflags(scp)
98238408Smckusick 	register struct syscontext *scp;
98338259Smckusick {
98438259Smckusick 	struct a {
98538259Smckusick 		char	*fname;
98638259Smckusick 		int	flags;
98738408Smckusick 	} *uap = (struct a *)scp->sc_ap;
98838408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
98938259Smckusick 	register struct vnode *vp;
99038259Smckusick 	struct vattr vattr;
99138259Smckusick 	int error;
99238259Smckusick 
99338259Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
99438259Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
99538259Smckusick 	ndp->ni_dirp = uap->fname;
99641362Smckusick 	VATTR_NULL(&vattr);
99738259Smckusick 	vattr.va_flags = uap->flags;
99838259Smckusick 	if (error = namei(ndp))
99938259Smckusick 		RETURN (error);
100038259Smckusick 	vp = ndp->ni_vp;
100141400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
100238259Smckusick 		error = EROFS;
100338259Smckusick 		goto out;
100438259Smckusick 	}
100538259Smckusick 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
100638259Smckusick out:
100738259Smckusick 	vput(vp);
100838259Smckusick 	RETURN (error);
100938259Smckusick }
101038259Smckusick 
101138259Smckusick /*
101238259Smckusick  * Change flags of a file given a file descriptor.
101338259Smckusick  */
101438408Smckusick fchflags(scp)
101538408Smckusick 	register struct syscontext *scp;
101638259Smckusick {
101738259Smckusick 	struct a {
101838259Smckusick 		int	fd;
101938259Smckusick 		int	flags;
102038408Smckusick 	} *uap = (struct a *)scp->sc_ap;
102138259Smckusick 	struct vattr vattr;
102238259Smckusick 	struct vnode *vp;
102338259Smckusick 	struct file *fp;
102438259Smckusick 	int error;
102538259Smckusick 
102638408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
102738259Smckusick 		RETURN (error);
102841362Smckusick 	VATTR_NULL(&vattr);
102938259Smckusick 	vattr.va_flags = uap->flags;
103038259Smckusick 	vp = (struct vnode *)fp->f_data;
103138259Smckusick 	VOP_LOCK(vp);
103241400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
103338259Smckusick 		error = EROFS;
103438259Smckusick 		goto out;
103538259Smckusick 	}
103638259Smckusick 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
103738259Smckusick out:
103838259Smckusick 	VOP_UNLOCK(vp);
103938259Smckusick 	RETURN (error);
104038259Smckusick }
104138259Smckusick 
104238259Smckusick /*
10439167Ssam  * Change mode of a file given path name.
10449167Ssam  */
104538408Smckusick chmod(scp)
104638408Smckusick 	register struct syscontext *scp;
10475992Swnj {
10487701Ssam 	struct a {
10496254Sroot 		char	*fname;
10506254Sroot 		int	fmode;
105138408Smckusick 	} *uap = (struct a *)scp->sc_ap;
105238408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
105337741Smckusick 	register struct vnode *vp;
105437741Smckusick 	struct vattr vattr;
105537741Smckusick 	int error;
10565992Swnj 
105737741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
105837741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
105937741Smckusick 	ndp->ni_dirp = uap->fname;
106041362Smckusick 	VATTR_NULL(&vattr);
106137741Smckusick 	vattr.va_mode = uap->fmode & 07777;
106237741Smckusick 	if (error = namei(ndp))
106337741Smckusick 		RETURN (error);
106437741Smckusick 	vp = ndp->ni_vp;
106541400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
106637741Smckusick 		error = EROFS;
106737741Smckusick 		goto out;
106837741Smckusick 	}
106937741Smckusick 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
107037741Smckusick out:
107137741Smckusick 	vput(vp);
107237741Smckusick 	RETURN (error);
10737701Ssam }
10747439Sroot 
10759167Ssam /*
10769167Ssam  * Change mode of a file given a file descriptor.
10779167Ssam  */
107838408Smckusick fchmod(scp)
107938408Smckusick 	register struct syscontext *scp;
10807701Ssam {
10817701Ssam 	struct a {
10827701Ssam 		int	fd;
10837701Ssam 		int	fmode;
108438408Smckusick 	} *uap = (struct a *)scp->sc_ap;
108537741Smckusick 	struct vattr vattr;
108637741Smckusick 	struct vnode *vp;
108737741Smckusick 	struct file *fp;
108837741Smckusick 	int error;
10897701Ssam 
109038408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
109137741Smckusick 		RETURN (error);
109241362Smckusick 	VATTR_NULL(&vattr);
109337741Smckusick 	vattr.va_mode = uap->fmode & 07777;
109437741Smckusick 	vp = (struct vnode *)fp->f_data;
109537741Smckusick 	VOP_LOCK(vp);
109641400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
109737741Smckusick 		error = EROFS;
109837741Smckusick 		goto out;
10997439Sroot 	}
110037741Smckusick 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
110137741Smckusick out:
110237741Smckusick 	VOP_UNLOCK(vp);
110337741Smckusick 	RETURN (error);
11045992Swnj }
11055992Swnj 
11069167Ssam /*
11079167Ssam  * Set ownership given a path name.
11089167Ssam  */
110938408Smckusick chown(scp)
111038408Smckusick 	register struct syscontext *scp;
111137Sbill {
11127701Ssam 	struct a {
11136254Sroot 		char	*fname;
11146254Sroot 		int	uid;
11156254Sroot 		int	gid;
111638408Smckusick 	} *uap = (struct a *)scp->sc_ap;
111738408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
111837741Smckusick 	register struct vnode *vp;
111937741Smckusick 	struct vattr vattr;
112037741Smckusick 	int error;
112137Sbill 
112237741Smckusick 	ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF;
112336614Sbostic 	ndp->ni_segflg = UIO_USERSPACE;
112436614Sbostic 	ndp->ni_dirp = uap->fname;
112541362Smckusick 	VATTR_NULL(&vattr);
112637741Smckusick 	vattr.va_uid = uap->uid;
112737741Smckusick 	vattr.va_gid = uap->gid;
112837741Smckusick 	if (error = namei(ndp))
112937741Smckusick 		RETURN (error);
113037741Smckusick 	vp = ndp->ni_vp;
113141400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
113237741Smckusick 		error = EROFS;
113337741Smckusick 		goto out;
113437741Smckusick 	}
113537741Smckusick 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
113637741Smckusick out:
113737741Smckusick 	vput(vp);
113837741Smckusick 	RETURN (error);
11397701Ssam }
11407439Sroot 
11419167Ssam /*
11429167Ssam  * Set ownership given a file descriptor.
11439167Ssam  */
114438408Smckusick fchown(scp)
114538408Smckusick 	register struct syscontext *scp;
11467701Ssam {
11477701Ssam 	struct a {
11487701Ssam 		int	fd;
11497701Ssam 		int	uid;
11507701Ssam 		int	gid;
115138408Smckusick 	} *uap = (struct a *)scp->sc_ap;
115237741Smckusick 	struct vattr vattr;
115337741Smckusick 	struct vnode *vp;
115437741Smckusick 	struct file *fp;
115537741Smckusick 	int error;
11567701Ssam 
115738408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
115837741Smckusick 		RETURN (error);
115941362Smckusick 	VATTR_NULL(&vattr);
116037741Smckusick 	vattr.va_uid = uap->uid;
116137741Smckusick 	vattr.va_gid = uap->gid;
116237741Smckusick 	vp = (struct vnode *)fp->f_data;
116337741Smckusick 	VOP_LOCK(vp);
116441400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
116537741Smckusick 		error = EROFS;
116637741Smckusick 		goto out;
116737741Smckusick 	}
116837741Smckusick 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
116937741Smckusick out:
117037741Smckusick 	VOP_UNLOCK(vp);
117137741Smckusick 	RETURN (error);
11727701Ssam }
11737701Ssam 
117438408Smckusick utimes(scp)
117538408Smckusick 	register struct syscontext *scp;
117611811Ssam {
117711811Ssam 	register struct a {
117811811Ssam 		char	*fname;
117911811Ssam 		struct	timeval *tptr;
118038408Smckusick 	} *uap = (struct a *)scp->sc_ap;
118138408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
118237741Smckusick 	register struct vnode *vp;
118311811Ssam 	struct timeval tv[2];
118437741Smckusick 	struct vattr vattr;
118537741Smckusick 	int error;
118611811Ssam 
118737741Smckusick 	if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
118837741Smckusick 		RETURN (error);
118937741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
119037741Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
119137741Smckusick 	ndp->ni_dirp = uap->fname;
119241362Smckusick 	VATTR_NULL(&vattr);
119337741Smckusick 	vattr.va_atime = tv[0];
119437741Smckusick 	vattr.va_mtime = tv[1];
119537741Smckusick 	if (error = namei(ndp))
119637741Smckusick 		RETURN (error);
119737741Smckusick 	vp = ndp->ni_vp;
119841400Smckusick 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
119937741Smckusick 		error = EROFS;
120037741Smckusick 		goto out;
120121015Smckusick 	}
120237741Smckusick 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
120337741Smckusick out:
120437741Smckusick 	vput(vp);
120537741Smckusick 	RETURN (error);
120611811Ssam }
120711811Ssam 
12089167Ssam /*
12099167Ssam  * Truncate a file given its path name.
12109167Ssam  */
121138408Smckusick truncate(scp)
121238408Smckusick 	register struct syscontext *scp;
12137701Ssam {
12147701Ssam 	struct a {
12157701Ssam 		char	*fname;
121626473Skarels 		off_t	length;
121738408Smckusick 	} *uap = (struct a *)scp->sc_ap;
121838408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
121937741Smckusick 	register struct vnode *vp;
122037741Smckusick 	struct vattr vattr;
122137741Smckusick 	int error;
12227701Ssam 
122337741Smckusick 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
122416694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
122516694Smckusick 	ndp->ni_dirp = uap->fname;
122641362Smckusick 	VATTR_NULL(&vattr);
122737741Smckusick 	vattr.va_size = uap->length;
122837741Smckusick 	if (error = namei(ndp))
122937741Smckusick 		RETURN (error);
123037741Smckusick 	vp = ndp->ni_vp;
123137741Smckusick 	if (vp->v_type == VDIR) {
123237741Smckusick 		error = EISDIR;
123337741Smckusick 		goto out;
12347701Ssam 	}
123538399Smckusick 	if ((error = vn_writechk(vp)) ||
123638399Smckusick 	    (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
123737741Smckusick 		goto out;
123837741Smckusick 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
123937741Smckusick out:
124037741Smckusick 	vput(vp);
124137741Smckusick 	RETURN (error);
12427701Ssam }
12437701Ssam 
12449167Ssam /*
12459167Ssam  * Truncate a file given a file descriptor.
12469167Ssam  */
124738408Smckusick ftruncate(scp)
124838408Smckusick 	register struct syscontext *scp;
12497701Ssam {
12507701Ssam 	struct a {
12517701Ssam 		int	fd;
125226473Skarels 		off_t	length;
125338408Smckusick 	} *uap = (struct a *)scp->sc_ap;
125437741Smckusick 	struct vattr vattr;
125537741Smckusick 	struct vnode *vp;
12567701Ssam 	struct file *fp;
125737741Smckusick 	int error;
12587701Ssam 
125938408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
126037741Smckusick 		RETURN (error);
126137741Smckusick 	if ((fp->f_flag & FWRITE) == 0)
126237741Smckusick 		RETURN (EINVAL);
126341362Smckusick 	VATTR_NULL(&vattr);
126437741Smckusick 	vattr.va_size = uap->length;
126537741Smckusick 	vp = (struct vnode *)fp->f_data;
126637741Smckusick 	VOP_LOCK(vp);
126737741Smckusick 	if (vp->v_type == VDIR) {
126837741Smckusick 		error = EISDIR;
126937741Smckusick 		goto out;
12707701Ssam 	}
127138399Smckusick 	if (error = vn_writechk(vp))
127237741Smckusick 		goto out;
127337741Smckusick 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
127437741Smckusick out:
127537741Smckusick 	VOP_UNLOCK(vp);
127637741Smckusick 	RETURN (error);
12777701Ssam }
12787701Ssam 
12799167Ssam /*
12809167Ssam  * Synch an open file.
12819167Ssam  */
128238408Smckusick fsync(scp)
128338408Smckusick 	register struct syscontext *scp;
12849167Ssam {
12859167Ssam 	struct a {
12869167Ssam 		int	fd;
128738408Smckusick 	} *uap = (struct a *)scp->sc_ap;
128839592Smckusick 	register struct vnode *vp;
12899167Ssam 	struct file *fp;
129037741Smckusick 	int error;
12919167Ssam 
129238408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
129337741Smckusick 		RETURN (error);
129439592Smckusick 	vp = (struct vnode *)fp->f_data;
129539592Smckusick 	VOP_LOCK(vp);
129639592Smckusick 	error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT);
129739592Smckusick 	VOP_UNLOCK(vp);
129837741Smckusick 	RETURN (error);
12999167Ssam }
13009167Ssam 
13019167Ssam /*
13029167Ssam  * Rename system call.
13039167Ssam  *
13049167Ssam  * Source and destination must either both be directories, or both
13059167Ssam  * not be directories.  If target is a directory, it must be empty.
13069167Ssam  */
130738408Smckusick rename(scp)
130838408Smckusick 	register struct syscontext *scp;
13097701Ssam {
13107701Ssam 	struct a {
13117701Ssam 		char	*from;
13127701Ssam 		char	*to;
131338408Smckusick 	} *uap = (struct a *)scp->sc_ap;
131437741Smckusick 	register struct vnode *tvp, *fvp, *tdvp;
131538408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
131637741Smckusick 	struct nameidata tond;
131737741Smckusick 	int error;
13187701Ssam 
131937741Smckusick 	ndp->ni_nameiop = DELETE | WANTPARENT;
132016694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
132116694Smckusick 	ndp->ni_dirp = uap->from;
132237741Smckusick 	if (error = namei(ndp))
132337741Smckusick 		RETURN (error);
132437741Smckusick 	fvp = ndp->ni_vp;
132538266Smckusick 	nddup(ndp, &tond);
132637741Smckusick 	tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
132737741Smckusick 	tond.ni_segflg = UIO_USERSPACE;
132837741Smckusick 	tond.ni_dirp = uap->to;
132937741Smckusick 	error = namei(&tond);
133037741Smckusick 	tdvp = tond.ni_dvp;
133137741Smckusick 	tvp = tond.ni_vp;
133237741Smckusick 	if (tvp != NULL) {
133337741Smckusick 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
133439242Sbostic 			error = ENOTDIR;
133537741Smckusick 			goto out;
133637741Smckusick 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
133739242Sbostic 			error = EISDIR;
133837741Smckusick 			goto out;
13399167Ssam 		}
13409167Ssam 	}
134137741Smckusick 	if (error) {
134237741Smckusick 		VOP_ABORTOP(ndp);
134337741Smckusick 		goto out1;
134437741Smckusick 	}
134537741Smckusick 	if (fvp->v_mount != tdvp->v_mount) {
134637741Smckusick 		error = EXDEV;
13479167Ssam 		goto out;
134810051Ssam 	}
134939286Smckusick 	if (fvp == tdvp)
135037741Smckusick 		error = EINVAL;
135139286Smckusick 	/*
135239286Smckusick 	 * If source is the same as the destination,
135339286Smckusick 	 * then there is nothing to do.
135439286Smckusick 	 */
135539286Smckusick 	if (fvp == tvp)
135639286Smckusick 		error = -1;
135737741Smckusick out:
135837741Smckusick 	if (error) {
135937741Smckusick 		VOP_ABORTOP(&tond);
136037741Smckusick 		VOP_ABORTOP(ndp);
13619167Ssam 	} else {
136237741Smckusick 		error = VOP_RENAME(ndp, &tond);
13639167Ssam 	}
136437741Smckusick out1:
136538266Smckusick 	ndrele(&tond);
136639286Smckusick 	if (error == -1)
136739286Smckusick 		RETURN (0);
136837741Smckusick 	RETURN (error);
13697701Ssam }
13707701Ssam 
13717535Sroot /*
137212756Ssam  * Mkdir system call
137312756Ssam  */
137438408Smckusick mkdir(scp)
137538408Smckusick 	register struct syscontext *scp;
137612756Ssam {
137712756Ssam 	struct a {
137812756Ssam 		char	*name;
137912756Ssam 		int	dmode;
138038408Smckusick 	} *uap = (struct a *)scp->sc_ap;
138138408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
138237741Smckusick 	register struct vnode *vp;
138337741Smckusick 	struct vattr vattr;
138437741Smckusick 	int error;
138512756Ssam 
138637741Smckusick 	ndp->ni_nameiop = CREATE | LOCKPARENT;
138716694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
138816694Smckusick 	ndp->ni_dirp = uap->name;
138937741Smckusick 	if (error = namei(ndp))
139037741Smckusick 		RETURN (error);
139137741Smckusick 	vp = ndp->ni_vp;
139237741Smckusick 	if (vp != NULL) {
139337741Smckusick 		VOP_ABORTOP(ndp);
139437741Smckusick 		RETURN (EEXIST);
139512756Ssam 	}
139641362Smckusick 	VATTR_NULL(&vattr);
139737741Smckusick 	vattr.va_type = VDIR;
139838408Smckusick 	vattr.va_mode = (uap->dmode & 0777) &~ scp->sc_cmask;
139937741Smckusick 	error = VOP_MKDIR(ndp, &vattr);
140038145Smckusick 	if (!error)
140138145Smckusick 		vput(ndp->ni_vp);
140237741Smckusick 	RETURN (error);
140312756Ssam }
140412756Ssam 
140512756Ssam /*
140612756Ssam  * Rmdir system call.
140712756Ssam  */
140838408Smckusick rmdir(scp)
140938408Smckusick 	register struct syscontext *scp;
141012756Ssam {
141112756Ssam 	struct a {
141212756Ssam 		char	*name;
141338408Smckusick 	} *uap = (struct a *)scp->sc_ap;
141438408Smckusick 	register struct nameidata *ndp = &scp->sc_nd;
141537741Smckusick 	register struct vnode *vp;
141637741Smckusick 	int error;
141712756Ssam 
141837741Smckusick 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
141916694Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
142016694Smckusick 	ndp->ni_dirp = uap->name;
142137741Smckusick 	if (error = namei(ndp))
142237741Smckusick 		RETURN (error);
142337741Smckusick 	vp = ndp->ni_vp;
142437741Smckusick 	if (vp->v_type != VDIR) {
142537741Smckusick 		error = ENOTDIR;
142612756Ssam 		goto out;
142712756Ssam 	}
142812756Ssam 	/*
142937741Smckusick 	 * No rmdir "." please.
143012756Ssam 	 */
143137741Smckusick 	if (ndp->ni_dvp == vp) {
143237741Smckusick 		error = EINVAL;
143312756Ssam 		goto out;
143412756Ssam 	}
143512756Ssam 	/*
143637741Smckusick 	 * Don't unlink a mounted file.
143712756Ssam 	 */
143837741Smckusick 	if (vp->v_flag & VROOT)
143937741Smckusick 		error = EBUSY;
144012756Ssam out:
144137741Smckusick 	if (error)
144237741Smckusick 		VOP_ABORTOP(ndp);
144337741Smckusick 	else
144437741Smckusick 		error = VOP_RMDIR(ndp);
144537741Smckusick 	RETURN (error);
144612756Ssam }
144712756Ssam 
144837741Smckusick /*
144937741Smckusick  * Read a block of directory entries in a file system independent format
145037741Smckusick  */
145138408Smckusick getdirentries(scp)
145238408Smckusick 	register struct syscontext *scp;
145312756Ssam {
145437741Smckusick 	register struct a {
145537741Smckusick 		int	fd;
145637741Smckusick 		char	*buf;
145737741Smckusick 		unsigned count;
145837741Smckusick 		long	*basep;
145938408Smckusick 	} *uap = (struct a *)scp->sc_ap;
146039592Smckusick 	register struct vnode *vp;
146116540Ssam 	struct file *fp;
146237741Smckusick 	struct uio auio;
146337741Smckusick 	struct iovec aiov;
146438129Smckusick 	off_t off;
146540321Smckusick 	int error, eofflag;
146612756Ssam 
146738408Smckusick 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
146837741Smckusick 		RETURN (error);
146937741Smckusick 	if ((fp->f_flag & FREAD) == 0)
147037741Smckusick 		RETURN (EBADF);
147139592Smckusick 	vp = (struct vnode *)fp->f_data;
147239592Smckusick 	if (vp->v_type != VDIR)
147339592Smckusick 		RETURN (EINVAL);
147437741Smckusick 	aiov.iov_base = uap->buf;
147537741Smckusick 	aiov.iov_len = uap->count;
147637741Smckusick 	auio.uio_iov = &aiov;
147737741Smckusick 	auio.uio_iovcnt = 1;
147837741Smckusick 	auio.uio_rw = UIO_READ;
147937741Smckusick 	auio.uio_segflg = UIO_USERSPACE;
148037741Smckusick 	auio.uio_resid = uap->count;
148139592Smckusick 	VOP_LOCK(vp);
148239592Smckusick 	auio.uio_offset = off = fp->f_offset;
148340321Smckusick 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag);
148439592Smckusick 	fp->f_offset = auio.uio_offset;
148539592Smckusick 	VOP_UNLOCK(vp);
148639592Smckusick 	if (error)
148737741Smckusick 		RETURN (error);
148839592Smckusick 	error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
148938408Smckusick 	scp->sc_retval1 = uap->count - auio.uio_resid;
149037741Smckusick 	RETURN (error);
149112756Ssam }
149212756Ssam 
149312756Ssam /*
149412756Ssam  * mode mask for creation of files
149512756Ssam  */
149638408Smckusick umask(scp)
149738408Smckusick 	register struct syscontext *scp;
149812756Ssam {
149912756Ssam 	register struct a {
150012756Ssam 		int	mask;
150138408Smckusick 	} *uap = (struct a *)scp->sc_ap;
150212756Ssam 
150338408Smckusick 	scp->sc_retval1 = scp->sc_cmask;
150438408Smckusick 	scp->sc_cmask = uap->mask & 07777;
150537741Smckusick 	RETURN (0);
150612756Ssam }
150737741Smckusick 
150839566Smarc /*
150939566Smarc  * Void all references to file by ripping underlying filesystem
151039566Smarc  * away from vnode.
151139566Smarc  */
151239566Smarc revoke(scp)
151339566Smarc 	register struct syscontext *scp;
151439566Smarc {
151539566Smarc 	struct a {
151639566Smarc 		char	*fname;
1517*41676Smckusick 		int	flags;
151839566Smarc 	} *uap = (struct a *)scp->sc_ap;
151939566Smarc 	register struct nameidata *ndp = &scp->sc_nd;
152039566Smarc 	register struct vnode *vp;
152139566Smarc 	struct vattr vattr;
152239566Smarc 	int error;
152339566Smarc 
152439566Smarc 	ndp->ni_nameiop = LOOKUP | FOLLOW;
152539566Smarc 	ndp->ni_segflg = UIO_USERSPACE;
152639566Smarc 	ndp->ni_dirp = uap->fname;
152739566Smarc 	if (error = namei(ndp))
152839566Smarc 		RETURN (error);
152939566Smarc 	vp = ndp->ni_vp;
153039566Smarc 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
153139566Smarc 		error = EINVAL;
153239566Smarc 		goto out;
153339566Smarc 	}
153439566Smarc 	if (error = VOP_GETATTR(vp, &vattr, scp->sc_cred))
153539566Smarc 		goto out;
153639566Smarc 	if (scp->sc_uid != vattr.va_uid ||
153739566Smarc 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
153839566Smarc 		goto out;
153939805Smckusick 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
154039632Smckusick 		vgoneall(vp);
154139566Smarc out:
154239566Smarc 	vrele(vp);
154339566Smarc 	RETURN (error);
154439566Smarc }
154539566Smarc 
154638408Smckusick getvnode(ofile, fdes, fpp)
154738408Smckusick 	struct file *ofile[];
154837741Smckusick 	struct file **fpp;
154937741Smckusick 	int fdes;
155037741Smckusick {
155137741Smckusick 	struct file *fp;
155237741Smckusick 
155338408Smckusick 	if ((unsigned)fdes >= NOFILE || (fp = ofile[fdes]) == NULL)
155437741Smckusick 		return (EBADF);
155537741Smckusick 	if (fp->f_type != DTYPE_VNODE)
155637741Smckusick 		return (EINVAL);
155737741Smckusick 	*fpp = fp;
155837741Smckusick 	return (0);
155937741Smckusick }
1560