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