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