xref: /openbsd-src/sys/kern/vfs_syscalls.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: vfs_syscalls.c,v 1.80 2001/07/26 20:24:47 millert Exp $	*/
2 /*	$NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $	*/
3 
4 /*
5  * Copyright (c) 1989, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  * (c) UNIX System Laboratories, Inc.
8  * All or some portions of this file are derived from material licensed
9  * to the University of California by American Telephone and Telegraph
10  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11  * the permission of UNIX System Laboratories, Inc.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. All advertising materials mentioning features or use of this software
22  *    must display the following acknowledgement:
23  *	This product includes software developed by the University of
24  *	California, Berkeley and its contributors.
25  * 4. Neither the name of the University nor the names of its contributors
26  *    may be used to endorse or promote products derived from this software
27  *    without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  *
41  *	@(#)vfs_syscalls.c	8.28 (Berkeley) 12/10/94
42  */
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/namei.h>
47 #include <sys/filedesc.h>
48 #include <sys/kernel.h>
49 #include <sys/file.h>
50 #include <sys/stat.h>
51 #include <sys/vnode.h>
52 #include <sys/mount.h>
53 #include <sys/proc.h>
54 #include <sys/uio.h>
55 #include <sys/malloc.h>
56 #include <sys/dirent.h>
57 
58 #include <sys/syscallargs.h>
59 
60 #include <vm/vm.h>
61 #include <sys/sysctl.h>
62 
63 #include <uvm/uvm_extern.h>
64 
65 extern int suid_clear;
66 int	usermount = 0;		/* sysctl: by default, users may not mount */
67 
68 static int change_dir __P((struct nameidata *, struct proc *));
69 
70 void checkdirs __P((struct vnode *));
71 
72 /*
73  * Redirection info so we don't have to include the union fs routines in
74  * the kernel directly.  This way, we can build unionfs as an LKM.  The
75  * pointer gets filled in later, when we modload the LKM, or when the
76  * compiled-in unionfs code gets initialized.  For now, we just set
77  * it to a stub routine.
78  */
79 
80 int (*union_check_p) __P((struct proc *, struct vnode **,
81     struct file *, struct uio, int *)) = NULL;
82 
83 /*
84  * Virtual File System System Calls
85  */
86 
87 /*
88  * Mount a file system.
89  */
90 /* ARGSUSED */
91 int
92 sys_mount(p, v, retval)
93 	struct proc *p;
94 	void *v;
95 	register_t *retval;
96 {
97 	register struct sys_mount_args /* {
98 		syscallarg(char *) type;
99 		syscallarg(char *) path;
100 		syscallarg(int) flags;
101 		syscallarg(void *) data;
102 	} */ *uap = v;
103 	register struct vnode *vp;
104 	register struct mount *mp;
105 	int error, flag = 0;
106 #ifdef COMPAT_43
107 	u_long fstypenum = 0;
108 #endif
109 	char fstypename[MFSNAMELEN];
110 	struct vattr va;
111 	struct nameidata nd;
112 	struct vfsconf *vfsp;
113 
114 	if (usermount == 0 && (error = suser(p->p_ucred, &p->p_acflag)))
115 		return (error);
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)) != 0)
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_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 		VOP_UNLOCK(vp, 0, p);
164 		goto update;
165 	}
166 	/*
167 	 * If the user is not root, ensure that they own the directory
168 	 * onto which we are attempting to mount.
169 	 */
170 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
171 	    (va.va_uid != p->p_ucred->cr_uid &&
172 	    (error = suser(p->p_ucred, &p->p_acflag)))) {
173 		vput(vp);
174 		return (error);
175 	}
176 	/*
177 	 * Do not allow NFS export by non-root users. Silently
178 	 * enforce MNT_NOSUID and MNT_NODEV for non-root users.
179 	 */
180 	if (p->p_ucred->cr_uid != 0) {
181 		if (SCARG(uap, flags) & MNT_EXPORTED) {
182 			vput(vp);
183 			return (EPERM);
184 		}
185 		SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
186 	}
187 	if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
188 		return (error);
189 	if (vp->v_type != VDIR) {
190 		vput(vp);
191 		return (ENOTDIR);
192 	}
193 	error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL);
194 	if (error) {
195 #ifdef COMPAT_43
196 		/*
197 		 * Historically filesystem types were identified by number.
198 		 * If we get an integer for the filesystem type instead of a
199 		 * string, we check to see if it matches one of the historic
200 		 * filesystem types.
201 		 */
202 		fstypenum = (u_long)SCARG(uap, type);
203 
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 
213 #else
214 		vput(vp);
215 		return (error);
216 #endif
217 	}
218 	for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
219 		if (!strcmp(vfsp->vfc_name, fstypename))
220 			break;
221 	}
222 
223 	if (vfsp == NULL) {
224 		vput(vp);
225 		return (EOPNOTSUPP);
226 	}
227 
228 	if (vp->v_mountedhere != NULL) {
229 		vput(vp);
230 		return (EBUSY);
231 	}
232 
233 	/*
234 	 * Allocate and initialize the file system.
235 	 */
236 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
237 		M_MOUNT, M_WAITOK);
238 	bzero((char *)mp, (u_long)sizeof(struct mount));
239 	lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
240 	vfs_busy(mp, LK_NOWAIT, 0, p);
241 	mp->mnt_op = vfsp->vfc_vfsops;
242 	mp->mnt_vfc = vfsp;
243 	mp->mnt_flag |= (vfsp->vfc_flags & MNT_VISFLAGMASK);
244 	strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
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_SOFTDEP |
257 	    MNT_NOATIME | MNT_FORCE);
258 	mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
259 	    MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC |
260 	    MNT_SOFTDEP | MNT_NOATIME | MNT_FORCE);
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 
274  		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
275  			if (mp->mnt_syncer == NULL)
276  				error = vfs_allocate_syncvnode(mp);
277  		} else {
278  			if (mp->mnt_syncer != NULL)
279  				vgone(mp->mnt_syncer);
280  			mp->mnt_syncer = NULL;
281  		}
282 
283 		vfs_unbusy(mp, p);
284 		return (error);
285 	}
286 
287 	vp->v_mountedhere = mp;
288 
289 	/*
290 	 * Put the new filesystem on the mount list after root.
291 	 */
292 	cache_purge(vp);
293 	if (!error) {
294 		vfsp->vfc_refcount++;
295 		simple_lock(&mountlist_slock);
296 		CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
297 		simple_unlock(&mountlist_slock);
298 		checkdirs(vp);
299 		VOP_UNLOCK(vp, 0, p);
300  		if ((mp->mnt_flag & MNT_RDONLY) == 0)
301  			error = vfs_allocate_syncvnode(mp);
302 		vfs_unbusy(mp, p);
303 		(void) VFS_STATFS(mp, &mp->mnt_stat, p);
304 		if ((error = VFS_START(mp, 0, p)) != 0)
305 			vrele(vp);
306 	} else {
307 		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
308 		vfs_unbusy(mp, p);
309 		free((caddr_t)mp, M_MOUNT);
310 		vput(vp);
311 	}
312 	return (error);
313 }
314 
315 /*
316  * Scan all active processes to see if any of them have a current
317  * or root directory onto which the new filesystem has just been
318  * mounted. If so, replace them with the new mount point.
319  */
320 void
321 checkdirs(olddp)
322 	struct vnode *olddp;
323 {
324 	struct filedesc *fdp;
325 	struct vnode *newdp;
326 	struct proc *p;
327 
328 	if (olddp->v_usecount == 1)
329 		return;
330 	if (VFS_ROOT(olddp->v_mountedhere, &newdp))
331 		panic("mount: lost mount");
332 	for (p = LIST_FIRST(&allproc); p != 0; p = LIST_NEXT(p, p_list)) {
333 		/*
334 		 * XXX - we have a race with fork here. We should probably
335 		 *       check if the process is SIDL before we fiddle with it.
336 		 */
337 		fdp = p->p_fd;
338 		if (fdp->fd_cdir == olddp) {
339 			vrele(fdp->fd_cdir);
340 			VREF(newdp);
341 			fdp->fd_cdir = newdp;
342 		}
343 		if (fdp->fd_rdir == olddp) {
344 			vrele(fdp->fd_rdir);
345 			VREF(newdp);
346 			fdp->fd_rdir = newdp;
347 		}
348 	}
349 	if (rootvnode == olddp) {
350 		vrele(rootvnode);
351 		VREF(newdp);
352 		rootvnode = newdp;
353 	}
354 	vput(newdp);
355 }
356 
357 /*
358  * Unmount a file system.
359  *
360  * Note: unmount takes a path to the vnode mounted on as argument,
361  * not special file (as before).
362  */
363 /* ARGSUSED */
364 int
365 sys_unmount(p, v, retval)
366 	struct proc *p;
367 	void *v;
368 	register_t *retval;
369 {
370 	register struct sys_unmount_args /* {
371 		syscallarg(char *) path;
372 		syscallarg(int) flags;
373 	} */ *uap = v;
374 	register struct vnode *vp;
375 	struct mount *mp;
376 	int error;
377 	struct nameidata nd;
378 
379 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
380 	    SCARG(uap, path), p);
381 	if ((error = namei(&nd)) != 0)
382 		return (error);
383 	vp = nd.ni_vp;
384 	mp = vp->v_mount;
385 
386 	/*
387 	 * Only root, or the user that did the original mount is
388 	 * permitted to unmount this filesystem.
389 	 */
390 	if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
391 	    (error = suser(p->p_ucred, &p->p_acflag))) {
392 		vput(vp);
393 		return (error);
394 	}
395 
396 	/*
397 	 * Don't allow unmounting the root file system.
398 	 */
399 	if (mp->mnt_flag & MNT_ROOTFS) {
400 		vput(vp);
401 		return (EINVAL);
402 	}
403 
404 	/*
405 	 * Must be the root of the filesystem
406 	 */
407 	if ((vp->v_flag & VROOT) == 0) {
408 		vput(vp);
409 		return (EINVAL);
410 	}
411 	vput(vp);
412 
413 	if (vfs_busy(mp, 0, NULL, p))
414 		return (EBUSY);
415 
416 	return (dounmount(mp, SCARG(uap, flags), p));
417 }
418 
419 /*
420  * Do the actual file system unmount.
421  */
422 int
423 dounmount(mp, flags, p)
424 	register struct mount *mp;
425 	int flags;
426 	struct proc *p;
427 {
428 	struct vnode *coveredvp;
429 	int error;
430 
431 	simple_lock(&mountlist_slock);
432 	mp->mnt_flag |= MNT_UNMOUNT;
433 	vfs_unbusy(mp, p);
434 	lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p);
435  	mp->mnt_flag &=~ MNT_ASYNC;
436  	cache_purgevfs(mp);	/* remove cache entries for this file sys */
437  	if (mp->mnt_syncer != NULL)
438  		vgone(mp->mnt_syncer);
439 	if (((mp->mnt_flag & MNT_RDONLY) ||
440 	    (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
441  	    (flags & MNT_FORCE))
442  		error = VFS_UNMOUNT(mp, flags, p);
443 	simple_lock(&mountlist_slock);
444  	if (error) {
445  		if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
446  			(void) vfs_allocate_syncvnode(mp);
447 		mp->mnt_flag &= ~MNT_UNMOUNT;
448 		lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
449 		    &mountlist_slock, p);
450 		if (mp->mnt_flag & MNT_MWAIT)
451 			wakeup((caddr_t)mp);
452 		mp->mnt_flag &= ~MNT_MWAIT;
453 		return (error);
454 	}
455 	CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
456 	if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
457 		coveredvp->v_mountedhere = (struct mount *)0;
458  		vrele(coveredvp);
459  	}
460 	mp->mnt_vfc->vfc_refcount--;
461 	if (mp->mnt_vnodelist.lh_first != NULL)
462 		panic("unmount: dangling vnode");
463 	lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
464 	if (mp->mnt_flag & MNT_MWAIT)
465 		wakeup((caddr_t)mp);
466 	free((caddr_t)mp, M_MOUNT);
467 	return (0);
468 }
469 
470 /*
471  * Sync each mounted filesystem.
472  */
473 #ifdef DEBUG
474 int syncprt = 0;
475 struct ctldebug debug0 = { "syncprt", &syncprt };
476 #endif
477 
478 /* ARGSUSED */
479 int
480 sys_sync(p, v, retval)
481 	struct proc *p;
482 	void *v;
483 	register_t *retval;
484 {
485 	register struct mount *mp, *nmp;
486 	int asyncflag;
487 
488 	simple_lock(&mountlist_slock);
489 	for (mp = CIRCLEQ_LAST(&mountlist); mp != CIRCLEQ_END(&mountlist);
490 	    mp = nmp) {
491 		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
492 			nmp = CIRCLEQ_PREV(mp, mnt_list);
493 			continue;
494 		}
495 		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
496 			asyncflag = mp->mnt_flag & MNT_ASYNC;
497 			mp->mnt_flag &= ~MNT_ASYNC;
498 			uvm_vnp_sync(mp);
499 			VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
500 			if (asyncflag)
501 				mp->mnt_flag |= MNT_ASYNC;
502 		}
503 		simple_lock(&mountlist_slock);
504 		nmp = CIRCLEQ_PREV(mp, mnt_list);
505 		vfs_unbusy(mp, p);
506 	}
507 	simple_unlock(&mountlist_slock);
508 
509 #ifdef DEBUG
510 	if (syncprt)
511 		vfs_bufstats();
512 #endif /* DEBUG */
513 	return (0);
514 }
515 
516 /*
517  * Change filesystem quotas.
518  */
519 /* ARGSUSED */
520 int
521 sys_quotactl(p, v, retval)
522 	struct proc *p;
523 	void *v;
524 	register_t *retval;
525 {
526 	register struct sys_quotactl_args /* {
527 		syscallarg(char *) path;
528 		syscallarg(int) cmd;
529 		syscallarg(int) uid;
530 		syscallarg(caddr_t) arg;
531 	} */ *uap = v;
532 	register struct mount *mp;
533 	int error;
534 	struct nameidata nd;
535 
536 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
537 	if ((error = namei(&nd)) != 0)
538 		return (error);
539 	mp = nd.ni_vp->v_mount;
540 	vrele(nd.ni_vp);
541 	return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
542 	    SCARG(uap, arg), p));
543 }
544 
545 /*
546  * Get filesystem statistics.
547  */
548 /* ARGSUSED */
549 int
550 sys_statfs(p, v, retval)
551 	struct proc *p;
552 	void *v;
553 	register_t *retval;
554 {
555 	register struct sys_statfs_args /* {
556 		syscallarg(char *) path;
557 		syscallarg(struct statfs *) buf;
558 	} */ *uap = v;
559 	register struct mount *mp;
560 	register struct statfs *sp;
561 	int error;
562 	struct nameidata nd;
563 	struct statfs sb;
564 
565 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
566 	if ((error = namei(&nd)) != 0)
567 		return (error);
568 	mp = nd.ni_vp->v_mount;
569 	sp = &mp->mnt_stat;
570 	vrele(nd.ni_vp);
571 	if ((error = VFS_STATFS(mp, sp, p)) != 0)
572 		return (error);
573 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
574 #if notyet
575 	if (mp->mnt_flag & MNT_SOFTDEP)
576 		sp->f_eflags = STATFS_SOFTUPD;
577 #endif
578 	/* Don't let non-root see filesystem id (for NFS security) */
579 	if (suser(p->p_ucred, &p->p_acflag)) {
580 		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
581 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
582 		sp = &sb;
583 	}
584 	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
585 }
586 
587 /*
588  * Get filesystem statistics.
589  */
590 /* ARGSUSED */
591 int
592 sys_fstatfs(p, v, retval)
593 	struct proc *p;
594 	void *v;
595 	register_t *retval;
596 {
597 	register struct sys_fstatfs_args /* {
598 		syscallarg(int) fd;
599 		syscallarg(struct statfs *) buf;
600 	} */ *uap = v;
601 	struct file *fp;
602 	struct mount *mp;
603 	register struct statfs *sp;
604 	int error;
605 	struct statfs sb;
606 
607 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
608 		return (error);
609 	mp = ((struct vnode *)fp->f_data)->v_mount;
610 	sp = &mp->mnt_stat;
611 	if ((error = VFS_STATFS(mp, sp, p)) != 0)
612 		return (error);
613 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
614 #if notyet
615 	if (mp->mnt_flag & MNT_SOFTDEP)
616 		sp->f_eflags = STATFS_SOFTUPD;
617 #endif
618 	/* Don't let non-root see filesystem id (for NFS security) */
619 	if (suser(p->p_ucred, &p->p_acflag)) {
620 		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
621 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
622 		sp = &sb;
623 	}
624 	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
625 }
626 
627 /*
628  * Get statistics on all filesystems.
629  */
630 int
631 sys_getfsstat(p, v, retval)
632 	struct proc *p;
633 	void *v;
634 	register_t *retval;
635 {
636 	register struct sys_getfsstat_args /* {
637 		syscallarg(struct statfs *) buf;
638 		syscallarg(size_t) bufsize;
639 		syscallarg(int) flags;
640 	} */ *uap = v;
641 	register struct mount *mp, *nmp;
642 	register struct statfs *sp;
643 	struct statfs sb;
644 	caddr_t sfsp;
645 	size_t count, maxcount;
646 	int error, flags = SCARG(uap, flags);
647 
648 	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
649 	sfsp = (caddr_t)SCARG(uap, buf);
650 	count = 0;
651 	simple_lock(&mountlist_slock);
652 	for (mp = CIRCLEQ_FIRST(&mountlist); mp != CIRCLEQ_END(&mountlist);
653 	    mp = nmp) {
654 		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
655 			nmp = CIRCLEQ_NEXT(mp, mnt_list);
656 			continue;
657 		}
658 		if (sfsp && count < maxcount) {
659 			sp = &mp->mnt_stat;
660 
661 			/* Refresh stats unless MNT_NOWAIT is specified */
662 			if (flags != MNT_NOWAIT &&
663 			    flags != MNT_LAZY &&
664 			    (flags == MNT_WAIT ||
665 			    flags == 0) &&
666 			    (error = VFS_STATFS(mp, sp, p))) {
667 				simple_lock(&mountlist_slock);
668 				nmp = CIRCLEQ_NEXT(mp, mnt_list);
669 				vfs_unbusy(mp, p);
670  				continue;
671 			}
672 
673 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
674 #if notyet
675 			if (mp->mnt_flag & MNT_SOFTDEP)
676 				sp->f_eflags = STATFS_SOFTUPD;
677 #endif
678 			if (suser(p->p_ucred, &p->p_acflag)) {
679 				bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
680 				sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
681 				sp = &sb;
682 			}
683 			error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
684 			if (error) {
685 				vfs_unbusy(mp, p);
686 				return (error);
687 			}
688 			sfsp += sizeof(*sp);
689 		}
690 		count++;
691 		simple_lock(&mountlist_slock);
692 		nmp = CIRCLEQ_NEXT(mp, mnt_list);
693 		vfs_unbusy(mp, p);
694 	}
695 	simple_unlock(&mountlist_slock);
696 	if (sfsp && count > maxcount)
697 		*retval = maxcount;
698 	else
699 		*retval = count;
700 	return (0);
701 }
702 
703 /*
704  * Change current working directory to a given file descriptor.
705  */
706 /* ARGSUSED */
707 int
708 sys_fchdir(p, v, retval)
709 	struct proc *p;
710 	void *v;
711 	register_t *retval;
712 {
713 	struct sys_fchdir_args /* {
714 		syscallarg(int) fd;
715 	} */ *uap = v;
716 	register struct filedesc *fdp = p->p_fd;
717 	struct vnode *vp, *tdp;
718 	struct mount *mp;
719 	struct file *fp;
720 	int error;
721 
722 	if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
723 		return (error);
724 	vp = (struct vnode *)fp->f_data;
725 	VREF(vp);
726 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
727 	if (vp->v_type != VDIR)
728 		error = ENOTDIR;
729 	else
730 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
731 
732 	while (!error && (mp = vp->v_mountedhere) != NULL) {
733 		if (vfs_busy(mp, 0, 0, p))
734 			continue;
735 		error = VFS_ROOT(mp, &tdp);
736 		vfs_unbusy(mp, p);
737 		if (error)
738 			break;
739 		vput(vp);
740 		vp = tdp;
741 	}
742 	if (error) {
743 		vput(vp);
744 		return (error);
745 	}
746 	VOP_UNLOCK(vp, 0, p);
747 	vrele(fdp->fd_cdir);
748 	fdp->fd_cdir = vp;
749 	return (0);
750 }
751 
752 /*
753  * Change current working directory (``.'').
754  */
755 /* ARGSUSED */
756 int
757 sys_chdir(p, v, retval)
758 	struct proc *p;
759 	void *v;
760 	register_t *retval;
761 {
762 	struct sys_chdir_args /* {
763 		syscallarg(char *) path;
764 	} */ *uap = v;
765 	register struct filedesc *fdp = p->p_fd;
766 	int error;
767 	struct nameidata nd;
768 
769 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
770 	    SCARG(uap, path), p);
771 	if ((error = change_dir(&nd, p)) != 0)
772 		return (error);
773 	vrele(fdp->fd_cdir);
774 	fdp->fd_cdir = nd.ni_vp;
775 	return (0);
776 }
777 
778 /*
779  * Change notion of root (``/'') directory.
780  */
781 /* ARGSUSED */
782 int
783 sys_chroot(p, v, retval)
784 	struct proc *p;
785 	void *v;
786 	register_t *retval;
787 {
788 	struct sys_chroot_args /* {
789 		syscallarg(char *) path;
790 	} */ *uap = v;
791 	register struct filedesc *fdp = p->p_fd;
792 	int error;
793 	struct nameidata nd;
794 
795 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
796 		return (error);
797 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
798 	    SCARG(uap, path), p);
799 	if ((error = change_dir(&nd, p)) != 0)
800 		return (error);
801 	if (fdp->fd_rdir != NULL) {
802 		/*
803 		 * A chroot() done inside a changed root environment does
804 		 * an automatic chdir to avoid the out-of-tree experience.
805 		 */
806 		vrele(fdp->fd_rdir);
807 		vrele(fdp->fd_cdir);
808 		VREF(nd.ni_vp);
809 		fdp->fd_cdir = nd.ni_vp;
810 	}
811 	fdp->fd_rdir = nd.ni_vp;
812 	return (0);
813 }
814 
815 /*
816  * Common routine for chroot and chdir.
817  */
818 static int
819 change_dir(ndp, p)
820 	register struct nameidata *ndp;
821 	struct proc *p;
822 {
823 	struct vnode *vp;
824 	int error;
825 
826 	if ((error = namei(ndp)) != 0)
827 		return (error);
828 	vp = ndp->ni_vp;
829 	if (vp->v_type != VDIR)
830 		error = ENOTDIR;
831 	else
832 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
833 	if (error)
834 		vput(vp);
835 	else
836 		VOP_UNLOCK(vp, 0, p);
837 	return (error);
838 }
839 
840 /*
841  * Check permissions, allocate an open file structure,
842  * and call the device open routine if any.
843  */
844 int
845 sys_open(p, v, retval)
846 	struct proc *p;
847 	void *v;
848 	register_t *retval;
849 {
850 	struct sys_open_args /* {
851 		syscallarg(char *) path;
852 		syscallarg(int) flags;
853 		syscallarg(int) mode;
854 	} */ *uap = v;
855 	struct filedesc *fdp = p->p_fd;
856 	struct file *fp;
857 	struct vnode *vp;
858 	struct vattr vattr;
859 	int flags, cmode;
860 	int type, indx, error, localtrunc = 0;
861 	struct flock lf;
862 	struct nameidata nd;
863 
864 	if ((error = falloc(p, &fp, &indx)) != 0)
865 		return (error);
866 
867 	flags = FFLAGS(SCARG(uap, flags));
868 	cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
869 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
870 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
871 	if ((flags & O_TRUNC) && (flags & (O_EXLOCK | O_SHLOCK))) {
872 		localtrunc = 1;
873 		flags &= ~O_TRUNC;	/* Must do truncate ourselves */
874 	}
875 	if ((error = vn_open(&nd, flags, cmode)) != 0) {
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 		fdremove(fdp, indx);
887 		return (error);
888 	}
889 	p->p_dupfd = 0;
890 	vp = nd.ni_vp;
891 	fp->f_flag = flags & FMASK;
892 	fp->f_type = DTYPE_VNODE;
893 	fp->f_ops = &vnops;
894 	fp->f_data = (caddr_t)vp;
895 	if (flags & (O_EXLOCK | O_SHLOCK)) {
896 		lf.l_whence = SEEK_SET;
897 		lf.l_start = 0;
898 		lf.l_len = 0;
899 		if (flags & O_EXLOCK)
900 			lf.l_type = F_WRLCK;
901 		else
902 			lf.l_type = F_RDLCK;
903 		type = F_FLOCK;
904 		if ((flags & FNONBLOCK) == 0)
905 			type |= F_WAIT;
906 		VOP_UNLOCK(vp, 0, p);
907 		error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
908 		if (error) {
909 			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
910 			ffree(fp);
911 			fdremove(fdp, indx);
912 			return (error);
913 		}
914 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
915 		fp->f_flag |= FHASLOCK;
916 	}
917 	if (localtrunc) {
918 		VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
919 		if ((fp->f_flag & FWRITE) == 0)
920 			error = EACCES;
921 		else if (vp->v_mount->mnt_flag & MNT_RDONLY)
922 			error = EROFS;
923 		else if (vp->v_type == VDIR)
924 			error = EISDIR;
925 		else if ((error = vn_writechk(vp)) == 0) {
926 			VATTR_NULL(&vattr);
927 			vattr.va_size = 0;
928 			error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
929 		}
930 		if (error) {
931 			VOP_UNLOCK(vp, 0, p);
932 			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
933 			ffree(fp);
934 			fdremove(fdp, indx);
935 			return (error);
936 		}
937 	}
938 	VOP_UNLOCK(vp, 0, p);
939 	*retval = indx;
940 	return (0);
941 }
942 
943 /*
944  * Get file handle system call
945  */
946 int
947 sys_getfh(p, v, retval)
948 	struct proc *p;
949 	register void *v;
950 	register_t *retval;
951 {
952 	register struct sys_getfh_args /* {
953 		syscallarg(char *) fname;
954 		syscallarg(fhandle_t *) fhp;
955 	} */ *uap = v;
956 	register struct vnode *vp;
957 	fhandle_t fh;
958 	int error;
959 	struct nameidata nd;
960 
961 	/*
962 	 * Must be super user
963 	 */
964 	error = suser(p->p_ucred, &p->p_acflag);
965 	if (error)
966 		return (error);
967 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
968 	    SCARG(uap, fname), p);
969 	error = namei(&nd);
970 	if (error)
971 		return (error);
972 	vp = nd.ni_vp;
973 	bzero((caddr_t)&fh, sizeof(fh));
974 	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
975 	error = VFS_VPTOFH(vp, &fh.fh_fid);
976 	vput(vp);
977 	if (error)
978 		return (error);
979 	error = copyout((caddr_t)&fh, (caddr_t)SCARG(uap, fhp), sizeof (fh));
980 	return (error);
981 }
982 
983 /*
984  * Open a file given a file handle.
985  *
986  * Check permissions, allocate an open file structure,
987  * and call the device open routine if any.
988  */
989 int
990 sys_fhopen(p, v, retval)
991 	struct proc *p;
992 	void *v;
993 	register_t *retval;
994 {
995 	register struct sys_fhopen_args /* {
996 		syscallarg(const fhandle_t *) fhp;
997 		syscallarg(int) flags;
998 	} */ *uap = v;
999 	struct filedesc *fdp = p->p_fd;
1000 	struct file *fp;
1001 	struct vnode *vp = NULL;
1002 	struct mount *mp;
1003 	struct ucred *cred = p->p_ucred;
1004 	int flags;
1005 	int type, indx, error=0;
1006 	struct flock lf;
1007 	struct vattr va;
1008 	fhandle_t fh;
1009 
1010 	/*
1011 	 * Must be super user
1012 	 */
1013 	if ((error = suser(p->p_ucred, &p->p_acflag)))
1014 		return (error);
1015 
1016 	flags = FFLAGS(SCARG(uap, flags));
1017 	if ((flags & (FREAD | FWRITE)) == 0)
1018 		return (EINVAL);
1019 	if ((flags & O_CREAT))
1020 		return (EINVAL);
1021 
1022 	if ((error = falloc(p, &fp, &indx)) != 0)
1023 		return (error);
1024 
1025 	if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
1026 		goto bad;
1027 
1028 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
1029 		error = ESTALE;
1030 		goto bad;
1031 	}
1032 
1033 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)) != 0) {
1034 		vp = NULL;	/* most likely unnecessary sanity for bad: */
1035 		goto bad;
1036 	}
1037 
1038 	/* Now do an effective vn_open */
1039 
1040 	if (vp->v_type == VSOCK) {
1041 		error = EOPNOTSUPP;
1042 		goto bad;
1043 	}
1044 	if (flags & FREAD) {
1045 		if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0)
1046 			goto bad;
1047 	}
1048 	if (flags & (FWRITE | O_TRUNC)) {
1049 		if (vp->v_type == VDIR) {
1050 			error = EISDIR;
1051 			goto bad;
1052 		}
1053 		if ((error = vn_writechk(vp)) != 0 ||
1054 		    (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
1055 			goto bad;
1056 	}
1057 	if (flags & O_TRUNC) {
1058 		VOP_UNLOCK(vp, 0, p);				/* XXX */
1059 		VOP_LEASE(vp, p, cred, LEASE_WRITE);
1060 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);	/* XXX */
1061 		VATTR_NULL(&va);
1062 		va.va_size = 0;
1063 		if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
1064 			goto bad;
1065 	}
1066 	if ((error = VOP_OPEN(vp, flags, cred, p)) != 0)
1067 		goto bad;
1068 	if (flags & FWRITE)
1069 		vp->v_writecount++;
1070 
1071 	/* done with modified vn_open, now finish what sys_open does. */
1072 
1073 	fp->f_flag = flags & FMASK;
1074 	fp->f_type = DTYPE_VNODE;
1075 	fp->f_ops = &vnops;
1076 	fp->f_data = (caddr_t)vp;
1077 	if (flags & (O_EXLOCK | O_SHLOCK)) {
1078 		lf.l_whence = SEEK_SET;
1079 		lf.l_start = 0;
1080 		lf.l_len = 0;
1081 		if (flags & O_EXLOCK)
1082 			lf.l_type = F_WRLCK;
1083 		else
1084 			lf.l_type = F_RDLCK;
1085 		type = F_FLOCK;
1086 		if ((flags & FNONBLOCK) == 0)
1087 			type |= F_WAIT;
1088 		VOP_UNLOCK(vp, 0, p);
1089 		error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
1090 		if (error) {
1091 			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
1092 			ffree(fp);
1093 			fdremove(fdp, indx);
1094 			return (error);
1095 		}
1096 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1097 		fp->f_flag |= FHASLOCK;
1098 	}
1099 	VOP_UNLOCK(vp, 0, p);
1100 	*retval = indx;
1101 	return (0);
1102 
1103 bad:
1104 	ffree(fp);
1105 	fdremove(fdp, indx);
1106 	if (vp != NULL)
1107 		vput(vp);
1108 	return (error);
1109 }
1110 
1111 /* ARGSUSED */
1112 int
1113 sys_fhstat(p, v, retval)
1114 	struct proc *p;
1115 	void *v;
1116 	register_t *retval;
1117 {
1118 	register struct sys_fhstat_args /* {
1119 		syscallarg(const fhandle_t *) fhp;
1120 		syscallarg(struct stat *) sb;
1121 	} */ *uap = v;
1122 	struct stat sb;
1123 	int error;
1124 	fhandle_t fh;
1125 	struct mount *mp;
1126 	struct vnode *vp;
1127 
1128 	/*
1129 	 * Must be super user
1130 	 */
1131 	if ((error = suser(p->p_ucred, &p->p_acflag)))
1132 		return (error);
1133 
1134 	if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
1135 		return (error);
1136 
1137 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
1138 		return (ESTALE);
1139 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
1140 		return (error);
1141 	error = vn_stat(vp, &sb, p);
1142 	vput(vp);
1143 	if (error)
1144 		return (error);
1145 	error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
1146 	return (error);
1147 }
1148 
1149 /* ARGSUSED */
1150 int
1151 sys_fhstatfs(p, v, retval)
1152 	struct proc *p;
1153 	void *v;
1154 	register_t *retval;
1155 {
1156 	register struct sys_fhstatfs_args /*
1157 		syscallarg(const fhandle_t *) fhp;
1158 		syscallarg(struct statfs *) buf;
1159 	} */ *uap = v;
1160 	struct statfs sp;
1161 	fhandle_t fh;
1162 	struct mount *mp;
1163 	struct vnode *vp;
1164 	int error;
1165 
1166 	/*
1167 	 * Must be super user
1168 	 */
1169 	if ((error = suser(p->p_ucred, &p->p_acflag)))
1170 		return (error);
1171 
1172 	if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
1173 		return (error);
1174 
1175 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
1176 		return (ESTALE);
1177 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
1178 		return (error);
1179 	mp = vp->v_mount;
1180 	vput(vp);
1181 	if ((error = VFS_STATFS(mp, &sp, p)) != 0)
1182 		return (error);
1183 	sp.f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1184 	return (copyout(&sp, SCARG(uap, buf), sizeof(sp)));
1185 }
1186 
1187 /*
1188  * Create a special file.
1189  */
1190 /* ARGSUSED */
1191 int
1192 sys_mknod(p, v, retval)
1193 	struct proc *p;
1194 	void *v;
1195 	register_t *retval;
1196 {
1197 	register struct sys_mknod_args /* {
1198 		syscallarg(char *) path;
1199 		syscallarg(int) mode;
1200 		syscallarg(int) dev;
1201 	} */ *uap = v;
1202 	register struct vnode *vp;
1203 	struct vattr vattr;
1204 	int error;
1205 	int whiteout = 0;
1206 	struct nameidata nd;
1207 
1208 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1209 		return (error);
1210 	if (p->p_fd->fd_rdir)
1211 		return (EINVAL);
1212 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1213 	if ((error = namei(&nd)) != 0)
1214 		return (error);
1215 	vp = nd.ni_vp;
1216 	if (vp != NULL)
1217 		error = EEXIST;
1218 	else {
1219 		VATTR_NULL(&vattr);
1220 		vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1221 		vattr.va_rdev = SCARG(uap, dev);
1222 		whiteout = 0;
1223 
1224 		switch (SCARG(uap, mode) & S_IFMT) {
1225 		case S_IFMT:	/* used by badsect to flag bad sectors */
1226 			vattr.va_type = VBAD;
1227 			break;
1228 		case S_IFCHR:
1229 			vattr.va_type = VCHR;
1230 			break;
1231 		case S_IFBLK:
1232 			vattr.va_type = VBLK;
1233 			break;
1234 		case S_IFWHT:
1235 			whiteout = 1;
1236 			break;
1237 		default:
1238 			error = EINVAL;
1239 			break;
1240 		}
1241 	}
1242 	if (!error) {
1243 		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1244 		if (whiteout) {
1245 			error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1246 			if (error)
1247 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1248 			vput(nd.ni_dvp);
1249 		} else {
1250 			error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1251 						&nd.ni_cnd, &vattr);
1252 		}
1253 	} else {
1254 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1255 		if (nd.ni_dvp == vp)
1256 			vrele(nd.ni_dvp);
1257 		else
1258 			vput(nd.ni_dvp);
1259 		if (vp)
1260 			vrele(vp);
1261 	}
1262 	return (error);
1263 }
1264 
1265 /*
1266  * Create a named pipe.
1267  */
1268 /* ARGSUSED */
1269 int
1270 sys_mkfifo(p, v, retval)
1271 	struct proc *p;
1272 	void *v;
1273 	register_t *retval;
1274 {
1275 #ifndef FIFO
1276 	return (EOPNOTSUPP);
1277 #else
1278 	register struct sys_mkfifo_args /* {
1279 		syscallarg(char *) path;
1280 		syscallarg(int) mode;
1281 	} */ *uap = v;
1282 	struct vattr vattr;
1283 	int error;
1284 	struct nameidata nd;
1285 
1286 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1287 	if ((error = namei(&nd)) != 0)
1288 		return (error);
1289 	if (nd.ni_vp != NULL) {
1290 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1291 		if (nd.ni_dvp == nd.ni_vp)
1292 			vrele(nd.ni_dvp);
1293 		else
1294 			vput(nd.ni_dvp);
1295 		vrele(nd.ni_vp);
1296 		return (EEXIST);
1297 	}
1298 	VATTR_NULL(&vattr);
1299 	vattr.va_type = VFIFO;
1300 	vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1301 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1302 	return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
1303 #endif /* FIFO */
1304 }
1305 
1306 /*
1307  * Make a hard file link.
1308  */
1309 /* ARGSUSED */
1310 int
1311 sys_link(p, v, retval)
1312 	struct proc *p;
1313 	void *v;
1314 	register_t *retval;
1315 {
1316 	register struct sys_link_args /* {
1317 		syscallarg(char *) path;
1318 		syscallarg(char *) link;
1319 	} */ *uap = v;
1320 	register struct vnode *vp;
1321 	struct nameidata nd;
1322 	int error;
1323 	int flags;
1324 
1325 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1326 	if ((error = namei(&nd)) != 0)
1327 		return (error);
1328 	vp = nd.ni_vp;
1329 
1330 	flags = LOCKPARENT;
1331 	if (vp->v_type == VDIR) {
1332 		flags |= STRIPSLASHES;
1333 	}
1334 
1335 	NDINIT(&nd, CREATE, flags, UIO_USERSPACE, SCARG(uap, link), p);
1336 	if ((error = namei(&nd)) != 0)
1337 		goto out;
1338 	if (nd.ni_vp) {
1339 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1340 		if (nd.ni_dvp == nd.ni_vp)
1341 			vrele(nd.ni_dvp);
1342 		else
1343 			vput(nd.ni_dvp);
1344 		vrele(nd.ni_vp);
1345 		error = EEXIST;
1346 		goto out;
1347 	}
1348 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1349 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1350 	error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1351 out:
1352 	vrele(vp);
1353 	return (error);
1354 }
1355 
1356 /*
1357  * Make a symbolic link.
1358  */
1359 /* ARGSUSED */
1360 int
1361 sys_symlink(p, v, retval)
1362 	struct proc *p;
1363 	void *v;
1364 	register_t *retval;
1365 {
1366 	register struct sys_symlink_args /* {
1367 		syscallarg(char *) path;
1368 		syscallarg(char *) link;
1369 	} */ *uap = v;
1370 	struct vattr vattr;
1371 	char *path;
1372 	int error;
1373 	struct nameidata nd;
1374 
1375 	MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
1376 	error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL);
1377 	if (error)
1378 		goto out;
1379 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
1380 	if ((error = namei(&nd)) != 0)
1381 		goto out;
1382 	if (nd.ni_vp) {
1383 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1384 		if (nd.ni_dvp == nd.ni_vp)
1385 			vrele(nd.ni_dvp);
1386 		else
1387 			vput(nd.ni_dvp);
1388 		vrele(nd.ni_vp);
1389 		error = EEXIST;
1390 		goto out;
1391 	}
1392 	VATTR_NULL(&vattr);
1393 	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
1394 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1395 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1396 out:
1397 	FREE(path, M_NAMEI);
1398 	return (error);
1399 }
1400 
1401 /*
1402  * Delete a whiteout from the filesystem.
1403  */
1404 /* ARGSUSED */
1405 int
1406 sys_undelete(p, v, retval)
1407 	struct proc *p;
1408 	void *v;
1409 	register_t *retval;
1410 {
1411 	register struct sys_undelete_args /* {
1412 		syscallarg(char *) path;
1413 	} */ *uap = v;
1414 	int error;
1415 	struct nameidata nd;
1416 
1417 	NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1418 	    SCARG(uap, path), p);
1419 	error = namei(&nd);
1420 	if (error)
1421 		return (error);
1422 
1423 	if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1424 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1425 		if (nd.ni_dvp == nd.ni_vp)
1426 			vrele(nd.ni_dvp);
1427 		else
1428 			vput(nd.ni_dvp);
1429 		if (nd.ni_vp)
1430 			vrele(nd.ni_vp);
1431 		return (EEXIST);
1432 	}
1433 
1434 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1435 	if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0)
1436 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1437 	vput(nd.ni_dvp);
1438 	return (error);
1439 }
1440 
1441 /*
1442  * Delete a name from the filesystem.
1443  */
1444 /* ARGSUSED */
1445 int
1446 sys_unlink(p, v, retval)
1447 	struct proc *p;
1448 	void *v;
1449 	register_t *retval;
1450 {
1451 	struct sys_unlink_args /* {
1452 		syscallarg(char *) path;
1453 	} */ *uap = v;
1454 	register struct vnode *vp;
1455 	int error;
1456 	struct nameidata nd;
1457 
1458 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
1459 	    SCARG(uap, path), p);
1460 	if ((error = namei(&nd)) != 0)
1461 		return (error);
1462 	vp = nd.ni_vp;
1463 
1464 	/*
1465 	 * The root of a mounted filesystem cannot be deleted.
1466 	 */
1467 	if (vp->v_flag & VROOT) {
1468 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1469 		if (nd.ni_dvp == vp)
1470 			vrele(nd.ni_dvp);
1471 		else
1472 			vput(nd.ni_dvp);
1473 		vput(vp);
1474 		error = EBUSY;
1475 		goto out;
1476 	}
1477 
1478 	(void)uvm_vnp_uncache(vp);
1479 
1480 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1481 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1482 	error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1483 out:
1484 	return (error);
1485 }
1486 
1487 /*
1488  * Reposition read/write file offset.
1489  */
1490 int
1491 sys_lseek(p, v, retval)
1492 	struct proc *p;
1493 	void *v;
1494 	register_t *retval;
1495 {
1496 	register struct sys_lseek_args /* {
1497 		syscallarg(int) fd;
1498 		syscallarg(int) pad;
1499 		syscallarg(off_t) offset;
1500 		syscallarg(int) whence;
1501 	} */ *uap = v;
1502 	struct ucred *cred = p->p_ucred;
1503 	register struct filedesc *fdp = p->p_fd;
1504 	register struct file *fp;
1505 	struct vattr vattr;
1506 	struct vnode *vp;
1507 	int error, special;
1508 
1509 	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1510 	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1511 		return (EBADF);
1512 	if (fp->f_type != DTYPE_VNODE)
1513 		return (ESPIPE);
1514 	vp = (struct vnode *)fp->f_data;
1515 	if (vp->v_type == VFIFO)
1516 		return (ESPIPE);
1517 	if (vp->v_type == VCHR)
1518 		special = 1;
1519 	else
1520 		special = 0;
1521 	switch (SCARG(uap, whence)) {
1522 	case SEEK_CUR:
1523 		if (!special && fp->f_offset + SCARG(uap, offset) < 0)
1524 			return (EINVAL);
1525 		fp->f_offset += SCARG(uap, offset);
1526 		break;
1527 	case SEEK_END:
1528 		error = VOP_GETATTR((struct vnode *)fp->f_data, &vattr,
1529 				    cred, p);
1530 		if (error)
1531 			return (error);
1532 		if (!special && (off_t)vattr.va_size + SCARG(uap, offset) < 0)
1533 			return (EINVAL);
1534 		fp->f_offset = SCARG(uap, offset) + vattr.va_size;
1535 		break;
1536 	case SEEK_SET:
1537 		if (!special && SCARG(uap, offset) < 0)
1538 			return (EINVAL);
1539 		fp->f_offset = SCARG(uap, offset);
1540 		break;
1541 	default:
1542 		return (EINVAL);
1543 	}
1544 	*(off_t *)retval = fp->f_offset;
1545 	return (0);
1546 }
1547 
1548 /*
1549  * Check access permissions.
1550  */
1551 int
1552 sys_access(p, v, retval)
1553 	struct proc *p;
1554 	void *v;
1555 	register_t *retval;
1556 {
1557 	register struct sys_access_args /* {
1558 		syscallarg(char *) path;
1559 		syscallarg(int) flags;
1560 	} */ *uap = v;
1561 	register struct ucred *cred = p->p_ucred;
1562 	register struct vnode *vp;
1563 	int error, flags, t_gid, t_uid;
1564 	struct nameidata nd;
1565 
1566 	if (SCARG(uap, flags) & ~(R_OK | W_OK | X_OK))
1567 		return (EINVAL);
1568 	t_uid = cred->cr_uid;
1569 	t_gid = cred->cr_gid;
1570 	cred->cr_uid = p->p_cred->p_ruid;
1571 	cred->cr_gid = p->p_cred->p_rgid;
1572 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1573 	    SCARG(uap, path), p);
1574 	if ((error = namei(&nd)) != 0)
1575 		goto out1;
1576 	vp = nd.ni_vp;
1577 
1578 	/* Flags == 0 means only check for existence. */
1579 	if (SCARG(uap, flags)) {
1580 		flags = 0;
1581 		if (SCARG(uap, flags) & R_OK)
1582 			flags |= VREAD;
1583 		if (SCARG(uap, flags) & W_OK)
1584 			flags |= VWRITE;
1585 		if (SCARG(uap, flags) & X_OK)
1586 			flags |= VEXEC;
1587 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1588 			error = VOP_ACCESS(vp, flags, cred, p);
1589 	}
1590 	vput(vp);
1591 out1:
1592 	cred->cr_uid = t_uid;
1593 	cred->cr_gid = t_gid;
1594 	return (error);
1595 }
1596 
1597 /*
1598  * Get file status; this version follows links.
1599  */
1600 /* ARGSUSED */
1601 int
1602 sys_stat(p, v, retval)
1603 	struct proc *p;
1604 	void *v;
1605 	register_t *retval;
1606 {
1607 	register struct sys_stat_args /* {
1608 		syscallarg(char *) path;
1609 		syscallarg(struct stat *) ub;
1610 	} */ *uap = v;
1611 	struct stat sb;
1612 	int error;
1613 	struct nameidata nd;
1614 
1615 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1616 	    SCARG(uap, path), p);
1617 	if ((error = namei(&nd)) != 0)
1618 		return (error);
1619 	error = vn_stat(nd.ni_vp, &sb, p);
1620 	vput(nd.ni_vp);
1621 	if (error)
1622 		return (error);
1623 	/* Don't let non-root see generation numbers (for NFS security) */
1624 	if (suser(p->p_ucred, &p->p_acflag))
1625 		sb.st_gen = 0;
1626 	error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1627 	return (error);
1628 }
1629 
1630 /*
1631  * Get file status; this version does not follow links.
1632  */
1633 /* ARGSUSED */
1634 int
1635 sys_lstat(p, v, retval)
1636 	struct proc *p;
1637 	void *v;
1638 	register_t *retval;
1639 {
1640 	register struct sys_lstat_args /* {
1641 		syscallarg(char *) path;
1642 		syscallarg(struct stat *) ub;
1643 	} */ *uap = v;
1644 	struct stat sb;
1645 	int error;
1646 	struct nameidata nd;
1647 
1648 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1649 	    SCARG(uap, path), p);
1650 	if ((error = namei(&nd)) != 0)
1651 		return (error);
1652 	error = vn_stat(nd.ni_vp, &sb, p);
1653 	vput(nd.ni_vp);
1654 	if (error)
1655 		return (error);
1656 	/* Don't let non-root see generation numbers (for NFS security) */
1657 	if (suser(p->p_ucred, &p->p_acflag))
1658 		sb.st_gen = 0;
1659 	error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1660 	return (error);
1661 }
1662 
1663 /*
1664  * Get configurable pathname variables.
1665  */
1666 /* ARGSUSED */
1667 int
1668 sys_pathconf(p, v, retval)
1669 	struct proc *p;
1670 	void *v;
1671 	register_t *retval;
1672 {
1673 	register struct sys_pathconf_args /* {
1674 		syscallarg(char *) path;
1675 		syscallarg(int) name;
1676 	} */ *uap = v;
1677 	int error;
1678 	struct nameidata nd;
1679 
1680 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1681 	    SCARG(uap, path), p);
1682 	if ((error = namei(&nd)) != 0)
1683 		return (error);
1684 	error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
1685 	vput(nd.ni_vp);
1686 	return (error);
1687 }
1688 
1689 /*
1690  * Return target name of a symbolic link.
1691  */
1692 /* ARGSUSED */
1693 int
1694 sys_readlink(p, v, retval)
1695 	struct proc *p;
1696 	void *v;
1697 	register_t *retval;
1698 {
1699 	register struct sys_readlink_args /* {
1700 		syscallarg(char *) path;
1701 		syscallarg(char *) buf;
1702 		syscallarg(size_t) count;
1703 	} */ *uap = v;
1704 	register struct vnode *vp;
1705 	struct iovec aiov;
1706 	struct uio auio;
1707 	int error;
1708 	struct nameidata nd;
1709 
1710 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1711 	    SCARG(uap, path), p);
1712 	if ((error = namei(&nd)) != 0)
1713 		return (error);
1714 	vp = nd.ni_vp;
1715 	if (vp->v_type != VLNK)
1716 		error = EINVAL;
1717 	else {
1718 		aiov.iov_base = SCARG(uap, buf);
1719 		aiov.iov_len = SCARG(uap, count);
1720 		auio.uio_iov = &aiov;
1721 		auio.uio_iovcnt = 1;
1722 		auio.uio_offset = 0;
1723 		auio.uio_rw = UIO_READ;
1724 		auio.uio_segflg = UIO_USERSPACE;
1725 		auio.uio_procp = p;
1726 		auio.uio_resid = SCARG(uap, count);
1727 		error = VOP_READLINK(vp, &auio, p->p_ucred);
1728 	}
1729 	vput(vp);
1730 	*retval = SCARG(uap, count) - auio.uio_resid;
1731 	return (error);
1732 }
1733 
1734 /*
1735  * Change flags of a file given a path name.
1736  */
1737 /* ARGSUSED */
1738 int
1739 sys_chflags(p, v, retval)
1740 	struct proc *p;
1741 	void *v;
1742 	register_t *retval;
1743 {
1744 	register struct sys_chflags_args /* {
1745 		syscallarg(char *) path;
1746 		syscallarg(unsigned int) flags;
1747 	} */ *uap = v;
1748 	register struct vnode *vp;
1749 	struct vattr vattr;
1750 	int error;
1751 	struct nameidata nd;
1752 
1753 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1754 	if ((error = namei(&nd)) != 0)
1755 		return (error);
1756 	vp = nd.ni_vp;
1757 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1758 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1759 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1760 		error = EROFS;
1761 	else if (SCARG(uap, flags) == VNOVAL)
1762 		error = EINVAL;
1763 	else {
1764 		if (suser(p->p_ucred, &p->p_acflag)) {
1765 			if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
1766 				goto out;
1767 			if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
1768 				error = EINVAL;
1769 				goto out;
1770 			}
1771 		}
1772 		VATTR_NULL(&vattr);
1773 		vattr.va_flags = SCARG(uap, flags);
1774 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1775 	}
1776 out:
1777 	vput(vp);
1778 	return (error);
1779 }
1780 
1781 /*
1782  * Change flags of a file given a file descriptor.
1783  */
1784 /* ARGSUSED */
1785 int
1786 sys_fchflags(p, v, retval)
1787 	struct proc *p;
1788 	void *v;
1789 	register_t *retval;
1790 {
1791 	register struct sys_fchflags_args /* {
1792 		syscallarg(int) fd;
1793 		syscallarg(unsigned int) flags;
1794 	} */ *uap = v;
1795 	struct vattr vattr;
1796 	struct vnode *vp;
1797 	struct file *fp;
1798 	int error;
1799 
1800 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1801 		return (error);
1802 	vp = (struct vnode *)fp->f_data;
1803 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1804 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1805 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1806 		error = EROFS;
1807 	else if (SCARG(uap, flags) == VNOVAL)
1808 		error = EINVAL;
1809 	else {
1810 		if (suser(p->p_ucred, &p->p_acflag)) {
1811 			if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
1812 			    != 0)
1813 				goto out;
1814 			if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
1815 				error = EINVAL;
1816 				goto out;
1817 			}
1818 		}
1819 		VATTR_NULL(&vattr);
1820 		vattr.va_flags = SCARG(uap, flags);
1821 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1822 	}
1823 out:
1824 	VOP_UNLOCK(vp, 0, p);
1825 	return (error);
1826 }
1827 
1828 /*
1829  * Change mode of a file given path name.
1830  */
1831 /* ARGSUSED */
1832 int
1833 sys_chmod(p, v, retval)
1834 	struct proc *p;
1835 	void *v;
1836 	register_t *retval;
1837 {
1838 	register struct sys_chmod_args /* {
1839 		syscallarg(char *) path;
1840 		syscallarg(int) mode;
1841 	} */ *uap = v;
1842 	register struct vnode *vp;
1843 	struct vattr vattr;
1844 	int error;
1845 	struct nameidata nd;
1846 
1847 	if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
1848 		return (EINVAL);
1849 
1850 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1851 	if ((error = namei(&nd)) != 0)
1852 		return (error);
1853 	vp = nd.ni_vp;
1854 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1855 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1856 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1857 		error = EROFS;
1858 	else {
1859 		VATTR_NULL(&vattr);
1860 		vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1861 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1862 	}
1863 	vput(vp);
1864 	return (error);
1865 }
1866 
1867 /*
1868  * Change mode of a file given a file descriptor.
1869  */
1870 /* ARGSUSED */
1871 int
1872 sys_fchmod(p, v, retval)
1873 	struct proc *p;
1874 	void *v;
1875 	register_t *retval;
1876 {
1877 	register struct sys_fchmod_args /* {
1878 		syscallarg(int) fd;
1879 		syscallarg(int) mode;
1880 	} */ *uap = v;
1881 	struct vattr vattr;
1882 	struct vnode *vp;
1883 	struct file *fp;
1884 	int error;
1885 
1886 	if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
1887 		return (EINVAL);
1888 
1889 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1890 		return (error);
1891 	vp = (struct vnode *)fp->f_data;
1892 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1893 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1894 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1895 		error = EROFS;
1896 	else {
1897 		VATTR_NULL(&vattr);
1898 		vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1899 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1900 	}
1901 	VOP_UNLOCK(vp, 0, p);
1902 	return (error);
1903 }
1904 
1905 /*
1906  * Set ownership given a path name.
1907  */
1908 /* ARGSUSED */
1909 int
1910 sys_chown(p, v, retval)
1911 	struct proc *p;
1912 	void *v;
1913 	register_t *retval;
1914 {
1915 	register struct sys_chown_args /* {
1916 		syscallarg(char *) path;
1917 		syscallarg(int) uid;
1918 		syscallarg(int) gid;
1919 	} */ *uap = v;
1920 	register struct vnode *vp;
1921 	struct vattr vattr;
1922 	int error;
1923 	struct nameidata nd;
1924 	u_short mode;
1925 
1926 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1927 	if ((error = namei(&nd)) != 0)
1928 		return (error);
1929 	vp = nd.ni_vp;
1930 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1931 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1932 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1933 		error = EROFS;
1934 	else {
1935 		if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
1936 		    (suser(p->p_ucred, &p->p_acflag) || suid_clear)) {
1937 			error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
1938 			if (error)
1939 				goto out;
1940 			mode = vattr.va_mode & ~(VSUID | VSGID);
1941 			if (mode == vattr.va_mode)
1942 				mode = VNOVAL;
1943 		}
1944 		else
1945 			mode = VNOVAL;
1946 		VATTR_NULL(&vattr);
1947 		vattr.va_uid = SCARG(uap, uid);
1948 		vattr.va_gid = SCARG(uap, gid);
1949 		vattr.va_mode = mode;
1950 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1951 	}
1952 out:
1953 	vput(vp);
1954 	return (error);
1955 }
1956 
1957 /*
1958  * Set ownership given a path name, without following links.
1959  */
1960 /* ARGSUSED */
1961 int
1962 sys_lchown(p, v, retval)
1963 	struct proc *p;
1964 	void *v;
1965 	register_t *retval;
1966 {
1967 	register struct sys_lchown_args /* {
1968 		syscallarg(char *) path;
1969 		syscallarg(int) uid;
1970 		syscallarg(int) gid;
1971 	} */ *uap = v;
1972 	register struct vnode *vp;
1973 	struct vattr vattr;
1974 	int error;
1975 	struct nameidata nd;
1976 	u_short mode;
1977 
1978 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1979 	if ((error = namei(&nd)) != 0)
1980 		return (error);
1981 	vp = nd.ni_vp;
1982 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1983 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1984 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1985 		error = EROFS;
1986 	else {
1987 		if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
1988 		    (suser(p->p_ucred, &p->p_acflag) || suid_clear)) {
1989 			error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
1990 			if (error)
1991 				goto out;
1992 			mode = vattr.va_mode & ~(VSUID | VSGID);
1993 			if (mode == vattr.va_mode)
1994 				mode = VNOVAL;
1995 		}
1996 		else
1997 			mode = VNOVAL;
1998 		VATTR_NULL(&vattr);
1999 		vattr.va_uid = SCARG(uap, uid);
2000 		vattr.va_gid = SCARG(uap, gid);
2001 		vattr.va_mode = mode;
2002 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2003 	}
2004 out:
2005 	vput(vp);
2006 	return (error);
2007 }
2008 
2009 /*
2010  * Set ownership given a file descriptor.
2011  */
2012 /* ARGSUSED */
2013 int
2014 sys_fchown(p, v, retval)
2015 	struct proc *p;
2016 	void *v;
2017 	register_t *retval;
2018 {
2019 	register struct sys_fchown_args /* {
2020 		syscallarg(int) fd;
2021 		syscallarg(int) uid;
2022 		syscallarg(int) gid;
2023 	} */ *uap = v;
2024 	register struct vnode *vp;
2025 	struct vattr vattr;
2026 	int error;
2027 	struct file *fp;
2028 	u_short mode;
2029 
2030 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2031 		return (error);
2032 	vp = (struct vnode *)fp->f_data;
2033 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2034 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2035 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
2036 		error = EROFS;
2037 	else {
2038 		if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
2039 		    (suser(p->p_ucred, &p->p_acflag) || suid_clear)) {
2040 			error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
2041 			if (error)
2042 				goto out;
2043 			mode = vattr.va_mode & ~(VSUID | VSGID);
2044 			if (mode == vattr.va_mode)
2045 				mode = VNOVAL;
2046 		} else
2047 			mode = VNOVAL;
2048 		VATTR_NULL(&vattr);
2049 		vattr.va_uid = SCARG(uap, uid);
2050 		vattr.va_gid = SCARG(uap, gid);
2051 		vattr.va_mode = mode;
2052 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2053 	}
2054 out:
2055 	VOP_UNLOCK(vp, 0, p);
2056 	return (error);
2057 }
2058 
2059 /*
2060  * Set the access and modification times given a path name.
2061  */
2062 /* ARGSUSED */
2063 int
2064 sys_utimes(p, v, retval)
2065 	struct proc *p;
2066 	void *v;
2067 	register_t *retval;
2068 {
2069 	register struct sys_utimes_args /* {
2070 		syscallarg(char *) path;
2071 		syscallarg(struct timeval *) tptr;
2072 	} */ *uap = v;
2073 	register struct vnode *vp;
2074 	struct timeval tv[2];
2075 	struct vattr vattr;
2076 	int error;
2077 	struct nameidata nd;
2078 
2079 	VATTR_NULL(&vattr);
2080 	if (SCARG(uap, tptr) == NULL) {
2081 		microtime(&tv[0]);
2082 		tv[1] = tv[0];
2083 		vattr.va_vaflags |= VA_UTIMES_NULL;
2084 	} else {
2085 		error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
2086 		    sizeof (tv));
2087 		if (error)
2088 			return (error);
2089 		/* XXX workaround timeval matching the VFS constant VNOVAL */
2090 		if (tv[0].tv_sec == VNOVAL)
2091 			tv[0].tv_sec = VNOVAL - 1;
2092 		if (tv[1].tv_sec == VNOVAL)
2093 			tv[1].tv_sec = VNOVAL - 1;
2094 	}
2095 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2096 	if ((error = namei(&nd)) != 0)
2097 		return (error);
2098 	vp = nd.ni_vp;
2099 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2100 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2101 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
2102 		error = EROFS;
2103 	else {
2104 		vattr.va_atime.tv_sec = tv[0].tv_sec;
2105 		vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
2106 		vattr.va_mtime.tv_sec = tv[1].tv_sec;
2107 		vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
2108 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2109 	}
2110 	vput(vp);
2111 	return (error);
2112 }
2113 
2114 
2115 /*
2116  * Set the access and modification times given a file descriptor.
2117  */
2118 /* ARGSUSED */
2119 int
2120 sys_futimes(p, v, retval)
2121 	struct proc *p;
2122 	void *v;
2123 	register_t *retval;
2124 {
2125 	register struct sys_futimes_args /* {
2126 		syscallarg(int) fd;
2127 		syscallarg(struct timeval *) tptr;
2128 	} */ *uap = v;
2129 	register struct vnode *vp;
2130 	struct timeval tv[2];
2131 	struct vattr vattr;
2132 	int error;
2133 	struct file *fp;
2134 
2135 	VATTR_NULL(&vattr);
2136 	if (SCARG(uap, tptr) == NULL) {
2137 		microtime(&tv[0]);
2138 		tv[1] = tv[0];
2139 		vattr.va_vaflags |= VA_UTIMES_NULL;
2140 	} else {
2141 		error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
2142 		    sizeof (tv));
2143 		if (error)
2144 			return (error);
2145 		/* XXX workaround timeval matching the VFS constant VNOVAL */
2146 		if (tv[0].tv_sec == VNOVAL)
2147 			tv[0].tv_sec = VNOVAL - 1;
2148 		if (tv[1].tv_sec == VNOVAL)
2149 			tv[1].tv_sec = VNOVAL - 1;
2150 	}
2151 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2152 		return (error);
2153 	vp = (struct vnode *)fp->f_data;
2154 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2155 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2156 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
2157 		error = EROFS;
2158 	else {
2159 		vattr.va_atime.tv_sec = tv[0].tv_sec;
2160 		vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
2161 		vattr.va_mtime.tv_sec = tv[1].tv_sec;
2162 		vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
2163 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2164 	}
2165 	VOP_UNLOCK(vp, 0, p);
2166 	return (error);
2167 }
2168 
2169 /*
2170  * Truncate a file given its path name.
2171  */
2172 /* ARGSUSED */
2173 int
2174 sys_truncate(p, v, retval)
2175 	struct proc *p;
2176 	void *v;
2177 	register_t *retval;
2178 {
2179 	register struct sys_truncate_args /* {
2180 		syscallarg(char *) path;
2181 		syscallarg(int) pad;
2182 		syscallarg(off_t) length;
2183 	} */ *uap = v;
2184 	register struct vnode *vp;
2185 	struct vattr vattr;
2186 	int error;
2187 	struct nameidata nd;
2188 
2189 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2190 	if ((error = namei(&nd)) != 0)
2191 		return (error);
2192 	vp = nd.ni_vp;
2193 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2194 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2195 	if (vp->v_type == VDIR)
2196 		error = EISDIR;
2197 	else if ((error = vn_writechk(vp)) == 0 &&
2198 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
2199 		VATTR_NULL(&vattr);
2200 		vattr.va_size = SCARG(uap, length);
2201 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2202 	}
2203 	vput(vp);
2204 	return (error);
2205 }
2206 
2207 /*
2208  * Truncate a file given a file descriptor.
2209  */
2210 /* ARGSUSED */
2211 int
2212 sys_ftruncate(p, v, retval)
2213 	struct proc *p;
2214 	void *v;
2215 	register_t *retval;
2216 {
2217 	register struct sys_ftruncate_args /* {
2218 		syscallarg(int) fd;
2219 		syscallarg(int) pad;
2220 		syscallarg(off_t) length;
2221 	} */ *uap = v;
2222 	struct vattr vattr;
2223 	struct vnode *vp;
2224 	struct file *fp;
2225 	int error;
2226 
2227 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2228 		return (error);
2229 	if ((fp->f_flag & FWRITE) == 0)
2230 		return (EINVAL);
2231 	vp = (struct vnode *)fp->f_data;
2232 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2233 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2234 	if (vp->v_type == VDIR)
2235 		error = EISDIR;
2236 	else if ((error = vn_writechk(vp)) == 0) {
2237 		VATTR_NULL(&vattr);
2238 		vattr.va_size = SCARG(uap, length);
2239 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
2240 	}
2241 	VOP_UNLOCK(vp, 0, p);
2242 	return (error);
2243 }
2244 
2245 /*
2246  * Sync an open file.
2247  */
2248 /* ARGSUSED */
2249 int
2250 sys_fsync(p, v, retval)
2251 	struct proc *p;
2252 	void *v;
2253 	register_t *retval;
2254 {
2255 	struct sys_fsync_args /* {
2256 		syscallarg(int) fd;
2257 	} */ *uap = v;
2258 	register struct vnode *vp;
2259 	struct file *fp;
2260 	int error;
2261 
2262 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2263 		return (error);
2264 	vp = (struct vnode *)fp->f_data;
2265 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2266 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
2267 #ifdef FFS_SOFTUPDATES
2268 	if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
2269 		error = softdep_fsync(vp);
2270 #endif
2271 
2272 	VOP_UNLOCK(vp, 0, p);
2273 	return (error);
2274 }
2275 
2276 /*
2277  * Rename files.  Source and destination must either both be directories,
2278  * or both not be directories.  If target is a directory, it must be empty.
2279  */
2280 /* ARGSUSED */
2281 int
2282 sys_rename(p, v, retval)
2283 	struct proc *p;
2284 	void *v;
2285 	register_t *retval;
2286 {
2287 	register struct sys_rename_args /* {
2288 		syscallarg(char *) from;
2289 		syscallarg(char *) to;
2290 	} */ *uap = v;
2291 	register struct vnode *tvp, *fvp, *tdvp;
2292 	struct nameidata fromnd, tond;
2293 	int error;
2294 	int flags;
2295 
2296 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2297 	    SCARG(uap, from), p);
2298 	if ((error = namei(&fromnd)) != 0)
2299 		return (error);
2300 	fvp = fromnd.ni_vp;
2301 
2302 	flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
2303 	/*
2304 	 * rename("foo/", "bar/");  is  OK
2305 	 */
2306 	if (fvp->v_type == VDIR)
2307 		flags |= STRIPSLASHES;
2308 
2309 	NDINIT(&tond, RENAME, flags,
2310 	    UIO_USERSPACE, SCARG(uap, to), p);
2311 	if ((error = namei(&tond)) != 0) {
2312 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2313 		vrele(fromnd.ni_dvp);
2314 		vrele(fvp);
2315 		goto out1;
2316 	}
2317 	tdvp = tond.ni_dvp;
2318 	tvp = tond.ni_vp;
2319 	if (tvp != NULL) {
2320 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2321 			error = ENOTDIR;
2322 			goto out;
2323 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2324 			error = EISDIR;
2325 			goto out;
2326 		}
2327 	}
2328 	if (fvp == tdvp)
2329 		error = EINVAL;
2330 	/*
2331 	 * If source is the same as the destination (that is the
2332 	 * same inode number)
2333 	 */
2334 	if (fvp == tvp)
2335 		error = -1;
2336 out:
2337 	if (!error) {
2338 		VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
2339 		if (fromnd.ni_dvp != tdvp)
2340 			VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2341 		if (tvp) {
2342 			(void)uvm_vnp_uncache(tvp);
2343 			VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
2344 		}
2345 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2346 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2347 	} else {
2348 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
2349 		if (tdvp == tvp)
2350 			vrele(tdvp);
2351 		else
2352 			vput(tdvp);
2353 		if (tvp)
2354 			vput(tvp);
2355 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2356 		vrele(fromnd.ni_dvp);
2357 		vrele(fvp);
2358 	}
2359 	vrele(tond.ni_startdir);
2360 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
2361 out1:
2362 	if (fromnd.ni_startdir)
2363 		vrele(fromnd.ni_startdir);
2364 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
2365 	if (error == -1)
2366 		return (0);
2367 	return (error);
2368 }
2369 
2370 /*
2371  * Make a directory file.
2372  */
2373 /* ARGSUSED */
2374 int
2375 sys_mkdir(p, v, retval)
2376 	struct proc *p;
2377 	void *v;
2378 	register_t *retval;
2379 {
2380 	register struct sys_mkdir_args /* {
2381 		syscallarg(char *) path;
2382 		syscallarg(int) mode;
2383 	} */ *uap = v;
2384 	register struct vnode *vp;
2385 	struct vattr vattr;
2386 	int error;
2387 	struct nameidata nd;
2388 
2389 	NDINIT(&nd, CREATE, LOCKPARENT | STRIPSLASHES,
2390 	    UIO_USERSPACE, SCARG(uap, path), p);
2391 	if ((error = namei(&nd)) != 0)
2392 		return (error);
2393 	vp = nd.ni_vp;
2394 	if (vp != NULL) {
2395 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2396 		if (nd.ni_dvp == vp)
2397 			vrele(nd.ni_dvp);
2398 		else
2399 			vput(nd.ni_dvp);
2400 		vrele(vp);
2401 		return (EEXIST);
2402 	}
2403 	VATTR_NULL(&vattr);
2404 	vattr.va_type = VDIR;
2405 	vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2406 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2407 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2408 	if (!error)
2409 		vput(nd.ni_vp);
2410 	return (error);
2411 }
2412 
2413 /*
2414  * Remove a directory file.
2415  */
2416 /* ARGSUSED */
2417 int
2418 sys_rmdir(p, v, retval)
2419 	struct proc *p;
2420 	void *v;
2421 	register_t *retval;
2422 {
2423 	struct sys_rmdir_args /* {
2424 		syscallarg(char *) path;
2425 	} */ *uap = v;
2426 	register struct vnode *vp;
2427 	int error;
2428 	struct nameidata nd;
2429 
2430 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2431 	    SCARG(uap, path), p);
2432 	if ((error = namei(&nd)) != 0)
2433 		return (error);
2434 	vp = nd.ni_vp;
2435 	if (vp->v_type != VDIR) {
2436 		error = ENOTDIR;
2437 		goto out;
2438 	}
2439 	/*
2440 	 * No rmdir "." please.
2441 	 */
2442 	if (nd.ni_dvp == vp) {
2443 		error = EBUSY;
2444 		goto out;
2445 	}
2446 	/*
2447 	 * The root of a mounted filesystem cannot be deleted.
2448 	 */
2449 	if (vp->v_flag & VROOT)
2450 		error = EBUSY;
2451 out:
2452 	if (!error) {
2453 		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2454 		VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2455 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2456 	} else {
2457 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2458 		if (nd.ni_dvp == vp)
2459 			vrele(nd.ni_dvp);
2460 		else
2461 			vput(nd.ni_dvp);
2462 		vput(vp);
2463 	}
2464 	return (error);
2465 }
2466 
2467 /*
2468  * Read a block of directory entries in a file system independent format.
2469  */
2470 int
2471 sys_getdirentries(p, v, retval)
2472 	struct proc *p;
2473 	void *v;
2474 	register_t *retval;
2475 {
2476 	register struct sys_getdirentries_args /* {
2477 		syscallarg(int) fd;
2478 		syscallarg(char *) buf;
2479 		syscallarg(u_int) count;
2480 		syscallarg(long *) basep;
2481 	} */ *uap = v;
2482 	struct vnode *vp;
2483 	struct file *fp;
2484 	struct uio auio;
2485 	struct iovec aiov;
2486 	long loff;
2487 	int error, eofflag;
2488 
2489 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2490 		return (error);
2491 	if ((fp->f_flag & FREAD) == 0)
2492 		return (EBADF);
2493 	vp = (struct vnode *)fp->f_data;
2494 unionread:
2495 	if (vp->v_type != VDIR)
2496 		return (EINVAL);
2497 	aiov.iov_base = SCARG(uap, buf);
2498 	aiov.iov_len = SCARG(uap, count);
2499 	auio.uio_iov = &aiov;
2500 	auio.uio_iovcnt = 1;
2501 	auio.uio_rw = UIO_READ;
2502 	auio.uio_segflg = UIO_USERSPACE;
2503 	auio.uio_procp = p;
2504 	auio.uio_resid = SCARG(uap, count);
2505 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2506 	loff = auio.uio_offset = fp->f_offset;
2507 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 0, 0);
2508 	fp->f_offset = auio.uio_offset;
2509 	VOP_UNLOCK(vp, 0, p);
2510 	if (error)
2511 		return (error);
2512 	if ((SCARG(uap, count) == auio.uio_resid) &&
2513 	    union_check_p &&
2514 	    (union_check_p(p, &vp, fp, auio, &error) != 0))
2515 		goto unionread;
2516 	if (error)
2517 		return (error);
2518 
2519 	if ((SCARG(uap, count) == auio.uio_resid) &&
2520 	    (vp->v_flag & VROOT) &&
2521 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
2522 		struct vnode *tvp = vp;
2523 		vp = vp->v_mount->mnt_vnodecovered;
2524 		VREF(vp);
2525 		fp->f_data = (caddr_t) vp;
2526 		fp->f_offset = 0;
2527 		vrele(tvp);
2528 		goto unionread;
2529 	}
2530 	error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2531 	    sizeof(long));
2532 	*retval = SCARG(uap, count) - auio.uio_resid;
2533 	return (error);
2534 }
2535 
2536 /*
2537  * Set the mode mask for creation of filesystem nodes.
2538  */
2539 int
2540 sys_umask(p, v, retval)
2541 	struct proc *p;
2542 	void *v;
2543 	register_t *retval;
2544 {
2545 	struct sys_umask_args /* {
2546 		syscallarg(int) newmask;
2547 	} */ *uap = v;
2548 	register struct filedesc *fdp;
2549 
2550 	fdp = p->p_fd;
2551 	*retval = fdp->fd_cmask;
2552 	fdp->fd_cmask = SCARG(uap, newmask) & ACCESSPERMS;
2553 	return (0);
2554 }
2555 
2556 /*
2557  * Void all references to file by ripping underlying filesystem
2558  * away from vnode.
2559  */
2560 /* ARGSUSED */
2561 int
2562 sys_revoke(p, v, retval)
2563 	struct proc *p;
2564 	void *v;
2565 	register_t *retval;
2566 {
2567 	register struct sys_revoke_args /* {
2568 		syscallarg(char *) path;
2569 	} */ *uap = v;
2570 	register struct vnode *vp;
2571 	struct vattr vattr;
2572 	int error;
2573 	struct nameidata nd;
2574 
2575 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2576 	if ((error = namei(&nd)) != 0)
2577 		return (error);
2578 	vp = nd.ni_vp;
2579 	if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
2580 		goto out;
2581 	if (p->p_ucred->cr_uid != vattr.va_uid &&
2582 	    (error = suser(p->p_ucred, &p->p_acflag)))
2583 		goto out;
2584 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2585 		VOP_REVOKE(vp, REVOKEALL);
2586 out:
2587 	vrele(vp);
2588 	return (error);
2589 }
2590 
2591 /*
2592  * Convert a user file descriptor to a kernel file entry.
2593  */
2594 int
2595 getvnode(fdp, fd, fpp)
2596 	struct filedesc *fdp;
2597 	struct file **fpp;
2598 	int fd;
2599 {
2600 	struct file *fp;
2601 
2602 	if ((u_int)fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
2603 		return (EBADF);
2604 	if (fp->f_type != DTYPE_VNODE)
2605 		return (EINVAL);
2606 	*fpp = fp;
2607 	return (0);
2608 }
2609 
2610 /*
2611  * Positional read system call.
2612  */
2613 int
2614 sys_pread(p, v, retval)
2615 	struct proc *p;
2616 	void *v;
2617 	register_t *retval;
2618 {
2619 	struct sys_pread_args /* {
2620 		syscallarg(int) fd;
2621 		syscallarg(void *) buf;
2622 		syscallarg(size_t) nbyte;
2623 		syscallarg(int) pad;
2624 		syscallarg(off_t) offset;
2625 	} */ *uap = v;
2626 	struct filedesc *fdp = p->p_fd;
2627 	struct file *fp;
2628 	struct vnode *vp;
2629 	off_t offset;
2630 	int error, fd = SCARG(uap, fd);
2631 
2632 	if ((u_int)fd >= fdp->fd_nfiles ||
2633 	    (fp = fdp->fd_ofiles[fd]) == NULL ||
2634 #if notyet
2635 	    (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
2636 #endif
2637 	    (fp->f_flag & FREAD) == 0)
2638 		return (EBADF);
2639 
2640 #if notyet
2641 	FILE_USE(fp);
2642 #endif
2643 
2644 	vp = (struct vnode *)fp->f_data;
2645 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
2646 		error = ESPIPE;
2647 		goto out;
2648 	}
2649 
2650 	offset = SCARG(uap, offset);
2651 
2652 	/* dofileread() will unuse the descriptor for us */
2653 	return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
2654 	    &offset, retval));
2655 
2656  out:
2657 #if notyet
2658 	FILE_UNUSE(fp, p);
2659 #endif
2660 	return (error);
2661 }
2662 
2663 /*
2664  * Positional scatter read system call.
2665  */
2666 int
2667 sys_preadv(p, v, retval)
2668 	struct proc *p;
2669 	void *v;
2670 	register_t *retval;
2671 {
2672 	struct sys_preadv_args /* {
2673 		syscallarg(int) fd;
2674 		syscallarg(const struct iovec *) iovp;
2675 		syscallarg(int) iovcnt;
2676 		syscallarg(int) pad;
2677 		syscallarg(off_t) offset;
2678 	} */ *uap = v;
2679 	struct filedesc *fdp = p->p_fd;
2680 	struct file *fp;
2681 	struct vnode *vp;
2682 	off_t offset;
2683 	int error, fd = SCARG(uap, fd);
2684 
2685 	if ((u_int)fd >= fdp->fd_nfiles ||
2686 	    (fp = fdp->fd_ofiles[fd]) == NULL ||
2687 #if notyet
2688 	    (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
2689 #endif
2690 	    (fp->f_flag & FREAD) == 0)
2691 		return (EBADF);
2692 
2693 #if notyet
2694 	FILE_USE(fp);
2695 #endif
2696 
2697 	vp = (struct vnode *)fp->f_data;
2698 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
2699 		error = ESPIPE;
2700 		goto out;
2701 	}
2702 
2703 	offset = SCARG(uap, offset);
2704 
2705 	/* dofilereadv() will unuse the descriptor for us */
2706 	return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
2707 	    &offset, retval));
2708 
2709  out:
2710 #if notyet
2711 	FILE_UNUSE(fp, p);
2712 #endif
2713 	return (error);
2714 }
2715 
2716 /*
2717  * Positional write system call.
2718  */
2719 int
2720 sys_pwrite(p, v, retval)
2721 	struct proc *p;
2722 	void *v;
2723 	register_t *retval;
2724 {
2725 	struct sys_pwrite_args /* {
2726 		syscallarg(int) fd;
2727 		syscallarg(const void *) buf;
2728 		syscallarg(size_t) nbyte;
2729 		syscallarg(int) pad;
2730 		syscallarg(off_t) offset;
2731 	} */ *uap = v;
2732 	struct filedesc *fdp = p->p_fd;
2733 	struct file *fp;
2734 	struct vnode *vp;
2735 	off_t offset;
2736 	int error, fd = SCARG(uap, fd);
2737 
2738 	if ((u_int)fd >= fdp->fd_nfiles ||
2739 	    (fp = fdp->fd_ofiles[fd]) == NULL ||
2740 #if notyet
2741 	    (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
2742 #endif
2743 	    (fp->f_flag & FWRITE) == 0)
2744 		return (EBADF);
2745 
2746 #if notyet
2747 	FILE_USE(fp);
2748 #endif
2749 
2750 	vp = (struct vnode *)fp->f_data;
2751 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
2752 		error = ESPIPE;
2753 		goto out;
2754 	}
2755 
2756 	offset = SCARG(uap, offset);
2757 
2758 	/* dofilewrite() will unuse the descriptor for us */
2759 	return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
2760 	    &offset, retval));
2761 
2762  out:
2763 #if notyet
2764 	FILE_UNUSE(fp, p);
2765 #endif
2766 	return (error);
2767 }
2768 
2769 
2770 /*
2771  * Positional gather write system call.
2772  */
2773 int
2774 sys_pwritev(p, v, retval)
2775 	struct proc *p;
2776 	void *v;
2777 	register_t *retval;
2778 {
2779 	struct sys_pwritev_args /* {
2780 		syscallarg(int) fd;
2781 		syscallarg(const struct iovec *) iovp;
2782 		syscallarg(int) iovcnt;
2783 		syscallarg(int) pad;
2784 		syscallarg(off_t) offset;
2785 	} */ *uap = v;
2786 	struct filedesc *fdp = p->p_fd;
2787 	struct file *fp;
2788 	struct vnode *vp;
2789 	off_t offset;
2790 	int error, fd = SCARG(uap, fd);
2791 
2792 	if ((u_int)fd >= fdp->fd_nfiles ||
2793 	    (fp = fdp->fd_ofiles[fd]) == NULL ||
2794 #if notyet
2795 	    (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
2796 #endif
2797 	    (fp->f_flag & FWRITE) == 0)
2798 		return (EBADF);
2799 
2800 #if notyet
2801 	FILE_USE(fp);
2802 #endif
2803 	vp = (struct vnode *)fp->f_data;
2804 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
2805 		error = ESPIPE;
2806 		goto out;
2807 	}
2808 
2809 	offset = SCARG(uap, offset);
2810 
2811 	/* dofilewritev() will unuse the descriptor for us */
2812 	return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
2813 	    &offset, retval));
2814 
2815  out:
2816 #if notyet
2817 	FILE_UNUSE(fp, p);
2818 #endif
2819 	return (error);
2820 }
2821