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