vfs_syscalls.c revision 62550
1/*
2 * Copyright (c) 1989, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 *	@(#)vfs_syscalls.c	8.13 (Berkeley) 4/15/94
39 * $FreeBSD: head/sys/kern/vfs_syscalls.c 62550 2000-07-04 03:34:11Z mckusick $
40 */
41
42/* For 4.3 integer FS ID compatibility */
43#include "opt_compat.h"
44#include "opt_ffs.h"
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/bio.h>
49#include <sys/buf.h>
50#include <sys/sysent.h>
51#include <sys/malloc.h>
52#include <sys/mount.h>
53#include <sys/sysproto.h>
54#include <sys/namei.h>
55#include <sys/filedesc.h>
56#include <sys/kernel.h>
57#include <sys/fcntl.h>
58#include <sys/file.h>
59#include <sys/linker.h>
60#include <sys/stat.h>
61#include <sys/unistd.h>
62#include <sys/vnode.h>
63#include <sys/proc.h>
64#include <sys/dirent.h>
65#include <sys/extattr.h>
66
67#include <machine/limits.h>
68#include <miscfs/union/union.h>
69#include <sys/sysctl.h>
70#include <vm/vm.h>
71#include <vm/vm_object.h>
72#include <vm/vm_zone.h>
73
74static int change_dir __P((struct nameidata *ndp, struct proc *p));
75static void checkdirs __P((struct vnode *olddp));
76static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
77static int getutimes __P((const struct timeval *, struct timespec *));
78static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
79static int setfmode __P((struct proc *, struct vnode *, int));
80static int setfflags __P((struct proc *, struct vnode *, int));
81static int setutimes __P((struct proc *, struct vnode *,
82    const struct timespec *, int));
83static int	usermount = 0;	/* if 1, non-root can mount fs. */
84
85int (*union_dircheckp) __P((struct proc *, struct vnode **, struct file *));
86
87SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
88
89/*
90 * Virtual File System System Calls
91 */
92
93/*
94 * Mount a file system.
95 */
96#ifndef _SYS_SYSPROTO_H_
97struct mount_args {
98	char	*type;
99	char	*path;
100	int	flags;
101	caddr_t	data;
102};
103#endif
104/* ARGSUSED */
105int
106mount(p, uap)
107	struct proc *p;
108	register struct mount_args /* {
109		syscallarg(char *) type;
110		syscallarg(char *) path;
111		syscallarg(int) flags;
112		syscallarg(caddr_t) data;
113	} */ *uap;
114{
115	struct vnode *vp;
116	struct mount *mp;
117	struct vfsconf *vfsp;
118	int error, flag = 0, flag2 = 0;
119	struct vattr va;
120#ifdef COMPAT_43
121	u_long fstypenum;
122#endif
123	struct nameidata nd;
124	char fstypename[MFSNAMELEN];
125
126	if (usermount == 0 && (error = suser(p)))
127		return (error);
128	/*
129	 * Do not allow NFS export by non-root users.
130	 */
131	if (SCARG(uap, flags) & MNT_EXPORTED) {
132		error = suser(p);
133		if (error)
134			return (error);
135	}
136	/*
137	 * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users
138	 */
139	if (suser_xxx(p->p_ucred, 0, 0))
140		SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
141	/*
142	 * Get vnode to be covered
143	 */
144	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
145	    SCARG(uap, path), p);
146	if ((error = namei(&nd)) != 0)
147		return (error);
148	NDFREE(&nd, NDF_ONLY_PNBUF);
149	vp = nd.ni_vp;
150	if (SCARG(uap, flags) & MNT_UPDATE) {
151		if ((vp->v_flag & VROOT) == 0) {
152			vput(vp);
153			return (EINVAL);
154		}
155		mp = vp->v_mount;
156		flag = mp->mnt_flag;
157		flag2 = mp->mnt_kern_flag;
158		/*
159		 * We only allow the filesystem to be reloaded if it
160		 * is currently mounted read-only.
161		 */
162		if ((SCARG(uap, flags) & MNT_RELOAD) &&
163		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
164			vput(vp);
165			return (EOPNOTSUPP);	/* Needs translation */
166		}
167		mp->mnt_flag |=
168		    SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
169		/*
170		 * Only root, or the user that did the original mount is
171		 * permitted to update it.
172		 */
173		if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
174		    (error = suser(p))) {
175			vput(vp);
176			return (error);
177		}
178		if (vfs_busy(mp, LK_NOWAIT, 0, p)) {
179			vput(vp);
180			return (EBUSY);
181		}
182		VOP_UNLOCK(vp, 0, p);
183		goto update;
184	}
185	/*
186	 * If the user is not root, ensure that they own the directory
187	 * onto which we are attempting to mount.
188	 */
189	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
190	    (va.va_uid != p->p_ucred->cr_uid &&
191	     (error = suser(p)))) {
192		vput(vp);
193		return (error);
194	}
195	if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
196		return (error);
197	if (vp->v_type != VDIR) {
198		vput(vp);
199		return (ENOTDIR);
200	}
201#ifdef COMPAT_43
202	/*
203	 * Historically filesystem types were identified by number. If we
204	 * get an integer for the filesystem type instead of a string, we
205	 * check to see if it matches one of the historic filesystem types.
206	 */
207	fstypenum = (uintptr_t)SCARG(uap, type);
208	if (fstypenum < maxvfsconf) {
209		for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
210			if (vfsp->vfc_typenum == fstypenum)
211				break;
212		if (vfsp == NULL) {
213			vput(vp);
214			return (ENODEV);
215		}
216		strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
217	} else
218#endif /* COMPAT_43 */
219	if ((error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) != 0) {
220		vput(vp);
221		return (error);
222	}
223	for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
224		if (!strcmp(vfsp->vfc_name, fstypename))
225			break;
226	if (vfsp == NULL) {
227		linker_file_t lf;
228
229		/* Only load modules for root (very important!) */
230		if ((error = suser(p)) != 0) {
231			vput(vp);
232			return error;
233		}
234		error = linker_load_file(fstypename, &lf);
235		if (error || lf == NULL) {
236			vput(vp);
237			if (lf == NULL)
238				error = ENODEV;
239			return error;
240		}
241		lf->userrefs++;
242		/* lookup again, see if the VFS was loaded */
243		for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
244			if (!strcmp(vfsp->vfc_name, fstypename))
245				break;
246		if (vfsp == NULL) {
247			lf->userrefs--;
248			linker_file_unload(lf);
249			vput(vp);
250			return (ENODEV);
251		}
252	}
253	simple_lock(&vp->v_interlock);
254	if ((vp->v_flag & VMOUNT) != 0 ||
255	    vp->v_mountedhere != NULL) {
256		simple_unlock(&vp->v_interlock);
257		vput(vp);
258		return (EBUSY);
259	}
260	vp->v_flag |= VMOUNT;
261	simple_unlock(&vp->v_interlock);
262
263	/*
264	 * Allocate and initialize the filesystem.
265	 */
266	mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK);
267	bzero((char *)mp, (u_long)sizeof(struct mount));
268	lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
269	(void)vfs_busy(mp, LK_NOWAIT, 0, p);
270	mp->mnt_op = vfsp->vfc_vfsops;
271	mp->mnt_vfc = vfsp;
272	vfsp->vfc_refcount++;
273	mp->mnt_stat.f_type = vfsp->vfc_typenum;
274	mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
275	strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
276	mp->mnt_vnodecovered = vp;
277	mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
278	mp->mnt_iosize_max = DFLTPHYS;
279	VOP_UNLOCK(vp, 0, p);
280update:
281	/*
282	 * Set the mount level flags.
283	 */
284	if (SCARG(uap, flags) & MNT_RDONLY)
285		mp->mnt_flag |= MNT_RDONLY;
286	else if (mp->mnt_flag & MNT_RDONLY)
287		mp->mnt_kern_flag |= MNTK_WANTRDWR;
288	mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
289	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
290	    MNT_NOSYMFOLLOW | MNT_IGNORE |
291	    MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
292	mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
293	    MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
294	    MNT_NOSYMFOLLOW | MNT_IGNORE |
295	    MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
296	/*
297	 * Mount the filesystem.
298	 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
299	 * get.  No freeing of cn_pnbuf.
300	 */
301	error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
302	if (mp->mnt_flag & MNT_UPDATE) {
303		vrele(vp);
304		if (mp->mnt_kern_flag & MNTK_WANTRDWR)
305			mp->mnt_flag &= ~MNT_RDONLY;
306		mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE);
307		mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
308		if (error) {
309			mp->mnt_flag = flag;
310			mp->mnt_kern_flag = flag2;
311		}
312		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
313			if (mp->mnt_syncer == NULL)
314				error = vfs_allocate_syncvnode(mp);
315		} else {
316			if (mp->mnt_syncer != NULL)
317				vrele(mp->mnt_syncer);
318			mp->mnt_syncer = NULL;
319		}
320		vfs_unbusy(mp, p);
321		return (error);
322	}
323	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
324	/*
325	 * Put the new filesystem on the mount list after root.
326	 */
327	cache_purge(vp);
328	if (!error) {
329		simple_lock(&vp->v_interlock);
330		vp->v_flag &= ~VMOUNT;
331		vp->v_mountedhere = mp;
332		simple_unlock(&vp->v_interlock);
333		simple_lock(&mountlist_slock);
334		TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
335		simple_unlock(&mountlist_slock);
336		checkdirs(vp);
337		VOP_UNLOCK(vp, 0, p);
338		if ((mp->mnt_flag & MNT_RDONLY) == 0)
339			error = vfs_allocate_syncvnode(mp);
340		vfs_unbusy(mp, p);
341		if ((error = VFS_START(mp, 0, p)) != 0)
342			vrele(vp);
343	} else {
344		simple_lock(&vp->v_interlock);
345		vp->v_flag &= ~VMOUNT;
346		simple_unlock(&vp->v_interlock);
347		mp->mnt_vfc->vfc_refcount--;
348		vfs_unbusy(mp, p);
349		free((caddr_t)mp, M_MOUNT);
350		vput(vp);
351	}
352	return (error);
353}
354
355/*
356 * Scan all active processes to see if any of them have a current
357 * or root directory onto which the new filesystem has just been
358 * mounted. If so, replace them with the new mount point.
359 */
360static void
361checkdirs(olddp)
362	struct vnode *olddp;
363{
364	struct filedesc *fdp;
365	struct vnode *newdp;
366	struct proc *p;
367
368	if (olddp->v_usecount == 1)
369		return;
370	if (VFS_ROOT(olddp->v_mountedhere, &newdp))
371		panic("mount: lost mount");
372	LIST_FOREACH(p, &allproc, p_list) {
373		fdp = p->p_fd;
374		if (fdp->fd_cdir == olddp) {
375			vrele(fdp->fd_cdir);
376			VREF(newdp);
377			fdp->fd_cdir = newdp;
378		}
379		if (fdp->fd_rdir == olddp) {
380			vrele(fdp->fd_rdir);
381			VREF(newdp);
382			fdp->fd_rdir = newdp;
383		}
384	}
385	if (rootvnode == olddp) {
386		vrele(rootvnode);
387		VREF(newdp);
388		rootvnode = newdp;
389	}
390	vput(newdp);
391}
392
393/*
394 * Unmount a file system.
395 *
396 * Note: unmount takes a path to the vnode mounted on as argument,
397 * not special file (as before).
398 */
399#ifndef _SYS_SYSPROTO_H_
400struct unmount_args {
401	char	*path;
402	int	flags;
403};
404#endif
405/* ARGSUSED */
406int
407unmount(p, uap)
408	struct proc *p;
409	register struct unmount_args /* {
410		syscallarg(char *) path;
411		syscallarg(int) flags;
412	} */ *uap;
413{
414	register struct vnode *vp;
415	struct mount *mp;
416	int error;
417	struct nameidata nd;
418
419	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
420	    SCARG(uap, path), p);
421	if ((error = namei(&nd)) != 0)
422		return (error);
423	vp = nd.ni_vp;
424	NDFREE(&nd, NDF_ONLY_PNBUF);
425	mp = vp->v_mount;
426
427	/*
428	 * Only root, or the user that did the original mount is
429	 * permitted to unmount this filesystem.
430	 */
431	if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
432	    (error = suser(p))) {
433		vput(vp);
434		return (error);
435	}
436
437	/*
438	 * Don't allow unmounting the root file system.
439	 */
440	if (mp->mnt_flag & MNT_ROOTFS) {
441		vput(vp);
442		return (EINVAL);
443	}
444
445	/*
446	 * Must be the root of the filesystem
447	 */
448	if ((vp->v_flag & VROOT) == 0) {
449		vput(vp);
450		return (EINVAL);
451	}
452	vput(vp);
453	return (dounmount(mp, SCARG(uap, flags), p));
454}
455
456/*
457 * Do the actual file system unmount.
458 */
459int
460dounmount(mp, flags, p)
461	register struct mount *mp;
462	int flags;
463	struct proc *p;
464{
465	struct vnode *coveredvp;
466	int error;
467	int async_flag;
468
469	simple_lock(&mountlist_slock);
470	mp->mnt_kern_flag |= MNTK_UNMOUNT;
471	lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p);
472
473	if (mp->mnt_flag & MNT_EXPUBLIC)
474		vfs_setpublicfs(NULL, NULL, NULL);
475
476	vfs_msync(mp, MNT_WAIT);
477	async_flag = mp->mnt_flag & MNT_ASYNC;
478	mp->mnt_flag &=~ MNT_ASYNC;
479	cache_purgevfs(mp);	/* remove cache entries for this file sys */
480	if (mp->mnt_syncer != NULL)
481		vrele(mp->mnt_syncer);
482	if (((mp->mnt_flag & MNT_RDONLY) ||
483	     (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
484	    (flags & MNT_FORCE))
485		error = VFS_UNMOUNT(mp, flags, p);
486	simple_lock(&mountlist_slock);
487	if (error) {
488		if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
489			(void) vfs_allocate_syncvnode(mp);
490		mp->mnt_kern_flag &= ~MNTK_UNMOUNT;
491		mp->mnt_flag |= async_flag;
492		lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
493		    &mountlist_slock, p);
494		if (mp->mnt_kern_flag & MNTK_MWAIT)
495			wakeup((caddr_t)mp);
496		return (error);
497	}
498	TAILQ_REMOVE(&mountlist, mp, mnt_list);
499	if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
500		coveredvp->v_mountedhere = (struct mount *)0;
501		vrele(coveredvp);
502	}
503	mp->mnt_vfc->vfc_refcount--;
504	if (!LIST_EMPTY(&mp->mnt_vnodelist))
505		panic("unmount: dangling vnode");
506	lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
507	if (mp->mnt_kern_flag & MNTK_MWAIT)
508		wakeup((caddr_t)mp);
509	free((caddr_t)mp, M_MOUNT);
510	return (0);
511}
512
513/*
514 * Sync each mounted filesystem.
515 */
516#ifndef _SYS_SYSPROTO_H_
517struct sync_args {
518        int     dummy;
519};
520#endif
521
522#ifdef DEBUG
523static int syncprt = 0;
524SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
525#endif
526
527/* ARGSUSED */
528int
529sync(p, uap)
530	struct proc *p;
531	struct sync_args *uap;
532{
533	register struct mount *mp, *nmp;
534	int asyncflag;
535
536	simple_lock(&mountlist_slock);
537	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
538		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
539			nmp = TAILQ_NEXT(mp, mnt_list);
540			continue;
541		}
542		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
543			asyncflag = mp->mnt_flag & MNT_ASYNC;
544			mp->mnt_flag &= ~MNT_ASYNC;
545			vfs_msync(mp, MNT_NOWAIT);
546			VFS_SYNC(mp, MNT_NOWAIT,
547				((p != NULL) ? p->p_ucred : NOCRED), p);
548			mp->mnt_flag |= asyncflag;
549		}
550		simple_lock(&mountlist_slock);
551		nmp = TAILQ_NEXT(mp, mnt_list);
552		vfs_unbusy(mp, p);
553	}
554	simple_unlock(&mountlist_slock);
555#if 0
556/*
557 * XXX don't call vfs_bufstats() yet because that routine
558 * was not imported in the Lite2 merge.
559 */
560#ifdef DIAGNOSTIC
561	if (syncprt)
562		vfs_bufstats();
563#endif /* DIAGNOSTIC */
564#endif
565	return (0);
566}
567
568/* XXX PRISON: could be per prison flag */
569static int prison_quotas;
570#if 0
571SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
572#endif
573
574/*
575 * Change filesystem quotas.
576 */
577#ifndef _SYS_SYSPROTO_H_
578struct quotactl_args {
579	char *path;
580	int cmd;
581	int uid;
582	caddr_t arg;
583};
584#endif
585/* ARGSUSED */
586int
587quotactl(p, uap)
588	struct proc *p;
589	register struct quotactl_args /* {
590		syscallarg(char *) path;
591		syscallarg(int) cmd;
592		syscallarg(int) uid;
593		syscallarg(caddr_t) arg;
594	} */ *uap;
595{
596	register struct mount *mp;
597	int error;
598	struct nameidata nd;
599
600	if (p->p_prison && !prison_quotas)
601		return (EPERM);
602	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
603	if ((error = namei(&nd)) != 0)
604		return (error);
605	mp = nd.ni_vp->v_mount;
606	NDFREE(&nd, NDF_ONLY_PNBUF);
607	vrele(nd.ni_vp);
608	return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
609	    SCARG(uap, arg), p));
610}
611
612/*
613 * Get filesystem statistics.
614 */
615#ifndef _SYS_SYSPROTO_H_
616struct statfs_args {
617	char *path;
618	struct statfs *buf;
619};
620#endif
621/* ARGSUSED */
622int
623statfs(p, uap)
624	struct proc *p;
625	register struct statfs_args /* {
626		syscallarg(char *) path;
627		syscallarg(struct statfs *) buf;
628	} */ *uap;
629{
630	register struct mount *mp;
631	register struct statfs *sp;
632	int error;
633	struct nameidata nd;
634	struct statfs sb;
635
636	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
637	if ((error = namei(&nd)) != 0)
638		return (error);
639	mp = nd.ni_vp->v_mount;
640	sp = &mp->mnt_stat;
641	NDFREE(&nd, NDF_ONLY_PNBUF);
642	vrele(nd.ni_vp);
643	error = VFS_STATFS(mp, sp, p);
644	if (error)
645		return (error);
646	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
647	if (suser_xxx(p->p_ucred, 0, 0)) {
648		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
649		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
650		sp = &sb;
651	}
652	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
653}
654
655/*
656 * Get filesystem statistics.
657 */
658#ifndef _SYS_SYSPROTO_H_
659struct fstatfs_args {
660	int fd;
661	struct statfs *buf;
662};
663#endif
664/* ARGSUSED */
665int
666fstatfs(p, uap)
667	struct proc *p;
668	register struct fstatfs_args /* {
669		syscallarg(int) fd;
670		syscallarg(struct statfs *) buf;
671	} */ *uap;
672{
673	struct file *fp;
674	struct mount *mp;
675	register struct statfs *sp;
676	int error;
677	struct statfs sb;
678
679	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
680		return (error);
681	mp = ((struct vnode *)fp->f_data)->v_mount;
682	sp = &mp->mnt_stat;
683	error = VFS_STATFS(mp, sp, p);
684	if (error)
685		return (error);
686	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
687	if (suser_xxx(p->p_ucred, 0, 0)) {
688		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
689		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
690		sp = &sb;
691	}
692	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
693}
694
695/*
696 * Get statistics on all filesystems.
697 */
698#ifndef _SYS_SYSPROTO_H_
699struct getfsstat_args {
700	struct statfs *buf;
701	long bufsize;
702	int flags;
703};
704#endif
705int
706getfsstat(p, uap)
707	struct proc *p;
708	register struct getfsstat_args /* {
709		syscallarg(struct statfs *) buf;
710		syscallarg(long) bufsize;
711		syscallarg(int) flags;
712	} */ *uap;
713{
714	register struct mount *mp, *nmp;
715	register struct statfs *sp;
716	caddr_t sfsp;
717	long count, maxcount, error;
718
719	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
720	sfsp = (caddr_t)SCARG(uap, buf);
721	count = 0;
722	simple_lock(&mountlist_slock);
723	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
724		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
725			nmp = TAILQ_NEXT(mp, mnt_list);
726			continue;
727		}
728		if (sfsp && count < maxcount) {
729			sp = &mp->mnt_stat;
730			/*
731			 * If MNT_NOWAIT or MNT_LAZY is specified, do not
732			 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
733			 * overrides MNT_WAIT.
734			 */
735			if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
736			    (SCARG(uap, flags) & MNT_WAIT)) &&
737			    (error = VFS_STATFS(mp, sp, p))) {
738				simple_lock(&mountlist_slock);
739				nmp = TAILQ_NEXT(mp, mnt_list);
740				vfs_unbusy(mp, p);
741				continue;
742			}
743			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
744			error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
745			if (error) {
746				vfs_unbusy(mp, p);
747				return (error);
748			}
749			sfsp += sizeof(*sp);
750		}
751		count++;
752		simple_lock(&mountlist_slock);
753		nmp = TAILQ_NEXT(mp, mnt_list);
754		vfs_unbusy(mp, p);
755	}
756	simple_unlock(&mountlist_slock);
757	if (sfsp && count > maxcount)
758		p->p_retval[0] = maxcount;
759	else
760		p->p_retval[0] = count;
761	return (0);
762}
763
764/*
765 * Change current working directory to a given file descriptor.
766 */
767#ifndef _SYS_SYSPROTO_H_
768struct fchdir_args {
769	int	fd;
770};
771#endif
772/* ARGSUSED */
773int
774fchdir(p, uap)
775	struct proc *p;
776	struct fchdir_args /* {
777		syscallarg(int) fd;
778	} */ *uap;
779{
780	register struct filedesc *fdp = p->p_fd;
781	struct vnode *vp, *tdp;
782	struct mount *mp;
783	struct file *fp;
784	int error;
785
786	if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
787		return (error);
788	vp = (struct vnode *)fp->f_data;
789	VREF(vp);
790	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
791	if (vp->v_type != VDIR)
792		error = ENOTDIR;
793	else
794		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
795	while (!error && (mp = vp->v_mountedhere) != NULL) {
796		if (vfs_busy(mp, 0, 0, p))
797			continue;
798		error = VFS_ROOT(mp, &tdp);
799		vfs_unbusy(mp, p);
800		if (error)
801			break;
802		vput(vp);
803		vp = tdp;
804	}
805	if (error) {
806		vput(vp);
807		return (error);
808	}
809	VOP_UNLOCK(vp, 0, p);
810	vrele(fdp->fd_cdir);
811	fdp->fd_cdir = vp;
812	return (0);
813}
814
815/*
816 * Change current working directory (``.'').
817 */
818#ifndef _SYS_SYSPROTO_H_
819struct chdir_args {
820	char	*path;
821};
822#endif
823/* ARGSUSED */
824int
825chdir(p, uap)
826	struct proc *p;
827	struct chdir_args /* {
828		syscallarg(char *) path;
829	} */ *uap;
830{
831	register struct filedesc *fdp = p->p_fd;
832	int error;
833	struct nameidata nd;
834
835	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
836	    SCARG(uap, path), p);
837	if ((error = change_dir(&nd, p)) != 0)
838		return (error);
839	NDFREE(&nd, NDF_ONLY_PNBUF);
840	vrele(fdp->fd_cdir);
841	fdp->fd_cdir = nd.ni_vp;
842	return (0);
843}
844
845/*
846 * Helper function for raised chroot(2) security function:  Refuse if
847 * any filedescriptors are open directories.
848 */
849static int
850chroot_refuse_vdir_fds(fdp)
851	struct filedesc *fdp;
852{
853	struct vnode *vp;
854	struct file *fp;
855	int error;
856	int fd;
857
858	for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
859		error = getvnode(fdp, fd, &fp);
860		if (error)
861			continue;
862		vp = (struct vnode *)fp->f_data;
863		if (vp->v_type != VDIR)
864			continue;
865		return(EPERM);
866	}
867	return (0);
868}
869
870/*
871 * This sysctl determines if we will allow a process to chroot(2) if it
872 * has a directory open:
873 *	0: disallowed for all processes.
874 *	1: allowed for processes that were not already chroot(2)'ed.
875 *	2: allowed for all processes.
876 */
877
878static int chroot_allow_open_directories = 1;
879
880SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
881     &chroot_allow_open_directories, 0, "");
882
883/*
884 * Change notion of root (``/'') directory.
885 */
886#ifndef _SYS_SYSPROTO_H_
887struct chroot_args {
888	char	*path;
889};
890#endif
891/* ARGSUSED */
892int
893chroot(p, uap)
894	struct proc *p;
895	struct chroot_args /* {
896		syscallarg(char *) path;
897	} */ *uap;
898{
899	register struct filedesc *fdp = p->p_fd;
900	int error;
901	struct nameidata nd;
902
903	error = suser_xxx(0, p, PRISON_ROOT);
904	if (error)
905		return (error);
906	if (chroot_allow_open_directories == 0 ||
907	    (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode))
908		error = chroot_refuse_vdir_fds(fdp);
909	if (error)
910		return (error);
911	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
912	    SCARG(uap, path), p);
913	if ((error = change_dir(&nd, p)) != 0)
914		return (error);
915	NDFREE(&nd, NDF_ONLY_PNBUF);
916	vrele(fdp->fd_rdir);
917	fdp->fd_rdir = nd.ni_vp;
918	if (!fdp->fd_jdir) {
919		fdp->fd_jdir = nd.ni_vp;
920                VREF(fdp->fd_jdir);
921	}
922	return (0);
923}
924
925/*
926 * Common routine for chroot and chdir.
927 */
928static int
929change_dir(ndp, p)
930	register struct nameidata *ndp;
931	struct proc *p;
932{
933	struct vnode *vp;
934	int error;
935
936	error = namei(ndp);
937	if (error)
938		return (error);
939	vp = ndp->ni_vp;
940	if (vp->v_type != VDIR)
941		error = ENOTDIR;
942	else
943		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
944	if (error)
945		vput(vp);
946	else
947		VOP_UNLOCK(vp, 0, p);
948	return (error);
949}
950
951/*
952 * Check permissions, allocate an open file structure,
953 * and call the device open routine if any.
954 */
955#ifndef _SYS_SYSPROTO_H_
956struct open_args {
957	char	*path;
958	int	flags;
959	int	mode;
960};
961#endif
962int
963open(p, uap)
964	struct proc *p;
965	register struct open_args /* {
966		syscallarg(char *) path;
967		syscallarg(int) flags;
968		syscallarg(int) mode;
969	} */ *uap;
970{
971	struct filedesc *fdp = p->p_fd;
972	struct file *fp;
973	struct vnode *vp;
974	struct vattr vat;
975	int cmode, flags, oflags;
976	struct file *nfp;
977	int type, indx, error;
978	struct flock lf;
979	struct nameidata nd;
980
981	oflags = SCARG(uap, flags);
982	if ((oflags & O_ACCMODE) == O_ACCMODE)
983		return (EINVAL);
984	flags = FFLAGS(oflags);
985	error = falloc(p, &nfp, &indx);
986	if (error)
987		return (error);
988	fp = nfp;
989	cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
990	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
991	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
992	error = vn_open(&nd, &flags, cmode);
993	if (error) {
994		ffree(fp);
995		if ((error == ENODEV || error == ENXIO) &&
996		    p->p_dupfd >= 0 &&			/* XXX from fdopen */
997		    (error =
998			dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
999			p->p_retval[0] = indx;
1000			return (0);
1001		}
1002		if (error == ERESTART)
1003			error = EINTR;
1004		fdp->fd_ofiles[indx] = NULL;
1005		return (error);
1006	}
1007	p->p_dupfd = 0;
1008	NDFREE(&nd, NDF_ONLY_PNBUF);
1009	vp = nd.ni_vp;
1010
1011	fp->f_data = (caddr_t)vp;
1012	fp->f_flag = flags & FMASK;
1013	fp->f_ops = &vnops;
1014	fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1015	VOP_UNLOCK(vp, 0, p);
1016	if (flags & (O_EXLOCK | O_SHLOCK)) {
1017		lf.l_whence = SEEK_SET;
1018		lf.l_start = 0;
1019		lf.l_len = 0;
1020		if (flags & O_EXLOCK)
1021			lf.l_type = F_WRLCK;
1022		else
1023			lf.l_type = F_RDLCK;
1024		type = F_FLOCK;
1025		if ((flags & FNONBLOCK) == 0)
1026			type |= F_WAIT;
1027		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0)
1028			goto bad;
1029		fp->f_flag |= FHASLOCK;
1030	}
1031	if (flags & O_TRUNC) {
1032		VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1033		VATTR_NULL(&vat);
1034		vat.va_size = 0;
1035		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1036		error = VOP_SETATTR(vp, &vat, p->p_ucred, p);
1037		VOP_UNLOCK(vp, 0, p);
1038		if (error)
1039			goto bad;
1040	}
1041	/* assert that vn_open created a backing object if one is needed */
1042	KASSERT(!vn_canvmio(vp) || vp->v_object != NULL,
1043		("open: vmio vnode has no backing object after vn_open"));
1044	p->p_retval[0] = indx;
1045	return (0);
1046bad:
1047	(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
1048	ffree(fp);
1049	fdp->fd_ofiles[indx] = NULL;
1050	return (error);
1051}
1052
1053#ifdef COMPAT_43
1054/*
1055 * Create a file.
1056 */
1057#ifndef _SYS_SYSPROTO_H_
1058struct ocreat_args {
1059	char	*path;
1060	int	mode;
1061};
1062#endif
1063int
1064ocreat(p, uap)
1065	struct proc *p;
1066	register struct ocreat_args /* {
1067		syscallarg(char *) path;
1068		syscallarg(int) mode;
1069	} */ *uap;
1070{
1071	struct open_args /* {
1072		syscallarg(char *) path;
1073		syscallarg(int) flags;
1074		syscallarg(int) mode;
1075	} */ nuap;
1076
1077	SCARG(&nuap, path) = SCARG(uap, path);
1078	SCARG(&nuap, mode) = SCARG(uap, mode);
1079	SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
1080	return (open(p, &nuap));
1081}
1082#endif /* COMPAT_43 */
1083
1084/*
1085 * Create a special file.
1086 */
1087#ifndef _SYS_SYSPROTO_H_
1088struct mknod_args {
1089	char	*path;
1090	int	mode;
1091	int	dev;
1092};
1093#endif
1094/* ARGSUSED */
1095int
1096mknod(p, uap)
1097	struct proc *p;
1098	register struct mknod_args /* {
1099		syscallarg(char *) path;
1100		syscallarg(int) mode;
1101		syscallarg(int) dev;
1102	} */ *uap;
1103{
1104	register struct vnode *vp;
1105	struct vattr vattr;
1106	int error;
1107	int whiteout = 0;
1108	struct nameidata nd;
1109
1110	switch (SCARG(uap, mode) & S_IFMT) {
1111	case S_IFCHR:
1112	case S_IFBLK:
1113		error = suser(p);
1114		break;
1115	default:
1116		error = suser_xxx(0, p, PRISON_ROOT);
1117		break;
1118	}
1119	if (error)
1120		return (error);
1121	bwillwrite();
1122	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1123	if ((error = namei(&nd)) != 0)
1124		return (error);
1125	vp = nd.ni_vp;
1126	if (vp != NULL)
1127		error = EEXIST;
1128	else {
1129		VATTR_NULL(&vattr);
1130		vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1131		vattr.va_rdev = SCARG(uap, dev);
1132		whiteout = 0;
1133
1134		switch (SCARG(uap, mode) & S_IFMT) {
1135		case S_IFMT:	/* used by badsect to flag bad sectors */
1136			vattr.va_type = VBAD;
1137			break;
1138		case S_IFCHR:
1139			vattr.va_type = VCHR;
1140			break;
1141		case S_IFBLK:
1142			vattr.va_type = VBLK;
1143			break;
1144		case S_IFWHT:
1145			whiteout = 1;
1146			break;
1147		default:
1148			error = EINVAL;
1149			break;
1150		}
1151	}
1152	if (!error) {
1153		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1154		if (whiteout)
1155			error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1156		else {
1157			error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1158						&nd.ni_cnd, &vattr);
1159			if (error == 0)
1160				vput(nd.ni_vp);
1161		}
1162		NDFREE(&nd, NDF_ONLY_PNBUF);
1163		vput(nd.ni_dvp);
1164	} else {
1165		NDFREE(&nd, NDF_ONLY_PNBUF);
1166		if (nd.ni_dvp == vp)
1167			vrele(nd.ni_dvp);
1168		else
1169			vput(nd.ni_dvp);
1170		if (vp)
1171			vrele(vp);
1172	}
1173	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod");
1174	ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod");
1175	return (error);
1176}
1177
1178/*
1179 * Create a named pipe.
1180 */
1181#ifndef _SYS_SYSPROTO_H_
1182struct mkfifo_args {
1183	char	*path;
1184	int	mode;
1185};
1186#endif
1187/* ARGSUSED */
1188int
1189mkfifo(p, uap)
1190	struct proc *p;
1191	register struct mkfifo_args /* {
1192		syscallarg(char *) path;
1193		syscallarg(int) mode;
1194	} */ *uap;
1195{
1196	struct vattr vattr;
1197	int error;
1198	struct nameidata nd;
1199
1200	bwillwrite();
1201	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1202	if ((error = namei(&nd)) != 0)
1203		return (error);
1204	if (nd.ni_vp != NULL) {
1205		NDFREE(&nd, NDF_ONLY_PNBUF);
1206		if (nd.ni_dvp == nd.ni_vp)
1207			vrele(nd.ni_dvp);
1208		else
1209			vput(nd.ni_dvp);
1210		vrele(nd.ni_vp);
1211		return (EEXIST);
1212	}
1213	VATTR_NULL(&vattr);
1214	vattr.va_type = VFIFO;
1215	vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1216	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1217	error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1218	if (error == 0)
1219		vput(nd.ni_vp);
1220	NDFREE(&nd, NDF_ONLY_PNBUF);
1221	vput(nd.ni_dvp);
1222	return (error);
1223}
1224
1225/*
1226 * Make a hard file link.
1227 */
1228#ifndef _SYS_SYSPROTO_H_
1229struct link_args {
1230	char	*path;
1231	char	*link;
1232};
1233#endif
1234/* ARGSUSED */
1235int
1236link(p, uap)
1237	struct proc *p;
1238	register struct link_args /* {
1239		syscallarg(char *) path;
1240		syscallarg(char *) link;
1241	} */ *uap;
1242{
1243	register struct vnode *vp;
1244	struct nameidata nd;
1245	int error;
1246
1247	bwillwrite();
1248	NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), p);
1249	if ((error = namei(&nd)) != 0)
1250		return (error);
1251	NDFREE(&nd, NDF_ONLY_PNBUF);
1252	vp = nd.ni_vp;
1253	if (vp->v_type == VDIR)
1254		error = EPERM;		/* POSIX */
1255	else {
1256		NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
1257		error = namei(&nd);
1258		if (!error) {
1259			if (nd.ni_vp != NULL) {
1260				if (nd.ni_vp)
1261					vrele(nd.ni_vp);
1262				error = EEXIST;
1263			} else {
1264				VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
1265				    LEASE_WRITE);
1266				VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1267				error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1268			}
1269			NDFREE(&nd, NDF_ONLY_PNBUF);
1270			if (nd.ni_dvp == nd.ni_vp)
1271				vrele(nd.ni_dvp);
1272			else
1273				vput(nd.ni_dvp);
1274		}
1275	}
1276	vrele(vp);
1277	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link");
1278	ASSERT_VOP_UNLOCKED(nd.ni_vp, "link");
1279	return (error);
1280}
1281
1282/*
1283 * Make a symbolic link.
1284 */
1285#ifndef _SYS_SYSPROTO_H_
1286struct symlink_args {
1287	char	*path;
1288	char	*link;
1289};
1290#endif
1291/* ARGSUSED */
1292int
1293symlink(p, uap)
1294	struct proc *p;
1295	register struct symlink_args /* {
1296		syscallarg(char *) path;
1297		syscallarg(char *) link;
1298	} */ *uap;
1299{
1300	struct vattr vattr;
1301	char *path;
1302	int error;
1303	struct nameidata nd;
1304
1305	path = zalloc(namei_zone);
1306	if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0)
1307		goto out;
1308	bwillwrite();
1309	NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), p);
1310	if ((error = namei(&nd)) != 0)
1311		goto out;
1312	if (nd.ni_vp) {
1313		NDFREE(&nd, NDF_ONLY_PNBUF);
1314		if (nd.ni_dvp == nd.ni_vp)
1315			vrele(nd.ni_dvp);
1316		else
1317			vput(nd.ni_dvp);
1318		vrele(nd.ni_vp);
1319		error = EEXIST;
1320		goto out;
1321	}
1322	VATTR_NULL(&vattr);
1323	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
1324	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1325	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1326	NDFREE(&nd, NDF_ONLY_PNBUF);
1327	if (error == 0)
1328		vput(nd.ni_vp);
1329	vput(nd.ni_dvp);
1330	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink");
1331	ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink");
1332out:
1333	zfree(namei_zone, path);
1334	return (error);
1335}
1336
1337/*
1338 * Delete a whiteout from the filesystem.
1339 */
1340/* ARGSUSED */
1341int
1342undelete(p, uap)
1343	struct proc *p;
1344	register struct undelete_args /* {
1345		syscallarg(char *) path;
1346	} */ *uap;
1347{
1348	int error;
1349	struct nameidata nd;
1350
1351	bwillwrite();
1352	NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1353	    SCARG(uap, path), p);
1354	error = namei(&nd);
1355	if (error)
1356		return (error);
1357
1358	if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1359		NDFREE(&nd, NDF_ONLY_PNBUF);
1360		if (nd.ni_dvp == nd.ni_vp)
1361			vrele(nd.ni_dvp);
1362		else
1363			vput(nd.ni_dvp);
1364		if (nd.ni_vp)
1365			vrele(nd.ni_vp);
1366		return (EEXIST);
1367	}
1368
1369	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1370	error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1371	NDFREE(&nd, NDF_ONLY_PNBUF);
1372	vput(nd.ni_dvp);
1373	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
1374	ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
1375	return (error);
1376}
1377
1378/*
1379 * Delete a name from the filesystem.
1380 */
1381#ifndef _SYS_SYSPROTO_H_
1382struct unlink_args {
1383	char	*path;
1384};
1385#endif
1386/* ARGSUSED */
1387int
1388unlink(p, uap)
1389	struct proc *p;
1390	struct unlink_args /* {
1391		syscallarg(char *) path;
1392	} */ *uap;
1393{
1394	register struct vnode *vp;
1395	int error;
1396	struct nameidata nd;
1397
1398	bwillwrite();
1399	NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1400	if ((error = namei(&nd)) != 0)
1401		return (error);
1402	vp = nd.ni_vp;
1403	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1404	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1405
1406	if (vp->v_type == VDIR)
1407		error = EPERM;		/* POSIX */
1408	else {
1409		/*
1410		 * The root of a mounted filesystem cannot be deleted.
1411		 *
1412		 * XXX: can this only be a VDIR case?
1413		 */
1414		if (vp->v_flag & VROOT)
1415			error = EBUSY;
1416	}
1417
1418	if (!error) {
1419		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1420		error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1421	}
1422	NDFREE(&nd, NDF_ONLY_PNBUF);
1423	if (nd.ni_dvp == vp)
1424		vrele(nd.ni_dvp);
1425	else
1426		vput(nd.ni_dvp);
1427	if (vp != NULLVP)
1428		vput(vp);
1429	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
1430	ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
1431	return (error);
1432}
1433
1434/*
1435 * Reposition read/write file offset.
1436 */
1437#ifndef _SYS_SYSPROTO_H_
1438struct lseek_args {
1439	int	fd;
1440	int	pad;
1441	off_t	offset;
1442	int	whence;
1443};
1444#endif
1445int
1446lseek(p, uap)
1447	struct proc *p;
1448	register struct lseek_args /* {
1449		syscallarg(int) fd;
1450		syscallarg(int) pad;
1451		syscallarg(off_t) offset;
1452		syscallarg(int) whence;
1453	} */ *uap;
1454{
1455	struct ucred *cred = p->p_ucred;
1456	register struct filedesc *fdp = p->p_fd;
1457	register struct file *fp;
1458	struct vattr vattr;
1459	int error;
1460
1461	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1462	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1463		return (EBADF);
1464	if (fp->f_type != DTYPE_VNODE)
1465		return (ESPIPE);
1466	switch (SCARG(uap, whence)) {
1467	case L_INCR:
1468		fp->f_offset += SCARG(uap, offset);
1469		break;
1470	case L_XTND:
1471		error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
1472		if (error)
1473			return (error);
1474		fp->f_offset = SCARG(uap, offset) + vattr.va_size;
1475		break;
1476	case L_SET:
1477		fp->f_offset = SCARG(uap, offset);
1478		break;
1479	default:
1480		return (EINVAL);
1481	}
1482	*(off_t *)(p->p_retval) = fp->f_offset;
1483	return (0);
1484}
1485
1486#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1487/*
1488 * Reposition read/write file offset.
1489 */
1490#ifndef _SYS_SYSPROTO_H_
1491struct olseek_args {
1492	int	fd;
1493	long	offset;
1494	int	whence;
1495};
1496#endif
1497int
1498olseek(p, uap)
1499	struct proc *p;
1500	register struct olseek_args /* {
1501		syscallarg(int) fd;
1502		syscallarg(long) offset;
1503		syscallarg(int) whence;
1504	} */ *uap;
1505{
1506	struct lseek_args /* {
1507		syscallarg(int) fd;
1508		syscallarg(int) pad;
1509		syscallarg(off_t) offset;
1510		syscallarg(int) whence;
1511	} */ nuap;
1512	int error;
1513
1514	SCARG(&nuap, fd) = SCARG(uap, fd);
1515	SCARG(&nuap, offset) = SCARG(uap, offset);
1516	SCARG(&nuap, whence) = SCARG(uap, whence);
1517	error = lseek(p, &nuap);
1518	return (error);
1519}
1520#endif /* COMPAT_43 */
1521
1522/*
1523 * Check access permissions.
1524 */
1525#ifndef _SYS_SYSPROTO_H_
1526struct access_args {
1527	char	*path;
1528	int	flags;
1529};
1530#endif
1531int
1532access(p, uap)
1533	struct proc *p;
1534	register struct access_args /* {
1535		syscallarg(char *) path;
1536		syscallarg(int) flags;
1537	} */ *uap;
1538{
1539	register struct ucred *cred = p->p_ucred;
1540	register struct vnode *vp;
1541	int error, flags, t_gid, t_uid;
1542	struct nameidata nd;
1543
1544	t_uid = cred->cr_uid;
1545	t_gid = cred->cr_groups[0];
1546	cred->cr_uid = p->p_cred->p_ruid;
1547	cred->cr_groups[0] = p->p_cred->p_rgid;
1548	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1549	    SCARG(uap, path), p);
1550	if ((error = namei(&nd)) != 0)
1551		goto out1;
1552	vp = nd.ni_vp;
1553
1554	/* Flags == 0 means only check for existence. */
1555	if (SCARG(uap, flags)) {
1556		flags = 0;
1557		if (SCARG(uap, flags) & R_OK)
1558			flags |= VREAD;
1559		if (SCARG(uap, flags) & W_OK)
1560			flags |= VWRITE;
1561		if (SCARG(uap, flags) & X_OK)
1562			flags |= VEXEC;
1563		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1564			error = VOP_ACCESS(vp, flags, cred, p);
1565	}
1566	NDFREE(&nd, NDF_ONLY_PNBUF);
1567	vput(vp);
1568out1:
1569	cred->cr_uid = t_uid;
1570	cred->cr_groups[0] = t_gid;
1571	return (error);
1572}
1573
1574#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1575/*
1576 * Get file status; this version follows links.
1577 */
1578#ifndef _SYS_SYSPROTO_H_
1579struct ostat_args {
1580	char	*path;
1581	struct ostat *ub;
1582};
1583#endif
1584/* ARGSUSED */
1585int
1586ostat(p, uap)
1587	struct proc *p;
1588	register struct ostat_args /* {
1589		syscallarg(char *) path;
1590		syscallarg(struct ostat *) ub;
1591	} */ *uap;
1592{
1593	struct stat sb;
1594	struct ostat osb;
1595	int error;
1596	struct nameidata nd;
1597
1598	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1599	    SCARG(uap, path), p);
1600	if ((error = namei(&nd)) != 0)
1601		return (error);
1602	NDFREE(&nd, NDF_ONLY_PNBUF);
1603	error = vn_stat(nd.ni_vp, &sb, p);
1604	vput(nd.ni_vp);
1605	if (error)
1606		return (error);
1607	cvtstat(&sb, &osb);
1608	error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1609	return (error);
1610}
1611
1612/*
1613 * Get file status; this version does not follow links.
1614 */
1615#ifndef _SYS_SYSPROTO_H_
1616struct olstat_args {
1617	char	*path;
1618	struct ostat *ub;
1619};
1620#endif
1621/* ARGSUSED */
1622int
1623olstat(p, uap)
1624	struct proc *p;
1625	register struct olstat_args /* {
1626		syscallarg(char *) path;
1627		syscallarg(struct ostat *) ub;
1628	} */ *uap;
1629{
1630	struct vnode *vp;
1631	struct stat sb;
1632	struct ostat osb;
1633	int error;
1634	struct nameidata nd;
1635
1636	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1637	    SCARG(uap, path), p);
1638	if ((error = namei(&nd)) != 0)
1639		return (error);
1640	vp = nd.ni_vp;
1641	error = vn_stat(vp, &sb, p);
1642	NDFREE(&nd, NDF_ONLY_PNBUF);
1643	vput(vp);
1644	if (error)
1645		return (error);
1646	cvtstat(&sb, &osb);
1647	error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1648	return (error);
1649}
1650
1651/*
1652 * Convert from an old to a new stat structure.
1653 */
1654void
1655cvtstat(st, ost)
1656	struct stat *st;
1657	struct ostat *ost;
1658{
1659
1660	ost->st_dev = st->st_dev;
1661	ost->st_ino = st->st_ino;
1662	ost->st_mode = st->st_mode;
1663	ost->st_nlink = st->st_nlink;
1664	ost->st_uid = st->st_uid;
1665	ost->st_gid = st->st_gid;
1666	ost->st_rdev = st->st_rdev;
1667	if (st->st_size < (quad_t)1 << 32)
1668		ost->st_size = st->st_size;
1669	else
1670		ost->st_size = -2;
1671	ost->st_atime = st->st_atime;
1672	ost->st_mtime = st->st_mtime;
1673	ost->st_ctime = st->st_ctime;
1674	ost->st_blksize = st->st_blksize;
1675	ost->st_blocks = st->st_blocks;
1676	ost->st_flags = st->st_flags;
1677	ost->st_gen = st->st_gen;
1678}
1679#endif /* COMPAT_43 || COMPAT_SUNOS */
1680
1681/*
1682 * Get file status; this version follows links.
1683 */
1684#ifndef _SYS_SYSPROTO_H_
1685struct stat_args {
1686	char	*path;
1687	struct stat *ub;
1688};
1689#endif
1690/* ARGSUSED */
1691int
1692stat(p, uap)
1693	struct proc *p;
1694	register struct stat_args /* {
1695		syscallarg(char *) path;
1696		syscallarg(struct stat *) ub;
1697	} */ *uap;
1698{
1699	struct stat sb;
1700	int error;
1701	struct nameidata nd;
1702
1703	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1704	    SCARG(uap, path), p);
1705	if ((error = namei(&nd)) != 0)
1706		return (error);
1707	error = vn_stat(nd.ni_vp, &sb, p);
1708	NDFREE(&nd, NDF_ONLY_PNBUF);
1709	vput(nd.ni_vp);
1710	if (error)
1711		return (error);
1712	error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1713	return (error);
1714}
1715
1716/*
1717 * Get file status; this version does not follow links.
1718 */
1719#ifndef _SYS_SYSPROTO_H_
1720struct lstat_args {
1721	char	*path;
1722	struct stat *ub;
1723};
1724#endif
1725/* ARGSUSED */
1726int
1727lstat(p, uap)
1728	struct proc *p;
1729	register struct lstat_args /* {
1730		syscallarg(char *) path;
1731		syscallarg(struct stat *) ub;
1732	} */ *uap;
1733{
1734	int error;
1735	struct vnode *vp;
1736	struct stat sb;
1737	struct nameidata nd;
1738
1739	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1740	    SCARG(uap, path), p);
1741	if ((error = namei(&nd)) != 0)
1742		return (error);
1743	vp = nd.ni_vp;
1744	error = vn_stat(vp, &sb, p);
1745	NDFREE(&nd, NDF_ONLY_PNBUF);
1746	vput(vp);
1747	if (error)
1748		return (error);
1749	error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1750	return (error);
1751}
1752
1753void
1754cvtnstat(sb, nsb)
1755	struct stat *sb;
1756	struct nstat *nsb;
1757{
1758	nsb->st_dev = sb->st_dev;
1759	nsb->st_ino = sb->st_ino;
1760	nsb->st_mode = sb->st_mode;
1761	nsb->st_nlink = sb->st_nlink;
1762	nsb->st_uid = sb->st_uid;
1763	nsb->st_gid = sb->st_gid;
1764	nsb->st_rdev = sb->st_rdev;
1765	nsb->st_atimespec = sb->st_atimespec;
1766	nsb->st_mtimespec = sb->st_mtimespec;
1767	nsb->st_ctimespec = sb->st_ctimespec;
1768	nsb->st_size = sb->st_size;
1769	nsb->st_blocks = sb->st_blocks;
1770	nsb->st_blksize = sb->st_blksize;
1771	nsb->st_flags = sb->st_flags;
1772	nsb->st_gen = sb->st_gen;
1773	nsb->st_qspare[0] = sb->st_qspare[0];
1774	nsb->st_qspare[1] = sb->st_qspare[1];
1775}
1776
1777#ifndef _SYS_SYSPROTO_H_
1778struct nstat_args {
1779	char	*path;
1780	struct nstat *ub;
1781};
1782#endif
1783/* ARGSUSED */
1784int
1785nstat(p, uap)
1786	struct proc *p;
1787	register struct nstat_args /* {
1788		syscallarg(char *) path;
1789		syscallarg(struct nstat *) ub;
1790	} */ *uap;
1791{
1792	struct stat sb;
1793	struct nstat nsb;
1794	int error;
1795	struct nameidata nd;
1796
1797	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1798	    SCARG(uap, path), p);
1799	if ((error = namei(&nd)) != 0)
1800		return (error);
1801	NDFREE(&nd, NDF_ONLY_PNBUF);
1802	error = vn_stat(nd.ni_vp, &sb, p);
1803	vput(nd.ni_vp);
1804	if (error)
1805		return (error);
1806	cvtnstat(&sb, &nsb);
1807	error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1808	return (error);
1809}
1810
1811/*
1812 * Get file status; this version does not follow links.
1813 */
1814#ifndef _SYS_SYSPROTO_H_
1815struct lstat_args {
1816	char	*path;
1817	struct stat *ub;
1818};
1819#endif
1820/* ARGSUSED */
1821int
1822nlstat(p, uap)
1823	struct proc *p;
1824	register struct nlstat_args /* {
1825		syscallarg(char *) path;
1826		syscallarg(struct nstat *) ub;
1827	} */ *uap;
1828{
1829	int error;
1830	struct vnode *vp;
1831	struct stat sb;
1832	struct nstat nsb;
1833	struct nameidata nd;
1834
1835	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1836	    SCARG(uap, path), p);
1837	if ((error = namei(&nd)) != 0)
1838		return (error);
1839	vp = nd.ni_vp;
1840	NDFREE(&nd, NDF_ONLY_PNBUF);
1841	error = vn_stat(vp, &sb, p);
1842	vput(vp);
1843	if (error)
1844		return (error);
1845	cvtnstat(&sb, &nsb);
1846	error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
1847	return (error);
1848}
1849
1850/*
1851 * Get configurable pathname variables.
1852 */
1853#ifndef _SYS_SYSPROTO_H_
1854struct pathconf_args {
1855	char	*path;
1856	int	name;
1857};
1858#endif
1859/* ARGSUSED */
1860int
1861pathconf(p, uap)
1862	struct proc *p;
1863	register struct pathconf_args /* {
1864		syscallarg(char *) path;
1865		syscallarg(int) name;
1866	} */ *uap;
1867{
1868	int error;
1869	struct nameidata nd;
1870
1871	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1872	    SCARG(uap, path), p);
1873	if ((error = namei(&nd)) != 0)
1874		return (error);
1875	NDFREE(&nd, NDF_ONLY_PNBUF);
1876	error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), p->p_retval);
1877	vput(nd.ni_vp);
1878	return (error);
1879}
1880
1881/*
1882 * Return target name of a symbolic link.
1883 */
1884#ifndef _SYS_SYSPROTO_H_
1885struct readlink_args {
1886	char	*path;
1887	char	*buf;
1888	int	count;
1889};
1890#endif
1891/* ARGSUSED */
1892int
1893readlink(p, uap)
1894	struct proc *p;
1895	register struct readlink_args /* {
1896		syscallarg(char *) path;
1897		syscallarg(char *) buf;
1898		syscallarg(int) count;
1899	} */ *uap;
1900{
1901	register struct vnode *vp;
1902	struct iovec aiov;
1903	struct uio auio;
1904	int error;
1905	struct nameidata nd;
1906
1907	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
1908	    SCARG(uap, path), p);
1909	if ((error = namei(&nd)) != 0)
1910		return (error);
1911	NDFREE(&nd, NDF_ONLY_PNBUF);
1912	vp = nd.ni_vp;
1913	if (vp->v_type != VLNK)
1914		error = EINVAL;
1915	else {
1916		aiov.iov_base = SCARG(uap, buf);
1917		aiov.iov_len = SCARG(uap, count);
1918		auio.uio_iov = &aiov;
1919		auio.uio_iovcnt = 1;
1920		auio.uio_offset = 0;
1921		auio.uio_rw = UIO_READ;
1922		auio.uio_segflg = UIO_USERSPACE;
1923		auio.uio_procp = p;
1924		auio.uio_resid = SCARG(uap, count);
1925		error = VOP_READLINK(vp, &auio, p->p_ucred);
1926	}
1927	vput(vp);
1928	p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
1929	return (error);
1930}
1931
1932static int
1933setfflags(p, vp, flags)
1934	struct proc *p;
1935	struct vnode *vp;
1936	int flags;
1937{
1938	int error;
1939	struct vattr vattr;
1940
1941	/*
1942	 * Prevent non-root users from setting flags on devices.  When
1943	 * a device is reused, users can retain ownership of the device
1944	 * if they are allowed to set flags and programs assume that
1945	 * chown can't fail when done as root.
1946	 */
1947	if ((vp->v_type == VCHR || vp->v_type == VBLK) &&
1948	    ((error = suser_xxx(p->p_ucred, p, PRISON_ROOT)) != 0))
1949		return (error);
1950
1951	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1952	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1953	VATTR_NULL(&vattr);
1954	vattr.va_flags = flags;
1955	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1956	VOP_UNLOCK(vp, 0, p);
1957	return (error);
1958}
1959
1960/*
1961 * Change flags of a file given a path name.
1962 */
1963#ifndef _SYS_SYSPROTO_H_
1964struct chflags_args {
1965	char	*path;
1966	int	flags;
1967};
1968#endif
1969/* ARGSUSED */
1970int
1971chflags(p, uap)
1972	struct proc *p;
1973	register struct chflags_args /* {
1974		syscallarg(char *) path;
1975		syscallarg(int) flags;
1976	} */ *uap;
1977{
1978	int error;
1979	struct nameidata nd;
1980
1981	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1982	if ((error = namei(&nd)) != 0)
1983		return (error);
1984	NDFREE(&nd, NDF_ONLY_PNBUF);
1985	error = setfflags(p, nd.ni_vp, SCARG(uap, flags));
1986	vrele(nd.ni_vp);
1987	return error;
1988}
1989
1990/*
1991 * Change flags of a file given a file descriptor.
1992 */
1993#ifndef _SYS_SYSPROTO_H_
1994struct fchflags_args {
1995	int	fd;
1996	int	flags;
1997};
1998#endif
1999/* ARGSUSED */
2000int
2001fchflags(p, uap)
2002	struct proc *p;
2003	register struct fchflags_args /* {
2004		syscallarg(int) fd;
2005		syscallarg(int) flags;
2006	} */ *uap;
2007{
2008	struct file *fp;
2009	int error;
2010
2011	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2012		return (error);
2013	return setfflags(p, (struct vnode *) fp->f_data, SCARG(uap, flags));
2014}
2015
2016static int
2017setfmode(p, vp, mode)
2018	struct proc *p;
2019	struct vnode *vp;
2020	int mode;
2021{
2022	int error;
2023	struct vattr vattr;
2024
2025	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2026	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2027	VATTR_NULL(&vattr);
2028	vattr.va_mode = mode & ALLPERMS;
2029	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2030	VOP_UNLOCK(vp, 0, p);
2031	return error;
2032}
2033
2034/*
2035 * Change mode of a file given path name.
2036 */
2037#ifndef _SYS_SYSPROTO_H_
2038struct chmod_args {
2039	char	*path;
2040	int	mode;
2041};
2042#endif
2043/* ARGSUSED */
2044int
2045chmod(p, uap)
2046	struct proc *p;
2047	register struct chmod_args /* {
2048		syscallarg(char *) path;
2049		syscallarg(int) mode;
2050	} */ *uap;
2051{
2052	int error;
2053	struct nameidata nd;
2054
2055	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2056	if ((error = namei(&nd)) != 0)
2057		return (error);
2058	NDFREE(&nd, NDF_ONLY_PNBUF);
2059	error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
2060	vrele(nd.ni_vp);
2061	return error;
2062}
2063
2064/*
2065 * Change mode of a file given path name (don't follow links.)
2066 */
2067#ifndef _SYS_SYSPROTO_H_
2068struct lchmod_args {
2069	char	*path;
2070	int	mode;
2071};
2072#endif
2073/* ARGSUSED */
2074int
2075lchmod(p, uap)
2076	struct proc *p;
2077	register struct lchmod_args /* {
2078		syscallarg(char *) path;
2079		syscallarg(int) mode;
2080	} */ *uap;
2081{
2082	int error;
2083	struct nameidata nd;
2084
2085	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2086	if ((error = namei(&nd)) != 0)
2087		return (error);
2088	NDFREE(&nd, NDF_ONLY_PNBUF);
2089	error = setfmode(p, nd.ni_vp, SCARG(uap, mode));
2090	vrele(nd.ni_vp);
2091	return error;
2092}
2093
2094/*
2095 * Change mode of a file given a file descriptor.
2096 */
2097#ifndef _SYS_SYSPROTO_H_
2098struct fchmod_args {
2099	int	fd;
2100	int	mode;
2101};
2102#endif
2103/* ARGSUSED */
2104int
2105fchmod(p, uap)
2106	struct proc *p;
2107	register struct fchmod_args /* {
2108		syscallarg(int) fd;
2109		syscallarg(int) mode;
2110	} */ *uap;
2111{
2112	struct file *fp;
2113	int error;
2114
2115	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2116		return (error);
2117	return setfmode(p, (struct vnode *)fp->f_data, SCARG(uap, mode));
2118}
2119
2120static int
2121setfown(p, vp, uid, gid)
2122	struct proc *p;
2123	struct vnode *vp;
2124	uid_t uid;
2125	gid_t gid;
2126{
2127	int error;
2128	struct vattr vattr;
2129
2130	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2131	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2132	VATTR_NULL(&vattr);
2133	vattr.va_uid = uid;
2134	vattr.va_gid = gid;
2135	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2136	VOP_UNLOCK(vp, 0, p);
2137	return error;
2138}
2139
2140/*
2141 * Set ownership given a path name.
2142 */
2143#ifndef _SYS_SYSPROTO_H_
2144struct chown_args {
2145	char	*path;
2146	int	uid;
2147	int	gid;
2148};
2149#endif
2150/* ARGSUSED */
2151int
2152chown(p, uap)
2153	struct proc *p;
2154	register struct chown_args /* {
2155		syscallarg(char *) path;
2156		syscallarg(int) uid;
2157		syscallarg(int) gid;
2158	} */ *uap;
2159{
2160	int error;
2161	struct nameidata nd;
2162
2163	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2164	if ((error = namei(&nd)) != 0)
2165		return (error);
2166	NDFREE(&nd, NDF_ONLY_PNBUF);
2167	error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2168	vrele(nd.ni_vp);
2169	return (error);
2170}
2171
2172/*
2173 * Set ownership given a path name, do not cross symlinks.
2174 */
2175#ifndef _SYS_SYSPROTO_H_
2176struct lchown_args {
2177	char	*path;
2178	int	uid;
2179	int	gid;
2180};
2181#endif
2182/* ARGSUSED */
2183int
2184lchown(p, uap)
2185	struct proc *p;
2186	register struct lchown_args /* {
2187		syscallarg(char *) path;
2188		syscallarg(int) uid;
2189		syscallarg(int) gid;
2190	} */ *uap;
2191{
2192	int error;
2193	struct nameidata nd;
2194
2195	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2196	if ((error = namei(&nd)) != 0)
2197		return (error);
2198	NDFREE(&nd, NDF_ONLY_PNBUF);
2199	error = setfown(p, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid));
2200	vrele(nd.ni_vp);
2201	return (error);
2202}
2203
2204/*
2205 * Set ownership given a file descriptor.
2206 */
2207#ifndef _SYS_SYSPROTO_H_
2208struct fchown_args {
2209	int	fd;
2210	int	uid;
2211	int	gid;
2212};
2213#endif
2214/* ARGSUSED */
2215int
2216fchown(p, uap)
2217	struct proc *p;
2218	register struct fchown_args /* {
2219		syscallarg(int) fd;
2220		syscallarg(int) uid;
2221		syscallarg(int) gid;
2222	} */ *uap;
2223{
2224	struct file *fp;
2225	int error;
2226
2227	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2228		return (error);
2229	return setfown(p, (struct vnode *)fp->f_data,
2230		SCARG(uap, uid), SCARG(uap, gid));
2231}
2232
2233static int
2234getutimes(usrtvp, tsp)
2235	const struct timeval *usrtvp;
2236	struct timespec *tsp;
2237{
2238	struct timeval tv[2];
2239	int error;
2240
2241	if (usrtvp == NULL) {
2242		microtime(&tv[0]);
2243		TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2244		tsp[1] = tsp[0];
2245	} else {
2246		if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0)
2247			return (error);
2248		TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2249		TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]);
2250	}
2251	return 0;
2252}
2253
2254static int
2255setutimes(p, vp, ts, nullflag)
2256	struct proc *p;
2257	struct vnode *vp;
2258	const struct timespec *ts;
2259	int nullflag;
2260{
2261	int error;
2262	struct vattr vattr;
2263
2264	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2265	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2266	VATTR_NULL(&vattr);
2267	vattr.va_atime = ts[0];
2268	vattr.va_mtime = ts[1];
2269	if (nullflag)
2270		vattr.va_vaflags |= VA_UTIMES_NULL;
2271	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2272	VOP_UNLOCK(vp, 0, p);
2273	return error;
2274}
2275
2276/*
2277 * Set the access and modification times of a file.
2278 */
2279#ifndef _SYS_SYSPROTO_H_
2280struct utimes_args {
2281	char	*path;
2282	struct	timeval *tptr;
2283};
2284#endif
2285/* ARGSUSED */
2286int
2287utimes(p, uap)
2288	struct proc *p;
2289	register struct utimes_args /* {
2290		syscallarg(char *) path;
2291		syscallarg(struct timeval *) tptr;
2292	} */ *uap;
2293{
2294	struct timespec ts[2];
2295	struct timeval *usrtvp;
2296	int error;
2297	struct nameidata nd;
2298
2299	usrtvp = SCARG(uap, tptr);
2300	if ((error = getutimes(usrtvp, ts)) != 0)
2301		return (error);
2302	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2303	if ((error = namei(&nd)) != 0)
2304		return (error);
2305	NDFREE(&nd, NDF_ONLY_PNBUF);
2306	error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL);
2307	vrele(nd.ni_vp);
2308	return (error);
2309}
2310
2311/*
2312 * Set the access and modification times of a file.
2313 */
2314#ifndef _SYS_SYSPROTO_H_
2315struct lutimes_args {
2316	char	*path;
2317	struct	timeval *tptr;
2318};
2319#endif
2320/* ARGSUSED */
2321int
2322lutimes(p, uap)
2323	struct proc *p;
2324	register struct lutimes_args /* {
2325		syscallarg(char *) path;
2326		syscallarg(struct timeval *) tptr;
2327	} */ *uap;
2328{
2329	struct timespec ts[2];
2330	struct timeval *usrtvp;
2331	int error;
2332	struct nameidata nd;
2333
2334	usrtvp = SCARG(uap, tptr);
2335	if ((error = getutimes(usrtvp, ts)) != 0)
2336		return (error);
2337	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2338	if ((error = namei(&nd)) != 0)
2339		return (error);
2340	NDFREE(&nd, NDF_ONLY_PNBUF);
2341	error = setutimes(p, nd.ni_vp, ts, usrtvp == NULL);
2342	vrele(nd.ni_vp);
2343	return (error);
2344}
2345
2346/*
2347 * Set the access and modification times of a file.
2348 */
2349#ifndef _SYS_SYSPROTO_H_
2350struct futimes_args {
2351	int	fd;
2352	struct	timeval *tptr;
2353};
2354#endif
2355/* ARGSUSED */
2356int
2357futimes(p, uap)
2358	struct proc *p;
2359	register struct futimes_args /* {
2360		syscallarg(int ) fd;
2361		syscallarg(struct timeval *) tptr;
2362	} */ *uap;
2363{
2364	struct timespec ts[2];
2365	struct file *fp;
2366	struct timeval *usrtvp;
2367	int error;
2368
2369	usrtvp = SCARG(uap, tptr);
2370	if ((error = getutimes(usrtvp, ts)) != 0)
2371		return (error);
2372	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2373		return (error);
2374	return setutimes(p, (struct vnode *)fp->f_data, ts, usrtvp == NULL);
2375}
2376
2377/*
2378 * Truncate a file given its path name.
2379 */
2380#ifndef _SYS_SYSPROTO_H_
2381struct truncate_args {
2382	char	*path;
2383	int	pad;
2384	off_t	length;
2385};
2386#endif
2387/* ARGSUSED */
2388int
2389truncate(p, uap)
2390	struct proc *p;
2391	register struct truncate_args /* {
2392		syscallarg(char *) path;
2393		syscallarg(int) pad;
2394		syscallarg(off_t) length;
2395	} */ *uap;
2396{
2397	register struct vnode *vp;
2398	struct vattr vattr;
2399	int error;
2400	struct nameidata nd;
2401
2402	if (uap->length < 0)
2403		return(EINVAL);
2404	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2405	if ((error = namei(&nd)) != 0)
2406		return (error);
2407	vp = nd.ni_vp;
2408	NDFREE(&nd, NDF_ONLY_PNBUF);
2409	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2410	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2411	if (vp->v_type == VDIR)
2412		error = EISDIR;
2413	else if ((error = vn_writechk(vp)) == 0 &&
2414	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
2415		VATTR_NULL(&vattr);
2416		vattr.va_size = SCARG(uap, length);
2417		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2418	}
2419	vput(vp);
2420	return (error);
2421}
2422
2423/*
2424 * Truncate a file given a file descriptor.
2425 */
2426#ifndef _SYS_SYSPROTO_H_
2427struct ftruncate_args {
2428	int	fd;
2429	int	pad;
2430	off_t	length;
2431};
2432#endif
2433/* ARGSUSED */
2434int
2435ftruncate(p, uap)
2436	struct proc *p;
2437	register struct ftruncate_args /* {
2438		syscallarg(int) fd;
2439		syscallarg(int) pad;
2440		syscallarg(off_t) length;
2441	} */ *uap;
2442{
2443	struct vattr vattr;
2444	struct vnode *vp;
2445	struct file *fp;
2446	int error;
2447
2448	if (uap->length < 0)
2449		return(EINVAL);
2450	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2451		return (error);
2452	if ((fp->f_flag & FWRITE) == 0)
2453		return (EINVAL);
2454	vp = (struct vnode *)fp->f_data;
2455	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2456	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2457	if (vp->v_type == VDIR)
2458		error = EISDIR;
2459	else if ((error = vn_writechk(vp)) == 0) {
2460		VATTR_NULL(&vattr);
2461		vattr.va_size = SCARG(uap, length);
2462		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
2463	}
2464	VOP_UNLOCK(vp, 0, p);
2465	return (error);
2466}
2467
2468#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2469/*
2470 * Truncate a file given its path name.
2471 */
2472#ifndef _SYS_SYSPROTO_H_
2473struct otruncate_args {
2474	char	*path;
2475	long	length;
2476};
2477#endif
2478/* ARGSUSED */
2479int
2480otruncate(p, uap)
2481	struct proc *p;
2482	register struct otruncate_args /* {
2483		syscallarg(char *) path;
2484		syscallarg(long) length;
2485	} */ *uap;
2486{
2487	struct truncate_args /* {
2488		syscallarg(char *) path;
2489		syscallarg(int) pad;
2490		syscallarg(off_t) length;
2491	} */ nuap;
2492
2493	SCARG(&nuap, path) = SCARG(uap, path);
2494	SCARG(&nuap, length) = SCARG(uap, length);
2495	return (truncate(p, &nuap));
2496}
2497
2498/*
2499 * Truncate a file given a file descriptor.
2500 */
2501#ifndef _SYS_SYSPROTO_H_
2502struct oftruncate_args {
2503	int	fd;
2504	long	length;
2505};
2506#endif
2507/* ARGSUSED */
2508int
2509oftruncate(p, uap)
2510	struct proc *p;
2511	register struct oftruncate_args /* {
2512		syscallarg(int) fd;
2513		syscallarg(long) length;
2514	} */ *uap;
2515{
2516	struct ftruncate_args /* {
2517		syscallarg(int) fd;
2518		syscallarg(int) pad;
2519		syscallarg(off_t) length;
2520	} */ nuap;
2521
2522	SCARG(&nuap, fd) = SCARG(uap, fd);
2523	SCARG(&nuap, length) = SCARG(uap, length);
2524	return (ftruncate(p, &nuap));
2525}
2526#endif /* COMPAT_43 || COMPAT_SUNOS */
2527
2528/*
2529 * Sync an open file.
2530 */
2531#ifndef _SYS_SYSPROTO_H_
2532struct fsync_args {
2533	int	fd;
2534};
2535#endif
2536/* ARGSUSED */
2537int
2538fsync(p, uap)
2539	struct proc *p;
2540	struct fsync_args /* {
2541		syscallarg(int) fd;
2542	} */ *uap;
2543{
2544	register struct vnode *vp;
2545	struct file *fp;
2546	int error;
2547
2548	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2549		return (error);
2550	vp = (struct vnode *)fp->f_data;
2551	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2552	if (vp->v_object)
2553		vm_object_page_clean(vp->v_object, 0, 0, 0);
2554	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
2555#ifdef SOFTUPDATES
2556	if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
2557	    error = softdep_fsync(vp);
2558#endif
2559
2560	VOP_UNLOCK(vp, 0, p);
2561	return (error);
2562}
2563
2564/*
2565 * Rename files.  Source and destination must either both be directories,
2566 * or both not be directories.  If target is a directory, it must be empty.
2567 */
2568#ifndef _SYS_SYSPROTO_H_
2569struct rename_args {
2570	char	*from;
2571	char	*to;
2572};
2573#endif
2574/* ARGSUSED */
2575int
2576rename(p, uap)
2577	struct proc *p;
2578	register struct rename_args /* {
2579		syscallarg(char *) from;
2580		syscallarg(char *) to;
2581	} */ *uap;
2582{
2583	register struct vnode *tvp, *fvp, *tdvp;
2584	struct nameidata fromnd, tond;
2585	int error;
2586
2587	bwillwrite();
2588	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2589	    SCARG(uap, from), p);
2590	if ((error = namei(&fromnd)) != 0)
2591		return (error);
2592	fvp = fromnd.ni_vp;
2593	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ,
2594	    UIO_USERSPACE, SCARG(uap, to), p);
2595	if (fromnd.ni_vp->v_type == VDIR)
2596		tond.ni_cnd.cn_flags |= WILLBEDIR;
2597	if ((error = namei(&tond)) != 0) {
2598		/* Translate error code for rename("dir1", "dir2/."). */
2599		if (error == EISDIR && fvp->v_type == VDIR)
2600			error = EINVAL;
2601		NDFREE(&fromnd, NDF_ONLY_PNBUF);
2602		vrele(fromnd.ni_dvp);
2603		vrele(fvp);
2604		goto out1;
2605	}
2606	tdvp = tond.ni_dvp;
2607	tvp = tond.ni_vp;
2608	if (tvp != NULL) {
2609		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2610			error = ENOTDIR;
2611			goto out;
2612		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2613			error = EISDIR;
2614			goto out;
2615		}
2616	}
2617	if (fvp == tdvp)
2618		error = EINVAL;
2619	/*
2620	 * If source is the same as the destination (that is the
2621	 * same inode number with the same name in the same directory),
2622	 * then there is nothing to do.
2623	 */
2624	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
2625	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
2626	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
2627	      fromnd.ni_cnd.cn_namelen))
2628		error = -1;
2629out:
2630	if (!error) {
2631		VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
2632		if (fromnd.ni_dvp != tdvp) {
2633			VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2634		}
2635		if (tvp) {
2636			VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
2637		}
2638		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2639				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2640		NDFREE(&fromnd, NDF_ONLY_PNBUF);
2641		NDFREE(&tond, NDF_ONLY_PNBUF);
2642	} else {
2643		NDFREE(&fromnd, NDF_ONLY_PNBUF);
2644		NDFREE(&tond, NDF_ONLY_PNBUF);
2645		if (tdvp == tvp)
2646			vrele(tdvp);
2647		else
2648			vput(tdvp);
2649		if (tvp)
2650			vput(tvp);
2651		vrele(fromnd.ni_dvp);
2652		vrele(fvp);
2653	}
2654	vrele(tond.ni_startdir);
2655	ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename");
2656	ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename");
2657	ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename");
2658	ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename");
2659out1:
2660	if (fromnd.ni_startdir)
2661		vrele(fromnd.ni_startdir);
2662	if (error == -1)
2663		return (0);
2664	return (error);
2665}
2666
2667/*
2668 * Make a directory file.
2669 */
2670#ifndef _SYS_SYSPROTO_H_
2671struct mkdir_args {
2672	char	*path;
2673	int	mode;
2674};
2675#endif
2676/* ARGSUSED */
2677int
2678mkdir(p, uap)
2679	struct proc *p;
2680	register struct mkdir_args /* {
2681		syscallarg(char *) path;
2682		syscallarg(int) mode;
2683	} */ *uap;
2684{
2685	register struct vnode *vp;
2686	struct vattr vattr;
2687	int error;
2688	struct nameidata nd;
2689
2690	bwillwrite();
2691	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
2692	nd.ni_cnd.cn_flags |= WILLBEDIR;
2693	if ((error = namei(&nd)) != 0)
2694		return (error);
2695	vp = nd.ni_vp;
2696	if (vp != NULL) {
2697		NDFREE(&nd, NDF_ONLY_PNBUF);
2698		if (nd.ni_dvp == vp)
2699			vrele(nd.ni_dvp);
2700		else
2701			vput(nd.ni_dvp);
2702		vrele(vp);
2703		return (EEXIST);
2704	}
2705	VATTR_NULL(&vattr);
2706	vattr.va_type = VDIR;
2707	vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2708	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2709	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2710	NDFREE(&nd, NDF_ONLY_PNBUF);
2711	vput(nd.ni_dvp);
2712	if (!error)
2713		vput(nd.ni_vp);
2714	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir");
2715	ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir");
2716	return (error);
2717}
2718
2719/*
2720 * Remove a directory file.
2721 */
2722#ifndef _SYS_SYSPROTO_H_
2723struct rmdir_args {
2724	char	*path;
2725};
2726#endif
2727/* ARGSUSED */
2728int
2729rmdir(p, uap)
2730	struct proc *p;
2731	struct rmdir_args /* {
2732		syscallarg(char *) path;
2733	} */ *uap;
2734{
2735	register struct vnode *vp;
2736	int error;
2737	struct nameidata nd;
2738
2739	bwillwrite();
2740	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2741	    SCARG(uap, path), p);
2742	if ((error = namei(&nd)) != 0)
2743		return (error);
2744	vp = nd.ni_vp;
2745	if (vp->v_type != VDIR) {
2746		error = ENOTDIR;
2747		goto out;
2748	}
2749	/*
2750	 * No rmdir "." please.
2751	 */
2752	if (nd.ni_dvp == vp) {
2753		error = EINVAL;
2754		goto out;
2755	}
2756	/*
2757	 * The root of a mounted filesystem cannot be deleted.
2758	 */
2759	if (vp->v_flag & VROOT)
2760		error = EBUSY;
2761	else {
2762		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2763		VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2764		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2765	}
2766out:
2767	NDFREE(&nd, NDF_ONLY_PNBUF);
2768	if (nd.ni_dvp == vp)
2769		vrele(nd.ni_dvp);
2770	else
2771		vput(nd.ni_dvp);
2772	if (vp != NULLVP)
2773		vput(vp);
2774	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir");
2775	ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir");
2776	return (error);
2777}
2778
2779#ifdef COMPAT_43
2780/*
2781 * Read a block of directory entries in a file system independent format.
2782 */
2783#ifndef _SYS_SYSPROTO_H_
2784struct ogetdirentries_args {
2785	int	fd;
2786	char	*buf;
2787	u_int	count;
2788	long	*basep;
2789};
2790#endif
2791int
2792ogetdirentries(p, uap)
2793	struct proc *p;
2794	register struct ogetdirentries_args /* {
2795		syscallarg(int) fd;
2796		syscallarg(char *) buf;
2797		syscallarg(u_int) count;
2798		syscallarg(long *) basep;
2799	} */ *uap;
2800{
2801	struct vnode *vp;
2802	struct file *fp;
2803	struct uio auio, kuio;
2804	struct iovec aiov, kiov;
2805	struct dirent *dp, *edp;
2806	caddr_t dirbuf;
2807	int error, eofflag, readcnt;
2808	long loff;
2809
2810	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2811		return (error);
2812	if ((fp->f_flag & FREAD) == 0)
2813		return (EBADF);
2814	vp = (struct vnode *)fp->f_data;
2815unionread:
2816	if (vp->v_type != VDIR)
2817		return (EINVAL);
2818	aiov.iov_base = SCARG(uap, buf);
2819	aiov.iov_len = SCARG(uap, count);
2820	auio.uio_iov = &aiov;
2821	auio.uio_iovcnt = 1;
2822	auio.uio_rw = UIO_READ;
2823	auio.uio_segflg = UIO_USERSPACE;
2824	auio.uio_procp = p;
2825	auio.uio_resid = SCARG(uap, count);
2826	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2827	loff = auio.uio_offset = fp->f_offset;
2828#	if (BYTE_ORDER != LITTLE_ENDIAN)
2829		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
2830			error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
2831			    NULL, NULL);
2832			fp->f_offset = auio.uio_offset;
2833		} else
2834#	endif
2835	{
2836		kuio = auio;
2837		kuio.uio_iov = &kiov;
2838		kuio.uio_segflg = UIO_SYSSPACE;
2839		kiov.iov_len = SCARG(uap, count);
2840		MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
2841		kiov.iov_base = dirbuf;
2842		error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
2843			    NULL, NULL);
2844		fp->f_offset = kuio.uio_offset;
2845		if (error == 0) {
2846			readcnt = SCARG(uap, count) - kuio.uio_resid;
2847			edp = (struct dirent *)&dirbuf[readcnt];
2848			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
2849#				if (BYTE_ORDER == LITTLE_ENDIAN)
2850					/*
2851					 * The expected low byte of
2852					 * dp->d_namlen is our dp->d_type.
2853					 * The high MBZ byte of dp->d_namlen
2854					 * is our dp->d_namlen.
2855					 */
2856					dp->d_type = dp->d_namlen;
2857					dp->d_namlen = 0;
2858#				else
2859					/*
2860					 * The dp->d_type is the high byte
2861					 * of the expected dp->d_namlen,
2862					 * so must be zero'ed.
2863					 */
2864					dp->d_type = 0;
2865#				endif
2866				if (dp->d_reclen > 0) {
2867					dp = (struct dirent *)
2868					    ((char *)dp + dp->d_reclen);
2869				} else {
2870					error = EIO;
2871					break;
2872				}
2873			}
2874			if (dp >= edp)
2875				error = uiomove(dirbuf, readcnt, &auio);
2876		}
2877		FREE(dirbuf, M_TEMP);
2878	}
2879	VOP_UNLOCK(vp, 0, p);
2880	if (error)
2881		return (error);
2882	if (SCARG(uap, count) == auio.uio_resid) {
2883		if (union_dircheckp) {
2884			error = union_dircheckp(p, &vp, fp);
2885			if (error == -1)
2886				goto unionread;
2887			if (error)
2888				return (error);
2889		}
2890		if ((vp->v_flag & VROOT) &&
2891		    (vp->v_mount->mnt_flag & MNT_UNION)) {
2892			struct vnode *tvp = vp;
2893			vp = vp->v_mount->mnt_vnodecovered;
2894			VREF(vp);
2895			fp->f_data = (caddr_t) vp;
2896			fp->f_offset = 0;
2897			vrele(tvp);
2898			goto unionread;
2899		}
2900	}
2901	error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2902	    sizeof(long));
2903	p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2904	return (error);
2905}
2906#endif /* COMPAT_43 */
2907
2908/*
2909 * Read a block of directory entries in a file system independent format.
2910 */
2911#ifndef _SYS_SYSPROTO_H_
2912struct getdirentries_args {
2913	int	fd;
2914	char	*buf;
2915	u_int	count;
2916	long	*basep;
2917};
2918#endif
2919int
2920getdirentries(p, uap)
2921	struct proc *p;
2922	register struct getdirentries_args /* {
2923		syscallarg(int) fd;
2924		syscallarg(char *) buf;
2925		syscallarg(u_int) count;
2926		syscallarg(long *) basep;
2927	} */ *uap;
2928{
2929	struct vnode *vp;
2930	struct file *fp;
2931	struct uio auio;
2932	struct iovec aiov;
2933	long loff;
2934	int error, eofflag;
2935
2936	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2937		return (error);
2938	if ((fp->f_flag & FREAD) == 0)
2939		return (EBADF);
2940	vp = (struct vnode *)fp->f_data;
2941unionread:
2942	if (vp->v_type != VDIR)
2943		return (EINVAL);
2944	aiov.iov_base = SCARG(uap, buf);
2945	aiov.iov_len = SCARG(uap, count);
2946	auio.uio_iov = &aiov;
2947	auio.uio_iovcnt = 1;
2948	auio.uio_rw = UIO_READ;
2949	auio.uio_segflg = UIO_USERSPACE;
2950	auio.uio_procp = p;
2951	auio.uio_resid = SCARG(uap, count);
2952	/* vn_lock(vp, LK_SHARED | LK_RETRY, p); */
2953	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2954	loff = auio.uio_offset = fp->f_offset;
2955	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
2956	fp->f_offset = auio.uio_offset;
2957	VOP_UNLOCK(vp, 0, p);
2958	if (error)
2959		return (error);
2960	if (SCARG(uap, count) == auio.uio_resid) {
2961		if (union_dircheckp) {
2962			error = union_dircheckp(p, &vp, fp);
2963			if (error == -1)
2964				goto unionread;
2965			if (error)
2966				return (error);
2967		}
2968		if ((vp->v_flag & VROOT) &&
2969		    (vp->v_mount->mnt_flag & MNT_UNION)) {
2970			struct vnode *tvp = vp;
2971			vp = vp->v_mount->mnt_vnodecovered;
2972			VREF(vp);
2973			fp->f_data = (caddr_t) vp;
2974			fp->f_offset = 0;
2975			vrele(tvp);
2976			goto unionread;
2977		}
2978	}
2979	if (SCARG(uap, basep) != NULL) {
2980		error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2981		    sizeof(long));
2982	}
2983	p->p_retval[0] = SCARG(uap, count) - auio.uio_resid;
2984	return (error);
2985}
2986#ifndef _SYS_SYSPROTO_H_
2987struct getdents_args {
2988	int fd;
2989	char *buf;
2990	size_t count;
2991};
2992#endif
2993int
2994getdents(p, uap)
2995	struct proc *p;
2996	register struct getdents_args /* {
2997		syscallarg(int) fd;
2998		syscallarg(char *) buf;
2999		syscallarg(u_int) count;
3000	} */ *uap;
3001{
3002	struct getdirentries_args ap;
3003	ap.fd = uap->fd;
3004	ap.buf = uap->buf;
3005	ap.count = uap->count;
3006	ap.basep = NULL;
3007	return getdirentries(p, &ap);
3008}
3009
3010/*
3011 * Set the mode mask for creation of filesystem nodes.
3012 *
3013 * MP SAFE
3014 */
3015#ifndef _SYS_SYSPROTO_H_
3016struct umask_args {
3017	int	newmask;
3018};
3019#endif
3020int
3021umask(p, uap)
3022	struct proc *p;
3023	struct umask_args /* {
3024		syscallarg(int) newmask;
3025	} */ *uap;
3026{
3027	register struct filedesc *fdp;
3028
3029	fdp = p->p_fd;
3030	p->p_retval[0] = fdp->fd_cmask;
3031	fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
3032	return (0);
3033}
3034
3035/*
3036 * Void all references to file by ripping underlying filesystem
3037 * away from vnode.
3038 */
3039#ifndef _SYS_SYSPROTO_H_
3040struct revoke_args {
3041	char	*path;
3042};
3043#endif
3044/* ARGSUSED */
3045int
3046revoke(p, uap)
3047	struct proc *p;
3048	register struct revoke_args /* {
3049		syscallarg(char *) path;
3050	} */ *uap;
3051{
3052	register struct vnode *vp;
3053	struct vattr vattr;
3054	int error;
3055	struct nameidata nd;
3056
3057	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
3058	if ((error = namei(&nd)) != 0)
3059		return (error);
3060	vp = nd.ni_vp;
3061	NDFREE(&nd, NDF_ONLY_PNBUF);
3062	if (vp->v_type != VCHR && vp->v_type != VBLK) {
3063		error = EINVAL;
3064		goto out;
3065	}
3066	if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
3067		goto out;
3068	if (p->p_ucred->cr_uid != vattr.va_uid &&
3069	    (error = suser_xxx(0, p, PRISON_ROOT)))
3070		goto out;
3071	if (vcount(vp) > 1)
3072		VOP_REVOKE(vp, REVOKEALL);
3073out:
3074	vrele(vp);
3075	return (error);
3076}
3077
3078/*
3079 * Convert a user file descriptor to a kernel file entry.
3080 */
3081int
3082getvnode(fdp, fd, fpp)
3083	struct filedesc *fdp;
3084	int fd;
3085	struct file **fpp;
3086{
3087	struct file *fp;
3088
3089	if ((u_int)fd >= fdp->fd_nfiles ||
3090	    (fp = fdp->fd_ofiles[fd]) == NULL)
3091		return (EBADF);
3092	if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO)
3093		return (EINVAL);
3094	*fpp = fp;
3095	return (0);
3096}
3097/*
3098 * Get (NFS) file handle
3099 */
3100#ifndef _SYS_SYSPROTO_H_
3101struct getfh_args {
3102	char	*fname;
3103	fhandle_t *fhp;
3104};
3105#endif
3106int
3107getfh(p, uap)
3108	struct proc *p;
3109	register struct getfh_args *uap;
3110{
3111	struct nameidata nd;
3112	fhandle_t fh;
3113	register struct vnode *vp;
3114	int error;
3115
3116	/*
3117	 * Must be super user
3118	 */
3119	error = suser(p);
3120	if (error)
3121		return (error);
3122	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
3123	error = namei(&nd);
3124	if (error)
3125		return (error);
3126	NDFREE(&nd, NDF_ONLY_PNBUF);
3127	vp = nd.ni_vp;
3128	bzero(&fh, sizeof(fh));
3129	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3130	error = VFS_VPTOFH(vp, &fh.fh_fid);
3131	vput(vp);
3132	if (error)
3133		return (error);
3134	error = copyout(&fh, uap->fhp, sizeof (fh));
3135	return (error);
3136}
3137
3138/*
3139 * syscall for the rpc.lockd to use to translate a NFS file handle into
3140 * an open descriptor.
3141 *
3142 * warning: do not remove the suser() call or this becomes one giant
3143 * security hole.
3144 */
3145#ifndef _SYS_SYSPROTO_H_
3146struct fhopen_args {
3147	const struct fhandle *u_fhp;
3148	int flags;
3149};
3150#endif
3151int
3152fhopen(p, uap)
3153	struct proc *p;
3154	struct fhopen_args /* {
3155		syscallarg(const struct fhandle *) u_fhp;
3156		syscallarg(int) flags;
3157	} */ *uap;
3158{
3159	struct mount *mp;
3160	struct vnode *vp;
3161	struct fhandle fhp;
3162	struct vattr vat;
3163	struct vattr *vap = &vat;
3164	struct flock lf;
3165	struct file *fp;
3166	register struct filedesc *fdp = p->p_fd;
3167	int fmode, mode, error, type;
3168	struct file *nfp;
3169	int indx;
3170
3171	/*
3172	 * Must be super user
3173	 */
3174	error = suser(p);
3175	if (error)
3176		return (error);
3177
3178	fmode = FFLAGS(SCARG(uap, flags));
3179	/* why not allow a non-read/write open for our lockd? */
3180	if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
3181		return (EINVAL);
3182	error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp));
3183	if (error)
3184		return(error);
3185	/* find the mount point */
3186	mp = vfs_getvfs(&fhp.fh_fsid);
3187	if (mp == NULL)
3188		return (ESTALE);
3189	/* now give me my vnode, it gets returned to me locked */
3190	error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
3191	if (error)
3192		return (error);
3193 	/*
3194	 * from now on we have to make sure not
3195	 * to forget about the vnode
3196	 * any error that causes an abort must vput(vp)
3197	 * just set error = err and 'goto bad;'.
3198	 */
3199
3200	/*
3201	 * from vn_open
3202	 */
3203	if (vp->v_type == VLNK) {
3204		error = EMLINK;
3205		goto bad;
3206	}
3207	if (vp->v_type == VSOCK) {
3208		error = EOPNOTSUPP;
3209		goto bad;
3210	}
3211	mode = 0;
3212	if (fmode & (FWRITE | O_TRUNC)) {
3213		if (vp->v_type == VDIR) {
3214			error = EISDIR;
3215			goto bad;
3216		}
3217		error = vn_writechk(vp);
3218		if (error)
3219			goto bad;
3220		mode |= VWRITE;
3221	}
3222	if (fmode & FREAD)
3223		mode |= VREAD;
3224	if (mode) {
3225		error = VOP_ACCESS(vp, mode, p->p_ucred, p);
3226		if (error)
3227			goto bad;
3228	}
3229	if (fmode & O_TRUNC) {
3230		VOP_UNLOCK(vp, 0, p);				/* XXX */
3231		VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
3232		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);	/* XXX */
3233		VATTR_NULL(vap);
3234		vap->va_size = 0;
3235		error = VOP_SETATTR(vp, vap, p->p_ucred, p);
3236		if (error)
3237			goto bad;
3238	}
3239	error = VOP_OPEN(vp, fmode, p->p_ucred, p);
3240	if (error)
3241		goto bad;
3242	/*
3243	 * Make sure that a VM object is created for VMIO support.
3244	 */
3245	if (vn_canvmio(vp) == TRUE) {
3246		if ((error = vfs_object_create(vp, p, p->p_ucred)) != 0)
3247			goto bad;
3248	}
3249	if (fmode & FWRITE)
3250		vp->v_writecount++;
3251
3252	/*
3253	 * end of vn_open code
3254	 */
3255
3256	if ((error = falloc(p, &nfp, &indx)) != 0)
3257		goto bad;
3258	fp = nfp;
3259	nfp->f_data = (caddr_t)vp;
3260	nfp->f_flag = fmode & FMASK;
3261	nfp->f_ops = &vnops;
3262	nfp->f_type = DTYPE_VNODE;
3263	if (fmode & (O_EXLOCK | O_SHLOCK)) {
3264		lf.l_whence = SEEK_SET;
3265		lf.l_start = 0;
3266		lf.l_len = 0;
3267		if (fmode & O_EXLOCK)
3268			lf.l_type = F_WRLCK;
3269		else
3270			lf.l_type = F_RDLCK;
3271		type = F_FLOCK;
3272		if ((fmode & FNONBLOCK) == 0)
3273			type |= F_WAIT;
3274		VOP_UNLOCK(vp, 0, p);
3275		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
3276			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
3277			ffree(fp);
3278			fdp->fd_ofiles[indx] = NULL;
3279			return (error);
3280		}
3281		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
3282		fp->f_flag |= FHASLOCK;
3283	}
3284	if ((vp->v_type == VREG) && (vp->v_object == NULL))
3285		vfs_object_create(vp, p, p->p_ucred);
3286
3287	VOP_UNLOCK(vp, 0, p);
3288	p->p_retval[0] = indx;
3289	return (0);
3290
3291bad:
3292	vput(vp);
3293	return (error);
3294}
3295
3296#ifndef _SYS_SYSPROTO_H_
3297struct fhstat_args {
3298	struct fhandle *u_fhp;
3299	struct stat *sb;
3300};
3301#endif
3302int
3303fhstat(p, uap)
3304	struct proc *p;
3305	register struct fhstat_args /* {
3306		syscallarg(struct fhandle *) u_fhp;
3307		syscallarg(struct stat *) sb;
3308	} */ *uap;
3309{
3310	struct stat sb;
3311	fhandle_t fh;
3312	struct mount *mp;
3313	struct vnode *vp;
3314	int error;
3315
3316	/*
3317	 * Must be super user
3318	 */
3319	error = suser(p);
3320	if (error)
3321		return (error);
3322
3323	error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t));
3324	if (error)
3325		return (error);
3326
3327	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3328		return (ESTALE);
3329	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3330		return (error);
3331	error = vn_stat(vp, &sb, p);
3332	vput(vp);
3333	if (error)
3334		return (error);
3335	error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
3336	return (error);
3337}
3338
3339#ifndef _SYS_SYSPROTO_H_
3340struct fhstatfs_args {
3341	struct fhandle *u_fhp;
3342	struct statfs *buf;
3343};
3344#endif
3345int
3346fhstatfs(p, uap)
3347	struct proc *p;
3348	struct fhstatfs_args /* {
3349		syscallarg(struct fhandle) *u_fhp;
3350		syscallarg(struct statfs) *buf;
3351	} */ *uap;
3352{
3353	struct statfs *sp;
3354	struct mount *mp;
3355	struct vnode *vp;
3356	struct statfs sb;
3357	fhandle_t fh;
3358	int error;
3359
3360	/*
3361	 * Must be super user
3362	 */
3363	if ((error = suser(p)))
3364		return (error);
3365
3366	if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0)
3367		return (error);
3368
3369	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
3370		return (ESTALE);
3371	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
3372		return (error);
3373	mp = vp->v_mount;
3374	sp = &mp->mnt_stat;
3375	vput(vp);
3376	if ((error = VFS_STATFS(mp, sp, p)) != 0)
3377		return (error);
3378	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3379	if (suser_xxx(p->p_ucred, 0, 0)) {
3380		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
3381		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3382		sp = &sb;
3383	}
3384	return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
3385}
3386
3387/*
3388 * Syscall to push extended attribute configuration information into the
3389 * VFS.  Accepts a path, which it converts to a mountpoint, as well as
3390 * a command (int cmd), and attribute name and misc data.  For now, the
3391 * attribute name is left in userspace for consumption by the VFS_op.
3392 * It will probably be changed to be copied into sysspace by the
3393 * syscall in the future, once issues with various consumers of the
3394 * attribute code have raised their hands.
3395 *
3396 * Currently this is used only by UFS Extended Attributes.
3397 */
3398int
3399extattrctl(p, uap)
3400	struct proc *p;
3401	struct extattrctl_args *uap;
3402{
3403	struct nameidata nd;
3404	struct mount *mp;
3405	int error;
3406
3407	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
3408	if ((error = namei(&nd)) != 0)
3409		return (error);
3410	mp = nd.ni_vp->v_mount;
3411	NDFREE(&nd, 0);
3412	return (VFS_EXTATTRCTL(mp, SCARG(uap, cmd), SCARG(uap, attrname),
3413	    SCARG(uap, arg), p));
3414}
3415
3416/*
3417 * Syscall to set a named extended attribute on a file or directory.
3418 * Accepts attribute name, and a uio structure pointing to the data to set.
3419 * The uio is consumed in the style of writev().  The real work happens
3420 * in VOP_SETEXTATTR().
3421 */
3422int
3423extattr_set_file(p, uap)
3424	struct proc *p;
3425	struct extattr_set_file_args *uap;
3426{
3427	struct nameidata nd;
3428	struct uio auio;
3429	struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV];
3430	char attrname[EXTATTR_MAXNAMELEN];
3431	u_int iovlen, cnt;
3432	int error, i;
3433
3434	error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3435	if (error)
3436		return (error);
3437	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, SCARG(uap, path),
3438	    p);
3439	if ((error = namei(&nd)) != 0)
3440		return(error);
3441	iovlen = uap->iovcnt * sizeof(struct iovec);
3442	if (uap->iovcnt > UIO_SMALLIOV) {
3443		if (uap->iovcnt > UIO_MAXIOV) {
3444			error = EINVAL;
3445			goto done;
3446		}
3447		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
3448		needfree = iov;
3449	} else
3450		iov = aiov;
3451	auio.uio_iov = iov;
3452	auio.uio_iovcnt = uap->iovcnt;
3453	auio.uio_rw = UIO_WRITE;
3454	auio.uio_segflg = UIO_USERSPACE;
3455	auio.uio_procp = p;
3456	auio.uio_offset = 0;
3457	if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
3458		goto done;
3459	auio.uio_resid = 0;
3460	for (i = 0; i < uap->iovcnt; i++) {
3461		if (iov->iov_len > INT_MAX - auio.uio_resid) {
3462			error = EINVAL;
3463			goto done;
3464		}
3465		auio.uio_resid += iov->iov_len;
3466		iov++;
3467	}
3468	cnt = auio.uio_resid;
3469	error = VOP_SETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred,
3470	    p);
3471	if (auio.uio_resid != cnt && (error == ERESTART ||
3472	    error == EINTR || error == EWOULDBLOCK))
3473		error = 0;
3474	cnt -= auio.uio_resid;
3475	p->p_retval[0] = cnt;
3476done:
3477	if (needfree)
3478		FREE(needfree, M_IOV);
3479	NDFREE(&nd, 0);
3480	return (error);
3481}
3482
3483/*
3484 * Syscall to get a named extended attribute on a file or directory.
3485 * Accepts attribute name, and a uio structure pointing to a buffer for the
3486 * data.  The uio is consumed in the style of readv().  The real work
3487 * happens in VOP_GETEXTATTR();
3488 */
3489int
3490extattr_get_file(p, uap)
3491	struct proc *p;
3492	struct extattr_get_file_args *uap;
3493{
3494	struct nameidata nd;
3495	struct uio auio;
3496	struct iovec *iov, *needfree, aiov[UIO_SMALLIOV];
3497	char attrname[EXTATTR_MAXNAMELEN];
3498	u_int iovlen, cnt;
3499	int error, i;
3500
3501	error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3502	if (error)
3503		return (error);
3504	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
3505	if ((error = namei(&nd)) != 0)
3506		return (error);
3507	iovlen = uap->iovcnt * sizeof (struct iovec);
3508	if (uap->iovcnt > UIO_SMALLIOV) {
3509		if (uap->iovcnt > UIO_MAXIOV) {
3510			NDFREE(&nd, 0);
3511			return (EINVAL);
3512		}
3513		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
3514		needfree = iov;
3515	} else {
3516		iov = aiov;
3517		needfree = NULL;
3518	}
3519	auio.uio_iov = iov;
3520	auio.uio_iovcnt = uap->iovcnt;
3521	auio.uio_rw = UIO_READ;
3522	auio.uio_segflg = UIO_USERSPACE;
3523	auio.uio_procp = p;
3524	auio.uio_offset = 0;
3525	if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
3526		goto done;
3527	auio.uio_resid = 0;
3528	for (i = 0; i < uap->iovcnt; i++) {
3529		if (iov->iov_len > INT_MAX - auio.uio_resid) {
3530			error = EINVAL;
3531			goto done;
3532		}
3533		auio.uio_resid += iov->iov_len;
3534		iov++;
3535	}
3536	cnt = auio.uio_resid;
3537	error = VOP_GETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred,
3538	    p);
3539	if (auio.uio_resid != cnt && (error == ERESTART ||
3540	    error == EINTR || error == EWOULDBLOCK))
3541		error = 0;
3542	cnt -= auio.uio_resid;
3543	p->p_retval[0] = cnt;
3544done:
3545	if (needfree)
3546		FREE(needfree, M_IOV);
3547	NDFREE(&nd, 0);
3548	return(error);
3549}
3550
3551/*
3552 * Syscall to delete a named extended attribute from a file or directory.
3553 * Accepts attribute name.  The real work happens in VOP_SETEXTATTR().
3554 */
3555int
3556extattr_delete_file(p, uap)
3557	struct proc *p;
3558	struct extattr_delete_file_args *uap;
3559{
3560	struct nameidata nd;
3561	char attrname[EXTATTR_MAXNAMELEN];
3562	int	error;
3563
3564	error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3565	if (error)
3566		return(error);
3567	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, SCARG(uap, path),
3568	    p);
3569	if ((error = namei(&nd)) != 0)
3570		return(error);
3571	error = VOP_SETEXTATTR(nd.ni_vp, attrname, NULL, p->p_cred->pc_ucred,
3572	    p);
3573	NDFREE(&nd, 0);
3574	return(error);
3575}
3576