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