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