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