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