ref: ef2a51a97c36d1f279993eb17314fa4b080fe488
dir: /jsonfs.c/
#include <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include <json.h>
#include <bio.h>
#include <String.h>
static char *delim = nil;
static char *uid = "json";
static char *mtpt = nil;
void
fsread(Req *r)
{
if(r->fid->file->aux)
readstr(r, r->fid->file->aux);
respond(r, nil);
}
Srv fs = {
.read = fsread,
};
char*
esmprint(char *fmt, ...)
{
char *s;
va_list arg;
va_start(arg, fmt);
s = vsmprint(fmt, arg);
va_end(arg);
if(s == nil)
sysfatal("out of memory");
return s;
}
char*
jprint(char *fmt, ...)
{
char *s, *p;
va_list arg;
p = nil;
if(delim != nil){
if((p = smprint("%s%s", fmt, delim)) == nil)
sysfatal("out of memory");
fmt = p;
}
va_start(arg, fmt);
s = vsmprint(fmt, arg);
va_end(arg);
if(s == nil)
sysfatal("out of memory");
if(p)
free(p);
return s;
}
void
json2files(File *dir, JSON *j)
{
File *d, *f;
JSONEl *tok;
char *p;
void *s;
int anum = 0;
int bnum = 0;
for(tok = j->first; tok != nil; tok = tok->next){
s = nil;
switch(tok->val->t){
case JSONNull:
s = jprint("null");
break;
case JSONBool:
if(tok->val->n)
s = jprint("true");
else
s = jprint("false");
break;
case JSONNumber:
s = jprint("%0.f", tok->val->n);
break;
case JSONString:
s = jprint("%s", tok->val->s);
break;
case JSONArray:
case JSONObject:
if((s = tok->name) == nil || strlen(s) < 1)
s = esmprint("%d", anum++);
if((d = createfile(dir, s, uid, DMDIR|0777, nil)) == nil)
sysfatal("createfile: JSONObject: %r");
d->qid.type = QTDIR;
json2files(d, tok->val);
continue;
default:
sysfatal("wut: %r");
}
if((p = tok->name) == nil)
p = esmprint("%d", bnum++);
if((f = createfile(dir, p, uid, 0666, s)) != nil)
f->length = strlen(s);
}
}
void
populatetree(File *root, int fd)
{
Biobuf in;
String *s;
JSON *j;
Binit(&in, fd, OREAD);
s = s_new();
while(s_read(&in, s, 8192))
;
if((j = jsonparse(s_to_c(s))) == nil)
sysfatal("jsonparse: %r");
json2files(root, j);
s_free(s);
Bterm(&in);
}
void
usage(void)
{
fprint(2, "usage: %s [-D] [-s srv] [-m mtpt] [-n] [file]\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
char *srv;
int fd;
fd = 0;
srv = nil;
mtpt = "/mnt/json";
ARGBEGIN{
case 'D':
chatty9p++;
break;
case 's':
srv = EARGF(usage());
break;
case 'm':
mtpt = EARGF(usage());
break;
case 'n':
delim = "\n";
break;
default:
usage();
}ARGEND;
if(argc > 1)
usage();
else if(argc == 1){
if((fd = open(argv[0], OREAD)) < 0)
sysfatal("open: %r");
}
if(chatty9p)
fprint(2, "srvname %s mtpt %s\n", srv, mtpt);
fs.tree = alloctree(nil, nil, DMDIR|0777, nil);
populatetree(fs.tree->root, fd);
postmountsrv(&fs, srv, mtpt, MREPL|MCREATE);
exits(nil);
}