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