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