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