From ad88539715c50f30c4e8fca27338158dc33feaaa Mon Sep 17 00:00:00 2001 From: "Charles.Forsyth" Date: Sat, 14 Jul 2007 09:52:44 +0000 Subject: 20070714-1052 --- appl/cmd/trfs.b | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 appl/cmd/trfs.b (limited to 'appl') diff --git a/appl/cmd/trfs.b b/appl/cmd/trfs.b new file mode 100644 index 00000000..1ccd0639 --- /dev/null +++ b/appl/cmd/trfs.b @@ -0,0 +1,213 @@ +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 + 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; ifprint(sys->fildes(2), "trfs: %s: %r\n", s); + raise "fail:error"; +} -- cgit v1.2.3