xref: /original-bsd/sys/kern/vfs_syscalls.c (revision a9392a99)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)vfs_syscalls.c	7.43 (Berkeley) 04/10/90
18  */
19 
20 #include "param.h"
21 #include "systm.h"
22 #include "syscontext.h"
23 #include "kernel.h"
24 #include "file.h"
25 #include "stat.h"
26 #include "vnode.h"
27 #include "mount.h"
28 #include "proc.h"
29 #include "uio.h"
30 #include "malloc.h"
31 
32 #undef RETURN
33 #define RETURN(val)	{ scp->u_error = (val); if (scp->u_spare[0] != 0) panic("lock count"); return; }
34 
35 /*
36  * Virtual File System System Calls
37  */
38 
39 /*
40  * mount system call
41  */
42 mount(scp)
43 	register struct syscontext *scp;
44 {
45 	register struct a {
46 		int	type;
47 		char	*dir;
48 		int	flags;
49 		caddr_t	data;
50 	} *uap = (struct a *)scp->sc_ap;
51 	register struct nameidata *ndp = &scp->sc_nd;
52 	register struct vnode *vp;
53 	register struct mount *mp;
54 	int error, flag;
55 
56 	/*
57 	 * Must be super user
58 	 */
59 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
60 		RETURN (error);
61 	/*
62 	 * Get vnode to be covered
63 	 */
64 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
65 	ndp->ni_segflg = UIO_USERSPACE;
66 	ndp->ni_dirp = uap->dir;
67 	if (error = namei(ndp))
68 		RETURN (error);
69 	vp = ndp->ni_vp;
70 	if (uap->flags & M_UPDATE) {
71 		if ((vp->v_flag & VROOT) == 0) {
72 			vput(vp);
73 			RETURN (EINVAL);
74 		}
75 		mp = vp->v_mount;
76 		/*
77 		 * We allow going from read-only to read-write,
78 		 * but not from read-write to read-only.
79 		 */
80 		if ((mp->m_flag & M_RDONLY) == 0 &&
81 		    (uap->flags & M_RDONLY) != 0) {
82 			vput(vp);
83 			RETURN (EOPNOTSUPP);	/* Needs translation */
84 		}
85 		flag = mp->m_flag;
86 		mp->m_flag |= M_UPDATE;
87 		VOP_UNLOCK(vp);
88 		goto update;
89 	}
90 	vinvalbuf(vp, 1);
91 	if (vp->v_usecount != 1) {
92 		vput(vp);
93 		RETURN (EBUSY);
94 	}
95 	if (vp->v_type != VDIR) {
96 		vput(vp);
97 		RETURN (ENOTDIR);
98 	}
99 	if ((unsigned long)uap->type > MOUNT_MAXTYPE ||
100 	    vfssw[uap->type] == (struct vfsops *)0) {
101 		vput(vp);
102 		RETURN (ENODEV);
103 	}
104 
105 	/*
106 	 * Allocate and initialize the file system.
107 	 */
108 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
109 		M_MOUNT, M_WAITOK);
110 	mp->m_op = vfssw[uap->type];
111 	mp->m_flag = 0;
112 	mp->m_exroot = 0;
113 	mp->m_mounth = (struct vnode *)0;
114 	if (error = vfs_lock(mp)) {
115 		free((caddr_t)mp, M_MOUNT);
116 		vput(vp);
117 		RETURN (error);
118 	}
119 	if (vp->v_mountedhere != (struct mount *)0) {
120 		vfs_unlock(mp);
121 		free((caddr_t)mp, M_MOUNT);
122 		vput(vp);
123 		RETURN (EBUSY);
124 	}
125 	vp->v_mountedhere = mp;
126 	mp->m_vnodecovered = vp;
127 update:
128 	/*
129 	 * Set the mount level flags.
130 	 */
131 	if (uap->flags & M_RDONLY)
132 		mp->m_flag |= M_RDONLY;
133 	else
134 		mp->m_flag &= ~M_RDONLY;
135 	if (uap->flags & M_NOSUID)
136 		mp->m_flag |= M_NOSUID;
137 	else
138 		mp->m_flag &= ~M_NOSUID;
139 	if (uap->flags & M_NOEXEC)
140 		mp->m_flag |= M_NOEXEC;
141 	else
142 		mp->m_flag &= ~M_NOEXEC;
143 	if (uap->flags & M_NODEV)
144 		mp->m_flag |= M_NODEV;
145 	else
146 		mp->m_flag &= ~M_NODEV;
147 	if (uap->flags & M_SYNCHRONOUS)
148 		mp->m_flag |= M_SYNCHRONOUS;
149 	else
150 		mp->m_flag &= ~M_SYNCHRONOUS;
151 	/*
152 	 * Mount the filesystem.
153 	 */
154 	error = VFS_MOUNT(mp, uap->dir, uap->data, ndp);
155 	if (mp->m_flag & M_UPDATE) {
156 		mp->m_flag &= ~M_UPDATE;
157 		vrele(vp);
158 		if (error)
159 			mp->m_flag = flag;
160 		RETURN (error);
161 	}
162 	/*
163 	 * Put the new filesystem on the mount list after root.
164 	 */
165 	mp->m_next = rootfs->m_next;
166 	mp->m_prev = rootfs;
167 	rootfs->m_next = mp;
168 	mp->m_next->m_prev = mp;
169 	cache_purge(vp);
170 	if (!error) {
171 		VOP_UNLOCK(vp);
172 		vfs_unlock(mp);
173 		error = VFS_START(mp, 0);
174 	} else {
175 		vfs_remove(mp);
176 		free((caddr_t)mp, M_MOUNT);
177 		vput(vp);
178 	}
179 	RETURN (error);
180 }
181 
182 /*
183  * Unmount system call.
184  *
185  * Note: unmount takes a path to the vnode mounted on as argument,
186  * not special file (as before).
187  */
188 unmount(scp)
189 	register struct syscontext *scp;
190 {
191 	struct a {
192 		char	*pathp;
193 		int	flags;
194 	} *uap = (struct a *)scp->sc_ap;
195 	register struct vnode *vp;
196 	register struct nameidata *ndp = &scp->sc_nd;
197 	struct mount *mp;
198 	int error;
199 
200 	/*
201 	 * Must be super user
202 	 */
203 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
204 		RETURN (error);
205 
206 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
207 	ndp->ni_segflg = UIO_USERSPACE;
208 	ndp->ni_dirp = uap->pathp;
209 	if (error = namei(ndp))
210 		RETURN (error);
211 	vp = ndp->ni_vp;
212 	/*
213 	 * Must be the root of the filesystem
214 	 */
215 	if ((vp->v_flag & VROOT) == 0) {
216 		vput(vp);
217 		RETURN (EINVAL);
218 	}
219 	mp = vp->v_mount;
220 	vput(vp);
221 	RETURN (dounmount(mp, uap->flags));
222 }
223 
224 /*
225  * Do an unmount.
226  */
227 dounmount(mp, flags)
228 	register struct mount *mp;
229 	int flags;
230 {
231 	struct vnode *coveredvp;
232 	int error;
233 
234 	coveredvp = mp->m_vnodecovered;
235 	if (error = vfs_lock(mp))
236 		return (error);
237 
238 	xumount(mp);		/* remove unused sticky files from text table */
239 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
240 	VFS_SYNC(mp, MNT_WAIT);
241 
242 	error = VFS_UNMOUNT(mp, flags);
243 	if (error) {
244 		vfs_unlock(mp);
245 	} else {
246 		vrele(coveredvp);
247 		vfs_remove(mp);
248 		free((caddr_t)mp, M_MOUNT);
249 	}
250 	return (error);
251 }
252 
253 /*
254  * Sync system call.
255  * Sync each mounted filesystem.
256  */
257 /* ARGSUSED */
258 sync(scp)
259 	struct syscontext *scp;
260 {
261 	register struct mount *mp;
262 
263 	mp = rootfs;
264 	do {
265 		/*
266 		 * The lock check below is to avoid races with mount
267 		 * and unmount.
268 		 */
269 		if ((mp->m_flag & (M_MLOCK|M_RDONLY)) == 0)
270 			VFS_SYNC(mp, MNT_NOWAIT);
271 		mp = mp->m_next;
272 	} while (mp != rootfs);
273 }
274 
275 /*
276  * get filesystem statistics
277  */
278 statfs(scp)
279 	register struct syscontext *scp;
280 {
281 	struct a {
282 		char *path;
283 		struct statfs *buf;
284 	} *uap = (struct a *)scp->sc_ap;
285 	register struct mount *mp;
286 	register struct nameidata *ndp = &scp->sc_nd;
287 	register struct statfs *sp;
288 	int error;
289 
290 	ndp->ni_nameiop = LOOKUP | FOLLOW;
291 	ndp->ni_segflg = UIO_USERSPACE;
292 	ndp->ni_dirp = uap->path;
293 	if (error = namei(ndp))
294 		RETURN (error);
295 	mp = ndp->ni_vp->v_mount;
296 	sp = &mp->m_stat;
297 	vrele(ndp->ni_vp);
298 	if (error = VFS_STATFS(mp, sp))
299 		RETURN (error);
300 	sp->f_flags = mp->m_flag & M_VISFLAGMASK;
301 	RETURN (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
302 }
303 
304 fstatfs(scp)
305 	register struct syscontext *scp;
306 {
307 	struct a {
308 		int fd;
309 		struct statfs *buf;
310 	} *uap = (struct a *)scp->sc_ap;
311 	struct file *fp;
312 	struct mount *mp;
313 	register struct statfs *sp;
314 	int error;
315 
316 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
317 		RETURN (error);
318 	mp = ((struct vnode *)fp->f_data)->v_mount;
319 	sp = &mp->m_stat;
320 	if (error = VFS_STATFS(mp, sp))
321 		RETURN (error);
322 	sp->f_flags = mp->m_flag & M_VISFLAGMASK;
323 	RETURN (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
324 }
325 
326 /*
327  * get statistics on all filesystems
328  */
329 getfsstat(scp)
330 	register struct syscontext *scp;
331 {
332 	struct a {
333 		struct statfs *buf;
334 		long bufsize;
335 		int flags;
336 	} *uap = (struct a *)scp->sc_ap;
337 	register struct mount *mp;
338 	register struct statfs *sp;
339 	caddr_t sfsp;
340 	long count, maxcount, error;
341 
342 	maxcount = uap->bufsize / sizeof(struct statfs);
343 	sfsp = (caddr_t)uap->buf;
344 	mp = rootfs;
345 	count = 0;
346 	do {
347 		if (sfsp && count < maxcount && ((mp->m_flag & M_MLOCK) == 0)) {
348 			sp = &mp->m_stat;
349 			/*
350 			 * If MNT_NOWAIT is specified, do not refresh the
351 			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
352 			 */
353 			if (((uap->flags & MNT_NOWAIT) == 0 ||
354 			    (uap->flags & MNT_WAIT)) &&
355 			    (error = VFS_STATFS(mp, sp))) {
356 				mp = mp->m_prev;
357 				continue;
358 			}
359 			sp->f_flags = mp->m_flag & M_VISFLAGMASK;
360 			if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
361 				RETURN (error);
362 			sfsp += sizeof(*sp);
363 		}
364 		count++;
365 		mp = mp->m_prev;
366 	} while (mp != rootfs);
367 	if (sfsp && count > maxcount)
368 		scp->sc_retval1 = maxcount;
369 	else
370 		scp->sc_retval1 = count;
371 	RETURN (0);
372 }
373 
374 /*
375  * Change current working directory to a given file descriptor.
376  */
377 fchdir(scp)
378 	register struct syscontext *scp;
379 {
380 	struct a {
381 		int	fd;
382 	} *uap = (struct a *)scp->sc_ap;
383 	register struct vnode *vp;
384 	struct file *fp;
385 	int error;
386 
387 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
388 		RETURN (error);
389 	vp = (struct vnode *)fp->f_data;
390 	VOP_LOCK(vp);
391 	if (vp->v_type != VDIR)
392 		error = ENOTDIR;
393 	else
394 		error = VOP_ACCESS(vp, VEXEC, scp->sc_cred);
395 	VOP_UNLOCK(vp);
396 	if (error)
397 		RETURN (error);
398 	VREF(vp);
399 	vrele(scp->sc_cdir);
400 	scp->sc_cdir = vp;
401 	RETURN (0);
402 }
403 
404 /*
405  * Change current working directory (``.'').
406  */
407 chdir(scp)
408 	register struct syscontext *scp;
409 {
410 	struct a {
411 		char	*fname;
412 	} *uap = (struct a *)scp->sc_ap;
413 	register struct nameidata *ndp = &scp->sc_nd;
414 	int error;
415 
416 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
417 	ndp->ni_segflg = UIO_USERSPACE;
418 	ndp->ni_dirp = uap->fname;
419 	if (error = chdirec(ndp))
420 		RETURN (error);
421 	vrele(scp->sc_cdir);
422 	scp->sc_cdir = ndp->ni_vp;
423 	RETURN (0);
424 }
425 
426 /*
427  * Change notion of root (``/'') directory.
428  */
429 chroot(scp)
430 	register struct syscontext *scp;
431 {
432 	struct a {
433 		char	*fname;
434 	} *uap = (struct a *)scp->sc_ap;
435 	register struct nameidata *ndp = &scp->sc_nd;
436 	int error;
437 
438 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
439 		RETURN (error);
440 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
441 	ndp->ni_segflg = UIO_USERSPACE;
442 	ndp->ni_dirp = uap->fname;
443 	if (error = chdirec(ndp))
444 		RETURN (error);
445 	if (scp->sc_rdir != NULL)
446 		vrele(scp->sc_rdir);
447 	scp->sc_rdir = ndp->ni_vp;
448 	RETURN (0);
449 }
450 
451 /*
452  * Common routine for chroot and chdir.
453  */
454 chdirec(ndp)
455 	register struct nameidata *ndp;
456 {
457 	struct vnode *vp;
458 	int error;
459 
460 	if (error = namei(ndp))
461 		return (error);
462 	vp = ndp->ni_vp;
463 	if (vp->v_type != VDIR)
464 		error = ENOTDIR;
465 	else
466 		error = VOP_ACCESS(vp, VEXEC, ndp->ni_cred);
467 	VOP_UNLOCK(vp);
468 	if (error)
469 		vrele(vp);
470 	return (error);
471 }
472 
473 /*
474  * Open system call.
475  */
476 open(scp)
477 	register struct syscontext *scp;
478 {
479 	struct a {
480 		char	*fname;
481 		int	mode;
482 		int	crtmode;
483 	} *uap = (struct a *) scp->sc_ap;
484 	struct nameidata *ndp = &scp->sc_nd;
485 
486 	ndp->ni_segflg = UIO_USERSPACE;
487 	ndp->ni_dirp = uap->fname;
488 	RETURN (copen(scp, uap->mode-FOPEN, uap->crtmode &~ scp->sc_cmask, ndp,
489 		&scp->sc_retval1));
490 }
491 
492 /*
493  * Creat system call.
494  */
495 creat(scp)
496 	register struct syscontext *scp;
497 {
498 	struct a {
499 		char	*fname;
500 		int	fmode;
501 	} *uap = (struct a *)scp->sc_ap;
502 	struct nameidata *ndp = &scp->sc_nd;
503 
504 	ndp->ni_segflg = UIO_USERSPACE;
505 	ndp->ni_dirp = uap->fname;
506 	RETURN (copen(scp, FWRITE|FCREAT|FTRUNC, uap->fmode &~ scp->sc_cmask,
507 		ndp, &scp->sc_retval1));
508 }
509 
510 /*
511  * Common code for open and creat.
512  * Check permissions, allocate an open file structure,
513  * and call the device open routine if any.
514  */
515 copen(scp, fmode, cmode, ndp, resultfd)
516 	register struct syscontext *scp;
517 	int fmode, cmode;
518 	struct nameidata *ndp;
519 	int *resultfd;
520 {
521 	register struct file *fp;
522 	struct file *nfp;
523 	int indx, error;
524 	extern struct fileops vnops;
525 
526 	if (error = falloc(&nfp, &indx))
527 		return (error);
528 	fp = nfp;
529 	scp->sc_retval1 = indx;	/* XXX for fdopen() */
530 	if (error = vn_open(ndp, fmode, (cmode & 07777) &~ S_ISVTX)) {
531 		crfree(fp->f_cred);
532 		fp->f_count--;
533 		if (error == EJUSTRETURN)	/* XXX from fdopen */
534 			return (0);		/* XXX from fdopen */
535 		if (error == ERESTART)
536 			error = EINTR;
537 		scp->sc_ofile[indx] = NULL;
538 		return (error);
539 	}
540 	fp->f_flag = fmode & FMASK;
541 	fp->f_type = DTYPE_VNODE;
542 	fp->f_ops = &vnops;
543 	fp->f_data = (caddr_t)ndp->ni_vp;
544 	if (resultfd)
545 		*resultfd = indx;
546 	return (0);
547 }
548 
549 /*
550  * Mknod system call
551  */
552 mknod(scp)
553 	register struct syscontext *scp;
554 {
555 	register struct a {
556 		char	*fname;
557 		int	fmode;
558 		int	dev;
559 	} *uap = (struct a *)scp->sc_ap;
560 	register struct nameidata *ndp = &scp->sc_nd;
561 	register struct vnode *vp;
562 	struct vattr vattr;
563 	int error;
564 
565 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
566 		RETURN (error);
567 	ndp->ni_nameiop = CREATE | LOCKPARENT;
568 	ndp->ni_segflg = UIO_USERSPACE;
569 	ndp->ni_dirp = uap->fname;
570 	if (error = namei(ndp))
571 		RETURN (error);
572 	vp = ndp->ni_vp;
573 	if (vp != NULL) {
574 		error = EEXIST;
575 		goto out;
576 	}
577 	vattr_null(&vattr);
578 	switch (uap->fmode & S_IFMT) {
579 
580 	case S_IFMT:	/* used by badsect to flag bad sectors */
581 		vattr.va_type = VBAD;
582 		break;
583 	case S_IFCHR:
584 		vattr.va_type = VCHR;
585 		break;
586 	case S_IFBLK:
587 		vattr.va_type = VBLK;
588 		break;
589 	default:
590 		error = EINVAL;
591 		goto out;
592 	}
593 	vattr.va_mode = (uap->fmode & 07777) &~ scp->sc_cmask;
594 	vattr.va_rdev = uap->dev;
595 out:
596 	if (error)
597 		VOP_ABORTOP(ndp);
598 	else
599 		error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred);
600 	RETURN (error);
601 }
602 
603 /*
604  * Mkfifo system call
605  */
606 mkfifo(scp)
607 	register struct syscontext *scp;
608 {
609 	register struct a {
610 		char	*fname;
611 		int	fmode;
612 	} *uap = (struct a *)scp->sc_ap;
613 	register struct nameidata *ndp = &scp->sc_nd;
614 	struct vattr vattr;
615 	int error;
616 
617 #ifndef FIFO
618 	RETURN (EOPNOTSUPP);
619 #else
620 	ndp->ni_nameiop = CREATE | LOCKPARENT;
621 	ndp->ni_segflg = UIO_USERSPACE;
622 	ndp->ni_dirp = uap->fname;
623 	if (error = namei(ndp))
624 		RETURN (error);
625 	if (ndp->ni_vp != NULL) {
626 		VOP_ABORTOP(ndp);
627 		RETURN (EEXIST);
628 	} else {
629 		vattr_null(&vattr);
630 		vattr.va_type = VFIFO;
631 		vattr.va_mode = (uap->fmode & 07777) &~ scp->sc_cmask;
632 	}
633 	RETURN (VOP_MKNOD(ndp, &vattr, ndp->ni_cred));
634 #endif /* FIFO */
635 }
636 
637 /*
638  * link system call
639  */
640 link(scp)
641 	register struct syscontext *scp;
642 {
643 	register struct a {
644 		char	*target;
645 		char	*linkname;
646 	} *uap = (struct a *)scp->sc_ap;
647 	register struct nameidata *ndp = &scp->sc_nd;
648 	register struct vnode *vp, *xp;
649 	int error;
650 
651 	ndp->ni_nameiop = LOOKUP | FOLLOW;
652 	ndp->ni_segflg = UIO_USERSPACE;
653 	ndp->ni_dirp = uap->target;
654 	if (error = namei(ndp))
655 		RETURN (error);
656 	vp = ndp->ni_vp;
657 	if (vp->v_type == VDIR &&
658 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
659 		goto out1;
660 	ndp->ni_nameiop = CREATE | LOCKPARENT;
661 	ndp->ni_dirp = (caddr_t)uap->linkname;
662 	if (error = namei(ndp))
663 		goto out1;
664 	xp = ndp->ni_vp;
665 	if (xp != NULL) {
666 		error = EEXIST;
667 		goto out;
668 	}
669 	xp = ndp->ni_dvp;
670 	if (vp->v_mount != xp->v_mount)
671 		error = EXDEV;
672 out:
673 	if (error)
674 		VOP_ABORTOP(ndp);
675 	else
676 		error = VOP_LINK(vp, ndp);
677 out1:
678 	vrele(vp);
679 	RETURN (error);
680 }
681 
682 /*
683  * symlink -- make a symbolic link
684  */
685 symlink(scp)
686 	register struct syscontext *scp;
687 {
688 	struct a {
689 		char	*target;
690 		char	*linkname;
691 	} *uap = (struct a *)scp->sc_ap;
692 	register struct nameidata *ndp = &scp->sc_nd;
693 	register struct vnode *vp;
694 	struct vattr vattr;
695 	char *target;
696 	int error;
697 
698 	ndp->ni_segflg = UIO_USERSPACE;
699 	ndp->ni_dirp = uap->linkname;
700 	MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
701 	if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
702 		goto out1;
703 	ndp->ni_nameiop = CREATE | LOCKPARENT;
704 	if (error = namei(ndp))
705 		goto out1;
706 	vp = ndp->ni_vp;
707 	if (vp) {
708 		error = EEXIST;
709 		goto out;
710 	}
711 	vp = ndp->ni_dvp;
712 	vattr_null(&vattr);
713 	vattr.va_mode = 0777 &~ scp->sc_cmask;
714 out:
715 	if (error)
716 		VOP_ABORTOP(ndp);
717 	else
718 		error = VOP_SYMLINK(ndp, &vattr, target);
719 out1:
720 	FREE(target, M_NAMEI);
721 	RETURN (error);
722 }
723 
724 /*
725  * Unlink system call.
726  * Hard to avoid races here, especially
727  * in unlinking directories.
728  */
729 unlink(scp)
730 	register struct syscontext *scp;
731 {
732 	struct a {
733 		char	*fname;
734 	} *uap = (struct a *)scp->sc_ap;
735 	register struct nameidata *ndp = &scp->sc_nd;
736 	register struct vnode *vp;
737 	int error;
738 
739 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
740 	ndp->ni_segflg = UIO_USERSPACE;
741 	ndp->ni_dirp = uap->fname;
742 	if (error = namei(ndp))
743 		RETURN (error);
744 	vp = ndp->ni_vp;
745 	if (vp->v_type == VDIR &&
746 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
747 		goto out;
748 	/*
749 	 * Don't unlink a mounted file.
750 	 */
751 	if (vp->v_flag & VROOT) {
752 		error = EBUSY;
753 		goto out;
754 	}
755 	if (vp->v_flag & VTEXT)
756 		xrele(vp);	/* try once to free text */
757 out:
758 	if (error)
759 		VOP_ABORTOP(ndp);
760 	else
761 		error = VOP_REMOVE(ndp);
762 	RETURN (error);
763 }
764 
765 /*
766  * Seek system call
767  */
768 lseek(scp)
769 	register struct syscontext *scp;
770 {
771 	register struct file *fp;
772 	register struct a {
773 		int	fdes;
774 		off_t	off;
775 		int	sbase;
776 	} *uap = (struct a *)scp->sc_ap;
777 	struct vattr vattr;
778 	int error;
779 
780 	if ((unsigned)uap->fdes >= NOFILE ||
781 	    (fp = scp->sc_ofile[uap->fdes]) == NULL)
782 		RETURN (EBADF);
783 	if (fp->f_type != DTYPE_VNODE)
784 		RETURN (ESPIPE);
785 	switch (uap->sbase) {
786 
787 	case L_INCR:
788 		fp->f_offset += uap->off;
789 		break;
790 
791 	case L_XTND:
792 		if (error = VOP_GETATTR((struct vnode *)fp->f_data,
793 		    &vattr, scp->sc_cred))
794 			RETURN (error);
795 		fp->f_offset = uap->off + vattr.va_size;
796 		break;
797 
798 	case L_SET:
799 		fp->f_offset = uap->off;
800 		break;
801 
802 	default:
803 		RETURN (EINVAL);
804 	}
805 	scp->sc_offset = fp->f_offset;
806 	RETURN (0);
807 }
808 
809 /*
810  * Access system call
811  */
812 saccess(scp)
813 	register struct syscontext *scp;
814 {
815 	register struct a {
816 		char	*fname;
817 		int	fmode;
818 	} *uap = (struct a *)scp->sc_ap;
819 	register struct nameidata *ndp = &scp->sc_nd;
820 	register struct vnode *vp;
821 	int error, mode, svuid, svgid;
822 
823 	svuid = scp->sc_uid;
824 	svgid = scp->sc_gid;
825 	scp->sc_uid = scp->sc_ruid;
826 	scp->sc_gid = scp->sc_rgid;
827 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
828 	ndp->ni_segflg = UIO_USERSPACE;
829 	ndp->ni_dirp = uap->fname;
830 	if (error = namei(ndp))
831 		goto out1;
832 	vp = ndp->ni_vp;
833 	/*
834 	 * fmode == 0 means only check for exist
835 	 */
836 	if (uap->fmode) {
837 		mode = 0;
838 		if (uap->fmode & R_OK)
839 			mode |= VREAD;
840 		if (uap->fmode & W_OK)
841 			mode |= VWRITE;
842 		if (uap->fmode & X_OK)
843 			mode |= VEXEC;
844 		if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
845 			error = VOP_ACCESS(vp, mode, ndp->ni_cred);
846 	}
847 	vput(vp);
848 out1:
849 	scp->sc_uid = svuid;
850 	scp->sc_gid = svgid;
851 	RETURN (error);
852 }
853 
854 /*
855  * Stat system call.  This version follows links.
856  */
857 stat(scp)
858 	struct syscontext *scp;
859 {
860 
861 	stat1(scp, FOLLOW);
862 }
863 
864 /*
865  * Lstat system call.  This version does not follow links.
866  */
867 lstat(scp)
868 	struct syscontext *scp;
869 {
870 
871 	stat1(scp, NOFOLLOW);
872 }
873 
874 stat1(scp, follow)
875 	register struct syscontext *scp;
876 	int follow;
877 {
878 	register struct a {
879 		char	*fname;
880 		struct stat *ub;
881 	} *uap = (struct a *)scp->sc_ap;
882 	register struct nameidata *ndp = &scp->sc_nd;
883 	struct stat sb;
884 	int error;
885 
886 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow;
887 	ndp->ni_segflg = UIO_USERSPACE;
888 	ndp->ni_dirp = uap->fname;
889 	if (error = namei(ndp))
890 		RETURN (error);
891 	error = vn_stat(ndp->ni_vp, &sb);
892 	vput(ndp->ni_vp);
893 	if (error)
894 		RETURN (error);
895 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
896 	RETURN (error);
897 }
898 
899 /*
900  * Return target name of a symbolic link
901  */
902 readlink(scp)
903 	register struct syscontext *scp;
904 {
905 	register struct a {
906 		char	*name;
907 		char	*buf;
908 		int	count;
909 	} *uap = (struct a *)scp->sc_ap;
910 	register struct nameidata *ndp = &scp->sc_nd;
911 	register struct vnode *vp;
912 	struct iovec aiov;
913 	struct uio auio;
914 	int error;
915 
916 	ndp->ni_nameiop = LOOKUP | LOCKLEAF;
917 	ndp->ni_segflg = UIO_USERSPACE;
918 	ndp->ni_dirp = uap->name;
919 	if (error = namei(ndp))
920 		RETURN (error);
921 	vp = ndp->ni_vp;
922 	if (vp->v_type != VLNK) {
923 		error = EINVAL;
924 		goto out;
925 	}
926 	aiov.iov_base = uap->buf;
927 	aiov.iov_len = uap->count;
928 	auio.uio_iov = &aiov;
929 	auio.uio_iovcnt = 1;
930 	auio.uio_offset = 0;
931 	auio.uio_rw = UIO_READ;
932 	auio.uio_segflg = UIO_USERSPACE;
933 	auio.uio_resid = uap->count;
934 	error = VOP_READLINK(vp, &auio, ndp->ni_cred);
935 out:
936 	vput(vp);
937 	scp->sc_retval1 = uap->count - auio.uio_resid;
938 	RETURN (error);
939 }
940 
941 /*
942  * Change flags of a file given path name.
943  */
944 chflags(scp)
945 	register struct syscontext *scp;
946 {
947 	struct a {
948 		char	*fname;
949 		int	flags;
950 	} *uap = (struct a *)scp->sc_ap;
951 	register struct nameidata *ndp = &scp->sc_nd;
952 	register struct vnode *vp;
953 	struct vattr vattr;
954 	int error;
955 
956 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
957 	ndp->ni_segflg = UIO_USERSPACE;
958 	ndp->ni_dirp = uap->fname;
959 	vattr_null(&vattr);
960 	vattr.va_flags = uap->flags;
961 	if (error = namei(ndp))
962 		RETURN (error);
963 	vp = ndp->ni_vp;
964 	if (vp->v_mount->m_flag & M_RDONLY) {
965 		error = EROFS;
966 		goto out;
967 	}
968 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
969 out:
970 	vput(vp);
971 	RETURN (error);
972 }
973 
974 /*
975  * Change flags of a file given a file descriptor.
976  */
977 fchflags(scp)
978 	register struct syscontext *scp;
979 {
980 	struct a {
981 		int	fd;
982 		int	flags;
983 	} *uap = (struct a *)scp->sc_ap;
984 	struct vattr vattr;
985 	struct vnode *vp;
986 	struct file *fp;
987 	int error;
988 
989 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
990 		RETURN (error);
991 	vattr_null(&vattr);
992 	vattr.va_flags = uap->flags;
993 	vp = (struct vnode *)fp->f_data;
994 	VOP_LOCK(vp);
995 	if (vp->v_mount->m_flag & M_RDONLY) {
996 		error = EROFS;
997 		goto out;
998 	}
999 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1000 out:
1001 	VOP_UNLOCK(vp);
1002 	RETURN (error);
1003 }
1004 
1005 /*
1006  * Change mode of a file given path name.
1007  */
1008 chmod(scp)
1009 	register struct syscontext *scp;
1010 {
1011 	struct a {
1012 		char	*fname;
1013 		int	fmode;
1014 	} *uap = (struct a *)scp->sc_ap;
1015 	register struct nameidata *ndp = &scp->sc_nd;
1016 	register struct vnode *vp;
1017 	struct vattr vattr;
1018 	int error;
1019 
1020 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1021 	ndp->ni_segflg = UIO_USERSPACE;
1022 	ndp->ni_dirp = uap->fname;
1023 	vattr_null(&vattr);
1024 	vattr.va_mode = uap->fmode & 07777;
1025 	if (error = namei(ndp))
1026 		RETURN (error);
1027 	vp = ndp->ni_vp;
1028 	if (vp->v_mount->m_flag & M_RDONLY) {
1029 		error = EROFS;
1030 		goto out;
1031 	}
1032 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1033 out:
1034 	vput(vp);
1035 	RETURN (error);
1036 }
1037 
1038 /*
1039  * Change mode of a file given a file descriptor.
1040  */
1041 fchmod(scp)
1042 	register struct syscontext *scp;
1043 {
1044 	struct a {
1045 		int	fd;
1046 		int	fmode;
1047 	} *uap = (struct a *)scp->sc_ap;
1048 	struct vattr vattr;
1049 	struct vnode *vp;
1050 	struct file *fp;
1051 	int error;
1052 
1053 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
1054 		RETURN (error);
1055 	vattr_null(&vattr);
1056 	vattr.va_mode = uap->fmode & 07777;
1057 	vp = (struct vnode *)fp->f_data;
1058 	VOP_LOCK(vp);
1059 	if (vp->v_mount->m_flag & M_RDONLY) {
1060 		error = EROFS;
1061 		goto out;
1062 	}
1063 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1064 out:
1065 	VOP_UNLOCK(vp);
1066 	RETURN (error);
1067 }
1068 
1069 /*
1070  * Set ownership given a path name.
1071  */
1072 chown(scp)
1073 	register struct syscontext *scp;
1074 {
1075 	struct a {
1076 		char	*fname;
1077 		int	uid;
1078 		int	gid;
1079 	} *uap = (struct a *)scp->sc_ap;
1080 	register struct nameidata *ndp = &scp->sc_nd;
1081 	register struct vnode *vp;
1082 	struct vattr vattr;
1083 	int error;
1084 
1085 	ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF;
1086 	ndp->ni_segflg = UIO_USERSPACE;
1087 	ndp->ni_dirp = uap->fname;
1088 	vattr_null(&vattr);
1089 	vattr.va_uid = uap->uid;
1090 	vattr.va_gid = uap->gid;
1091 	if (error = namei(ndp))
1092 		RETURN (error);
1093 	vp = ndp->ni_vp;
1094 	if (vp->v_mount->m_flag & M_RDONLY) {
1095 		error = EROFS;
1096 		goto out;
1097 	}
1098 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1099 out:
1100 	vput(vp);
1101 	RETURN (error);
1102 }
1103 
1104 /*
1105  * Set ownership given a file descriptor.
1106  */
1107 fchown(scp)
1108 	register struct syscontext *scp;
1109 {
1110 	struct a {
1111 		int	fd;
1112 		int	uid;
1113 		int	gid;
1114 	} *uap = (struct a *)scp->sc_ap;
1115 	struct vattr vattr;
1116 	struct vnode *vp;
1117 	struct file *fp;
1118 	int error;
1119 
1120 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
1121 		RETURN (error);
1122 	vattr_null(&vattr);
1123 	vattr.va_uid = uap->uid;
1124 	vattr.va_gid = uap->gid;
1125 	vp = (struct vnode *)fp->f_data;
1126 	VOP_LOCK(vp);
1127 	if (vp->v_mount->m_flag & M_RDONLY) {
1128 		error = EROFS;
1129 		goto out;
1130 	}
1131 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1132 out:
1133 	VOP_UNLOCK(vp);
1134 	RETURN (error);
1135 }
1136 
1137 utimes(scp)
1138 	register struct syscontext *scp;
1139 {
1140 	register struct a {
1141 		char	*fname;
1142 		struct	timeval *tptr;
1143 	} *uap = (struct a *)scp->sc_ap;
1144 	register struct nameidata *ndp = &scp->sc_nd;
1145 	register struct vnode *vp;
1146 	struct timeval tv[2];
1147 	struct vattr vattr;
1148 	int error;
1149 
1150 	if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1151 		RETURN (error);
1152 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1153 	ndp->ni_segflg = UIO_USERSPACE;
1154 	ndp->ni_dirp = uap->fname;
1155 	vattr_null(&vattr);
1156 	vattr.va_atime = tv[0];
1157 	vattr.va_mtime = tv[1];
1158 	if (error = namei(ndp))
1159 		RETURN (error);
1160 	vp = ndp->ni_vp;
1161 	if (vp->v_mount->m_flag & M_RDONLY) {
1162 		error = EROFS;
1163 		goto out;
1164 	}
1165 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1166 out:
1167 	vput(vp);
1168 	RETURN (error);
1169 }
1170 
1171 /*
1172  * Truncate a file given its path name.
1173  */
1174 truncate(scp)
1175 	register struct syscontext *scp;
1176 {
1177 	struct a {
1178 		char	*fname;
1179 		off_t	length;
1180 	} *uap = (struct a *)scp->sc_ap;
1181 	register struct nameidata *ndp = &scp->sc_nd;
1182 	register struct vnode *vp;
1183 	struct vattr vattr;
1184 	int error;
1185 
1186 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1187 	ndp->ni_segflg = UIO_USERSPACE;
1188 	ndp->ni_dirp = uap->fname;
1189 	vattr_null(&vattr);
1190 	vattr.va_size = uap->length;
1191 	if (error = namei(ndp))
1192 		RETURN (error);
1193 	vp = ndp->ni_vp;
1194 	if (vp->v_type == VDIR) {
1195 		error = EISDIR;
1196 		goto out;
1197 	}
1198 	if ((error = vn_writechk(vp)) ||
1199 	    (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
1200 		goto out;
1201 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1202 out:
1203 	vput(vp);
1204 	RETURN (error);
1205 }
1206 
1207 /*
1208  * Truncate a file given a file descriptor.
1209  */
1210 ftruncate(scp)
1211 	register struct syscontext *scp;
1212 {
1213 	struct a {
1214 		int	fd;
1215 		off_t	length;
1216 	} *uap = (struct a *)scp->sc_ap;
1217 	struct vattr vattr;
1218 	struct vnode *vp;
1219 	struct file *fp;
1220 	int error;
1221 
1222 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
1223 		RETURN (error);
1224 	if ((fp->f_flag & FWRITE) == 0)
1225 		RETURN (EINVAL);
1226 	vattr_null(&vattr);
1227 	vattr.va_size = uap->length;
1228 	vp = (struct vnode *)fp->f_data;
1229 	VOP_LOCK(vp);
1230 	if (vp->v_type == VDIR) {
1231 		error = EISDIR;
1232 		goto out;
1233 	}
1234 	if (error = vn_writechk(vp))
1235 		goto out;
1236 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1237 out:
1238 	VOP_UNLOCK(vp);
1239 	RETURN (error);
1240 }
1241 
1242 /*
1243  * Synch an open file.
1244  */
1245 fsync(scp)
1246 	register struct syscontext *scp;
1247 {
1248 	struct a {
1249 		int	fd;
1250 	} *uap = (struct a *)scp->sc_ap;
1251 	register struct vnode *vp;
1252 	struct file *fp;
1253 	int error;
1254 
1255 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
1256 		RETURN (error);
1257 	vp = (struct vnode *)fp->f_data;
1258 	VOP_LOCK(vp);
1259 	error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT);
1260 	VOP_UNLOCK(vp);
1261 	RETURN (error);
1262 }
1263 
1264 /*
1265  * Rename system call.
1266  *
1267  * Source and destination must either both be directories, or both
1268  * not be directories.  If target is a directory, it must be empty.
1269  */
1270 rename(scp)
1271 	register struct syscontext *scp;
1272 {
1273 	struct a {
1274 		char	*from;
1275 		char	*to;
1276 	} *uap = (struct a *)scp->sc_ap;
1277 	register struct vnode *tvp, *fvp, *tdvp;
1278 	register struct nameidata *ndp = &scp->sc_nd;
1279 	struct nameidata tond;
1280 	int error;
1281 
1282 	ndp->ni_nameiop = DELETE | WANTPARENT;
1283 	ndp->ni_segflg = UIO_USERSPACE;
1284 	ndp->ni_dirp = uap->from;
1285 	if (error = namei(ndp))
1286 		RETURN (error);
1287 	fvp = ndp->ni_vp;
1288 	nddup(ndp, &tond);
1289 	tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
1290 	tond.ni_segflg = UIO_USERSPACE;
1291 	tond.ni_dirp = uap->to;
1292 	error = namei(&tond);
1293 	tdvp = tond.ni_dvp;
1294 	tvp = tond.ni_vp;
1295 	if (tvp != NULL) {
1296 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1297 			error = ENOTDIR;
1298 			goto out;
1299 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1300 			error = EISDIR;
1301 			goto out;
1302 		}
1303 	}
1304 	if (error) {
1305 		VOP_ABORTOP(ndp);
1306 		goto out1;
1307 	}
1308 	if (fvp->v_mount != tdvp->v_mount) {
1309 		error = EXDEV;
1310 		goto out;
1311 	}
1312 	if (fvp == tdvp)
1313 		error = EINVAL;
1314 	/*
1315 	 * If source is the same as the destination,
1316 	 * then there is nothing to do.
1317 	 */
1318 	if (fvp == tvp)
1319 		error = -1;
1320 out:
1321 	if (error) {
1322 		VOP_ABORTOP(&tond);
1323 		VOP_ABORTOP(ndp);
1324 	} else {
1325 		error = VOP_RENAME(ndp, &tond);
1326 	}
1327 out1:
1328 	ndrele(&tond);
1329 	if (error == -1)
1330 		RETURN (0);
1331 	RETURN (error);
1332 }
1333 
1334 /*
1335  * Mkdir system call
1336  */
1337 mkdir(scp)
1338 	register struct syscontext *scp;
1339 {
1340 	struct a {
1341 		char	*name;
1342 		int	dmode;
1343 	} *uap = (struct a *)scp->sc_ap;
1344 	register struct nameidata *ndp = &scp->sc_nd;
1345 	register struct vnode *vp;
1346 	struct vattr vattr;
1347 	int error;
1348 
1349 	ndp->ni_nameiop = CREATE | LOCKPARENT;
1350 	ndp->ni_segflg = UIO_USERSPACE;
1351 	ndp->ni_dirp = uap->name;
1352 	if (error = namei(ndp))
1353 		RETURN (error);
1354 	vp = ndp->ni_vp;
1355 	if (vp != NULL) {
1356 		VOP_ABORTOP(ndp);
1357 		RETURN (EEXIST);
1358 	}
1359 	vattr_null(&vattr);
1360 	vattr.va_type = VDIR;
1361 	vattr.va_mode = (uap->dmode & 0777) &~ scp->sc_cmask;
1362 	error = VOP_MKDIR(ndp, &vattr);
1363 	if (!error)
1364 		vput(ndp->ni_vp);
1365 	RETURN (error);
1366 }
1367 
1368 /*
1369  * Rmdir system call.
1370  */
1371 rmdir(scp)
1372 	register struct syscontext *scp;
1373 {
1374 	struct a {
1375 		char	*name;
1376 	} *uap = (struct a *)scp->sc_ap;
1377 	register struct nameidata *ndp = &scp->sc_nd;
1378 	register struct vnode *vp;
1379 	int error;
1380 
1381 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
1382 	ndp->ni_segflg = UIO_USERSPACE;
1383 	ndp->ni_dirp = uap->name;
1384 	if (error = namei(ndp))
1385 		RETURN (error);
1386 	vp = ndp->ni_vp;
1387 	if (vp->v_type != VDIR) {
1388 		error = ENOTDIR;
1389 		goto out;
1390 	}
1391 	/*
1392 	 * No rmdir "." please.
1393 	 */
1394 	if (ndp->ni_dvp == vp) {
1395 		error = EINVAL;
1396 		goto out;
1397 	}
1398 	/*
1399 	 * Don't unlink a mounted file.
1400 	 */
1401 	if (vp->v_flag & VROOT)
1402 		error = EBUSY;
1403 out:
1404 	if (error)
1405 		VOP_ABORTOP(ndp);
1406 	else
1407 		error = VOP_RMDIR(ndp);
1408 	RETURN (error);
1409 }
1410 
1411 /*
1412  * Read a block of directory entries in a file system independent format
1413  */
1414 getdirentries(scp)
1415 	register struct syscontext *scp;
1416 {
1417 	register struct a {
1418 		int	fd;
1419 		char	*buf;
1420 		unsigned count;
1421 		long	*basep;
1422 	} *uap = (struct a *)scp->sc_ap;
1423 	register struct vnode *vp;
1424 	struct file *fp;
1425 	struct uio auio;
1426 	struct iovec aiov;
1427 	off_t off;
1428 	int error, eofflag;
1429 
1430 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
1431 		RETURN (error);
1432 	if ((fp->f_flag & FREAD) == 0)
1433 		RETURN (EBADF);
1434 	vp = (struct vnode *)fp->f_data;
1435 	if (vp->v_type != VDIR)
1436 		RETURN (EINVAL);
1437 	aiov.iov_base = uap->buf;
1438 	aiov.iov_len = uap->count;
1439 	auio.uio_iov = &aiov;
1440 	auio.uio_iovcnt = 1;
1441 	auio.uio_rw = UIO_READ;
1442 	auio.uio_segflg = UIO_USERSPACE;
1443 	auio.uio_resid = uap->count;
1444 	VOP_LOCK(vp);
1445 	auio.uio_offset = off = fp->f_offset;
1446 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag);
1447 	fp->f_offset = auio.uio_offset;
1448 	VOP_UNLOCK(vp);
1449 	if (error)
1450 		RETURN (error);
1451 	error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
1452 	scp->sc_retval1 = uap->count - auio.uio_resid;
1453 	RETURN (error);
1454 }
1455 
1456 /*
1457  * mode mask for creation of files
1458  */
1459 umask(scp)
1460 	register struct syscontext *scp;
1461 {
1462 	register struct a {
1463 		int	mask;
1464 	} *uap = (struct a *)scp->sc_ap;
1465 
1466 	scp->sc_retval1 = scp->sc_cmask;
1467 	scp->sc_cmask = uap->mask & 07777;
1468 	RETURN (0);
1469 }
1470 
1471 /*
1472  * Void all references to file by ripping underlying filesystem
1473  * away from vnode.
1474  */
1475 revoke(scp)
1476 	register struct syscontext *scp;
1477 {
1478 	struct a {
1479 		char	*fname;
1480 	} *uap = (struct a *)scp->sc_ap;
1481 	register struct nameidata *ndp = &scp->sc_nd;
1482 	register struct vnode *vp;
1483 	struct vattr vattr;
1484 	int error;
1485 
1486 	ndp->ni_nameiop = LOOKUP | FOLLOW;
1487 	ndp->ni_segflg = UIO_USERSPACE;
1488 	ndp->ni_dirp = uap->fname;
1489 	if (error = namei(ndp))
1490 		RETURN (error);
1491 	vp = ndp->ni_vp;
1492 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
1493 		error = EINVAL;
1494 		goto out;
1495 	}
1496 	if (error = VOP_GETATTR(vp, &vattr, scp->sc_cred))
1497 		goto out;
1498 	if (scp->sc_uid != vattr.va_uid ||
1499 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
1500 		goto out;
1501 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
1502 		vgoneall(vp);
1503 out:
1504 	vrele(vp);
1505 	RETURN (error);
1506 }
1507 
1508 getvnode(ofile, fdes, fpp)
1509 	struct file *ofile[];
1510 	struct file **fpp;
1511 	int fdes;
1512 {
1513 	struct file *fp;
1514 
1515 	if ((unsigned)fdes >= NOFILE || (fp = ofile[fdes]) == NULL)
1516 		return (EBADF);
1517 	if (fp->f_type != DTYPE_VNODE)
1518 		return (EINVAL);
1519 	*fpp = fp;
1520 	return (0);
1521 }
1522