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