xref: /original-bsd/sys/kern/vfs_syscalls.c (revision 6ab384a1)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)vfs_syscalls.c	7.57 (Berkeley) 07/28/90
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "user.h"
13 #include "kernel.h"
14 #include "file.h"
15 #include "stat.h"
16 #include "vnode.h"
17 #include "mount.h"
18 #include "proc.h"
19 #include "uio.h"
20 #include "malloc.h"
21 
22 #define RETURN(val) {if (u.u_spare[0] != 0) panic("lock count"); return (val);}
23 
24 /*
25  * Virtual File System System Calls
26  */
27 
28 /*
29  * mount system call
30  */
31 /* ARGSUSED */
32 mount(p, uap, retval)
33 	register struct proc *p;
34 	register struct args {
35 		int	type;
36 		char	*dir;
37 		int	flags;
38 		caddr_t	data;
39 	} *uap;
40 	int *retval;
41 {
42 	register struct nameidata *ndp = &u.u_nd;
43 	register struct vnode *vp;
44 	register struct mount *mp;
45 	int error, flag;
46 
47 	/*
48 	 * Must be super user
49 	 */
50 	if (error = suser(ndp->ni_cred, &u.u_acflag))
51 		RETURN (error);
52 	/*
53 	 * Get vnode to be covered
54 	 */
55 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
56 	ndp->ni_segflg = UIO_USERSPACE;
57 	ndp->ni_dirp = uap->dir;
58 	if (error = namei(ndp))
59 		RETURN (error);
60 	vp = ndp->ni_vp;
61 	if (uap->flags & MNT_UPDATE) {
62 		if ((vp->v_flag & VROOT) == 0) {
63 			vput(vp);
64 			RETURN (EINVAL);
65 		}
66 		mp = vp->v_mount;
67 		/*
68 		 * We allow going from read-only to read-write,
69 		 * but not from read-write to read-only.
70 		 */
71 		if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
72 		    (uap->flags & MNT_RDONLY) != 0) {
73 			vput(vp);
74 			RETURN (EOPNOTSUPP);	/* Needs translation */
75 		}
76 		flag = mp->mnt_flag;
77 		mp->mnt_flag |= MNT_UPDATE;
78 		VOP_UNLOCK(vp);
79 		goto update;
80 	}
81 	vinvalbuf(vp, 1);
82 	if (vp->v_usecount != 1) {
83 		vput(vp);
84 		RETURN (EBUSY);
85 	}
86 	if (vp->v_type != VDIR) {
87 		vput(vp);
88 		RETURN (ENOTDIR);
89 	}
90 	if ((unsigned long)uap->type > MOUNT_MAXTYPE ||
91 	    vfssw[uap->type] == (struct vfsops *)0) {
92 		vput(vp);
93 		RETURN (ENODEV);
94 	}
95 
96 	/*
97 	 * Allocate and initialize the file system.
98 	 */
99 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
100 		M_MOUNT, M_WAITOK);
101 	mp->mnt_op = vfssw[uap->type];
102 	mp->mnt_flag = 0;
103 	mp->mnt_exroot = 0;
104 	mp->mnt_mounth = NULLVP;
105 	if (error = vfs_lock(mp)) {
106 		free((caddr_t)mp, M_MOUNT);
107 		vput(vp);
108 		RETURN (error);
109 	}
110 	if (vp->v_mountedhere != (struct mount *)0) {
111 		vfs_unlock(mp);
112 		free((caddr_t)mp, M_MOUNT);
113 		vput(vp);
114 		RETURN (EBUSY);
115 	}
116 	vp->v_mountedhere = mp;
117 	mp->mnt_vnodecovered = vp;
118 update:
119 	/*
120 	 * Set the mount level flags.
121 	 */
122 	if (uap->flags & MNT_RDONLY)
123 		mp->mnt_flag |= MNT_RDONLY;
124 	else
125 		mp->mnt_flag &= ~MNT_RDONLY;
126 	if (uap->flags & MNT_NOSUID)
127 		mp->mnt_flag |= MNT_NOSUID;
128 	else
129 		mp->mnt_flag &= ~MNT_NOSUID;
130 	if (uap->flags & MNT_NOEXEC)
131 		mp->mnt_flag |= MNT_NOEXEC;
132 	else
133 		mp->mnt_flag &= ~MNT_NOEXEC;
134 	if (uap->flags & MNT_NODEV)
135 		mp->mnt_flag |= MNT_NODEV;
136 	else
137 		mp->mnt_flag &= ~MNT_NODEV;
138 	if (uap->flags & MNT_SYNCHRONOUS)
139 		mp->mnt_flag |= MNT_SYNCHRONOUS;
140 	else
141 		mp->mnt_flag &= ~MNT_SYNCHRONOUS;
142 	/*
143 	 * Mount the filesystem.
144 	 */
145 	error = VFS_MOUNT(mp, uap->dir, uap->data, ndp);
146 	if (mp->mnt_flag & MNT_UPDATE) {
147 		mp->mnt_flag &= ~MNT_UPDATE;
148 		vrele(vp);
149 		if (error)
150 			mp->mnt_flag = flag;
151 		RETURN (error);
152 	}
153 	/*
154 	 * Put the new filesystem on the mount list after root.
155 	 */
156 	mp->mnt_next = rootfs->mnt_next;
157 	mp->mnt_prev = rootfs;
158 	rootfs->mnt_next = mp;
159 	mp->mnt_next->mnt_prev = mp;
160 	cache_purge(vp);
161 	if (!error) {
162 		VOP_UNLOCK(vp);
163 		vfs_unlock(mp);
164 		error = VFS_START(mp, 0);
165 	} else {
166 		vfs_remove(mp);
167 		free((caddr_t)mp, M_MOUNT);
168 		vput(vp);
169 	}
170 	RETURN (error);
171 }
172 
173 /*
174  * Unmount system call.
175  *
176  * Note: unmount takes a path to the vnode mounted on as argument,
177  * not special file (as before).
178  */
179 /* ARGSUSED */
180 unmount(p, uap, retval)
181 	register struct proc *p;
182 	register struct args {
183 		char	*pathp;
184 		int	flags;
185 	} *uap;
186 	int *retval;
187 {
188 	register struct vnode *vp;
189 	register struct nameidata *ndp = &u.u_nd;
190 	struct mount *mp;
191 	int error;
192 
193 	/*
194 	 * Must be super user
195 	 */
196 	if (error = suser(ndp->ni_cred, &u.u_acflag))
197 		RETURN (error);
198 
199 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
200 	ndp->ni_segflg = UIO_USERSPACE;
201 	ndp->ni_dirp = uap->pathp;
202 	if (error = namei(ndp))
203 		RETURN (error);
204 	vp = ndp->ni_vp;
205 	/*
206 	 * Must be the root of the filesystem
207 	 */
208 	if ((vp->v_flag & VROOT) == 0) {
209 		vput(vp);
210 		RETURN (EINVAL);
211 	}
212 	mp = vp->v_mount;
213 	vput(vp);
214 	RETURN (dounmount(mp, uap->flags));
215 }
216 
217 /*
218  * Do an unmount.
219  */
220 dounmount(mp, flags)
221 	register struct mount *mp;
222 	int flags;
223 {
224 	struct vnode *coveredvp;
225 	int error;
226 
227 	coveredvp = mp->mnt_vnodecovered;
228 	if (vfs_busy(mp))
229 		return (EBUSY);
230 	mp->mnt_flag |= MNT_UNMOUNT;
231 	if (error = vfs_lock(mp))
232 		return (error);
233 
234 	xumount(mp);		/* remove unused sticky files from text table */
235 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
236 	if ((error = VFS_SYNC(mp, MNT_WAIT)) == 0 || (flags & MNT_FORCE))
237 		error = VFS_UNMOUNT(mp, flags);
238 	mp->mnt_flag &= ~MNT_UNMOUNT;
239 	vfs_unbusy(mp);
240 	if (error) {
241 		vfs_unlock(mp);
242 	} else {
243 		vrele(coveredvp);
244 		vfs_remove(mp);
245 		free((caddr_t)mp, M_MOUNT);
246 	}
247 	return (error);
248 }
249 
250 /*
251  * Sync system call.
252  * Sync each mounted filesystem.
253  */
254 /* ARGSUSED */
255 sync(p, uap, retval)
256 	register struct proc *p;
257 	struct args *uap;
258 	int *retval;
259 {
260 	register struct mount *mp;
261 	struct mount *omp;
262 
263 	mp = rootfs;
264 	do {
265 		/*
266 		 * The lock check below is to avoid races with mount
267 		 * and unmount.
268 		 */
269 		if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
270 		    !vfs_busy(mp)) {
271 			VFS_SYNC(mp, MNT_NOWAIT);
272 			omp = mp;
273 			mp = mp->mnt_next;
274 			vfs_unbusy(omp);
275 		} else
276 			mp = mp->mnt_next;
277 	} while (mp != rootfs);
278 }
279 
280 /*
281  * operate on filesystem quotas
282  */
283 /* ARGSUSED */
284 quotactl(p, uap, retval)
285 	register struct proc *p;
286 	register struct args {
287 		char *path;
288 		int cmd;
289 		int uid;
290 		caddr_t arg;
291 	} *uap;
292 	int *retval;
293 {
294 	register struct mount *mp;
295 	register struct nameidata *ndp = &u.u_nd;
296 	int error;
297 
298 	ndp->ni_nameiop = LOOKUP | FOLLOW;
299 	ndp->ni_segflg = UIO_USERSPACE;
300 	ndp->ni_dirp = uap->path;
301 	if (error = namei(ndp))
302 		RETURN (error);
303 	mp = ndp->ni_vp->v_mount;
304 	vrele(ndp->ni_vp);
305 	RETURN (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg));
306 }
307 
308 /*
309  * get filesystem statistics
310  */
311 /* ARGSUSED */
312 statfs(p, uap, retval)
313 	register struct proc *p;
314 	register struct args {
315 		char *path;
316 		struct statfs *buf;
317 	} *uap;
318 	int *retval;
319 {
320 	register struct mount *mp;
321 	register struct nameidata *ndp = &u.u_nd;
322 	register struct statfs *sp;
323 	int error;
324 
325 	ndp->ni_nameiop = LOOKUP | FOLLOW;
326 	ndp->ni_segflg = UIO_USERSPACE;
327 	ndp->ni_dirp = uap->path;
328 	if (error = namei(ndp))
329 		RETURN (error);
330 	mp = ndp->ni_vp->v_mount;
331 	sp = &mp->mnt_stat;
332 	vrele(ndp->ni_vp);
333 	if (error = VFS_STATFS(mp, sp))
334 		RETURN (error);
335 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
336 	RETURN (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
337 }
338 
339 /*
340  * get filesystem statistics
341  */
342 /* ARGSUSED */
343 fstatfs(p, uap, retval)
344 	register struct proc *p;
345 	register struct args {
346 		int fd;
347 		struct statfs *buf;
348 	} *uap;
349 	int *retval;
350 {
351 	struct file *fp;
352 	struct mount *mp;
353 	register struct statfs *sp;
354 	int error;
355 
356 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
357 		RETURN (error);
358 	mp = ((struct vnode *)fp->f_data)->v_mount;
359 	sp = &mp->mnt_stat;
360 	if (error = VFS_STATFS(mp, sp))
361 		RETURN (error);
362 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
363 	RETURN (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
364 }
365 
366 /*
367  * get statistics on all filesystems
368  */
369 getfsstat(p, uap, retval)
370 	register struct proc *p;
371 	register struct args {
372 		struct statfs *buf;
373 		long bufsize;
374 		int flags;
375 	} *uap;
376 	int *retval;
377 {
378 	register struct mount *mp;
379 	register struct statfs *sp;
380 	caddr_t sfsp;
381 	long count, maxcount, error;
382 
383 	maxcount = uap->bufsize / sizeof(struct statfs);
384 	sfsp = (caddr_t)uap->buf;
385 	mp = rootfs;
386 	count = 0;
387 	do {
388 		if (sfsp && count < maxcount &&
389 		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
390 			sp = &mp->mnt_stat;
391 			/*
392 			 * If MNT_NOWAIT is specified, do not refresh the
393 			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
394 			 */
395 			if (((uap->flags & MNT_NOWAIT) == 0 ||
396 			    (uap->flags & MNT_WAIT)) &&
397 			    (error = VFS_STATFS(mp, sp))) {
398 				mp = mp->mnt_prev;
399 				continue;
400 			}
401 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
402 			if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
403 				RETURN (error);
404 			sfsp += sizeof(*sp);
405 		}
406 		count++;
407 		mp = mp->mnt_prev;
408 	} while (mp != rootfs);
409 	if (sfsp && count > maxcount)
410 		*retval = maxcount;
411 	else
412 		*retval = count;
413 	RETURN (0);
414 }
415 
416 /*
417  * Change current working directory to a given file descriptor.
418  */
419 /* ARGSUSED */
420 fchdir(p, uap, retval)
421 	register struct proc *p;
422 	struct args {
423 		int	fd;
424 	} *uap;
425 	int *retval;
426 {
427 	register struct nameidata *ndp = &u.u_nd;
428 	register struct vnode *vp;
429 	struct file *fp;
430 	int error;
431 
432 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
433 		RETURN (error);
434 	vp = (struct vnode *)fp->f_data;
435 	VOP_LOCK(vp);
436 	if (vp->v_type != VDIR)
437 		error = ENOTDIR;
438 	else
439 		error = VOP_ACCESS(vp, VEXEC, ndp->ni_cred);
440 	VOP_UNLOCK(vp);
441 	if (error)
442 		RETURN (error);
443 	VREF(vp);
444 	vrele(ndp->ni_cdir);
445 	ndp->ni_cdir = vp;
446 	RETURN (0);
447 }
448 
449 /*
450  * Change current working directory (``.'').
451  */
452 /* ARGSUSED */
453 chdir(p, uap, retval)
454 	register struct proc *p;
455 	struct args {
456 		char	*fname;
457 	} *uap;
458 	int *retval;
459 {
460 	register struct nameidata *ndp = &u.u_nd;
461 	int error;
462 
463 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
464 	ndp->ni_segflg = UIO_USERSPACE;
465 	ndp->ni_dirp = uap->fname;
466 	if (error = chdirec(ndp))
467 		RETURN (error);
468 	vrele(ndp->ni_cdir);
469 	ndp->ni_cdir = ndp->ni_vp;
470 	RETURN (0);
471 }
472 
473 /*
474  * Change notion of root (``/'') directory.
475  */
476 /* ARGSUSED */
477 chroot(p, uap, retval)
478 	register struct proc *p;
479 	struct args {
480 		char	*fname;
481 	} *uap;
482 	int *retval;
483 {
484 	register struct nameidata *ndp = &u.u_nd;
485 	int error;
486 
487 	if (error = suser(ndp->ni_cred, &u.u_acflag))
488 		RETURN (error);
489 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
490 	ndp->ni_segflg = UIO_USERSPACE;
491 	ndp->ni_dirp = uap->fname;
492 	if (error = chdirec(ndp))
493 		RETURN (error);
494 	if (ndp->ni_rdir != NULL)
495 		vrele(ndp->ni_rdir);
496 	ndp->ni_rdir = ndp->ni_vp;
497 	RETURN (0);
498 }
499 
500 /*
501  * Common routine for chroot and chdir.
502  */
503 chdirec(ndp)
504 	register struct nameidata *ndp;
505 {
506 	struct vnode *vp;
507 	int error;
508 
509 	if (error = namei(ndp))
510 		return (error);
511 	vp = ndp->ni_vp;
512 	if (vp->v_type != VDIR)
513 		error = ENOTDIR;
514 	else
515 		error = VOP_ACCESS(vp, VEXEC, ndp->ni_cred);
516 	VOP_UNLOCK(vp);
517 	if (error)
518 		vrele(vp);
519 	return (error);
520 }
521 
522 /*
523  * Open system call.
524  * Check permissions, allocate an open file structure,
525  * and call the device open routine if any.
526  */
527 open(p, uap, retval)
528 	register struct proc *p;
529 	register struct args {
530 		char	*fname;
531 		int	mode;
532 		int	crtmode;
533 	} *uap;
534 	int *retval;
535 {
536 	struct nameidata *ndp = &u.u_nd;
537 	register struct file *fp;
538 	int fmode, cmode;
539 	struct file *nfp;
540 	int indx, error;
541 	extern struct fileops vnops;
542 
543 	if (error = falloc(&nfp, &indx))
544 		RETURN (error);
545 	fp = nfp;
546 	fmode = uap->mode - FOPEN;
547 	cmode = ((uap->crtmode &~ u.u_cmask) & 07777) &~ S_ISVTX;
548 	ndp->ni_segflg = UIO_USERSPACE;
549 	ndp->ni_dirp = uap->fname;
550 	p->p_dupfd = (u_char)-1;		/* XXX check for fdopen */
551 	if (error = vn_open(ndp, fmode, cmode)) {
552 		crfree(fp->f_cred);
553 		fp->f_count--;
554 		if (error == ENODEV &&		/* XXX from fdopen */
555 		    p->p_dupfd != (u_char)-1 &&
556 		    (error = dupfdopen(indx, p->p_dupfd, fmode)) == 0) {
557 			*retval = indx;
558 			RETURN (0);
559 		}
560 		if (error == ERESTART)
561 			error = EINTR;
562 		u.u_ofile[indx] = NULL;
563 		RETURN (error);
564 	}
565 	fp->f_flag = fmode & FMASK;
566 	fp->f_type = DTYPE_VNODE;
567 	fp->f_ops = &vnops;
568 	fp->f_data = (caddr_t)ndp->ni_vp;
569 	*retval = indx;
570 	RETURN (0);
571 }
572 
573 #ifdef COMPAT_43
574 /*
575  * Creat system call.
576  */
577 ocreat(p, uap, retval)
578 	struct proc *p;
579 	register struct args {
580 		char	*fname;
581 		int	fmode;
582 	} *uap;
583 	int *retval;
584 {
585 	struct args {
586 		char	*fname;
587 		int	mode;
588 		int	crtmode;
589 	} openuap;
590 
591 	openuap.fname = uap->fname;
592 	openuap.crtmode = uap->fmode;
593 	openuap.mode = O_WRONLY | O_CREAT | O_TRUNC;
594 	RETURN (open(p, &openuap, retval));
595 }
596 #endif /* COMPAT_43 */
597 
598 /*
599  * Mknod system call
600  */
601 /* ARGSUSED */
602 mknod(p, uap, retval)
603 	register struct proc *p;
604 	register struct args {
605 		char	*fname;
606 		int	fmode;
607 		int	dev;
608 	} *uap;
609 	int *retval;
610 {
611 	register struct nameidata *ndp = &u.u_nd;
612 	register struct vnode *vp;
613 	struct vattr vattr;
614 	int error;
615 
616 	if (error = suser(ndp->ni_cred, &u.u_acflag))
617 		RETURN (error);
618 	ndp->ni_nameiop = CREATE | LOCKPARENT;
619 	ndp->ni_segflg = UIO_USERSPACE;
620 	ndp->ni_dirp = uap->fname;
621 	if (error = namei(ndp))
622 		RETURN (error);
623 	vp = ndp->ni_vp;
624 	if (vp != NULL) {
625 		error = EEXIST;
626 		goto out;
627 	}
628 	VATTR_NULL(&vattr);
629 	switch (uap->fmode & S_IFMT) {
630 
631 	case S_IFMT:	/* used by badsect to flag bad sectors */
632 		vattr.va_type = VBAD;
633 		break;
634 	case S_IFCHR:
635 		vattr.va_type = VCHR;
636 		break;
637 	case S_IFBLK:
638 		vattr.va_type = VBLK;
639 		break;
640 	default:
641 		error = EINVAL;
642 		goto out;
643 	}
644 	vattr.va_mode = (uap->fmode & 07777) &~ u.u_cmask;
645 	vattr.va_rdev = uap->dev;
646 out:
647 	if (!error) {
648 		error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred);
649 	} else {
650 		VOP_ABORTOP(ndp);
651 		if (ndp->ni_dvp == vp)
652 			vrele(ndp->ni_dvp);
653 		else
654 			vput(ndp->ni_dvp);
655 		if (vp)
656 			vrele(vp);
657 	}
658 	RETURN (error);
659 }
660 
661 /*
662  * Mkfifo system call
663  */
664 /* ARGSUSED */
665 mkfifo(p, uap, retval)
666 	register struct proc *p;
667 	register struct args {
668 		char	*fname;
669 		int	fmode;
670 	} *uap;
671 	int *retval;
672 {
673 	register struct nameidata *ndp = &u.u_nd;
674 	struct vattr vattr;
675 	int error;
676 
677 #ifndef FIFO
678 	RETURN (EOPNOTSUPP);
679 #else
680 	ndp->ni_nameiop = CREATE | LOCKPARENT;
681 	ndp->ni_segflg = UIO_USERSPACE;
682 	ndp->ni_dirp = uap->fname;
683 	if (error = namei(ndp))
684 		RETURN (error);
685 	if (ndp->ni_vp != NULL) {
686 		VOP_ABORTOP(ndp);
687 		if (ndp->ni_dvp == ndp->ni_vp)
688 			vrele(ndp->ni_dvp);
689 		else
690 			vput(ndp->ni_dvp);
691 		vrele(ndp->ni_vp);
692 		RETURN (EEXIST);
693 	} else {
694 		VATTR_NULL(&vattr);
695 		vattr.va_type = VFIFO;
696 		vattr.va_mode = (uap->fmode & 07777) &~ u.u_cmask;
697 	}
698 	RETURN (VOP_MKNOD(ndp, &vattr, ndp->ni_cred));
699 #endif /* FIFO */
700 }
701 
702 /*
703  * link system call
704  */
705 /* ARGSUSED */
706 link(p, uap, retval)
707 	register struct proc *p;
708 	register struct args {
709 		char	*target;
710 		char	*linkname;
711 	} *uap;
712 	int *retval;
713 {
714 	register struct nameidata *ndp = &u.u_nd;
715 	register struct vnode *vp, *xp;
716 	int error;
717 
718 	ndp->ni_nameiop = LOOKUP | FOLLOW;
719 	ndp->ni_segflg = UIO_USERSPACE;
720 	ndp->ni_dirp = uap->target;
721 	if (error = namei(ndp))
722 		RETURN (error);
723 	vp = ndp->ni_vp;
724 	if (vp->v_type == VDIR &&
725 	    (error = suser(ndp->ni_cred, &u.u_acflag)))
726 		goto out1;
727 	ndp->ni_nameiop = CREATE | LOCKPARENT;
728 	ndp->ni_dirp = (caddr_t)uap->linkname;
729 	if (error = namei(ndp))
730 		goto out1;
731 	xp = ndp->ni_vp;
732 	if (xp != NULL) {
733 		error = EEXIST;
734 		goto out;
735 	}
736 	xp = ndp->ni_dvp;
737 	if (vp->v_mount != xp->v_mount)
738 		error = EXDEV;
739 out:
740 	if (!error) {
741 		error = VOP_LINK(vp, ndp);
742 	} else {
743 		VOP_ABORTOP(ndp);
744 		if (ndp->ni_dvp == ndp->ni_vp)
745 			vrele(ndp->ni_dvp);
746 		else
747 			vput(ndp->ni_dvp);
748 		if (ndp->ni_vp)
749 			vrele(ndp->ni_vp);
750 	}
751 out1:
752 	vrele(vp);
753 	RETURN (error);
754 }
755 
756 /*
757  * symlink -- make a symbolic link
758  */
759 /* ARGSUSED */
760 symlink(p, uap, retval)
761 	register struct proc *p;
762 	register struct args {
763 		char	*target;
764 		char	*linkname;
765 	} *uap;
766 	int *retval;
767 {
768 	register struct nameidata *ndp = &u.u_nd;
769 	struct vattr vattr;
770 	char *target;
771 	int error;
772 
773 	ndp->ni_segflg = UIO_USERSPACE;
774 	ndp->ni_dirp = uap->linkname;
775 	MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
776 	if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
777 		goto out;
778 	ndp->ni_nameiop = CREATE | LOCKPARENT;
779 	if (error = namei(ndp))
780 		goto out;
781 	if (ndp->ni_vp) {
782 		VOP_ABORTOP(ndp);
783 		if (ndp->ni_dvp == ndp->ni_vp)
784 			vrele(ndp->ni_dvp);
785 		else
786 			vput(ndp->ni_dvp);
787 		vrele(ndp->ni_vp);
788 		error = EEXIST;
789 		goto out;
790 	}
791 	VATTR_NULL(&vattr);
792 	vattr.va_mode = 0777 &~ u.u_cmask;
793 	error = VOP_SYMLINK(ndp, &vattr, target);
794 out:
795 	FREE(target, M_NAMEI);
796 	RETURN (error);
797 }
798 
799 /*
800  * Unlink system call.
801  * Hard to avoid races here, especially
802  * in unlinking directories.
803  */
804 /* ARGSUSED */
805 unlink(p, uap, retval)
806 	register struct proc *p;
807 	struct args {
808 		char	*fname;
809 	} *uap;
810 	int *retval;
811 {
812 	register struct nameidata *ndp = &u.u_nd;
813 	register struct vnode *vp;
814 	int error;
815 
816 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
817 	ndp->ni_segflg = UIO_USERSPACE;
818 	ndp->ni_dirp = uap->fname;
819 	if (error = namei(ndp))
820 		RETURN (error);
821 	vp = ndp->ni_vp;
822 	if (vp->v_type == VDIR &&
823 	    (error = suser(ndp->ni_cred, &u.u_acflag)))
824 		goto out;
825 	/*
826 	 * Don't unlink a mounted file.
827 	 */
828 	if (vp->v_flag & VROOT) {
829 		error = EBUSY;
830 		goto out;
831 	}
832 	if (vp->v_flag & VTEXT)
833 		xrele(vp);	/* try once to free text */
834 out:
835 	if (!error) {
836 		error = VOP_REMOVE(ndp);
837 	} else {
838 		VOP_ABORTOP(ndp);
839 		if (ndp->ni_dvp == vp)
840 			vrele(ndp->ni_dvp);
841 		else
842 			vput(ndp->ni_dvp);
843 		vput(vp);
844 	}
845 	RETURN (error);
846 }
847 
848 /*
849  * Seek system call
850  */
851 lseek(p, uap, retval)
852 	register struct proc *p;
853 	register struct args {
854 		int	fdes;
855 		off_t	off;
856 		int	sbase;
857 	} *uap;
858 	off_t *retval;
859 {
860 	struct ucred *cred = u.u_nd.ni_cred;
861 	register struct file *fp;
862 	struct vattr vattr;
863 	int error;
864 
865 	if ((unsigned)uap->fdes >= NOFILE ||
866 	    (fp = u.u_ofile[uap->fdes]) == NULL)
867 		RETURN (EBADF);
868 	if (fp->f_type != DTYPE_VNODE)
869 		RETURN (ESPIPE);
870 	switch (uap->sbase) {
871 
872 	case L_INCR:
873 		fp->f_offset += uap->off;
874 		break;
875 
876 	case L_XTND:
877 		if (error = VOP_GETATTR((struct vnode *)fp->f_data,
878 		    &vattr, cred))
879 			RETURN (error);
880 		fp->f_offset = uap->off + vattr.va_size;
881 		break;
882 
883 	case L_SET:
884 		fp->f_offset = uap->off;
885 		break;
886 
887 	default:
888 		RETURN (EINVAL);
889 	}
890 	*retval = fp->f_offset;
891 	RETURN (0);
892 }
893 
894 /*
895  * Access system call
896  */
897 /* ARGSUSED */
898 saccess(p, uap, retval)
899 	register struct proc *p;
900 	register struct args {
901 		char	*fname;
902 		int	fmode;
903 	} *uap;
904 	int *retval;
905 {
906 	register struct nameidata *ndp = &u.u_nd;
907 	register struct ucred *cred = ndp->ni_cred;
908 	register struct vnode *vp;
909 	int error, mode, svuid, svgid;
910 
911 	svuid = cred->cr_uid;
912 	svgid = cred->cr_groups[0];
913 	cred->cr_uid = p->p_ruid;
914 	cred->cr_groups[0] = p->p_rgid;
915 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
916 	ndp->ni_segflg = UIO_USERSPACE;
917 	ndp->ni_dirp = uap->fname;
918 	if (error = namei(ndp))
919 		goto out1;
920 	vp = ndp->ni_vp;
921 	/*
922 	 * fmode == 0 means only check for exist
923 	 */
924 	if (uap->fmode) {
925 		mode = 0;
926 		if (uap->fmode & R_OK)
927 			mode |= VREAD;
928 		if (uap->fmode & W_OK)
929 			mode |= VWRITE;
930 		if (uap->fmode & X_OK)
931 			mode |= VEXEC;
932 		if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
933 			error = VOP_ACCESS(vp, mode, ndp->ni_cred);
934 	}
935 	vput(vp);
936 out1:
937 	cred->cr_uid = svuid;
938 	cred->cr_groups[0] = svgid;
939 	RETURN (error);
940 }
941 
942 /*
943  * Stat system call.  This version follows links.
944  */
945 /* ARGSUSED */
946 stat(p, uap, retval)
947 	register struct proc *p;
948 	register struct args {
949 		char	*fname;
950 		struct stat *ub;
951 	} *uap;
952 	int *retval;
953 {
954 	register struct nameidata *ndp = &u.u_nd;
955 	struct stat sb;
956 	int error;
957 
958 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
959 	ndp->ni_segflg = UIO_USERSPACE;
960 	ndp->ni_dirp = uap->fname;
961 	if (error = namei(ndp))
962 		RETURN (error);
963 	error = vn_stat(ndp->ni_vp, &sb);
964 	vput(ndp->ni_vp);
965 	if (error)
966 		RETURN (error);
967 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
968 	RETURN (error);
969 }
970 
971 /*
972  * Lstat system call.  This version does not follow links.
973  */
974 /* ARGSUSED */
975 lstat(p, uap, retval)
976 	register struct proc *p;
977 	register struct args {
978 		char	*fname;
979 		struct stat *ub;
980 	} *uap;
981 	int *retval;
982 {
983 	register struct nameidata *ndp = &u.u_nd;
984 	struct stat sb;
985 	int error;
986 
987 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | NOFOLLOW;
988 	ndp->ni_segflg = UIO_USERSPACE;
989 	ndp->ni_dirp = uap->fname;
990 	if (error = namei(ndp))
991 		RETURN (error);
992 	error = vn_stat(ndp->ni_vp, &sb);
993 	vput(ndp->ni_vp);
994 	if (error)
995 		RETURN (error);
996 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
997 	RETURN (error);
998 }
999 
1000 /*
1001  * Return target name of a symbolic link
1002  */
1003 /* ARGSUSED */
1004 readlink(p, uap, retval)
1005 	register struct proc *p;
1006 	register struct args {
1007 		char	*name;
1008 		char	*buf;
1009 		int	count;
1010 	} *uap;
1011 	int *retval;
1012 {
1013 	register struct nameidata *ndp = &u.u_nd;
1014 	register struct vnode *vp;
1015 	struct iovec aiov;
1016 	struct uio auio;
1017 	int error;
1018 
1019 	ndp->ni_nameiop = LOOKUP | LOCKLEAF;
1020 	ndp->ni_segflg = UIO_USERSPACE;
1021 	ndp->ni_dirp = uap->name;
1022 	if (error = namei(ndp))
1023 		RETURN (error);
1024 	vp = ndp->ni_vp;
1025 	if (vp->v_type != VLNK) {
1026 		error = EINVAL;
1027 		goto out;
1028 	}
1029 	aiov.iov_base = uap->buf;
1030 	aiov.iov_len = uap->count;
1031 	auio.uio_iov = &aiov;
1032 	auio.uio_iovcnt = 1;
1033 	auio.uio_offset = 0;
1034 	auio.uio_rw = UIO_READ;
1035 	auio.uio_segflg = UIO_USERSPACE;
1036 	auio.uio_resid = uap->count;
1037 	error = VOP_READLINK(vp, &auio, ndp->ni_cred);
1038 out:
1039 	vput(vp);
1040 	*retval = uap->count - auio.uio_resid;
1041 	RETURN (error);
1042 }
1043 
1044 /*
1045  * Change flags of a file given path name.
1046  */
1047 /* ARGSUSED */
1048 chflags(p, uap, retval)
1049 	register struct proc *p;
1050 	register struct args {
1051 		char	*fname;
1052 		int	flags;
1053 	} *uap;
1054 	int *retval;
1055 {
1056 	register struct nameidata *ndp = &u.u_nd;
1057 	register struct vnode *vp;
1058 	struct vattr vattr;
1059 	int error;
1060 
1061 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1062 	ndp->ni_segflg = UIO_USERSPACE;
1063 	ndp->ni_dirp = uap->fname;
1064 	VATTR_NULL(&vattr);
1065 	vattr.va_flags = uap->flags;
1066 	if (error = namei(ndp))
1067 		RETURN (error);
1068 	vp = ndp->ni_vp;
1069 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1070 		error = EROFS;
1071 		goto out;
1072 	}
1073 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1074 out:
1075 	vput(vp);
1076 	RETURN (error);
1077 }
1078 
1079 /*
1080  * Change flags of a file given a file descriptor.
1081  */
1082 /* ARGSUSED */
1083 fchflags(p, uap, retval)
1084 	register struct proc *p;
1085 	register struct args {
1086 		int	fd;
1087 		int	flags;
1088 	} *uap;
1089 	int *retval;
1090 {
1091 	struct vattr vattr;
1092 	struct vnode *vp;
1093 	struct file *fp;
1094 	int error;
1095 
1096 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1097 		RETURN (error);
1098 	VATTR_NULL(&vattr);
1099 	vattr.va_flags = uap->flags;
1100 	vp = (struct vnode *)fp->f_data;
1101 	VOP_LOCK(vp);
1102 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1103 		error = EROFS;
1104 		goto out;
1105 	}
1106 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1107 out:
1108 	VOP_UNLOCK(vp);
1109 	RETURN (error);
1110 }
1111 
1112 /*
1113  * Change mode of a file given path name.
1114  */
1115 /* ARGSUSED */
1116 chmod(p, uap, retval)
1117 	register struct proc *p;
1118 	register struct args {
1119 		char	*fname;
1120 		int	fmode;
1121 	} *uap;
1122 	int *retval;
1123 {
1124 	register struct nameidata *ndp = &u.u_nd;
1125 	register struct vnode *vp;
1126 	struct vattr vattr;
1127 	int error;
1128 
1129 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1130 	ndp->ni_segflg = UIO_USERSPACE;
1131 	ndp->ni_dirp = uap->fname;
1132 	VATTR_NULL(&vattr);
1133 	vattr.va_mode = uap->fmode & 07777;
1134 	if (error = namei(ndp))
1135 		RETURN (error);
1136 	vp = ndp->ni_vp;
1137 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1138 		error = EROFS;
1139 		goto out;
1140 	}
1141 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1142 out:
1143 	vput(vp);
1144 	RETURN (error);
1145 }
1146 
1147 /*
1148  * Change mode of a file given a file descriptor.
1149  */
1150 /* ARGSUSED */
1151 fchmod(p, uap, retval)
1152 	register struct proc *p;
1153 	register struct args {
1154 		int	fd;
1155 		int	fmode;
1156 	} *uap;
1157 	int *retval;
1158 {
1159 	struct vattr vattr;
1160 	struct vnode *vp;
1161 	struct file *fp;
1162 	int error;
1163 
1164 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1165 		RETURN (error);
1166 	VATTR_NULL(&vattr);
1167 	vattr.va_mode = uap->fmode & 07777;
1168 	vp = (struct vnode *)fp->f_data;
1169 	VOP_LOCK(vp);
1170 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1171 		error = EROFS;
1172 		goto out;
1173 	}
1174 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1175 out:
1176 	VOP_UNLOCK(vp);
1177 	RETURN (error);
1178 }
1179 
1180 /*
1181  * Set ownership given a path name.
1182  */
1183 /* ARGSUSED */
1184 chown(p, uap, retval)
1185 	register struct proc *p;
1186 	register struct args {
1187 		char	*fname;
1188 		int	uid;
1189 		int	gid;
1190 	} *uap;
1191 	int *retval;
1192 {
1193 	register struct nameidata *ndp = &u.u_nd;
1194 	register struct vnode *vp;
1195 	struct vattr vattr;
1196 	int error;
1197 
1198 	ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF;
1199 	ndp->ni_segflg = UIO_USERSPACE;
1200 	ndp->ni_dirp = uap->fname;
1201 	VATTR_NULL(&vattr);
1202 	vattr.va_uid = uap->uid;
1203 	vattr.va_gid = uap->gid;
1204 	if (error = namei(ndp))
1205 		RETURN (error);
1206 	vp = ndp->ni_vp;
1207 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1208 		error = EROFS;
1209 		goto out;
1210 	}
1211 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1212 out:
1213 	vput(vp);
1214 	RETURN (error);
1215 }
1216 
1217 /*
1218  * Set ownership given a file descriptor.
1219  */
1220 /* ARGSUSED */
1221 fchown(p, uap, retval)
1222 	register struct proc *p;
1223 	register struct args {
1224 		int	fd;
1225 		int	uid;
1226 		int	gid;
1227 	} *uap;
1228 	int *retval;
1229 {
1230 	struct vattr vattr;
1231 	struct vnode *vp;
1232 	struct file *fp;
1233 	int error;
1234 
1235 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1236 		RETURN (error);
1237 	VATTR_NULL(&vattr);
1238 	vattr.va_uid = uap->uid;
1239 	vattr.va_gid = uap->gid;
1240 	vp = (struct vnode *)fp->f_data;
1241 	VOP_LOCK(vp);
1242 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1243 		error = EROFS;
1244 		goto out;
1245 	}
1246 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1247 out:
1248 	VOP_UNLOCK(vp);
1249 	RETURN (error);
1250 }
1251 
1252 /*
1253  * Set the access and modification times of a file.
1254  */
1255 /* ARGSUSED */
1256 utimes(p, uap, retval)
1257 	register struct proc *p;
1258 	register struct args {
1259 		char	*fname;
1260 		struct	timeval *tptr;
1261 	} *uap;
1262 	int *retval;
1263 {
1264 	register struct nameidata *ndp = &u.u_nd;
1265 	register struct vnode *vp;
1266 	struct timeval tv[2];
1267 	struct vattr vattr;
1268 	int error;
1269 
1270 	if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1271 		RETURN (error);
1272 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1273 	ndp->ni_segflg = UIO_USERSPACE;
1274 	ndp->ni_dirp = uap->fname;
1275 	VATTR_NULL(&vattr);
1276 	vattr.va_atime = tv[0];
1277 	vattr.va_mtime = tv[1];
1278 	if (error = namei(ndp))
1279 		RETURN (error);
1280 	vp = ndp->ni_vp;
1281 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1282 		error = EROFS;
1283 		goto out;
1284 	}
1285 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1286 out:
1287 	vput(vp);
1288 	RETURN (error);
1289 }
1290 
1291 /*
1292  * Truncate a file given its path name.
1293  */
1294 /* ARGSUSED */
1295 truncate(p, uap, retval)
1296 	register struct proc *p;
1297 	register struct args {
1298 		char	*fname;
1299 		off_t	length;
1300 	} *uap;
1301 	int *retval;
1302 {
1303 	register struct nameidata *ndp = &u.u_nd;
1304 	register struct vnode *vp;
1305 	struct vattr vattr;
1306 	int error;
1307 
1308 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1309 	ndp->ni_segflg = UIO_USERSPACE;
1310 	ndp->ni_dirp = uap->fname;
1311 	VATTR_NULL(&vattr);
1312 	vattr.va_size = uap->length;
1313 	if (error = namei(ndp))
1314 		RETURN (error);
1315 	vp = ndp->ni_vp;
1316 	if (vp->v_type == VDIR) {
1317 		error = EISDIR;
1318 		goto out;
1319 	}
1320 	if ((error = vn_writechk(vp)) ||
1321 	    (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
1322 		goto out;
1323 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1324 out:
1325 	vput(vp);
1326 	RETURN (error);
1327 }
1328 
1329 /*
1330  * Truncate a file given a file descriptor.
1331  */
1332 /* ARGSUSED */
1333 ftruncate(p, uap, retval)
1334 	register struct proc *p;
1335 	register struct args {
1336 		int	fd;
1337 		off_t	length;
1338 	} *uap;
1339 	int *retval;
1340 {
1341 	struct vattr vattr;
1342 	struct vnode *vp;
1343 	struct file *fp;
1344 	int error;
1345 
1346 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1347 		RETURN (error);
1348 	if ((fp->f_flag & FWRITE) == 0)
1349 		RETURN (EINVAL);
1350 	VATTR_NULL(&vattr);
1351 	vattr.va_size = uap->length;
1352 	vp = (struct vnode *)fp->f_data;
1353 	VOP_LOCK(vp);
1354 	if (vp->v_type == VDIR) {
1355 		error = EISDIR;
1356 		goto out;
1357 	}
1358 	if (error = vn_writechk(vp))
1359 		goto out;
1360 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1361 out:
1362 	VOP_UNLOCK(vp);
1363 	RETURN (error);
1364 }
1365 
1366 /*
1367  * Synch an open file.
1368  */
1369 /* ARGSUSED */
1370 fsync(p, uap, retval)
1371 	register struct proc *p;
1372 	struct args {
1373 		int	fd;
1374 	} *uap;
1375 	int *retval;
1376 {
1377 	register struct vnode *vp;
1378 	struct file *fp;
1379 	int error;
1380 
1381 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1382 		RETURN (error);
1383 	vp = (struct vnode *)fp->f_data;
1384 	VOP_LOCK(vp);
1385 	error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT);
1386 	VOP_UNLOCK(vp);
1387 	RETURN (error);
1388 }
1389 
1390 /*
1391  * Rename system call.
1392  *
1393  * Source and destination must either both be directories, or both
1394  * not be directories.  If target is a directory, it must be empty.
1395  */
1396 /* ARGSUSED */
1397 rename(p, uap, retval)
1398 	register struct proc *p;
1399 	register struct args {
1400 		char	*from;
1401 		char	*to;
1402 	} *uap;
1403 	int *retval;
1404 {
1405 	register struct vnode *tvp, *fvp, *tdvp;
1406 	register struct nameidata *ndp = &u.u_nd;
1407 	struct nameidata tond;
1408 	int error;
1409 
1410 	ndp->ni_nameiop = DELETE | WANTPARENT;
1411 	ndp->ni_segflg = UIO_USERSPACE;
1412 	ndp->ni_dirp = uap->from;
1413 	if (error = namei(ndp))
1414 		RETURN (error);
1415 	fvp = ndp->ni_vp;
1416 	nddup(ndp, &tond);
1417 	tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
1418 	tond.ni_segflg = UIO_USERSPACE;
1419 	tond.ni_dirp = uap->to;
1420 	if (error = namei(&tond)) {
1421 		VOP_ABORTOP(ndp);
1422 		vrele(ndp->ni_dvp);
1423 		vrele(fvp);
1424 		goto out1;
1425 	}
1426 	tdvp = tond.ni_dvp;
1427 	tvp = tond.ni_vp;
1428 	if (tvp != NULL) {
1429 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1430 			error = ENOTDIR;
1431 			goto out;
1432 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1433 			error = EISDIR;
1434 			goto out;
1435 		}
1436 	}
1437 	if (fvp->v_mount != tdvp->v_mount) {
1438 		error = EXDEV;
1439 		goto out;
1440 	}
1441 	if (fvp == tdvp)
1442 		error = EINVAL;
1443 	/*
1444 	 * If source is the same as the destination,
1445 	 * then there is nothing to do.
1446 	 */
1447 	if (fvp == tvp)
1448 		error = -1;
1449 out:
1450 	if (!error) {
1451 		error = VOP_RENAME(ndp, &tond);
1452 	} else {
1453 		VOP_ABORTOP(&tond);
1454 		if (tdvp == tvp)
1455 			vrele(tdvp);
1456 		else
1457 			vput(tdvp);
1458 		if (tvp)
1459 			vput(tvp);
1460 		VOP_ABORTOP(ndp);
1461 		vrele(ndp->ni_dvp);
1462 		vrele(fvp);
1463 	}
1464 out1:
1465 	ndrele(&tond);
1466 	if (error == -1)
1467 		RETURN (0);
1468 	RETURN (error);
1469 }
1470 
1471 /*
1472  * Mkdir system call
1473  */
1474 /* ARGSUSED */
1475 mkdir(p, uap, retval)
1476 	register struct proc *p;
1477 	register struct args {
1478 		char	*name;
1479 		int	dmode;
1480 	} *uap;
1481 	int *retval;
1482 {
1483 	register struct nameidata *ndp = &u.u_nd;
1484 	register struct vnode *vp;
1485 	struct vattr vattr;
1486 	int error;
1487 
1488 	ndp->ni_nameiop = CREATE | LOCKPARENT;
1489 	ndp->ni_segflg = UIO_USERSPACE;
1490 	ndp->ni_dirp = uap->name;
1491 	if (error = namei(ndp))
1492 		RETURN (error);
1493 	vp = ndp->ni_vp;
1494 	if (vp != NULL) {
1495 		VOP_ABORTOP(ndp);
1496 		if (ndp->ni_dvp == vp)
1497 			vrele(ndp->ni_dvp);
1498 		else
1499 			vput(ndp->ni_dvp);
1500 		vrele(vp);
1501 		RETURN (EEXIST);
1502 	}
1503 	VATTR_NULL(&vattr);
1504 	vattr.va_type = VDIR;
1505 	vattr.va_mode = (uap->dmode & 0777) &~ u.u_cmask;
1506 	error = VOP_MKDIR(ndp, &vattr);
1507 	if (!error)
1508 		vput(ndp->ni_vp);
1509 	RETURN (error);
1510 }
1511 
1512 /*
1513  * Rmdir system call.
1514  */
1515 /* ARGSUSED */
1516 rmdir(p, uap, retval)
1517 	register struct proc *p;
1518 	struct args {
1519 		char	*name;
1520 	} *uap;
1521 	int *retval;
1522 {
1523 	register struct nameidata *ndp = &u.u_nd;
1524 	register struct vnode *vp;
1525 	int error;
1526 
1527 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
1528 	ndp->ni_segflg = UIO_USERSPACE;
1529 	ndp->ni_dirp = uap->name;
1530 	if (error = namei(ndp))
1531 		RETURN (error);
1532 	vp = ndp->ni_vp;
1533 	if (vp->v_type != VDIR) {
1534 		error = ENOTDIR;
1535 		goto out;
1536 	}
1537 	/*
1538 	 * No rmdir "." please.
1539 	 */
1540 	if (ndp->ni_dvp == vp) {
1541 		error = EINVAL;
1542 		goto out;
1543 	}
1544 	/*
1545 	 * Don't unlink a mounted file.
1546 	 */
1547 	if (vp->v_flag & VROOT)
1548 		error = EBUSY;
1549 out:
1550 	if (!error) {
1551 		error = VOP_RMDIR(ndp);
1552 	} else {
1553 		VOP_ABORTOP(ndp);
1554 		if (ndp->ni_dvp == vp)
1555 			vrele(ndp->ni_dvp);
1556 		else
1557 			vput(ndp->ni_dvp);
1558 		vput(vp);
1559 	}
1560 	RETURN (error);
1561 }
1562 
1563 /*
1564  * Read a block of directory entries in a file system independent format
1565  */
1566 getdirentries(p, uap, retval)
1567 	register struct proc *p;
1568 	register struct args {
1569 		int	fd;
1570 		char	*buf;
1571 		unsigned count;
1572 		long	*basep;
1573 	} *uap;
1574 	int *retval;
1575 {
1576 	register struct vnode *vp;
1577 	struct file *fp;
1578 	struct uio auio;
1579 	struct iovec aiov;
1580 	off_t off;
1581 	int error, eofflag;
1582 
1583 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1584 		RETURN (error);
1585 	if ((fp->f_flag & FREAD) == 0)
1586 		RETURN (EBADF);
1587 	vp = (struct vnode *)fp->f_data;
1588 	if (vp->v_type != VDIR)
1589 		RETURN (EINVAL);
1590 	aiov.iov_base = uap->buf;
1591 	aiov.iov_len = uap->count;
1592 	auio.uio_iov = &aiov;
1593 	auio.uio_iovcnt = 1;
1594 	auio.uio_rw = UIO_READ;
1595 	auio.uio_segflg = UIO_USERSPACE;
1596 	auio.uio_resid = uap->count;
1597 	VOP_LOCK(vp);
1598 	auio.uio_offset = off = fp->f_offset;
1599 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag);
1600 	fp->f_offset = auio.uio_offset;
1601 	VOP_UNLOCK(vp);
1602 	if (error)
1603 		RETURN (error);
1604 	error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
1605 	*retval = uap->count - auio.uio_resid;
1606 	RETURN (error);
1607 }
1608 
1609 /*
1610  * mode mask for creation of files
1611  */
1612 mode_t
1613 umask(p, uap, retval)
1614 	register struct proc *p;
1615 	struct args {
1616 		int	mask;
1617 	} *uap;
1618 	int *retval;
1619 {
1620 
1621 	*retval = u.u_cmask;
1622 	u.u_cmask = uap->mask & 07777;
1623 	RETURN (0);
1624 }
1625 
1626 /*
1627  * Void all references to file by ripping underlying filesystem
1628  * away from vnode.
1629  */
1630 /* ARGSUSED */
1631 revoke(p, uap, retval)
1632 	register struct proc *p;
1633 	register struct args {
1634 		char	*fname;
1635 	} *uap;
1636 	int *retval;
1637 {
1638 	register struct nameidata *ndp = &u.u_nd;
1639 	register struct vnode *vp;
1640 	struct vattr vattr;
1641 	int error;
1642 
1643 	ndp->ni_nameiop = LOOKUP | FOLLOW;
1644 	ndp->ni_segflg = UIO_USERSPACE;
1645 	ndp->ni_dirp = uap->fname;
1646 	if (error = namei(ndp))
1647 		RETURN (error);
1648 	vp = ndp->ni_vp;
1649 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
1650 		error = EINVAL;
1651 		goto out;
1652 	}
1653 	if (error = VOP_GETATTR(vp, &vattr, ndp->ni_cred))
1654 		goto out;
1655 	if (ndp->ni_cred->cr_uid != vattr.va_uid &&
1656 	    (error = suser(ndp->ni_cred, &u.u_acflag)))
1657 		goto out;
1658 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
1659 		vgoneall(vp);
1660 out:
1661 	vrele(vp);
1662 	RETURN (error);
1663 }
1664 
1665 getvnode(ofile, fdes, fpp)
1666 	struct file *ofile[];
1667 	struct file **fpp;
1668 	int fdes;
1669 {
1670 	struct file *fp;
1671 
1672 	if ((unsigned)fdes >= NOFILE || (fp = ofile[fdes]) == NULL)
1673 		return (EBADF);
1674 	if (fp->f_type != DTYPE_VNODE)
1675 		return (EINVAL);
1676 	*fpp = fp;
1677 	return (0);
1678 }
1679