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