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