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