xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 43405)
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.53 (Berkeley) 06/21/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 #define	p_devtmp	p_logname[11]
33 
34 #undef RETURN
35 #define RETURN(val)	{ u.u_error = (val); if (u.u_spare[0] != 0) panic("lock count"); return (u.u_error); }
36 
37 /*
38  * Virtual File System System Calls
39  */
40 
41 /*
42  * mount system call
43  */
44 /* ARGSUSED */
45 mount(p, uap, retval)
46 	register struct proc *p;
47 	register struct args {
48 		int	type;
49 		char	*dir;
50 		int	flags;
51 		caddr_t	data;
52 	} *uap;
53 	int *retval;
54 {
55 	register struct nameidata *ndp = &u.u_nd;
56 	register struct vnode *vp;
57 	register struct mount *mp;
58 	int error, flag;
59 
60 	/*
61 	 * Must be super user
62 	 */
63 	if (error = suser(ndp->ni_cred, &u.u_acflag))
64 		RETURN (error);
65 	/*
66 	 * Get vnode to be covered
67 	 */
68 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
69 	ndp->ni_segflg = UIO_USERSPACE;
70 	ndp->ni_dirp = uap->dir;
71 	if (error = namei(ndp))
72 		RETURN (error);
73 	vp = ndp->ni_vp;
74 	if (uap->flags & MNT_UPDATE) {
75 		if ((vp->v_flag & VROOT) == 0) {
76 			vput(vp);
77 			RETURN (EINVAL);
78 		}
79 		mp = vp->v_mount;
80 		/*
81 		 * We allow going from read-only to read-write,
82 		 * but not from read-write to read-only.
83 		 */
84 		if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
85 		    (uap->flags & MNT_RDONLY) != 0) {
86 			vput(vp);
87 			RETURN (EOPNOTSUPP);	/* Needs translation */
88 		}
89 		flag = mp->mnt_flag;
90 		mp->mnt_flag |= MNT_UPDATE;
91 		VOP_UNLOCK(vp);
92 		goto update;
93 	}
94 	vinvalbuf(vp, 1);
95 	if (vp->v_usecount != 1) {
96 		vput(vp);
97 		RETURN (EBUSY);
98 	}
99 	if (vp->v_type != VDIR) {
100 		vput(vp);
101 		RETURN (ENOTDIR);
102 	}
103 	if ((unsigned long)uap->type > MOUNT_MAXTYPE ||
104 	    vfssw[uap->type] == (struct vfsops *)0) {
105 		vput(vp);
106 		RETURN (ENODEV);
107 	}
108 
109 	/*
110 	 * Allocate and initialize the file system.
111 	 */
112 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
113 		M_MOUNT, M_WAITOK);
114 	mp->mnt_op = vfssw[uap->type];
115 	mp->mnt_flag = 0;
116 	mp->mnt_exroot = 0;
117 	mp->mnt_mounth = NULLVP;
118 	if (error = vfs_lock(mp)) {
119 		free((caddr_t)mp, M_MOUNT);
120 		vput(vp);
121 		RETURN (error);
122 	}
123 	if (vp->v_mountedhere != (struct mount *)0) {
124 		vfs_unlock(mp);
125 		free((caddr_t)mp, M_MOUNT);
126 		vput(vp);
127 		RETURN (EBUSY);
128 	}
129 	vp->v_mountedhere = mp;
130 	mp->mnt_vnodecovered = vp;
131 update:
132 	/*
133 	 * Set the mount level flags.
134 	 */
135 	if (uap->flags & MNT_RDONLY)
136 		mp->mnt_flag |= MNT_RDONLY;
137 	else
138 		mp->mnt_flag &= ~MNT_RDONLY;
139 	if (uap->flags & MNT_NOSUID)
140 		mp->mnt_flag |= MNT_NOSUID;
141 	else
142 		mp->mnt_flag &= ~MNT_NOSUID;
143 	if (uap->flags & MNT_NOEXEC)
144 		mp->mnt_flag |= MNT_NOEXEC;
145 	else
146 		mp->mnt_flag &= ~MNT_NOEXEC;
147 	if (uap->flags & MNT_NODEV)
148 		mp->mnt_flag |= MNT_NODEV;
149 	else
150 		mp->mnt_flag &= ~MNT_NODEV;
151 	if (uap->flags & MNT_SYNCHRONOUS)
152 		mp->mnt_flag |= MNT_SYNCHRONOUS;
153 	else
154 		mp->mnt_flag &= ~MNT_SYNCHRONOUS;
155 	/*
156 	 * Mount the filesystem.
157 	 */
158 	error = VFS_MOUNT(mp, uap->dir, uap->data, ndp);
159 	if (mp->mnt_flag & MNT_UPDATE) {
160 		mp->mnt_flag &= ~MNT_UPDATE;
161 		vrele(vp);
162 		if (error)
163 			mp->mnt_flag = flag;
164 		RETURN (error);
165 	}
166 	/*
167 	 * Put the new filesystem on the mount list after root.
168 	 */
169 	mp->mnt_next = rootfs->mnt_next;
170 	mp->mnt_prev = rootfs;
171 	rootfs->mnt_next = mp;
172 	mp->mnt_next->mnt_prev = mp;
173 	cache_purge(vp);
174 	if (!error) {
175 		VOP_UNLOCK(vp);
176 		vfs_unlock(mp);
177 		error = VFS_START(mp, 0);
178 	} else {
179 		vfs_remove(mp);
180 		free((caddr_t)mp, M_MOUNT);
181 		vput(vp);
182 	}
183 	RETURN (error);
184 }
185 
186 /*
187  * Unmount system call.
188  *
189  * Note: unmount takes a path to the vnode mounted on as argument,
190  * not special file (as before).
191  */
192 /* ARGSUSED */
193 unmount(p, uap, retval)
194 	register struct proc *p;
195 	register struct args {
196 		char	*pathp;
197 		int	flags;
198 	} *uap;
199 	int *retval;
200 {
201 	register struct vnode *vp;
202 	register struct nameidata *ndp = &u.u_nd;
203 	struct mount *mp;
204 	int error;
205 
206 	/*
207 	 * Must be super user
208 	 */
209 	if (error = suser(ndp->ni_cred, &u.u_acflag))
210 		RETURN (error);
211 
212 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
213 	ndp->ni_segflg = UIO_USERSPACE;
214 	ndp->ni_dirp = uap->pathp;
215 	if (error = namei(ndp))
216 		RETURN (error);
217 	vp = ndp->ni_vp;
218 	/*
219 	 * Must be the root of the filesystem
220 	 */
221 	if ((vp->v_flag & VROOT) == 0) {
222 		vput(vp);
223 		RETURN (EINVAL);
224 	}
225 	mp = vp->v_mount;
226 	vput(vp);
227 	RETURN (dounmount(mp, uap->flags));
228 }
229 
230 /*
231  * Do an unmount.
232  */
233 dounmount(mp, flags)
234 	register struct mount *mp;
235 	int flags;
236 {
237 	struct vnode *coveredvp;
238 	int error;
239 
240 	coveredvp = mp->mnt_vnodecovered;
241 	if (vfs_busy(mp))
242 		return (EBUSY);
243 	mp->mnt_flag |= MNT_UNMOUNT;
244 	if (error = vfs_lock(mp))
245 		return (error);
246 
247 	xumount(mp);		/* remove unused sticky files from text table */
248 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
249 	if ((error = VFS_SYNC(mp, MNT_WAIT)) == 0 || (flags & MNT_FORCE))
250 		error = VFS_UNMOUNT(mp, flags);
251 	mp->mnt_flag &= ~MNT_UNMOUNT;
252 	vfs_unbusy(mp);
253 	if (error) {
254 		vfs_unlock(mp);
255 	} else {
256 		vrele(coveredvp);
257 		vfs_remove(mp);
258 		free((caddr_t)mp, M_MOUNT);
259 	}
260 	return (error);
261 }
262 
263 /*
264  * Sync system call.
265  * Sync each mounted filesystem.
266  */
267 /* ARGSUSED */
268 sync(p, uap, retval)
269 	register struct proc *p;
270 	struct args *uap;
271 	int *retval;
272 {
273 	register struct mount *mp;
274 	struct mount *omp;
275 
276 	mp = rootfs;
277 	do {
278 		/*
279 		 * The lock check below is to avoid races with mount
280 		 * and unmount.
281 		 */
282 		if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
283 		    !vfs_busy(mp)) {
284 			VFS_SYNC(mp, MNT_NOWAIT);
285 			omp = mp;
286 			mp = mp->mnt_next;
287 			vfs_unbusy(omp);
288 		} else
289 			mp = mp->mnt_next;
290 	} while (mp != rootfs);
291 }
292 
293 /*
294  * operate on filesystem quotas
295  */
296 /* ARGSUSED */
297 quotactl(p, uap, retval)
298 	register struct proc *p;
299 	register struct args {
300 		char *path;
301 		int cmd;
302 		int uid;
303 		caddr_t arg;
304 	} *uap;
305 	int *retval;
306 {
307 	register struct mount *mp;
308 	register struct nameidata *ndp = &u.u_nd;
309 	int error;
310 
311 	ndp->ni_nameiop = LOOKUP | FOLLOW;
312 	ndp->ni_segflg = UIO_USERSPACE;
313 	ndp->ni_dirp = uap->path;
314 	if (error = namei(ndp))
315 		RETURN (error);
316 	mp = ndp->ni_vp->v_mount;
317 	vrele(ndp->ni_vp);
318 	RETURN (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg));
319 }
320 
321 /*
322  * get filesystem statistics
323  */
324 /* ARGSUSED */
325 statfs(p, uap, retval)
326 	register struct proc *p;
327 	register struct args {
328 		char *path;
329 		struct statfs *buf;
330 	} *uap;
331 	int *retval;
332 {
333 	register struct mount *mp;
334 	register struct nameidata *ndp = &u.u_nd;
335 	register struct statfs *sp;
336 	int error;
337 
338 	ndp->ni_nameiop = LOOKUP | FOLLOW;
339 	ndp->ni_segflg = UIO_USERSPACE;
340 	ndp->ni_dirp = uap->path;
341 	if (error = namei(ndp))
342 		RETURN (error);
343 	mp = ndp->ni_vp->v_mount;
344 	sp = &mp->mnt_stat;
345 	vrele(ndp->ni_vp);
346 	if (error = VFS_STATFS(mp, sp))
347 		RETURN (error);
348 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
349 	RETURN (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
350 }
351 
352 /*
353  * get filesystem statistics
354  */
355 /* ARGSUSED */
356 fstatfs(p, uap, retval)
357 	register struct proc *p;
358 	register struct args {
359 		int fd;
360 		struct statfs *buf;
361 	} *uap;
362 	int *retval;
363 {
364 	struct file *fp;
365 	struct mount *mp;
366 	register struct statfs *sp;
367 	int error;
368 
369 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
370 		RETURN (error);
371 	mp = ((struct vnode *)fp->f_data)->v_mount;
372 	sp = &mp->mnt_stat;
373 	if (error = VFS_STATFS(mp, sp))
374 		RETURN (error);
375 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
376 	RETURN (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
377 }
378 
379 /*
380  * get statistics on all filesystems
381  */
382 getfsstat(p, uap, retval)
383 	register struct proc *p;
384 	register struct args {
385 		struct statfs *buf;
386 		long bufsize;
387 		int flags;
388 	} *uap;
389 	int *retval;
390 {
391 	register struct mount *mp;
392 	register struct statfs *sp;
393 	caddr_t sfsp;
394 	long count, maxcount, error;
395 
396 	maxcount = uap->bufsize / sizeof(struct statfs);
397 	sfsp = (caddr_t)uap->buf;
398 	mp = rootfs;
399 	count = 0;
400 	do {
401 		if (sfsp && count < maxcount &&
402 		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
403 			sp = &mp->mnt_stat;
404 			/*
405 			 * If MNT_NOWAIT is specified, do not refresh the
406 			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
407 			 */
408 			if (((uap->flags & MNT_NOWAIT) == 0 ||
409 			    (uap->flags & MNT_WAIT)) &&
410 			    (error = VFS_STATFS(mp, sp))) {
411 				mp = mp->mnt_prev;
412 				continue;
413 			}
414 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
415 			if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
416 				RETURN (error);
417 			sfsp += sizeof(*sp);
418 		}
419 		count++;
420 		mp = mp->mnt_prev;
421 	} while (mp != rootfs);
422 	if (sfsp && count > maxcount)
423 		*retval = maxcount;
424 	else
425 		*retval = count;
426 	RETURN (0);
427 }
428 
429 /*
430  * Change current working directory to a given file descriptor.
431  */
432 /* ARGSUSED */
433 fchdir(p, uap, retval)
434 	register struct proc *p;
435 	struct args {
436 		int	fd;
437 	} *uap;
438 	int *retval;
439 {
440 	register struct nameidata *ndp = &u.u_nd;
441 	register struct vnode *vp;
442 	struct file *fp;
443 	int error;
444 
445 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
446 		RETURN (error);
447 	vp = (struct vnode *)fp->f_data;
448 	VOP_LOCK(vp);
449 	if (vp->v_type != VDIR)
450 		error = ENOTDIR;
451 	else
452 		error = VOP_ACCESS(vp, VEXEC, ndp->ni_cred);
453 	VOP_UNLOCK(vp);
454 	if (error)
455 		RETURN (error);
456 	VREF(vp);
457 	vrele(ndp->ni_cdir);
458 	ndp->ni_cdir = vp;
459 	RETURN (0);
460 }
461 
462 /*
463  * Change current working directory (``.'').
464  */
465 /* ARGSUSED */
466 chdir(p, uap, retval)
467 	register struct proc *p;
468 	struct args {
469 		char	*fname;
470 	} *uap;
471 	int *retval;
472 {
473 	register struct nameidata *ndp = &u.u_nd;
474 	int error;
475 
476 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
477 	ndp->ni_segflg = UIO_USERSPACE;
478 	ndp->ni_dirp = uap->fname;
479 	if (error = chdirec(ndp))
480 		RETURN (error);
481 	vrele(ndp->ni_cdir);
482 	ndp->ni_cdir = ndp->ni_vp;
483 	RETURN (0);
484 }
485 
486 /*
487  * Change notion of root (``/'') directory.
488  */
489 /* ARGSUSED */
490 chroot(p, uap, retval)
491 	register struct proc *p;
492 	struct args {
493 		char	*fname;
494 	} *uap;
495 	int *retval;
496 {
497 	register struct nameidata *ndp = &u.u_nd;
498 	int error;
499 
500 	if (error = suser(ndp->ni_cred, &u.u_acflag))
501 		RETURN (error);
502 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
503 	ndp->ni_segflg = UIO_USERSPACE;
504 	ndp->ni_dirp = uap->fname;
505 	if (error = chdirec(ndp))
506 		RETURN (error);
507 	if (ndp->ni_rdir != NULL)
508 		vrele(ndp->ni_rdir);
509 	ndp->ni_rdir = ndp->ni_vp;
510 	RETURN (0);
511 }
512 
513 /*
514  * Common routine for chroot and chdir.
515  */
516 chdirec(ndp)
517 	register struct nameidata *ndp;
518 {
519 	struct vnode *vp;
520 	int error;
521 
522 	if (error = namei(ndp))
523 		return (error);
524 	vp = ndp->ni_vp;
525 	if (vp->v_type != VDIR)
526 		error = ENOTDIR;
527 	else
528 		error = VOP_ACCESS(vp, VEXEC, ndp->ni_cred);
529 	VOP_UNLOCK(vp);
530 	if (error)
531 		vrele(vp);
532 	return (error);
533 }
534 
535 /*
536  * Open system call.
537  * Check permissions, allocate an open file structure,
538  * and call the device open routine if any.
539  */
540 open(p, uap, retval)
541 	register struct proc *p;
542 	register struct args {
543 		char	*fname;
544 		int	mode;
545 		int	crtmode;
546 	} *uap;
547 	int *retval;
548 {
549 	struct nameidata *ndp = &u.u_nd;
550 	register struct file *fp;
551 	int fmode, cmode;
552 	struct file *nfp;
553 	int indx, error;
554 	extern struct fileops vnops;
555 
556 	if (error = falloc(&nfp, &indx))
557 		RETURN (error);
558 	fp = nfp;
559 	fmode = uap->mode - FOPEN;
560 	cmode = ((uap->crtmode &~ u.u_cmask) & 07777) &~ S_ISVTX;
561 	ndp->ni_segflg = UIO_USERSPACE;
562 	ndp->ni_dirp = uap->fname;
563 	p->p_devtmp = -1;			/* XXX check for fdopen */
564 	if (error = vn_open(ndp, fmode, cmode)) {
565 		crfree(fp->f_cred);
566 		fp->f_count--;
567 		if (error == ENODEV &&		/* XXX from fdopen */
568 		    p->p_devtmp >= 0 &&
569 		    (error = dupfdopen(indx, p->p_devtmp, fmode)) == 0) {
570 			*retval = indx;
571 			RETURN (0);
572 		}
573 		if (error == ERESTART)
574 			error = EINTR;
575 		u.u_ofile[indx] = NULL;
576 		RETURN (error);
577 	}
578 	fp->f_flag = fmode & FMASK;
579 	fp->f_type = DTYPE_VNODE;
580 	fp->f_ops = &vnops;
581 	fp->f_data = (caddr_t)ndp->ni_vp;
582 	*retval = indx;
583 	RETURN (0);
584 }
585 
586 #ifdef COMPAT_43
587 /*
588  * Creat system call.
589  */
590 ocreat(p, uap, retval)
591 	struct proc *p;
592 	register struct args {
593 		char	*fname;
594 		int	fmode;
595 	} *uap;
596 	int *retval;
597 {
598 	struct args {
599 		char	*fname;
600 		int	mode;
601 		int	crtmode;
602 	} openuap;
603 
604 	openuap.fname = uap->fname;
605 	openuap.crtmode = uap->fmode;
606 	openuap.mode = O_WRONLY | O_CREAT | O_TRUNC;
607 	RETURN (open(p, &openuap, retval));
608 }
609 #endif /* COMPAT_43 */
610 
611 /*
612  * Mknod system call
613  */
614 /* ARGSUSED */
615 mknod(p, uap, retval)
616 	register struct proc *p;
617 	register struct args {
618 		char	*fname;
619 		int	fmode;
620 		int	dev;
621 	} *uap;
622 	int *retval;
623 {
624 	register struct nameidata *ndp = &u.u_nd;
625 	register struct vnode *vp;
626 	struct vattr vattr;
627 	int error;
628 
629 	if (error = suser(ndp->ni_cred, &u.u_acflag))
630 		RETURN (error);
631 	ndp->ni_nameiop = CREATE | LOCKPARENT;
632 	ndp->ni_segflg = UIO_USERSPACE;
633 	ndp->ni_dirp = uap->fname;
634 	if (error = namei(ndp))
635 		RETURN (error);
636 	vp = ndp->ni_vp;
637 	if (vp != NULL) {
638 		error = EEXIST;
639 		goto out;
640 	}
641 	VATTR_NULL(&vattr);
642 	switch (uap->fmode & S_IFMT) {
643 
644 	case S_IFMT:	/* used by badsect to flag bad sectors */
645 		vattr.va_type = VBAD;
646 		break;
647 	case S_IFCHR:
648 		vattr.va_type = VCHR;
649 		break;
650 	case S_IFBLK:
651 		vattr.va_type = VBLK;
652 		break;
653 	default:
654 		error = EINVAL;
655 		goto out;
656 	}
657 	vattr.va_mode = (uap->fmode & 07777) &~ u.u_cmask;
658 	vattr.va_rdev = uap->dev;
659 out:
660 	if (!error) {
661 		error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred);
662 	} else {
663 		VOP_ABORTOP(ndp);
664 		if (ndp->ni_dvp == vp)
665 			vrele(ndp->ni_dvp);
666 		else
667 			vput(ndp->ni_dvp);
668 		if (vp)
669 			vrele(vp);
670 	}
671 	RETURN (error);
672 }
673 
674 /*
675  * Mkfifo system call
676  */
677 /* ARGSUSED */
678 mkfifo(p, uap, retval)
679 	register struct proc *p;
680 	register struct args {
681 		char	*fname;
682 		int	fmode;
683 	} *uap;
684 	int *retval;
685 {
686 	register struct nameidata *ndp = &u.u_nd;
687 	struct vattr vattr;
688 	int error;
689 
690 #ifndef FIFO
691 	RETURN (EOPNOTSUPP);
692 #else
693 	ndp->ni_nameiop = CREATE | LOCKPARENT;
694 	ndp->ni_segflg = UIO_USERSPACE;
695 	ndp->ni_dirp = uap->fname;
696 	if (error = namei(ndp))
697 		RETURN (error);
698 	if (ndp->ni_vp != NULL) {
699 		VOP_ABORTOP(ndp);
700 		if (ndp->ni_dvp == ndp->ni_vp)
701 			vrele(ndp->ni_dvp);
702 		else
703 			vput(ndp->ni_dvp);
704 		vrele(ndp->ni_vp);
705 		RETURN (EEXIST);
706 	} else {
707 		VATTR_NULL(&vattr);
708 		vattr.va_type = VFIFO;
709 		vattr.va_mode = (uap->fmode & 07777) &~ u.u_cmask;
710 	}
711 	RETURN (VOP_MKNOD(ndp, &vattr, ndp->ni_cred));
712 #endif /* FIFO */
713 }
714 
715 /*
716  * link system call
717  */
718 /* ARGSUSED */
719 link(p, uap, retval)
720 	register struct proc *p;
721 	register struct args {
722 		char	*target;
723 		char	*linkname;
724 	} *uap;
725 	int *retval;
726 {
727 	register struct nameidata *ndp = &u.u_nd;
728 	register struct vnode *vp, *xp;
729 	int error;
730 
731 	ndp->ni_nameiop = LOOKUP | FOLLOW;
732 	ndp->ni_segflg = UIO_USERSPACE;
733 	ndp->ni_dirp = uap->target;
734 	if (error = namei(ndp))
735 		RETURN (error);
736 	vp = ndp->ni_vp;
737 	if (vp->v_type == VDIR &&
738 	    (error = suser(ndp->ni_cred, &u.u_acflag)))
739 		goto out1;
740 	ndp->ni_nameiop = CREATE | LOCKPARENT;
741 	ndp->ni_dirp = (caddr_t)uap->linkname;
742 	if (error = namei(ndp))
743 		goto out1;
744 	xp = ndp->ni_vp;
745 	if (xp != NULL) {
746 		error = EEXIST;
747 		goto out;
748 	}
749 	xp = ndp->ni_dvp;
750 	if (vp->v_mount != xp->v_mount)
751 		error = EXDEV;
752 out:
753 	if (!error) {
754 		error = VOP_LINK(vp, ndp);
755 	} else {
756 		VOP_ABORTOP(ndp);
757 		if (ndp->ni_dvp == ndp->ni_vp)
758 			vrele(ndp->ni_dvp);
759 		else
760 			vput(ndp->ni_dvp);
761 		if (ndp->ni_vp)
762 			vrele(ndp->ni_vp);
763 	}
764 out1:
765 	vrele(vp);
766 	RETURN (error);
767 }
768 
769 /*
770  * symlink -- make a symbolic link
771  */
772 /* ARGSUSED */
773 symlink(p, uap, retval)
774 	register struct proc *p;
775 	register struct args {
776 		char	*target;
777 		char	*linkname;
778 	} *uap;
779 	int *retval;
780 {
781 	register struct nameidata *ndp = &u.u_nd;
782 	struct vattr vattr;
783 	char *target;
784 	int error;
785 
786 	ndp->ni_segflg = UIO_USERSPACE;
787 	ndp->ni_dirp = uap->linkname;
788 	MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
789 	if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
790 		goto out;
791 	ndp->ni_nameiop = CREATE | LOCKPARENT;
792 	if (error = namei(ndp))
793 		goto out;
794 	if (ndp->ni_vp) {
795 		VOP_ABORTOP(ndp);
796 		if (ndp->ni_dvp == ndp->ni_vp)
797 			vrele(ndp->ni_dvp);
798 		else
799 			vput(ndp->ni_dvp);
800 		vrele(ndp->ni_vp);
801 		error = EEXIST;
802 		goto out;
803 	}
804 	VATTR_NULL(&vattr);
805 	vattr.va_mode = 0777 &~ u.u_cmask;
806 	error = VOP_SYMLINK(ndp, &vattr, target);
807 out:
808 	FREE(target, M_NAMEI);
809 	RETURN (error);
810 }
811 
812 /*
813  * Unlink system call.
814  * Hard to avoid races here, especially
815  * in unlinking directories.
816  */
817 /* ARGSUSED */
818 unlink(p, uap, retval)
819 	register struct proc *p;
820 	struct args {
821 		char	*fname;
822 	} *uap;
823 	int *retval;
824 {
825 	register struct nameidata *ndp = &u.u_nd;
826 	register struct vnode *vp;
827 	int error;
828 
829 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
830 	ndp->ni_segflg = UIO_USERSPACE;
831 	ndp->ni_dirp = uap->fname;
832 	if (error = namei(ndp))
833 		RETURN (error);
834 	vp = ndp->ni_vp;
835 	if (vp->v_type == VDIR &&
836 	    (error = suser(ndp->ni_cred, &u.u_acflag)))
837 		goto out;
838 	/*
839 	 * Don't unlink a mounted file.
840 	 */
841 	if (vp->v_flag & VROOT) {
842 		error = EBUSY;
843 		goto out;
844 	}
845 	if (vp->v_flag & VTEXT)
846 		xrele(vp);	/* try once to free text */
847 out:
848 	if (!error) {
849 		error = VOP_REMOVE(ndp);
850 	} else {
851 		VOP_ABORTOP(ndp);
852 		if (ndp->ni_dvp == vp)
853 			vrele(ndp->ni_dvp);
854 		else
855 			vput(ndp->ni_dvp);
856 		vput(vp);
857 	}
858 	RETURN (error);
859 }
860 
861 /*
862  * Seek system call
863  */
864 lseek(p, uap, retval)
865 	register struct proc *p;
866 	register struct args {
867 		int	fdes;
868 		off_t	off;
869 		int	sbase;
870 	} *uap;
871 	off_t *retval;
872 {
873 	struct ucred *cred = u.u_nd.ni_cred;
874 	register struct file *fp;
875 	struct vattr vattr;
876 	int error;
877 
878 	if ((unsigned)uap->fdes >= NOFILE ||
879 	    (fp = u.u_ofile[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 	register 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 	register 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 	register 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 	register 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 	register 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 	VATTR_NULL(&vattr);
1078 	vattr.va_flags = uap->flags;
1079 	if (error = namei(ndp))
1080 		RETURN (error);
1081 	vp = ndp->ni_vp;
1082 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1083 		error = EROFS;
1084 		goto out;
1085 	}
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 	register 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(u.u_ofile, uap->fd, &fp))
1110 		RETURN (error);
1111 	VATTR_NULL(&vattr);
1112 	vattr.va_flags = uap->flags;
1113 	vp = (struct vnode *)fp->f_data;
1114 	VOP_LOCK(vp);
1115 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1116 		error = EROFS;
1117 		goto out;
1118 	}
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 	register 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 	VATTR_NULL(&vattr);
1146 	vattr.va_mode = uap->fmode & 07777;
1147 	if (error = namei(ndp))
1148 		RETURN (error);
1149 	vp = ndp->ni_vp;
1150 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1151 		error = EROFS;
1152 		goto out;
1153 	}
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 	register 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(u.u_ofile, uap->fd, &fp))
1178 		RETURN (error);
1179 	VATTR_NULL(&vattr);
1180 	vattr.va_mode = uap->fmode & 07777;
1181 	vp = (struct vnode *)fp->f_data;
1182 	VOP_LOCK(vp);
1183 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1184 		error = EROFS;
1185 		goto out;
1186 	}
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 	register 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 	VATTR_NULL(&vattr);
1215 	vattr.va_uid = uap->uid;
1216 	vattr.va_gid = uap->gid;
1217 	if (error = namei(ndp))
1218 		RETURN (error);
1219 	vp = ndp->ni_vp;
1220 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1221 		error = EROFS;
1222 		goto out;
1223 	}
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 	register 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(u.u_ofile, uap->fd, &fp))
1249 		RETURN (error);
1250 	VATTR_NULL(&vattr);
1251 	vattr.va_uid = uap->uid;
1252 	vattr.va_gid = uap->gid;
1253 	vp = (struct vnode *)fp->f_data;
1254 	VOP_LOCK(vp);
1255 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1256 		error = EROFS;
1257 		goto out;
1258 	}
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 	register 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 	VATTR_NULL(&vattr);
1289 	vattr.va_atime = tv[0];
1290 	vattr.va_mtime = tv[1];
1291 	if (error = namei(ndp))
1292 		RETURN (error);
1293 	vp = ndp->ni_vp;
1294 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1295 		error = EROFS;
1296 		goto out;
1297 	}
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 	register 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 	VATTR_NULL(&vattr);
1325 	vattr.va_size = uap->length;
1326 	if (error = namei(ndp))
1327 		RETURN (error);
1328 	vp = ndp->ni_vp;
1329 	if (vp->v_type == VDIR) {
1330 		error = EISDIR;
1331 		goto out;
1332 	}
1333 	if ((error = vn_writechk(vp)) ||
1334 	    (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
1335 		goto out;
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 	register 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(u.u_ofile, uap->fd, &fp))
1360 		RETURN (error);
1361 	if ((fp->f_flag & FWRITE) == 0)
1362 		RETURN (EINVAL);
1363 	VATTR_NULL(&vattr);
1364 	vattr.va_size = uap->length;
1365 	vp = (struct vnode *)fp->f_data;
1366 	VOP_LOCK(vp);
1367 	if (vp->v_type == VDIR) {
1368 		error = EISDIR;
1369 		goto out;
1370 	}
1371 	if (error = vn_writechk(vp))
1372 		goto out;
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 	register 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(u.u_ofile, 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 	register 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 	}
1450 	if (fvp->v_mount != tdvp->v_mount) {
1451 		error = EXDEV;
1452 		goto out;
1453 	}
1454 	if (fvp == tdvp)
1455 		error = EINVAL;
1456 	/*
1457 	 * If source is the same as the destination,
1458 	 * then there is nothing to do.
1459 	 */
1460 	if (fvp == tvp)
1461 		error = -1;
1462 out:
1463 	if (!error) {
1464 		error = VOP_RENAME(ndp, &tond);
1465 	} else {
1466 		VOP_ABORTOP(&tond);
1467 		if (tdvp == tvp)
1468 			vrele(tdvp);
1469 		else
1470 			vput(tdvp);
1471 		if (tvp)
1472 			vput(tvp);
1473 		VOP_ABORTOP(ndp);
1474 		vrele(ndp->ni_dvp);
1475 		vrele(fvp);
1476 	}
1477 out1:
1478 	ndrele(&tond);
1479 	if (error == -1)
1480 		RETURN (0);
1481 	RETURN (error);
1482 }
1483 
1484 /*
1485  * Mkdir system call
1486  */
1487 /* ARGSUSED */
1488 mkdir(p, uap, retval)
1489 	register struct proc *p;
1490 	register struct args {
1491 		char	*name;
1492 		int	dmode;
1493 	} *uap;
1494 	int *retval;
1495 {
1496 	register struct nameidata *ndp = &u.u_nd;
1497 	register struct vnode *vp;
1498 	struct vattr vattr;
1499 	int error;
1500 
1501 	ndp->ni_nameiop = CREATE | LOCKPARENT;
1502 	ndp->ni_segflg = UIO_USERSPACE;
1503 	ndp->ni_dirp = uap->name;
1504 	if (error = namei(ndp))
1505 		RETURN (error);
1506 	vp = ndp->ni_vp;
1507 	if (vp != NULL) {
1508 		VOP_ABORTOP(ndp);
1509 		if (ndp->ni_dvp == vp)
1510 			vrele(ndp->ni_dvp);
1511 		else
1512 			vput(ndp->ni_dvp);
1513 		vrele(vp);
1514 		RETURN (EEXIST);
1515 	}
1516 	VATTR_NULL(&vattr);
1517 	vattr.va_type = VDIR;
1518 	vattr.va_mode = (uap->dmode & 0777) &~ u.u_cmask;
1519 	error = VOP_MKDIR(ndp, &vattr);
1520 	if (!error)
1521 		vput(ndp->ni_vp);
1522 	RETURN (error);
1523 }
1524 
1525 /*
1526  * Rmdir system call.
1527  */
1528 /* ARGSUSED */
1529 rmdir(p, uap, retval)
1530 	register struct proc *p;
1531 	struct args {
1532 		char	*name;
1533 	} *uap;
1534 	int *retval;
1535 {
1536 	register struct nameidata *ndp = &u.u_nd;
1537 	register struct vnode *vp;
1538 	int error;
1539 
1540 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
1541 	ndp->ni_segflg = UIO_USERSPACE;
1542 	ndp->ni_dirp = uap->name;
1543 	if (error = namei(ndp))
1544 		RETURN (error);
1545 	vp = ndp->ni_vp;
1546 	if (vp->v_type != VDIR) {
1547 		error = ENOTDIR;
1548 		goto out;
1549 	}
1550 	/*
1551 	 * No rmdir "." please.
1552 	 */
1553 	if (ndp->ni_dvp == vp) {
1554 		error = EINVAL;
1555 		goto out;
1556 	}
1557 	/*
1558 	 * Don't unlink a mounted file.
1559 	 */
1560 	if (vp->v_flag & VROOT)
1561 		error = EBUSY;
1562 out:
1563 	if (!error) {
1564 		error = VOP_RMDIR(ndp);
1565 	} else {
1566 		VOP_ABORTOP(ndp);
1567 		if (ndp->ni_dvp == vp)
1568 			vrele(ndp->ni_dvp);
1569 		else
1570 			vput(ndp->ni_dvp);
1571 		vput(vp);
1572 	}
1573 	RETURN (error);
1574 }
1575 
1576 /*
1577  * Read a block of directory entries in a file system independent format
1578  */
1579 getdirentries(p, uap, retval)
1580 	register struct proc *p;
1581 	register struct args {
1582 		int	fd;
1583 		char	*buf;
1584 		unsigned count;
1585 		long	*basep;
1586 	} *uap;
1587 	int *retval;
1588 {
1589 	register struct vnode *vp;
1590 	struct file *fp;
1591 	struct uio auio;
1592 	struct iovec aiov;
1593 	off_t off;
1594 	int error, eofflag;
1595 
1596 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1597 		RETURN (error);
1598 	if ((fp->f_flag & FREAD) == 0)
1599 		RETURN (EBADF);
1600 	vp = (struct vnode *)fp->f_data;
1601 	if (vp->v_type != VDIR)
1602 		RETURN (EINVAL);
1603 	aiov.iov_base = uap->buf;
1604 	aiov.iov_len = uap->count;
1605 	auio.uio_iov = &aiov;
1606 	auio.uio_iovcnt = 1;
1607 	auio.uio_rw = UIO_READ;
1608 	auio.uio_segflg = UIO_USERSPACE;
1609 	auio.uio_resid = uap->count;
1610 	VOP_LOCK(vp);
1611 	auio.uio_offset = off = fp->f_offset;
1612 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag);
1613 	fp->f_offset = auio.uio_offset;
1614 	VOP_UNLOCK(vp);
1615 	if (error)
1616 		RETURN (error);
1617 	error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
1618 	*retval = uap->count - auio.uio_resid;
1619 	RETURN (error);
1620 }
1621 
1622 /*
1623  * mode mask for creation of files
1624  */
1625 mode_t
1626 umask(p, uap, retval)
1627 	register struct proc *p;
1628 	struct args {
1629 		int	mask;
1630 	} *uap;
1631 	int *retval;
1632 {
1633 
1634 	*retval = u.u_cmask;
1635 	u.u_cmask = uap->mask & 07777;
1636 	RETURN (0);
1637 }
1638 
1639 /*
1640  * Void all references to file by ripping underlying filesystem
1641  * away from vnode.
1642  */
1643 /* ARGSUSED */
1644 revoke(p, uap, retval)
1645 	register struct proc *p;
1646 	register struct args {
1647 		char	*fname;
1648 	} *uap;
1649 	int *retval;
1650 {
1651 	register struct nameidata *ndp = &u.u_nd;
1652 	register struct vnode *vp;
1653 	struct vattr vattr;
1654 	int error;
1655 
1656 	ndp->ni_nameiop = LOOKUP | FOLLOW;
1657 	ndp->ni_segflg = UIO_USERSPACE;
1658 	ndp->ni_dirp = uap->fname;
1659 	if (error = namei(ndp))
1660 		RETURN (error);
1661 	vp = ndp->ni_vp;
1662 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
1663 		error = EINVAL;
1664 		goto out;
1665 	}
1666 	if (error = VOP_GETATTR(vp, &vattr, ndp->ni_cred))
1667 		goto out;
1668 	if (ndp->ni_cred->cr_uid != vattr.va_uid &&
1669 	    (error = suser(ndp->ni_cred, &u.u_acflag)))
1670 		goto out;
1671 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
1672 		vgoneall(vp);
1673 out:
1674 	vrele(vp);
1675 	RETURN (error);
1676 }
1677 
1678 getvnode(ofile, fdes, fpp)
1679 	struct file *ofile[];
1680 	struct file **fpp;
1681 	int fdes;
1682 {
1683 	struct file *fp;
1684 
1685 	if ((unsigned)fdes >= NOFILE || (fp = ofile[fdes]) == NULL)
1686 		return (EBADF);
1687 	if (fp->f_type != DTYPE_VNODE)
1688 		return (EINVAL);
1689 	*fpp = fp;
1690 	return (0);
1691 }
1692