xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 42955)
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.50 (Berkeley) 06/06/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 #ifdef COMPAT_43
583 /*
584  * Creat system call.
585  */
586 ocreat(p, uap, retval)
587 	struct proc *p;
588 	register struct args {
589 		char	*fname;
590 		int	fmode;
591 	} *uap;
592 	int *retval;
593 {
594 	struct args {
595 		char	*fname;
596 		int	mode;
597 		int	crtmode;
598 	} openuap;
599 
600 	openuap.fname = uap->fname;
601 	openuap.crtmode = uap->fmode;
602 	openuap.mode = O_WRONLY | O_CREAT | O_TRUNC;
603 	RETURN (open(p, &openuap, retval));
604 }
605 #endif /* COMPAT_43 */
606 
607 /*
608  * Mknod system call
609  */
610 /* ARGSUSED */
611 mknod(p, uap, retval)
612 	register struct proc *p;
613 	register struct args {
614 		char	*fname;
615 		int	fmode;
616 		int	dev;
617 	} *uap;
618 	int *retval;
619 {
620 	register struct nameidata *ndp = &u.u_nd;
621 	register struct vnode *vp;
622 	struct vattr vattr;
623 	int error;
624 
625 	if (error = suser(ndp->ni_cred, &u.u_acflag))
626 		RETURN (error);
627 	ndp->ni_nameiop = CREATE | LOCKPARENT;
628 	ndp->ni_segflg = UIO_USERSPACE;
629 	ndp->ni_dirp = uap->fname;
630 	if (error = namei(ndp))
631 		RETURN (error);
632 	vp = ndp->ni_vp;
633 	if (vp != NULL) {
634 		error = EEXIST;
635 		goto out;
636 	}
637 	VATTR_NULL(&vattr);
638 	switch (uap->fmode & S_IFMT) {
639 
640 	case S_IFMT:	/* used by badsect to flag bad sectors */
641 		vattr.va_type = VBAD;
642 		break;
643 	case S_IFCHR:
644 		vattr.va_type = VCHR;
645 		break;
646 	case S_IFBLK:
647 		vattr.va_type = VBLK;
648 		break;
649 	default:
650 		error = EINVAL;
651 		goto out;
652 	}
653 	vattr.va_mode = (uap->fmode & 07777) &~ u.u_cmask;
654 	vattr.va_rdev = uap->dev;
655 out:
656 	if (!error) {
657 		error = VOP_MKNOD(ndp, &vattr, ndp->ni_cred);
658 	} else {
659 		VOP_ABORTOP(ndp);
660 		vput(ndp->ni_dvp);
661 		if (vp)
662 			vrele(vp);
663 	}
664 	RETURN (error);
665 }
666 
667 /*
668  * Mkfifo system call
669  */
670 /* ARGSUSED */
671 mkfifo(p, uap, retval)
672 	register struct proc *p;
673 	register struct args {
674 		char	*fname;
675 		int	fmode;
676 	} *uap;
677 	int *retval;
678 {
679 	register struct nameidata *ndp = &u.u_nd;
680 	struct vattr vattr;
681 	int error;
682 
683 #ifndef FIFO
684 	RETURN (EOPNOTSUPP);
685 #else
686 	ndp->ni_nameiop = CREATE | LOCKPARENT;
687 	ndp->ni_segflg = UIO_USERSPACE;
688 	ndp->ni_dirp = uap->fname;
689 	if (error = namei(ndp))
690 		RETURN (error);
691 	if (ndp->ni_vp != NULL) {
692 		VOP_ABORTOP(ndp);
693 		vput(ndp->ni_dvp);
694 		vrele(ndp->ni_vp);
695 		RETURN (EEXIST);
696 	} else {
697 		VATTR_NULL(&vattr);
698 		vattr.va_type = VFIFO;
699 		vattr.va_mode = (uap->fmode & 07777) &~ u.u_cmask;
700 	}
701 	RETURN (VOP_MKNOD(ndp, &vattr, ndp->ni_cred));
702 #endif /* FIFO */
703 }
704 
705 /*
706  * link system call
707  */
708 /* ARGSUSED */
709 link(p, uap, retval)
710 	register struct proc *p;
711 	register struct args {
712 		char	*target;
713 		char	*linkname;
714 	} *uap;
715 	int *retval;
716 {
717 	register struct nameidata *ndp = &u.u_nd;
718 	register struct vnode *vp, *xp;
719 	int error;
720 
721 	ndp->ni_nameiop = LOOKUP | FOLLOW;
722 	ndp->ni_segflg = UIO_USERSPACE;
723 	ndp->ni_dirp = uap->target;
724 	if (error = namei(ndp))
725 		RETURN (error);
726 	vp = ndp->ni_vp;
727 	if (vp->v_type == VDIR &&
728 	    (error = suser(ndp->ni_cred, &u.u_acflag)))
729 		goto out1;
730 	ndp->ni_nameiop = CREATE | LOCKPARENT;
731 	ndp->ni_dirp = (caddr_t)uap->linkname;
732 	if (error = namei(ndp))
733 		goto out1;
734 	xp = ndp->ni_vp;
735 	if (xp != NULL) {
736 		error = EEXIST;
737 		goto out;
738 	}
739 	xp = ndp->ni_dvp;
740 	if (vp->v_mount != xp->v_mount)
741 		error = EXDEV;
742 out:
743 	if (!error) {
744 		error = VOP_LINK(vp, ndp);
745 	} else {
746 		VOP_ABORTOP(ndp);
747 		vput(ndp->ni_dvp);
748 		if (ndp->ni_vp)
749 			vrele(ndp->ni_vp);
750 	}
751 out1:
752 	vrele(vp);
753 	RETURN (error);
754 }
755 
756 /*
757  * symlink -- make a symbolic link
758  */
759 /* ARGSUSED */
760 symlink(p, uap, retval)
761 	register struct proc *p;
762 	register struct args {
763 		char	*target;
764 		char	*linkname;
765 	} *uap;
766 	int *retval;
767 {
768 	register struct nameidata *ndp = &u.u_nd;
769 	struct vattr vattr;
770 	char *target;
771 	int error;
772 
773 	ndp->ni_segflg = UIO_USERSPACE;
774 	ndp->ni_dirp = uap->linkname;
775 	MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
776 	if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
777 		goto out;
778 	ndp->ni_nameiop = CREATE | LOCKPARENT;
779 	if (error = namei(ndp))
780 		goto out;
781 	if (ndp->ni_vp) {
782 		VOP_ABORTOP(ndp);
783 		vput(ndp->ni_dvp);
784 		vrele(ndp->ni_vp);
785 		error = EEXIST;
786 		goto out;
787 	}
788 	VATTR_NULL(&vattr);
789 	vattr.va_mode = 0777 &~ u.u_cmask;
790 	error = VOP_SYMLINK(ndp, &vattr, target);
791 out:
792 	FREE(target, M_NAMEI);
793 	RETURN (error);
794 }
795 
796 /*
797  * Unlink system call.
798  * Hard to avoid races here, especially
799  * in unlinking directories.
800  */
801 /* ARGSUSED */
802 unlink(p, uap, retval)
803 	register struct proc *p;
804 	struct args {
805 		char	*fname;
806 	} *uap;
807 	int *retval;
808 {
809 	register struct nameidata *ndp = &u.u_nd;
810 	register struct vnode *vp;
811 	int error;
812 
813 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
814 	ndp->ni_segflg = UIO_USERSPACE;
815 	ndp->ni_dirp = uap->fname;
816 	if (error = namei(ndp))
817 		RETURN (error);
818 	vp = ndp->ni_vp;
819 	if (vp->v_type == VDIR &&
820 	    (error = suser(ndp->ni_cred, &u.u_acflag)))
821 		goto out;
822 	/*
823 	 * Don't unlink a mounted file.
824 	 */
825 	if (vp->v_flag & VROOT) {
826 		error = EBUSY;
827 		goto out;
828 	}
829 	if (vp->v_flag & VTEXT)
830 		xrele(vp);	/* try once to free text */
831 out:
832 	if (!error) {
833 		error = VOP_REMOVE(ndp);
834 	} else {
835 		VOP_ABORTOP(ndp);
836 		vput(ndp->ni_dvp);
837 		vput(vp);
838 	}
839 	RETURN (error);
840 }
841 
842 /*
843  * Seek system call
844  */
845 lseek(p, uap, retval)
846 	register struct proc *p;
847 	register struct args {
848 		int	fdes;
849 		off_t	off;
850 		int	sbase;
851 	} *uap;
852 	off_t *retval;
853 {
854 	struct ucred *cred = u.u_nd.ni_cred;
855 	register struct file *fp;
856 	struct vattr vattr;
857 	int error;
858 
859 	if ((unsigned)uap->fdes >= NOFILE ||
860 	    (fp = u.u_ofile[uap->fdes]) == NULL)
861 		RETURN (EBADF);
862 	if (fp->f_type != DTYPE_VNODE)
863 		RETURN (ESPIPE);
864 	switch (uap->sbase) {
865 
866 	case L_INCR:
867 		fp->f_offset += uap->off;
868 		break;
869 
870 	case L_XTND:
871 		if (error = VOP_GETATTR((struct vnode *)fp->f_data,
872 		    &vattr, cred))
873 			RETURN (error);
874 		fp->f_offset = uap->off + vattr.va_size;
875 		break;
876 
877 	case L_SET:
878 		fp->f_offset = uap->off;
879 		break;
880 
881 	default:
882 		RETURN (EINVAL);
883 	}
884 	*retval = fp->f_offset;
885 	RETURN (0);
886 }
887 
888 /*
889  * Access system call
890  */
891 /* ARGSUSED */
892 saccess(p, uap, retval)
893 	register struct proc *p;
894 	register struct args {
895 		char	*fname;
896 		int	fmode;
897 	} *uap;
898 	int *retval;
899 {
900 	register struct nameidata *ndp = &u.u_nd;
901 	register struct ucred *cred = ndp->ni_cred;
902 	register struct vnode *vp;
903 	int error, mode, svuid, svgid;
904 
905 	svuid = cred->cr_uid;
906 	svgid = cred->cr_groups[0];
907 	cred->cr_uid = p->p_ruid;
908 	cred->cr_groups[0] = p->p_rgid;
909 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
910 	ndp->ni_segflg = UIO_USERSPACE;
911 	ndp->ni_dirp = uap->fname;
912 	if (error = namei(ndp))
913 		goto out1;
914 	vp = ndp->ni_vp;
915 	/*
916 	 * fmode == 0 means only check for exist
917 	 */
918 	if (uap->fmode) {
919 		mode = 0;
920 		if (uap->fmode & R_OK)
921 			mode |= VREAD;
922 		if (uap->fmode & W_OK)
923 			mode |= VWRITE;
924 		if (uap->fmode & X_OK)
925 			mode |= VEXEC;
926 		if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
927 			error = VOP_ACCESS(vp, mode, ndp->ni_cred);
928 	}
929 	vput(vp);
930 out1:
931 	cred->cr_uid = svuid;
932 	cred->cr_groups[0] = svgid;
933 	RETURN (error);
934 }
935 
936 /*
937  * Stat system call.  This version follows links.
938  */
939 /* ARGSUSED */
940 stat(p, uap, retval)
941 	register struct proc *p;
942 	register struct args {
943 		char	*fname;
944 		struct stat *ub;
945 	} *uap;
946 	int *retval;
947 {
948 	register struct nameidata *ndp = &u.u_nd;
949 	struct stat sb;
950 	int error;
951 
952 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
953 	ndp->ni_segflg = UIO_USERSPACE;
954 	ndp->ni_dirp = uap->fname;
955 	if (error = namei(ndp))
956 		RETURN (error);
957 	error = vn_stat(ndp->ni_vp, &sb);
958 	vput(ndp->ni_vp);
959 	if (error)
960 		RETURN (error);
961 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
962 	RETURN (error);
963 }
964 
965 /*
966  * Lstat system call.  This version does not follow links.
967  */
968 /* ARGSUSED */
969 lstat(p, uap, retval)
970 	register struct proc *p;
971 	register struct args {
972 		char	*fname;
973 		struct stat *ub;
974 	} *uap;
975 	int *retval;
976 {
977 	register struct nameidata *ndp = &u.u_nd;
978 	struct stat sb;
979 	int error;
980 
981 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | NOFOLLOW;
982 	ndp->ni_segflg = UIO_USERSPACE;
983 	ndp->ni_dirp = uap->fname;
984 	if (error = namei(ndp))
985 		RETURN (error);
986 	error = vn_stat(ndp->ni_vp, &sb);
987 	vput(ndp->ni_vp);
988 	if (error)
989 		RETURN (error);
990 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
991 	RETURN (error);
992 }
993 
994 /*
995  * Return target name of a symbolic link
996  */
997 /* ARGSUSED */
998 readlink(p, uap, retval)
999 	register struct proc *p;
1000 	register struct args {
1001 		char	*name;
1002 		char	*buf;
1003 		int	count;
1004 	} *uap;
1005 	int *retval;
1006 {
1007 	register struct nameidata *ndp = &u.u_nd;
1008 	register struct vnode *vp;
1009 	struct iovec aiov;
1010 	struct uio auio;
1011 	int error;
1012 
1013 	ndp->ni_nameiop = LOOKUP | LOCKLEAF;
1014 	ndp->ni_segflg = UIO_USERSPACE;
1015 	ndp->ni_dirp = uap->name;
1016 	if (error = namei(ndp))
1017 		RETURN (error);
1018 	vp = ndp->ni_vp;
1019 	if (vp->v_type != VLNK) {
1020 		error = EINVAL;
1021 		goto out;
1022 	}
1023 	aiov.iov_base = uap->buf;
1024 	aiov.iov_len = uap->count;
1025 	auio.uio_iov = &aiov;
1026 	auio.uio_iovcnt = 1;
1027 	auio.uio_offset = 0;
1028 	auio.uio_rw = UIO_READ;
1029 	auio.uio_segflg = UIO_USERSPACE;
1030 	auio.uio_resid = uap->count;
1031 	error = VOP_READLINK(vp, &auio, ndp->ni_cred);
1032 out:
1033 	vput(vp);
1034 	*retval = uap->count - auio.uio_resid;
1035 	RETURN (error);
1036 }
1037 
1038 /*
1039  * Change flags of a file given path name.
1040  */
1041 /* ARGSUSED */
1042 chflags(p, uap, retval)
1043 	register struct proc *p;
1044 	register struct args {
1045 		char	*fname;
1046 		int	flags;
1047 	} *uap;
1048 	int *retval;
1049 {
1050 	register struct nameidata *ndp = &u.u_nd;
1051 	register struct vnode *vp;
1052 	struct vattr vattr;
1053 	int error;
1054 
1055 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1056 	ndp->ni_segflg = UIO_USERSPACE;
1057 	ndp->ni_dirp = uap->fname;
1058 	VATTR_NULL(&vattr);
1059 	vattr.va_flags = uap->flags;
1060 	if (error = namei(ndp))
1061 		RETURN (error);
1062 	vp = ndp->ni_vp;
1063 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1064 		error = EROFS;
1065 		goto out;
1066 	}
1067 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1068 out:
1069 	vput(vp);
1070 	RETURN (error);
1071 }
1072 
1073 /*
1074  * Change flags of a file given a file descriptor.
1075  */
1076 /* ARGSUSED */
1077 fchflags(p, uap, retval)
1078 	register struct proc *p;
1079 	register struct args {
1080 		int	fd;
1081 		int	flags;
1082 	} *uap;
1083 	int *retval;
1084 {
1085 	struct vattr vattr;
1086 	struct vnode *vp;
1087 	struct file *fp;
1088 	int error;
1089 
1090 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1091 		RETURN (error);
1092 	VATTR_NULL(&vattr);
1093 	vattr.va_flags = uap->flags;
1094 	vp = (struct vnode *)fp->f_data;
1095 	VOP_LOCK(vp);
1096 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1097 		error = EROFS;
1098 		goto out;
1099 	}
1100 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1101 out:
1102 	VOP_UNLOCK(vp);
1103 	RETURN (error);
1104 }
1105 
1106 /*
1107  * Change mode of a file given path name.
1108  */
1109 /* ARGSUSED */
1110 chmod(p, uap, retval)
1111 	register struct proc *p;
1112 	register struct args {
1113 		char	*fname;
1114 		int	fmode;
1115 	} *uap;
1116 	int *retval;
1117 {
1118 	register struct nameidata *ndp = &u.u_nd;
1119 	register struct vnode *vp;
1120 	struct vattr vattr;
1121 	int error;
1122 
1123 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1124 	ndp->ni_segflg = UIO_USERSPACE;
1125 	ndp->ni_dirp = uap->fname;
1126 	VATTR_NULL(&vattr);
1127 	vattr.va_mode = uap->fmode & 07777;
1128 	if (error = namei(ndp))
1129 		RETURN (error);
1130 	vp = ndp->ni_vp;
1131 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1132 		error = EROFS;
1133 		goto out;
1134 	}
1135 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1136 out:
1137 	vput(vp);
1138 	RETURN (error);
1139 }
1140 
1141 /*
1142  * Change mode of a file given a file descriptor.
1143  */
1144 /* ARGSUSED */
1145 fchmod(p, uap, retval)
1146 	register struct proc *p;
1147 	register struct args {
1148 		int	fd;
1149 		int	fmode;
1150 	} *uap;
1151 	int *retval;
1152 {
1153 	struct vattr vattr;
1154 	struct vnode *vp;
1155 	struct file *fp;
1156 	int error;
1157 
1158 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1159 		RETURN (error);
1160 	VATTR_NULL(&vattr);
1161 	vattr.va_mode = uap->fmode & 07777;
1162 	vp = (struct vnode *)fp->f_data;
1163 	VOP_LOCK(vp);
1164 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1165 		error = EROFS;
1166 		goto out;
1167 	}
1168 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1169 out:
1170 	VOP_UNLOCK(vp);
1171 	RETURN (error);
1172 }
1173 
1174 /*
1175  * Set ownership given a path name.
1176  */
1177 /* ARGSUSED */
1178 chown(p, uap, retval)
1179 	register struct proc *p;
1180 	register struct args {
1181 		char	*fname;
1182 		int	uid;
1183 		int	gid;
1184 	} *uap;
1185 	int *retval;
1186 {
1187 	register struct nameidata *ndp = &u.u_nd;
1188 	register struct vnode *vp;
1189 	struct vattr vattr;
1190 	int error;
1191 
1192 	ndp->ni_nameiop = LOOKUP | NOFOLLOW | LOCKLEAF;
1193 	ndp->ni_segflg = UIO_USERSPACE;
1194 	ndp->ni_dirp = uap->fname;
1195 	VATTR_NULL(&vattr);
1196 	vattr.va_uid = uap->uid;
1197 	vattr.va_gid = uap->gid;
1198 	if (error = namei(ndp))
1199 		RETURN (error);
1200 	vp = ndp->ni_vp;
1201 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1202 		error = EROFS;
1203 		goto out;
1204 	}
1205 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1206 out:
1207 	vput(vp);
1208 	RETURN (error);
1209 }
1210 
1211 /*
1212  * Set ownership given a file descriptor.
1213  */
1214 /* ARGSUSED */
1215 fchown(p, uap, retval)
1216 	register struct proc *p;
1217 	register struct args {
1218 		int	fd;
1219 		int	uid;
1220 		int	gid;
1221 	} *uap;
1222 	int *retval;
1223 {
1224 	struct vattr vattr;
1225 	struct vnode *vp;
1226 	struct file *fp;
1227 	int error;
1228 
1229 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1230 		RETURN (error);
1231 	VATTR_NULL(&vattr);
1232 	vattr.va_uid = uap->uid;
1233 	vattr.va_gid = uap->gid;
1234 	vp = (struct vnode *)fp->f_data;
1235 	VOP_LOCK(vp);
1236 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1237 		error = EROFS;
1238 		goto out;
1239 	}
1240 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1241 out:
1242 	VOP_UNLOCK(vp);
1243 	RETURN (error);
1244 }
1245 
1246 /*
1247  * Set the access and modification times of a file.
1248  */
1249 /* ARGSUSED */
1250 utimes(p, uap, retval)
1251 	register struct proc *p;
1252 	register struct args {
1253 		char	*fname;
1254 		struct	timeval *tptr;
1255 	} *uap;
1256 	int *retval;
1257 {
1258 	register struct nameidata *ndp = &u.u_nd;
1259 	register struct vnode *vp;
1260 	struct timeval tv[2];
1261 	struct vattr vattr;
1262 	int error;
1263 
1264 	if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1265 		RETURN (error);
1266 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1267 	ndp->ni_segflg = UIO_USERSPACE;
1268 	ndp->ni_dirp = uap->fname;
1269 	VATTR_NULL(&vattr);
1270 	vattr.va_atime = tv[0];
1271 	vattr.va_mtime = tv[1];
1272 	if (error = namei(ndp))
1273 		RETURN (error);
1274 	vp = ndp->ni_vp;
1275 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1276 		error = EROFS;
1277 		goto out;
1278 	}
1279 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1280 out:
1281 	vput(vp);
1282 	RETURN (error);
1283 }
1284 
1285 /*
1286  * Truncate a file given its path name.
1287  */
1288 /* ARGSUSED */
1289 truncate(p, uap, retval)
1290 	register struct proc *p;
1291 	register struct args {
1292 		char	*fname;
1293 		off_t	length;
1294 	} *uap;
1295 	int *retval;
1296 {
1297 	register struct nameidata *ndp = &u.u_nd;
1298 	register struct vnode *vp;
1299 	struct vattr vattr;
1300 	int error;
1301 
1302 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
1303 	ndp->ni_segflg = UIO_USERSPACE;
1304 	ndp->ni_dirp = uap->fname;
1305 	VATTR_NULL(&vattr);
1306 	vattr.va_size = uap->length;
1307 	if (error = namei(ndp))
1308 		RETURN (error);
1309 	vp = ndp->ni_vp;
1310 	if (vp->v_type == VDIR) {
1311 		error = EISDIR;
1312 		goto out;
1313 	}
1314 	if ((error = vn_writechk(vp)) ||
1315 	    (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
1316 		goto out;
1317 	error = VOP_SETATTR(vp, &vattr, ndp->ni_cred);
1318 out:
1319 	vput(vp);
1320 	RETURN (error);
1321 }
1322 
1323 /*
1324  * Truncate a file given a file descriptor.
1325  */
1326 /* ARGSUSED */
1327 ftruncate(p, uap, retval)
1328 	register struct proc *p;
1329 	register struct args {
1330 		int	fd;
1331 		off_t	length;
1332 	} *uap;
1333 	int *retval;
1334 {
1335 	struct vattr vattr;
1336 	struct vnode *vp;
1337 	struct file *fp;
1338 	int error;
1339 
1340 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1341 		RETURN (error);
1342 	if ((fp->f_flag & FWRITE) == 0)
1343 		RETURN (EINVAL);
1344 	VATTR_NULL(&vattr);
1345 	vattr.va_size = uap->length;
1346 	vp = (struct vnode *)fp->f_data;
1347 	VOP_LOCK(vp);
1348 	if (vp->v_type == VDIR) {
1349 		error = EISDIR;
1350 		goto out;
1351 	}
1352 	if (error = vn_writechk(vp))
1353 		goto out;
1354 	error = VOP_SETATTR(vp, &vattr, fp->f_cred);
1355 out:
1356 	VOP_UNLOCK(vp);
1357 	RETURN (error);
1358 }
1359 
1360 /*
1361  * Synch an open file.
1362  */
1363 /* ARGSUSED */
1364 fsync(p, uap, retval)
1365 	register struct proc *p;
1366 	struct args {
1367 		int	fd;
1368 	} *uap;
1369 	int *retval;
1370 {
1371 	register struct vnode *vp;
1372 	struct file *fp;
1373 	int error;
1374 
1375 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1376 		RETURN (error);
1377 	vp = (struct vnode *)fp->f_data;
1378 	VOP_LOCK(vp);
1379 	error = VOP_FSYNC(vp, fp->f_flag, fp->f_cred, MNT_WAIT);
1380 	VOP_UNLOCK(vp);
1381 	RETURN (error);
1382 }
1383 
1384 /*
1385  * Rename system call.
1386  *
1387  * Source and destination must either both be directories, or both
1388  * not be directories.  If target is a directory, it must be empty.
1389  */
1390 /* ARGSUSED */
1391 rename(p, uap, retval)
1392 	register struct proc *p;
1393 	register struct args {
1394 		char	*from;
1395 		char	*to;
1396 	} *uap;
1397 	int *retval;
1398 {
1399 	register struct vnode *tvp, *fvp, *tdvp;
1400 	register struct nameidata *ndp = &u.u_nd;
1401 	struct nameidata tond;
1402 	int error;
1403 
1404 	ndp->ni_nameiop = DELETE | WANTPARENT;
1405 	ndp->ni_segflg = UIO_USERSPACE;
1406 	ndp->ni_dirp = uap->from;
1407 	if (error = namei(ndp))
1408 		RETURN (error);
1409 	fvp = ndp->ni_vp;
1410 	nddup(ndp, &tond);
1411 	tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
1412 	tond.ni_segflg = UIO_USERSPACE;
1413 	tond.ni_dirp = uap->to;
1414 	if (error = namei(&tond)) {
1415 		VOP_ABORTOP(ndp);
1416 		vrele(ndp->ni_dvp);
1417 		vrele(fvp);
1418 		goto out1;
1419 	}
1420 	tdvp = tond.ni_dvp;
1421 	tvp = tond.ni_vp;
1422 	if (tvp != NULL) {
1423 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1424 			error = ENOTDIR;
1425 			goto out;
1426 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1427 			error = EISDIR;
1428 			goto out;
1429 		}
1430 	}
1431 	if (fvp->v_mount != tdvp->v_mount) {
1432 		error = EXDEV;
1433 		goto out;
1434 	}
1435 	if (fvp == tdvp)
1436 		error = EINVAL;
1437 	/*
1438 	 * If source is the same as the destination,
1439 	 * then there is nothing to do.
1440 	 */
1441 	if (fvp == tvp)
1442 		error = -1;
1443 out:
1444 	if (!error) {
1445 		error = VOP_RENAME(ndp, &tond);
1446 	} else {
1447 		VOP_ABORTOP(&tond);
1448 		vput(tdvp);
1449 		if (tvp)
1450 			vput(tvp);
1451 		VOP_ABORTOP(ndp);
1452 		vrele(ndp->ni_dvp);
1453 		vrele(fvp);
1454 	}
1455 out1:
1456 	ndrele(&tond);
1457 	if (error == -1)
1458 		RETURN (0);
1459 	RETURN (error);
1460 }
1461 
1462 /*
1463  * Mkdir system call
1464  */
1465 /* ARGSUSED */
1466 mkdir(p, uap, retval)
1467 	register struct proc *p;
1468 	register struct args {
1469 		char	*name;
1470 		int	dmode;
1471 	} *uap;
1472 	int *retval;
1473 {
1474 	register struct nameidata *ndp = &u.u_nd;
1475 	register struct vnode *vp;
1476 	struct vattr vattr;
1477 	int error;
1478 
1479 	ndp->ni_nameiop = CREATE | LOCKPARENT;
1480 	ndp->ni_segflg = UIO_USERSPACE;
1481 	ndp->ni_dirp = uap->name;
1482 	if (error = namei(ndp))
1483 		RETURN (error);
1484 	vp = ndp->ni_vp;
1485 	if (vp != NULL) {
1486 		VOP_ABORTOP(ndp);
1487 		vput(ndp->ni_dvp);
1488 		vrele(vp);
1489 		RETURN (EEXIST);
1490 	}
1491 	VATTR_NULL(&vattr);
1492 	vattr.va_type = VDIR;
1493 	vattr.va_mode = (uap->dmode & 0777) &~ u.u_cmask;
1494 	error = VOP_MKDIR(ndp, &vattr);
1495 	if (!error)
1496 		vput(ndp->ni_vp);
1497 	RETURN (error);
1498 }
1499 
1500 /*
1501  * Rmdir system call.
1502  */
1503 /* ARGSUSED */
1504 rmdir(p, uap, retval)
1505 	register struct proc *p;
1506 	struct args {
1507 		char	*name;
1508 	} *uap;
1509 	int *retval;
1510 {
1511 	register struct nameidata *ndp = &u.u_nd;
1512 	register struct vnode *vp;
1513 	int error;
1514 
1515 	ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
1516 	ndp->ni_segflg = UIO_USERSPACE;
1517 	ndp->ni_dirp = uap->name;
1518 	if (error = namei(ndp))
1519 		RETURN (error);
1520 	vp = ndp->ni_vp;
1521 	if (vp->v_type != VDIR) {
1522 		error = ENOTDIR;
1523 		goto out;
1524 	}
1525 	/*
1526 	 * No rmdir "." please.
1527 	 */
1528 	if (ndp->ni_dvp == vp) {
1529 		error = EINVAL;
1530 		goto out;
1531 	}
1532 	/*
1533 	 * Don't unlink a mounted file.
1534 	 */
1535 	if (vp->v_flag & VROOT)
1536 		error = EBUSY;
1537 out:
1538 	if (!error) {
1539 		error = VOP_RMDIR(ndp);
1540 	} else {
1541 		VOP_ABORTOP(ndp);
1542 		vput(ndp->ni_dvp);
1543 		vput(vp);
1544 	}
1545 	RETURN (error);
1546 }
1547 
1548 /*
1549  * Read a block of directory entries in a file system independent format
1550  */
1551 getdirentries(p, uap, retval)
1552 	register struct proc *p;
1553 	register struct args {
1554 		int	fd;
1555 		char	*buf;
1556 		unsigned count;
1557 		long	*basep;
1558 	} *uap;
1559 	int *retval;
1560 {
1561 	register struct vnode *vp;
1562 	struct file *fp;
1563 	struct uio auio;
1564 	struct iovec aiov;
1565 	off_t off;
1566 	int error, eofflag;
1567 
1568 	if (error = getvnode(u.u_ofile, uap->fd, &fp))
1569 		RETURN (error);
1570 	if ((fp->f_flag & FREAD) == 0)
1571 		RETURN (EBADF);
1572 	vp = (struct vnode *)fp->f_data;
1573 	if (vp->v_type != VDIR)
1574 		RETURN (EINVAL);
1575 	aiov.iov_base = uap->buf;
1576 	aiov.iov_len = uap->count;
1577 	auio.uio_iov = &aiov;
1578 	auio.uio_iovcnt = 1;
1579 	auio.uio_rw = UIO_READ;
1580 	auio.uio_segflg = UIO_USERSPACE;
1581 	auio.uio_resid = uap->count;
1582 	VOP_LOCK(vp);
1583 	auio.uio_offset = off = fp->f_offset;
1584 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag);
1585 	fp->f_offset = auio.uio_offset;
1586 	VOP_UNLOCK(vp);
1587 	if (error)
1588 		RETURN (error);
1589 	error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long));
1590 	*retval = uap->count - auio.uio_resid;
1591 	RETURN (error);
1592 }
1593 
1594 /*
1595  * mode mask for creation of files
1596  */
1597 mode_t
1598 umask(p, uap, retval)
1599 	register struct proc *p;
1600 	struct args {
1601 		int	mask;
1602 	} *uap;
1603 	int *retval;
1604 {
1605 
1606 	*retval = u.u_cmask;
1607 	u.u_cmask = uap->mask & 07777;
1608 	RETURN (0);
1609 }
1610 
1611 /*
1612  * Void all references to file by ripping underlying filesystem
1613  * away from vnode.
1614  */
1615 /* ARGSUSED */
1616 revoke(p, uap, retval)
1617 	register struct proc *p;
1618 	register struct args {
1619 		char	*fname;
1620 		int	flags;
1621 	} *uap;
1622 	int *retval;
1623 {
1624 	register struct nameidata *ndp = &u.u_nd;
1625 	register struct vnode *vp;
1626 	struct vattr vattr;
1627 	int error;
1628 
1629 	ndp->ni_nameiop = LOOKUP | FOLLOW;
1630 	ndp->ni_segflg = UIO_USERSPACE;
1631 	ndp->ni_dirp = uap->fname;
1632 	if (error = namei(ndp))
1633 		RETURN (error);
1634 	vp = ndp->ni_vp;
1635 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
1636 		error = EINVAL;
1637 		goto out;
1638 	}
1639 	if (error = VOP_GETATTR(vp, &vattr, ndp->ni_cred))
1640 		goto out;
1641 	if (ndp->ni_cred->cr_uid != vattr.va_uid &&
1642 	    (error = suser(ndp->ni_cred, &u.u_acflag)))
1643 		goto out;
1644 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
1645 		vgoneall(vp);
1646 out:
1647 	vrele(vp);
1648 	RETURN (error);
1649 }
1650 
1651 getvnode(ofile, fdes, fpp)
1652 	struct file *ofile[];
1653 	struct file **fpp;
1654 	int fdes;
1655 {
1656 	struct file *fp;
1657 
1658 	if ((unsigned)fdes >= NOFILE || (fp = ofile[fdes]) == NULL)
1659 		return (EBADF);
1660 	if (fp->f_type != DTYPE_VNODE)
1661 		return (EINVAL);
1662 	*fpp = fp;
1663 	return (0);
1664 }
1665