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