shithub: 9volt

ref: ef2a51a97c36d1f279993eb17314fa4b080fe488
dir: /jsonfs.c/

View raw version
#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);
}