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