xref: /freebsd/sys/kern/vfs_extattr.c (revision 2ad872c5794e4c26fdf6ed219ad3f09ca0d5304a)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)vfs_syscalls.c	8.13 (Berkeley) 4/15/94
39  * $Id: vfs_syscalls.c,v 1.111 1998/12/12 21:07:09 dillon Exp $
40  */
41 
42 /* For 4.3 integer FS ID compatibility */
43 #include "opt_compat.h"
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/sysent.h>
48 #include <sys/sysproto.h>
49 #include <sys/namei.h>
50 #include <sys/filedesc.h>
51 #include <sys/kernel.h>
52 #include <sys/fcntl.h>
53 #include <sys/file.h>
54 #include <sys/linker.h>
55 #include <sys/stat.h>
56 #include <sys/unistd.h>
57 #include <sys/vnode.h>
58 #include <sys/malloc.h>
59 #include <sys/mount.h>
60 #include <sys/proc.h>
61 #include <sys/dirent.h>
62 
63 #include <miscfs/union/union.h>
64 
65 #include <vm/vm.h>
66 #include <vm/vm_object.h>
67 #include <vm/vm_extern.h>
68 #include <vm/vm_zone.h>
69 #include <sys/sysctl.h>
70 
71 static int change_dir __P((struct nameidata *ndp, struct proc *p));
72 static void checkdirs __P((struct vnode *olddp));
73 static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
74 static int setfmode __P((struct proc *, struct vnode *, int));
75 static int setfflags __P((struct proc *, struct vnode *, int));
76 static int setutimes __P((struct proc *, struct vnode *, struct timeval *, int));
77 static int	usermount = 0;	/* if 1, non-root can mount fs. */
78 
79 int (*union_dircheckp) __P((struct proc *, struct vnode **, struct file *));
80 
81 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
82 
83 /*
84  * Virtual File System System Calls
85  */
86 
87 /*
88  * Mount a file system.
89  */
90 #ifndef _SYS_SYSPROTO_H_
91 struct mount_args {
92 	char	*type;
93 	char	*path;
94 	int	flags;
95 	caddr_t	data;
96 };
97 #endif
98 /* ARGSUSED */
99 int
100 mount(p, uap)
101 	struct proc *p;
102 	register struct mount_args /* {
103 		syscallarg(char *) type;
104 		syscallarg(char *) path;
105 		syscallarg(int) flags;
106 		syscallarg(caddr_t) data;
107 	} */ *uap;
108 {
109 	struct vnode *vp;
110 	struct mount *mp;
111 	struct vfsconf *vfsp;
112 	int error, flag = 0, flag2 = 0;
113 	struct vattr va;
114 	u_long fstypenum;
115 	struct nameidata nd;
116 	char fstypename[MFSNAMELEN];
117 
118 	if (usermount == 0 && (error = suser(p->p_ucred, &p->p_acflag)))
119 		return (error);
120 
121 	/*
122 	 * Get vnode to be covered
123 	 */
124 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
125 	    SCARG(uap, path), p);
126 	if (error = namei(&nd))
127 		return (error);
128 	vp = nd.ni_vp;
129 	if (SCARG(uap, flags) & MNT_UPDATE) {
130 		if ((vp->v_flag & VROOT) == 0) {
131 			vput(vp);
132 			return (EINVAL);
133 		}
134 		mp = vp->v_mount;
135 		flag = mp->mnt_flag;
136 		flag2 = mp->mnt_kern_flag;
137 		/*
138 		 * We only allow the filesystem to be reloaded if it
139 		 * is currently mounted read-only.
140 		 */
141 		if ((SCARG(uap, flags) & MNT_RELOAD) &&
142 		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
143 			vput(vp);
144 			return (EOPNOTSUPP);	/* Needs translation */
145 		}
146 		mp->mnt_flag |=
147 		    SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
148 		/*
149 		 * Only root, or the user that did the original mount is
150 		 * permitted to update it.
151 		 */
152 		if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
153 		    (error = suser(p->p_ucred, &p->p_acflag))) {
154 			vput(vp);
155 			return (error);
156 		}
157 		/*
158 		 * Do not allow NFS export by non-root users. Silently
159 		 * enforce MNT_NOSUID and MNT_NODEV for non-root users.
160 		 */
161 		if (p->p_ucred->cr_uid != 0) {
162 			if (SCARG(uap, flags) & MNT_EXPORTED) {
163 				vput(vp);
164 				return (EPERM);
165 			}
166 			SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
167 		}
168 		if (vfs_busy(mp, LK_NOWAIT, 0, p)) {
169 			vput(vp);
170 			return (EBUSY);
171 		}
172 		VOP_UNLOCK(vp, 0, p);
173 		goto update;
174 	}
175 	/*
176 	 * If the user is not root, ensure that they own the directory
177 	 * onto which we are attempting to mount.
178 	 */
179 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
180 	    (va.va_uid != p->p_ucred->cr_uid &&
181 	     (error = suser(p->p_ucred, &p->p_acflag)))) {
182 		vput(vp);
183 		return (error);
184 	}
185 	/*
186 	 * Do not allow NFS export by non-root users. Silently
187 	 * enforce MNT_NOSUID and MNT_NODEV for non-root users.
188 	 */
189 	if (p->p_ucred->cr_uid != 0) {
190 		if (SCARG(uap, flags) & MNT_EXPORTED) {
191 			vput(vp);
192 			return (EPERM);
193 		}
194 		SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
195 	}
196 	if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
197 		return (error);
198 	if (vp->v_type != VDIR) {
199 		vput(vp);
200 		return (ENOTDIR);
201 	}
202 #ifdef COMPAT_43
203 	/*
204 	 * Historically filesystem types were identified by number. If we
205 	 * get an integer for the filesystem type instead of a string, we
206 	 * check to see if it matches one of the historic filesystem types.
207 	 */
208 	fstypenum = (uintptr_t)SCARG(uap, type);
209 	if (fstypenum < maxvfsconf) {
210 		for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
211 			if (vfsp->vfc_typenum == fstypenum)
212 				break;
213 		if (vfsp == NULL) {
214 			vput(vp);
215 			return (ENODEV);
216 		}
217 		strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
218 	} else
219 #endif /* COMPAT_43 */
220 	if (error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) {
221 		vput(vp);
222 		return (error);
223 	}
224 	for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
225 		if (!strcmp(vfsp->vfc_name, fstypename))
226 			break;
227 	if (vfsp == NULL) {
228 		linker_file_t lf;
229 
230 		/* Refuse to load modules if securelevel raised */
231 		if (securelevel > 0) {
232 			vput(vp);
233 			return EPERM;
234 		}
235 		/* Only load modules for root (very important!) */
236 		if (error = suser(p->p_ucred, &p->p_acflag)) {
237 			vput(vp);
238 			return error;
239 		}
240 		error = linker_load_file(fstypename, &lf);
241 		if (error || lf == NULL) {
242 			vput(vp);
243 			if (lf == NULL)
244 				error = ENODEV;
245 			return error;
246 		}
247 		lf->userrefs++;
248 		/* lookup again, see if the VFS was loaded */
249 		for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
250 			if (!strcmp(vfsp->vfc_name, fstypename))
251 				break;
252 		if (vfsp == NULL) {
253 			lf->userrefs--;
254 			linker_file_unload(lf);
255 			vput(vp);
256 			return (ENODEV);
257 		}
258 	}
259 	simple_lock(&vp->v_interlock);
260 	if ((vp->v_flag & VMOUNT) != 0 ||
261 	    vp->v_mountedhere != NULL) {
262 		simple_unlock(&vp->v_interlock);
263 		vput(vp);
264 		return (EBUSY);
265 	}
266 	vp->v_flag |= VMOUNT;
267 	simple_unlock(&vp->v_interlock);
268 
269 	/*
270 	 * Allocate and initialize the filesystem.
271 	 */
272 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
273 		M_MOUNT, M_WAITOK);
274 	bzero((char *)mp, (u_long)sizeof(struct mount));
275 	lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
276 	(void)vfs_busy(mp, LK_NOWAIT, 0, p);
277 	mp->mnt_op = vfsp->vfc_vfsops;
278 	mp->mnt_vfc = vfsp;
279 	vfsp->vfc_refcount++;
280 	mp->mnt_stat.f_type = vfsp->vfc_typenum;
281 	mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
282 	strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
283 	mp->mnt_vnodecovered = vp;
284 	mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
285 	VOP_UNLOCK(vp, 0, p);
286 update:
287 	/*
288 	 * Set the mount level flags.
289 	 */
290 	if (SCARG(uap, flags) & MNT_RDONLY)
291 		mp->mnt_flag |= MNT_RDONLY;
292 	else if (mp->mnt_flag & MNT_RDONLY)
293 		mp->mnt_kern_flag |= MNTK_WANTRDWR;
294 	mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
295 	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
296 	    MNT_NOSYMFOLLOW |
297 	    MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
298 	mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
299 	    MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
300 	    MNT_NOSYMFOLLOW |
301 	    MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
302 	/*
303 	 * Mount the filesystem.
304 	 */
305 	error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
306 	if (mp->mnt_flag & MNT_UPDATE) {
307 		vrele(vp);
308 		if (mp->mnt_kern_flag & MNTK_WANTRDWR)
309 			mp->mnt_flag &= ~MNT_RDONLY;
310 		mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE);
311 		mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
312 		if (error) {
313 			mp->mnt_flag = flag;
314 			mp->mnt_kern_flag = flag2;
315 		}
316 		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
317 			if (mp->mnt_syncer == NULL)
318 				error = vfs_allocate_syncvnode(mp);
319 		} else {
320 			if (mp->mnt_syncer != NULL)
321 				vrele(mp->mnt_syncer);
322 			mp->mnt_syncer = NULL;
323 		}
324 		vfs_unbusy(mp, p);
325 		return (error);
326 	}
327 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
328 	/*
329 	 * Put the new filesystem on the mount list after root.
330 	 */
331 	cache_purge(vp);
332 	if (!error) {
333 		simple_lock(&vp->v_interlock);
334 		vp->v_flag &= ~VMOUNT;
335 		vp->v_mountedhere = mp;
336 		simple_unlock(&vp->v_interlock);
337 		simple_lock(&mountlist_slock);
338 		CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
339 		simple_unlock(&mountlist_slock);
340 		checkdirs(vp);
341 		VOP_UNLOCK(vp, 0, p);
342 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
343 			error = vfs_allocate_syncvnode(mp);
344 		vfs_unbusy(mp, p);
345 		if (error = VFS_START(mp, 0, p))
346 			vrele(vp);
347 	} else {
348 		simple_lock(&vp->v_interlock);
349 		vp->v_flag &= ~VMOUNT;
350 		simple_unlock(&vp->v_interlock);
351 		mp->mnt_vfc->vfc_refcount--;
352 		vfs_unbusy(mp, p);
353 		free((caddr_t)mp, M_MOUNT);
354 		vput(vp);
355 	}
356 	return (error);
357 }
358 
359 /*
360  * Scan all active processes to see if any of them have a current
361  * or root directory onto which the new filesystem has just been
362  * mounted. If so, replace them with the new mount point.
363  */
364 static void
365 checkdirs(olddp)
366 	struct vnode *olddp;
367 {
368 	struct filedesc *fdp;
369 	struct vnode *newdp;
370 	struct proc *p;
371 
372 	if (olddp->v_usecount == 1)
373 		return;
374 	if (VFS_ROOT(olddp->v_mountedhere, &newdp))
375 		panic("mount: lost mount");
376 	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
377 		fdp = p->p_fd;
378 		if (fdp->fd_cdir == olddp) {
379 			vrele(fdp->fd_cdir);
380 			VREF(newdp);
381 			fdp->fd_cdir = newdp;
382 		}
383 		if (fdp->fd_rdir == olddp) {
384 			vrele(fdp->fd_rdir);
385 			VREF(newdp);
386 			fdp->fd_rdir = newdp;
387 		}
388 	}
389 	if (rootvnode == olddp) {
390 		vrele(rootvnode);
391 		VREF(newdp);
392 		rootvnode = newdp;
393 	}
394 	vput(newdp);
395 }
396 
397 /*
398  * Unmount a file system.
399  *
400  * Note: unmount takes a path to the vnode mounted on as argument,
401  * not special file (as before).
402  */
403 #ifndef _SYS_SYSPROTO_H_
404 struct unmount_args {
405 	char	*path;
406 	int	flags;
407 };
408 #endif
409 /* ARGSUSED */
410 int
411 unmount(p, uap)
412 	struct proc *p;
413 	register struct unmount_args /* {
414 		syscallarg(char *) path;
415 		syscallarg(int) flags;
416 	} */ *uap;
417 {
418 	register struct vnode *vp;
419 	struct mount *mp;
420 	int error;
421 	struct nameidata nd;
422 
423 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
424 	    SCARG(uap, path), p);
425 	if (error = namei(&nd))
426 		return (error);
427 	vp = nd.ni_vp;
428 	mp = vp->v_mount;
429 
430 	/*
431 	 * Only root, or the user that did the original mount is
432 	 * permitted to unmount this filesystem.
433 	 */
434 	if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
435 	    (error = suser(p->p_ucred, &p->p_acflag))) {
436 		vput(vp);
437 		return (error);
438 	}
439 
440 	/*
441 	 * Don't allow unmounting the root file system.
442 	 */
443 	if (mp->mnt_flag & MNT_ROOTFS) {
444 		vput(vp);
445 		return (EINVAL);
446 	}
447 
448 	/*
449 	 * Must be the root of the filesystem
450 	 */
451 	if ((vp->v_flag & VROOT) == 0) {
452 		vput(vp);
453 		return (EINVAL);
454 	}
455 	vput(vp);
456 	return (dounmount(mp, SCARG(uap, flags), p));
457 }
458 
459 /*
460  * Do the actual file system unmount.
461  */
462 int
463 dounmount(mp, flags, p)
464 	register struct mount *mp;
465 	int flags;
466 	struct proc *p;
467 {
468 	struct vnode *coveredvp;
469 	int error;
470 	int async_flag;
471 
472 	simple_lock(&mountlist_slock);
473 	mp->mnt_kern_flag |= MNTK_UNMOUNT;
474 	lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p);
475 
476 	if (mp->mnt_flag & MNT_EXPUBLIC)
477 		vfs_setpublicfs(NULL, NULL, NULL);
478 
479 	vfs_msync(mp, MNT_WAIT);
480 	async_flag = mp->mnt_flag & MNT_ASYNC;
481 	mp->mnt_flag &=~ MNT_ASYNC;
482 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
483 	if (mp->mnt_syncer != NULL)
484 		vrele(mp->mnt_syncer);
485 	if (((mp->mnt_flag & MNT_RDONLY) ||
486 	     (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
487 	    (flags & MNT_FORCE))
488 		error = VFS_UNMOUNT(mp, flags, p);
489 	simple_lock(&mountlist_slock);
490 	if (error) {
491 		if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
492 			(void) vfs_allocate_syncvnode(mp);
493 		mp->mnt_kern_flag &= ~MNTK_UNMOUNT;
494 		mp->mnt_flag |= async_flag;
495 		lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
496 		    &mountlist_slock, p);
497 		if (mp->mnt_kern_flag & MNTK_MWAIT)
498 			wakeup((caddr_t)mp);
499 		return (error);
500 	}
501 	CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
502 	if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
503 		coveredvp->v_mountedhere = (struct mount *)0;
504 		vrele(coveredvp);
505 	}
506 	mp->mnt_vfc->vfc_refcount--;
507 	if (mp->mnt_vnodelist.lh_first != NULL)
508 		panic("unmount: dangling vnode");
509 	lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
510 	if (mp->mnt_kern_flag & MNTK_MWAIT)
511 		wakeup((caddr_t)mp);
512 	free((caddr_t)mp, M_MOUNT);
513 	return (0);
514 }
515 
516 /*
517  * Sync each mounted filesystem.
518  */
519 #ifndef _SYS_SYSPROTO_H_
520 struct sync_args {
521         int     dummy;
522 };
523 #endif
524 
525 #ifdef DEBUG
526 static int syncprt = 0;
527 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
528 #endif
529 
530 /* ARGSUSED */
531 int
532 sync(p, uap)
533 	struct proc *p;
534 	struct sync_args *uap;
535 {
536 	register struct mount *mp, *nmp;
537 	int asyncflag;
538 
539 	simple_lock(&mountlist_slock);
540 	for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
541 		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
542 			nmp = mp->mnt_list.cqe_next;
543 			continue;
544 		}
545 		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
546 			asyncflag = mp->mnt_flag & MNT_ASYNC;
547 			mp->mnt_flag &= ~MNT_ASYNC;
548 			vfs_msync(mp, MNT_NOWAIT);
549 			VFS_SYNC(mp, MNT_NOWAIT,
550 				((p != NULL) ? p->p_ucred : NOCRED), p);
551 			mp->mnt_flag |= asyncflag;
552 		}
553 		simple_lock(&mountlist_slock);
554 		nmp = mp->mnt_list.cqe_next;
555 		vfs_unbusy(mp, p);
556 	}
557 	simple_unlock(&mountlist_slock);
558 #if 0
559 /*
560  * XXX don't call vfs_bufstats() yet because that routine
561  * was not imported in the Lite2 merge.
562  */
563 #ifdef DIAGNOSTIC
564 	if (syncprt)
565 		vfs_bufstats();
566 #endif /* DIAGNOSTIC */
567 #endif
568 	return (0);
569 }
570 
571 /*
572  * Change filesystem quotas.
573  */
574 #ifndef _SYS_SYSPROTO_H_
575 struct quotactl_args {
576 	char *path;
577 	int cmd;
578 	int uid;
579 	caddr_t arg;
580 };
581 #endif
582 /* ARGSUSED */
583 int
584 quotactl(p, uap)
585 	struct proc *p;
586 	register struct quotactl_args /* {
587 		syscallarg(char *) path;
588 		syscallarg(int) cmd;
589 		syscallarg(int) uid;
590 		syscallarg(caddr_t) arg;
591 	} */ *uap;
592 {
593 	register struct mount *mp;
594 	int error;
595 	struct nameidata nd;
596 
597 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
598 	if (error = namei(&nd))
599 		return (error);
600 	mp = nd.ni_vp->v_mount;
601 	vrele(nd.ni_vp);
602 	return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
603 	    SCARG(uap, arg), p));
604 }
605 
606 /*
607  * Get filesystem statistics.
608  */
609 #ifndef _SYS_SYSPROTO_H_
610 struct statfs_args {
611 	char *path;
612 	struct statfs *buf;
613 };
614 #endif
615 /* ARGSUSED */
616 int
617 statfs(p, uap)
618 	struct proc *p;
619 	register struct statfs_args /* {
620 		syscallarg(char *) path;
621 		syscallarg(struct statfs *) buf;
622 	} */ *uap;
623 {
624 	register struct mount *mp;
625 	register struct statfs *sp;
626 	int error;
627 	struct nameidata nd;
628 	struct statfs sb;
629 
630 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
631 	if (error = namei(&nd))
632 		return (error);
633 	mp = nd.ni_vp->v_mount;
634 	sp = &mp->mnt_stat;
635 	vrele(nd.ni_vp);
636 	error = VFS_STATFS(mp, sp, p);
637 	if (error)
638 		return (error);
639 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
640 	if (p->p_ucred->cr_uid != 0) {
641 		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
642 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
643 		sp = &sb;
644 	}
645 	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
646 }
647 
648 /*
649  * Get filesystem statistics.
650  */
651 #ifndef _SYS_SYSPROTO_H_
652 struct fstatfs_args {
653 	int fd;
654 	struct statfs *buf;
655 };
656 #endif
657 /* ARGSUSED */
658 int
659 fstatfs(p, uap)
660 	struct proc *p;
661 	register struct fstatfs_args /* {
662 		syscallarg(int) fd;
663 		syscallarg(struct statfs *) buf;
664 	} */ *uap;
665 {
666 	struct file *fp;
667 	struct mount *mp;
668 	register struct statfs *sp;
669 	int error;
670 	struct statfs sb;
671 
672 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
673 		return (error);
674 	mp = ((struct vnode *)fp->f_data)->v_mount;
675 	sp = &mp->mnt_stat;
676 	error = VFS_STATFS(mp, sp, p);
677 	if (error)
678 		return (error);
679 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
680 	if (p->p_ucred->cr_uid != 0) {
681 		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
682 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
683 		sp = &sb;
684 	}
685 	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
686 }
687 
688 /*
689  * Get statistics on all filesystems.
690  */
691 #ifndef _SYS_SYSPROTO_H_
692 struct getfsstat_args {
693 	struct statfs *buf;
694 	long bufsize;
695 	int flags;
696 };
697 #endif
698 int
699 getfsstat(p, uap)
700 	struct proc *p;
701 	register struct getfsstat_args /* {
702 		syscallarg(struct statfs *) buf;
703 		syscallarg(long) bufsize;
704 		syscallarg(int) flags;
705 	} */ *uap;
706 {
707 	register struct mount *mp, *nmp;
708 	register struct statfs *sp;
709 	caddr_t sfsp;
710 	long count, maxcount, error;
711 
712 	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
713 	sfsp = (caddr_t)SCARG(uap, buf);
714 	count = 0;
715 	simple_lock(&mountlist_slock);
716 	for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
717 		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
718 			nmp = mp->mnt_list.cqe_next;
719 			continue;
720 		}
721 		if (sfsp && count < maxcount) {
722 			sp = &mp->mnt_stat;
723 			/*
724 			 * If MNT_NOWAIT or MNT_LAZY is specified, do not
725 			 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
726 			 * overrides MNT_WAIT.
727 			 */
728 			if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
729 			    (SCARG(uap, flags) & MNT_WAIT)) &&
730 			    (error = VFS_STATFS(mp, sp, p))) {
731 				simple_lock(&mountlist_slock);
732 				nmp = mp->mnt_list.cqe_next;
733 				vfs_unbusy(mp, p);
734 				continue;
735 			}
736 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
737 			error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
738 			if (error) {
739 				vfs_unbusy(mp, p);
740 				return (error);
741 			}
742 			sfsp += sizeof(*sp);
743 		}
744 		count++;
745 		simple_lock(&mountlist_slock);
746 		nmp = mp->mnt_list.cqe_next;
747 		vfs_unbusy(mp, p);
748 	}
749 	simple_unlock(&mountlist_slock);
750 	if (sfsp && count > maxcount)
751 		p->p_retval[0] = maxcount;
752 	else
753 		p->p_retval[0] = count;
754 	return (0);
755 }
756 
757 /*
758  * Change current working directory to a given file descriptor.
759  */
760 #ifndef _SYS_SYSPROTO_H_
761 struct fchdir_args {
762 	int	fd;
763 };
764 #endif
765 /* ARGSUSED */
766 int
767 fchdir(p, uap)
768 	struct proc *p;
769 	struct fchdir_args /* {
770 		syscallarg(int) fd;
771 	} */ *uap;
772 {
773 	register struct filedesc *fdp = p->p_fd;
774 	struct vnode *vp, *tdp;
775 	struct mount *mp;
776 	struct file *fp;
777 	int error;
778 
779 	if (error = getvnode(fdp, SCARG(uap, fd), &fp))
780 		return (error);
781 	vp = (struct vnode *)fp->f_data;
782 	VREF(vp);
783 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
784 	if (vp->v_type != VDIR)
785 		error = ENOTDIR;
786 	else
787 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
788 	while (!error && (mp = vp->v_mountedhere) != NULL) {
789 		if (vfs_busy(mp, 0, 0, p))
790 			continue;
791 		error = VFS_ROOT(mp, &tdp);
792 		vfs_unbusy(mp, p);
793 		if (error)
794 			break;
795 		vput(vp);
796 		vp = tdp;
797 	}
798 	if (error) {
799 		vput(vp);
800 		return (error);
801 	}
802 	VOP_UNLOCK(vp, 0, p);
803 	vrele(fdp->fd_cdir);
804 	fdp->fd_cdir = vp;
805 	return (0);
806 }
807 
808 /*
809  * Change current working directory (``.'').
810  */
811 #ifndef _SYS_SYSPROTO_H_
812 struct chdir_args {
813 	char	*path;
814 };
815 #endif
816 /* ARGSUSED */
817 int
818 chdir(p, uap)
819 	struct proc *p;
820 	struct chdir_args /* {
821 		syscallarg(char *) path;
822 	} */ *uap;
823 {
824 	register struct filedesc *fdp = p->p_fd;
825 	int error;
826 	struct nameidata nd;
827 
828 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
829 	    SCARG(uap, path), p);
830 	if (error = change_dir(&nd, p))
831 		return (error);
832 	vrele(fdp->fd_cdir);
833 	fdp->fd_cdir = nd.ni_vp;
834 	return (0);
835 }
836 
837 /*
838  * Change notion of root (``/'') directory.
839  */
840 #ifndef _SYS_SYSPROTO_H_
841 struct chroot_args {
842 	char	*path;
843 };
844 #endif
845 /* ARGSUSED */
846 int
847 chroot(p, uap)
848 	struct proc *p;
849 	struct chroot_args /* {
850 		syscallarg(char *) path;
851 	} */ *uap;
852 {
853 	register struct filedesc *fdp = p->p_fd;
854 	int error;
855 	struct nameidata nd;
856 
857 	error = suser(p->p_ucred, &p->p_acflag);
858 	if (error)
859 		return (error);
860 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
861 	    SCARG(uap, path), p);
862 	if (error = change_dir(&nd, p))
863 		return (error);
864 	vrele(fdp->fd_rdir);
865 	fdp->fd_rdir = nd.ni_vp;
866 	return (0);
867 }
868 
869 /*
870  * Common routine for chroot and chdir.
871  */
872 static int
873 change_dir(ndp, p)
874 	register struct nameidata *ndp;
875 	struct proc *p;
876 {
877 	struct vnode *vp;
878 	int error;
879 
880 	error = namei(ndp);
881 	if (error)
882 		return (error);
883 	vp = ndp->ni_vp;
884 	if (vp->v_type != VDIR)
885 		error = ENOTDIR;
886 	else
887 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
888 	if (error)
889 		vput(vp);
890 	else
891 		VOP_UNLOCK(vp, 0, p);
892 	return (error);
893 }
894 
895 /*
896  * Check permissions, allocate an open file structure,
897  * and call the device open routine if any.
898  */
899 #ifndef _SYS_SYSPROTO_H_
900 struct open_args {
901 	char	*path;
902 	int	flags;
903 	int	mode;
904 };
905 #endif
906 int
907 open(p, uap)
908 	struct proc *p;
909 	register struct open_args /* {
910 		syscallarg(char *) path;
911 		syscallarg(int) flags;
912 		syscallarg(int) mode;
913 	} */ *uap;
914 {
915 	register struct filedesc *fdp = p->p_fd;
916 	register struct file *fp;
917 	register struct vnode *vp;
918 	int cmode, flags, oflags;
919 	struct file *nfp;
920 	int type, indx, error;
921 	struct flock lf;
922 	struct nameidata nd;
923 
924 	oflags = SCARG(uap, flags);
925 	if ((oflags & O_ACCMODE) == O_ACCMODE)
926 		return (EINVAL);
927 	flags = FFLAGS(oflags);
928 	error = falloc(p, &nfp, &indx);
929 	if (error)
930 		return (error);
931 	fp = nfp;
932 	cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
933 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
934 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
935 	error = vn_open(&nd, flags, cmode);
936 	if (error) {
937 		ffree(fp);
938 		if ((error == ENODEV || error == ENXIO) &&
939 		    p->p_dupfd >= 0 &&			/* XXX from fdopen */
940 		    (error =
941 			dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
942 			p->p_retval[0] = indx;
943 			return (0);
944 		}
945 		if (error == ERESTART)
946 			error = EINTR;
947 		fdp->fd_ofiles[indx] = NULL;
948 		return (error);
949 	}
950 	p->p_dupfd = 0;
951 	vp = nd.ni_vp;
952 
953 	fp->f_flag = flags & FMASK;
954 	fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
955 	fp->f_ops = &vnops;
956 	fp->f_data = (caddr_t)vp;
957 	if (flags & (O_EXLOCK | O_SHLOCK)) {
958 		lf.l_whence = SEEK_SET;
959 		lf.l_start = 0;
960 		lf.l_len = 0;
961 		if (flags & O_EXLOCK)
962 			lf.l_type = F_WRLCK;
963 		else
964 			lf.l_type = F_RDLCK;
965 		type = F_FLOCK;
966 		if ((flags & FNONBLOCK) == 0)
967 			type |= F_WAIT;
968 		VOP_UNLOCK(vp, 0, p);
969 		if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
970 			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
971 			ffree(fp);
972 			fdp->fd_ofiles[indx] = NULL;
973 			return (error);
974 		}
975 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
976 		fp->f_flag |= FHASLOCK;
977 	}
978 	if ((vp->v_type == VREG) && (vp->v_object == NULL))
979 		vfs_object_create(vp, p, p->p_ucred);
980 	VOP_UNLOCK(vp, 0, p);
981 	p->p_retval[0] = indx;
982 	return (0);
983 }
984 
985 #ifdef COMPAT_43
986 /*
987  * Create a file.
988  */
989 #ifndef _SYS_SYSPROTO_H_
990 struct ocreat_args {
991 	char	*path;
992 	int	mode;
993 };
994 #endif
995 int
996 ocreat(p, uap)
997 	struct proc *p;
998 	register struct ocreat_args /* {
999 		syscallarg(char *) path;
1000 		syscallarg(int) mode;
1001 	} */ *uap;
1002 {
1003 	struct open_args /* {
1004 		syscallarg(char *) path;
1005 		syscallarg(int) flags;
1006 		syscallarg(int) mode;
1007 	} */ nuap;
1008 
1009 	SCARG(&nuap, path) = SCARG(uap, path);
1010 	SCARG(&nuap, mode) = SCARG(uap, mode);
1011 	SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
1012 	return (open(p, &nuap));
1013 }
1014 #endif /* COMPAT_43 */
1015 
1016 /*
1017  * Create a special file.
1018  */
1019 #ifndef _SYS_SYSPROTO_H_
1020 struct mknod_args {
1021 	char	*path;
1022 	int	mode;
1023 	int	dev;
1024 };
1025 #endif
1026 /* ARGSUSED */
1027 int
1028 mknod(p, uap)
1029 	struct proc *p;
1030 	register struct mknod_args /* {
1031 		syscallarg(char *) path;
1032 		syscallarg(int) mode;
1033 		syscallarg(int) dev;
1034 	} */ *uap;
1035 {
1036 	register struct vnode *vp;
1037 	struct vattr vattr;
1038 	int error;
1039 	int whiteout = 0;
1040 	struct nameidata nd;
1041 
1042 	error = suser(p->p_ucred, &p->p_acflag);
1043 	if (error)
1044 		return (error);
1045 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1046 	if (error = namei(&nd))
1047 		return (error);
1048 	vp = nd.ni_vp;
1049 	if (vp != NULL)
1050 		error = EEXIST;
1051 	else {
1052 		VATTR_NULL(&vattr);
1053 		vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1054 		vattr.va_rdev = SCARG(uap, dev);
1055 		whiteout = 0;
1056 
1057 		switch (SCARG(uap, mode) & S_IFMT) {
1058 		case S_IFMT:	/* used by badsect to flag bad sectors */
1059 			vattr.va_type = VBAD;
1060 			break;
1061 		case S_IFCHR:
1062 			vattr.va_type = VCHR;
1063 			break;
1064 		case S_IFBLK:
1065 			vattr.va_type = VBLK;
1066 			break;
1067 		case S_IFWHT:
1068 			whiteout = 1;
1069 			break;
1070 		default:
1071 			error = EINVAL;
1072 			break;
1073 		}
1074 	}
1075 	if (!error) {
1076 		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1077 		if (whiteout) {
1078 			error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1079 			if (error)
1080 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1081 			vput(nd.ni_dvp);
1082 		} else {
1083 			error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1084 						&nd.ni_cnd, &vattr);
1085 			vput(nd.ni_dvp);
1086 		}
1087 	} else {
1088 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1089 		if (nd.ni_dvp == vp)
1090 			vrele(nd.ni_dvp);
1091 		else
1092 			vput(nd.ni_dvp);
1093 		if (vp)
1094 			vrele(vp);
1095 	}
1096 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
1097 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
1098 	return (error);
1099 }
1100 
1101 /*
1102  * Create a named pipe.
1103  */
1104 #ifndef _SYS_SYSPROTO_H_
1105 struct mkfifo_args {
1106 	char	*path;
1107 	int	mode;
1108 };
1109 #endif
1110 /* ARGSUSED */
1111 int
1112 mkfifo(p, uap)
1113 	struct proc *p;
1114 	register struct mkfifo_args /* {
1115 		syscallarg(char *) path;
1116 		syscallarg(int) mode;
1117 	} */ *uap;
1118 {
1119 	struct vattr vattr;
1120 	int error;
1121 	struct nameidata nd;
1122 
1123 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1124 	if (error = namei(&nd))
1125 		return (error);
1126 	if (nd.ni_vp != NULL) {
1127 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1128 		if (nd.ni_dvp == nd.ni_vp)
1129 			vrele(nd.ni_dvp);
1130 		else
1131 			vput(nd.ni_dvp);
1132 		vrele(nd.ni_vp);
1133 		return (EEXIST);
1134 	}
1135 	VATTR_NULL(&vattr);
1136 	vattr.va_type = VFIFO;
1137 	vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1138 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1139 	error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1140 	vput(nd.ni_dvp);
1141 	return (error);
1142 }
1143 
1144 /*
1145  * Make a hard file link.
1146  */
1147 #ifndef _SYS_SYSPROTO_H_
1148 struct link_args {
1149 	char	*path;
1150 	char	*link;
1151 };
1152 #endif
1153 /* ARGSUSED */
1154 int
1155 link(p, uap)
1156 	struct proc *p;
1157 	register struct link_args /* {
1158 		syscallarg(char *) path;
1159 		syscallarg(char *) link;
1160 	} */ *uap;
1161 {
1162 	register struct vnode *vp;
1163 	struct nameidata nd;
1164 	int error;
1165 
1166 	NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p);
1167 	if (error = namei(&nd))
1168 		return (error);
1169 	vp = nd.ni_vp;
1170 	if (vp->v_type == VDIR)
1171 		error = EPERM;		/* POSIX */
1172 	else {
1173 		NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
1174 		error = namei(&nd);
1175 		if (!error) {
1176 			if (nd.ni_vp != NULL) {
1177 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1178 				if (nd.ni_vp)
1179 					vrele(nd.ni_vp);
1180 				error = EEXIST;
1181 			} else {
1182 				VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
1183 				    LEASE_WRITE);
1184 				VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1185 				error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1186 			}
1187 			if (nd.ni_dvp == nd.ni_vp)
1188 				vrele(nd.ni_dvp);
1189 			else
1190 				vput(nd.ni_dvp);
1191 		}
1192 	}
1193 	vrele(vp);
1194 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1195 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1196 	return (error);
1197 }
1198 
1199 /*
1200  * Make a symbolic link.
1201  */
1202 #ifndef _SYS_SYSPROTO_H_
1203 struct symlink_args {
1204 	char	*path;
1205 	char	*link;
1206 };
1207 #endif
1208 /* ARGSUSED */
1209 int
1210 symlink(p, uap)
1211 	struct proc *p;
1212 	register struct symlink_args /* {
1213 		syscallarg(char *) path;
1214 		syscallarg(char *) link;
1215 	} */ *uap;
1216 {
1217 	struct vattr vattr;
1218 	char *path;
1219 	int error;
1220 	struct nameidata nd;
1221 
1222 	path = zalloc(namei_zone);
1223 	if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL))
1224 		goto out;
1225 	NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
1226 	if (error = namei(&nd))
1227 		goto out;
1228 	if (nd.ni_vp) {
1229 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1230 		if (nd.ni_dvp == nd.ni_vp)
1231 			vrele(nd.ni_dvp);
1232 		else
1233 			vput(nd.ni_dvp);
1234 		vrele(nd.ni_vp);
1235 		error = EEXIST;
1236 		goto out;
1237 	}
1238 	VATTR_NULL(&vattr);
1239 	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
1240 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1241 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1242 	vput(nd.ni_dvp);
1243 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1244 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1245 out:
1246 	zfree(namei_zone, path);
1247 	return (error);
1248 }
1249 
1250 /*
1251  * Delete a whiteout from the filesystem.
1252  */
1253 /* ARGSUSED */
1254 int
1255 undelete(p, uap)
1256 	struct proc *p;
1257 	register struct undelete_args /* {
1258 		syscallarg(char *) path;
1259 	} */ *uap;
1260 {
1261 	int error;
1262 	struct nameidata nd;
1263 
1264 	NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1265 	    SCARG(uap, path), p);
1266 	error = namei(&nd);
1267 	if (error)
1268 		return (error);
1269 
1270 	if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1271 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1272 		if (nd.ni_dvp == nd.ni_vp)
1273 			vrele(nd.ni_dvp);
1274 		else
1275 			vput(nd.ni_dvp);
1276 		if (nd.ni_vp)
1277 			vrele(nd.ni_vp);
1278 		return (EEXIST);
1279 	}
1280 
1281 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1282 	if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE))
1283 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1284 	vput(nd.ni_dvp);
1285 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1286 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1287 	return (error);
1288 }
1289 
1290 /*
1291  * Delete a name from the filesystem.
1292  */
1293 #ifndef _SYS_SYSPROTO_H_
1294 struct unlink_args {
1295 	char	*path;
1296 };
1297 #endif
1298 /* ARGSUSED */
1299 int
1300 unlink(p, uap)
1301 	struct proc *p;
1302 	struct unlink_args /* {
1303 		syscallarg(char *) path;
1304 	} */ *uap;
1305 {
1306 	register struct vnode *vp;
1307 	int error;
1308 	struct nameidata nd;
1309 
1310 	NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1311 	if (error = namei(&nd))
1312 		return (error);
1313 	vp = nd.ni_vp;
1314 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1315 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1316 
1317 	if (vp->v_type == VDIR)
1318 		error = EPERM;		/* POSIX */
1319 	else {
1320 		/*
1321 		 * The root of a mounted filesystem cannot be deleted.
1322 		 *
1323 		 * XXX: can this only be a VDIR case?
1324 		 */
1325 		if (vp->v_flag & VROOT)
1326 			error = EBUSY;
1327 	}
1328 
1329 	if (!error) {
1330 		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1331 		error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1332 	} else {
1333 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1334 	}
1335 	if (nd.ni_dvp == vp)
1336 		vrele(nd.ni_dvp);
1337 	else
1338 		vput(nd.ni_dvp);
1339 	if (vp != NULLVP)
1340 		vput(vp);
1341 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1342 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1343 	return (error);
1344 }
1345 
1346 /*
1347  * Reposition read/write file offset.
1348  */
1349 #ifndef _SYS_SYSPROTO_H_
1350 struct lseek_args {
1351 	int	fd;
1352 	int	pad;
1353 	off_t	offset;
1354 	int	whence;
1355 };
1356 #endif
1357 int
1358 lseek(p, uap)
1359 	struct proc *p;
1360 	register struct lseek_args /* {
1361 		syscallarg(int) fd;
1362 		syscallarg(int) pad;
1363 		syscallarg(off_t) offset;
1364 		syscallarg(int) whence;
1365 	} */ *uap;
1366 {
1367 	struct ucred *cred = p->p_ucred;
1368 	register struct filedesc *fdp = p->p_fd;
1369 	register struct file *fp;
1370 	struct vattr vattr;
1371 	int error;
1372 
1373 	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1374 	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1375 		return (EBADF);
1376 	if (fp->f_type != DTYPE_VNODE)
1377 		return (ESPIPE);
1378 	switch (SCARG(uap, whence)) {
1379 	case L_INCR:
1380 		fp->f_offset += SCARG(uap, offset);
1381 		break;
1382 	case L_XTND:
1383 		error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
1384 		if (error)
1385 			return (error);
1386 		fp->f_offset = SCARG(uap, offset) + vattr.va_size;
1387 		break;
1388 	case L_SET:
1389 		fp->f_offset = SCARG(uap, offset);
1390 		break;
1391 	default:
1392 		return (EINVAL);
1393 	}
1394 	*(off_t *)(p->p_retval) = fp->f_offset;
1395 	return (0);
1396 }
1397 
1398 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1399 /*
1400  * Reposition read/write file offset.
1401  */
1402 #ifndef _SYS_SYSPROTO_H_
1403 struct olseek_args {
1404 	int	fd;
1405 	long	offset;
1406 	int	whence;
1407 };
1408 #endif
1409 int
1410 olseek(p, uap)
1411 	struct proc *p;
1412 	register struct olseek_args /* {
1413 		syscallarg(int) fd;
1414 		syscallarg(long) offset;
1415 		syscallarg(int) whence;
1416 	} */ *uap;
1417 {
1418 	struct lseek_args /* {
1419 		syscallarg(int) fd;
1420 		syscallarg(int) pad;
1421 		syscallarg(off_t) offset;
1422 		syscallarg(int) whence;
1423 	} */ nuap;
1424 	int error;
1425 
1426 	SCARG(&nuap, fd) = SCARG(uap, fd);
1427 	SCARG(&nuap, offset) = SCARG(uap, offset);
1428 	SCARG(&nuap, whence) = SCARG(uap, whence);
1429 	error = lseek(p, &nuap);
1430 	return (error);
1431 }
1432 #endif /* COMPAT_43 */
1433 
1434 /*
1435  * Check access permissions.
1436  */
1437 #ifndef _SYS_SYSPROTO_H_
1438 struct access_args {
1439 	char	*path;
1440 	int	flags;
1441 };
1442 #endif
1443 int
1444 access(p, uap)
1445 	struct proc *p;
1446 	register struct access_args /* {
1447 		syscallarg(char *) path;
1448 		syscallarg(int) flags;
1449 	} */ *uap;
1450 {
1451 	register struct ucred *cred = p->p_ucred;
1452 	register struct vnode *vp;
1453 	int error, flags, t_gid, t_uid;
1454 	struct nameidata nd;
1455 
1456 	t_uid = cred->cr_uid;
1457 	t_gid = cred->cr_groups[0];
1458 	cred->cr_uid = p->p_cred->p_ruid;
1459 	cred->cr_groups[0] = p->p_cred->p_rgid;
1460 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1461 	    SCARG(uap, path), p);
1462 	if (error = namei(&nd))
1463 		goto out1;
1464 	vp = nd.ni_vp;
1465 
1466 	/* Flags == 0 means only check for existence. */
1467 	if (SCARG(uap, flags)) {
1468 		flags = 0;
1469 		if (SCARG(uap, flags) & R_OK)
1470 			flags |= VREAD;
1471 		if (SCARG(uap, flags) & W_OK)
1472 			flags |= VWRITE;
1473 		if (SCARG(uap, flags) & X_OK)
1474 			flags |= VEXEC;
1475 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1476 			error = VOP_ACCESS(vp, flags, cred, p);
1477 	}
1478 	vput(vp);
1479 out1:
1480 	cred->cr_uid = t_uid;
1481 	cred->cr_groups[0] = t_gid;
1482 	return (error);
1483 }
1484 
1485 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1486 /*
1487  * Get file status; this version follows links.
1488  */
1489 #ifndef _SYS_SYSPROTO_H_
1490 struct ostat_args {
1491 	char	*path;
1492 	struct ostat *ub;
1493 };
1494 #endif
1495 /* ARGSUSED */
1496 int
1497 ostat(p, uap)
1498 	struct proc *p;
1499 	register struct ostat_args /* {
1500 		syscallarg(char *) path;
1501 		syscallarg(struct ostat *) ub;
1502 	} */ *uap;
1503 {
1504 	struct stat sb;
1505 	struct ostat osb;
1506 	int error;
1507 	struct nameidata nd;
1508 
1509 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1510 	    SCARG(uap, path), p);
1511 	if (error = namei(&nd))
1512 		return (error);
1513 	error = vn_stat(nd.ni_vp, &sb, p);
1514 	vput(nd.ni_vp);
1515 	if (error)
1516 		return (error);
1517 	cvtstat(&sb, &osb);
1518 	error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1519 	return (error);
1520 }
1521 
1522 /*
1523  * Get file status; this version does not follow links.
1524  */
1525 #ifndef _SYS_SYSPROTO_H_
1526 struct olstat_args {
1527 	char	*path;
1528 	struct ostat *ub;
1529 };
1530 #endif
1531 /* ARGSUSED */
1532 int
1533 olstat(p, uap)
1534 	struct proc *p;
1535 	register struct olstat_args /* {
1536 		syscallarg(char *) path;
1537 		syscallarg(struct ostat *) ub;
1538 	} */ *uap;
1539 {
1540 	struct vnode *vp;
1541 	struct stat sb;
1542 	struct ostat osb;
1543 	int error;
1544 	struct nameidata nd;
1545 
1546 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1547 	    SCARG(uap, path), p);
1548 	if (error = namei(&nd))
1549 		return (error);
1550 	vp = nd.ni_vp;
1551 	error = vn_stat(vp, &sb, p);
1552 	vput(vp);
1553 	if (error)
1554 		return (error);
1555 	cvtstat(&sb, &osb);
1556 	error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1557 	return (error);
1558 }
1559 
1560 /*
1561  * Convert from an old to a new stat structure.
1562  */
1563 void
1564 cvtstat(st, ost)
1565 	struct stat *st;
1566 	struct ostat *ost;
1567 {
1568 
1569 	ost->st_dev = st->st_dev;
1570 	ost->st_ino = st->st_ino;
1571 	ost->st_mode = st->st_mode;
1572 	ost->st_nlink = st->st_nlink;
1573 	ost->st_uid = st->st_uid;
1574 	ost->st_gid = st->st_gid;
1575 	ost->st_rdev = st->st_rdev;
1576 	if (st->st_size < (quad_t)1 << 32)
1577 		ost->st_size = st->st_size;
1578 	else
1579 		ost->st_size = -2;
1580 	ost->st_atime = st->st_atime;
1581 	ost->st_mtime = st->st_mtime;
1582 	ost->st_ctime = st->st_ctime;
1583 	ost->st_blksize = st->st_blksize;
1584 	ost->st_blocks = st->st_blocks;
1585 	ost->st_flags = st->st_flags;
1586 	ost->st_gen = st->st_gen;
1587 }
1588 #endif /* COMPAT_43 || COMPAT_SUNOS */
1589 
1590 /*
1591  * Get file status; this version follows links.
1592  */
1593 #ifndef _SYS_SYSPROTO_H_
1594 struct stat_args {
1595 	char	*path;
1596 	struct stat *ub;
1597 };
1598 #endif
1599 /* ARGSUSED */
1600 int
1601 stat(p, uap)
1602 	struct proc *p;
1603 	register struct stat_args /* {
1604 		syscallarg(char *) path;
1605 		syscallarg(struct stat *) ub;
1606 	} */ *uap;
1607 {
1608 	struct stat sb;
1609 	int error;
1610 	struct nameidata nd;
1611 
1612 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1613 	    SCARG(uap, path), p);
1614 	if (error = namei(&nd))
1615 		return (error);
1616 	error = vn_stat(nd.ni_vp, &sb, p);
1617 	vput(nd.ni_vp);
1618 	if (error)
1619 		return (error);
1620 	error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1621 	return (error);
1622 }
1623 
1624 /*
1625  * Get file status; this version does not follow links.
1626  */
1627 #ifndef _SYS_SYSPROTO_H_
1628 struct lstat_args {
1629 	char	*path;
1630 	struct stat *ub;
1631 };
1632 #endif
1633 /* ARGSUSED */
1634 int
1635 lstat(p, uap)
1636 	struct proc *p;
1637 	register struct lstat_args /* {
1638 		syscallarg(char *) path;
1639 		syscallarg(struct stat *) ub;
1640 	} */ *uap;
1641 {
1642 	int error;
1643 	struct vnode *vp;
1644 	struct stat sb;
1645 	struct nameidata nd;
1646 
1647 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1648 	    SCARG(uap, path), p);
1649 	if (error = namei(&nd))
1650 		return (error);
1651 	vp = nd.ni_vp;
1652 	error = vn_stat(vp, &sb, p);
1653 	vput(vp);
1654 	if (error)
1655 		return (error);
1656 	error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1657 	return (error);
1658 }
1659 
1660 void
1661 cvtnstat(sb, nsb)
1662 	struct stat *sb;
1663 	struct nstat *nsb;
1664 {
1665 	nsb->st_dev = sb->st_dev;
1666 	nsb->st_ino = sb->st_ino;
1667 	nsb->st_mode = sb->st_mode;
1668 	nsb->st_nlink = sb->st_nlink;
1669 	nsb->st_uid = sb->st_uid;
1670 	nsb->st_gid = sb->st_gid;
1671 	nsb->st_rdev = sb->st_rdev;
1672 	nsb->st_atimespec = sb->st_atimespec;
1673 	nsb->st_mtimespec = sb->st_mtimespec;
1674 	nsb->st_ctimespec = sb->st_ctimespec;
1675 	nsb->st_size = sb->st_size;
1676 	nsb->st_blocks = sb->st_blocks;
1677 	nsb->st_blksize = sb->st_blksize;
1678 	nsb->st_flags = sb->st_flags;
1679 	nsb->st_gen = sb->st_gen;
1680 }
1681 
1682 #ifndef _SYS_SYSPROTO_H_
1683 struct nstat_args {
1684 	char	*path;
1685 	struct nstat *ub;
1686 };
1687 #endif
1688 /* ARGSUSED */
1689 int
1690 nstat(p, uap)
1691 	struct proc *p;
1692 	register struct nstat_args /* {
1693 		syscallarg(char *) path;
1694 		syscallarg(struct nstat *) ub;
1695 	} */ *uap;
1696 {
1697 	struct stat sb;
1698 	struct nstat nsb;
1699 	int error;
1700 	struct nameidata nd;
1701 
1702 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1703 	    SCARG(uap, path), p);
1704 	if (error = namei(&nd))
1705 		return (error);
1706 	error = vn_stat(nd.ni_vp, &sb, p);
1707 	vput(nd.ni_vp);
1708 	if (error)
1709 		return (error);
1710 	cvtnstat(&sb, &nsb);
1711 	error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1712 	return (error);
1713 }
1714 
1715 /*
1716  * Get file status; this version does not follow links.
1717  */
1718 #ifndef _SYS_SYSPROTO_H_
1719 struct lstat_args {
1720 	char	*path;
1721 	struct stat *ub;
1722 };
1723 #endif
1724 /* ARGSUSED */
1725 int
1726 nlstat(p, uap)
1727 	struct proc *p;
1728 	register struct nlstat_args /* {
1729 		syscallarg(char *) path;
1730 		syscallarg(struct nstat *) ub;
1731 	} */ *uap;
1732 {
1733 	int error;
1734 	struct vnode *vp;
1735 	struct stat sb;
1736 	struct nstat nsb;
1737 	struct nameidata nd;
1738 
1739 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1740 	    SCARG(uap, path), p);
1741 	if (error = namei(&nd))
1742 		return (error);
1743 	vp = nd.ni_vp;
1744 	error = vn_stat(vp, &sb, p);
1745 	vput(vp);
1746 	if (error)
1747 		return (error);
1748 	cvtnstat(&sb, &nsb);
1749 	error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1750 	return (error);
1751 }
1752 
1753 /*
1754  * Get configurable pathname variables.
1755  */
1756 #ifndef _SYS_SYSPROTO_H_
1757 struct pathconf_args {
1758 	char	*path;
1759 	int	name;
1760 };
1761 #endif
1762 /* ARGSUSED */
1763 int
1764 pathconf(p, uap)
1765 	struct proc *p;
1766 	register struct pathconf_args /* {
1767 		syscallarg(char *) path;
1768 		syscallarg(int) name;
1769 	} */ *uap;
1770 {
1771 	int error;
1772 	struct nameidata nd;
1773 
1774 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1775 	    SCARG(uap, path), p);
1776 	if (error = namei(&nd))
1777 		return (error);
1778 	error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval);
1779 	vput(nd.ni_vp);
1780 	return (error);
1781 }
1782 
1783 /*
1784  * Return target name of a symbolic link.
1785  */
1786 #ifndef _SYS_SYSPROTO_H_
1787 struct readlink_args {
1788 	char	*path;
1789 	char	*buf;
1790 	int	count;
1791 };
1792 #endif
1793 /* ARGSUSED */
1794 int
1795 readlink(p, uap)
1796 	struct proc *p;
1797 	register struct readlink_args /* {
1798 		syscallarg(char *) path;
1799 		syscallarg(char *) buf;
1800 		syscallarg(int) count;
1801 	} */ *uap;
1802 {
1803 	register struct vnode *vp;
1804 	struct iovec aiov;
1805 	struct uio auio;
1806 	int error;
1807 	struct nameidata nd;
1808 
1809 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1810 	    SCARG(uap, path), p);
1811 	if (error = namei(&nd))
1812 		return (error);
1813 	vp = nd.ni_vp;
1814 	if (vp->v_type != VLNK)
1815 		error = EINVAL;
1816 	else {
1817 		aiov.iov_base = SCARG(uap, buf);
1818 		aiov.iov_len = SCARG(uap, count);
1819 		auio.uio_iov = &aiov;
1820 		auio.uio_iovcnt = 1;
1821 		auio.uio_offset = 0;
1822 		auio.uio_rw = UIO_READ;
1823 		auio.uio_segflg = UIO_USERSPACE;
1824 		auio.uio_procp = p;
1825 		auio.uio_resid = SCARG(uap, count);
1826 		error = VOP_READLINK(vp, &auio, p->p_ucred);
1827 	}
1828 	vput(vp);
1829 	p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
1830 	return (error);
1831 }
1832 
1833 static int
1834 setfflags(p, vp, flags)
1835 	struct proc *p;
1836 	struct vnode *vp;
1837 	int flags;
1838 {
1839 	int error;
1840 	struct vattr vattr;
1841 
1842 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1843 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1844 	VATTR_NULL(&vattr);
1845 	vattr.va_flags = flags;
1846 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1847 	VOP_UNLOCK(vp, 0, p);
1848 	return error;
1849 }
1850 
1851 /*
1852  * Change flags of a file given a path name.
1853  */
1854 #ifndef _SYS_SYSPROTO_H_
1855 struct chflags_args {
1856 	char	*path;
1857 	int	flags;
1858 };
1859 #endif
1860 /* ARGSUSED */
1861 int
1862 chflags(p, uap)
1863 	struct proc *p;
1864 	register struct chflags_args /* {
1865 		syscallarg(char *) path;
1866 		syscallarg(int) flags;
1867 	} */ *uap;
1868 {
1869 	int error;
1870 	struct nameidata nd;
1871 
1872 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1873 	if (error = namei(&nd))
1874 		return (error);
1875 	error = setfflags(p, nd.ni_vp, SCARG(uap, flags));
1876 	vrele(nd.ni_vp);
1877 	return error;
1878 }
1879 
1880 /*
1881  * Change flags of a file given a file descriptor.
1882  */
1883 #ifndef _SYS_SYSPROTO_H_
1884 struct fchflags_args {
1885 	int	fd;
1886 	int	flags;
1887 };
1888 #endif
1889 /* ARGSUSED */
1890 int
1891 fchflags(p, uap)
1892 	struct proc *p;
1893 	register struct fchflags_args /* {
1894 		syscallarg(int) fd;
1895 		syscallarg(int) flags;
1896 	} */ *uap;
1897 {
1898 	struct file *fp;
1899 	int error;
1900 
1901 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1902 		return (error);
1903 	return setfflags(p, (struct vnode *) fp->f_data, SCARG(uap, flags));
1904 }
1905 
1906 static int
1907 setfmode(p, vp, mode)
1908 	struct proc *p;
1909 	struct vnode *vp;
1910 	int mode;
1911 {
1912 	int error;
1913 	struct vattr vattr;
1914 
1915 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1916 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1917 	VATTR_NULL(&vattr);
1918 	vattr.va_mode = mode & ALLPERMS;
1919 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1920 	VOP_UNLOCK(vp, 0, p);
1921 	return error;
1922 }
1923 
1924 /*
1925  * Change mode of a file given path name.
1926  */
1927 #ifndef _SYS_SYSPROTO_H_
1928 struct chmod_args {
1929 	char	*path;
1930 	int	mode;
1931 };
1932 #endif
1933 /* ARGSUSED */
1934 int
1935 chmod(p, uap)
1936 	struct proc *p;
1937 	register struct chmod_args /* {
1938 		syscallarg(char *) path;
1939 		syscallarg(int) mode;
1940 	} */ *uap;
1941 {
1942 	int error;
1943 	struct nameidata nd;
1944 
1945 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1946 	if (error = namei(&nd))
1947 		return (error);
1948 	error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
1949 	vrele(nd.ni_vp);
1950 	return error;
1951 }
1952 
1953 /*
1954  * Change mode of a file given path name (don't follow links.)
1955  */
1956 #ifndef _SYS_SYSPROTO_H_
1957 struct lchmod_args {
1958 	char	*path;
1959 	int	mode;
1960 };
1961 #endif
1962 /* ARGSUSED */
1963 int
1964 lchmod(p, uap)
1965 	struct proc *p;
1966 	register struct lchmod_args /* {
1967 		syscallarg(char *) path;
1968 		syscallarg(int) mode;
1969 	} */ *uap;
1970 {
1971 	int error;
1972 	struct nameidata nd;
1973 
1974 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1975 	if (error = namei(&nd))
1976 		return (error);
1977 	error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
1978 	vrele(nd.ni_vp);
1979 	return error;
1980 }
1981 
1982 /*
1983  * Change mode of a file given a file descriptor.
1984  */
1985 #ifndef _SYS_SYSPROTO_H_
1986 struct fchmod_args {
1987 	int	fd;
1988 	int	mode;
1989 };
1990 #endif
1991 /* ARGSUSED */
1992 int
1993 fchmod(p, uap)
1994 	struct proc *p;
1995 	register struct fchmod_args /* {
1996 		syscallarg(int) fd;
1997 		syscallarg(int) mode;
1998 	} */ *uap;
1999 {
2000 	struct file *fp;
2001 	int error;
2002 
2003 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2004 		return (error);
2005 	return setfmode(p, (struct vnode *)fp->f_data, SCARG(uap, mode));
2006 }
2007 
2008 static int
2009 setfown(p, vp, uid, gid)
2010 	struct proc *p;
2011 	struct vnode *vp;
2012 	uid_t uid;
2013 	gid_t gid;
2014 {
2015 	int error;
2016 	struct vattr vattr;
2017 
2018 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2019 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2020 	VATTR_NULL(&vattr);
2021 	vattr.va_uid = uid;
2022 	vattr.va_gid = gid;
2023 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2024 	VOP_UNLOCK(vp, 0, p);
2025 	return error;
2026 }
2027 
2028 /*
2029  * Set ownership given a path name.
2030  */
2031 #ifndef _SYS_SYSPROTO_H_
2032 struct chown_args {
2033 	char	*path;
2034 	int	uid;
2035 	int	gid;
2036 };
2037 #endif
2038 /* ARGSUSED */
2039 int
2040 chown(p, uap)
2041 	struct proc *p;
2042 	register struct chown_args /* {
2043 		syscallarg(char *) path;
2044 		syscallarg(int) uid;
2045 		syscallarg(int) gid;
2046 	} */ *uap;
2047 {
2048 	int error;
2049 	struct nameidata nd;
2050 
2051 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2052 	if (error = namei(&nd))
2053 		return (error);
2054 	error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2055 	vrele(nd.ni_vp);
2056 
2057 	return (error);
2058 }
2059 
2060 /*
2061  * Set ownership given a path name, do not cross symlinks.
2062  */
2063 #ifndef _SYS_SYSPROTO_H_
2064 struct lchown_args {
2065 	char	*path;
2066 	int	uid;
2067 	int	gid;
2068 };
2069 #endif
2070 /* ARGSUSED */
2071 int
2072 lchown(p, uap)
2073 	struct proc *p;
2074 	register struct lchown_args /* {
2075 		syscallarg(char *) path;
2076 		syscallarg(int) uid;
2077 		syscallarg(int) gid;
2078 	} */ *uap;
2079 {
2080 	int error;
2081 	struct nameidata nd;
2082 
2083 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2084 	if (error = namei(&nd))
2085 		return (error);
2086 	error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2087 	vrele(nd.ni_vp);
2088 	return (error);
2089 }
2090 
2091 /*
2092  * Set ownership given a file descriptor.
2093  */
2094 #ifndef _SYS_SYSPROTO_H_
2095 struct fchown_args {
2096 	int	fd;
2097 	int	uid;
2098 	int	gid;
2099 };
2100 #endif
2101 /* ARGSUSED */
2102 int
2103 fchown(p, uap)
2104 	struct proc *p;
2105 	register struct fchown_args /* {
2106 		syscallarg(int) fd;
2107 		syscallarg(int) uid;
2108 		syscallarg(int) gid;
2109 	} */ *uap;
2110 {
2111 	struct file *fp;
2112 	int error;
2113 
2114 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2115 		return (error);
2116 	return setfown(p, (struct vnode *)fp->f_data,
2117 		SCARG(uap, uid), SCARG(uap, gid));
2118 }
2119 
2120 static int
2121 setutimes(p, vp, tv, nullflag)
2122 	struct proc *p;
2123 	struct vnode *vp;
2124 	struct timeval *tv;
2125 	int nullflag;
2126 {
2127 	int error;
2128 	struct vattr vattr;
2129 
2130 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2131 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2132 	VATTR_NULL(&vattr);
2133 	vattr.va_atime.tv_sec = tv[0].tv_sec;
2134 	vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
2135 	vattr.va_mtime.tv_sec = tv[1].tv_sec;
2136 	vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
2137 	if (nullflag)
2138 		vattr.va_vaflags |= VA_UTIMES_NULL;
2139 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2140 	VOP_UNLOCK(vp, 0, p);
2141 	return error;
2142 }
2143 
2144 /*
2145  * Set the access and modification times of a file.
2146  */
2147 #ifndef _SYS_SYSPROTO_H_
2148 struct utimes_args {
2149 	char	*path;
2150 	struct	timeval *tptr;
2151 };
2152 #endif
2153 /* ARGSUSED */
2154 int
2155 utimes(p, uap)
2156 	struct proc *p;
2157 	register struct utimes_args /* {
2158 		syscallarg(char *) path;
2159 		syscallarg(struct timeval *) tptr;
2160 	} */ *uap;
2161 {
2162 	struct timeval tv[2];
2163 	int error;
2164 	struct nameidata nd;
2165 	int nullflag;
2166 
2167 	nullflag = 0;
2168 	if (SCARG(uap, tptr) == NULL) {
2169 		microtime(&tv[0]);
2170 		tv[1] = tv[0];
2171 		nullflag = 1;
2172 	} else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
2173 	    sizeof (tv)))
2174   		return (error);
2175 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2176 	if (error = namei(&nd))
2177 		return (error);
2178 	error = setutimes(p, nd.ni_vp, tv, nullflag);
2179 	vrele(nd.ni_vp);
2180 	return (error);
2181 }
2182 
2183 /*
2184  * Set the access and modification times of a file.
2185  */
2186 #ifndef _SYS_SYSPROTO_H_
2187 struct lutimes_args {
2188 	char	*path;
2189 	struct	timeval *tptr;
2190 };
2191 #endif
2192 /* ARGSUSED */
2193 int
2194 lutimes(p, uap)
2195 	struct proc *p;
2196 	register struct lutimes_args /* {
2197 		syscallarg(char *) path;
2198 		syscallarg(struct timeval *) tptr;
2199 	} */ *uap;
2200 {
2201 	struct timeval tv[2];
2202 	int error;
2203 	struct nameidata nd;
2204 	int nullflag;
2205 
2206 	nullflag = 0;
2207 	if (SCARG(uap, tptr) == NULL) {
2208 		microtime(&tv[0]);
2209 		tv[1] = tv[0];
2210 		nullflag = 1;
2211 	} else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
2212 	    sizeof (tv)))
2213   		return (error);
2214 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2215 	if (error = namei(&nd))
2216 		return (error);
2217 
2218 	error = setutimes(p, nd.ni_vp, tv, nullflag);
2219 	vrele(nd.ni_vp);
2220 	return (error);
2221 }
2222 
2223 /*
2224  * Set the access and modification times of a file.
2225  */
2226 #ifndef _SYS_SYSPROTO_H_
2227 struct futimes_args {
2228 	int	fd;
2229 	struct	timeval *tptr;
2230 };
2231 #endif
2232 /* ARGSUSED */
2233 int
2234 futimes(p, uap)
2235 	struct proc *p;
2236 	register struct futimes_args /* {
2237 		syscallarg(int ) fd;
2238 		syscallarg(struct timeval *) tptr;
2239 	} */ *uap;
2240 {
2241 	struct timeval tv[2];
2242 	struct file *fp;
2243 	int error;
2244 	int nullflag;
2245 
2246 	nullflag = 0;
2247 	if (SCARG(uap, tptr) == NULL) {
2248 		microtime(&tv[0]);
2249 		tv[1] = tv[0];
2250 		nullflag = 1;
2251 	} else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
2252 	    sizeof (tv)))
2253   		return (error);
2254 
2255 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2256 		return (error);
2257 	return setutimes(p, (struct vnode *)fp->f_data, tv, nullflag);
2258 }
2259 
2260 /*
2261  * Truncate a file given its path name.
2262  */
2263 #ifndef _SYS_SYSPROTO_H_
2264 struct truncate_args {
2265 	char	*path;
2266 	int	pad;
2267 	off_t	length;
2268 };
2269 #endif
2270 /* ARGSUSED */
2271 int
2272 truncate(p, uap)
2273 	struct proc *p;
2274 	register struct truncate_args /* {
2275 		syscallarg(char *) path;
2276 		syscallarg(int) pad;
2277 		syscallarg(off_t) length;
2278 	} */ *uap;
2279 {
2280 	register struct vnode *vp;
2281 	struct vattr vattr;
2282 	int error;
2283 	struct nameidata nd;
2284 
2285 	if (uap->length < 0)
2286 		return(EINVAL);
2287 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2288 	if (error = namei(&nd))
2289 		return (error);
2290 	vp = nd.ni_vp;
2291 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2292 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2293 	if (vp->v_type == VDIR)
2294 		error = EISDIR;
2295 	else if ((error = vn_writechk(vp)) == 0 &&
2296 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
2297 		VATTR_NULL(&vattr);
2298 		vattr.va_size = SCARG(uap, length);
2299 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2300 	}
2301 	vput(vp);
2302 	return (error);
2303 }
2304 
2305 /*
2306  * Truncate a file given a file descriptor.
2307  */
2308 #ifndef _SYS_SYSPROTO_H_
2309 struct ftruncate_args {
2310 	int	fd;
2311 	int	pad;
2312 	off_t	length;
2313 };
2314 #endif
2315 /* ARGSUSED */
2316 int
2317 ftruncate(p, uap)
2318 	struct proc *p;
2319 	register struct ftruncate_args /* {
2320 		syscallarg(int) fd;
2321 		syscallarg(int) pad;
2322 		syscallarg(off_t) length;
2323 	} */ *uap;
2324 {
2325 	struct vattr vattr;
2326 	struct vnode *vp;
2327 	struct file *fp;
2328 	int error;
2329 
2330 	if (uap->length < 0)
2331 		return(EINVAL);
2332 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2333 		return (error);
2334 	if ((fp->f_flag & FWRITE) == 0)
2335 		return (EINVAL);
2336 	vp = (struct vnode *)fp->f_data;
2337 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2338 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2339 	if (vp->v_type == VDIR)
2340 		error = EISDIR;
2341 	else if ((error = vn_writechk(vp)) == 0) {
2342 		VATTR_NULL(&vattr);
2343 		vattr.va_size = SCARG(uap, length);
2344 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
2345 	}
2346 	VOP_UNLOCK(vp, 0, p);
2347 	return (error);
2348 }
2349 
2350 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2351 /*
2352  * Truncate a file given its path name.
2353  */
2354 #ifndef _SYS_SYSPROTO_H_
2355 struct otruncate_args {
2356 	char	*path;
2357 	long	length;
2358 };
2359 #endif
2360 /* ARGSUSED */
2361 int
2362 otruncate(p, uap)
2363 	struct proc *p;
2364 	register struct otruncate_args /* {
2365 		syscallarg(char *) path;
2366 		syscallarg(long) length;
2367 	} */ *uap;
2368 {
2369 	struct truncate_args /* {
2370 		syscallarg(char *) path;
2371 		syscallarg(int) pad;
2372 		syscallarg(off_t) length;
2373 	} */ nuap;
2374 
2375 	SCARG(&nuap, path) = SCARG(uap, path);
2376 	SCARG(&nuap, length) = SCARG(uap, length);
2377 	return (truncate(p, &nuap));
2378 }
2379 
2380 /*
2381  * Truncate a file given a file descriptor.
2382  */
2383 #ifndef _SYS_SYSPROTO_H_
2384 struct oftruncate_args {
2385 	int	fd;
2386 	long	length;
2387 };
2388 #endif
2389 /* ARGSUSED */
2390 int
2391 oftruncate(p, uap)
2392 	struct proc *p;
2393 	register struct oftruncate_args /* {
2394 		syscallarg(int) fd;
2395 		syscallarg(long) length;
2396 	} */ *uap;
2397 {
2398 	struct ftruncate_args /* {
2399 		syscallarg(int) fd;
2400 		syscallarg(int) pad;
2401 		syscallarg(off_t) length;
2402 	} */ nuap;
2403 
2404 	SCARG(&nuap, fd) = SCARG(uap, fd);
2405 	SCARG(&nuap, length) = SCARG(uap, length);
2406 	return (ftruncate(p, &nuap));
2407 }
2408 #endif /* COMPAT_43 || COMPAT_SUNOS */
2409 
2410 /*
2411  * Sync an open file.
2412  */
2413 #ifndef _SYS_SYSPROTO_H_
2414 struct fsync_args {
2415 	int	fd;
2416 };
2417 #endif
2418 /* ARGSUSED */
2419 int
2420 fsync(p, uap)
2421 	struct proc *p;
2422 	struct fsync_args /* {
2423 		syscallarg(int) fd;
2424 	} */ *uap;
2425 {
2426 	register struct vnode *vp;
2427 	struct file *fp;
2428 	int error;
2429 
2430 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2431 		return (error);
2432 	vp = (struct vnode *)fp->f_data;
2433 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2434 	if (vp->v_object)
2435 		vm_object_page_clean(vp->v_object, 0, 0, 0);
2436 	if ((error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p)) == 0 &&
2437 	    vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) &&
2438 	    bioops.io_fsync)
2439 		error = (*bioops.io_fsync)(vp);
2440 	VOP_UNLOCK(vp, 0, p);
2441 	return (error);
2442 }
2443 
2444 /*
2445  * Rename files.  Source and destination must either both be directories,
2446  * or both not be directories.  If target is a directory, it must be empty.
2447  */
2448 #ifndef _SYS_SYSPROTO_H_
2449 struct rename_args {
2450 	char	*from;
2451 	char	*to;
2452 };
2453 #endif
2454 /* ARGSUSED */
2455 int
2456 rename(p, uap)
2457 	struct proc *p;
2458 	register struct rename_args /* {
2459 		syscallarg(char *) from;
2460 		syscallarg(char *) to;
2461 	} */ *uap;
2462 {
2463 	register struct vnode *tvp, *fvp, *tdvp;
2464 	struct nameidata fromnd, tond;
2465 	int error;
2466 
2467 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2468 	    SCARG(uap, from), p);
2469 	if (error = namei(&fromnd))
2470 		return (error);
2471 	fvp = fromnd.ni_vp;
2472 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
2473 	    UIO_USERSPACE, SCARG(uap, to), p);
2474 	if (fromnd.ni_vp->v_type == VDIR)
2475 		tond.ni_cnd.cn_flags |= WILLBEDIR;
2476 	if (error = namei(&tond)) {
2477 		/* Translate error code for rename("dir1", "dir2/."). */
2478 		if (error == EISDIR && fvp->v_type == VDIR)
2479 			error = EINVAL;
2480 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2481 		vrele(fromnd.ni_dvp);
2482 		vrele(fvp);
2483 		goto out1;
2484 	}
2485 	tdvp = tond.ni_dvp;
2486 	tvp = tond.ni_vp;
2487 	if (tvp != NULL) {
2488 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2489 			error = ENOTDIR;
2490 			goto out;
2491 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2492 			error = EISDIR;
2493 			goto out;
2494 		}
2495 	}
2496 	if (fvp == tdvp)
2497 		error = EINVAL;
2498 	/*
2499 	 * If source is the same as the destination (that is the
2500 	 * same inode number with the same name in the same directory),
2501 	 * then there is nothing to do.
2502 	 */
2503 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
2504 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
2505 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
2506 	      fromnd.ni_cnd.cn_namelen))
2507 		error = -1;
2508 out:
2509 	if (!error) {
2510 		VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
2511 		if (fromnd.ni_dvp != tdvp) {
2512 			VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2513 		}
2514 		if (tvp) {
2515 			VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
2516 		}
2517 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2518 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2519 	} else {
2520 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
2521 		if (tdvp == tvp)
2522 			vrele(tdvp);
2523 		else
2524 			vput(tdvp);
2525 		if (tvp)
2526 			vput(tvp);
2527 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2528 		vrele(fromnd.ni_dvp);
2529 		vrele(fvp);
2530 	}
2531 	vrele(tond.ni_startdir);
2532 	ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
2533 	ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
2534 	ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
2535 	ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
2536 	zfree(namei_zone, tond.ni_cnd.cn_pnbuf);
2537 out1:
2538 	if (fromnd.ni_startdir)
2539 		vrele(fromnd.ni_startdir);
2540 	zfree(namei_zone, fromnd.ni_cnd.cn_pnbuf);
2541 	if (error == -1)
2542 		return (0);
2543 	return (error);
2544 }
2545 
2546 /*
2547  * Make a directory file.
2548  */
2549 #ifndef _SYS_SYSPROTO_H_
2550 struct mkdir_args {
2551 	char	*path;
2552 	int	mode;
2553 };
2554 #endif
2555 /* ARGSUSED */
2556 int
2557 mkdir(p, uap)
2558 	struct proc *p;
2559 	register struct mkdir_args /* {
2560 		syscallarg(char *) path;
2561 		syscallarg(int) mode;
2562 	} */ *uap;
2563 {
2564 	register struct vnode *vp;
2565 	struct vattr vattr;
2566 	int error;
2567 	struct nameidata nd;
2568 
2569 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
2570 	nd.ni_cnd.cn_flags |= WILLBEDIR;
2571 	if (error = namei(&nd))
2572 		return (error);
2573 	vp = nd.ni_vp;
2574 	if (vp != NULL) {
2575 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2576 		if (nd.ni_dvp == vp)
2577 			vrele(nd.ni_dvp);
2578 		else
2579 			vput(nd.ni_dvp);
2580 		vrele(vp);
2581 		return (EEXIST);
2582 	}
2583 	VATTR_NULL(&vattr);
2584 	vattr.va_type = VDIR;
2585 	vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2586 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2587 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2588 	vput(nd.ni_dvp);
2589 	if (!error)
2590 		vput(nd.ni_vp);
2591 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
2592 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
2593 	return (error);
2594 }
2595 
2596 /*
2597  * Remove a directory file.
2598  */
2599 #ifndef _SYS_SYSPROTO_H_
2600 struct rmdir_args {
2601 	char	*path;
2602 };
2603 #endif
2604 /* ARGSUSED */
2605 int
2606 rmdir(p, uap)
2607 	struct proc *p;
2608 	struct rmdir_args /* {
2609 		syscallarg(char *) path;
2610 	} */ *uap;
2611 {
2612 	register struct vnode *vp;
2613 	int error;
2614 	struct nameidata nd;
2615 
2616 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2617 	    SCARG(uap, path), p);
2618 	if (error = namei(&nd))
2619 		return (error);
2620 	vp = nd.ni_vp;
2621 	if (vp->v_type != VDIR) {
2622 		error = ENOTDIR;
2623 		goto out;
2624 	}
2625 	/*
2626 	 * No rmdir "." please.
2627 	 */
2628 	if (nd.ni_dvp == vp) {
2629 		error = EINVAL;
2630 		goto out;
2631 	}
2632 	/*
2633 	 * The root of a mounted filesystem cannot be deleted.
2634 	 */
2635 	if (vp->v_flag & VROOT)
2636 		error = EBUSY;
2637 out:
2638 	if (!error) {
2639 		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2640 		VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2641 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2642 	} else {
2643 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2644 	}
2645 	if (nd.ni_dvp == vp)
2646 		vrele(nd.ni_dvp);
2647 	else
2648 		vput(nd.ni_dvp);
2649 	if (vp != NULLVP)
2650 		vput(vp);
2651 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
2652 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
2653 	return (error);
2654 }
2655 
2656 #ifdef COMPAT_43
2657 /*
2658  * Read a block of directory entries in a file system independent format.
2659  */
2660 #ifndef _SYS_SYSPROTO_H_
2661 struct ogetdirentries_args {
2662 	int	fd;
2663 	char	*buf;
2664 	u_int	count;
2665 	long	*basep;
2666 };
2667 #endif
2668 int
2669 ogetdirentries(p, uap)
2670 	struct proc *p;
2671 	register struct ogetdirentries_args /* {
2672 		syscallarg(int) fd;
2673 		syscallarg(char *) buf;
2674 		syscallarg(u_int) count;
2675 		syscallarg(long *) basep;
2676 	} */ *uap;
2677 {
2678 	struct vnode *vp;
2679 	struct file *fp;
2680 	struct uio auio, kuio;
2681 	struct iovec aiov, kiov;
2682 	struct dirent *dp, *edp;
2683 	caddr_t dirbuf;
2684 	int error, eofflag, readcnt;
2685 	long loff;
2686 
2687 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2688 		return (error);
2689 	if ((fp->f_flag & FREAD) == 0)
2690 		return (EBADF);
2691 	vp = (struct vnode *)fp->f_data;
2692 unionread:
2693 	if (vp->v_type != VDIR)
2694 		return (EINVAL);
2695 	aiov.iov_base = SCARG(uap, buf);
2696 	aiov.iov_len = SCARG(uap, count);
2697 	auio.uio_iov = &aiov;
2698 	auio.uio_iovcnt = 1;
2699 	auio.uio_rw = UIO_READ;
2700 	auio.uio_segflg = UIO_USERSPACE;
2701 	auio.uio_procp = p;
2702 	auio.uio_resid = SCARG(uap, count);
2703 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2704 	loff = auio.uio_offset = fp->f_offset;
2705 #	if (BYTE_ORDER != LITTLE_ENDIAN)
2706 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
2707 			error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
2708 			    NULL, NULL);
2709 			fp->f_offset = auio.uio_offset;
2710 		} else
2711 #	endif
2712 	{
2713 		kuio = auio;
2714 		kuio.uio_iov = &kiov;
2715 		kuio.uio_segflg = UIO_SYSSPACE;
2716 		kiov.iov_len = SCARG(uap, count);
2717 		MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
2718 		kiov.iov_base = dirbuf;
2719 		error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
2720 			    NULL, NULL);
2721 		fp->f_offset = kuio.uio_offset;
2722 		if (error == 0) {
2723 			readcnt = SCARG(uap, count) - kuio.uio_resid;
2724 			edp = (struct dirent *)&dirbuf[readcnt];
2725 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
2726 #				if (BYTE_ORDER == LITTLE_ENDIAN)
2727 					/*
2728 					 * The expected low byte of
2729 					 * dp->d_namlen is our dp->d_type.
2730 					 * The high MBZ byte of dp->d_namlen
2731 					 * is our dp->d_namlen.
2732 					 */
2733 					dp->d_type = dp->d_namlen;
2734 					dp->d_namlen = 0;
2735 #				else
2736 					/*
2737 					 * The dp->d_type is the high byte
2738 					 * of the expected dp->d_namlen,
2739 					 * so must be zero'ed.
2740 					 */
2741 					dp->d_type = 0;
2742 #				endif
2743 				if (dp->d_reclen > 0) {
2744 					dp = (struct dirent *)
2745 					    ((char *)dp + dp->d_reclen);
2746 				} else {
2747 					error = EIO;
2748 					break;
2749 				}
2750 			}
2751 			if (dp >= edp)
2752 				error = uiomove(dirbuf, readcnt, &auio);
2753 		}
2754 		FREE(dirbuf, M_TEMP);
2755 	}
2756 	VOP_UNLOCK(vp, 0, p);
2757 	if (error)
2758 		return (error);
2759 	if (union_dircheckp && SCARG(uap, count) == auio.uio_resid) {
2760 		error = union_dircheckp(p, &vp, fp);
2761 		if (error == -1)
2762 			goto unionread;
2763 		if (error)
2764 			return (error);
2765 	}
2766 	error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2767 	    sizeof(long));
2768 	p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2769 	return (error);
2770 }
2771 #endif /* COMPAT_43 */
2772 
2773 /*
2774  * Read a block of directory entries in a file system independent format.
2775  */
2776 #ifndef _SYS_SYSPROTO_H_
2777 struct getdirentries_args {
2778 	int	fd;
2779 	char	*buf;
2780 	u_int	count;
2781 	long	*basep;
2782 };
2783 #endif
2784 int
2785 getdirentries(p, uap)
2786 	struct proc *p;
2787 	register struct getdirentries_args /* {
2788 		syscallarg(int) fd;
2789 		syscallarg(char *) buf;
2790 		syscallarg(u_int) count;
2791 		syscallarg(long *) basep;
2792 	} */ *uap;
2793 {
2794 	struct vnode *vp;
2795 	struct file *fp;
2796 	struct uio auio;
2797 	struct iovec aiov;
2798 	long loff;
2799 	int error, eofflag;
2800 
2801 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2802 		return (error);
2803 	if ((fp->f_flag & FREAD) == 0)
2804 		return (EBADF);
2805 	vp = (struct vnode *)fp->f_data;
2806 unionread:
2807 	if (vp->v_type != VDIR)
2808 		return (EINVAL);
2809 	aiov.iov_base = SCARG(uap, buf);
2810 	aiov.iov_len = SCARG(uap, count);
2811 	auio.uio_iov = &aiov;
2812 	auio.uio_iovcnt = 1;
2813 	auio.uio_rw = UIO_READ;
2814 	auio.uio_segflg = UIO_USERSPACE;
2815 	auio.uio_procp = p;
2816 	auio.uio_resid = SCARG(uap, count);
2817 	/* vn_lock(vp, LK_SHARED | LK_RETRY, p); */
2818 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2819 	loff = auio.uio_offset = fp->f_offset;
2820 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
2821 	fp->f_offset = auio.uio_offset;
2822 	VOP_UNLOCK(vp, 0, p);
2823 	if (error)
2824 		return (error);
2825 	if (union_dircheckp && SCARG(uap, count) == auio.uio_resid) {
2826 		error = union_dircheckp(p, &vp, fp);
2827 		if (error == -1)
2828 			goto unionread;
2829 		if (error)
2830 			return (error);
2831 	}
2832 	if (SCARG(uap, basep) != NULL) {
2833 		error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2834 		    sizeof(long));
2835 	}
2836 	p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2837 	return (error);
2838 }
2839 #ifndef _SYS_SYSPROTO_H_
2840 struct getdents_args {
2841 	int fd;
2842 	char *buf;
2843 	size_t count;
2844 };
2845 #endif
2846 int
2847 getdents(p, uap)
2848 	struct proc *p;
2849 	register struct getdents_args /* {
2850 		syscallarg(int) fd;
2851 		syscallarg(char *) buf;
2852 		syscallarg(u_int) count;
2853 	} */ *uap;
2854 {
2855 	struct getdirentries_args ap;
2856 	ap.fd = uap->fd;
2857 	ap.buf = uap->buf;
2858 	ap.count = uap->count;
2859 	ap.basep = NULL;
2860 	return getdirentries(p, &ap);
2861 }
2862 
2863 /*
2864  * Set the mode mask for creation of filesystem nodes.
2865  */
2866 #ifndef _SYS_SYSPROTO_H_
2867 struct umask_args {
2868 	int	newmask;
2869 };
2870 #endif
2871 int
2872 umask(p, uap)
2873 	struct proc *p;
2874 	struct umask_args /* {
2875 		syscallarg(int) newmask;
2876 	} */ *uap;
2877 {
2878 	register struct filedesc *fdp;
2879 
2880 	fdp = p->p_fd;
2881 	p->p_retval[0] = fdp->fd_cmask;
2882 	fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
2883 	return (0);
2884 }
2885 
2886 /*
2887  * Void all references to file by ripping underlying filesystem
2888  * away from vnode.
2889  */
2890 #ifndef _SYS_SYSPROTO_H_
2891 struct revoke_args {
2892 	char	*path;
2893 };
2894 #endif
2895 /* ARGSUSED */
2896 int
2897 revoke(p, uap)
2898 	struct proc *p;
2899 	register struct revoke_args /* {
2900 		syscallarg(char *) path;
2901 	} */ *uap;
2902 {
2903 	register struct vnode *vp;
2904 	struct vattr vattr;
2905 	int error;
2906 	struct nameidata nd;
2907 
2908 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2909 	if (error = namei(&nd))
2910 		return (error);
2911 	vp = nd.ni_vp;
2912 	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2913 		goto out;
2914 	if (p->p_ucred->cr_uid != vattr.va_uid &&
2915 	    (error = suser(p->p_ucred, &p->p_acflag)))
2916 		goto out;
2917 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2918 		VOP_REVOKE(vp, REVOKEALL);
2919 out:
2920 	vrele(vp);
2921 	return (error);
2922 }
2923 
2924 /*
2925  * Convert a user file descriptor to a kernel file entry.
2926  */
2927 int
2928 getvnode(fdp, fd, fpp)
2929 	struct filedesc *fdp;
2930 	int fd;
2931 	struct file **fpp;
2932 {
2933 	struct file *fp;
2934 
2935 	if ((u_int)fd >= fdp->fd_nfiles ||
2936 	    (fp = fdp->fd_ofiles[fd]) == NULL)
2937 		return (EBADF);
2938 	if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO)
2939 		return (EINVAL);
2940 	*fpp = fp;
2941 	return (0);
2942 }
2943 #ifndef _SYS_SYSPROTO_H_
2944 struct  __getcwd_args {
2945 	u_char	*buf;
2946 	u_int	buflen;
2947 };
2948 #endif
2949 #define STATNODE(mode, name, var) \
2950 	SYSCTL_INT(_vfs_cache, OID_AUTO, name, mode, var, 0, "");
2951 
2952 static int disablecwd;
2953 SYSCTL_INT(_debug, OID_AUTO, disablecwd, CTLFLAG_RW, &disablecwd, 0, "");
2954 
2955 static u_long numcwdcalls; STATNODE(CTLFLAG_RD, numcwdcalls, &numcwdcalls);
2956 static u_long numcwdfail1; STATNODE(CTLFLAG_RD, numcwdfail1, &numcwdfail1);
2957 static u_long numcwdfail2; STATNODE(CTLFLAG_RD, numcwdfail2, &numcwdfail2);
2958 static u_long numcwdfail3; STATNODE(CTLFLAG_RD, numcwdfail3, &numcwdfail3);
2959 static u_long numcwdfail4; STATNODE(CTLFLAG_RD, numcwdfail4, &numcwdfail4);
2960 static u_long numcwdfound; STATNODE(CTLFLAG_RD, numcwdfound, &numcwdfound);
2961 int
2962 __getcwd(p, uap)
2963 	struct proc *p;
2964 	struct __getcwd_args *uap;
2965 {
2966 	char *bp, *buf;
2967 	int error, i, slash_prefixed;
2968 	struct filedesc *fdp;
2969 	struct namecache *ncp;
2970 	struct vnode *vp;
2971 
2972 	numcwdcalls++;
2973 	if (disablecwd)
2974 		return (ENODEV);
2975 	if (uap->buflen < 2)
2976 		return (EINVAL);
2977 	if (uap->buflen > MAXPATHLEN)
2978 		uap->buflen = MAXPATHLEN;
2979 	buf = bp = malloc(uap->buflen, M_TEMP, M_WAITOK);
2980 	bp += uap->buflen - 1;
2981 	*bp = '\0';
2982 	fdp = p->p_fd;
2983 	slash_prefixed = 0;
2984 	for (vp = fdp->fd_cdir; vp != fdp->fd_rdir && vp != rootvnode;) {
2985 		if (vp->v_flag & VROOT) {
2986 			vp = vp->v_mount->mnt_vnodecovered;
2987 			continue;
2988 		}
2989 		if (vp->v_dd->v_id != vp->v_ddid) {
2990 			numcwdfail1++;
2991 			free(buf, M_TEMP);
2992 			return (ENOTDIR);
2993 		}
2994 		ncp = TAILQ_FIRST(&vp->v_cache_dst);
2995 		if (!ncp) {
2996 			numcwdfail2++;
2997 			free(buf, M_TEMP);
2998 			return (ENOENT);
2999 		}
3000 		if (ncp->nc_dvp != vp->v_dd) {
3001 			numcwdfail3++;
3002 			free(buf, M_TEMP);
3003 			return (EBADF);
3004 		}
3005 		for (i = ncp->nc_nlen - 1; i >= 0; i--) {
3006 			if (bp == buf) {
3007 				numcwdfail4++;
3008 				free(buf, M_TEMP);
3009 				return (ENOMEM);
3010 			}
3011 			*--bp = ncp->nc_name[i];
3012 		}
3013 		if (bp == buf) {
3014 			numcwdfail4++;
3015 			free(buf, M_TEMP);
3016 			return (ENOMEM);
3017 		}
3018 		*--bp = '/';
3019 		slash_prefixed = 1;
3020 		vp = vp->v_dd;
3021 	}
3022 	if (!slash_prefixed) {
3023 		if (bp == buf) {
3024 			numcwdfail4++;
3025 			free(buf, M_TEMP);
3026 			return (ENOMEM);
3027 		}
3028 		*--bp = '/';
3029 	}
3030 	numcwdfound++;
3031 	error = copyout(bp, uap->buf, strlen(bp) + 1);
3032 	free(buf, M_TEMP);
3033 	return (error);
3034 }
3035