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