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