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