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