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