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