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