Ejemplo n.º 1
0
static int
nread_9p(node_9p *np, uio_t uio)
{
	openfid_9p *op;
	uint32_t n, l, sz;
	char *p;
	int e;

	TRACE();
	op = &np->openfid[OREAD];
	if (op->fid == NOFID)
		op = &np->openfid[ORDWR];
	if (op->fid == NOFID)
		return EBADF;

	sz = np->iounit;
	if (sz == 0)
		sz = np->nmp->msize-IOHDRSZ;

	p = malloc_9p(sz);
	if (p == NULL)
		return ENOMEM;

	e = 0;
	while (uio_resid(uio) > 0) {
		n = MIN(uio_resid(uio), sz);
		if ((e=read_9p(np->nmp, op->fid, p, n, uio_offset(uio), &l)) || l==0)
			break;
		if ((e=uiomove(p, l, uio)))
			break;
	}
	free_9p(p);
	return e;
}
Ejemplo n.º 2
0
__private_extern__ int
readdirs_9p(mount_9p *nmp, fid_9p fid, dir_9p **d, uint32_t *nd)
{
	uint8_t *p, *newp;
	uint32_t n;
	int e, ts;

	TRACE();
	*d = NULL;
	*nd = 0;
	ts = 0;
	p = NULL;
	for (;;) {
		newp = malloc_9p(ts+DIRMAX);
		if (newp == NULL) {
			e = ENOMEM;
			break;
		}
		bcopy(p, newp, ts);
		free_9p(p);
		p = newp;
		if ((e=read_9p(nmp, fid, p+ts, DIRMAX, ts, &n)) || n==0)
			break;
		ts += n;
	}

	if (!e)
		e = dirpackage(p, ts, d, nd, ISSET(nmp->flags, F_DOTU));

	free_9p(p);
	return e;
}
Ejemplo n.º 3
0
__private_extern__ int
wstat_9p(mount_9p *nmp, fid_9p fid, dir_9p *dp)
{
	Fcall tx, rx;
	void *p;
	uint32_t n;
	int e, dotu;

	TRACE();
	dotu = ISSET(nmp->flags, F_DOTU);
	n = sizeD2M(dp, dotu);
	p = malloc_9p(n);
	if (p == NULL)
		return ENOMEM;
	
	if(convD2M(dp, p, n, dotu) != n){
		free_9p(p);
		return EINVAL;
	}
	tx.type = Twstat;
	tx.fid = fid;
	tx.stat = p;
	tx.nstat = n;
	e = rpc_9p(nmp, &tx, &rx, NULL);
	free_9p(p);

	return e;
}
Ejemplo n.º 4
0
__private_extern__ int
stat_9p(mount_9p *nmp, fid_9p fid, dir_9p **dpp)
{
	Fcall tx, rx;
	Dir *dp;
	void *p;
	int e, n;
	
	TRACE();
	p = NULL;
	dp = NULL;
	tx.type = Tstat;
	tx.fid = fid;
	if ((e=rpc_9p(nmp, &tx, &rx, &p)))
		return e;

	n = GBIT16((uint8_t*)p);
	dp = malloc_9p(sizeof(Dir) + BIT16SZ + n);
	if (dp == NULL) {
		e = ENOMEM;
		goto error;
	}

	if(convM2D(rx.stat, rx.nstat, dp, (char*)&dp[1], ISSET(nmp->flags, F_DOTU)) != rx.nstat) {
		DEBUG("convM2D");
		e = EBADRPC;
		goto error;
	}

error:
	free_9p(p);
	*dpp = dp;
	return e;
}
Ejemplo n.º 5
0
static int
dirpackage(uint8_t *buf, int ts, Dir **d, uint32_t *nd, int dotu)
{
	char *s;
	int ss, i, n, nn;
	uint m;
	
	*d = nil;
	*nd = 0;
	if(ts <= 0) 
		return 0;

	/*
	 * first find number of all stats, check they look like stats, & size all associated strings
	 */
	ss = 0;
	n = 0;
	for(i = 0; i < ts; i += m){
		m = BIT16SZ + GBIT16(&buf[i]);
		if(statcheck(&buf[i], m, dotu) < 0)
			break;
		ss += m;
		n++;
	}

	if(i != ts) {
		DEBUG("statcheck");
		return EBADRPC;
	}
	
	*d = malloc_9p(n * sizeof(Dir) + ss);
	if (*d == NULL)
		return ENOMEM;
	/*
	 * then convert all buffers
	 */
	s = (char*)*d + n * sizeof(Dir);
	nn = 0;
	for(i = 0; i < ts; i += m){
		m = BIT16SZ + GBIT16(&buf[i]);
		if(nn >= n || convM2D(&buf[i], m, *d + nn, s, dotu) != m){
			free_9p(*d);
			*d = nil;
			DEBUG("convM2D");
			return EBADRPC;
		}
		nn++;
		s += m;
	}
	*nd = nn;
	return 0;
}
Ejemplo n.º 6
0
static int
addrget_9p(user_addr_t name, int len, struct sockaddr **addrp)
{
	struct sockaddr *addr;
	int e;

	addr = malloc_9p(len);
	if (addr == NULL)
		return ENOMEM;
	if ((e=copyin(name, addr, len))) {
		free_9p(addr);
		return e;
	}
	*addrp = addr;
	return 0;
}
Ejemplo n.º 7
0
static int
strndup(char *name, int nname, char **sp)
{
	char *s;

	if (!name || nname<=0)
		return EINVAL;

	s = malloc_9p(nname+1);
	if (s == NULL)
		return ENOMEM;
	bcopy(name, s, nname);
	s[nname] = 0;
	*sp = s;
	return 0;
}
Ejemplo n.º 8
0
static int
nameget_9p(user_addr_t in, char **out)
{
	size_t size;
	char *p;
	int e;
	
	p = malloc_9p(NAME_MAX+1);
	if (p == NULL)
		return ENOMEM;
	if ((e=copyinstr(in, p, NAME_MAX, &size)) || !size) {
		free_9p(p);
		return e;
	}
	*out = p;
	return 0;
}
Ejemplo n.º 9
0
static int
vnop_rename_9p(struct vnop_rename_args *ap)
{
	struct componentname *tcnp;
	vnode_t fdvp, tdvp, fvp;
	node_9p *fdnp, *fnp;
	dir_9p d;
	char *s;
	int e;

	TRACE();
	fdvp = ap->a_fdvp;
	tdvp = ap->a_tdvp;
	fvp = ap->a_fvp;
	tcnp = ap->a_tcnp;
	fdnp = NTO9P(fdvp);
	fnp = NTO9P(fvp);

	if (fdvp!=tdvp || NTO9P(fdvp)!=NTO9P(tdvp))
		return ENOTSUP;

	nlock_9p(fdnp, NODE_LCK_EXCLUSIVE);
	nlock_9p(fnp, NODE_LCK_EXCLUSIVE);
	nulldir(&d);
	e = ENOMEM;
	s = malloc_9p(tcnp->cn_namelen+1);
	if (s == NULL)
		goto error;

	bcopy(tcnp->cn_nameptr, s, tcnp->cn_namelen);
	s[tcnp->cn_namelen] = 0;
	d.name = s;
	e = wstat_9p(fnp->nmp, fnp->fid, &d);
	free_9p(s);
	if (e == 0) {
		cache_purge(fvp);
		cache_purge(fdvp);
	}

error:
	nunlock_9p(fnp);
	nunlock_9p(fdnp);
	return e;
}
Ejemplo n.º 10
0
__private_extern__ int
readdir_9p(mount_9p *nmp, fid_9p fid, off_t off, dir_9p **d, uint32_t *nd, uint32_t *nrd)
{
	void *p;
	int e;
	
	TRACE();
	*d = NULL;
	*nd = 0;
	*nrd = 0;
	p = malloc_9p(DIRMAX);
	if (p == NULL)
		return ENOMEM;

	e = read_9p(nmp, fid, p, DIRMAX, off, nrd);
	if (!e)
		e = dirpackage(p, *nrd, d, nd, ISSET(nmp->flags, F_DOTU));
	free_9p(p);
	return e;
}
Ejemplo n.º 11
0
static int
nwrite_9p(node_9p *np, uio_t uio)
{
	openfid_9p *op;
	user_ssize_t resid;
	uint32_t l, sz;
	off_t off;
	char *p;
	int n, e;

	TRACE();
	op = &np->openfid[OWRITE];
	if (op->fid == NOFID)
		op = &np->openfid[ORDWR];
	if (op->fid == NOFID)
		return EBADF;

	sz = np->iounit;
	if (sz == 0)
		sz = np->nmp->msize-IOHDRSZ;

	p = malloc_9p(sz);
	if (p == NULL)
		return ENOMEM;

	e = 0;
	while (uio_resid(uio) > 0) {
		l = 0;
		off = uio_offset(uio);
		resid = uio_resid(uio);
		n = MIN(resid, sz);
		if ((e=uiomove(p, n, uio)))
			break;
		if ((e=write_9p(np->nmp, op->fid, p, n, off, &l)))
			break;
		uio_setoffset(uio, off+l);
		uio_setresid(uio, resid-l);
	}
	free_9p(p);
	return e;
}
Ejemplo n.º 12
0
__private_extern__ int
nget_9p(mount_9p *nmp, fid_9p fid, qid_9p qid, vnode_t dvp, vnode_t *vpp, struct componentname *cnp, vfs_context_t ctx)
{
#pragma unused(ctx)
	struct vnode_fsparam fsp;
	struct hnode_9p *nhp;
	node_9p *np;
	uint32_t vid;
	int e, i;

	TRACE();
	nhp = HASH9P(nmp, qid.path);
loop:
	lck_mtx_lock(nmp->nodelck);
	LIST_FOREACH (np, nhp, next) {
		if(np->dir.qid.path != qid.path)
			continue;
		if (ISSET(np->flags, NODE_INIT)) {
			SET(np->flags, NODE_WAITINIT);
			msleep(np, nmp->nodelck, PINOD|PDROP, "nget_9p_init", NULL);
			goto loop;
		}
		if (ISSET(np->flags, NODE_RECL)) {
			SET(np->flags, NODE_WAITRECL);
			msleep(np, nmp->nodelck, PINOD|PDROP, "nget_9p_reclaim", NULL);
			goto loop;
		}
		vid = vnode_vid(np->vp);
		lck_mtx_unlock(nmp->nodelck);
		if (vnode_getwithvid(np->vp, vid))
			goto loop;
		
		nlock_9p(np, NODE_LCK_EXCLUSIVE);
		if (dvp && cnp && ISSET(cnp->cn_flags, MAKEENTRY) && np->dir.qid.vers!=0) {
			// DEBUG("caching %s", np->dir->name);
			cache_enter(dvp, np->vp, cnp);
		} else {
			// DEBUG("not in cache qid=%d %s", qid.vers, np->dir->name);
		}

		*vpp = np->vp;
		return 0;
	}
	
	if (fid == NOFID)
		return EFAULT;

	np = malloc_9p(sizeof(*np));
	if (np == NULL) {
err0:
		lck_mtx_unlock(nmp->nodelck);
		return ENOMEM;
	}
	np->lck = lck_rw_alloc_init(lck_grp_9p, LCK_ATTR_NULL);
	if (np->lck == NULL) {
		free_9p(np);
		goto err0;
	}

	np->nmp = nmp;
	np->fid = fid;
	np->dir.qid = qid;
	for (i=0; i<3; i++)
		np->openfid[i].fid = NOFID;

	SET(np->flags, NODE_INIT);
	LIST_INSERT_HEAD(nhp, np, next);
	nlock_9p(np, NODE_LCK_EXCLUSIVE);
	lck_mtx_unlock(nmp->nodelck);

	if ((e=ngetdir_9p(np))) {
err1:
		nunlock_9p(np);
		lck_mtx_lock(nmp->nodelck);
		LIST_REMOVE(np, next);
		CLR(np->flags, NODE_INIT);
		if (ISSET(np->flags, NODE_WAITINIT)) {
			CLR(np->flags, NODE_WAITINIT);
			wakeup(np);
		}
		lck_mtx_unlock(nmp->nodelck);
		lck_rw_free(np->lck, lck_grp_9p);
		free_9p(np);
		return e;
	}

	fsp.vnfs_mp			= nmp->mp;
	fsp.vnfs_str		= fsname;
	fsp.vnfs_dvp		= dvp;
	fsp.vnfs_fsnode		= np;
	fsp.vnfs_vops		= vnode_op_9p;
	fsp.vnfs_markroot	= dvp==NULL? TRUE: FALSE;
	fsp.vnfs_marksystem	= FALSE;
	fsp.vnfs_filesize	= np->dir.length;
	fsp.vnfs_cnp		= cnp;
	fsp.vnfs_flags		= VNFS_ADDFSREF;
	dirvtype_9p(&np->dir, ISSET(nmp->flags, F_DOTU), &fsp.vnfs_vtype, &fsp.vnfs_rdev);
	if (!dvp || !cnp || !ISSET(cnp->cn_flags, MAKEENTRY) || qid.vers==0)
		SET(fsp.vnfs_flags, VNFS_NOCACHE);

	if ((e=vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &fsp, &np->vp)))
		goto err1;

	vnode_settag(np->vp, VT_OTHER);
	lck_mtx_lock(nmp->nodelck);
	CLR(np->flags, NODE_INIT);
	if (ISSET(np->flags, NODE_WAITINIT)) {
		CLR(np->flags, NODE_WAITINIT);
		wakeup(np);
	}
	lck_mtx_unlock(nmp->nodelck);
	*vpp = np->vp;

	return 0;
}
Ejemplo n.º 13
0
static int
vfs_mount_9p(mount_t mp, vnode_t devvp, user_addr_t data, vfs_context_t ctx)
{
#pragma unused(devvp)
	struct sockaddr *addr, *authaddr;
	struct vfsstatfs *sp;
	char authkey[DESKEYLEN+1];
	kauth_cred_t cred;
	user_args_9p args;
	mount_9p *nmp;
	size_t size;
	fid_9p fid;
	qid_9p qid;
	char *vers;
	int e;

	TRACE();
	nmp = NULL;
	addr = NULL;
	authaddr = NULL;
	fid = NOFID;

	if (vfs_isupdate(mp))
		return ENOTSUP;

	if (vfs_context_is64bit(ctx)) {
		if ((e=copyin(data, &args, sizeof(args))))
			goto error;
	} else {
		args_9p args32;
		if ((e=copyin(data, &args32, sizeof(args32))))
			goto error;
		args.spec			= CAST_USER_ADDR_T(args32.spec);
		args.addr			= CAST_USER_ADDR_T(args32.addr);
		args.addrlen		= args32.addrlen;
		args.authaddr		= CAST_USER_ADDR_T(args32.authaddr);
		args.authaddrlen	= args32.authaddrlen;
		args.volume			= CAST_USER_ADDR_T(args32.volume);
		args.uname			= CAST_USER_ADDR_T(args32.uname);
		args.aname			= CAST_USER_ADDR_T(args32.aname);
		args.authkey		= CAST_USER_ADDR_T(args32.authkey);
		args.flags			= args32.flags;
	}
	e = ENOMEM;
	nmp = malloc_9p(sizeof(*nmp));
	if (nmp == NULL)
		return e;

	nmp->mp = mp;
	TAILQ_INIT(&nmp->req);
	nmp->lck = lck_mtx_alloc_init(lck_grp_9p, LCK_ATTR_NULL);
	nmp->reqlck = lck_mtx_alloc_init(lck_grp_9p, LCK_ATTR_NULL);
	nmp->nodelck = lck_mtx_alloc_init(lck_grp_9p, LCK_ATTR_NULL);
	nmp->node = hashinit(desiredvnodes, M_TEMP, &nmp->nodelen);
	if (nmp->lck==NULL || nmp->reqlck==NULL || nmp->nodelck==NULL || nmp->node==NULL)
		goto error;

	if ((e=nameget_9p(args.volume, &nmp->volume)))
		goto error;
	if ((e=nameget_9p(args.uname, &nmp->uname)))
		goto error;
	if ((e=nameget_9p(args.aname, &nmp->aname)))
		goto error;

	cred = vfs_context_ucred(ctx);
	if (IS_VALID_CRED(cred)) {
		nmp->uid = kauth_cred_getuid(cred);
		nmp->gid = kauth_cred_getgid(cred);
	} else {
		nmp->uid = KAUTH_UID_NONE;
		nmp->gid = KAUTH_GID_NONE;
	}
	
	vfs_getnewfsid(mp);
	vfs_setfsprivate(mp, nmp);
	
	nmp->flags = args.flags;
	if ((e=addrget_9p(args.addr, args.addrlen, &addr)))
		goto error;
	if ((e=connect_9p(nmp, addr)))
		goto error;

	vers = VERSION9P;
	if (ISSET(nmp->flags, FLAG_DOTU))
		vers = VERSION9PDOTU;
	if ((e=version_9p(nmp, vers, &nmp->version)))
		goto error;
	if (ISSET(nmp->flags, FLAG_DOTU) && strcmp(VERSION9PDOTU, nmp->version)==0)
		SET(nmp->flags, F_DOTU);

	nmp->afid = NOFID;
	if (args.authaddr && args.authaddrlen && args.authkey) {
		if ((e=copyin(args.authkey, authkey, DESKEYLEN)))
			goto error;
		if ((e=addrget_9p(args.authaddr, args.authaddrlen, &authaddr)))
			goto error;
		if ((e=auth_9p(nmp, nmp->uname, nmp->aname, nmp->uid, &nmp->afid, &qid)))
			goto error;
		if (nmp->afid!=NOFID &&
			(e=authp9any_9p(nmp, nmp->afid, authaddr, nmp->uname, authkey)))
			goto error;
		bzero(authkey, DESKEYLEN);
	}
	if ((e=attach_9p(nmp, nmp->uname, nmp->aname, nmp->afid, nmp->uid, &fid, &qid)))
		goto error;

	if ((e=nget_9p(nmp, fid, qid, NULL, &nmp->root, NULL, ctx)))
		goto error;

	nunlock_9p(NTO9P(nmp->root));
	e = vnode_ref(nmp->root);
	vnode_put(nmp->root);
	if (e)
		goto error;

	vfs_setauthopaque(mp);
	vfs_clearauthopaqueaccess(mp);
	vfs_setlocklocal(mp);

	// init stats
	sp = vfs_statfs(nmp->mp);
	copyinstr(args.spec, sp->f_mntfromname, MNAMELEN-1, &size);
	bzero(sp->f_mntfromname+size, MNAMELEN-size);
	sp->f_bsize = PAGE_SIZE;
	sp->f_iosize = nmp->msize-IOHDRSZ;
	sp->f_blocks = sp->f_bfree = sp->f_bavail = sp->f_bused = 0;
	sp->f_files = 65535;
	sp->f_ffree = sp->f_files-2;
	sp->f_flags = vfs_flags(mp);
	
	free_9p(addr);
	free_9p(authaddr);
	return 0;

error:
	bzero(authkey, DESKEYLEN);
	free_9p(addr);
	free_9p(authaddr);
	if (nmp->so) {
		clunk_9p(nmp, fid);
		disconnect_9p(nmp);
	}
	freemount_9p(nmp);
	vfs_setfsprivate(mp, NULL);
	return e;
}