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