xref: /freebsd/sys/kern/vfs_extattr.c (revision afe61c15161c324a7af299a9b8457aba5afc92db)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)vfs_syscalls.c	8.13 (Berkeley) 4/15/94
39  */
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/namei.h>
44 #include <sys/filedesc.h>
45 #include <sys/kernel.h>
46 #include <sys/file.h>
47 #include <sys/stat.h>
48 #include <sys/vnode.h>
49 #include <sys/mount.h>
50 #include <sys/proc.h>
51 #include <sys/uio.h>
52 #include <sys/malloc.h>
53 #include <sys/dirent.h>
54 
55 #include <vm/vm.h>
56 #include <sys/sysctl.h>
57 
58 void	cvtstat		__P((struct stat *, struct ostat *));
59 static int change_dir	__P((struct nameidata *ndp, struct proc *p));
60 
61 /*
62  * Virtual File System System Calls
63  */
64 
65 /*
66  * Mount a file system.
67  */
68 struct mount_args {
69 	int	type;
70 	char	*path;
71 	int	flags;
72 	caddr_t	data;
73 };
74 /* ARGSUSED */
75 int
76 mount(p, uap, retval)
77 	struct proc *p;
78 	register struct mount_args *uap;
79 	int *retval;
80 {
81 	register struct vnode *vp;
82 	register struct mount *mp;
83 	int error, flag = 0;
84 	struct nameidata nd;
85 
86 	/*
87 	 * Must be super user
88 	 */
89 	if (error = suser(p->p_ucred, &p->p_acflag))
90 		return (error);
91 	/*
92 	 * Get vnode to be covered
93 	 */
94 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
95 	if (error = namei(&nd))
96 		return (error);
97 	vp = nd.ni_vp;
98 	if (uap->flags & MNT_UPDATE) {
99 		if ((vp->v_flag & VROOT) == 0) {
100 			vput(vp);
101 			return (EINVAL);
102 		}
103 		mp = vp->v_mount;
104 		flag = mp->mnt_flag;
105 		/*
106 		 * We only allow the filesystem to be reloaded if it
107 		 * is currently mounted read-only.
108 		 */
109 		if ((uap->flags & MNT_RELOAD) &&
110 		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
111 			vput(vp);
112 			return (EOPNOTSUPP);	/* Needs translation */
113 		}
114 		mp->mnt_flag |=
115 		    uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
116 		VOP_UNLOCK(vp);
117 		goto update;
118 	}
119 	if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
120 		return (error);
121 	if (vp->v_type != VDIR) {
122 		vput(vp);
123 		return (ENOTDIR);
124 	}
125 	if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) {
126 		vput(vp);
127 		return (ENODEV);
128 	}
129 
130 	/*
131 	 * Allocate and initialize the file system.
132 	 */
133 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
134 		M_MOUNT, M_WAITOK);
135 	bzero((char *)mp, (u_long)sizeof(struct mount));
136 	mp->mnt_op = vfssw[uap->type];
137 	if (error = vfs_lock(mp)) {
138 		free((caddr_t)mp, M_MOUNT);
139 		vput(vp);
140 		return (error);
141 	}
142 	if (vp->v_mountedhere != NULL) {
143 		vfs_unlock(mp);
144 		free((caddr_t)mp, M_MOUNT);
145 		vput(vp);
146 		return (EBUSY);
147 	}
148 	vp->v_mountedhere = mp;
149 	mp->mnt_vnodecovered = vp;
150 update:
151 	/*
152 	 * Set the mount level flags.
153 	 */
154 	if (uap->flags & MNT_RDONLY)
155 		mp->mnt_flag |= MNT_RDONLY;
156 	else if (mp->mnt_flag & MNT_RDONLY)
157 		mp->mnt_flag |= MNT_WANTRDWR;
158 	mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
159 	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
160 	mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
161 	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
162 	/*
163 	 * Mount the filesystem.
164 	 */
165 	error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p);
166 	if (mp->mnt_flag & MNT_UPDATE) {
167 		vrele(vp);
168 		if (mp->mnt_flag & MNT_WANTRDWR)
169 			mp->mnt_flag &= ~MNT_RDONLY;
170 		mp->mnt_flag &=~
171 		    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
172 		if (error)
173 			mp->mnt_flag = flag;
174 		return (error);
175 	}
176 	/*
177 	 * Put the new filesystem on the mount list after root.
178 	 */
179 	cache_purge(vp);
180 	if (!error) {
181 		TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
182 		VOP_UNLOCK(vp);
183 		vfs_unlock(mp);
184 		error = VFS_START(mp, 0, p);
185 	} else {
186 		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
187 		vfs_unlock(mp);
188 		free((caddr_t)mp, M_MOUNT);
189 		vput(vp);
190 	}
191 	return (error);
192 }
193 
194 /*
195  * Unmount a file system.
196  *
197  * Note: unmount takes a path to the vnode mounted on as argument,
198  * not special file (as before).
199  */
200 struct unmount_args {
201 	char	*path;
202 	int	flags;
203 };
204 /* ARGSUSED */
205 int
206 unmount(p, uap, retval)
207 	struct proc *p;
208 	register struct unmount_args *uap;
209 	int *retval;
210 {
211 	register struct vnode *vp;
212 	struct mount *mp;
213 	int error;
214 	struct nameidata nd;
215 
216 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
217 	if (error = namei(&nd))
218 		return (error);
219 	vp = nd.ni_vp;
220 
221 	/*
222 	 * Unless this is a user mount, then must
223 	 * have suser privilege.
224 	 */
225 	if (((vp->v_mount->mnt_flag & MNT_USER) == 0) &&
226 	    (error = suser(p->p_ucred, &p->p_acflag))) {
227 		vput(vp);
228 		return (error);
229 	}
230 
231 	/*
232 	 * Must be the root of the filesystem
233 	 */
234 	if ((vp->v_flag & VROOT) == 0) {
235 		vput(vp);
236 		return (EINVAL);
237 	}
238 	mp = vp->v_mount;
239 	vput(vp);
240 	return (dounmount(mp, uap->flags, p));
241 }
242 
243 /*
244  * Do the actual file system unmount.
245  */
246 int
247 dounmount(mp, flags, p)
248 	register struct mount *mp;
249 	int flags;
250 	struct proc *p;
251 {
252 	struct vnode *coveredvp;
253 	int error;
254 
255 	coveredvp = mp->mnt_vnodecovered;
256 	if (vfs_busy(mp))
257 		return (EBUSY);
258 	mp->mnt_flag |= MNT_UNMOUNT;
259 	if (error = vfs_lock(mp))
260 		return (error);
261 
262 	mp->mnt_flag &=~ MNT_ASYNC;
263 	vnode_pager_umount(mp);	/* release cached vnodes */
264 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
265 	if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
266 	    (flags & MNT_FORCE))
267 		error = VFS_UNMOUNT(mp, flags, p);
268 	mp->mnt_flag &= ~MNT_UNMOUNT;
269 	vfs_unbusy(mp);
270 	if (error) {
271 		vfs_unlock(mp);
272 	} else {
273 		vrele(coveredvp);
274 		TAILQ_REMOVE(&mountlist, mp, mnt_list);
275 		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
276 		vfs_unlock(mp);
277 		if (mp->mnt_vnodelist.lh_first != NULL)
278 			panic("unmount: dangling vnode");
279 		free((caddr_t)mp, M_MOUNT);
280 	}
281 	return (error);
282 }
283 
284 /*
285  * Sync each mounted filesystem.
286  */
287 #ifdef DIAGNOSTIC
288 int syncprt = 0;
289 struct ctldebug debug0 = { "syncprt", &syncprt };
290 #endif
291 
292 struct sync_args {
293 	int	dummy;
294 };
295 /* ARGSUSED */
296 int
297 sync(p, uap, retval)
298 	struct proc *p;
299 	struct sync_args *uap;
300 	int *retval;
301 {
302 	register struct mount *mp, *nmp;
303 	int asyncflag;
304 
305 	for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
306 		nmp = mp->mnt_list.tqe_next;
307 		/*
308 		 * The lock check below is to avoid races with mount
309 		 * and unmount.
310 		 */
311 		if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
312 		    !vfs_busy(mp)) {
313 			asyncflag = mp->mnt_flag & MNT_ASYNC;
314 			mp->mnt_flag &= ~MNT_ASYNC;
315 			VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
316 			if (asyncflag)
317 				mp->mnt_flag |= MNT_ASYNC;
318 			vfs_unbusy(mp);
319 		}
320 	}
321 #ifdef DIAGNOSTIC
322 	if (syncprt)
323 		vfs_bufstats();
324 #endif /* DIAGNOSTIC */
325 	return (0);
326 }
327 
328 /*
329  * Change filesystem quotas.
330  */
331 struct quotactl_args {
332 	char *path;
333 	int cmd;
334 	int uid;
335 	caddr_t arg;
336 };
337 /* ARGSUSED */
338 int
339 quotactl(p, uap, retval)
340 	struct proc *p;
341 	register struct quotactl_args *uap;
342 	int *retval;
343 {
344 	register struct mount *mp;
345 	int error;
346 	struct nameidata nd;
347 
348 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
349 	if (error = namei(&nd))
350 		return (error);
351 	mp = nd.ni_vp->v_mount;
352 	vrele(nd.ni_vp);
353 	return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
354 }
355 
356 /*
357  * Get filesystem statistics.
358  */
359 struct statfs_args {
360 	char *path;
361 	struct statfs *buf;
362 };
363 /* ARGSUSED */
364 int
365 statfs(p, uap, retval)
366 	struct proc *p;
367 	register struct statfs_args *uap;
368 	int *retval;
369 {
370 	register struct mount *mp;
371 	register struct statfs *sp;
372 	int error;
373 	struct nameidata nd;
374 
375 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
376 	if (error = namei(&nd))
377 		return (error);
378 	mp = nd.ni_vp->v_mount;
379 	sp = &mp->mnt_stat;
380 	vrele(nd.ni_vp);
381 	if (error = VFS_STATFS(mp, sp, p))
382 		return (error);
383 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
384 	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
385 }
386 
387 /*
388  * Get filesystem statistics.
389  */
390 struct fstatfs_args {
391 	int fd;
392 	struct statfs *buf;
393 };
394 /* ARGSUSED */
395 int
396 fstatfs(p, uap, retval)
397 	struct proc *p;
398 	register struct fstatfs_args *uap;
399 	int *retval;
400 {
401 	struct file *fp;
402 	struct mount *mp;
403 	register struct statfs *sp;
404 	int error;
405 
406 	if (error = getvnode(p->p_fd, uap->fd, &fp))
407 		return (error);
408 	mp = ((struct vnode *)fp->f_data)->v_mount;
409 	sp = &mp->mnt_stat;
410 	if (error = VFS_STATFS(mp, sp, p))
411 		return (error);
412 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
413 	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
414 }
415 
416 /*
417  * Get statistics on all filesystems.
418  */
419 struct getfsstat_args {
420 	struct statfs *buf;
421 	long bufsize;
422 	int flags;
423 };
424 int
425 getfsstat(p, uap, retval)
426 	struct proc *p;
427 	register struct getfsstat_args *uap;
428 	int *retval;
429 {
430 	register struct mount *mp, *nmp;
431 	register struct statfs *sp;
432 	caddr_t sfsp;
433 	long count, maxcount, error;
434 
435 	maxcount = uap->bufsize / sizeof(struct statfs);
436 	sfsp = (caddr_t)uap->buf;
437 	for (count = 0, mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
438 		nmp = mp->mnt_list.tqe_next;
439 		if (sfsp && count < maxcount &&
440 		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
441 			sp = &mp->mnt_stat;
442 			/*
443 			 * If MNT_NOWAIT is specified, do not refresh the
444 			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
445 			 */
446 			if (((uap->flags & MNT_NOWAIT) == 0 ||
447 			    (uap->flags & MNT_WAIT)) &&
448 			    (error = VFS_STATFS(mp, sp, p)))
449 				continue;
450 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
451 			if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
452 				return (error);
453 			sfsp += sizeof(*sp);
454 		}
455 		count++;
456 	}
457 	if (sfsp && count > maxcount)
458 		*retval = maxcount;
459 	else
460 		*retval = count;
461 	return (0);
462 }
463 
464 /*
465  * Change current working directory to a given file descriptor.
466  */
467 struct fchdir_args {
468 	int	fd;
469 };
470 /* ARGSUSED */
471 int
472 fchdir(p, uap, retval)
473 	struct proc *p;
474 	struct fchdir_args *uap;
475 	int *retval;
476 {
477 	register struct filedesc *fdp = p->p_fd;
478 	register struct vnode *vp;
479 	struct file *fp;
480 	int error;
481 
482 	if (error = getvnode(fdp, uap->fd, &fp))
483 		return (error);
484 	vp = (struct vnode *)fp->f_data;
485 	VOP_LOCK(vp);
486 	if (vp->v_type != VDIR)
487 		error = ENOTDIR;
488 	else
489 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
490 	VOP_UNLOCK(vp);
491 	if (error)
492 		return (error);
493 	VREF(vp);
494 	vrele(fdp->fd_cdir);
495 	fdp->fd_cdir = vp;
496 	return (0);
497 }
498 
499 /*
500  * Change current working directory (``.'').
501  */
502 struct chdir_args {
503 	char	*path;
504 };
505 /* ARGSUSED */
506 int
507 chdir(p, uap, retval)
508 	struct proc *p;
509 	struct chdir_args *uap;
510 	int *retval;
511 {
512 	register struct filedesc *fdp = p->p_fd;
513 	int error;
514 	struct nameidata nd;
515 
516 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
517 	if (error = change_dir(&nd, p))
518 		return (error);
519 	vrele(fdp->fd_cdir);
520 	fdp->fd_cdir = nd.ni_vp;
521 	return (0);
522 }
523 
524 /*
525  * Change notion of root (``/'') directory.
526  */
527 struct chroot_args {
528 	char	*path;
529 };
530 /* ARGSUSED */
531 int
532 chroot(p, uap, retval)
533 	struct proc *p;
534 	struct chroot_args *uap;
535 	int *retval;
536 {
537 	register struct filedesc *fdp = p->p_fd;
538 	int error;
539 	struct nameidata nd;
540 
541 	if (error = suser(p->p_ucred, &p->p_acflag))
542 		return (error);
543 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
544 	if (error = change_dir(&nd, p))
545 		return (error);
546 	if (fdp->fd_rdir != NULL)
547 		vrele(fdp->fd_rdir);
548 	fdp->fd_rdir = nd.ni_vp;
549 	return (0);
550 }
551 
552 /*
553  * Common routine for chroot and chdir.
554  */
555 static int
556 change_dir(ndp, p)
557 	register struct nameidata *ndp;
558 	struct proc *p;
559 {
560 	struct vnode *vp;
561 	int error;
562 
563 	if (error = namei(ndp))
564 		return (error);
565 	vp = ndp->ni_vp;
566 	if (vp->v_type != VDIR)
567 		error = ENOTDIR;
568 	else
569 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
570 	VOP_UNLOCK(vp);
571 	if (error)
572 		vrele(vp);
573 	return (error);
574 }
575 
576 /*
577  * Check permissions, allocate an open file structure,
578  * and call the device open routine if any.
579  */
580 struct open_args {
581 	char	*path;
582 	int	flags;
583 	int	mode;
584 };
585 int
586 open(p, uap, retval)
587 	struct proc *p;
588 	register struct open_args *uap;
589 	int *retval;
590 {
591 	register struct filedesc *fdp = p->p_fd;
592 	register struct file *fp;
593 	register struct vnode *vp;
594 	int flags, cmode;
595 	struct file *nfp;
596 	int type, indx, error;
597 	struct flock lf;
598 	struct nameidata nd;
599 	extern struct fileops vnops;
600 
601 	if (error = falloc(p, &nfp, &indx))
602 		return (error);
603 	fp = nfp;
604 	flags = FFLAGS(uap->flags);
605 	cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
606 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
607 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
608 	if (error = vn_open(&nd, flags, cmode)) {
609 		ffree(fp);
610 		if ((error == ENODEV || error == ENXIO) &&
611 		    p->p_dupfd >= 0 && 			/* XXX from fdopen */
612 		    (error =
613 		        dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
614 			*retval = indx;
615 			return (0);
616 		}
617 		if (error == ERESTART)
618 			error = EINTR;
619 		fdp->fd_ofiles[indx] = NULL;
620 		return (error);
621 	}
622 	p->p_dupfd = 0;
623 	vp = nd.ni_vp;
624 	fp->f_flag = flags & FMASK;
625 	fp->f_type = DTYPE_VNODE;
626 	fp->f_ops = &vnops;
627 	fp->f_data = (caddr_t)vp;
628 	if (flags & (O_EXLOCK | O_SHLOCK)) {
629 		lf.l_whence = SEEK_SET;
630 		lf.l_start = 0;
631 		lf.l_len = 0;
632 		if (flags & O_EXLOCK)
633 			lf.l_type = F_WRLCK;
634 		else
635 			lf.l_type = F_RDLCK;
636 		type = F_FLOCK;
637 		if ((flags & FNONBLOCK) == 0)
638 			type |= F_WAIT;
639 		VOP_UNLOCK(vp);
640 		if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
641 			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
642 			ffree(fp);
643 			fdp->fd_ofiles[indx] = NULL;
644 			return (error);
645 		}
646 		VOP_LOCK(vp);
647 		fp->f_flag |= FHASLOCK;
648 	}
649 	VOP_UNLOCK(vp);
650 	*retval = indx;
651 	return (0);
652 }
653 
654 #ifdef COMPAT_43
655 /*
656  * Create a file.
657  */
658 struct ocreat_args {
659 	char	*path;
660 	int	mode;
661 };
662 int
663 ocreat(p, uap, retval)
664 	struct proc *p;
665 	register struct ocreat_args *uap;
666 	int *retval;
667 {
668 	struct open_args openuap;
669 
670 	openuap.path = uap->path;
671 	openuap.mode = uap->mode;
672 	openuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
673 	return (open(p, &openuap, retval));
674 }
675 #endif /* COMPAT_43 */
676 
677 /*
678  * Create a special file.
679  */
680 struct mknod_args {
681 	char	*path;
682 	int	mode;
683 	int	dev;
684 };
685 /* ARGSUSED */
686 int
687 mknod(p, uap, retval)
688 	struct proc *p;
689 	register struct mknod_args *uap;
690 	int *retval;
691 {
692 	register struct vnode *vp;
693 	struct vattr vattr;
694 	int error;
695 	struct nameidata nd;
696 
697 	if (error = suser(p->p_ucred, &p->p_acflag))
698 		return (error);
699 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
700 	if (error = namei(&nd))
701 		return (error);
702 	vp = nd.ni_vp;
703 	if (vp != NULL)
704 		error = EEXIST;
705 	else {
706 		VATTR_NULL(&vattr);
707 		vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
708 		vattr.va_rdev = uap->dev;
709 
710 		switch (uap->mode & S_IFMT) {
711 		case S_IFMT:	/* used by badsect to flag bad sectors */
712 			vattr.va_type = VBAD;
713 			break;
714 		case S_IFCHR:
715 			vattr.va_type = VCHR;
716 			break;
717 		case S_IFBLK:
718 			vattr.va_type = VBLK;
719 			break;
720 		default:
721 			error = EINVAL;
722 			break;
723 		}
724 	}
725 	if (!error) {
726 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
727 		error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
728 	} else {
729 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
730 		if (nd.ni_dvp == vp)
731 			vrele(nd.ni_dvp);
732 		else
733 			vput(nd.ni_dvp);
734 		if (vp)
735 			vrele(vp);
736 	}
737 	return (error);
738 }
739 
740 /*
741  * Create named pipe.
742  */
743 struct mkfifo_args {
744 	char	*path;
745 	int	mode;
746 };
747 /* ARGSUSED */
748 int
749 mkfifo(p, uap, retval)
750 	struct proc *p;
751 	register struct mkfifo_args *uap;
752 	int *retval;
753 {
754 	struct vattr vattr;
755 	int error;
756 	struct nameidata nd;
757 
758 #ifndef FIFO
759 	return (EOPNOTSUPP);
760 #else
761 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
762 	if (error = namei(&nd))
763 		return (error);
764 	if (nd.ni_vp != NULL) {
765 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
766 		if (nd.ni_dvp == nd.ni_vp)
767 			vrele(nd.ni_dvp);
768 		else
769 			vput(nd.ni_dvp);
770 		vrele(nd.ni_vp);
771 		return (EEXIST);
772 	}
773 	VATTR_NULL(&vattr);
774 	vattr.va_type = VFIFO;
775 	vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
776 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
777 	return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
778 #endif /* FIFO */
779 }
780 
781 /*
782  * Make a hard file link.
783  */
784 struct link_args {
785 	char	*path;
786 	char	*link;
787 };
788 /* ARGSUSED */
789 int
790 link(p, uap, retval)
791 	struct proc *p;
792 	register struct link_args *uap;
793 	int *retval;
794 {
795 	register struct vnode *vp;
796 	struct nameidata nd;
797 	int error;
798 
799 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
800 	if (error = namei(&nd))
801 		return (error);
802 	vp = nd.ni_vp;
803 	if (vp->v_type != VDIR ||
804 	    (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
805 		nd.ni_cnd.cn_nameiop = CREATE;
806 		nd.ni_cnd.cn_flags = LOCKPARENT;
807 		nd.ni_dirp = uap->link;
808 		if ((error = namei(&nd)) == 0) {
809 			if (nd.ni_vp != NULL)
810 				error = EEXIST;
811 			if (!error) {
812 				LEASE_CHECK(nd.ni_dvp,
813 				    p, p->p_ucred, LEASE_WRITE);
814 				LEASE_CHECK(vp,
815 				    p, p->p_ucred, LEASE_WRITE);
816 				error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
817 			} else {
818 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
819 				if (nd.ni_dvp == nd.ni_vp)
820 					vrele(nd.ni_dvp);
821 				else
822 					vput(nd.ni_dvp);
823 				if (nd.ni_vp)
824 					vrele(nd.ni_vp);
825 			}
826 		}
827 	}
828 	vrele(vp);
829 	return (error);
830 }
831 
832 /*
833  * Make a symbolic link.
834  */
835 struct symlink_args {
836 	char	*path;
837 	char	*link;
838 };
839 /* ARGSUSED */
840 int
841 symlink(p, uap, retval)
842 	struct proc *p;
843 	register struct symlink_args *uap;
844 	int *retval;
845 {
846 	struct vattr vattr;
847 	char *path;
848 	int error;
849 	struct nameidata nd;
850 
851 	MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
852 	if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL))
853 		goto out;
854 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
855 	if (error = namei(&nd))
856 		goto out;
857 	if (nd.ni_vp) {
858 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
859 		if (nd.ni_dvp == nd.ni_vp)
860 			vrele(nd.ni_dvp);
861 		else
862 			vput(nd.ni_dvp);
863 		vrele(nd.ni_vp);
864 		error = EEXIST;
865 		goto out;
866 	}
867 	VATTR_NULL(&vattr);
868 	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
869 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
870 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
871 out:
872 	FREE(path, M_NAMEI);
873 	return (error);
874 }
875 
876 /*
877  * Delete a name from the filesystem.
878  */
879 struct unlink_args {
880 	char	*path;
881 };
882 /* ARGSUSED */
883 int
884 unlink(p, uap, retval)
885 	struct proc *p;
886 	struct unlink_args *uap;
887 	int *retval;
888 {
889 	register struct vnode *vp;
890 	int error;
891 	struct nameidata nd;
892 
893 	NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
894 	if (error = namei(&nd))
895 		return (error);
896 	vp = nd.ni_vp;
897 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
898 	VOP_LOCK(vp);
899 
900 	if (vp->v_type != VDIR ||
901 	    (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
902 		/*
903 		 * The root of a mounted filesystem cannot be deleted.
904 		 */
905 		if (vp->v_flag & VROOT)
906 			error = EBUSY;
907 		else
908 			(void)vnode_pager_uncache(vp);
909 	}
910 
911 	if (!error) {
912 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
913 		error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
914 	} else {
915 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
916 		if (nd.ni_dvp == vp)
917 			vrele(nd.ni_dvp);
918 		else
919 			vput(nd.ni_dvp);
920 		vput(vp);
921 	}
922 	return (error);
923 }
924 
925 /*
926  * Reposition read/write file offset.
927  */
928 struct lseek_args {
929 	int	fd;
930 	int	pad;
931 	off_t	offset;
932 	int	whence;
933 };
934 int
935 lseek(p, uap, retval)
936 	struct proc *p;
937 	register struct lseek_args *uap;
938 	int *retval;
939 {
940 	struct ucred *cred = p->p_ucred;
941 	register struct filedesc *fdp = p->p_fd;
942 	register struct file *fp;
943 	struct vattr vattr;
944 	int error;
945 
946 	if ((u_int)uap->fd >= fdp->fd_nfiles ||
947 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
948 		return (EBADF);
949 	if (fp->f_type != DTYPE_VNODE)
950 		return (ESPIPE);
951 	switch (uap->whence) {
952 	case L_INCR:
953 		fp->f_offset += uap->offset;
954 		break;
955 	case L_XTND:
956 		if (error =
957 		    VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p))
958 			return (error);
959 		fp->f_offset = uap->offset + vattr.va_size;
960 		break;
961 	case L_SET:
962 		fp->f_offset = uap->offset;
963 		break;
964 	default:
965 		return (EINVAL);
966 	}
967 	*(off_t *)retval = fp->f_offset;
968 	return (0);
969 }
970 
971 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
972 /*
973  * Reposition read/write file offset.
974  */
975 struct olseek_args {
976 	int	fd;
977 	long	offset;
978 	int	whence;
979 };
980 int
981 olseek(p, uap, retval)
982 	struct proc *p;
983 	register struct olseek_args *uap;
984 	int *retval;
985 {
986 	struct lseek_args nuap;
987 	off_t qret;
988 	int error;
989 
990 	nuap.fd = uap->fd;
991 	nuap.offset = uap->offset;
992 	nuap.whence = uap->whence;
993 	error = lseek(p, &nuap, &qret);
994 	*(long *)retval = qret;
995 	return (error);
996 }
997 #endif /* COMPAT_43 */
998 
999 /*
1000  * Check access permissions.
1001  */
1002 struct access_args {
1003 	char	*path;
1004 	int	flags;
1005 };
1006 int
1007 access(p, uap, retval)
1008 	struct proc *p;
1009 	register struct access_args *uap;
1010 	int *retval;
1011 {
1012 	register struct ucred *cred = p->p_ucred;
1013 	register struct vnode *vp;
1014 	int error, flags, t_gid, t_uid;
1015 	struct nameidata nd;
1016 
1017 	t_uid = cred->cr_uid;
1018 	t_gid = cred->cr_groups[0];
1019 	cred->cr_uid = p->p_cred->p_ruid;
1020 	cred->cr_groups[0] = p->p_cred->p_rgid;
1021 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1022 	if (error = namei(&nd))
1023 		goto out1;
1024 	vp = nd.ni_vp;
1025 
1026 	/* Flags == 0 means only check for existence. */
1027 	if (uap->flags) {
1028 		flags = 0;
1029 		if (uap->flags & R_OK)
1030 			flags |= VREAD;
1031 		if (uap->flags & W_OK)
1032 			flags |= VWRITE;
1033 		if (uap->flags & X_OK)
1034 			flags |= VEXEC;
1035 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1036 			error = VOP_ACCESS(vp, flags, cred, p);
1037 	}
1038 	vput(vp);
1039 out1:
1040 	cred->cr_uid = t_uid;
1041 	cred->cr_groups[0] = t_gid;
1042 	return (error);
1043 }
1044 
1045 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1046 /*
1047  * Get file status; this version follows links.
1048  */
1049 struct ostat_args {
1050 	char	*path;
1051 	struct ostat *ub;
1052 };
1053 /* ARGSUSED */
1054 int
1055 ostat(p, uap, retval)
1056 	struct proc *p;
1057 	register struct ostat_args *uap;
1058 	int *retval;
1059 {
1060 	struct stat sb;
1061 	struct ostat osb;
1062 	int error;
1063 	struct nameidata nd;
1064 
1065 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1066 	if (error = namei(&nd))
1067 		return (error);
1068 	error = vn_stat(nd.ni_vp, &sb, p);
1069 	vput(nd.ni_vp);
1070 	if (error)
1071 		return (error);
1072 	cvtstat(&sb, &osb);
1073 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1074 	return (error);
1075 }
1076 
1077 /*
1078  * Get file status; this version does not follow links.
1079  */
1080 struct olstat_args {
1081 	char	*path;
1082 	struct ostat *ub;
1083 };
1084 /* ARGSUSED */
1085 int
1086 olstat(p, uap, retval)
1087 	struct proc *p;
1088 	register struct olstat_args *uap;
1089 	int *retval;
1090 {
1091 	struct stat sb;
1092 	struct ostat osb;
1093 	int error;
1094 	struct nameidata nd;
1095 
1096 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1097 	if (error = namei(&nd))
1098 		return (error);
1099 	error = vn_stat(nd.ni_vp, &sb, p);
1100 	vput(nd.ni_vp);
1101 	if (error)
1102 		return (error);
1103 	cvtstat(&sb, &osb);
1104 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1105 	return (error);
1106 }
1107 
1108 /*
1109  * Convert from an old to a new stat structure.
1110  */
1111 void
1112 cvtstat(st, ost)
1113 	struct stat *st;
1114 	struct ostat *ost;
1115 {
1116 
1117 	ost->st_dev = st->st_dev;
1118 	ost->st_ino = st->st_ino;
1119 	ost->st_mode = st->st_mode;
1120 	ost->st_nlink = st->st_nlink;
1121 	ost->st_uid = st->st_uid;
1122 	ost->st_gid = st->st_gid;
1123 	ost->st_rdev = st->st_rdev;
1124 	if (st->st_size < (quad_t)1 << 32)
1125 		ost->st_size = st->st_size;
1126 	else
1127 		ost->st_size = -2;
1128 	ost->st_atime = st->st_atime;
1129 	ost->st_mtime = st->st_mtime;
1130 	ost->st_ctime = st->st_ctime;
1131 	ost->st_blksize = st->st_blksize;
1132 	ost->st_blocks = st->st_blocks;
1133 	ost->st_flags = st->st_flags;
1134 	ost->st_gen = st->st_gen;
1135 }
1136 #endif /* COMPAT_43 || COMPAT_SUNOS */
1137 
1138 /*
1139  * Get file status; this version follows links.
1140  */
1141 struct stat_args {
1142 	char	*path;
1143 	struct stat *ub;
1144 };
1145 /* ARGSUSED */
1146 int
1147 stat(p, uap, retval)
1148 	struct proc *p;
1149 	register struct stat_args *uap;
1150 	int *retval;
1151 {
1152 	struct stat sb;
1153 	int error;
1154 	struct nameidata nd;
1155 
1156 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1157 	if (error = namei(&nd))
1158 		return (error);
1159 	error = vn_stat(nd.ni_vp, &sb, p);
1160 	vput(nd.ni_vp);
1161 	if (error)
1162 		return (error);
1163 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1164 	return (error);
1165 }
1166 
1167 /*
1168  * Get file status; this version does not follow links.
1169  */
1170 struct lstat_args {
1171 	char	*path;
1172 	struct stat *ub;
1173 };
1174 /* ARGSUSED */
1175 int
1176 lstat(p, uap, retval)
1177 	struct proc *p;
1178 	register struct lstat_args *uap;
1179 	int *retval;
1180 {
1181 	int error;
1182 	struct vnode *vp, *dvp;
1183 	struct stat sb, sb1;
1184 	struct nameidata nd;
1185 
1186 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1187 	    uap->path, p);
1188 	if (error = namei(&nd))
1189 		return (error);
1190 	/*
1191 	 * For symbolic links, always return the attributes of its
1192 	 * containing directory, except for mode, size, and links.
1193 	 */
1194 	vp = nd.ni_vp;
1195 	dvp = nd.ni_dvp;
1196 	if (vp->v_type != VLNK) {
1197 		if (dvp == vp)
1198 			vrele(dvp);
1199 		else
1200 			vput(dvp);
1201 		error = vn_stat(vp, &sb, p);
1202 		vput(vp);
1203 		if (error)
1204 			return (error);
1205 	} else {
1206 		error = vn_stat(dvp, &sb, p);
1207 		vput(dvp);
1208 		if (error) {
1209 			vput(vp);
1210 			return (error);
1211 		}
1212 		error = vn_stat(vp, &sb1, p);
1213 		vput(vp);
1214 		if (error)
1215 			return (error);
1216 		sb.st_mode &= ~S_IFDIR;
1217 		sb.st_mode |= S_IFLNK;
1218 		sb.st_nlink = sb1.st_nlink;
1219 		sb.st_size = sb1.st_size;
1220 		sb.st_blocks = sb1.st_blocks;
1221 	}
1222 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1223 	return (error);
1224 }
1225 
1226 /*
1227  * Get configurable pathname variables.
1228  */
1229 struct pathconf_args {
1230 	char	*path;
1231 	int	name;
1232 };
1233 /* ARGSUSED */
1234 int
1235 pathconf(p, uap, retval)
1236 	struct proc *p;
1237 	register struct pathconf_args *uap;
1238 	int *retval;
1239 {
1240 	int error;
1241 	struct nameidata nd;
1242 
1243 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1244 	if (error = namei(&nd))
1245 		return (error);
1246 	error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
1247 	vput(nd.ni_vp);
1248 	return (error);
1249 }
1250 
1251 /*
1252  * Return target name of a symbolic link.
1253  */
1254 struct readlink_args {
1255 	char	*path;
1256 	char	*buf;
1257 	int	count;
1258 };
1259 /* ARGSUSED */
1260 int
1261 readlink(p, uap, retval)
1262 	struct proc *p;
1263 	register struct readlink_args *uap;
1264 	int *retval;
1265 {
1266 	register struct vnode *vp;
1267 	struct iovec aiov;
1268 	struct uio auio;
1269 	int error;
1270 	struct nameidata nd;
1271 
1272 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1273 	if (error = namei(&nd))
1274 		return (error);
1275 	vp = nd.ni_vp;
1276 	if (vp->v_type != VLNK)
1277 		error = EINVAL;
1278 	else {
1279 		aiov.iov_base = uap->buf;
1280 		aiov.iov_len = uap->count;
1281 		auio.uio_iov = &aiov;
1282 		auio.uio_iovcnt = 1;
1283 		auio.uio_offset = 0;
1284 		auio.uio_rw = UIO_READ;
1285 		auio.uio_segflg = UIO_USERSPACE;
1286 		auio.uio_procp = p;
1287 		auio.uio_resid = uap->count;
1288 		error = VOP_READLINK(vp, &auio, p->p_ucred);
1289 	}
1290 	vput(vp);
1291 	*retval = uap->count - auio.uio_resid;
1292 	return (error);
1293 }
1294 
1295 /*
1296  * Change flags of a file given a path name.
1297  */
1298 struct chflags_args {
1299 	char	*path;
1300 	int	flags;
1301 };
1302 /* ARGSUSED */
1303 int
1304 chflags(p, uap, retval)
1305 	struct proc *p;
1306 	register struct chflags_args *uap;
1307 	int *retval;
1308 {
1309 	register struct vnode *vp;
1310 	struct vattr vattr;
1311 	int error;
1312 	struct nameidata nd;
1313 
1314 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1315 	if (error = namei(&nd))
1316 		return (error);
1317 	vp = nd.ni_vp;
1318 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1319 	VOP_LOCK(vp);
1320 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1321 		error = EROFS;
1322 	else {
1323 		VATTR_NULL(&vattr);
1324 		vattr.va_flags = uap->flags;
1325 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1326 	}
1327 	vput(vp);
1328 	return (error);
1329 }
1330 
1331 /*
1332  * Change flags of a file given a file descriptor.
1333  */
1334 struct fchflags_args {
1335 	int	fd;
1336 	int	flags;
1337 };
1338 /* ARGSUSED */
1339 int
1340 fchflags(p, uap, retval)
1341 	struct proc *p;
1342 	register struct fchflags_args *uap;
1343 	int *retval;
1344 {
1345 	struct vattr vattr;
1346 	struct vnode *vp;
1347 	struct file *fp;
1348 	int error;
1349 
1350 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1351 		return (error);
1352 	vp = (struct vnode *)fp->f_data;
1353 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1354 	VOP_LOCK(vp);
1355 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1356 		error = EROFS;
1357 	else {
1358 		VATTR_NULL(&vattr);
1359 		vattr.va_flags = uap->flags;
1360 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1361 	}
1362 	VOP_UNLOCK(vp);
1363 	return (error);
1364 }
1365 
1366 /*
1367  * Change mode of a file given path name.
1368  */
1369 struct chmod_args {
1370 	char	*path;
1371 	int	mode;
1372 };
1373 /* ARGSUSED */
1374 int
1375 chmod(p, uap, retval)
1376 	struct proc *p;
1377 	register struct chmod_args *uap;
1378 	int *retval;
1379 {
1380 	register struct vnode *vp;
1381 	struct vattr vattr;
1382 	int error;
1383 	struct nameidata nd;
1384 
1385 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1386 	if (error = namei(&nd))
1387 		return (error);
1388 	vp = nd.ni_vp;
1389 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1390 	VOP_LOCK(vp);
1391 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1392 		error = EROFS;
1393 	else {
1394 		VATTR_NULL(&vattr);
1395 		vattr.va_mode = uap->mode & ALLPERMS;
1396 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1397 	}
1398 	vput(vp);
1399 	return (error);
1400 }
1401 
1402 /*
1403  * Change mode of a file given a file descriptor.
1404  */
1405 struct fchmod_args {
1406 	int	fd;
1407 	int	mode;
1408 };
1409 /* ARGSUSED */
1410 int
1411 fchmod(p, uap, retval)
1412 	struct proc *p;
1413 	register struct fchmod_args *uap;
1414 	int *retval;
1415 {
1416 	struct vattr vattr;
1417 	struct vnode *vp;
1418 	struct file *fp;
1419 	int error;
1420 
1421 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1422 		return (error);
1423 	vp = (struct vnode *)fp->f_data;
1424 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1425 	VOP_LOCK(vp);
1426 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1427 		error = EROFS;
1428 	else {
1429 		VATTR_NULL(&vattr);
1430 		vattr.va_mode = uap->mode & ALLPERMS;
1431 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1432 	}
1433 	VOP_UNLOCK(vp);
1434 	return (error);
1435 }
1436 
1437 /*
1438  * Set ownership given a path name.
1439  */
1440 struct chown_args {
1441 	char	*path;
1442 	int	uid;
1443 	int	gid;
1444 };
1445 /* ARGSUSED */
1446 int
1447 chown(p, uap, retval)
1448 	struct proc *p;
1449 	register struct chown_args *uap;
1450 	int *retval;
1451 {
1452 	register struct vnode *vp;
1453 	struct vattr vattr;
1454 	int error;
1455 	struct nameidata nd;
1456 
1457 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1458 	if (error = namei(&nd))
1459 		return (error);
1460 	vp = nd.ni_vp;
1461 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1462 	VOP_LOCK(vp);
1463 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1464 		error = EROFS;
1465 	else {
1466 		VATTR_NULL(&vattr);
1467 		vattr.va_uid = uap->uid;
1468 		vattr.va_gid = uap->gid;
1469 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1470 	}
1471 	vput(vp);
1472 	return (error);
1473 }
1474 
1475 /*
1476  * Set ownership given a file descriptor.
1477  */
1478 struct fchown_args {
1479 	int	fd;
1480 	int	uid;
1481 	int	gid;
1482 };
1483 /* ARGSUSED */
1484 int
1485 fchown(p, uap, retval)
1486 	struct proc *p;
1487 	register struct fchown_args *uap;
1488 	int *retval;
1489 {
1490 	struct vattr vattr;
1491 	struct vnode *vp;
1492 	struct file *fp;
1493 	int error;
1494 
1495 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1496 		return (error);
1497 	vp = (struct vnode *)fp->f_data;
1498 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1499 	VOP_LOCK(vp);
1500 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1501 		error = EROFS;
1502 	else {
1503 		VATTR_NULL(&vattr);
1504 		vattr.va_uid = uap->uid;
1505 		vattr.va_gid = uap->gid;
1506 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1507 	}
1508 	VOP_UNLOCK(vp);
1509 	return (error);
1510 }
1511 
1512 /*
1513  * Set the access and modification times of a file.
1514  */
1515 struct utimes_args {
1516 	char	*path;
1517 	struct	timeval *tptr;
1518 };
1519 /* ARGSUSED */
1520 int
1521 utimes(p, uap, retval)
1522 	struct proc *p;
1523 	register struct utimes_args *uap;
1524 	int *retval;
1525 {
1526 	register struct vnode *vp;
1527 	struct timeval tv[2];
1528 	struct vattr vattr;
1529 	int error;
1530 	struct nameidata nd;
1531 
1532 	VATTR_NULL(&vattr);
1533 	if (uap->tptr == NULL) {
1534 		microtime(&tv[0]);
1535 		tv[1] = tv[0];
1536 		vattr.va_vaflags |= VA_UTIMES_NULL;
1537 	} else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1538   		return (error);
1539 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1540 	if (error = namei(&nd))
1541 		return (error);
1542 	vp = nd.ni_vp;
1543 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1544 	VOP_LOCK(vp);
1545 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1546 		error = EROFS;
1547 	else {
1548 		vattr.va_atime.ts_sec = tv[0].tv_sec;
1549 		vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1550 		vattr.va_mtime.ts_sec = tv[1].tv_sec;
1551 		vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
1552 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1553 	}
1554 	vput(vp);
1555 	return (error);
1556 }
1557 
1558 /*
1559  * Truncate a file given its path name.
1560  */
1561 struct truncate_args {
1562 	char	*path;
1563 	int	pad;
1564 	off_t	length;
1565 };
1566 /* ARGSUSED */
1567 int
1568 truncate(p, uap, retval)
1569 	struct proc *p;
1570 	register struct truncate_args *uap;
1571 	int *retval;
1572 {
1573 	register struct vnode *vp;
1574 	struct vattr vattr;
1575 	int error;
1576 	struct nameidata nd;
1577 
1578 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1579 	if (error = namei(&nd))
1580 		return (error);
1581 	vp = nd.ni_vp;
1582 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1583 	VOP_LOCK(vp);
1584 	if (vp->v_type == VDIR)
1585 		error = EISDIR;
1586 	else if ((error = vn_writechk(vp)) == 0 &&
1587 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
1588 		VATTR_NULL(&vattr);
1589 		vattr.va_size = uap->length;
1590 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1591 	}
1592 	vput(vp);
1593 	return (error);
1594 }
1595 
1596 /*
1597  * Truncate a file given a file descriptor.
1598  */
1599 struct ftruncate_args {
1600 	int	fd;
1601 	int	pad;
1602 	off_t	length;
1603 };
1604 /* ARGSUSED */
1605 int
1606 ftruncate(p, uap, retval)
1607 	struct proc *p;
1608 	register struct ftruncate_args *uap;
1609 	int *retval;
1610 {
1611 	struct vattr vattr;
1612 	struct vnode *vp;
1613 	struct file *fp;
1614 	int error;
1615 
1616 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1617 		return (error);
1618 	if ((fp->f_flag & FWRITE) == 0)
1619 		return (EINVAL);
1620 	vp = (struct vnode *)fp->f_data;
1621 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1622 	VOP_LOCK(vp);
1623 	if (vp->v_type == VDIR)
1624 		error = EISDIR;
1625 	else if ((error = vn_writechk(vp)) == 0) {
1626 		VATTR_NULL(&vattr);
1627 		vattr.va_size = uap->length;
1628 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1629 	}
1630 	VOP_UNLOCK(vp);
1631 	return (error);
1632 }
1633 
1634 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1635 /*
1636  * Truncate a file given its path name.
1637  */
1638 struct otruncate_args {
1639 	char	*path;
1640 	long	length;
1641 };
1642 /* ARGSUSED */
1643 int
1644 otruncate(p, uap, retval)
1645 	struct proc *p;
1646 	register struct otruncate_args *uap;
1647 	int *retval;
1648 {
1649 	struct truncate_args nuap;
1650 
1651 	nuap.path = uap->path;
1652 	nuap.length = uap->length;
1653 	return (truncate(p, &nuap, retval));
1654 }
1655 
1656 /*
1657  * Truncate a file given a file descriptor.
1658  */
1659 struct oftruncate_args {
1660 	int	fd;
1661 	long	length;
1662 };
1663 /* ARGSUSED */
1664 int
1665 oftruncate(p, uap, retval)
1666 	struct proc *p;
1667 	register struct oftruncate_args *uap;
1668 	int *retval;
1669 {
1670 	struct ftruncate_args nuap;
1671 
1672 	nuap.fd = uap->fd;
1673 	nuap.length = uap->length;
1674 	return (ftruncate(p, &nuap, retval));
1675 }
1676 #endif /* COMPAT_43 || COMPAT_SUNOS */
1677 
1678 /*
1679  * Sync an open file.
1680  */
1681 struct fsync_args {
1682 	int	fd;
1683 };
1684 /* ARGSUSED */
1685 int
1686 fsync(p, uap, retval)
1687 	struct proc *p;
1688 	struct fsync_args *uap;
1689 	int *retval;
1690 {
1691 	register struct vnode *vp;
1692 	struct file *fp;
1693 	int error;
1694 
1695 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1696 		return (error);
1697 	vp = (struct vnode *)fp->f_data;
1698 	VOP_LOCK(vp);
1699 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
1700 	VOP_UNLOCK(vp);
1701 	return (error);
1702 }
1703 
1704 /*
1705  * Rename files.  Source and destination must either both be directories,
1706  * or both not be directories.  If target is a directory, it must be empty.
1707  */
1708 struct rename_args {
1709 	char	*from;
1710 	char	*to;
1711 };
1712 /* ARGSUSED */
1713 int
1714 rename(p, uap, retval)
1715 	struct proc *p;
1716 	register struct rename_args *uap;
1717 	int *retval;
1718 {
1719 	register struct vnode *tvp, *fvp, *tdvp;
1720 	struct nameidata fromnd, tond;
1721 	int error;
1722 
1723 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1724 		uap->from, p);
1725 	if (error = namei(&fromnd))
1726 		return (error);
1727 	fvp = fromnd.ni_vp;
1728 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1729 		UIO_USERSPACE, uap->to, p);
1730 	if (error = namei(&tond)) {
1731 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1732 		vrele(fromnd.ni_dvp);
1733 		vrele(fvp);
1734 		goto out1;
1735 	}
1736 	tdvp = tond.ni_dvp;
1737 	tvp = tond.ni_vp;
1738 	if (tvp != NULL) {
1739 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1740 			error = ENOTDIR;
1741 			goto out;
1742 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1743 			error = EISDIR;
1744 			goto out;
1745 		}
1746 	}
1747 	if (fvp == tdvp)
1748 		error = EINVAL;
1749 	/*
1750 	 * If source is the same as the destination (that is the
1751 	 * same inode number with the same name in the same directory),
1752 	 * then there is nothing to do.
1753 	 */
1754 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1755 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1756 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1757 	      fromnd.ni_cnd.cn_namelen))
1758 		error = -1;
1759 out:
1760 	if (!error) {
1761 		LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
1762 		if (fromnd.ni_dvp != tdvp)
1763 			LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1764 		if (tvp)
1765 			LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
1766 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1767 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1768 	} else {
1769 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1770 		if (tdvp == tvp)
1771 			vrele(tdvp);
1772 		else
1773 			vput(tdvp);
1774 		if (tvp)
1775 			vput(tvp);
1776 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1777 		vrele(fromnd.ni_dvp);
1778 		vrele(fvp);
1779 	}
1780 	vrele(tond.ni_startdir);
1781 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1782 out1:
1783 	if (fromnd.ni_startdir)
1784 		vrele(fromnd.ni_startdir);
1785 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1786 	if (error == -1)
1787 		return (0);
1788 	return (error);
1789 }
1790 
1791 /*
1792  * Make a directory file.
1793  */
1794 struct mkdir_args {
1795 	char	*path;
1796 	int	mode;
1797 };
1798 /* ARGSUSED */
1799 int
1800 mkdir(p, uap, retval)
1801 	struct proc *p;
1802 	register struct mkdir_args *uap;
1803 	int *retval;
1804 {
1805 	register struct vnode *vp;
1806 	struct vattr vattr;
1807 	int error;
1808 	struct nameidata nd;
1809 
1810 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
1811 	if (error = namei(&nd))
1812 		return (error);
1813 	vp = nd.ni_vp;
1814 	if (vp != NULL) {
1815 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1816 		if (nd.ni_dvp == vp)
1817 			vrele(nd.ni_dvp);
1818 		else
1819 			vput(nd.ni_dvp);
1820 		vrele(vp);
1821 		return (EEXIST);
1822 	}
1823 	VATTR_NULL(&vattr);
1824 	vattr.va_type = VDIR;
1825 	vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
1826 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1827 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1828 	if (!error)
1829 		vput(nd.ni_vp);
1830 	return (error);
1831 }
1832 
1833 /*
1834  * Remove a directory file.
1835  */
1836 struct rmdir_args {
1837 	char	*path;
1838 };
1839 /* ARGSUSED */
1840 int
1841 rmdir(p, uap, retval)
1842 	struct proc *p;
1843 	struct rmdir_args *uap;
1844 	int *retval;
1845 {
1846 	register struct vnode *vp;
1847 	int error;
1848 	struct nameidata nd;
1849 
1850 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1851 	if (error = namei(&nd))
1852 		return (error);
1853 	vp = nd.ni_vp;
1854 	if (vp->v_type != VDIR) {
1855 		error = ENOTDIR;
1856 		goto out;
1857 	}
1858 	/*
1859 	 * No rmdir "." please.
1860 	 */
1861 	if (nd.ni_dvp == vp) {
1862 		error = EINVAL;
1863 		goto out;
1864 	}
1865 	/*
1866 	 * The root of a mounted filesystem cannot be deleted.
1867 	 */
1868 	if (vp->v_flag & VROOT)
1869 		error = EBUSY;
1870 out:
1871 	if (!error) {
1872 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1873 		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1874 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1875 	} else {
1876 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1877 		if (nd.ni_dvp == vp)
1878 			vrele(nd.ni_dvp);
1879 		else
1880 			vput(nd.ni_dvp);
1881 		vput(vp);
1882 	}
1883 	return (error);
1884 }
1885 
1886 #ifdef COMPAT_43
1887 /*
1888  * Read a block of directory entries in a file system independent format.
1889  */
1890 struct ogetdirentries_args {
1891 	int	fd;
1892 	char	*buf;
1893 	u_int	count;
1894 	long	*basep;
1895 };
1896 int
1897 ogetdirentries(p, uap, retval)
1898 	struct proc *p;
1899 	register struct ogetdirentries_args *uap;
1900 	int *retval;
1901 {
1902 	register struct vnode *vp;
1903 	struct file *fp;
1904 	struct uio auio, kuio;
1905 	struct iovec aiov, kiov;
1906 	struct dirent *dp, *edp;
1907 	caddr_t dirbuf;
1908 	int error, readcnt;
1909 	long loff;
1910 
1911 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1912 		return (error);
1913 	if ((fp->f_flag & FREAD) == 0)
1914 		return (EBADF);
1915 	vp = (struct vnode *)fp->f_data;
1916 	if (vp->v_type != VDIR)
1917 		return (EINVAL);
1918 	aiov.iov_base = uap->buf;
1919 	aiov.iov_len = uap->count;
1920 	auio.uio_iov = &aiov;
1921 	auio.uio_iovcnt = 1;
1922 	auio.uio_rw = UIO_READ;
1923 	auio.uio_segflg = UIO_USERSPACE;
1924 	auio.uio_procp = p;
1925 	auio.uio_resid = uap->count;
1926 	VOP_LOCK(vp);
1927 	loff = auio.uio_offset = fp->f_offset;
1928 #	if (BYTE_ORDER != LITTLE_ENDIAN)
1929 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
1930 			error = VOP_READDIR(vp, &auio, fp->f_cred);
1931 			fp->f_offset = auio.uio_offset;
1932 		} else
1933 #	endif
1934 	{
1935 		kuio = auio;
1936 		kuio.uio_iov = &kiov;
1937 		kuio.uio_segflg = UIO_SYSSPACE;
1938 		kiov.iov_len = uap->count;
1939 		MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
1940 		kiov.iov_base = dirbuf;
1941 		error = VOP_READDIR(vp, &kuio, fp->f_cred);
1942 		fp->f_offset = kuio.uio_offset;
1943 		if (error == 0) {
1944 			readcnt = uap->count - kuio.uio_resid;
1945 			edp = (struct dirent *)&dirbuf[readcnt];
1946 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1947 #				if (BYTE_ORDER == LITTLE_ENDIAN)
1948 					/*
1949 					 * The expected low byte of
1950 					 * dp->d_namlen is our dp->d_type.
1951 					 * The high MBZ byte of dp->d_namlen
1952 					 * is our dp->d_namlen.
1953 					 */
1954 					dp->d_type = dp->d_namlen;
1955 					dp->d_namlen = 0;
1956 #				else
1957 					/*
1958 					 * The dp->d_type is the high byte
1959 					 * of the expected dp->d_namlen,
1960 					 * so must be zero'ed.
1961 					 */
1962 					dp->d_type = 0;
1963 #				endif
1964 				if (dp->d_reclen > 0) {
1965 					dp = (struct dirent *)
1966 					    ((char *)dp + dp->d_reclen);
1967 				} else {
1968 					error = EIO;
1969 					break;
1970 				}
1971 			}
1972 			if (dp >= edp)
1973 				error = uiomove(dirbuf, readcnt, &auio);
1974 		}
1975 		FREE(dirbuf, M_TEMP);
1976 	}
1977 	VOP_UNLOCK(vp);
1978 	if (error)
1979 		return (error);
1980 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
1981 	*retval = uap->count - auio.uio_resid;
1982 	return (error);
1983 }
1984 #endif
1985 
1986 /*
1987  * Read a block of directory entries in a file system independent format.
1988  */
1989 struct getdirentries_args {
1990 	int	fd;
1991 	char	*buf;
1992 	u_int	count;
1993 	long	*basep;
1994 };
1995 int
1996 getdirentries(p, uap, retval)
1997 	struct proc *p;
1998 	register struct getdirentries_args *uap;
1999 	int *retval;
2000 {
2001 	register struct vnode *vp;
2002 	struct file *fp;
2003 	struct uio auio;
2004 	struct iovec aiov;
2005 	long loff;
2006 	int error;
2007 
2008 	if (error = getvnode(p->p_fd, uap->fd, &fp))
2009 		return (error);
2010 	if ((fp->f_flag & FREAD) == 0)
2011 		return (EBADF);
2012 	vp = (struct vnode *)fp->f_data;
2013 unionread:
2014 	if (vp->v_type != VDIR)
2015 		return (EINVAL);
2016 	aiov.iov_base = uap->buf;
2017 	aiov.iov_len = uap->count;
2018 	auio.uio_iov = &aiov;
2019 	auio.uio_iovcnt = 1;
2020 	auio.uio_rw = UIO_READ;
2021 	auio.uio_segflg = UIO_USERSPACE;
2022 	auio.uio_procp = p;
2023 	auio.uio_resid = uap->count;
2024 	VOP_LOCK(vp);
2025 	loff = auio.uio_offset = fp->f_offset;
2026 	error = VOP_READDIR(vp, &auio, fp->f_cred);
2027 	fp->f_offset = auio.uio_offset;
2028 	VOP_UNLOCK(vp);
2029 	if (error)
2030 		return (error);
2031 
2032 #ifdef UNION
2033 {
2034 	extern int (**union_vnodeop_p)();
2035 	extern struct vnode *union_lowervp __P((struct vnode *));
2036 
2037 	if ((uap->count == auio.uio_resid) &&
2038 	    (vp->v_op == union_vnodeop_p)) {
2039 		struct vnode *tvp = vp;
2040 
2041 		vp = union_lowervp(vp);
2042 		if (vp != NULLVP) {
2043 			VOP_LOCK(vp);
2044 			error = VOP_OPEN(vp, FREAD);
2045 			VOP_UNLOCK(vp);
2046 
2047 			if (error) {
2048 				vrele(vp);
2049 				return (error);
2050 			}
2051 			fp->f_data = (caddr_t) vp;
2052 			fp->f_offset = 0;
2053 			error = vn_close(tvp, FREAD, fp->f_cred, p);
2054 			if (error)
2055 				return (error);
2056 			goto unionread;
2057 		}
2058 	}
2059 }
2060 #endif
2061 
2062 	if ((uap->count == auio.uio_resid) &&
2063 	    (vp->v_flag & VROOT) &&
2064 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
2065 		struct vnode *tvp = vp;
2066 		vp = vp->v_mount->mnt_vnodecovered;
2067 		VREF(vp);
2068 		fp->f_data = (caddr_t) vp;
2069 		fp->f_offset = 0;
2070 		vrele(tvp);
2071 		goto unionread;
2072 	}
2073 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
2074 	*retval = uap->count - auio.uio_resid;
2075 	return (error);
2076 }
2077 
2078 /*
2079  * Set the mode mask for creation of filesystem nodes.
2080  */
2081 struct umask_args {
2082 	int	newmask;
2083 };
2084 mode_t				/* XXX */
2085 umask(p, uap, retval)
2086 	struct proc *p;
2087 	struct umask_args *uap;
2088 	int *retval;
2089 {
2090 	register struct filedesc *fdp;
2091 
2092 	fdp = p->p_fd;
2093 	*retval = fdp->fd_cmask;
2094 	fdp->fd_cmask = uap->newmask & ALLPERMS;
2095 	return (0);
2096 }
2097 
2098 /*
2099  * Void all references to file by ripping underlying filesystem
2100  * away from vnode.
2101  */
2102 struct revoke_args {
2103 	char	*path;
2104 };
2105 /* ARGSUSED */
2106 int
2107 revoke(p, uap, retval)
2108 	struct proc *p;
2109 	register struct revoke_args *uap;
2110 	int *retval;
2111 {
2112 	register struct vnode *vp;
2113 	struct vattr vattr;
2114 	int error;
2115 	struct nameidata nd;
2116 
2117 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
2118 	if (error = namei(&nd))
2119 		return (error);
2120 	vp = nd.ni_vp;
2121 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
2122 		error = EINVAL;
2123 		goto out;
2124 	}
2125 	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2126 		goto out;
2127 	if (p->p_ucred->cr_uid != vattr.va_uid &&
2128 	    (error = suser(p->p_ucred, &p->p_acflag)))
2129 		goto out;
2130 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2131 		vgoneall(vp);
2132 out:
2133 	vrele(vp);
2134 	return (error);
2135 }
2136 
2137 /*
2138  * Convert a user file descriptor to a kernel file entry.
2139  */
2140 int
2141 getvnode(fdp, fd, fpp)
2142 	struct filedesc *fdp;
2143 	struct file **fpp;
2144 	int fd;
2145 {
2146 	struct file *fp;
2147 
2148 	if ((u_int)fd >= fdp->fd_nfiles ||
2149 	    (fp = fdp->fd_ofiles[fd]) == NULL)
2150 		return (EBADF);
2151 	if (fp->f_type != DTYPE_VNODE)
2152 		return (EINVAL);
2153 	*fpp = fp;
2154 	return (0);
2155 }
2156