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