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