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