ref: ca13eab7fd19cd77015655a8104c40d5983bb1f0
dir: /sys/src/cmd/btc/fs.c/
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include "dat.h"
Reqqueue *queue;
static char *addrwalk(Fid *, char *, Qid *);
char *balancestr(DirEntry *, Aux *);
char *txstr(DirEntry *, Aux *);
char *blocksstr(DirEntry *, Aux *);
DirEntry entr[] = {
[TROOT] = {
.name = "",
.qid = {TROOT, 0, QTDIR},
.par = TROOT,
.sub = {TADDR, TBLOCKS},
},
[TBLOCKS] = {
.name = "blocks",
.qid = {TBLOCKS, 0, 0},
.par = TROOT,
.str = blocksstr,
},
[TADDR] = {
.name = "addr",
.qid = {TADDR, 0, QTDIR},
.walk = addrwalk,
.par = TROOT,
},
[TADDRSUB] = {
.qid = {TADDRSUB, 0, QTDIR},
.par = TADDR,
.sub = {TADDRBALANCE, TADDRTX},
},
[TADDRBALANCE] = {
.name = "balance",
.qid = {TADDRBALANCE, 0, 0},
.par = TADDRSUB,
.str = balancestr,
},
[TADDRTX] = {
.name = "tx",
.qid = {TADDRTX, 0, 0},
.par = TADDRSUB,
.str = txstr,
},
};
void
pfree(void **v)
{
if(*v != nil)
free(*v);
*v = nil;
}
static void
btcattach(Req *req)
{
req->ofcall.qid = (Qid){0, 0, QTDIR};
req->fid->qid = req->ofcall.qid;
req->fid->aux = emalloc9p(sizeof(Aux));
respond(req, nil);
}
static char *
addrwalk(Fid *fid, char *name, Qid *qid)
{
Aux *a;
a = fid->aux;
pfree(&a->addr);
a->addr = strdup(name);
fid->qid = entr[TADDRSUB].qid;
*qid = fid->qid;
return nil;
}
static char *
btcwalk1(Fid *fid, char *name, Qid *qid)
{
DirEntry *d;
int *s;
d = entr + (int)fid->qid.path;
if(strcmp(name, "..") == 0){
fid->qid = entr[d->par].qid;
*qid = fid->qid;
return nil;
}
if(d->walk)
return d->walk(fid, name, qid);
for(s = d->sub; *s; s++)
if(strcmp(entr[*s].name, name) == 0){
fid->qid = entr[*s].qid;
*qid = fid->qid;
return nil;
}
return "directory entry not found";
}
static char *
btcclone(Fid *oldfid, Fid *newfid)
{
Aux *a, *b;
a = oldfid->aux;
b = emalloc9p(sizeof(Aux));
memcpy(b, a, sizeof(Aux));
if(b->addr)
b->addr = strdup(b->addr);
newfid->aux = b;
return nil;
}
static void
btcopenread(Req *req)
{
DirEntry *d;
Aux *a;
d = entr + (int)req->fid->qid.path;
a = req->fid->aux;
a->str = d->str(d, a);
if(a->str == nil)
responderror(req);
else
respond(req, nil);
}
static void
btcopen(Req *req)
{
DirEntry *d;
d = entr + (int)req->fid->qid.path;
switch(req->ifcall.mode & 3){
case OREAD:
if((req->fid->qid.type & QTDIR) != 0)
break;
if(d->str == nil)
goto noperm;
reqqueuepush(queue, req, btcopenread);
return;
case OWRITE:
if(d->write == nil)
goto noperm;
break;
case ORDWR:
if(d->str == nil || d->write == nil)
goto noperm;
break;
case OEXEC:
goto noperm;
}
respond(req, nil);
return;
noperm:
respond(req, "permission denied");
}
static void
fill(Dir *de, int t, Aux *a)
{
DirEntry *d;
d = entr + t;
de->qid = d->qid;
if(d->qid.type & QTDIR)
de->mode = 0555;
else
de->mode = (d->str ? 0444 : 0) | (d->write ? 0222 : 0);
if(d->name != nil)
de->name = strdup(d->name);
else if(a->addr != nil)
de->name = strdup(a->addr);
else
de->name = strdup("");
de->uid = strdup("satoshi");
de->gid = strdup("satoshi");
de->muid = strdup("satoshi");
de->atime = de->mtime = time(0);
}
static void
btcstat(Req *req)
{
fill(&req->d, (int)req->fid->qid.path, req->fid->aux);
respond(req, nil);
}
static int
btcdirgen(int n, Dir *dir, void *aux)
{
DirEntry *d;
d = entr + (int)((Req*)aux)->fid->qid.path;
if(n >= nelem(d->sub) || d->sub[n] == 0)
return -1;
fill(dir, d->sub[n], ((Req*)aux)->fid->aux);
return 0;
}
static void
btcread(Req *req)
{
DirEntry *d;
Aux *a;
d = entr + (int)req->fid->qid.path;
a = req->fid->aux;
if(req->fid->qid.type & QTDIR){
dirread9p(req, btcdirgen, req);
respond(req, nil);
}else if(d->str && a->str){
readstr(req, a->str);
respond(req, nil);
}else
respond(req, "permission denied");
}
static void
btcflush(Req *req)
{
reqqueueflush(queue, req->oldreq);
respond(req, nil);
}
static void
btcdestroyfid(Fid *fid)
{
Aux *a;
a = fid->aux;
if(a != nil){
pfree(&a->addr);
pfree(&a->str);
free(a);
}
fid->aux = nil;
}
Srv btcsrv = {
.attach = btcattach,
.walk1 = btcwalk1,
.clone = btcclone,
.stat = btcstat,
.open = btcopen,
.read = btcread,
.flush = btcflush,
.destroyfid = btcdestroyfid,
};
void
gofs(void)
{
queue = reqqueuecreate();
threadpostmountsrv(&btcsrv, nil, "/mnt/btc", 0);
}