xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 40635)
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.42 (Berkeley) 03/26/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 == -1)	/* XXX from fdopen */
534 			return (0);	/* XXX from fdopen */
535 		scp->sc_ofile[indx] = NULL;
536 		return (error);
537 	}
538 	fp->f_flag = fmode & FMASK;
539 	fp->f_type = DTYPE_VNODE;
540 	fp->f_ops = &vnops;
541 	fp->f_data = (caddr_t)ndp->ni_vp;
542 	if (resultfd)
543 		*resultfd = indx;
544 	return (0);
545 }
546 
547 /*
548  * Mknod system call
549  */
550 mknod(scp)
551 	register struct syscontext *scp;
552 {
553 	register struct a {
554 		char	*fname;
555 		int	fmode;
556 		int	dev;
557 	} *uap = (struct a *)scp->sc_ap;
558 	register struct nameidata *ndp = &scp->sc_nd;
559 	register struct vnode *vp;
560 	struct vattr vattr;
561 	int error;
562 
563 	if (error = suser(scp->sc_cred, &scp->sc_acflag))
564 		RETURN (error);
565 	ndp->ni_nameiop = CREATE | LOCKPARENT;
566 	ndp->ni_segflg = UIO_USERSPACE;
567 	ndp->ni_dirp = uap->fname;
568 	if (error = namei(ndp))
569 		RETURN (error);
570 	vp = ndp->ni_vp;
571 	if (vp != NULL) {
572 		error = EEXIST;
573 		goto out;
574 	}
575 	vattr_null(&vattr);
576 	switch (uap->fmode & S_IFMT) {
577 
578 	case S_IFMT:	/* used by badsect to flag bad sectors */
579 		vattr.va_type = VBAD;
580 		break;
581 	case S_IFCHR:
582 		vattr.va_type = VCHR;
583 		break;
584 	case S_IFBLK:
585 		vattr.va_type = VBLK;
586 		break;
587 	default:
588 		error = EINVAL;
589 		goto out;
590 	}
591 	vattr.va_mode = (uap->fmode & 07777) &~ scp->sc_cmask;
592 	vattr.va_rdev = uap->dev;
593 out:
594 	if (error)
595 		VOP_ABORTOP(ndp);
596 	else
597 		error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred);
598 	RETURN (error);
599 }
600 
601 /*
602  * Mkfifo system call
603  */
604 mkfifo(scp)
605 	register struct syscontext *scp;
606 {
607 	register struct a {
608 		char	*fname;
609 		int	fmode;
610 	} *uap = (struct a *)scp->sc_ap;
611 	register struct nameidata *ndp = &scp->sc_nd;
612 	struct vattr vattr;
613 	int error;
614 
615 #ifndef FIFO
616 	RETURN (EOPNOTSUPP);
617 #else
618 	ndp->ni_nameiop = CREATE | LOCKPARENT;
619 	ndp->ni_segflg = UIO_USERSPACE;
620 	ndp->ni_dirp = uap->fname;
621 	if (error = namei(ndp))
622 		RETURN (error);
623 	if (ndp->ni_vp != NULL) {
624 		VOP_ABORTOP(ndp);
625 		RETURN (EEXIST);
626 	} else {
627 		vattr_null(&vattr);
628 		vattr.va_type = VFIFO;
629 		vattr.va_mode = (uap->fmode & 07777) &~ scp->sc_cmask;
630 	}
631 	RETURN (VOP_MKNOD(ndp, &vattr, ndp->ni_cred));
632 #endif /* FIFO */
633 }
634 
635 /*
636  * link system call
637  */
638 link(scp)
639 	register struct syscontext *scp;
640 {
641 	register struct a {
642 		char	*target;
643 		char	*linkname;
644 	} *uap = (struct a *)scp->sc_ap;
645 	register struct nameidata *ndp = &scp->sc_nd;
646 	register struct vnode *vp, *xp;
647 	int error;
648 
649 	ndp->ni_nameiop = LOOKUP | FOLLOW;
650 	ndp->ni_segflg = UIO_USERSPACE;
651 	ndp->ni_dirp = uap->target;
652 	if (error = namei(ndp))
653 		RETURN (error);
654 	vp = ndp->ni_vp;
655 	if (vp->v_type == VDIR &&
656 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
657 		goto out1;
658 	ndp->ni_nameiop = CREATE | LOCKPARENT;
659 	ndp->ni_dirp = (caddr_t)uap->linkname;
660 	if (error = namei(ndp))
661 		goto out1;
662 	xp = ndp->ni_vp;
663 	if (xp != NULL) {
664 		error = EEXIST;
665 		goto out;
666 	}
667 	xp = ndp->ni_dvp;
668 	if (vp->v_mount != xp->v_mount)
669 		error = EXDEV;
670 out:
671 	if (error)
672 		VOP_ABORTOP(ndp);
673 	else
674 		error = VOP_LINK(vp, ndp);
675 out1:
676 	vrele(vp);
677 	RETURN (error);
678 }
679 
680 /*
681  * symlink -- make a symbolic link
682  */
683 symlink(scp)
684 	register struct syscontext *scp;
685 {
686 	struct a {
687 		char	*target;
688 		char	*linkname;
689 	} *uap = (struct a *)scp->sc_ap;
690 	register struct nameidata *ndp = &scp->sc_nd;
691 	register struct vnode *vp;
692 	struct vattr vattr;
693 	char *target;
694 	int error;
695 
696 	ndp->ni_segflg = UIO_USERSPACE;
697 	ndp->ni_dirp = uap->linkname;
698 	MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
699 	if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
700 		goto out1;
701 	ndp->ni_nameiop = CREATE | LOCKPARENT;
702 	if (error = namei(ndp))
703 		goto out1;
704 	vp = ndp->ni_vp;
705 	if (vp) {
706 		error = EEXIST;
707 		goto out;
708 	}
709 	vp = ndp->ni_dvp;
710 	vattr_null(&vattr);
711 	vattr.va_mode = 0777 &~ scp->sc_cmask;
712 out:
713 	if (error)
714 		VOP_ABORTOP(ndp);
715 	else
716 		error = VOP_SYMLINK(ndp, &vattr, target);
717 out1:
718 	FREE(target, M_NAMEI);
719 	RETURN (error);
720 }
721 
722 /*
723  * Unlink system call.
724  * Hard to avoid races here, especially
725  * in unlinking directories.
726  */
727 unlink(scp)
728 	register struct syscontext *scp;
729 {
730 	struct a {
731 		char	*fname;
732 	} *uap = (struct a *)scp->sc_ap;
733 	register struct nameidata *ndp = &scp->sc_nd;
734 	register struct vnode *vp;
735 	int error;
736 
737 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
738 	ndp->ni_segflg = UIO_USERSPACE;
739 	ndp->ni_dirp = uap->fname;
740 	if (error = namei(ndp))
741 		RETURN (error);
742 	vp = ndp->ni_vp;
743 	if (vp->v_type == VDIR &&
744 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
745 		goto out;
746 	/*
747 	 * Don't unlink a mounted file.
748 	 */
749 	if (vp->v_flag & VROOT) {
750 		error = EBUSY;
751 		goto out;
752 	}
753 	if (vp->v_flag & VTEXT)
754 		xrele(vp);	/* try once to free text */
755 out:
756 	if (error)
757 		VOP_ABORTOP(ndp);
758 	else
759 		error = VOP_REMOVE(ndp);
760 	RETURN (error);
761 }
762 
763 /*
764  * Seek system call
765  */
766 lseek(scp)
767 	register struct syscontext *scp;
768 {
769 	register struct file *fp;
770 	register struct a {
771 		int	fdes;
772 		off_t	off;
773 		int	sbase;
774 	} *uap = (struct a *)scp->sc_ap;
775 	struct vattr vattr;
776 	int error;
777 
778 	if ((unsigned)uap->fdes >= NOFILE ||
779 	    (fp = scp->sc_ofile[uap->fdes]) == NULL)
780 		RETURN (EBADF);
781 	if (fp->f_type != DTYPE_VNODE)
782 		RETURN (ESPIPE);
783 	switch (uap->sbase) {
784 
785 	case L_INCR:
786 		fp->f_offset += uap->off;
787 		break;
788 
789 	case L_XTND:
790 		if (error = VOP_GETATTR((struct vnode *)fp->f_data,
791 		    &vattr, scp->sc_cred))
792 			RETURN (error);
793 		fp->f_offset = uap->off + vattr.va_size;
794 		break;
795 
796 	case L_SET:
797 		fp->f_offset = uap->off;
798 		break;
799 
800 	default:
801 		RETURN (EINVAL);
802 	}
803 	scp->sc_offset = fp->f_offset;
804 	RETURN (0);
805 }
806 
807 /*
808  * Access system call
809  */
810 saccess(scp)
811 	register struct syscontext *scp;
812 {
813 	register struct a {
814 		char	*fname;
815 		int	fmode;
816 	} *uap = (struct a *)scp->sc_ap;
817 	register struct nameidata *ndp = &scp->sc_nd;
818 	register struct vnode *vp;
819 	int error, mode, svuid, svgid;
820 
821 	svuid = scp->sc_uid;
822 	svgid = scp->sc_gid;
823 	scp->sc_uid = scp->sc_ruid;
824 	scp->sc_gid = scp->sc_rgid;
825 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
826 	ndp->ni_segflg = UIO_USERSPACE;
827 	ndp->ni_dirp = uap->fname;
828 	if (error = namei(ndp))
829 		goto out1;
830 	vp = ndp->ni_vp;
831 	/*
832 	 * fmode == 0 means only check for exist
833 	 */
834 	if (uap->fmode) {
835 		mode = 0;
836 		if (uap->fmode & R_OK)
837 			mode |= VREAD;
838 		if (uap->fmode & W_OK)
839 			mode |= VWRITE;
840 		if (uap->fmode & X_OK)
841 			mode |= VEXEC;
842 		if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
843 			error = VOP_ACCESS(vp, mode, ndp->ni_cred);
844 	}
845 	vput(vp);
846 out1:
847 	scp->sc_uid = svuid;
848 	scp->sc_gid = svgid;
849 	RETURN (error);
850 }
851 
852 /*
853  * Stat system call.  This version follows links.
854  */
855 stat(scp)
856 	struct syscontext *scp;
857 {
858 
859 	stat1(scp, FOLLOW);
860 }
861 
862 /*
863  * Lstat system call.  This version does not follow links.
864  */
865 lstat(scp)
866 	struct syscontext *scp;
867 {
868 
869 	stat1(scp, NOFOLLOW);
870 }
871 
872 stat1(scp, follow)
873 	register struct syscontext *scp;
874 	int follow;
875 {
876 	register struct a {
877 		char	*fname;
878 		struct stat *ub;
879 	} *uap = (struct a *)scp->sc_ap;
880 	register struct nameidata *ndp = &scp->sc_nd;
881 	struct stat sb;
882 	int error;
883 
884 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow;
885 	ndp->ni_segflg = UIO_USERSPACE;
886 	ndp->ni_dirp = uap->fname;
887 	if (error = namei(ndp))
888 		RETURN (error);
889 	error = vn_stat(ndp->ni_vp, &sb);
890 	vput(ndp->ni_vp);
891 	if (error)
892 		RETURN (error);
893 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
894 	RETURN (error);
895 }
896 
897 /*
898  * Return target name of a symbolic link
899  */
900 readlink(scp)
901 	register struct syscontext *scp;
902 {
903 	register struct a {
904 		char	*name;
905 		char	*buf;
906 		int	count;
907 	} *uap = (struct a *)scp->sc_ap;
908 	register struct nameidata *ndp = &scp->sc_nd;
909 	register struct vnode *vp;
910 	struct iovec aiov;
911 	struct uio auio;
912 	int error;
913 
914 	ndp->ni_nameiop = LOOKUP | LOCKLEAF;
915 	ndp->ni_segflg = UIO_USERSPACE;
916 	ndp->ni_dirp = uap->name;
917 	if (error = namei(ndp))
918 		RETURN (error);
919 	vp = ndp->ni_vp;
920 	if (vp->v_type != VLNK) {
921 		error = EINVAL;
922 		goto out;
923 	}
924 	aiov.iov_base = uap->buf;
925 	aiov.iov_len = uap->count;
926 	auio.uio_iov = &aiov;
927 	auio.uio_iovcnt = 1;
928 	auio.uio_offset = 0;
929 	auio.uio_rw = UIO_READ;
930 	auio.uio_segflg = UIO_USERSPACE;
931 	auio.uio_resid = uap->count;
932 	error = VOP_READLINK(vp, &auio, ndp->ni_cred);
933 out:
934 	vput(vp);
935 	scp->sc_retval1 = uap->count - auio.uio_resid;
936 	RETURN (error);
937 }
938 
939 /*
940  * Change flags of a file given path name.
941  */
942 chflags(scp)
943 	register struct syscontext *scp;
944 {
945 	struct a {
946 		char	*fname;
947 		int	flags;
948 	} *uap = (struct a *)scp->sc_ap;
949 	register struct nameidata *ndp = &scp->sc_nd;
950 	register struct vnode *vp;
951 	struct vattr vattr;
952 	int error;
953 
954 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
955 	ndp->ni_segflg = UIO_USERSPACE;
956 	ndp->ni_dirp = uap->fname;
957 	vattr_null(&vattr);
958 	vattr.va_flags = uap->flags;
959 	if (error = namei(ndp))
960 		RETURN (error);
961 	vp = ndp->ni_vp;
962 	if (vp->v_mount->m_flag & M_RDONLY) {
963 		error = EROFS;
964 		goto out;
965 	}
966 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
967 out:
968 	vput(vp);
969 	RETURN (error);
970 }
971 
972 /*
973  * Change flags of a file given a file descriptor.
974  */
975 fchflags(scp)
976 	register struct syscontext *scp;
977 {
978 	struct a {
979 		int	fd;
980 		int	flags;
981 	} *uap = (struct a *)scp->sc_ap;
982 	struct vattr vattr;
983 	struct vnode *vp;
984 	struct file *fp;
985 	int error;
986 
987 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
988 		RETURN (error);
989 	vattr_null(&vattr);
990 	vattr.va_flags = uap->flags;
991 	vp = (struct vnode *)fp->f_data;
992 	VOP_LOCK(vp);
993 	if (vp->v_mount->m_flag & M_RDONLY) {
994 		error = EROFS;
995 		goto out;
996 	}
997 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
998 out:
999 	VOP_UNLOCK(vp);
1000 	RETURN (error);
1001 }
1002 
1003 /*
1004  * Change mode of a file given path name.
1005  */
1006 chmod(scp)
1007 	register struct syscontext *scp;
1008 {
1009 	struct a {
1010 		char	*fname;
1011 		int	fmode;
1012 	} *uap = (struct a *)scp->sc_ap;
1013 	register struct nameidata *ndp = &scp->sc_nd;
1014 	register struct vnode *vp;
1015 	struct vattr vattr;
1016 	int error;
1017 
1018 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1019 	ndp->ni_segflg = UIO_USERSPACE;
1020 	ndp->ni_dirp = uap->fname;
1021 	vattr_null(&vattr);
1022 	vattr.va_mode = uap->fmode & 07777;
1023 	if (error = namei(ndp))
1024 		RETURN (error);
1025 	vp = ndp->ni_vp;
1026 	if (vp->v_mount->m_flag & M_RDONLY) {
1027 		error = EROFS;
1028 		goto out;
1029 	}
1030 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1031 out:
1032 	vput(vp);
1033 	RETURN (error);
1034 }
1035 
1036 /*
1037  * Change mode of a file given a file descriptor.
1038  */
1039 fchmod(scp)
1040 	register struct syscontext *scp;
1041 {
1042 	struct a {
1043 		int	fd;
1044 		int	fmode;
1045 	} *uap = (struct a *)scp->sc_ap;
1046 	struct vattr vattr;
1047 	struct vnode *vp;
1048 	struct file *fp;
1049 	int error;
1050 
1051 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
1052 		RETURN (error);
1053 	vattr_null(&vattr);
1054 	vattr.va_mode = uap->fmode & 07777;
1055 	vp = (struct vnode *)fp->f_data;
1056 	VOP_LOCK(vp);
1057 	if (vp->v_mount->m_flag & M_RDONLY) {
1058 		error = EROFS;
1059 		goto out;
1060 	}
1061 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1062 out:
1063 	VOP_UNLOCK(vp);
1064 	RETURN (error);
1065 }
1066 
1067 /*
1068  * Set ownership given a path name.
1069  */
1070 chown(scp)
1071 	register struct syscontext *scp;
1072 {
1073 	struct a {
1074 		char	*fname;
1075 		int	uid;
1076 		int	gid;
1077 	} *uap = (struct a *)scp->sc_ap;
1078 	register struct nameidata *ndp = &scp->sc_nd;
1079 	register struct vnode *vp;
1080 	struct vattr vattr;
1081 	int error;
1082 
1083 	ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF;
1084 	ndp->ni_segflg = UIO_USERSPACE;
1085 	ndp->ni_dirp = uap->fname;
1086 	vattr_null(&vattr);
1087 	vattr.va_uid = uap->uid;
1088 	vattr.va_gid = uap->gid;
1089 	if (error = namei(ndp))
1090 		RETURN (error);
1091 	vp = ndp->ni_vp;
1092 	if (vp->v_mount->m_flag & M_RDONLY) {
1093 		error = EROFS;
1094 		goto out;
1095 	}
1096 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1097 out:
1098 	vput(vp);
1099 	RETURN (error);
1100 }
1101 
1102 /*
1103  * Set ownership given a file descriptor.
1104  */
1105 fchown(scp)
1106 	register struct syscontext *scp;
1107 {
1108 	struct a {
1109 		int	fd;
1110 		int	uid;
1111 		int	gid;
1112 	} *uap = (struct a *)scp->sc_ap;
1113 	struct vattr vattr;
1114 	struct vnode *vp;
1115 	struct file *fp;
1116 	int error;
1117 
1118 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
1119 		RETURN (error);
1120 	vattr_null(&vattr);
1121 	vattr.va_uid = uap->uid;
1122 	vattr.va_gid = uap->gid;
1123 	vp = (struct vnode *)fp->f_data;
1124 	VOP_LOCK(vp);
1125 	if (vp->v_mount->m_flag & M_RDONLY) {
1126 		error = EROFS;
1127 		goto out;
1128 	}
1129 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1130 out:
1131 	VOP_UNLOCK(vp);
1132 	RETURN (error);
1133 }
1134 
1135 utimes(scp)
1136 	register struct syscontext *scp;
1137 {
1138 	register struct a {
1139 		char	*fname;
1140 		struct	timeval *tptr;
1141 	} *uap = (struct a *)scp->sc_ap;
1142 	register struct nameidata *ndp = &scp->sc_nd;
1143 	register struct vnode *vp;
1144 	struct timeval tv[2];
1145 	struct vattr vattr;
1146 	int error;
1147 
1148 	if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1149 		RETURN (error);
1150 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1151 	ndp->ni_segflg = UIO_USERSPACE;
1152 	ndp->ni_dirp = uap->fname;
1153 	vattr_null(&vattr);
1154 	vattr.va_atime = tv[0];
1155 	vattr.va_mtime = tv[1];
1156 	if (error = namei(ndp))
1157 		RETURN (error);
1158 	vp = ndp->ni_vp;
1159 	if (vp->v_mount->m_flag & M_RDONLY) {
1160 		error = EROFS;
1161 		goto out;
1162 	}
1163 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1164 out:
1165 	vput(vp);
1166 	RETURN (error);
1167 }
1168 
1169 /*
1170  * Truncate a file given its path name.
1171  */
1172 truncate(scp)
1173 	register struct syscontext *scp;
1174 {
1175 	struct a {
1176 		char	*fname;
1177 		off_t	length;
1178 	} *uap = (struct a *)scp->sc_ap;
1179 	register struct nameidata *ndp = &scp->sc_nd;
1180 	register struct vnode *vp;
1181 	struct vattr vattr;
1182 	int error;
1183 
1184 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1185 	ndp->ni_segflg = UIO_USERSPACE;
1186 	ndp->ni_dirp = uap->fname;
1187 	vattr_null(&vattr);
1188 	vattr.va_size = uap->length;
1189 	if (error = namei(ndp))
1190 		RETURN (error);
1191 	vp = ndp->ni_vp;
1192 	if (vp->v_type == VDIR) {
1193 		error = EISDIR;
1194 		goto out;
1195 	}
1196 	if ((error = vn_writechk(vp)) ||
1197 	    (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
1198 		goto out;
1199 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1200 out:
1201 	vput(vp);
1202 	RETURN (error);
1203 }
1204 
1205 /*
1206  * Truncate a file given a file descriptor.
1207  */
1208 ftruncate(scp)
1209 	register struct syscontext *scp;
1210 {
1211 	struct a {
1212 		int	fd;
1213 		off_t	length;
1214 	} *uap = (struct a *)scp->sc_ap;
1215 	struct vattr vattr;
1216 	struct vnode *vp;
1217 	struct file *fp;
1218 	int error;
1219 
1220 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
1221 		RETURN (error);
1222 	if ((fp->f_flag & FWRITE) == 0)
1223 		RETURN (EINVAL);
1224 	vattr_null(&vattr);
1225 	vattr.va_size = uap->length;
1226 	vp = (struct vnode *)fp->f_data;
1227 	VOP_LOCK(vp);
1228 	if (vp->v_type == VDIR) {
1229 		error = EISDIR;
1230 		goto out;
1231 	}
1232 	if (error = vn_writechk(vp))
1233 		goto out;
1234 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1235 out:
1236 	VOP_UNLOCK(vp);
1237 	RETURN (error);
1238 }
1239 
1240 /*
1241  * Synch an open file.
1242  */
1243 fsync(scp)
1244 	register struct syscontext *scp;
1245 {
1246 	struct a {
1247 		int	fd;
1248 	} *uap = (struct a *)scp->sc_ap;
1249 	register struct vnode *vp;
1250 	struct file *fp;
1251 	int error;
1252 
1253 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
1254 		RETURN (error);
1255 	vp = (struct vnode *)fp->f_data;
1256 	VOP_LOCK(vp);
1257 	error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT);
1258 	VOP_UNLOCK(vp);
1259 	RETURN (error);
1260 }
1261 
1262 /*
1263  * Rename system call.
1264  *
1265  * Source and destination must either both be directories, or both
1266  * not be directories.  If target is a directory, it must be empty.
1267  */
1268 rename(scp)
1269 	register struct syscontext *scp;
1270 {
1271 	struct a {
1272 		char	*from;
1273 		char	*to;
1274 	} *uap = (struct a *)scp->sc_ap;
1275 	register struct vnode *tvp, *fvp, *tdvp;
1276 	register struct nameidata *ndp = &scp->sc_nd;
1277 	struct nameidata tond;
1278 	int error;
1279 
1280 	ndp->ni_nameiop = DELETE | WANTPARENT;
1281 	ndp->ni_segflg = UIO_USERSPACE;
1282 	ndp->ni_dirp = uap->from;
1283 	if (error = namei(ndp))
1284 		RETURN (error);
1285 	fvp = ndp->ni_vp;
1286 	nddup(ndp, &tond);
1287 	tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
1288 	tond.ni_segflg = UIO_USERSPACE;
1289 	tond.ni_dirp = uap->to;
1290 	error = namei(&tond);
1291 	tdvp = tond.ni_dvp;
1292 	tvp = tond.ni_vp;
1293 	if (tvp != NULL) {
1294 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1295 			error = ENOTDIR;
1296 			goto out;
1297 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1298 			error = EISDIR;
1299 			goto out;
1300 		}
1301 	}
1302 	if (error) {
1303 		VOP_ABORTOP(ndp);
1304 		goto out1;
1305 	}
1306 	if (fvp->v_mount != tdvp->v_mount) {
1307 		error = EXDEV;
1308 		goto out;
1309 	}
1310 	if (fvp == tdvp)
1311 		error = EINVAL;
1312 	/*
1313 	 * If source is the same as the destination,
1314 	 * then there is nothing to do.
1315 	 */
1316 	if (fvp == tvp)
1317 		error = -1;
1318 out:
1319 	if (error) {
1320 		VOP_ABORTOP(&tond);
1321 		VOP_ABORTOP(ndp);
1322 	} else {
1323 		error = VOP_RENAME(ndp, &tond);
1324 	}
1325 out1:
1326 	ndrele(&tond);
1327 	if (error == -1)
1328 		RETURN (0);
1329 	RETURN (error);
1330 }
1331 
1332 /*
1333  * Mkdir system call
1334  */
1335 mkdir(scp)
1336 	register struct syscontext *scp;
1337 {
1338 	struct a {
1339 		char	*name;
1340 		int	dmode;
1341 	} *uap = (struct a *)scp->sc_ap;
1342 	register struct nameidata *ndp = &scp->sc_nd;
1343 	register struct vnode *vp;
1344 	struct vattr vattr;
1345 	int error;
1346 
1347 	ndp->ni_nameiop = CREATE | LOCKPARENT;
1348 	ndp->ni_segflg = UIO_USERSPACE;
1349 	ndp->ni_dirp = uap->name;
1350 	if (error = namei(ndp))
1351 		RETURN (error);
1352 	vp = ndp->ni_vp;
1353 	if (vp != NULL) {
1354 		VOP_ABORTOP(ndp);
1355 		RETURN (EEXIST);
1356 	}
1357 	vattr_null(&vattr);
1358 	vattr.va_type = VDIR;
1359 	vattr.va_mode = (uap->dmode & 0777) &~ scp->sc_cmask;
1360 	error = VOP_MKDIR(ndp, &vattr);
1361 	if (!error)
1362 		vput(ndp->ni_vp);
1363 	RETURN (error);
1364 }
1365 
1366 /*
1367  * Rmdir system call.
1368  */
1369 rmdir(scp)
1370 	register struct syscontext *scp;
1371 {
1372 	struct a {
1373 		char	*name;
1374 	} *uap = (struct a *)scp->sc_ap;
1375 	register struct nameidata *ndp = &scp->sc_nd;
1376 	register struct vnode *vp;
1377 	int error;
1378 
1379 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
1380 	ndp->ni_segflg = UIO_USERSPACE;
1381 	ndp->ni_dirp = uap->name;
1382 	if (error = namei(ndp))
1383 		RETURN (error);
1384 	vp = ndp->ni_vp;
1385 	if (vp->v_type != VDIR) {
1386 		error = ENOTDIR;
1387 		goto out;
1388 	}
1389 	/*
1390 	 * No rmdir "." please.
1391 	 */
1392 	if (ndp->ni_dvp == vp) {
1393 		error = EINVAL;
1394 		goto out;
1395 	}
1396 	/*
1397 	 * Don't unlink a mounted file.
1398 	 */
1399 	if (vp->v_flag & VROOT)
1400 		error = EBUSY;
1401 out:
1402 	if (error)
1403 		VOP_ABORTOP(ndp);
1404 	else
1405 		error = VOP_RMDIR(ndp);
1406 	RETURN (error);
1407 }
1408 
1409 /*
1410  * Read a block of directory entries in a file system independent format
1411  */
1412 getdirentries(scp)
1413 	register struct syscontext *scp;
1414 {
1415 	register struct a {
1416 		int	fd;
1417 		char	*buf;
1418 		unsigned count;
1419 		long	*basep;
1420 	} *uap = (struct a *)scp->sc_ap;
1421 	register struct vnode *vp;
1422 	struct file *fp;
1423 	struct uio auio;
1424 	struct iovec aiov;
1425 	off_t off;
1426 	int error, eofflag;
1427 
1428 	if (error = getvnode(scp->sc_ofile, uap->fd, &fp))
1429 		RETURN (error);
1430 	if ((fp->f_flag & FREAD) == 0)
1431 		RETURN (EBADF);
1432 	vp = (struct vnode *)fp->f_data;
1433 	if (vp->v_type != VDIR)
1434 		RETURN (EINVAL);
1435 	aiov.iov_base = uap->buf;
1436 	aiov.iov_len = uap->count;
1437 	auio.uio_iov = &aiov;
1438 	auio.uio_iovcnt = 1;
1439 	auio.uio_rw = UIO_READ;
1440 	auio.uio_segflg = UIO_USERSPACE;
1441 	auio.uio_resid = uap->count;
1442 	VOP_LOCK(vp);
1443 	auio.uio_offset = off = fp->f_offset;
1444 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag);
1445 	fp->f_offset = auio.uio_offset;
1446 	VOP_UNLOCK(vp);
1447 	if (error)
1448 		RETURN (error);
1449 	error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
1450 	scp->sc_retval1 = uap->count - auio.uio_resid;
1451 	RETURN (error);
1452 }
1453 
1454 /*
1455  * mode mask for creation of files
1456  */
1457 umask(scp)
1458 	register struct syscontext *scp;
1459 {
1460 	register struct a {
1461 		int	mask;
1462 	} *uap = (struct a *)scp->sc_ap;
1463 
1464 	scp->sc_retval1 = scp->sc_cmask;
1465 	scp->sc_cmask = uap->mask & 07777;
1466 	RETURN (0);
1467 }
1468 
1469 /*
1470  * Void all references to file by ripping underlying filesystem
1471  * away from vnode.
1472  */
1473 revoke(scp)
1474 	register struct syscontext *scp;
1475 {
1476 	struct a {
1477 		char	*fname;
1478 	} *uap = (struct a *)scp->sc_ap;
1479 	register struct nameidata *ndp = &scp->sc_nd;
1480 	register struct vnode *vp;
1481 	struct vattr vattr;
1482 	int error;
1483 
1484 	ndp->ni_nameiop = LOOKUP | FOLLOW;
1485 	ndp->ni_segflg = UIO_USERSPACE;
1486 	ndp->ni_dirp = uap->fname;
1487 	if (error = namei(ndp))
1488 		RETURN (error);
1489 	vp = ndp->ni_vp;
1490 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
1491 		error = EINVAL;
1492 		goto out;
1493 	}
1494 	if (error = VOP_GETATTR(vp, &vattr, scp->sc_cred))
1495 		goto out;
1496 	if (scp->sc_uid != vattr.va_uid ||
1497 	    (error = suser(scp->sc_cred, &scp->sc_acflag)))
1498 		goto out;
1499 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
1500 		vgoneall(vp);
1501 out:
1502 	vrele(vp);
1503 	RETURN (error);
1504 }
1505 
1506 getvnode(ofile, fdes, fpp)
1507 	struct file *ofile[];
1508 	struct file **fpp;
1509 	int fdes;
1510 {
1511 	struct file *fp;
1512 
1513 	if ((unsigned)fdes >= NOFILE || (fp = ofile[fdes]) == NULL)
1514 		return (EBADF);
1515 	if (fp->f_type != DTYPE_VNODE)
1516 		return (EINVAL);
1517 	*fpp = fp;
1518 	return (0);
1519 }
1520