xref: /original-bsd/sys/kern/vfs_syscalls.c (revision edc2ab72)
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.3 (Berkeley) 09/23/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 	else {
660 		VATTR_NULL(&vattr);
661 		vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
662 		vattr.va_rdev = uap->dev;
663 
664 		switch (uap->mode & S_IFMT) {
665 		case S_IFMT:	/* used by badsect to flag bad sectors */
666 			vattr.va_type = VBAD;
667 			break;
668 		case S_IFCHR:
669 			vattr.va_type = VCHR;
670 			break;
671 		case S_IFBLK:
672 			vattr.va_type = VBLK;
673 			break;
674 		default:
675 			error = EINVAL;
676 			break;
677 		}
678 	}
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)) == 0) {
757 		nd.ni_cnd.cn_nameiop = CREATE;
758 		nd.ni_cnd.cn_flags = LOCKPARENT;
759 		nd.ni_dirp = uap->link;
760 		if ((error = namei(&nd)) == 0) {
761 			if (nd.ni_vp != NULL)
762 				error = EEXIST;
763 			if (!error) {
764 				LEASE_CHECK(nd.ni_dvp,
765 				    p, p->p_ucred, LEASE_WRITE);
766 				LEASE_CHECK(vp,
767 				    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 		}
779 	}
780 	vrele(vp);
781 	return (error);
782 }
783 
784 /*
785  * Make a symbolic link.
786  */
787 struct symlink_args {
788 	char	*path;
789 	char	*link;
790 };
791 /* ARGSUSED */
792 symlink(p, uap, retval)
793 	struct proc *p;
794 	register struct symlink_args *uap;
795 	int *retval;
796 {
797 	struct vattr vattr;
798 	char *path;
799 	int error;
800 	struct nameidata nd;
801 
802 	MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
803 	if (error = copyinstr(uap->path, path, MAXPATHLEN, NULL))
804 		goto out;
805 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
806 	if (error = namei(&nd))
807 		goto out;
808 	if (nd.ni_vp) {
809 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
810 		if (nd.ni_dvp == nd.ni_vp)
811 			vrele(nd.ni_dvp);
812 		else
813 			vput(nd.ni_dvp);
814 		vrele(nd.ni_vp);
815 		error = EEXIST;
816 		goto out;
817 	}
818 	VATTR_NULL(&vattr);
819 	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
820 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
821 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
822 out:
823 	FREE(path, M_NAMEI);
824 	return (error);
825 }
826 
827 /*
828  * Delete a name from the filesystem.
829  */
830 struct unlink_args {
831 	char	*path;
832 };
833 /* ARGSUSED */
834 unlink(p, uap, retval)
835 	struct proc *p;
836 	struct unlink_args *uap;
837 	int *retval;
838 {
839 	register struct vnode *vp;
840 	int error;
841 	struct nameidata nd;
842 
843 	NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
844 	if (error = namei(&nd))
845 		return (error);
846 	vp = nd.ni_vp;
847 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
848 	VOP_LOCK(vp);
849 
850 	if (vp->v_type != VDIR ||
851 	    (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
852 		/*
853 		 * The root of a mounted filesystem cannot be deleted.
854 		 */
855 		if (vp->v_flag & VROOT)
856 			error = EBUSY;
857 		else
858 			(void)vnode_pager_uncache(vp);
859 	}
860 
861 	if (!error) {
862 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
863 		error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
864 	} else {
865 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
866 		if (nd.ni_dvp == vp)
867 			vrele(nd.ni_dvp);
868 		else
869 			vput(nd.ni_dvp);
870 		vput(vp);
871 	}
872 	return (error);
873 }
874 
875 /*
876  * Reposition read/write file offset.
877  */
878 struct lseek_args {
879 	int	fd;
880 	int	pad;
881 	off_t	offset;
882 	int	whence;
883 };
884 lseek(p, uap, retval)
885 	struct proc *p;
886 	register struct lseek_args *uap;
887 	int *retval;
888 {
889 	struct ucred *cred = p->p_ucred;
890 	register struct filedesc *fdp = p->p_fd;
891 	register struct file *fp;
892 	struct vattr vattr;
893 	int error;
894 
895 	if ((u_int)uap->fd >= fdp->fd_nfiles ||
896 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
897 		return (EBADF);
898 	if (fp->f_type != DTYPE_VNODE)
899 		return (ESPIPE);
900 	switch (uap->whence) {
901 	case L_INCR:
902 		fp->f_offset += uap->offset;
903 		break;
904 	case L_XTND:
905 		if (error =
906 		    VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p))
907 			return (error);
908 		fp->f_offset = uap->offset + vattr.va_size;
909 		break;
910 	case L_SET:
911 		fp->f_offset = uap->offset;
912 		break;
913 	default:
914 		return (EINVAL);
915 	}
916 	*(off_t *)retval = fp->f_offset;
917 	return (0);
918 }
919 
920 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
921 /*
922  * Reposition read/write file offset.
923  */
924 struct olseek_args {
925 	int	fd;
926 	long	offset;
927 	int	whence;
928 };
929 olseek(p, uap, retval)
930 	struct proc *p;
931 	register struct olseek_args *uap;
932 	int *retval;
933 {
934 	struct lseek_args nuap;
935 	off_t qret;
936 	int error;
937 
938 	nuap.fd = uap->fd;
939 	nuap.offset = uap->offset;
940 	nuap.whence = uap->whence;
941 	error = lseek(p, &nuap, &qret);
942 	*(long *)retval = qret;
943 	return (error);
944 }
945 #endif /* COMPAT_43 */
946 
947 /*
948  * Check access permissions.
949  */
950 struct access_args {
951 	char	*path;
952 	int	flags;
953 };
954 access(p, uap, retval)
955 	struct proc *p;
956 	register struct access_args *uap;
957 	int *retval;
958 {
959 	register struct ucred *cred = p->p_ucred;
960 	register struct vnode *vp;
961 	int error, flags, t_gid, t_uid;
962 	struct nameidata nd;
963 
964 	t_uid = cred->cr_uid;
965 	t_gid = cred->cr_groups[0];
966 	cred->cr_uid = p->p_cred->p_ruid;
967 	cred->cr_groups[0] = p->p_cred->p_rgid;
968 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
969 	if (error = namei(&nd))
970 		goto out1;
971 	vp = nd.ni_vp;
972 
973 	/* Flags == 0 means only check for existence. */
974 	if (uap->flags) {
975 		flags = 0;
976 		if (uap->flags & R_OK)
977 			flags |= VREAD;
978 		if (uap->flags & W_OK)
979 			flags |= VWRITE;
980 		if (uap->flags & X_OK)
981 			flags |= VEXEC;
982 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
983 			error = VOP_ACCESS(vp, flags, cred, p);
984 	}
985 	vput(vp);
986 out1:
987 	cred->cr_uid = t_uid;
988 	cred->cr_groups[0] = t_gid;
989 	return (error);
990 }
991 
992 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
993 /*
994  * Get file status; this version follows links.
995  */
996 struct ostat_args {
997 	char	*path;
998 	struct ostat *ub;
999 };
1000 /* ARGSUSED */
1001 ostat(p, uap, retval)
1002 	struct proc *p;
1003 	register struct ostat_args *uap;
1004 	int *retval;
1005 {
1006 	struct stat sb;
1007 	struct ostat osb;
1008 	int error;
1009 	struct nameidata nd;
1010 
1011 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1012 	if (error = namei(&nd))
1013 		return (error);
1014 	error = vn_stat(nd.ni_vp, &sb, p);
1015 	vput(nd.ni_vp);
1016 	if (error)
1017 		return (error);
1018 	cvtstat(&sb, &osb);
1019 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1020 	return (error);
1021 }
1022 
1023 /*
1024  * Get file status; this version does not follow links.
1025  */
1026 struct olstat_args {
1027 	char	*path;
1028 	struct ostat *ub;
1029 };
1030 /* ARGSUSED */
1031 olstat(p, uap, retval)
1032 	struct proc *p;
1033 	register struct olstat_args *uap;
1034 	int *retval;
1035 {
1036 	struct stat sb;
1037 	struct ostat osb;
1038 	int error;
1039 	struct nameidata nd;
1040 
1041 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1042 	if (error = namei(&nd))
1043 		return (error);
1044 	error = vn_stat(nd.ni_vp, &sb, p);
1045 	vput(nd.ni_vp);
1046 	if (error)
1047 		return (error);
1048 	cvtstat(&sb, &osb);
1049 	error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
1050 	return (error);
1051 }
1052 
1053 /*
1054  * Convert from an old to a new stat structure.
1055  */
1056 cvtstat(st, ost)
1057 	struct stat *st;
1058 	struct ostat *ost;
1059 {
1060 
1061 	ost->st_dev = st->st_dev;
1062 	ost->st_ino = st->st_ino;
1063 	ost->st_mode = st->st_mode;
1064 	ost->st_nlink = st->st_nlink;
1065 	ost->st_uid = st->st_uid;
1066 	ost->st_gid = st->st_gid;
1067 	ost->st_rdev = st->st_rdev;
1068 	if (st->st_size < (quad_t)1 << 32)
1069 		ost->st_size = st->st_size;
1070 	else
1071 		ost->st_size = -2;
1072 	ost->st_atime = st->st_atime;
1073 	ost->st_mtime = st->st_mtime;
1074 	ost->st_ctime = st->st_ctime;
1075 	ost->st_blksize = st->st_blksize;
1076 	ost->st_blocks = st->st_blocks;
1077 	ost->st_flags = st->st_flags;
1078 	ost->st_gen = st->st_gen;
1079 }
1080 #endif /* COMPAT_43 || COMPAT_SUNOS */
1081 
1082 /*
1083  * Get file status; this version follows links.
1084  */
1085 struct stat_args {
1086 	char	*path;
1087 	struct stat *ub;
1088 };
1089 /* ARGSUSED */
1090 stat(p, uap, retval)
1091 	struct proc *p;
1092 	register struct stat_args *uap;
1093 	int *retval;
1094 {
1095 	struct stat sb;
1096 	int error;
1097 	struct nameidata nd;
1098 
1099 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1100 	if (error = namei(&nd))
1101 		return (error);
1102 	error = vn_stat(nd.ni_vp, &sb, p);
1103 	vput(nd.ni_vp);
1104 	if (error)
1105 		return (error);
1106 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1107 	return (error);
1108 }
1109 
1110 /*
1111  * Get file status; this version does not follow links.
1112  */
1113 struct lstat_args {
1114 	char	*path;
1115 	struct stat *ub;
1116 };
1117 /* ARGSUSED */
1118 lstat(p, uap, retval)
1119 	struct proc *p;
1120 	register struct lstat_args *uap;
1121 	int *retval;
1122 {
1123 	int error;
1124 	struct vnode *vp, *dvp;
1125 	struct stat sb, sb1;
1126 	struct nameidata nd;
1127 
1128 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1129 	    uap->path, p);
1130 	if (error = namei(&nd))
1131 		return (error);
1132 	/*
1133 	 * For symbolic links, always return the attributes of its
1134 	 * containing directory, except for mode, size, and links.
1135 	 */
1136 	vp = nd.ni_vp;
1137 	dvp = nd.ni_dvp;
1138 	if (vp->v_type != VLNK) {
1139 		if (dvp == vp)
1140 			vrele(dvp);
1141 		else
1142 			vput(dvp);
1143 		error = vn_stat(vp, &sb, p);
1144 		vput(vp);
1145 		if (error)
1146 			return (error);
1147 	} else {
1148 		error = vn_stat(dvp, &sb, p);
1149 		vput(dvp);
1150 		if (error) {
1151 			vput(vp);
1152 			return (error);
1153 		}
1154 		error = vn_stat(vp, &sb1, p);
1155 		vput(vp);
1156 		if (error)
1157 			return (error);
1158 		sb.st_mode &= ~S_IFDIR;
1159 		sb.st_mode |= S_IFLNK;
1160 		sb.st_nlink = sb1.st_nlink;
1161 		sb.st_size = sb1.st_size;
1162 		sb.st_blocks = sb1.st_blocks;
1163 	}
1164 	error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
1165 	return (error);
1166 }
1167 
1168 /*
1169  * Get configurable pathname variables.
1170  */
1171 struct pathconf_args {
1172 	char	*path;
1173 	int	name;
1174 };
1175 /* ARGSUSED */
1176 pathconf(p, uap, retval)
1177 	struct proc *p;
1178 	register struct pathconf_args *uap;
1179 	int *retval;
1180 {
1181 	int error;
1182 	struct nameidata nd;
1183 
1184 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1185 	if (error = namei(&nd))
1186 		return (error);
1187 	error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
1188 	vput(nd.ni_vp);
1189 	return (error);
1190 }
1191 
1192 /*
1193  * Return target name of a symbolic link.
1194  */
1195 struct readlink_args {
1196 	char	*path;
1197 	char	*buf;
1198 	int	count;
1199 };
1200 /* ARGSUSED */
1201 readlink(p, uap, retval)
1202 	struct proc *p;
1203 	register struct readlink_args *uap;
1204 	int *retval;
1205 {
1206 	register struct vnode *vp;
1207 	struct iovec aiov;
1208 	struct uio auio;
1209 	int error;
1210 	struct nameidata nd;
1211 
1212 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1213 	if (error = namei(&nd))
1214 		return (error);
1215 	vp = nd.ni_vp;
1216 	if (vp->v_type != VLNK)
1217 		error = EINVAL;
1218 	else {
1219 		aiov.iov_base = uap->buf;
1220 		aiov.iov_len = uap->count;
1221 		auio.uio_iov = &aiov;
1222 		auio.uio_iovcnt = 1;
1223 		auio.uio_offset = 0;
1224 		auio.uio_rw = UIO_READ;
1225 		auio.uio_segflg = UIO_USERSPACE;
1226 		auio.uio_procp = p;
1227 		auio.uio_resid = uap->count;
1228 		error = VOP_READLINK(vp, &auio, p->p_ucred);
1229 	}
1230 	vput(vp);
1231 	*retval = uap->count - auio.uio_resid;
1232 	return (error);
1233 }
1234 
1235 /*
1236  * Change flags of a file given a path name.
1237  */
1238 struct chflags_args {
1239 	char	*path;
1240 	int	flags;
1241 };
1242 /* ARGSUSED */
1243 chflags(p, uap, retval)
1244 	struct proc *p;
1245 	register struct chflags_args *uap;
1246 	int *retval;
1247 {
1248 	register struct vnode *vp;
1249 	struct vattr vattr;
1250 	int error;
1251 	struct nameidata nd;
1252 
1253 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1254 	if (error = namei(&nd))
1255 		return (error);
1256 	vp = nd.ni_vp;
1257 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1258 	VOP_LOCK(vp);
1259 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1260 		error = EROFS;
1261 	else {
1262 		VATTR_NULL(&vattr);
1263 		vattr.va_flags = uap->flags;
1264 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1265 	}
1266 	vput(vp);
1267 	return (error);
1268 }
1269 
1270 /*
1271  * Change flags of a file given a file descriptor.
1272  */
1273 struct fchflags_args {
1274 	int	fd;
1275 	int	flags;
1276 };
1277 /* ARGSUSED */
1278 fchflags(p, uap, retval)
1279 	struct proc *p;
1280 	register struct fchflags_args *uap;
1281 	int *retval;
1282 {
1283 	struct vattr vattr;
1284 	struct vnode *vp;
1285 	struct file *fp;
1286 	int error;
1287 
1288 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1289 		return (error);
1290 	vp = (struct vnode *)fp->f_data;
1291 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1292 	VOP_LOCK(vp);
1293 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1294 		error = EROFS;
1295 	else {
1296 		VATTR_NULL(&vattr);
1297 		vattr.va_flags = uap->flags;
1298 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1299 	}
1300 	VOP_UNLOCK(vp);
1301 	return (error);
1302 }
1303 
1304 /*
1305  * Change mode of a file given path name.
1306  */
1307 struct chmod_args {
1308 	char	*path;
1309 	int	mode;
1310 };
1311 /* ARGSUSED */
1312 chmod(p, uap, retval)
1313 	struct proc *p;
1314 	register struct chmod_args *uap;
1315 	int *retval;
1316 {
1317 	register struct vnode *vp;
1318 	struct vattr vattr;
1319 	int error;
1320 	struct nameidata nd;
1321 
1322 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1323 	if (error = namei(&nd))
1324 		return (error);
1325 	vp = nd.ni_vp;
1326 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1327 	VOP_LOCK(vp);
1328 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1329 		error = EROFS;
1330 	else {
1331 		VATTR_NULL(&vattr);
1332 		vattr.va_mode = uap->mode & ALLPERMS;
1333 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1334 	}
1335 	vput(vp);
1336 	return (error);
1337 }
1338 
1339 /*
1340  * Change mode of a file given a file descriptor.
1341  */
1342 struct fchmod_args {
1343 	int	fd;
1344 	int	mode;
1345 };
1346 /* ARGSUSED */
1347 fchmod(p, uap, retval)
1348 	struct proc *p;
1349 	register struct fchmod_args *uap;
1350 	int *retval;
1351 {
1352 	struct vattr vattr;
1353 	struct vnode *vp;
1354 	struct file *fp;
1355 	int error;
1356 
1357 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1358 		return (error);
1359 	vp = (struct vnode *)fp->f_data;
1360 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1361 	VOP_LOCK(vp);
1362 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1363 		error = EROFS;
1364 	else {
1365 		VATTR_NULL(&vattr);
1366 		vattr.va_mode = uap->mode & ALLPERMS;
1367 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1368 	}
1369 	VOP_UNLOCK(vp);
1370 	return (error);
1371 }
1372 
1373 /*
1374  * Set ownership given a path name.
1375  */
1376 struct chown_args {
1377 	char	*path;
1378 	int	uid;
1379 	int	gid;
1380 };
1381 /* ARGSUSED */
1382 chown(p, uap, retval)
1383 	struct proc *p;
1384 	register struct chown_args *uap;
1385 	int *retval;
1386 {
1387 	register struct vnode *vp;
1388 	struct vattr vattr;
1389 	int error;
1390 	struct nameidata nd;
1391 
1392 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, p);
1393 	if (error = namei(&nd))
1394 		return (error);
1395 	vp = nd.ni_vp;
1396 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1397 	VOP_LOCK(vp);
1398 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1399 		error = EROFS;
1400 	else {
1401 		VATTR_NULL(&vattr);
1402 		vattr.va_uid = uap->uid;
1403 		vattr.va_gid = uap->gid;
1404 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1405 	}
1406 	vput(vp);
1407 	return (error);
1408 }
1409 
1410 /*
1411  * Set ownership given a file descriptor.
1412  */
1413 struct fchown_args {
1414 	int	fd;
1415 	int	uid;
1416 	int	gid;
1417 };
1418 /* ARGSUSED */
1419 fchown(p, uap, retval)
1420 	struct proc *p;
1421 	register struct fchown_args *uap;
1422 	int *retval;
1423 {
1424 	struct vattr vattr;
1425 	struct vnode *vp;
1426 	struct file *fp;
1427 	int error;
1428 
1429 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1430 		return (error);
1431 	vp = (struct vnode *)fp->f_data;
1432 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1433 	VOP_LOCK(vp);
1434 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1435 		error = EROFS;
1436 	else {
1437 		VATTR_NULL(&vattr);
1438 		vattr.va_uid = uap->uid;
1439 		vattr.va_gid = uap->gid;
1440 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1441 	}
1442 	VOP_UNLOCK(vp);
1443 	return (error);
1444 }
1445 
1446 /*
1447  * Set the access and modification times of a file.
1448  */
1449 struct utimes_args {
1450 	char	*path;
1451 	struct	timeval *tptr;
1452 };
1453 /* ARGSUSED */
1454 utimes(p, uap, retval)
1455 	struct proc *p;
1456 	register struct utimes_args *uap;
1457 	int *retval;
1458 {
1459 	register struct vnode *vp;
1460 	struct timeval tv[2];
1461 	struct vattr vattr;
1462 	int error;
1463 	struct nameidata nd;
1464 
1465 	VATTR_NULL(&vattr);
1466 	if (uap->tptr == NULL) {
1467 		microtime(&tv[0]);
1468 		tv[1] = tv[0];
1469 		vattr.va_vaflags |= VA_UTIMES_NULL;
1470 	} else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
1471   		return (error);
1472 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1473 	if (error = namei(&nd))
1474 		return (error);
1475 	vp = nd.ni_vp;
1476 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1477 	VOP_LOCK(vp);
1478 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1479 		error = EROFS;
1480 	else {
1481 		vattr.va_atime.ts_sec = tv[0].tv_sec;
1482 		vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1483 		vattr.va_mtime.ts_sec = tv[1].tv_sec;
1484 		vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
1485 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1486 	}
1487 	vput(vp);
1488 	return (error);
1489 }
1490 
1491 /*
1492  * Truncate a file given its path name.
1493  */
1494 struct truncate_args {
1495 	char	*path;
1496 	int	pad;
1497 	off_t	length;
1498 };
1499 /* ARGSUSED */
1500 truncate(p, uap, retval)
1501 	struct proc *p;
1502 	register struct truncate_args *uap;
1503 	int *retval;
1504 {
1505 	register struct vnode *vp;
1506 	struct vattr vattr;
1507 	int error;
1508 	struct nameidata nd;
1509 
1510 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
1511 	if (error = namei(&nd))
1512 		return (error);
1513 	vp = nd.ni_vp;
1514 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1515 	VOP_LOCK(vp);
1516 	if (vp->v_type == VDIR)
1517 		error = EISDIR;
1518 	else if ((error = vn_writechk(vp)) == 0 &&
1519 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
1520 		VATTR_NULL(&vattr);
1521 		vattr.va_size = uap->length;
1522 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1523 	}
1524 	vput(vp);
1525 	return (error);
1526 }
1527 
1528 /*
1529  * Truncate a file given a file descriptor.
1530  */
1531 struct ftruncate_args {
1532 	int	fd;
1533 	int	pad;
1534 	off_t	length;
1535 };
1536 /* ARGSUSED */
1537 ftruncate(p, uap, retval)
1538 	struct proc *p;
1539 	register struct ftruncate_args *uap;
1540 	int *retval;
1541 {
1542 	struct vattr vattr;
1543 	struct vnode *vp;
1544 	struct file *fp;
1545 	int error;
1546 
1547 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1548 		return (error);
1549 	if ((fp->f_flag & FWRITE) == 0)
1550 		return (EINVAL);
1551 	vp = (struct vnode *)fp->f_data;
1552 	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1553 	VOP_LOCK(vp);
1554 	if (vp->v_type == VDIR)
1555 		error = EISDIR;
1556 	else if ((error = vn_writechk(vp)) == 0) {
1557 		VATTR_NULL(&vattr);
1558 		vattr.va_size = uap->length;
1559 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1560 	}
1561 	VOP_UNLOCK(vp);
1562 	return (error);
1563 }
1564 
1565 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1566 /*
1567  * Truncate a file given its path name.
1568  */
1569 struct otruncate_args {
1570 	char	*path;
1571 	long	length;
1572 };
1573 /* ARGSUSED */
1574 otruncate(p, uap, retval)
1575 	struct proc *p;
1576 	register struct otruncate_args *uap;
1577 	int *retval;
1578 {
1579 	struct truncate_args nuap;
1580 
1581 	nuap.path = uap->path;
1582 	nuap.length = uap->length;
1583 	return (truncate(p, &nuap, retval));
1584 }
1585 
1586 /*
1587  * Truncate a file given a file descriptor.
1588  */
1589 struct oftruncate_args {
1590 	int	fd;
1591 	long	length;
1592 };
1593 /* ARGSUSED */
1594 oftruncate(p, uap, retval)
1595 	struct proc *p;
1596 	register struct oftruncate_args *uap;
1597 	int *retval;
1598 {
1599 	struct ftruncate_args nuap;
1600 
1601 	nuap.fd = uap->fd;
1602 	nuap.length = uap->length;
1603 	return (ftruncate(p, &nuap, retval));
1604 }
1605 #endif /* COMPAT_43 || COMPAT_SUNOS */
1606 
1607 /*
1608  * Sync an open file.
1609  */
1610 struct fsync_args {
1611 	int	fd;
1612 };
1613 /* ARGSUSED */
1614 fsync(p, uap, retval)
1615 	struct proc *p;
1616 	struct fsync_args *uap;
1617 	int *retval;
1618 {
1619 	register struct vnode *vp;
1620 	struct file *fp;
1621 	int error;
1622 
1623 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1624 		return (error);
1625 	vp = (struct vnode *)fp->f_data;
1626 	VOP_LOCK(vp);
1627 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
1628 	VOP_UNLOCK(vp);
1629 	return (error);
1630 }
1631 
1632 /*
1633  * Rename files.  Source and destination must either both be directories,
1634  * or both not be directories.  If target is a directory, it must be empty.
1635  */
1636 struct rename_args {
1637 	char	*from;
1638 	char	*to;
1639 };
1640 /* ARGSUSED */
1641 rename(p, uap, retval)
1642 	struct proc *p;
1643 	register struct rename_args *uap;
1644 	int *retval;
1645 {
1646 	register struct vnode *tvp, *fvp, *tdvp;
1647 	struct nameidata fromnd, tond;
1648 	int error;
1649 
1650 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1651 		uap->from, p);
1652 	if (error = namei(&fromnd))
1653 		return (error);
1654 	fvp = fromnd.ni_vp;
1655 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1656 		UIO_USERSPACE, uap->to, p);
1657 	if (error = namei(&tond)) {
1658 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1659 		vrele(fromnd.ni_dvp);
1660 		vrele(fvp);
1661 		goto out1;
1662 	}
1663 	tdvp = tond.ni_dvp;
1664 	tvp = tond.ni_vp;
1665 	if (tvp != NULL) {
1666 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1667 			error = ENOTDIR;
1668 			goto out;
1669 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1670 			error = EISDIR;
1671 			goto out;
1672 		}
1673 	}
1674 	if (fvp == tdvp)
1675 		error = EINVAL;
1676 	/*
1677 	 * If source is the same as the destination (that is the
1678 	 * same inode number with the same name in the same directory),
1679 	 * then there is nothing to do.
1680 	 */
1681 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1682 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1683 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1684 	      fromnd.ni_cnd.cn_namelen))
1685 		error = -1;
1686 out:
1687 	if (!error) {
1688 		LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
1689 		if (fromnd.ni_dvp != tdvp)
1690 			LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1691 		if (tvp)
1692 			LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
1693 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1694 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1695 	} else {
1696 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1697 		if (tdvp == tvp)
1698 			vrele(tdvp);
1699 		else
1700 			vput(tdvp);
1701 		if (tvp)
1702 			vput(tvp);
1703 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1704 		vrele(fromnd.ni_dvp);
1705 		vrele(fvp);
1706 	}
1707 	vrele(tond.ni_startdir);
1708 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1709 out1:
1710 	vrele(fromnd.ni_startdir);
1711 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1712 	if (error == -1)
1713 		return (0);
1714 	return (error);
1715 }
1716 
1717 /*
1718  * Make a directory file.
1719  */
1720 struct mkdir_args {
1721 	char	*path;
1722 	int	mode;
1723 };
1724 /* ARGSUSED */
1725 mkdir(p, uap, retval)
1726 	struct proc *p;
1727 	register struct mkdir_args *uap;
1728 	int *retval;
1729 {
1730 	register struct vnode *vp;
1731 	struct vattr vattr;
1732 	int error;
1733 	struct nameidata nd;
1734 
1735 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
1736 	if (error = namei(&nd))
1737 		return (error);
1738 	vp = nd.ni_vp;
1739 	if (vp != NULL) {
1740 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1741 		if (nd.ni_dvp == vp)
1742 			vrele(nd.ni_dvp);
1743 		else
1744 			vput(nd.ni_dvp);
1745 		vrele(vp);
1746 		return (EEXIST);
1747 	}
1748 	VATTR_NULL(&vattr);
1749 	vattr.va_type = VDIR;
1750 	vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
1751 	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1752 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1753 	if (!error)
1754 		vput(nd.ni_vp);
1755 	return (error);
1756 }
1757 
1758 /*
1759  * Remove a directory file.
1760  */
1761 struct rmdir_args {
1762 	char	*path;
1763 };
1764 /* ARGSUSED */
1765 rmdir(p, uap, retval)
1766 	struct proc *p;
1767 	struct rmdir_args *uap;
1768 	int *retval;
1769 {
1770 	register struct vnode *vp;
1771 	int error;
1772 	struct nameidata nd;
1773 
1774 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p);
1775 	if (error = namei(&nd))
1776 		return (error);
1777 	vp = nd.ni_vp;
1778 	if (vp->v_type != VDIR) {
1779 		error = ENOTDIR;
1780 		goto out;
1781 	}
1782 	/*
1783 	 * No rmdir "." please.
1784 	 */
1785 	if (nd.ni_dvp == vp) {
1786 		error = EINVAL;
1787 		goto out;
1788 	}
1789 	/*
1790 	 * The root of a mounted filesystem cannot be deleted.
1791 	 */
1792 	if (vp->v_flag & VROOT)
1793 		error = EBUSY;
1794 out:
1795 	if (!error) {
1796 		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1797 		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
1798 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1799 	} else {
1800 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1801 		if (nd.ni_dvp == vp)
1802 			vrele(nd.ni_dvp);
1803 		else
1804 			vput(nd.ni_dvp);
1805 		vput(vp);
1806 	}
1807 	return (error);
1808 }
1809 
1810 #ifdef COMPAT_43
1811 /*
1812  * Read a block of directory entries in a file system independent format.
1813  */
1814 struct ogetdirentries_args {
1815 	int	fd;
1816 	char	*buf;
1817 	u_int	count;
1818 	long	*basep;
1819 };
1820 ogetdirentries(p, uap, retval)
1821 	struct proc *p;
1822 	register struct ogetdirentries_args *uap;
1823 	int *retval;
1824 {
1825 	register struct vnode *vp;
1826 	struct file *fp;
1827 	struct uio auio, kuio;
1828 	struct iovec aiov, kiov;
1829 	struct dirent *dp, *edp;
1830 	caddr_t dirbuf;
1831 	int error, readcnt;
1832 	long loff;
1833 
1834 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1835 		return (error);
1836 	if ((fp->f_flag & FREAD) == 0)
1837 		return (EBADF);
1838 	vp = (struct vnode *)fp->f_data;
1839 	if (vp->v_type != VDIR)
1840 		return (EINVAL);
1841 	aiov.iov_base = uap->buf;
1842 	aiov.iov_len = uap->count;
1843 	auio.uio_iov = &aiov;
1844 	auio.uio_iovcnt = 1;
1845 	auio.uio_rw = UIO_READ;
1846 	auio.uio_segflg = UIO_USERSPACE;
1847 	auio.uio_procp = p;
1848 	auio.uio_resid = uap->count;
1849 	VOP_LOCK(vp);
1850 	loff = auio.uio_offset = fp->f_offset;
1851 #	if (BYTE_ORDER != LITTLE_ENDIAN)
1852 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
1853 			error = VOP_READDIR(vp, &auio, fp->f_cred);
1854 			fp->f_offset = auio.uio_offset;
1855 		} else
1856 #	endif
1857 	{
1858 		kuio = auio;
1859 		kuio.uio_iov = &kiov;
1860 		kuio.uio_segflg = UIO_SYSSPACE;
1861 		kiov.iov_len = uap->count;
1862 		MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
1863 		kiov.iov_base = dirbuf;
1864 		error = VOP_READDIR(vp, &kuio, fp->f_cred);
1865 		fp->f_offset = kuio.uio_offset;
1866 		if (error == 0) {
1867 			readcnt = uap->count - kuio.uio_resid;
1868 			edp = (struct dirent *)&dirbuf[readcnt];
1869 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1870 #				if (BYTE_ORDER == LITTLE_ENDIAN)
1871 					/*
1872 					 * The expected low byte of
1873 					 * dp->d_namlen is our dp->d_type.
1874 					 * The high MBZ byte of dp->d_namlen
1875 					 * is our dp->d_namlen.
1876 					 */
1877 					dp->d_type = dp->d_namlen;
1878 					dp->d_namlen = 0;
1879 #				else
1880 					/*
1881 					 * The dp->d_type is the high byte
1882 					 * of the expected dp->d_namlen,
1883 					 * so must be zero'ed.
1884 					 */
1885 					dp->d_type = 0;
1886 #				endif
1887 				if (dp->d_reclen > 0) {
1888 					dp = (struct dirent *)
1889 					    ((char *)dp + dp->d_reclen);
1890 				} else {
1891 					error = EIO;
1892 					break;
1893 				}
1894 			}
1895 			if (dp >= edp)
1896 				error = uiomove(dirbuf, readcnt, &auio);
1897 		}
1898 		FREE(dirbuf, M_TEMP);
1899 	}
1900 	VOP_UNLOCK(vp);
1901 	if (error)
1902 		return (error);
1903 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
1904 	*retval = uap->count - auio.uio_resid;
1905 	return (error);
1906 }
1907 #endif
1908 
1909 /*
1910  * Read a block of directory entries in a file system independent format.
1911  */
1912 struct getdirentries_args {
1913 	int	fd;
1914 	char	*buf;
1915 	u_int	count;
1916 	long	*basep;
1917 };
1918 getdirentries(p, uap, retval)
1919 	struct proc *p;
1920 	register struct getdirentries_args *uap;
1921 	int *retval;
1922 {
1923 	register struct vnode *vp;
1924 	struct file *fp;
1925 	struct uio auio;
1926 	struct iovec aiov;
1927 	long loff;
1928 	int error;
1929 
1930 	if (error = getvnode(p->p_fd, uap->fd, &fp))
1931 		return (error);
1932 	if ((fp->f_flag & FREAD) == 0)
1933 		return (EBADF);
1934 	vp = (struct vnode *)fp->f_data;
1935 unionread:
1936 	if (vp->v_type != VDIR)
1937 		return (EINVAL);
1938 	aiov.iov_base = uap->buf;
1939 	aiov.iov_len = uap->count;
1940 	auio.uio_iov = &aiov;
1941 	auio.uio_iovcnt = 1;
1942 	auio.uio_rw = UIO_READ;
1943 	auio.uio_segflg = UIO_USERSPACE;
1944 	auio.uio_procp = p;
1945 	auio.uio_resid = uap->count;
1946 	VOP_LOCK(vp);
1947 	loff = auio.uio_offset = fp->f_offset;
1948 	error = VOP_READDIR(vp, &auio, fp->f_cred);
1949 	fp->f_offset = auio.uio_offset;
1950 	VOP_UNLOCK(vp);
1951 	if (error)
1952 		return (error);
1953 	if ((uap->count == auio.uio_resid) &&
1954 	    (vp->v_flag & VROOT) &&
1955 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
1956 		struct vnode *tvp = vp;
1957 		vp = vp->v_mount->mnt_vnodecovered;
1958 		VREF(vp);
1959 		fp->f_data = (caddr_t) vp;
1960 		fp->f_offset = 0;
1961 		vrele(tvp);
1962 		goto unionread;
1963 	}
1964 	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
1965 	*retval = uap->count - auio.uio_resid;
1966 	return (error);
1967 }
1968 
1969 /*
1970  * Set the mode mask for creation of filesystem nodes.
1971  */
1972 struct umask_args {
1973 	int	newmask;
1974 };
1975 mode_t				/* XXX */
1976 umask(p, uap, retval)
1977 	struct proc *p;
1978 	struct umask_args *uap;
1979 	int *retval;
1980 {
1981 	register struct filedesc *fdp;
1982 
1983 	fdp = p->p_fd;
1984 	*retval = fdp->fd_cmask;
1985 	fdp->fd_cmask = uap->newmask & ALLPERMS;
1986 	return (0);
1987 }
1988 
1989 /*
1990  * Void all references to file by ripping underlying filesystem
1991  * away from vnode.
1992  */
1993 struct revoke_args {
1994 	char	*path;
1995 };
1996 /* ARGSUSED */
1997 revoke(p, uap, retval)
1998 	struct proc *p;
1999 	register struct revoke_args *uap;
2000 	int *retval;
2001 {
2002 	register struct vnode *vp;
2003 	struct vattr vattr;
2004 	int error;
2005 	struct nameidata nd;
2006 
2007 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
2008 	if (error = namei(&nd))
2009 		return (error);
2010 	vp = nd.ni_vp;
2011 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
2012 		error = EINVAL;
2013 		goto out;
2014 	}
2015 	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2016 		goto out;
2017 	if (p->p_ucred->cr_uid != vattr.va_uid &&
2018 	    (error = suser(p->p_ucred, &p->p_acflag)))
2019 		goto out;
2020 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2021 		vgoneall(vp);
2022 out:
2023 	vrele(vp);
2024 	return (error);
2025 }
2026 
2027 /*
2028  * Convert a user file descriptor to a kernel file entry.
2029  */
2030 getvnode(fdp, fd, fpp)
2031 	struct filedesc *fdp;
2032 	struct file **fpp;
2033 	int fd;
2034 {
2035 	struct file *fp;
2036 
2037 	if ((u_int)fd >= fdp->fd_nfiles ||
2038 	    (fp = fdp->fd_ofiles[fd]) == NULL)
2039 		return (EBADF);
2040 	if (fp->f_type != DTYPE_VNODE)
2041 		return (EINVAL);
2042 	*fpp = fp;
2043 	return (0);
2044 }
2045