xref: /freebsd/sys/kern/vfs_extattr.c (revision 6780ab54325a71e7e70112b11657973edde8655e)
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  * $FreeBSD$
40  */
41 
42 /* For 4.3 integer FS ID compatibility */
43 #include "opt_compat.h"
44 #include "opt_mac.h"
45 
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/bio.h>
49 #include <sys/buf.h>
50 #include <sys/sysent.h>
51 #include <sys/mac.h>
52 #include <sys/malloc.h>
53 #include <sys/mount.h>
54 #include <sys/mutex.h>
55 #include <sys/sysproto.h>
56 #include <sys/namei.h>
57 #include <sys/filedesc.h>
58 #include <sys/kernel.h>
59 #include <sys/fcntl.h>
60 #include <sys/file.h>
61 #include <sys/linker.h>
62 #include <sys/stat.h>
63 #include <sys/sx.h>
64 #include <sys/unistd.h>
65 #include <sys/vnode.h>
66 #include <sys/proc.h>
67 #include <sys/dirent.h>
68 #include <sys/extattr.h>
69 #include <sys/jail.h>
70 #include <sys/syscallsubr.h>
71 #include <sys/sysctl.h>
72 
73 #include <machine/limits.h>
74 #include <machine/stdarg.h>
75 
76 #include <vm/vm.h>
77 #include <vm/vm_object.h>
78 #include <vm/vm_page.h>
79 #include <vm/uma.h>
80 
81 static int change_dir(struct nameidata *ndp, struct thread *td);
82 static int chroot_refuse_vdir_fds(struct filedesc *fdp);
83 static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
84 static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
85 static int setfmode(struct thread *td, struct vnode *, int);
86 static int setfflags(struct thread *td, struct vnode *, int);
87 static int setutimes(struct thread *td, struct vnode *,
88     const struct timespec *, int, int);
89 static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
90     struct thread *td);
91 
92 int (*union_dircheckp)(struct thread *td, struct vnode **, struct file *);
93 int (*softdep_fsync_hook)(struct vnode *);
94 
95 /*
96  * The module initialization routine for POSIX asynchronous I/O will
97  * set this to the version of AIO that it implements.  (Zero means
98  * that it is not implemented.)  This value is used here by pathconf()
99  * and in kern_descrip.c by fpathconf().
100  */
101 int async_io_version;
102 
103 /*
104  * Sync each mounted filesystem.
105  */
106 #ifndef _SYS_SYSPROTO_H_
107 struct sync_args {
108         int     dummy;
109 };
110 #endif
111 
112 #ifdef DEBUG
113 static int syncprt = 0;
114 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
115 #endif
116 
117 /* ARGSUSED */
118 int
119 sync(td, uap)
120 	struct thread *td;
121 	struct sync_args *uap;
122 {
123 	struct mount *mp, *nmp;
124 	int asyncflag;
125 
126 	mtx_lock(&mountlist_mtx);
127 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
128 		if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
129 			nmp = TAILQ_NEXT(mp, mnt_list);
130 			continue;
131 		}
132 		if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
133 		    vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
134 			asyncflag = mp->mnt_flag & MNT_ASYNC;
135 			mp->mnt_flag &= ~MNT_ASYNC;
136 			vfs_msync(mp, MNT_NOWAIT);
137 			VFS_SYNC(mp, MNT_NOWAIT,
138 			    ((td != NULL) ? td->td_ucred : NOCRED), td);
139 			mp->mnt_flag |= asyncflag;
140 			vn_finished_write(mp);
141 		}
142 		mtx_lock(&mountlist_mtx);
143 		nmp = TAILQ_NEXT(mp, mnt_list);
144 		vfs_unbusy(mp, td);
145 	}
146 	mtx_unlock(&mountlist_mtx);
147 #if 0
148 /*
149  * XXX don't call vfs_bufstats() yet because that routine
150  * was not imported in the Lite2 merge.
151  */
152 #ifdef DIAGNOSTIC
153 	if (syncprt)
154 		vfs_bufstats();
155 #endif /* DIAGNOSTIC */
156 #endif
157 	return (0);
158 }
159 
160 /* XXX PRISON: could be per prison flag */
161 static int prison_quotas;
162 #if 0
163 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
164 #endif
165 
166 /*
167  * Change filesystem quotas.
168  */
169 #ifndef _SYS_SYSPROTO_H_
170 struct quotactl_args {
171 	char *path;
172 	int cmd;
173 	int uid;
174 	caddr_t arg;
175 };
176 #endif
177 /* ARGSUSED */
178 int
179 quotactl(td, uap)
180 	struct thread *td;
181 	register struct quotactl_args /* {
182 		char *path;
183 		int cmd;
184 		int uid;
185 		caddr_t arg;
186 	} */ *uap;
187 {
188 	struct mount *mp;
189 	int error;
190 	struct nameidata nd;
191 
192 	if (jailed(td->td_ucred) && !prison_quotas)
193 		return (EPERM);
194 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
195 	if ((error = namei(&nd)) != 0)
196 		return (error);
197 	NDFREE(&nd, NDF_ONLY_PNBUF);
198 	error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
199 	vrele(nd.ni_vp);
200 	if (error)
201 		return (error);
202 	error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td);
203 	vn_finished_write(mp);
204 	return (error);
205 }
206 
207 /*
208  * Get filesystem statistics.
209  */
210 #ifndef _SYS_SYSPROTO_H_
211 struct statfs_args {
212 	char *path;
213 	struct statfs *buf;
214 };
215 #endif
216 /* ARGSUSED */
217 int
218 statfs(td, uap)
219 	struct thread *td;
220 	register struct statfs_args /* {
221 		char *path;
222 		struct statfs *buf;
223 	} */ *uap;
224 {
225 	register struct mount *mp;
226 	register struct statfs *sp;
227 	int error;
228 	struct nameidata nd;
229 	struct statfs sb;
230 
231 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
232 	if ((error = namei(&nd)) != 0)
233 		return (error);
234 	mp = nd.ni_vp->v_mount;
235 	sp = &mp->mnt_stat;
236 	NDFREE(&nd, NDF_ONLY_PNBUF);
237 	vrele(nd.ni_vp);
238 #ifdef MAC
239 	error = mac_check_mount_stat(td->td_ucred, mp);
240 	if (error)
241 		return (error);
242 #endif
243 	error = VFS_STATFS(mp, sp, td);
244 	if (error)
245 		return (error);
246 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
247 	if (suser(td)) {
248 		bcopy(sp, &sb, sizeof(sb));
249 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
250 		sp = &sb;
251 	}
252 	return (copyout(sp, uap->buf, sizeof(*sp)));
253 }
254 
255 /*
256  * Get filesystem statistics.
257  */
258 #ifndef _SYS_SYSPROTO_H_
259 struct fstatfs_args {
260 	int fd;
261 	struct statfs *buf;
262 };
263 #endif
264 /* ARGSUSED */
265 int
266 fstatfs(td, uap)
267 	struct thread *td;
268 	register struct fstatfs_args /* {
269 		int fd;
270 		struct statfs *buf;
271 	} */ *uap;
272 {
273 	struct file *fp;
274 	struct mount *mp;
275 	register struct statfs *sp;
276 	int error;
277 	struct statfs sb;
278 
279 	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
280 		return (error);
281 	mp = ((struct vnode *)fp->f_data)->v_mount;
282 	fdrop(fp, td);
283 	if (mp == NULL)
284 		return (EBADF);
285 #ifdef MAC
286 	error = mac_check_mount_stat(td->td_ucred, mp);
287 	if (error)
288 		return (error);
289 #endif
290 	sp = &mp->mnt_stat;
291 	error = VFS_STATFS(mp, sp, td);
292 	if (error)
293 		return (error);
294 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
295 	if (suser(td)) {
296 		bcopy(sp, &sb, sizeof(sb));
297 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
298 		sp = &sb;
299 	}
300 	return (copyout(sp, uap->buf, sizeof(*sp)));
301 }
302 
303 /*
304  * Get statistics on all filesystems.
305  */
306 #ifndef _SYS_SYSPROTO_H_
307 struct getfsstat_args {
308 	struct statfs *buf;
309 	long bufsize;
310 	int flags;
311 };
312 #endif
313 int
314 getfsstat(td, uap)
315 	struct thread *td;
316 	register struct getfsstat_args /* {
317 		struct statfs *buf;
318 		long bufsize;
319 		int flags;
320 	} */ *uap;
321 {
322 	register struct mount *mp, *nmp;
323 	register struct statfs *sp;
324 	caddr_t sfsp;
325 	long count, maxcount, error;
326 
327 	maxcount = uap->bufsize / sizeof(struct statfs);
328 	sfsp = (caddr_t)uap->buf;
329 	count = 0;
330 	mtx_lock(&mountlist_mtx);
331 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
332 #ifdef MAC
333 		if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
334 			nmp = TAILQ_NEXT(mp, mnt_list);
335 			continue;
336 		}
337 #endif
338 		if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
339 			nmp = TAILQ_NEXT(mp, mnt_list);
340 			continue;
341 		}
342 		if (sfsp && count < maxcount) {
343 			sp = &mp->mnt_stat;
344 			/*
345 			 * If MNT_NOWAIT or MNT_LAZY is specified, do not
346 			 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
347 			 * overrides MNT_WAIT.
348 			 */
349 			if (((uap->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
350 			    (uap->flags & MNT_WAIT)) &&
351 			    (error = VFS_STATFS(mp, sp, td))) {
352 				mtx_lock(&mountlist_mtx);
353 				nmp = TAILQ_NEXT(mp, mnt_list);
354 				vfs_unbusy(mp, td);
355 				continue;
356 			}
357 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
358 			error = copyout(sp, sfsp, sizeof(*sp));
359 			if (error) {
360 				vfs_unbusy(mp, td);
361 				return (error);
362 			}
363 			sfsp += sizeof(*sp);
364 		}
365 		count++;
366 		mtx_lock(&mountlist_mtx);
367 		nmp = TAILQ_NEXT(mp, mnt_list);
368 		vfs_unbusy(mp, td);
369 	}
370 	mtx_unlock(&mountlist_mtx);
371 	if (sfsp && count > maxcount)
372 		td->td_retval[0] = maxcount;
373 	else
374 		td->td_retval[0] = count;
375 	return (0);
376 }
377 
378 /*
379  * Change current working directory to a given file descriptor.
380  */
381 #ifndef _SYS_SYSPROTO_H_
382 struct fchdir_args {
383 	int	fd;
384 };
385 #endif
386 /* ARGSUSED */
387 int
388 fchdir(td, uap)
389 	struct thread *td;
390 	struct fchdir_args /* {
391 		int fd;
392 	} */ *uap;
393 {
394 	register struct filedesc *fdp = td->td_proc->p_fd;
395 	struct vnode *vp, *tdp, *vpold;
396 	struct mount *mp;
397 	struct file *fp;
398 	int error;
399 
400 	if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
401 		return (error);
402 	vp = fp->f_data;
403 	VREF(vp);
404 	fdrop(fp, td);
405 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
406 	if (vp->v_type != VDIR)
407 		error = ENOTDIR;
408 #ifdef MAC
409 	else if ((error = mac_check_vnode_chdir(td->td_ucred, vp)) != 0) {
410 	}
411 #endif
412 	else
413 		error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
414 	while (!error && (mp = vp->v_mountedhere) != NULL) {
415 		if (vfs_busy(mp, 0, 0, td))
416 			continue;
417 		error = VFS_ROOT(mp, &tdp);
418 		vfs_unbusy(mp, td);
419 		if (error)
420 			break;
421 		vput(vp);
422 		vp = tdp;
423 	}
424 	if (error) {
425 		vput(vp);
426 		return (error);
427 	}
428 	VOP_UNLOCK(vp, 0, td);
429 	FILEDESC_LOCK(fdp);
430 	vpold = fdp->fd_cdir;
431 	fdp->fd_cdir = vp;
432 	FILEDESC_UNLOCK(fdp);
433 	vrele(vpold);
434 	return (0);
435 }
436 
437 /*
438  * Change current working directory (``.'').
439  */
440 #ifndef _SYS_SYSPROTO_H_
441 struct chdir_args {
442 	char	*path;
443 };
444 #endif
445 /* ARGSUSED */
446 int
447 chdir(td, uap)
448 	struct thread *td;
449 	struct chdir_args /* {
450 		char *path;
451 	} */ *uap;
452 {
453 
454 	return (kern_chdir(td, uap->path, UIO_USERSPACE));
455 }
456 
457 int
458 kern_chdir(struct thread *td, char *path, enum uio_seg pathseg)
459 {
460 	register struct filedesc *fdp = td->td_proc->p_fd;
461 	int error;
462 	struct nameidata nd;
463 	struct vnode *vp;
464 
465 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, pathseg, path, td);
466 	if ((error = change_dir(&nd, td)) != 0)
467 		return (error);
468 	VOP_UNLOCK(nd.ni_vp, 0, td);
469 	NDFREE(&nd, NDF_ONLY_PNBUF);
470 	FILEDESC_LOCK(fdp);
471 	vp = fdp->fd_cdir;
472 	fdp->fd_cdir = nd.ni_vp;
473 	FILEDESC_UNLOCK(fdp);
474 	vrele(vp);
475 	return (0);
476 }
477 
478 /*
479  * Helper function for raised chroot(2) security function:  Refuse if
480  * any filedescriptors are open directories.
481  */
482 static int
483 chroot_refuse_vdir_fds(fdp)
484 	struct filedesc *fdp;
485 {
486 	struct vnode *vp;
487 	struct file *fp;
488 	int fd;
489 
490 	FILEDESC_LOCK_ASSERT(fdp, MA_OWNED);
491 	for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
492 		fp = fget_locked(fdp, fd);
493 		if (fp == NULL)
494 			continue;
495 		if (fp->f_type == DTYPE_VNODE) {
496 			vp = fp->f_data;
497 			if (vp->v_type == VDIR)
498 				return (EPERM);
499 		}
500 	}
501 	return (0);
502 }
503 
504 /*
505  * This sysctl determines if we will allow a process to chroot(2) if it
506  * has a directory open:
507  *	0: disallowed for all processes.
508  *	1: allowed for processes that were not already chroot(2)'ed.
509  *	2: allowed for all processes.
510  */
511 
512 static int chroot_allow_open_directories = 1;
513 
514 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
515      &chroot_allow_open_directories, 0, "");
516 
517 /*
518  * Change notion of root (``/'') directory.
519  */
520 #ifndef _SYS_SYSPROTO_H_
521 struct chroot_args {
522 	char	*path;
523 };
524 #endif
525 /* ARGSUSED */
526 int
527 chroot(td, uap)
528 	struct thread *td;
529 	struct chroot_args /* {
530 		char *path;
531 	} */ *uap;
532 {
533 	register struct filedesc *fdp = td->td_proc->p_fd;
534 	int error;
535 	struct nameidata nd;
536 	struct vnode *vp;
537 
538 	error = suser_cred(td->td_ucred, PRISON_ROOT);
539 	if (error)
540 		return (error);
541 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, td);
542 	mtx_lock(&Giant);
543 	if ((error = change_dir(&nd, td)) != 0)
544 		goto error;
545 #ifdef MAC
546 	if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp))) {
547 		vput(nd.ni_vp);
548 		goto error;
549 	}
550 #endif
551 	VOP_UNLOCK(nd.ni_vp, 0, td);
552 	FILEDESC_LOCK(fdp);
553 	if (chroot_allow_open_directories == 0 ||
554 	    (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
555 		error = chroot_refuse_vdir_fds(fdp);
556 		if (error)
557 			goto error_unlock;
558 	}
559 	vp = fdp->fd_rdir;
560 	fdp->fd_rdir = nd.ni_vp;
561 	if (!fdp->fd_jdir) {
562 		fdp->fd_jdir = nd.ni_vp;
563                 VREF(fdp->fd_jdir);
564 	}
565 	FILEDESC_UNLOCK(fdp);
566 	NDFREE(&nd, NDF_ONLY_PNBUF);
567 	vrele(vp);
568 	mtx_unlock(&Giant);
569 	return (0);
570 error_unlock:
571 	FILEDESC_UNLOCK(fdp);
572 error:
573 	mtx_unlock(&Giant);
574 	NDFREE(&nd, NDF_ONLY_PNBUF);
575 	return (error);
576 }
577 
578 /*
579  * Common routine for chroot and chdir.  On success, the directory vnode
580  * is returned locked, and must be unlocked by the caller.
581  */
582 static int
583 change_dir(ndp, td)
584 	register struct nameidata *ndp;
585 	struct thread *td;
586 {
587 	struct vnode *vp;
588 	int error;
589 
590 	error = namei(ndp);
591 	if (error)
592 		return (error);
593 	vp = ndp->ni_vp;
594 	if (vp->v_type != VDIR)
595 		error = ENOTDIR;
596 #ifdef MAC
597 	if (error == 0)
598 		error = mac_check_vnode_chdir(td->td_ucred, vp);
599 #endif
600 	if (error == 0)
601 		error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
602 	if (error)
603 		vput(vp);
604 	return (error);
605 }
606 
607 /*
608  * Check permissions, allocate an open file structure,
609  * and call the device open routine if any.
610  */
611 #ifndef _SYS_SYSPROTO_H_
612 struct open_args {
613 	char	*path;
614 	int	flags;
615 	int	mode;
616 };
617 #endif
618 int
619 open(td, uap)
620 	struct thread *td;
621 	register struct open_args /* {
622 		char *path;
623 		int flags;
624 		int mode;
625 	} */ *uap;
626 {
627 
628 	return (kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode));
629 }
630 
631 int
632 kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags,
633     int mode)
634 {
635 	struct proc *p = td->td_proc;
636 	struct filedesc *fdp = p->p_fd;
637 	struct file *fp;
638 	struct vnode *vp;
639 	struct vattr vat;
640 	struct mount *mp;
641 	int cmode, oflags;
642 	struct file *nfp;
643 	int type, indx, error;
644 	struct flock lf;
645 	struct nameidata nd;
646 
647 	if ((flags & O_ACCMODE) == O_ACCMODE)
648 		return (EINVAL);
649 	oflags = flags;
650 	flags = FFLAGS(flags);
651 	error = falloc(td, &nfp, &indx);
652 	if (error)
653 		return (error);
654 	fp = nfp;
655 	FILEDESC_LOCK(fdp);
656 	cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
657 	FILEDESC_UNLOCK(fdp);
658 	NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
659 	td->td_dupfd = -indx - 1;		/* XXX check for fdopen */
660 	/*
661 	 * Bump the ref count to prevent another process from closing
662 	 * the descriptor while we are blocked in vn_open()
663 	 */
664 	fhold(fp);
665 	error = vn_open(&nd, &flags, cmode);
666 	if (error) {
667 		/*
668 		 * release our own reference
669 		 */
670 		fdrop(fp, td);
671 
672 		/*
673 		 * handle special fdopen() case.  bleh.  dupfdopen() is
674 		 * responsible for dropping the old contents of ofiles[indx]
675 		 * if it succeeds.
676 		 */
677 		if ((error == ENODEV || error == ENXIO) &&
678 		    td->td_dupfd >= 0 &&		/* XXX from fdopen */
679 		    (error =
680 			dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
681 			td->td_retval[0] = indx;
682 			return (0);
683 		}
684 		/*
685 		 * Clean up the descriptor, but only if another thread hadn't
686 		 * replaced or closed it.
687 		 */
688 		FILEDESC_LOCK(fdp);
689 		if (fdp->fd_ofiles[indx] == fp) {
690 			fdp->fd_ofiles[indx] = NULL;
691 			FILEDESC_UNLOCK(fdp);
692 			fdrop(fp, td);
693 		} else
694 			FILEDESC_UNLOCK(fdp);
695 
696 		if (error == ERESTART)
697 			error = EINTR;
698 		return (error);
699 	}
700 	td->td_dupfd = 0;
701 	NDFREE(&nd, NDF_ONLY_PNBUF);
702 	vp = nd.ni_vp;
703 
704 	/*
705 	 * There should be 2 references on the file, one from the descriptor
706 	 * table, and one for us.
707 	 *
708 	 * Handle the case where someone closed the file (via its file
709 	 * descriptor) while we were blocked.  The end result should look
710 	 * like opening the file succeeded but it was immediately closed.
711 	 */
712 	FILEDESC_LOCK(fdp);
713 	FILE_LOCK(fp);
714 	if (fp->f_count == 1) {
715 		KASSERT(fdp->fd_ofiles[indx] != fp,
716 		    ("Open file descriptor lost all refs"));
717 		FILEDESC_UNLOCK(fdp);
718 		FILE_UNLOCK(fp);
719 		VOP_UNLOCK(vp, 0, td);
720 		vn_close(vp, flags & FMASK, fp->f_cred, td);
721 		fdrop(fp, td);
722 		td->td_retval[0] = indx;
723 		return 0;
724 	}
725 
726 	/* assert that vn_open created a backing object if one is needed */
727 	KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
728 		("open: vmio vnode has no backing object after vn_open"));
729 
730 	fp->f_data = vp;
731 	fp->f_flag = flags & FMASK;
732 	fp->f_ops = &vnops;
733 	fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
734 	FILEDESC_UNLOCK(fdp);
735 	FILE_UNLOCK(fp);
736 	VOP_UNLOCK(vp, 0, td);
737 	if (flags & (O_EXLOCK | O_SHLOCK)) {
738 		lf.l_whence = SEEK_SET;
739 		lf.l_start = 0;
740 		lf.l_len = 0;
741 		if (flags & O_EXLOCK)
742 			lf.l_type = F_WRLCK;
743 		else
744 			lf.l_type = F_RDLCK;
745 		type = F_FLOCK;
746 		if ((flags & FNONBLOCK) == 0)
747 			type |= F_WAIT;
748 		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
749 			    type)) != 0)
750 			goto bad;
751 		fp->f_flag |= FHASLOCK;
752 	}
753 	if (flags & O_TRUNC) {
754 		if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
755 			goto bad;
756 		VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
757 		VATTR_NULL(&vat);
758 		vat.va_size = 0;
759 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
760 #ifdef MAC
761 		error = mac_check_vnode_write(td->td_ucred, fp->f_cred, vp);
762 		if (error == 0)
763 #endif
764 			error = VOP_SETATTR(vp, &vat, td->td_ucred, td);
765 		VOP_UNLOCK(vp, 0, td);
766 		vn_finished_write(mp);
767 		if (error)
768 			goto bad;
769 	}
770 	/*
771 	 * Release our private reference, leaving the one associated with
772 	 * the descriptor table intact.
773 	 */
774 	fdrop(fp, td);
775 	td->td_retval[0] = indx;
776 	return (0);
777 bad:
778 	FILEDESC_LOCK(fdp);
779 	if (fdp->fd_ofiles[indx] == fp) {
780 		fdp->fd_ofiles[indx] = NULL;
781 		FILEDESC_UNLOCK(fdp);
782 		fdrop(fp, td);
783 	} else
784 		FILEDESC_UNLOCK(fdp);
785 	fdrop(fp, td);
786 	return (error);
787 }
788 
789 #ifdef COMPAT_43
790 /*
791  * Create a file.
792  */
793 #ifndef _SYS_SYSPROTO_H_
794 struct ocreat_args {
795 	char	*path;
796 	int	mode;
797 };
798 #endif
799 int
800 ocreat(td, uap)
801 	struct thread *td;
802 	register struct ocreat_args /* {
803 		char *path;
804 		int mode;
805 	} */ *uap;
806 {
807 	struct open_args /* {
808 		char *path;
809 		int flags;
810 		int mode;
811 	} */ nuap;
812 
813 	nuap.path = uap->path;
814 	nuap.mode = uap->mode;
815 	nuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
816 	return (open(td, &nuap));
817 }
818 #endif /* COMPAT_43 */
819 
820 /*
821  * Create a special file.
822  */
823 #ifndef _SYS_SYSPROTO_H_
824 struct mknod_args {
825 	char	*path;
826 	int	mode;
827 	int	dev;
828 };
829 #endif
830 /* ARGSUSED */
831 int
832 mknod(td, uap)
833 	struct thread *td;
834 	register struct mknod_args /* {
835 		char *path;
836 		int mode;
837 		int dev;
838 	} */ *uap;
839 {
840 
841 	return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev));
842 }
843 
844 int
845 kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode,
846     int dev)
847 {
848 	struct vnode *vp;
849 	struct mount *mp;
850 	struct vattr vattr;
851 	int error;
852 	int whiteout = 0;
853 	struct nameidata nd;
854 
855 	switch (mode & S_IFMT) {
856 	case S_IFCHR:
857 	case S_IFBLK:
858 		error = suser(td);
859 		break;
860 	default:
861 		error = suser_cred(td->td_ucred, PRISON_ROOT);
862 		break;
863 	}
864 	if (error)
865 		return (error);
866 restart:
867 	bwillwrite();
868 	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td);
869 	if ((error = namei(&nd)) != 0)
870 		return (error);
871 	vp = nd.ni_vp;
872 	if (vp != NULL) {
873 		vrele(vp);
874 		error = EEXIST;
875 	} else {
876 		VATTR_NULL(&vattr);
877 		FILEDESC_LOCK(td->td_proc->p_fd);
878 		vattr.va_mode = (mode & ALLPERMS) &
879 		    ~td->td_proc->p_fd->fd_cmask;
880 		FILEDESC_UNLOCK(td->td_proc->p_fd);
881 		vattr.va_rdev = dev;
882 		whiteout = 0;
883 
884 		switch (mode & S_IFMT) {
885 		case S_IFMT:	/* used by badsect to flag bad sectors */
886 			vattr.va_type = VBAD;
887 			break;
888 		case S_IFCHR:
889 			vattr.va_type = VCHR;
890 			break;
891 		case S_IFBLK:
892 			vattr.va_type = VBLK;
893 			break;
894 		case S_IFWHT:
895 			whiteout = 1;
896 			break;
897 		default:
898 			error = EINVAL;
899 			break;
900 		}
901 	}
902 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
903 		NDFREE(&nd, NDF_ONLY_PNBUF);
904 		vput(nd.ni_dvp);
905 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
906 			return (error);
907 		goto restart;
908 	}
909 #ifdef MAC
910 	if (error == 0 && !whiteout)
911 		error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp,
912 		    &nd.ni_cnd, &vattr);
913 #endif
914 	if (!error) {
915 		VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
916 		if (whiteout)
917 			error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
918 		else {
919 			error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
920 						&nd.ni_cnd, &vattr);
921 			if (error == 0)
922 				vput(nd.ni_vp);
923 		}
924 	}
925 	NDFREE(&nd, NDF_ONLY_PNBUF);
926 	vput(nd.ni_dvp);
927 	vn_finished_write(mp);
928 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
929 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
930 	return (error);
931 }
932 
933 /*
934  * Create a named pipe.
935  */
936 #ifndef _SYS_SYSPROTO_H_
937 struct mkfifo_args {
938 	char	*path;
939 	int	mode;
940 };
941 #endif
942 /* ARGSUSED */
943 int
944 mkfifo(td, uap)
945 	struct thread *td;
946 	register struct mkfifo_args /* {
947 		char *path;
948 		int mode;
949 	} */ *uap;
950 {
951 
952 	return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode));
953 }
954 
955 int
956 kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode)
957 {
958 	struct mount *mp;
959 	struct vattr vattr;
960 	int error;
961 	struct nameidata nd;
962 
963 restart:
964 	bwillwrite();
965 	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, pathseg, path, td);
966 	if ((error = namei(&nd)) != 0)
967 		return (error);
968 	if (nd.ni_vp != NULL) {
969 		NDFREE(&nd, NDF_ONLY_PNBUF);
970 		vrele(nd.ni_vp);
971 		vput(nd.ni_dvp);
972 		return (EEXIST);
973 	}
974 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
975 		NDFREE(&nd, NDF_ONLY_PNBUF);
976 		vput(nd.ni_dvp);
977 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
978 			return (error);
979 		goto restart;
980 	}
981 	VATTR_NULL(&vattr);
982 	vattr.va_type = VFIFO;
983 	FILEDESC_LOCK(td->td_proc->p_fd);
984 	vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask;
985 	FILEDESC_UNLOCK(td->td_proc->p_fd);
986 #ifdef MAC
987 	error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
988 	    &vattr);
989 	if (error)
990 		goto out;
991 #endif
992 	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
993 	error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
994 	if (error == 0)
995 		vput(nd.ni_vp);
996 #ifdef MAC
997 out:
998 #endif
999 	NDFREE(&nd, NDF_ONLY_PNBUF);
1000 	vput(nd.ni_dvp);
1001 	vn_finished_write(mp);
1002 	return (error);
1003 }
1004 
1005 /*
1006  * Make a hard file link.
1007  */
1008 #ifndef _SYS_SYSPROTO_H_
1009 struct link_args {
1010 	char	*path;
1011 	char	*link;
1012 };
1013 #endif
1014 /* ARGSUSED */
1015 int
1016 link(td, uap)
1017 	struct thread *td;
1018 	register struct link_args /* {
1019 		char *path;
1020 		char *link;
1021 	} */ *uap;
1022 {
1023 
1024 	return (kern_link(td, uap->path, uap->link, UIO_USERSPACE));
1025 }
1026 
1027 int
1028 kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
1029 {
1030 	struct vnode *vp;
1031 	struct mount *mp;
1032 	struct nameidata nd;
1033 	int error;
1034 
1035 	bwillwrite();
1036 	NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, segflg, path, td);
1037 	if ((error = namei(&nd)) != 0)
1038 		return (error);
1039 	NDFREE(&nd, NDF_ONLY_PNBUF);
1040 	vp = nd.ni_vp;
1041 	if (vp->v_type == VDIR) {
1042 		vrele(vp);
1043 		return (EPERM);		/* POSIX */
1044 	}
1045 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
1046 		vrele(vp);
1047 		return (error);
1048 	}
1049 	NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td);
1050 	if ((error = namei(&nd)) == 0) {
1051 		if (nd.ni_vp != NULL) {
1052 			vrele(nd.ni_vp);
1053 			error = EEXIST;
1054 		} else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td))
1055 		    == 0) {
1056 			VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1057 			VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1058 #ifdef MAC
1059 			error = mac_check_vnode_link(td->td_ucred, nd.ni_dvp,
1060 			    vp, &nd.ni_cnd);
1061 			if (error == 0)
1062 #endif
1063 				error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1064 			VOP_UNLOCK(vp, 0, td);
1065 		}
1066 		NDFREE(&nd, NDF_ONLY_PNBUF);
1067 		vput(nd.ni_dvp);
1068 	}
1069 	vrele(vp);
1070 	vn_finished_write(mp);
1071 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1072 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1073 	return (error);
1074 }
1075 
1076 /*
1077  * Make a symbolic link.
1078  */
1079 #ifndef _SYS_SYSPROTO_H_
1080 struct symlink_args {
1081 	char	*path;
1082 	char	*link;
1083 };
1084 #endif
1085 /* ARGSUSED */
1086 int
1087 symlink(td, uap)
1088 	struct thread *td;
1089 	register struct symlink_args /* {
1090 		char *path;
1091 		char *link;
1092 	} */ *uap;
1093 {
1094 
1095 	return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE));
1096 }
1097 
1098 int
1099 kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg)
1100 {
1101 	struct mount *mp;
1102 	struct vattr vattr;
1103 	char *syspath;
1104 	int error;
1105 	struct nameidata nd;
1106 
1107 	if (segflg == UIO_SYSSPACE) {
1108 		syspath = path;
1109 	} else {
1110 		syspath = uma_zalloc(namei_zone, 0);
1111 		if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0)
1112 			goto out;
1113 	}
1114 restart:
1115 	bwillwrite();
1116 	NDINIT(&nd, CREATE, LOCKPARENT | NOOBJ | SAVENAME, segflg, link, td);
1117 	if ((error = namei(&nd)) != 0)
1118 		goto out;
1119 	if (nd.ni_vp) {
1120 		NDFREE(&nd, NDF_ONLY_PNBUF);
1121 		vrele(nd.ni_vp);
1122 		vput(nd.ni_dvp);
1123 		error = EEXIST;
1124 		goto out;
1125 	}
1126 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1127 		NDFREE(&nd, NDF_ONLY_PNBUF);
1128 		vput(nd.ni_dvp);
1129 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1130 			return (error);
1131 		goto restart;
1132 	}
1133 	VATTR_NULL(&vattr);
1134 	FILEDESC_LOCK(td->td_proc->p_fd);
1135 	vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
1136 	FILEDESC_UNLOCK(td->td_proc->p_fd);
1137 #ifdef MAC
1138 	vattr.va_type = VLNK;
1139 	error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1140 	    &vattr);
1141 	if (error)
1142 		goto out2;
1143 #endif
1144 	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1145 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath);
1146 	if (error == 0)
1147 		vput(nd.ni_vp);
1148 #ifdef MAC
1149 out2:
1150 #endif
1151 	NDFREE(&nd, NDF_ONLY_PNBUF);
1152 	vput(nd.ni_dvp);
1153 	vn_finished_write(mp);
1154 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1155 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1156 out:
1157 	if (segflg != UIO_SYSSPACE)
1158 		uma_zfree(namei_zone, syspath);
1159 	return (error);
1160 }
1161 
1162 /*
1163  * Delete a whiteout from the filesystem.
1164  */
1165 /* ARGSUSED */
1166 int
1167 undelete(td, uap)
1168 	struct thread *td;
1169 	register struct undelete_args /* {
1170 		char *path;
1171 	} */ *uap;
1172 {
1173 	int error;
1174 	struct mount *mp;
1175 	struct nameidata nd;
1176 
1177 restart:
1178 	bwillwrite();
1179 	NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1180 	    uap->path, td);
1181 	error = namei(&nd);
1182 	if (error)
1183 		return (error);
1184 
1185 	if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1186 		NDFREE(&nd, NDF_ONLY_PNBUF);
1187 		if (nd.ni_vp)
1188 			vrele(nd.ni_vp);
1189 		vput(nd.ni_dvp);
1190 		return (EEXIST);
1191 	}
1192 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1193 		NDFREE(&nd, NDF_ONLY_PNBUF);
1194 		vput(nd.ni_dvp);
1195 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1196 			return (error);
1197 		goto restart;
1198 	}
1199 	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1200 	error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1201 	NDFREE(&nd, NDF_ONLY_PNBUF);
1202 	vput(nd.ni_dvp);
1203 	vn_finished_write(mp);
1204 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1205 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1206 	return (error);
1207 }
1208 
1209 /*
1210  * Delete a name from the filesystem.
1211  */
1212 #ifndef _SYS_SYSPROTO_H_
1213 struct unlink_args {
1214 	char	*path;
1215 };
1216 #endif
1217 /* ARGSUSED */
1218 int
1219 unlink(td, uap)
1220 	struct thread *td;
1221 	struct unlink_args /* {
1222 		char *path;
1223 	} */ *uap;
1224 {
1225 
1226 	return (kern_unlink(td, uap->path, UIO_USERSPACE));
1227 }
1228 
1229 int
1230 kern_unlink(struct thread *td, char *path, enum uio_seg pathseg)
1231 {
1232 	struct mount *mp;
1233 	struct vnode *vp;
1234 	int error;
1235 	struct nameidata nd;
1236 
1237 restart:
1238 	bwillwrite();
1239 	NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, pathseg, path, td);
1240 	if ((error = namei(&nd)) != 0)
1241 		return (error);
1242 	vp = nd.ni_vp;
1243 	if (vp->v_type == VDIR)
1244 		error = EPERM;		/* POSIX */
1245 	else {
1246 		/*
1247 		 * The root of a mounted filesystem cannot be deleted.
1248 		 *
1249 		 * XXX: can this only be a VDIR case?
1250 		 */
1251 		if (vp->v_vflag & VV_ROOT)
1252 			error = EBUSY;
1253 	}
1254 	if (error == 0) {
1255 		if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1256 			NDFREE(&nd, NDF_ONLY_PNBUF);
1257 			if (vp == nd.ni_dvp)
1258 				vrele(vp);
1259 			else
1260 				vput(vp);
1261 			vput(nd.ni_dvp);
1262 			if ((error = vn_start_write(NULL, &mp,
1263 			    V_XSLEEP | PCATCH)) != 0)
1264 				return (error);
1265 			goto restart;
1266 		}
1267 #ifdef MAC
1268 		error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
1269 		    &nd.ni_cnd);
1270 		if (error)
1271 			goto out;
1272 #endif
1273 		VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1274 		error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1275 #ifdef MAC
1276 out:
1277 #endif
1278 		vn_finished_write(mp);
1279 	}
1280 	NDFREE(&nd, NDF_ONLY_PNBUF);
1281 	if (vp == nd.ni_dvp)
1282 		vrele(vp);
1283 	else
1284 		vput(vp);
1285 	vput(nd.ni_dvp);
1286 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1287 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1288 	return (error);
1289 }
1290 
1291 /*
1292  * Reposition read/write file offset.
1293  */
1294 #ifndef _SYS_SYSPROTO_H_
1295 struct lseek_args {
1296 	int	fd;
1297 	int	pad;
1298 	off_t	offset;
1299 	int	whence;
1300 };
1301 #endif
1302 int
1303 lseek(td, uap)
1304 	struct thread *td;
1305 	register struct lseek_args /* {
1306 		int fd;
1307 		int pad;
1308 		off_t offset;
1309 		int whence;
1310 	} */ *uap;
1311 {
1312 	struct ucred *cred = td->td_ucred;
1313 	struct file *fp;
1314 	struct vnode *vp;
1315 	struct vattr vattr;
1316 	off_t offset;
1317 	int error, noneg;
1318 
1319 	if ((error = fget(td, uap->fd, &fp)) != 0)
1320 		return (error);
1321 	if (fp->f_type != DTYPE_VNODE) {
1322 		fdrop(fp, td);
1323 		return (ESPIPE);
1324 	}
1325 	vp = fp->f_data;
1326 	noneg = (vp->v_type != VCHR);
1327 	offset = uap->offset;
1328 	switch (uap->whence) {
1329 	case L_INCR:
1330 		if (noneg &&
1331 		    (fp->f_offset < 0 ||
1332 		    (offset > 0 && fp->f_offset > OFF_MAX - offset))) {
1333 			error = EOVERFLOW;
1334 			break;
1335 		}
1336 		offset += fp->f_offset;
1337 		break;
1338 	case L_XTND:
1339 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1340 		error = VOP_GETATTR(vp, &vattr, cred, td);
1341 		VOP_UNLOCK(vp, 0, td);
1342 		if (error)
1343 			break;
1344 		if (noneg &&
1345 		    (vattr.va_size > OFF_MAX ||
1346 		    (offset > 0 && vattr.va_size > OFF_MAX - offset))) {
1347 			error = EOVERFLOW;
1348 			break;
1349 		}
1350 		offset += vattr.va_size;
1351 		break;
1352 	case L_SET:
1353 		break;
1354 	default:
1355 		error = EINVAL;
1356 	}
1357 	if (error == 0 && noneg && offset < 0)
1358 		error = EINVAL;
1359 	if (error != 0) {
1360 		fdrop(fp, td);
1361 		return (error);
1362 	}
1363 	fp->f_offset = offset;
1364 	*(off_t *)(td->td_retval) = fp->f_offset;
1365 	fdrop(fp, td);
1366 	return (0);
1367 }
1368 
1369 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1370 /*
1371  * Reposition read/write file offset.
1372  */
1373 #ifndef _SYS_SYSPROTO_H_
1374 struct olseek_args {
1375 	int	fd;
1376 	long	offset;
1377 	int	whence;
1378 };
1379 #endif
1380 int
1381 olseek(td, uap)
1382 	struct thread *td;
1383 	register struct olseek_args /* {
1384 		int fd;
1385 		long offset;
1386 		int whence;
1387 	} */ *uap;
1388 {
1389 	struct lseek_args /* {
1390 		int fd;
1391 		int pad;
1392 		off_t offset;
1393 		int whence;
1394 	} */ nuap;
1395 	int error;
1396 
1397 	nuap.fd = uap->fd;
1398 	nuap.offset = uap->offset;
1399 	nuap.whence = uap->whence;
1400 	error = lseek(td, &nuap);
1401 	return (error);
1402 }
1403 #endif /* COMPAT_43 */
1404 
1405 /*
1406  * Check access permissions using passed credentials.
1407  */
1408 static int
1409 vn_access(vp, user_flags, cred, td)
1410 	struct vnode	*vp;
1411 	int		user_flags;
1412 	struct ucred	*cred;
1413 	struct thread	*td;
1414 {
1415 	int error, flags;
1416 
1417 	/* Flags == 0 means only check for existence. */
1418 	error = 0;
1419 	if (user_flags) {
1420 		flags = 0;
1421 		if (user_flags & R_OK)
1422 			flags |= VREAD;
1423 		if (user_flags & W_OK)
1424 			flags |= VWRITE;
1425 		if (user_flags & X_OK)
1426 			flags |= VEXEC;
1427 #ifdef MAC
1428 		error = mac_check_vnode_access(cred, vp, flags);
1429 		if (error)
1430 			return (error);
1431 #endif
1432 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1433 			error = VOP_ACCESS(vp, flags, cred, td);
1434 	}
1435 	return (error);
1436 }
1437 
1438 /*
1439  * Check access permissions using "real" credentials.
1440  */
1441 #ifndef _SYS_SYSPROTO_H_
1442 struct access_args {
1443 	char	*path;
1444 	int	flags;
1445 };
1446 #endif
1447 int
1448 access(td, uap)
1449 	struct thread *td;
1450 	register struct access_args /* {
1451 		char *path;
1452 		int flags;
1453 	} */ *uap;
1454 {
1455 
1456 	return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags));
1457 }
1458 
1459 int
1460 kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags)
1461 {
1462 	struct ucred *cred, *tmpcred;
1463 	register struct vnode *vp;
1464 	int error;
1465 	struct nameidata nd;
1466 
1467 	/*
1468 	 * Create and modify a temporary credential instead of one that
1469 	 * is potentially shared.  This could also mess up socket
1470 	 * buffer accounting which can run in an interrupt context.
1471 	 *
1472 	 * XXX - Depending on how "threads" are finally implemented, it
1473 	 * may be better to explicitly pass the credential to namei()
1474 	 * rather than to modify the potentially shared process structure.
1475 	 */
1476 	cred = td->td_ucred;
1477 	tmpcred = crdup(cred);
1478 	tmpcred->cr_uid = cred->cr_ruid;
1479 	tmpcred->cr_groups[0] = cred->cr_rgid;
1480 	td->td_ucred = tmpcred;
1481 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td);
1482 	if ((error = namei(&nd)) != 0)
1483 		goto out1;
1484 	vp = nd.ni_vp;
1485 
1486 	error = vn_access(vp, flags, tmpcred, td);
1487 	NDFREE(&nd, NDF_ONLY_PNBUF);
1488 	vput(vp);
1489 out1:
1490 	td->td_ucred = cred;
1491 	crfree(tmpcred);
1492 	return (error);
1493 }
1494 
1495 /*
1496  * Check access permissions using "effective" credentials.
1497  */
1498 #ifndef _SYS_SYSPROTO_H_
1499 struct eaccess_args {
1500 	char	*path;
1501 	int	flags;
1502 };
1503 #endif
1504 int
1505 eaccess(td, uap)
1506 	struct thread *td;
1507 	register struct eaccess_args /* {
1508 		char *path;
1509 		int flags;
1510 	} */ *uap;
1511 {
1512 	struct nameidata nd;
1513 	struct vnode *vp;
1514 	int error;
1515 
1516 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1517 	    uap->path, td);
1518 	if ((error = namei(&nd)) != 0)
1519 		return (error);
1520 	vp = nd.ni_vp;
1521 
1522 	error = vn_access(vp, uap->flags, td->td_ucred, td);
1523 	NDFREE(&nd, NDF_ONLY_PNBUF);
1524 	vput(vp);
1525 	return (error);
1526 }
1527 
1528 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1529 /*
1530  * Get file status; this version follows links.
1531  */
1532 #ifndef _SYS_SYSPROTO_H_
1533 struct ostat_args {
1534 	char	*path;
1535 	struct ostat *ub;
1536 };
1537 #endif
1538 /* ARGSUSED */
1539 int
1540 ostat(td, uap)
1541 	struct thread *td;
1542 	register struct ostat_args /* {
1543 		char *path;
1544 		struct ostat *ub;
1545 	} */ *uap;
1546 {
1547 	struct stat sb;
1548 	struct ostat osb;
1549 	int error;
1550 	struct nameidata nd;
1551 
1552 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1553 	    uap->path, td);
1554 	if ((error = namei(&nd)) != 0)
1555 		return (error);
1556 	NDFREE(&nd, NDF_ONLY_PNBUF);
1557 	error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
1558 	vput(nd.ni_vp);
1559 	if (error)
1560 		return (error);
1561 	cvtstat(&sb, &osb);
1562 	error = copyout(&osb, uap->ub, sizeof (osb));
1563 	return (error);
1564 }
1565 
1566 /*
1567  * Get file status; this version does not follow links.
1568  */
1569 #ifndef _SYS_SYSPROTO_H_
1570 struct olstat_args {
1571 	char	*path;
1572 	struct ostat *ub;
1573 };
1574 #endif
1575 /* ARGSUSED */
1576 int
1577 olstat(td, uap)
1578 	struct thread *td;
1579 	register struct olstat_args /* {
1580 		char *path;
1581 		struct ostat *ub;
1582 	} */ *uap;
1583 {
1584 	struct vnode *vp;
1585 	struct stat sb;
1586 	struct ostat osb;
1587 	int error;
1588 	struct nameidata nd;
1589 
1590 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1591 	    uap->path, td);
1592 	if ((error = namei(&nd)) != 0)
1593 		return (error);
1594 	vp = nd.ni_vp;
1595 	error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
1596 	NDFREE(&nd, NDF_ONLY_PNBUF);
1597 	vput(vp);
1598 	if (error)
1599 		return (error);
1600 	cvtstat(&sb, &osb);
1601 	error = copyout(&osb, uap->ub, sizeof (osb));
1602 	return (error);
1603 }
1604 
1605 /*
1606  * Convert from an old to a new stat structure.
1607  */
1608 void
1609 cvtstat(st, ost)
1610 	struct stat *st;
1611 	struct ostat *ost;
1612 {
1613 
1614 	ost->st_dev = st->st_dev;
1615 	ost->st_ino = st->st_ino;
1616 	ost->st_mode = st->st_mode;
1617 	ost->st_nlink = st->st_nlink;
1618 	ost->st_uid = st->st_uid;
1619 	ost->st_gid = st->st_gid;
1620 	ost->st_rdev = st->st_rdev;
1621 	if (st->st_size < (quad_t)1 << 32)
1622 		ost->st_size = st->st_size;
1623 	else
1624 		ost->st_size = -2;
1625 	ost->st_atime = st->st_atime;
1626 	ost->st_mtime = st->st_mtime;
1627 	ost->st_ctime = st->st_ctime;
1628 	ost->st_blksize = st->st_blksize;
1629 	ost->st_blocks = st->st_blocks;
1630 	ost->st_flags = st->st_flags;
1631 	ost->st_gen = st->st_gen;
1632 }
1633 #endif /* COMPAT_43 || COMPAT_SUNOS */
1634 
1635 /*
1636  * Get file status; this version follows links.
1637  */
1638 #ifndef _SYS_SYSPROTO_H_
1639 struct stat_args {
1640 	char	*path;
1641 	struct stat *ub;
1642 };
1643 #endif
1644 /* ARGSUSED */
1645 int
1646 stat(td, uap)
1647 	struct thread *td;
1648 	register struct stat_args /* {
1649 		char *path;
1650 		struct stat *ub;
1651 	} */ *uap;
1652 {
1653 	struct stat sb;
1654 	int error;
1655 	struct nameidata nd;
1656 
1657 #ifdef LOOKUP_SHARED
1658 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ,
1659 	    UIO_USERSPACE, uap->path, td);
1660 #else
1661 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1662 	    uap->path, td);
1663 #endif
1664 	if ((error = namei(&nd)) != 0)
1665 		return (error);
1666 	error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
1667 	NDFREE(&nd, NDF_ONLY_PNBUF);
1668 	vput(nd.ni_vp);
1669 	if (error)
1670 		return (error);
1671 	error = copyout(&sb, uap->ub, sizeof (sb));
1672 	return (error);
1673 }
1674 
1675 /*
1676  * Get file status; this version does not follow links.
1677  */
1678 #ifndef _SYS_SYSPROTO_H_
1679 struct lstat_args {
1680 	char	*path;
1681 	struct stat *ub;
1682 };
1683 #endif
1684 /* ARGSUSED */
1685 int
1686 lstat(td, uap)
1687 	struct thread *td;
1688 	register struct lstat_args /* {
1689 		char *path;
1690 		struct stat *ub;
1691 	} */ *uap;
1692 {
1693 	int error;
1694 	struct vnode *vp;
1695 	struct stat sb;
1696 	struct nameidata nd;
1697 
1698 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1699 	    uap->path, td);
1700 	if ((error = namei(&nd)) != 0)
1701 		return (error);
1702 	vp = nd.ni_vp;
1703 	error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
1704 	NDFREE(&nd, NDF_ONLY_PNBUF);
1705 	vput(vp);
1706 	if (error)
1707 		return (error);
1708 	error = copyout(&sb, uap->ub, sizeof (sb));
1709 	return (error);
1710 }
1711 
1712 /*
1713  * Implementation of the NetBSD stat() function.
1714  * XXX This should probably be collapsed with the FreeBSD version,
1715  * as the differences are only due to vn_stat() clearing spares at
1716  * the end of the structures.  vn_stat could be split to avoid this,
1717  * and thus collapse the following to close to zero code.
1718  */
1719 void
1720 cvtnstat(sb, nsb)
1721 	struct stat *sb;
1722 	struct nstat *nsb;
1723 {
1724 	bzero(nsb, sizeof *nsb);
1725 	nsb->st_dev = sb->st_dev;
1726 	nsb->st_ino = sb->st_ino;
1727 	nsb->st_mode = sb->st_mode;
1728 	nsb->st_nlink = sb->st_nlink;
1729 	nsb->st_uid = sb->st_uid;
1730 	nsb->st_gid = sb->st_gid;
1731 	nsb->st_rdev = sb->st_rdev;
1732 	nsb->st_atimespec = sb->st_atimespec;
1733 	nsb->st_mtimespec = sb->st_mtimespec;
1734 	nsb->st_ctimespec = sb->st_ctimespec;
1735 	nsb->st_size = sb->st_size;
1736 	nsb->st_blocks = sb->st_blocks;
1737 	nsb->st_blksize = sb->st_blksize;
1738 	nsb->st_flags = sb->st_flags;
1739 	nsb->st_gen = sb->st_gen;
1740 	nsb->st_birthtimespec = sb->st_birthtimespec;
1741 }
1742 
1743 #ifndef _SYS_SYSPROTO_H_
1744 struct nstat_args {
1745 	char	*path;
1746 	struct nstat *ub;
1747 };
1748 #endif
1749 /* ARGSUSED */
1750 int
1751 nstat(td, uap)
1752 	struct thread *td;
1753 	register struct nstat_args /* {
1754 		char *path;
1755 		struct nstat *ub;
1756 	} */ *uap;
1757 {
1758 	struct stat sb;
1759 	struct nstat nsb;
1760 	int error;
1761 	struct nameidata nd;
1762 
1763 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1764 	    uap->path, td);
1765 	if ((error = namei(&nd)) != 0)
1766 		return (error);
1767 	NDFREE(&nd, NDF_ONLY_PNBUF);
1768 	error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
1769 	vput(nd.ni_vp);
1770 	if (error)
1771 		return (error);
1772 	cvtnstat(&sb, &nsb);
1773 	error = copyout(&nsb, uap->ub, sizeof (nsb));
1774 	return (error);
1775 }
1776 
1777 /*
1778  * NetBSD lstat.  Get file status; this version does not follow links.
1779  */
1780 #ifndef _SYS_SYSPROTO_H_
1781 struct lstat_args {
1782 	char	*path;
1783 	struct stat *ub;
1784 };
1785 #endif
1786 /* ARGSUSED */
1787 int
1788 nlstat(td, uap)
1789 	struct thread *td;
1790 	register struct nlstat_args /* {
1791 		char *path;
1792 		struct nstat *ub;
1793 	} */ *uap;
1794 {
1795 	int error;
1796 	struct vnode *vp;
1797 	struct stat sb;
1798 	struct nstat nsb;
1799 	struct nameidata nd;
1800 
1801 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1802 	    uap->path, td);
1803 	if ((error = namei(&nd)) != 0)
1804 		return (error);
1805 	vp = nd.ni_vp;
1806 	NDFREE(&nd, NDF_ONLY_PNBUF);
1807 	error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
1808 	vput(vp);
1809 	if (error)
1810 		return (error);
1811 	cvtnstat(&sb, &nsb);
1812 	error = copyout(&nsb, uap->ub, sizeof (nsb));
1813 	return (error);
1814 }
1815 
1816 /*
1817  * Get configurable pathname variables.
1818  */
1819 #ifndef _SYS_SYSPROTO_H_
1820 struct pathconf_args {
1821 	char	*path;
1822 	int	name;
1823 };
1824 #endif
1825 /* ARGSUSED */
1826 int
1827 pathconf(td, uap)
1828 	struct thread *td;
1829 	register struct pathconf_args /* {
1830 		char *path;
1831 		int name;
1832 	} */ *uap;
1833 {
1834 	int error;
1835 	struct nameidata nd;
1836 
1837 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1838 	    uap->path, td);
1839 	if ((error = namei(&nd)) != 0)
1840 		return (error);
1841 	NDFREE(&nd, NDF_ONLY_PNBUF);
1842 
1843 	/* If asynchronous I/O is available, it works for all files. */
1844 	if (uap->name == _PC_ASYNC_IO)
1845 		td->td_retval[0] = async_io_version;
1846 	else
1847 		error = VOP_PATHCONF(nd.ni_vp, uap->name, td->td_retval);
1848 	vput(nd.ni_vp);
1849 	return (error);
1850 }
1851 
1852 /*
1853  * Return target name of a symbolic link.
1854  */
1855 #ifndef _SYS_SYSPROTO_H_
1856 struct readlink_args {
1857 	char	*path;
1858 	char	*buf;
1859 	int	count;
1860 };
1861 #endif
1862 /* ARGSUSED */
1863 int
1864 readlink(td, uap)
1865 	struct thread *td;
1866 	register struct readlink_args /* {
1867 		char *path;
1868 		char *buf;
1869 		int count;
1870 	} */ *uap;
1871 {
1872 
1873 	return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf,
1874 	    UIO_USERSPACE, uap->count));
1875 }
1876 
1877 int
1878 kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf,
1879     enum uio_seg bufseg, int count)
1880 {
1881 	register struct vnode *vp;
1882 	struct iovec aiov;
1883 	struct uio auio;
1884 	int error;
1885 	struct nameidata nd;
1886 
1887 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, pathseg, path, td);
1888 	if ((error = namei(&nd)) != 0)
1889 		return (error);
1890 	NDFREE(&nd, NDF_ONLY_PNBUF);
1891 	vp = nd.ni_vp;
1892 #ifdef MAC
1893 	error = mac_check_vnode_readlink(td->td_ucred, vp);
1894 	if (error) {
1895 		vput(vp);
1896 		return (error);
1897 	}
1898 #endif
1899 	if (vp->v_type != VLNK)
1900 		error = EINVAL;
1901 	else {
1902 		aiov.iov_base = buf;
1903 		aiov.iov_len = count;
1904 		auio.uio_iov = &aiov;
1905 		auio.uio_iovcnt = 1;
1906 		auio.uio_offset = 0;
1907 		auio.uio_rw = UIO_READ;
1908 		auio.uio_segflg = bufseg;
1909 		auio.uio_td = td;
1910 		auio.uio_resid = count;
1911 		error = VOP_READLINK(vp, &auio, td->td_ucred);
1912 	}
1913 	vput(vp);
1914 	td->td_retval[0] = count - auio.uio_resid;
1915 	return (error);
1916 }
1917 
1918 /*
1919  * Common implementation code for chflags() and fchflags().
1920  */
1921 static int
1922 setfflags(td, vp, flags)
1923 	struct thread *td;
1924 	struct vnode *vp;
1925 	int flags;
1926 {
1927 	int error;
1928 	struct mount *mp;
1929 	struct vattr vattr;
1930 
1931 	/*
1932 	 * Prevent non-root users from setting flags on devices.  When
1933 	 * a device is reused, users can retain ownership of the device
1934 	 * if they are allowed to set flags and programs assume that
1935 	 * chown can't fail when done as root.
1936 	 */
1937 	if (vp->v_type == VCHR || vp->v_type == VBLK) {
1938 		error = suser_cred(td->td_ucred, PRISON_ROOT);
1939 		if (error)
1940 			return (error);
1941 	}
1942 
1943 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1944 		return (error);
1945 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1946 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1947 #ifdef MAC
1948 	error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags);
1949 	if (error == 0) {
1950 #endif
1951 		VATTR_NULL(&vattr);
1952 		vattr.va_flags = flags;
1953 		error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
1954 #ifdef MAC
1955 	}
1956 #endif
1957 	VOP_UNLOCK(vp, 0, td);
1958 	vn_finished_write(mp);
1959 	return (error);
1960 }
1961 
1962 /*
1963  * Change flags of a file given a path name.
1964  */
1965 #ifndef _SYS_SYSPROTO_H_
1966 struct chflags_args {
1967 	char	*path;
1968 	int	flags;
1969 };
1970 #endif
1971 /* ARGSUSED */
1972 int
1973 chflags(td, uap)
1974 	struct thread *td;
1975 	register struct chflags_args /* {
1976 		char *path;
1977 		int flags;
1978 	} */ *uap;
1979 {
1980 	int error;
1981 	struct nameidata nd;
1982 
1983 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
1984 	if ((error = namei(&nd)) != 0)
1985 		return (error);
1986 	NDFREE(&nd, NDF_ONLY_PNBUF);
1987 	error = setfflags(td, nd.ni_vp, uap->flags);
1988 	vrele(nd.ni_vp);
1989 	return error;
1990 }
1991 
1992 /*
1993  * Same as chflags() but doesn't follow symlinks.
1994  */
1995 int
1996 lchflags(td, uap)
1997 	struct thread *td;
1998 	register struct lchflags_args /* {
1999 		char *path;
2000 		int flags;
2001 	} */ *uap;
2002 {
2003 	int error;
2004 	struct nameidata nd;
2005 
2006 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
2007 	if ((error = namei(&nd)) != 0)
2008 		return (error);
2009 	NDFREE(&nd, NDF_ONLY_PNBUF);
2010 	error = setfflags(td, nd.ni_vp, uap->flags);
2011 	vrele(nd.ni_vp);
2012 	return error;
2013 }
2014 
2015 /*
2016  * Change flags of a file given a file descriptor.
2017  */
2018 #ifndef _SYS_SYSPROTO_H_
2019 struct fchflags_args {
2020 	int	fd;
2021 	int	flags;
2022 };
2023 #endif
2024 /* ARGSUSED */
2025 int
2026 fchflags(td, uap)
2027 	struct thread *td;
2028 	register struct fchflags_args /* {
2029 		int fd;
2030 		int flags;
2031 	} */ *uap;
2032 {
2033 	struct file *fp;
2034 	int error;
2035 
2036 	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2037 		return (error);
2038 	error = setfflags(td, fp->f_data, uap->flags);
2039 	fdrop(fp, td);
2040 	return (error);
2041 }
2042 
2043 /*
2044  * Common implementation code for chmod(), lchmod() and fchmod().
2045  */
2046 static int
2047 setfmode(td, vp, mode)
2048 	struct thread *td;
2049 	struct vnode *vp;
2050 	int mode;
2051 {
2052 	int error;
2053 	struct mount *mp;
2054 	struct vattr vattr;
2055 
2056 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2057 		return (error);
2058 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2059 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2060 	VATTR_NULL(&vattr);
2061 	vattr.va_mode = mode & ALLPERMS;
2062 #ifdef MAC
2063 	error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode);
2064 	if (error == 0)
2065 #endif
2066 		error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2067 	VOP_UNLOCK(vp, 0, td);
2068 	vn_finished_write(mp);
2069 	return error;
2070 }
2071 
2072 /*
2073  * Change mode of a file given path name.
2074  */
2075 #ifndef _SYS_SYSPROTO_H_
2076 struct chmod_args {
2077 	char	*path;
2078 	int	mode;
2079 };
2080 #endif
2081 /* ARGSUSED */
2082 int
2083 chmod(td, uap)
2084 	struct thread *td;
2085 	register struct chmod_args /* {
2086 		char *path;
2087 		int mode;
2088 	} */ *uap;
2089 {
2090 
2091 	return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode));
2092 }
2093 
2094 int
2095 kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode)
2096 {
2097 	int error;
2098 	struct nameidata nd;
2099 
2100 	NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
2101 	if ((error = namei(&nd)) != 0)
2102 		return (error);
2103 	NDFREE(&nd, NDF_ONLY_PNBUF);
2104 	error = setfmode(td, nd.ni_vp, mode);
2105 	vrele(nd.ni_vp);
2106 	return error;
2107 }
2108 
2109 /*
2110  * Change mode of a file given path name (don't follow links.)
2111  */
2112 #ifndef _SYS_SYSPROTO_H_
2113 struct lchmod_args {
2114 	char	*path;
2115 	int	mode;
2116 };
2117 #endif
2118 /* ARGSUSED */
2119 int
2120 lchmod(td, uap)
2121 	struct thread *td;
2122 	register struct lchmod_args /* {
2123 		char *path;
2124 		int mode;
2125 	} */ *uap;
2126 {
2127 	int error;
2128 	struct nameidata nd;
2129 
2130 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
2131 	if ((error = namei(&nd)) != 0)
2132 		return (error);
2133 	NDFREE(&nd, NDF_ONLY_PNBUF);
2134 	error = setfmode(td, nd.ni_vp, uap->mode);
2135 	vrele(nd.ni_vp);
2136 	return error;
2137 }
2138 
2139 /*
2140  * Change mode of a file given a file descriptor.
2141  */
2142 #ifndef _SYS_SYSPROTO_H_
2143 struct fchmod_args {
2144 	int	fd;
2145 	int	mode;
2146 };
2147 #endif
2148 /* ARGSUSED */
2149 int
2150 fchmod(td, uap)
2151 	struct thread *td;
2152 	register struct fchmod_args /* {
2153 		int fd;
2154 		int mode;
2155 	} */ *uap;
2156 {
2157 	struct file *fp;
2158 	struct vnode *vp;
2159 	int error;
2160 
2161 	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2162 		return (error);
2163 	vp = fp->f_data;
2164 	error = setfmode(td, fp->f_data, uap->mode);
2165 	fdrop(fp, td);
2166 	return (error);
2167 }
2168 
2169 /*
2170  * Common implementation for chown(), lchown(), and fchown()
2171  */
2172 static int
2173 setfown(td, vp, uid, gid)
2174 	struct thread *td;
2175 	struct vnode *vp;
2176 	uid_t uid;
2177 	gid_t gid;
2178 {
2179 	int error;
2180 	struct mount *mp;
2181 	struct vattr vattr;
2182 
2183 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2184 		return (error);
2185 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2186 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2187 	VATTR_NULL(&vattr);
2188 	vattr.va_uid = uid;
2189 	vattr.va_gid = gid;
2190 #ifdef MAC
2191 	error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid,
2192 	    vattr.va_gid);
2193 	if (error == 0)
2194 #endif
2195 		error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2196 	VOP_UNLOCK(vp, 0, td);
2197 	vn_finished_write(mp);
2198 	return error;
2199 }
2200 
2201 /*
2202  * Set ownership given a path name.
2203  */
2204 #ifndef _SYS_SYSPROTO_H_
2205 struct chown_args {
2206 	char	*path;
2207 	int	uid;
2208 	int	gid;
2209 };
2210 #endif
2211 /* ARGSUSED */
2212 int
2213 chown(td, uap)
2214 	struct thread *td;
2215 	register struct chown_args /* {
2216 		char *path;
2217 		int uid;
2218 		int gid;
2219 	} */ *uap;
2220 {
2221 
2222 	return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2223 }
2224 
2225 int
2226 kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2227     int gid)
2228 {
2229 	int error;
2230 	struct nameidata nd;
2231 
2232 	NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
2233 	if ((error = namei(&nd)) != 0)
2234 		return (error);
2235 	NDFREE(&nd, NDF_ONLY_PNBUF);
2236 	error = setfown(td, nd.ni_vp, uid, gid);
2237 	vrele(nd.ni_vp);
2238 	return (error);
2239 }
2240 
2241 /*
2242  * Set ownership given a path name, do not cross symlinks.
2243  */
2244 #ifndef _SYS_SYSPROTO_H_
2245 struct lchown_args {
2246 	char	*path;
2247 	int	uid;
2248 	int	gid;
2249 };
2250 #endif
2251 /* ARGSUSED */
2252 int
2253 lchown(td, uap)
2254 	struct thread *td;
2255 	register struct lchown_args /* {
2256 		char *path;
2257 		int uid;
2258 		int gid;
2259 	} */ *uap;
2260 {
2261 
2262 	return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2263 }
2264 
2265 int
2266 kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2267     int gid)
2268 {
2269 	int error;
2270 	struct nameidata nd;
2271 
2272 	NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td);
2273 	if ((error = namei(&nd)) != 0)
2274 		return (error);
2275 	NDFREE(&nd, NDF_ONLY_PNBUF);
2276 	error = setfown(td, nd.ni_vp, uid, gid);
2277 	vrele(nd.ni_vp);
2278 	return (error);
2279 }
2280 
2281 /*
2282  * Set ownership given a file descriptor.
2283  */
2284 #ifndef _SYS_SYSPROTO_H_
2285 struct fchown_args {
2286 	int	fd;
2287 	int	uid;
2288 	int	gid;
2289 };
2290 #endif
2291 /* ARGSUSED */
2292 int
2293 fchown(td, uap)
2294 	struct thread *td;
2295 	register struct fchown_args /* {
2296 		int fd;
2297 		int uid;
2298 		int gid;
2299 	} */ *uap;
2300 {
2301 	struct file *fp;
2302 	struct vnode *vp;
2303 	int error;
2304 
2305 	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2306 		return (error);
2307 	vp = fp->f_data;
2308 	error = setfown(td, fp->f_data, uap->uid, uap->gid);
2309 	fdrop(fp, td);
2310 	return (error);
2311 }
2312 
2313 /*
2314  * Common implementation code for utimes(), lutimes(), and futimes().
2315  */
2316 static int
2317 getutimes(usrtvp, tvpseg, tsp)
2318 	const struct timeval *usrtvp;
2319 	enum uio_seg tvpseg;
2320 	struct timespec *tsp;
2321 {
2322 	struct timeval tv[2];
2323 	const struct timeval *tvp;
2324 	int error;
2325 
2326 	if (usrtvp == NULL) {
2327 		microtime(&tv[0]);
2328 		TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2329 		tsp[1] = tsp[0];
2330 	} else {
2331 		if (tvpseg == UIO_SYSSPACE) {
2332 			tvp = usrtvp;
2333 		} else {
2334 			if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0)
2335 				return (error);
2336 			tvp = tv;
2337 		}
2338 
2339 		TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
2340 		TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
2341 	}
2342 	return 0;
2343 }
2344 
2345 /*
2346  * Common implementation code for utimes(), lutimes(), and futimes().
2347  */
2348 static int
2349 setutimes(td, vp, ts, numtimes, nullflag)
2350 	struct thread *td;
2351 	struct vnode *vp;
2352 	const struct timespec *ts;
2353 	int numtimes;
2354 	int nullflag;
2355 {
2356 	int error, setbirthtime;
2357 	struct mount *mp;
2358 	struct vattr vattr;
2359 
2360 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2361 		return (error);
2362 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2363 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2364 	setbirthtime = 0;
2365 	if (numtimes < 3 && VOP_GETATTR(vp, &vattr, td->td_ucred, td) == 0 &&
2366 	    timespeccmp(&ts[1], &vattr.va_birthtime, < ))
2367 		setbirthtime = 1;
2368 	VATTR_NULL(&vattr);
2369 	vattr.va_atime = ts[0];
2370 	vattr.va_mtime = ts[1];
2371 	if (setbirthtime)
2372 		vattr.va_birthtime = ts[1];
2373 	if (numtimes > 2)
2374 		vattr.va_birthtime = ts[2];
2375 	if (nullflag)
2376 		vattr.va_vaflags |= VA_UTIMES_NULL;
2377 #ifdef MAC
2378 	error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime,
2379 	    vattr.va_mtime);
2380 #endif
2381 	if (error == 0)
2382 		error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2383 	VOP_UNLOCK(vp, 0, td);
2384 	vn_finished_write(mp);
2385 	return error;
2386 }
2387 
2388 /*
2389  * Set the access and modification times of a file.
2390  */
2391 #ifndef _SYS_SYSPROTO_H_
2392 struct utimes_args {
2393 	char	*path;
2394 	struct	timeval *tptr;
2395 };
2396 #endif
2397 /* ARGSUSED */
2398 int
2399 utimes(td, uap)
2400 	struct thread *td;
2401 	register struct utimes_args /* {
2402 		char *path;
2403 		struct timeval *tptr;
2404 	} */ *uap;
2405 {
2406 
2407 	return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2408 	    UIO_USERSPACE));
2409 }
2410 
2411 int
2412 kern_utimes(struct thread *td, char *path, enum uio_seg pathseg,
2413     struct timeval *tptr, enum uio_seg tptrseg)
2414 {
2415 	struct timespec ts[2];
2416 	int error;
2417 	struct nameidata nd;
2418 
2419 	if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2420 		return (error);
2421 	NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
2422 	if ((error = namei(&nd)) != 0)
2423 		return (error);
2424 	NDFREE(&nd, NDF_ONLY_PNBUF);
2425 	error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2426 	vrele(nd.ni_vp);
2427 	return (error);
2428 }
2429 
2430 /*
2431  * Set the access and modification times of a file.
2432  */
2433 #ifndef _SYS_SYSPROTO_H_
2434 struct lutimes_args {
2435 	char	*path;
2436 	struct	timeval *tptr;
2437 };
2438 #endif
2439 /* ARGSUSED */
2440 int
2441 lutimes(td, uap)
2442 	struct thread *td;
2443 	register struct lutimes_args /* {
2444 		char *path;
2445 		struct timeval *tptr;
2446 	} */ *uap;
2447 {
2448 
2449 	return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2450 	    UIO_USERSPACE));
2451 }
2452 
2453 int
2454 kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg,
2455     struct timeval *tptr, enum uio_seg tptrseg)
2456 {
2457 	struct timespec ts[2];
2458 	int error;
2459 	struct nameidata nd;
2460 
2461 	if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2462 		return (error);
2463 	NDINIT(&nd, LOOKUP, NOFOLLOW, pathseg, path, td);
2464 	if ((error = namei(&nd)) != 0)
2465 		return (error);
2466 	NDFREE(&nd, NDF_ONLY_PNBUF);
2467 	error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2468 	vrele(nd.ni_vp);
2469 	return (error);
2470 }
2471 
2472 /*
2473  * Set the access and modification times of a file.
2474  */
2475 #ifndef _SYS_SYSPROTO_H_
2476 struct futimes_args {
2477 	int	fd;
2478 	struct	timeval *tptr;
2479 };
2480 #endif
2481 /* ARGSUSED */
2482 int
2483 futimes(td, uap)
2484 	struct thread *td;
2485 	register struct futimes_args /* {
2486 		int  fd;
2487 		struct timeval *tptr;
2488 	} */ *uap;
2489 {
2490 
2491 	return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE));
2492 }
2493 
2494 int
2495 kern_futimes(struct thread *td, int fd, struct timeval *tptr,
2496     enum uio_seg tptrseg)
2497 {
2498 	struct timespec ts[2];
2499 	struct file *fp;
2500 	int error;
2501 
2502 	if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2503 		return (error);
2504 	if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
2505 		return (error);
2506 	error = setutimes(td, fp->f_data, ts, 2, tptr == NULL);
2507 	fdrop(fp, td);
2508 	return (error);
2509 }
2510 
2511 /*
2512  * Truncate a file given its path name.
2513  */
2514 #ifndef _SYS_SYSPROTO_H_
2515 struct truncate_args {
2516 	char	*path;
2517 	int	pad;
2518 	off_t	length;
2519 };
2520 #endif
2521 /* ARGSUSED */
2522 int
2523 truncate(td, uap)
2524 	struct thread *td;
2525 	register struct truncate_args /* {
2526 		char *path;
2527 		int pad;
2528 		off_t length;
2529 	} */ *uap;
2530 {
2531 
2532 	return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
2533 }
2534 
2535 int
2536 kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length)
2537 {
2538 	struct mount *mp;
2539 	struct vnode *vp;
2540 	struct vattr vattr;
2541 	int error;
2542 	struct nameidata nd;
2543 
2544 	if (length < 0)
2545 		return(EINVAL);
2546 	NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
2547 	if ((error = namei(&nd)) != 0)
2548 		return (error);
2549 	vp = nd.ni_vp;
2550 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2551 		vrele(vp);
2552 		return (error);
2553 	}
2554 	NDFREE(&nd, NDF_ONLY_PNBUF);
2555 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2556 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2557 	if (vp->v_type == VDIR)
2558 		error = EISDIR;
2559 #ifdef MAC
2560 	else if ((error = mac_check_vnode_write(td->td_ucred, NOCRED, vp))) {
2561 	}
2562 #endif
2563 	else if ((error = vn_writechk(vp)) == 0 &&
2564 	    (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
2565 		VATTR_NULL(&vattr);
2566 		vattr.va_size = length;
2567 		error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2568 	}
2569 	vput(vp);
2570 	vn_finished_write(mp);
2571 	return (error);
2572 }
2573 
2574 /*
2575  * Truncate a file given a file descriptor.
2576  */
2577 #ifndef _SYS_SYSPROTO_H_
2578 struct ftruncate_args {
2579 	int	fd;
2580 	int	pad;
2581 	off_t	length;
2582 };
2583 #endif
2584 /* ARGSUSED */
2585 int
2586 ftruncate(td, uap)
2587 	struct thread *td;
2588 	register struct ftruncate_args /* {
2589 		int fd;
2590 		int pad;
2591 		off_t length;
2592 	} */ *uap;
2593 {
2594 	struct mount *mp;
2595 	struct vattr vattr;
2596 	struct vnode *vp;
2597 	struct file *fp;
2598 	int error;
2599 
2600 	if (uap->length < 0)
2601 		return(EINVAL);
2602 	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2603 		return (error);
2604 	if ((fp->f_flag & FWRITE) == 0) {
2605 		fdrop(fp, td);
2606 		return (EINVAL);
2607 	}
2608 	vp = fp->f_data;
2609 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2610 		fdrop(fp, td);
2611 		return (error);
2612 	}
2613 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2614 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2615 	if (vp->v_type == VDIR)
2616 		error = EISDIR;
2617 #ifdef MAC
2618 	else if ((error = mac_check_vnode_write(td->td_ucred, fp->f_cred,
2619 	    vp))) {
2620 	}
2621 #endif
2622 	else if ((error = vn_writechk(vp)) == 0) {
2623 		VATTR_NULL(&vattr);
2624 		vattr.va_size = uap->length;
2625 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
2626 	}
2627 	VOP_UNLOCK(vp, 0, td);
2628 	vn_finished_write(mp);
2629 	fdrop(fp, td);
2630 	return (error);
2631 }
2632 
2633 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2634 /*
2635  * Truncate a file given its path name.
2636  */
2637 #ifndef _SYS_SYSPROTO_H_
2638 struct otruncate_args {
2639 	char	*path;
2640 	long	length;
2641 };
2642 #endif
2643 /* ARGSUSED */
2644 int
2645 otruncate(td, uap)
2646 	struct thread *td;
2647 	register struct otruncate_args /* {
2648 		char *path;
2649 		long length;
2650 	} */ *uap;
2651 {
2652 	struct truncate_args /* {
2653 		char *path;
2654 		int pad;
2655 		off_t length;
2656 	} */ nuap;
2657 
2658 	nuap.path = uap->path;
2659 	nuap.length = uap->length;
2660 	return (truncate(td, &nuap));
2661 }
2662 
2663 /*
2664  * Truncate a file given a file descriptor.
2665  */
2666 #ifndef _SYS_SYSPROTO_H_
2667 struct oftruncate_args {
2668 	int	fd;
2669 	long	length;
2670 };
2671 #endif
2672 /* ARGSUSED */
2673 int
2674 oftruncate(td, uap)
2675 	struct thread *td;
2676 	register struct oftruncate_args /* {
2677 		int fd;
2678 		long length;
2679 	} */ *uap;
2680 {
2681 	struct ftruncate_args /* {
2682 		int fd;
2683 		int pad;
2684 		off_t length;
2685 	} */ nuap;
2686 
2687 	nuap.fd = uap->fd;
2688 	nuap.length = uap->length;
2689 	return (ftruncate(td, &nuap));
2690 }
2691 #endif /* COMPAT_43 || COMPAT_SUNOS */
2692 
2693 /*
2694  * Sync an open file.
2695  */
2696 #ifndef _SYS_SYSPROTO_H_
2697 struct fsync_args {
2698 	int	fd;
2699 };
2700 #endif
2701 /* ARGSUSED */
2702 int
2703 fsync(td, uap)
2704 	struct thread *td;
2705 	struct fsync_args /* {
2706 		int fd;
2707 	} */ *uap;
2708 {
2709 	struct vnode *vp;
2710 	struct mount *mp;
2711 	struct file *fp;
2712 	vm_object_t obj;
2713 	int error;
2714 
2715 	GIANT_REQUIRED;
2716 
2717 	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2718 		return (error);
2719 	vp = fp->f_data;
2720 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
2721 		fdrop(fp, td);
2722 		return (error);
2723 	}
2724 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2725 	if (VOP_GETVOBJECT(vp, &obj) == 0) {
2726 		vm_object_page_clean(obj, 0, 0, 0);
2727 	}
2728 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td);
2729 	if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)
2730 	    && softdep_fsync_hook != NULL)
2731 		error = (*softdep_fsync_hook)(vp);
2732 
2733 	VOP_UNLOCK(vp, 0, td);
2734 	vn_finished_write(mp);
2735 	fdrop(fp, td);
2736 	return (error);
2737 }
2738 
2739 /*
2740  * Rename files.  Source and destination must either both be directories,
2741  * or both not be directories.  If target is a directory, it must be empty.
2742  */
2743 #ifndef _SYS_SYSPROTO_H_
2744 struct rename_args {
2745 	char	*from;
2746 	char	*to;
2747 };
2748 #endif
2749 /* ARGSUSED */
2750 int
2751 rename(td, uap)
2752 	struct thread *td;
2753 	register struct rename_args /* {
2754 		char *from;
2755 		char *to;
2756 	} */ *uap;
2757 {
2758 
2759 	return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE));
2760 }
2761 
2762 int
2763 kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg)
2764 {
2765 	struct mount *mp = NULL;
2766 	struct vnode *tvp, *fvp, *tdvp;
2767 	struct nameidata fromnd, tond;
2768 	int error;
2769 
2770 	bwillwrite();
2771 #ifdef MAC
2772 	NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART, pathseg,
2773 	    from, td);
2774 #else
2775 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, pathseg, from, td);
2776 #endif
2777 	if ((error = namei(&fromnd)) != 0)
2778 		return (error);
2779 #ifdef MAC
2780 	error = mac_check_vnode_rename_from(td->td_ucred, fromnd.ni_dvp,
2781 	    fromnd.ni_vp, &fromnd.ni_cnd);
2782 	VOP_UNLOCK(fromnd.ni_dvp, 0, td);
2783 	VOP_UNLOCK(fromnd.ni_vp, 0, td);
2784 #endif
2785 	fvp = fromnd.ni_vp;
2786 	if (error == 0)
2787 		error = vn_start_write(fvp, &mp, V_WAIT | PCATCH);
2788 	if (error != 0) {
2789 		NDFREE(&fromnd, NDF_ONLY_PNBUF);
2790 		vrele(fromnd.ni_dvp);
2791 		vrele(fvp);
2792 		goto out1;
2793 	}
2794 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART |
2795 	    NOOBJ, pathseg, to, td);
2796 	if (fromnd.ni_vp->v_type == VDIR)
2797 		tond.ni_cnd.cn_flags |= WILLBEDIR;
2798 	if ((error = namei(&tond)) != 0) {
2799 		/* Translate error code for rename("dir1", "dir2/."). */
2800 		if (error == EISDIR && fvp->v_type == VDIR)
2801 			error = EINVAL;
2802 		NDFREE(&fromnd, NDF_ONLY_PNBUF);
2803 		vrele(fromnd.ni_dvp);
2804 		vrele(fvp);
2805 		goto out1;
2806 	}
2807 	tdvp = tond.ni_dvp;
2808 	tvp = tond.ni_vp;
2809 	if (tvp != NULL) {
2810 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2811 			error = ENOTDIR;
2812 			goto out;
2813 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2814 			error = EISDIR;
2815 			goto out;
2816 		}
2817 	}
2818 	if (fvp == tdvp)
2819 		error = EINVAL;
2820 	/*
2821 	 * If the source is the same as the destination (that is, if they
2822 	 * are links to the same vnode), then there is nothing to do.
2823 	 */
2824 	if (fvp == tvp)
2825 		error = -1;
2826 #ifdef MAC
2827 	else
2828 		error = mac_check_vnode_rename_to(td->td_ucred, tdvp,
2829 		    tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd);
2830 #endif
2831 out:
2832 	if (!error) {
2833 		VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
2834 		if (fromnd.ni_dvp != tdvp) {
2835 			VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
2836 		}
2837 		if (tvp) {
2838 			VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
2839 		}
2840 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2841 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2842 		NDFREE(&fromnd, NDF_ONLY_PNBUF);
2843 		NDFREE(&tond, NDF_ONLY_PNBUF);
2844 	} else {
2845 		NDFREE(&fromnd, NDF_ONLY_PNBUF);
2846 		NDFREE(&tond, NDF_ONLY_PNBUF);
2847 		if (tdvp == tvp)
2848 			vrele(tdvp);
2849 		else
2850 			vput(tdvp);
2851 		if (tvp)
2852 			vput(tvp);
2853 		vrele(fromnd.ni_dvp);
2854 		vrele(fvp);
2855 	}
2856 	vrele(tond.ni_startdir);
2857 	ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
2858 	ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
2859 	ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
2860 	ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
2861 out1:
2862 	vn_finished_write(mp);
2863 	if (fromnd.ni_startdir)
2864 		vrele(fromnd.ni_startdir);
2865 	if (error == -1)
2866 		return (0);
2867 	return (error);
2868 }
2869 
2870 /*
2871  * Make a directory file.
2872  */
2873 #ifndef _SYS_SYSPROTO_H_
2874 struct mkdir_args {
2875 	char	*path;
2876 	int	mode;
2877 };
2878 #endif
2879 /* ARGSUSED */
2880 int
2881 mkdir(td, uap)
2882 	struct thread *td;
2883 	register struct mkdir_args /* {
2884 		char *path;
2885 		int mode;
2886 	} */ *uap;
2887 {
2888 
2889 	return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode));
2890 }
2891 
2892 int
2893 kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode)
2894 {
2895 	struct mount *mp;
2896 	struct vnode *vp;
2897 	struct vattr vattr;
2898 	int error;
2899 	struct nameidata nd;
2900 
2901 restart:
2902 	bwillwrite();
2903 	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME, segflg, path, td);
2904 	nd.ni_cnd.cn_flags |= WILLBEDIR;
2905 	if ((error = namei(&nd)) != 0)
2906 		return (error);
2907 	vp = nd.ni_vp;
2908 	if (vp != NULL) {
2909 		NDFREE(&nd, NDF_ONLY_PNBUF);
2910 		vrele(vp);
2911 		/*
2912 		 * XXX namei called with LOCKPARENT but not LOCKLEAF has
2913 		 * the strange behaviour of leaving the vnode unlocked
2914 		 * if the target is the same vnode as the parent.
2915 		 */
2916 		if (vp == nd.ni_dvp)
2917 			vrele(nd.ni_dvp);
2918 		else
2919 			vput(nd.ni_dvp);
2920 		return (EEXIST);
2921 	}
2922 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
2923 		NDFREE(&nd, NDF_ONLY_PNBUF);
2924 		vput(nd.ni_dvp);
2925 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
2926 			return (error);
2927 		goto restart;
2928 	}
2929 	VATTR_NULL(&vattr);
2930 	vattr.va_type = VDIR;
2931 	FILEDESC_LOCK(td->td_proc->p_fd);
2932 	vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
2933 	FILEDESC_UNLOCK(td->td_proc->p_fd);
2934 #ifdef MAC
2935 	error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
2936 	    &vattr);
2937 	if (error)
2938 		goto out;
2939 #endif
2940 	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
2941 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2942 #ifdef MAC
2943 out:
2944 #endif
2945 	NDFREE(&nd, NDF_ONLY_PNBUF);
2946 	vput(nd.ni_dvp);
2947 	if (!error)
2948 		vput(nd.ni_vp);
2949 	vn_finished_write(mp);
2950 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
2951 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
2952 	return (error);
2953 }
2954 
2955 /*
2956  * Remove a directory file.
2957  */
2958 #ifndef _SYS_SYSPROTO_H_
2959 struct rmdir_args {
2960 	char	*path;
2961 };
2962 #endif
2963 /* ARGSUSED */
2964 int
2965 rmdir(td, uap)
2966 	struct thread *td;
2967 	struct rmdir_args /* {
2968 		char *path;
2969 	} */ *uap;
2970 {
2971 
2972 	return (kern_rmdir(td, uap->path, UIO_USERSPACE));
2973 }
2974 
2975 int
2976 kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg)
2977 {
2978 	struct mount *mp;
2979 	struct vnode *vp;
2980 	int error;
2981 	struct nameidata nd;
2982 
2983 restart:
2984 	bwillwrite();
2985 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, pathseg, path, td);
2986 	if ((error = namei(&nd)) != 0)
2987 		return (error);
2988 	vp = nd.ni_vp;
2989 	if (vp->v_type != VDIR) {
2990 		error = ENOTDIR;
2991 		goto out;
2992 	}
2993 	/*
2994 	 * No rmdir "." please.
2995 	 */
2996 	if (nd.ni_dvp == vp) {
2997 		error = EINVAL;
2998 		goto out;
2999 	}
3000 	/*
3001 	 * The root of a mounted filesystem cannot be deleted.
3002 	 */
3003 	if (vp->v_vflag & VV_ROOT) {
3004 		error = EBUSY;
3005 		goto out;
3006 	}
3007 #ifdef MAC
3008 	error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
3009 	    &nd.ni_cnd);
3010 	if (error)
3011 		goto out;
3012 #endif
3013 	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3014 		NDFREE(&nd, NDF_ONLY_PNBUF);
3015 		if (nd.ni_dvp == vp)
3016 			vrele(nd.ni_dvp);
3017 		else
3018 			vput(nd.ni_dvp);
3019 		vput(vp);
3020 		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3021 			return (error);
3022 		goto restart;
3023 	}
3024 	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3025 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3026 	error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3027 	vn_finished_write(mp);
3028 out:
3029 	NDFREE(&nd, NDF_ONLY_PNBUF);
3030 	if (nd.ni_dvp == vp)
3031 		vrele(nd.ni_dvp);
3032 	else
3033 		vput(nd.ni_dvp);
3034 	vput(vp);
3035 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
3036 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
3037 	return (error);
3038 }
3039 
3040 #ifdef COMPAT_43
3041 /*
3042  * Read a block of directory entries in a filesystem independent format.
3043  */
3044 #ifndef _SYS_SYSPROTO_H_
3045 struct ogetdirentries_args {
3046 	int	fd;
3047 	char	*buf;
3048 	u_int	count;
3049 	long	*basep;
3050 };
3051 #endif
3052 int
3053 ogetdirentries(td, uap)
3054 	struct thread *td;
3055 	register struct ogetdirentries_args /* {
3056 		int fd;
3057 		char *buf;
3058 		u_int count;
3059 		long *basep;
3060 	} */ *uap;
3061 {
3062 	struct vnode *vp;
3063 	struct file *fp;
3064 	struct uio auio, kuio;
3065 	struct iovec aiov, kiov;
3066 	struct dirent *dp, *edp;
3067 	caddr_t dirbuf;
3068 	int error, eofflag, readcnt;
3069 	long loff;
3070 
3071 	/* XXX arbitrary sanity limit on `count'. */
3072 	if (uap->count > 64 * 1024)
3073 		return (EINVAL);
3074 	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3075 		return (error);
3076 	if ((fp->f_flag & FREAD) == 0) {
3077 		fdrop(fp, td);
3078 		return (EBADF);
3079 	}
3080 	vp = fp->f_data;
3081 unionread:
3082 	if (vp->v_type != VDIR) {
3083 		fdrop(fp, td);
3084 		return (EINVAL);
3085 	}
3086 	aiov.iov_base = uap->buf;
3087 	aiov.iov_len = uap->count;
3088 	auio.uio_iov = &aiov;
3089 	auio.uio_iovcnt = 1;
3090 	auio.uio_rw = UIO_READ;
3091 	auio.uio_segflg = UIO_USERSPACE;
3092 	auio.uio_td = td;
3093 	auio.uio_resid = uap->count;
3094 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3095 	loff = auio.uio_offset = fp->f_offset;
3096 #ifdef MAC
3097 	error = mac_check_vnode_readdir(td->td_ucred, vp);
3098 	if (error) {
3099 		VOP_UNLOCK(vp, 0, td);
3100 		fdrop(fp, td);
3101 		return (error);
3102 	}
3103 #endif
3104 #	if (BYTE_ORDER != LITTLE_ENDIAN)
3105 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3106 			error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
3107 			    NULL, NULL);
3108 			fp->f_offset = auio.uio_offset;
3109 		} else
3110 #	endif
3111 	{
3112 		kuio = auio;
3113 		kuio.uio_iov = &kiov;
3114 		kuio.uio_segflg = UIO_SYSSPACE;
3115 		kiov.iov_len = uap->count;
3116 		MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, 0);
3117 		kiov.iov_base = dirbuf;
3118 		error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
3119 			    NULL, NULL);
3120 		fp->f_offset = kuio.uio_offset;
3121 		if (error == 0) {
3122 			readcnt = uap->count - kuio.uio_resid;
3123 			edp = (struct dirent *)&dirbuf[readcnt];
3124 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3125 #				if (BYTE_ORDER == LITTLE_ENDIAN)
3126 					/*
3127 					 * The expected low byte of
3128 					 * dp->d_namlen is our dp->d_type.
3129 					 * The high MBZ byte of dp->d_namlen
3130 					 * is our dp->d_namlen.
3131 					 */
3132 					dp->d_type = dp->d_namlen;
3133 					dp->d_namlen = 0;
3134 #				else
3135 					/*
3136 					 * The dp->d_type is the high byte
3137 					 * of the expected dp->d_namlen,
3138 					 * so must be zero'ed.
3139 					 */
3140 					dp->d_type = 0;
3141 #				endif
3142 				if (dp->d_reclen > 0) {
3143 					dp = (struct dirent *)
3144 					    ((char *)dp + dp->d_reclen);
3145 				} else {
3146 					error = EIO;
3147 					break;
3148 				}
3149 			}
3150 			if (dp >= edp)
3151 				error = uiomove(dirbuf, readcnt, &auio);
3152 		}
3153 		FREE(dirbuf, M_TEMP);
3154 	}
3155 	VOP_UNLOCK(vp, 0, td);
3156 	if (error) {
3157 		fdrop(fp, td);
3158 		return (error);
3159 	}
3160 	if (uap->count == auio.uio_resid) {
3161 		if (union_dircheckp) {
3162 			error = union_dircheckp(td, &vp, fp);
3163 			if (error == -1)
3164 				goto unionread;
3165 			if (error) {
3166 				fdrop(fp, td);
3167 				return (error);
3168 			}
3169 		}
3170 		/*
3171 		 * XXX We could delay dropping the lock above but
3172 		 * union_dircheckp complicates things.
3173 		 */
3174 		vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, td);
3175 		if ((vp->v_vflag & VV_ROOT) &&
3176 		    (vp->v_mount->mnt_flag & MNT_UNION)) {
3177 			struct vnode *tvp = vp;
3178 			vp = vp->v_mount->mnt_vnodecovered;
3179 			VREF(vp);
3180 			fp->f_data = vp;
3181 			fp->f_offset = 0;
3182 			vput(tvp);
3183 			goto unionread;
3184 		}
3185 		VOP_UNLOCK(vp, 0, td);
3186 	}
3187 	error = copyout(&loff, uap->basep, sizeof(long));
3188 	fdrop(fp, td);
3189 	td->td_retval[0] = uap->count - auio.uio_resid;
3190 	return (error);
3191 }
3192 #endif /* COMPAT_43 */
3193 
3194 /*
3195  * Read a block of directory entries in a filesystem independent format.
3196  */
3197 #ifndef _SYS_SYSPROTO_H_
3198 struct getdirentries_args {
3199 	int	fd;
3200 	char	*buf;
3201 	u_int	count;
3202 	long	*basep;
3203 };
3204 #endif
3205 int
3206 getdirentries(td, uap)
3207 	struct thread *td;
3208 	register struct getdirentries_args /* {
3209 		int fd;
3210 		char *buf;
3211 		u_int count;
3212 		long *basep;
3213 	} */ *uap;
3214 {
3215 	struct vnode *vp;
3216 	struct file *fp;
3217 	struct uio auio;
3218 	struct iovec aiov;
3219 	long loff;
3220 	int error, eofflag;
3221 
3222 	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3223 		return (error);
3224 	if ((fp->f_flag & FREAD) == 0) {
3225 		fdrop(fp, td);
3226 		return (EBADF);
3227 	}
3228 	vp = fp->f_data;
3229 unionread:
3230 	if (vp->v_type != VDIR) {
3231 		fdrop(fp, td);
3232 		return (EINVAL);
3233 	}
3234 	aiov.iov_base = uap->buf;
3235 	aiov.iov_len = uap->count;
3236 	auio.uio_iov = &aiov;
3237 	auio.uio_iovcnt = 1;
3238 	auio.uio_rw = UIO_READ;
3239 	auio.uio_segflg = UIO_USERSPACE;
3240 	auio.uio_td = td;
3241 	auio.uio_resid = uap->count;
3242 	/* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
3243 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3244 	loff = auio.uio_offset = fp->f_offset;
3245 #ifdef MAC
3246 	error = mac_check_vnode_readdir(td->td_ucred, vp);
3247 	if (error == 0)
3248 #endif
3249 		error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL,
3250 		    NULL);
3251 	fp->f_offset = auio.uio_offset;
3252 	VOP_UNLOCK(vp, 0, td);
3253 	if (error) {
3254 		fdrop(fp, td);
3255 		return (error);
3256 	}
3257 	if (uap->count == auio.uio_resid) {
3258 		if (union_dircheckp) {
3259 			error = union_dircheckp(td, &vp, fp);
3260 			if (error == -1)
3261 				goto unionread;
3262 			if (error) {
3263 				fdrop(fp, td);
3264 				return (error);
3265 			}
3266 		}
3267 		/*
3268 		 * XXX We could delay dropping the lock above but
3269 		 * union_dircheckp complicates things.
3270 		 */
3271 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3272 		if ((vp->v_vflag & VV_ROOT) &&
3273 		    (vp->v_mount->mnt_flag & MNT_UNION)) {
3274 			struct vnode *tvp = vp;
3275 			vp = vp->v_mount->mnt_vnodecovered;
3276 			VREF(vp);
3277 			fp->f_data = vp;
3278 			fp->f_offset = 0;
3279 			vput(tvp);
3280 			goto unionread;
3281 		}
3282 		VOP_UNLOCK(vp, 0, td);
3283 	}
3284 	if (uap->basep != NULL) {
3285 		error = copyout(&loff, uap->basep, sizeof(long));
3286 	}
3287 	td->td_retval[0] = uap->count - auio.uio_resid;
3288 	fdrop(fp, td);
3289 	return (error);
3290 }
3291 #ifndef _SYS_SYSPROTO_H_
3292 struct getdents_args {
3293 	int fd;
3294 	char *buf;
3295 	size_t count;
3296 };
3297 #endif
3298 int
3299 getdents(td, uap)
3300 	struct thread *td;
3301 	register struct getdents_args /* {
3302 		int fd;
3303 		char *buf;
3304 		u_int count;
3305 	} */ *uap;
3306 {
3307 	struct getdirentries_args ap;
3308 	ap.fd = uap->fd;
3309 	ap.buf = uap->buf;
3310 	ap.count = uap->count;
3311 	ap.basep = NULL;
3312 	return getdirentries(td, &ap);
3313 }
3314 
3315 /*
3316  * Set the mode mask for creation of filesystem nodes.
3317  *
3318  * MP SAFE
3319  */
3320 #ifndef _SYS_SYSPROTO_H_
3321 struct umask_args {
3322 	int	newmask;
3323 };
3324 #endif
3325 int
3326 umask(td, uap)
3327 	struct thread *td;
3328 	struct umask_args /* {
3329 		int newmask;
3330 	} */ *uap;
3331 {
3332 	register struct filedesc *fdp;
3333 
3334 	FILEDESC_LOCK(td->td_proc->p_fd);
3335 	fdp = td->td_proc->p_fd;
3336 	td->td_retval[0] = fdp->fd_cmask;
3337 	fdp->fd_cmask = uap->newmask & ALLPERMS;
3338 	FILEDESC_UNLOCK(td->td_proc->p_fd);
3339 	return (0);
3340 }
3341 
3342 /*
3343  * Void all references to file by ripping underlying filesystem
3344  * away from vnode.
3345  */
3346 #ifndef _SYS_SYSPROTO_H_
3347 struct revoke_args {
3348 	char	*path;
3349 };
3350 #endif
3351 /* ARGSUSED */
3352 int
3353 revoke(td, uap)
3354 	struct thread *td;
3355 	register struct revoke_args /* {
3356 		char *path;
3357 	} */ *uap;
3358 {
3359 	struct mount *mp;
3360 	struct vnode *vp;
3361 	struct vattr vattr;
3362 	int error;
3363 	struct nameidata nd;
3364 
3365 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, td);
3366 	if ((error = namei(&nd)) != 0)
3367 		return (error);
3368 	vp = nd.ni_vp;
3369 	NDFREE(&nd, NDF_ONLY_PNBUF);
3370 	if (vp->v_type != VCHR) {
3371 		vput(vp);
3372 		return (EINVAL);
3373 	}
3374 #ifdef MAC
3375 	error = mac_check_vnode_revoke(td->td_ucred, vp);
3376 	if (error) {
3377 		vput(vp);
3378 		return (error);
3379 	}
3380 #endif
3381 	error = VOP_GETATTR(vp, &vattr, td->td_ucred, td);
3382 	if (error) {
3383 		vput(vp);
3384 		return (error);
3385 	}
3386 	VOP_UNLOCK(vp, 0, td);
3387 	if (td->td_ucred->cr_uid != vattr.va_uid) {
3388 		error = suser_cred(td->td_ucred, PRISON_ROOT);
3389 		if (error)
3390 			goto out;
3391 	}
3392 	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3393 		goto out;
3394 	if (vcount(vp) > 1)
3395 		VOP_REVOKE(vp, REVOKEALL);
3396 	vn_finished_write(mp);
3397 out:
3398 	vrele(vp);
3399 	return (error);
3400 }
3401 
3402 /*
3403  * Convert a user file descriptor to a kernel file entry.
3404  * The file entry is locked upon returning.
3405  */
3406 int
3407 getvnode(fdp, fd, fpp)
3408 	struct filedesc *fdp;
3409 	int fd;
3410 	struct file **fpp;
3411 {
3412 	int error;
3413 	struct file *fp;
3414 
3415 	fp = NULL;
3416 	if (fdp == NULL)
3417 		error = EBADF;
3418 	else {
3419 		FILEDESC_LOCK(fdp);
3420 		if ((u_int)fd >= fdp->fd_nfiles ||
3421 		    (fp = fdp->fd_ofiles[fd]) == NULL)
3422 			error = EBADF;
3423 		else if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) {
3424 			fp = NULL;
3425 			error = EINVAL;
3426 		} else {
3427 			fhold(fp);
3428 			error = 0;
3429 		}
3430 		FILEDESC_UNLOCK(fdp);
3431 	}
3432 	*fpp = fp;
3433 	return (error);
3434 }
3435 /*
3436  * Get (NFS) file handle
3437  */
3438 #ifndef _SYS_SYSPROTO_H_
3439 struct getfh_args {
3440 	char	*fname;
3441 	fhandle_t *fhp;
3442 };
3443 #endif
3444 int
3445 getfh(td, uap)
3446 	struct thread *td;
3447 	register struct getfh_args *uap;
3448 {
3449 	struct nameidata nd;
3450 	fhandle_t fh;
3451 	register struct vnode *vp;
3452 	int error;
3453 
3454 	/*
3455 	 * Must be super user
3456 	 */
3457 	error = suser(td);
3458 	if (error)
3459 		return (error);
3460 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td);
3461 	error = namei(&nd);
3462 	if (error)
3463 		return (error);
3464 	NDFREE(&nd, NDF_ONLY_PNBUF);
3465 	vp = nd.ni_vp;
3466 	bzero(&fh, sizeof(fh));
3467 	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3468 	error = VFS_VPTOFH(vp, &fh.fh_fid);
3469 	vput(vp);
3470 	if (error)
3471 		return (error);
3472 	error = copyout(&fh, uap->fhp, sizeof (fh));
3473 	return (error);
3474 }
3475 
3476 /*
3477  * syscall for the rpc.lockd to use to translate a NFS file handle into
3478  * an open descriptor.
3479  *
3480  * warning: do not remove the suser() call or this becomes one giant
3481  * security hole.
3482  */
3483 #ifndef _SYS_SYSPROTO_H_
3484 struct fhopen_args {
3485 	const struct fhandle *u_fhp;
3486 	int flags;
3487 };
3488 #endif
3489 int
3490 fhopen(td, uap)
3491 	struct thread *td;
3492 	struct fhopen_args /* {
3493 		const struct fhandle *u_fhp;
3494 		int flags;
3495 	} */ *uap;
3496 {
3497 	struct proc *p = td->td_proc;
3498 	struct mount *mp;
3499 	struct vnode *vp;
3500 	struct fhandle fhp;
3501 	struct vattr vat;
3502 	struct vattr *vap = &vat;
3503 	struct flock lf;
3504 	struct file *fp;
3505 	register struct filedesc *fdp = p->p_fd;
3506 	int fmode, mode, error, type;
3507 	struct file *nfp;
3508 	int indx;
3509 
3510 	/*
3511 	 * Must be super user
3512 	 */
3513 	error = suser(td);
3514 	if (error)
3515 		return (error);
3516 
3517 	fmode = FFLAGS(uap->flags);
3518 	/* why not allow a non-read/write open for our lockd? */
3519 	if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3520 		return (EINVAL);
3521 	error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
3522 	if (error)
3523 		return(error);
3524 	/* find the mount point */
3525 	mp = vfs_getvfs(&fhp.fh_fsid);
3526 	if (mp == NULL)
3527 		return (ESTALE);
3528 	/* now give me my vnode, it gets returned to me locked */
3529 	error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
3530 	if (error)
3531 		return (error);
3532  	/*
3533 	 * from now on we have to make sure not
3534 	 * to forget about the vnode
3535 	 * any error that causes an abort must vput(vp)
3536 	 * just set error = err and 'goto bad;'.
3537 	 */
3538 
3539 	/*
3540 	 * from vn_open
3541 	 */
3542 	if (vp->v_type == VLNK) {
3543 		error = EMLINK;
3544 		goto bad;
3545 	}
3546 	if (vp->v_type == VSOCK) {
3547 		error = EOPNOTSUPP;
3548 		goto bad;
3549 	}
3550 	mode = 0;
3551 	if (fmode & (FWRITE | O_TRUNC)) {
3552 		if (vp->v_type == VDIR) {
3553 			error = EISDIR;
3554 			goto bad;
3555 		}
3556 		error = vn_writechk(vp);
3557 		if (error)
3558 			goto bad;
3559 		mode |= VWRITE;
3560 	}
3561 	if (fmode & FREAD)
3562 		mode |= VREAD;
3563 	if (fmode & O_APPEND)
3564 		mode |= VAPPEND;
3565 #ifdef MAC
3566 	error = mac_check_vnode_open(td->td_ucred, vp, mode);
3567 	if (error)
3568 		goto bad;
3569 #endif
3570 	if (mode) {
3571 		error = VOP_ACCESS(vp, mode, td->td_ucred, td);
3572 		if (error)
3573 			goto bad;
3574 	}
3575 	if (fmode & O_TRUNC) {
3576 		VOP_UNLOCK(vp, 0, td);				/* XXX */
3577 		if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
3578 			vrele(vp);
3579 			return (error);
3580 		}
3581 		VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3582 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);	/* XXX */
3583 #ifdef MAC
3584 		/*
3585 		 * We don't yet have fp->f_cred, so use td->td_ucred, which
3586 		 * should be right.
3587 		 */
3588 		error = mac_check_vnode_write(td->td_ucred, td->td_ucred, vp);
3589 		if (error == 0) {
3590 #endif
3591 			VATTR_NULL(vap);
3592 			vap->va_size = 0;
3593 			error = VOP_SETATTR(vp, vap, td->td_ucred, td);
3594 #ifdef MAC
3595 		}
3596 #endif
3597 		vn_finished_write(mp);
3598 		if (error)
3599 			goto bad;
3600 	}
3601 	error = VOP_OPEN(vp, fmode, td->td_ucred, td);
3602 	if (error)
3603 		goto bad;
3604 	/*
3605 	 * Make sure that a VM object is created for VMIO support.
3606 	 */
3607 	if (vn_canvmio(vp) == TRUE) {
3608 		if ((error = vfs_object_create(vp, td, td->td_ucred)) != 0)
3609 			goto bad;
3610 	}
3611 	if (fmode & FWRITE)
3612 		vp->v_writecount++;
3613 
3614 	/*
3615 	 * end of vn_open code
3616 	 */
3617 
3618 	if ((error = falloc(td, &nfp, &indx)) != 0) {
3619 		if (fmode & FWRITE)
3620 			vp->v_writecount--;
3621 		goto bad;
3622 	}
3623 	fp = nfp;
3624 
3625 	/*
3626 	 * Hold an extra reference to avoid having fp ripped out
3627 	 * from under us while we block in the lock op
3628 	 */
3629 	fhold(fp);
3630 	nfp->f_data = vp;
3631 	nfp->f_flag = fmode & FMASK;
3632 	nfp->f_ops = &vnops;
3633 	nfp->f_type = DTYPE_VNODE;
3634 	if (fmode & (O_EXLOCK | O_SHLOCK)) {
3635 		lf.l_whence = SEEK_SET;
3636 		lf.l_start = 0;
3637 		lf.l_len = 0;
3638 		if (fmode & O_EXLOCK)
3639 			lf.l_type = F_WRLCK;
3640 		else
3641 			lf.l_type = F_RDLCK;
3642 		type = F_FLOCK;
3643 		if ((fmode & FNONBLOCK) == 0)
3644 			type |= F_WAIT;
3645 		VOP_UNLOCK(vp, 0, td);
3646 		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
3647 			    type)) != 0) {
3648 			/*
3649 			 * The lock request failed.  Normally close the
3650 			 * descriptor but handle the case where someone might
3651 			 * have dup()d or close()d it when we weren't looking.
3652 			 */
3653 			FILEDESC_LOCK(fdp);
3654 			if (fdp->fd_ofiles[indx] == fp) {
3655 				fdp->fd_ofiles[indx] = NULL;
3656 				FILEDESC_UNLOCK(fdp);
3657 				fdrop(fp, td);
3658 			} else
3659 				FILEDESC_UNLOCK(fdp);
3660 			/*
3661 			 * release our private reference
3662 			 */
3663 			fdrop(fp, td);
3664 			return(error);
3665 		}
3666 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3667 		fp->f_flag |= FHASLOCK;
3668 	}
3669 	if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
3670 		vfs_object_create(vp, td, td->td_ucred);
3671 
3672 	VOP_UNLOCK(vp, 0, td);
3673 	fdrop(fp, td);
3674 	td->td_retval[0] = indx;
3675 	return (0);
3676 
3677 bad:
3678 	vput(vp);
3679 	return (error);
3680 }
3681 
3682 /*
3683  * Stat an (NFS) file handle.
3684  */
3685 #ifndef _SYS_SYSPROTO_H_
3686 struct fhstat_args {
3687 	struct fhandle *u_fhp;
3688 	struct stat *sb;
3689 };
3690 #endif
3691 int
3692 fhstat(td, uap)
3693 	struct thread *td;
3694 	register struct fhstat_args /* {
3695 		struct fhandle *u_fhp;
3696 		struct stat *sb;
3697 	} */ *uap;
3698 {
3699 	struct stat sb;
3700 	fhandle_t fh;
3701 	struct mount *mp;
3702 	struct vnode *vp;
3703 	int error;
3704 
3705 	/*
3706 	 * Must be super user
3707 	 */
3708 	error = suser(td);
3709 	if (error)
3710 		return (error);
3711 
3712 	error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
3713 	if (error)
3714 		return (error);
3715 
3716 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3717 		return (ESTALE);
3718 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3719 		return (error);
3720 	error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
3721 	vput(vp);
3722 	if (error)
3723 		return (error);
3724 	error = copyout(&sb, uap->sb, sizeof(sb));
3725 	return (error);
3726 }
3727 
3728 /*
3729  * Implement fstatfs() for (NFS) file handles.
3730  */
3731 #ifndef _SYS_SYSPROTO_H_
3732 struct fhstatfs_args {
3733 	struct fhandle *u_fhp;
3734 	struct statfs *buf;
3735 };
3736 #endif
3737 int
3738 fhstatfs(td, uap)
3739 	struct thread *td;
3740 	struct fhstatfs_args /* {
3741 		struct fhandle *u_fhp;
3742 		struct statfs *buf;
3743 	} */ *uap;
3744 {
3745 	struct statfs *sp;
3746 	struct mount *mp;
3747 	struct vnode *vp;
3748 	struct statfs sb;
3749 	fhandle_t fh;
3750 	int error;
3751 
3752 	/*
3753 	 * Must be super user
3754 	 */
3755 	error = suser(td);
3756 	if (error)
3757 		return (error);
3758 
3759 	if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
3760 		return (error);
3761 
3762 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3763 		return (ESTALE);
3764 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3765 		return (error);
3766 	mp = vp->v_mount;
3767 	sp = &mp->mnt_stat;
3768 	vput(vp);
3769 #ifdef MAC
3770 	error = mac_check_mount_stat(td->td_ucred, mp);
3771 	if (error)
3772 		return (error);
3773 #endif
3774 	if ((error = VFS_STATFS(mp, sp, td)) != 0)
3775 		return (error);
3776 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3777 	if (suser(td)) {
3778 		bcopy(sp, &sb, sizeof(sb));
3779 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3780 		sp = &sb;
3781 	}
3782 	return (copyout(sp, uap->buf, sizeof(*sp)));
3783 }
3784 
3785 /*
3786  * Syscall to push extended attribute configuration information into the
3787  * VFS.  Accepts a path, which it converts to a mountpoint, as well as
3788  * a command (int cmd), and attribute name and misc data.  For now, the
3789  * attribute name is left in userspace for consumption by the VFS_op.
3790  * It will probably be changed to be copied into sysspace by the
3791  * syscall in the future, once issues with various consumers of the
3792  * attribute code have raised their hands.
3793  *
3794  * Currently this is used only by UFS Extended Attributes.
3795  */
3796 int
3797 extattrctl(td, uap)
3798 	struct thread *td;
3799 	struct extattrctl_args /* {
3800 		const char *path;
3801 		int cmd;
3802 		const char *filename;
3803 		int attrnamespace;
3804 		const char *attrname;
3805 	} */ *uap;
3806 {
3807 	struct vnode *filename_vp;
3808 	struct nameidata nd;
3809 	struct mount *mp, *mp_writable;
3810 	char attrname[EXTATTR_MAXNAMELEN];
3811 	int error;
3812 
3813 	/*
3814 	 * uap->attrname is not always defined.  We check again later when we
3815 	 * invoke the VFS call so as to pass in NULL there if needed.
3816 	 */
3817 	if (uap->attrname != NULL) {
3818 		error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
3819 		    NULL);
3820 		if (error)
3821 			return (error);
3822 	}
3823 
3824 	/*
3825 	 * uap->filename is not always defined.  If it is, grab a vnode lock,
3826 	 * which VFS_EXTATTRCTL() will later release.
3827 	 */
3828 	filename_vp = NULL;
3829 	if (uap->filename != NULL) {
3830 		NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
3831 		    uap->filename, td);
3832 		error = namei(&nd);
3833 		if (error)
3834 			return (error);
3835 		filename_vp = nd.ni_vp;
3836 		NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
3837 	}
3838 
3839 	/* uap->path is always defined. */
3840 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
3841 	error = namei(&nd);
3842 	if (error) {
3843 		if (filename_vp != NULL)
3844 			vput(filename_vp);
3845 		return (error);
3846 	}
3847 	mp = nd.ni_vp->v_mount;
3848 	error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
3849 	NDFREE(&nd, 0);
3850 	if (error) {
3851 		if (filename_vp != NULL)
3852 			vput(filename_vp);
3853 		return (error);
3854 	}
3855 
3856 	error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
3857 	    uap->attrname != NULL ? attrname : NULL, td);
3858 
3859 	vn_finished_write(mp_writable);
3860 	/*
3861 	 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
3862 	 * filename_vp, so vrele it if it is defined.
3863 	 */
3864 	if (filename_vp != NULL)
3865 		vrele(filename_vp);
3866 	return (error);
3867 }
3868 
3869 /*-
3870  * Set a named extended attribute on a file or directory
3871  *
3872  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
3873  *            kernelspace string pointer "attrname", userspace buffer
3874  *            pointer "data", buffer length "nbytes", thread "td".
3875  * Returns: 0 on success, an error number otherwise
3876  * Locks: none
3877  * References: vp must be a valid reference for the duration of the call
3878  */
3879 static int
3880 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
3881     void *data, size_t nbytes, struct thread *td)
3882 {
3883 	struct mount *mp;
3884 	struct uio auio;
3885 	struct iovec aiov;
3886 	ssize_t cnt;
3887 	int error;
3888 
3889 	error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3890 	if (error)
3891 		return (error);
3892 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3893 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3894 
3895 	aiov.iov_base = data;
3896 	aiov.iov_len = nbytes;
3897 	auio.uio_iov = &aiov;
3898 	auio.uio_iovcnt = 1;
3899 	auio.uio_offset = 0;
3900 	if (nbytes > INT_MAX) {
3901 		error = EINVAL;
3902 		goto done;
3903 	}
3904 	auio.uio_resid = nbytes;
3905 	auio.uio_rw = UIO_WRITE;
3906 	auio.uio_segflg = UIO_USERSPACE;
3907 	auio.uio_td = td;
3908 	cnt = nbytes;
3909 
3910 #ifdef MAC
3911 	error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace,
3912 	    attrname, &auio);
3913 	if (error)
3914 		goto done;
3915 #endif
3916 
3917 	error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
3918 	    td->td_ucred, td);
3919 	cnt -= auio.uio_resid;
3920 	td->td_retval[0] = cnt;
3921 
3922 done:
3923 	VOP_UNLOCK(vp, 0, td);
3924 	vn_finished_write(mp);
3925 	return (error);
3926 }
3927 
3928 int
3929 extattr_set_fd(td, uap)
3930 	struct thread *td;
3931 	struct extattr_set_fd_args /* {
3932 		int fd;
3933 		int attrnamespace;
3934 		const char *attrname;
3935 		void *data;
3936 		size_t nbytes;
3937 	} */ *uap;
3938 {
3939 	struct file *fp;
3940 	char attrname[EXTATTR_MAXNAMELEN];
3941 	int error;
3942 
3943 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
3944 	if (error)
3945 		return (error);
3946 
3947 	error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
3948 	if (error)
3949 		return (error);
3950 
3951 	error = extattr_set_vp(fp->f_data, uap->attrnamespace,
3952 	    attrname, uap->data, uap->nbytes, td);
3953 	fdrop(fp, td);
3954 
3955 	return (error);
3956 }
3957 
3958 int
3959 extattr_set_file(td, uap)
3960 	struct thread *td;
3961 	struct extattr_set_file_args /* {
3962 		const char *path;
3963 		int attrnamespace;
3964 		const char *attrname;
3965 		void *data;
3966 		size_t nbytes;
3967 	} */ *uap;
3968 {
3969 	struct nameidata nd;
3970 	char attrname[EXTATTR_MAXNAMELEN];
3971 	int error;
3972 
3973 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
3974 	if (error)
3975 		return (error);
3976 
3977 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
3978 	error = namei(&nd);
3979 	if (error)
3980 		return (error);
3981 	NDFREE(&nd, NDF_ONLY_PNBUF);
3982 
3983 	error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
3984 	    uap->data, uap->nbytes, td);
3985 
3986 	vrele(nd.ni_vp);
3987 	return (error);
3988 }
3989 
3990 int
3991 extattr_set_link(td, uap)
3992 	struct thread *td;
3993 	struct extattr_set_link_args /* {
3994 		const char *path;
3995 		int attrnamespace;
3996 		const char *attrname;
3997 		void *data;
3998 		size_t nbytes;
3999 	} */ *uap;
4000 {
4001 	struct nameidata nd;
4002 	char attrname[EXTATTR_MAXNAMELEN];
4003 	int error;
4004 
4005 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4006 	if (error)
4007 		return (error);
4008 
4009 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4010 	error = namei(&nd);
4011 	if (error)
4012 		return (error);
4013 	NDFREE(&nd, NDF_ONLY_PNBUF);
4014 
4015 	error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4016 	    uap->data, uap->nbytes, td);
4017 
4018 	vrele(nd.ni_vp);
4019 	return (error);
4020 }
4021 
4022 /*-
4023  * Get a named extended attribute on a file or directory
4024  *
4025  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4026  *            kernelspace string pointer "attrname", userspace buffer
4027  *            pointer "data", buffer length "nbytes", thread "td".
4028  * Returns: 0 on success, an error number otherwise
4029  * Locks: none
4030  * References: vp must be a valid reference for the duration of the call
4031  */
4032 static int
4033 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4034     void *data, size_t nbytes, struct thread *td)
4035 {
4036 	struct uio auio, *auiop;
4037 	struct iovec aiov;
4038 	ssize_t cnt;
4039 	size_t size, *sizep;
4040 	int error;
4041 
4042 	VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4043 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4044 
4045 	/*
4046 	 * Slightly unusual semantics: if the user provides a NULL data
4047 	 * pointer, they don't want to receive the data, just the
4048 	 * maximum read length.
4049 	 */
4050 	auiop = NULL;
4051 	sizep = NULL;
4052 	cnt = 0;
4053 	if (data != NULL) {
4054 		aiov.iov_base = data;
4055 		aiov.iov_len = nbytes;
4056 		auio.uio_iov = &aiov;
4057 		auio.uio_offset = 0;
4058 		if (nbytes > INT_MAX) {
4059 			error = EINVAL;
4060 			goto done;
4061 		}
4062 		auio.uio_resid = nbytes;
4063 		auio.uio_rw = UIO_READ;
4064 		auio.uio_segflg = UIO_USERSPACE;
4065 		auio.uio_td = td;
4066 		auiop = &auio;
4067 		cnt = nbytes;
4068 	} else
4069 		sizep = &size;
4070 
4071 #ifdef MAC
4072 	error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace,
4073 	    attrname, &auio);
4074 	if (error)
4075 		goto done;
4076 #endif
4077 
4078 	error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
4079 	    td->td_ucred, td);
4080 
4081 	if (auiop != NULL) {
4082 		cnt -= auio.uio_resid;
4083 		td->td_retval[0] = cnt;
4084 	} else
4085 		td->td_retval[0] = size;
4086 
4087 done:
4088 	VOP_UNLOCK(vp, 0, td);
4089 	return (error);
4090 }
4091 
4092 int
4093 extattr_get_fd(td, uap)
4094 	struct thread *td;
4095 	struct extattr_get_fd_args /* {
4096 		int fd;
4097 		int attrnamespace;
4098 		const char *attrname;
4099 		void *data;
4100 		size_t nbytes;
4101 	} */ *uap;
4102 {
4103 	struct file *fp;
4104 	char attrname[EXTATTR_MAXNAMELEN];
4105 	int error;
4106 
4107 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4108 	if (error)
4109 		return (error);
4110 
4111 	error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4112 	if (error)
4113 		return (error);
4114 
4115 	error = extattr_get_vp(fp->f_data, uap->attrnamespace,
4116 	    attrname, uap->data, uap->nbytes, td);
4117 
4118 	fdrop(fp, td);
4119 	return (error);
4120 }
4121 
4122 int
4123 extattr_get_file(td, uap)
4124 	struct thread *td;
4125 	struct extattr_get_file_args /* {
4126 		const char *path;
4127 		int attrnamespace;
4128 		const char *attrname;
4129 		void *data;
4130 		size_t nbytes;
4131 	} */ *uap;
4132 {
4133 	struct nameidata nd;
4134 	char attrname[EXTATTR_MAXNAMELEN];
4135 	int error;
4136 
4137 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4138 	if (error)
4139 		return (error);
4140 
4141 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4142 	error = namei(&nd);
4143 	if (error)
4144 		return (error);
4145 	NDFREE(&nd, NDF_ONLY_PNBUF);
4146 
4147 	error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4148 	    uap->data, uap->nbytes, td);
4149 
4150 	vrele(nd.ni_vp);
4151 	return (error);
4152 }
4153 
4154 int
4155 extattr_get_link(td, uap)
4156 	struct thread *td;
4157 	struct extattr_get_link_args /* {
4158 		const char *path;
4159 		int attrnamespace;
4160 		const char *attrname;
4161 		void *data;
4162 		size_t nbytes;
4163 	} */ *uap;
4164 {
4165 	struct nameidata nd;
4166 	char attrname[EXTATTR_MAXNAMELEN];
4167 	int error;
4168 
4169 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4170 	if (error)
4171 		return (error);
4172 
4173 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4174 	error = namei(&nd);
4175 	if (error)
4176 		return (error);
4177 	NDFREE(&nd, NDF_ONLY_PNBUF);
4178 
4179 	error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4180 	    uap->data, uap->nbytes, td);
4181 
4182 	vrele(nd.ni_vp);
4183 	return (error);
4184 }
4185 
4186 /*
4187  * extattr_delete_vp(): Delete a named extended attribute on a file or
4188  *                      directory
4189  *
4190  * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4191  *            kernelspace string pointer "attrname", proc "p"
4192  * Returns: 0 on success, an error number otherwise
4193  * Locks: none
4194  * References: vp must be a valid reference for the duration of the call
4195  */
4196 static int
4197 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4198     struct thread *td)
4199 {
4200 	struct mount *mp;
4201 	int error;
4202 
4203 	error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4204 	if (error)
4205 		return (error);
4206 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4207 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4208 
4209 #ifdef MAC
4210 	error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace,
4211 	    attrname, NULL);
4212 	if (error)
4213 		goto done;
4214 #endif
4215 
4216 	error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, td->td_ucred,
4217 	    td);
4218 #ifdef MAC
4219 done:
4220 #endif
4221 	VOP_UNLOCK(vp, 0, td);
4222 	vn_finished_write(mp);
4223 	return (error);
4224 }
4225 
4226 int
4227 extattr_delete_fd(td, uap)
4228 	struct thread *td;
4229 	struct extattr_delete_fd_args /* {
4230 		int fd;
4231 		int attrnamespace;
4232 		const char *attrname;
4233 	} */ *uap;
4234 {
4235 	struct file *fp;
4236 	struct vnode *vp;
4237 	char attrname[EXTATTR_MAXNAMELEN];
4238 	int error;
4239 
4240 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4241 	if (error)
4242 		return (error);
4243 
4244 	error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4245 	if (error)
4246 		return (error);
4247 	vp = fp->f_data;
4248 
4249 	error = extattr_delete_vp(vp, uap->attrnamespace, attrname, td);
4250 	fdrop(fp, td);
4251 	return (error);
4252 }
4253 
4254 int
4255 extattr_delete_file(td, uap)
4256 	struct thread *td;
4257 	struct extattr_delete_file_args /* {
4258 		const char *path;
4259 		int attrnamespace;
4260 		const char *attrname;
4261 	} */ *uap;
4262 {
4263 	struct nameidata nd;
4264 	char attrname[EXTATTR_MAXNAMELEN];
4265 	int error;
4266 
4267 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4268 	if (error)
4269 		return(error);
4270 
4271 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
4272 	error = namei(&nd);
4273 	if (error)
4274 		return(error);
4275 	NDFREE(&nd, NDF_ONLY_PNBUF);
4276 
4277 	error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4278 	vrele(nd.ni_vp);
4279 	return(error);
4280 }
4281 
4282 int
4283 extattr_delete_link(td, uap)
4284 	struct thread *td;
4285 	struct extattr_delete_link_args /* {
4286 		const char *path;
4287 		int attrnamespace;
4288 		const char *attrname;
4289 	} */ *uap;
4290 {
4291 	struct nameidata nd;
4292 	char attrname[EXTATTR_MAXNAMELEN];
4293 	int error;
4294 
4295 	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4296 	if (error)
4297 		return(error);
4298 
4299 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
4300 	error = namei(&nd);
4301 	if (error)
4302 		return(error);
4303 	NDFREE(&nd, NDF_ONLY_PNBUF);
4304 
4305 	error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4306 	vrele(nd.ni_vp);
4307 	return(error);
4308 }
4309