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