xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 64410)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)vfs_syscalls.c	8.2 (Berkeley) 09/05/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 static int change_dir __P((struct nameidata *ndp, struct proc *p));
28 
29 /*
30  * Virtual File System System Calls
31  */
32 
33 /*
34  * Mount a file system.
35  */
36 struct mount_args {
37 	int	type;
38 	char	*path;
39 	int	flags;
40 	caddr_t	data;
41 };
42 /* ARGSUSED */
43 mount(p, uap, retval)
44 	struct proc *p;
45 	register struct mount_args *uap;
46 	int *retval;
47 {
48 	register struct vnode *vp;
49 	register struct mount *mp;
50 	int error, flag;
51 	struct nameidata nd;
52 
53 	/*
54 	 * Must be super user
55 	 */
56 	if (error = suser(p->p_ucred, &p->p_acflag))
57 		return (error);
58 	/*
59 	 * Get vnode to be covered
60 	 */
61 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
62 	if (error = namei(&nd))
63 		return (error);
64 	vp = nd.ni_vp;
65 	if (uap->flags & MNT_UPDATE) {
66 		if ((vp->v_flag & VROOT) == 0) {
67 			vput(vp);
68 			return (EINVAL);
69 		}
70 		mp = vp->v_mount;
71 		flag = mp->mnt_flag;
72 		/*
73 		 * We only allow the filesystem to be reloaded if it
74 		 * is currently mounted read-only.
75 		 */
76 		if ((uap->flags & MNT_RELOAD) &&
77 		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
78 			vput(vp);
79 			return (EOPNOTSUPP);	/* Needs translation */
80 		}
81 		mp->mnt_flag |=
82 		    uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
83 		VOP_UNLOCK(vp);
84 		goto update;
85 	}
86 	if (vp->v_usecount != 1 && (uap->flags & MNT_UNION) == 0) {
87 		vput(vp);
88 		return (EBUSY);
89 	}
90 	if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
91 		return (error);
92 	if (vp->v_type != VDIR) {
93 		vput(vp);
94 		return (ENOTDIR);
95 	}
96 	if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) {
97 		vput(vp);
98 		return (ENODEV);
99 	}
100 
101 	/*
102 	 * Allocate and initialize the file system.
103 	 */
104 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
105 		M_MOUNT, M_WAITOK);
106 	bzero((char *)mp, (u_long)sizeof(struct mount));
107 	mp->mnt_op = vfssw[uap->type];
108 	if (error = vfs_lock(mp)) {
109 		free((caddr_t)mp, M_MOUNT);
110 		vput(vp);
111 		return (error);
112 	}
113 	if (vp->v_mountedhere != NULL) {
114 		vfs_unlock(mp);
115 		free((caddr_t)mp, M_MOUNT);
116 		vput(vp);
117 		return (EBUSY);
118 	}
119 	vp->v_mountedhere = mp;
120 	mp->mnt_vnodecovered = vp;
121 update:
122 	/*
123 	 * Set the mount level flags.
124 	 */
125 	if (uap->flags & MNT_RDONLY)
126 		mp->mnt_flag |= MNT_RDONLY;
127 	else if (mp->mnt_flag & MNT_RDONLY)
128 		mp->mnt_flag |= MNT_WANTRDWR;
129 	mp->mnt_flag &=~
130 	    (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION);
131 	mp->mnt_flag |= uap->flags &
132 	    (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION);
133 	/*
134 	 * Mount the filesystem.
135 	 */
136 	error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p);
137 	if (mp->mnt_flag & MNT_UPDATE) {
138 		vrele(vp);
139 		if (mp->mnt_flag & MNT_WANTRDWR)
140 			mp->mnt_flag &= ~MNT_RDONLY;
141 		mp->mnt_flag &=~
142 		    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
143 		if (error)
144 			mp->mnt_flag = flag;
145 		return (error);
146 	}
147 	/*
148 	 * Put the new filesystem on the mount list after root.
149 	 */
150 	mp->mnt_next = rootfs->mnt_next;
151 	mp->mnt_prev = rootfs;
152 	rootfs->mnt_next = mp;
153 	mp->mnt_next->mnt_prev = mp;
154 	cache_purge(vp);
155 	if (!error) {
156 		VOP_UNLOCK(vp);
157 		vfs_unlock(mp);
158 		error = VFS_START(mp, 0, p);
159 	} else {
160 		vfs_remove(mp);
161 		free((caddr_t)mp, M_MOUNT);
162 		vput(vp);
163 	}
164 	return (error);
165 }
166 
167 /*
168  * Unmount a file system.
169  *
170  * Note: unmount takes a path to the vnode mounted on as argument,
171  * not special file (as before).
172  */
173 struct unmount_args {
174 	char	*path;
175 	int	flags;
176 };
177 /* ARGSUSED */
178 unmount(p, uap, retval)
179 	struct proc *p;
180 	register struct unmount_args *uap;
181 	int *retval;
182 {
183 	register struct vnode *vp;
184 	struct mount *mp;
185 	int error;
186 	struct nameidata nd;
187 
188 	/*
189 	 * Must be super user
190 	 */
191 	if (error = suser(p->p_ucred, &p->p_acflag))
192 		return (error);
193 
194 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
195 	if (error = namei(&nd))
196 		return (error);
197 	vp = nd.ni_vp;
198 	/*
199 	 * Must be the root of the filesystem
200 	 */
201 	if ((vp->v_flag & VROOT) == 0) {
202 		vput(vp);
203 		return (EINVAL);
204 	}
205 	mp = vp->v_mount;
206 	vput(vp);
207 	return (dounmount(mp, uap->flags, p));
208 }
209 
210 /*
211  * Do the actual file system unmount.
212  */
213 dounmount(mp, flags, p)
214 	register struct mount *mp;
215 	int flags;
216 	struct proc *p;
217 {
218 	struct vnode *coveredvp;
219 	int error;
220 
221 	coveredvp = mp->mnt_vnodecovered;
222 	if (vfs_busy(mp))
223 		return (EBUSY);
224 	mp->mnt_flag |= MNT_UNMOUNT;
225 	if (error = vfs_lock(mp))
226 		return (error);
227 
228 	vnode_pager_umount(mp);	/* release cached vnodes */
229 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
230 	if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
231 	    (flags & MNT_FORCE))
232 		error = VFS_UNMOUNT(mp, flags, p);
233 	mp->mnt_flag &= ~MNT_UNMOUNT;
234 	vfs_unbusy(mp);
235 	if (error) {
236 		vfs_unlock(mp);
237 	} else {
238 		vrele(coveredvp);
239 		vfs_remove(mp);
240 		if (mp->mnt_mounth != NULL)
241 			panic("unmount: dangling vnode");
242 		free((caddr_t)mp, M_MOUNT);
243 	}
244 	return (error);
245 }
246 
247 /*
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  * Change 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	*path;
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->path, p);
476 	if (error = change_dir(&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	*path;
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->path, p);
502 	if (error = change_dir(&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 static int
514 change_dir(ndp, p)
515 	register struct nameidata *ndp;
516 	struct proc *p;
517 {
518 	struct vnode *vp;
519 	int error;
520 
521 	if (error = namei(ndp))
522 		return (error);
523 	vp = ndp->ni_vp;
524 	if (vp->v_type != VDIR)
525 		error = ENOTDIR;
526 	else
527 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
528 	VOP_UNLOCK(vp);
529 	if (error)
530 		vrele(vp);
531 	return (error);
532 }
533 
534 /*
535  * Check permissions, allocate an open file structure,
536  * and call the device open routine if any.
537  */
538 struct open_args {
539 	char	*path;
540 	int	flags;
541 	int	mode;
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 flags, 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 	flags = FFLAGS(uap->flags);
562 	cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
563 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
564 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
565 	if (error = vn_open(&nd, flags, cmode)) {
566 		ffree(fp);
567 		if ((error == ENODEV || error == ENXIO) &&
568 		    p->p_dupfd >= 0 && 			/* XXX from fdopen */
569 		    (error =
570 		        dupfdopen(fdp, indx, p->p_dupfd, flags, 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 = flags & FMASK;
582 	fp->f_type = DTYPE_VNODE;
583 	fp->f_ops = &vnops;
584 	fp->f_data = (caddr_t)vp;
585 	if (flags & (O_EXLOCK | O_SHLOCK)) {
586 		lf.l_whence = SEEK_SET;
587 		lf.l_start = 0;
588 		lf.l_len = 0;
589 		if (flags & O_EXLOCK)
590 			lf.l_type = F_WRLCK;
591 		else
592 			lf.l_type = F_RDLCK;
593 		type = F_FLOCK;
594 		if ((flags & 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  * Create a file.
613  */
614 struct ocreat_args {
615 	char	*path;
616 	int	mode;
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.path = uap->path;
626 	openuap.mode = uap->mode;
627 	openuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
628 	return (open(p, &openuap, retval));
629 }
630 #endif /* COMPAT_43 */
631 
632 /*
633  * Create a special file.
634  */
635 struct mknod_args {
636 	char	*path;
637 	int	mode;
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->path, 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->mode & S_IFMT) {
663 	case S_IFMT:	/* used by badsect to flag bad sectors */
664 		vattr.va_type = VBAD;
665 		break;
666 	case S_IFCHR:
667 		vattr.va_type = VCHR;
668 		break;
669 	case S_IFBLK:
670 		vattr.va_type = VBLK;
671 		break;
672 	default:
673 		error = EINVAL;
674 		goto out;
675 	}
676 	vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
677 	vattr.va_rdev = uap->dev;
678 out:
679 	if (!error) {
680 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
681 		error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
682 	} else {
683 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
684 		if (nd.ni_dvp == vp)
685 			vrele(nd.ni_dvp);
686 		else
687 			vput(nd.ni_dvp);
688 		if (vp)
689 			vrele(vp);
690 	}
691 	return (error);
692 }
693 
694 /*
695  * Create named pipe.
696  */
697 struct mkfifo_args {
698 	char	*path;
699 	int	mode;
700 };
701 /* ARGSUSED */
702 mkfifo(p, uap, retval)
703 	struct proc *p;
704 	register struct mkfifo_args *uap;
705 	int *retval;
706 {
707 	struct vattr vattr;
708 	int error;
709 	struct nameidata nd;
710 
711 #ifndef FIFO
712 	return (EOPNOTSUPP);
713 #else
714 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
715 	if (error = namei(&nd))
716 		return (error);
717 	if (nd.ni_vp != NULL) {
718 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
719 		if (nd.ni_dvp == nd.ni_vp)
720 			vrele(nd.ni_dvp);
721 		else
722 			vput(nd.ni_dvp);
723 		vrele(nd.ni_vp);
724 		return (EEXIST);
725 	}
726 	VATTR_NULL(&vattr);
727 	vattr.va_type = VFIFO;
728 	vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
729 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
730 	return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
731 #endif /* FIFO */
732 }
733 
734 /*
735  * Make a hard file link.
736  */
737 struct link_args {
738 	char	*path;
739 	char	*link;
740 };
741 /* ARGSUSED */
742 link(p, uap, retval)
743 	struct proc *p;
744 	register struct link_args *uap;
745 	int *retval;
746 {
747 	register struct vnode *vp;
748 	struct nameidata nd;
749 	int error;
750 
751 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
752 	if (error = namei(&nd))
753 		return (error);
754 	vp = nd.ni_vp;
755 	if (vp->v_type == VDIR &&
756 	    (error = suser(p->p_ucred, &p->p_acflag)))
757 		goto out;
758 	nd.ni_cnd.cn_nameiop = CREATE;
759 	nd.ni_cnd.cn_flags = LOCKPARENT;
760 	nd.ni_dirp = uap->link;
761 	if (error = namei(&nd))
762 		goto out;
763 	if (nd.ni_vp != NULL)
764 		error = EEXIST;
765 	if (!error) {
766 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
767 		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
768 		error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
769 	} else {
770 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
771 		if (nd.ni_dvp == nd.ni_vp)
772 			vrele(nd.ni_dvp);
773 		else
774 			vput(nd.ni_dvp);
775 		if (nd.ni_vp)
776 			vrele(nd.ni_vp);
777 	}
778 out:	vrele(vp);
779 	return (error);
780 }
781 
782 /*
783  * Make a symbolic link.
784  */
785 struct symlink_args {
786 	char	*path;
787 	char	*link;
788 };
789 /* ARGSUSED */
790 symlink(p, uap, retval)
791 	struct proc *p;
792 	register struct symlink_args *uap;
793 	int *retval;
794 {
795 	struct vattr vattr;
796 	char *path;
797 	int error;
798 	struct nameidata nd;
799 
800 	MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
801 	if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL))
802 		goto out;
803 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
804 	if (error = namei(&nd))
805 		goto out;
806 	if (nd.ni_vp) {
807 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
808 		if (nd.ni_dvp == nd.ni_vp)
809 			vrele(nd.ni_dvp);
810 		else
811 			vput(nd.ni_dvp);
812 		vrele(nd.ni_vp);
813 		error = EEXIST;
814 		goto out;
815 	}
816 	VATTR_NULL(&vattr);
817 	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
818 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
819 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
820 out:
821 	FREE(path, M_NAMEI);
822 	return (error);
823 }
824 
825 /*
826  * Delete a name from the filesystem.
827  */
828 struct unlink_args {
829 	char	*path;
830 };
831 /* ARGSUSED */
832 unlink(p, uap, retval)
833 	struct proc *p;
834 	struct unlink_args *uap;
835 	int *retval;
836 {
837 	register struct vnode *vp;
838 	int error;
839 	struct nameidata nd;
840 
841 	NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
842 	if (error = namei(&nd))
843 		return (error);
844 	vp = nd.ni_vp;
845 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
846 	VOP_LOCK(vp);
847 	if (vp->v_type == VDIR &&
848 	    (error = suser(p->p_ucred, &p->p_acflag)))
849 		goto out;
850 	/*
851 	 * The root of a mounted filesystem cannot be deleted.
852 	 */
853 	if (vp->v_flag & VROOT)
854 		error = EBUSY;
855 	else
856 		(void)vnode_pager_uncache(vp);
857 
858 out:	if (!error) {
859 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
860 		error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
861 	} else {
862 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
863 		if (nd.ni_dvp == vp)
864 			vrele(nd.ni_dvp);
865 		else
866 			vput(nd.ni_dvp);
867 		vput(vp);
868 	}
869 	return (error);
870 }
871 
872 /*
873  * Reposition read/write file offset.
874  */
875 struct lseek_args {
876 	int	fd;
877 	int	pad;
878 	off_t	offset;
879 	int	whence;
880 };
881 lseek(p, uap, retval)
882 	struct proc *p;
883 	register struct lseek_args *uap;
884 	int *retval;
885 {
886 	struct ucred *cred = p->p_ucred;
887 	register struct filedesc *fdp = p->p_fd;
888 	register struct file *fp;
889 	struct vattr vattr;
890 	int error;
891 
892 	if ((u_int)uap->fd >= fdp->fd_nfiles ||
893 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
894 		return (EBADF);
895 	if (fp->f_type != DTYPE_VNODE)
896 		return (ESPIPE);
897 	switch (uap->whence) {
898 	case L_INCR:
899 		fp->f_offset += uap->offset;
900 		break;
901 	case L_XTND:
902 		if (error =
903 		    VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p))
904 			return (error);
905 		fp->f_offset = uap->offset + vattr.va_size;
906 		break;
907 	case L_SET:
908 		fp->f_offset = uap->offset;
909 		break;
910 	default:
911 		return (EINVAL);
912 	}
913 	*(off_t *)retval = fp->f_offset;
914 	return (0);
915 }
916 
917 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
918 /*
919  * Reposition read/write file offset.
920  */
921 struct olseek_args {
922 	int	fd;
923 	long	offset;
924 	int	whence;
925 };
926 olseek(p, uap, retval)
927 	struct proc *p;
928 	register struct olseek_args *uap;
929 	int *retval;
930 {
931 	struct lseek_args nuap;
932 	off_t qret;
933 	int error;
934 
935 	nuap.fd = uap->fd;
936 	nuap.offset = uap->offset;
937 	nuap.whence = uap->whence;
938 	error = lseek(p, &nuap, &qret);
939 	*(long *)retval = qret;
940 	return (error);
941 }
942 #endif /* COMPAT_43 */
943 
944 /*
945  * Check access permissions.
946  */
947 struct access_args {
948 	char	*path;
949 	int	flags;
950 };
951 access(p, uap, retval)
952 	struct proc *p;
953 	register struct access_args *uap;
954 	int *retval;
955 {
956 	register struct ucred *cred = p->p_ucred;
957 	register struct vnode *vp;
958 	int error, flags, saved_uid, saved_gid;
959 	struct nameidata nd;
960 
961 	saved_uid = cred->cr_uid;
962 	saved_gid = cred->cr_groups[0];
963 	cred->cr_uid = p->p_cred->p_ruid;
964 	cred->cr_groups[0] = p->p_cred->p_rgid;
965 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
966 	if (error = namei(&nd))
967 		goto out1;
968 	vp = nd.ni_vp;
969 
970 	/* Flags == 0 means only check for existence. */
971 	if (uap->flags) {
972 		flags = 0;
973 		if (uap->flags & R_OK)
974 			flags |= VREAD;
975 		if (uap->flags & W_OK)
976 			flags |= VWRITE;
977 		if (uap->flags & X_OK)
978 			flags |= VEXEC;
979 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
980 			error = VOP_ACCESS(vp, flags, cred, p);
981 	}
982 	vput(vp);
983 out1:
984 	cred->cr_uid = saved_uid;
985 	cred->cr_groups[0] = saved_gid;
986 	return (error);
987 }
988 
989 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
990 /*
991  * Get file status; this version follows links.
992  */
993 struct ostat_args {
994 	char	*path;
995 	struct ostat *ub;
996 };
997 /* ARGSUSED */
998 ostat(p, uap, retval)
999 	struct proc *p;
1000 	register struct ostat_args *uap;
1001 	int *retval;
1002 {
1003 	struct stat sb;
1004 	struct ostat osb;
1005 	int error;
1006 	struct nameidata nd;
1007 
1008 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1009 	if (error = namei(&nd))
1010 		return (error);
1011 	error = vn_stat(nd.ni_vp, &sb, p);
1012 	vput(nd.ni_vp);
1013 	if (error)
1014 		return (error);
1015 	cvtstat(&sb, &osb);
1016 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1017 	return (error);
1018 }
1019 
1020 /*
1021  * Get file status; this version does not follow links.
1022  */
1023 struct olstat_args {
1024 	char	*path;
1025 	struct ostat *ub;
1026 };
1027 /* ARGSUSED */
1028 olstat(p, uap, retval)
1029 	struct proc *p;
1030 	register struct olstat_args *uap;
1031 	int *retval;
1032 {
1033 	struct stat sb;
1034 	struct ostat osb;
1035 	int error;
1036 	struct nameidata nd;
1037 
1038 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1039 	if (error = namei(&nd))
1040 		return (error);
1041 	error = vn_stat(nd.ni_vp, &sb, p);
1042 	vput(nd.ni_vp);
1043 	if (error)
1044 		return (error);
1045 	cvtstat(&sb, &osb);
1046 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1047 	return (error);
1048 }
1049 
1050 /*
1051  * Convert from an old to a new stat structure.
1052  */
1053 cvtstat(st, ost)
1054 	struct stat *st;
1055 	struct ostat *ost;
1056 {
1057 
1058 	ost->st_dev = st->st_dev;
1059 	ost->st_ino = st->st_ino;
1060 	ost->st_mode = st->st_mode;
1061 	ost->st_nlink = st->st_nlink;
1062 	ost->st_uid = st->st_uid;
1063 	ost->st_gid = st->st_gid;
1064 	ost->st_rdev = st->st_rdev;
1065 	if (st->st_size < (quad_t)1 << 32)
1066 		ost->st_size = st->st_size;
1067 	else
1068 		ost->st_size = -2;
1069 	ost->st_atime = st->st_atime;
1070 	ost->st_mtime = st->st_mtime;
1071 	ost->st_ctime = st->st_ctime;
1072 	ost->st_blksize = st->st_blksize;
1073 	ost->st_blocks = st->st_blocks;
1074 	ost->st_flags = st->st_flags;
1075 	ost->st_gen = st->st_gen;
1076 }
1077 #endif /* COMPAT_43 || COMPAT_SUNOS */
1078 
1079 /*
1080  * Get file status; this version follows links.
1081  */
1082 struct stat_args {
1083 	char	*path;
1084 	struct stat *ub;
1085 };
1086 /* ARGSUSED */
1087 stat(p, uap, retval)
1088 	struct proc *p;
1089 	register struct stat_args *uap;
1090 	int *retval;
1091 {
1092 	struct stat sb;
1093 	int error;
1094 	struct nameidata nd;
1095 
1096 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1097 	if (error = namei(&nd))
1098 		return (error);
1099 	error = vn_stat(nd.ni_vp, &sb, p);
1100 	vput(nd.ni_vp);
1101 	if (error)
1102 		return (error);
1103 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1104 	return (error);
1105 }
1106 
1107 /*
1108  * Get file status; this version does not follow links.
1109  */
1110 struct lstat_args {
1111 	char	*path;
1112 	struct stat *ub;
1113 };
1114 /* ARGSUSED */
1115 lstat(p, uap, retval)
1116 	struct proc *p;
1117 	register struct lstat_args *uap;
1118 	int *retval;
1119 {
1120 	int error;
1121 	struct vnode *vp, *dvp;
1122 	struct stat sb, sb1;
1123 	struct nameidata nd;
1124 
1125 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1126 	    uap->path, p);
1127 	if (error = namei(&nd))
1128 		return (error);
1129 	/*
1130 	 * For symbolic links, always return the attributes of its
1131 	 * containing directory, except for mode, size, and links.
1132 	 */
1133 	vp = nd.ni_vp;
1134 	dvp = nd.ni_dvp;
1135 	if (vp->v_type != VLNK) {
1136 		if (dvp == vp)
1137 			vrele(dvp);
1138 		else
1139 			vput(dvp);
1140 		error = vn_stat(vp, &sb, p);
1141 		vput(vp);
1142 		if (error)
1143 			return (error);
1144 	} else {
1145 		error = vn_stat(dvp, &sb, p);
1146 		vput(dvp);
1147 		if (error) {
1148 			vput(vp);
1149 			return (error);
1150 		}
1151 		error = vn_stat(vp, &sb1, p);
1152 		vput(vp);
1153 		if (error)
1154 			return (error);
1155 		sb.st_mode &= ~S_IFDIR;
1156 		sb.st_mode |= S_IFLNK;
1157 		sb.st_nlink = sb1.st_nlink;
1158 		sb.st_size = sb1.st_size;
1159 		sb.st_blocks = sb1.st_blocks;
1160 	}
1161 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1162 	return (error);
1163 }
1164 
1165 /*
1166  * Get configurable pathname variables.
1167  */
1168 struct pathconf_args {
1169 	char	*path;
1170 	int	name;
1171 };
1172 /* ARGSUSED */
1173 pathconf(p, uap, retval)
1174 	struct proc *p;
1175 	register struct pathconf_args *uap;
1176 	int *retval;
1177 {
1178 	int error;
1179 	struct nameidata nd;
1180 
1181 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1182 	if (error = namei(&nd))
1183 		return (error);
1184 	error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
1185 	vput(nd.ni_vp);
1186 	return (error);
1187 }
1188 
1189 /*
1190  * Return target name of a symbolic link.
1191  */
1192 struct readlink_args {
1193 	char	*path;
1194 	char	*buf;
1195 	int	count;
1196 };
1197 /* ARGSUSED */
1198 readlink(p, uap, retval)
1199 	struct proc *p;
1200 	register struct readlink_args *uap;
1201 	int *retval;
1202 {
1203 	register struct vnode *vp;
1204 	struct iovec aiov;
1205 	struct uio auio;
1206 	int error;
1207 	struct nameidata nd;
1208 
1209 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1210 	if (error = namei(&nd))
1211 		return (error);
1212 	vp = nd.ni_vp;
1213 	if (vp->v_type != VLNK)
1214 		error = EINVAL;
1215 	else {
1216 		aiov.iov_base = uap->buf;
1217 		aiov.iov_len = uap->count;
1218 		auio.uio_iov = &aiov;
1219 		auio.uio_iovcnt = 1;
1220 		auio.uio_offset = 0;
1221 		auio.uio_rw = UIO_READ;
1222 		auio.uio_segflg = UIO_USERSPACE;
1223 		auio.uio_procp = p;
1224 		auio.uio_resid = uap->count;
1225 		error = VOP_READLINK(vp, &auio, p->p_ucred);
1226 	}
1227 	vput(vp);
1228 	*retval = uap->count - auio.uio_resid;
1229 	return (error);
1230 }
1231 
1232 /*
1233  * Change flags of a file given a path name.
1234  */
1235 struct chflags_args {
1236 	char	*path;
1237 	int	flags;
1238 };
1239 /* ARGSUSED */
1240 chflags(p, uap, retval)
1241 	struct proc *p;
1242 	register struct chflags_args *uap;
1243 	int *retval;
1244 {
1245 	register struct vnode *vp;
1246 	struct vattr vattr;
1247 	int error;
1248 	struct nameidata nd;
1249 
1250 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1251 	if (error = namei(&nd))
1252 		return (error);
1253 	vp = nd.ni_vp;
1254 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1255 	VOP_LOCK(vp);
1256 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1257 		error = EROFS;
1258 	else {
1259 		VATTR_NULL(&vattr);
1260 		vattr.va_flags = uap->flags;
1261 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1262 	}
1263 	vput(vp);
1264 	return (error);
1265 }
1266 
1267 /*
1268  * Change flags of a file given a file descriptor.
1269  */
1270 struct fchflags_args {
1271 	int	fd;
1272 	int	flags;
1273 };
1274 /* ARGSUSED */
1275 fchflags(p, uap, retval)
1276 	struct proc *p;
1277 	register struct fchflags_args *uap;
1278 	int *retval;
1279 {
1280 	struct vattr vattr;
1281 	struct vnode *vp;
1282 	struct file *fp;
1283 	int error;
1284 
1285 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1286 		return (error);
1287 	vp = (struct vnode *)fp->f_data;
1288 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1289 	VOP_LOCK(vp);
1290 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1291 		error = EROFS;
1292 	else {
1293 		VATTR_NULL(&vattr);
1294 		vattr.va_flags = uap->flags;
1295 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1296 	}
1297 	VOP_UNLOCK(vp);
1298 	return (error);
1299 }
1300 
1301 /*
1302  * Change mode of a file given path name.
1303  */
1304 struct chmod_args {
1305 	char	*path;
1306 	int	mode;
1307 };
1308 /* ARGSUSED */
1309 chmod(p, uap, retval)
1310 	struct proc *p;
1311 	register struct chmod_args *uap;
1312 	int *retval;
1313 {
1314 	register struct vnode *vp;
1315 	struct vattr vattr;
1316 	int error;
1317 	struct nameidata nd;
1318 
1319 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1320 	if (error = namei(&nd))
1321 		return (error);
1322 	vp = nd.ni_vp;
1323 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1324 	VOP_LOCK(vp);
1325 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1326 		error = EROFS;
1327 	else {
1328 		VATTR_NULL(&vattr);
1329 		vattr.va_mode = uap->mode & ALLPERMS;
1330 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1331 	}
1332 	vput(vp);
1333 	return (error);
1334 }
1335 
1336 /*
1337  * Change mode of a file given a file descriptor.
1338  */
1339 struct fchmod_args {
1340 	int	fd;
1341 	int	mode;
1342 };
1343 /* ARGSUSED */
1344 fchmod(p, uap, retval)
1345 	struct proc *p;
1346 	register struct fchmod_args *uap;
1347 	int *retval;
1348 {
1349 	struct vattr vattr;
1350 	struct vnode *vp;
1351 	struct file *fp;
1352 	int error;
1353 
1354 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1355 		return (error);
1356 	vp = (struct vnode *)fp->f_data;
1357 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1358 	VOP_LOCK(vp);
1359 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1360 		error = EROFS;
1361 	else {
1362 		VATTR_NULL(&vattr);
1363 		vattr.va_mode = uap->mode & ALLPERMS;
1364 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1365 	}
1366 	VOP_UNLOCK(vp);
1367 	return (error);
1368 }
1369 
1370 /*
1371  * Set ownership given a path name.
1372  */
1373 struct chown_args {
1374 	char	*path;
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->path, 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 	else {
1398 		VATTR_NULL(&vattr);
1399 		vattr.va_uid = uap->uid;
1400 		vattr.va_gid = uap->gid;
1401 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1402 	}
1403 	vput(vp);
1404 	return (error);
1405 }
1406 
1407 /*
1408  * Set ownership given a file descriptor.
1409  */
1410 struct fchown_args {
1411 	int	fd;
1412 	int	uid;
1413 	int	gid;
1414 };
1415 /* ARGSUSED */
1416 fchown(p, uap, retval)
1417 	struct proc *p;
1418 	register struct fchown_args *uap;
1419 	int *retval;
1420 {
1421 	struct vattr vattr;
1422 	struct vnode *vp;
1423 	struct file *fp;
1424 	int error;
1425 
1426 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1427 		return (error);
1428 	vp = (struct vnode *)fp->f_data;
1429 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1430 	VOP_LOCK(vp);
1431 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1432 		error = EROFS;
1433 	else {
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 	}
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	*path;
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->path, 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 	else {
1478 		vattr.va_atime.ts_sec = tv[0].tv_sec;
1479 		vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1480 		vattr.va_mtime.ts_sec = tv[1].tv_sec;
1481 		vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
1482 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1483 	}
1484 	vput(vp);
1485 	return (error);
1486 }
1487 
1488 /*
1489  * Truncate a file given its path name.
1490  */
1491 struct truncate_args {
1492 	char	*path;
1493 	int	pad;
1494 	off_t	length;
1495 };
1496 /* ARGSUSED */
1497 truncate(p, uap, retval)
1498 	struct proc *p;
1499 	register struct truncate_args *uap;
1500 	int *retval;
1501 {
1502 	register struct vnode *vp;
1503 	struct vattr vattr;
1504 	int error;
1505 	struct nameidata nd;
1506 
1507 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1508 	if (error = namei(&nd))
1509 		return (error);
1510 	vp = nd.ni_vp;
1511 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1512 	VOP_LOCK(vp);
1513 	if (vp->v_type == VDIR)
1514 		error = EISDIR;
1515 	else if ((error = vn_writechk(vp)) == 0 &&
1516 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
1517 		VATTR_NULL(&vattr);
1518 		vattr.va_size = uap->length;
1519 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1520 	}
1521 	vput(vp);
1522 	return (error);
1523 }
1524 
1525 /*
1526  * Truncate a file given a file descriptor.
1527  */
1528 struct ftruncate_args {
1529 	int	fd;
1530 	int	pad;
1531 	off_t	length;
1532 };
1533 /* ARGSUSED */
1534 ftruncate(p, uap, retval)
1535 	struct proc *p;
1536 	register struct ftruncate_args *uap;
1537 	int *retval;
1538 {
1539 	struct vattr vattr;
1540 	struct vnode *vp;
1541 	struct file *fp;
1542 	int error;
1543 
1544 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1545 		return (error);
1546 	if ((fp->f_flag & FWRITE) == 0)
1547 		return (EINVAL);
1548 	vp = (struct vnode *)fp->f_data;
1549 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1550 	VOP_LOCK(vp);
1551 	if (vp->v_type == VDIR)
1552 		error = EISDIR;
1553 	else if ((error = vn_writechk(vp)) == 0) {
1554 		VATTR_NULL(&vattr);
1555 		vattr.va_size = uap->length;
1556 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1557 	}
1558 	VOP_UNLOCK(vp);
1559 	return (error);
1560 }
1561 
1562 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1563 /*
1564  * Truncate a file given its path name.
1565  */
1566 struct otruncate_args {
1567 	char	*path;
1568 	long	length;
1569 };
1570 /* ARGSUSED */
1571 otruncate(p, uap, retval)
1572 	struct proc *p;
1573 	register struct otruncate_args *uap;
1574 	int *retval;
1575 {
1576 	struct truncate_args nuap;
1577 
1578 	nuap.path = uap->path;
1579 	nuap.length = uap->length;
1580 	return (truncate(p, &nuap, retval));
1581 }
1582 
1583 /*
1584  * Truncate a file given a file descriptor.
1585  */
1586 struct oftruncate_args {
1587 	int	fd;
1588 	long	length;
1589 };
1590 /* ARGSUSED */
1591 oftruncate(p, uap, retval)
1592 	struct proc *p;
1593 	register struct oftruncate_args *uap;
1594 	int *retval;
1595 {
1596 	struct ftruncate_args nuap;
1597 
1598 	nuap.fd = uap->fd;
1599 	nuap.length = uap->length;
1600 	return (ftruncate(p, &nuap, retval));
1601 }
1602 #endif /* COMPAT_43 || COMPAT_SUNOS */
1603 
1604 /*
1605  * Sync an open file.
1606  */
1607 struct fsync_args {
1608 	int	fd;
1609 };
1610 /* ARGSUSED */
1611 fsync(p, uap, retval)
1612 	struct proc *p;
1613 	struct fsync_args *uap;
1614 	int *retval;
1615 {
1616 	register struct vnode *vp;
1617 	struct file *fp;
1618 	int error;
1619 
1620 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1621 		return (error);
1622 	vp = (struct vnode *)fp->f_data;
1623 	VOP_LOCK(vp);
1624 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
1625 	VOP_UNLOCK(vp);
1626 	return (error);
1627 }
1628 
1629 /*
1630  * Rename files.  Source and destination must either both be directories,
1631  * or both not be directories.  If target is a directory, it must be empty.
1632  */
1633 struct rename_args {
1634 	char	*from;
1635 	char	*to;
1636 };
1637 /* ARGSUSED */
1638 rename(p, uap, retval)
1639 	struct proc *p;
1640 	register struct rename_args *uap;
1641 	int *retval;
1642 {
1643 	register struct vnode *tvp, *fvp, *tdvp;
1644 	struct nameidata fromnd, tond;
1645 	int error;
1646 
1647 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1648 		uap->from, p);
1649 	if (error = namei(&fromnd))
1650 		return (error);
1651 	fvp = fromnd.ni_vp;
1652 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1653 		UIO_USERSPACE, uap->to, p);
1654 	if (error = namei(&tond)) {
1655 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1656 		vrele(fromnd.ni_dvp);
1657 		vrele(fvp);
1658 		goto out1;
1659 	}
1660 	tdvp = tond.ni_dvp;
1661 	tvp = tond.ni_vp;
1662 	if (tvp != NULL) {
1663 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1664 			error = ENOTDIR;
1665 			goto out;
1666 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1667 			error = EISDIR;
1668 			goto out;
1669 		}
1670 	}
1671 	if (fvp == tdvp)
1672 		error = EINVAL;
1673 	/*
1674 	 * If source is the same as the destination (that is the
1675 	 * same inode number with the same name in the same directory),
1676 	 * then there is nothing to do.
1677 	 */
1678 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1679 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1680 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1681 	      fromnd.ni_cnd.cn_namelen))
1682 		error = -1;
1683 out:
1684 	if (!error) {
1685 		LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
1686 		if (fromnd.ni_dvp != tdvp)
1687 			LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1688 		if (tvp)
1689 			LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
1690 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1691 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1692 	} else {
1693 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1694 		if (tdvp == tvp)
1695 			vrele(tdvp);
1696 		else
1697 			vput(tdvp);
1698 		if (tvp)
1699 			vput(tvp);
1700 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1701 		vrele(fromnd.ni_dvp);
1702 		vrele(fvp);
1703 	}
1704 	vrele(tond.ni_startdir);
1705 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1706 out1:
1707 	vrele(fromnd.ni_startdir);
1708 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1709 	if (error == -1)
1710 		return (0);
1711 	return (error);
1712 }
1713 
1714 /*
1715  * Make a directory file.
1716  */
1717 struct mkdir_args {
1718 	char	*path;
1719 	int	mode;
1720 };
1721 /* ARGSUSED */
1722 mkdir(p, uap, retval)
1723 	struct proc *p;
1724 	register struct mkdir_args *uap;
1725 	int *retval;
1726 {
1727 	register struct vnode *vp;
1728 	struct vattr vattr;
1729 	int error;
1730 	struct nameidata nd;
1731 
1732 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
1733 	if (error = namei(&nd))
1734 		return (error);
1735 	vp = nd.ni_vp;
1736 	if (vp != NULL) {
1737 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1738 		if (nd.ni_dvp == vp)
1739 			vrele(nd.ni_dvp);
1740 		else
1741 			vput(nd.ni_dvp);
1742 		vrele(vp);
1743 		return (EEXIST);
1744 	}
1745 	VATTR_NULL(&vattr);
1746 	vattr.va_type = VDIR;
1747 	vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
1748 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1749 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1750 	if (!error)
1751 		vput(nd.ni_vp);
1752 	return (error);
1753 }
1754 
1755 /*
1756  * Remove a directory file.
1757  */
1758 struct rmdir_args {
1759 	char	*path;
1760 };
1761 /* ARGSUSED */
1762 rmdir(p, uap, retval)
1763 	struct proc *p;
1764 	struct rmdir_args *uap;
1765 	int *retval;
1766 {
1767 	register struct vnode *vp;
1768 	int error;
1769 	struct nameidata nd;
1770 
1771 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1772 	if (error = namei(&nd))
1773 		return (error);
1774 	vp = nd.ni_vp;
1775 	if (vp->v_type != VDIR) {
1776 		error = ENOTDIR;
1777 		goto out;
1778 	}
1779 	/*
1780 	 * No rmdir "." please.
1781 	 */
1782 	if (nd.ni_dvp == vp) {
1783 		error = EINVAL;
1784 		goto out;
1785 	}
1786 	/*
1787 	 * The root of a mounted filesystem cannot be deleted.
1788 	 */
1789 	if (vp->v_flag & VROOT)
1790 		error = EBUSY;
1791 out:
1792 	if (!error) {
1793 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1794 		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1795 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1796 	} else {
1797 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1798 		if (nd.ni_dvp == vp)
1799 			vrele(nd.ni_dvp);
1800 		else
1801 			vput(nd.ni_dvp);
1802 		vput(vp);
1803 	}
1804 	return (error);
1805 }
1806 
1807 #ifdef COMPAT_43
1808 /*
1809  * Read a block of directory entries in a file system independent format.
1810  */
1811 struct ogetdirentries_args {
1812 	int	fd;
1813 	char	*buf;
1814 	u_int	count;
1815 	long	*basep;
1816 };
1817 ogetdirentries(p, uap, retval)
1818 	struct proc *p;
1819 	register struct ogetdirentries_args *uap;
1820 	int *retval;
1821 {
1822 	register struct vnode *vp;
1823 	struct file *fp;
1824 	struct uio auio, kuio;
1825 	struct iovec aiov, kiov;
1826 	struct dirent *dp, *edp;
1827 	caddr_t dirbuf;
1828 	int error, readcnt;
1829 	long loff;
1830 
1831 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1832 		return (error);
1833 	if ((fp->f_flag & FREAD) == 0)
1834 		return (EBADF);
1835 	vp = (struct vnode *)fp->f_data;
1836 	if (vp->v_type != VDIR)
1837 		return (EINVAL);
1838 	aiov.iov_base = uap->buf;
1839 	aiov.iov_len = uap->count;
1840 	auio.uio_iov = &aiov;
1841 	auio.uio_iovcnt = 1;
1842 	auio.uio_rw = UIO_READ;
1843 	auio.uio_segflg = UIO_USERSPACE;
1844 	auio.uio_procp = p;
1845 	auio.uio_resid = uap->count;
1846 	VOP_LOCK(vp);
1847 	loff = auio.uio_offset = fp->f_offset;
1848 #	if (BYTE_ORDER != LITTLE_ENDIAN)
1849 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
1850 			error = VOP_READDIR(vp, &auio, fp->f_cred);
1851 			fp->f_offset = auio.uio_offset;
1852 		} else
1853 #	endif
1854 	{
1855 		kuio = auio;
1856 		kuio.uio_iov = &kiov;
1857 		kuio.uio_segflg = UIO_SYSSPACE;
1858 		kiov.iov_len = uap->count;
1859 		MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
1860 		kiov.iov_base = dirbuf;
1861 		error = VOP_READDIR(vp, &kuio, fp->f_cred);
1862 		fp->f_offset = kuio.uio_offset;
1863 		if (error == 0) {
1864 			readcnt = uap->count - kuio.uio_resid;
1865 			edp = (struct dirent *)&dirbuf[readcnt];
1866 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1867 #				if (BYTE_ORDER == LITTLE_ENDIAN)
1868 					/*
1869 					 * The expected low byte of
1870 					 * dp->d_namlen is our dp->d_type.
1871 					 * The high MBZ byte of dp->d_namlen
1872 					 * is our dp->d_namlen.
1873 					 */
1874 					dp->d_type = dp->d_namlen;
1875 					dp->d_namlen = 0;
1876 #				else
1877 					/*
1878 					 * The dp->d_type is the high byte
1879 					 * of the expected dp->d_namlen,
1880 					 * so must be zero'ed.
1881 					 */
1882 					dp->d_type = 0;
1883 #				endif
1884 				if (dp->d_reclen > 0) {
1885 					dp = (struct dirent *)
1886 					    ((char *)dp + dp->d_reclen);
1887 				} else {
1888 					error = EIO;
1889 					break;
1890 				}
1891 			}
1892 			if (dp >= edp)
1893 				error = uiomove(dirbuf, readcnt, &auio);
1894 		}
1895 		FREE(dirbuf, M_TEMP);
1896 	}
1897 	VOP_UNLOCK(vp);
1898 	if (error)
1899 		return (error);
1900 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
1901 	*retval = uap->count - auio.uio_resid;
1902 	return (error);
1903 }
1904 #endif
1905 
1906 /*
1907  * Read a block of directory entries in a file system independent format.
1908  */
1909 struct getdirentries_args {
1910 	int	fd;
1911 	char	*buf;
1912 	u_int	count;
1913 	long	*basep;
1914 };
1915 getdirentries(p, uap, retval)
1916 	struct proc *p;
1917 	register struct getdirentries_args *uap;
1918 	int *retval;
1919 {
1920 	register struct vnode *vp;
1921 	struct file *fp;
1922 	struct uio auio;
1923 	struct iovec aiov;
1924 	long loff;
1925 	int error;
1926 
1927 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1928 		return (error);
1929 	if ((fp->f_flag & FREAD) == 0)
1930 		return (EBADF);
1931 	vp = (struct vnode *)fp->f_data;
1932 unionread:
1933 	if (vp->v_type != VDIR)
1934 		return (EINVAL);
1935 	aiov.iov_base = uap->buf;
1936 	aiov.iov_len = uap->count;
1937 	auio.uio_iov = &aiov;
1938 	auio.uio_iovcnt = 1;
1939 	auio.uio_rw = UIO_READ;
1940 	auio.uio_segflg = UIO_USERSPACE;
1941 	auio.uio_procp = p;
1942 	auio.uio_resid = uap->count;
1943 	VOP_LOCK(vp);
1944 	loff = auio.uio_offset = fp->f_offset;
1945 	error = VOP_READDIR(vp, &auio, fp->f_cred);
1946 	fp->f_offset = auio.uio_offset;
1947 	VOP_UNLOCK(vp);
1948 	if (error)
1949 		return (error);
1950 	if ((uap->count == auio.uio_resid) &&
1951 	    (vp->v_flag & VROOT) &&
1952 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
1953 		struct vnode *tvp = vp;
1954 		vp = vp->v_mount->mnt_vnodecovered;
1955 		VREF(vp);
1956 		fp->f_data = (caddr_t) vp;
1957 		fp->f_offset = 0;
1958 		vrele(tvp);
1959 		goto unionread;
1960 	}
1961 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
1962 	*retval = uap->count - auio.uio_resid;
1963 	return (error);
1964 }
1965 
1966 /*
1967  * Set the mode mask for creation of filesystem nodes.
1968  */
1969 struct umask_args {
1970 	int	newmask;
1971 };
1972 mode_t				/* XXX */
1973 umask(p, uap, retval)
1974 	struct proc *p;
1975 	struct umask_args *uap;
1976 	int *retval;
1977 {
1978 	register struct filedesc *fdp;
1979 
1980 	fdp = p->p_fd;
1981 	*retval = fdp->fd_cmask;
1982 	fdp->fd_cmask = uap->newmask & ALLPERMS;
1983 	return (0);
1984 }
1985 
1986 /*
1987  * Void all references to file by ripping underlying filesystem
1988  * away from vnode.
1989  */
1990 struct revoke_args {
1991 	char	*path;
1992 };
1993 /* ARGSUSED */
1994 revoke(p, uap, retval)
1995 	struct proc *p;
1996 	register struct revoke_args *uap;
1997 	int *retval;
1998 {
1999 	register struct vnode *vp;
2000 	struct vattr vattr;
2001 	int error;
2002 	struct nameidata nd;
2003 
2004 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
2005 	if (error = namei(&nd))
2006 		return (error);
2007 	vp = nd.ni_vp;
2008 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
2009 		error = EINVAL;
2010 		goto out;
2011 	}
2012 	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2013 		goto out;
2014 	if (p->p_ucred->cr_uid != vattr.va_uid &&
2015 	    (error = suser(p->p_ucred, &p->p_acflag)))
2016 		goto out;
2017 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2018 		vgoneall(vp);
2019 out:
2020 	vrele(vp);
2021 	return (error);
2022 }
2023 
2024 /*
2025  * Convert a user file descriptor to a kernel file entry.
2026  */
2027 getvnode(fdp, fd, fpp)
2028 	struct filedesc *fdp;
2029 	struct file **fpp;
2030 	int fd;
2031 {
2032 	struct file *fp;
2033 
2034 	if ((u_int)fd >= fdp->fd_nfiles ||
2035 	    (fp = fdp->fd_ofiles[fd]) == NULL)
2036 		return (EBADF);
2037 	if (fp->f_type != DTYPE_VNODE)
2038 		return (EINVAL);
2039 	*fpp = fp;
2040 	return (0);
2041 }
2042