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