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