xref: /original-bsd/sys/kern/vfs_syscalls.c (revision 35d77a20)
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.73 (Berkeley) 06/03/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 type, indx, error;
558 	struct flock lf;
559 	struct nameidata nd;
560 	extern struct fileops vnops;
561 
562 	if (error = falloc(p, &nfp, &indx))
563 		return (error);
564 	fp = nfp;
565 	fmode = FFLAGS(uap->mode);
566 	cmode = ((uap->crtmode &~ fdp->fd_cmask) & 07777) &~ S_ISVTX;
567 	ndp = &nd;
568 	ndp->ni_segflg = UIO_USERSPACE;
569 	ndp->ni_dirp = uap->fname;
570 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
571 	if (error = vn_open(ndp, p, fmode, cmode)) {
572 		ffree(fp);
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 	if (fmode & (O_EXLOCK | O_SHLOCK)) {
586 		lf.l_whence = SEEK_SET;
587 		lf.l_start = 0;
588 		lf.l_len = 0;
589 		if (fmode & O_EXLOCK)
590 			lf.l_type = F_WRLCK;
591 		else
592 			lf.l_type = F_RDLCK;
593 		type = F_FLOCK;
594 		if ((fmode & FNONBLOCK) == 0)
595 			type |= F_WAIT;
596 		if (error =
597 		    VOP_ADVLOCK(ndp->ni_vp, (caddr_t)fp, F_SETLK, &lf, type)) {
598 			vput(ndp->ni_vp);
599 			ffree(fp);
600 			fdp->fd_ofiles[indx] = NULL;
601 			return (error);
602 		}
603 		fp->f_flag |= FHASLOCK;
604 	}
605 	VOP_UNLOCK(ndp->ni_vp);
606 	fp->f_type = DTYPE_VNODE;
607 	fp->f_ops = &vnops;
608 	fp->f_data = (caddr_t)ndp->ni_vp;
609 	*retval = indx;
610 	return (0);
611 }
612 
613 #ifdef COMPAT_43
614 /*
615  * Creat system call.
616  */
617 ocreat(p, uap, retval)
618 	struct proc *p;
619 	register struct args {
620 		char	*fname;
621 		int	fmode;
622 	} *uap;
623 	int *retval;
624 {
625 	struct args {
626 		char	*fname;
627 		int	mode;
628 		int	crtmode;
629 	} openuap;
630 
631 	openuap.fname = uap->fname;
632 	openuap.crtmode = uap->fmode;
633 	openuap.mode = O_WRONLY | O_CREAT | O_TRUNC;
634 	return (open(p, &openuap, retval));
635 }
636 #endif /* COMPAT_43 */
637 
638 /*
639  * Mknod system call.
640  */
641 /* ARGSUSED */
642 mknod(p, uap, retval)
643 	struct proc *p;
644 	register struct args {
645 		char	*fname;
646 		int	fmode;
647 		int	dev;
648 	} *uap;
649 	int *retval;
650 {
651 	register struct nameidata *ndp;
652 	register struct vnode *vp;
653 	struct vattr vattr;
654 	int error;
655 	struct nameidata nd;
656 
657 	if (error = suser(p->p_ucred, &p->p_acflag))
658 		return (error);
659 	ndp = &nd;
660 	ndp->ni_nameiop = CREATE | LOCKPARENT;
661 	ndp->ni_segflg = UIO_USERSPACE;
662 	ndp->ni_dirp = uap->fname;
663 	if (error = namei(ndp, p))
664 		return (error);
665 	vp = ndp->ni_vp;
666 	if (vp != NULL) {
667 		error = EEXIST;
668 		goto out;
669 	}
670 	VATTR_NULL(&vattr);
671 	switch (uap->fmode & S_IFMT) {
672 
673 	case S_IFMT:	/* used by badsect to flag bad sectors */
674 		vattr.va_type = VBAD;
675 		break;
676 	case S_IFCHR:
677 		vattr.va_type = VCHR;
678 		break;
679 	case S_IFBLK:
680 		vattr.va_type = VBLK;
681 		break;
682 	default:
683 		error = EINVAL;
684 		goto out;
685 	}
686 	vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask;
687 	vattr.va_rdev = uap->dev;
688 out:
689 	if (!error) {
690 		error = VOP_MKNOD(ndp, &vattr, p->p_ucred, p);
691 	} else {
692 		VOP_ABORTOP(ndp);
693 		if (ndp->ni_dvp == vp)
694 			vrele(ndp->ni_dvp);
695 		else
696 			vput(ndp->ni_dvp);
697 		if (vp)
698 			vrele(vp);
699 	}
700 	return (error);
701 }
702 
703 /*
704  * Mkfifo system call.
705  */
706 /* ARGSUSED */
707 mkfifo(p, uap, retval)
708 	struct proc *p;
709 	register struct args {
710 		char	*fname;
711 		int	fmode;
712 	} *uap;
713 	int *retval;
714 {
715 	register struct nameidata *ndp;
716 	struct vattr vattr;
717 	int error;
718 	struct nameidata nd;
719 
720 #ifndef FIFO
721 	return (EOPNOTSUPP);
722 #else
723 	ndp = &nd;
724 	ndp->ni_nameiop = CREATE | LOCKPARENT;
725 	ndp->ni_segflg = UIO_USERSPACE;
726 	ndp->ni_dirp = uap->fname;
727 	if (error = namei(ndp, p))
728 		return (error);
729 	if (ndp->ni_vp != NULL) {
730 		VOP_ABORTOP(ndp);
731 		if (ndp->ni_dvp == ndp->ni_vp)
732 			vrele(ndp->ni_dvp);
733 		else
734 			vput(ndp->ni_dvp);
735 		vrele(ndp->ni_vp);
736 		return (EEXIST);
737 	}
738 	VATTR_NULL(&vattr);
739 	vattr.va_type = VFIFO;
740 	vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask;
741 	return (VOP_MKNOD(ndp, &vattr, p->p_ucred, p));
742 #endif /* FIFO */
743 }
744 
745 /*
746  * Link system call.
747  */
748 /* ARGSUSED */
749 link(p, uap, retval)
750 	struct proc *p;
751 	register struct args {
752 		char	*target;
753 		char	*linkname;
754 	} *uap;
755 	int *retval;
756 {
757 	register struct nameidata *ndp;
758 	register struct vnode *vp, *xp;
759 	int error;
760 	struct nameidata nd;
761 
762 	ndp = &nd;
763 	ndp->ni_nameiop = LOOKUP | FOLLOW;
764 	ndp->ni_segflg = UIO_USERSPACE;
765 	ndp->ni_dirp = uap->target;
766 	if (error = namei(ndp, p))
767 		return (error);
768 	vp = ndp->ni_vp;
769 	if (vp->v_type == VDIR &&
770 	    (error = suser(p->p_ucred, &p->p_acflag)))
771 		goto out1;
772 	ndp->ni_nameiop = CREATE | LOCKPARENT;
773 	ndp->ni_dirp = (caddr_t)uap->linkname;
774 	if (error = namei(ndp, p))
775 		goto out1;
776 	xp = ndp->ni_vp;
777 	if (xp != NULL) {
778 		error = EEXIST;
779 		goto out;
780 	}
781 	xp = ndp->ni_dvp;
782 	if (vp->v_mount != xp->v_mount)
783 		error = EXDEV;
784 out:
785 	if (!error) {
786 		error = VOP_LINK(vp, ndp, p);
787 	} else {
788 		VOP_ABORTOP(ndp);
789 		if (ndp->ni_dvp == ndp->ni_vp)
790 			vrele(ndp->ni_dvp);
791 		else
792 			vput(ndp->ni_dvp);
793 		if (ndp->ni_vp)
794 			vrele(ndp->ni_vp);
795 	}
796 out1:
797 	vrele(vp);
798 	return (error);
799 }
800 
801 /*
802  * Make a symbolic link.
803  */
804 /* ARGSUSED */
805 symlink(p, uap, retval)
806 	struct proc *p;
807 	register struct args {
808 		char	*target;
809 		char	*linkname;
810 	} *uap;
811 	int *retval;
812 {
813 	register struct nameidata *ndp;
814 	struct vattr vattr;
815 	char *target;
816 	int error;
817 	struct nameidata nd;
818 
819 	ndp = &nd;
820 	ndp->ni_segflg = UIO_USERSPACE;
821 	ndp->ni_dirp = uap->linkname;
822 	MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
823 	if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
824 		goto out;
825 	ndp->ni_nameiop = CREATE | LOCKPARENT;
826 	if (error = namei(ndp, p))
827 		goto out;
828 	if (ndp->ni_vp) {
829 		VOP_ABORTOP(ndp);
830 		if (ndp->ni_dvp == ndp->ni_vp)
831 			vrele(ndp->ni_dvp);
832 		else
833 			vput(ndp->ni_dvp);
834 		vrele(ndp->ni_vp);
835 		error = EEXIST;
836 		goto out;
837 	}
838 	VATTR_NULL(&vattr);
839 	vattr.va_mode = 0777 &~ p->p_fd->fd_cmask;
840 	error = VOP_SYMLINK(ndp, &vattr, target, p);
841 out:
842 	FREE(target, M_NAMEI);
843 	return (error);
844 }
845 
846 /*
847  * Delete a name from the filesystem.
848  */
849 /* ARGSUSED */
850 unlink(p, uap, retval)
851 	struct proc *p;
852 	struct args {
853 		char	*fname;
854 	} *uap;
855 	int *retval;
856 {
857 	register struct nameidata *ndp;
858 	register struct vnode *vp;
859 	int error;
860 	struct nameidata nd;
861 
862 	ndp = &nd;
863 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
864 	ndp->ni_segflg = UIO_USERSPACE;
865 	ndp->ni_dirp = uap->fname;
866 	if (error = namei(ndp, p))
867 		return (error);
868 	vp = ndp->ni_vp;
869 	if (vp->v_type == VDIR &&
870 	    (error = suser(p->p_ucred, &p->p_acflag)))
871 		goto out;
872 	/*
873 	 * The root of a mounted filesystem cannot be deleted.
874 	 */
875 	if (vp->v_flag & VROOT) {
876 		error = EBUSY;
877 		goto out;
878 	}
879 	(void) vnode_pager_uncache(vp);
880 out:
881 	if (!error) {
882 		error = VOP_REMOVE(ndp, p);
883 	} else {
884 		VOP_ABORTOP(ndp);
885 		if (ndp->ni_dvp == vp)
886 			vrele(ndp->ni_dvp);
887 		else
888 			vput(ndp->ni_dvp);
889 		vput(vp);
890 	}
891 	return (error);
892 }
893 
894 /*
895  * Seek system call.
896  */
897 lseek(p, uap, retval)
898 	struct proc *p;
899 	register struct args {
900 		int	fdes;
901 		off_t	off;
902 		int	sbase;
903 	} *uap;
904 	off_t *retval;
905 {
906 	struct ucred *cred = p->p_ucred;
907 	register struct filedesc *fdp = p->p_fd;
908 	register struct file *fp;
909 	struct vattr vattr;
910 	int error;
911 
912 	if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
913 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
914 		return (EBADF);
915 	if (fp->f_type != DTYPE_VNODE)
916 		return (ESPIPE);
917 	switch (uap->sbase) {
918 
919 	case L_INCR:
920 		fp->f_offset += uap->off;
921 		break;
922 
923 	case L_XTND:
924 		if (error = VOP_GETATTR((struct vnode *)fp->f_data,
925 		    &vattr, cred, p))
926 			return (error);
927 		fp->f_offset = uap->off + vattr.va_size;
928 		break;
929 
930 	case L_SET:
931 		fp->f_offset = uap->off;
932 		break;
933 
934 	default:
935 		return (EINVAL);
936 	}
937 	*retval = fp->f_offset;
938 	return (0);
939 }
940 
941 /*
942  * Check access permissions.
943  */
944 /* ARGSUSED */
945 saccess(p, uap, retval)
946 	struct proc *p;
947 	register struct args {
948 		char	*fname;
949 		int	fmode;
950 	} *uap;
951 	int *retval;
952 {
953 	register struct nameidata *ndp;
954 	register struct ucred *cred = p->p_ucred;
955 	register struct vnode *vp;
956 	int error, mode, svuid, svgid;
957 	struct nameidata nd;
958 
959 	ndp = &nd;
960 	svuid = cred->cr_uid;
961 	svgid = cred->cr_groups[0];
962 	cred->cr_uid = p->p_cred->p_ruid;
963 	cred->cr_groups[0] = p->p_cred->p_rgid;
964 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
965 	ndp->ni_segflg = UIO_USERSPACE;
966 	ndp->ni_dirp = uap->fname;
967 	if (error = namei(ndp, p))
968 		goto out1;
969 	vp = ndp->ni_vp;
970 	/*
971 	 * fmode == 0 means only check for exist
972 	 */
973 	if (uap->fmode) {
974 		mode = 0;
975 		if (uap->fmode & R_OK)
976 			mode |= VREAD;
977 		if (uap->fmode & W_OK)
978 			mode |= VWRITE;
979 		if (uap->fmode & X_OK)
980 			mode |= VEXEC;
981 		if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
982 			error = VOP_ACCESS(vp, mode, cred, p);
983 	}
984 	vput(vp);
985 out1:
986 	cred->cr_uid = svuid;
987 	cred->cr_groups[0] = svgid;
988 	return (error);
989 }
990 
991 /*
992  * Stat system call.
993  * This version follows links.
994  */
995 /* ARGSUSED */
996 stat(p, uap, retval)
997 	struct proc *p;
998 	register struct args {
999 		char	*fname;
1000 		struct stat *ub;
1001 	} *uap;
1002 	int *retval;
1003 {
1004 	register struct nameidata *ndp;
1005 	struct stat sb;
1006 	int error;
1007 	struct nameidata nd;
1008 
1009 	ndp = &nd;
1010 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
1011 	ndp->ni_segflg = UIO_USERSPACE;
1012 	ndp->ni_dirp = uap->fname;
1013 	if (error = namei(ndp, p))
1014 		return (error);
1015 	error = vn_stat(ndp->ni_vp, &sb, p);
1016 	vput(ndp->ni_vp);
1017 	if (error)
1018 		return (error);
1019 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1020 	return (error);
1021 }
1022 
1023 /*
1024  * Lstat system call.
1025  * This version does not follow links.
1026  */
1027 /* ARGSUSED */
1028 lstat(p, uap, retval)
1029 	struct proc *p;
1030 	register struct args {
1031 		char	*fname;
1032 		struct stat *ub;
1033 	} *uap;
1034 	int *retval;
1035 {
1036 	register struct nameidata *ndp;
1037 	struct stat sb;
1038 	int error;
1039 	struct nameidata nd;
1040 
1041 	ndp = &nd;
1042 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | NOFOLLOW;
1043 	ndp->ni_segflg = UIO_USERSPACE;
1044 	ndp->ni_dirp = uap->fname;
1045 	if (error = namei(ndp, p))
1046 		return (error);
1047 	error = vn_stat(ndp->ni_vp, &sb, p);
1048 	vput(ndp->ni_vp);
1049 	if (error)
1050 		return (error);
1051 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1052 	return (error);
1053 }
1054 
1055 /*
1056  * Return target name of a symbolic link.
1057  */
1058 /* ARGSUSED */
1059 readlink(p, uap, retval)
1060 	struct proc *p;
1061 	register struct args {
1062 		char	*name;
1063 		char	*buf;
1064 		int	count;
1065 	} *uap;
1066 	int *retval;
1067 {
1068 	register struct nameidata *ndp;
1069 	register struct vnode *vp;
1070 	struct iovec aiov;
1071 	struct uio auio;
1072 	int error;
1073 	struct nameidata nd;
1074 
1075 	ndp = &nd;
1076 	ndp->ni_nameiop = LOOKUP | LOCKLEAF;
1077 	ndp->ni_segflg = UIO_USERSPACE;
1078 	ndp->ni_dirp = uap->name;
1079 	if (error = namei(ndp, p))
1080 		return (error);
1081 	vp = ndp->ni_vp;
1082 	if (vp->v_type != VLNK) {
1083 		error = EINVAL;
1084 		goto out;
1085 	}
1086 	aiov.iov_base = uap->buf;
1087 	aiov.iov_len = uap->count;
1088 	auio.uio_iov = &aiov;
1089 	auio.uio_iovcnt = 1;
1090 	auio.uio_offset = 0;
1091 	auio.uio_rw = UIO_READ;
1092 	auio.uio_segflg = UIO_USERSPACE;
1093 	auio.uio_procp = p;
1094 	auio.uio_resid = uap->count;
1095 	error = VOP_READLINK(vp, &auio, p->p_ucred);
1096 out:
1097 	vput(vp);
1098 	*retval = uap->count - auio.uio_resid;
1099 	return (error);
1100 }
1101 
1102 /*
1103  * Change flags of a file given path name.
1104  */
1105 /* ARGSUSED */
1106 chflags(p, uap, retval)
1107 	struct proc *p;
1108 	register struct args {
1109 		char	*fname;
1110 		int	flags;
1111 	} *uap;
1112 	int *retval;
1113 {
1114 	register struct nameidata *ndp;
1115 	register struct vnode *vp;
1116 	struct vattr vattr;
1117 	int error;
1118 	struct nameidata nd;
1119 
1120 	ndp = &nd;
1121 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1122 	ndp->ni_segflg = UIO_USERSPACE;
1123 	ndp->ni_dirp = uap->fname;
1124 	if (error = namei(ndp, p))
1125 		return (error);
1126 	vp = ndp->ni_vp;
1127 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1128 		error = EROFS;
1129 		goto out;
1130 	}
1131 	VATTR_NULL(&vattr);
1132 	vattr.va_flags = uap->flags;
1133 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1134 out:
1135 	vput(vp);
1136 	return (error);
1137 }
1138 
1139 /*
1140  * Change flags of a file given a file descriptor.
1141  */
1142 /* ARGSUSED */
1143 fchflags(p, uap, retval)
1144 	struct proc *p;
1145 	register struct args {
1146 		int	fd;
1147 		int	flags;
1148 	} *uap;
1149 	int *retval;
1150 {
1151 	struct vattr vattr;
1152 	struct vnode *vp;
1153 	struct file *fp;
1154 	int error;
1155 
1156 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1157 		return (error);
1158 	vp = (struct vnode *)fp->f_data;
1159 	VOP_LOCK(vp);
1160 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1161 		error = EROFS;
1162 		goto out;
1163 	}
1164 	VATTR_NULL(&vattr);
1165 	vattr.va_flags = uap->flags;
1166 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1167 out:
1168 	VOP_UNLOCK(vp);
1169 	return (error);
1170 }
1171 
1172 /*
1173  * Change mode of a file given path name.
1174  */
1175 /* ARGSUSED */
1176 chmod(p, uap, retval)
1177 	struct proc *p;
1178 	register struct args {
1179 		char	*fname;
1180 		int	fmode;
1181 	} *uap;
1182 	int *retval;
1183 {
1184 	register struct nameidata *ndp;
1185 	register struct vnode *vp;
1186 	struct vattr vattr;
1187 	int error;
1188 	struct nameidata nd;
1189 
1190 	ndp = &nd;
1191 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1192 	ndp->ni_segflg = UIO_USERSPACE;
1193 	ndp->ni_dirp = uap->fname;
1194 	if (error = namei(ndp, p))
1195 		return (error);
1196 	vp = ndp->ni_vp;
1197 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1198 		error = EROFS;
1199 		goto out;
1200 	}
1201 	VATTR_NULL(&vattr);
1202 	vattr.va_mode = uap->fmode & 07777;
1203 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1204 out:
1205 	vput(vp);
1206 	return (error);
1207 }
1208 
1209 /*
1210  * Change mode of a file given a file descriptor.
1211  */
1212 /* ARGSUSED */
1213 fchmod(p, uap, retval)
1214 	struct proc *p;
1215 	register struct args {
1216 		int	fd;
1217 		int	fmode;
1218 	} *uap;
1219 	int *retval;
1220 {
1221 	struct vattr vattr;
1222 	struct vnode *vp;
1223 	struct file *fp;
1224 	int error;
1225 
1226 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1227 		return (error);
1228 	vp = (struct vnode *)fp->f_data;
1229 	VOP_LOCK(vp);
1230 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1231 		error = EROFS;
1232 		goto out;
1233 	}
1234 	VATTR_NULL(&vattr);
1235 	vattr.va_mode = uap->fmode & 07777;
1236 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1237 out:
1238 	VOP_UNLOCK(vp);
1239 	return (error);
1240 }
1241 
1242 /*
1243  * Set ownership given a path name.
1244  */
1245 /* ARGSUSED */
1246 chown(p, uap, retval)
1247 	struct proc *p;
1248 	register struct args {
1249 		char	*fname;
1250 		int	uid;
1251 		int	gid;
1252 	} *uap;
1253 	int *retval;
1254 {
1255 	register struct nameidata *ndp;
1256 	register struct vnode *vp;
1257 	struct vattr vattr;
1258 	int error;
1259 	struct nameidata nd;
1260 
1261 	ndp = &nd;
1262 	ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF;
1263 	ndp->ni_segflg = UIO_USERSPACE;
1264 	ndp->ni_dirp = uap->fname;
1265 	if (error = namei(ndp, p))
1266 		return (error);
1267 	vp = ndp->ni_vp;
1268 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1269 		error = EROFS;
1270 		goto out;
1271 	}
1272 	VATTR_NULL(&vattr);
1273 	vattr.va_uid = uap->uid;
1274 	vattr.va_gid = uap->gid;
1275 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1276 out:
1277 	vput(vp);
1278 	return (error);
1279 }
1280 
1281 /*
1282  * Set ownership given a file descriptor.
1283  */
1284 /* ARGSUSED */
1285 fchown(p, uap, retval)
1286 	struct proc *p;
1287 	register struct args {
1288 		int	fd;
1289 		int	uid;
1290 		int	gid;
1291 	} *uap;
1292 	int *retval;
1293 {
1294 	struct vattr vattr;
1295 	struct vnode *vp;
1296 	struct file *fp;
1297 	int error;
1298 
1299 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1300 		return (error);
1301 	vp = (struct vnode *)fp->f_data;
1302 	VOP_LOCK(vp);
1303 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1304 		error = EROFS;
1305 		goto out;
1306 	}
1307 	VATTR_NULL(&vattr);
1308 	vattr.va_uid = uap->uid;
1309 	vattr.va_gid = uap->gid;
1310 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1311 out:
1312 	VOP_UNLOCK(vp);
1313 	return (error);
1314 }
1315 
1316 /*
1317  * Set the access and modification times of a file.
1318  */
1319 /* ARGSUSED */
1320 utimes(p, uap, retval)
1321 	struct proc *p;
1322 	register struct args {
1323 		char	*fname;
1324 		struct	timeval *tptr;
1325 	} *uap;
1326 	int *retval;
1327 {
1328 	register struct nameidata *ndp;
1329 	register struct vnode *vp;
1330 	struct timeval tv[2];
1331 	struct vattr vattr;
1332 	int error;
1333 	struct nameidata nd;
1334 
1335 	if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1336 		return (error);
1337 	ndp = &nd;
1338 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1339 	ndp->ni_segflg = UIO_USERSPACE;
1340 	ndp->ni_dirp = uap->fname;
1341 	if (error = namei(ndp, p))
1342 		return (error);
1343 	vp = ndp->ni_vp;
1344 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1345 		error = EROFS;
1346 		goto out;
1347 	}
1348 	VATTR_NULL(&vattr);
1349 	vattr.va_atime = tv[0];
1350 	vattr.va_mtime = tv[1];
1351 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1352 out:
1353 	vput(vp);
1354 	return (error);
1355 }
1356 
1357 /*
1358  * Truncate a file given its path name.
1359  */
1360 /* ARGSUSED */
1361 truncate(p, uap, retval)
1362 	struct proc *p;
1363 	register struct args {
1364 		char	*fname;
1365 		off_t	length;
1366 	} *uap;
1367 	int *retval;
1368 {
1369 	register struct nameidata *ndp;
1370 	register struct vnode *vp;
1371 	struct vattr vattr;
1372 	int error;
1373 	struct nameidata nd;
1374 
1375 	ndp = &nd;
1376 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1377 	ndp->ni_segflg = UIO_USERSPACE;
1378 	ndp->ni_dirp = uap->fname;
1379 	if (error = namei(ndp, p))
1380 		return (error);
1381 	vp = ndp->ni_vp;
1382 	if (vp->v_type == VDIR) {
1383 		error = EISDIR;
1384 		goto out;
1385 	}
1386 	if ((error = vn_writechk(vp)) ||
1387 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)))
1388 		goto out;
1389 	VATTR_NULL(&vattr);
1390 	vattr.va_size = uap->length;
1391 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1392 out:
1393 	vput(vp);
1394 	return (error);
1395 }
1396 
1397 /*
1398  * Truncate a file given a file descriptor.
1399  */
1400 /* ARGSUSED */
1401 ftruncate(p, uap, retval)
1402 	struct proc *p;
1403 	register struct args {
1404 		int	fd;
1405 		off_t	length;
1406 	} *uap;
1407 	int *retval;
1408 {
1409 	struct vattr vattr;
1410 	struct vnode *vp;
1411 	struct file *fp;
1412 	int error;
1413 
1414 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1415 		return (error);
1416 	if ((fp->f_flag & FWRITE) == 0)
1417 		return (EINVAL);
1418 	vp = (struct vnode *)fp->f_data;
1419 	VOP_LOCK(vp);
1420 	if (vp->v_type == VDIR) {
1421 		error = EISDIR;
1422 		goto out;
1423 	}
1424 	if (error = vn_writechk(vp))
1425 		goto out;
1426 	VATTR_NULL(&vattr);
1427 	vattr.va_size = uap->length;
1428 	error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1429 out:
1430 	VOP_UNLOCK(vp);
1431 	return (error);
1432 }
1433 
1434 /*
1435  * Synch an open file.
1436  */
1437 /* ARGSUSED */
1438 fsync(p, uap, retval)
1439 	struct proc *p;
1440 	struct args {
1441 		int	fd;
1442 	} *uap;
1443 	int *retval;
1444 {
1445 	register struct vnode *vp;
1446 	struct file *fp;
1447 	int error;
1448 
1449 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1450 		return (error);
1451 	vp = (struct vnode *)fp->f_data;
1452 	VOP_LOCK(vp);
1453 	error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT, p);
1454 	VOP_UNLOCK(vp);
1455 	return (error);
1456 }
1457 
1458 /*
1459  * Rename system call.
1460  *
1461  * Source and destination must either both be directories, or both
1462  * not be directories.  If target is a directory, it must be empty.
1463  */
1464 /* ARGSUSED */
1465 rename(p, uap, retval)
1466 	struct proc *p;
1467 	register struct args {
1468 		char	*from;
1469 		char	*to;
1470 	} *uap;
1471 	int *retval;
1472 {
1473 	register struct vnode *tvp, *fvp, *tdvp;
1474 	struct nameidata fromnd, tond;
1475 	int error;
1476 
1477 	fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART;
1478 	fromnd.ni_segflg = UIO_USERSPACE;
1479 	fromnd.ni_dirp = uap->from;
1480 	if (error = namei(&fromnd, p))
1481 		return (error);
1482 	fvp = fromnd.ni_vp;
1483 	tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
1484 	tond.ni_segflg = UIO_USERSPACE;
1485 	tond.ni_dirp = uap->to;
1486 	if (error = namei(&tond, p)) {
1487 		VOP_ABORTOP(&fromnd);
1488 		vrele(fromnd.ni_dvp);
1489 		vrele(fvp);
1490 		goto out1;
1491 	}
1492 	tdvp = tond.ni_dvp;
1493 	tvp = tond.ni_vp;
1494 	if (tvp != NULL) {
1495 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1496 			error = ENOTDIR;
1497 			goto out;
1498 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1499 			error = EISDIR;
1500 			goto out;
1501 		}
1502 		if (fvp->v_mount != tvp->v_mount) {
1503 			error = EXDEV;
1504 			goto out;
1505 		}
1506 	}
1507 	if (fvp->v_mount != tdvp->v_mount) {
1508 		error = EXDEV;
1509 		goto out;
1510 	}
1511 	if (fvp == tdvp)
1512 		error = EINVAL;
1513 	/*
1514 	 * If source is the same as the destination (that is the
1515 	 * same inode number with the same name in the same directory),
1516 	 * then there is nothing to do.
1517 	 */
1518 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1519 	    fromnd.ni_namelen == tond.ni_namelen &&
1520 	    !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen))
1521 		error = -1;
1522 out:
1523 	if (!error) {
1524 		error = VOP_RENAME(&fromnd, &tond, p);
1525 	} else {
1526 		VOP_ABORTOP(&tond);
1527 		if (tdvp == tvp)
1528 			vrele(tdvp);
1529 		else
1530 			vput(tdvp);
1531 		if (tvp)
1532 			vput(tvp);
1533 		VOP_ABORTOP(&fromnd);
1534 		vrele(fromnd.ni_dvp);
1535 		vrele(fvp);
1536 	}
1537 	vrele(tond.ni_startdir);
1538 	FREE(tond.ni_pnbuf, M_NAMEI);
1539 out1:
1540 	vrele(fromnd.ni_startdir);
1541 	FREE(fromnd.ni_pnbuf, M_NAMEI);
1542 	if (error == -1)
1543 		return (0);
1544 	return (error);
1545 }
1546 
1547 /*
1548  * Mkdir system call.
1549  */
1550 /* ARGSUSED */
1551 mkdir(p, uap, retval)
1552 	struct proc *p;
1553 	register struct args {
1554 		char	*name;
1555 		int	dmode;
1556 	} *uap;
1557 	int *retval;
1558 {
1559 	register struct nameidata *ndp;
1560 	register struct vnode *vp;
1561 	struct vattr vattr;
1562 	int error;
1563 	struct nameidata nd;
1564 
1565 	ndp = &nd;
1566 	ndp->ni_nameiop = CREATE | LOCKPARENT;
1567 	ndp->ni_segflg = UIO_USERSPACE;
1568 	ndp->ni_dirp = uap->name;
1569 	if (error = namei(ndp, p))
1570 		return (error);
1571 	vp = ndp->ni_vp;
1572 	if (vp != NULL) {
1573 		VOP_ABORTOP(ndp);
1574 		if (ndp->ni_dvp == vp)
1575 			vrele(ndp->ni_dvp);
1576 		else
1577 			vput(ndp->ni_dvp);
1578 		vrele(vp);
1579 		return (EEXIST);
1580 	}
1581 	VATTR_NULL(&vattr);
1582 	vattr.va_type = VDIR;
1583 	vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask;
1584 	error = VOP_MKDIR(ndp, &vattr, p);
1585 	if (!error)
1586 		vput(ndp->ni_vp);
1587 	return (error);
1588 }
1589 
1590 /*
1591  * Rmdir system call.
1592  */
1593 /* ARGSUSED */
1594 rmdir(p, uap, retval)
1595 	struct proc *p;
1596 	struct args {
1597 		char	*name;
1598 	} *uap;
1599 	int *retval;
1600 {
1601 	register struct nameidata *ndp;
1602 	register struct vnode *vp;
1603 	int error;
1604 	struct nameidata nd;
1605 
1606 	ndp = &nd;
1607 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
1608 	ndp->ni_segflg = UIO_USERSPACE;
1609 	ndp->ni_dirp = uap->name;
1610 	if (error = namei(ndp, p))
1611 		return (error);
1612 	vp = ndp->ni_vp;
1613 	if (vp->v_type != VDIR) {
1614 		error = ENOTDIR;
1615 		goto out;
1616 	}
1617 	/*
1618 	 * No rmdir "." please.
1619 	 */
1620 	if (ndp->ni_dvp == vp) {
1621 		error = EINVAL;
1622 		goto out;
1623 	}
1624 	/*
1625 	 * The root of a mounted filesystem cannot be deleted.
1626 	 */
1627 	if (vp->v_flag & VROOT)
1628 		error = EBUSY;
1629 out:
1630 	if (!error) {
1631 		error = VOP_RMDIR(ndp, p);
1632 	} else {
1633 		VOP_ABORTOP(ndp);
1634 		if (ndp->ni_dvp == vp)
1635 			vrele(ndp->ni_dvp);
1636 		else
1637 			vput(ndp->ni_dvp);
1638 		vput(vp);
1639 	}
1640 	return (error);
1641 }
1642 
1643 /*
1644  * Read a block of directory entries in a file system independent format.
1645  */
1646 getdirentries(p, uap, retval)
1647 	struct proc *p;
1648 	register struct args {
1649 		int	fd;
1650 		char	*buf;
1651 		unsigned count;
1652 		long	*basep;
1653 	} *uap;
1654 	int *retval;
1655 {
1656 	register struct vnode *vp;
1657 	struct file *fp;
1658 	struct uio auio;
1659 	struct iovec aiov;
1660 	off_t off;
1661 	int error, eofflag;
1662 
1663 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1664 		return (error);
1665 	if ((fp->f_flag & FREAD) == 0)
1666 		return (EBADF);
1667 	vp = (struct vnode *)fp->f_data;
1668 	if (vp->v_type != VDIR)
1669 		return (EINVAL);
1670 	aiov.iov_base = uap->buf;
1671 	aiov.iov_len = uap->count;
1672 	auio.uio_iov = &aiov;
1673 	auio.uio_iovcnt = 1;
1674 	auio.uio_rw = UIO_READ;
1675 	auio.uio_segflg = UIO_USERSPACE;
1676 	auio.uio_procp = p;
1677 	auio.uio_resid = uap->count;
1678 	VOP_LOCK(vp);
1679 	auio.uio_offset = off = fp->f_offset;
1680 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag);
1681 	fp->f_offset = auio.uio_offset;
1682 	VOP_UNLOCK(vp);
1683 	if (error)
1684 		return (error);
1685 	error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
1686 	*retval = uap->count - auio.uio_resid;
1687 	return (error);
1688 }
1689 
1690 /*
1691  * Set the mode mask for creation of filesystem nodes.
1692  */
1693 mode_t
1694 umask(p, uap, retval)
1695 	struct proc *p;
1696 	struct args {
1697 		int	mask;
1698 	} *uap;
1699 	int *retval;
1700 {
1701 	register struct filedesc *fdp = p->p_fd;
1702 
1703 	*retval = fdp->fd_cmask;
1704 	fdp->fd_cmask = uap->mask & 07777;
1705 	return (0);
1706 }
1707 
1708 /*
1709  * Void all references to file by ripping underlying filesystem
1710  * away from vnode.
1711  */
1712 /* ARGSUSED */
1713 revoke(p, uap, retval)
1714 	struct proc *p;
1715 	register struct args {
1716 		char	*fname;
1717 	} *uap;
1718 	int *retval;
1719 {
1720 	register struct nameidata *ndp;
1721 	register struct vnode *vp;
1722 	struct vattr vattr;
1723 	int error;
1724 	struct nameidata nd;
1725 
1726 	ndp = &nd;
1727 	ndp->ni_nameiop = LOOKUP | FOLLOW;
1728 	ndp->ni_segflg = UIO_USERSPACE;
1729 	ndp->ni_dirp = uap->fname;
1730 	if (error = namei(ndp, p))
1731 		return (error);
1732 	vp = ndp->ni_vp;
1733 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
1734 		error = EINVAL;
1735 		goto out;
1736 	}
1737 	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
1738 		goto out;
1739 	if (p->p_ucred->cr_uid != vattr.va_uid &&
1740 	    (error = suser(p->p_ucred, &p->p_acflag)))
1741 		goto out;
1742 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
1743 		vgoneall(vp);
1744 out:
1745 	vrele(vp);
1746 	return (error);
1747 }
1748 
1749 /*
1750  * Convert a user file descriptor to a kernel file entry.
1751  */
1752 getvnode(fdp, fdes, fpp)
1753 	struct filedesc *fdp;
1754 	struct file **fpp;
1755 	int fdes;
1756 {
1757 	struct file *fp;
1758 
1759 	if ((unsigned)fdes >= fdp->fd_nfiles ||
1760 	    (fp = fdp->fd_ofiles[fdes]) == NULL)
1761 		return (EBADF);
1762 	if (fp->f_type != DTYPE_VNODE)
1763 		return (EINVAL);
1764 	*fpp = fp;
1765 	return (0);
1766 }
1767