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