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