xref: /original-bsd/sys/kern/vfs_syscalls.c (revision c8c7253d)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)vfs_syscalls.c	7.108 (Berkeley) 05/10/93
8  */
9 
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/namei.h>
13 #include <sys/filedesc.h>
14 #include <sys/kernel.h>
15 #include <sys/file.h>
16 #include <sys/stat.h>
17 #include <sys/vnode.h>
18 #include <sys/mount.h>
19 #include <sys/proc.h>
20 #include <sys/uio.h>
21 #include <sys/malloc.h>
22 #include <sys/dirent.h>
23 
24 #include <vm/vm.h>
25 #include <sys/sysctl.h>
26 
27 /*
28  * Virtual File System System Calls
29  */
30 
31 /*
32  * Mount system call.
33  */
34 struct mount_args {
35 	int	type;
36 	char	*dir;
37 	int	flags;
38 	caddr_t	data;
39 };
40 /* ARGSUSED */
41 mount(p, uap, retval)
42 	struct proc *p;
43 	register struct mount_args *uap;
44 	int *retval;
45 {
46 	register struct vnode *vp;
47 	register struct mount *mp;
48 	int error, flag;
49 	struct nameidata nd;
50 
51 	/*
52 	 * Must be super user
53 	 */
54 	if (error = suser(p->p_ucred, &p->p_acflag))
55 		return (error);
56 	/*
57 	 * Get vnode to be covered
58 	 */
59 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->dir, p);
60 	if (error = namei(&nd))
61 		return (error);
62 	vp = nd.ni_vp;
63 	if (uap->flags & MNT_UPDATE) {
64 		if ((vp->v_flag & VROOT) == 0) {
65 			vput(vp);
66 			return (EINVAL);
67 		}
68 		mp = vp->v_mount;
69 		flag = mp->mnt_flag;
70 		/*
71 		 * We only allow the filesystem to be reloaded if it
72 		 * is currently mounted read-only.
73 		 */
74 		if ((uap->flags & MNT_RELOAD) &&
75 		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
76 			vput(vp);
77 			return (EOPNOTSUPP);	/* Needs translation */
78 		}
79 		mp->mnt_flag |=
80 		    uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
81 		VOP_UNLOCK(vp);
82 		goto update;
83 	}
84 	if (vp->v_usecount != 1 && (uap->flags & MNT_UNION) == 0) {
85 		vput(vp);
86 		return (EBUSY);
87 	}
88 	if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
89 		return (error);
90 	if (vp->v_type != VDIR) {
91 		vput(vp);
92 		return (ENOTDIR);
93 	}
94 	if ((unsigned long)uap->type > MOUNT_MAXTYPE ||
95 	    vfssw[uap->type] == (struct vfsops *)0) {
96 		vput(vp);
97 		return (ENODEV);
98 	}
99 
100 	/*
101 	 * Allocate and initialize the file system.
102 	 */
103 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
104 		M_MOUNT, M_WAITOK);
105 	bzero((char *)mp, (u_long)sizeof(struct mount));
106 	mp->mnt_op = vfssw[uap->type];
107 	if (error = vfs_lock(mp)) {
108 		free((caddr_t)mp, M_MOUNT);
109 		vput(vp);
110 		return (error);
111 	}
112 	if (vp->v_mountedhere != (struct mount *)0) {
113 		vfs_unlock(mp);
114 		free((caddr_t)mp, M_MOUNT);
115 		vput(vp);
116 		return (EBUSY);
117 	}
118 	vp->v_mountedhere = mp;
119 	mp->mnt_vnodecovered = vp;
120 update:
121 	/*
122 	 * Set the mount level flags.
123 	 */
124 	if (uap->flags & MNT_RDONLY)
125 		mp->mnt_flag |= MNT_RDONLY;
126 	else if (mp->mnt_flag & MNT_RDONLY)
127 		mp->mnt_flag |= MNT_WANTRDWR;
128 	mp->mnt_flag &=~
129 	    (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION);
130 	mp->mnt_flag |= uap->flags &
131 	    (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION);
132 	/*
133 	 * Mount the filesystem.
134 	 */
135 	error = VFS_MOUNT(mp, uap->dir, uap->data, &nd, p);
136 	if (mp->mnt_flag & MNT_UPDATE) {
137 		vrele(vp);
138 		if (mp->mnt_flag & MNT_WANTRDWR)
139 			mp->mnt_flag &= ~MNT_RDONLY;
140 		mp->mnt_flag &=~
141 		    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
142 		if (error)
143 			mp->mnt_flag = flag;
144 		return (error);
145 	}
146 	/*
147 	 * Put the new filesystem on the mount list after root.
148 	 */
149 	mp->mnt_next = rootfs->mnt_next;
150 	mp->mnt_prev = rootfs;
151 	rootfs->mnt_next = mp;
152 	mp->mnt_next->mnt_prev = mp;
153 	cache_purge(vp);
154 	if (!error) {
155 		VOP_UNLOCK(vp);
156 		vfs_unlock(mp);
157 		error = VFS_START(mp, 0, p);
158 	} else {
159 		vfs_remove(mp);
160 		free((caddr_t)mp, M_MOUNT);
161 		vput(vp);
162 	}
163 	return (error);
164 }
165 
166 /*
167  * Unmount system call.
168  *
169  * Note: unmount takes a path to the vnode mounted on as argument,
170  * not special file (as before).
171  */
172 struct unmount_args {
173 	char	*pathp;
174 	int	flags;
175 };
176 /* ARGSUSED */
177 unmount(p, uap, retval)
178 	struct proc *p;
179 	register struct unmount_args *uap;
180 	int *retval;
181 {
182 	register struct vnode *vp;
183 	struct mount *mp;
184 	int error;
185 	struct nameidata nd;
186 
187 	/*
188 	 * Must be super user
189 	 */
190 	if (error = suser(p->p_ucred, &p->p_acflag))
191 		return (error);
192 
193 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->pathp, p);
194 	if (error = namei(&nd))
195 		return (error);
196 	vp = nd.ni_vp;
197 	/*
198 	 * Must be the root of the filesystem
199 	 */
200 	if ((vp->v_flag & VROOT) == 0) {
201 		vput(vp);
202 		return (EINVAL);
203 	}
204 	mp = vp->v_mount;
205 	vput(vp);
206 	return (dounmount(mp, uap->flags, p));
207 }
208 
209 /*
210  * Do an unmount.
211  */
212 dounmount(mp, flags, p)
213 	register struct mount *mp;
214 	int flags;
215 	struct proc *p;
216 {
217 	struct vnode *coveredvp;
218 	int error;
219 
220 	coveredvp = mp->mnt_vnodecovered;
221 	if (vfs_busy(mp))
222 		return (EBUSY);
223 	mp->mnt_flag |= MNT_UNMOUNT;
224 	if (error = vfs_lock(mp))
225 		return (error);
226 
227 	vnode_pager_umount(mp);	/* release cached vnodes */
228 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
229 	if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
230 	    (flags & MNT_FORCE))
231 		error = VFS_UNMOUNT(mp, flags, p);
232 	mp->mnt_flag &= ~MNT_UNMOUNT;
233 	vfs_unbusy(mp);
234 	if (error) {
235 		vfs_unlock(mp);
236 	} else {
237 		vrele(coveredvp);
238 		vfs_remove(mp);
239 		if (mp->mnt_mounth != NULL)
240 			panic("unmount: dangling vnode");
241 		free((caddr_t)mp, M_MOUNT);
242 	}
243 	return (error);
244 }
245 
246 /*
247  * Sync system call.
248  * Sync each mounted filesystem.
249  */
250 #ifdef DIAGNOSTIC
251 int syncprt = 0;
252 struct ctldebug debug0 = { "syncprt", &syncprt };
253 #endif
254 
255 struct sync_args {
256 	int	dummy;
257 };
258 /* ARGSUSED */
259 sync(p, uap, retval)
260 	struct proc *p;
261 	struct sync_args *uap;
262 	int *retval;
263 {
264 	register struct mount *mp;
265 	struct mount *omp;
266 
267 	mp = rootfs;
268 	do {
269 		/*
270 		 * The lock check below is to avoid races with mount
271 		 * and unmount.
272 		 */
273 		if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
274 		    !vfs_busy(mp)) {
275 			VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
276 			omp = mp;
277 			mp = mp->mnt_next;
278 			vfs_unbusy(omp);
279 		} else
280 			mp = mp->mnt_next;
281 	} while (mp != rootfs);
282 #ifdef DIAGNOSTIC
283 	if (syncprt)
284 		vfs_bufstats();
285 #endif /* DIAGNOSTIC */
286 	return (0);
287 }
288 
289 /*
290  * Operate on filesystem quotas.
291  */
292 struct quotactl_args {
293 	char *path;
294 	int cmd;
295 	int uid;
296 	caddr_t arg;
297 };
298 /* ARGSUSED */
299 quotactl(p, uap, retval)
300 	struct proc *p;
301 	register struct quotactl_args *uap;
302 	int *retval;
303 {
304 	register struct mount *mp;
305 	int error;
306 	struct nameidata nd;
307 
308 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
309 	if (error = namei(&nd))
310 		return (error);
311 	mp = nd.ni_vp->v_mount;
312 	vrele(nd.ni_vp);
313 	return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
314 }
315 
316 /*
317  * Get filesystem statistics.
318  */
319 struct statfs_args {
320 	char *path;
321 	struct statfs *buf;
322 };
323 /* ARGSUSED */
324 statfs(p, uap, retval)
325 	struct proc *p;
326 	register struct statfs_args *uap;
327 	int *retval;
328 {
329 	register struct mount *mp;
330 	register struct statfs *sp;
331 	int error;
332 	struct nameidata nd;
333 
334 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
335 	if (error = namei(&nd))
336 		return (error);
337 	mp = nd.ni_vp->v_mount;
338 	sp = &mp->mnt_stat;
339 	vrele(nd.ni_vp);
340 	if (error = VFS_STATFS(mp, sp, p))
341 		return (error);
342 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
343 	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
344 }
345 
346 /*
347  * Get filesystem statistics.
348  */
349 struct fstatfs_args {
350 	int fd;
351 	struct statfs *buf;
352 };
353 /* ARGSUSED */
354 fstatfs(p, uap, retval)
355 	struct proc *p;
356 	register struct fstatfs_args *uap;
357 	int *retval;
358 {
359 	struct file *fp;
360 	struct mount *mp;
361 	register struct statfs *sp;
362 	int error;
363 
364 	if (error = getvnode(p->p_fd, uap->fd, &fp))
365 		return (error);
366 	mp = ((struct vnode *)fp->f_data)->v_mount;
367 	sp = &mp->mnt_stat;
368 	if (error = VFS_STATFS(mp, sp, p))
369 		return (error);
370 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
371 	return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
372 }
373 
374 /*
375  * Get statistics on all filesystems.
376  */
377 struct getfsstat_args {
378 	struct statfs *buf;
379 	long bufsize;
380 	int flags;
381 };
382 getfsstat(p, uap, retval)
383 	struct proc *p;
384 	register struct getfsstat_args *uap;
385 	int *retval;
386 {
387 	register struct mount *mp;
388 	register struct statfs *sp;
389 	caddr_t sfsp;
390 	long count, maxcount, error;
391 
392 	maxcount = uap->bufsize / sizeof(struct statfs);
393 	sfsp = (caddr_t)uap->buf;
394 	mp = rootfs;
395 	count = 0;
396 	do {
397 		if (sfsp && count < maxcount &&
398 		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
399 			sp = &mp->mnt_stat;
400 			/*
401 			 * If MNT_NOWAIT is specified, do not refresh the
402 			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
403 			 */
404 			if (((uap->flags & MNT_NOWAIT) == 0 ||
405 			    (uap->flags & MNT_WAIT)) &&
406 			    (error = VFS_STATFS(mp, sp, p))) {
407 				mp = mp->mnt_prev;
408 				continue;
409 			}
410 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
411 			if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
412 				return (error);
413 			sfsp += sizeof(*sp);
414 		}
415 		count++;
416 		mp = mp->mnt_prev;
417 	} while (mp != rootfs);
418 	if (sfsp && count > maxcount)
419 		*retval = maxcount;
420 	else
421 		*retval = count;
422 	return (0);
423 }
424 
425 /*
426  * Change current working directory to a given file descriptor.
427  */
428 struct fchdir_args {
429 	int	fd;
430 };
431 /* ARGSUSED */
432 fchdir(p, uap, retval)
433 	struct proc *p;
434 	struct fchdir_args *uap;
435 	int *retval;
436 {
437 	register struct filedesc *fdp = p->p_fd;
438 	register struct vnode *vp;
439 	struct file *fp;
440 	int error;
441 
442 	if (error = getvnode(fdp, uap->fd, &fp))
443 		return (error);
444 	vp = (struct vnode *)fp->f_data;
445 	VOP_LOCK(vp);
446 	if (vp->v_type != VDIR)
447 		error = ENOTDIR;
448 	else
449 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
450 	VOP_UNLOCK(vp);
451 	if (error)
452 		return (error);
453 	VREF(vp);
454 	vrele(fdp->fd_cdir);
455 	fdp->fd_cdir = vp;
456 	return (0);
457 }
458 
459 /*
460  * Change current working directory (``.'').
461  */
462 struct chdir_args {
463 	char	*fname;
464 };
465 /* ARGSUSED */
466 chdir(p, uap, retval)
467 	struct proc *p;
468 	struct chdir_args *uap;
469 	int *retval;
470 {
471 	register struct filedesc *fdp = p->p_fd;
472 	int error;
473 	struct nameidata nd;
474 
475 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
476 	if (error = chdirec(&nd, p))
477 		return (error);
478 	vrele(fdp->fd_cdir);
479 	fdp->fd_cdir = nd.ni_vp;
480 	return (0);
481 }
482 
483 /*
484  * Change notion of root (``/'') directory.
485  */
486 struct chroot_args {
487 	char	*fname;
488 };
489 /* ARGSUSED */
490 chroot(p, uap, retval)
491 	struct proc *p;
492 	struct chroot_args *uap;
493 	int *retval;
494 {
495 	register struct filedesc *fdp = p->p_fd;
496 	int error;
497 	struct nameidata nd;
498 
499 	if (error = suser(p->p_ucred, &p->p_acflag))
500 		return (error);
501 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
502 	if (error = chdirec(&nd, p))
503 		return (error);
504 	if (fdp->fd_rdir != NULL)
505 		vrele(fdp->fd_rdir);
506 	fdp->fd_rdir = nd.ni_vp;
507 	return (0);
508 }
509 
510 /*
511  * Common routine for chroot and chdir.
512  */
513 chdirec(ndp, p)
514 	register struct nameidata *ndp;
515 	struct proc *p;
516 {
517 	struct vnode *vp;
518 	int error;
519 
520 	if (error = namei(ndp))
521 		return (error);
522 	vp = ndp->ni_vp;
523 	if (vp->v_type != VDIR)
524 		error = ENOTDIR;
525 	else
526 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
527 	VOP_UNLOCK(vp);
528 	if (error)
529 		vrele(vp);
530 	return (error);
531 }
532 
533 /*
534  * Open system call.
535  * Check permissions, allocate an open file structure,
536  * and call the device open routine if any.
537  */
538 struct open_args {
539 	char	*fname;
540 	int	mode;
541 	int	crtmode;
542 };
543 open(p, uap, retval)
544 	struct proc *p;
545 	register struct open_args *uap;
546 	int *retval;
547 {
548 	register struct filedesc *fdp = p->p_fd;
549 	register struct file *fp;
550 	register struct vnode *vp;
551 	int fmode, cmode;
552 	struct file *nfp;
553 	int type, indx, error;
554 	struct flock lf;
555 	struct nameidata nd;
556 	extern struct fileops vnops;
557 
558 	if (error = falloc(p, &nfp, &indx))
559 		return (error);
560 	fp = nfp;
561 	fmode = FFLAGS(uap->mode);
562 	cmode = ((uap->crtmode &~ fdp->fd_cmask) & 07777) &~ S_ISVTX;
563 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
564 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
565 	if (error = vn_open(&nd, fmode, cmode)) {
566 		ffree(fp);
567 		if ((error == ENODEV || error == ENXIO) &&
568 		    p->p_dupfd >= 0 && 			/* XXX from fdopen */
569 		    (error = dupfdopen(fdp, indx, p->p_dupfd,
570 					fmode, error)) == 0) {
571 			*retval = indx;
572 			return (0);
573 		}
574 		if (error == ERESTART)
575 			error = EINTR;
576 		fdp->fd_ofiles[indx] = NULL;
577 		return (error);
578 	}
579 	p->p_dupfd = 0;
580 	vp = nd.ni_vp;
581 	fp->f_flag = fmode & FMASK;
582 	fp->f_type = DTYPE_VNODE;
583 	fp->f_ops = &vnops;
584 	fp->f_data = (caddr_t)vp;
585 	if (fmode & (O_EXLOCK | O_SHLOCK)) {
586 		lf.l_whence = SEEK_SET;
587 		lf.l_start = 0;
588 		lf.l_len = 0;
589 		if (fmode & O_EXLOCK)
590 			lf.l_type = F_WRLCK;
591 		else
592 			lf.l_type = F_RDLCK;
593 		type = F_FLOCK;
594 		if ((fmode & FNONBLOCK) == 0)
595 			type |= F_WAIT;
596 		if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
597 			VOP_UNLOCK(vp);
598 			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
599 			ffree(fp);
600 			fdp->fd_ofiles[indx] = NULL;
601 			return (error);
602 		}
603 		fp->f_flag |= FHASLOCK;
604 	}
605 	VOP_UNLOCK(vp);
606 	*retval = indx;
607 	return (0);
608 }
609 
610 #ifdef COMPAT_43
611 /*
612  * Creat system call.
613  */
614 struct ocreat_args {
615 	char	*fname;
616 	int	fmode;
617 };
618 ocreat(p, uap, retval)
619 	struct proc *p;
620 	register struct ocreat_args *uap;
621 	int *retval;
622 {
623 	struct open_args openuap;
624 
625 	openuap.fname = uap->fname;
626 	openuap.crtmode = uap->fmode;
627 	openuap.mode = O_WRONLY | O_CREAT | O_TRUNC;
628 	return (open(p, &openuap, retval));
629 }
630 #endif /* COMPAT_43 */
631 
632 /*
633  * Mknod system call.
634  */
635 struct mknod_args {
636 	char	*fname;
637 	int	fmode;
638 	int	dev;
639 };
640 /* ARGSUSED */
641 mknod(p, uap, retval)
642 	struct proc *p;
643 	register struct mknod_args *uap;
644 	int *retval;
645 {
646 	register struct vnode *vp;
647 	struct vattr vattr;
648 	int error;
649 	struct nameidata nd;
650 
651 	if (error = suser(p->p_ucred, &p->p_acflag))
652 		return (error);
653 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->fname, p);
654 	if (error = namei(&nd))
655 		return (error);
656 	vp = nd.ni_vp;
657 	if (vp != NULL) {
658 		error = EEXIST;
659 		goto out;
660 	}
661 	VATTR_NULL(&vattr);
662 	switch (uap->fmode & S_IFMT) {
663 
664 	case S_IFMT:	/* used by badsect to flag bad sectors */
665 		vattr.va_type = VBAD;
666 		break;
667 	case S_IFCHR:
668 		vattr.va_type = VCHR;
669 		break;
670 	case S_IFBLK:
671 		vattr.va_type = VBLK;
672 		break;
673 	default:
674 		error = EINVAL;
675 		goto out;
676 	}
677 	vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask;
678 	vattr.va_rdev = uap->dev;
679 out:
680 	if (!error) {
681 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
682 		error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
683 	} else {
684 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
685 		if (nd.ni_dvp == vp)
686 			vrele(nd.ni_dvp);
687 		else
688 			vput(nd.ni_dvp);
689 		if (vp)
690 			vrele(vp);
691 	}
692 	return (error);
693 }
694 
695 /*
696  * Mkfifo system call.
697  */
698 struct mkfifo_args {
699 	char	*fname;
700 	int	fmode;
701 };
702 /* ARGSUSED */
703 mkfifo(p, uap, retval)
704 	struct proc *p;
705 	register struct mkfifo_args *uap;
706 	int *retval;
707 {
708 	struct vattr vattr;
709 	int error;
710 	struct nameidata nd;
711 
712 #ifndef FIFO
713 	return (EOPNOTSUPP);
714 #else
715 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->fname, p);
716 	if (error = namei(&nd))
717 		return (error);
718 	if (nd.ni_vp != NULL) {
719 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
720 		if (nd.ni_dvp == nd.ni_vp)
721 			vrele(nd.ni_dvp);
722 		else
723 			vput(nd.ni_dvp);
724 		vrele(nd.ni_vp);
725 		return (EEXIST);
726 	}
727 	VATTR_NULL(&vattr);
728 	vattr.va_type = VFIFO;
729 	vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask;
730 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
731 	return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
732 #endif /* FIFO */
733 }
734 
735 /*
736  * Link system call.
737  */
738 struct link_args {
739 	char	*target;
740 	char	*linkname;
741 };
742 /* ARGSUSED */
743 link(p, uap, retval)
744 	struct proc *p;
745 	register struct link_args *uap;
746 	int *retval;
747 {
748 	register struct vnode *vp, *xp;
749 	int error;
750 	struct nameidata nd;
751 
752 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->target, p);
753 	if (error = namei(&nd))
754 		return (error);
755 	vp = nd.ni_vp;
756 	if (vp->v_type == VDIR &&
757 	    (error = suser(p->p_ucred, &p->p_acflag)))
758 		goto out1;
759 	nd.ni_cnd.cn_nameiop = CREATE;
760 	nd.ni_cnd.cn_flags = LOCKPARENT;
761 	nd.ni_dirp = (caddr_t)uap->linkname;
762 	if (error = namei(&nd))
763 		goto out1;
764 	xp = nd.ni_vp;
765 	if (xp != NULL) {
766 		error = EEXIST;
767 		goto out;
768 	}
769 	xp = nd.ni_dvp;
770 out:
771 	if (!error) {
772 		LEASE_CHECK(xp, p, p->p_ucred, LEASE_WRITE);
773 		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
774 		error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
775 	} else {
776 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
777 		if (nd.ni_dvp == nd.ni_vp)
778 			vrele(nd.ni_dvp);
779 		else
780 			vput(nd.ni_dvp);
781 		if (nd.ni_vp)
782 			vrele(nd.ni_vp);
783 	}
784 out1:
785 	vrele(vp);
786 	return (error);
787 }
788 
789 /*
790  * Make a symbolic link.
791  */
792 struct symlink_args {
793 	char	*target;
794 	char	*linkname;
795 };
796 /* ARGSUSED */
797 symlink(p, uap, retval)
798 	struct proc *p;
799 	register struct symlink_args *uap;
800 	int *retval;
801 {
802 	struct vattr vattr;
803 	char *target;
804 	int error;
805 	struct nameidata nd;
806 
807 	MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
808 	if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0))
809 		goto out;
810 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->linkname, p);
811 	if (error = namei(&nd))
812 		goto out;
813 	if (nd.ni_vp) {
814 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
815 		if (nd.ni_dvp == nd.ni_vp)
816 			vrele(nd.ni_dvp);
817 		else
818 			vput(nd.ni_dvp);
819 		vrele(nd.ni_vp);
820 		error = EEXIST;
821 		goto out;
822 	}
823 	VATTR_NULL(&vattr);
824 	vattr.va_mode = 0777 &~ p->p_fd->fd_cmask;
825 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
826 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, target);
827 out:
828 	FREE(target, M_NAMEI);
829 	return (error);
830 }
831 
832 /*
833  * Delete a name from the filesystem.
834  */
835 struct unlink_args {
836 	char	*name;
837 };
838 /* ARGSUSED */
839 unlink(p, uap, retval)
840 	struct proc *p;
841 	struct unlink_args *uap;
842 	int *retval;
843 {
844 	register struct vnode *vp;
845 	int error;
846 	struct nameidata nd;
847 
848 	NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->name, p);
849 	if (error = namei(&nd))
850 		return (error);
851 	vp = nd.ni_vp;
852 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
853 	VOP_LOCK(vp);
854 	if (vp->v_type == VDIR &&
855 	    (error = suser(p->p_ucred, &p->p_acflag)))
856 		goto out;
857 	/*
858 	 * The root of a mounted filesystem cannot be deleted.
859 	 */
860 	if (vp->v_flag & VROOT) {
861 		error = EBUSY;
862 		goto out;
863 	}
864 	(void) vnode_pager_uncache(vp);
865 out:
866 	if (!error) {
867 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
868 		error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
869 	} else {
870 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
871 		if (nd.ni_dvp == vp)
872 			vrele(nd.ni_dvp);
873 		else
874 			vput(nd.ni_dvp);
875 		vput(vp);
876 	}
877 	return (error);
878 }
879 
880 struct __lseek_args {
881 	int	fdes;
882 	int	pad;
883 	off_t	off;
884 	int	sbase;
885 };
886 
887 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
888 /*
889  * Seek system call.
890  */
891 struct lseek_args {
892 	int	fdes;
893 	long	off;
894 	int	sbase;
895 };
896 lseek(p, uap, retval)
897 	struct proc *p;
898 	register struct lseek_args *uap;
899 	int *retval;
900 {
901 	struct __lseek_args nuap;
902 	off_t qret;
903 	int error;
904 
905 	nuap.fdes = uap->fdes;
906 	nuap.off = uap->off;
907 	nuap.sbase = uap->sbase;
908 	error = __lseek(p, &nuap, &qret);
909 	*(long *)retval = qret;
910 	return (error);
911 }
912 #endif /* COMPAT_43 || COMPAT_SUNOS */
913 
914 /*
915  * Seek system call.
916  */
917 __lseek(p, uap, retval)
918 	struct proc *p;
919 	register struct __lseek_args *uap;
920 	int *retval;
921 {
922 	struct ucred *cred = p->p_ucred;
923 	register struct filedesc *fdp = p->p_fd;
924 	register struct file *fp;
925 	struct vattr vattr;
926 	int error;
927 
928 	if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
929 	    (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
930 		return (EBADF);
931 	if (fp->f_type != DTYPE_VNODE)
932 		return (ESPIPE);
933 	switch (uap->sbase) {
934 
935 	case L_INCR:
936 		fp->f_offset += uap->off;
937 		break;
938 
939 	case L_XTND:
940 		if (error = VOP_GETATTR((struct vnode *)fp->f_data,
941 		    &vattr, cred, p))
942 			return (error);
943 		fp->f_offset = uap->off + vattr.va_size;
944 		break;
945 
946 	case L_SET:
947 		fp->f_offset = uap->off;
948 		break;
949 
950 	default:
951 		return (EINVAL);
952 	}
953 	*(off_t *)retval = fp->f_offset;
954 	return (0);
955 }
956 
957 /*
958  * Check access permissions.
959  */
960 struct saccess_args {
961 	char	*fname;
962 	int	fmode;
963 };
964 /* ARGSUSED */
965 saccess(p, uap, retval)
966 	struct proc *p;
967 	register struct saccess_args *uap;
968 	int *retval;
969 {
970 	register struct ucred *cred = p->p_ucred;
971 	register struct vnode *vp;
972 	int error, mode, svuid, svgid;
973 	struct nameidata nd;
974 
975 	svuid = cred->cr_uid;
976 	svgid = cred->cr_groups[0];
977 	cred->cr_uid = p->p_cred->p_ruid;
978 	cred->cr_groups[0] = p->p_cred->p_rgid;
979 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
980 	if (error = namei(&nd))
981 		goto out1;
982 	vp = nd.ni_vp;
983 	/*
984 	 * fmode == 0 means only check for exist
985 	 */
986 	if (uap->fmode) {
987 		mode = 0;
988 		if (uap->fmode & R_OK)
989 			mode |= VREAD;
990 		if (uap->fmode & W_OK)
991 			mode |= VWRITE;
992 		if (uap->fmode & X_OK)
993 			mode |= VEXEC;
994 		if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
995 			error = VOP_ACCESS(vp, mode, cred, p);
996 	}
997 	vput(vp);
998 out1:
999 	cred->cr_uid = svuid;
1000 	cred->cr_groups[0] = svgid;
1001 	return (error);
1002 }
1003 
1004 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1005 /*
1006  * Stat system call.
1007  * This version follows links.
1008  */
1009 struct ostat_args {
1010 	char	*fname;
1011 	struct ostat *ub;
1012 };
1013 /* ARGSUSED */
1014 ostat(p, uap, retval)
1015 	struct proc *p;
1016 	register struct ostat_args *uap;
1017 	int *retval;
1018 {
1019 	struct stat sb;
1020 	struct ostat osb;
1021 	int error;
1022 	struct nameidata nd;
1023 
1024 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
1025 	if (error = namei(&nd))
1026 		return (error);
1027 	error = vn_stat(nd.ni_vp, &sb, p);
1028 	vput(nd.ni_vp);
1029 	if (error)
1030 		return (error);
1031 	cvtstat(&sb, &osb);
1032 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1033 	return (error);
1034 }
1035 
1036 /*
1037  * Lstat system call.
1038  * This version does not follow links.
1039  */
1040 struct olstat_args {
1041 	char	*fname;
1042 	struct ostat *ub;
1043 };
1044 /* ARGSUSED */
1045 olstat(p, uap, retval)
1046 	struct proc *p;
1047 	register struct olstat_args *uap;
1048 	int *retval;
1049 {
1050 	struct stat sb;
1051 	struct ostat osb;
1052 	int error;
1053 	struct nameidata nd;
1054 
1055 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
1056 	if (error = namei(&nd))
1057 		return (error);
1058 	error = vn_stat(nd.ni_vp, &sb, p);
1059 	vput(nd.ni_vp);
1060 	if (error)
1061 		return (error);
1062 	cvtstat(&sb, &osb);
1063 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1064 	return (error);
1065 }
1066 
1067 /*
1068  * convert from an old to a new stat structure.
1069  */
1070 cvtstat(st, ost)
1071 	struct stat *st;
1072 	struct ostat *ost;
1073 {
1074 
1075 	ost->st_dev = st->st_dev;
1076 	ost->st_ino = st->st_ino;
1077 	ost->st_mode = st->st_mode;
1078 	ost->st_nlink = st->st_nlink;
1079 	ost->st_uid = st->st_uid;
1080 	ost->st_gid = st->st_gid;
1081 	ost->st_rdev = st->st_rdev;
1082 	if (st->st_size < (quad_t)1 << 32)
1083 		ost->st_size = st->st_size;
1084 	else
1085 		ost->st_size = -2;
1086 	ost->st_atime = st->st_atime;
1087 	ost->st_mtime = st->st_mtime;
1088 	ost->st_ctime = st->st_ctime;
1089 	ost->st_blksize = st->st_blksize;
1090 	ost->st_blocks = st->st_blocks;
1091 	ost->st_flags = st->st_flags;
1092 	ost->st_gen = st->st_gen;
1093 }
1094 #endif /* COMPAT_43 || COMPAT_SUNOS */
1095 
1096 /*
1097  * Stat system call.
1098  * This version follows links.
1099  */
1100 struct stat_args {
1101 	char	*fname;
1102 	struct stat *ub;
1103 };
1104 /* ARGSUSED */
1105 stat(p, uap, retval)
1106 	struct proc *p;
1107 	register struct stat_args *uap;
1108 	int *retval;
1109 {
1110 	struct stat sb;
1111 	int error;
1112 	struct nameidata nd;
1113 
1114 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);
1115 	if (error = namei(&nd))
1116 		return (error);
1117 	error = vn_stat(nd.ni_vp, &sb, p);
1118 	vput(nd.ni_vp);
1119 	if (error)
1120 		return (error);
1121 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1122 	return (error);
1123 }
1124 
1125 /*
1126  * Lstat system call.
1127  * This version does not follow links.
1128  */
1129 struct lstat_args {
1130 	char	*fname;
1131 	struct stat *ub;
1132 };
1133 /* ARGSUSED */
1134 lstat(p, uap, retval)
1135 	struct proc *p;
1136 	register struct lstat_args *uap;
1137 	int *retval;
1138 {
1139 	int error;
1140 	struct vnode *vp, *dvp;
1141 	struct stat sb, sb1;
1142 	struct nameidata nd;
1143 
1144 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1145 	    uap->fname, p);
1146 	if (error = namei(&nd))
1147 		return (error);
1148 	/*
1149 	 * For symbolic links, always return the attributes of its
1150 	 * containing directory, except for mode, size, and links.
1151 	 */
1152 	vp = nd.ni_vp;
1153 	dvp = nd.ni_dvp;
1154 	if (vp->v_type != VLNK) {
1155 		if (dvp == vp)
1156 			vrele(dvp);
1157 		else
1158 			vput(dvp);
1159 		error = vn_stat(vp, &sb, p);
1160 		vput(vp);
1161 		if (error)
1162 			return (error);
1163 	} else {
1164 		error = vn_stat(dvp, &sb, p);
1165 		vput(dvp);
1166 		if (error) {
1167 			vput(vp);
1168 			return (error);
1169 		}
1170 		error = vn_stat(vp, &sb1, p);
1171 		vput(vp);
1172 		if (error)
1173 			return (error);
1174 		sb.st_mode &= ~S_IFDIR;
1175 		sb.st_mode |= S_IFLNK;
1176 		sb.st_nlink = sb1.st_nlink;
1177 		sb.st_size = sb1.st_size;
1178 		sb.st_blocks = sb1.st_blocks;
1179 	}
1180 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1181 	return (error);
1182 }
1183 
1184 /*
1185  * Return target name of a symbolic link.
1186  */
1187 struct readlink_args {
1188 	char	*name;
1189 	char	*buf;
1190 	int	count;
1191 };
1192 /* ARGSUSED */
1193 readlink(p, uap, retval)
1194 	struct proc *p;
1195 	register struct readlink_args *uap;
1196 	int *retval;
1197 {
1198 	register struct vnode *vp;
1199 	struct iovec aiov;
1200 	struct uio auio;
1201 	int error;
1202 	struct nameidata nd;
1203 
1204 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->name, p);
1205 	if (error = namei(&nd))
1206 		return (error);
1207 	vp = nd.ni_vp;
1208 	if (vp->v_type != VLNK) {
1209 		error = EINVAL;
1210 		goto out;
1211 	}
1212 	aiov.iov_base = uap->buf;
1213 	aiov.iov_len = uap->count;
1214 	auio.uio_iov = &aiov;
1215 	auio.uio_iovcnt = 1;
1216 	auio.uio_offset = 0;
1217 	auio.uio_rw = UIO_READ;
1218 	auio.uio_segflg = UIO_USERSPACE;
1219 	auio.uio_procp = p;
1220 	auio.uio_resid = uap->count;
1221 	error = VOP_READLINK(vp, &auio, p->p_ucred);
1222 out:
1223 	vput(vp);
1224 	*retval = uap->count - auio.uio_resid;
1225 	return (error);
1226 }
1227 
1228 /*
1229  * Change flags of a file given path name.
1230  */
1231 struct chflags_args {
1232 	char	*fname;
1233 	int	flags;
1234 };
1235 /* ARGSUSED */
1236 chflags(p, uap, retval)
1237 	struct proc *p;
1238 	register struct chflags_args *uap;
1239 	int *retval;
1240 {
1241 	register struct vnode *vp;
1242 	struct vattr vattr;
1243 	int error;
1244 	struct nameidata nd;
1245 
1246 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
1247 	if (error = namei(&nd))
1248 		return (error);
1249 	vp = nd.ni_vp;
1250 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1251 	VOP_LOCK(vp);
1252 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1253 		error = EROFS;
1254 		goto out;
1255 	}
1256 	VATTR_NULL(&vattr);
1257 	vattr.va_flags = uap->flags;
1258 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1259 out:
1260 	vput(vp);
1261 	return (error);
1262 }
1263 
1264 /*
1265  * Change flags of a file given a file descriptor.
1266  */
1267 struct fchflags_args {
1268 	int	fd;
1269 	int	flags;
1270 };
1271 /* ARGSUSED */
1272 fchflags(p, uap, retval)
1273 	struct proc *p;
1274 	register struct fchflags_args *uap;
1275 	int *retval;
1276 {
1277 	struct vattr vattr;
1278 	struct vnode *vp;
1279 	struct file *fp;
1280 	int error;
1281 
1282 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1283 		return (error);
1284 	vp = (struct vnode *)fp->f_data;
1285 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1286 	VOP_LOCK(vp);
1287 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1288 		error = EROFS;
1289 		goto out;
1290 	}
1291 	VATTR_NULL(&vattr);
1292 	vattr.va_flags = uap->flags;
1293 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1294 out:
1295 	VOP_UNLOCK(vp);
1296 	return (error);
1297 }
1298 
1299 /*
1300  * Change mode of a file given path name.
1301  */
1302 struct chmod_args {
1303 	char	*fname;
1304 	int	fmode;
1305 };
1306 /* ARGSUSED */
1307 chmod(p, uap, retval)
1308 	struct proc *p;
1309 	register struct chmod_args *uap;
1310 	int *retval;
1311 {
1312 	register struct vnode *vp;
1313 	struct vattr vattr;
1314 	int error;
1315 	struct nameidata nd;
1316 
1317 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
1318 	if (error = namei(&nd))
1319 		return (error);
1320 	vp = nd.ni_vp;
1321 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1322 	VOP_LOCK(vp);
1323 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1324 		error = EROFS;
1325 		goto out;
1326 	}
1327 	VATTR_NULL(&vattr);
1328 	vattr.va_mode = uap->fmode & 07777;
1329 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1330 out:
1331 	vput(vp);
1332 	return (error);
1333 }
1334 
1335 /*
1336  * Change mode of a file given a file descriptor.
1337  */
1338 struct fchmod_args {
1339 	int	fd;
1340 	int	fmode;
1341 };
1342 /* ARGSUSED */
1343 fchmod(p, uap, retval)
1344 	struct proc *p;
1345 	register struct fchmod_args *uap;
1346 	int *retval;
1347 {
1348 	struct vattr vattr;
1349 	struct vnode *vp;
1350 	struct file *fp;
1351 	int error;
1352 
1353 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1354 		return (error);
1355 	vp = (struct vnode *)fp->f_data;
1356 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1357 	VOP_LOCK(vp);
1358 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1359 		error = EROFS;
1360 		goto out;
1361 	}
1362 	VATTR_NULL(&vattr);
1363 	vattr.va_mode = uap->fmode & 07777;
1364 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1365 out:
1366 	VOP_UNLOCK(vp);
1367 	return (error);
1368 }
1369 
1370 /*
1371  * Set ownership given a path name.
1372  */
1373 struct chown_args {
1374 	char	*fname;
1375 	int	uid;
1376 	int	gid;
1377 };
1378 /* ARGSUSED */
1379 chown(p, uap, retval)
1380 	struct proc *p;
1381 	register struct chown_args *uap;
1382 	int *retval;
1383 {
1384 	register struct vnode *vp;
1385 	struct vattr vattr;
1386 	int error;
1387 	struct nameidata nd;
1388 
1389 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->fname, p);
1390 	if (error = namei(&nd))
1391 		return (error);
1392 	vp = nd.ni_vp;
1393 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1394 	VOP_LOCK(vp);
1395 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1396 		error = EROFS;
1397 		goto out;
1398 	}
1399 	VATTR_NULL(&vattr);
1400 	vattr.va_uid = uap->uid;
1401 	vattr.va_gid = uap->gid;
1402 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1403 out:
1404 	vput(vp);
1405 	return (error);
1406 }
1407 
1408 /*
1409  * Set ownership given a file descriptor.
1410  */
1411 struct fchown_args {
1412 	int	fd;
1413 	int	uid;
1414 	int	gid;
1415 };
1416 /* ARGSUSED */
1417 fchown(p, uap, retval)
1418 	struct proc *p;
1419 	register struct fchown_args *uap;
1420 	int *retval;
1421 {
1422 	struct vattr vattr;
1423 	struct vnode *vp;
1424 	struct file *fp;
1425 	int error;
1426 
1427 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1428 		return (error);
1429 	vp = (struct vnode *)fp->f_data;
1430 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1431 	VOP_LOCK(vp);
1432 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1433 		error = EROFS;
1434 		goto out;
1435 	}
1436 	VATTR_NULL(&vattr);
1437 	vattr.va_uid = uap->uid;
1438 	vattr.va_gid = uap->gid;
1439 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1440 out:
1441 	VOP_UNLOCK(vp);
1442 	return (error);
1443 }
1444 
1445 /*
1446  * Set the access and modification times of a file.
1447  */
1448 struct utimes_args {
1449 	char	*fname;
1450 	struct	timeval *tptr;
1451 };
1452 /* ARGSUSED */
1453 utimes(p, uap, retval)
1454 	struct proc *p;
1455 	register struct utimes_args *uap;
1456 	int *retval;
1457 {
1458 	register struct vnode *vp;
1459 	struct timeval tv[2];
1460 	struct vattr vattr;
1461 	int error;
1462 	struct nameidata nd;
1463 
1464 	VATTR_NULL(&vattr);
1465 	if (uap->tptr == NULL) {
1466 		microtime(&tv[0]);
1467 		tv[1] = tv[0];
1468 		vattr.va_vaflags |= VA_UTIMES_NULL;
1469 	} else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1470   		return (error);
1471 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
1472 	if (error = namei(&nd))
1473 		return (error);
1474 	vp = nd.ni_vp;
1475 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1476 	VOP_LOCK(vp);
1477 	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1478 		error = EROFS;
1479 		goto out;
1480 	}
1481 	vattr.va_atime.ts_sec = tv[0].tv_sec;
1482 	vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1483 	vattr.va_mtime.ts_sec = tv[1].tv_sec;
1484 	vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
1485 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1486 out:
1487 	vput(vp);
1488 	return (error);
1489 }
1490 
1491 struct __truncate_args {
1492 	char	*fname;
1493 	int	pad;
1494 	off_t	length;
1495 };
1496 
1497 /*
1498  * Truncate a file given its path name.
1499  */
1500 /* ARGSUSED */
1501 __truncate(p, uap, retval)
1502 	struct proc *p;
1503 	register struct __truncate_args *uap;
1504 	int *retval;
1505 {
1506 	register struct vnode *vp;
1507 	struct vattr vattr;
1508 	int error;
1509 	struct nameidata nd;
1510 
1511 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
1512 	if (error = namei(&nd))
1513 		return (error);
1514 	vp = nd.ni_vp;
1515 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1516 	VOP_LOCK(vp);
1517 	if (vp->v_type == VDIR) {
1518 		error = EISDIR;
1519 		goto out;
1520 	}
1521 	if ((error = vn_writechk(vp)) ||
1522 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)))
1523 		goto out;
1524 	VATTR_NULL(&vattr);
1525 	vattr.va_size = uap->length;
1526 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1527 out:
1528 	vput(vp);
1529 	return (error);
1530 }
1531 
1532 struct __ftruncate_args {
1533 	int	fd;
1534 	int	pad;
1535 	off_t	length;
1536 };
1537 
1538 /*
1539  * Truncate a file given a file descriptor.
1540  */
1541 /* ARGSUSED */
1542 __ftruncate(p, uap, retval)
1543 	struct proc *p;
1544 	register struct __ftruncate_args *uap;
1545 	int *retval;
1546 {
1547 	struct vattr vattr;
1548 	struct vnode *vp;
1549 	struct file *fp;
1550 	int error;
1551 
1552 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1553 		return (error);
1554 	if ((fp->f_flag & FWRITE) == 0)
1555 		return (EINVAL);
1556 	vp = (struct vnode *)fp->f_data;
1557 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1558 	VOP_LOCK(vp);
1559 	if (vp->v_type == VDIR) {
1560 		error = EISDIR;
1561 		goto out;
1562 	}
1563 	if (error = vn_writechk(vp))
1564 		goto out;
1565 	VATTR_NULL(&vattr);
1566 	vattr.va_size = uap->length;
1567 	error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1568 out:
1569 	VOP_UNLOCK(vp);
1570 	return (error);
1571 }
1572 
1573 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1574 /*
1575  * Truncate a file given its path name.
1576  */
1577 struct truncate_args {
1578 	char	*fname;
1579 	long	length;
1580 };
1581 /* ARGSUSED */
1582 truncate(p, uap, retval)
1583 	struct proc *p;
1584 	register struct truncate_args *uap;
1585 	int *retval;
1586 {
1587 	struct __truncate_args nuap;
1588 
1589 	nuap.fname = uap->fname;
1590 	nuap.length = uap->length;
1591 	return (__truncate(p, &nuap, retval));
1592 }
1593 
1594 /*
1595  * Truncate a file given a file descriptor.
1596  */
1597 struct ftruncate_args {
1598 	int	fd;
1599 	long	length;
1600 };
1601 /* ARGSUSED */
1602 ftruncate(p, uap, retval)
1603 	struct proc *p;
1604 	register struct ftruncate_args *uap;
1605 	int *retval;
1606 {
1607 	struct __ftruncate_args nuap;
1608 
1609 	nuap.fd = uap->fd;
1610 	nuap.length = uap->length;
1611 	return (__ftruncate(p, &nuap, retval));
1612 }
1613 #endif /* COMPAT_43 || COMPAT_SUNOS */
1614 
1615 /*
1616  * Synch an open file.
1617  */
1618 struct fsync_args {
1619 	int	fd;
1620 };
1621 /* ARGSUSED */
1622 fsync(p, uap, retval)
1623 	struct proc *p;
1624 	struct fsync_args *uap;
1625 	int *retval;
1626 {
1627 	register struct vnode *vp;
1628 	struct file *fp;
1629 	int error;
1630 
1631 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1632 		return (error);
1633 	vp = (struct vnode *)fp->f_data;
1634 	VOP_LOCK(vp);
1635 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
1636 	VOP_UNLOCK(vp);
1637 	return (error);
1638 }
1639 
1640 /*
1641  * Rename system call.
1642  *
1643  * Source and destination must either both be directories, or both
1644  * not be directories.  If target is a directory, it must be empty.
1645  */
1646 struct rename_args {
1647 	char	*from;
1648 	char	*to;
1649 };
1650 /* ARGSUSED */
1651 rename(p, uap, retval)
1652 	struct proc *p;
1653 	register struct rename_args *uap;
1654 	int *retval;
1655 {
1656 	register struct vnode *tvp, *fvp, *tdvp;
1657 	struct nameidata fromnd, tond;
1658 	int error;
1659 
1660 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1661 		uap->from, p);
1662 	if (error = namei(&fromnd))
1663 		return (error);
1664 	fvp = fromnd.ni_vp;
1665 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1666 		UIO_USERSPACE, uap->to, p);
1667 	if (error = namei(&tond)) {
1668 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1669 		vrele(fromnd.ni_dvp);
1670 		vrele(fvp);
1671 		goto out1;
1672 	}
1673 	tdvp = tond.ni_dvp;
1674 	tvp = tond.ni_vp;
1675 	if (tvp != NULL) {
1676 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1677 			error = ENOTDIR;
1678 			goto out;
1679 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1680 			error = EISDIR;
1681 			goto out;
1682 		}
1683 	}
1684 	if (fvp == tdvp)
1685 		error = EINVAL;
1686 	/*
1687 	 * If source is the same as the destination (that is the
1688 	 * same inode number with the same name in the same directory),
1689 	 * then there is nothing to do.
1690 	 */
1691 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1692 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1693 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1694 	      fromnd.ni_cnd.cn_namelen))
1695 		error = -1;
1696 out:
1697 	if (!error) {
1698 		LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
1699 		if (fromnd.ni_dvp != tdvp)
1700 			LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1701 		if (tvp)
1702 			LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
1703 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1704 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1705 	} else {
1706 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1707 		if (tdvp == tvp)
1708 			vrele(tdvp);
1709 		else
1710 			vput(tdvp);
1711 		if (tvp)
1712 			vput(tvp);
1713 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1714 		vrele(fromnd.ni_dvp);
1715 		vrele(fvp);
1716 	}
1717 	vrele(tond.ni_startdir);
1718 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1719 out1:
1720 	vrele(fromnd.ni_startdir);
1721 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1722 	if (error == -1)
1723 		return (0);
1724 	return (error);
1725 }
1726 
1727 /*
1728  * Mkdir system call.
1729  */
1730 struct mkdir_args {
1731 	char	*name;
1732 	int	dmode;
1733 };
1734 /* ARGSUSED */
1735 mkdir(p, uap, retval)
1736 	struct proc *p;
1737 	register struct mkdir_args *uap;
1738 	int *retval;
1739 {
1740 	register struct vnode *vp;
1741 	struct vattr vattr;
1742 	int error;
1743 	struct nameidata nd;
1744 
1745 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->name, p);
1746 	if (error = namei(&nd))
1747 		return (error);
1748 	vp = nd.ni_vp;
1749 	if (vp != NULL) {
1750 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1751 		if (nd.ni_dvp == vp)
1752 			vrele(nd.ni_dvp);
1753 		else
1754 			vput(nd.ni_dvp);
1755 		vrele(vp);
1756 		return (EEXIST);
1757 	}
1758 	VATTR_NULL(&vattr);
1759 	vattr.va_type = VDIR;
1760 	vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask;
1761 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1762 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1763 	if (!error)
1764 		vput(nd.ni_vp);
1765 	return (error);
1766 }
1767 
1768 /*
1769  * Rmdir system call.
1770  */
1771 struct rmdir_args {
1772 	char	*name;
1773 };
1774 /* ARGSUSED */
1775 rmdir(p, uap, retval)
1776 	struct proc *p;
1777 	struct rmdir_args *uap;
1778 	int *retval;
1779 {
1780 	register struct vnode *vp;
1781 	int error;
1782 	struct nameidata nd;
1783 
1784 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p);
1785 	if (error = namei(&nd))
1786 		return (error);
1787 	vp = nd.ni_vp;
1788 	if (vp->v_type != VDIR) {
1789 		error = ENOTDIR;
1790 		goto out;
1791 	}
1792 	/*
1793 	 * No rmdir "." please.
1794 	 */
1795 	if (nd.ni_dvp == vp) {
1796 		error = EINVAL;
1797 		goto out;
1798 	}
1799 	/*
1800 	 * The root of a mounted filesystem cannot be deleted.
1801 	 */
1802 	if (vp->v_flag & VROOT)
1803 		error = EBUSY;
1804 out:
1805 	if (!error) {
1806 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1807 		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1808 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1809 	} else {
1810 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1811 		if (nd.ni_dvp == vp)
1812 			vrele(nd.ni_dvp);
1813 		else
1814 			vput(nd.ni_dvp);
1815 		vput(vp);
1816 	}
1817 	return (error);
1818 }
1819 
1820 #ifdef COMPAT_43
1821 /*
1822  * Read a block of directory entries in a file system independent format.
1823  */
1824 struct ogetdirentries_args {
1825 	int	fd;
1826 	char	*buf;
1827 	unsigned count;
1828 	long	*basep;
1829 };
1830 ogetdirentries(p, uap, retval)
1831 	struct proc *p;
1832 	register struct ogetdirentries_args *uap;
1833 	int *retval;
1834 {
1835 	register struct vnode *vp;
1836 	struct file *fp;
1837 	struct uio auio, kuio;
1838 	struct iovec aiov, kiov;
1839 	struct dirent *dp, *edp;
1840 	caddr_t dirbuf;
1841 	int error, readcnt;
1842 	long loff;
1843 
1844 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1845 		return (error);
1846 	if ((fp->f_flag & FREAD) == 0)
1847 		return (EBADF);
1848 	vp = (struct vnode *)fp->f_data;
1849 	if (vp->v_type != VDIR)
1850 		return (EINVAL);
1851 	aiov.iov_base = uap->buf;
1852 	aiov.iov_len = uap->count;
1853 	auio.uio_iov = &aiov;
1854 	auio.uio_iovcnt = 1;
1855 	auio.uio_rw = UIO_READ;
1856 	auio.uio_segflg = UIO_USERSPACE;
1857 	auio.uio_procp = p;
1858 	auio.uio_resid = uap->count;
1859 	VOP_LOCK(vp);
1860 	loff = auio.uio_offset = fp->f_offset;
1861 #	if (BYTE_ORDER != LITTLE_ENDIAN)
1862 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
1863 			error = VOP_READDIR(vp, &auio, fp->f_cred);
1864 			fp->f_offset = auio.uio_offset;
1865 		} else
1866 #	endif
1867 	{
1868 		kuio = auio;
1869 		kuio.uio_iov = &kiov;
1870 		kuio.uio_segflg = UIO_SYSSPACE;
1871 		kiov.iov_len = uap->count;
1872 		MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
1873 		kiov.iov_base = dirbuf;
1874 		error = VOP_READDIR(vp, &kuio, fp->f_cred);
1875 		fp->f_offset = kuio.uio_offset;
1876 		if (error == 0) {
1877 			readcnt = uap->count - kuio.uio_resid;
1878 			edp = (struct dirent *)&dirbuf[readcnt];
1879 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1880 #				if (BYTE_ORDER == LITTLE_ENDIAN)
1881 					/*
1882 					 * The expected low byte of
1883 					 * dp->d_namlen is our dp->d_type.
1884 					 * The high MBZ byte of dp->d_namlen
1885 					 * is our dp->d_namlen.
1886 					 */
1887 					dp->d_type = dp->d_namlen;
1888 					dp->d_namlen = 0;
1889 #				else
1890 					/*
1891 					 * The dp->d_type is the high byte
1892 					 * of the expected dp->d_namlen,
1893 					 * so must be zero'ed.
1894 					 */
1895 					dp->d_type = 0;
1896 #				endif
1897 				if (dp->d_reclen > 0) {
1898 					dp = (struct dirent *)
1899 					    ((char *)dp + dp->d_reclen);
1900 				} else {
1901 					error = EIO;
1902 					break;
1903 				}
1904 			}
1905 			if (dp >= edp)
1906 				error = uiomove(dirbuf, readcnt, &auio);
1907 		}
1908 		FREE(dirbuf, M_TEMP);
1909 	}
1910 	VOP_UNLOCK(vp);
1911 	if (error)
1912 		return (error);
1913 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
1914 	*retval = uap->count - auio.uio_resid;
1915 	return (error);
1916 }
1917 #endif
1918 
1919 /*
1920  * Read a block of directory entries in a file system independent format.
1921  */
1922 struct getdirentries_args {
1923 	int	fd;
1924 	char	*buf;
1925 	unsigned count;
1926 	long	*basep;
1927 };
1928 getdirentries(p, uap, retval)
1929 	struct proc *p;
1930 	register struct getdirentries_args *uap;
1931 	int *retval;
1932 {
1933 	register struct vnode *vp;
1934 	struct file *fp;
1935 	struct uio auio;
1936 	struct iovec aiov;
1937 	long loff;
1938 	int error;
1939 
1940 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1941 		return (error);
1942 	if ((fp->f_flag & FREAD) == 0)
1943 		return (EBADF);
1944 	vp = (struct vnode *)fp->f_data;
1945 unionread:
1946 	if (vp->v_type != VDIR)
1947 		return (EINVAL);
1948 	aiov.iov_base = uap->buf;
1949 	aiov.iov_len = uap->count;
1950 	auio.uio_iov = &aiov;
1951 	auio.uio_iovcnt = 1;
1952 	auio.uio_rw = UIO_READ;
1953 	auio.uio_segflg = UIO_USERSPACE;
1954 	auio.uio_procp = p;
1955 	auio.uio_resid = uap->count;
1956 	VOP_LOCK(vp);
1957 	loff = auio.uio_offset = fp->f_offset;
1958 	error = VOP_READDIR(vp, &auio, fp->f_cred);
1959 	fp->f_offset = auio.uio_offset;
1960 	VOP_UNLOCK(vp);
1961 	if (error)
1962 		return (error);
1963 	if ((uap->count == auio.uio_resid) &&
1964 	    (vp->v_flag & VROOT) &&
1965 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
1966 		struct vnode *tvp = vp;
1967 		vp = vp->v_mount->mnt_vnodecovered;
1968 		VREF(vp);
1969 		fp->f_data = (caddr_t) vp;
1970 		fp->f_offset = 0;
1971 		vrele(tvp);
1972 		goto unionread;
1973 	}
1974 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
1975 	*retval = uap->count - auio.uio_resid;
1976 	return (error);
1977 }
1978 
1979 /*
1980  * Set the mode mask for creation of filesystem nodes.
1981  */
1982 struct umask_args {
1983 	int	mask;
1984 };
1985 mode_t				/* XXX */
1986 umask(p, uap, retval)
1987 	struct proc *p;
1988 	struct umask_args *uap;
1989 	int *retval;
1990 {
1991 	register struct filedesc *fdp = p->p_fd;
1992 
1993 	*retval = fdp->fd_cmask;
1994 	fdp->fd_cmask = uap->mask & 07777;
1995 	return (0);
1996 }
1997 
1998 /*
1999  * Void all references to file by ripping underlying filesystem
2000  * away from vnode.
2001  */
2002 struct revoke_args {
2003 	char	*fname;
2004 };
2005 /* ARGSUSED */
2006 revoke(p, uap, retval)
2007 	struct proc *p;
2008 	register struct revoke_args *uap;
2009 	int *retval;
2010 {
2011 	register struct vnode *vp;
2012 	struct vattr vattr;
2013 	int error;
2014 	struct nameidata nd;
2015 
2016 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
2017 	if (error = namei(&nd))
2018 		return (error);
2019 	vp = nd.ni_vp;
2020 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
2021 		error = EINVAL;
2022 		goto out;
2023 	}
2024 	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2025 		goto out;
2026 	if (p->p_ucred->cr_uid != vattr.va_uid &&
2027 	    (error = suser(p->p_ucred, &p->p_acflag)))
2028 		goto out;
2029 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2030 		vgoneall(vp);
2031 out:
2032 	vrele(vp);
2033 	return (error);
2034 }
2035 
2036 /*
2037  * Convert a user file descriptor to a kernel file entry.
2038  */
2039 getvnode(fdp, fdes, fpp)
2040 	struct filedesc *fdp;
2041 	struct file **fpp;
2042 	int fdes;
2043 {
2044 	struct file *fp;
2045 
2046 	if ((unsigned)fdes >= fdp->fd_nfiles ||
2047 	    (fp = fdp->fd_ofiles[fdes]) == NULL)
2048 		return (EBADF);
2049 	if (fp->f_type != DTYPE_VNODE)
2050 		return (EINVAL);
2051 	*fpp = fp;
2052 	return (0);
2053 }
2054