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