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