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