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