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