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