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