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