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