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