xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 69334)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * %sccs.include.redist.c%
11  *
12  *	@(#)vfs_syscalls.c	8.35 (Berkeley) 05/10/95
13  */
14 
15 #include <sys/param.h>
16 #include <sys/systm.h>
17 #include <sys/namei.h>
18 #include <sys/filedesc.h>
19 #include <sys/kernel.h>
20 #include <sys/file.h>
21 #include <sys/stat.h>
22 #include <sys/vnode.h>
23 #include <sys/mount.h>
24 #include <sys/proc.h>
25 #include <sys/uio.h>
26 #include <sys/malloc.h>
27 #include <sys/dirent.h>
28 
29 #include <sys/syscallargs.h>
30 
31 #include <vm/vm.h>
32 #include <sys/sysctl.h>
33 
34 static int change_dir __P((struct nameidata *ndp, struct proc *p));
35 static void checkdirs __P((struct vnode *olddp));
36 
37 /*
38  * Virtual File System System Calls
39  */
40 
41 /*
42  * Mount a file system.
43  */
44 /* ARGSUSED */
45 int
46 mount(p, uap, retval)
47 	struct proc *p;
48 	register struct mount_args /* {
49 		syscallarg(char *) type;
50 		syscallarg(char *) path;
51 		syscallarg(int) flags;
52 		syscallarg(caddr_t) data;
53 	} */ *uap;
54 	register_t *retval;
55 {
56 	struct vnode *vp;
57 	struct mount *mp;
58 	struct vfsconf *vfsp;
59 	int error, flag;
60 	struct vattr va;
61 	u_long fstypenum;
62 	struct nameidata nd;
63 	char fstypename[MFSNAMELEN];
64 
65 	/*
66 	 * Get vnode to be covered
67 	 */
68 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
69 	    SCARG(uap, path), p);
70 	if (error = namei(&nd))
71 		return (error);
72 	vp = nd.ni_vp;
73 	if (SCARG(uap, flags) & MNT_UPDATE) {
74 		if ((vp->v_flag & VROOT) == 0) {
75 			vput(vp);
76 			return (EINVAL);
77 		}
78 		mp = vp->v_mount;
79 		flag = mp->mnt_flag;
80 		/*
81 		 * We only allow the filesystem to be reloaded if it
82 		 * is currently mounted read-only.
83 		 */
84 		if ((SCARG(uap, flags) & MNT_RELOAD) &&
85 		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
86 			vput(vp);
87 			return (EOPNOTSUPP);	/* Needs translation */
88 		}
89 		mp->mnt_flag |=
90 		    SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
91 		/*
92 		 * Only root, or the user that did the original mount is
93 		 * permitted to update it.
94 		 */
95 		if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
96 		    (error = suser(p->p_ucred, &p->p_acflag))) {
97 			vput(vp);
98 			return (error);
99 		}
100 		/*
101 		 * Do not allow NFS export by non-root users. Silently
102 		 * enforce MNT_NOSUID and MNT_NODEV for non-root users.
103 		 */
104 		if (p->p_ucred->cr_uid != 0) {
105 			if (SCARG(uap, flags) & MNT_EXPORTED) {
106 				vput(vp);
107 				return (EPERM);
108 			}
109 			SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
110 		}
111 		VOP_UNLOCK(vp);
112 		goto update;
113 	}
114 	/*
115 	 * If the user is not root, ensure that they own the directory
116 	 * onto which we are attempting to mount.
117 	 */
118 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
119 	    (va.va_uid != p->p_ucred->cr_uid &&
120 	     (error = suser(p->p_ucred, &p->p_acflag)))) {
121 		vput(vp);
122 		return (error);
123 	}
124 	/*
125 	 * Do not allow NFS export by non-root users. Silently
126 	 * enforce MNT_NOSUID and MNT_NODEV for non-root users.
127 	 */
128 	if (p->p_ucred->cr_uid != 0) {
129 		if (SCARG(uap, flags) & MNT_EXPORTED) {
130 			vput(vp);
131 			return (EPERM);
132 		}
133 		SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
134 	}
135 	if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
136 		return (error);
137 	if (vp->v_type != VDIR) {
138 		vput(vp);
139 		return (ENOTDIR);
140 	}
141 #ifdef COMPAT_43
142 	/*
143 	 * Historically filesystem types were identified by number. If we
144 	 * get an integer for the filesystem type instead of a string, we
145 	 * check to see if it matches one of the historic filesystem types.
146 	 */
147 	fstypenum = (u_long)SCARG(uap, type);
148 	if (fstypenum < maxvfsconf) {
149 		for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
150 			if (vfsp->vfc_typenum == fstypenum)
151 				break;
152 		if (vfsp == NULL) {
153 			vput(vp);
154 			return (ENODEV);
155 		}
156 		strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
157 	} else
158 #endif /* COMPAT_43 */
159 	if (error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) {
160 		vput(vp);
161 		return (error);
162 	}
163 	for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
164 		if (!strcmp(vfsp->vfc_name, fstypename))
165 			break;
166 	if (vfsp == NULL) {
167 		vput(vp);
168 		return (ENODEV);
169 	}
170 	if (vp->v_mountedhere != NULL) {
171 		vput(vp);
172 		return (EBUSY);
173 	}
174 
175 	/*
176 	 * Allocate and initialize the filesystem.
177 	 */
178 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
179 		M_MOUNT, M_WAITOK);
180 	bzero((char *)mp, (u_long)sizeof(struct mount));
181 	mp->mnt_op = vfsp->vfc_vfsops;
182 	if (error = vfs_lock(mp)) {
183 		free((caddr_t)mp, M_MOUNT);
184 		vput(vp);
185 		return (error);
186 	}
187 	mp->mnt_vfc = vfsp;
188 	vfsp->vfc_refcount++;
189 	mp->mnt_stat.f_type = vfsp->vfc_typenum;
190 	mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
191 	strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
192 	vp->v_mountedhere = mp;
193 	mp->mnt_vnodecovered = vp;
194 	mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
195 update:
196 	/*
197 	 * Set the mount level flags.
198 	 */
199 	if (SCARG(uap, flags) & MNT_RDONLY)
200 		mp->mnt_flag |= MNT_RDONLY;
201 	else if (mp->mnt_flag & MNT_RDONLY)
202 		mp->mnt_flag |= MNT_WANTRDWR;
203 	mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
204 	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
205 	mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
206 	    MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC);
207 	/*
208 	 * Mount the filesystem.
209 	 */
210 	error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
211 	if (mp->mnt_flag & MNT_UPDATE) {
212 		vrele(vp);
213 		if (mp->mnt_flag & MNT_WANTRDWR)
214 			mp->mnt_flag &= ~MNT_RDONLY;
215 		mp->mnt_flag &=~
216 		    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
217 		if (error)
218 			mp->mnt_flag = flag;
219 		return (error);
220 	}
221 	/*
222 	 * Put the new filesystem on the mount list after root.
223 	 */
224 	cache_purge(vp);
225 	if (!error) {
226 		CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
227 		checkdirs(vp);
228 		VOP_UNLOCK(vp);
229 		vfs_unlock(mp);
230 		error = VFS_START(mp, 0, p);
231 	} else {
232 		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
233 		mp->mnt_vfc->vfc_refcount--;
234 		vfs_unlock(mp);
235 		free((caddr_t)mp, M_MOUNT);
236 		vput(vp);
237 	}
238 	return (error);
239 }
240 
241 /*
242  * Scan all active processes to see if any of them have a current
243  * or root directory onto which the new filesystem has just been
244  * mounted. If so, replace them with the new mount point.
245  */
246 static void
247 checkdirs(olddp)
248 	struct vnode *olddp;
249 {
250 	struct filedesc *fdp;
251 	struct vnode *newdp;
252 	struct proc *p;
253 
254 	if (olddp->v_usecount == 1)
255 		return;
256 	if (VFS_ROOT(olddp->v_mountedhere, &newdp))
257 		panic("mount: lost mount");
258 	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
259 		fdp = p->p_fd;
260 		if (fdp->fd_cdir == olddp) {
261 			vrele(fdp->fd_cdir);
262 			VREF(newdp);
263 			fdp->fd_cdir = newdp;
264 		}
265 		if (fdp->fd_rdir == olddp) {
266 			vrele(fdp->fd_rdir);
267 			VREF(newdp);
268 			fdp->fd_rdir = newdp;
269 		}
270 	}
271 	if (rootvnode == olddp) {
272 		vrele(rootvnode);
273 		VREF(newdp);
274 		rootvnode = newdp;
275 	}
276 	vput(newdp);
277 }
278 
279 /*
280  * Unmount a file system.
281  *
282  * Note: unmount takes a path to the vnode mounted on as argument,
283  * not special file (as before).
284  */
285 /* ARGSUSED */
286 int
287 unmount(p, uap, retval)
288 	struct proc *p;
289 	register struct unmount_args /* {
290 		syscallarg(char *) path;
291 		syscallarg(int) flags;
292 	} */ *uap;
293 	register_t *retval;
294 {
295 	register struct vnode *vp;
296 	struct mount *mp;
297 	int error;
298 	struct nameidata nd;
299 
300 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
301 	    SCARG(uap, path), p);
302 	if (error = namei(&nd))
303 		return (error);
304 	vp = nd.ni_vp;
305 	mp = vp->v_mount;
306 
307 	/*
308 	 * Only root, or the user that did the original mount is
309 	 * permitted to unmount this filesystem.
310 	 */
311 	if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
312 	    (error = suser(p->p_ucred, &p->p_acflag))) {
313 		vput(vp);
314 		return (error);
315 	}
316 
317 	/*
318 	 * Don't allow unmounting the root file system.
319 	 */
320 	if (mp->mnt_flag & MNT_ROOTFS) {
321 		vput(vp);
322 		return (EINVAL);
323 	}
324 
325 	/*
326 	 * Must be the root of the filesystem
327 	 */
328 	if ((vp->v_flag & VROOT) == 0) {
329 		vput(vp);
330 		return (EINVAL);
331 	}
332 	vput(vp);
333 	return (dounmount(mp, SCARG(uap, flags), p));
334 }
335 
336 /*
337  * Do the actual file system unmount.
338  */
339 int
340 dounmount(mp, flags, p)
341 	register struct mount *mp;
342 	int flags;
343 	struct proc *p;
344 {
345 	struct vnode *coveredvp;
346 	int error;
347 
348 	coveredvp = mp->mnt_vnodecovered;
349 	if (vfs_busy(mp))
350 		return (EBUSY);
351 	mp->mnt_flag |= MNT_UNMOUNT;
352 	if (error = vfs_lock(mp))
353 		return (error);
354 
355 	mp->mnt_flag &=~ MNT_ASYNC;
356 	vnode_pager_umount(mp);	/* release cached vnodes */
357 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
358 	if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
359 	    (flags & MNT_FORCE))
360 		error = VFS_UNMOUNT(mp, flags, p);
361 	mp->mnt_flag &= ~MNT_UNMOUNT;
362 	vfs_unbusy(mp);
363 	if (error) {
364 		vfs_unlock(mp);
365 	} else {
366 		CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
367 		if (coveredvp != NULLVP) {
368 			vrele(coveredvp);
369 			mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
370 		}
371 		mp->mnt_vfc->vfc_refcount--;
372 		vfs_unlock(mp);
373 		if (mp->mnt_vnodelist.lh_first != NULL)
374 			panic("unmount: dangling vnode");
375 		free((caddr_t)mp, M_MOUNT);
376 	}
377 	return (error);
378 }
379 
380 /*
381  * Sync each mounted filesystem.
382  */
383 #ifdef DEBUG
384 int syncprt = 0;
385 struct ctldebug debug0 = { "syncprt", &syncprt };
386 #endif
387 
388 /* ARGSUSED */
389 int
390 sync(p, uap, retval)
391 	struct proc *p;
392 	void *uap;
393 	register_t *retval;
394 {
395 	register struct mount *mp, *nmp;
396 	int asyncflag;
397 
398 	for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
399 		/*
400 		 * Get the next pointer in case we hang on vfs_busy
401 		 * while we are being unmounted.
402 		 */
403 		nmp = mp->mnt_list.cqe_next;
404 		/*
405 		 * The lock check below is to avoid races with mount
406 		 * and unmount.
407 		 */
408 		if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 &&
409 		    !vfs_busy(mp)) {
410 			asyncflag = mp->mnt_flag & MNT_ASYNC;
411 			mp->mnt_flag &= ~MNT_ASYNC;
412 			VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
413 			if (asyncflag)
414 				mp->mnt_flag |= MNT_ASYNC;
415 			/*
416 			 * Get the next pointer again, as the next filesystem
417 			 * might have been unmounted while we were sync'ing.
418 			 */
419 			nmp = mp->mnt_list.cqe_next;
420 			vfs_unbusy(mp);
421 		}
422 	}
423 #ifdef DIAGNOSTIC
424 	if (syncprt)
425 		vfs_bufstats();
426 #endif /* DIAGNOSTIC */
427 	return (0);
428 }
429 
430 /*
431  * Change filesystem quotas.
432  */
433 /* ARGSUSED */
434 int
435 quotactl(p, uap, retval)
436 	struct proc *p;
437 	register struct quotactl_args /* {
438 		syscallarg(char *) path;
439 		syscallarg(int) cmd;
440 		syscallarg(int) uid;
441 		syscallarg(caddr_t) arg;
442 	} */ *uap;
443 	register_t *retval;
444 {
445 	register struct mount *mp;
446 	int error;
447 	struct nameidata nd;
448 
449 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
450 	if (error = namei(&nd))
451 		return (error);
452 	mp = nd.ni_vp->v_mount;
453 	vrele(nd.ni_vp);
454 	return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
455 	    SCARG(uap, arg), p));
456 }
457 
458 /*
459  * Get filesystem statistics.
460  */
461 /* ARGSUSED */
462 int
463 statfs(p, uap, retval)
464 	struct proc *p;
465 	register struct statfs_args /* {
466 		syscallarg(char *) path;
467 		syscallarg(struct statfs *) buf;
468 	} */ *uap;
469 	register_t *retval;
470 {
471 	register struct mount *mp;
472 	register struct statfs *sp;
473 	int error;
474 	struct nameidata nd;
475 
476 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
477 	if (error = namei(&nd))
478 		return (error);
479 	mp = nd.ni_vp->v_mount;
480 	sp = &mp->mnt_stat;
481 	vrele(nd.ni_vp);
482 	if (error = VFS_STATFS(mp, sp, p))
483 		return (error);
484 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
485 	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
486 }
487 
488 /*
489  * Get filesystem statistics.
490  */
491 /* ARGSUSED */
492 int
493 fstatfs(p, uap, retval)
494 	struct proc *p;
495 	register struct fstatfs_args /* {
496 		syscallarg(int) fd;
497 		syscallarg(struct statfs *) buf;
498 	} */ *uap;
499 	register_t *retval;
500 {
501 	struct file *fp;
502 	struct mount *mp;
503 	register struct statfs *sp;
504 	int error;
505 
506 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
507 		return (error);
508 	mp = ((struct vnode *)fp->f_data)->v_mount;
509 	sp = &mp->mnt_stat;
510 	if (error = VFS_STATFS(mp, sp, p))
511 		return (error);
512 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
513 	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
514 }
515 
516 /*
517  * Get statistics on all filesystems.
518  */
519 int
520 getfsstat(p, uap, retval)
521 	struct proc *p;
522 	register struct getfsstat_args /* {
523 		syscallarg(struct statfs *) buf;
524 		syscallarg(long) bufsize;
525 		syscallarg(int) flags;
526 	} */ *uap;
527 	register_t *retval;
528 {
529 	register struct mount *mp, *nmp;
530 	register struct statfs *sp;
531 	caddr_t sfsp;
532 	long count, maxcount, error;
533 
534 	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
535 	sfsp = (caddr_t)SCARG(uap, buf);
536 	count = 0;
537 	for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
538 		nmp = mp->mnt_list.cqe_next;
539 		if (sfsp && count < maxcount &&
540 		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
541 			sp = &mp->mnt_stat;
542 			/*
543 			 * If MNT_NOWAIT is specified, do not refresh the
544 			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
545 			 */
546 			if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 ||
547 			    (SCARG(uap, flags) & MNT_WAIT)) &&
548 			    (error = VFS_STATFS(mp, sp, p)))
549 				continue;
550 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
551 			if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp)))
552 				return (error);
553 			sfsp += sizeof(*sp);
554 		}
555 		count++;
556 	}
557 	if (sfsp && count > maxcount)
558 		*retval = maxcount;
559 	else
560 		*retval = count;
561 	return (0);
562 }
563 
564 /*
565  * Change current working directory to a given file descriptor.
566  */
567 /* ARGSUSED */
568 int
569 fchdir(p, uap, retval)
570 	struct proc *p;
571 	struct fchdir_args /* {
572 		syscallarg(int) fd;
573 	} */ *uap;
574 	register_t *retval;
575 {
576 	register struct filedesc *fdp = p->p_fd;
577 	struct vnode *vp, *tdp;
578 	struct mount *mp;
579 	struct file *fp;
580 	int error;
581 
582 	if (error = getvnode(fdp, SCARG(uap, fd), &fp))
583 		return (error);
584 	vp = (struct vnode *)fp->f_data;
585 	VREF(vp);
586 	VOP_LOCK(vp);
587 	if (vp->v_type != VDIR)
588 		error = ENOTDIR;
589 	else
590 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
591 	while (!error && (mp = vp->v_mountedhere) != NULL) {
592 		if (mp->mnt_flag & MNT_MLOCK) {
593 			mp->mnt_flag |= MNT_MWAIT;
594 			sleep((caddr_t)mp, PVFS);
595 			continue;
596 		}
597 		if (error = VFS_ROOT(mp, &tdp))
598 			break;
599 		vput(vp);
600 		vp = tdp;
601 	}
602 	VOP_UNLOCK(vp);
603 	if (error) {
604 		vrele(vp);
605 		return (error);
606 	}
607 	vrele(fdp->fd_cdir);
608 	fdp->fd_cdir = vp;
609 	return (0);
610 }
611 
612 /*
613  * Change current working directory (``.'').
614  */
615 /* ARGSUSED */
616 int
617 chdir(p, uap, retval)
618 	struct proc *p;
619 	struct chdir_args /* {
620 		syscallarg(char *) path;
621 	} */ *uap;
622 	register_t *retval;
623 {
624 	register struct filedesc *fdp = p->p_fd;
625 	int error;
626 	struct nameidata nd;
627 
628 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
629 	    SCARG(uap, path), p);
630 	if (error = change_dir(&nd, p))
631 		return (error);
632 	vrele(fdp->fd_cdir);
633 	fdp->fd_cdir = nd.ni_vp;
634 	return (0);
635 }
636 
637 /*
638  * Change notion of root (``/'') directory.
639  */
640 /* ARGSUSED */
641 int
642 chroot(p, uap, retval)
643 	struct proc *p;
644 	struct chroot_args /* {
645 		syscallarg(char *) path;
646 	} */ *uap;
647 	register_t *retval;
648 {
649 	register struct filedesc *fdp = p->p_fd;
650 	int error;
651 	struct nameidata nd;
652 
653 	if (error = suser(p->p_ucred, &p->p_acflag))
654 		return (error);
655 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
656 	    SCARG(uap, path), p);
657 	if (error = change_dir(&nd, p))
658 		return (error);
659 	if (fdp->fd_rdir != NULL)
660 		vrele(fdp->fd_rdir);
661 	fdp->fd_rdir = nd.ni_vp;
662 	return (0);
663 }
664 
665 /*
666  * Common routine for chroot and chdir.
667  */
668 static int
669 change_dir(ndp, p)
670 	register struct nameidata *ndp;
671 	struct proc *p;
672 {
673 	struct vnode *vp;
674 	int error;
675 
676 	if (error = namei(ndp))
677 		return (error);
678 	vp = ndp->ni_vp;
679 	if (vp->v_type != VDIR)
680 		error = ENOTDIR;
681 	else
682 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
683 	VOP_UNLOCK(vp);
684 	if (error)
685 		vrele(vp);
686 	return (error);
687 }
688 
689 /*
690  * Check permissions, allocate an open file structure,
691  * and call the device open routine if any.
692  */
693 int
694 open(p, uap, retval)
695 	struct proc *p;
696 	register struct open_args /* {
697 		syscallarg(char *) path;
698 		syscallarg(int) flags;
699 		syscallarg(int) mode;
700 	} */ *uap;
701 	register_t *retval;
702 {
703 	register struct filedesc *fdp = p->p_fd;
704 	register struct file *fp;
705 	register struct vnode *vp;
706 	int flags, cmode;
707 	struct file *nfp;
708 	int type, indx, error;
709 	struct flock lf;
710 	struct nameidata nd;
711 	extern struct fileops vnops;
712 
713 	if (error = falloc(p, &nfp, &indx))
714 		return (error);
715 	fp = nfp;
716 	flags = FFLAGS(SCARG(uap, flags));
717 	cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
718 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
719 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
720 	if (error = vn_open(&nd, flags, cmode)) {
721 		ffree(fp);
722 		if ((error == ENODEV || error == ENXIO) &&
723 		    p->p_dupfd >= 0 &&			/* XXX from fdopen */
724 		    (error =
725 			dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
726 			*retval = indx;
727 			return (0);
728 		}
729 		if (error == ERESTART)
730 			error = EINTR;
731 		fdp->fd_ofiles[indx] = NULL;
732 		return (error);
733 	}
734 	p->p_dupfd = 0;
735 	vp = nd.ni_vp;
736 	fp->f_flag = flags & FMASK;
737 	fp->f_type = DTYPE_VNODE;
738 	fp->f_ops = &vnops;
739 	fp->f_data = (caddr_t)vp;
740 	if (flags & (O_EXLOCK | O_SHLOCK)) {
741 		lf.l_whence = SEEK_SET;
742 		lf.l_start = 0;
743 		lf.l_len = 0;
744 		if (flags & O_EXLOCK)
745 			lf.l_type = F_WRLCK;
746 		else
747 			lf.l_type = F_RDLCK;
748 		type = F_FLOCK;
749 		if ((flags & FNONBLOCK) == 0)
750 			type |= F_WAIT;
751 		VOP_UNLOCK(vp);
752 		if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
753 			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
754 			ffree(fp);
755 			fdp->fd_ofiles[indx] = NULL;
756 			return (error);
757 		}
758 		VOP_LOCK(vp);
759 		fp->f_flag |= FHASLOCK;
760 	}
761 	VOP_UNLOCK(vp);
762 	*retval = indx;
763 	return (0);
764 }
765 
766 #ifdef COMPAT_43
767 /*
768  * Create a file.
769  */
770 int
771 compat_43_creat(p, uap, retval)
772 	struct proc *p;
773 	register struct compat_43_creat_args /* {
774 		syscallarg(char *) path;
775 		syscallarg(int) mode;
776 	} */ *uap;
777 	register_t *retval;
778 {
779 	struct open_args /* {
780 		syscallarg(char *) path;
781 		syscallarg(int) flags;
782 		syscallarg(int) mode;
783 	} */ nuap;
784 
785 	SCARG(&nuap, path) = SCARG(uap, path);
786 	SCARG(&nuap, mode) = SCARG(uap, mode);
787 	SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
788 	return (open(p, &nuap, retval));
789 }
790 #endif /* COMPAT_43 */
791 
792 /*
793  * Create a special file.
794  */
795 /* ARGSUSED */
796 int
797 mknod(p, uap, retval)
798 	struct proc *p;
799 	register struct mknod_args /* {
800 		syscallarg(char *) path;
801 		syscallarg(int) mode;
802 		syscallarg(int) dev;
803 	} */ *uap;
804 	register_t *retval;
805 {
806 	register struct vnode *vp;
807 	struct vattr vattr;
808 	int error;
809 	int whiteout;
810 	struct nameidata nd;
811 
812 	if (error = suser(p->p_ucred, &p->p_acflag))
813 		return (error);
814 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
815 	if (error = namei(&nd))
816 		return (error);
817 	vp = nd.ni_vp;
818 	if (vp != NULL)
819 		error = EEXIST;
820 	else {
821 		VATTR_NULL(&vattr);
822 		vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
823 		vattr.va_rdev = SCARG(uap, dev);
824 		whiteout = 0;
825 
826 		switch (SCARG(uap, mode) & S_IFMT) {
827 		case S_IFMT:	/* used by badsect to flag bad sectors */
828 			vattr.va_type = VBAD;
829 			break;
830 		case S_IFCHR:
831 			vattr.va_type = VCHR;
832 			break;
833 		case S_IFBLK:
834 			vattr.va_type = VBLK;
835 			break;
836 		case S_IFWHT:
837 			whiteout = 1;
838 			break;
839 		default:
840 			error = EINVAL;
841 			break;
842 		}
843 	}
844 	if (!error) {
845 		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
846 		if (whiteout) {
847 			error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
848 			if (error)
849 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
850 			vput(nd.ni_dvp);
851 		} else {
852 			error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
853 						&nd.ni_cnd, &vattr);
854 		}
855 	} else {
856 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
857 		if (nd.ni_dvp == vp)
858 			vrele(nd.ni_dvp);
859 		else
860 			vput(nd.ni_dvp);
861 		if (vp)
862 			vrele(vp);
863 	}
864 	return (error);
865 }
866 
867 /*
868  * Create a named pipe.
869  */
870 /* ARGSUSED */
871 int
872 mkfifo(p, uap, retval)
873 	struct proc *p;
874 	register struct mkfifo_args /* {
875 		syscallarg(char *) path;
876 		syscallarg(int) mode;
877 	} */ *uap;
878 	register_t *retval;
879 {
880 	struct vattr vattr;
881 	int error;
882 	struct nameidata nd;
883 
884 #ifndef FIFO
885 	return (EOPNOTSUPP);
886 #else
887 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
888 	if (error = namei(&nd))
889 		return (error);
890 	if (nd.ni_vp != NULL) {
891 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
892 		if (nd.ni_dvp == nd.ni_vp)
893 			vrele(nd.ni_dvp);
894 		else
895 			vput(nd.ni_dvp);
896 		vrele(nd.ni_vp);
897 		return (EEXIST);
898 	}
899 	VATTR_NULL(&vattr);
900 	vattr.va_type = VFIFO;
901 	vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
902 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
903 	return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
904 #endif /* FIFO */
905 }
906 
907 /*
908  * Make a hard file link.
909  */
910 /* ARGSUSED */
911 int
912 link(p, uap, retval)
913 	struct proc *p;
914 	register struct link_args /* {
915 		syscallarg(char *) path;
916 		syscallarg(char *) link;
917 	} */ *uap;
918 	register_t *retval;
919 {
920 	register struct vnode *vp;
921 	struct nameidata nd;
922 	int error;
923 
924 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
925 	if (error = namei(&nd))
926 		return (error);
927 	vp = nd.ni_vp;
928 	if (vp->v_type != VDIR ||
929 	    (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
930 		nd.ni_cnd.cn_nameiop = CREATE;
931 		nd.ni_cnd.cn_flags = LOCKPARENT;
932 		nd.ni_dirp = SCARG(uap, link);
933 		if ((error = namei(&nd)) == 0) {
934 			if (nd.ni_vp != NULL)
935 				error = EEXIST;
936 			if (!error) {
937 				VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
938 				    LEASE_WRITE);
939 				VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
940 				error = VOP_LINK(vp, nd.ni_dvp, &nd.ni_cnd);
941 			} else {
942 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
943 				if (nd.ni_dvp == nd.ni_vp)
944 					vrele(nd.ni_dvp);
945 				else
946 					vput(nd.ni_dvp);
947 				if (nd.ni_vp)
948 					vrele(nd.ni_vp);
949 			}
950 		}
951 	}
952 	vrele(vp);
953 	return (error);
954 }
955 
956 /*
957  * Make a symbolic link.
958  */
959 /* ARGSUSED */
960 int
961 symlink(p, uap, retval)
962 	struct proc *p;
963 	register struct symlink_args /* {
964 		syscallarg(char *) path;
965 		syscallarg(char *) link;
966 	} */ *uap;
967 	register_t *retval;
968 {
969 	struct vattr vattr;
970 	char *path;
971 	int error;
972 	struct nameidata nd;
973 
974 	MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
975 	if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL))
976 		goto out;
977 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
978 	if (error = namei(&nd))
979 		goto out;
980 	if (nd.ni_vp) {
981 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
982 		if (nd.ni_dvp == nd.ni_vp)
983 			vrele(nd.ni_dvp);
984 		else
985 			vput(nd.ni_dvp);
986 		vrele(nd.ni_vp);
987 		error = EEXIST;
988 		goto out;
989 	}
990 	VATTR_NULL(&vattr);
991 	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
992 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
993 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
994 out:
995 	FREE(path, M_NAMEI);
996 	return (error);
997 }
998 
999 /*
1000  * Delete a whiteout from the filesystem.
1001  */
1002 /* ARGSUSED */
1003 int
1004 undelete(p, uap, retval)
1005 	struct proc *p;
1006 	register struct undelete_args /* {
1007 		syscallarg(char *) path;
1008 	} */ *uap;
1009 	register_t *retval;
1010 {
1011 	int error;
1012 	struct nameidata nd;
1013 
1014 	NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
1015 	    SCARG(uap, path), p);
1016 	error = namei(&nd);
1017 	if (error)
1018 		return (error);
1019 
1020 	if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1021 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1022 		if (nd.ni_dvp == nd.ni_vp)
1023 			vrele(nd.ni_dvp);
1024 		else
1025 			vput(nd.ni_dvp);
1026 		if (nd.ni_vp)
1027 			vrele(nd.ni_vp);
1028 		return (EEXIST);
1029 	}
1030 
1031 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1032 	if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE))
1033 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1034 	vput(nd.ni_dvp);
1035 	return (error);
1036 }
1037 
1038 /*
1039  * Delete a name from the filesystem.
1040  */
1041 /* ARGSUSED */
1042 int
1043 unlink(p, uap, retval)
1044 	struct proc *p;
1045 	struct unlink_args /* {
1046 		syscallarg(char *) path;
1047 	} */ *uap;
1048 	register_t *retval;
1049 {
1050 	register struct vnode *vp;
1051 	int error;
1052 	struct nameidata nd;
1053 
1054 	NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1055 	if (error = namei(&nd))
1056 		return (error);
1057 	vp = nd.ni_vp;
1058 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1059 	VOP_LOCK(vp);
1060 
1061 	if (vp->v_type != VDIR ||
1062 	    (error = suser(p->p_ucred, &p->p_acflag)) == 0) {
1063 		/*
1064 		 * The root of a mounted filesystem cannot be deleted.
1065 		 */
1066 		if (vp->v_flag & VROOT)
1067 			error = EBUSY;
1068 		else
1069 			(void)vnode_pager_uncache(vp);
1070 	}
1071 
1072 	if (!error) {
1073 		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1074 		error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1075 	} else {
1076 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1077 		if (nd.ni_dvp == vp)
1078 			vrele(nd.ni_dvp);
1079 		else
1080 			vput(nd.ni_dvp);
1081 		if (vp != NULLVP)
1082 			vput(vp);
1083 	}
1084 	return (error);
1085 }
1086 
1087 /*
1088  * Reposition read/write file offset.
1089  */
1090 int
1091 lseek(p, uap, retval)
1092 	struct proc *p;
1093 	register struct lseek_args /* {
1094 		syscallarg(int) fd;
1095 		syscallarg(int) pad;
1096 		syscallarg(off_t) offset;
1097 		syscallarg(int) whence;
1098 	} */ *uap;
1099 	register_t *retval;
1100 {
1101 	struct ucred *cred = p->p_ucred;
1102 	register struct filedesc *fdp = p->p_fd;
1103 	register struct file *fp;
1104 	struct vattr vattr;
1105 	int error;
1106 
1107 	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1108 	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
1109 		return (EBADF);
1110 	if (fp->f_type != DTYPE_VNODE)
1111 		return (ESPIPE);
1112 	switch (SCARG(uap, whence)) {
1113 	case L_INCR:
1114 		fp->f_offset += SCARG(uap, offset);
1115 		break;
1116 	case L_XTND:
1117 		if (error =
1118 		    VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p))
1119 			return (error);
1120 		fp->f_offset = SCARG(uap, offset) + vattr.va_size;
1121 		break;
1122 	case L_SET:
1123 		fp->f_offset = SCARG(uap, offset);
1124 		break;
1125 	default:
1126 		return (EINVAL);
1127 	}
1128 	*(off_t *)retval = fp->f_offset;
1129 	return (0);
1130 }
1131 
1132 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1133 /*
1134  * Reposition read/write file offset.
1135  */
1136 int
1137 compat_43_lseek(p, uap, retval)
1138 	struct proc *p;
1139 	register struct compat_43_lseek_args /* {
1140 		syscallarg(int) fd;
1141 		syscallarg(long) offset;
1142 		syscallarg(int) whence;
1143 	} */ *uap;
1144 	register_t *retval;
1145 {
1146 	struct lseek_args /* {
1147 		syscallarg(int) fd;
1148 		syscallarg(int) pad;
1149 		syscallarg(off_t) offset;
1150 		syscallarg(int) whence;
1151 	} */ nuap;
1152 	off_t qret;
1153 	int error;
1154 
1155 	SCARG(&nuap, fd) = SCARG(uap, fd);
1156 	SCARG(&nuap, offset) = SCARG(uap, offset);
1157 	SCARG(&nuap, whence) = SCARG(uap, whence);
1158 	error = lseek(p, &nuap, &qret);
1159 	*(long *)retval = qret;
1160 	return (error);
1161 }
1162 #endif /* COMPAT_43 */
1163 
1164 /*
1165  * Check access permissions.
1166  */
1167 int
1168 access(p, uap, retval)
1169 	struct proc *p;
1170 	register struct access_args /* {
1171 		syscallarg(char *) path;
1172 		syscallarg(int) flags;
1173 	} */ *uap;
1174 	register_t *retval;
1175 {
1176 	register struct ucred *cred = p->p_ucred;
1177 	register struct vnode *vp;
1178 	int error, flags, t_gid, t_uid;
1179 	struct nameidata nd;
1180 
1181 	t_uid = cred->cr_uid;
1182 	t_gid = cred->cr_groups[0];
1183 	cred->cr_uid = p->p_cred->p_ruid;
1184 	cred->cr_groups[0] = p->p_cred->p_rgid;
1185 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1186 	    SCARG(uap, path), p);
1187 	if (error = namei(&nd))
1188 		goto out1;
1189 	vp = nd.ni_vp;
1190 
1191 	/* Flags == 0 means only check for existence. */
1192 	if (SCARG(uap, flags)) {
1193 		flags = 0;
1194 		if (SCARG(uap, flags) & R_OK)
1195 			flags |= VREAD;
1196 		if (SCARG(uap, flags) & W_OK)
1197 			flags |= VWRITE;
1198 		if (SCARG(uap, flags) & X_OK)
1199 			flags |= VEXEC;
1200 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1201 			error = VOP_ACCESS(vp, flags, cred, p);
1202 	}
1203 	vput(vp);
1204 out1:
1205 	cred->cr_uid = t_uid;
1206 	cred->cr_groups[0] = t_gid;
1207 	return (error);
1208 }
1209 
1210 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1211 /*
1212  * Get file status; this version follows links.
1213  */
1214 /* ARGSUSED */
1215 int
1216 compat_43_stat(p, uap, retval)
1217 	struct proc *p;
1218 	register struct compat_43_stat_args /* {
1219 		syscallarg(char *) path;
1220 		syscallarg(struct ostat *) ub;
1221 	} */ *uap;
1222 	register_t *retval;
1223 {
1224 	struct stat sb;
1225 	struct ostat osb;
1226 	int error;
1227 	struct nameidata nd;
1228 
1229 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1230 	    SCARG(uap, path), p);
1231 	if (error = namei(&nd))
1232 		return (error);
1233 	error = vn_stat(nd.ni_vp, &sb, p);
1234 	vput(nd.ni_vp);
1235 	if (error)
1236 		return (error);
1237 	cvtstat(&sb, &osb);
1238 	error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1239 	return (error);
1240 }
1241 
1242 /*
1243  * Get file status; this version does not follow links.
1244  */
1245 /* ARGSUSED */
1246 int
1247 compat_43_lstat(p, uap, retval)
1248 	struct proc *p;
1249 	register struct compat_43_lstat_args /* {
1250 		syscallarg(char *) path;
1251 		syscallarg(struct ostat *) ub;
1252 	} */ *uap;
1253 	register_t *retval;
1254 {
1255 	struct vnode *vp, *dvp;
1256 	struct stat sb, sb1;
1257 	struct ostat osb;
1258 	int error;
1259 	struct nameidata nd;
1260 
1261 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1262 	    SCARG(uap, path), p);
1263 	if (error = namei(&nd))
1264 		return (error);
1265 	/*
1266 	 * For symbolic links, always return the attributes of its
1267 	 * containing directory, except for mode, size, and links.
1268 	 */
1269 	vp = nd.ni_vp;
1270 	dvp = nd.ni_dvp;
1271 	if (vp->v_type != VLNK) {
1272 		if (dvp == vp)
1273 			vrele(dvp);
1274 		else
1275 			vput(dvp);
1276 		error = vn_stat(vp, &sb, p);
1277 		vput(vp);
1278 		if (error)
1279 			return (error);
1280 	} else {
1281 		error = vn_stat(dvp, &sb, p);
1282 		vput(dvp);
1283 		if (error) {
1284 			vput(vp);
1285 			return (error);
1286 		}
1287 		error = vn_stat(vp, &sb1, p);
1288 		vput(vp);
1289 		if (error)
1290 			return (error);
1291 		sb.st_mode &= ~S_IFDIR;
1292 		sb.st_mode |= S_IFLNK;
1293 		sb.st_nlink = sb1.st_nlink;
1294 		sb.st_size = sb1.st_size;
1295 		sb.st_blocks = sb1.st_blocks;
1296 	}
1297 	cvtstat(&sb, &osb);
1298 	error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
1299 	return (error);
1300 }
1301 
1302 /*
1303  * Convert from an old to a new stat structure.
1304  */
1305 void
1306 cvtstat(st, ost)
1307 	struct stat *st;
1308 	struct ostat *ost;
1309 {
1310 
1311 	ost->st_dev = st->st_dev;
1312 	ost->st_ino = st->st_ino;
1313 	ost->st_mode = st->st_mode;
1314 	ost->st_nlink = st->st_nlink;
1315 	ost->st_uid = st->st_uid;
1316 	ost->st_gid = st->st_gid;
1317 	ost->st_rdev = st->st_rdev;
1318 	if (st->st_size < (quad_t)1 << 32)
1319 		ost->st_size = st->st_size;
1320 	else
1321 		ost->st_size = -2;
1322 	ost->st_atime = st->st_atime;
1323 	ost->st_mtime = st->st_mtime;
1324 	ost->st_ctime = st->st_ctime;
1325 	ost->st_blksize = st->st_blksize;
1326 	ost->st_blocks = st->st_blocks;
1327 	ost->st_flags = st->st_flags;
1328 	ost->st_gen = st->st_gen;
1329 }
1330 #endif /* COMPAT_43 || COMPAT_SUNOS */
1331 
1332 /*
1333  * Get file status; this version follows links.
1334  */
1335 /* ARGSUSED */
1336 int
1337 stat(p, uap, retval)
1338 	struct proc *p;
1339 	register struct stat_args /* {
1340 		syscallarg(char *) path;
1341 		syscallarg(struct stat *) ub;
1342 	} */ *uap;
1343 	register_t *retval;
1344 {
1345 	struct stat sb;
1346 	int error;
1347 	struct nameidata nd;
1348 
1349 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1350 	    SCARG(uap, path), p);
1351 	if (error = namei(&nd))
1352 		return (error);
1353 	error = vn_stat(nd.ni_vp, &sb, p);
1354 	vput(nd.ni_vp);
1355 	if (error)
1356 		return (error);
1357 	error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1358 	return (error);
1359 }
1360 
1361 /*
1362  * Get file status; this version does not follow links.
1363  */
1364 /* ARGSUSED */
1365 int
1366 lstat(p, uap, retval)
1367 	struct proc *p;
1368 	register struct lstat_args /* {
1369 		syscallarg(char *) path;
1370 		syscallarg(struct stat *) ub;
1371 	} */ *uap;
1372 	register_t *retval;
1373 {
1374 	int error;
1375 	struct vnode *vp, *dvp;
1376 	struct stat sb, sb1;
1377 	struct nameidata nd;
1378 
1379 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
1380 	    SCARG(uap, path), p);
1381 	if (error = namei(&nd))
1382 		return (error);
1383 	/*
1384 	 * For symbolic links, always return the attributes of its containing
1385 	 * directory, except for mode, size, inode number, and links.
1386 	 */
1387 	vp = nd.ni_vp;
1388 	dvp = nd.ni_dvp;
1389 	if (vp->v_type != VLNK) {
1390 		if (dvp == vp)
1391 			vrele(dvp);
1392 		else
1393 			vput(dvp);
1394 		error = vn_stat(vp, &sb, p);
1395 		vput(vp);
1396 		if (error)
1397 			return (error);
1398 	} else {
1399 		error = vn_stat(dvp, &sb, p);
1400 		vput(dvp);
1401 		if (error) {
1402 			vput(vp);
1403 			return (error);
1404 		}
1405 		error = vn_stat(vp, &sb1, p);
1406 		vput(vp);
1407 		if (error)
1408 			return (error);
1409 		sb.st_mode &= ~S_IFDIR;
1410 		sb.st_mode |= S_IFLNK;
1411 		sb.st_nlink = sb1.st_nlink;
1412 		sb.st_size = sb1.st_size;
1413 		sb.st_blocks = sb1.st_blocks;
1414 		sb.st_ino = sb1.st_ino;
1415 	}
1416 	error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
1417 	return (error);
1418 }
1419 
1420 /*
1421  * Get configurable pathname variables.
1422  */
1423 /* ARGSUSED */
1424 int
1425 pathconf(p, uap, retval)
1426 	struct proc *p;
1427 	register struct pathconf_args /* {
1428 		syscallarg(char *) path;
1429 		syscallarg(int) name;
1430 	} */ *uap;
1431 	register_t *retval;
1432 {
1433 	int error;
1434 	struct nameidata nd;
1435 
1436 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1437 	    SCARG(uap, path), p);
1438 	if (error = namei(&nd))
1439 		return (error);
1440 	error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
1441 	vput(nd.ni_vp);
1442 	return (error);
1443 }
1444 
1445 /*
1446  * Return target name of a symbolic link.
1447  */
1448 /* ARGSUSED */
1449 int
1450 readlink(p, uap, retval)
1451 	struct proc *p;
1452 	register struct readlink_args /* {
1453 		syscallarg(char *) path;
1454 		syscallarg(char *) buf;
1455 		syscallarg(int) count;
1456 	} */ *uap;
1457 	register_t *retval;
1458 {
1459 	register struct vnode *vp;
1460 	struct iovec aiov;
1461 	struct uio auio;
1462 	int error;
1463 	struct nameidata nd;
1464 
1465 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1466 	    SCARG(uap, path), p);
1467 	if (error = namei(&nd))
1468 		return (error);
1469 	vp = nd.ni_vp;
1470 	if (vp->v_type != VLNK)
1471 		error = EINVAL;
1472 	else {
1473 		aiov.iov_base = SCARG(uap, buf);
1474 		aiov.iov_len = SCARG(uap, count);
1475 		auio.uio_iov = &aiov;
1476 		auio.uio_iovcnt = 1;
1477 		auio.uio_offset = 0;
1478 		auio.uio_rw = UIO_READ;
1479 		auio.uio_segflg = UIO_USERSPACE;
1480 		auio.uio_procp = p;
1481 		auio.uio_resid = SCARG(uap, count);
1482 		error = VOP_READLINK(vp, &auio, p->p_ucred);
1483 	}
1484 	vput(vp);
1485 	*retval = SCARG(uap, count) - auio.uio_resid;
1486 	return (error);
1487 }
1488 
1489 /*
1490  * Change flags of a file given a path name.
1491  */
1492 /* ARGSUSED */
1493 int
1494 chflags(p, uap, retval)
1495 	struct proc *p;
1496 	register struct chflags_args /* {
1497 		syscallarg(char *) path;
1498 		syscallarg(int) flags;
1499 	} */ *uap;
1500 	register_t *retval;
1501 {
1502 	register struct vnode *vp;
1503 	struct vattr vattr;
1504 	int error;
1505 	struct nameidata nd;
1506 
1507 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1508 	if (error = namei(&nd))
1509 		return (error);
1510 	vp = nd.ni_vp;
1511 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1512 	VOP_LOCK(vp);
1513 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1514 		error = EROFS;
1515 	else {
1516 		VATTR_NULL(&vattr);
1517 		vattr.va_flags = SCARG(uap, flags);
1518 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1519 	}
1520 	vput(vp);
1521 	return (error);
1522 }
1523 
1524 /*
1525  * Change flags of a file given a file descriptor.
1526  */
1527 /* ARGSUSED */
1528 int
1529 fchflags(p, uap, retval)
1530 	struct proc *p;
1531 	register struct fchflags_args /* {
1532 		syscallarg(int) fd;
1533 		syscallarg(int) flags;
1534 	} */ *uap;
1535 	register_t *retval;
1536 {
1537 	struct vattr vattr;
1538 	struct vnode *vp;
1539 	struct file *fp;
1540 	int error;
1541 
1542 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1543 		return (error);
1544 	vp = (struct vnode *)fp->f_data;
1545 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1546 	VOP_LOCK(vp);
1547 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1548 		error = EROFS;
1549 	else {
1550 		VATTR_NULL(&vattr);
1551 		vattr.va_flags = SCARG(uap, flags);
1552 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1553 	}
1554 	VOP_UNLOCK(vp);
1555 	return (error);
1556 }
1557 
1558 /*
1559  * Change mode of a file given path name.
1560  */
1561 /* ARGSUSED */
1562 int
1563 chmod(p, uap, retval)
1564 	struct proc *p;
1565 	register struct chmod_args /* {
1566 		syscallarg(char *) path;
1567 		syscallarg(int) mode;
1568 	} */ *uap;
1569 	register_t *retval;
1570 {
1571 	register struct vnode *vp;
1572 	struct vattr vattr;
1573 	int error;
1574 	struct nameidata nd;
1575 
1576 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1577 	if (error = namei(&nd))
1578 		return (error);
1579 	vp = nd.ni_vp;
1580 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1581 	VOP_LOCK(vp);
1582 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1583 		error = EROFS;
1584 	else {
1585 		VATTR_NULL(&vattr);
1586 		vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1587 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1588 	}
1589 	vput(vp);
1590 	return (error);
1591 }
1592 
1593 /*
1594  * Change mode of a file given a file descriptor.
1595  */
1596 /* ARGSUSED */
1597 int
1598 fchmod(p, uap, retval)
1599 	struct proc *p;
1600 	register struct fchmod_args /* {
1601 		syscallarg(int) fd;
1602 		syscallarg(int) mode;
1603 	} */ *uap;
1604 	register_t *retval;
1605 {
1606 	struct vattr vattr;
1607 	struct vnode *vp;
1608 	struct file *fp;
1609 	int error;
1610 
1611 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1612 		return (error);
1613 	vp = (struct vnode *)fp->f_data;
1614 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1615 	VOP_LOCK(vp);
1616 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1617 		error = EROFS;
1618 	else {
1619 		VATTR_NULL(&vattr);
1620 		vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1621 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1622 	}
1623 	VOP_UNLOCK(vp);
1624 	return (error);
1625 }
1626 
1627 /*
1628  * Set ownership given a path name.
1629  */
1630 /* ARGSUSED */
1631 int
1632 chown(p, uap, retval)
1633 	struct proc *p;
1634 	register struct chown_args /* {
1635 		syscallarg(char *) path;
1636 		syscallarg(int) uid;
1637 		syscallarg(int) gid;
1638 	} */ *uap;
1639 	register_t *retval;
1640 {
1641 	register struct vnode *vp;
1642 	struct vattr vattr;
1643 	int error;
1644 	struct nameidata nd;
1645 
1646 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1647 	if (error = namei(&nd))
1648 		return (error);
1649 	vp = nd.ni_vp;
1650 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1651 	VOP_LOCK(vp);
1652 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1653 		error = EROFS;
1654 	else {
1655 		VATTR_NULL(&vattr);
1656 		vattr.va_uid = SCARG(uap, uid);
1657 		vattr.va_gid = SCARG(uap, gid);
1658 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1659 	}
1660 	vput(vp);
1661 	return (error);
1662 }
1663 
1664 /*
1665  * Set ownership given a file descriptor.
1666  */
1667 /* ARGSUSED */
1668 int
1669 fchown(p, uap, retval)
1670 	struct proc *p;
1671 	register struct fchown_args /* {
1672 		syscallarg(int) fd;
1673 		syscallarg(int) uid;
1674 		syscallarg(int) gid;
1675 	} */ *uap;
1676 	register_t *retval;
1677 {
1678 	struct vattr vattr;
1679 	struct vnode *vp;
1680 	struct file *fp;
1681 	int error;
1682 
1683 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1684 		return (error);
1685 	vp = (struct vnode *)fp->f_data;
1686 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1687 	VOP_LOCK(vp);
1688 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1689 		error = EROFS;
1690 	else {
1691 		VATTR_NULL(&vattr);
1692 		vattr.va_uid = SCARG(uap, uid);
1693 		vattr.va_gid = SCARG(uap, gid);
1694 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1695 	}
1696 	VOP_UNLOCK(vp);
1697 	return (error);
1698 }
1699 
1700 /*
1701  * Set the access and modification times of a file.
1702  */
1703 /* ARGSUSED */
1704 int
1705 utimes(p, uap, retval)
1706 	struct proc *p;
1707 	register struct utimes_args /* {
1708 		syscallarg(char *) path;
1709 		syscallarg(struct timeval *) tptr;
1710 	} */ *uap;
1711 	register_t *retval;
1712 {
1713 	register struct vnode *vp;
1714 	struct timeval tv[2];
1715 	struct vattr vattr;
1716 	int error;
1717 	struct nameidata nd;
1718 
1719 	VATTR_NULL(&vattr);
1720 	if (SCARG(uap, tptr) == NULL) {
1721 		microtime(&tv[0]);
1722 		tv[1] = tv[0];
1723 		vattr.va_vaflags |= VA_UTIMES_NULL;
1724 	} else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
1725 	    sizeof (tv)))
1726   		return (error);
1727 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1728 	if (error = namei(&nd))
1729 		return (error);
1730 	vp = nd.ni_vp;
1731 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1732 	VOP_LOCK(vp);
1733 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1734 		error = EROFS;
1735 	else {
1736 		vattr.va_atime.ts_sec = tv[0].tv_sec;
1737 		vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1738 		vattr.va_mtime.ts_sec = tv[1].tv_sec;
1739 		vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
1740 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1741 	}
1742 	vput(vp);
1743 	return (error);
1744 }
1745 
1746 /*
1747  * Truncate a file given its path name.
1748  */
1749 /* ARGSUSED */
1750 int
1751 truncate(p, uap, retval)
1752 	struct proc *p;
1753 	register struct truncate_args /* {
1754 		syscallarg(char *) path;
1755 		syscallarg(int) pad;
1756 		syscallarg(off_t) length;
1757 	} */ *uap;
1758 	register_t *retval;
1759 {
1760 	register struct vnode *vp;
1761 	struct vattr vattr;
1762 	int error;
1763 	struct nameidata nd;
1764 
1765 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1766 	if (error = namei(&nd))
1767 		return (error);
1768 	vp = nd.ni_vp;
1769 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1770 	VOP_LOCK(vp);
1771 	if (vp->v_type == VDIR)
1772 		error = EISDIR;
1773 	else if ((error = vn_writechk(vp)) == 0 &&
1774 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
1775 		VATTR_NULL(&vattr);
1776 		vattr.va_size = SCARG(uap, length);
1777 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1778 	}
1779 	vput(vp);
1780 	return (error);
1781 }
1782 
1783 /*
1784  * Truncate a file given a file descriptor.
1785  */
1786 /* ARGSUSED */
1787 int
1788 ftruncate(p, uap, retval)
1789 	struct proc *p;
1790 	register struct ftruncate_args /* {
1791 		syscallarg(int) fd;
1792 		syscallarg(int) pad;
1793 		syscallarg(off_t) length;
1794 	} */ *uap;
1795 	register_t *retval;
1796 {
1797 	struct vattr vattr;
1798 	struct vnode *vp;
1799 	struct file *fp;
1800 	int error;
1801 
1802 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1803 		return (error);
1804 	if ((fp->f_flag & FWRITE) == 0)
1805 		return (EINVAL);
1806 	vp = (struct vnode *)fp->f_data;
1807 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1808 	VOP_LOCK(vp);
1809 	if (vp->v_type == VDIR)
1810 		error = EISDIR;
1811 	else if ((error = vn_writechk(vp)) == 0) {
1812 		VATTR_NULL(&vattr);
1813 		vattr.va_size = SCARG(uap, length);
1814 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1815 	}
1816 	VOP_UNLOCK(vp);
1817 	return (error);
1818 }
1819 
1820 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1821 /*
1822  * Truncate a file given its path name.
1823  */
1824 /* ARGSUSED */
1825 int
1826 compat_43_truncate(p, uap, retval)
1827 	struct proc *p;
1828 	register struct compat_43_truncate_args /* {
1829 		syscallarg(char *) path;
1830 		syscallarg(long) length;
1831 	} */ *uap;
1832 	register_t *retval;
1833 {
1834 	struct truncate_args /* {
1835 		syscallarg(char *) path;
1836 		syscallarg(int) pad;
1837 		syscallarg(off_t) length;
1838 	} */ nuap;
1839 
1840 	SCARG(&nuap, path) = SCARG(uap, path);
1841 	SCARG(&nuap, length) = SCARG(uap, length);
1842 	return (truncate(p, &nuap, retval));
1843 }
1844 
1845 /*
1846  * Truncate a file given a file descriptor.
1847  */
1848 /* ARGSUSED */
1849 int
1850 compat_43_ftruncate(p, uap, retval)
1851 	struct proc *p;
1852 	register struct compat_43_ftruncate_args /* {
1853 		syscallarg(int) fd;
1854 		syscallarg(long) length;
1855 	} */ *uap;
1856 	register_t *retval;
1857 {
1858 	struct ftruncate_args /* {
1859 		syscallarg(int) fd;
1860 		syscallarg(int) pad;
1861 		syscallarg(off_t) length;
1862 	} */ nuap;
1863 
1864 	SCARG(&nuap, fd) = SCARG(uap, fd);
1865 	SCARG(&nuap, length) = SCARG(uap, length);
1866 	return (ftruncate(p, &nuap, retval));
1867 }
1868 #endif /* COMPAT_43 || COMPAT_SUNOS */
1869 
1870 /*
1871  * Sync an open file.
1872  */
1873 /* ARGSUSED */
1874 int
1875 fsync(p, uap, retval)
1876 	struct proc *p;
1877 	struct fsync_args /* {
1878 		syscallarg(int) fd;
1879 	} */ *uap;
1880 	register_t *retval;
1881 {
1882 	register struct vnode *vp;
1883 	struct file *fp;
1884 	int error;
1885 
1886 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1887 		return (error);
1888 	vp = (struct vnode *)fp->f_data;
1889 	VOP_LOCK(vp);
1890 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
1891 	VOP_UNLOCK(vp);
1892 	return (error);
1893 }
1894 
1895 /*
1896  * Rename files.  Source and destination must either both be directories,
1897  * or both not be directories.  If target is a directory, it must be empty.
1898  */
1899 /* ARGSUSED */
1900 int
1901 rename(p, uap, retval)
1902 	struct proc *p;
1903 	register struct rename_args /* {
1904 		syscallarg(char *) from;
1905 		syscallarg(char *) to;
1906 	} */ *uap;
1907 	register_t *retval;
1908 {
1909 	register struct vnode *tvp, *fvp, *tdvp;
1910 	struct nameidata fromnd, tond;
1911 	int error;
1912 
1913 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1914 	    SCARG(uap, from), p);
1915 	if (error = namei(&fromnd))
1916 		return (error);
1917 	fvp = fromnd.ni_vp;
1918 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1919 	    UIO_USERSPACE, SCARG(uap, to), p);
1920 	if (error = namei(&tond)) {
1921 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1922 		vrele(fromnd.ni_dvp);
1923 		vrele(fvp);
1924 		goto out1;
1925 	}
1926 	tdvp = tond.ni_dvp;
1927 	tvp = tond.ni_vp;
1928 	if (tvp != NULL) {
1929 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1930 			error = ENOTDIR;
1931 			goto out;
1932 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1933 			error = EISDIR;
1934 			goto out;
1935 		}
1936 	}
1937 	if (fvp == tdvp)
1938 		error = EINVAL;
1939 	/*
1940 	 * If source is the same as the destination (that is the
1941 	 * same inode number with the same name in the same directory),
1942 	 * then there is nothing to do.
1943 	 */
1944 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1945 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1946 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1947 	      fromnd.ni_cnd.cn_namelen))
1948 		error = -1;
1949 out:
1950 	if (!error) {
1951 		VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
1952 		if (fromnd.ni_dvp != tdvp)
1953 			VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1954 		if (tvp)
1955 			VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
1956 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1957 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1958 	} else {
1959 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1960 		if (tdvp == tvp)
1961 			vrele(tdvp);
1962 		else
1963 			vput(tdvp);
1964 		if (tvp)
1965 			vput(tvp);
1966 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1967 		vrele(fromnd.ni_dvp);
1968 		vrele(fvp);
1969 	}
1970 	vrele(tond.ni_startdir);
1971 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1972 out1:
1973 	if (fromnd.ni_startdir)
1974 		vrele(fromnd.ni_startdir);
1975 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1976 	if (error == -1)
1977 		return (0);
1978 	return (error);
1979 }
1980 
1981 /*
1982  * Make a directory file.
1983  */
1984 /* ARGSUSED */
1985 int
1986 mkdir(p, uap, retval)
1987 	struct proc *p;
1988 	register struct mkdir_args /* {
1989 		syscallarg(char *) path;
1990 		syscallarg(int) mode;
1991 	} */ *uap;
1992 	register_t *retval;
1993 {
1994 	register struct vnode *vp;
1995 	struct vattr vattr;
1996 	int error;
1997 	struct nameidata nd;
1998 
1999 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
2000 	if (error = namei(&nd))
2001 		return (error);
2002 	vp = nd.ni_vp;
2003 	if (vp != NULL) {
2004 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2005 		if (nd.ni_dvp == vp)
2006 			vrele(nd.ni_dvp);
2007 		else
2008 			vput(nd.ni_dvp);
2009 		vrele(vp);
2010 		return (EEXIST);
2011 	}
2012 	VATTR_NULL(&vattr);
2013 	vattr.va_type = VDIR;
2014 	vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2015 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2016 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2017 	if (!error)
2018 		vput(nd.ni_vp);
2019 	return (error);
2020 }
2021 
2022 /*
2023  * Remove a directory file.
2024  */
2025 /* ARGSUSED */
2026 int
2027 rmdir(p, uap, retval)
2028 	struct proc *p;
2029 	struct rmdir_args /* {
2030 		syscallarg(char *) path;
2031 	} */ *uap;
2032 	register_t *retval;
2033 {
2034 	register struct vnode *vp;
2035 	int error;
2036 	struct nameidata nd;
2037 
2038 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2039 	    SCARG(uap, path), p);
2040 	if (error = namei(&nd))
2041 		return (error);
2042 	vp = nd.ni_vp;
2043 	if (vp->v_type != VDIR) {
2044 		error = ENOTDIR;
2045 		goto out;
2046 	}
2047 	/*
2048 	 * No rmdir "." please.
2049 	 */
2050 	if (nd.ni_dvp == vp) {
2051 		error = EINVAL;
2052 		goto out;
2053 	}
2054 	/*
2055 	 * The root of a mounted filesystem cannot be deleted.
2056 	 */
2057 	if (vp->v_flag & VROOT)
2058 		error = EBUSY;
2059 out:
2060 	if (!error) {
2061 		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2062 		VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2063 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2064 	} else {
2065 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2066 		if (nd.ni_dvp == vp)
2067 			vrele(nd.ni_dvp);
2068 		else
2069 			vput(nd.ni_dvp);
2070 		vput(vp);
2071 	}
2072 	return (error);
2073 }
2074 
2075 #ifdef COMPAT_43
2076 /*
2077  * Read a block of directory entries in a file system independent format.
2078  */
2079 int
2080 compat_43_getdirentries(p, uap, retval)
2081 	struct proc *p;
2082 	register struct compat_43_getdirentries_args /* {
2083 		syscallarg(int) fd;
2084 		syscallarg(char *) buf;
2085 		syscallarg(u_int) count;
2086 		syscallarg(long *) basep;
2087 	} */ *uap;
2088 	register_t *retval;
2089 {
2090 	register struct vnode *vp;
2091 	struct file *fp;
2092 	struct uio auio, kuio;
2093 	struct iovec aiov, kiov;
2094 	struct dirent *dp, *edp;
2095 	caddr_t dirbuf;
2096 	int error, eofflag, readcnt;
2097 	long loff;
2098 
2099 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2100 		return (error);
2101 	if ((fp->f_flag & FREAD) == 0)
2102 		return (EBADF);
2103 	vp = (struct vnode *)fp->f_data;
2104 unionread:
2105 	if (vp->v_type != VDIR)
2106 		return (EINVAL);
2107 	aiov.iov_base = SCARG(uap, buf);
2108 	aiov.iov_len = SCARG(uap, count);
2109 	auio.uio_iov = &aiov;
2110 	auio.uio_iovcnt = 1;
2111 	auio.uio_rw = UIO_READ;
2112 	auio.uio_segflg = UIO_USERSPACE;
2113 	auio.uio_procp = p;
2114 	auio.uio_resid = SCARG(uap, count);
2115 	VOP_LOCK(vp);
2116 	loff = auio.uio_offset = fp->f_offset;
2117 #	if (BYTE_ORDER != LITTLE_ENDIAN)
2118 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
2119 			error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
2120 			    (int *)0, (u_long *)0);
2121 			fp->f_offset = auio.uio_offset;
2122 		} else
2123 #	endif
2124 	{
2125 		kuio = auio;
2126 		kuio.uio_iov = &kiov;
2127 		kuio.uio_segflg = UIO_SYSSPACE;
2128 		kiov.iov_len = SCARG(uap, count);
2129 		MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
2130 		kiov.iov_base = dirbuf;
2131 		error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
2132 			    (int *)0, (u_long *)0);
2133 		fp->f_offset = kuio.uio_offset;
2134 		if (error == 0) {
2135 			readcnt = SCARG(uap, count) - kuio.uio_resid;
2136 			edp = (struct dirent *)&dirbuf[readcnt];
2137 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
2138 #				if (BYTE_ORDER == LITTLE_ENDIAN)
2139 					/*
2140 					 * The expected low byte of
2141 					 * dp->d_namlen is our dp->d_type.
2142 					 * The high MBZ byte of dp->d_namlen
2143 					 * is our dp->d_namlen.
2144 					 */
2145 					dp->d_type = dp->d_namlen;
2146 					dp->d_namlen = 0;
2147 #				else
2148 					/*
2149 					 * The dp->d_type is the high byte
2150 					 * of the expected dp->d_namlen,
2151 					 * so must be zero'ed.
2152 					 */
2153 					dp->d_type = 0;
2154 #				endif
2155 				if (dp->d_reclen > 0) {
2156 					dp = (struct dirent *)
2157 					    ((char *)dp + dp->d_reclen);
2158 				} else {
2159 					error = EIO;
2160 					break;
2161 				}
2162 			}
2163 			if (dp >= edp)
2164 				error = uiomove(dirbuf, readcnt, &auio);
2165 		}
2166 		FREE(dirbuf, M_TEMP);
2167 	}
2168 	VOP_UNLOCK(vp);
2169 	if (error)
2170 		return (error);
2171 
2172 #ifdef UNION
2173 {
2174 	extern int (**union_vnodeop_p)();
2175 	extern struct vnode *union_dircache __P((struct vnode *));
2176 
2177 	if ((SCARG(uap, count) == auio.uio_resid) &&
2178 	    (vp->v_op == union_vnodeop_p)) {
2179 		struct vnode *lvp;
2180 
2181 		lvp = union_dircache(vp);
2182 		if (lvp != NULLVP) {
2183 			struct vattr va;
2184 
2185 			/*
2186 			 * If the directory is opaque,
2187 			 * then don't show lower entries
2188 			 */
2189 			error = VOP_GETATTR(vp, &va, fp->f_cred, p);
2190 			if (va.va_flags & OPAQUE) {
2191 				vput(lvp);
2192 				lvp = NULL;
2193 			}
2194 		}
2195 
2196 		if (lvp != NULLVP) {
2197 			error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
2198 			VOP_UNLOCK(lvp);
2199 
2200 			if (error) {
2201 				vrele(lvp);
2202 				return (error);
2203 			}
2204 			fp->f_data = (caddr_t) lvp;
2205 			fp->f_offset = 0;
2206 			error = vn_close(vp, FREAD, fp->f_cred, p);
2207 			if (error)
2208 				return (error);
2209 			vp = lvp;
2210 			goto unionread;
2211 		}
2212 	}
2213 }
2214 #endif /* UNION */
2215 
2216 	if ((SCARG(uap, count) == auio.uio_resid) &&
2217 	    (vp->v_flag & VROOT) &&
2218 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
2219 		struct vnode *tvp = vp;
2220 		vp = vp->v_mount->mnt_vnodecovered;
2221 		VREF(vp);
2222 		fp->f_data = (caddr_t) vp;
2223 		fp->f_offset = 0;
2224 		vrele(tvp);
2225 		goto unionread;
2226 	}
2227 	error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2228 	    sizeof(long));
2229 	*retval = SCARG(uap, count) - auio.uio_resid;
2230 	return (error);
2231 }
2232 #endif /* COMPAT_43 */
2233 
2234 /*
2235  * Read a block of directory entries in a file system independent format.
2236  */
2237 int
2238 getdirentries(p, uap, retval)
2239 	struct proc *p;
2240 	register struct getdirentries_args /* {
2241 		syscallarg(int) fd;
2242 		syscallarg(char *) buf;
2243 		syscallarg(u_int) count;
2244 		syscallarg(long *) basep;
2245 	} */ *uap;
2246 	register_t *retval;
2247 {
2248 	register struct vnode *vp;
2249 	struct file *fp;
2250 	struct uio auio;
2251 	struct iovec aiov;
2252 	long loff;
2253 	int error, eofflag;
2254 
2255 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2256 		return (error);
2257 	if ((fp->f_flag & FREAD) == 0)
2258 		return (EBADF);
2259 	vp = (struct vnode *)fp->f_data;
2260 unionread:
2261 	if (vp->v_type != VDIR)
2262 		return (EINVAL);
2263 	aiov.iov_base = SCARG(uap, buf);
2264 	aiov.iov_len = SCARG(uap, count);
2265 	auio.uio_iov = &aiov;
2266 	auio.uio_iovcnt = 1;
2267 	auio.uio_rw = UIO_READ;
2268 	auio.uio_segflg = UIO_USERSPACE;
2269 	auio.uio_procp = p;
2270 	auio.uio_resid = SCARG(uap, count);
2271 	VOP_LOCK(vp);
2272 	loff = auio.uio_offset = fp->f_offset;
2273 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
2274 			    (int *)0, (u_long *)0);
2275 	fp->f_offset = auio.uio_offset;
2276 	VOP_UNLOCK(vp);
2277 	if (error)
2278 		return (error);
2279 
2280 #ifdef UNION
2281 {
2282 	extern int (**union_vnodeop_p)();
2283 	extern struct vnode *union_dircache __P((struct vnode *));
2284 
2285 	if ((SCARG(uap, count) == auio.uio_resid) &&
2286 	    (vp->v_op == union_vnodeop_p)) {
2287 		struct vnode *lvp;
2288 
2289 		lvp = union_dircache(vp);
2290 		if (lvp != NULLVP) {
2291 			struct vattr va;
2292 
2293 			/*
2294 			 * If the directory is opaque,
2295 			 * then don't show lower entries
2296 			 */
2297 			error = VOP_GETATTR(vp, &va, fp->f_cred, p);
2298 			if (va.va_flags & OPAQUE) {
2299 				vput(lvp);
2300 				lvp = NULL;
2301 			}
2302 		}
2303 
2304 		if (lvp != NULLVP) {
2305 			error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
2306 			VOP_UNLOCK(lvp);
2307 
2308 			if (error) {
2309 				vrele(lvp);
2310 				return (error);
2311 			}
2312 			fp->f_data = (caddr_t) lvp;
2313 			fp->f_offset = 0;
2314 			error = vn_close(vp, FREAD, fp->f_cred, p);
2315 			if (error)
2316 				return (error);
2317 			vp = lvp;
2318 			goto unionread;
2319 		}
2320 	}
2321 }
2322 #endif /* UNION */
2323 
2324 	if ((SCARG(uap, count) == auio.uio_resid) &&
2325 	    (vp->v_flag & VROOT) &&
2326 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
2327 		struct vnode *tvp = vp;
2328 		vp = vp->v_mount->mnt_vnodecovered;
2329 		VREF(vp);
2330 		fp->f_data = (caddr_t) vp;
2331 		fp->f_offset = 0;
2332 		vrele(tvp);
2333 		goto unionread;
2334 	}
2335 	error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2336 	    sizeof(long));
2337 	*retval = SCARG(uap, count) - auio.uio_resid;
2338 	return (error);
2339 }
2340 
2341 /*
2342  * Set the mode mask for creation of filesystem nodes.
2343  */
2344 int
2345 umask(p, uap, retval)
2346 	struct proc *p;
2347 	struct umask_args /* {
2348 		syscallarg(int) newmask;
2349 	} */ *uap;
2350 	register_t *retval;
2351 {
2352 	register struct filedesc *fdp;
2353 
2354 	fdp = p->p_fd;
2355 	*retval = fdp->fd_cmask;
2356 	fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
2357 	return (0);
2358 }
2359 
2360 /*
2361  * Void all references to file by ripping underlying filesystem
2362  * away from vnode.
2363  */
2364 /* ARGSUSED */
2365 int
2366 revoke(p, uap, retval)
2367 	struct proc *p;
2368 	register struct revoke_args /* {
2369 		syscallarg(char *) path;
2370 	} */ *uap;
2371 	register_t *retval;
2372 {
2373 	register struct vnode *vp;
2374 	struct vattr vattr;
2375 	int error;
2376 	struct nameidata nd;
2377 
2378 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2379 	if (error = namei(&nd))
2380 		return (error);
2381 	vp = nd.ni_vp;
2382 	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2383 		goto out;
2384 	if (p->p_ucred->cr_uid != vattr.va_uid &&
2385 	    (error = suser(p->p_ucred, &p->p_acflag)))
2386 		goto out;
2387 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2388 		VOP_REVOKE(vp, REVOKEALL);
2389 out:
2390 	vrele(vp);
2391 	return (error);
2392 }
2393 
2394 /*
2395  * Convert a user file descriptor to a kernel file entry.
2396  */
2397 int
2398 getvnode(fdp, fd, fpp)
2399 	struct filedesc *fdp;
2400 	struct file **fpp;
2401 	int fd;
2402 {
2403 	struct file *fp;
2404 
2405 	if ((u_int)fd >= fdp->fd_nfiles ||
2406 	    (fp = fdp->fd_ofiles[fd]) == NULL)
2407 		return (EBADF);
2408 	if (fp->f_type != DTYPE_VNODE)
2409 		return (EINVAL);
2410 	*fpp = fp;
2411 	return (0);
2412 }
2413