File:  [DragonFly] / src / sys / kern / vfs_syscalls.c
Revision 1.29: download - view: text, annotated - select for diffs
Mon Mar 1 06:33:17 2004 UTC (10 years, 8 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Newtoken commit.  Change the token implementation as follows:  (1) Obtaining
a token no longer enters a critical section.  (2) tokens can be held through
schedular switches and blocking conditions and are effectively released and
reacquired on resume.  Thus tokens serialize access only while the thread
is actually running.  Serialization is not broken by preemptive interrupts.
That is, interrupt threads which preempt do no release the preempted thread's
tokens.  (3) Unlike spl's, tokens will interlock w/ interrupt threads on
the same or on a different cpu.

The vnode interlock code has been rewritten and the API has changed.  The
mountlist vnode scanning code has been consolidated and all known races have
been fixed.  The vnode interlock is now a pool token.

The code that frees unreferenced vnodes whos last VM page has been freed has
been moved out of the low level vm_page_free() code and moved to the
periodic filesystem sycer code in vfs_msycn().

The SMP startup code and the IPI code has been cleaned up considerably.
Certain early token interactions on AP cpus have been moved to the BSP.

The LWKT rwlock API has been cleaned up and turned on.

Major testing by: David Rhodus

    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:  * Redistribution and use in source and binary forms, with or without
   11:  * modification, are permitted provided that the following conditions
   12:  * are met:
   13:  * 1. Redistributions of source code must retain the above copyright
   14:  *    notice, this list of conditions and the following disclaimer.
   15:  * 2. Redistributions in binary form must reproduce the above copyright
   16:  *    notice, this list of conditions and the following disclaimer in the
   17:  *    documentation and/or other materials provided with the distribution.
   18:  * 3. All advertising materials mentioning features or use of this software
   19:  *    must display the following acknowledgement:
   20:  *	This product includes software developed by the University of
   21:  *	California, Berkeley and its contributors.
   22:  * 4. 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.13 (Berkeley) 4/15/94
   39:  * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $
   40:  * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.29 2004/03/01 06:33:17 dillon Exp $
   41:  */
   42: 
   43: #include <sys/param.h>
   44: #include <sys/systm.h>
   45: #include <sys/buf.h>
   46: #include <sys/sysent.h>
   47: #include <sys/malloc.h>
   48: #include <sys/mount.h>
   49: #include <sys/sysproto.h>
   50: #include <sys/filedesc.h>
   51: #include <sys/kernel.h>
   52: #include <sys/fcntl.h>
   53: #include <sys/file.h>
   54: #include <sys/linker.h>
   55: #include <sys/stat.h>
   56: #include <sys/unistd.h>
   57: #include <sys/vnode.h>
   58: #include <sys/proc.h>
   59: #include <sys/namei.h>
   60: #include <sys/dirent.h>
   61: #include <sys/extattr.h>
   62: #include <sys/kern_syscall.h>
   63: 
   64: #include <machine/limits.h>
   65: #include <vfs/union/union.h>
   66: #include <sys/sysctl.h>
   67: #include <vm/vm.h>
   68: #include <vm/vm_object.h>
   69: #include <vm/vm_zone.h>
   70: #include <vm/vm_page.h>
   71: 
   72: #include <sys/file2.h>
   73: 
   74: static int change_dir (struct nameidata *ndp, struct thread *td);
   75: static void checkdirs (struct vnode *olddp);
   76: static int chroot_refuse_vdir_fds (struct filedesc *fdp);
   77: static int getutimes (const struct timeval *, struct timespec *);
   78: static int setfown (struct vnode *, uid_t, gid_t);
   79: static int setfmode (struct vnode *, int);
   80: static int setfflags (struct vnode *, int);
   81: static int setutimes (struct vnode *, const struct timespec *, int);
   82: static int	usermount = 0;	/* if 1, non-root can mount fs. */
   83: 
   84: int (*union_dircheckp) (struct thread *, struct vnode **, struct file *);
   85: 
   86: SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
   87: 
   88: /*
   89:  * Virtual File System System Calls
   90:  */
   91: 
   92: /*
   93:  * Mount a file system.
   94:  */
   95: /*
   96:  * mount_args(char *type, char *path, int flags, caddr_t data)
   97:  */
   98: /* ARGSUSED */
   99: int
  100: mount(struct mount_args *uap)
  101: {
  102: 	struct thread *td = curthread;
  103: 	struct proc *p = td->td_proc;
  104: 	struct vnode *vp;
  105: 	struct mount *mp;
  106: 	struct vfsconf *vfsp;
  107: 	int error, flag = 0, flag2 = 0;
  108: 	struct vattr va;
  109: 	struct nameidata nd;
  110: 	char fstypename[MFSNAMELEN];
  111: 	lwkt_tokref vlock;
  112: 	lwkt_tokref ilock;
  113: 
  114: 	if (usermount == 0 && (error = suser(td)))
  115: 		return (error);
  116: 	/*
  117: 	 * Do not allow NFS export by non-root users.
  118: 	 */
  119: 	if (SCARG(uap, flags) & MNT_EXPORTED) {
  120: 		error = suser(td);
  121: 		if (error)
  122: 			return (error);
  123: 	}
  124: 	/*
  125: 	 * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users
  126: 	 */
  127: 	if (suser(td)) 
  128: 		SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
  129: 	/*
  130: 	 * Get vnode to be covered
  131: 	 */
  132: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_USERSPACE,
  133: 	    SCARG(uap, path), td);
  134: 	if ((error = namei(&nd)) != 0)
  135: 		return (error);
  136: 	NDFREE(&nd, NDF_ONLY_PNBUF);
  137: 	vp = nd.ni_vp;
  138: 	if (SCARG(uap, flags) & MNT_UPDATE) {
  139: 		if ((vp->v_flag & VROOT) == 0) {
  140: 			vput(vp);
  141: 			return (EINVAL);
  142: 		}
  143: 		mp = vp->v_mount;
  144: 		flag = mp->mnt_flag;
  145: 		flag2 = mp->mnt_kern_flag;
  146: 		/*
  147: 		 * We only allow the filesystem to be reloaded if it
  148: 		 * is currently mounted read-only.
  149: 		 */
  150: 		if ((SCARG(uap, flags) & MNT_RELOAD) &&
  151: 		    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
  152: 			vput(vp);
  153: 			return (EOPNOTSUPP);	/* Needs translation */
  154: 		}
  155: 		/*
  156: 		 * Only root, or the user that did the original mount is
  157: 		 * permitted to update it.
  158: 		 */
  159: 		if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
  160: 		    (error = suser(td))) {
  161: 			vput(vp);
  162: 			return (error);
  163: 		}
  164: 		if (vfs_busy(mp, LK_NOWAIT, NULL, td)) {
  165: 			vput(vp);
  166: 			return (EBUSY);
  167: 		}
  168: 		lwkt_gettoken(&vlock, vp->v_interlock);
  169: 		if ((vp->v_flag & VMOUNT) != 0 ||
  170: 		    vp->v_mountedhere != NULL) {
  171: 			lwkt_reltoken(&vlock);
  172: 			vfs_unbusy(mp, td);
  173: 			vput(vp);
  174: 			return (EBUSY);
  175: 		}
  176: 		vp->v_flag |= VMOUNT;
  177: 		lwkt_reltoken(&vlock);
  178: 		mp->mnt_flag |=
  179: 		    SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
  180: 		VOP_UNLOCK(vp, NULL, 0, td);
  181: 		goto update;
  182: 	}
  183: 	/*
  184: 	 * If the user is not root, ensure that they own the directory
  185: 	 * onto which we are attempting to mount.
  186: 	 */
  187: 	if ((error = VOP_GETATTR(vp, &va, td)) ||
  188: 	    (va.va_uid != p->p_ucred->cr_uid &&
  189: 	     (error = suser(td)))) {
  190: 		vput(vp);
  191: 		return (error);
  192: 	}
  193: 	if ((error = vinvalbuf(vp, V_SAVE, td, 0, 0)) != 0) {
  194: 		vput(vp);
  195: 		return (error);
  196: 	}
  197: 	if (vp->v_type != VDIR) {
  198: 		vput(vp);
  199: 		return (ENOTDIR);
  200: 	}
  201: 	if ((error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) != 0) {
  202: 		vput(vp);
  203: 		return (error);
  204: 	}
  205: 	for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
  206: 		if (!strcmp(vfsp->vfc_name, fstypename))
  207: 			break;
  208: 	if (vfsp == NULL) {
  209: 		linker_file_t lf;
  210: 
  211: 		/* Only load modules for root (very important!) */
  212: 		if ((error = suser(td)) != 0) {
  213: 			vput(vp);
  214: 			return error;
  215: 		}
  216: 		error = linker_load_file(fstypename, &lf);
  217: 		if (error || lf == NULL) {
  218: 			vput(vp);
  219: 			if (lf == NULL)
  220: 				error = ENODEV;
  221: 			return error;
  222: 		}
  223: 		lf->userrefs++;
  224: 		/* lookup again, see if the VFS was loaded */
  225: 		for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
  226: 			if (!strcmp(vfsp->vfc_name, fstypename))
  227: 				break;
  228: 		if (vfsp == NULL) {
  229: 			lf->userrefs--;
  230: 			linker_file_unload(lf);
  231: 			vput(vp);
  232: 			return (ENODEV);
  233: 		}
  234: 	}
  235: 	lwkt_gettoken(&vlock, vp->v_interlock);
  236: 	if ((vp->v_flag & VMOUNT) != 0 ||
  237: 	    vp->v_mountedhere != NULL) {
  238: 		lwkt_reltoken(&vlock);
  239: 		vput(vp);
  240: 		return (EBUSY);
  241: 	}
  242: 	vp->v_flag |= VMOUNT;
  243: 	lwkt_reltoken(&vlock);
  244: 
  245: 	/*
  246: 	 * Allocate and initialize the filesystem.
  247: 	 */
  248: 	mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK);
  249: 	bzero((char *)mp, (u_long)sizeof(struct mount));
  250: 	TAILQ_INIT(&mp->mnt_nvnodelist);
  251: 	TAILQ_INIT(&mp->mnt_reservedvnlist);
  252: 	mp->mnt_nvnodelistsize = 0;
  253: 	lockinit(&mp->mnt_lock, 0, "vfslock", 0, LK_NOPAUSE);
  254: 	vfs_busy(mp, LK_NOWAIT, NULL, td);
  255: 	mp->mnt_op = vfsp->vfc_vfsops;
  256: 	mp->mnt_vfc = vfsp;
  257: 	vfsp->vfc_refcount++;
  258: 	mp->mnt_stat.f_type = vfsp->vfc_typenum;
  259: 	mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
  260: 	strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
  261: 	mp->mnt_vnodecovered = vp;
  262: 	mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
  263: 	mp->mnt_iosize_max = DFLTPHYS;
  264: 	VOP_UNLOCK(vp, NULL, 0, td);
  265: update:
  266: 	/*
  267: 	 * Set the mount level flags.
  268: 	 */
  269: 	if (SCARG(uap, flags) & MNT_RDONLY)
  270: 		mp->mnt_flag |= MNT_RDONLY;
  271: 	else if (mp->mnt_flag & MNT_RDONLY)
  272: 		mp->mnt_kern_flag |= MNTK_WANTRDWR;
  273: 	mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
  274: 	    MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
  275: 	    MNT_NOSYMFOLLOW | MNT_IGNORE |
  276: 	    MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
  277: 	mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
  278: 	    MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
  279: 	    MNT_NOSYMFOLLOW | MNT_IGNORE |
  280: 	    MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
  281: 	/*
  282: 	 * Mount the filesystem.
  283: 	 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
  284: 	 * get.  No freeing of cn_pnbuf.
  285: 	 */
  286: 	error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, td);
  287: 	if (mp->mnt_flag & MNT_UPDATE) {
  288: 		if (mp->mnt_kern_flag & MNTK_WANTRDWR)
  289: 			mp->mnt_flag &= ~MNT_RDONLY;
  290: 		mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE);
  291: 		mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
  292: 		if (error) {
  293: 			mp->mnt_flag = flag;
  294: 			mp->mnt_kern_flag = flag2;
  295: 		}
  296: 		vfs_unbusy(mp, td);
  297: 		lwkt_gettoken(&vlock, vp->v_interlock);
  298: 		vp->v_flag &= ~VMOUNT;
  299: 		lwkt_reltoken(&vlock);
  300: 		vrele(vp);
  301: 		return (error);
  302: 	}
  303: 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
  304: 	/*
  305: 	 * Put the new filesystem on the mount list after root.
  306: 	 */
  307: 	cache_purge(vp);
  308: 	if (!error) {
  309: 		lwkt_gettoken(&vlock, vp->v_interlock);
  310: 		vp->v_flag &= ~VMOUNT;
  311: 		vp->v_mountedhere = mp;
  312: 		lwkt_reltoken(&vlock);
  313: 		lwkt_gettoken(&ilock, &mountlist_token);
  314: 		TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  315: 		lwkt_reltoken(&ilock);
  316: 		checkdirs(vp);
  317: 		VOP_UNLOCK(vp, NULL, 0, td);
  318: 		error = vfs_allocate_syncvnode(mp);
  319: 		vfs_unbusy(mp, td);
  320: 		if ((error = VFS_START(mp, 0, td)) != 0)
  321: 			vrele(vp);
  322: 	} else {
  323: 		lwkt_gettoken(&vlock, vp->v_interlock);
  324: 		vp->v_flag &= ~VMOUNT;
  325: 		lwkt_reltoken(&vlock);
  326: 		mp->mnt_vfc->vfc_refcount--;
  327: 		vfs_unbusy(mp, td);
  328: 		free((caddr_t)mp, M_MOUNT);
  329: 		vput(vp);
  330: 	}
  331: 	return (error);
  332: }
  333: 
  334: /*
  335:  * Scan all active processes to see if any of them have a current
  336:  * or root directory onto which the new filesystem has just been
  337:  * mounted. If so, replace them with the new mount point.
  338:  */
  339: static void
  340: checkdirs(struct vnode *olddp)
  341: {
  342: 	struct filedesc *fdp;
  343: 	struct vnode *newdp;
  344: 	struct proc *p;
  345: 
  346: 	if (olddp->v_usecount == 1)
  347: 		return;
  348: 	if (VFS_ROOT(olddp->v_mountedhere, &newdp))
  349: 		panic("mount: lost mount");
  350: 	FOREACH_PROC_IN_SYSTEM(p) {
  351: 		fdp = p->p_fd;
  352: 		if (fdp->fd_cdir == olddp) {
  353: 			vrele(fdp->fd_cdir);
  354: 			VREF(newdp);
  355: 			fdp->fd_cdir = newdp;
  356: 		}
  357: 		if (fdp->fd_rdir == olddp) {
  358: 			vrele(fdp->fd_rdir);
  359: 			VREF(newdp);
  360: 			fdp->fd_rdir = newdp;
  361: 		}
  362: 	}
  363: 	if (rootvnode == olddp) {
  364: 		vrele(rootvnode);
  365: 		VREF(newdp);
  366: 		rootvnode = newdp;
  367: 		vfs_cache_setroot(rootvnode);
  368: 	}
  369: 	vput(newdp);
  370: }
  371: 
  372: /*
  373:  * Unmount a file system.
  374:  *
  375:  * Note: unmount takes a path to the vnode mounted on as argument,
  376:  * not special file (as before).
  377:  */
  378: /*
  379:  * umount_args(char *path, int flags)
  380:  */
  381: /* ARGSUSED */
  382: int
  383: unmount(struct unmount_args *uap)
  384: {
  385: 	struct thread *td = curthread;
  386: 	struct proc *p = td->td_proc;
  387: 	struct vnode *vp;
  388: 	struct mount *mp;
  389: 	int error;
  390: 	struct nameidata nd;
  391: 
  392: 	KKASSERT(p);
  393: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_USERSPACE,
  394: 	    SCARG(uap, path), td);
  395: 	if ((error = namei(&nd)) != 0)
  396: 		return (error);
  397: 	vp = nd.ni_vp;
  398: 	NDFREE(&nd, NDF_ONLY_PNBUF);
  399: 	mp = vp->v_mount;
  400: 
  401: 	/*
  402: 	 * Only root, or the user that did the original mount is
  403: 	 * permitted to unmount this filesystem.
  404: 	 */
  405: 	if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
  406: 	    (error = suser(td))) {
  407: 		vput(vp);
  408: 		return (error);
  409: 	}
  410: 
  411: 	/*
  412: 	 * Don't allow unmounting the root file system.
  413: 	 */
  414: 	if (mp->mnt_flag & MNT_ROOTFS) {
  415: 		vput(vp);
  416: 		return (EINVAL);
  417: 	}
  418: 
  419: 	/*
  420: 	 * Must be the root of the filesystem
  421: 	 */
  422: 	if ((vp->v_flag & VROOT) == 0) {
  423: 		vput(vp);
  424: 		return (EINVAL);
  425: 	}
  426: 	vput(vp);
  427: 	return (dounmount(mp, SCARG(uap, flags), td));
  428: }
  429: 
  430: /*
  431:  * Do the actual file system unmount.
  432:  */
  433: int
  434: dounmount(struct mount *mp, int flags, struct thread *td)
  435: {
  436: 	struct vnode *coveredvp;
  437: 	int error;
  438: 	int async_flag;
  439: 	lwkt_tokref ilock;
  440: 
  441: 	lwkt_gettoken(&ilock, &mountlist_token);
  442: 	if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
  443: 		lwkt_reltoken(&ilock);
  444: 		return (EBUSY);
  445: 	}
  446: 	mp->mnt_kern_flag |= MNTK_UNMOUNT;
  447: 	/* Allow filesystems to detect that a forced unmount is in progress. */
  448: 	if (flags & MNT_FORCE)
  449: 		mp->mnt_kern_flag |= MNTK_UNMOUNTF;
  450: 	error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK |
  451: 	    ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &ilock, td);
  452: 	if (error) {
  453: 		mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
  454: 		if (mp->mnt_kern_flag & MNTK_MWAIT)
  455: 			wakeup((caddr_t)mp);
  456: 		return (error);
  457: 	}
  458: 
  459: 	if (mp->mnt_flag & MNT_EXPUBLIC)
  460: 		vfs_setpublicfs(NULL, NULL, NULL);
  461: 
  462: 	vfs_msync(mp, MNT_WAIT);
  463: 	async_flag = mp->mnt_flag & MNT_ASYNC;
  464: 	mp->mnt_flag &=~ MNT_ASYNC;
  465: 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
  466: 	if (mp->mnt_syncer != NULL)
  467: 		vrele(mp->mnt_syncer);
  468: 	if (((mp->mnt_flag & MNT_RDONLY) ||
  469: 	     (error = VFS_SYNC(mp, MNT_WAIT, td)) == 0) ||
  470: 	    (flags & MNT_FORCE))
  471: 		error = VFS_UNMOUNT(mp, flags, td);
  472: 	lwkt_gettokref(&ilock);
  473: 	if (error) {
  474: 		if (mp->mnt_syncer == NULL)
  475: 			vfs_allocate_syncvnode(mp);
  476: 		mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
  477: 		mp->mnt_flag |= async_flag;
  478: 		lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
  479: 		    &ilock, td);
  480: 		if (mp->mnt_kern_flag & MNTK_MWAIT)
  481: 			wakeup((caddr_t)mp);
  482: 		return (error);
  483: 	}
  484: 	TAILQ_REMOVE(&mountlist, mp, mnt_list);
  485: 	if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
  486: 		coveredvp->v_mountedhere = NULL;
  487: 		vrele(coveredvp);
  488: 	}
  489: 	mp->mnt_vfc->vfc_refcount--;
  490: 	if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
  491: 		panic("unmount: dangling vnode");
  492: 	lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &ilock, td);
  493: 	if (mp->mnt_kern_flag & MNTK_MWAIT)
  494: 		wakeup((caddr_t)mp);
  495: 	free((caddr_t)mp, M_MOUNT);
  496: 	return (0);
  497: }
  498: 
  499: /*
  500:  * Sync each mounted filesystem.
  501:  */
  502: 
  503: #ifdef DEBUG
  504: static int syncprt = 0;
  505: SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
  506: #endif
  507: 
  508: /* ARGSUSED */
  509: int
  510: sync(struct sync_args *uap)
  511: {
  512: 	struct thread *td = curthread;
  513: 	struct mount *mp, *nmp;
  514: 	lwkt_tokref ilock;
  515: 	int asyncflag;
  516: 
  517: 	lwkt_gettoken(&ilock, &mountlist_token);
  518: 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
  519: 		if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {
  520: 			nmp = TAILQ_NEXT(mp, mnt_list);
  521: 			continue;
  522: 		}
  523: 		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
  524: 			asyncflag = mp->mnt_flag & MNT_ASYNC;
  525: 			mp->mnt_flag &= ~MNT_ASYNC;
  526: 			vfs_msync(mp, MNT_NOWAIT);
  527: 			VFS_SYNC(mp, MNT_NOWAIT, td);
  528: 			mp->mnt_flag |= asyncflag;
  529: 		}
  530: 		lwkt_gettokref(&ilock);
  531: 		nmp = TAILQ_NEXT(mp, mnt_list);
  532: 		vfs_unbusy(mp, td);
  533: 	}
  534: 	lwkt_reltoken(&ilock);
  535: #if 0
  536: /*
  537:  * XXX don't call vfs_bufstats() yet because that routine
  538:  * was not imported in the Lite2 merge.
  539:  */
  540: #ifdef DIAGNOSTIC
  541: 	if (syncprt)
  542: 		vfs_bufstats();
  543: #endif /* DIAGNOSTIC */
  544: #endif
  545: 	return (0);
  546: }
  547: 
  548: /* XXX PRISON: could be per prison flag */
  549: static int prison_quotas;
  550: #if 0
  551: SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
  552: #endif
  553: 
  554: /*
  555:  *  quotactl_args(char *path, int fcmd, int uid, caddr_t arg)
  556:  *
  557:  * Change filesystem quotas.
  558:  */
  559: /* ARGSUSED */
  560: int
  561: quotactl(struct quotactl_args *uap)
  562: {
  563: 	struct thread *td = curthread;
  564: 	struct proc *p = td->td_proc;
  565: 	struct mount *mp;
  566: 	int error;
  567: 	struct nameidata nd;
  568: 
  569: 	KKASSERT(p);
  570: 	if (p->p_ucred->cr_prison && !prison_quotas)
  571: 		return (EPERM);
  572: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE,
  573: 	    SCARG(uap, path), td);
  574: 	if ((error = namei(&nd)) != 0)
  575: 		return (error);
  576: 	mp = nd.ni_vp->v_mount;
  577: 	NDFREE(&nd, NDF_ONLY_PNBUF);
  578: 	vrele(nd.ni_vp);
  579: 	return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
  580: 	    SCARG(uap, arg), td));
  581: }
  582: 
  583: int
  584: kern_statfs(struct nameidata *nd, struct statfs *buf)
  585: {
  586: 	struct thread *td = curthread;
  587: 	struct mount *mp;
  588: 	struct statfs *sp;
  589: 	int error;
  590: 
  591: 	error = namei(nd);
  592: 	if (error)
  593: 		return (error);
  594: 	mp = nd->ni_vp->v_mount;
  595: 	sp = &mp->mnt_stat;
  596: 	NDFREE(nd, NDF_ONLY_PNBUF);
  597: 	vrele(nd->ni_vp);
  598: 	error = VFS_STATFS(mp, sp, td);
  599: 	if (error)
  600: 		return (error);
  601: 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  602: 	bcopy(sp, buf, sizeof(*buf));
  603: 	/* Only root should have access to the fsid's. */
  604: 	if (suser(td))
  605: 		buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0;
  606: 	return (0);
  607: }
  608: 
  609: /*
  610:  * statfs_args(char *path, struct statfs *buf)
  611:  *
  612:  * Get filesystem statistics.
  613:  */
  614: int
  615: statfs(struct statfs_args *uap)
  616: {
  617: 	struct thread *td = curthread;
  618: 	struct nameidata nd;
  619: 	struct statfs buf;
  620: 	int error;
  621: 
  622: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td);
  623: 
  624: 	error = kern_statfs(&nd, &buf);
  625: 
  626: 	if (error == 0)
  627: 		error = copyout(&buf, uap->buf, sizeof(*uap->buf));
  628: 	return (error);
  629: }
  630: 
  631: int
  632: kern_fstatfs(int fd, struct statfs *buf)
  633: {
  634: 	struct thread *td = curthread;
  635: 	struct proc *p = td->td_proc;
  636: 	struct file *fp;
  637: 	struct mount *mp;
  638: 	struct statfs *sp;
  639: 	int error;
  640: 
  641: 	KKASSERT(p);
  642: 	error = getvnode(p->p_fd, fd, &fp);
  643: 	if (error)
  644: 		return (error);
  645: 	mp = ((struct vnode *)fp->f_data)->v_mount;
  646: 	if (mp == NULL)
  647: 		return (EBADF);
  648: 	sp = &mp->mnt_stat;
  649: 	error = VFS_STATFS(mp, sp, td);
  650: 	if (error)
  651: 		return (error);
  652: 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  653: 	bcopy(sp, buf, sizeof(*buf));
  654: 	/* Only root should have access to the fsid's. */
  655: 	if (suser(td))
  656: 		buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0;
  657: 	return (0);
  658: }
  659: 
  660: /*
  661:  * fstatfs_args(int fd, struct statfs *buf)
  662:  *
  663:  * Get filesystem statistics.
  664:  */
  665: int
  666: fstatfs(struct fstatfs_args *uap)
  667: {
  668: 	struct statfs buf;
  669: 	int error;
  670: 
  671: 	error = kern_fstatfs(uap->fd, &buf);
  672: 
  673: 	if (error == 0)
  674: 		error = copyout(&buf, uap->buf, sizeof(*uap->buf));
  675: 	return (error);
  676: }
  677: 
  678: /*
  679:  * getfsstat_args(struct statfs *buf, long bufsize, int flags)
  680:  *
  681:  * Get statistics on all filesystems.
  682:  */
  683: /* ARGSUSED */
  684: int
  685: getfsstat(struct getfsstat_args *uap)
  686: {
  687: 	struct thread *td = curthread;
  688: 	struct mount *mp, *nmp;
  689: 	struct statfs *sp;
  690: 	caddr_t sfsp;
  691: 	lwkt_tokref ilock;
  692: 	long count, maxcount, error;
  693: 
  694: 	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
  695: 	sfsp = (caddr_t)SCARG(uap, buf);
  696: 	count = 0;
  697: 	lwkt_gettoken(&ilock, &mountlist_token);
  698: 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
  699: 		if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {
  700: 			nmp = TAILQ_NEXT(mp, mnt_list);
  701: 			continue;
  702: 		}
  703: 		if (sfsp && count < maxcount) {
  704: 			sp = &mp->mnt_stat;
  705: 			/*
  706: 			 * If MNT_NOWAIT or MNT_LAZY is specified, do not
  707: 			 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
  708: 			 * overrides MNT_WAIT.
  709: 			 */
  710: 			if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
  711: 			    (SCARG(uap, flags) & MNT_WAIT)) &&
  712: 			    (error = VFS_STATFS(mp, sp, td))) {
  713: 				lwkt_gettokref(&ilock);
  714: 				nmp = TAILQ_NEXT(mp, mnt_list);
  715: 				vfs_unbusy(mp, td);
  716: 				continue;
  717: 			}
  718: 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
  719: 			error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
  720: 			if (error) {
  721: 				vfs_unbusy(mp, td);
  722: 				return (error);
  723: 			}
  724: 			sfsp += sizeof(*sp);
  725: 		}
  726: 		count++;
  727: 		lwkt_gettokref(&ilock);
  728: 		nmp = TAILQ_NEXT(mp, mnt_list);
  729: 		vfs_unbusy(mp, td);
  730: 	}
  731: 	lwkt_reltoken(&ilock);
  732: 	if (sfsp && count > maxcount)
  733: 		uap->sysmsg_result = maxcount;
  734: 	else
  735: 		uap->sysmsg_result = count;
  736: 	return (0);
  737: }
  738: 
  739: /*
  740:  * fchdir_args(int fd)
  741:  *
  742:  * Change current working directory to a given file descriptor.
  743:  */
  744: /* ARGSUSED */
  745: int
  746: fchdir(struct fchdir_args *uap)
  747: {
  748: 	struct thread *td = curthread;
  749: 	struct proc *p = td->td_proc;
  750: 	struct filedesc *fdp = p->p_fd;
  751: 	struct vnode *vp, *tdp;
  752: 	struct mount *mp;
  753: 	struct file *fp;
  754: 	int error;
  755: 
  756: 	if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
  757: 		return (error);
  758: 	vp = (struct vnode *)fp->f_data;
  759: 	VREF(vp);
  760: 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
  761: 	if (vp->v_type != VDIR)
  762: 		error = ENOTDIR;
  763: 	else
  764: 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, td);
  765: 	while (!error && (mp = vp->v_mountedhere) != NULL) {
  766: 		if (vfs_busy(mp, 0, NULL, td))
  767: 			continue;
  768: 		error = VFS_ROOT(mp, &tdp);
  769: 		vfs_unbusy(mp, td);
  770: 		if (error)
  771: 			break;
  772: 		vput(vp);
  773: 		vp = tdp;
  774: 	}
  775: 	if (error) {
  776: 		vput(vp);
  777: 		return (error);
  778: 	}
  779: 	VOP_UNLOCK(vp, NULL, 0, td);
  780: 	vrele(fdp->fd_cdir);
  781: 	fdp->fd_cdir = vp;
  782: 	return (0);
  783: }
  784: 
  785: int
  786: kern_chdir(struct nameidata *nd)
  787: {
  788: 	struct thread *td = curthread;
  789: 	struct proc *p = td->td_proc;
  790: 	struct filedesc *fdp = p->p_fd;
  791: 	int error;
  792: 
  793: 	error = change_dir(nd, td);
  794: 	if (error)
  795: 		return (error);
  796: 	NDFREE(nd, NDF_ONLY_PNBUF);
  797: 	vrele(fdp->fd_cdir);
  798: 	fdp->fd_cdir = nd->ni_vp;
  799: 	return (0);
  800: }
  801: 
  802: /*
  803:  * chdir_args(char *path)
  804:  *
  805:  * Change current working directory (``.'').
  806:  */
  807: int
  808: chdir(struct chdir_args *uap)
  809: {
  810: 	struct thread *td = curthread;
  811: 	struct nameidata nd;
  812: 	int error;
  813: 
  814: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_USERSPACE,
  815: 	    uap->path, td);
  816: 
  817: 	error = kern_chdir(&nd);
  818: 
  819: 	return (error);
  820: }
  821: 
  822: /*
  823:  * Helper function for raised chroot(2) security function:  Refuse if
  824:  * any filedescriptors are open directories.
  825:  */
  826: static int
  827: chroot_refuse_vdir_fds(fdp)
  828: 	struct filedesc *fdp;
  829: {
  830: 	struct vnode *vp;
  831: 	struct file *fp;
  832: 	int error;
  833: 	int fd;
  834: 
  835: 	for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
  836: 		error = getvnode(fdp, fd, &fp);
  837: 		if (error)
  838: 			continue;
  839: 		vp = (struct vnode *)fp->f_data;
  840: 		if (vp->v_type != VDIR)
  841: 			continue;
  842: 		return(EPERM);
  843: 	}
  844: 	return (0);
  845: }
  846: 
  847: /*
  848:  * This sysctl determines if we will allow a process to chroot(2) if it
  849:  * has a directory open:
  850:  *	0: disallowed for all processes.
  851:  *	1: allowed for processes that were not already chroot(2)'ed.
  852:  *	2: allowed for all processes.
  853:  */
  854: 
  855: static int chroot_allow_open_directories = 1;
  856: 
  857: SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
  858:      &chroot_allow_open_directories, 0, "");
  859: 
  860: /*
  861:  * chroot_args(char *path)
  862:  *
  863:  * Change notion of root (``/'') directory.
  864:  */
  865: /* ARGSUSED */
  866: int
  867: chroot(struct chroot_args *uap)
  868: {
  869: 	struct thread *td = curthread;
  870: 	struct proc *p = td->td_proc;
  871: 	struct filedesc *fdp = p->p_fd;
  872: 	int error;
  873: 	struct nameidata nd;
  874: 
  875: 	KKASSERT(p);
  876: 	error = suser_cred(p->p_ucred, PRISON_ROOT);
  877: 	if (error)
  878: 		return (error);
  879: 	if (chroot_allow_open_directories == 0 ||
  880: 	    (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode))
  881: 		error = chroot_refuse_vdir_fds(fdp);
  882: 	if (error)
  883: 		return (error);
  884: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_USERSPACE,
  885: 	    SCARG(uap, path), td);
  886: 	if ((error = change_dir(&nd, td)) != 0)
  887: 		return (error);
  888: 	NDFREE(&nd, NDF_ONLY_PNBUF);
  889: 	vrele(fdp->fd_rdir);
  890: 	fdp->fd_rdir = nd.ni_vp;
  891: 	if (!fdp->fd_jdir) {
  892: 		fdp->fd_jdir = nd.ni_vp;
  893:                 VREF(fdp->fd_jdir);
  894: 	}
  895: 	return (0);
  896: }
  897: 
  898: /*
  899:  * Common routine for chroot and chdir.
  900:  */
  901: static int
  902: change_dir(struct nameidata *ndp, struct thread *td)
  903: {
  904: 	struct vnode *vp;
  905: 	int error;
  906: 
  907: 	error = namei(ndp);
  908: 	if (error)
  909: 		return (error);
  910: 	vp = ndp->ni_vp;
  911: 	if (vp->v_type != VDIR)
  912: 		error = ENOTDIR;
  913: 	else
  914: 		error = VOP_ACCESS(vp, VEXEC, ndp->ni_cnd.cn_cred, td);
  915: 	if (error)
  916: 		vput(vp);
  917: 	else
  918: 		VOP_UNLOCK(vp, NULL, 0, td);
  919: 	return (error);
  920: }
  921: 
  922: int
  923: kern_open(struct nameidata *nd, int oflags, int mode, int *res)
  924: {
  925: 	struct thread *td = curthread;
  926: 	struct proc *p = td->td_proc;
  927: 	struct filedesc *fdp = p->p_fd;
  928: 	struct file *fp;
  929: 	struct vnode *vp;
  930: 	int cmode, flags;
  931: 	struct file *nfp;
  932: 	int type, indx, error;
  933: 	struct flock lf;
  934: 
  935: 	if ((oflags & O_ACCMODE) == O_ACCMODE)
  936: 		return (EINVAL);
  937: 	flags = FFLAGS(oflags);
  938: 	error = falloc(p, &nfp, &indx);
  939: 	if (error)
  940: 		return (error);
  941: 	fp = nfp;
  942: 	cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
  943: 	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */
  944: 	/*
  945: 	 * Bump the ref count to prevent another process from closing
  946: 	 * the descriptor while we are blocked in vn_open()
  947: 	 */
  948: 	fhold(fp);
  949: 	error = vn_open(nd, flags, cmode);
  950: 	if (error) {
  951: 		/*
  952: 		 * release our own reference
  953: 		 */
  954: 		fdrop(fp, td);
  955: 
  956: 		/*
  957: 		 * handle special fdopen() case.  bleh.  dupfdopen() is
  958: 		 * responsible for dropping the old contents of ofiles[indx]
  959: 		 * if it succeeds.
  960: 		 */
  961: 		if ((error == ENODEV || error == ENXIO) &&
  962: 		    p->p_dupfd >= 0 &&			/* XXX from fdopen */
  963: 		    (error =
  964: 			dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
  965: 			*res = indx;
  966: 			return (0);
  967: 		}
  968: 		/*
  969: 		 * Clean up the descriptor, but only if another thread hadn't
  970: 		 * replaced or closed it.
  971: 		 */
  972: 		if (fdp->fd_ofiles[indx] == fp) {
  973: 			fdp->fd_ofiles[indx] = NULL;
  974: 			fdrop(fp, td);
  975: 		}
  976: 
  977: 		if (error == ERESTART)
  978: 			error = EINTR;
  979: 		return (error);
  980: 	}
  981: 	p->p_dupfd = 0;
  982: 	NDFREE(nd, NDF_ONLY_PNBUF);
  983: 	vp = nd->ni_vp;
  984: 
  985: 	/*
  986: 	 * There should be 2 references on the file, one from the descriptor
  987: 	 * table, and one for us.
  988: 	 *
  989: 	 * Handle the case where someone closed the file (via its file
  990: 	 * descriptor) while we were blocked.  The end result should look
  991: 	 * like opening the file succeeded but it was immediately closed.
  992: 	 */
  993: 	if (fp->f_count == 1) {
  994: 		KASSERT(fdp->fd_ofiles[indx] != fp,
  995: 		    ("Open file descriptor lost all refs"));
  996: 		VOP_UNLOCK(vp, NULL, 0, td);
  997: 		vn_close(vp, flags & FMASK, td);
  998: 		fdrop(fp, td);
  999: 		*res = indx;
 1000: 		return 0;
 1001: 	}
 1002: 
 1003: 	fp->f_data = (caddr_t)vp;
 1004: 	fp->f_flag = flags & FMASK;
 1005: 	fp->f_ops = &vnops;
 1006: 	fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
 1007: 	if (flags & (O_EXLOCK | O_SHLOCK)) {
 1008: 		lf.l_whence = SEEK_SET;
 1009: 		lf.l_start = 0;
 1010: 		lf.l_len = 0;
 1011: 		if (flags & O_EXLOCK)
 1012: 			lf.l_type = F_WRLCK;
 1013: 		else
 1014: 			lf.l_type = F_RDLCK;
 1015: 		type = F_FLOCK;
 1016: 		if ((flags & FNONBLOCK) == 0)
 1017: 			type |= F_WAIT;
 1018: 		VOP_UNLOCK(vp, NULL, 0, td);
 1019: 		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
 1020: 			/*
 1021: 			 * lock request failed.  Normally close the descriptor
 1022: 			 * but handle the case where someone might have dup()d
 1023: 			 * it when we weren't looking.  One reference is
 1024: 			 * owned by the descriptor array, the other by us.
 1025: 			 */
 1026: 			if (fdp->fd_ofiles[indx] == fp) {
 1027: 				fdp->fd_ofiles[indx] = NULL;
 1028: 				fdrop(fp, td);
 1029: 			}
 1030: 			fdrop(fp, td);
 1031: 			return (error);
 1032: 		}
 1033: 		vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 1034: 		fp->f_flag |= FHASLOCK;
 1035: 	}
 1036: 	/* assert that vn_open created a backing object if one is needed */
 1037: 	KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
 1038: 		("open: vmio vnode has no backing object after vn_open"));
 1039: 	VOP_UNLOCK(vp, NULL, 0, td);
 1040: 
 1041: 	/*
 1042: 	 * release our private reference, leaving the one associated with the
 1043: 	 * descriptor table intact.
 1044: 	 */
 1045: 	fdrop(fp, td);
 1046: 	*res = indx;
 1047: 	return (0);
 1048: }
 1049: 
 1050: /*
 1051:  * open_args(char *path, int flags, int mode)
 1052:  *
 1053:  * Check permissions, allocate an open file structure,
 1054:  * and call the device open routine if any.
 1055:  */
 1056: int
 1057: open(struct open_args *uap)
 1058: {
 1059: 	struct thread *td = curthread;
 1060: 	struct nameidata nd;
 1061: 	int error;
 1062: 
 1063: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td);
 1064: 
 1065: 	error = kern_open(&nd, uap->flags, uap->mode, &uap->sysmsg_result);
 1066: 
 1067: 	return (error);
 1068: }
 1069: 
 1070: int
 1071: kern_mknod(struct nameidata *nd, int mode, int dev)
 1072: {
 1073: 	struct thread *td = curthread;
 1074: 	struct proc *p = td->td_proc;
 1075: 	struct vnode *vp;
 1076: 	struct vattr vattr;
 1077: 	int error;
 1078: 	int whiteout = 0;
 1079: 
 1080: 	KKASSERT(p);
 1081: 
 1082: 	switch (mode & S_IFMT) {
 1083: 	case S_IFCHR:
 1084: 	case S_IFBLK:
 1085: 		error = suser(td);
 1086: 		break;
 1087: 	default:
 1088: 		error = suser_cred(p->p_ucred, PRISON_ROOT);
 1089: 		break;
 1090: 	}
 1091: 	if (error)
 1092: 		return (error);
 1093: 	bwillwrite();
 1094: 	error = namei(nd);
 1095: 	if (error)
 1096: 		return (error);
 1097: 	vp = nd->ni_vp;
 1098: 	if (vp != NULL)
 1099: 		error = EEXIST;
 1100: 	else {
 1101: 		VATTR_NULL(&vattr);
 1102: 		vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
 1103: 		vattr.va_rdev = dev;
 1104: 		whiteout = 0;
 1105: 
 1106: 		switch (mode & S_IFMT) {
 1107: 		case S_IFMT:	/* used by badsect to flag bad sectors */
 1108: 			vattr.va_type = VBAD;
 1109: 			break;
 1110: 		case S_IFCHR:
 1111: 			vattr.va_type = VCHR;
 1112: 			break;
 1113: 		case S_IFBLK:
 1114: 			vattr.va_type = VBLK;
 1115: 			break;
 1116: 		case S_IFWHT:
 1117: 			whiteout = 1;
 1118: 			break;
 1119: 		default:
 1120: 			error = EINVAL;
 1121: 			break;
 1122: 		}
 1123: 	}
 1124: 	if (error == 0) {
 1125: 		VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE);
 1126: 		if (whiteout)
 1127: 			error = VOP_WHITEOUT(nd->ni_dvp, NCPNULL,
 1128: 			    &nd->ni_cnd, NAMEI_CREATE);
 1129: 		else {
 1130: 			error = VOP_MKNOD(nd->ni_dvp, NCPNULL, &nd->ni_vp,
 1131: 			    &nd->ni_cnd, &vattr);
 1132: 			if (error == 0)
 1133: 				vput(nd->ni_vp);
 1134: 		}
 1135: 		NDFREE(nd, NDF_ONLY_PNBUF);
 1136: 		vput(nd->ni_dvp);
 1137: 	} else {
 1138: 		NDFREE(nd, NDF_ONLY_PNBUF);
 1139: 		if (nd->ni_dvp == vp)
 1140: 			vrele(nd->ni_dvp);
 1141: 		else
 1142: 			vput(nd->ni_dvp);
 1143: 		if (vp)
 1144: 			vrele(vp);
 1145: 	}
 1146: 	ASSERT_VOP_UNLOCKED(nd->ni_dvp, "mknod");
 1147: 	ASSERT_VOP_UNLOCKED(nd->ni_vp, "mknod");
 1148: 	return (error);
 1149: }
 1150: 
 1151: /*
 1152:  * mknod_args(char *path, int mode, int dev)
 1153:  *
 1154:  * Create a special file.
 1155:  */
 1156: int
 1157: mknod(struct mknod_args *uap)
 1158: {
 1159: 	struct thread *td = curthread;
 1160: 	struct nameidata nd;
 1161: 	int error;
 1162: 
 1163: 	NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT, UIO_USERSPACE, uap->path,
 1164: 	    td);
 1165: 
 1166: 	error = kern_mknod(&nd, uap->mode, uap->dev);
 1167: 
 1168: 	return (error);
 1169: }
 1170: 
 1171: int
 1172: kern_mkfifo(struct nameidata *nd, int mode)
 1173: {
 1174: 	struct thread *td = curthread;
 1175: 	struct proc *p = td->td_proc;
 1176: 	struct vattr vattr;
 1177: 	int error;
 1178: 
 1179: 	bwillwrite();
 1180: 	error = namei(nd);
 1181: 	if (error)
 1182: 		return (error);
 1183: 	if (nd->ni_vp != NULL) {
 1184: 		NDFREE(nd, NDF_ONLY_PNBUF);
 1185: 		if (nd->ni_dvp == nd->ni_vp)
 1186: 			vrele(nd->ni_dvp);
 1187: 		else
 1188: 			vput(nd->ni_dvp);
 1189: 		vrele(nd->ni_vp);
 1190: 		return (EEXIST);
 1191: 	}
 1192: 	VATTR_NULL(&vattr);
 1193: 	vattr.va_type = VFIFO;
 1194: 	vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
 1195: 	VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE);
 1196: 	error = VOP_MKNOD(nd->ni_dvp, NCPNULL, &nd->ni_vp, &nd->ni_cnd, &vattr);
 1197: 	if (error == 0)
 1198: 		vput(nd->ni_vp);
 1199: 	NDFREE(nd, NDF_ONLY_PNBUF);
 1200: 	vput(nd->ni_dvp);
 1201: 	return (error);
 1202: }
 1203: 
 1204: /*
 1205:  * mkfifo_args(char *path, int mode)
 1206:  *
 1207:  * Create a named pipe.
 1208:  */
 1209: int
 1210: mkfifo(struct mkfifo_args *uap)
 1211: {
 1212: 	struct thread *td = curthread;
 1213: 	struct nameidata nd;
 1214: 	int error;
 1215: 
 1216: 	NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT, UIO_USERSPACE, uap->path,
 1217: 	    td);
 1218: 
 1219: 	error = kern_mkfifo(&nd, uap->mode);
 1220: 
 1221: 	return (error);
 1222: }
 1223: 
 1224: int
 1225: kern_link(struct nameidata *nd, struct nameidata *linknd)
 1226: {
 1227: 	struct thread *td = curthread;
 1228: 	struct proc *p = td->td_proc;
 1229: 	struct vnode *vp;
 1230: 	int error;
 1231: 
 1232: 	bwillwrite();
 1233: 	error = namei(nd);
 1234: 	if (error)
 1235: 		return (error);
 1236: 	NDFREE(nd, NDF_ONLY_PNBUF);
 1237: 	vp = nd->ni_vp;
 1238: 	if (vp->v_type == VDIR)
 1239: 		error = EPERM;		/* POSIX */
 1240: 	else {
 1241: 		error = namei(linknd);
 1242: 		if (error == 0) {
 1243: 			if (linknd->ni_vp != NULL) {
 1244: 				if (linknd->ni_vp)
 1245: 					vrele(linknd->ni_vp);
 1246: 				error = EEXIST;
 1247: 			} else {
 1248: 				VOP_LEASE(linknd->ni_dvp, td, p->p_ucred,
 1249: 				    LEASE_WRITE);
 1250: 				VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 1251: 				error = VOP_LINK(linknd->ni_dvp, NCPNULL, vp,
 1252: 				    &linknd->ni_cnd);
 1253: 			}
 1254: 			NDFREE(linknd, NDF_ONLY_PNBUF);
 1255: 			if (linknd->ni_dvp == linknd->ni_vp)
 1256: 				vrele(linknd->ni_dvp);
 1257: 			else
 1258: 				vput(linknd->ni_dvp);
 1259: 			ASSERT_VOP_UNLOCKED(linknd->ni_dvp, "link");
 1260: 			ASSERT_VOP_UNLOCKED(linknd->ni_vp, "link");
 1261: 		}
 1262: 	}
 1263: 	vrele(vp);
 1264: 	return (error);
 1265: }
 1266: 
 1267: /*
 1268:  * link_args(char *path, char *link)
 1269:  *
 1270:  * Make a hard file link.
 1271:  */
 1272: int
 1273: link(struct link_args *uap)
 1274: {
 1275: 	struct thread *td = curthread;
 1276: 	struct nameidata nd, linknd;
 1277: 	int error;
 1278: 
 1279: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_NOOBJ, UIO_USERSPACE,
 1280: 	    uap->path, td);
 1281: 	NDINIT(&linknd, NAMEI_CREATE, CNP_LOCKPARENT | CNP_NOOBJ,
 1282: 	    UIO_USERSPACE, uap->link, td);
 1283: 
 1284: 	error = kern_link(&nd, &linknd);
 1285: 
 1286: 	return (error);
 1287: }
 1288: 
 1289: int
 1290: kern_symlink(char *path, struct nameidata *nd)
 1291: {
 1292: 	struct thread *td = curthread;
 1293: 	struct proc *p = td->td_proc;
 1294: 	struct vattr vattr;
 1295: 	int error;
 1296: 
 1297: 	bwillwrite();
 1298: 	error = namei(nd);
 1299: 	if (error)
 1300: 		return (error);
 1301: 	if (nd->ni_vp) {
 1302: 		NDFREE(nd, NDF_ONLY_PNBUF);
 1303: 		if (nd->ni_dvp == nd->ni_vp)
 1304: 			vrele(nd->ni_dvp);
 1305: 		else
 1306: 			vput(nd->ni_dvp);
 1307: 		vrele(nd->ni_vp);
 1308: 		return (EEXIST);
 1309: 	}
 1310: 	VATTR_NULL(&vattr);
 1311: 	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
 1312: 	VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE);
 1313: 	error = VOP_SYMLINK(nd->ni_dvp, NCPNULL, &nd->ni_vp, &nd->ni_cnd,
 1314: 	    &vattr, path);
 1315: 	NDFREE(nd, NDF_ONLY_PNBUF);
 1316: 	if (error == 0)
 1317: 		vput(nd->ni_vp);
 1318: 	vput(nd->ni_dvp);
 1319: 	ASSERT_VOP_UNLOCKED(nd->ni_dvp, "symlink");
 1320: 	ASSERT_VOP_UNLOCKED(nd->ni_vp, "symlink");
 1321: 
 1322: 	return (error);
 1323: }
 1324: 
 1325: /*
 1326:  * symlink(char *path, char *link)
 1327:  *
 1328:  * Make a symbolic link.
 1329:  */
 1330: int
 1331: symlink(struct symlink_args *uap)
 1332: {
 1333: 	struct thread *td = curthread;
 1334: 	struct nameidata nd;
 1335: 	char *path;
 1336: 	int error;
 1337: 
 1338: 	path = zalloc(namei_zone);
 1339: 	error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
 1340: 	if (error)
 1341: 		return (error);
 1342: 	NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT | CNP_NOOBJ, UIO_USERSPACE,
 1343: 	    uap->link, td);
 1344: 
 1345: 	error = kern_symlink(path, &nd);
 1346: 
 1347: 	zfree(namei_zone, path);
 1348: 	return (error);
 1349: }
 1350: 
 1351: /*
 1352:  * undelete_args(char *path)
 1353:  *
 1354:  * Delete a whiteout from the filesystem.
 1355:  */
 1356: /* ARGSUSED */
 1357: int
 1358: undelete(struct undelete_args *uap)
 1359: {
 1360: 	struct thread *td = curthread;
 1361: 	struct proc *p = td->td_proc;
 1362: 	int error;
 1363: 	struct nameidata nd;
 1364: 
 1365: 	bwillwrite();
 1366: 	NDINIT(&nd, NAMEI_DELETE, CNP_LOCKPARENT | CNP_DOWHITEOUT, UIO_USERSPACE,
 1367: 	    SCARG(uap, path), td);
 1368: 	error = namei(&nd);
 1369: 	if (error)
 1370: 		return (error);
 1371: 
 1372: 	if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & CNP_ISWHITEOUT)) {
 1373: 		NDFREE(&nd, NDF_ONLY_PNBUF);
 1374: 		if (nd.ni_dvp == nd.ni_vp)
 1375: 			vrele(nd.ni_dvp);
 1376: 		else
 1377: 			vput(nd.ni_dvp);
 1378: 		if (nd.ni_vp)
 1379: 			vrele(nd.ni_vp);
 1380: 		return (EEXIST);
 1381: 	}
 1382: 
 1383: 	VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE);
 1384: 	error = VOP_WHITEOUT(nd.ni_dvp, NCPNULL, &nd.ni_cnd, NAMEI_DELETE);
 1385: 	NDFREE(&nd, NDF_ONLY_PNBUF);
 1386: 	vput(nd.ni_dvp);
 1387: 	ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete");
 1388: 	ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete");
 1389: 	return (error);
 1390: }
 1391: 
 1392: int
 1393: kern_unlink(struct nameidata *nd)
 1394: {
 1395: 	struct thread *td = curthread;
 1396: 	struct proc *p = td->td_proc;
 1397: 	struct vnode *vp;
 1398: 	int error;
 1399: 
 1400: 	bwillwrite();
 1401: 	error = namei(nd);
 1402: 	if (error)
 1403: 		return (error);
 1404: 	vp = nd->ni_vp;
 1405: 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 1406: 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 1407: 
 1408: 	if (vp->v_type == VDIR)
 1409: 		error = EPERM;		/* POSIX */
 1410: 	else {
 1411: 		/*
 1412: 		 * The root of a mounted filesystem cannot be deleted.
 1413: 		 *
 1414: 		 * XXX: can this only be a VDIR case?
 1415: 		 */
 1416: 		if (vp->v_flag & VROOT)
 1417: 			error = EBUSY;
 1418: 	}
 1419: 
 1420: 	if (error == 0) {
 1421: 		VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE);
 1422: 		error = VOP_REMOVE(nd->ni_dvp, NCPNULL, vp, &nd->ni_cnd);
 1423: 	}
 1424: 	NDFREE(nd, NDF_ONLY_PNBUF);
 1425: 	if (nd->ni_dvp == vp)
 1426: 		vrele(nd->ni_dvp);
 1427: 	else
 1428: 		vput(nd->ni_dvp);
 1429: 	if (vp != NULLVP)
 1430: 		vput(vp);
 1431: 	ASSERT_VOP_UNLOCKED(nd->ni_dvp, "unlink");
 1432: 	ASSERT_VOP_UNLOCKED(nd->ni_vp, "unlink");
 1433: 	return (error);
 1434: }
 1435: 
 1436: /*
 1437:  * unlink_args(char *path)
 1438:  *
 1439:  * Delete a name from the filesystem.
 1440:  */
 1441: int
 1442: unlink(struct unlink_args *uap)
 1443: {
 1444: 	struct thread *td = curthread;
 1445: 	struct nameidata nd;
 1446: 	int error;
 1447: 
 1448: 	NDINIT(&nd, NAMEI_DELETE, CNP_LOCKPARENT, UIO_USERSPACE, uap->path,
 1449: 	    td);
 1450: 
 1451: 	error = kern_unlink(&nd);
 1452: 
 1453: 	return (error);
 1454: }
 1455: 
 1456: int
 1457: kern_lseek(int fd, off_t offset, int whence, off_t *res)
 1458: {
 1459: 	struct thread *td = curthread;
 1460: 	struct proc *p = td->td_proc;
 1461: 	struct filedesc *fdp = p->p_fd;
 1462: 	struct file *fp;
 1463: 	struct vattr vattr;
 1464: 	int error;
 1465: 
 1466: 	if (fd >= fdp->fd_nfiles ||
 1467: 	    (fp = fdp->fd_ofiles[fd]) == NULL)
 1468: 		return (EBADF);
 1469: 	if (fp->f_type != DTYPE_VNODE)
 1470: 		return (ESPIPE);
 1471: 	switch (whence) {
 1472: 	case L_INCR:
 1473: 		fp->f_offset += offset;
 1474: 		break;
 1475: 	case L_XTND:
 1476: 		error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, td);
 1477: 		if (error)
 1478: 			return (error);
 1479: 		fp->f_offset = offset + vattr.va_size;
 1480: 		break;
 1481: 	case L_SET:
 1482: 		fp->f_offset = offset;
 1483: 		break;
 1484: 	default:
 1485: 		return (EINVAL);
 1486: 	}
 1487: 	*res = fp->f_offset;
 1488: 	return (0);
 1489: }
 1490: 
 1491: /*
 1492:  * lseek_args(int fd, int pad, off_t offset, int whence)
 1493:  *
 1494:  * Reposition read/write file offset.
 1495:  */
 1496: int
 1497: lseek(struct lseek_args *uap)
 1498: {
 1499: 	int error;
 1500: 
 1501: 	error = kern_lseek(uap->fd, uap->offset, uap->whence,
 1502: 	    &uap->sysmsg_offset);
 1503: 
 1504: 	return (error);
 1505: }
 1506: 
 1507: int
 1508: kern_access(struct nameidata *nd, int aflags)
 1509: {
 1510: 	struct thread *td = curthread;
 1511: 	struct proc *p = td->td_proc;
 1512: 	struct ucred *cred, *tmpcred;
 1513: 	struct vnode *vp;
 1514: 	int error, flags;
 1515: 
 1516: 	cred = p->p_ucred;
 1517: 	/*
 1518: 	 * Create and modify a temporary credential instead of one that
 1519: 	 * is potentially shared.  This could also mess up socket
 1520: 	 * buffer accounting which can run in an interrupt context.
 1521: 	 */
 1522: 	tmpcred = crdup(cred);
 1523: 	tmpcred->cr_uid = p->p_ucred->cr_ruid;
 1524: 	tmpcred->cr_groups[0] = p->p_ucred->cr_rgid;
 1525: 	p->p_ucred = tmpcred;
 1526: 	nd->ni_cnd.cn_cred = tmpcred;
 1527: 	error = namei(nd);
 1528: 	if (error)
 1529: 		goto out1;
 1530: 	vp = nd->ni_vp;
 1531: 
 1532: 	/* Flags == 0 means only check for existence. */
 1533: 	if (aflags) {
 1534: 		flags = 0;
 1535: 		if (aflags & R_OK)
 1536: 			flags |= VREAD;
 1537: 		if (aflags & W_OK)
 1538: 			flags |= VWRITE;
 1539: 		if (aflags & X_OK)
 1540: 			flags |= VEXEC;
 1541: 		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
 1542: 			error = VOP_ACCESS(vp, flags, tmpcred, td);
 1543: 	}
 1544: 	NDFREE(nd, NDF_ONLY_PNBUF);
 1545: 	vput(vp);
 1546: out1:
 1547: 	p->p_ucred = cred;
 1548: 	crfree(tmpcred);
 1549: 	return (error);
 1550: }
 1551: 
 1552: /*
 1553:  * access_args(char *path, int flags)
 1554:  *
 1555:  * Check access permissions.
 1556:  */
 1557: int
 1558: access(struct access_args *uap)
 1559: {
 1560: 	struct thread *td = curthread;
 1561: 	struct nameidata nd;
 1562: 	int error;
 1563: 
 1564: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF | CNP_NOOBJ,
 1565: 	    UIO_USERSPACE, uap->path, td);
 1566: 
 1567: 	error = kern_access(&nd, uap->flags);
 1568: 
 1569: 	return (error);
 1570: }
 1571: 
 1572: int
 1573: kern_stat(struct nameidata *nd, struct stat *st)
 1574: {
 1575: 	struct thread *td = curthread;
 1576: 	int error;
 1577: 
 1578: 	error = namei(nd);
 1579: 	if (error)
 1580: 		return (error);
 1581: 	error = vn_stat(nd->ni_vp, st, td);
 1582: 	NDFREE(nd, NDF_ONLY_PNBUF);
 1583: 	vput(nd->ni_vp);
 1584: 	return (error);
 1585: }
 1586: 
 1587: /*
 1588:  * stat_args(char *path, struct stat *ub)
 1589:  *
 1590:  * Get file status; this version follows links.
 1591:  */
 1592: int
 1593: stat(struct stat_args *uap)
 1594: {
 1595: 	struct thread *td = curthread;
 1596: 	struct nameidata nd;
 1597: 	struct stat st;
 1598: 	int error;
 1599: 
 1600: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF | CNP_NOOBJ,
 1601: 	    UIO_USERSPACE, uap->path, td);
 1602: 
 1603: 	error = kern_stat(&nd, &st);
 1604: 
 1605: 	if (error == 0)
 1606: 		error = copyout(&st, uap->ub, sizeof(*uap->ub));
 1607: 	return (error);
 1608: }
 1609: 
 1610: /*
 1611:  * lstat_args(char *path, struct stat *ub)
 1612:  *
 1613:  * Get file status; this version does not follow links.
 1614:  */
 1615: int
 1616: lstat(struct lstat_args *uap)
 1617: {
 1618: 	struct thread *td = curthread;
 1619: 	struct nameidata nd;
 1620: 	struct stat st;
 1621: 	int error;
 1622: 
 1623: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_NOOBJ,
 1624: 	    UIO_USERSPACE, SCARG(uap, path), td);
 1625: 
 1626: 	error = kern_stat(&nd, &st);
 1627: 
 1628: 	if (error == 0)
 1629: 		error = copyout(&st, uap->ub, sizeof(*uap->ub));
 1630: 	return (error);
 1631: }
 1632: 
 1633: void
 1634: cvtnstat(sb, nsb)
 1635: 	struct stat *sb;
 1636: 	struct nstat *nsb;
 1637: {
 1638: 	nsb->st_dev = sb->st_dev;
 1639: 	nsb->st_ino = sb->st_ino;
 1640: 	nsb->st_mode = sb->st_mode;
 1641: 	nsb->st_nlink = sb->st_nlink;
 1642: 	nsb->st_uid = sb->st_uid;
 1643: 	nsb->st_gid = sb->st_gid;
 1644: 	nsb->st_rdev = sb->st_rdev;
 1645: 	nsb->st_atimespec = sb->st_atimespec;
 1646: 	nsb->st_mtimespec = sb->st_mtimespec;
 1647: 	nsb->st_ctimespec = sb->st_ctimespec;
 1648: 	nsb->st_size = sb->st_size;
 1649: 	nsb->st_blocks = sb->st_blocks;
 1650: 	nsb->st_blksize = sb->st_blksize;
 1651: 	nsb->st_flags = sb->st_flags;
 1652: 	nsb->st_gen = sb->st_gen;
 1653: 	nsb->st_qspare[0] = sb->st_qspare[0];
 1654: 	nsb->st_qspare[1] = sb->st_qspare[1];
 1655: }
 1656: 
 1657: /*
 1658:  * nstat_args(char *path, struct nstat *ub)
 1659:  */
 1660: /* ARGSUSED */
 1661: int
 1662: nstat(struct nstat_args *uap)
 1663: {
 1664: 	struct thread *td = curthread;
 1665: 	struct stat sb;
 1666: 	struct nstat nsb;
 1667: 	int error;
 1668: 	struct nameidata nd;
 1669: 
 1670: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF | CNP_NOOBJ,
 1671: 	    UIO_USERSPACE, SCARG(uap, path), td);
 1672: 	if ((error = namei(&nd)) != 0)
 1673: 		return (error);
 1674: 	NDFREE(&nd, NDF_ONLY_PNBUF);
 1675: 	error = vn_stat(nd.ni_vp, &sb, td);
 1676: 	vput(nd.ni_vp);
 1677: 	if (error)
 1678: 		return (error);
 1679: 	cvtnstat(&sb, &nsb);
 1680: 	error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
 1681: 	return (error);
 1682: }
 1683: 
 1684: /*
 1685:  * lstat_args(char *path, struct stat *ub)
 1686:  *
 1687:  * Get file status; this version does not follow links.
 1688:  */
 1689: /* ARGSUSED */
 1690: int
 1691: nlstat(struct nlstat_args *uap)
 1692: {
 1693: 	struct thread *td = curthread;
 1694: 	int error;
 1695: 	struct vnode *vp;
 1696: 	struct stat sb;
 1697: 	struct nstat nsb;
 1698: 	struct nameidata nd;
 1699: 
 1700: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_NOOBJ,
 1701: 	    UIO_USERSPACE, SCARG(uap, path), td);
 1702: 	if ((error = namei(&nd)) != 0)
 1703: 		return (error);
 1704: 	vp = nd.ni_vp;
 1705: 	NDFREE(&nd, NDF_ONLY_PNBUF);
 1706: 	error = vn_stat(vp, &sb, td);
 1707: 	vput(vp);
 1708: 	if (error)
 1709: 		return (error);
 1710: 	cvtnstat(&sb, &nsb);
 1711: 	error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
 1712: 	return (error);
 1713: }
 1714: 
 1715: /*
 1716:  * pathconf_Args(char *path, int name)
 1717:  *
 1718:  * Get configurable pathname variables.
 1719:  */
 1720: /* ARGSUSED */
 1721: int
 1722: pathconf(struct pathconf_args *uap)
 1723: {
 1724: 	struct thread *td = curthread;
 1725: 	int error;
 1726: 	struct nameidata nd;
 1727: 
 1728: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF | CNP_NOOBJ,
 1729: 	    UIO_USERSPACE, SCARG(uap, path), td);
 1730: 	if ((error = namei(&nd)) != 0)
 1731: 		return (error);
 1732: 	NDFREE(&nd, NDF_ONLY_PNBUF);
 1733: 	error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), uap->sysmsg_fds);
 1734: 	vput(nd.ni_vp);
 1735: 	return (error);
 1736: }
 1737: 
 1738: /*
 1739:  * XXX: daver
 1740:  * kern_readlink isn't properly split yet.  There is a copyin burried
 1741:  * in VOP_READLINK().
 1742:  */
 1743: int
 1744: kern_readlink(struct nameidata *nd, char *buf, int count, int *res)
 1745: {
 1746: 	struct thread *td = curthread;
 1747: 	struct proc *p = td->td_proc;
 1748: 	struct vnode *vp;
 1749: 	struct iovec aiov;
 1750: 	struct uio auio;
 1751: 	int error;
 1752: 
 1753: 	error = namei(nd);
 1754: 	if (error)
 1755: 		return (error);
 1756: 	NDFREE(nd, NDF_ONLY_PNBUF);
 1757: 	vp = nd->ni_vp;
 1758: 	if (vp->v_type != VLNK)
 1759: 		error = EINVAL;
 1760: 	else {
 1761: 		aiov.iov_base = buf;
 1762: 		aiov.iov_len = count;
 1763: 		auio.uio_iov = &aiov;
 1764: 		auio.uio_iovcnt = 1;
 1765: 		auio.uio_offset = 0;
 1766: 		auio.uio_rw = UIO_READ;
 1767: 		auio.uio_segflg = UIO_USERSPACE;
 1768: 		auio.uio_td = td;
 1769: 		auio.uio_resid = count;
 1770: 		error = VOP_READLINK(vp, &auio, p->p_ucred);
 1771: 	}
 1772: 	vput(vp);
 1773: 	*res = count - auio.uio_resid;
 1774: 	return (error);
 1775: }
 1776: 
 1777: /*
 1778:  * readlink_args(char *path, char *buf, int count)
 1779:  *
 1780:  * Return target name of a symbolic link.
 1781:  */
 1782: int
 1783: readlink(struct readlink_args *uap)
 1784: {
 1785: 	struct thread *td = curthread;
 1786: 	struct nameidata nd;
 1787: 	int error;
 1788: 
 1789: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_NOOBJ, UIO_USERSPACE,
 1790: 	    uap->path, td);
 1791: 
 1792: 	error = kern_readlink(&nd, uap->buf, uap->count,
 1793: 	    &uap->sysmsg_result);
 1794: 
 1795: 	return (error);
 1796: }
 1797: 
 1798: static int
 1799: setfflags(struct vnode *vp, int flags)
 1800: {
 1801: 	struct thread *td = curthread;
 1802: 	struct proc *p = td->td_proc;
 1803: 	int error;
 1804: 	struct vattr vattr;
 1805: 
 1806: 	/*
 1807: 	 * Prevent non-root users from setting flags on devices.  When
 1808: 	 * a device is reused, users can retain ownership of the device
 1809: 	 * if they are allowed to set flags and programs assume that
 1810: 	 * chown can't fail when done as root.
 1811: 	 */
 1812: 	if ((vp->v_type == VCHR || vp->v_type == VBLK) && 
 1813: 	    ((error = suser_cred(p->p_ucred, PRISON_ROOT)) != 0))
 1814: 		return (error);
 1815: 
 1816: 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 1817: 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 1818: 	VATTR_NULL(&vattr);
 1819: 	vattr.va_flags = flags;
 1820: 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
 1821: 	VOP_UNLOCK(vp, NULL, 0, td);
 1822: 	return (error);
 1823: }
 1824: 
 1825: /*
 1826:  * chflags(char *path, int flags)
 1827:  *
 1828:  * Change flags of a file given a path name.
 1829:  */
 1830: /* ARGSUSED */
 1831: int
 1832: chflags(struct chflags_args *uap)
 1833: {
 1834: 	struct thread *td = curthread;
 1835: 	int error;
 1836: 	struct nameidata nd;
 1837: 
 1838: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE,
 1839: 	    SCARG(uap, path), td);
 1840: 	if ((error = namei(&nd)) != 0)
 1841: 		return (error);
 1842: 	NDFREE(&nd, NDF_ONLY_PNBUF);
 1843: 	error = setfflags(nd.ni_vp, SCARG(uap, flags));
 1844: 	vrele(nd.ni_vp);
 1845: 	return error;
 1846: }
 1847: 
 1848: /*
 1849:  * fchflags_args(int fd, int flags)
 1850:  *
 1851:  * Change flags of a file given a file descriptor.
 1852:  */
 1853: /* ARGSUSED */
 1854: int
 1855: fchflags(struct fchflags_args *uap)
 1856: {
 1857: 	struct thread *td = curthread;
 1858: 	struct proc *p = td->td_proc;
 1859: 	struct file *fp;
 1860: 	int error;
 1861: 
 1862: 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 1863: 		return (error);
 1864: 	return setfflags((struct vnode *) fp->f_data, SCARG(uap, flags));
 1865: }
 1866: 
 1867: static int
 1868: setfmode(struct vnode *vp, int mode)
 1869: {
 1870: 	struct thread *td = curthread;
 1871: 	struct proc *p = td->td_proc;
 1872: 	int error;
 1873: 	struct vattr vattr;
 1874: 
 1875: 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 1876: 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 1877: 	VATTR_NULL(&vattr);
 1878: 	vattr.va_mode = mode & ALLPERMS;
 1879: 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
 1880: 	VOP_UNLOCK(vp, NULL, 0, td);
 1881: 	return error;
 1882: }
 1883: 
 1884: int
 1885: kern_chmod(struct nameidata *nd, int mode)
 1886: {
 1887: 	int error;
 1888: 
 1889: 	error = namei(nd);
 1890: 	if (error)
 1891: 		return (error);
 1892: 	NDFREE(nd, NDF_ONLY_PNBUF);
 1893: 	error = setfmode(nd->ni_vp, mode);
 1894: 	vrele(nd->ni_vp);
 1895: 	return error;
 1896: }
 1897: 
 1898: /*
 1899:  * chmod_args(char *path, int mode)
 1900:  *
 1901:  * Change mode of a file given path name.
 1902:  */
 1903: /* ARGSUSED */
 1904: int
 1905: chmod(struct chmod_args *uap)
 1906: {
 1907: 	struct thread *td = curthread;
 1908: 	struct nameidata nd;
 1909: 	int error;
 1910: 
 1911: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td);
 1912: 
 1913: 	error = kern_chmod(&nd, uap->mode);
 1914: 
 1915: 	return (error);
 1916: }
 1917: 
 1918: /*
 1919:  * lchmod_args(char *path, int mode)
 1920:  *
 1921:  * Change mode of a file given path name (don't follow links.)
 1922:  */
 1923: /* ARGSUSED */
 1924: int
 1925: lchmod(struct lchmod_args *uap)
 1926: {
 1927: 	struct thread *td = curthread;
 1928: 	int error;
 1929: 	struct nameidata nd;
 1930: 
 1931: 	NDINIT(&nd, NAMEI_LOOKUP, 0, UIO_USERSPACE, SCARG(uap, path), td);
 1932: 	if ((error = namei(&nd)) != 0)
 1933: 		return (error);
 1934: 	NDFREE(&nd, NDF_ONLY_PNBUF);
 1935: 	error = setfmode(nd.ni_vp, SCARG(uap, mode));
 1936: 	vrele(nd.ni_vp);
 1937: 	return error;
 1938: }
 1939: 
 1940: /*
 1941:  * fchmod_args(int fd, int mode)
 1942:  *
 1943:  * Change mode of a file given a file descriptor.
 1944:  */
 1945: /* ARGSUSED */
 1946: int
 1947: fchmod(struct fchmod_args *uap)
 1948: {
 1949: 	struct thread *td = curthread;
 1950: 	struct proc *p = td->td_proc;
 1951: 	struct file *fp;
 1952: 	int error;
 1953: 
 1954: 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 1955: 		return (error);
 1956: 	return setfmode((struct vnode *)fp->f_data, SCARG(uap, mode));
 1957: }
 1958: 
 1959: static int
 1960: setfown(struct vnode *vp, uid_t uid, gid_t gid)
 1961: {
 1962: 	struct thread *td = curthread;
 1963: 	struct proc *p = td->td_proc;
 1964: 	int error;
 1965: 	struct vattr vattr;
 1966: 
 1967: 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 1968: 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 1969: 	VATTR_NULL(&vattr);
 1970: 	vattr.va_uid = uid;
 1971: 	vattr.va_gid = gid;
 1972: 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
 1973: 	VOP_UNLOCK(vp, NULL, 0, td);
 1974: 	return error;
 1975: }
 1976: 
 1977: int
 1978: kern_chown(struct nameidata *nd, int uid, int gid)
 1979: {
 1980: 	int error;
 1981: 
 1982: 	error = namei(nd);
 1983: 	if (error)
 1984: 		return (error);
 1985: 	NDFREE(nd, NDF_ONLY_PNBUF);
 1986: 	error = setfown(nd->ni_vp, uid, gid);
 1987: 	vrele(nd->ni_vp);
 1988: 	return (error);
 1989: }
 1990: 
 1991: /*
 1992:  * chown(char *path, int uid, int gid)
 1993:  *
 1994:  * Set ownership given a path name.
 1995:  */
 1996: int
 1997: chown(struct chown_args *uap)
 1998: {
 1999: 	struct thread *td = curthread;
 2000: 	struct nameidata nd;
 2001: 	int error;
 2002: 
 2003: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td);
 2004: 
 2005: 	error = kern_chown(&nd, uap->uid, uap->gid);
 2006: 
 2007: 	return (error);
 2008: }
 2009: 
 2010: /*
 2011:  * lchown_args(char *path, int uid, int gid)
 2012:  *
 2013:  * Set ownership given a path name, do not cross symlinks.
 2014:  */
 2015: int
 2016: lchown(struct lchown_args *uap)
 2017: {
 2018: 	struct thread *td = curthread;
 2019: 	int error;
 2020: 	struct nameidata nd;
 2021: 
 2022: 	NDINIT(&nd, NAMEI_LOOKUP, 0, UIO_USERSPACE, uap->path, td);
 2023: 
 2024: 	error = kern_chown(&nd, uap->uid, uap->gid);
 2025: 
 2026: 	return (error);
 2027: }
 2028: 
 2029: /*
 2030:  * fchown_args(int fd, int uid, int gid)
 2031:  *
 2032:  * Set ownership given a file descriptor.
 2033:  */
 2034: /* ARGSUSED */
 2035: int
 2036: fchown(struct fchown_args *uap)
 2037: {
 2038: 	struct thread *td = curthread;
 2039: 	struct proc *p = td->td_proc;
 2040: 	struct file *fp;
 2041: 	int error;
 2042: 
 2043: 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2044: 		return (error);
 2045: 	return setfown((struct vnode *)fp->f_data,
 2046: 		SCARG(uap, uid), SCARG(uap, gid));
 2047: }
 2048: 
 2049: static int
 2050: getutimes(const struct timeval *tvp, struct timespec *tsp)
 2051: {
 2052: 	struct timeval tv[2];
 2053: 
 2054: 	if (tvp == NULL) {
 2055: 		microtime(&tv[0]);
 2056: 		TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
 2057: 		tsp[1] = tsp[0];
 2058: 	} else {
 2059: 		TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
 2060: 		TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
 2061: 	}
 2062: 	return 0;
 2063: }
 2064: 
 2065: static int
 2066: setutimes(struct vnode *vp, const struct timespec *ts, int nullflag)
 2067: {
 2068: 	struct thread *td = curthread;
 2069: 	struct proc *p = td->td_proc;
 2070: 	int error;
 2071: 	struct vattr vattr;
 2072: 
 2073: 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 2074: 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 2075: 	VATTR_NULL(&vattr);
 2076: 	vattr.va_atime = ts[0];
 2077: 	vattr.va_mtime = ts[1];
 2078: 	if (nullflag)
 2079: 		vattr.va_vaflags |= VA_UTIMES_NULL;
 2080: 	error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
 2081: 	VOP_UNLOCK(vp, NULL, 0, td);
 2082: 	return error;
 2083: }
 2084: 
 2085: int
 2086: kern_utimes(struct nameidata *nd, struct timeval *tptr)
 2087: {
 2088: 	struct timespec ts[2];
 2089: 	int error;
 2090: 
 2091: 	error = getutimes(tptr, ts);
 2092: 	if (error)
 2093: 		return (error);
 2094: 	error = namei(nd);
 2095: 	if (error)
 2096: 		return (error);
 2097: 	NDFREE(nd, NDF_ONLY_PNBUF);
 2098: 	error = setutimes(nd->ni_vp, ts, tptr == NULL);
 2099: 	vrele(nd->ni_vp);
 2100: 	return (error);
 2101: }
 2102: 
 2103: /*
 2104:  * utimes_args(char *path, struct timeval *tptr)
 2105:  *
 2106:  * Set the access and modification times of a file.
 2107:  */
 2108: int
 2109: utimes(struct utimes_args *uap)
 2110: {
 2111: 	struct thread *td = curthread;
 2112: 	struct timeval tv[2];
 2113: 	struct nameidata nd;
 2114: 	int error;
 2115: 
 2116: 	if (uap->tptr) {
 2117:  		error = copyin(uap->tptr, tv, sizeof(tv));
 2118: 		if (error)
 2119: 			return (error);
 2120: 	}
 2121: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td);
 2122: 
 2123: 	error = kern_utimes(&nd, uap->tptr ? tv : NULL);
 2124: 
 2125: 	return (error);
 2126: }
 2127: 
 2128: /*
 2129:  * lutimes_args(char *path, struct timeval *tptr)
 2130:  *
 2131:  * Set the access and modification times of a file.
 2132:  */
 2133: int
 2134: lutimes(struct lutimes_args *uap)
 2135: {
 2136: 	struct thread *td = curthread;
 2137: 	struct timeval tv[2];
 2138: 	struct nameidata nd;
 2139: 	int error;
 2140: 
 2141: 	if (uap->tptr) {
 2142: 		error = copyin(uap->tptr, tv, sizeof(tv));
 2143: 		if (error)
 2144: 			return (error);
 2145: 	}
 2146: 	NDINIT(&nd, NAMEI_LOOKUP, 0, UIO_USERSPACE, uap->path, td);
 2147: 
 2148: 	error = kern_utimes(&nd, uap->tptr ? tv : NULL);
 2149: 
 2150: 	return (error);
 2151: }
 2152: 
 2153: int
 2154: kern_futimes(int fd, struct timeval *tptr)
 2155: {
 2156: 	struct thread *td = curthread;
 2157: 	struct proc *p = td->td_proc;
 2158: 	struct timespec ts[2];
 2159: 	struct file *fp;
 2160: 	int error;
 2161: 
 2162: 	error = getutimes(tptr, ts);
 2163: 	if (error)
 2164: 		return (error);
 2165: 	error = getvnode(p->p_fd, fd, &fp);
 2166: 	if (error)
 2167: 		return (error);
 2168: 	error =  setutimes((struct vnode *)fp->f_data, ts, tptr == NULL);
 2169: 	return (error);
 2170: }
 2171: 
 2172: /*
 2173:  * futimes_args(int fd, struct timeval *tptr)
 2174:  *
 2175:  * Set the access and modification times of a file.
 2176:  */
 2177: int
 2178: futimes(struct futimes_args *uap)
 2179: {
 2180: 	struct timeval tv[2];
 2181: 	int error;
 2182: 
 2183: 	if (uap->tptr) {
 2184: 		error = copyin(uap->tptr, tv, sizeof(tv));
 2185: 		if (error)
 2186: 			return (error);
 2187: 	}
 2188: 
 2189: 	error = kern_futimes(uap->fd, uap->tptr ? tv : NULL);
 2190: 
 2191: 	return (error);
 2192: }
 2193: 
 2194: int
 2195: kern_truncate(struct nameidata* nd, off_t length)
 2196: {
 2197: 	struct thread *td = curthread;
 2198: 	struct proc *p = td->td_proc;
 2199: 	struct vnode *vp;
 2200: 	struct vattr vattr;
 2201: 	int error;
 2202: 
 2203: 	if (length < 0)
 2204: 		return(EINVAL);
 2205: 	if ((error = namei(nd)) != 0)
 2206: 		return (error);
 2207: 	vp = nd->ni_vp;
 2208: 	NDFREE(nd, NDF_ONLY_PNBUF);
 2209: 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 2210: 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 2211: 	if (vp->v_type == VDIR)
 2212: 		error = EISDIR;
 2213: 	else if ((error = vn_writechk(vp)) == 0 &&
 2214: 	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, td)) == 0) {
 2215: 		VATTR_NULL(&vattr);
 2216: 		vattr.va_size = length;
 2217: 		error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
 2218: 	}
 2219: 	vput(vp);
 2220: 	return (error);
 2221: }
 2222: 
 2223: /*
 2224:  * truncate(char *path, int pad, off_t length)
 2225:  *
 2226:  * Truncate a file given its path name.
 2227:  */
 2228: int
 2229: truncate(struct truncate_args *uap)
 2230: {
 2231: 	struct thread *td = curthread;
 2232: 	struct nameidata nd;
 2233: 	int error;
 2234: 
 2235: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td);
 2236: 
 2237: 	error = kern_truncate(&nd, uap->length);
 2238: 
 2239: 	return error;
 2240: }
 2241: 
 2242: int
 2243: kern_ftruncate(int fd, off_t length)
 2244: {
 2245: 	struct thread *td = curthread;
 2246: 	struct proc *p = td->td_proc;
 2247: 	struct vattr vattr;
 2248: 	struct vnode *vp;
 2249: 	struct file *fp;
 2250: 	int error;
 2251: 
 2252: 	if (length < 0)
 2253: 		return(EINVAL);
 2254: 	if ((error = getvnode(p->p_fd, fd, &fp)) != 0)
 2255: 		return (error);
 2256: 	if ((fp->f_flag & FWRITE) == 0)
 2257: 		return (EINVAL);
 2258: 	vp = (struct vnode *)fp->f_data;
 2259: 	VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 2260: 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 2261: 	if (vp->v_type == VDIR)
 2262: 		error = EISDIR;
 2263: 	else if ((error = vn_writechk(vp)) == 0) {
 2264: 		VATTR_NULL(&vattr);
 2265: 		vattr.va_size = length;
 2266: 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
 2267: 	}
 2268: 	VOP_UNLOCK(vp, NULL, 0, td);
 2269: 	return (error);
 2270: }
 2271: 
 2272: /*
 2273:  * ftruncate_args(int fd, int pad, off_t length)
 2274:  *
 2275:  * Truncate a file given a file descriptor.
 2276:  */
 2277: int
 2278: ftruncate(struct ftruncate_args *uap)
 2279: {
 2280: 	int error;
 2281: 
 2282: 	error = kern_ftruncate(uap->fd, uap->length);
 2283: 
 2284: 	return (error);
 2285: }
 2286: 
 2287: /*
 2288:  * fsync(int fd)
 2289:  *
 2290:  * Sync an open file.
 2291:  */
 2292: /* ARGSUSED */
 2293: int
 2294: fsync(struct fsync_args *uap)
 2295: {
 2296: 	struct thread *td = curthread;
 2297: 	struct proc *p = td->td_proc;
 2298: 	struct vnode *vp;
 2299: 	struct file *fp;
 2300: 	vm_object_t obj;
 2301: 	int error;
 2302: 
 2303: 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 2304: 		return (error);
 2305: 	vp = (struct vnode *)fp->f_data;
 2306: 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 2307: 	if (VOP_GETVOBJECT(vp, &obj) == 0)
 2308: 		vm_object_page_clean(obj, 0, 0, 0);
 2309: 	if ((error = VOP_FSYNC(vp, MNT_WAIT, td)) == 0 &&
 2310: 	    vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) &&
 2311: 	    bioops.io_fsync)
 2312: 		error = (*bioops.io_fsync)(vp);
 2313: 	VOP_UNLOCK(vp, NULL, 0, td);
 2314: 	return (error);
 2315: }
 2316: 
 2317: int
 2318: kern_rename(struct nameidata *fromnd, struct nameidata *tond)
 2319: {
 2320: 	struct thread *td = curthread;
 2321: 	struct proc *p = td->td_proc;
 2322: 	struct vnode *tvp, *fvp, *tdvp;
 2323: 	int error;
 2324: 
 2325: 	bwillwrite();
 2326: 	error = namei(fromnd);
 2327: 	if (error)
 2328: 		return (error);
 2329: 	fvp = fromnd->ni_vp;
 2330: 	if (fromnd->ni_vp->v_type == VDIR)
 2331: 		tond->ni_cnd.cn_flags |= CNP_WILLBEDIR;
 2332: 	error = namei(tond);
 2333: 	if (error) {
 2334: 		/* Translate error code for rename("dir1", "dir2/."). */
 2335: 		if (error == EISDIR && fvp->v_type == VDIR)
 2336: 			error = EINVAL;
 2337: 		NDFREE(fromnd, NDF_ONLY_PNBUF);
 2338: 		vrele(fromnd->ni_dvp);
 2339: 		vrele(fvp);
 2340: 		goto out1;
 2341: 	}
 2342: 	tdvp = tond->ni_dvp;
 2343: 	tvp = tond->ni_vp;
 2344: 	if (tvp != NULL) {
 2345: 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
 2346: 			error = ENOTDIR;
 2347: 			goto out;
 2348: 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
 2349: 			error = EISDIR;
 2350: 			goto out;
 2351: 		}
 2352: 	}
 2353: 	if (fvp == tdvp)
 2354: 		error = EINVAL;
 2355: 	/*
 2356: 	 * If the source is the same as the destination (that is, if they
 2357: 	 * are links to the same vnode), then there is nothing to do.
 2358: 	 */
 2359: 	if (fvp == tvp)
 2360: 		error = -1;
 2361: out:
 2362: 	if (!error) {
 2363: 		VOP_LEASE(tdvp, td, p->p_ucred, LEASE_WRITE);
 2364: 		if (fromnd->ni_dvp != tdvp) {
 2365: 			VOP_LEASE(fromnd->ni_dvp, td, p->p_ucred, LEASE_WRITE);
 2366: 		}
 2367: 		if (tvp) {
 2368: 			VOP_LEASE(tvp, td, p->p_ucred, LEASE_WRITE);
 2369: 		}
 2370: 		error = VOP_RENAME(fromnd->ni_dvp, NCPNULL, fromnd->ni_vp,
 2371: 		    &fromnd->ni_cnd, tond->ni_dvp, NCPNULL, tond->ni_vp,
 2372: 		    &tond->ni_cnd);
 2373: 		NDFREE(fromnd, NDF_ONLY_PNBUF);
 2374: 		NDFREE(tond, NDF_ONLY_PNBUF);
 2375: 	} else {
 2376: 		NDFREE(fromnd, NDF_ONLY_PNBUF);
 2377: 		NDFREE(tond, NDF_ONLY_PNBUF);
 2378: 		if (tdvp == tvp)
 2379: 			vrele(tdvp);
 2380: 		else
 2381: 			vput(tdvp);
 2382: 		if (tvp)
 2383: 			vput(tvp);
 2384: 		vrele(fromnd->ni_dvp);
 2385: 		vrele(fvp);
 2386: 	}
 2387: 	vrele(tond->ni_startdir);
 2388: 	ASSERT_VOP_UNLOCKED(fromnd->ni_dvp, "rename");
 2389: 	ASSERT_VOP_UNLOCKED(fromnd->ni_vp, "rename");
 2390: 	ASSERT_VOP_UNLOCKED(tond->ni_dvp, "rename");
 2391: 	ASSERT_VOP_UNLOCKED(tond->ni_vp, "rename");
 2392: out1:
 2393: 	if (fromnd->ni_startdir)
 2394: 		vrele(fromnd->ni_startdir);
 2395: 	if (error == -1)
 2396: 		return (0);
 2397: 	return (error);
 2398: }
 2399: 
 2400: /*
 2401:  * rename_args(char *from, char *to)
 2402:  *
 2403:  * Rename files.  Source and destination must either both be directories,
 2404:  * or both not be directories.  If target is a directory, it must be empty.
 2405:  */
 2406: int
 2407: rename(struct rename_args *uap)
 2408: {
 2409: 	struct thread *td = curthread;
 2410: 	struct nameidata fromnd, tond;
 2411: 	int error;
 2412: 
 2413: 	NDINIT(&fromnd, NAMEI_DELETE, CNP_WANTPARENT | CNP_SAVESTART,
 2414: 		UIO_USERSPACE, uap->from, td);
 2415: 	NDINIT(&tond, NAMEI_RENAME, 
 2416: 	    CNP_LOCKPARENT | CNP_LOCKLEAF | CNP_NOCACHE |
 2417: 	     CNP_SAVESTART | CNP_NOOBJ,
 2418: 	    UIO_USERSPACE, uap->to, td);
 2419: 
 2420: 	error = kern_rename(&fromnd, &tond);
 2421: 
 2422: 	return (error);
 2423: }
 2424: 
 2425: int
 2426: kern_mkdir(struct nameidata *nd, int mode)
 2427: {
 2428: 	struct thread *td = curthread;
 2429: 	struct proc *p = td->td_proc;
 2430: 	struct vnode *vp;
 2431: 	struct vattr vattr;
 2432: 	int error;
 2433: 
 2434: 	bwillwrite();
 2435: 	nd->ni_cnd.cn_flags |= CNP_WILLBEDIR;
 2436: 	error = namei(nd);
 2437: 	if (error)
 2438: 		return (error);
 2439: 	vp = nd->ni_vp;
 2440: 	if (vp) {
 2441: 		NDFREE(nd, NDF_ONLY_PNBUF);
 2442: 		if (nd->ni_dvp == vp)
 2443: 			vrele(nd->ni_dvp);
 2444: 		else
 2445: 			vput(nd->ni_dvp);
 2446: 		vrele(vp);
 2447: 		return (EEXIST);
 2448: 	}
 2449: 	VATTR_NULL(&vattr);
 2450: 	vattr.va_type = VDIR;
 2451: 	vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
 2452: 	VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE);
 2453: 	error = VOP_MKDIR(nd->ni_dvp, NCPNULL, &nd->ni_vp, &nd->ni_cnd,
 2454: 	    &vattr);
 2455: 	NDFREE(nd, NDF_ONLY_PNBUF);
 2456: 	vput(nd->ni_dvp);
 2457: 	if (error == 0)
 2458: 		vput(nd->ni_vp);
 2459: 	ASSERT_VOP_UNLOCKED(nd->ni_dvp, "mkdir");
 2460: 	ASSERT_VOP_UNLOCKED(nd->ni_vp, "mkdir");
 2461: 	return (error);
 2462: }
 2463: 
 2464: /*
 2465:  * mkdir_args(char *path, int mode)
 2466:  *
 2467:  * Make a directory file.
 2468:  */
 2469: /* ARGSUSED */
 2470: int
 2471: mkdir(struct mkdir_args *uap)
 2472: {
 2473: 	struct thread *td = curthread;
 2474: 	struct nameidata nd;
 2475: 	int error;
 2476: 
 2477: 	NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT, UIO_USERSPACE, uap->path,
 2478: 	    td);
 2479: 
 2480: 	error = kern_mkdir(&nd, uap->mode);
 2481: 
 2482: 	return (error);
 2483: }
 2484: 
 2485: int
 2486: kern_rmdir(struct nameidata *nd)
 2487: {
 2488: 	struct thread *td = curthread;
 2489: 	struct proc *p = td->td_proc;
 2490: 	struct vnode *vp;
 2491: 	int error;
 2492: 
 2493: 	bwillwrite();
 2494: 	error = namei(nd);
 2495: 	if (error)
 2496: 		return (error);
 2497: 	vp = nd->ni_vp;
 2498: 	if (vp->v_type != VDIR) {
 2499: 		error = ENOTDIR;
 2500: 		goto out;
 2501: 	}
 2502: 	/*
 2503: 	 * No rmdir "." please.
 2504: 	 */
 2505: 	if (nd->ni_dvp == vp) {
 2506: 		error = EINVAL;
 2507: 		goto out;
 2508: 	}
 2509: 	/*
 2510: 	 * The root of a mounted filesystem cannot be deleted.
 2511: 	 */
 2512: 	if (vp->v_flag & VROOT)
 2513: 		error = EBUSY;
 2514: 	else {
 2515: 		VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE);
 2516: 		VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 2517: 		error = VOP_RMDIR(nd->ni_dvp, NCPNULL, nd->ni_vp,
 2518: 		    &nd->ni_cnd);
 2519: 	}
 2520: out:
 2521: 	NDFREE(nd, NDF_ONLY_PNBUF);
 2522: 	if (nd->ni_dvp == vp)
 2523: 		vrele(nd->ni_dvp);
 2524: 	else
 2525: 		vput(nd->ni_dvp);
 2526: 	if (vp != NULLVP)
 2527: 		vput(vp);
 2528: 	ASSERT_VOP_UNLOCKED(nd->ni_dvp, "rmdir");
 2529: 	ASSERT_VOP_UNLOCKED(nd->ni_vp, "rmdir");
 2530: 	return (error);
 2531: }
 2532: 
 2533: /*
 2534:  * rmdir_args(char *path)
 2535:  *
 2536:  * Remove a directory file.
 2537:  */
 2538: /* ARGSUSED */
 2539: int
 2540: rmdir(struct rmdir_args *uap)
 2541: {
 2542: 	struct thread *td = curthread;
 2543: 	struct nameidata nd;
 2544: 	int error;
 2545: 
 2546: 	NDINIT(&nd, NAMEI_DELETE, CNP_LOCKPARENT | CNP_LOCKLEAF,
 2547: 	    UIO_USERSPACE, uap->path, td);
 2548: 
 2549: 	error = kern_rmdir(&nd);
 2550: 
 2551: 	return (error);
 2552: }
 2553: 
 2554: int
 2555: kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res)
 2556: {
 2557: 	struct thread *td = curthread;
 2558: 	struct proc *p = td->td_proc;
 2559: 	struct vnode *vp;
 2560: 	struct file *fp;
 2561: 	struct uio auio;
 2562: 	struct iovec aiov;
 2563: 	long loff;
 2564: 	int error, eofflag;
 2565: 
 2566: 	if ((error = getvnode(p->p_fd, fd, &fp)) != 0)
 2567: 		return (error);
 2568: 	if ((fp->f_flag & FREAD) == 0)
 2569: 		return (EBADF);
 2570: 	vp = (struct vnode *)fp->f_data;
 2571: unionread:
 2572: 	if (vp->v_type != VDIR)
 2573: 		return (EINVAL);
 2574: 	aiov.iov_base = buf;
 2575: 	aiov.iov_len = count;
 2576: 	auio.uio_iov = &aiov;
 2577: 	auio.uio_iovcnt = 1;
 2578: 	auio.uio_rw = UIO_READ;
 2579: 	auio.uio_segflg = UIO_USERSPACE;
 2580: 	auio.uio_td = td;
 2581: 	auio.uio_resid = count;
 2582: 	/* vn_lock(vp, NULL, LK_SHARED | LK_RETRY, td); */
 2583: 	vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 2584: 	loff = auio.uio_offset = fp->f_offset;
 2585: 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
 2586: 	fp->f_offset = auio.uio_offset;
 2587: 	VOP_UNLOCK(vp, NULL, 0, td);
 2588: 	if (error)
 2589: 		return (error);
 2590: 	if (count == auio.uio_resid) {
 2591: 		if (union_dircheckp) {
 2592: 			error = union_dircheckp(td, &vp, fp);
 2593: 			if (error == -1)
 2594: 				goto unionread;
 2595: 			if (error)
 2596: 				return (error);
 2597: 		}
 2598: 		if ((vp->v_flag & VROOT) &&
 2599: 		    (vp->v_mount->mnt_flag & MNT_UNION)) {
 2600: 			struct vnode *tvp = vp;
 2601: 			vp = vp->v_mount->mnt_vnodecovered;
 2602: 			VREF(vp);
 2603: 			fp->f_data = (caddr_t) vp;
 2604: 			fp->f_offset = 0;
 2605: 			vrele(tvp);
 2606: 			goto unionread;
 2607: 		}
 2608: 	}
 2609: 	if (basep) {
 2610: 		*basep = loff;
 2611: 	}
 2612: 	*res = count - auio.uio_resid;
 2613: 	return (error);
 2614: }
 2615: 
 2616: /*
 2617:  * getdirentries_args(int fd, char *buf, u_int conut, long *basep)
 2618:  *
 2619:  * Read a block of directory entries in a file system independent format.
 2620:  */
 2621: int
 2622: getdirentries(struct getdirentries_args *uap)
 2623: {
 2624: 	long base;
 2625: 	int error;
 2626: 
 2627: 	error = kern_getdirentries(uap->fd, uap->buf, uap->count, &base,
 2628: 	    &uap->sysmsg_result);
 2629: 
 2630: 	if (error == 0)
 2631: 		error = copyout(&base, uap->basep, sizeof(*uap->basep));
 2632: 	return (error);
 2633: }
 2634: 
 2635: /*
 2636:  * getdents_args(int fd, char *buf, size_t count)
 2637:  */
 2638: int
 2639: getdents(struct getdents_args *uap)
 2640: {
 2641: 	int error;
 2642: 
 2643: 	error = kern_getdirentries(uap->fd, uap->buf, uap->count, NULL,
 2644: 	    &uap->sysmsg_result);
 2645: 
 2646: 	return (error);
 2647: }
 2648: 
 2649: /*
 2650:  * umask(int newmask)
 2651:  *
 2652:  * Set the mode mask for creation of filesystem nodes.
 2653:  *
 2654:  * MP SAFE
 2655:  */
 2656: int
 2657: umask(struct umask_args *uap)
 2658: {
 2659: 	struct thread *td = curthread;
 2660: 	struct proc *p = td->td_proc;
 2661: 	struct filedesc *fdp;
 2662: 
 2663: 	fdp = p->p_fd;
 2664: 	uap->sysmsg_result = fdp->fd_cmask;
 2665: 	fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
 2666: 	return (0);
 2667: }
 2668: 
 2669: /*
 2670:  * revoke(char *path)
 2671:  *
 2672:  * Void all references to file by ripping underlying filesystem
 2673:  * away from vnode.
 2674:  */
 2675: /* ARGSUSED */
 2676: int
 2677: revoke(struct revoke_args *uap)
 2678: {
 2679: 	struct thread *td = curthread;
 2680: 	struct proc *p = td->td_proc;
 2681: 	struct vnode *vp;
 2682: 	struct vattr vattr;
 2683: 	int error;
 2684: 	struct nameidata nd;
 2685: 
 2686: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
 2687: 	if ((error = namei(&nd)) != 0)
 2688: 		return (error);
 2689: 	vp = nd.ni_vp;
 2690: 	NDFREE(&nd, NDF_ONLY_PNBUF);
 2691: 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
 2692: 		error = EINVAL;
 2693: 		goto out;
 2694: 	}
 2695: 	if ((error = VOP_GETATTR(vp, &vattr, td)) != 0)
 2696: 		goto out;
 2697: 	if (p->p_ucred->cr_uid != vattr.va_uid &&
 2698: 	    (error = suser_cred(p->p_ucred, PRISON_ROOT)))
 2699: 		goto out;
 2700: 	if (vcount(vp) > 1)
 2701: 		VOP_REVOKE(vp, REVOKEALL);
 2702: out:
 2703: 	vrele(vp);
 2704: 	return (error);
 2705: }
 2706: 
 2707: /*
 2708:  * Convert a user file descriptor to a kernel file entry.
 2709:  */
 2710: int
 2711: getvnode(struct filedesc *fdp, int fd, struct file **fpp)
 2712: {
 2713: 	struct file *fp;
 2714: 
 2715: 	if ((u_int)fd >= fdp->fd_nfiles ||
 2716: 	    (fp = fdp->fd_ofiles[fd]) == NULL)
 2717: 		return (EBADF);
 2718: 	if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO)
 2719: 		return (EINVAL);
 2720: 	*fpp = fp;
 2721: 	return (0);
 2722: }
 2723: /*
 2724:  * getfh_args(char *fname, fhandle_t *fhp)
 2725:  *
 2726:  * Get (NFS) file handle
 2727:  */
 2728: int
 2729: getfh(struct getfh_args *uap)
 2730: {
 2731: 	struct thread *td = curthread;
 2732: 	struct nameidata nd;
 2733: 	fhandle_t fh;
 2734: 	struct vnode *vp;
 2735: 	int error;
 2736: 
 2737: 	/*
 2738: 	 * Must be super user
 2739: 	 */
 2740: 	error = suser(td);
 2741: 	if (error)
 2742: 		return (error);
 2743: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_USERSPACE, uap->fname, td);
 2744: 	error = namei(&nd);
 2745: 	if (error)
 2746: 		return (error);
 2747: 	NDFREE(&nd, NDF_ONLY_PNBUF);
 2748: 	vp = nd.ni_vp;
 2749: 	bzero(&fh, sizeof(fh));
 2750: 	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
 2751: 	error = VFS_VPTOFH(vp, &fh.fh_fid);
 2752: 	vput(vp);
 2753: 	if (error)
 2754: 		return (error);
 2755: 	error = copyout(&fh, uap->fhp, sizeof (fh));
 2756: 	return (error);
 2757: }
 2758: 
 2759: /*
 2760:  * fhopen_args(const struct fhandle *u_fhp, int flags)
 2761:  *
 2762:  * syscall for the rpc.lockd to use to translate a NFS file handle into
 2763:  * an open descriptor.
 2764:  *
 2765:  * warning: do not remove the suser() call or this becomes one giant
 2766:  * security hole.
 2767:  */
 2768: int
 2769: fhopen(struct fhopen_args *uap)
 2770: {
 2771: 	struct thread *td = curthread;
 2772: 	struct proc *p = td->td_proc;
 2773: 	struct mount *mp;
 2774: 	struct vnode *vp;
 2775: 	struct fhandle fhp;
 2776: 	struct vattr vat;
 2777: 	struct vattr *vap = &vat;
 2778: 	struct flock lf;
 2779: 	struct file *fp;
 2780: 	struct filedesc *fdp = p->p_fd;
 2781: 	int fmode, mode, error, type;
 2782: 	struct file *nfp; 
 2783: 	int indx;
 2784: 
 2785: 	/*
 2786: 	 * Must be super user
 2787: 	 */
 2788: 	error = suser(td);
 2789: 	if (error)
 2790: 		return (error);
 2791: 
 2792: 	fmode = FFLAGS(SCARG(uap, flags));
 2793: 	/* why not allow a non-read/write open for our lockd? */
 2794: 	if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
 2795: 		return (EINVAL);
 2796: 	error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp));
 2797: 	if (error)
 2798: 		return(error);
 2799: 	/* find the mount point */
 2800: 	mp = vfs_getvfs(&fhp.fh_fsid);
 2801: 	if (mp == NULL)
 2802: 		return (ESTALE);
 2803: 	/* now give me my vnode, it gets returned to me locked */
 2804: 	error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
 2805: 	if (error)
 2806: 		return (error);
 2807:  	/*
 2808: 	 * from now on we have to make sure not
 2809: 	 * to forget about the vnode
 2810: 	 * any error that causes an abort must vput(vp) 
 2811: 	 * just set error = err and 'goto bad;'.
 2812: 	 */
 2813: 
 2814: 	/* 
 2815: 	 * from vn_open 
 2816: 	 */
 2817: 	if (vp->v_type == VLNK) {
 2818: 		error = EMLINK;
 2819: 		goto bad;
 2820: 	}
 2821: 	if (vp->v_type == VSOCK) {
 2822: 		error = EOPNOTSUPP;
 2823: 		goto bad;
 2824: 	}
 2825: 	mode = 0;
 2826: 	if (fmode & (FWRITE | O_TRUNC)) {
 2827: 		if (vp->v_type == VDIR) {
 2828: 			error = EISDIR;
 2829: 			goto bad;
 2830: 		}
 2831: 		error = vn_writechk(vp);
 2832: 		if (error)
 2833: 			goto bad;
 2834: 		mode |= VWRITE;
 2835: 	}
 2836: 	if (fmode & FREAD)
 2837: 		mode |= VREAD;
 2838: 	if (mode) {
 2839: 		error = VOP_ACCESS(vp, mode, p->p_ucred, td);
 2840: 		if (error)
 2841: 			goto bad;
 2842: 	}
 2843: 	if (fmode & O_TRUNC) {
 2844: 		VOP_UNLOCK(vp, NULL, 0, td);			/* XXX */
 2845: 		VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
 2846: 		vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);	/* XXX */
 2847: 		VATTR_NULL(vap);
 2848: 		vap->va_size = 0;
 2849: 		error = VOP_SETATTR(vp, vap, p->p_ucred, td);
 2850: 		if (error)
 2851: 			goto bad;
 2852: 	}
 2853: 	error = VOP_OPEN(vp, fmode, p->p_ucred, td);
 2854: 	if (error)
 2855: 		goto bad;
 2856: 	/*
 2857: 	 * Make sure that a VM object is created for VMIO support.
 2858: 	 */
 2859: 	if (vn_canvmio(vp) == TRUE) {
 2860: 		if ((error = vfs_object_create(vp, td)) != 0)
 2861: 			goto bad;
 2862: 	}
 2863: 	if (fmode & FWRITE)
 2864: 		vp->v_writecount++;
 2865: 
 2866: 	/*
 2867: 	 * end of vn_open code 
 2868: 	 */
 2869: 
 2870: 	if ((error = falloc(p, &nfp, &indx)) != 0) {
 2871: 		if (fmode & FWRITE)
 2872: 			vp->v_writecount--;
 2873: 		goto bad;
 2874: 	}
 2875: 	fp = nfp;	
 2876: 
 2877: 	/*
 2878: 	 * hold an extra reference to avoid having fp ripped out
 2879: 	 * from under us while we block in the lock op.
 2880: 	 */
 2881: 	fhold(fp);
 2882: 	nfp->f_data = (caddr_t)vp;
 2883: 	nfp->f_flag = fmode & FMASK;
 2884: 	nfp->f_ops = &vnops;
 2885: 	nfp->f_type = DTYPE_VNODE;
 2886: 	if (fmode & (O_EXLOCK | O_SHLOCK)) {
 2887: 		lf.l_whence = SEEK_SET;
 2888: 		lf.l_start = 0;
 2889: 		lf.l_len = 0;
 2890: 		if (fmode & O_EXLOCK)
 2891: 			lf.l_type = F_WRLCK;
 2892: 		else
 2893: 			lf.l_type = F_RDLCK;
 2894: 		type = F_FLOCK;
 2895: 		if ((fmode & FNONBLOCK) == 0)
 2896: 			type |= F_WAIT;
 2897: 		VOP_UNLOCK(vp, NULL, 0, td);
 2898: 		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
 2899: 			/*
 2900: 			 * lock request failed.  Normally close the descriptor
 2901: 			 * but handle the case where someone might have dup()d
 2902: 			 * or close()d it when we weren't looking.
 2903: 			 */
 2904: 			if (fdp->fd_ofiles[indx] == fp) {
 2905: 				fdp->fd_ofiles[indx] = NULL;
 2906: 				fdrop(fp, td);
 2907: 			}
 2908: 
 2909: 			/*
 2910: 			 * release our private reference.
 2911: 			 */
 2912: 			fdrop(fp, td);
 2913: 			return (error);
 2914: 		}
 2915: 		vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 2916: 		fp->f_flag |= FHASLOCK;
 2917: 	}
 2918: 	if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
 2919: 		vfs_object_create(vp, td);
 2920: 
 2921: 	VOP_UNLOCK(vp, NULL, 0, td);
 2922: 	fdrop(fp, td);
 2923: 	uap->sysmsg_result = indx;
 2924: 	return (0);
 2925: 
 2926: bad:
 2927: 	vput(vp);
 2928: 	return (error);
 2929: }
 2930: 
 2931: /*
 2932:  * fhstat_args(struct fhandle *u_fhp, struct stat *sb)
 2933:  */
 2934: int
 2935: fhstat(struct fhstat_args *uap)
 2936: {
 2937: 	struct thread *td = curthread;
 2938: 	struct stat sb;
 2939: 	fhandle_t fh;
 2940: 	struct mount *mp;
 2941: 	struct vnode *vp;
 2942: 	int error;
 2943: 
 2944: 	/*
 2945: 	 * Must be super user
 2946: 	 */
 2947: 	error = suser(td);
 2948: 	if (error)
 2949: 		return (error);
 2950: 	
 2951: 	error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t));
 2952: 	if (error)
 2953: 		return (error);
 2954: 
 2955: 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
 2956: 		return (ESTALE);
 2957: 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
 2958: 		return (error);
 2959: 	error = vn_stat(vp, &sb, td);
 2960: 	vput(vp);
 2961: 	if (error)
 2962: 		return (error);
 2963: 	error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
 2964: 	return (error);
 2965: }
 2966: 
 2967: /*
 2968:  * fhstatfs_args(struct fhandle *u_fhp, struct statfs *buf)
 2969:  */
 2970: int
 2971: fhstatfs(struct fhstatfs_args *uap)
 2972: {
 2973: 	struct thread *td = curthread;
 2974: 	struct statfs *sp;
 2975: 	struct mount *mp;
 2976: 	struct vnode *vp;
 2977: 	struct statfs sb;
 2978: 	fhandle_t fh;
 2979: 	int error;
 2980: 
 2981: 	/*
 2982: 	 * Must be super user
 2983: 	 */
 2984: 	if ((error = suser(td)))
 2985: 		return (error);
 2986: 
 2987: 	if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0)
 2988: 		return (error);
 2989: 
 2990: 	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
 2991: 		return (ESTALE);
 2992: 	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
 2993: 		return (error);
 2994: 	mp = vp->v_mount;
 2995: 	sp = &mp->mnt_stat;
 2996: 	vput(vp);
 2997: 	if ((error = VFS_STATFS(mp, sp, td)) != 0)
 2998: 		return (error);
 2999: 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
 3000: 	if (suser(td)) {
 3001: 		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
 3002: 		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
 3003: 		sp = &sb;
 3004: 	}
 3005: 	return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
 3006: }
 3007: 
 3008: /*
 3009:  * Syscall to push extended attribute configuration information into the
 3010:  * VFS.  Accepts a path, which it converts to a mountpoint, as well as
 3011:  * a command (int cmd), and attribute name and misc data.  For now, the
 3012:  * attribute name is left in userspace for consumption by the VFS_op.
 3013:  * It will probably be changed to be copied into sysspace by the
 3014:  * syscall in the future, once issues with various consumers of the
 3015:  * attribute code have raised their hands.
 3016:  *
 3017:  * Currently this is used only by UFS Extended Attributes.
 3018:  */
 3019: int
 3020: extattrctl(struct extattrctl_args *uap)
 3021: {
 3022: 	struct thread *td = curthread;
 3023: 	struct nameidata nd;
 3024: 	struct mount *mp;
 3025: 	int error;
 3026: 
 3027: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, SCARG(uap, path), td);
 3028: 	if ((error = namei(&nd)) != 0)
 3029: 		return (error);
 3030: 	mp = nd.ni_vp->v_mount;
 3031: 	NDFREE(&nd, 0);
 3032: 	return (VFS_EXTATTRCTL(mp, SCARG(uap, cmd), SCARG(uap, attrname),
 3033: 	    SCARG(uap, arg), td));
 3034: }
 3035: 
 3036: /*
 3037:  * Syscall to set a named extended attribute on a file or directory.
 3038:  * Accepts attribute name, and a uio structure pointing to the data to set.
 3039:  * The uio is consumed in the style of writev().  The real work happens
 3040:  * in VOP_SETEXTATTR().
 3041:  */
 3042: int
 3043: extattr_set_file(struct extattr_set_file_args *uap)
 3044: {
 3045: 	struct thread *td = curthread;
 3046: 	struct proc *p = td->td_proc;
 3047: 	struct nameidata nd;
 3048: 	struct uio auio;
 3049: 	struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV];
 3050: 	char attrname[EXTATTR_MAXNAMELEN];
 3051: 	u_int iovlen, cnt;
 3052: 	int error, i;
 3053: 
 3054: 	error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
 3055: 	if (error)
 3056: 		return (error);
 3057: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_USERSPACE,
 3058: 	    SCARG(uap, path), td);
 3059: 	if ((error = namei(&nd)) != 0)
 3060: 		return(error);
 3061: 	iovlen = uap->iovcnt * sizeof(struct iovec);
 3062: 	if (uap->iovcnt > UIO_SMALLIOV) {
 3063: 		if (uap->iovcnt > UIO_MAXIOV) {
 3064: 			error = EINVAL;
 3065: 			goto done;
 3066: 		}
 3067: 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
 3068: 		needfree = iov;
 3069: 	} else
 3070: 		iov = aiov;
 3071: 	auio.uio_iov = iov;
 3072: 	auio.uio_iovcnt = uap->iovcnt;
 3073: 	auio.uio_rw = UIO_WRITE;
 3074: 	auio.uio_segflg = UIO_USERSPACE;
 3075: 	auio.uio_td = td;
 3076: 	auio.uio_offset = 0;
 3077: 	if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
 3078: 		goto done;
 3079: 	auio.uio_resid = 0;
 3080: 	for (i = 0; i < uap->iovcnt; i++) {
 3081: 		if (iov->iov_len > INT_MAX - auio.uio_resid) {
 3082: 			error = EINVAL;
 3083: 			goto done;
 3084: 		}
 3085: 		auio.uio_resid += iov->iov_len;
 3086: 		iov++;
 3087: 	}
 3088: 	cnt = auio.uio_resid;
 3089: 	error = VOP_SETEXTATTR(nd.ni_vp, attrname, &auio, p->p_ucred, td);
 3090: 	cnt -= auio.uio_resid;
 3091: 	uap->sysmsg_result = cnt;
 3092: done:
 3093: 	if (needfree)
 3094: 		FREE(needfree, M_IOV);
 3095: 	NDFREE(&nd, 0);
 3096: 	return (error);
 3097: }
 3098: 
 3099: /*
 3100:  * Syscall to get a named extended attribute on a file or directory.
 3101:  * Accepts attribute name, and a uio structure pointing to a buffer for the
 3102:  * data.  The uio is consumed in the style of readv().  The real work
 3103:  * happens in VOP_GETEXTATTR();
 3104:  */
 3105: int
 3106: extattr_get_file(struct extattr_get_file_args *uap)
 3107: {
 3108: 	struct thread *td = curthread;
 3109: 	struct proc *p = td->td_proc;
 3110: 	struct nameidata nd;
 3111: 	struct uio auio;
 3112: 	struct iovec *iov, *needfree, aiov[UIO_SMALLIOV];
 3113: 	char attrname[EXTATTR_MAXNAMELEN];
 3114: 	u_int iovlen, cnt;
 3115: 	int error, i;
 3116: 
 3117: 	error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
 3118: 	if (error)
 3119: 		return (error);
 3120: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_USERSPACE,
 3121: 	    SCARG(uap, path), td);
 3122: 	if ((error = namei(&nd)) != 0)
 3123: 		return (error);
 3124: 	iovlen = uap->iovcnt * sizeof (struct iovec);
 3125: 	if (uap->iovcnt > UIO_SMALLIOV) {
 3126: 		if (uap->iovcnt > UIO_MAXIOV) {
 3127: 			NDFREE(&nd, 0);
 3128: 			return (EINVAL);
 3129: 		}
 3130: 		MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
 3131: 		needfree = iov;
 3132: 	} else {
 3133: 		iov = aiov;
 3134: 		needfree = NULL;
 3135: 	}
 3136: 	auio.uio_iov = iov;
 3137: 	auio.uio_iovcnt = uap->iovcnt;
 3138: 	auio.uio_rw = UIO_READ;
 3139: 	auio.uio_segflg = UIO_USERSPACE;
 3140: 	auio.uio_td = td;
 3141: 	auio.uio_offset = 0;
 3142: 	if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
 3143: 		goto done;
 3144: 	auio.uio_resid = 0;
 3145: 	for (i = 0; i < uap->iovcnt; i++) {
 3146: 		if (iov->iov_len > INT_MAX - auio.uio_resid) {
 3147: 			error = EINVAL;
 3148: 			goto done;
 3149: 		}
 3150: 		auio.uio_resid += iov->iov_len;
 3151: 		iov++;
 3152: 	}
 3153: 	cnt = auio.uio_resid;
 3154: 	error = VOP_GETEXTATTR(nd.ni_vp, attrname, &auio, p->p_ucred, td);
 3155: 	cnt -= auio.uio_resid;
 3156: 	uap->sysmsg_result = cnt;
 3157: done:
 3158: 	if (needfree)
 3159: 		FREE(needfree, M_IOV);
 3160: 	NDFREE(&nd, 0);
 3161: 	return(error);
 3162: }
 3163: 
 3164: /*
 3165:  * Syscall to delete a named extended attribute from a file or directory.
 3166:  * Accepts attribute name.  The real work happens in VOP_SETEXTATTR().
 3167:  */
 3168: int
 3169: extattr_delete_file(struct extattr_delete_file_args *uap)
 3170: {
 3171: 	struct thread *td = curthread;
 3172: 	struct proc *p = td->td_proc;
 3173: 	struct nameidata nd;
 3174: 	char attrname[EXTATTR_MAXNAMELEN];
 3175: 	int	error;
 3176: 
 3177: 	error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
 3178: 	if (error)
 3179: 		return(error);
 3180: 	NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_USERSPACE,
 3181: 	    SCARG(uap, path), td);
 3182: 	if ((error = namei(&nd)) != 0)
 3183: 		return(error);
 3184: 	error = VOP_SETEXTATTR(nd.ni_vp, attrname, NULL, p->p_ucred, td);
 3185: 	NDFREE(&nd, 0);
 3186: 	return(error);
 3187: }