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