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