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