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