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