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