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