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