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