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