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