vfs_syscalls.c revision 3602
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 * $Id: vfs_syscalls.c,v 1.13 1994/10/11 20:40:12 sos Exp $
40 */
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/namei.h>
45#include <sys/filedesc.h>
46#include <sys/kernel.h>
47#include <sys/file.h>
48#include <sys/stat.h>
49#include <sys/vnode.h>
50#include <sys/mount.h>
51#include <sys/proc.h>
52#include <sys/uio.h>
53#include <sys/malloc.h>
54#include <sys/dirent.h>
55
56#include <vm/vm.h>
57#include <sys/sysctl.h>
58
59static int change_dir	__P((struct nameidata *ndp, struct proc *p));
60int getvnode __P((struct filedesc *, int, struct file **));
61
62/*
63 * Virtual File System System Calls
64 */
65
66/*
67 * Mount a file system.
68 */
69struct mount_args {
70	int	type;
71	char	*path;
72	int	flags;
73	caddr_t	data;
74};
75/* ARGSUSED */
76int
77mount(p, uap, retval)
78	struct proc *p;
79	register struct mount_args *uap;
80	int *retval;
81{
82	register struct vnode *vp;
83	register struct mount *mp;
84	int error, flag = 0;
85	struct nameidata nd;
86
87	/*
88	 * Must be super user
89	 */
90	error = suser(p->p_ucred, &p->p_acflag);
91	if (error)
92		return (error);
93	/*
94	 * Get vnode to be covered
95	 */
96	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
97	error = namei(&nd);
98	if (error)
99		return (error);
100	vp = nd.ni_vp;
101	if (uap->flags & MNT_UPDATE) {
102		if ((vp->v_flag & VROOT) == 0) {
103			vput(vp);
104			return (EINVAL);
105		}
106		mp = vp->v_mount;
107		flag = mp->mnt_flag;
108		/*
109		 * We only allow the filesystem to be reloaded if it
110		 * is currently mounted read-only.
111		 */
112		if ((uap->flags & MNT_RELOAD) &&
113		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
114			vput(vp);
115			return (EOPNOTSUPP);	/* Needs translation */
116		}
117		mp->mnt_flag |=
118		    uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
119		VOP_UNLOCK(vp);
120		goto update;
121	}
122	error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0);
123	if (error)
124		return (error);
125	if (vp->v_type != VDIR) {
126		vput(vp);
127		return (ENOTDIR);
128	}
129	if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) {
130		vput(vp);
131		return (ENODEV);
132	}
133
134	/*
135	 * Allocate and initialize the file system.
136	 */
137	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
138		M_MOUNT, M_WAITOK);
139	bzero((char *)mp, (u_long)sizeof(struct mount));
140	mp->mnt_op = vfssw[uap->type];
141	mp->mnt_vfc = vfsconf[uap->type];
142	error = vfs_lock(mp);
143	if (error) {
144		free((caddr_t)mp, M_MOUNT);
145		vput(vp);
146		return (error);
147	}
148	if (vp->v_mountedhere != NULL) {
149		vfs_unlock(mp);
150		free((caddr_t)mp, M_MOUNT);
151		vput(vp);
152		return (EBUSY);
153	}
154	vp->v_mountedhere = mp;
155	mp->mnt_vnodecovered = vp;
156	vfsconf[uap->type]->vfc_refcount++;
157
158update:
159	/*
160	 * Set the mount level flags.
161	 */
162	if (uap->flags & MNT_RDONLY)
163		mp->mnt_flag |= MNT_RDONLY;
164	else if (mp->mnt_flag & MNT_RDONLY)
165		mp->mnt_flag |= MNT_WANTRDWR;
166	mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
167	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
168	mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
169	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
170	/*
171	 * Mount the filesystem.
172	 */
173	error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p);
174	if (mp->mnt_flag & MNT_UPDATE) {
175		vrele(vp);
176		if (mp->mnt_flag & MNT_WANTRDWR)
177			mp->mnt_flag &= ~MNT_RDONLY;
178		mp->mnt_flag &=~
179		    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
180		if (error)
181			mp->mnt_flag = flag;
182		return (error);
183	}
184	/*
185	 * Put the new filesystem on the mount list after root.
186	 */
187	cache_purge(vp);
188	if (!error) {
189		TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
190		VOP_UNLOCK(vp);
191		vfs_unlock(mp);
192		error = VFS_START(mp, 0, p);
193	} else {
194		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
195		vfs_unlock(mp);
196		free((caddr_t)mp, M_MOUNT);
197		vput(vp);
198		vfsconf[uap->type]->vfc_refcount--;
199	}
200	return (error);
201}
202
203/*
204 * Unmount a file system.
205 *
206 * Note: unmount takes a path to the vnode mounted on as argument,
207 * not special file (as before).
208 */
209struct unmount_args {
210	char	*path;
211	int	flags;
212};
213/* ARGSUSED */
214int
215unmount(p, uap, retval)
216	struct proc *p;
217	register struct unmount_args *uap;
218	int *retval;
219{
220	register struct vnode *vp;
221	struct mount *mp;
222	int error;
223	struct nameidata nd;
224
225	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
226	error = namei(&nd);
227	if (error)
228		return (error);
229	vp = nd.ni_vp;
230
231	/*
232	 * Unless this is a user mount, then must
233	 * have suser privilege.
234	 */
235	if (((vp->v_mount->mnt_flag & MNT_USER) == 0) &&
236	    (error = suser(p->p_ucred, &p->p_acflag))) {
237		vput(vp);
238		return (error);
239	}
240
241	/*
242	 * Must be the root of the filesystem
243	 */
244	if ((vp->v_flag & VROOT) == 0) {
245		vput(vp);
246		return (EINVAL);
247	}
248	mp = vp->v_mount;
249	vput(vp);
250
251	/*
252	 * Don't allow unmount of the root filesystem
253	 */
254	if (mp->mnt_flag & MNT_ROOTFS)
255		return (EINVAL);
256
257	return (dounmount(mp, uap->flags, p));
258}
259
260/*
261 * Do the actual file system unmount.
262 */
263int
264dounmount(mp, flags, p)
265	register struct mount *mp;
266	int flags;
267	struct proc *p;
268{
269	struct vnode *coveredvp;
270	int error;
271
272	coveredvp = mp->mnt_vnodecovered;
273	if (vfs_busy(mp))
274		return (EBUSY);
275	mp->mnt_flag |= MNT_UNMOUNT;
276	error = vfs_lock(mp);
277	if (error)
278		return (error);
279
280	mp->mnt_flag &=~ MNT_ASYNC;
281	vnode_pager_umount(mp);	/* release cached vnodes */
282	cache_purgevfs(mp);	/* remove cache entries for this file sys */
283	if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
284	    (flags & MNT_FORCE))
285		error = VFS_UNMOUNT(mp, flags, p);
286	mp->mnt_flag &= ~MNT_UNMOUNT;
287	vfs_unbusy(mp);
288	if (error) {
289		vfs_unlock(mp);
290	} else {
291		vrele(coveredvp);
292		TAILQ_REMOVE(&mountlist, mp, mnt_list);
293		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
294		vfs_unlock(mp);
295		mp->mnt_vfc->vfc_refcount--;
296		if (mp->mnt_vnodelist.lh_first != NULL)
297			panic("unmount: dangling vnode");
298		free((caddr_t)mp, M_MOUNT);
299	}
300	return (error);
301}
302
303/*
304 * Sync each mounted filesystem.
305 */
306#ifdef DIAGNOSTIC
307int syncprt = 0;
308struct ctldebug debug0 = { "syncprt", &syncprt };
309#endif
310
311struct sync_args {
312	int	dummy;
313};
314/* ARGSUSED */
315int
316sync(p, uap, retval)
317	struct proc *p;
318	struct sync_args *uap;
319	int *retval;
320{
321	register struct mount *mp, *nmp;
322	int asyncflag;
323
324	for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
325		nmp = mp->mnt_list.tqe_next;
326		/*
327		 * The lock check below is to avoid races with mount
328		 * and unmount.
329		 */
330		if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
331		    !vfs_busy(mp)) {
332			asyncflag = mp->mnt_flag & MNT_ASYNC;
333			mp->mnt_flag &= ~MNT_ASYNC;
334			VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
335			if (asyncflag)
336				mp->mnt_flag |= MNT_ASYNC;
337			vfs_unbusy(mp);
338		}
339	}
340#ifdef DIAGNOSTIC
341	if (syncprt)
342		vfs_bufstats();
343#endif /* DIAGNOSTIC */
344	return (0);
345}
346
347/*
348 * Change filesystem quotas.
349 */
350struct quotactl_args {
351	char *path;
352	int cmd;
353	int uid;
354	caddr_t arg;
355};
356/* ARGSUSED */
357int
358quotactl(p, uap, retval)
359	struct proc *p;
360	register struct quotactl_args *uap;
361	int *retval;
362{
363	register struct mount *mp;
364	int error;
365	struct nameidata nd;
366
367	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
368	error = namei(&nd);
369	if (error)
370		return (error);
371	mp = nd.ni_vp->v_mount;
372	vrele(nd.ni_vp);
373	return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
374}
375
376/*
377 * Get filesystem statistics.
378 */
379struct statfs_args {
380	char *path;
381	struct statfs *buf;
382};
383/* ARGSUSED */
384int
385statfs(p, uap, retval)
386	struct proc *p;
387	register struct statfs_args *uap;
388	int *retval;
389{
390	register struct mount *mp;
391	register struct statfs *sp;
392	int error;
393	struct nameidata nd;
394
395	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
396	error = namei(&nd);
397	if (error)
398		return (error);
399	mp = nd.ni_vp->v_mount;
400	sp = &mp->mnt_stat;
401	vrele(nd.ni_vp);
402	error = VFS_STATFS(mp, sp, p);
403	if (error)
404		return (error);
405	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
406	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
407}
408
409/*
410 * Get filesystem statistics.
411 */
412struct fstatfs_args {
413	int fd;
414	struct statfs *buf;
415};
416/* ARGSUSED */
417int
418fstatfs(p, uap, retval)
419	struct proc *p;
420	register struct fstatfs_args *uap;
421	int *retval;
422{
423	struct file *fp;
424	struct mount *mp;
425	register struct statfs *sp;
426	int error;
427
428	error = getvnode(p->p_fd, uap->fd, &fp);
429	if (error)
430		return (error);
431	mp = ((struct vnode *)fp->f_data)->v_mount;
432	sp = &mp->mnt_stat;
433	error = VFS_STATFS(mp, sp, p);
434	if (error)
435		return (error);
436	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
437	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
438}
439
440/*
441 * Get statistics on all filesystems.
442 */
443struct getfsstat_args {
444	struct statfs *buf;
445	long bufsize;
446	int flags;
447};
448int
449getfsstat(p, uap, retval)
450	struct proc *p;
451	register struct getfsstat_args *uap;
452	int *retval;
453{
454	register struct mount *mp, *nmp;
455	register struct statfs *sp;
456	caddr_t sfsp;
457	long count, maxcount, error;
458
459	maxcount = uap->bufsize / sizeof(struct statfs);
460	sfsp = (caddr_t)uap->buf;
461	for (count = 0, mp = mountlist.tqh_first; mp != NULL; mp = nmp) {
462		nmp = mp->mnt_list.tqe_next;
463		if (sfsp && count < maxcount &&
464		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
465			sp = &mp->mnt_stat;
466			/*
467			 * If MNT_NOWAIT is specified, do not refresh the
468			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
469			 */
470			if (((uap->flags & MNT_NOWAIT) == 0 ||
471			    (uap->flags & MNT_WAIT)) &&
472			    (error = VFS_STATFS(mp, sp, p)))
473				continue;
474			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
475			error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
476			if (error)
477				return (error);
478			sfsp += sizeof(*sp);
479		}
480		count++;
481	}
482	if (sfsp && count > maxcount)
483		*retval = maxcount;
484	else
485		*retval = count;
486	return (0);
487}
488
489/*
490 * Change current working directory to a given file descriptor.
491 */
492struct fchdir_args {
493	int	fd;
494};
495/* ARGSUSED */
496int
497fchdir(p, uap, retval)
498	struct proc *p;
499	struct fchdir_args *uap;
500	int *retval;
501{
502	register struct filedesc *fdp = p->p_fd;
503	register struct vnode *vp;
504	struct file *fp;
505	int error;
506
507	error = getvnode(fdp, uap->fd, &fp);
508	if (error)
509		return (error);
510	vp = (struct vnode *)fp->f_data;
511	VOP_LOCK(vp);
512	if (vp->v_type != VDIR)
513		error = ENOTDIR;
514	else
515		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
516	VOP_UNLOCK(vp);
517	if (error)
518		return (error);
519	VREF(vp);
520	vrele(fdp->fd_cdir);
521	fdp->fd_cdir = vp;
522	return (0);
523}
524
525/*
526 * Change current working directory (``.'').
527 */
528struct chdir_args {
529	char	*path;
530};
531/* ARGSUSED */
532int
533chdir(p, uap, retval)
534	struct proc *p;
535	struct chdir_args *uap;
536	int *retval;
537{
538	register struct filedesc *fdp = p->p_fd;
539	int error;
540	struct nameidata nd;
541
542	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
543	error = change_dir(&nd, p);
544	if (error)
545		return (error);
546	vrele(fdp->fd_cdir);
547	fdp->fd_cdir = nd.ni_vp;
548	return (0);
549}
550
551/*
552 * Change notion of root (``/'') directory.
553 */
554struct chroot_args {
555	char	*path;
556};
557/* ARGSUSED */
558int
559chroot(p, uap, retval)
560	struct proc *p;
561	struct chroot_args *uap;
562	int *retval;
563{
564	register struct filedesc *fdp = p->p_fd;
565	int error;
566	struct nameidata nd;
567
568	error = suser(p->p_ucred, &p->p_acflag);
569	if (error)
570		return (error);
571	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
572	error = change_dir(&nd, p);
573	if (error)
574		return (error);
575	if (fdp->fd_rdir != NULL)
576		vrele(fdp->fd_rdir);
577	fdp->fd_rdir = nd.ni_vp;
578	return (0);
579}
580
581/*
582 * Common routine for chroot and chdir.
583 */
584static int
585change_dir(ndp, p)
586	register struct nameidata *ndp;
587	struct proc *p;
588{
589	struct vnode *vp;
590	int error;
591
592	error = namei(ndp);
593	if (error)
594		return (error);
595	vp = ndp->ni_vp;
596	if (vp->v_type != VDIR)
597		error = ENOTDIR;
598	else
599		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
600	VOP_UNLOCK(vp);
601	if (error)
602		vrele(vp);
603	return (error);
604}
605
606/*
607 * Check permissions, allocate an open file structure,
608 * and call the device open routine if any.
609 */
610struct open_args {
611	char	*path;
612	int	flags;
613	int	mode;
614};
615int
616open(p, uap, retval)
617	struct proc *p;
618	register struct open_args *uap;
619	int *retval;
620{
621	register struct filedesc *fdp = p->p_fd;
622	register struct file *fp;
623	register struct vnode *vp;
624	int flags, cmode;
625	struct file *nfp;
626	int type, indx, error;
627	struct flock lf;
628	struct nameidata nd;
629	extern struct fileops vnops;
630
631	error = falloc(p, &nfp, &indx);
632	if (error)
633		return (error);
634	fp = nfp;
635	flags = FFLAGS(uap->flags);
636	cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
637	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
638	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
639	error = vn_open(&nd, flags, cmode);
640	if (error) {
641		ffree(fp);
642		if ((error == ENODEV || error == ENXIO) &&
643		    p->p_dupfd >= 0 && 			/* XXX from fdopen */
644		    (error =
645		        dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
646			*retval = indx;
647			return (0);
648		}
649		if (error == ERESTART)
650			error = EINTR;
651		fdp->fd_ofiles[indx] = NULL;
652		return (error);
653	}
654	p->p_dupfd = 0;
655	vp = nd.ni_vp;
656	fp->f_flag = flags & FMASK;
657	fp->f_type = DTYPE_VNODE;
658	fp->f_ops = &vnops;
659	fp->f_data = (caddr_t)vp;
660	if (flags & (O_EXLOCK | O_SHLOCK)) {
661		lf.l_whence = SEEK_SET;
662		lf.l_start = 0;
663		lf.l_len = 0;
664		if (flags & O_EXLOCK)
665			lf.l_type = F_WRLCK;
666		else
667			lf.l_type = F_RDLCK;
668		type = F_FLOCK;
669		if ((flags & FNONBLOCK) == 0)
670			type |= F_WAIT;
671		VOP_UNLOCK(vp);
672		error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
673		if (error) {
674			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
675			ffree(fp);
676			fdp->fd_ofiles[indx] = NULL;
677			return (error);
678		}
679		VOP_LOCK(vp);
680		fp->f_flag |= FHASLOCK;
681	}
682	VOP_UNLOCK(vp);
683	*retval = indx;
684	return (0);
685}
686
687#ifdef COMPAT_43
688/*
689 * Create a file.
690 */
691struct ocreat_args {
692	char	*path;
693	int	mode;
694};
695int
696ocreat(p, uap, retval)
697	struct proc *p;
698	register struct ocreat_args *uap;
699	int *retval;
700{
701	struct open_args openuap;
702
703	openuap.path = uap->path;
704	openuap.mode = uap->mode;
705	openuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
706	return (open(p, &openuap, retval));
707}
708#endif /* COMPAT_43 */
709
710/*
711 * Create a special file.
712 */
713struct mknod_args {
714	char	*path;
715	int	mode;
716	int	dev;
717};
718/* ARGSUSED */
719int
720mknod(p, uap, retval)
721	struct proc *p;
722	register struct mknod_args *uap;
723	int *retval;
724{
725	register struct vnode *vp;
726	struct vattr vattr;
727	int error;
728	struct nameidata nd;
729
730	error = suser(p->p_ucred, &p->p_acflag);
731	if (error)
732		return (error);
733	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
734	error = namei(&nd);
735	if (error)
736		return (error);
737	vp = nd.ni_vp;
738	if (vp != NULL)
739		error = EEXIST;
740	else {
741		VATTR_NULL(&vattr);
742		vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
743		vattr.va_rdev = uap->dev;
744
745		switch (uap->mode & S_IFMT) {
746		case S_IFMT:	/* used by badsect to flag bad sectors */
747			vattr.va_type = VBAD;
748			break;
749		case S_IFCHR:
750			vattr.va_type = VCHR;
751			break;
752		case S_IFBLK:
753			vattr.va_type = VBLK;
754			break;
755		default:
756			error = EINVAL;
757			break;
758		}
759	}
760	if (!error) {
761		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
762		error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
763	} else {
764		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
765		if (nd.ni_dvp == vp)
766			vrele(nd.ni_dvp);
767		else
768			vput(nd.ni_dvp);
769		if (vp)
770			vrele(vp);
771	}
772	return (error);
773}
774
775/*
776 * Create named pipe.
777 */
778struct mkfifo_args {
779	char	*path;
780	int	mode;
781};
782/* ARGSUSED */
783int
784mkfifo(p, uap, retval)
785	struct proc *p;
786	register struct mkfifo_args *uap;
787	int *retval;
788{
789	struct vattr vattr;
790	int error;
791	struct nameidata nd;
792
793	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
794	error = namei(&nd);
795	if (error)
796		return (error);
797	if (nd.ni_vp != NULL) {
798		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
799		if (nd.ni_dvp == nd.ni_vp)
800			vrele(nd.ni_dvp);
801		else
802			vput(nd.ni_dvp);
803		vrele(nd.ni_vp);
804		return (EEXIST);
805	}
806	VATTR_NULL(&vattr);
807	vattr.va_type = VFIFO;
808	vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
809	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
810	return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
811}
812
813/*
814 * Make a hard file link.
815 */
816struct link_args {
817	char	*path;
818	char	*link;
819};
820/* ARGSUSED */
821int
822link(p, uap, retval)
823	struct proc *p;
824	register struct link_args *uap;
825	int *retval;
826{
827	register struct vnode *vp;
828	struct nameidata nd;
829	int error;
830
831	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
832	error = namei(&nd);
833	if (error)
834		return (error);
835	vp = nd.ni_vp;
836	if (vp->v_type != VDIR ||
837	    (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
838		nd.ni_cnd.cn_nameiop = CREATE;
839		nd.ni_cnd.cn_flags = LOCKPARENT;
840		nd.ni_dirp = uap->link;
841		error = namei(&nd);
842		if (!error) {
843			if (nd.ni_vp != NULL)
844				error = EEXIST;
845			if (!error) {
846				LEASE_CHECK(nd.ni_dvp,
847				    p, p->p_ucred, LEASE_WRITE);
848				LEASE_CHECK(vp,
849				    p, p->p_ucred, LEASE_WRITE);
850				error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
851			} else {
852				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
853				if (nd.ni_dvp == nd.ni_vp)
854					vrele(nd.ni_dvp);
855				else
856					vput(nd.ni_dvp);
857				if (nd.ni_vp)
858					vrele(nd.ni_vp);
859			}
860		}
861	}
862	vrele(vp);
863	return (error);
864}
865
866/*
867 * Make a symbolic link.
868 */
869struct symlink_args {
870	char	*path;
871	char	*link;
872};
873/* ARGSUSED */
874int
875symlink(p, uap, retval)
876	struct proc *p;
877	register struct symlink_args *uap;
878	int *retval;
879{
880	struct vattr vattr;
881	char *path;
882	int error;
883	struct nameidata nd;
884
885	MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
886	error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
887	if (error)
888		goto out;
889	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
890	error = namei(&nd);
891	if (error)
892		goto out;
893	if (nd.ni_vp) {
894		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
895		if (nd.ni_dvp == nd.ni_vp)
896			vrele(nd.ni_dvp);
897		else
898			vput(nd.ni_dvp);
899		vrele(nd.ni_vp);
900		error = EEXIST;
901		goto out;
902	}
903	VATTR_NULL(&vattr);
904	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
905	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
906	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
907out:
908	FREE(path, M_NAMEI);
909	return (error);
910}
911
912/*
913 * Delete a name from the filesystem.
914 */
915struct unlink_args {
916	char	*path;
917};
918/* ARGSUSED */
919int
920unlink(p, uap, retval)
921	struct proc *p;
922	struct unlink_args *uap;
923	int *retval;
924{
925	register struct vnode *vp;
926	int error;
927	struct nameidata nd;
928
929	NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
930	error = namei(&nd);
931	if (error)
932		return (error);
933	vp = nd.ni_vp;
934	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
935	VOP_LOCK(vp);
936
937	if (vp->v_type != VDIR ||
938	    (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
939		/*
940		 * The root of a mounted filesystem cannot be deleted.
941		 */
942		if (vp->v_flag & VROOT)
943			error = EBUSY;
944		else
945			(void)vnode_pager_uncache(vp);
946	}
947
948	if (!error) {
949		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
950		error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
951	} else {
952		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
953		if (nd.ni_dvp == vp)
954			vrele(nd.ni_dvp);
955		else
956			vput(nd.ni_dvp);
957		vput(vp);
958	}
959	return (error);
960}
961
962/*
963 * Reposition read/write file offset.
964 */
965struct lseek_args {
966	int	fd;
967	int	pad;
968	off_t	offset;
969	int	whence;
970};
971int
972lseek(p, uap, retval)
973	struct proc *p;
974	register struct lseek_args *uap;
975	int *retval;
976{
977	struct ucred *cred = p->p_ucred;
978	register struct filedesc *fdp = p->p_fd;
979	register struct file *fp;
980	struct vattr vattr;
981	int error;
982
983	if ((u_int)uap->fd >= fdp->fd_nfiles ||
984	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
985		return (EBADF);
986	if (fp->f_type != DTYPE_VNODE)
987		return (ESPIPE);
988	switch (uap->whence) {
989	case L_INCR:
990		fp->f_offset += uap->offset;
991		break;
992	case L_XTND:
993		error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
994		if (error)
995			return (error);
996		fp->f_offset = uap->offset + vattr.va_size;
997		break;
998	case L_SET:
999		fp->f_offset = uap->offset;
1000		break;
1001	default:
1002		return (EINVAL);
1003	}
1004	*(off_t *)retval = fp->f_offset;
1005	return (0);
1006}
1007
1008#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1009/*
1010 * Reposition read/write file offset.
1011 */
1012struct olseek_args {
1013	int	fd;
1014	long	offset;
1015	int	whence;
1016};
1017int
1018olseek(p, uap, retval)
1019	struct proc *p;
1020	register struct olseek_args *uap;
1021	int *retval;
1022{
1023	struct lseek_args nuap;
1024	off_t qret;
1025	int error;
1026
1027	nuap.fd = uap->fd;
1028	nuap.offset = uap->offset;
1029	nuap.whence = uap->whence;
1030	error = lseek(p, &nuap, &qret);
1031	*(long *)retval = qret;
1032	return (error);
1033}
1034#endif /* COMPAT_43 */
1035
1036/*
1037 * Check access permissions.
1038 */
1039struct access_args {
1040	char	*path;
1041	int	flags;
1042};
1043int
1044access(p, uap, retval)
1045	struct proc *p;
1046	register struct access_args *uap;
1047	int *retval;
1048{
1049	register struct ucred *cred = p->p_ucred;
1050	register struct vnode *vp;
1051	int error, flags, t_gid, t_uid;
1052	struct nameidata nd;
1053
1054	t_uid = cred->cr_uid;
1055	t_gid = cred->cr_groups[0];
1056	cred->cr_uid = p->p_cred->p_ruid;
1057	cred->cr_groups[0] = p->p_cred->p_rgid;
1058	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1059	error = namei(&nd);
1060	if (error)
1061		goto out1;
1062	vp = nd.ni_vp;
1063
1064	/* Flags == 0 means only check for existence. */
1065	if (uap->flags) {
1066		flags = 0;
1067		if (uap->flags & R_OK)
1068			flags |= VREAD;
1069		if (uap->flags & W_OK)
1070			flags |= VWRITE;
1071		if (uap->flags & X_OK)
1072			flags |= VEXEC;
1073		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1074			error = VOP_ACCESS(vp, flags, cred, p);
1075	}
1076	vput(vp);
1077out1:
1078	cred->cr_uid = t_uid;
1079	cred->cr_groups[0] = t_gid;
1080	return (error);
1081}
1082
1083#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1084/*
1085 * Get file status; this version follows links.
1086 */
1087struct ostat_args {
1088	char	*path;
1089	struct ostat *ub;
1090};
1091/* ARGSUSED */
1092int
1093ostat(p, uap, retval)
1094	struct proc *p;
1095	register struct ostat_args *uap;
1096	int *retval;
1097{
1098	struct stat sb;
1099	struct ostat osb;
1100	int error;
1101	struct nameidata nd;
1102
1103	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1104	error = namei(&nd);
1105	if (error)
1106		return (error);
1107	error = vn_stat(nd.ni_vp, &sb, p);
1108	vput(nd.ni_vp);
1109	if (error)
1110		return (error);
1111	cvtstat(&sb, &osb);
1112	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1113	return (error);
1114}
1115
1116/*
1117 * Get file status; this version does not follow links.
1118 */
1119struct olstat_args {
1120	char	*path;
1121	struct ostat *ub;
1122};
1123/* ARGSUSED */
1124int
1125olstat(p, uap, retval)
1126	struct proc *p;
1127	register struct olstat_args *uap;
1128	int *retval;
1129{
1130	struct vnode *vp, *dvp;
1131	struct stat sb, sb1;
1132	struct ostat osb;
1133	int error;
1134	struct nameidata nd;
1135
1136	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1137	    uap->path, p);
1138	error = namei(&nd);
1139	if (error)
1140		return (error);
1141	/*
1142	 * For symbolic links, always return the attributes of its
1143	 * containing directory, except for mode, size, and links.
1144	 */
1145	vp = nd.ni_vp;
1146	dvp = nd.ni_dvp;
1147	if (vp->v_type != VLNK) {
1148		if (dvp == vp)
1149			vrele(dvp);
1150		else
1151			vput(dvp);
1152		error = vn_stat(vp, &sb, p);
1153		vput(vp);
1154		if (error)
1155			return (error);
1156	} else {
1157		error = vn_stat(dvp, &sb, p);
1158		vput(dvp);
1159		if (error) {
1160			vput(vp);
1161			return (error);
1162		}
1163		error = vn_stat(vp, &sb1, p);
1164		vput(vp);
1165		if (error)
1166			return (error);
1167		sb.st_mode &= ~S_IFDIR;
1168		sb.st_mode |= S_IFLNK;
1169		sb.st_nlink = sb1.st_nlink;
1170		sb.st_size = sb1.st_size;
1171		sb.st_blocks = sb1.st_blocks;
1172	}
1173	cvtstat(&sb, &osb);
1174	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1175	return (error);
1176}
1177
1178/*
1179 * Convert from an old to a new stat structure.
1180 */
1181void
1182cvtstat(st, ost)
1183	struct stat *st;
1184	struct ostat *ost;
1185{
1186
1187	ost->st_dev = st->st_dev;
1188	ost->st_ino = st->st_ino;
1189	ost->st_mode = st->st_mode;
1190	ost->st_nlink = st->st_nlink;
1191	ost->st_uid = st->st_uid;
1192	ost->st_gid = st->st_gid;
1193	ost->st_rdev = st->st_rdev;
1194	if (st->st_size < (quad_t)1 << 32)
1195		ost->st_size = st->st_size;
1196	else
1197		ost->st_size = -2;
1198	ost->st_atime = st->st_atime;
1199	ost->st_mtime = st->st_mtime;
1200	ost->st_ctime = st->st_ctime;
1201	ost->st_blksize = st->st_blksize;
1202	ost->st_blocks = st->st_blocks;
1203	ost->st_flags = st->st_flags;
1204	ost->st_gen = st->st_gen;
1205}
1206#endif /* COMPAT_43 || COMPAT_SUNOS */
1207
1208/*
1209 * Get file status; this version follows links.
1210 */
1211struct stat_args {
1212	char	*path;
1213	struct stat *ub;
1214};
1215/* ARGSUSED */
1216int
1217stat(p, uap, retval)
1218	struct proc *p;
1219	register struct stat_args *uap;
1220	int *retval;
1221{
1222	struct stat sb;
1223	int error;
1224	struct nameidata nd;
1225
1226	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1227	error = namei(&nd);
1228	if (error)
1229		return (error);
1230	error = vn_stat(nd.ni_vp, &sb, p);
1231	vput(nd.ni_vp);
1232	if (error)
1233		return (error);
1234	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1235	return (error);
1236}
1237
1238/*
1239 * Get file status; this version does not follow links.
1240 */
1241struct lstat_args {
1242	char	*path;
1243	struct stat *ub;
1244};
1245/* ARGSUSED */
1246int
1247lstat(p, uap, retval)
1248	struct proc *p;
1249	register struct lstat_args *uap;
1250	int *retval;
1251{
1252	int error;
1253	struct vnode *vp, *dvp;
1254	struct stat sb, sb1;
1255	struct nameidata nd;
1256
1257	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1258	    uap->path, p);
1259	error = namei(&nd);
1260	if (error)
1261		return (error);
1262	/*
1263	 * For symbolic links, always return the attributes of its
1264	 * containing directory, except for mode, size, and links.
1265	 */
1266	vp = nd.ni_vp;
1267	dvp = nd.ni_dvp;
1268	if (vp->v_type != VLNK) {
1269		if (dvp == vp)
1270			vrele(dvp);
1271		else
1272			vput(dvp);
1273		error = vn_stat(vp, &sb, p);
1274		vput(vp);
1275		if (error)
1276			return (error);
1277	} else {
1278		error = vn_stat(dvp, &sb, p);
1279		vput(dvp);
1280		if (error) {
1281			vput(vp);
1282			return (error);
1283		}
1284		error = vn_stat(vp, &sb1, p);
1285		vput(vp);
1286		if (error)
1287			return (error);
1288		sb.st_mode &= ~S_IFDIR;
1289		sb.st_mode |= S_IFLNK;
1290		sb.st_nlink = sb1.st_nlink;
1291		sb.st_size = sb1.st_size;
1292		sb.st_blocks = sb1.st_blocks;
1293	}
1294	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1295	return (error);
1296}
1297
1298/*
1299 * Get configurable pathname variables.
1300 */
1301struct pathconf_args {
1302	char	*path;
1303	int	name;
1304};
1305/* ARGSUSED */
1306int
1307pathconf(p, uap, retval)
1308	struct proc *p;
1309	register struct pathconf_args *uap;
1310	int *retval;
1311{
1312	int error;
1313	struct nameidata nd;
1314
1315	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1316	error = namei(&nd);
1317	if (error)
1318		return (error);
1319	error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
1320	vput(nd.ni_vp);
1321	return (error);
1322}
1323
1324/*
1325 * Return target name of a symbolic link.
1326 */
1327struct readlink_args {
1328	char	*path;
1329	char	*buf;
1330	int	count;
1331};
1332/* ARGSUSED */
1333int
1334readlink(p, uap, retval)
1335	struct proc *p;
1336	register struct readlink_args *uap;
1337	int *retval;
1338{
1339	register struct vnode *vp;
1340	struct iovec aiov;
1341	struct uio auio;
1342	int error;
1343	struct nameidata nd;
1344
1345	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1346	error = namei(&nd);
1347	if (error)
1348		return (error);
1349	vp = nd.ni_vp;
1350	if (vp->v_type != VLNK)
1351		error = EINVAL;
1352	else {
1353		aiov.iov_base = uap->buf;
1354		aiov.iov_len = uap->count;
1355		auio.uio_iov = &aiov;
1356		auio.uio_iovcnt = 1;
1357		auio.uio_offset = 0;
1358		auio.uio_rw = UIO_READ;
1359		auio.uio_segflg = UIO_USERSPACE;
1360		auio.uio_procp = p;
1361		auio.uio_resid = uap->count;
1362		error = VOP_READLINK(vp, &auio, p->p_ucred);
1363	}
1364	vput(vp);
1365	*retval = uap->count - auio.uio_resid;
1366	return (error);
1367}
1368
1369/*
1370 * Change flags of a file given a path name.
1371 */
1372struct chflags_args {
1373	char	*path;
1374	int	flags;
1375};
1376/* ARGSUSED */
1377int
1378chflags(p, uap, retval)
1379	struct proc *p;
1380	register struct chflags_args *uap;
1381	int *retval;
1382{
1383	register struct vnode *vp;
1384	struct vattr vattr;
1385	int error;
1386	struct nameidata nd;
1387
1388	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1389	error = namei(&nd);
1390	if (error)
1391		return (error);
1392	vp = nd.ni_vp;
1393	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1394	VOP_LOCK(vp);
1395	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1396		error = EROFS;
1397	else {
1398		VATTR_NULL(&vattr);
1399		vattr.va_flags = uap->flags;
1400		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1401	}
1402	vput(vp);
1403	return (error);
1404}
1405
1406/*
1407 * Change flags of a file given a file descriptor.
1408 */
1409struct fchflags_args {
1410	int	fd;
1411	int	flags;
1412};
1413/* ARGSUSED */
1414int
1415fchflags(p, uap, retval)
1416	struct proc *p;
1417	register struct fchflags_args *uap;
1418	int *retval;
1419{
1420	struct vattr vattr;
1421	struct vnode *vp;
1422	struct file *fp;
1423	int error;
1424
1425	error = getvnode(p->p_fd, uap->fd, &fp);
1426	if (error)
1427		return (error);
1428	vp = (struct vnode *)fp->f_data;
1429	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1430	VOP_LOCK(vp);
1431	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1432		error = EROFS;
1433	else {
1434		VATTR_NULL(&vattr);
1435		vattr.va_flags = uap->flags;
1436		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1437	}
1438	VOP_UNLOCK(vp);
1439	return (error);
1440}
1441
1442/*
1443 * Change mode of a file given path name.
1444 */
1445struct chmod_args {
1446	char	*path;
1447	int	mode;
1448};
1449/* ARGSUSED */
1450int
1451chmod(p, uap, retval)
1452	struct proc *p;
1453	register struct chmod_args *uap;
1454	int *retval;
1455{
1456	register struct vnode *vp;
1457	struct vattr vattr;
1458	int error;
1459	struct nameidata nd;
1460
1461	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1462	error = namei(&nd);
1463	if (error)
1464		return (error);
1465	vp = nd.ni_vp;
1466	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1467	VOP_LOCK(vp);
1468	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1469		error = EROFS;
1470	else {
1471		VATTR_NULL(&vattr);
1472		vattr.va_mode = uap->mode & ALLPERMS;
1473		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1474	}
1475	vput(vp);
1476	return (error);
1477}
1478
1479/*
1480 * Change mode of a file given a file descriptor.
1481 */
1482struct fchmod_args {
1483	int	fd;
1484	int	mode;
1485};
1486/* ARGSUSED */
1487int
1488fchmod(p, uap, retval)
1489	struct proc *p;
1490	register struct fchmod_args *uap;
1491	int *retval;
1492{
1493	struct vattr vattr;
1494	struct vnode *vp;
1495	struct file *fp;
1496	int error;
1497
1498	error = getvnode(p->p_fd, uap->fd, &fp);
1499	if (error)
1500		return (error);
1501	vp = (struct vnode *)fp->f_data;
1502	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1503	VOP_LOCK(vp);
1504	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1505		error = EROFS;
1506	else {
1507		VATTR_NULL(&vattr);
1508		vattr.va_mode = uap->mode & ALLPERMS;
1509		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1510	}
1511	VOP_UNLOCK(vp);
1512	return (error);
1513}
1514
1515/*
1516 * Set ownership given a path name.
1517 */
1518struct chown_args {
1519	char	*path;
1520	int	uid;
1521	int	gid;
1522};
1523/* ARGSUSED */
1524int
1525chown(p, uap, retval)
1526	struct proc *p;
1527	register struct chown_args *uap;
1528	int *retval;
1529{
1530	register struct vnode *vp;
1531	struct vattr vattr;
1532	int error;
1533	struct nameidata nd;
1534
1535	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1536	error = namei(&nd);
1537	if (error)
1538		return (error);
1539	vp = nd.ni_vp;
1540	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1541	VOP_LOCK(vp);
1542	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1543		error = EROFS;
1544	else {
1545		VATTR_NULL(&vattr);
1546		vattr.va_uid = uap->uid;
1547		vattr.va_gid = uap->gid;
1548		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1549	}
1550	vput(vp);
1551	return (error);
1552}
1553
1554/*
1555 * Set ownership given a file descriptor.
1556 */
1557struct fchown_args {
1558	int	fd;
1559	int	uid;
1560	int	gid;
1561};
1562/* ARGSUSED */
1563int
1564fchown(p, uap, retval)
1565	struct proc *p;
1566	register struct fchown_args *uap;
1567	int *retval;
1568{
1569	struct vattr vattr;
1570	struct vnode *vp;
1571	struct file *fp;
1572	int error;
1573
1574	error = getvnode(p->p_fd, uap->fd, &fp);
1575	if (error)
1576		return (error);
1577	vp = (struct vnode *)fp->f_data;
1578	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1579	VOP_LOCK(vp);
1580	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1581		error = EROFS;
1582	else {
1583		VATTR_NULL(&vattr);
1584		vattr.va_uid = uap->uid;
1585		vattr.va_gid = uap->gid;
1586		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1587	}
1588	VOP_UNLOCK(vp);
1589	return (error);
1590}
1591
1592/*
1593 * Set the access and modification times of a file.
1594 */
1595struct utimes_args {
1596	char	*path;
1597	struct	timeval *tptr;
1598};
1599/* ARGSUSED */
1600int
1601utimes(p, uap, retval)
1602	struct proc *p;
1603	register struct utimes_args *uap;
1604	int *retval;
1605{
1606	register struct vnode *vp;
1607	struct timeval tv[2];
1608	struct vattr vattr;
1609	int error;
1610	struct nameidata nd;
1611
1612	VATTR_NULL(&vattr);
1613	if (uap->tptr == NULL) {
1614		microtime(&tv[0]);
1615		tv[1] = tv[0];
1616		vattr.va_vaflags |= VA_UTIMES_NULL;
1617	} else {
1618		error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv));
1619		if (error)
1620			return (error);
1621	}
1622	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1623	error = namei(&nd);
1624	if (error)
1625		return (error);
1626	vp = nd.ni_vp;
1627	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1628	VOP_LOCK(vp);
1629	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1630		error = EROFS;
1631	else {
1632		vattr.va_atime.ts_sec = tv[0].tv_sec;
1633		vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1634		vattr.va_mtime.ts_sec = tv[1].tv_sec;
1635		vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
1636		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1637	}
1638	vput(vp);
1639	return (error);
1640}
1641
1642/*
1643 * Truncate a file given its path name.
1644 */
1645struct truncate_args {
1646	char	*path;
1647	int	pad;
1648	off_t	length;
1649};
1650/* ARGSUSED */
1651int
1652truncate(p, uap, retval)
1653	struct proc *p;
1654	register struct truncate_args *uap;
1655	int *retval;
1656{
1657	register struct vnode *vp;
1658	struct vattr vattr;
1659	int error;
1660	struct nameidata nd;
1661
1662	if (uap->length < 0)
1663		return(EINVAL);
1664	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1665	error = namei(&nd);
1666	if (error)
1667		return (error);
1668	vp = nd.ni_vp;
1669	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1670	VOP_LOCK(vp);
1671	if (vp->v_type == VDIR)
1672		error = EISDIR;
1673	else if ((error = vn_writechk(vp)) == 0 &&
1674	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
1675		VATTR_NULL(&vattr);
1676		vattr.va_size = uap->length;
1677		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1678	}
1679	vput(vp);
1680	return (error);
1681}
1682
1683/*
1684 * Truncate a file given a file descriptor.
1685 */
1686struct ftruncate_args {
1687	int	fd;
1688	int	pad;
1689	off_t	length;
1690};
1691/* ARGSUSED */
1692int
1693ftruncate(p, uap, retval)
1694	struct proc *p;
1695	register struct ftruncate_args *uap;
1696	int *retval;
1697{
1698	struct vattr vattr;
1699	struct vnode *vp;
1700	struct file *fp;
1701	int error;
1702
1703	if (uap->length < 0)
1704		return(EINVAL);
1705	error = getvnode(p->p_fd, uap->fd, &fp);
1706	if (error)
1707		return (error);
1708	if ((fp->f_flag & FWRITE) == 0)
1709		return (EINVAL);
1710	vp = (struct vnode *)fp->f_data;
1711	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1712	VOP_LOCK(vp);
1713	if (vp->v_type == VDIR)
1714		error = EISDIR;
1715	else if ((error = vn_writechk(vp)) == 0) {
1716		VATTR_NULL(&vattr);
1717		vattr.va_size = uap->length;
1718		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1719	}
1720	VOP_UNLOCK(vp);
1721	return (error);
1722}
1723
1724#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1725/*
1726 * Truncate a file given its path name.
1727 */
1728struct otruncate_args {
1729	char	*path;
1730	long	length;
1731};
1732/* ARGSUSED */
1733int
1734otruncate(p, uap, retval)
1735	struct proc *p;
1736	register struct otruncate_args *uap;
1737	int *retval;
1738{
1739	struct truncate_args nuap;
1740
1741	nuap.path = uap->path;
1742	nuap.length = uap->length;
1743	return (truncate(p, &nuap, retval));
1744}
1745
1746/*
1747 * Truncate a file given a file descriptor.
1748 */
1749struct oftruncate_args {
1750	int	fd;
1751	long	length;
1752};
1753/* ARGSUSED */
1754int
1755oftruncate(p, uap, retval)
1756	struct proc *p;
1757	register struct oftruncate_args *uap;
1758	int *retval;
1759{
1760	struct ftruncate_args nuap;
1761
1762	nuap.fd = uap->fd;
1763	nuap.length = uap->length;
1764	return (ftruncate(p, &nuap, retval));
1765}
1766#endif /* COMPAT_43 || COMPAT_SUNOS */
1767
1768/*
1769 * Sync an open file.
1770 */
1771struct fsync_args {
1772	int	fd;
1773};
1774/* ARGSUSED */
1775int
1776fsync(p, uap, retval)
1777	struct proc *p;
1778	struct fsync_args *uap;
1779	int *retval;
1780{
1781	register struct vnode *vp;
1782	struct file *fp;
1783	int error;
1784
1785	error = getvnode(p->p_fd, uap->fd, &fp);
1786	if (error)
1787		return (error);
1788	vp = (struct vnode *)fp->f_data;
1789	VOP_LOCK(vp);
1790	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
1791	VOP_UNLOCK(vp);
1792	return (error);
1793}
1794
1795/*
1796 * Rename files.  Source and destination must either both be directories,
1797 * or both not be directories.  If target is a directory, it must be empty.
1798 */
1799struct rename_args {
1800	char	*from;
1801	char	*to;
1802};
1803/* ARGSUSED */
1804int
1805rename(p, uap, retval)
1806	struct proc *p;
1807	register struct rename_args *uap;
1808	int *retval;
1809{
1810	register struct vnode *tvp, *fvp, *tdvp;
1811	struct nameidata fromnd, tond;
1812	int error;
1813
1814	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1815		uap->from, p);
1816	error = namei(&fromnd);
1817	if (error)
1818		return (error);
1819	fvp = fromnd.ni_vp;
1820	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1821		UIO_USERSPACE, uap->to, p);
1822	error = namei(&tond);
1823	if (error) {
1824		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1825		vrele(fromnd.ni_dvp);
1826		vrele(fvp);
1827		goto out1;
1828	}
1829	tdvp = tond.ni_dvp;
1830	tvp = tond.ni_vp;
1831	if (tvp != NULL) {
1832		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1833			error = ENOTDIR;
1834			goto out;
1835		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1836			error = EISDIR;
1837			goto out;
1838		}
1839	}
1840	if (fvp == tdvp)
1841		error = EINVAL;
1842	/*
1843	 * If source is the same as the destination (that is the
1844	 * same inode number with the same name in the same directory),
1845	 * then there is nothing to do.
1846	 */
1847	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1848	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1849	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1850	      fromnd.ni_cnd.cn_namelen))
1851		error = -1;
1852out:
1853	if (!error) {
1854		LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
1855		if (fromnd.ni_dvp != tdvp)
1856			LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1857		if (tvp)
1858			LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
1859		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1860				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1861	} else {
1862		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1863		if (tdvp == tvp)
1864			vrele(tdvp);
1865		else
1866			vput(tdvp);
1867		if (tvp)
1868			vput(tvp);
1869		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1870		vrele(fromnd.ni_dvp);
1871		vrele(fvp);
1872	}
1873	vrele(tond.ni_startdir);
1874	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1875out1:
1876	if (fromnd.ni_startdir)
1877		vrele(fromnd.ni_startdir);
1878	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1879	if (error == -1)
1880		return (0);
1881	return (error);
1882}
1883
1884/*
1885 * Make a directory file.
1886 */
1887struct mkdir_args {
1888	char	*path;
1889	int	mode;
1890};
1891/* ARGSUSED */
1892int
1893mkdir(p, uap, retval)
1894	struct proc *p;
1895	register struct mkdir_args *uap;
1896	int *retval;
1897{
1898	register struct vnode *vp;
1899	struct vattr vattr;
1900	int error;
1901	struct nameidata nd;
1902
1903	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
1904	error = namei(&nd);
1905	if (error)
1906		return (error);
1907	vp = nd.ni_vp;
1908	if (vp != NULL) {
1909		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1910		if (nd.ni_dvp == vp)
1911			vrele(nd.ni_dvp);
1912		else
1913			vput(nd.ni_dvp);
1914		vrele(vp);
1915		return (EEXIST);
1916	}
1917	VATTR_NULL(&vattr);
1918	vattr.va_type = VDIR;
1919	vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
1920	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1921	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1922	if (!error)
1923		vput(nd.ni_vp);
1924	return (error);
1925}
1926
1927/*
1928 * Remove a directory file.
1929 */
1930struct rmdir_args {
1931	char	*path;
1932};
1933/* ARGSUSED */
1934int
1935rmdir(p, uap, retval)
1936	struct proc *p;
1937	struct rmdir_args *uap;
1938	int *retval;
1939{
1940	register struct vnode *vp;
1941	int error;
1942	struct nameidata nd;
1943
1944	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1945	error = namei(&nd);
1946	if (error)
1947		return (error);
1948	vp = nd.ni_vp;
1949	if (vp->v_type != VDIR) {
1950		error = ENOTDIR;
1951		goto out;
1952	}
1953	/*
1954	 * No rmdir "." please.
1955	 */
1956	if (nd.ni_dvp == vp) {
1957		error = EINVAL;
1958		goto out;
1959	}
1960	/*
1961	 * The root of a mounted filesystem cannot be deleted.
1962	 */
1963	if (vp->v_flag & VROOT)
1964		error = EBUSY;
1965out:
1966	if (!error) {
1967		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1968		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1969		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1970	} else {
1971		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1972		if (nd.ni_dvp == vp)
1973			vrele(nd.ni_dvp);
1974		else
1975			vput(nd.ni_dvp);
1976		vput(vp);
1977	}
1978	return (error);
1979}
1980
1981#ifdef COMPAT_43
1982/*
1983 * Read a block of directory entries in a file system independent format.
1984 */
1985struct ogetdirentries_args {
1986	int	fd;
1987	char	*buf;
1988	u_int	count;
1989	long	*basep;
1990};
1991int
1992ogetdirentries(p, uap, retval)
1993	struct proc *p;
1994	register struct ogetdirentries_args *uap;
1995	int *retval;
1996{
1997	register struct vnode *vp;
1998	struct file *fp;
1999	struct uio auio, kuio;
2000	struct iovec aiov, kiov;
2001	struct dirent *dp, *edp;
2002	caddr_t dirbuf;
2003	int error, readcnt;
2004	long loff;
2005
2006	error = getvnode(p->p_fd, uap->fd, &fp);
2007	if (error)
2008		return (error);
2009	if ((fp->f_flag & FREAD) == 0)
2010		return (EBADF);
2011	vp = (struct vnode *)fp->f_data;
2012	if (vp->v_type != VDIR)
2013		return (EINVAL);
2014	aiov.iov_base = uap->buf;
2015	aiov.iov_len = uap->count;
2016	auio.uio_iov = &aiov;
2017	auio.uio_iovcnt = 1;
2018	auio.uio_rw = UIO_READ;
2019	auio.uio_segflg = UIO_USERSPACE;
2020	auio.uio_procp = p;
2021	auio.uio_resid = uap->count;
2022	VOP_LOCK(vp);
2023	loff = auio.uio_offset = fp->f_offset;
2024#	if (BYTE_ORDER != LITTLE_ENDIAN)
2025		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
2026			error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL);
2027			fp->f_offset = auio.uio_offset;
2028		} else
2029#	endif
2030	{
2031		kuio = auio;
2032		kuio.uio_iov = &kiov;
2033		kuio.uio_segflg = UIO_SYSSPACE;
2034		kiov.iov_len = uap->count;
2035		MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
2036		kiov.iov_base = dirbuf;
2037		error = VOP_READDIR(vp, &kuio, fp->f_cred, NULL, NULL, NULL);
2038		fp->f_offset = kuio.uio_offset;
2039		if (error == 0) {
2040			readcnt = uap->count - kuio.uio_resid;
2041			edp = (struct dirent *)&dirbuf[readcnt];
2042			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
2043#				if (BYTE_ORDER == LITTLE_ENDIAN)
2044					/*
2045					 * The expected low byte of
2046					 * dp->d_namlen is our dp->d_type.
2047					 * The high MBZ byte of dp->d_namlen
2048					 * is our dp->d_namlen.
2049					 */
2050					dp->d_type = dp->d_namlen;
2051					dp->d_namlen = 0;
2052#				else
2053					/*
2054					 * The dp->d_type is the high byte
2055					 * of the expected dp->d_namlen,
2056					 * so must be zero'ed.
2057					 */
2058					dp->d_type = 0;
2059#				endif
2060				if (dp->d_reclen > 0) {
2061					dp = (struct dirent *)
2062					    ((char *)dp + dp->d_reclen);
2063				} else {
2064					error = EIO;
2065					break;
2066				}
2067			}
2068			if (dp >= edp)
2069				error = uiomove(dirbuf, readcnt, &auio);
2070		}
2071		FREE(dirbuf, M_TEMP);
2072	}
2073	VOP_UNLOCK(vp);
2074	if (error)
2075		return (error);
2076	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
2077	*retval = uap->count - auio.uio_resid;
2078	return (error);
2079}
2080#endif
2081
2082/*
2083 * Read a block of directory entries in a file system independent format.
2084 */
2085struct getdirentries_args {
2086	int	fd;
2087	char	*buf;
2088	u_int	count;
2089	long	*basep;
2090};
2091int
2092getdirentries(p, uap, retval)
2093	struct proc *p;
2094	register struct getdirentries_args *uap;
2095	int *retval;
2096{
2097	register struct vnode *vp;
2098	struct file *fp;
2099	struct uio auio;
2100	struct iovec aiov;
2101	long loff;
2102	int error;
2103
2104	error = getvnode(p->p_fd, uap->fd, &fp);
2105	if (error)
2106		return (error);
2107	if ((fp->f_flag & FREAD) == 0)
2108		return (EBADF);
2109	vp = (struct vnode *)fp->f_data;
2110unionread:
2111	if (vp->v_type != VDIR)
2112		return (EINVAL);
2113	aiov.iov_base = uap->buf;
2114	aiov.iov_len = uap->count;
2115	auio.uio_iov = &aiov;
2116	auio.uio_iovcnt = 1;
2117	auio.uio_rw = UIO_READ;
2118	auio.uio_segflg = UIO_USERSPACE;
2119	auio.uio_procp = p;
2120	auio.uio_resid = uap->count;
2121	VOP_LOCK(vp);
2122	loff = auio.uio_offset = fp->f_offset;
2123	error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL);
2124	fp->f_offset = auio.uio_offset;
2125	VOP_UNLOCK(vp);
2126	if (error)
2127		return (error);
2128
2129#ifdef UNION
2130{
2131	extern int (**union_vnodeop_p)();
2132	extern struct vnode *union_lowervp __P((struct vnode *));
2133
2134	if ((uap->count == auio.uio_resid) &&
2135	    (vp->v_op == union_vnodeop_p)) {
2136		struct vnode *tvp = vp;
2137
2138		vp = union_lowervp(vp);
2139		if (vp != NULLVP) {
2140			VOP_LOCK(vp);
2141			error = VOP_OPEN(vp, FREAD);
2142			VOP_UNLOCK(vp);
2143
2144			if (error) {
2145				vrele(vp);
2146				return (error);
2147			}
2148			fp->f_data = (caddr_t) vp;
2149			fp->f_offset = 0;
2150			error = vn_close(tvp, FREAD, fp->f_cred, p);
2151			if (error)
2152				return (error);
2153			goto unionread;
2154		}
2155	}
2156}
2157#endif
2158
2159	if ((uap->count == auio.uio_resid) &&
2160	    (vp->v_flag & VROOT) &&
2161	    (vp->v_mount->mnt_flag & MNT_UNION)) {
2162		struct vnode *tvp = vp;
2163		vp = vp->v_mount->mnt_vnodecovered;
2164		VREF(vp);
2165		fp->f_data = (caddr_t) vp;
2166		fp->f_offset = 0;
2167		vrele(tvp);
2168		goto unionread;
2169	}
2170	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
2171	*retval = uap->count - auio.uio_resid;
2172	return (error);
2173}
2174
2175/*
2176 * Set the mode mask for creation of filesystem nodes.
2177 */
2178struct umask_args {
2179	int	newmask;
2180};
2181mode_t				/* XXX */
2182umask(p, uap, retval)
2183	struct proc *p;
2184	struct umask_args *uap;
2185	int *retval;
2186{
2187	register struct filedesc *fdp;
2188
2189	fdp = p->p_fd;
2190	*retval = fdp->fd_cmask;
2191	fdp->fd_cmask = uap->newmask & ALLPERMS;
2192	return (0);
2193}
2194
2195/*
2196 * Void all references to file by ripping underlying filesystem
2197 * away from vnode.
2198 */
2199struct revoke_args {
2200	char	*path;
2201};
2202/* ARGSUSED */
2203int
2204revoke(p, uap, retval)
2205	struct proc *p;
2206	register struct revoke_args *uap;
2207	int *retval;
2208{
2209	register struct vnode *vp;
2210	struct vattr vattr;
2211	int error;
2212	struct nameidata nd;
2213
2214	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
2215	error = namei(&nd);
2216	if (error)
2217		return (error);
2218	vp = nd.ni_vp;
2219	if (vp->v_type != VCHR && vp->v_type != VBLK) {
2220		error = EINVAL;
2221		goto out;
2222	}
2223	error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
2224	if (error)
2225		goto out;
2226	if (p->p_ucred->cr_uid != vattr.va_uid &&
2227	    (error = suser(p->p_ucred, &p->p_acflag)))
2228		goto out;
2229	if( vp->v_vmdata)
2230		vnode_pager_uncache( vp);
2231	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2232		vgoneall(vp);
2233out:
2234	vrele(vp);
2235	return (error);
2236}
2237
2238/*
2239 * Convert a user file descriptor to a kernel file entry.
2240 */
2241int
2242getvnode(fdp, fd, fpp)
2243	struct filedesc *fdp;
2244	struct file **fpp;
2245	int fd;
2246{
2247	struct file *fp;
2248
2249	if ((u_int)fd >= fdp->fd_nfiles ||
2250	    (fp = fdp->fd_ofiles[fd]) == NULL)
2251		return (EBADF);
2252	if (fp->f_type != DTYPE_VNODE)
2253		return (EINVAL);
2254	*fpp = fp;
2255	return (0);
2256}
2257