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