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