162 lines · 2.5 KB · C
RawDownload
/* * host's snarf buffer */ #include "dat.h"#include "fns.h"#include "error.h" enum{	Qdir,	Qsnarf, 	Maxsnarf=	100*1024}; staticDirtab snarftab[]={	".",		{Qdir, 0, QTDIR},	0,	0555,	"snarf",	{Qsnarf},			0,	0666,}; static QLock snarflock;	/* easiest to synchronise all access */ static Chan*snarfattach(char *spec){	return devattach('^', spec);} static Walkqid*snarfwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, snarftab, nelem(snarftab), devgen);} static intsnarfstat(Chan* c, uchar *db, int n){	return devstat(c, db, n, snarftab, nelem(snarftab), devgen);} static Chan*snarfopen(Chan* c, int omode){	c = devopen(c, omode, snarftab, nelem(snarftab), devgen);	if(c->qid.path == Qsnarf){		if(c->mode == ORDWR || c->mode == OWRITE){			qlock(&snarflock);			free(c->aux);			c->aux = nil;			qunlock(&snarflock);		}	}	return c;} static voidsnarfclose(Chan* c){	if((c->flag & COPEN) == 0)		return;	if(c->qid.path == Qsnarf){		/* this must be the last reference: no need to lock */		if(c->mode == ORDWR || c->mode == OWRITE){			if(!waserror()){				if(c->aux != nil)					clipwrite(c->aux);				poperror();			}		}		free(c->aux);	}} static longsnarfread(Chan* c, void* a, long n, vlong offset){	void *p; 	switch((ulong)c->qid.path){	case Qdir:		return devdirread(c, a, n, snarftab, nelem(snarftab), devgen);	case Qsnarf:		qlock(&snarflock);		if(waserror()){			qunlock(&snarflock);			nexterror();		}		if(offset == 0){			p = c->aux;			c->aux = nil;			free(p);			c->aux = clipread();		}		if(c->aux != nil)			n = readstr(offset, a, n, c->aux);		else			n = 0;		poperror();		qunlock(&snarflock);		break;	default:		n=0;		break;	}	return n;} static longsnarfwrite(Chan* c, void* va, long n, vlong offset){	ulong l;	char *p; 	switch((ulong)c->qid.path){	case Qsnarf:		/* append only */		USED(offset);	/* not */		qlock(&snarflock);		if(waserror()){			qunlock(&snarflock);			nexterror();		}		if(c->aux != nil)			l = strlen(c->aux);		else			l = 0;		if(l+n > Maxsnarf)			error(Etoobig);		c->aux = realloc(c->aux, l+n+1);		if((p = c->aux) == nil)			error(Enovmem);		memmove(p+l, va, n);		p[l+n] = 0;		snarftab[1].qid.vers++;		poperror();		qunlock(&snarflock);		break;	default:		error(Ebadusefd);	}	return n;} Dev snarfdevtab = {	'^',	"snarf", 	devinit,	snarfattach,	snarfwalk,	snarfstat,	snarfopen,	devcreate,	snarfclose,	snarfread,	devbread,	snarfwrite,	devbwrite,	devremove,	devwstat,};