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