Sigrid Haflínudóttirfirstdf3a7526 years agoHistory
244 lines · 3.7 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <fcall.h>#include <thread.h>#include <9p.h> enum {	Xpath,	Xreader,	Xfilter,}; typedef struct Aux Aux;typedef struct Data Data; struct Aux {	Reqqueue *reader;	Reqqueue *filter;	Channel *data;	Aux *path;	int fd;	int type;}; struct Data {	int n;	u8int p[1];}; #define FAUX(r) ((Aux*)r->fid->file->aux) static voidfsopen(Req *r){	Aux *a;	char *e; 	if(FAUX(r) == nil){		respond(r, nil);		return;	} 	e = nil;	switch(r->ifcall.mode){	case OREAD:		if(FAUX(r)->reader != nil){			e = "only one reader allowed";		}else{			a = calloc(1, sizeof(Aux));			a->type = Xreader;			a->path = FAUX(r);			a->path->reader = reqqueuecreate();			r->fid->aux = a;		}		break;	case ORDWR:		/* FIXME chain multiple filters together */		if(FAUX(r)->filter != nil){			e = "only one filter allowed";		}else{			a = calloc(1, sizeof(Aux));			a->type = Xfilter;			a->path = FAUX(r);			a->path->filter = reqqueuecreate();			a->fd = a->path->fd;			r->fid->aux = a;		}		break;	default:		e = "invalid mode";		break;	}	respond(r, e);} static voidfilterread(Req *r){	int n; 	if((n = read(FAUX(r)->fd, r->ofcall.data, r->ifcall.count)) >= 0){		r->ofcall.count = n;		respond(r, nil);	}else{		respond(r, "%r");	}} static voidreaderread(Req *r){	Data *d; 	if((d = recvp(FAUX(r)->data)) != nil){		r->ofcall.count = d->n;		memmove(r->ofcall.data, d->p, d->n);		free(d);		respond(r, nil);	}else{		filterread(r);	}} static voidfsread(Req *r){	Aux *a; 	a = r->fid->aux;	switch(a->type){	case Xreader:		reqqueuepush(a->path->reader, r, readerread);		break;	case Xfilter:		reqqueuepush(a->path->filter, r, filterread);		break;	}} static voidfilterwrite(Req *r){	Data *d; 	d = malloc(sizeof(*d)+r->ifcall.count);	d->n = r->ifcall.count;	memmove(d->p, r->ifcall.data, d->n);	sendp(FAUX(r)->data, d);	respond(r, nil);} static voidfswrite(Req *r){	Aux *a; 	a = r->fid->aux;	switch(a->type){	case Xfilter:		reqqueuepush(a->path->filter, r, filterwrite);		break;	default:		respond(r, "invalid op");	}} static voidfsflush(Req *r){	Aux *a;	Req *o; 	o = r->oldreq;	a = o->fid->aux;	if(o->ifcall.type == Tread && a != nil){		if(a->type == Xreader)			reqqueueflush(FAUX(o)->reader, o);		if(a->type == Xfilter)			reqqueueflush(FAUX(o)->filter, o);	} 	respond(r, nil);} static voidfsdestroyfid(Fid *fid){	Aux *a; 	a = fid->aux;	if(a == nil)		return;	switch(a->type){	case Xreader:		if(a->path->reader != nil)			reqqueuefree(a->path->reader);		a->path->reader = nil;		free(a);		break;	case Xfilter:		if(a->path->filter != nil)			reqqueuefree(a->path->filter);		a->path->filter = nil;		free(a);		break;	}} static Srv fs = {	.open = fsopen,	.read = fsread,	.write = fswrite,	.flush = fsflush,	.destroyfid = fsdestroyfid,}; static voidusage(void){	print("usage: %s [-s srv] [-m mtpt] file ...\n", argv0);	threadexitsall("usage");} voidthreadmain(int argc, char **argv){	Aux *a;	char *srv, *mtpt, *file;	int i, fd; 	srv = nil;	mtpt = nil;	ARGBEGIN{	case 'D':		chatty9p++;		break;	case 's':		srv = EARGF(usage());		break;	case 'm':		mtpt = EARGF(usage());		break;	default:		usage();	}ARGEND 	fs.tree = alloctree(nil, nil, DMDIR|0775, nil);	for(i = 0; i < argc; i++){		if((fd = open(argv[i], OREAD)) < 0)			sysfatal("%r");		if((file = utfrrune(argv[i], '/')) != nil)			file++;		else			file = argv[i];		if((a = calloc(1, sizeof(*a))) == nil)			sysfatal("no memory");		a->type = Xpath;		a->fd = fd;		a->data = chancreate(sizeof(Data*), 32);		closefile(createfile(fs.tree->root, file, nil, 0600, a));	}	threadpostmountsrv(&fs, srv, mtpt, MREPL);	threadexits(nil);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t