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