1 /**	$MirOS: src/sys/kern/vfs_syscalls.c,v 1.8 2007/05/19 21:31:57 tg Exp $ */
2 /*	$OpenBSD: vfs_syscalls.c,v 1.125 2005/06/17 20:39:14 millert Exp $	*/
3 /*	$NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $	*/
4 
5 /*
6  * Copyright (c) 1989, 1993
7  *	The Regents of the University of California.  All rights reserved.
8  * (c) UNIX System Laboratories, Inc.
9  * All or some portions of this file are derived from material licensed
10  * to the University of California by American Telephone and Telegraph
11  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
12  * the permission of UNIX System Laboratories, Inc.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)vfs_syscalls.c	8.28 (Berkeley) 12/10/94
39  */
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/namei.h>
44 #include <sys/filedesc.h>
45 #include <sys/kernel.h>
46 #include <sys/file.h>
47 #include <sys/stat.h>
48 #include <sys/vnode.h>
49 #include <sys/mount.h>
50 #include <sys/proc.h>
51 #include <sys/uio.h>
52 #include <sys/malloc.h>
53 #include <sys/pool.h>
54 #include <sys/dirent.h>
55 
56 #include <sys/syscallargs.h>
57 
58 #include <uvm/uvm_extern.h>
59 #include <sys/sysctl.h>
60 
61 extern int suid_clear;
62 int	usermount = 0;		/* sysctl: by default, users may not mount */
63 
64 static int change_dir(struct nameidata *, struct proc *);
65 
66 void checkdirs(struct vnode *);
67 
68 /*
69  * Virtual File System System Calls
70  */
71 
72 /*
73  * Mount a file system.
74  */
75 /* ARGSUSED */
76 int
sys_mount(p,v,retval)77 sys_mount(p, v, retval)
78 	struct proc *p;
79 	void *v;
80 	register_t *retval;
81 {
82 	struct sys_mount_args /* {
83 		syscallarg(const char *) type;
84 		syscallarg(const char *) path;
85 		syscallarg(int) flags;
86 		syscallarg(void *) data;
87 	} */ *uap = v;
88 	struct vnode *vp;
89 	struct mount *mp;
90 	int error, flag = 0;
91 #ifdef COMPAT_43
92 	u_long fstypenum = 0;
93 #endif
94 	char fstypename[MFSNAMELEN];
95 	char fspath[MNAMELEN];
96 	struct vattr va;
97 	struct nameidata nd;
98 	struct vfsconf *vfsp;
99 
100 	if (securelevel > 1)
101 		return (EAUTH);
102 
103 	if (usermount == 0 && (error = suser(p, 0)))
104 		return (error);
105 
106 	/*
107 	 * Mount points must fit in MNAMELEN, not MAXPATHLEN.
108 	 */
109 	error = copyinstr(SCARG(uap, path), fspath, MNAMELEN, NULL);
110 	if (error)
111 		return(error);
112 
113 	/*
114 	 * Get vnode to be covered
115 	 */
116 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, p);
117 	if ((error = namei(&nd)) != 0)
118 		return (error);
119 	vp = nd.ni_vp;
120 	if (SCARG(uap, flags) & MNT_UPDATE) {
121 		if ((vp->v_flag & VROOT) == 0) {
122 			vput(vp);
123 			return (EINVAL);
124 		}
125 		mp = vp->v_mount;
126 		flag = mp->mnt_flag;
127 		/*
128 		 * We only allow the filesystem to be reloaded if it
129 		 * is currently mounted read-only.
130 		 */
131 		if ((SCARG(uap, flags) & MNT_RELOAD) &&
132 		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
133 			vput(vp);
134 			return (EOPNOTSUPP);	/* Needs translation */
135 		}
136 		mp->mnt_flag |=
137 		    SCARG(uap, flags) & (MNT_RELOAD | MNT_UPDATE);
138 		/*
139 		 * Only root, or the user that did the original mount is
140 		 * permitted to update it.
141 		 */
142 		if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
143 		    (error = suser(p, 0))) {
144 			vput(vp);
145 			return (error);
146 		}
147 		/*
148 		 * Do not allow NFS export by non-root users. Silently
149 		 * enforce MNT_NOSUID and MNT_NODEV for non-root users, and
150 		 * inherit MNT_NOEXEC from the mount point.
151 		 */
152 		if (p->p_ucred->cr_uid != 0) {
153 			if (SCARG(uap, flags) & MNT_EXPORTED) {
154 				vput(vp);
155 				return (EPERM);
156 			}
157 			SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
158 			if (flag & MNT_NOEXEC)
159 				SCARG(uap, flags) |= MNT_NOEXEC;
160 		}
161 		if ((error = vfs_busy(mp, LK_NOWAIT, 0, p)) != 0) {
162 			vput(vp);
163 			return (error);
164 		}
165 		VOP_UNLOCK(vp, 0, p);
166 		goto update;
167 	}
168 	/*
169 	 * If the user is not root, ensure that they own the directory
170 	 * onto which we are attempting to mount.
171 	 */
172 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
173 	    (va.va_uid != p->p_ucred->cr_uid &&
174 	    (error = suser(p, 0)))) {
175 		vput(vp);
176 		return (error);
177 	}
178 	/*
179 	 * Do not allow NFS export by non-root users. Silently
180 	 * enforce MNT_NOSUID and MNT_NODEV for non-root users, and inherit
181 	 * MNT_NOEXEC from the mount point.
182 	 */
183 	if (p->p_ucred->cr_uid != 0) {
184 		if (SCARG(uap, flags) & MNT_EXPORTED) {
185 			vput(vp);
186 			return (EPERM);
187 		}
188 		SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
189 		if (vp->v_mount->mnt_flag & MNT_NOEXEC)
190 			SCARG(uap, flags) |= MNT_NOEXEC;
191 	}
192 	if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) {
193 		vput(vp);
194 		return (error);
195 	}
196 	if (vp->v_type != VDIR) {
197 		vput(vp);
198 		return (ENOTDIR);
199 	}
200 	error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL);
201 	if (error) {
202 #ifdef COMPAT_43
203 		/*
204 		 * Historically filesystem types were identified by number.
205 		 * If we get an integer for the filesystem type instead of a
206 		 * string, we check to see if it matches one of the historic
207 		 * filesystem types.
208 		 */
209 		fstypenum = (u_long)SCARG(uap, type);
210 
211 		for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
212 			if (vfsp->vfc_typenum == fstypenum)
213 				break;
214 		if (vfsp == NULL) {
215 			vput(vp);
216 			return (ENODEV);
217 		}
218 		strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
219 
220 #else
221 		vput(vp);
222 		return (error);
223 #endif
224 	}
225 	for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
226 		if (!strcmp(vfsp->vfc_name, fstypename))
227 			break;
228 	}
229 
230 	if (vfsp == NULL) {
231 		vput(vp);
232 		return (EOPNOTSUPP);
233 	}
234 
235 	if (vp->v_mountedhere != NULL) {
236 		vput(vp);
237 		return (EBUSY);
238 	}
239 
240 	/*
241 	 * Allocate and initialize the file system.
242 	 */
243 	mp = (struct mount *)malloc((u_long)sizeof(struct mount),
244 		M_MOUNT, M_WAITOK);
245 	bzero((char *)mp, (u_long)sizeof(struct mount));
246 	lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
247 	/* This error never happens, but it makes auditing easier */
248 	if ((error = vfs_busy(mp, LK_NOWAIT, 0, p)))
249 		return (error);
250 	mp->mnt_op = vfsp->vfc_vfsops;
251 	mp->mnt_vfc = vfsp;
252 	mp->mnt_flag |= (vfsp->vfc_flags & MNT_VISFLAGMASK);
253 	strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
254 	mp->mnt_vnodecovered = vp;
255 	mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
256 update:
257 	/*
258 	 * Set the mount level flags.
259 	 */
260 	if (SCARG(uap, flags) & MNT_RDONLY)
261 		mp->mnt_flag |= MNT_RDONLY;
262 	else if (mp->mnt_flag & MNT_RDONLY)
263 		mp->mnt_flag |= MNT_WANTRDWR;
264 	mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
265 	    MNT_SYNCHRONOUS | MNT_ASYNC | MNT_SOFTDEP | MNT_NOATIME |
266 	    MNT_FORCE);
267 	mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
268 	    MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_SOFTDEP |
269 	    MNT_NOATIME | MNT_FORCE);
270 	/*
271 	 * Mount the filesystem.
272 	 */
273 	error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
274 	if (!error) {
275 		mp->mnt_stat.f_ctime = time.tv_sec; /* XXX uint32_t vs time_t */
276 	}
277 	if (mp->mnt_flag & MNT_UPDATE) {
278 		vrele(vp);
279 		if (mp->mnt_flag & MNT_WANTRDWR)
280 			mp->mnt_flag &= ~MNT_RDONLY;
281 		mp->mnt_flag &=~
282 		    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
283 		if (error)
284 			mp->mnt_flag = flag;
285 
286 		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
287 			if (mp->mnt_syncer == NULL)
288 				error = vfs_allocate_syncvnode(mp);
289 		} else {
290 			if (mp->mnt_syncer != NULL)
291 				vgone(mp->mnt_syncer);
292 			mp->mnt_syncer = NULL;
293 		}
294 
295 		vfs_unbusy(mp, p);
296 		return (error);
297 	}
298 
299 	vp->v_mountedhere = mp;
300 
301 	/*
302 	 * Put the new filesystem on the mount list after root.
303 	 */
304 	cache_purge(vp);
305 	if (!error) {
306 		vfsp->vfc_refcount++;
307 		simple_lock(&mountlist_slock);
308 		CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
309 		simple_unlock(&mountlist_slock);
310 		checkdirs(vp);
311 		VOP_UNLOCK(vp, 0, p);
312 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
313 			error = vfs_allocate_syncvnode(mp);
314 		vfs_unbusy(mp, p);
315 		(void) VFS_STATFS(mp, &mp->mnt_stat, p);
316 		if ((error = VFS_START(mp, 0, p)) != 0)
317 			vrele(vp);
318 	} else {
319 		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
320 		vfs_unbusy(mp, p);
321 		free(mp, M_MOUNT);
322 		vput(vp);
323 	}
324 	return (error);
325 }
326 
327 /*
328  * Scan all active processes to see if any of them have a current
329  * or root directory onto which the new filesystem has just been
330  * mounted. If so, replace them with the new mount point.
331  */
332 void
checkdirs(olddp)333 checkdirs(olddp)
334 	struct vnode *olddp;
335 {
336 	struct filedesc *fdp;
337 	struct vnode *newdp;
338 	struct proc *p;
339 
340 	if (olddp->v_usecount == 1)
341 		return;
342 	if (VFS_ROOT(olddp->v_mountedhere, &newdp))
343 		panic("mount: lost mount");
344 	for (p = LIST_FIRST(&allproc); p != 0; p = LIST_NEXT(p, p_list)) {
345 		fdp = p->p_fd;
346 		if (fdp->fd_cdir == olddp) {
347 			vrele(fdp->fd_cdir);
348 			VREF(newdp);
349 			fdp->fd_cdir = newdp;
350 		}
351 		if (fdp->fd_rdir == olddp) {
352 			vrele(fdp->fd_rdir);
353 			VREF(newdp);
354 			fdp->fd_rdir = newdp;
355 		}
356 	}
357 	if (rootvnode == olddp) {
358 		vrele(rootvnode);
359 		VREF(newdp);
360 		rootvnode = newdp;
361 	}
362 	vput(newdp);
363 }
364 
365 /*
366  * Unmount a file system.
367  *
368  * Note: unmount takes a path to the vnode mounted on as argument,
369  * not special file (as before).
370  */
371 /* ARGSUSED */
372 int
sys_unmount(p,v,retval)373 sys_unmount(p, v, retval)
374 	struct proc *p;
375 	void *v;
376 	register_t *retval;
377 {
378 	struct sys_unmount_args /* {
379 		syscallarg(const char *) path;
380 		syscallarg(int) flags;
381 	} */ *uap = v;
382 	struct vnode *vp;
383 	struct mount *mp;
384 	int error;
385 	struct nameidata nd;
386 
387 	if (securelevel > 1)
388 		return (EAUTH);
389 
390 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
391 	    SCARG(uap, path), p);
392 	if ((error = namei(&nd)) != 0)
393 		return (error);
394 	vp = nd.ni_vp;
395 	mp = vp->v_mount;
396 
397 	/*
398 	 * Only root, or the user that did the original mount is
399 	 * permitted to unmount this filesystem.
400 	 */
401 	if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
402 	    (error = suser(p, 0))) {
403 		vput(vp);
404 		return (error);
405 	}
406 
407 	/*
408 	 * Don't allow unmounting the root file system.
409 	 */
410 	if (mp->mnt_flag & MNT_ROOTFS) {
411 		vput(vp);
412 		return (EINVAL);
413 	}
414 
415 	/*
416 	 * Must be the root of the filesystem
417 	 */
418 	if ((vp->v_flag & VROOT) == 0) {
419 		vput(vp);
420 		return (EINVAL);
421 	}
422 	vput(vp);
423 
424 	if (vfs_busy(mp, LK_EXCLUSIVE, NULL, p))
425 		return (EBUSY);
426 
427 	return (dounmount(mp, SCARG(uap, flags), p, vp));
428 }
429 
430 /*
431  * Do the actual file system unmount.
432  */
433 int
dounmount(struct mount * mp,int flags,struct proc * p,struct vnode * olddp)434 dounmount(struct mount *mp, int flags, struct proc *p, struct vnode *olddp)
435 {
436 	struct vnode *coveredvp;
437 	int error;
438 	int hadsyncer = 0;
439 
440 	mp->mnt_flag &=~ MNT_ASYNC;
441 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
442 	if (mp->mnt_syncer != NULL) {
443 		hadsyncer = 1;
444 		vgone(mp->mnt_syncer);
445 		mp->mnt_syncer = NULL;
446 	}
447 	if (((mp->mnt_flag & MNT_RDONLY) ||
448 	    (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
449 	    (flags & MNT_FORCE))
450 		error = VFS_UNMOUNT(mp, flags, p);
451 	simple_lock(&mountlist_slock);
452  	if (error && error != EIO && !(flags & MNT_DOOMED)) {
453  		if ((mp->mnt_flag & MNT_RDONLY) == 0 && hadsyncer)
454  			(void) vfs_allocate_syncvnode(mp);
455 		lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK,
456 		    &mountlist_slock, p);
457 		return (error);
458 	}
459 	CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
460 	if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
461 		coveredvp->v_mountedhere = NULL;
462 		vrele(coveredvp);
463 	}
464 	mp->mnt_vfc->vfc_refcount--;
465 	if (!LIST_EMPTY(&mp->mnt_vnodelist))
466 		panic("unmount: dangling vnode");
467 	lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
468 	free(mp, M_MOUNT);
469 	return (0);
470 }
471 
472 /*
473  * Sync each mounted filesystem.
474  */
475 #ifdef DEBUG
476 int syncprt = 0;
477 struct ctldebug debug0 = { "syncprt", &syncprt };
478 #endif
479 
480 /* ARGSUSED */
481 int
sys_sync(p,v,retval)482 sys_sync(p, v, retval)
483 	struct proc *p;
484 	void *v;
485 	register_t *retval;
486 {
487 	struct mount *mp, *nmp;
488 	int asyncflag;
489 
490 	simple_lock(&mountlist_slock);
491 	for (mp = CIRCLEQ_LAST(&mountlist); mp != CIRCLEQ_END(&mountlist);
492 	    mp = nmp) {
493 		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
494 			nmp = CIRCLEQ_PREV(mp, mnt_list);
495 			continue;
496 		}
497 		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
498 			asyncflag = mp->mnt_flag & MNT_ASYNC;
499 			mp->mnt_flag &= ~MNT_ASYNC;
500 			uvm_vnp_sync(mp);
501 			VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
502 			if (asyncflag)
503 				mp->mnt_flag |= MNT_ASYNC;
504 		}
505 		simple_lock(&mountlist_slock);
506 		nmp = CIRCLEQ_PREV(mp, mnt_list);
507 		vfs_unbusy(mp, p);
508 	}
509 	simple_unlock(&mountlist_slock);
510 
511 #ifdef DEBUG
512 	if (syncprt)
513 		vfs_bufstats();
514 #endif /* DEBUG */
515 	return (0);
516 }
517 
518 /*
519  * Change filesystem quotas.
520  */
521 /* ARGSUSED */
522 int
sys_quotactl(p,v,retval)523 sys_quotactl(p, v, retval)
524 	struct proc *p;
525 	void *v;
526 	register_t *retval;
527 {
528 	struct sys_quotactl_args /* {
529 		syscallarg(const char *) path;
530 		syscallarg(int) cmd;
531 		syscallarg(int) uid;
532 		syscallarg(char *) arg;
533 	} */ *uap = v;
534 	struct mount *mp;
535 	int error;
536 	struct nameidata nd;
537 
538 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
539 	if ((error = namei(&nd)) != 0)
540 		return (error);
541 	mp = nd.ni_vp->v_mount;
542 	vrele(nd.ni_vp);
543 	return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
544 	    SCARG(uap, arg), p));
545 }
546 
547 /*
548  * Get filesystem statistics.
549  */
550 /* ARGSUSED */
551 int
sys_statfs(p,v,retval)552 sys_statfs(p, v, retval)
553 	struct proc *p;
554 	void *v;
555 	register_t *retval;
556 {
557 	struct sys_statfs_args /* {
558 		syscallarg(const char *) path;
559 		syscallarg(struct statfs *) buf;
560 	} */ *uap = v;
561 	struct mount *mp;
562 	struct statfs *sp;
563 	int error;
564 	struct nameidata nd;
565 	struct statfs sb;
566 
567 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
568 	if ((error = namei(&nd)) != 0)
569 		return (error);
570 	mp = nd.ni_vp->v_mount;
571 	sp = &mp->mnt_stat;
572 	vrele(nd.ni_vp);
573 	if ((error = VFS_STATFS(mp, sp, p)) != 0)
574 		return (error);
575 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
576 #if notyet
577 	if (mp->mnt_flag & MNT_SOFTDEP)
578 		sp->f_eflags = STATFS_SOFTUPD;
579 #endif
580 	/* Don't let non-root see filesystem id (for NFS security) */
581 	if (suser(p, 0)) {
582 		bcopy(sp, &sb, sizeof(sb));
583 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
584 		sp = &sb;
585 	}
586 	return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
587 }
588 
589 /*
590  * Get filesystem statistics.
591  */
592 /* ARGSUSED */
593 int
sys_fstatfs(p,v,retval)594 sys_fstatfs(p, v, retval)
595 	struct proc *p;
596 	void *v;
597 	register_t *retval;
598 {
599 	struct sys_fstatfs_args /* {
600 		syscallarg(int) fd;
601 		syscallarg(struct statfs *) buf;
602 	} */ *uap = v;
603 	struct file *fp;
604 	struct mount *mp;
605 	struct statfs *sp;
606 	int error;
607 	struct statfs sb;
608 
609 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
610 		return (error);
611 	mp = ((struct vnode *)fp->f_data)->v_mount;
612 	if (!mp) {
613 		FRELE(fp);
614 		return (ENOENT);
615 	}
616 	sp = &mp->mnt_stat;
617 	error = VFS_STATFS(mp, sp, p);
618 	FRELE(fp);
619 	if (error)
620 		return (error);
621 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
622 #if notyet
623 	if (mp->mnt_flag & MNT_SOFTDEP)
624 		sp->f_eflags = STATFS_SOFTUPD;
625 #endif
626 	/* Don't let non-root see filesystem id (for NFS security) */
627 	if (suser(p, 0)) {
628 		bcopy(sp, &sb, sizeof(sb));
629 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
630 		sp = &sb;
631 	}
632 	return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
633 }
634 
635 /*
636  * Get statistics on all filesystems.
637  */
638 int
sys_getfsstat(p,v,retval)639 sys_getfsstat(p, v, retval)
640 	struct proc *p;
641 	void *v;
642 	register_t *retval;
643 {
644 	struct sys_getfsstat_args /* {
645 		syscallarg(struct statfs *) buf;
646 		syscallarg(size_t) bufsize;
647 		syscallarg(int) flags;
648 	} */ *uap = v;
649 	struct mount *mp, *nmp;
650 	struct statfs *sp;
651 	struct statfs sb;
652 	struct statfs *sfsp;
653 	size_t count, maxcount;
654 	int error, flags = SCARG(uap, flags);
655 
656 	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
657 	sfsp = SCARG(uap, buf);
658 	count = 0;
659 	simple_lock(&mountlist_slock);
660 	for (mp = CIRCLEQ_FIRST(&mountlist); mp != CIRCLEQ_END(&mountlist);
661 	    mp = nmp) {
662 		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
663 			nmp = CIRCLEQ_NEXT(mp, mnt_list);
664 			continue;
665 		}
666 		if (sfsp && count < maxcount) {
667 			sp = &mp->mnt_stat;
668 
669 			/* Refresh stats unless MNT_NOWAIT is specified */
670 			if (flags != MNT_NOWAIT &&
671 			    flags != MNT_LAZY &&
672 			    (flags == MNT_WAIT ||
673 			    flags == 0) &&
674 			    (error = VFS_STATFS(mp, sp, p))) {
675 				simple_lock(&mountlist_slock);
676 				nmp = CIRCLEQ_NEXT(mp, mnt_list);
677 				vfs_unbusy(mp, p);
678 				continue;
679 			}
680 
681 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
682 #if notyet
683 			if (mp->mnt_flag & MNT_SOFTDEP)
684 				sp->f_eflags = STATFS_SOFTUPD;
685 #endif
686 			if (suser(p, 0)) {
687 				bcopy(sp, &sb, sizeof(sb));
688 				sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
689 				sp = &sb;
690 			}
691 			error = copyout(sp, sfsp, sizeof(*sp));
692 			if (error) {
693 				vfs_unbusy(mp, p);
694 				return (error);
695 			}
696 			sfsp++;
697 		}
698 		count++;
699 		simple_lock(&mountlist_slock);
700 		nmp = CIRCLEQ_NEXT(mp, mnt_list);
701 		vfs_unbusy(mp, p);
702 	}
703 	simple_unlock(&mountlist_slock);
704 	if (sfsp && count > maxcount)
705 		*retval = maxcount;
706 	else
707 		*retval = count;
708 	return (0);
709 }
710 
711 /*
712  * Change current working directory to a given file descriptor.
713  */
714 /* ARGSUSED */
715 int
sys_fchdir(p,v,retval)716 sys_fchdir(p, v, retval)
717 	struct proc *p;
718 	void *v;
719 	register_t *retval;
720 {
721 	struct sys_fchdir_args /* {
722 		syscallarg(int) fd;
723 	} */ *uap = v;
724 	struct filedesc *fdp = p->p_fd;
725 	struct vnode *vp, *tdp;
726 	struct mount *mp;
727 	struct file *fp;
728 	int error;
729 
730 	if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
731 		return (error);
732 	vp = (struct vnode *)fp->f_data;
733 	VREF(vp);
734 	FRELE(fp);
735 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
736 	if (vp->v_type != VDIR)
737 		error = ENOTDIR;
738 	else
739 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
740 
741 	while (!error && (mp = vp->v_mountedhere) != NULL) {
742 		if (vfs_busy(mp, 0, 0, p))
743 			continue;
744 		error = VFS_ROOT(mp, &tdp);
745 		vfs_unbusy(mp, p);
746 		if (error)
747 			break;
748 		vput(vp);
749 		vp = tdp;
750 	}
751 	if (error) {
752 		vput(vp);
753 		return (error);
754 	}
755 	VOP_UNLOCK(vp, 0, p);
756 	vrele(fdp->fd_cdir);
757 	fdp->fd_cdir = vp;
758 	return (0);
759 }
760 
761 /*
762  * Change current working directory (".").
763  */
764 /* ARGSUSED */
765 int
sys_chdir(p,v,retval)766 sys_chdir(p, v, retval)
767 	struct proc *p;
768 	void *v;
769 	register_t *retval;
770 {
771 	struct sys_chdir_args /* {
772 		syscallarg(const char *) path;
773 	} */ *uap = v;
774 	struct filedesc *fdp = p->p_fd;
775 	int error;
776 	struct nameidata nd;
777 
778 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
779 	    SCARG(uap, path), p);
780 	if ((error = change_dir(&nd, p)) != 0)
781 		return (error);
782 	vrele(fdp->fd_cdir);
783 	fdp->fd_cdir = nd.ni_vp;
784 	return (0);
785 }
786 
787 /*
788  * Change notion of root ("/") directory.
789  */
790 /* ARGSUSED */
791 int
sys_chroot(p,v,retval)792 sys_chroot(p, v, retval)
793 	struct proc *p;
794 	void *v;
795 	register_t *retval;
796 {
797 	struct sys_chroot_args /* {
798 		syscallarg(const char *) path;
799 	} */ *uap = v;
800 	struct filedesc *fdp = p->p_fd;
801 	int error;
802 	struct nameidata nd;
803 
804 	if ((error = suser(p, 0)) != 0)
805 		return (error);
806 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
807 	    SCARG(uap, path), p);
808 	if ((error = change_dir(&nd, p)) != 0)
809 		return (error);
810 	if (fdp->fd_rdir != NULL) {
811 		/*
812 		 * A chroot() done inside a changed root environment does
813 		 * an automatic chdir to avoid the out-of-tree experience.
814 		 */
815 		vrele(fdp->fd_rdir);
816 		vrele(fdp->fd_cdir);
817 		VREF(nd.ni_vp);
818 		fdp->fd_cdir = nd.ni_vp;
819 	}
820 	fdp->fd_rdir = nd.ni_vp;
821 	return (0);
822 }
823 
824 /*
825  * Change notion of root (``/'') directory to a file descriptor.
826  */
827 int
sys_fchroot(p,v,retval)828 sys_fchroot(p, v, retval)
829 	struct proc *p;
830 	void *v;
831 	register_t *retval;
832 {
833 	struct sys_fchroot_args *uap = v;
834 	struct filedesc *fdp = p->p_fd;
835 	struct vnode *vp;
836 	struct file *fp;
837 	int error;
838 
839 	if ((error = suser(p, 0)) != 0)
840 		return (error);
841 	if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
842 		return (error);
843 
844 	vp = (struct vnode *)fp->f_data;
845 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
846 
847 	if (vp->v_type != VDIR)
848 		error = ENOTDIR;
849 	else
850 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
851 
852 	VOP_UNLOCK(vp, 0, p);
853 
854 	if (error)
855 		return (error);
856 
857 	VREF(vp);
858 
859 	if (fdp->fd_rdir != NULL) {
860 		/*
861 		 * A chroot() done inside a changed root environment does
862 		 * an automatic chdir to avoid the out-of-tree experience.
863 		 */
864 		vrele(fdp->fd_rdir);
865 		vrele(fdp->fd_cdir);
866 		VREF(vp);
867 		fdp->fd_cdir = vp;
868 	}
869 
870 	fdp->fd_rdir = vp;
871 	return (0);
872 }
873 
874 /*
875  * Common routine for chroot and chdir.
876  */
877 static int
change_dir(ndp,p)878 change_dir(ndp, p)
879 	struct nameidata *ndp;
880 	struct proc *p;
881 {
882 	struct vnode *vp;
883 	int error;
884 
885 	if ((error = namei(ndp)) != 0)
886 		return (error);
887 	vp = ndp->ni_vp;
888 	if (vp->v_type != VDIR)
889 		error = ENOTDIR;
890 	else
891 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
892 	if (error)
893 		vput(vp);
894 	else
895 		VOP_UNLOCK(vp, 0, p);
896 	return (error);
897 }
898 
899 /*
900  * Check permissions, allocate an open file structure,
901  * and call the device open routine if any.
902  */
903 int
sys_open(p,v,retval)904 sys_open(p, v, retval)
905 	struct proc *p;
906 	void *v;
907 	register_t *retval;
908 {
909 	struct sys_open_args /* {
910 		syscallarg(const char *) path;
911 		syscallarg(int) flags;
912 		syscallarg(mode_t) mode;
913 	} */ *uap = v;
914 	struct filedesc *fdp = p->p_fd;
915 	struct file *fp;
916 	struct vnode *vp;
917 	struct vattr vattr;
918 	int flags, cmode;
919 	int type, indx, error, localtrunc = 0;
920 	struct flock lf;
921 	struct nameidata nd;
922 
923 	fdplock(fdp, p);
924 
925 	if ((error = falloc(p, &fp, &indx)) != 0)
926 		goto out;
927 
928 	flags = FFLAGS(SCARG(uap, flags));
929 	cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
930 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
931 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
932 	if ((flags & O_TRUNC) && (flags & (O_EXLOCK | O_SHLOCK))) {
933 		localtrunc = 1;
934 		flags &= ~O_TRUNC;	/* Must do truncate ourselves */
935 	}
936 	if ((error = vn_open(&nd, flags, cmode)) != 0) {
937 		if ((error == ENODEV || error == ENXIO) &&
938 		    p->p_dupfd >= 0 &&			/* XXX from fdopen */
939 		    (error =
940 			dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
941 			closef(fp, p);
942 			*retval = indx;
943 			goto out;
944 		}
945 		if (error == ERESTART)
946 			error = EINTR;
947 		fdremove(fdp, indx);
948 		closef(fp, p);
949 		goto out;
950 	}
951 	p->p_dupfd = 0;
952 	vp = nd.ni_vp;
953 	fp->f_flag = flags & FMASK;
954 	fp->f_type = DTYPE_VNODE;
955 	fp->f_ops = &vnops;
956 	fp->f_data = vp;
957 	if (flags & (O_EXLOCK | O_SHLOCK)) {
958 		lf.l_whence = SEEK_SET;
959 		lf.l_start = 0;
960 		lf.l_len = 0;
961 		if (flags & O_EXLOCK)
962 			lf.l_type = F_WRLCK;
963 		else
964 			lf.l_type = F_RDLCK;
965 		type = F_FLOCK;
966 		if ((flags & FNONBLOCK) == 0)
967 			type |= F_WAIT;
968 		VOP_UNLOCK(vp, 0, p);
969 		error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
970 		if (error) {
971 			/* closef will vn_close the file for us. */
972 			fdremove(fdp, indx);
973 			closef(fp, p);
974 			goto out;
975 		}
976 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
977 		fp->f_flag |= FHASLOCK;
978 	}
979 	if (localtrunc) {
980 		VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
981 		if ((fp->f_flag & FWRITE) == 0)
982 			error = EACCES;
983 		else if (vp->v_mount->mnt_flag & MNT_RDONLY)
984 			error = EROFS;
985 		else if (vp->v_type == VDIR)
986 			error = EISDIR;
987 		else if ((error = vn_writechk(vp)) == 0) {
988 			VATTR_NULL(&vattr);
989 			vattr.va_size = 0;
990 			error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
991 		}
992 		if (error) {
993 			VOP_UNLOCK(vp, 0, p);
994 			/* closef will close the file for us. */
995 			fdremove(fdp, indx);
996 			closef(fp, p);
997 			goto out;
998 		}
999 	}
1000 	VOP_UNLOCK(vp, 0, p);
1001 	*retval = indx;
1002 	FILE_SET_MATURE(fp);
1003 out:
1004 	fdpunlock(fdp);
1005 	return (error);
1006 }
1007 
1008 /*
1009  * Get file handle system call
1010  */
1011 int
sys_getfh(p,v,retval)1012 sys_getfh(p, v, retval)
1013 	struct proc *p;
1014 	void *v;
1015 	register_t *retval;
1016 {
1017 	struct sys_getfh_args /* {
1018 		syscallarg(const char *) fname;
1019 		syscallarg(fhandle_t *) fhp;
1020 	} */ *uap = v;
1021 	struct vnode *vp;
1022 	fhandle_t fh;
1023 	int error;
1024 	struct nameidata nd;
1025 
1026 	/*
1027 	 * Must be super user
1028 	 */
1029 	error = suser(p, 0);
1030 	if (error)
1031 		return (error);
1032 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1033 	    SCARG(uap, fname), p);
1034 	error = namei(&nd);
1035 	if (error)
1036 		return (error);
1037 	vp = nd.ni_vp;
1038 	bzero(&fh, sizeof(fh));
1039 	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1040 	error = VFS_VPTOFH(vp, &fh.fh_fid);
1041 	vput(vp);
1042 	if (error)
1043 		return (error);
1044 	error = copyout(&fh, SCARG(uap, fhp), sizeof(fh));
1045 	return (error);
1046 }
1047 
1048 /*
1049  * Open a file given a file handle.
1050  *
1051  * Check permissions, allocate an open file structure,
1052  * and call the device open routine if any.
1053  */
1054 int
sys_fhopen(p,v,retval)1055 sys_fhopen(p, v, retval)
1056 	struct proc *p;
1057 	void *v;
1058 	register_t *retval;
1059 {
1060 	struct sys_fhopen_args /* {
1061 		syscallarg(const fhandle_t *) fhp;
1062 		syscallarg(int) flags;
1063 	} */ *uap = v;
1064 	struct filedesc *fdp = p->p_fd;
1065 	struct file *fp;
1066 	struct vnode *vp = NULL;
1067 	struct mount *mp;
1068 	struct ucred *cred = p->p_ucred;
1069 	int flags;
1070 	int type, indx, error=0;
1071 	struct flock lf;
1072 	struct vattr va;
1073 	fhandle_t fh;
1074 
1075 	/*
1076 	 * Must be super user
1077 	 */
1078 	if ((error = suser(p, 0)))
1079 		return (error);
1080 
1081 	flags = FFLAGS(SCARG(uap, flags));
1082 	if ((flags & (FREAD | FWRITE)) == 0)
1083 		return (EINVAL);
1084 	if ((flags & O_CREAT))
1085 		return (EINVAL);
1086 
1087 	fdplock(fdp, p);
1088 	if ((error = falloc(p, &fp, &indx)) != 0) {
1089 		fp = NULL;
1090 		goto bad;
1091 	}
1092 
1093 	if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
1094 		goto bad;
1095 
1096 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
1097 		error = ESTALE;
1098 		goto bad;
1099 	}
1100 
1101 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)) != 0) {
1102 		vp = NULL;	/* most likely unnecessary sanity for bad: */
1103 		goto bad;
1104 	}
1105 
1106 	/* Now do an effective vn_open */
1107 
1108 	if (vp->v_type == VSOCK) {
1109 		error = EOPNOTSUPP;
1110 		goto bad;
1111 	}
1112 	if (flags & FREAD) {
1113 		if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0)
1114 			goto bad;
1115 	}
1116 	if (flags & (FWRITE | O_TRUNC)) {
1117 		if (vp->v_type == VDIR) {
1118 			error = EISDIR;
1119 			goto bad;
1120 		}
1121 		if ((error = vn_writechk(vp)) != 0 ||
1122 		    (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
1123 			goto bad;
1124 	}
1125 	if (flags & O_TRUNC) {
1126 		VOP_UNLOCK(vp, 0, p);				/* XXX */
1127 		VOP_LEASE(vp, p, cred, LEASE_WRITE);
1128 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);	/* XXX */
1129 		VATTR_NULL(&va);
1130 		va.va_size = 0;
1131 		if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
1132 			goto bad;
1133 	}
1134 	if ((error = VOP_OPEN(vp, flags, cred, p)) != 0)
1135 		goto bad;
1136 	if (flags & FWRITE)
1137 		vp->v_writecount++;
1138 
1139 	/* done with modified vn_open, now finish what sys_open does. */
1140 
1141 	fp->f_flag = flags & FMASK;
1142 	fp->f_type = DTYPE_VNODE;
1143 	fp->f_ops = &vnops;
1144 	fp->f_data = vp;
1145 	if (flags & (O_EXLOCK | O_SHLOCK)) {
1146 		lf.l_whence = SEEK_SET;
1147 		lf.l_start = 0;
1148 		lf.l_len = 0;
1149 		if (flags & O_EXLOCK)
1150 			lf.l_type = F_WRLCK;
1151 		else
1152 			lf.l_type = F_RDLCK;
1153 		type = F_FLOCK;
1154 		if ((flags & FNONBLOCK) == 0)
1155 			type |= F_WAIT;
1156 		VOP_UNLOCK(vp, 0, p);
1157 		error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
1158 		if (error) {
1159 			/* closef will vn_close the file for us. */
1160 			fdremove(fdp, indx);
1161 			closef(fp, p);
1162 			return (error);
1163 		}
1164 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1165 		fp->f_flag |= FHASLOCK;
1166 	}
1167 	VOP_UNLOCK(vp, 0, p);
1168 	*retval = indx;
1169 	FILE_SET_MATURE(fp);
1170 
1171 	fdpunlock(fdp);
1172 	return (0);
1173 
1174 bad:
1175 	if (fp) {
1176 		fdremove(fdp, indx);
1177 		closef(fp, p);
1178 		if (vp != NULL)
1179 			vput(vp);
1180 	}
1181 	fdpunlock(fdp);
1182 	return (error);
1183 }
1184 
1185 /* ARGSUSED */
1186 int
sys_fhstat(p,v,retval)1187 sys_fhstat(p, v, retval)
1188 	struct proc *p;
1189 	void *v;
1190 	register_t *retval;
1191 {
1192 	struct sys_fhstat_args /* {
1193 		syscallarg(const fhandle_t *) fhp;
1194 		syscallarg(struct stat *) sb;
1195 	} */ *uap = v;
1196 	struct stat sb;
1197 	int error;
1198 	fhandle_t fh;
1199 	struct mount *mp;
1200 	struct vnode *vp;
1201 
1202 	/*
1203 	 * Must be super user
1204 	 */
1205 	if ((error = suser(p, 0)))
1206 		return (error);
1207 
1208 	if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
1209 		return (error);
1210 
1211 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
1212 		return (ESTALE);
1213 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
1214 		return (error);
1215 	error = vn_stat(vp, &sb, p);
1216 	vput(vp);
1217 	if (error)
1218 		return (error);
1219 	error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
1220 	return (error);
1221 }
1222 
1223 /* ARGSUSED */
1224 int
sys_fhstatfs(p,v,retval)1225 sys_fhstatfs(p, v, retval)
1226 	struct proc *p;
1227 	void *v;
1228 	register_t *retval;
1229 {
1230 	struct sys_fhstatfs_args /*
1231 		syscallarg(const fhandle_t *) fhp;
1232 		syscallarg(struct statfs *) buf;
1233 	} */ *uap = v;
1234 	struct statfs sp;
1235 	fhandle_t fh;
1236 	struct mount *mp;
1237 	struct vnode *vp;
1238 	int error;
1239 
1240 	/*
1241 	 * Must be super user
1242 	 */
1243 	if ((error = suser(p, 0)))
1244 		return (error);
1245 
1246 	if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
1247 		return (error);
1248 
1249 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
1250 		return (ESTALE);
1251 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
1252 		return (error);
1253 	mp = vp->v_mount;
1254 	vput(vp);
1255 	if ((error = VFS_STATFS(mp, &sp, p)) != 0)
1256 		return (error);
1257 	sp.f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1258 	return (copyout(&sp, SCARG(uap, buf), sizeof(sp)));
1259 }
1260 
1261 /*
1262  * Create a special file.
1263  */
1264 /* ARGSUSED */
1265 int
sys_mknod(p,v,retval)1266 sys_mknod(p, v, retval)
1267 	struct proc *p;
1268 	void *v;
1269 	register_t *retval;
1270 {
1271 	struct sys_mknod_args /* {
1272 		syscallarg(const char *) path;
1273 		syscallarg(mode_t) mode;
1274 		syscallarg(int) dev;
1275 	} */ *uap = v;
1276 	struct vnode *vp;
1277 	struct vattr vattr;
1278 	int error;
1279 	struct nameidata nd;
1280 
1281 	if ((error = suser(p, 0)) != 0)
1282 		return (error);
1283 #ifdef	HARD_CHROOT
1284 	if (p->p_fd->fd_rdir)
1285 		return (EINVAL);
1286 #endif
1287 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1288 	if ((error = namei(&nd)) != 0)
1289 		return (error);
1290 	vp = nd.ni_vp;
1291 	if (vp != NULL)
1292 		error = EEXIST;
1293 	else {
1294 		VATTR_NULL(&vattr);
1295 		vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1296 		vattr.va_rdev = SCARG(uap, dev);
1297 
1298 		switch (SCARG(uap, mode) & S_IFMT) {
1299 		case S_IFMT:	/* used by badsect to flag bad sectors */
1300 			vattr.va_type = VBAD;
1301 			break;
1302 		case S_IFCHR:
1303 			vattr.va_type = VCHR;
1304 			break;
1305 		case S_IFBLK:
1306 			vattr.va_type = VBLK;
1307 			break;
1308 		default:
1309 			error = EINVAL;
1310 			break;
1311 		}
1312 	}
1313 	if (!error) {
1314 		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1315 		error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1316 	} else {
1317 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1318 		if (nd.ni_dvp == vp)
1319 			vrele(nd.ni_dvp);
1320 		else
1321 			vput(nd.ni_dvp);
1322 		if (vp)
1323 			vrele(vp);
1324 	}
1325 	return (error);
1326 }
1327 
1328 /*
1329  * Create a named pipe.
1330  */
1331 /* ARGSUSED */
1332 int
sys_mkfifo(p,v,retval)1333 sys_mkfifo(p, v, retval)
1334 	struct proc *p;
1335 	void *v;
1336 	register_t *retval;
1337 {
1338 #ifndef FIFO
1339 	return (EOPNOTSUPP);
1340 #else
1341 	struct sys_mkfifo_args /* {
1342 		syscallarg(const char *) path;
1343 		syscallarg(mode_t) mode;
1344 	} */ *uap = v;
1345 	struct vattr vattr;
1346 	int error;
1347 	struct nameidata nd;
1348 
1349 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1350 	if ((error = namei(&nd)) != 0)
1351 		return (error);
1352 	if (nd.ni_vp != NULL) {
1353 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1354 		if (nd.ni_dvp == nd.ni_vp)
1355 			vrele(nd.ni_dvp);
1356 		else
1357 			vput(nd.ni_dvp);
1358 		vrele(nd.ni_vp);
1359 		return (EEXIST);
1360 	}
1361 	VATTR_NULL(&vattr);
1362 	vattr.va_type = VFIFO;
1363 	vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
1364 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1365 	return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
1366 #endif /* FIFO */
1367 }
1368 
1369 /*
1370  * Make a hard file link.
1371  */
1372 /* ARGSUSED */
1373 int
sys_link(p,v,retval)1374 sys_link(p, v, retval)
1375 	struct proc *p;
1376 	void *v;
1377 	register_t *retval;
1378 {
1379 	struct sys_link_args /* {
1380 		syscallarg(const char *) path;
1381 		syscallarg(const char *) link;
1382 	} */ *uap = v;
1383 	struct vnode *vp;
1384 	struct nameidata nd;
1385 	int error;
1386 	int flags;
1387 
1388 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1389 	if ((error = namei(&nd)) != 0)
1390 		return (error);
1391 	vp = nd.ni_vp;
1392 
1393 	flags = LOCKPARENT;
1394 	if (vp->v_type == VDIR) {
1395 		flags |= STRIPSLASHES;
1396 	}
1397 
1398 	NDINIT(&nd, CREATE, flags, UIO_USERSPACE, SCARG(uap, link), p);
1399 	if ((error = namei(&nd)) != 0)
1400 		goto out;
1401 	if (nd.ni_vp) {
1402 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1403 		if (nd.ni_dvp == nd.ni_vp)
1404 			vrele(nd.ni_dvp);
1405 		else
1406 			vput(nd.ni_dvp);
1407 		vrele(nd.ni_vp);
1408 		error = EEXIST;
1409 		goto out;
1410 	}
1411 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1412 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1413 	error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1414 out:
1415 	vrele(vp);
1416 	return (error);
1417 }
1418 
1419 /*
1420  * Make a symbolic link.
1421  */
1422 /* ARGSUSED */
1423 int
sys_symlink(p,v,retval)1424 sys_symlink(p, v, retval)
1425 	struct proc *p;
1426 	void *v;
1427 	register_t *retval;
1428 {
1429 	struct sys_symlink_args /* {
1430 		syscallarg(const char *) path;
1431 		syscallarg(const char *) link;
1432 	} */ *uap = v;
1433 	struct vattr vattr;
1434 	char *path;
1435 	int error;
1436 	struct nameidata nd;
1437 
1438 	path = pool_get(&namei_pool, PR_WAITOK);
1439 	error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL);
1440 	if (error)
1441 		goto out;
1442 	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
1443 	if ((error = namei(&nd)) != 0)
1444 		goto out;
1445 	if (nd.ni_vp) {
1446 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1447 		if (nd.ni_dvp == nd.ni_vp)
1448 			vrele(nd.ni_dvp);
1449 		else
1450 			vput(nd.ni_dvp);
1451 		vrele(nd.ni_vp);
1452 		error = EEXIST;
1453 		goto out;
1454 	}
1455 	VATTR_NULL(&vattr);
1456 	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
1457 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1458 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1459 out:
1460 	pool_put(&namei_pool, path);
1461 	return (error);
1462 }
1463 
1464 /*
1465  * Delete a name from the filesystem.
1466  */
1467 /* ARGSUSED */
1468 int
sys_unlink(p,v,retval)1469 sys_unlink(p, v, retval)
1470 	struct proc *p;
1471 	void *v;
1472 	register_t *retval;
1473 {
1474 	struct sys_unlink_args /* {
1475 		syscallarg(const char *) path;
1476 	} */ *uap = v;
1477 	struct vnode *vp;
1478 	int error;
1479 	struct nameidata nd;
1480 
1481 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
1482 	    SCARG(uap, path), p);
1483 	if ((error = namei(&nd)) != 0)
1484 		return (error);
1485 	vp = nd.ni_vp;
1486 
1487 	/*
1488 	 * The root of a mounted filesystem cannot be deleted.
1489 	 */
1490 	if (vp->v_flag & VROOT) {
1491 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1492 		if (nd.ni_dvp == vp)
1493 			vrele(nd.ni_dvp);
1494 		else
1495 			vput(nd.ni_dvp);
1496 		vput(vp);
1497 		error = EBUSY;
1498 		goto out;
1499 	}
1500 
1501 	(void)uvm_vnp_uncache(vp);
1502 
1503 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1504 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1505 	error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1506 out:
1507 	return (error);
1508 }
1509 
1510 /*
1511  * Reposition read/write file offset.
1512  */
1513 int
sys_lseek(p,v,retval)1514 sys_lseek(p, v, retval)
1515 	struct proc *p;
1516 	void *v;
1517 	register_t *retval;
1518 {
1519 	struct sys_lseek_args /* {
1520 		syscallarg(int) fd;
1521 		syscallarg(int) pad;
1522 		syscallarg(off_t) offset;
1523 		syscallarg(int) whence;
1524 	} */ *uap = v;
1525 	struct ucred *cred = p->p_ucred;
1526 	struct filedesc *fdp = p->p_fd;
1527 	struct file *fp;
1528 	struct vattr vattr;
1529 	struct vnode *vp;
1530 	int error, special;
1531 
1532 	if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
1533 		return (EBADF);
1534 	if (fp->f_type != DTYPE_VNODE)
1535 		return (ESPIPE);
1536 	vp = (struct vnode *)fp->f_data;
1537 	if (vp->v_type == VFIFO)
1538 		return (ESPIPE);
1539 	if (vp->v_type == VCHR)
1540 		special = 1;
1541 	else
1542 		special = 0;
1543 	switch (SCARG(uap, whence)) {
1544 	case SEEK_CUR:
1545 		if (!special && fp->f_offset + SCARG(uap, offset) < 0)
1546 			return (EINVAL);
1547 		fp->f_offset += SCARG(uap, offset);
1548 		break;
1549 	case SEEK_END:
1550 		error = VOP_GETATTR((struct vnode *)fp->f_data, &vattr,
1551 				    cred, p);
1552 		if (error)
1553 			return (error);
1554 		if (!special && (off_t)vattr.va_size + SCARG(uap, offset) < 0)
1555 			return (EINVAL);
1556 		fp->f_offset = SCARG(uap, offset) + vattr.va_size;
1557 		break;
1558 	case SEEK_SET:
1559 		if (!special && SCARG(uap, offset) < 0)
1560 			return (EINVAL);
1561 		fp->f_offset = SCARG(uap, offset);
1562 		break;
1563 	default:
1564 		return (EINVAL);
1565 	}
1566 	*(off_t *)retval = fp->f_offset;
1567 	return (0);
1568 }
1569 
1570 /*
1571  * Check access permissions.
1572  */
1573 int
sys_access(p,v,retval)1574 sys_access(p, v, retval)
1575 	struct proc *p;
1576 	void *v;
1577 	register_t *retval;
1578 {
1579 	struct sys_access_args /* {
1580 		syscallarg(const char *) path;
1581 		syscallarg(int) flags;
1582 	} */ *uap = v;
1583 	struct ucred *cred = p->p_ucred;
1584 	struct vnode *vp;
1585 	int error, flags, t_gid, t_uid;
1586 	struct nameidata nd;
1587 
1588 	if (SCARG(uap, flags) & ~(R_OK | W_OK | X_OK))
1589 		return (EINVAL);
1590 	t_uid = cred->cr_uid;
1591 	t_gid = cred->cr_gid;
1592 	cred->cr_uid = p->p_cred->p_ruid;
1593 	cred->cr_gid = p->p_cred->p_rgid;
1594 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1595 	    SCARG(uap, path), p);
1596 	if ((error = namei(&nd)) != 0)
1597 		goto out1;
1598 	vp = nd.ni_vp;
1599 
1600 	/* Flags == 0 means only check for existence. */
1601 	if (SCARG(uap, flags)) {
1602 		flags = 0;
1603 		if (SCARG(uap, flags) & R_OK)
1604 			flags |= VREAD;
1605 		if (SCARG(uap, flags) & W_OK)
1606 			flags |= VWRITE;
1607 		if (SCARG(uap, flags) & X_OK)
1608 			flags |= VEXEC;
1609 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1610 			error = VOP_ACCESS(vp, flags, cred, p);
1611 	}
1612 	vput(vp);
1613 out1:
1614 	cred->cr_uid = t_uid;
1615 	cred->cr_gid = t_gid;
1616 	return (error);
1617 }
1618 
1619 /*
1620  * Get file status; this version follows links.
1621  */
1622 /* ARGSUSED */
1623 int
sys_stat(p,v,retval)1624 sys_stat(p, v, retval)
1625 	struct proc *p;
1626 	void *v;
1627 	register_t *retval;
1628 {
1629 	struct sys_stat_args /* {
1630 		syscallarg(const char *) path;
1631 		syscallarg(struct stat *) ub;
1632 	} */ *uap = v;
1633 	struct stat sb;
1634 	int error;
1635 	struct nameidata nd;
1636 
1637 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1638 	    SCARG(uap, path), p);
1639 	if ((error = namei(&nd)) != 0)
1640 		return (error);
1641 	error = vn_stat(nd.ni_vp, &sb, p);
1642 	vput(nd.ni_vp);
1643 	if (error)
1644 		return (error);
1645 	/* Don't let non-root see generation numbers (for NFS security) */
1646 	if (suser(p, 0))
1647 		sb.st_gen = 0;
1648 	error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
1649 	return (error);
1650 }
1651 
1652 /*
1653  * Get file status; this version does not follow links.
1654  */
1655 /* ARGSUSED */
1656 int
sys_lstat(p,v,retval)1657 sys_lstat(p, v, retval)
1658 	struct proc *p;
1659 	void *v;
1660 	register_t *retval;
1661 {
1662 	struct sys_lstat_args /* {
1663 		syscallarg(const char *) path;
1664 		syscallarg(struct stat *) ub;
1665 	} */ *uap = v;
1666 	struct stat sb;
1667 	int error;
1668 	struct nameidata nd;
1669 
1670 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1671 	    SCARG(uap, path), p);
1672 	if ((error = namei(&nd)) != 0)
1673 		return (error);
1674 	error = vn_stat(nd.ni_vp, &sb, p);
1675 	vput(nd.ni_vp);
1676 	if (error)
1677 		return (error);
1678 	/* Don't let non-root see generation numbers (for NFS security) */
1679 	if (suser(p, 0))
1680 		sb.st_gen = 0;
1681 	error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
1682 	return (error);
1683 }
1684 
1685 /*
1686  * Get configurable pathname variables.
1687  */
1688 /* ARGSUSED */
1689 int
sys_pathconf(p,v,retval)1690 sys_pathconf(p, v, retval)
1691 	struct proc *p;
1692 	void *v;
1693 	register_t *retval;
1694 {
1695 	struct sys_pathconf_args /* {
1696 		syscallarg(const char *) path;
1697 		syscallarg(int) name;
1698 	} */ *uap = v;
1699 	int error;
1700 	struct nameidata nd;
1701 
1702 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1703 	    SCARG(uap, path), p);
1704 	if ((error = namei(&nd)) != 0)
1705 		return (error);
1706 	error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
1707 	vput(nd.ni_vp);
1708 	return (error);
1709 }
1710 
1711 /*
1712  * Return target name of a symbolic link.
1713  */
1714 /* ARGSUSED */
1715 int
sys_readlink(p,v,retval)1716 sys_readlink(p, v, retval)
1717 	struct proc *p;
1718 	void *v;
1719 	register_t *retval;
1720 {
1721 	struct sys_readlink_args /* {
1722 		syscallarg(const char *) path;
1723 		syscallarg(char *) buf;
1724 		syscallarg(size_t) count;
1725 	} */ *uap = v;
1726 	struct vnode *vp;
1727 	struct iovec aiov;
1728 	struct uio auio;
1729 	int error;
1730 	struct nameidata nd;
1731 
1732 	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1733 	    SCARG(uap, path), p);
1734 	if ((error = namei(&nd)) != 0)
1735 		return (error);
1736 	vp = nd.ni_vp;
1737 	if (vp->v_type != VLNK)
1738 		error = EINVAL;
1739 	else {
1740 		aiov.iov_base = SCARG(uap, buf);
1741 		aiov.iov_len = SCARG(uap, count);
1742 		auio.uio_iov = &aiov;
1743 		auio.uio_iovcnt = 1;
1744 		auio.uio_offset = 0;
1745 		auio.uio_rw = UIO_READ;
1746 		auio.uio_segflg = UIO_USERSPACE;
1747 		auio.uio_procp = p;
1748 		auio.uio_resid = SCARG(uap, count);
1749 		error = VOP_READLINK(vp, &auio, p->p_ucred);
1750 	}
1751 	vput(vp);
1752 	*retval = SCARG(uap, count) - auio.uio_resid;
1753 	return (error);
1754 }
1755 
1756 /*
1757  * Change flags of a file given a path name.
1758  */
1759 /* ARGSUSED */
1760 int
sys_chflags(p,v,retval)1761 sys_chflags(p, v, retval)
1762 	struct proc *p;
1763 	void *v;
1764 	register_t *retval;
1765 {
1766 	struct sys_chflags_args /* {
1767 		syscallarg(const char *) path;
1768 		syscallarg(u_int) flags;
1769 	} */ *uap = v;
1770 	struct vnode *vp;
1771 	struct vattr vattr;
1772 	int error;
1773 	struct nameidata nd;
1774 
1775 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1776 	if ((error = namei(&nd)) != 0)
1777 		return (error);
1778 	vp = nd.ni_vp;
1779 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1780 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1781 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1782 		error = EROFS;
1783 	else if (SCARG(uap, flags) == VNOVAL)
1784 		error = EINVAL;
1785 	else {
1786 		if (suser(p, 0)) {
1787 			if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
1788 				goto out;
1789 			if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
1790 				error = EINVAL;
1791 				goto out;
1792 			}
1793 		}
1794 		VATTR_NULL(&vattr);
1795 		vattr.va_flags = SCARG(uap, flags);
1796 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1797 	}
1798 out:
1799 	vput(vp);
1800 	return (error);
1801 }
1802 
1803 /*
1804  * Change flags of a file given a path name, without following links.
1805  */
1806 /* ARGSUSED */
1807 int
sys_lchflags(struct proc * p,void * v,register_t * retval)1808 sys_lchflags(struct proc *p, void *v, register_t *retval)
1809 {
1810 	struct sys_lchflags_args /* {
1811 		syscallarg(const char *) path;
1812 		syscallarg(u_int) flags;
1813 	} */ *uap = v;
1814 	struct vnode *vp;
1815 	struct vattr vattr;
1816 	int error;
1817 	struct nameidata nd;
1818 
1819 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1820 	if ((error = namei(&nd)) != 0)
1821 		return (error);
1822 	vp = nd.ni_vp;
1823 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1824 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1825 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1826 		error = EROFS;
1827 	else if (SCARG(uap, flags) == VNOVAL)
1828 		error = EINVAL;
1829 	else {
1830 		if (suser(p, 0)) {
1831 			if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
1832 				goto out;
1833 			if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
1834 				error = EINVAL;
1835 				goto out;
1836 			}
1837 		}
1838 		VATTR_NULL(&vattr);
1839 		vattr.va_flags = SCARG(uap, flags);
1840 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1841 	}
1842 out:
1843 	vput(vp);
1844 	return (error);
1845 }
1846 
1847 /*
1848  * Change flags of a file given a file descriptor.
1849  */
1850 /* ARGSUSED */
1851 int
sys_fchflags(p,v,retval)1852 sys_fchflags(p, v, retval)
1853 	struct proc *p;
1854 	void *v;
1855 	register_t *retval;
1856 {
1857 	struct sys_fchflags_args /* {
1858 		syscallarg(int) fd;
1859 		syscallarg(u_int) flags;
1860 	} */ *uap = v;
1861 	struct vattr vattr;
1862 	struct vnode *vp;
1863 	struct file *fp;
1864 	int error;
1865 
1866 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1867 		return (error);
1868 	vp = (struct vnode *)fp->f_data;
1869 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1870 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1871 	if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY)
1872 		error = EROFS;
1873 	else if (SCARG(uap, flags) == VNOVAL)
1874 		error = EINVAL;
1875 	else {
1876 		if (suser(p, 0)) {
1877 			if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
1878 			    != 0)
1879 				goto out;
1880 			if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
1881 				error = EINVAL;
1882 				goto out;
1883 			}
1884 		}
1885 		VATTR_NULL(&vattr);
1886 		vattr.va_flags = SCARG(uap, flags);
1887 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1888 	}
1889 out:
1890 	VOP_UNLOCK(vp, 0, p);
1891 	FRELE(fp);
1892 	return (error);
1893 }
1894 
1895 /*
1896  * Change mode of a file given path name.
1897  */
1898 /* ARGSUSED */
1899 int
sys_chmod(p,v,retval)1900 sys_chmod(p, v, retval)
1901 	struct proc *p;
1902 	void *v;
1903 	register_t *retval;
1904 {
1905 	struct sys_chmod_args /* {
1906 		syscallarg(const char *) path;
1907 		syscallarg(mode_t) mode;
1908 	} */ *uap = v;
1909 	struct vnode *vp;
1910 	struct vattr vattr;
1911 	int error;
1912 	struct nameidata nd;
1913 
1914 	if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
1915 		return (EINVAL);
1916 
1917 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1918 	if ((error = namei(&nd)) != 0)
1919 		return (error);
1920 	vp = nd.ni_vp;
1921 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1922 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1923 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1924 		error = EROFS;
1925 	else {
1926 		VATTR_NULL(&vattr);
1927 		vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1928 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1929 	}
1930 	vput(vp);
1931 	return (error);
1932 }
1933 
1934 /*
1935  * Change mode of a file given path name, without following links.
1936  */
1937 /* ARGSUSED */
1938 int
sys_lchmod(struct proc * p,void * v,register_t * retval)1939 sys_lchmod(struct proc *p, void *v, register_t *retval)
1940 {
1941 	struct sys_lchmod_args /* {
1942 		syscallarg(const char *) path;
1943 		syscallarg(mode_t) mode;
1944 	} */ *uap = v;
1945 	struct vnode *vp;
1946 	struct vattr vattr;
1947 	int error;
1948 	struct nameidata nd;
1949 
1950 	if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
1951 		return (EINVAL);
1952 
1953 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1954 	if ((error = namei(&nd)) != 0)
1955 		return (error);
1956 	vp = nd.ni_vp;
1957 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1958 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1959 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
1960 		error = EROFS;
1961 	else {
1962 		VATTR_NULL(&vattr);
1963 		vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
1964 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1965 	}
1966 	vput(vp);
1967 	return (error);
1968 }
1969 
1970 /*
1971  * Change mode of a file given a file descriptor.
1972  */
1973 /* ARGSUSED */
1974 int
sys_fchmod(p,v,retval)1975 sys_fchmod(p, v, retval)
1976 	struct proc *p;
1977 	void *v;
1978 	register_t *retval;
1979 {
1980 	struct sys_fchmod_args /* {
1981 		syscallarg(int) fd;
1982 		syscallarg(mode_t) mode;
1983 	} */ *uap = v;
1984 	struct vattr vattr;
1985 	struct vnode *vp;
1986 	struct file *fp;
1987 	int error;
1988 
1989 	if (SCARG(uap, mode) & ~(S_IFMT | ALLPERMS))
1990 		return (EINVAL);
1991 
1992 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1993 		return (error);
1994 	vp = (struct vnode *)fp->f_data;
1995 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1996 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1997 	if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY)
1998 		error = EROFS;
1999 	else {
2000 		VATTR_NULL(&vattr);
2001 		vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
2002 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2003 	}
2004 	VOP_UNLOCK(vp, 0, p);
2005 	FRELE(fp);
2006 	return (error);
2007 }
2008 
2009 /*
2010  * Set ownership given a path name.
2011  */
2012 /* ARGSUSED */
2013 int
sys_chown(p,v,retval)2014 sys_chown(p, v, retval)
2015 	struct proc *p;
2016 	void *v;
2017 	register_t *retval;
2018 {
2019 	struct sys_chown_args /* {
2020 		syscallarg(const char *) path;
2021 		syscallarg(uid_t) uid;
2022 		syscallarg(gid_t) gid;
2023 	} */ *uap = v;
2024 	struct vnode *vp;
2025 	struct vattr vattr;
2026 	int error;
2027 	struct nameidata nd;
2028 	mode_t mode;
2029 
2030 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2031 	if ((error = namei(&nd)) != 0)
2032 		return (error);
2033 	vp = nd.ni_vp;
2034 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2035 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2036 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
2037 		error = EROFS;
2038 	else {
2039 		if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
2040 		    (suser(p, 0) || suid_clear)) {
2041 			error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
2042 			if (error)
2043 				goto out;
2044 			mode = vattr.va_mode & ~(VSUID | VSGID);
2045 			if (mode == vattr.va_mode)
2046 				mode = VNOVAL;
2047 		}
2048 		else
2049 			mode = VNOVAL;
2050 		VATTR_NULL(&vattr);
2051 		vattr.va_uid = SCARG(uap, uid);
2052 		vattr.va_gid = SCARG(uap, gid);
2053 		vattr.va_mode = mode;
2054 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2055 	}
2056 out:
2057 	vput(vp);
2058 	return (error);
2059 }
2060 
2061 /*
2062  * Set ownership given a path name, without following links.
2063  */
2064 /* ARGSUSED */
2065 int
sys_lchown(p,v,retval)2066 sys_lchown(p, v, retval)
2067 	struct proc *p;
2068 	void *v;
2069 	register_t *retval;
2070 {
2071 	struct sys_lchown_args /* {
2072 		syscallarg(const char *) path;
2073 		syscallarg(uid_t) uid;
2074 		syscallarg(gid_t) gid;
2075 	} */ *uap = v;
2076 	struct vnode *vp;
2077 	struct vattr vattr;
2078 	int error;
2079 	struct nameidata nd;
2080 	mode_t mode;
2081 
2082 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2083 	if ((error = namei(&nd)) != 0)
2084 		return (error);
2085 	vp = nd.ni_vp;
2086 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2087 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2088 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
2089 		error = EROFS;
2090 	else {
2091 		if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
2092 		    (suser(p, 0) || suid_clear)) {
2093 			error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
2094 			if (error)
2095 				goto out;
2096 			mode = vattr.va_mode & ~(VSUID | VSGID);
2097 			if (mode == vattr.va_mode)
2098 				mode = VNOVAL;
2099 		}
2100 		else
2101 			mode = VNOVAL;
2102 		VATTR_NULL(&vattr);
2103 		vattr.va_uid = SCARG(uap, uid);
2104 		vattr.va_gid = SCARG(uap, gid);
2105 		vattr.va_mode = mode;
2106 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2107 	}
2108 out:
2109 	vput(vp);
2110 	return (error);
2111 }
2112 
2113 /*
2114  * Set ownership given a file descriptor.
2115  */
2116 /* ARGSUSED */
2117 int
sys_fchown(p,v,retval)2118 sys_fchown(p, v, retval)
2119 	struct proc *p;
2120 	void *v;
2121 	register_t *retval;
2122 {
2123 	struct sys_fchown_args /* {
2124 		syscallarg(int) fd;
2125 		syscallarg(uid_t) uid;
2126 		syscallarg(gid_t) gid;
2127 	} */ *uap = v;
2128 	struct vnode *vp;
2129 	struct vattr vattr;
2130 	int error;
2131 	struct file *fp;
2132 	mode_t mode;
2133 
2134 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2135 		return (error);
2136 	vp = (struct vnode *)fp->f_data;
2137 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2138 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2139 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
2140 		error = EROFS;
2141 	else {
2142 		if ((SCARG(uap, uid) != -1 || SCARG(uap, gid) != -1) &&
2143 		    (suser(p, 0) || suid_clear)) {
2144 			error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
2145 			if (error)
2146 				goto out;
2147 			mode = vattr.va_mode & ~(VSUID | VSGID);
2148 			if (mode == vattr.va_mode)
2149 				mode = VNOVAL;
2150 		} else
2151 			mode = VNOVAL;
2152 		VATTR_NULL(&vattr);
2153 		vattr.va_uid = SCARG(uap, uid);
2154 		vattr.va_gid = SCARG(uap, gid);
2155 		vattr.va_mode = mode;
2156 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2157 	}
2158 out:
2159 	VOP_UNLOCK(vp, 0, p);
2160 	FRELE(fp);
2161 	return (error);
2162 }
2163 
2164 /*
2165  * Set the access and modification times given a path name.
2166  */
2167 /* ARGSUSED */
2168 int
sys_utimes(p,v,retval)2169 sys_utimes(p, v, retval)
2170 	struct proc *p;
2171 	void *v;
2172 	register_t *retval;
2173 {
2174 	struct sys_utimes_args /* {
2175 		syscallarg(const char *) path;
2176 		syscallarg(const struct timeval *) tptr;
2177 	} */ *uap = v;
2178 	struct vnode *vp;
2179 	struct timeval tv[2];
2180 	struct vattr vattr;
2181 	int error;
2182 	struct nameidata nd;
2183 
2184 	VATTR_NULL(&vattr);
2185 	if (SCARG(uap, tptr) == NULL) {
2186 		microtime(&tv[0]);
2187 		tv[1] = tv[0];
2188 		vattr.va_vaflags |= VA_UTIMES_NULL;
2189 	} else {
2190 		error = copyin(SCARG(uap, tptr), tv,
2191 		    sizeof(tv));
2192 		if (error)
2193 			return (error);
2194 		/* XXX workaround timeval matching the VFS constant VNOVAL */
2195 		if (tv[0].tv_sec == VNOVAL)
2196 			tv[0].tv_sec = VNOVAL - 1;
2197 		if (tv[1].tv_sec == VNOVAL)
2198 			tv[1].tv_sec = VNOVAL - 1;
2199 	}
2200 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2201 	if ((error = namei(&nd)) != 0)
2202 		return (error);
2203 	vp = nd.ni_vp;
2204 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2205 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2206 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
2207 		error = EROFS;
2208 	else {
2209 		vattr.va_atime.tv_sec = tv[0].tv_sec;
2210 		vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
2211 		vattr.va_mtime.tv_sec = tv[1].tv_sec;
2212 		vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
2213 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2214 	}
2215 	vput(vp);
2216 	return (error);
2217 }
2218 
2219 /*
2220  * Set the access and modification times given a path name, without following links.
2221  */
2222 /* ARGSUSED */
2223 int
sys_lutimes(struct proc * p,void * v,register_t * retval)2224 sys_lutimes(struct proc *p, void *v, register_t *retval)
2225 {
2226 	struct sys_lutimes_args /* {
2227 		syscallarg(const char *) path;
2228 		syscallarg(const struct timeval *) tptr;
2229 	} */ *uap = v;
2230 	struct vnode *vp;
2231 	struct timeval tv[2];
2232 	struct vattr vattr;
2233 	int error;
2234 	struct nameidata nd;
2235 
2236 	VATTR_NULL(&vattr);
2237 	if (SCARG(uap, tptr) == NULL) {
2238 		microtime(&tv[0]);
2239 		tv[1] = tv[0];
2240 		vattr.va_vaflags |= VA_UTIMES_NULL;
2241 	} else {
2242 		error = copyin(SCARG(uap, tptr), tv,
2243 		    sizeof(tv));
2244 		if (error)
2245 			return (error);
2246 		/* XXX workaround timeval matching the VFS constant VNOVAL */
2247 		if (tv[0].tv_sec == VNOVAL)
2248 			tv[0].tv_sec = VNOVAL - 1;
2249 		if (tv[1].tv_sec == VNOVAL)
2250 			tv[1].tv_sec = VNOVAL - 1;
2251 	}
2252 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2253 	if ((error = namei(&nd)) != 0)
2254 		return (error);
2255 	vp = nd.ni_vp;
2256 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2257 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2258 	if (vp->v_mount->mnt_flag & MNT_RDONLY)
2259 		error = EROFS;
2260 	else {
2261 		vattr.va_atime.tv_sec = tv[0].tv_sec;
2262 		vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
2263 		vattr.va_mtime.tv_sec = tv[1].tv_sec;
2264 		vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
2265 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2266 	}
2267 	vput(vp);
2268 	return (error);
2269 }
2270 
2271 /*
2272  * Set the access and modification times given a file descriptor.
2273  */
2274 /* ARGSUSED */
2275 int
sys_futimes(p,v,retval)2276 sys_futimes(p, v, retval)
2277 	struct proc *p;
2278 	void *v;
2279 	register_t *retval;
2280 {
2281 	struct sys_futimes_args /* {
2282 		syscallarg(int) fd;
2283 		syscallarg(const struct timeval *) tptr;
2284 	} */ *uap = v;
2285 	struct vnode *vp;
2286 	struct timeval tv[2];
2287 	struct vattr vattr;
2288 	int error;
2289 	struct file *fp;
2290 
2291 	VATTR_NULL(&vattr);
2292 	if (SCARG(uap, tptr) == NULL) {
2293 		microtime(&tv[0]);
2294 		tv[1] = tv[0];
2295 		vattr.va_vaflags |= VA_UTIMES_NULL;
2296 	} else {
2297 		error = copyin(SCARG(uap, tptr), tv,
2298 		    sizeof(tv));
2299 		if (error)
2300 			return (error);
2301 		/* XXX workaround timeval matching the VFS constant VNOVAL */
2302 		if (tv[0].tv_sec == VNOVAL)
2303 			tv[0].tv_sec = VNOVAL - 1;
2304 		if (tv[1].tv_sec == VNOVAL)
2305 			tv[1].tv_sec = VNOVAL - 1;
2306 	}
2307 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2308 		return (error);
2309 	vp = (struct vnode *)fp->f_data;
2310 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2311 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2312 	if (vp->v_mount && vp->v_mount->mnt_flag & MNT_RDONLY)
2313 		error = EROFS;
2314 	else {
2315 		vattr.va_atime.tv_sec = tv[0].tv_sec;
2316 		vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
2317 		vattr.va_mtime.tv_sec = tv[1].tv_sec;
2318 		vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
2319 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2320 	}
2321 	VOP_UNLOCK(vp, 0, p);
2322 	FRELE(fp);
2323 	return (error);
2324 }
2325 
2326 /*
2327  * Truncate a file given its path name.
2328  */
2329 /* ARGSUSED */
2330 int
sys_truncate(p,v,retval)2331 sys_truncate(p, v, retval)
2332 	struct proc *p;
2333 	void *v;
2334 	register_t *retval;
2335 {
2336 	struct sys_truncate_args /* {
2337 		syscallarg(const char *) path;
2338 		syscallarg(int) pad;
2339 		syscallarg(off_t) length;
2340 	} */ *uap = v;
2341 	struct vnode *vp;
2342 	struct vattr vattr;
2343 	int error;
2344 	struct nameidata nd;
2345 
2346 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2347 	if ((error = namei(&nd)) != 0)
2348 		return (error);
2349 	vp = nd.ni_vp;
2350 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2351 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2352 	if (vp->v_type == VDIR)
2353 		error = EISDIR;
2354 	else if ((error = vn_writechk(vp)) == 0 &&
2355 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
2356 		VATTR_NULL(&vattr);
2357 		vattr.va_size = SCARG(uap, length);
2358 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
2359 	}
2360 	vput(vp);
2361 	return (error);
2362 }
2363 
2364 /*
2365  * Truncate a file given a file descriptor.
2366  */
2367 /* ARGSUSED */
2368 int
sys_ftruncate(p,v,retval)2369 sys_ftruncate(p, v, retval)
2370 	struct proc *p;
2371 	void *v;
2372 	register_t *retval;
2373 {
2374 	struct sys_ftruncate_args /* {
2375 		syscallarg(int) fd;
2376 		syscallarg(int) pad;
2377 		syscallarg(off_t) length;
2378 	} */ *uap = v;
2379 	struct vattr vattr;
2380 	struct vnode *vp;
2381 	struct file *fp;
2382 	off_t len;
2383 	int error;
2384 
2385 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2386 		return (error);
2387 	len = SCARG(uap, length);
2388 	if ((fp->f_flag & FWRITE) == 0 || len < 0) {
2389 		error = EINVAL;
2390 		goto bad;
2391 	}
2392 	vp = (struct vnode *)fp->f_data;
2393 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2394 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2395 	if (vp->v_type == VDIR)
2396 		error = EISDIR;
2397 	else if ((error = vn_writechk(vp)) == 0) {
2398 		VATTR_NULL(&vattr);
2399 		vattr.va_size = len;
2400 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
2401 	}
2402 	VOP_UNLOCK(vp, 0, p);
2403 bad:
2404 	FRELE(fp);
2405 	return (error);
2406 }
2407 
2408 /*
2409  * Sync an open file.
2410  */
2411 /* ARGSUSED */
2412 int
sys_fsync(p,v,retval)2413 sys_fsync(p, v, retval)
2414 	struct proc *p;
2415 	void *v;
2416 	register_t *retval;
2417 {
2418 	struct sys_fsync_args /* {
2419 		syscallarg(int) fd;
2420 	} */ *uap = v;
2421 	struct vnode *vp;
2422 	struct file *fp;
2423 	int error;
2424 
2425 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2426 		return (error);
2427 	vp = (struct vnode *)fp->f_data;
2428 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2429 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
2430 #ifdef FFS_SOFTUPDATES
2431 	if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
2432 		error = softdep_fsync(vp);
2433 #endif
2434 
2435 	VOP_UNLOCK(vp, 0, p);
2436 	FRELE(fp);
2437 	return (error);
2438 }
2439 
2440 /*
2441  * Rename files.  Source and destination must either both be directories,
2442  * or both not be directories.  If target is a directory, it must be empty.
2443  */
2444 /* ARGSUSED */
2445 int
sys_rename(p,v,retval)2446 sys_rename(p, v, retval)
2447 	struct proc *p;
2448 	void *v;
2449 	register_t *retval;
2450 {
2451 	struct sys_rename_args /* {
2452 		syscallarg(const char *) from;
2453 		syscallarg(const char *) to;
2454 	} */ *uap = v;
2455 	struct vnode *tvp, *fvp, *tdvp;
2456 	struct nameidata fromnd, tond;
2457 	int error;
2458 	int flags;
2459 
2460 	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
2461 	    SCARG(uap, from), p);
2462 	if ((error = namei(&fromnd)) != 0)
2463 		return (error);
2464 	fvp = fromnd.ni_vp;
2465 
2466 	flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
2467 	/*
2468 	 * rename("foo/", "bar/");  is  OK
2469 	 */
2470 	if (fvp->v_type == VDIR)
2471 		flags |= STRIPSLASHES;
2472 
2473 	NDINIT(&tond, RENAME, flags,
2474 	    UIO_USERSPACE, SCARG(uap, to), p);
2475 	if ((error = namei(&tond)) != 0) {
2476 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2477 		vrele(fromnd.ni_dvp);
2478 		vrele(fvp);
2479 		goto out1;
2480 	}
2481 	tdvp = tond.ni_dvp;
2482 	tvp = tond.ni_vp;
2483 	if (tvp != NULL) {
2484 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2485 			error = ENOTDIR;
2486 			goto out;
2487 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2488 			error = EISDIR;
2489 			goto out;
2490 		}
2491 	}
2492 	if (fvp == tdvp)
2493 		error = EINVAL;
2494 	/*
2495 	 * If source is the same as the destination (that is the
2496 	 * same inode number)
2497 	 */
2498 	if (fvp == tvp)
2499 		error = -1;
2500 out:
2501 	if (!error) {
2502 		VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
2503 		if (fromnd.ni_dvp != tdvp)
2504 			VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2505 		if (tvp) {
2506 			(void)uvm_vnp_uncache(tvp);
2507 			VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
2508 		}
2509 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2510 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2511 	} else {
2512 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
2513 		if (tdvp == tvp)
2514 			vrele(tdvp);
2515 		else
2516 			vput(tdvp);
2517 		if (tvp)
2518 			vput(tvp);
2519 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2520 		vrele(fromnd.ni_dvp);
2521 		vrele(fvp);
2522 	}
2523 	vrele(tond.ni_startdir);
2524 	pool_put(&namei_pool, tond.ni_cnd.cn_pnbuf);
2525 out1:
2526 	if (fromnd.ni_startdir)
2527 		vrele(fromnd.ni_startdir);
2528 	pool_put(&namei_pool, fromnd.ni_cnd.cn_pnbuf);
2529 	if (error == -1)
2530 		return (0);
2531 	return (error);
2532 }
2533 
2534 /*
2535  * Make a directory file.
2536  */
2537 /* ARGSUSED */
2538 int
sys_mkdir(p,v,retval)2539 sys_mkdir(p, v, retval)
2540 	struct proc *p;
2541 	void *v;
2542 	register_t *retval;
2543 {
2544 	struct sys_mkdir_args /* {
2545 		syscallarg(const char *) path;
2546 		syscallarg(mode_t) mode;
2547 	} */ *uap = v;
2548 	struct vnode *vp;
2549 	struct vattr vattr;
2550 	int error;
2551 	struct nameidata nd;
2552 
2553 	NDINIT(&nd, CREATE, LOCKPARENT | STRIPSLASHES,
2554 	    UIO_USERSPACE, SCARG(uap, path), p);
2555 	if ((error = namei(&nd)) != 0)
2556 		return (error);
2557 	vp = nd.ni_vp;
2558 	if (vp != NULL) {
2559 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2560 		if (nd.ni_dvp == vp)
2561 			vrele(nd.ni_dvp);
2562 		else
2563 			vput(nd.ni_dvp);
2564 		vrele(vp);
2565 		return (EEXIST);
2566 	}
2567 	VATTR_NULL(&vattr);
2568 	vattr.va_type = VDIR;
2569 	vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
2570 	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2571 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
2572 	if (!error)
2573 		vput(nd.ni_vp);
2574 	return (error);
2575 }
2576 
2577 /*
2578  * Remove a directory file.
2579  */
2580 /* ARGSUSED */
2581 int
sys_rmdir(p,v,retval)2582 sys_rmdir(p, v, retval)
2583 	struct proc *p;
2584 	void *v;
2585 	register_t *retval;
2586 {
2587 	struct sys_rmdir_args /* {
2588 		syscallarg(const char *) path;
2589 	} */ *uap = v;
2590 	struct vnode *vp;
2591 	int error;
2592 	struct nameidata nd;
2593 
2594 	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
2595 	    SCARG(uap, path), p);
2596 	if ((error = namei(&nd)) != 0)
2597 		return (error);
2598 	vp = nd.ni_vp;
2599 	if (vp->v_type != VDIR) {
2600 		error = ENOTDIR;
2601 		goto out;
2602 	}
2603 	/*
2604 	 * No rmdir "." please.
2605 	 */
2606 	if (nd.ni_dvp == vp) {
2607 		error = EBUSY;
2608 		goto out;
2609 	}
2610 	/*
2611 	 * The root of a mounted filesystem cannot be deleted.
2612 	 */
2613 	if (vp->v_flag & VROOT)
2614 		error = EBUSY;
2615 out:
2616 	if (!error) {
2617 		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
2618 		VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
2619 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2620 	} else {
2621 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2622 		if (nd.ni_dvp == vp)
2623 			vrele(nd.ni_dvp);
2624 		else
2625 			vput(nd.ni_dvp);
2626 		vput(vp);
2627 	}
2628 	return (error);
2629 }
2630 
2631 /*
2632  * Read a block of directory entries in a file system independent format.
2633  */
2634 int
sys_getdirentries(p,v,retval)2635 sys_getdirentries(p, v, retval)
2636 	struct proc *p;
2637 	void *v;
2638 	register_t *retval;
2639 {
2640 	struct sys_getdirentries_args /* {
2641 		syscallarg(int) fd;
2642 		syscallarg(char *) buf;
2643 		syscallarg(int) count;
2644 		syscallarg(long *) basep;
2645 	} */ *uap = v;
2646 	struct vnode *vp;
2647 	struct file *fp;
2648 	struct uio auio;
2649 	struct iovec aiov;
2650 	long loff;
2651 	int error, eofflag;
2652 
2653 	if (SCARG(uap, count) < 0)
2654 		return EINVAL;
2655 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
2656 		return (error);
2657 	if ((fp->f_flag & FREAD) == 0) {
2658 		error = EBADF;
2659 		goto bad;
2660 	}
2661 	vp = (struct vnode *)fp->f_data;
2662 	if (vp->v_type != VDIR) {
2663 		error = EINVAL;
2664 		goto bad;
2665 	}
2666 	aiov.iov_base = SCARG(uap, buf);
2667 	aiov.iov_len = SCARG(uap, count);
2668 	auio.uio_iov = &aiov;
2669 	auio.uio_iovcnt = 1;
2670 	auio.uio_rw = UIO_READ;
2671 	auio.uio_segflg = UIO_USERSPACE;
2672 	auio.uio_procp = p;
2673 	auio.uio_resid = SCARG(uap, count);
2674 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
2675 	loff = auio.uio_offset = fp->f_offset;
2676 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 0, 0);
2677 	fp->f_offset = auio.uio_offset;
2678 	VOP_UNLOCK(vp, 0, p);
2679 	if (error)
2680 		goto bad;
2681 	error = copyout(&loff, SCARG(uap, basep),
2682 	    sizeof(long));
2683 	*retval = SCARG(uap, count) - auio.uio_resid;
2684 bad:
2685 	FRELE(fp);
2686 	return (error);
2687 }
2688 
2689 /*
2690  * Set the mode mask for creation of filesystem nodes.
2691  */
2692 int
sys_umask(p,v,retval)2693 sys_umask(p, v, retval)
2694 	struct proc *p;
2695 	void *v;
2696 	register_t *retval;
2697 {
2698 	struct sys_umask_args /* {
2699 		syscallarg(mode_t) newmask;
2700 	} */ *uap = v;
2701 	struct filedesc *fdp;
2702 
2703 	fdp = p->p_fd;
2704 	*retval = fdp->fd_cmask;
2705 	fdp->fd_cmask = SCARG(uap, newmask) & ACCESSPERMS;
2706 	return (0);
2707 }
2708 
2709 /*
2710  * Void all references to file by ripping underlying filesystem
2711  * away from vnode.
2712  */
2713 /* ARGSUSED */
2714 int
sys_revoke(p,v,retval)2715 sys_revoke(p, v, retval)
2716 	struct proc *p;
2717 	void *v;
2718 	register_t *retval;
2719 {
2720 	struct sys_revoke_args /* {
2721 		syscallarg(const char *) path;
2722 	} */ *uap = v;
2723 	struct vnode *vp;
2724 	struct vattr vattr;
2725 	int error;
2726 	struct nameidata nd;
2727 
2728 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
2729 	if ((error = namei(&nd)) != 0)
2730 		return (error);
2731 	vp = nd.ni_vp;
2732 	if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
2733 		goto out;
2734 	if (p->p_ucred->cr_uid != vattr.va_uid &&
2735 	    (error = suser(p, 0)))
2736 		goto out;
2737 	if (vp->v_usecount > 1 || (vp->v_flag & (VALIASED)))
2738 		VOP_REVOKE(vp, REVOKEALL);
2739 out:
2740 	vrele(vp);
2741 	return (error);
2742 }
2743 
2744 /*
2745  * Convert a user file descriptor to a kernel file entry.
2746  *
2747  * On return *fpp is FREF:ed.
2748  */
2749 int
getvnode(fdp,fd,fpp)2750 getvnode(fdp, fd, fpp)
2751 	struct filedesc *fdp;
2752 	struct file **fpp;
2753 	int fd;
2754 {
2755 	struct file *fp;
2756 	struct vnode *vp;
2757 
2758 	if ((fp = fd_getfile(fdp, fd)) == NULL)
2759 		return (EBADF);
2760 
2761 	if (fp->f_type != DTYPE_VNODE)
2762 		return (EINVAL);
2763 
2764 	vp = (struct vnode *)fp->f_data;
2765 	if (vp->v_type == VBAD)
2766 		return (EBADF);
2767 
2768 	FREF(fp);
2769 	*fpp = fp;
2770 
2771 	return (0);
2772 }
2773 
2774 /*
2775  * Positional read system call.
2776  */
2777 int
sys_pread(p,v,retval)2778 sys_pread(p, v, retval)
2779 	struct proc *p;
2780 	void *v;
2781 	register_t *retval;
2782 {
2783 	struct sys_pread_args /* {
2784 		syscallarg(int) fd;
2785 		syscallarg(void *) buf;
2786 		syscallarg(size_t) nbyte;
2787 		syscallarg(int) pad;
2788 		syscallarg(off_t) offset;
2789 	} */ *uap = v;
2790 	struct filedesc *fdp = p->p_fd;
2791 	struct file *fp;
2792 	struct vnode *vp;
2793 	off_t offset;
2794 	int fd = SCARG(uap, fd);
2795 
2796 	if ((fp = fd_getfile(fdp, fd)) == NULL)
2797 		return (EBADF);
2798 	if ((fp->f_flag & FREAD) == 0)
2799 		return (EBADF);
2800 
2801 	vp = (struct vnode *)fp->f_data;
2802 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
2803 		return (ESPIPE);
2804 	}
2805 
2806 	offset = SCARG(uap, offset);
2807 
2808 	FREF(fp);
2809 
2810 	/* dofileread() will FRELE the descriptor for us */
2811 	return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
2812 	    &offset, retval));
2813 }
2814 
2815 /*
2816  * Positional scatter read system call.
2817  */
2818 int
sys_preadv(p,v,retval)2819 sys_preadv(p, v, retval)
2820 	struct proc *p;
2821 	void *v;
2822 	register_t *retval;
2823 {
2824 	struct sys_preadv_args /* {
2825 		syscallarg(int) fd;
2826 		syscallarg(const struct iovec *) iovp;
2827 		syscallarg(int) iovcnt;
2828 		syscallarg(int) pad;
2829 		syscallarg(off_t) offset;
2830 	} */ *uap = v;
2831 	struct filedesc *fdp = p->p_fd;
2832 	struct file *fp;
2833 	struct vnode *vp;
2834 	off_t offset;
2835 	int fd = SCARG(uap, fd);
2836 
2837 	if ((fp = fd_getfile(fdp, fd)) == NULL)
2838 		return (EBADF);
2839 	if ((fp->f_flag & FREAD) == 0)
2840 		return (EBADF);
2841 
2842 	vp = (struct vnode *)fp->f_data;
2843 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
2844 		return (ESPIPE);
2845 	}
2846 
2847 	FREF(fp);
2848 
2849 	offset = SCARG(uap, offset);
2850 
2851 	/* dofilereadv() will FRELE the descriptor for us */
2852 	return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
2853 	    &offset, retval));
2854 }
2855 
2856 /*
2857  * Positional write system call.
2858  */
2859 int
sys_pwrite(p,v,retval)2860 sys_pwrite(p, v, retval)
2861 	struct proc *p;
2862 	void *v;
2863 	register_t *retval;
2864 {
2865 	struct sys_pwrite_args /* {
2866 		syscallarg(int) fd;
2867 		syscallarg(const void *) buf;
2868 		syscallarg(size_t) nbyte;
2869 		syscallarg(int) pad;
2870 		syscallarg(off_t) offset;
2871 	} */ *uap = v;
2872 	struct filedesc *fdp = p->p_fd;
2873 	struct file *fp;
2874 	struct vnode *vp;
2875 	off_t offset;
2876 	int fd = SCARG(uap, fd);
2877 
2878 	if ((fp = fd_getfile(fdp, fd)) == NULL)
2879 		return (EBADF);
2880 	if ((fp->f_flag & FWRITE) == 0)
2881 		return (EBADF);
2882 
2883 	vp = (struct vnode *)fp->f_data;
2884 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
2885 		return (ESPIPE);
2886 	}
2887 
2888 	FREF(fp);
2889 
2890 	offset = SCARG(uap, offset);
2891 
2892 	/* dofilewrite() will FRELE the descriptor for us */
2893 	return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
2894 	    &offset, retval));
2895 }
2896 
2897 
2898 /*
2899  * Positional gather write system call.
2900  */
2901 int
sys_pwritev(p,v,retval)2902 sys_pwritev(p, v, retval)
2903 	struct proc *p;
2904 	void *v;
2905 	register_t *retval;
2906 {
2907 	struct sys_pwritev_args /* {
2908 		syscallarg(int) fd;
2909 		syscallarg(const struct iovec *) iovp;
2910 		syscallarg(int) iovcnt;
2911 		syscallarg(int) pad;
2912 		syscallarg(off_t) offset;
2913 	} */ *uap = v;
2914 	struct filedesc *fdp = p->p_fd;
2915 	struct file *fp;
2916 	struct vnode *vp;
2917 	off_t offset;
2918 	int fd = SCARG(uap, fd);
2919 
2920 	if ((fp = fd_getfile(fdp, fd)) == NULL)
2921 		return (EBADF);
2922 	if ((fp->f_flag & FWRITE) == 0)
2923 		return (EBADF);
2924 
2925 	vp = (struct vnode *)fp->f_data;
2926 	if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
2927 		return (ESPIPE);
2928 	}
2929 
2930 	FREF(fp);
2931 
2932 	offset = SCARG(uap, offset);
2933 
2934 	/* dofilewritev() will FRELE the descriptor for us */
2935 	return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
2936 	    &offset, retval));
2937 }
2938