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