xref: /original-bsd/sys/kern/vfs_syscalls.c (revision 9a35f7df)
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.39 (Berkeley) 05/20/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 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1519 		error = EROFS;
1520 	else {
1521 		VATTR_NULL(&vattr);
1522 		vattr.va_flags = SCARG(uap, flags);
1523 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1524 	}
1525 	vput(vp);
1526 	return (error);
1527 }
1528 
1529 /*
1530  * Change flags of a file given a file descriptor.
1531  */
1532 /* ARGSUSED */
1533 int
1534 fchflags(p, uap, retval)
1535 	struct proc *p;
1536 	register struct fchflags_args /* {
1537 		syscallarg(int) fd;
1538 		syscallarg(int) flags;
1539 	} */ *uap;
1540 	register_t *retval;
1541 {
1542 	struct vattr vattr;
1543 	struct vnode *vp;
1544 	struct file *fp;
1545 	int error;
1546 
1547 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1548 		return (error);
1549 	vp = (struct vnode *)fp->f_data;
1550 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1551 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1552 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1553 		error = EROFS;
1554 	else {
1555 		VATTR_NULL(&vattr);
1556 		vattr.va_flags = SCARG(uap, flags);
1557 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1558 	}
1559 	VOP_UNLOCK(vp, 0, p);
1560 	return (error);
1561 }
1562 
1563 /*
1564  * Change mode of a file given path name.
1565  */
1566 /* ARGSUSED */
1567 int
1568 chmod(p, uap, retval)
1569 	struct proc *p;
1570 	register struct chmod_args /* {
1571 		syscallarg(char *) path;
1572 		syscallarg(int) mode;
1573 	} */ *uap;
1574 	register_t *retval;
1575 {
1576 	register struct vnode *vp;
1577 	struct vattr vattr;
1578 	int error;
1579 	struct nameidata nd;
1580 
1581 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1582 	if (error = namei(&nd))
1583 		return (error);
1584 	vp = nd.ni_vp;
1585 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1586 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1587 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1588 		error = EROFS;
1589 	else {
1590 		VATTR_NULL(&vattr);
1591 		vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1592 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1593 	}
1594 	vput(vp);
1595 	return (error);
1596 }
1597 
1598 /*
1599  * Change mode of a file given a file descriptor.
1600  */
1601 /* ARGSUSED */
1602 int
1603 fchmod(p, uap, retval)
1604 	struct proc *p;
1605 	register struct fchmod_args /* {
1606 		syscallarg(int) fd;
1607 		syscallarg(int) mode;
1608 	} */ *uap;
1609 	register_t *retval;
1610 {
1611 	struct vattr vattr;
1612 	struct vnode *vp;
1613 	struct file *fp;
1614 	int error;
1615 
1616 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1617 		return (error);
1618 	vp = (struct vnode *)fp->f_data;
1619 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1620 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1621 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1622 		error = EROFS;
1623 	else {
1624 		VATTR_NULL(&vattr);
1625 		vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1626 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1627 	}
1628 	VOP_UNLOCK(vp, 0, p);
1629 	return (error);
1630 }
1631 
1632 /*
1633  * Set ownership given a path name.
1634  */
1635 /* ARGSUSED */
1636 int
1637 chown(p, uap, retval)
1638 	struct proc *p;
1639 	register struct chown_args /* {
1640 		syscallarg(char *) path;
1641 		syscallarg(int) uid;
1642 		syscallarg(int) gid;
1643 	} */ *uap;
1644 	register_t *retval;
1645 {
1646 	register struct vnode *vp;
1647 	struct vattr vattr;
1648 	int error;
1649 	struct nameidata nd;
1650 
1651 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1652 	if (error = namei(&nd))
1653 		return (error);
1654 	vp = nd.ni_vp;
1655 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1656 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1657 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1658 		error = EROFS;
1659 	else {
1660 		VATTR_NULL(&vattr);
1661 		vattr.va_uid = SCARG(uap, uid);
1662 		vattr.va_gid = SCARG(uap, gid);
1663 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1664 	}
1665 	vput(vp);
1666 	return (error);
1667 }
1668 
1669 /*
1670  * Set ownership given a file descriptor.
1671  */
1672 /* ARGSUSED */
1673 int
1674 fchown(p, uap, retval)
1675 	struct proc *p;
1676 	register struct fchown_args /* {
1677 		syscallarg(int) fd;
1678 		syscallarg(int) uid;
1679 		syscallarg(int) gid;
1680 	} */ *uap;
1681 	register_t *retval;
1682 {
1683 	struct vattr vattr;
1684 	struct vnode *vp;
1685 	struct file *fp;
1686 	int error;
1687 
1688 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1689 		return (error);
1690 	vp = (struct vnode *)fp->f_data;
1691 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1692 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1693 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1694 		error = EROFS;
1695 	else {
1696 		VATTR_NULL(&vattr);
1697 		vattr.va_uid = SCARG(uap, uid);
1698 		vattr.va_gid = SCARG(uap, gid);
1699 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1700 	}
1701 	VOP_UNLOCK(vp, 0, p);
1702 	return (error);
1703 }
1704 
1705 /*
1706  * Set the access and modification times of a file.
1707  */
1708 /* ARGSUSED */
1709 int
1710 utimes(p, uap, retval)
1711 	struct proc *p;
1712 	register struct utimes_args /* {
1713 		syscallarg(char *) path;
1714 		syscallarg(struct timeval *) tptr;
1715 	} */ *uap;
1716 	register_t *retval;
1717 {
1718 	register struct vnode *vp;
1719 	struct timeval tv[2];
1720 	struct vattr vattr;
1721 	int error;
1722 	struct nameidata nd;
1723 
1724 	VATTR_NULL(&vattr);
1725 	if (SCARG(uap, tptr) == NULL) {
1726 		microtime(&tv[0]);
1727 		tv[1] = tv[0];
1728 		vattr.va_vaflags |= VA_UTIMES_NULL;
1729 	} else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
1730 	    sizeof (tv)))
1731   		return (error);
1732 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1733 	if (error = namei(&nd))
1734 		return (error);
1735 	vp = nd.ni_vp;
1736 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1737 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1738 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1739 		error = EROFS;
1740 	else {
1741 		vattr.va_atime.ts_sec = tv[0].tv_sec;
1742 		vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;
1743 		vattr.va_mtime.ts_sec = tv[1].tv_sec;
1744 		vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;
1745 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1746 	}
1747 	vput(vp);
1748 	return (error);
1749 }
1750 
1751 /*
1752  * Truncate a file given its path name.
1753  */
1754 /* ARGSUSED */
1755 int
1756 truncate(p, uap, retval)
1757 	struct proc *p;
1758 	register struct truncate_args /* {
1759 		syscallarg(char *) path;
1760 		syscallarg(int) pad;
1761 		syscallarg(off_t) length;
1762 	} */ *uap;
1763 	register_t *retval;
1764 {
1765 	register struct vnode *vp;
1766 	struct vattr vattr;
1767 	int error;
1768 	struct nameidata nd;
1769 
1770 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1771 	if (error = namei(&nd))
1772 		return (error);
1773 	vp = nd.ni_vp;
1774 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1775 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1776 	if (vp->v_type == VDIR)
1777 		error = EISDIR;
1778 	else if ((error = vn_writechk(vp)) == 0 &&
1779 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
1780 		VATTR_NULL(&vattr);
1781 		vattr.va_size = SCARG(uap, length);
1782 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1783 	}
1784 	vput(vp);
1785 	return (error);
1786 }
1787 
1788 /*
1789  * Truncate a file given a file descriptor.
1790  */
1791 /* ARGSUSED */
1792 int
1793 ftruncate(p, uap, retval)
1794 	struct proc *p;
1795 	register struct ftruncate_args /* {
1796 		syscallarg(int) fd;
1797 		syscallarg(int) pad;
1798 		syscallarg(off_t) length;
1799 	} */ *uap;
1800 	register_t *retval;
1801 {
1802 	struct vattr vattr;
1803 	struct vnode *vp;
1804 	struct file *fp;
1805 	int error;
1806 
1807 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1808 		return (error);
1809 	if ((fp->f_flag & FWRITE) == 0)
1810 		return (EINVAL);
1811 	vp = (struct vnode *)fp->f_data;
1812 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1813 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1814 	if (vp->v_type == VDIR)
1815 		error = EISDIR;
1816 	else if ((error = vn_writechk(vp)) == 0) {
1817 		VATTR_NULL(&vattr);
1818 		vattr.va_size = SCARG(uap, length);
1819 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
1820 	}
1821 	VOP_UNLOCK(vp, 0, p);
1822 	return (error);
1823 }
1824 
1825 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1826 /*
1827  * Truncate a file given its path name.
1828  */
1829 /* ARGSUSED */
1830 int
1831 compat_43_truncate(p, uap, retval)
1832 	struct proc *p;
1833 	register struct compat_43_truncate_args /* {
1834 		syscallarg(char *) path;
1835 		syscallarg(long) length;
1836 	} */ *uap;
1837 	register_t *retval;
1838 {
1839 	struct truncate_args /* {
1840 		syscallarg(char *) path;
1841 		syscallarg(int) pad;
1842 		syscallarg(off_t) length;
1843 	} */ nuap;
1844 
1845 	SCARG(&nuap, path) = SCARG(uap, path);
1846 	SCARG(&nuap, length) = SCARG(uap, length);
1847 	return (truncate(p, &nuap, retval));
1848 }
1849 
1850 /*
1851  * Truncate a file given a file descriptor.
1852  */
1853 /* ARGSUSED */
1854 int
1855 compat_43_ftruncate(p, uap, retval)
1856 	struct proc *p;
1857 	register struct compat_43_ftruncate_args /* {
1858 		syscallarg(int) fd;
1859 		syscallarg(long) length;
1860 	} */ *uap;
1861 	register_t *retval;
1862 {
1863 	struct ftruncate_args /* {
1864 		syscallarg(int) fd;
1865 		syscallarg(int) pad;
1866 		syscallarg(off_t) length;
1867 	} */ nuap;
1868 
1869 	SCARG(&nuap, fd) = SCARG(uap, fd);
1870 	SCARG(&nuap, length) = SCARG(uap, length);
1871 	return (ftruncate(p, &nuap, retval));
1872 }
1873 #endif /* COMPAT_43 || COMPAT_SUNOS */
1874 
1875 /*
1876  * Sync an open file.
1877  */
1878 /* ARGSUSED */
1879 int
1880 fsync(p, uap, retval)
1881 	struct proc *p;
1882 	struct fsync_args /* {
1883 		syscallarg(int) fd;
1884 	} */ *uap;
1885 	register_t *retval;
1886 {
1887 	register struct vnode *vp;
1888 	struct file *fp;
1889 	int error;
1890 
1891 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
1892 		return (error);
1893 	vp = (struct vnode *)fp->f_data;
1894 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1895 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
1896 	VOP_UNLOCK(vp, 0, p);
1897 	return (error);
1898 }
1899 
1900 /*
1901  * Rename files.  Source and destination must either both be directories,
1902  * or both not be directories.  If target is a directory, it must be empty.
1903  */
1904 /* ARGSUSED */
1905 int
1906 rename(p, uap, retval)
1907 	struct proc *p;
1908 	register struct rename_args /* {
1909 		syscallarg(char *) from;
1910 		syscallarg(char *) to;
1911 	} */ *uap;
1912 	register_t *retval;
1913 {
1914 	register struct vnode *tvp, *fvp, *tdvp;
1915 	struct nameidata fromnd, tond;
1916 	int error;
1917 
1918 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1919 	    SCARG(uap, from), p);
1920 	if (error = namei(&fromnd))
1921 		return (error);
1922 	fvp = fromnd.ni_vp;
1923 	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1924 	    UIO_USERSPACE, SCARG(uap, to), p);
1925 	if (error = namei(&tond)) {
1926 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1927 		vrele(fromnd.ni_dvp);
1928 		vrele(fvp);
1929 		goto out1;
1930 	}
1931 	tdvp = tond.ni_dvp;
1932 	tvp = tond.ni_vp;
1933 	if (tvp != NULL) {
1934 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1935 			error = ENOTDIR;
1936 			goto out;
1937 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1938 			error = EISDIR;
1939 			goto out;
1940 		}
1941 	}
1942 	if (fvp == tdvp)
1943 		error = EINVAL;
1944 	/*
1945 	 * If source is the same as the destination (that is the
1946 	 * same inode number with the same name in the same directory),
1947 	 * then there is nothing to do.
1948 	 */
1949 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1950 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1951 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1952 	      fromnd.ni_cnd.cn_namelen))
1953 		error = -1;
1954 out:
1955 	if (!error) {
1956 		VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
1957 		if (fromnd.ni_dvp != tdvp)
1958 			VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1959 		if (tvp)
1960 			VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
1961 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1962 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1963 	} else {
1964 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1965 		if (tdvp == tvp)
1966 			vrele(tdvp);
1967 		else
1968 			vput(tdvp);
1969 		if (tvp)
1970 			vput(tvp);
1971 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1972 		vrele(fromnd.ni_dvp);
1973 		vrele(fvp);
1974 	}
1975 	vrele(tond.ni_startdir);
1976 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
1977 out1:
1978 	if (fromnd.ni_startdir)
1979 		vrele(fromnd.ni_startdir);
1980 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1981 	if (error == -1)
1982 		return (0);
1983 	return (error);
1984 }
1985 
1986 /*
1987  * Make a directory file.
1988  */
1989 /* ARGSUSED */
1990 int
1991 mkdir(p, uap, retval)
1992 	struct proc *p;
1993 	register struct mkdir_args /* {
1994 		syscallarg(char *) path;
1995 		syscallarg(int) mode;
1996 	} */ *uap;
1997 	register_t *retval;
1998 {
1999 	register struct vnode *vp;
2000 	struct vattr vattr;
2001 	int error;
2002 	struct nameidata nd;
2003 
2004 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
2005 	if (error = namei(&nd))
2006 		return (error);
2007 	vp = nd.ni_vp;
2008 	if (vp != NULL) {
2009 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2010 		if (nd.ni_dvp == vp)
2011 			vrele(nd.ni_dvp);
2012 		else
2013 			vput(nd.ni_dvp);
2014 		vrele(vp);
2015 		return (EEXIST);
2016 	}
2017 	VATTR_NULL(&vattr);
2018 	vattr.va_type = VDIR;
2019 	vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2020 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2021 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2022 	if (!error)
2023 		vput(nd.ni_vp);
2024 	return (error);
2025 }
2026 
2027 /*
2028  * Remove a directory file.
2029  */
2030 /* ARGSUSED */
2031 int
2032 rmdir(p, uap, retval)
2033 	struct proc *p;
2034 	struct rmdir_args /* {
2035 		syscallarg(char *) path;
2036 	} */ *uap;
2037 	register_t *retval;
2038 {
2039 	register struct vnode *vp;
2040 	int error;
2041 	struct nameidata nd;
2042 
2043 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2044 	    SCARG(uap, path), p);
2045 	if (error = namei(&nd))
2046 		return (error);
2047 	vp = nd.ni_vp;
2048 	if (vp->v_type != VDIR) {
2049 		error = ENOTDIR;
2050 		goto out;
2051 	}
2052 	/*
2053 	 * No rmdir "." please.
2054 	 */
2055 	if (nd.ni_dvp == vp) {
2056 		error = EINVAL;
2057 		goto out;
2058 	}
2059 	/*
2060 	 * The root of a mounted filesystem cannot be deleted.
2061 	 */
2062 	if (vp->v_flag & VROOT)
2063 		error = EBUSY;
2064 out:
2065 	if (!error) {
2066 		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2067 		VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2068 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2069 	} else {
2070 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2071 		if (nd.ni_dvp == vp)
2072 			vrele(nd.ni_dvp);
2073 		else
2074 			vput(nd.ni_dvp);
2075 		vput(vp);
2076 	}
2077 	return (error);
2078 }
2079 
2080 #ifdef COMPAT_43
2081 /*
2082  * Read a block of directory entries in a file system independent format.
2083  */
2084 int
2085 compat_43_getdirentries(p, uap, retval)
2086 	struct proc *p;
2087 	register struct compat_43_getdirentries_args /* {
2088 		syscallarg(int) fd;
2089 		syscallarg(char *) buf;
2090 		syscallarg(u_int) count;
2091 		syscallarg(long *) basep;
2092 	} */ *uap;
2093 	register_t *retval;
2094 {
2095 	register struct vnode *vp;
2096 	struct file *fp;
2097 	struct uio auio, kuio;
2098 	struct iovec aiov, kiov;
2099 	struct dirent *dp, *edp;
2100 	caddr_t dirbuf;
2101 	int error, eofflag, readcnt;
2102 	long loff;
2103 
2104 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2105 		return (error);
2106 	if ((fp->f_flag & FREAD) == 0)
2107 		return (EBADF);
2108 	vp = (struct vnode *)fp->f_data;
2109 unionread:
2110 	if (vp->v_type != VDIR)
2111 		return (EINVAL);
2112 	aiov.iov_base = SCARG(uap, buf);
2113 	aiov.iov_len = SCARG(uap, count);
2114 	auio.uio_iov = &aiov;
2115 	auio.uio_iovcnt = 1;
2116 	auio.uio_rw = UIO_READ;
2117 	auio.uio_segflg = UIO_USERSPACE;
2118 	auio.uio_procp = p;
2119 	auio.uio_resid = SCARG(uap, count);
2120 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2121 	loff = auio.uio_offset = fp->f_offset;
2122 #	if (BYTE_ORDER != LITTLE_ENDIAN)
2123 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
2124 			error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
2125 			    (int *)0, (u_long *)0);
2126 			fp->f_offset = auio.uio_offset;
2127 		} else
2128 #	endif
2129 	{
2130 		kuio = auio;
2131 		kuio.uio_iov = &kiov;
2132 		kuio.uio_segflg = UIO_SYSSPACE;
2133 		kiov.iov_len = SCARG(uap, count);
2134 		MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
2135 		kiov.iov_base = dirbuf;
2136 		error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
2137 			    (int *)0, (u_long *)0);
2138 		fp->f_offset = kuio.uio_offset;
2139 		if (error == 0) {
2140 			readcnt = SCARG(uap, count) - kuio.uio_resid;
2141 			edp = (struct dirent *)&dirbuf[readcnt];
2142 			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
2143 #				if (BYTE_ORDER == LITTLE_ENDIAN)
2144 					/*
2145 					 * The expected low byte of
2146 					 * dp->d_namlen is our dp->d_type.
2147 					 * The high MBZ byte of dp->d_namlen
2148 					 * is our dp->d_namlen.
2149 					 */
2150 					dp->d_type = dp->d_namlen;
2151 					dp->d_namlen = 0;
2152 #				else
2153 					/*
2154 					 * The dp->d_type is the high byte
2155 					 * of the expected dp->d_namlen,
2156 					 * so must be zero'ed.
2157 					 */
2158 					dp->d_type = 0;
2159 #				endif
2160 				if (dp->d_reclen > 0) {
2161 					dp = (struct dirent *)
2162 					    ((char *)dp + dp->d_reclen);
2163 				} else {
2164 					error = EIO;
2165 					break;
2166 				}
2167 			}
2168 			if (dp >= edp)
2169 				error = uiomove(dirbuf, readcnt, &auio);
2170 		}
2171 		FREE(dirbuf, M_TEMP);
2172 	}
2173 	VOP_UNLOCK(vp, 0, p);
2174 	if (error)
2175 		return (error);
2176 
2177 #ifdef UNION
2178 {
2179 	extern int (**union_vnodeop_p)();
2180 	extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
2181 
2182 	if ((SCARG(uap, count) == auio.uio_resid) &&
2183 	    (vp->v_op == union_vnodeop_p)) {
2184 		struct vnode *lvp;
2185 
2186 		lvp = union_dircache(vp, p);
2187 		if (lvp != NULLVP) {
2188 			struct vattr va;
2189 
2190 			/*
2191 			 * If the directory is opaque,
2192 			 * then don't show lower entries
2193 			 */
2194 			error = VOP_GETATTR(vp, &va, fp->f_cred, p);
2195 			if (va.va_flags & OPAQUE) {
2196 				vput(lvp);
2197 				lvp = NULL;
2198 			}
2199 		}
2200 
2201 		if (lvp != NULLVP) {
2202 			error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
2203 			if (error) {
2204 				vput(lvp);
2205 				return (error);
2206 			}
2207 			VOP_UNLOCK(lvp, 0, p);
2208 			fp->f_data = (caddr_t) lvp;
2209 			fp->f_offset = 0;
2210 			error = vn_close(vp, FREAD, fp->f_cred, p);
2211 			if (error)
2212 				return (error);
2213 			vp = lvp;
2214 			goto unionread;
2215 		}
2216 	}
2217 }
2218 #endif /* UNION */
2219 
2220 	if ((SCARG(uap, count) == auio.uio_resid) &&
2221 	    (vp->v_flag & VROOT) &&
2222 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
2223 		struct vnode *tvp = vp;
2224 		vp = vp->v_mount->mnt_vnodecovered;
2225 		VREF(vp);
2226 		fp->f_data = (caddr_t) vp;
2227 		fp->f_offset = 0;
2228 		vrele(tvp);
2229 		goto unionread;
2230 	}
2231 	error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2232 	    sizeof(long));
2233 	*retval = SCARG(uap, count) - auio.uio_resid;
2234 	return (error);
2235 }
2236 #endif /* COMPAT_43 */
2237 
2238 /*
2239  * Read a block of directory entries in a file system independent format.
2240  */
2241 int
2242 getdirentries(p, uap, retval)
2243 	struct proc *p;
2244 	register struct getdirentries_args /* {
2245 		syscallarg(int) fd;
2246 		syscallarg(char *) buf;
2247 		syscallarg(u_int) count;
2248 		syscallarg(long *) basep;
2249 	} */ *uap;
2250 	register_t *retval;
2251 {
2252 	register struct vnode *vp;
2253 	struct file *fp;
2254 	struct uio auio;
2255 	struct iovec aiov;
2256 	long loff;
2257 	int error, eofflag;
2258 
2259 	if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
2260 		return (error);
2261 	if ((fp->f_flag & FREAD) == 0)
2262 		return (EBADF);
2263 	vp = (struct vnode *)fp->f_data;
2264 unionread:
2265 	if (vp->v_type != VDIR)
2266 		return (EINVAL);
2267 	aiov.iov_base = SCARG(uap, buf);
2268 	aiov.iov_len = SCARG(uap, count);
2269 	auio.uio_iov = &aiov;
2270 	auio.uio_iovcnt = 1;
2271 	auio.uio_rw = UIO_READ;
2272 	auio.uio_segflg = UIO_USERSPACE;
2273 	auio.uio_procp = p;
2274 	auio.uio_resid = SCARG(uap, count);
2275 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2276 	loff = auio.uio_offset = fp->f_offset;
2277 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
2278 			    (int *)0, (u_long *)0);
2279 	fp->f_offset = auio.uio_offset;
2280 	VOP_UNLOCK(vp, 0, p);
2281 	if (error)
2282 		return (error);
2283 
2284 #ifdef UNION
2285 {
2286 	extern int (**union_vnodeop_p)();
2287 	extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
2288 
2289 	if ((SCARG(uap, count) == auio.uio_resid) &&
2290 	    (vp->v_op == union_vnodeop_p)) {
2291 		struct vnode *lvp;
2292 
2293 		lvp = union_dircache(vp, p);
2294 		if (lvp != NULLVP) {
2295 			struct vattr va;
2296 
2297 			/*
2298 			 * If the directory is opaque,
2299 			 * then don't show lower entries
2300 			 */
2301 			error = VOP_GETATTR(vp, &va, fp->f_cred, p);
2302 			if (va.va_flags & OPAQUE) {
2303 				vput(lvp);
2304 				lvp = NULL;
2305 			}
2306 		}
2307 
2308 		if (lvp != NULLVP) {
2309 			error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
2310 			if (error) {
2311 				vput(lvp);
2312 				return (error);
2313 			}
2314 			VOP_UNLOCK(lvp, 0, p);
2315 			fp->f_data = (caddr_t) lvp;
2316 			fp->f_offset = 0;
2317 			error = vn_close(vp, FREAD, fp->f_cred, p);
2318 			if (error)
2319 				return (error);
2320 			vp = lvp;
2321 			goto unionread;
2322 		}
2323 	}
2324 }
2325 #endif /* UNION */
2326 
2327 	if ((SCARG(uap, count) == auio.uio_resid) &&
2328 	    (vp->v_flag & VROOT) &&
2329 	    (vp->v_mount->mnt_flag & MNT_UNION)) {
2330 		struct vnode *tvp = vp;
2331 		vp = vp->v_mount->mnt_vnodecovered;
2332 		VREF(vp);
2333 		fp->f_data = (caddr_t) vp;
2334 		fp->f_offset = 0;
2335 		vrele(tvp);
2336 		goto unionread;
2337 	}
2338 	error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
2339 	    sizeof(long));
2340 	*retval = SCARG(uap, count) - auio.uio_resid;
2341 	return (error);
2342 }
2343 
2344 /*
2345  * Set the mode mask for creation of filesystem nodes.
2346  */
2347 int
2348 umask(p, uap, retval)
2349 	struct proc *p;
2350 	struct umask_args /* {
2351 		syscallarg(int) newmask;
2352 	} */ *uap;
2353 	register_t *retval;
2354 {
2355 	register struct filedesc *fdp;
2356 
2357 	fdp = p->p_fd;
2358 	*retval = fdp->fd_cmask;
2359 	fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
2360 	return (0);
2361 }
2362 
2363 /*
2364  * Void all references to file by ripping underlying filesystem
2365  * away from vnode.
2366  */
2367 /* ARGSUSED */
2368 int
2369 revoke(p, uap, retval)
2370 	struct proc *p;
2371 	register struct revoke_args /* {
2372 		syscallarg(char *) path;
2373 	} */ *uap;
2374 	register_t *retval;
2375 {
2376 	register struct vnode *vp;
2377 	struct vattr vattr;
2378 	int error;
2379 	struct nameidata nd;
2380 
2381 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2382 	if (error = namei(&nd))
2383 		return (error);
2384 	vp = nd.ni_vp;
2385 	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
2386 		goto out;
2387 	if (p->p_ucred->cr_uid != vattr.va_uid &&
2388 	    (error = suser(p->p_ucred, &p->p_acflag)))
2389 		goto out;
2390 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
2391 		VOP_REVOKE(vp, REVOKEALL);
2392 out:
2393 	vrele(vp);
2394 	return (error);
2395 }
2396 
2397 /*
2398  * Convert a user file descriptor to a kernel file entry.
2399  */
2400 int
2401 getvnode(fdp, fd, fpp)
2402 	struct filedesc *fdp;
2403 	struct file **fpp;
2404 	int fd;
2405 {
2406 	struct file *fp;
2407 
2408 	if ((u_int)fd >= fdp->fd_nfiles ||
2409 	    (fp = fdp->fd_ofiles[fd]) == NULL)
2410 		return (EBADF);
2411 	if (fp->f_type != DTYPE_VNODE)
2412 		return (EINVAL);
2413 	*fpp = fp;
2414 	return (0);
2415 }
2416