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