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