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