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