mischiefinitial commitbd439e57 years agoHistory
452 lines · 8.2 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <fcall.h> #include "cbor.h" static char*cbor_print(cbor *c, char *bp, char *be){	int i;	char *p, *e, *bracket; 	switch(c->type){	case CBOR_UINT:		return seprint(bp, be, "%llud", c->uint); 	case CBOR_SINT:		return seprint(bp, be, "%lld", c->sint); 	case CBOR_BYTE:		return seprint(bp, be, "%.*H", c->len, c->byte); 	case CBOR_STRING:		return seprint(bp, be, "\"%.*s\"", c->len, c->string); 	case CBOR_ARRAY:		bracket = "[]";		goto arr; 	case CBOR_MAP:		bracket = "{}"; arr:		p = bp;		e = be; 		p = seprint(p, e, "%c", bracket[0]); 		for(i = 0; i < c->len; i++){			p = cbor_print(c->array[i], p, e);			if(c->len > 1 && i < c->len - 1)				p = seprint(p, e, ", ");		} 		p = seprint(p, e, "%c", bracket[1]);		return p; 	case CBOR_MAP_ELEMENT:		p = bp;		e = be; 		p = cbor_print(c->key, p, e);		p = seprint(p, e, ": ");		p = cbor_print(c->value, p, e);		return p; 	case CBOR_TAG:		p = bp;		e = be; 		p = seprint(p, e, "%llud(", c->tag);		p = cbor_print(c->item, p, e);		p = seprint(p, e, ")");		return p; 	case CBOR_NULL:		return seprint(bp, be, "null"); 	case CBOR_FLOAT:		return seprint(bp, be, "%#g", c->f); 	case CBOR_DOUBLE:		return seprint(bp, be, "%#g", c->d); 	default:		abort();	} 	return nil;} static voidcbor_fprint(int fd, cbor *c){	char buf[2048]; 	cbor_print(c, buf, buf+sizeof(buf)); 	fprint(fd, "%s\n", buf);} ulongconvS2Mcbor(Fcall *f, uchar *ap, uint nap){	int i, n, nn;	ulong sz;	cbor *o, *c, *a; 	switch(f->type){	default:		abort(); 	case Tversion:		n = strlen(f->version);		o = cbor_pack(&cbor_default_allocator, "[us]", (u64int)f->msize, n, f->version);		break; 	case Tflush:		o = cbor_pack(&cbor_default_allocator, "u", (u64int)f->oldtag);		break; 	case Tauth:		n = strlen(f->uname);		nn = strlen(f->aname);		o = cbor_pack(&cbor_default_allocator, "[uss]", (u64int)f->afid, n, f->uname, nn, f->aname);		break; 	case Tattach:		n = strlen(f->uname);		nn = strlen(f->aname);		o = cbor_pack(&cbor_default_allocator, "[uuss]", (u64int)f->fid, (u64int)f->afid, n, f->uname, nn, f->aname);		break; 	case Twalk:		a = cbor_make_array(&cbor_default_allocator, 0);		assert(a != nil);		for(i = 0; i < f->nwname; i++){			o = cbor_make_string(&cbor_default_allocator, f->wname[i], strlen(f->wname[i]));			assert(o != nil);			assert(cbor_array_append(&cbor_default_allocator, a, o) != nil);		} 		o = cbor_pack(&cbor_default_allocator, "[uuc]", (u64int)f->fid, (u64int)f->newfid, a);		break; 	case Topen:		o = cbor_pack(&cbor_default_allocator, "[uu]", (u64int)f->fid, f->mode);		break; 	case Tcreate:		n = strlen(f->name);		o = cbor_pack(&cbor_default_allocator, "[usuu]", (u64int)f->fid, n, f->name, f->perm, f->mode);		break; 	case Tread:		o = cbor_pack(&cbor_default_allocator, "[uiu]", (u64int)f->fid, (s64int)f->offset, f->count);		break; 	case Twrite:		o = cbor_pack(&cbor_default_allocator, "[uib]", (u64int)f->fid, (s64int)f->offset, f->count, f->data);		break; 	case Tclunk:	case Tremove:	case Tstat:		o = cbor_pack(&cbor_default_allocator, "u", (u64int)f->fid);		break; 	case Twstat:		o = cbor_pack(&cbor_default_allocator, "[ub]", (u64int)f->fid, f->nstat, f->stat);		break; 	case Rversion:		n = strlen(f->version);		o = cbor_pack(&cbor_default_allocator, "[us]", (u64int)f->msize, n, f->version);		break; 	case Rerror:		n = strlen(f->ename);		o = cbor_pack(&cbor_default_allocator, "s", n, f->ename);		break; 	case Rflush:		o = cbor_pack(&cbor_default_allocator, "N");		break; 	case Rauth:		o = cbor_pack(&cbor_default_allocator, "[uuu]",			(u64int)f->aqid.type, (u64int)f->aqid.vers, (u64int)f->aqid.path);		break; 	case Rattach:		o = cbor_pack(&cbor_default_allocator, "[uuu]",			(u64int)f->qid.type, (u64int)f->qid.vers, (u64int)f->qid.path);		break; 	case Rwalk:		a = cbor_make_array(&cbor_default_allocator, 0);		assert(a != nil);		for(i = 0; i < f->nwqid; i++){			o = cbor_pack(&cbor_default_allocator, "[uuu]",				(u64int)f->wqid[i].type, (u64int)f->wqid[i].vers, (u64int)f->wqid[i].path);			assert(o != nil);			assert(cbor_array_append(&cbor_default_allocator, a, o) != nil);		} 		o = a; 		break; 	case Ropen:	case Rcreate:		o = cbor_pack(&cbor_default_allocator, "[uuuu]",			(u64int)f->qid.type, (u64int)f->qid.vers, (u64int)f->qid.path, (u64int)f->iounit);		break; 	case Rread:		o = cbor_pack(&cbor_default_allocator, "b", f->count, f->data);		break; 	case Rwrite:		o = cbor_pack(&cbor_default_allocator, "u", (u64int)f->count);		break; 	case Rclunk:	case Rremove:	case Rwstat:		o = cbor_pack(&cbor_default_allocator, "N");		break; 	case Rstat:		o = cbor_pack(&cbor_default_allocator, "b", f->nstat, f->stat);		break;	} 	assert(o != nil); 	c = cbor_pack(&cbor_default_allocator, "t[uc]", (u64int)f->type, (u64int)f->tag, o); 	assert(c != nil); 	sz = cbor_encode_size(c); 	if(nap >= sz){		assert(cbor_encode(c, ap, nap) == sz);	} 	cbor_free(&cbor_default_allocator, c); 	return sz;} uintconvM2Scbor(uchar *ap, uint nap, Fcall *f){	int len, len2;	u64int type, tag, msize, afid;	char *s, *s2;	cbor *c, *v; 	c = cbor_decode(&cbor_default_allocator, ap, nap);	if(c == nil){		fprint(2, "decode M2S failed\n");		return 0;	} 	if(cbor_unpack(&cbor_default_allocator, c, "t[uc]", &type, &tag, &v) < 0){		fprint(2, "unpack type/tag failed\n");		goto err;	} 	f->type = type;	f->tag = tag; 	switch(f->type){	default:		goto err; 	case Rversion:	case Tversion:		if(cbor_unpack(&cbor_default_allocator, v, "[us]", &msize, &len, &s) < 0){			fprint(2, "unpack Tversion failed\n");			goto err;		} 		f->msize = msize;		f->version = s;		break; 	case Tauth:		if(cbor_unpack(&cbor_default_allocator, v, "[uss]", &afid, &len, &s, &len2, &s2) < 0)			goto err; 		f->afid = afid;		f->uname = s;		f->aname = s2;		break; 	} 	return 1; err:	cbor_free(&cbor_default_allocator, c);	return 0;} static Fcall fcalls[17]; voidusage(void){	fprint(2, "usage: %s\n", argv0);	exits("usage");} voidmain(int argc, char *argv[]){	int i, sz;	uchar buf[1024];	Fcall *f, f2;; 	ARGBEGIN{	default:		usage();	}ARGEND 	fmtinstall('H', encodefmt);	fmtinstall('F', fcallfmt); 	f = &fcalls[0];	f->type = Tversion;	f->tag = 100;	f->msize = 8192+IOHDRSZ;	f->version = "9P2000"; 	f = &fcalls[1];	f->type = Rversion;	f->tag = 100;	f->msize = 8192+IOHDRSZ;	f->version = "9P2000"; 	f = &fcalls[2];	f->type = Tauth;	f->tag = 100;	f->afid = 1;	f->uname = "glenda";	f->aname = ""; 	f = &fcalls[3];	f->type = Rauth;	f->tag = 100;	f->aqid = (Qid){0, 0, QTAUTH}; 	f = &fcalls[4];	f->type = Tattach;	f->tag = 100;	f->fid = 200;	f->afid = 1;	f->uname = "glenda";	f->aname = ""; 	f = &fcalls[5];	f->type = Rattach;	f->tag = 100;	f->qid = (Qid){1, 1, QTDIR}; 	f = &fcalls[6];	f->type = Rerror;	f->tag = 100;	f->ename = "some kind of horrible error"; 	f = &fcalls[7];	f->type = Tflush;	f->tag = 100;	f->oldtag = 99; 	f = &fcalls[8];	f->type = Rflush;	f->tag = 100; 	f = &fcalls[9];	f->type = Twalk;	f->tag = 100;	f->fid = 200;	f->newfid = 201;	f->nwname = 4;	f->wname[0] = "foo";	f->wname[1] = "bar";	f->wname[2] = "baz";	f->wname[3] = "quux"; 	f = &fcalls[10];	f->type = Rwalk;	f->tag = 100;	f->nwqid = 4;	f->wqid[0] = (Qid){2, 1, QTDIR};	f->wqid[1] = (Qid){3, 1, QTDIR};	f->wqid[2] = (Qid){4, 1, QTDIR};	f->wqid[3] = (Qid){5, 1, QTFILE}; 	f = &fcalls[11];	f->type = Topen;	f->tag = 100;	f->fid = 200;	f->mode = ORDWR; 	f = &fcalls[12];	f->type = Ropen;	f->tag = 100;	f->qid = (Qid){1, 1, QTFILE};	f->iounit = 8192; 	f = &fcalls[13];	f->type = Tcreate;	f->tag = 100;	f->fid = 200;	f->name = "foo";	f->perm = 0755;	f->mode = ORDWR; 	f = &fcalls[14];	f->type = Rcreate;	f->tag = 100;	f->qid = (Qid){1, 1, QTFILE};	f->iounit = 8192; 	f = &fcalls[15];	f->type = Tread;	f->tag = 100;	f->fid = 200;	f->offset = 1234;	f->count = 8192; 	f = &fcalls[16];	f->type = Rread;	f->tag = 100;	f->count = 5;	f->data = "hello"; 	for(i = 0; i < nelem(fcalls); i++){		f = &fcalls[i]; 		print("<- %F\n", f); 		sz = convS2M(f, buf, sizeof(buf));		print("9p   %4d 0x%.*H\n", sz, sz, buf); 		sz = convS2Mcbor(f, buf, sizeof(buf));		print("cbor %4d 0x%.*H\n", sz, sz, buf); 		if(convM2Scbor(buf, sz, &f2) == 0)			fprint(2, "convM2Scbor failed\n");		else			print("-> %F\n", &f2); 		// free shit in f2	} 	exits(nil);}