Charles.Forsyth20070714-105261ffbe219 years agoHistory
213 lines · 4.2 KB · Brainfuck
RawDownload
implement Trfs; include "sys.m";	sys: Sys; include "draw.m"; include "styx.m";	styx: Styx;	Rmsg, Tmsg: import styx; Trfs: module{	init: fn(nil: ref Draw->Context, nil: list of string);}; Fid: adt {	fid:	int;	isdir:	int;	aux:	int;}; Table: adt[T] {	items: array of list of (int, T);	nilval: T; 	new: fn(nslots: int, nilval: T): ref Table[T];	add:	fn(t: self ref Table, id: int, x: T): int;	del:	fn(t: self ref Table, id: int): T;	find:	fn(t: self ref Table, id: int): T;}; NBspace: con 16r00A0;	# Unicode `no-break' space (looks like a faint box in some fonts)NBspacelen: con 2;		# length of it in utf-8 msize: int;lock: chan of int;fids: ref Table[ref Fid];tfids: ref Table[ref Fid]; init(nil: ref Draw->Context, args: list of string){	sys = load Sys Sys->PATH;	styx = load Styx Styx->PATH;		if(len args != 3){		sys->fprint(sys->fildes(2), "usage: trfs dir mountpoint\n");		raise "fail:usage";	}	dir := hd tl args;	mntpt := hd tl tl args;	p := array[2] of ref Sys->FD;	q := array[2] of ref Sys->FD;	fids = Table[ref Fid].new(11, nil);	tfids = Table[ref Fid].new(11, nil);	lock = chan[1] of int; 	styx->init();	sys->pipe(p);	sys->pipe(q);	if(sys->export(q[0], dir, Sys->EXPASYNC) < 0)		fatal("can't export " + dir);	spawn trfsin(p[1], q[1]);	spawn trfsout(p[1], q[1]);	if(sys->mount(p[0], nil, mntpt, Sys->MREPL|Sys->MCREATE, nil) < 0)		fatal("can't mount on " + mntpt);} trfsin(cfd, sfd: ref Sys->FD){	while((t:=Tmsg.read(cfd, msize)) != nil){		pick m := t {		Clunk or		Remove =>			fids.del(m.fid);		Create =>			fid := ref Fid(m.fid, 0, 0);			fids.add(m.fid, fid);			addtfid(m.tag, fid);			m.name = tr(m.name, NBspace, ' ');		Open =>			fid := ref Fid(m.fid, 0, 0);			fids.add(m.fid, fid);			addtfid(m.tag, fid);		Read =>			fid := fids.find(m.fid);			addtfid(m.tag, fid);			if(fid.isdir){				m.count /= NBspacelen;	# translated strings might grow by this much				if(m.offset == big 0)					fid.aux = 0;				m.offset -= big fid.aux;			}		Walk =>			for(i:=0; i<len m.names; i++)				m.names[i] = tr(m.names[i], NBspace, ' ');		Wstat =>			m.stat.name = tr(m.stat.name, NBspace, ' ');		}		sys->write(sfd, t.pack(), t.packedsize());	}}		trfsout(cfd, sfd: ref Sys->FD){	b := array[Styx->MAXFDATA] of byte;	while((r := Rmsg.read(sfd, msize)) != nil){		pick m := r {		Version =>			msize = m.msize;			if(msize > len b)				b = array[msize] of byte;	# a bit more than needed but doesn't matter		Create or		Open =>			fid := deltfid(m.tag);			fid.isdir = m.qid.qtype & Sys->QTDIR;		Read =>			fid := deltfid(m.tag);			if(fid.isdir){				bs := 0;				for(n := 0; n < len m.data; ){					(ds, d) := styx->unpackdir(m.data[n:]);					if(ds <= 0)						break;					d.name = tr(d.name, ' ', NBspace);					b[bs:] = styx->packdir(d);					bs += styx->packdirsize(d);					n += ds;				}				fid.aux += bs-n;				m.data = b[0:bs];			}		Stat =>			m.stat.name = tr(m.stat.name, ' ', NBspace);		}		sys->write(cfd, r.pack(), r.packedsize());	}} tr(name: string, c1, c2: int): string{	for(i:=0; i<len name; i++)		if(name[i] == c1)			name[i] = c2;	return name;} Table[T].new(nslots: int, nilval: T): ref Table[T]{	if(nslots == 0)		nslots = 13;	return ref Table[T](array[nslots] of list of (int, T), nilval);} Table[T].add(t: self ref Table[T], id: int, x: T): int{	slot := id % len t.items;	for(q := t.items[slot]; q != nil; q = tl q)		if((hd q).t0 == id)			return 0;	t.items[slot] = (id, x) :: t.items[slot];	return 1;} Table[T].del(t: self ref Table[T], id: int): T{	p: list of (int, T);	slot := id % len t.items;	for(q := t.items[slot]; q != nil; q = tl q){		if((hd q).t0 == id){			t.items[slot] = join(p, tl q);			return (hd q).t1;		}		p = hd q :: p;	}	return t.nilval;} Table[T].find(t: self ref Table[T], id: int): T{	for(p := t.items[id % len t.items]; p != nil; p = tl p)		if((hd p).t0 == id)			return (hd p).t1;	return t.nilval;} join[T](x, y: list of (int, T)): list of (int, T){	for(; x != nil; x = tl x)		y = hd x :: y;	return y;} addtfid(t: int, fid: ref Fid){	lock <-= 1;	tfids.add(t, fid);	<- lock;} deltfid(t: int): ref Fid{	lock <-= 1;	r := tfids.del(t);	<- lock;	return r;} fatal(s: string){	sys->fprint(sys->fildes(2), "trfs: %s: %r\n", s);	raise "fail:error";}