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