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