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