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