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