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