xref: /freebsd/sys/kern/vfs_syscalls.c (revision 0c43d89a0d8e976ca494d4837f4c1f3734d2c300)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)vfs_syscalls.c	8.13 (Berkeley) 4/15/94
39  * $Id: vfs_syscalls.c,v 1.3 1994/08/02 07:43:31 davidg Exp $
40  */
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/namei.h>
45 #include <sys/filedesc.h>
46 #include <sys/kernel.h>
47 #include <sys/file.h>
48 #include <sys/stat.h>
49 #include <sys/vnode.h>
50 #include <sys/mount.h>
51 #include <sys/proc.h>
52 #include <sys/uio.h>
53 #include <sys/malloc.h>
54 #include <sys/dirent.h>
55 
56 #include <vm/vm.h>
57 #include <sys/sysctl.h>
58 
59 void	cvtstat		__P((struct stat *, struct ostat *));
60 static int change_dir	__P((struct nameidata *ndp, struct proc *p));
61 
62 /*
63  * Virtual File System System Calls
64  */
65 
66 /*
67  * Mount a file system.
68  */
69 struct mount_args {
70 	int	type;
71 	char	*path;
72 	int	flags;
73 	caddr_t	data;
74 };
75 /* ARGSUSED */
76 int
77 mount(p, uap, retval)
78 	struct proc *p;
79 	register struct mount_args *uap;
80 	int *retval;
81 {
82 	register struct vnode *vp;
83 	register struct mount *mp;
84 	int error, flag = 0;
85 	struct nameidata nd;
86 
87 	/*
88 	 * Must be super user
89 	 */
90 	if (error = suser(p->p_ucred, &p->p_acflag))
91 		return (error);
92 	/*
93 	 * Get vnode to be covered
94 	 */
95 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
96 	if (error = namei(&nd))
97 		return (error);
98 	vp = nd.ni_vp;
99 	if (uap->flags & MNT_UPDATE) {
100 		if ((vp->v_flag & VROOT) == 0) {
101 			vput(vp);
102 			return (EINVAL);
103 		}
104 		mp = vp->v_mount;
105 		flag = mp->mnt_flag;
106 		/*
107 		 * We only allow the filesystem to be reloaded if it
108 		 * is currently mounted read-only.
109 		 */
110 		if ((uap->flags & MNT_RELOAD) &&
111 		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
112 			vput(vp);
113 			return (EOPNOTSUPP);	/* Needs translation */
114 		}
115 		mp->mnt_flag |=
116 		    uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
117 		VOP_UNLOCK(vp);
118 		goto update;
119 	}
120 	if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
121 		return (error);
122 	if (vp->v_type != VDIR) {
123 		vput(vp);
124 		return (ENOTDIR);
125 	}
126 	if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) {
127 		vput(vp);
128 		return (ENODEV);
129 	}
130 
131 	/*
132 	 * Allocate and initialize the file system.
133 	 */
134 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
135 		M_MOUNT, M_WAITOK);
136 	bzero((char *)mp, (u_long)sizeof(struct mount));
137 	mp->mnt_op = vfssw[uap->type];
138 	if (error = vfs_lock(mp)) {
139 		free((caddr_t)mp, M_MOUNT);
140 		vput(vp);
141 		return (error);
142 	}
143 	if (vp->v_mountedhere != NULL) {
144 		vfs_unlock(mp);
145 		free((caddr_t)mp, M_MOUNT);
146 		vput(vp);
147 		return (EBUSY);
148 	}
149 	vp->v_mountedhere = mp;
150 	mp->mnt_vnodecovered = vp;
151 update:
152 	/*
153 	 * Set the mount level flags.
154 	 */
155 	if (uap->flags & MNT_RDONLY)
156 		mp->mnt_flag |= MNT_RDONLY;
157 	else if (mp->mnt_flag & MNT_RDONLY)
158 		mp->mnt_flag |= MNT_WANTRDWR;
159 	mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
160 	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
161 	mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
162 	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
163 	/*
164 	 * Mount the filesystem.
165 	 */
166 	error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p);
167 	if (mp->mnt_flag & MNT_UPDATE) {
168 		vrele(vp);
169 		if (mp->mnt_flag & MNT_WANTRDWR)
170 			mp->mnt_flag &= ~MNT_RDONLY;
171 		mp->mnt_flag &=~
172 		    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
173 		if (error)
174 			mp->mnt_flag = flag;
175 		return (error);
176 	}
177 	/*
178 	 * Put the new filesystem on the mount list after root.
179 	 */
180 	cache_purge(vp);
181 	if (!error) {
182 		TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
183 		VOP_UNLOCK(vp);
184 		vfs_unlock(mp);
185 		error = VFS_START(mp, 0, p);
186 	} else {
187 		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
188 		vfs_unlock(mp);
189 		free((caddr_t)mp, M_MOUNT);
190 		vput(vp);
191 	}
192 	return (error);
193 }
194 
195 /*
196  * Unmount a file system.
197  *
198  * Note: unmount takes a path to the vnode mounted on as argument,
199  * not special file (as before).
200  */
201 struct unmount_args {
202 	char	*path;
203 	int	flags;
204 };
205 /* ARGSUSED */
206 int
207 unmount(p, uap, retval)
208 	struct proc *p;
209 	register struct unmount_args *uap;
210 	int *retval;
211 {
212 	register struct vnode *vp;
213 	struct mount *mp;
214 	int error;
215 	struct nameidata nd;
216 
217 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
218 	if (error = namei(&nd))
219 		return (error);
220 	vp = nd.ni_vp;
221 
222 	/*
223 	 * Unless this is a user mount, then must
224 	 * have suser privilege.
225 	 */
226 	if (((vp->v_mount->mnt_flag & MNT_USER) == 0) &&
227 	    (error = suser(p->p_ucred, &p->p_acflag))) {
228 		vput(vp);
229 		return (error);
230 	}
231 
232 	/*
233 	 * Must be the root of the filesystem
234 	 */
235 	if ((vp->v_flag & VROOT) == 0) {
236 		vput(vp);
237 		return (EINVAL);
238 	}
239 	mp = vp->v_mount;
240 	vput(vp);
241 
242 	/*
243 	 * Don't allow unmount of the root filesystem
244 	 */
245 	if (mp->mnt_flag & MNT_ROOTFS)
246 		return (EINVAL);
247 
248 	return (dounmount(mp, uap->flags, p));
249 }
250 
251 /*
252  * Do the actual file system unmount.
253  */
254 int
255 dounmount(mp, flags, p)
256 	register struct mount *mp;
257 	int flags;
258 	struct proc *p;
259 {
260 	struct vnode *coveredvp;
261 	int error;
262 
263 	coveredvp = mp->mnt_vnodecovered;
264 	if (vfs_busy(mp))
265 		return (EBUSY);
266 	mp->mnt_flag |= MNT_UNMOUNT;
267 	if (error = vfs_lock(mp))
268 		return (error);
269 
270 	mp->mnt_flag &=~ MNT_ASYNC;
271 	vnode_pager_umount(mp);	/* release cached vnodes */
272 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
273 	if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
274 	    (flags & MNT_FORCE))
275 		error = VFS_UNMOUNT(mp, flags, p);
276 	mp->mnt_flag &= ~MNT_UNMOUNT;
277 	vfs_unbusy(mp);
278 	if (error) {
279 		vfs_unlock(mp);
280 	} else {
281 		vrele(coveredvp);
282 		TAILQ_REMOVE(&mountlist, mp, mnt_list);
283 		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
284 		vfs_unlock(mp);
285 		if (mp->mnt_vnodelist.lh_first != NULL)
286 			panic("unmount: dangling vnode");
287 		free((caddr_t)mp, M_MOUNT);
288 	}
289 	return (error);
290 }
291 
292 /*
293  * Sync each mounted filesystem.
294  */
295 #ifdef DIAGNOSTIC
296 int syncprt = 0;
297 struct ctldebug debug0 = { "syncprt", &syncprt };
298 #endif
299 
300 struct sync_args {
301 	int	dummy;
302 };
303 /* ARGSUSED */
304 int
305 sync(p, uap, retval)
306 	struct proc *p;
307 	struct sync_args *uap;
308 	int *retval;
309 {
310 	register struct mount *mp, *nmp;
311 	int asyncflag;
312 
313 	for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
314 		nmp = mp->mnt_list.tqe_next;
315 		/*
316 		 * The lock check below is to avoid races with mount
317 		 * and unmount.
318 		 */
319 		if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
320 		    !vfs_busy(mp)) {
321 			asyncflag = mp->mnt_flag & MNT_ASYNC;
322 			mp->mnt_flag &= ~MNT_ASYNC;
323 			VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
324 			if (asyncflag)
325 				mp->mnt_flag |= MNT_ASYNC;
326 			vfs_unbusy(mp);
327 		}
328 	}
329 #ifdef DIAGNOSTIC
330 	if (syncprt)
331 		vfs_bufstats();
332 #endif /* DIAGNOSTIC */
333 	return (0);
334 }
335 
336 /*
337  * Change filesystem quotas.
338  */
339 struct quotactl_args {
340 	char *path;
341 	int cmd;
342 	int uid;
343 	caddr_t arg;
344 };
345 /* ARGSUSED */
346 int
347 quotactl(p, uap, retval)
348 	struct proc *p;
349 	register struct quotactl_args *uap;
350 	int *retval;
351 {
352 	register struct mount *mp;
353 	int error;
354 	struct nameidata nd;
355 
356 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
357 	if (error = namei(&nd))
358 		return (error);
359 	mp = nd.ni_vp->v_mount;
360 	vrele(nd.ni_vp);
361 	return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
362 }
363 
364 /*
365  * Get filesystem statistics.
366  */
367 struct statfs_args {
368 	char *path;
369 	struct statfs *buf;
370 };
371 /* ARGSUSED */
372 int
373 statfs(p, uap, retval)
374 	struct proc *p;
375 	register struct statfs_args *uap;
376 	int *retval;
377 {
378 	register struct mount *mp;
379 	register struct statfs *sp;
380 	int error;
381 	struct nameidata nd;
382 
383 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
384 	if (error = namei(&nd))
385 		return (error);
386 	mp = nd.ni_vp->v_mount;
387 	sp = &mp->mnt_stat;
388 	vrele(nd.ni_vp);
389 	if (error = VFS_STATFS(mp, sp, p))
390 		return (error);
391 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
392 	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
393 }
394 
395 /*
396  * Get filesystem statistics.
397  */
398 struct fstatfs_args {
399 	int fd;
400 	struct statfs *buf;
401 };
402 /* ARGSUSED */
403 int
404 fstatfs(p, uap, retval)
405 	struct proc *p;
406 	register struct fstatfs_args *uap;
407 	int *retval;
408 {
409 	struct file *fp;
410 	struct mount *mp;
411 	register struct statfs *sp;
412 	int error;
413 
414 	if (error = getvnode(p->p_fd, uap->fd, &fp))
415 		return (error);
416 	mp = ((struct vnode *)fp->f_data)->v_mount;
417 	sp = &mp->mnt_stat;
418 	if (error = VFS_STATFS(mp, sp, p))
419 		return (error);
420 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
421 	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
422 }
423 
424 /*
425  * Get statistics on all filesystems.
426  */
427 struct getfsstat_args {
428 	struct statfs *buf;
429 	long bufsize;
430 	int flags;
431 };
432 int
433 getfsstat(p, uap, retval)
434 	struct proc *p;
435 	register struct getfsstat_args *uap;
436 	int *retval;
437 {
438 	register struct mount *mp, *nmp;
439 	register struct statfs *sp;
440 	caddr_t sfsp;
441 	long count, maxcount, error;
442 
443 	maxcount = uap->bufsize / sizeof(struct statfs);
444 	sfsp = (caddr_t)uap->buf;
445 	for (count = 0, mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
446 		nmp = mp->mnt_list.tqe_next;
447 		if (sfsp && count < maxcount &&
448 		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
449 			sp = &mp->mnt_stat;
450 			/*
451 			 * If MNT_NOWAIT is specified, do not refresh the
452 			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
453 			 */
454 			if (((uap->flags & MNT_NOWAIT) == 0 ||
455 			    (uap->flags & MNT_WAIT)) &&
456 			    (error = VFS_STATFS(mp, sp, p)))
457 				continue;
458 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
459 			if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
460 				return (error);
461 			sfsp += sizeof(*sp);
462 		}
463 		count++;
464 	}
465 	if (sfsp && count > maxcount)
466 		*retval = maxcount;
467 	else
468 		*retval = count;
469 	return (0);
470 }
471 
472 /*
473  * Change current working directory to a given file descriptor.
474  */
475 struct fchdir_args {
476 	int	fd;
477 };
478 /* ARGSUSED */
479 int
480 fchdir(p, uap, retval)
481 	struct proc *p;
482 	struct fchdir_args *uap;
483 	int *retval;
484 {
485 	register struct filedesc *fdp = p->p_fd;
486 	register struct vnode *vp;
487 	struct file *fp;
488 	int error;
489 
490 	if (error = getvnode(fdp, uap->fd, &fp))
491 		return (error);
492 	vp = (struct vnode *)fp->f_data;
493 	VOP_LOCK(vp);
494 	if (vp->v_type != VDIR)
495 		error = ENOTDIR;
496 	else
497 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
498 	VOP_UNLOCK(vp);
499 	if (error)
500 		return (error);
501 	VREF(vp);
502 	vrele(fdp->fd_cdir);
503 	fdp->fd_cdir = vp;
504 	return (0);
505 }
506 
507 /*
508  * Change current working directory (``.'').
509  */
510 struct chdir_args {
511 	char	*path;
512 };
513 /* ARGSUSED */
514 int
515 chdir(p, uap, retval)
516 	struct proc *p;
517 	struct chdir_args *uap;
518 	int *retval;
519 {
520 	register struct filedesc *fdp = p->p_fd;
521 	int error;
522 	struct nameidata nd;
523 
524 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
525 	if (error = change_dir(&nd, p))
526 		return (error);
527 	vrele(fdp->fd_cdir);
528 	fdp->fd_cdir = nd.ni_vp;
529 	return (0);
530 }
531 
532 /*
533  * Change notion of root (``/'') directory.
534  */
535 struct chroot_args {
536 	char	*path;
537 };
538 /* ARGSUSED */
539 int
540 chroot(p, uap, retval)
541 	struct proc *p;
542 	struct chroot_args *uap;
543 	int *retval;
544 {
545 	register struct filedesc *fdp = p->p_fd;
546 	int error;
547 	struct nameidata nd;
548 
549 	if (error = suser(p->p_ucred, &p->p_acflag))
550 		return (error);
551 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
552 	if (error = change_dir(&nd, p))
553 		return (error);
554 	if (fdp->fd_rdir != NULL)
555 		vrele(fdp->fd_rdir);
556 	fdp->fd_rdir = nd.ni_vp;
557 	return (0);
558 }
559 
560 /*
561  * Common routine for chroot and chdir.
562  */
563 static int
564 change_dir(ndp, p)
565 	register struct nameidata *ndp;
566 	struct proc *p;
567 {
568 	struct vnode *vp;
569 	int error;
570 
571 	if (error = namei(ndp))
572 		return (error);
573 	vp = ndp->ni_vp;
574 	if (vp->v_type != VDIR)
575 		error = ENOTDIR;
576 	else
577 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
578 	VOP_UNLOCK(vp);
579 	if (error)
580 		vrele(vp);
581 	return (error);
582 }
583 
584 /*
585  * Check permissions, allocate an open file structure,
586  * and call the device open routine if any.
587  */
588 struct open_args {
589 	char	*path;
590 	int	flags;
591 	int	mode;
592 };
593 int
594 open(p, uap, retval)
595 	struct proc *p;
596 	register struct open_args *uap;
597 	int *retval;
598 {
599 	register struct filedesc *fdp = p->p_fd;
600 	register struct file *fp;
601 	register struct vnode *vp;
602 	int flags, cmode;
603 	struct file *nfp;
604 	int type, indx, error;
605 	struct flock lf;
606 	struct nameidata nd;
607 	extern struct fileops vnops;
608 
609 	if (error = falloc(p, &nfp, &indx))
610 		return (error);
611 	fp = nfp;
612 	flags = FFLAGS(uap->flags);
613 	cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
614 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
615 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
616 	if (error = vn_open(&nd, flags, cmode)) {
617 		ffree(fp);
618 		if ((error == ENODEV || error == ENXIO) &&
619 		    p->p_dupfd >= 0 && 			/* XXX from fdopen */
620 		    (error =
621 		        dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
622 			*retval = indx;
623 			return (0);
624 		}
625 		if (error == ERESTART)
626 			error = EINTR;
627 		fdp->fd_ofiles[indx] = NULL;
628 		return (error);
629 	}
630 	p->p_dupfd = 0;
631 	vp = nd.ni_vp;
632 	fp->f_flag = flags & FMASK;
633 	fp->f_type = DTYPE_VNODE;
634 	fp->f_ops = &vnops;
635 	fp->f_data = (caddr_t)vp;
636 	if (flags & (O_EXLOCK | O_SHLOCK)) {
637 		lf.l_whence = SEEK_SET;
638 		lf.l_start = 0;
639 		lf.l_len = 0;
640 		if (flags & O_EXLOCK)
641 			lf.l_type = F_WRLCK;
642 		else
643 			lf.l_type = F_RDLCK;
644 		type = F_FLOCK;
645 		if ((flags & FNONBLOCK) == 0)
646 			type |= F_WAIT;
647 		VOP_UNLOCK(vp);
648 		if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
649 			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
650 			ffree(fp);
651 			fdp->fd_ofiles[indx] = NULL;
652 			return (error);
653 		}
654 		VOP_LOCK(vp);
655 		fp->f_flag |= FHASLOCK;
656 	}
657 	VOP_UNLOCK(vp);
658 	*retval = indx;
659 	return (0);
660 }
661 
662 #ifdef COMPAT_43
663 /*
664  * Create a file.
665  */
666 struct ocreat_args {
667 	char	*path;
668 	int	mode;
669 };
670 int
671 ocreat(p, uap, retval)
672 	struct proc *p;
673 	register struct ocreat_args *uap;
674 	int *retval;
675 {
676 	struct open_args openuap;
677 
678 	openuap.path = uap->path;
679 	openuap.mode = uap->mode;
680 	openuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
681 	return (open(p, &openuap, retval));
682 }
683 #endif /* COMPAT_43 */
684 
685 /*
686  * Create a special file.
687  */
688 struct mknod_args {
689 	char	*path;
690 	int	mode;
691 	int	dev;
692 };
693 /* ARGSUSED */
694 int
695 mknod(p, uap, retval)
696 	struct proc *p;
697 	register struct mknod_args *uap;
698 	int *retval;
699 {
700 	register struct vnode *vp;
701 	struct vattr vattr;
702 	int error;
703 	struct nameidata nd;
704 
705 	if (error = suser(p->p_ucred, &p->p_acflag))
706 		return (error);
707 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
708 	if (error = namei(&nd))
709 		return (error);
710 	vp = nd.ni_vp;
711 	if (vp != NULL)
712 		error = EEXIST;
713 	else {
714 		VATTR_NULL(&vattr);
715 		vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
716 		vattr.va_rdev = uap->dev;
717 
718 		switch (uap->mode & S_IFMT) {
719 		case S_IFMT:	/* used by badsect to flag bad sectors */
720 			vattr.va_type = VBAD;
721 			break;
722 		case S_IFCHR:
723 			vattr.va_type = VCHR;
724 			break;
725 		case S_IFBLK:
726 			vattr.va_type = VBLK;
727 			break;
728 		default:
729 			error = EINVAL;
730 			break;
731 		}
732 	}
733 	if (!error) {
734 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
735 		error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
736 	} else {
737 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
738 		if (nd.ni_dvp == vp)
739 			vrele(nd.ni_dvp);
740 		else
741 			vput(nd.ni_dvp);
742 		if (vp)
743 			vrele(vp);
744 	}
745 	return (error);
746 }
747 
748 /*
749  * Create named pipe.
750  */
751 struct mkfifo_args {
752 	char	*path;
753 	int	mode;
754 };
755 /* ARGSUSED */
756 int
757 mkfifo(p, uap, retval)
758 	struct proc *p;
759 	register struct mkfifo_args *uap;
760 	int *retval;
761 {
762 	struct vattr vattr;
763 	int error;
764 	struct nameidata nd;
765 
766 #ifndef FIFO
767 	return (EOPNOTSUPP);
768 #else
769 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
770 	if (error = namei(&nd))
771 		return (error);
772 	if (nd.ni_vp != NULL) {
773 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
774 		if (nd.ni_dvp == nd.ni_vp)
775 			vrele(nd.ni_dvp);
776 		else
777 			vput(nd.ni_dvp);
778 		vrele(nd.ni_vp);
779 		return (EEXIST);
780 	}
781 	VATTR_NULL(&vattr);
782 	vattr.va_type = VFIFO;
783 	vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
784 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
785 	return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
786 #endif /* FIFO */
787 }
788 
789 /*
790  * Make a hard file link.
791  */
792 struct link_args {
793 	char	*path;
794 	char	*link;
795 };
796 /* ARGSUSED */
797 int
798 link(p, uap, retval)
799 	struct proc *p;
800 	register struct link_args *uap;
801 	int *retval;
802 {
803 	register struct vnode *vp;
804 	struct nameidata nd;
805 	int error;
806 
807 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
808 	if (error = namei(&nd))
809 		return (error);
810 	vp = nd.ni_vp;
811 	if (vp->v_type != VDIR ||
812 	    (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
813 		nd.ni_cnd.cn_nameiop = CREATE;
814 		nd.ni_cnd.cn_flags = LOCKPARENT;
815 		nd.ni_dirp = uap->link;
816 		if ((error = namei(&nd)) == 0) {
817 			if (nd.ni_vp != NULL)
818 				error = EEXIST;
819 			if (!error) {
820 				LEASE_CHECK(nd.ni_dvp,
821 				    p, p->p_ucred, LEASE_WRITE);
822 				LEASE_CHECK(vp,
823 				    p, p->p_ucred, LEASE_WRITE);
824 				error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
825 			} else {
826 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
827 				if (nd.ni_dvp == nd.ni_vp)
828 					vrele(nd.ni_dvp);
829 				else
830 					vput(nd.ni_dvp);
831 				if (nd.ni_vp)
832 					vrele(nd.ni_vp);
833 			}
834 		}
835 	}
836 	vrele(vp);
837 	return (error);
838 }
839 
840 /*
841  * Make a symbolic link.
842  */
843 struct symlink_args {
844 	char	*path;
845 	char	*link;
846 };
847 /* ARGSUSED */
848 int
849 symlink(p, uap, retval)
850 	struct proc *p;
851 	register struct symlink_args *uap;
852 	int *retval;
853 {
854 	struct vattr vattr;
855 	char *path;
856 	int error;
857 	struct nameidata nd;
858 
859 	MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
860 	if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL))
861 		goto out;
862 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
863 	if (error = namei(&nd))
864 		goto out;
865 	if (nd.ni_vp) {
866 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
867 		if (nd.ni_dvp == nd.ni_vp)
868 			vrele(nd.ni_dvp);
869 		else
870 			vput(nd.ni_dvp);
871 		vrele(nd.ni_vp);
872 		error = EEXIST;
873 		goto out;
874 	}
875 	VATTR_NULL(&vattr);
876 	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
877 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
878 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
879 out:
880 	FREE(path, M_NAMEI);
881 	return (error);
882 }
883 
884 /*
885  * Delete a name from the filesystem.
886  */
887 struct unlink_args {
888 	char	*path;
889 };
890 /* ARGSUSED */
891 int
892 unlink(p, uap, retval)
893 	struct proc *p;
894 	struct unlink_args *uap;
895 	int *retval;
896 {
897 	register struct vnode *vp;
898 	int error;
899 	struct nameidata nd;
900 
901 	NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
902 	if (error = namei(&nd))
903 		return (error);
904 	vp = nd.ni_vp;
905 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
906 	VOP_LOCK(vp);
907 
908 	if (vp->v_type != VDIR ||
909 	    (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
910 		/*
911 		 * The root of a mounted filesystem cannot be deleted.
912 		 */
913 		if (vp->v_flag & VROOT)
914 			error = EBUSY;
915 		else
916 			(void)vnode_pager_uncache(vp);
917 	}
918 
919 	if (!error) {
920 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
921 		error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
922 	} else {
923 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
924 		if (nd.ni_dvp == vp)
925 			vrele(nd.ni_dvp);
926 		else
927 			vput(nd.ni_dvp);
928 		vput(vp);
929 	}
930 	return (error);
931 }
932 
933 /*
934  * Reposition read/write file offset.
935  */
936 struct lseek_args {
937 	int	fd;
938 	int	pad;
939 	off_t	offset;
940 	int	whence;
941 };
942 int
943 lseek(p, uap, retval)
944 	struct proc *p;
945 	register struct lseek_args *uap;
946 	int *retval;
947 {
948 	struct ucred *cred = p->p_ucred;
949 	register struct filedesc *fdp = p->p_fd;
950 	register struct file *fp;
951 	struct vattr vattr;
952 	int error;
953 
954 	if ((u_int)uap->fd >= fdp->fd_nfiles ||
955 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
956 		return (EBADF);
957 	if (fp->f_type != DTYPE_VNODE)
958 		return (ESPIPE);
959 	switch (uap->whence) {
960 	case L_INCR:
961 		fp->f_offset += uap->offset;
962 		break;
963 	case L_XTND:
964 		if (error =
965 		    VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p))
966 			return (error);
967 		fp->f_offset = uap->offset + vattr.va_size;
968 		break;
969 	case L_SET:
970 		fp->f_offset = uap->offset;
971 		break;
972 	default:
973 		return (EINVAL);
974 	}
975 	*(off_t *)retval = fp->f_offset;
976 	return (0);
977 }
978 
979 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
980 /*
981  * Reposition read/write file offset.
982  */
983 struct olseek_args {
984 	int	fd;
985 	long	offset;
986 	int	whence;
987 };
988 int
989 olseek(p, uap, retval)
990 	struct proc *p;
991 	register struct olseek_args *uap;
992 	int *retval;
993 {
994 	struct lseek_args nuap;
995 	off_t qret;
996 	int error;
997 
998 	nuap.fd = uap->fd;
999 	nuap.offset = uap->offset;
1000 	nuap.whence = uap->whence;
1001 	error = lseek(p, &nuap, &qret);
1002 	*(long *)retval = qret;
1003 	return (error);
1004 }
1005 #endif /* COMPAT_43 */
1006 
1007 /*
1008  * Check access permissions.
1009  */
1010 struct access_args {
1011 	char	*path;
1012 	int	flags;
1013 };
1014 int
1015 access(p, uap, retval)
1016 	struct proc *p;
1017 	register struct access_args *uap;
1018 	int *retval;
1019 {
1020 	register struct ucred *cred = p->p_ucred;
1021 	register struct vnode *vp;
1022 	int error, flags, t_gid, t_uid;
1023 	struct nameidata nd;
1024 
1025 	t_uid = cred->cr_uid;
1026 	t_gid = cred->cr_groups[0];
1027 	cred->cr_uid = p->p_cred->p_ruid;
1028 	cred->cr_groups[0] = p->p_cred->p_rgid;
1029 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1030 	if (error = namei(&nd))
1031 		goto out1;
1032 	vp = nd.ni_vp;
1033 
1034 	/* Flags == 0 means only check for existence. */
1035 	if (uap->flags) {
1036 		flags = 0;
1037 		if (uap->flags & R_OK)
1038 			flags |= VREAD;
1039 		if (uap->flags & W_OK)
1040 			flags |= VWRITE;
1041 		if (uap->flags & X_OK)
1042 			flags |= VEXEC;
1043 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1044 			error = VOP_ACCESS(vp, flags, cred, p);
1045 	}
1046 	vput(vp);
1047 out1:
1048 	cred->cr_uid = t_uid;
1049 	cred->cr_groups[0] = t_gid;
1050 	return (error);
1051 }
1052 
1053 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1054 /*
1055  * Get file status; this version follows links.
1056  */
1057 struct ostat_args {
1058 	char	*path;
1059 	struct ostat *ub;
1060 };
1061 /* ARGSUSED */
1062 int
1063 ostat(p, uap, retval)
1064 	struct proc *p;
1065 	register struct ostat_args *uap;
1066 	int *retval;
1067 {
1068 	struct stat sb;
1069 	struct ostat osb;
1070 	int error;
1071 	struct nameidata nd;
1072 
1073 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1074 	if (error = namei(&nd))
1075 		return (error);
1076 	error = vn_stat(nd.ni_vp, &sb, p);
1077 	vput(nd.ni_vp);
1078 	if (error)
1079 		return (error);
1080 	cvtstat(&sb, &osb);
1081 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1082 	return (error);
1083 }
1084 
1085 /*
1086  * Get file status; this version does not follow links.
1087  */
1088 struct olstat_args {
1089 	char	*path;
1090 	struct ostat *ub;
1091 };
1092 /* ARGSUSED */
1093 int
1094 olstat(p, uap, retval)
1095 	struct proc *p;
1096 	register struct olstat_args *uap;
1097 	int *retval;
1098 {
1099 	struct stat sb;
1100 	struct ostat osb;
1101 	int error;
1102 	struct nameidata nd;
1103 
1104 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1105 	if (error = namei(&nd))
1106 		return (error);
1107 	error = vn_stat(nd.ni_vp, &sb, p);
1108 	vput(nd.ni_vp);
1109 	if (error)
1110 		return (error);
1111 	cvtstat(&sb, &osb);
1112 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1113 	return (error);
1114 }
1115 
1116 /*
1117  * Convert from an old to a new stat structure.
1118  */
1119 void
1120 cvtstat(st, ost)
1121 	struct stat *st;
1122 	struct ostat *ost;
1123 {
1124 
1125 	ost->st_dev = st->st_dev;
1126 	ost->st_ino = st->st_ino;
1127 	ost->st_mode = st->st_mode;
1128 	ost->st_nlink = st->st_nlink;
1129 	ost->st_uid = st->st_uid;
1130 	ost->st_gid = st->st_gid;
1131 	ost->st_rdev = st->st_rdev;
1132 	if (st->st_size < (quad_t)1 << 32)
1133 		ost->st_size = st->st_size;
1134 	else
1135 		ost->st_size = -2;
1136 	ost->st_atime = st->st_atime;
1137 	ost->st_mtime = st->st_mtime;
1138 	ost->st_ctime = st->st_ctime;
1139 	ost->st_blksize = st->st_blksize;
1140 	ost->st_blocks = st->st_blocks;
1141 	ost->st_flags = st->st_flags;
1142 	ost->st_gen = st->st_gen;
1143 }
1144 #endif /* COMPAT_43 || COMPAT_SUNOS */
1145 
1146 /*
1147  * Get file status; this version follows links.
1148  */
1149 struct stat_args {
1150 	char	*path;
1151 	struct stat *ub;
1152 };
1153 /* ARGSUSED */
1154 int
1155 stat(p, uap, retval)
1156 	struct proc *p;
1157 	register struct stat_args *uap;
1158 	int *retval;
1159 {
1160 	struct stat sb;
1161 	int error;
1162 	struct nameidata nd;
1163 
1164 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1165 	if (error = namei(&nd))
1166 		return (error);
1167 	error = vn_stat(nd.ni_vp, &sb, p);
1168 	vput(nd.ni_vp);
1169 	if (error)
1170 		return (error);
1171 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1172 	return (error);
1173 }
1174 
1175 /*
1176  * Get file status; this version does not follow links.
1177  */
1178 struct lstat_args {
1179 	char	*path;
1180 	struct stat *ub;
1181 };
1182 /* ARGSUSED */
1183 int
1184 lstat(p, uap, retval)
1185 	struct proc *p;
1186 	register struct lstat_args *uap;
1187 	int *retval;
1188 {
1189 	int error;
1190 	struct vnode *vp, *dvp;
1191 	struct stat sb, sb1;
1192 	struct nameidata nd;
1193 
1194 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1195 	    uap->path, p);
1196 	if (error = namei(&nd))
1197 		return (error);
1198 	/*
1199 	 * For symbolic links, always return the attributes of its
1200 	 * containing directory, except for mode, size, and links.
1201 	 */
1202 	vp = nd.ni_vp;
1203 	dvp = nd.ni_dvp;
1204 	if (vp->v_type != VLNK) {
1205 		if (dvp == vp)
1206 			vrele(dvp);
1207 		else
1208 			vput(dvp);
1209 		error = vn_stat(vp, &sb, p);
1210 		vput(vp);
1211 		if (error)
1212 			return (error);
1213 	} else {
1214 		error = vn_stat(dvp, &sb, p);
1215 		vput(dvp);
1216 		if (error) {
1217 			vput(vp);
1218 			return (error);
1219 		}
1220 		error = vn_stat(vp, &sb1, p);
1221 		vput(vp);
1222 		if (error)
1223 			return (error);
1224 		sb.st_mode &= ~S_IFDIR;
1225 		sb.st_mode |= S_IFLNK;
1226 		sb.st_nlink = sb1.st_nlink;
1227 		sb.st_size = sb1.st_size;
1228 		sb.st_blocks = sb1.st_blocks;
1229 	}
1230 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1231 	return (error);
1232 }
1233 
1234 /*
1235  * Get configurable pathname variables.
1236  */
1237 struct pathconf_args {
1238 	char	*path;
1239 	int	name;
1240 };
1241 /* ARGSUSED */
1242 int
1243 pathconf(p, uap, retval)
1244 	struct proc *p;
1245 	register struct pathconf_args *uap;
1246 	int *retval;
1247 {
1248 	int error;
1249 	struct nameidata nd;
1250 
1251 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1252 	if (error = namei(&nd))
1253 		return (error);
1254 	error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
1255 	vput(nd.ni_vp);
1256 	return (error);
1257 }
1258 
1259 /*
1260  * Return target name of a symbolic link.
1261  */
1262 struct readlink_args {
1263 	char	*path;
1264 	char	*buf;
1265 	int	count;
1266 };
1267 /* ARGSUSED */
1268 int
1269 readlink(p, uap, retval)
1270 	struct proc *p;
1271 	register struct readlink_args *uap;
1272 	int *retval;
1273 {
1274 	register struct vnode *vp;
1275 	struct iovec aiov;
1276 	struct uio auio;
1277 	int error;
1278 	struct nameidata nd;
1279 
1280 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1281 	if (error = namei(&nd))
1282 		return (error);
1283 	vp = nd.ni_vp;
1284 	if (vp->v_type != VLNK)
1285 		error = EINVAL;
1286 	else {
1287 		aiov.iov_base = uap->buf;
1288 		aiov.iov_len = uap->count;
1289 		auio.uio_iov = &aiov;
1290 		auio.uio_iovcnt = 1;
1291 		auio.uio_offset = 0;
1292 		auio.uio_rw = UIO_READ;
1293 		auio.uio_segflg = UIO_USERSPACE;
1294 		auio.uio_procp = p;
1295 		auio.uio_resid = uap->count;
1296 		error = VOP_READLINK(vp, &auio, p->p_ucred);
1297 	}
1298 	vput(vp);
1299 	*retval = uap->count - auio.uio_resid;
1300 	return (error);
1301 }
1302 
1303 /*
1304  * Change flags of a file given a path name.
1305  */
1306 struct chflags_args {
1307 	char	*path;
1308 	int	flags;
1309 };
1310 /* ARGSUSED */
1311 int
1312 chflags(p, uap, retval)
1313 	struct proc *p;
1314 	register struct chflags_args *uap;
1315 	int *retval;
1316 {
1317 	register struct vnode *vp;
1318 	struct vattr vattr;
1319 	int error;
1320 	struct nameidata nd;
1321 
1322 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1323 	if (error = namei(&nd))
1324 		return (error);
1325 	vp = nd.ni_vp;
1326 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1327 	VOP_LOCK(vp);
1328 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1329 		error = EROFS;
1330 	else {
1331 		VATTR_NULL(&vattr);
1332 		vattr.va_flags = uap->flags;
1333 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1334 	}
1335 	vput(vp);
1336 	return (error);
1337 }
1338 
1339 /*
1340  * Change flags of a file given a file descriptor.
1341  */
1342 struct fchflags_args {
1343 	int	fd;
1344 	int	flags;
1345 };
1346 /* ARGSUSED */
1347 int
1348 fchflags(p, uap, retval)
1349 	struct proc *p;
1350 	register struct fchflags_args *uap;
1351 	int *retval;
1352 {
1353 	struct vattr vattr;
1354 	struct vnode *vp;
1355 	struct file *fp;
1356 	int error;
1357 
1358 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1359 		return (error);
1360 	vp = (struct vnode *)fp->f_data;
1361 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1362 	VOP_LOCK(vp);
1363 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1364 		error = EROFS;
1365 	else {
1366 		VATTR_NULL(&vattr);
1367 		vattr.va_flags = uap->flags;
1368 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1369 	}
1370 	VOP_UNLOCK(vp);
1371 	return (error);
1372 }
1373 
1374 /*
1375  * Change mode of a file given path name.
1376  */
1377 struct chmod_args {
1378 	char	*path;
1379 	int	mode;
1380 };
1381 /* ARGSUSED */
1382 int
1383 chmod(p, uap, retval)
1384 	struct proc *p;
1385 	register struct chmod_args *uap;
1386 	int *retval;
1387 {
1388 	register struct vnode *vp;
1389 	struct vattr vattr;
1390 	int error;
1391 	struct nameidata nd;
1392 
1393 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1394 	if (error = namei(&nd))
1395 		return (error);
1396 	vp = nd.ni_vp;
1397 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1398 	VOP_LOCK(vp);
1399 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1400 		error = EROFS;
1401 	else {
1402 		VATTR_NULL(&vattr);
1403 		vattr.va_mode = uap->mode & ALLPERMS;
1404 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1405 	}
1406 	vput(vp);
1407 	return (error);
1408 }
1409 
1410 /*
1411  * Change mode of a file given a file descriptor.
1412  */
1413 struct fchmod_args {
1414 	int	fd;
1415 	int	mode;
1416 };
1417 /* ARGSUSED */
1418 int
1419 fchmod(p, uap, retval)
1420 	struct proc *p;
1421 	register struct fchmod_args *uap;
1422 	int *retval;
1423 {
1424 	struct vattr vattr;
1425 	struct vnode *vp;
1426 	struct file *fp;
1427 	int error;
1428 
1429 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1430 		return (error);
1431 	vp = (struct vnode *)fp->f_data;
1432 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1433 	VOP_LOCK(vp);
1434 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1435 		error = EROFS;
1436 	else {
1437 		VATTR_NULL(&vattr);
1438 		vattr.va_mode = uap->mode & ALLPERMS;
1439 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1440 	}
1441 	VOP_UNLOCK(vp);
1442 	return (error);
1443 }
1444 
1445 /*
1446  * Set ownership given a path name.
1447  */
1448 struct chown_args {
1449 	char	*path;
1450 	int	uid;
1451 	int	gid;
1452 };
1453 /* ARGSUSED */
1454 int
1455 chown(p, uap, retval)
1456 	struct proc *p;
1457 	register struct chown_args *uap;
1458 	int *retval;
1459 {
1460 	register struct vnode *vp;
1461 	struct vattr vattr;
1462 	int error;
1463 	struct nameidata nd;
1464 
1465 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1466 	if (error = namei(&nd))
1467 		return (error);
1468 	vp = nd.ni_vp;
1469 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1470 	VOP_LOCK(vp);
1471 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1472 		error = EROFS;
1473 	else {
1474 		VATTR_NULL(&vattr);
1475 		vattr.va_uid = uap->uid;
1476 		vattr.va_gid = uap->gid;
1477 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1478 	}
1479 	vput(vp);
1480 	return (error);
1481 }
1482 
1483 /*
1484  * Set ownership given a file descriptor.
1485  */
1486 struct fchown_args {
1487 	int	fd;
1488 	int	uid;
1489 	int	gid;
1490 };
1491 /* ARGSUSED */
1492 int
1493 fchown(p, uap, retval)
1494 	struct proc *p;
1495 	register struct fchown_args *uap;
1496 	int *retval;
1497 {
1498 	struct vattr vattr;
1499 	struct vnode *vp;
1500 	struct file *fp;
1501 	int error;
1502 
1503 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1504 		return (error);
1505 	vp = (struct vnode *)fp->f_data;
1506 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1507 	VOP_LOCK(vp);
1508 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1509 		error = EROFS;
1510 	else {
1511 		VATTR_NULL(&vattr);
1512 		vattr.va_uid = uap->uid;
1513 		vattr.va_gid = uap->gid;
1514 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1515 	}
1516 	VOP_UNLOCK(vp);
1517 	return (error);
1518 }
1519 
1520 /*
1521  * Set the access and modification times of a file.
1522  */
1523 struct utimes_args {
1524 	char	*path;
1525 	struct	timeval *tptr;
1526 };
1527 /* ARGSUSED */
1528 int
1529 utimes(p, uap, retval)
1530 	struct proc *p;
1531 	register struct utimes_args *uap;
1532 	int *retval;
1533 {
1534 	register struct vnode *vp;
1535 	struct timeval tv[2];
1536 	struct vattr vattr;
1537 	int error;
1538 	struct nameidata nd;
1539 
1540 	VATTR_NULL(&vattr);
1541 	if (uap->tptr == NULL) {
1542 		microtime(&tv[0]);
1543 		tv[1] = tv[0];
1544 		vattr.va_vaflags |= VA_UTIMES_NULL;
1545 	} else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1546   		return (error);
1547 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1548 	if (error = namei(&nd))
1549 		return (error);
1550 	vp = nd.ni_vp;
1551 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1552 	VOP_LOCK(vp);
1553 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1554 		error = EROFS;
1555 	else {
1556 		vattr.va_atime.ts_sec = tv[0].tv_sec;
1557 		vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1558 		vattr.va_mtime.ts_sec = tv[1].tv_sec;
1559 		vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
1560 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1561 	}
1562 	vput(vp);
1563 	return (error);
1564 }
1565 
1566 /*
1567  * Truncate a file given its path name.
1568  */
1569 struct truncate_args {
1570 	char	*path;
1571 	int	pad;
1572 	off_t	length;
1573 };
1574 /* ARGSUSED */
1575 int
1576 truncate(p, uap, retval)
1577 	struct proc *p;
1578 	register struct truncate_args *uap;
1579 	int *retval;
1580 {
1581 	register struct vnode *vp;
1582 	struct vattr vattr;
1583 	int error;
1584 	struct nameidata nd;
1585 
1586 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1587 	if (error = namei(&nd))
1588 		return (error);
1589 	vp = nd.ni_vp;
1590 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1591 	VOP_LOCK(vp);
1592 	if (vp->v_type == VDIR)
1593 		error = EISDIR;
1594 	else if ((error = vn_writechk(vp)) == 0 &&
1595 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
1596 		VATTR_NULL(&vattr);
1597 		vattr.va_size = uap->length;
1598 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1599 	}
1600 	vput(vp);
1601 	return (error);
1602 }
1603 
1604 /*
1605  * Truncate a file given a file descriptor.
1606  */
1607 struct ftruncate_args {
1608 	int	fd;
1609 	int	pad;
1610 	off_t	length;
1611 };
1612 /* ARGSUSED */
1613 int
1614 ftruncate(p, uap, retval)
1615 	struct proc *p;
1616 	register struct ftruncate_args *uap;
1617 	int *retval;
1618 {
1619 	struct vattr vattr;
1620 	struct vnode *vp;
1621 	struct file *fp;
1622 	int error;
1623 
1624 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1625 		return (error);
1626 	if ((fp->f_flag & FWRITE) == 0)
1627 		return (EINVAL);
1628 	vp = (struct vnode *)fp->f_data;
1629 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1630 	VOP_LOCK(vp);
1631 	if (vp->v_type == VDIR)
1632 		error = EISDIR;
1633 	else if ((error = vn_writechk(vp)) == 0) {
1634 		VATTR_NULL(&vattr);
1635 		vattr.va_size = uap->length;
1636 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1637 	}
1638 	VOP_UNLOCK(vp);
1639 	return (error);
1640 }
1641 
1642 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1643 /*
1644  * Truncate a file given its path name.
1645  */
1646 struct otruncate_args {
1647 	char	*path;
1648 	long	length;
1649 };
1650 /* ARGSUSED */
1651 int
1652 otruncate(p, uap, retval)
1653 	struct proc *p;
1654 	register struct otruncate_args *uap;
1655 	int *retval;
1656 {
1657 	struct truncate_args nuap;
1658 
1659 	nuap.path = uap->path;
1660 	nuap.length = uap->length;
1661 	return (truncate(p, &nuap, retval));
1662 }
1663 
1664 /*
1665  * Truncate a file given a file descriptor.
1666  */
1667 struct oftruncate_args {
1668 	int	fd;
1669 	long	length;
1670 };
1671 /* ARGSUSED */
1672 int
1673 oftruncate(p, uap, retval)
1674 	struct proc *p;
1675 	register struct oftruncate_args *uap;
1676 	int *retval;
1677 {
1678 	struct ftruncate_args nuap;
1679 
1680 	nuap.fd = uap->fd;
1681 	nuap.length = uap->length;
1682 	return (ftruncate(p, &nuap, retval));
1683 }
1684 #endif /* COMPAT_43 || COMPAT_SUNOS */
1685 
1686 /*
1687  * Sync an open file.
1688  */
1689 struct fsync_args {
1690 	int	fd;
1691 };
1692 /* ARGSUSED */
1693 int
1694 fsync(p, uap, retval)
1695 	struct proc *p;
1696 	struct fsync_args *uap;
1697 	int *retval;
1698 {
1699 	register struct vnode *vp;
1700 	struct file *fp;
1701 	int error;
1702 
1703 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1704 		return (error);
1705 	vp = (struct vnode *)fp->f_data;
1706 	VOP_LOCK(vp);
1707 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
1708 	VOP_UNLOCK(vp);
1709 	return (error);
1710 }
1711 
1712 /*
1713  * Rename files.  Source and destination must either both be directories,
1714  * or both not be directories.  If target is a directory, it must be empty.
1715  */
1716 struct rename_args {
1717 	char	*from;
1718 	char	*to;
1719 };
1720 /* ARGSUSED */
1721 int
1722 rename(p, uap, retval)
1723 	struct proc *p;
1724 	register struct rename_args *uap;
1725 	int *retval;
1726 {
1727 	register struct vnode *tvp, *fvp, *tdvp;
1728 	struct nameidata fromnd, tond;
1729 	int error;
1730 
1731 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1732 		uap->from, p);
1733 	if (error = namei(&fromnd))
1734 		return (error);
1735 	fvp = fromnd.ni_vp;
1736 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1737 		UIO_USERSPACE, uap->to, p);
1738 	if (error = namei(&tond)) {
1739 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1740 		vrele(fromnd.ni_dvp);
1741 		vrele(fvp);
1742 		goto out1;
1743 	}
1744 	tdvp = tond.ni_dvp;
1745 	tvp = tond.ni_vp;
1746 	if (tvp != NULL) {
1747 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1748 			error = ENOTDIR;
1749 			goto out;
1750 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1751 			error = EISDIR;
1752 			goto out;
1753 		}
1754 	}
1755 	if (fvp == tdvp)
1756 		error = EINVAL;
1757 	/*
1758 	 * If source is the same as the destination (that is the
1759 	 * same inode number with the same name in the same directory),
1760 	 * then there is nothing to do.
1761 	 */
1762 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1763 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1764 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1765 	      fromnd.ni_cnd.cn_namelen))
1766 		error = -1;
1767 out:
1768 	if (!error) {
1769 		LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
1770 		if (fromnd.ni_dvp != tdvp)
1771 			LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1772 		if (tvp)
1773 			LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
1774 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1775 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1776 	} else {
1777 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1778 		if (tdvp == tvp)
1779 			vrele(tdvp);
1780 		else
1781 			vput(tdvp);
1782 		if (tvp)
1783 			vput(tvp);
1784 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1785 		vrele(fromnd.ni_dvp);
1786 		vrele(fvp);
1787 	}
1788 	vrele(tond.ni_startdir);
1789 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1790 out1:
1791 	if (fromnd.ni_startdir)
1792 		vrele(fromnd.ni_startdir);
1793 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1794 	if (error == -1)
1795 		return (0);
1796 	return (error);
1797 }
1798 
1799 /*
1800  * Make a directory file.
1801  */
1802 struct mkdir_args {
1803 	char	*path;
1804 	int	mode;
1805 };
1806 /* ARGSUSED */
1807 int
1808 mkdir(p, uap, retval)
1809 	struct proc *p;
1810 	register struct mkdir_args *uap;
1811 	int *retval;
1812 {
1813 	register struct vnode *vp;
1814 	struct vattr vattr;
1815 	int error;
1816 	struct nameidata nd;
1817 
1818 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
1819 	if (error = namei(&nd))
1820 		return (error);
1821 	vp = nd.ni_vp;
1822 	if (vp != NULL) {
1823 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1824 		if (nd.ni_dvp == vp)
1825 			vrele(nd.ni_dvp);
1826 		else
1827 			vput(nd.ni_dvp);
1828 		vrele(vp);
1829 		return (EEXIST);
1830 	}
1831 	VATTR_NULL(&vattr);
1832 	vattr.va_type = VDIR;
1833 	vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
1834 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1835 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1836 	if (!error)
1837 		vput(nd.ni_vp);
1838 	return (error);
1839 }
1840 
1841 /*
1842  * Remove a directory file.
1843  */
1844 struct rmdir_args {
1845 	char	*path;
1846 };
1847 /* ARGSUSED */
1848 int
1849 rmdir(p, uap, retval)
1850 	struct proc *p;
1851 	struct rmdir_args *uap;
1852 	int *retval;
1853 {
1854 	register struct vnode *vp;
1855 	int error;
1856 	struct nameidata nd;
1857 
1858 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1859 	if (error = namei(&nd))
1860 		return (error);
1861 	vp = nd.ni_vp;
1862 	if (vp->v_type != VDIR) {
1863 		error = ENOTDIR;
1864 		goto out;
1865 	}
1866 	/*
1867 	 * No rmdir "." please.
1868 	 */
1869 	if (nd.ni_dvp == vp) {
1870 		error = EINVAL;
1871 		goto out;
1872 	}
1873 	/*
1874 	 * The root of a mounted filesystem cannot be deleted.
1875 	 */
1876 	if (vp->v_flag & VROOT)
1877 		error = EBUSY;
1878 out:
1879 	if (!error) {
1880 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1881 		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1882 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1883 	} else {
1884 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1885 		if (nd.ni_dvp == vp)
1886 			vrele(nd.ni_dvp);
1887 		else
1888 			vput(nd.ni_dvp);
1889 		vput(vp);
1890 	}
1891 	return (error);
1892 }
1893 
1894 #ifdef COMPAT_43
1895 /*
1896  * Read a block of directory entries in a file system independent format.
1897  */
1898 struct ogetdirentries_args {
1899 	int	fd;
1900 	char	*buf;
1901 	u_int	count;
1902 	long	*basep;
1903 };
1904 int
1905 ogetdirentries(p, uap, retval)
1906 	struct proc *p;
1907 	register struct ogetdirentries_args *uap;
1908 	int *retval;
1909 {
1910 	register struct vnode *vp;
1911 	struct file *fp;
1912 	struct uio auio, kuio;
1913 	struct iovec aiov, kiov;
1914 	struct dirent *dp, *edp;
1915 	caddr_t dirbuf;
1916 	int error, readcnt;
1917 	long loff;
1918 
1919 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1920 		return (error);
1921 	if ((fp->f_flag & FREAD) == 0)
1922 		return (EBADF);
1923 	vp = (struct vnode *)fp->f_data;
1924 	if (vp->v_type != VDIR)
1925 		return (EINVAL);
1926 	aiov.iov_base = uap->buf;
1927 	aiov.iov_len = uap->count;
1928 	auio.uio_iov = &aiov;
1929 	auio.uio_iovcnt = 1;
1930 	auio.uio_rw = UIO_READ;
1931 	auio.uio_segflg = UIO_USERSPACE;
1932 	auio.uio_procp = p;
1933 	auio.uio_resid = uap->count;
1934 	VOP_LOCK(vp);
1935 	loff = auio.uio_offset = fp->f_offset;
1936 #	if (BYTE_ORDER != LITTLE_ENDIAN)
1937 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
1938 			error = VOP_READDIR(vp, &auio, fp->f_cred);
1939 			fp->f_offset = auio.uio_offset;
1940 		} else
1941 #	endif
1942 	{
1943 		kuio = auio;
1944 		kuio.uio_iov = &kiov;
1945 		kuio.uio_segflg = UIO_SYSSPACE;
1946 		kiov.iov_len = uap->count;
1947 		MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
1948 		kiov.iov_base = dirbuf;
1949 		error = VOP_READDIR(vp, &kuio, fp->f_cred);
1950 		fp->f_offset = kuio.uio_offset;
1951 		if (error == 0) {
1952 			readcnt = uap->count - kuio.uio_resid;
1953 			edp = (struct dirent *)&dirbuf[readcnt];
1954 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1955 #				if (BYTE_ORDER == LITTLE_ENDIAN)
1956 					/*
1957 					 * The expected low byte of
1958 					 * dp->d_namlen is our dp->d_type.
1959 					 * The high MBZ byte of dp->d_namlen
1960 					 * is our dp->d_namlen.
1961 					 */
1962 					dp->d_type = dp->d_namlen;
1963 					dp->d_namlen = 0;
1964 #				else
1965 					/*
1966 					 * The dp->d_type is the high byte
1967 					 * of the expected dp->d_namlen,
1968 					 * so must be zero'ed.
1969 					 */
1970 					dp->d_type = 0;
1971 #				endif
1972 				if (dp->d_reclen > 0) {
1973 					dp = (struct dirent *)
1974 					    ((char *)dp + dp->d_reclen);
1975 				} else {
1976 					error = EIO;
1977 					break;
1978 				}
1979 			}
1980 			if (dp >= edp)
1981 				error = uiomove(dirbuf, readcnt, &auio);
1982 		}
1983 		FREE(dirbuf, M_TEMP);
1984 	}
1985 	VOP_UNLOCK(vp);
1986 	if (error)
1987 		return (error);
1988 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
1989 	*retval = uap->count - auio.uio_resid;
1990 	return (error);
1991 }
1992 #endif
1993 
1994 /*
1995  * Read a block of directory entries in a file system independent format.
1996  */
1997 struct getdirentries_args {
1998 	int	fd;
1999 	char	*buf;
2000 	u_int	count;
2001 	long	*basep;
2002 };
2003 int
2004 getdirentries(p, uap, retval)
2005 	struct proc *p;
2006 	register struct getdirentries_args *uap;
2007 	int *retval;
2008 {
2009 	register struct vnode *vp;
2010 	struct file *fp;
2011 	struct uio auio;
2012 	struct iovec aiov;
2013 	long loff;
2014 	int error;
2015 
2016 	if (error = getvnode(p->p_fd, uap->fd, &fp))
2017 		return (error);
2018 	if ((fp->f_flag & FREAD) == 0)
2019 		return (EBADF);
2020 	vp = (struct vnode *)fp->f_data;
2021 unionread:
2022 	if (vp->v_type != VDIR)
2023 		return (EINVAL);
2024 	aiov.iov_base = uap->buf;
2025 	aiov.iov_len = uap->count;
2026 	auio.uio_iov = &aiov;
2027 	auio.uio_iovcnt = 1;
2028 	auio.uio_rw = UIO_READ;
2029 	auio.uio_segflg = UIO_USERSPACE;
2030 	auio.uio_procp = p;
2031 	auio.uio_resid = uap->count;
2032 	VOP_LOCK(vp);
2033 	loff = auio.uio_offset = fp->f_offset;
2034 	error = VOP_READDIR(vp, &auio, fp->f_cred);
2035 	fp->f_offset = auio.uio_offset;
2036 	VOP_UNLOCK(vp);
2037 	if (error)
2038 		return (error);
2039 
2040 #ifdef UNION
2041 {
2042 	extern int (**union_vnodeop_p)();
2043 	extern struct vnode *union_lowervp __P((struct vnode *));
2044 
2045 	if ((uap->count == auio.uio_resid) &&
2046 	    (vp->v_op == union_vnodeop_p)) {
2047 		struct vnode *tvp = vp;
2048 
2049 		vp = union_lowervp(vp);
2050 		if (vp != NULLVP) {
2051 			VOP_LOCK(vp);
2052 			error = VOP_OPEN(vp, FREAD);
2053 			VOP_UNLOCK(vp);
2054 
2055 			if (error) {
2056 				vrele(vp);
2057 				return (error);
2058 			}
2059 			fp->f_data = (caddr_t) vp;
2060 			fp->f_offset = 0;
2061 			error = vn_close(tvp, FREAD, fp->f_cred, p);
2062 			if (error)
2063 				return (error);
2064 			goto unionread;
2065 		}
2066 	}
2067 }
2068 #endif
2069 
2070 	if ((uap->count == auio.uio_resid) &&
2071 	    (vp->v_flag & VROOT) &&
2072 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
2073 		struct vnode *tvp = vp;
2074 		vp = vp->v_mount->mnt_vnodecovered;
2075 		VREF(vp);
2076 		fp->f_data = (caddr_t) vp;
2077 		fp->f_offset = 0;
2078 		vrele(tvp);
2079 		goto unionread;
2080 	}
2081 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
2082 	*retval = uap->count - auio.uio_resid;
2083 	return (error);
2084 }
2085 
2086 /*
2087  * Set the mode mask for creation of filesystem nodes.
2088  */
2089 struct umask_args {
2090 	int	newmask;
2091 };
2092 mode_t				/* XXX */
2093 umask(p, uap, retval)
2094 	struct proc *p;
2095 	struct umask_args *uap;
2096 	int *retval;
2097 {
2098 	register struct filedesc *fdp;
2099 
2100 	fdp = p->p_fd;
2101 	*retval = fdp->fd_cmask;
2102 	fdp->fd_cmask = uap->newmask & ALLPERMS;
2103 	return (0);
2104 }
2105 
2106 /*
2107  * Void all references to file by ripping underlying filesystem
2108  * away from vnode.
2109  */
2110 struct revoke_args {
2111 	char	*path;
2112 };
2113 /* ARGSUSED */
2114 int
2115 revoke(p, uap, retval)
2116 	struct proc *p;
2117 	register struct revoke_args *uap;
2118 	int *retval;
2119 {
2120 	register struct vnode *vp;
2121 	struct vattr vattr;
2122 	int error;
2123 	struct nameidata nd;
2124 
2125 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
2126 	if (error = namei(&nd))
2127 		return (error);
2128 	vp = nd.ni_vp;
2129 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
2130 		error = EINVAL;
2131 		goto out;
2132 	}
2133 	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2134 		goto out;
2135 	if (p->p_ucred->cr_uid != vattr.va_uid &&
2136 	    (error = suser(p->p_ucred, &p->p_acflag)))
2137 		goto out;
2138 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2139 		vgoneall(vp);
2140 out:
2141 	vrele(vp);
2142 	return (error);
2143 }
2144 
2145 /*
2146  * Convert a user file descriptor to a kernel file entry.
2147  */
2148 int
2149 getvnode(fdp, fd, fpp)
2150 	struct filedesc *fdp;
2151 	struct file **fpp;
2152 	int fd;
2153 {
2154 	struct file *fp;
2155 
2156 	if ((u_int)fd >= fdp->fd_nfiles ||
2157 	    (fp = fdp->fd_ofiles[fd]) == NULL)
2158 		return (EBADF);
2159 	if (fp->f_type != DTYPE_VNODE)
2160 		return (EINVAL);
2161 	*fpp = fp;
2162 	return (0);
2163 }
2164