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