예제 #1
0
static int
tmpfs_open(struct vop_open_args *v)
{
	struct vnode *vp = v->a_vp;
	int mode = v->a_mode;
	struct tmpfs_node *node;
	int error;

	node = VP_TO_TMPFS_NODE(vp);

#if 0
	/* The file is still active but all its names have been removed
	 * (e.g. by a "rmdir $(pwd)").  It cannot be opened any more as
	 * it is about to die. */
	if (node->tn_links < 1)
		return (ENOENT);
#endif

	/* If the file is marked append-only, deny write requests. */
	if ((node->tn_flags & APPEND) &&
	    (mode & (FWRITE | O_APPEND)) == FWRITE) {
		error = EPERM;
	} else {
		error = (vop_stdopen(v));
	}

	return (error);
}
예제 #2
0
/*
 * set things up for doing i/o on
 * the pfsnode (vp).  (vp) is locked
 * on entry, and should be left locked
 * on exit.
 *
 * for procfs we don't need to do anything
 * in particular for i/o.  all that is done
 * is to support exclusive open on process
 * memory images.
 */
static int
linprocfs_open(struct vop_open_args *ap)
{
	struct pfsnode *pfs = VTOPFS(ap->a_vp);
	struct proc *p2;

	p2 = PFIND(pfs->pfs_pid);
	if (p2 == NULL)
		return (ENOENT);
	if (pfs->pfs_pid && !PRISON_CHECK(ap->a_cred, p2->p_ucred))
		return (ENOENT);

	switch (pfs->pfs_type) {
	case Pmem:
		if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
		    ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE)))
			return (EBUSY);

		if (p_trespass(ap->a_cred, p2->p_ucred))
			return (EPERM);

		if (ap->a_mode & FWRITE)
			pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);

		break;
	default:
		break;
	}

	return (vop_stdopen(ap));
}
예제 #3
0
static int
puffs_vnop_open(struct vop_open_args *ap)
{
    PUFFS_MSG_VARS(vn, open);
    struct vnode *vp = ap->a_vp;
    struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
    int mode = ap->a_mode;
    int error;

    DPRINTF(("puffs_open: vp %p, mode 0x%x\n", vp, mode));

    if (vp->v_type == VREG && mode & FWRITE && !EXISTSOP(pmp, WRITE))
        ERROUT(EROFS);

    if (!EXISTSOP(pmp, OPEN))
        ERROUT(0);

    PUFFS_MSG_ALLOC(vn, open);
    open_msg->pvnr_mode = mode;
    puffs_credcvt(&open_msg->pvnr_cred, ap->a_cred);
    puffs_msg_setinfo(park_open, PUFFSOP_VN,
                      PUFFS_VN_OPEN, VPTOPNC(vp));

    PUFFS_MSG_ENQUEUEWAIT2(pmp, park_open, vp->v_data, NULL, error);
    error = checkerr(pmp, error, __func__);

out:
    DPRINTF(("puffs_open: returning %d\n", error));
    PUFFS_MSG_RELEASE(open);
    if (error)
        return error;
    return vop_stdopen(ap);
}
예제 #4
0
/*
 * set things up for doing i/o on
 * the pfsnode (vp).  (vp) is locked
 * on entry, and should be left locked
 * on exit.
 *
 * for procfs we don't need to do anything
 * in particular for i/o.  all that is done
 * is to support exclusive open on process
 * memory images.
 *
 * procfs_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
 *	       struct file *a_fp)
 */
static int
procfs_open(struct vop_open_args *ap)
{
	struct pfsnode *pfs = VTOPFS(ap->a_vp);
	struct proc *p1, *p2;
	int error;

	p2 = pfs_pfind(pfs->pfs_pid);
	if (p2 == NULL)
		return (ENOENT);
	if (pfs->pfs_pid && !PRISON_CHECK(ap->a_cred, p2->p_ucred)) {
		error = ENOENT;
		goto done;
	}

	switch (pfs->pfs_type) {
	case Pmem:
		if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
		    ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) {
			error = EBUSY;
			goto done;
		}

		p1 = curproc;
		KKASSERT(p1);
		/* Can't trace a process that's currently exec'ing. */ 
		if ((p2->p_flags & P_INEXEC) != 0) {
			error = EAGAIN;
			goto done;
		}
		if (!CHECKIO(p1, p2) || p_trespass(ap->a_cred, p2->p_ucred)) {
			error = EPERM;
			goto done;
		}

		if (ap->a_mode & FWRITE)
			pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);

		break;

	default:
		break;
	}
	error = vop_stdopen(ap);
done:
	pfs_pdone(p2);
	return error;
}
예제 #5
0
/*
 * fdesc_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
 *	      struct file *a_fp)
 */
static int
fdesc_open(struct vop_open_args *ap)
{
	struct vnode *vp = ap->a_vp;
	struct lwp *lp = curthread->td_lwp;

	KKASSERT(lp);

	if (VTOFDESC(vp)->fd_type == Froot)
		return (vop_stdopen(ap));

	/*
	 * XXX Kludge: set lp->lwp_dupfd to contain the value of the the file
	 * descriptor being sought for duplication. The error return ensures
	 * that the vnode for this device will be released by vn_open. Open
	 * will detect this special error and take the actions in dupfdopen.
	 * Other callers of vn_open or VOP_OPEN will simply report the
	 * error.
	 */
	lp->lwp_dupfd = VTOFDESC(vp)->fd_fd;	/* XXX */
	return (ENODEV);
}
예제 #6
0
/*
 * portal_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
 *	       struct file *a_fp)
 */
static int
portal_open(struct vop_open_args *ap)
{
	struct socket *so = 0;
	struct portalnode *pt;
	struct thread *td = curthread;
	struct vnode *vp = ap->a_vp;
	struct uio auio;
	struct iovec aiov[2];
	struct sockbuf sio;
	int res;
	struct mbuf *cm = 0;
	struct cmsghdr *cmsg;
	int newfds;
	int *ip;
	int fd;
	int error;
	int len;
	struct portalmount *fmp;
	struct file *fp;
	struct portal_cred pcred;

	/*
	 * Nothing to do when opening the root node.
	 */
	if (vp->v_flag & VROOT)
		return (vop_stdopen(ap));

	/*
	 * Can't be opened unless the caller is set up
	 * to deal with the side effects.  Check for this
	 * by testing whether the p_dupfd has been set.
	 */
	KKASSERT(td->td_proc);
	if (td->td_lwp->lwp_dupfd >= 0)
		return (ENODEV);

	pt = VTOPORTAL(vp);
	fmp = VFSTOPORTAL(vp->v_mount);

	/*
	 * Create a new socket.
	 */
	error = socreate(AF_UNIX, &so, SOCK_STREAM, 0, td);
	if (error)
		goto bad;

	/*
	 * Reserve some buffer space
	 */
	res = pt->pt_size + sizeof(pcred) + 512;	/* XXX */
	error = soreserve(so, res, res, &td->td_proc->p_rlimit[RLIMIT_SBSIZE]);
	if (error)
		goto bad;

	/*
	 * Kick off connection
	 */
	error = portal_connect(so, (struct socket *)fmp->pm_server->f_data);
	if (error)
		goto bad;

	/*
	 * Wait for connection to complete
	 */
	/*
	 * XXX: Since the mount point is holding a reference on the
	 * underlying server socket, it is not easy to find out whether
	 * the server process is still running.  To handle this problem
	 * we loop waiting for the new socket to be connected (something
	 * which will only happen if the server is still running) or for
	 * the reference count on the server socket to drop to 1, which
	 * will happen if the server dies.  Sleep for 5 second intervals
	 * and keep polling the reference count.   XXX.
	 */
	crit_enter();
	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
		if (fmp->pm_server->f_count == 1) {
			error = ECONNREFUSED;
			crit_exit();
			goto bad;
		}
		(void) tsleep((caddr_t) &so->so_timeo, 0, "portalcon", 5 * hz);
	}
	crit_exit();

	if (so->so_error) {
		error = so->so_error;
		goto bad;
	}

	/*
	 * Set miscellaneous flags
	 */
	so->so_rcv.ssb_timeo = 0;
	so->so_snd.ssb_timeo = 0;
	atomic_set_int(&so->so_rcv.ssb_flags, SSB_NOINTR);
	atomic_set_int(&so->so_snd.ssb_flags, SSB_NOINTR);


	pcred.pcr_flag = ap->a_mode;
	pcred.pcr_uid = ap->a_cred->cr_uid;
	pcred.pcr_ngroups = ap->a_cred->cr_ngroups;
	bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t));
	aiov[0].iov_base = (caddr_t) &pcred;
	aiov[0].iov_len = sizeof(pcred);
	aiov[1].iov_base = pt->pt_arg;
	aiov[1].iov_len = pt->pt_size;
	auio.uio_iov = aiov;
	auio.uio_iovcnt = 2;
	auio.uio_rw = UIO_WRITE;
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_td = td;
	auio.uio_offset = 0;
	auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len;

	error = sosend(so, NULL, &auio, NULL, NULL, 0, td);
	if (error)
		goto bad;

	len = sizeof(int);
	sbinit(&sio, len);
	do {
		struct mbuf *m;
		int flags;

		flags = MSG_WAITALL;
		error = soreceive(so, NULL, NULL, &sio, &cm, &flags);
		if (error)
			goto bad;

		/*
		 * Grab an error code from the mbuf.
		 */
		if ((m = sio.sb_mb) != NULL) {
			m = m_pullup(m, sizeof(int));	/* Needed? */
			if (m) {
				error = *(mtod(m, int *));
				m_freem(m);
			} else {
				error = EINVAL;
			}
		} else {
예제 #7
0
/* ARGSUSED */
static int
nwfs_open(struct vop_open_args *ap)
{
 	thread_t td = curthread; /* XXX */
	struct vnode *vp = ap->a_vp;
	int mode = ap->a_mode;
	struct nwnode *np = VTONW(vp);
	struct ncp_open_info no;
	struct nwmount *nmp = VTONWFS(vp);
	struct vattr vattr;
	int error, nwm;

	NCPVNDEBUG("%s,%d\n",np->n_name, np->opened);
	if (vp->v_type != VREG && vp->v_type != VDIR) { 
		NCPFATAL("open vtype = %d\n", vp->v_type);
		return (EACCES);
	}
	if (vp->v_type == VDIR) return 0;	/* nothing to do now */
	if (np->n_flag & NMODIFIED) {
		if ((error = nwfs_vinvalbuf(vp, V_SAVE, 1)) == EINTR)
			return (error);
		np->n_atime = 0;
		error = VOP_GETATTR(vp, &vattr);
		if (error) 
			return (error);
		np->n_mtime = vattr.va_mtime.tv_sec;
	} else {
		error = VOP_GETATTR(vp, &vattr);
		if (error) 
			return (error);
		if (np->n_mtime != vattr.va_mtime.tv_sec) {
			if ((error = nwfs_vinvalbuf(vp, V_SAVE,	1)) == EINTR)
				return (error);
			np->n_mtime = vattr.va_mtime.tv_sec;
		}
	}
	if (np->opened) {
		np->opened++;
		return (vop_stdopen(ap));
	}
	nwm = AR_READ;
	if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
		nwm |= AR_WRITE;
	error = ncp_open_create_file_or_subdir(nmp, vp, 0, NULL, OC_MODE_OPEN,
					       0, nwm, &no, td, ap->a_cred);
	if (error) {
		if (mode & FWRITE)
			return EACCES;
		nwm = AR_READ;
		error = ncp_open_create_file_or_subdir(nmp, vp, 0, NULL, OC_MODE_OPEN, 0,
						   nwm, &no, td, ap->a_cred);
	}
	np->n_atime = 0;
	if (error == 0) {
		np->opened++;
		np->n_fh = no.fh;
		np->n_origfh = no.origfh;
		error = vop_stdopen(ap);
	}
	return (error);
}
예제 #8
0
static int
devfs_spec_open(struct vop_open_args *ap)
{
	struct vnode *vp = ap->a_vp;
	struct vnode *orig_vp = NULL;
	struct devfs_node *node = DEVFS_NODE(vp);
	struct devfs_node *newnode;
	cdev_t dev, ndev = NULL;
	int error = 0;

	if (node) {
		if (node->d_dev == NULL)
			return ENXIO;
		if (!devfs_node_is_accessible(node))
			return ENOENT;
	}

	if ((dev = vp->v_rdev) == NULL)
		return ENXIO;

	vn_lock(vp, LK_UPGRADE | LK_RETRY);

	if (node && ap->a_fp) {
		devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_spec_open: -1.1-\n");
		lockmgr(&devfs_lock, LK_EXCLUSIVE);

		ndev = devfs_clone(dev, node->d_dir.d_name,
				   node->d_dir.d_namlen,
				   ap->a_mode, ap->a_cred);
		if (ndev != NULL) {
			newnode = devfs_create_device_node(
					DEVFS_MNTDATA(vp->v_mount)->root_node,
					ndev, NULL, NULL);
			/* XXX: possibly destroy device if this happens */

			if (newnode != NULL) {
				dev = ndev;
				devfs_link_dev(dev);

				devfs_debug(DEVFS_DEBUG_DEBUG,
						"parent here is: %s, node is: |%s|\n",
						((node->parent->node_type == Nroot) ?
						"ROOT!" : node->parent->d_dir.d_name),
						newnode->d_dir.d_name);
				devfs_debug(DEVFS_DEBUG_DEBUG,
						"test: %s\n",
						((struct devfs_node *)(TAILQ_LAST(DEVFS_DENODE_HEAD(node->parent), devfs_node_head)))->d_dir.d_name);

				/*
				 * orig_vp is set to the original vp if we cloned.
				 */
				/* node->flags |= DEVFS_CLONED; */
				devfs_allocv(&vp, newnode);
				orig_vp = ap->a_vp;
				ap->a_vp = vp;
			}
		}
		lockmgr(&devfs_lock, LK_RELEASE);
	}

	devfs_debug(DEVFS_DEBUG_DEBUG,
		    "devfs_spec_open() called on %s! \n",
		    dev->si_name);

	/*
	 * Make this field valid before any I/O in ->d_open
	 */
	if (!dev->si_iosize_max)
		/* XXX: old DFLTPHYS == 64KB dependency */
		dev->si_iosize_max = min(MAXPHYS,64*1024);

	if (dev_dflags(dev) & D_TTY)
		vsetflags(vp, VISTTY);

	/*
	 * Open underlying device
	 */
	vn_unlock(vp);
	error = dev_dopen(dev, ap->a_mode, S_IFCHR, ap->a_cred, ap->a_fp);
	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);

	/*
	 * Clean up any cloned vp if we error out.
	 */
	if (error) {
		if (orig_vp) {
			vput(vp);
			ap->a_vp = orig_vp;
			/* orig_vp = NULL; */
		}
		return error;
	}

	/*
	 * This checks if the disk device is going to be opened for writing.
	 * It will be only allowed in the cases where securelevel permits it
	 * and it's not mounted R/W.
	 */
	if ((dev_dflags(dev) & D_DISK) && (ap->a_mode & FWRITE) &&
	    (ap->a_cred != FSCRED)) {

		/* Very secure mode. No open for writing allowed */
		if (securelevel >= 2)
			return EPERM;

		/*
		 * If it is mounted R/W, do not allow to open for writing.
		 * In the case it's mounted read-only but securelevel
		 * is >= 1, then do not allow opening for writing either.
		 */
		if (vfs_mountedon(vp)) {
			if (!(dev->si_mountpoint->mnt_flag & MNT_RDONLY))
				return EBUSY;
			else if (securelevel >= 1)
				return EPERM;
		}
	}

	if (dev_dflags(dev) & D_TTY) {
		if (dev->si_tty) {
			struct tty *tp;
			tp = dev->si_tty;
			if (!tp->t_stop) {
				devfs_debug(DEVFS_DEBUG_DEBUG,
					    "devfs: no t_stop\n");
				tp->t_stop = nottystop;
			}
		}
	}


	if (vn_isdisk(vp, NULL)) {
		if (!dev->si_bsize_phys)
			dev->si_bsize_phys = DEV_BSIZE;
		vinitvmio(vp, IDX_TO_OFF(INT_MAX), PAGE_SIZE, -1);
	}

	vop_stdopen(ap);
#if 0
	if (node)
		nanotime(&node->atime);
#endif

	/*
	 * If we replaced the vp the vop_stdopen() call will have loaded
	 * it into fp->f_data and vref()d the vp, giving us two refs.  So
	 * instead of just unlocking it here we have to vput() it.
	 */
	if (orig_vp)
		vput(vp);

	/* Ugly pty magic, to make pty devices appear once they are opened */
	if (node && (node->flags & DEVFS_PTY) == DEVFS_PTY)
		node->flags &= ~DEVFS_INVISIBLE;

	if (ap->a_fp) {
		KKASSERT(ap->a_fp->f_type == DTYPE_VNODE);
		KKASSERT((ap->a_fp->f_flag & FMASK) == (ap->a_mode & FMASK));
		ap->a_fp->f_ops = &devfs_dev_fileops;
		KKASSERT(ap->a_fp->f_data == (void *)vp);
	}

	return 0;
}