diff options
| author | forsyth <forsyth@vitanuova.com> | 2009-12-04 20:41:24 +0000 |
|---|---|---|
| committer | forsyth <forsyth@vitanuova.com> | 2009-12-04 20:41:24 +0000 |
| commit | 54041ca415f1fdfa1c3dcd82d524223cfa890940 (patch) | |
| tree | 61b7d29f9df1ade1b3cb5ad859f53fecead5e356 | |
| parent | 1d6f6b43a0f31b37b3302fc0d627c904c381f3d1 (diff) | |
20091204
| -rw-r--r-- | CHANGES | 6 | ||||
| -rw-r--r-- | appl/charon/build.b | 2 | ||||
| -rw-r--r-- | appl/charon/chutils.b | 13 | ||||
| -rw-r--r-- | appl/charon/chutils.m | 1 | ||||
| -rw-r--r-- | appl/charon/date.b | 2 | ||||
| -rw-r--r-- | appl/charon/gui.b | 6 | ||||
| -rw-r--r-- | appl/charon/img.b | 6 | ||||
| -rw-r--r-- | appl/charon/jscript.b | 2 | ||||
| -rw-r--r-- | appl/charon/layout.b | 14 | ||||
| -rw-r--r-- | appl/cmd/mount.b | 8 | ||||
| -rw-r--r-- | appl/lib/styxconv/mkfile | 6 | ||||
| -rw-r--r-- | appl/lib/styxconv/new2old.b | 640 | ||||
| -rw-r--r-- | appl/lib/styxconv/nsys.m | 51 | ||||
| -rw-r--r-- | appl/lib/styxconv/old2new.b | 480 | ||||
| -rw-r--r-- | appl/lib/styxconv/ostyx.b | 87 | ||||
| -rw-r--r-- | appl/lib/styxconv/ostyx.m | 4 | ||||
| -rw-r--r-- | dis/charon.dis | bin | 27991 -> 27980 bytes | |||
| -rw-r--r-- | dis/charon/build.dis | bin | 38663 -> 38649 bytes | |||
| -rw-r--r-- | dis/charon/chutils.dis | bin | 29634 -> 29555 bytes | |||
| -rw-r--r-- | dis/charon/date.dis | bin | 674 -> 658 bytes | |||
| -rw-r--r-- | dis/charon/file.dis | bin | 1344 -> 1344 bytes | |||
| -rw-r--r-- | dis/charon/ftp.dis | bin | 3907 -> 3907 bytes | |||
| -rw-r--r-- | dis/charon/gui.dis | bin | 9827 -> 9766 bytes | |||
| -rw-r--r-- | dis/charon/http.dis | bin | 12056 -> 12056 bytes | |||
| -rw-r--r-- | dis/charon/img.dis | bin | 62156 -> 62112 bytes | |||
| -rw-r--r-- | dis/charon/jscript.dis | bin | 50995 -> 50983 bytes | |||
| -rw-r--r-- | dis/charon/layout.dis | bin | 67654 -> 67536 bytes | |||
| -rw-r--r-- | dis/charon/lex.dis | bin | 13338 -> 13338 bytes | |||
| -rw-r--r-- | dis/lib/styxconv/new2old.dis | bin | 0 -> 7646 bytes | |||
| -rw-r--r-- | dis/lib/styxconv/old2new.dis | bin | 0 -> 5698 bytes | |||
| -rw-r--r-- | dis/lib/styxconv/ostyx.dis | bin | 13434 -> 13741 bytes | |||
| -rw-r--r-- | dis/mount.dis | bin | 5776 -> 5767 bytes | |||
| -rw-r--r-- | include/version.h | 2 | ||||
| -rw-r--r-- | man/2/styxconv | 56 | ||||
| -rw-r--r-- | module/styxconv.m | 7 | ||||
| -rw-r--r-- | os/pc/fns.h | 4 | ||||
| -rw-r--r-- | os/pc/mmu.c | 6 |
37 files changed, 1310 insertions, 93 deletions
@@ -1,3 +1,9 @@ +20091127 + problems fixed in styxconv(2), which can now convert both ways [rog] +20091119 + emu/port/devfs-posix.c missing waserror in dirread (obscure but possible failure) +20091007 + remove intermediate exception-raising function from charon implementation 20091004 restore "keyring" to lib section of emu/Plan9/emu 20090930 diff --git a/appl/charon/build.b b/appl/charon/build.b index c9b4ab01..b0eef1de 100644 --- a/appl/charon/build.b +++ b/appl/charon/build.b @@ -1620,7 +1620,7 @@ lexstring(s: string) : array of ref Token lastps(psl: list of ref Pstate) : ref Pstate { if(psl == nil) - CU->raisex("EXInternal: empty pstate stack"); + raise "EXInternal: empty pstate stack"; while(tl psl != nil) psl = tl psl; return hd psl; diff --git a/appl/charon/chutils.b b/appl/charon/chutils.b index 40da2f5f..8d8bdf33 100644 --- a/appl/charon/chutils.b +++ b/appl/charon/chutils.b @@ -1227,14 +1227,14 @@ ResourceState.cur() : ResourceState if(mfd == nil) mfd = sys->open("/dev/memory", sys->OREAD); if (mfd == nil) - raisex(sys->sprint("can't open /dev/memory: %r")); + raise sys->sprint("can't open /dev/memory: %r"); sys->seek(mfd, big 0, Sys->SEEKSTART); buf := array[400] of byte; n := sys->read(mfd, buf, len buf); if (n <= 0) - raisex(sys->sprint("can't read /dev/memory: %r")); + raise sys->sprint("can't read /dev/memory: %r"); (nil, l) := sys->tokenize(string buf[0:n], "\n"); # p->cursize, p->maxsize, p->hw, p->nalloc, p->nfree, p->nbrk, poolmax(p), p->name) @@ -1763,7 +1763,7 @@ makestrinttab(a: array of string) : array of T->StringInt ans[i].key = a[i]; ans[i].val = i; if(i > 0 && a[i] < a[i-1]) - raisex("EXInternal: table out of alphabetical order"); + raise "EXInternal: table out of alphabetical order"; } return ans; } @@ -1866,15 +1866,10 @@ min(a,b: int) : int return b; } -raisex(e: string) -{ - raise e; -} - assert(i: int) { if(!i) { - raisex("EXInternal: assertion failed"); + raise "EXInternal: assertion failed"; # sys->print("assertion failed\n"); # s := hmeth[-1]; } diff --git a/appl/charon/chutils.m b/appl/charon/chutils.m index 8d7d3a8c..15c3308f 100644 --- a/appl/charon/chutils.m +++ b/appl/charon/chutils.m @@ -360,7 +360,6 @@ CharonUtils: module color: fn(s: string, dflt: int) : int; max: fn(a, b : int) : int; min: fn(a, b : int) : int; - raisex: fn(e: string); assert: fn(i: int); stripscript: fn(s: string) : string; # strip HTML comments from Script getconv: fn(chset : string) : Btos; diff --git a/appl/charon/date.b b/appl/charon/date.b index b247d578..c801772e 100644 --- a/appl/charon/date.b +++ b/appl/charon/date.b @@ -23,7 +23,7 @@ init(cu: CharonUtils) CU = cu; daytime = load Daytime Daytime->PATH; if (daytime==nil) - CU->raisex(sys->sprint("EXInternal: can't load Daytime: %r")); + raise sys->sprint("EXInternal: can't load Daytime: %r"); } # print dates in the format diff --git a/appl/charon/gui.b b/appl/charon/gui.b index d433bf82..0b4b7f1c 100644 --- a/appl/charon/gui.b +++ b/appl/charon/gui.b @@ -98,7 +98,7 @@ init(ctxt: ref Draw->Context, cu: CharonUtils): ref Draw->Context tk = load Tk Tk->PATH; tkclient = load Tkclient Tkclient->PATH; if(tkclient == nil) - CU->raisex(sys->sprint("EXInternal: can't load module Tkclient: %r")); + raise sys->sprint("EXInternal: can't load module Tkclient: %r"); tkclient->init(); wmctl: chan of string; @@ -386,11 +386,11 @@ makewins() realwin = screen.newwindow(r, D->Refnone, D->White); realwin.origin(ZP, r.min); if(realwin == nil) - CU->raisex(sys->sprint("EXFatal: can't initialize windows: %r")); + raise sys->sprint("EXFatal: can't initialize windows: %r"); mainwin = display.newimage(realwin.r, realwin.chans, 0, D->White); if(mainwin == nil) - CU->raisex(sys->sprint("EXFatal: can't initialize windows: %r")); + raise sys->sprint("EXFatal: can't initialize windows: %r"); } hidewins() diff --git a/appl/charon/img.b b/appl/charon/img.b index fd8b625d..299ddeeb 100644 --- a/appl/charon/img.b +++ b/appl/charon/img.b @@ -161,7 +161,7 @@ imgerror(is: ref ImageSource, msg: string) is.err = msg; if(dbg) sys->print("Image error: %s\n", msg); - CU->raisex("exImageerror:"); + raise "exImageerror:"; } # Get next char or raise exception if cannot @@ -179,7 +179,7 @@ getc(is: ref ImageSource) : int ungetc(is: ref ImageSource) { if(is.i == 0) - CU->raisex("EXInternal: ungetc past beginning of buffer"); + raise "EXInternal: ungetc past beginning of buffer"; is.i--; } @@ -190,7 +190,7 @@ ungetc2(is: ref ImageSource, nil: byte) { if(is.i < 2) { if(is.i != 1) - CU->raisex("EXInternal: ungetc2 past beginning of buffer"); + raise "EXInternal: ungetc2 past beginning of buffer"; is.i = 0; } else diff --git a/appl/charon/jscript.b b/appl/charon/jscript.b index 0742da31..315baf78 100644 --- a/appl/charon/jscript.b +++ b/appl/charon/jscript.b @@ -2107,7 +2107,7 @@ specindex(class: string) : int if(objspecs[i].name == class) break; if(i == len objspecs) - CU->raisex("EXInternal: couldn't find host object class " + class); + raise "EXInternal: couldn't find host object class " + class; return i; } diff --git a/appl/charon/layout.b b/appl/charon/layout.b index ee5c9064..a4ad1c8f 100644 --- a/appl/charon/layout.b +++ b/appl/charon/layout.b @@ -516,7 +516,7 @@ createvscroll(f: ref Frame) f.vscr.r = f.vscr.r.addpt(Point(f.cr.max.x-breadth, f.cr.min.y)); f.cr.max.x -= breadth; if(f.cr.dx() <= 2*f.marginw) - CU->raisex("EXInternal: frame too small for layout"); + raise "EXInternal: frame too small for layout"; f.vscr.draw(1); } @@ -531,7 +531,7 @@ createhscroll(f: ref Frame) f.hscr.r = f.hscr.r.addpt(Point(x,f.cr.max.y-breadth)); f.cr.max.y -= breadth; if(f.cr.dy() <= 2*f.marginh) - CU->raisex("EXInternal: frame too small for layout"); + raise "EXInternal: frame too small for layout"; f.hscr.draw(1); } @@ -985,7 +985,7 @@ fixlinegeom(f: ref Frame, lay: ref Lay, l: ref Line) # line is complete, next line will start with it (or it is nil) rest := it; if(lastit == nil) - CU->raisex("EXInternal: no items on line"); + raise "EXInternal: no items on line"; lastit.next = nil; l.width = w; @@ -1087,7 +1087,7 @@ getfont(num: int) : ref Font f = Font.open(display, fonts[num].name); if(f == nil) { if(num == DefFnt) - CU->raisex(sys->sprint("exLayout: can't open default font %s: %r", fonts[num].name)); + raise sys->sprint("exLayout: can't open default font %s: %r", fonts[num].name); else { if(int (CU->config).dbg['w']) sys->print("warning: substituting default for font %s\n", @@ -2389,7 +2389,7 @@ markchanges(loc: ref Loc) } LEtablecell => if(lastf == nil) - CU->raisex("EXInternal: markchanges no lastf"); + raise "EXInternal: markchanges no lastf"; c := loc.le[i].tcell; clay := lastf.sublays[c.layid]; if(clay != nil) @@ -2424,7 +2424,7 @@ colorimage(rgb: int) : ref Image # im := display.color(pix); im := display.rgb((rgb>>16)&255, (rgb>>8)&255, rgb&255); if(im == nil) - CU->raisex(sys->sprint("exLayout: can't allocate color #%8.8ux: %r", rgb)); + raise sys->sprint("exLayout: can't allocate color #%8.8ux: %r", rgb); x = ref Colornode(rgb, im, xhd); colorhashtab[hv] = x; } @@ -3309,7 +3309,7 @@ Control.scrollset(c: self ref Control, v1, v2, vmax, nsteps, draw: int) if(l <= 0) l = 1; if(l < 0) - CU->raisex("EXInternal: negative scrollbar trough"); + raise "EXInternal: negative scrollbar trough"; sc.top = l*v1/vmax; sc.bot = l*(vmax-v2)/vmax; if (nsteps == 0) diff --git a/appl/cmd/mount.b b/appl/cmd/mount.b index 9eb6e3a9..514db41a 100644 --- a/appl/cmd/mount.b +++ b/appl/cmd/mount.b @@ -215,17 +215,15 @@ runcmd(sh: Sh, ctxt: ref Draw->Context, argv: list of string, stdin: ref Sys->FD cvstyx(fd: ref Sys->FD): (ref Sys->FD, string) { - styxconv := load Styxconv Styxconv->PATH; + styxconv := load Styxconv Styxconv->PATHNEW2OLD; if(styxconv == nil) - return (nil, sys->sprint("cannot load %s: %r", Styxconv->PATH)); + return (nil, sys->sprint("cannot load %s: %r", Styxconv->PATHNEW2OLD)); styxconv->init(); p := array[2] of ref Sys->FD; if(sys->pipe(p) < 0) return (nil, sys->sprint("can't create pipe: %r")); - pidc := chan of int; - spawn styxconv->styxconv(p[1], fd, pidc); + spawn styxconv->styxconv(p[1], fd); p[1] = nil; - <-pidc; return (p[0], nil); } diff --git a/appl/lib/styxconv/mkfile b/appl/lib/styxconv/mkfile index fe4ad61e..02b28bc0 100644 --- a/appl/lib/styxconv/mkfile +++ b/appl/lib/styxconv/mkfile @@ -2,11 +2,13 @@ TARG=\ ostyx.dis\ - styxconv.dis\ - + new2old.dis\ + old2new.dis\ + MODULES=\ ostyx.m\ osys.m\ + nsys.m\ SYSMODULES=\ bufio.m\ diff --git a/appl/lib/styxconv/new2old.b b/appl/lib/styxconv/new2old.b new file mode 100644 index 00000000..36c1e91b --- /dev/null +++ b/appl/lib/styxconv/new2old.b @@ -0,0 +1,640 @@ +implement Styxconv; + +include "sys.m"; + sys: Sys; +include "osys.m"; +include "nsys.m"; +include "draw.m"; +include "styx.m"; + nstyx: Styx; + Tmsg, Rmsg: import nstyx; +include "ostyx.m"; + ostyx: OStyx; + OTmsg, ORmsg: import ostyx; +include "styxconv.m"; + +# todo: map fids > ffff into 16 bits + +DEBUG: con 1; + +Fid: adt +{ + fid: int; + isdir: int; + n: int; # size of last new client dirread request. + soff: int; # dir offset on old server. + coff: int; # dir offset on new client. + next: cyclic ref Fid; +}; + +Req: adt { + tag: int; + oldtag: int; # if it's a flush. + rp: ref Reqproc; + next: cyclic ref Req; + flushes: list of ref Rmsg.Flush; # flushes awaiting req finish. +}; + +Reqproc: adt { + newtmsg: chan of ref Tmsg; # convproc -> reqproc, once per req. + newrmsg: chan of ref Rmsg; # reqproc -> convproc, once per req + + oldtmsg: chan of ref OTmsg; # reqproc -> convproc + oldrmsg: chan of ref ORmsg; # convproc -> reqproc + + flushable: int; + + new: fn(): ref Reqproc; + rpc: fn(rp: self ref Reqproc, otm: ref OTmsg): ref ORmsg; +}; + +tags: ref Req; +avail: chan of ref Reqproc; +fids: ref Fid; +nprocs := 0; + +init() +{ + sys = load Sys Sys->PATH; + if(sys == nil) + nomod("Sys", Sys->PATH); + nstyx = load Styx Styx->PATH; + if(nstyx == nil) + nomod("Styx", Styx->PATH); + ostyx = load OStyx OStyx->PATH; + if(ostyx == nil) + nomod("OStyx", OStyx->PATH); + + ostyx->init(); + nstyx->init(); + avail = chan of ref Reqproc; +} + +styxconv(newclient: ref Sys->FD, oldsrv: ref Sys->FD) +{ + newtmsg := chan of ref Tmsg; + oldrmsg := chan of ref ORmsg; + + killpids := chan[2] of int; + spawn readnewtmsgs(killpids, newclient, newtmsg); + spawn readoldrmsgs(killpids, oldsrv, oldrmsg); + +converting: + for(;;)alt{ + ntm := <-newtmsg => + if(DEBUG) + sys->fprint(sys->fildes(2), "-> %s\n", ntm.text()); + if(ntm == nil) + break converting; + ns2os(ntm, newclient, oldsrv); + orm := <-oldrmsg => + if(DEBUG) + sys->fprint(sys->fildes(2), " <- %s\n", ostyx->rmsg2s(orm)); + if(orm == nil) + break converting; + t := looktag(orm.tag); + if(t == nil){ + warning("reply by old-server to non-existent tag"); + break; + } + pick rm := orm { + Flush => + ot := looktag(t.oldtag); + # if it's an Rflush of a request-in-progress, + # we send it to the reqproc, which + # can then clean up as it likes. + if(ot != nil){ + if(ot.rp != nil){ + if(ot.rp.flushable){ + ot.rp.oldrmsg <-= rm; + # reqproc is bound to finish after a flush + reqreply(ot, newclient, oldsrv); + }else { + # hold flush reply for later + ot.flushes = ref Rmsg.Flush(rm.tag) :: ot.flushes; + } + break; + } + deletetag(t.oldtag); + } + NRsend(newclient, ref Rmsg.Flush(rm.tag)); + deletetag(rm.tag); + * => + if(t.rp != nil){ + t.rp.oldrmsg <-= orm; + reqreply(t, newclient, oldsrv); + }else{ + os2ns(orm, newclient); + deletetag(orm.tag); + } + } + } + # kill off active reqprocs + for(; tags != nil; tags = tags.next){ + if(tags.rp != nil){ + tags.rp.oldrmsg <-= nil; + nprocs--; + } + } + # kill off idle reqprocs + while(nprocs > 0){ + rp := <-avail; + rp.newtmsg <-= nil; + nprocs--; + } + # kill off message readers + kill(<-killpids); + kill(<-killpids); +} + +# process one response from the request proc. +# request proc can respond by sending a new tmsg to the old server +# or by sending an rmsg to the new client, in which case +# it implicitly signals that it has finished processing the request. +# the actual reply might be an Rflush, signifying that +# the request has been aborted. +reqreply(t: ref Req, newclient: ref Sys->FD, oldsrv: ref Sys->FD) +{ + rp := t.rp; + alt{ + nrm := <-rp.newrmsg => + # request is done when process sends rmsg + pick rm := nrm { + Flush => + deletetag(t.tag); + } + deletetag(nrm.tag); + NRsend(newclient, nrm); + for(; t.flushes != nil; t.flushes = tl t.flushes) + NRsend(newclient, hd t.flushes); + + otm := <-rp.oldtmsg => + OTsend(oldsrv, otm); + } +} + + +# T messages: forward on, reply immediately, or start processing. +ns2os(tm0: ref Tmsg, newclient, oldsrv: ref Sys->FD) +{ + otm: ref OTmsg; + + t := ref Req(tm0.tag, -1, nil, nil, nil); + pick tm := tm0{ + Readerror => + exit; + Version => + (s, v) := nstyx->compatible(tm, nstyx->MAXRPC, nil); + NRsend(newclient, ref Rmsg.Version(tm.tag, s, v)); + return; + Auth => + NRsend(newclient, ref Rmsg.Error(tm.tag, "authorization not required")); + return; + Walk => + storetag(t); + t.rp = Reqproc.new(); + t.rp.newtmsg <-= tm; + reqreply(t, newclient, oldsrv); + return; + Attach => + otm = ref OTmsg.Attach(tm.tag, tm.fid, tm.uname, tm.aname); + Flush => + t.oldtag = tm.oldtag; + otm = ref OTmsg.Flush(tm.tag, tm.oldtag); + Open => + otm = ref OTmsg.Open(tm.tag, tm.fid, tm.mode); + Create => + otm = ref OTmsg.Create(tm.tag, tm.fid, tm.perm, tm.mode, tm.name); + Read => + fp := findfid(tm.fid); + count := tm.count; + offset := tm.offset; + if(fp != nil && fp.isdir){ + fp.n = count; + count = (count/OStyx->DIRLEN)*OStyx->DIRLEN; + if(int offset != fp.coff){ + NRsend(newclient, ref Rmsg.Error(tm.tag, "unexpected offset in dirread")); + return; + } + offset = big fp.soff; + } + otm = ref OTmsg.Read(tm.tag, tm.fid, count, offset); + Write => + otm = ref OTmsg.Write(tm.tag, tm.fid, tm.offset, tm.data); + Clunk => + otm = ref OTmsg.Clunk(tm.tag, tm.fid); + Remove => + otm = ref OTmsg.Remove(tm.tag, tm.fid); + Stat => + otm = ref OTmsg.Stat(tm.tag, tm.fid); + Wstat => + otm = ref OTmsg.Wstat(tm.tag, tm.fid, nd2od(tm.stat)); + * => + fatal("bad T message"); + } + storetag(t); + OTsend(oldsrv, otm); +} + +# R messages: old to new +os2ns(orm0: ref ORmsg, newclient: ref Sys->FD) +{ + rm: ref Rmsg; + + rm = nil; + pick orm := orm0 { + Error => + rm = ref Rmsg.Error(orm.tag, orm.err); + Flush => + rm = ref Rmsg.Flush(orm.tag); + Clone => + rm = ref Rmsg.Walk(orm.tag, nil); + Walk => + fatal("walk rmsgs should be dealt with be walkreqproc"); + Open => + setfid(orm.fid, orm.qid); + rm = ref Rmsg.Open(orm.tag, oq2nq(orm.qid), 0); + Create => + setfid(orm.fid, orm.qid); + rm = ref Rmsg.Create(orm.tag, oq2nq(orm.qid), 0); + Read => + fp := findfid(orm.fid); + data := orm.data; + if(fp != nil && fp.isdir) + data = ods2nds(data, fp.n); + fp.coff += len data; + fp.soff += len orm.data; + rm = ref Rmsg.Read(orm.tag, data); + Write => + rm = ref Rmsg.Write(orm.tag, orm.count); + Clunk => + rm = ref Rmsg.Clunk(orm.tag); + deletefid(orm.fid); + Remove => + rm = ref Rmsg.Remove(orm.tag); + deletefid(orm.fid); + Stat => + rm = ref Rmsg.Stat(orm.tag, od2nd(orm.stat)); + Wstat => + rm = ref Rmsg.Wstat(orm.tag); + Attach => + newfid(orm.fid, orm.qid.path & OSys->CHDIR); + rm = ref Rmsg.Attach(orm.tag, oq2nq(orm.qid)); + * => + fatal("bad R message"); + } + NRsend(newclient, rm); +} + +Reqproc.rpc(rp: self ref Reqproc, otm: ref OTmsg): ref ORmsg +{ + rp.oldtmsg <-= otm; + m := <-rp.oldrmsg; + if(m == nil) + exit; + return m; +} + +Reqproc.new(): ref Reqproc +{ + alt{ + rp := <-avail => + return rp; + * => + rp := ref Reqproc( + chan of ref Tmsg, + chan of ref Rmsg, + chan of ref OTmsg, + chan of ref ORmsg, + 1); + spawn reqproc(rp); + nprocs++; + return rp; + } +} + +reqproc(rp: ref Reqproc) +{ + for(;;){ + tm := <-rp.newtmsg; + if(tm == nil) + return; + rm: ref Rmsg; + pick m := tm { + Walk => + rm = walkreq(m, rp); + * => + fatal("non-walk req passed to reqproc"); + } + rp.flushable = 1; + rp.newrmsg <-= rm; + avail <-= rp; + } +} + +# note that although this is in a separate process, +# whenever it's not in Reqproc.rpc, the styxconv +# process is blocked, so although state is shared, +# there are no race conditions. +walkreq(tm: ref Tmsg.Walk, rp: ref Reqproc): ref Rmsg +{ + cloned := 0; + n := len tm.names; + if(tm.newfid != tm.fid){ + cloned = 1; + pick rm := rp.rpc(ref OTmsg.Clone(tm.tag, tm.fid, tm.newfid)) { + Clone => + ; + Error => + return ref Rmsg.Error(tm.tag, rm.err); + Flush => + return ref Rmsg.Flush(rm.tag); + * => + fatal("unexpected reply to OTmsg.Clone"); + } + cloned = 1; + } + qids := array[n] of NSys->Qid; + finalqid: OSys->Qid; + + # make sure we don't get flushed in an unwindable state. + rp.flushable = n == 1 || cloned; + for(i := 0; i < n; i++){ + pick rm := rp.rpc(ref OTmsg.Walk(tm.tag, tm.newfid, tm.names[i])) { + Walk => + qids[i] = oq2nq(rm.qid); + finalqid = rm.qid; + Flush => + if(cloned){ + rp.flushable = 0; + rp.rpc(ref OTmsg.Clunk(tm.tag, tm.newfid)); + } + return ref Rmsg.Flush(rm.tag); + Error => + if(cloned){ + rp.flushable = 0; + rp.rpc(ref OTmsg.Clunk(tm.tag, tm.newfid)); + } + if(i == 0) + return ref Rmsg.Error(tm.tag, rm.err); + return ref Rmsg.Walk(tm.tag, qids[0:i]); + } + } + if(cloned) + clonefid(tm.fid, tm.newfid); + if(n > 0) + setfid(tm.newfid, finalqid); + return ref Rmsg.Walk(tm.tag, qids); +} + +storetag(t: ref Req) +{ + t.next = tags; + tags = t; +} + +looktag(tag: int): ref Req +{ + for(t := tags; t != nil; t = t.next) + if(t.tag == tag) + return t; + return nil; +} + +deletetag(tag: int) +{ + prev: ref Req; + t := tags; + while(t != nil){ + if(t.tag == tag){ + next := t.next; + t.next = nil; + if(prev != nil) + prev.next = next; + else + tags = next; + t = next; + }else{ + prev = t; + t = t.next; + } + } +} + +newfid(fid: int, isdir: int): ref Fid +{ + f := ref Fid; + f.fid = fid; + f.isdir = isdir; + f.n = f.soff = f.coff = 0; + f.next = fids; + fids = f; + return f; +} + +clonefid(ofid: int, fid: int): ref Fid +{ + if((f := findfid(ofid)) != nil){ + nf := newfid(fid, f.isdir); + return nf; + } + warning("clone of non-existent fid"); + return newfid(fid, 0); +} + +deletefid(fid: int) +{ + lf: ref Fid; + + for(f := fids; f != nil; f = f.next){ + if(f.fid == fid){ + if(lf == nil) + fids = f.next; + else + lf.next = f.next; + return; + } + lf = f; + } +} + +findfid(fid: int): ref Fid +{ + for(f := fids; f != nil; f = f.next) + if(f.fid == fid) + return f; + return nil; +} + +setfid(fid: int, qid: OSys->Qid) +{ + f := findfid(fid); + if(f == nil){ + warning(sys->sprint("cannot find fid %d", fid)); + }else{ + f.isdir = qid.path & OSys->CHDIR; + } +} + +om2nm(om: int): int +{ + # DMDIR == CHDIR + return om; +} + +nm2om(m: int): int +{ + # DMDIR == CHDIR + return m&~(NSys->DMAPPEND|NSys->DMEXCL|NSys->DMAUTH); +} + +oq2nq(oq: OSys->Qid): NSys->Qid +{ + q: NSys->Qid; + + isdir := oq.path&OSys->CHDIR; + q.path = big (oq.path&~OSys->CHDIR); + q.vers = oq.vers; + q.qtype = 0; + if(isdir) + q.qtype |= NSys->QTDIR; + return q; +} + +nq2oq(q: NSys->Qid): OSys->Qid +{ + oq: OSys->Qid; + + isdir := q.qtype&NSys->QTDIR; + oq.path = int q.path; + oq.vers = q.vers; + if(isdir) + oq.path |= OSys->CHDIR; + return oq; +} + +od2nd(od: OSys->Dir): NSys->Dir +{ + d: NSys->Dir; + + d.name = od.name; + d.uid = od.uid; + d.gid = od.gid; + d.muid = od.uid; + d.qid = oq2nq(od.qid); + d.mode = om2nm(od.mode); + d.atime = od.atime; + d.mtime = od.mtime; + d.length = big od.length; + d.dtype = od.dtype; + d.dev = od.dev; + return d; +} + +nd2od(d: NSys->Dir): OSys->Dir +{ + od: OSys->Dir; + + od.name = d.name; + od.uid = d.uid; + od.gid = d.gid; + od.qid = nq2oq(d.qid); + od.mode = nm2om(d.mode); + od.atime = d.atime; + od.mtime = d.mtime; + od.length = int d.length; + od.dtype = d.dtype; + od.dev = d.dev; + return od; +} + +ods2nds(ob: array of byte, max: int): array of byte +{ + od: OSys->Dir; + + m := len ob; + if(m % OStyx->DIRLEN != 0) + fatal(sys->sprint("bad dir len %d", m)); + m /= OStyx->DIRLEN; + n := 0; + p := ob; + for(i := 0; i < m; i++){ + (p, od) = ostyx->convM2D(p); + d := od2nd(od); + nn := nstyx->packdirsize(d); + if(n+nn > max) # might just happen with long file names + break; + n += nn; + } + m = i; + b := array[n] of byte; + n = 0; + p = ob; + for(i = 0; i < m; i++){ + (p, od) = ostyx->convM2D(p); + d := od2nd(od); + q := nstyx->packdir(d); + nn := len q; + b[n: ] = q[0: nn]; + n += nn; + } + return b; +} + +OTsend(fd: ref Sys->FD, otm: ref OTmsg): int +{ + if(DEBUG) + sys->fprint(sys->fildes(2), " -> %s\n", ostyx->tmsg2s(otm)); + s := array[OStyx->MAXRPC] of byte; + n := ostyx->tmsg2d(otm, s); + if(n < 0) + return -1; + return sys->write(fd, s, n); +} + +NRsend(fd: ref Sys->FD, rm: ref Rmsg): int +{ + if(DEBUG) + sys->fprint(sys->fildes(2), "<- %s\n", rm.text()); + s := rm.pack(); + if(s == nil) + return -1; + return sys->write(fd, s, len s); +} + +readnewtmsgs(pidc: chan of int, newclient: ref Sys->FD, newtmsg: chan of ref Tmsg) +{ + pidc <-= sys->pctl(0, nil); + for(;;){ + newtmsg <-= Tmsg.read(newclient, nstyx->MAXRPC); + } +} + +readoldrmsgs(pidc: chan of int, oldsrv: ref Sys->FD, oldrmsg: chan of ref ORmsg) +{ + pidc <-= sys->pctl(0, nil); + for(;;){ + oldrmsg <-= ORmsg.read(oldsrv); + } +} + +warning(err: string) +{ + sys->fprint(sys->fildes(2), "warning: %s\n", err); +} + +fatal(err: string) +{ + sys->fprint(sys->fildes(2), "%s\n", err); + exit; +} + +nomod(mod: string, path: string) +{ + fatal(sys->sprint("can't load %s(%s): %r", mod, path)); +} + +kill(pid: int) +{ + sys->fprint(sys->open("#p/"+string pid+"/ctl", Sys->OWRITE), "kill"); +} diff --git a/appl/lib/styxconv/nsys.m b/appl/lib/styxconv/nsys.m new file mode 100644 index 00000000..5fe267ec --- /dev/null +++ b/appl/lib/styxconv/nsys.m @@ -0,0 +1,51 @@ +NSys: module +{ + # Unique file identifier for file objects + Qid: adt + { + path: big; + vers: int; + qtype: int; + }; + + QTDIR: con 16r80; + QTAPPEND: con 16r40; + QTEXCL: con 16r20; + QTAUTH: con 16r08; + QTTMP: con 16r04; + QTFILE: con 0; + + # Return from stat and directory read + Dir: adt + { + name: string; + uid: string; + gid: string; + muid: string; + qid: Qid; + mode: int; + atime: int; + mtime: int; + length: big; + dtype: int; + dev: int; + }; + + # Maximum read which will be completed atomically; + # also the optimum block size + # + ATOMICIO: con 8192; + + OREAD: con 0; + OWRITE: con 1; + ORDWR: con 2; + OTRUNC: con 16; + ORCLOSE: con 64; + OEXCL: con 16r1000; + + DMDIR: con int 1<<31; + DMAPPEND: con int 1<<30; + DMEXCL: con int 1<<29; + DMAUTH: con int 1<<27; + DMTMP: con int 1<<26; +}; diff --git a/appl/lib/styxconv/old2new.b b/appl/lib/styxconv/old2new.b new file mode 100644 index 00000000..a9ced502 --- /dev/null +++ b/appl/lib/styxconv/old2new.b @@ -0,0 +1,480 @@ +implement Styxconv; + +include "sys.m"; + sys: Sys; +include "osys.m"; +include "nsys.m"; +include "draw.m"; +include "styx.m"; + nstyx: Styx; + Tmsg, Rmsg: import nstyx; +include "ostyx.m"; + ostyx: OStyx; + OTmsg, ORmsg: import ostyx; +include "styxconv.m"; + +DEBUG: con 0; + +# convert from old styx client to new styx server. +# more straightforward than the other way around +# because there's an almost exactly 1-1 mapping +# between message types. (the exception is Tversion, +# but we do that synchronously anyway). + +# todo: map qids > ffffffff into 32 bits. + +Msize: con nstyx->IOHDRSZ + OSys->ATOMICIO; +Fid: adt +{ + fid: int; + isdir: int; + n: int; # size of last new client dirread request. + soff: int; # dir offset on new server. + coff: int; # dir offset on old client. + next: cyclic ref Fid; + extras: array of byte; # packed old styx dir structures +}; + +Req: adt { + tag: int; + fid: int; + oldtag: int; # if it's a flush. + newfid: int; # if it's a clone + next: cyclic ref Req; +}; + +tags: ref Req; +fids: ref Fid; + +init() +{ + sys = load Sys Sys->PATH; + if(sys == nil) + nomod("Sys", Sys->PATH); + nstyx = load Styx Styx->PATH; + if(nstyx == nil) + nomod("Styx", Styx->PATH); + ostyx = load OStyx OStyx->PATH; + if(ostyx == nil) + nomod("OStyx", OStyx->PATH); + + ostyx->init(); + nstyx->init(); +} + +styxconv(oldclient, newsrv: ref Sys->FD) +{ + oldtmsg := chan of ref OTmsg; + newrmsg := chan of ref Rmsg; + + killpids := chan[2] of int; + spawn readoldtmsgs(killpids, oldclient, oldtmsg); + spawn readnewrmsgs(killpids, newsrv, newrmsg); + # XXX difficulty: what happens if the server isn't responding + # and the client hangs up? we won't know about it. + # but we don't want to know about normal t-messages + # piling up either, so we don't want to alt on oldtmsg too. + NTsend(newsrv, ref Tmsg.Version(nstyx->NOTAG, Msize, "9P2000")); + pick nrm := <-newrmsg { + Version => + if(DEBUG) + sys->fprint(sys->fildes(2), " <- %s\n", nrm.text()); + if(nrm.msize < Msize) + fatal("message size too small"); + Error => + fatal("versioning failed: " + nrm.ename); + * => + fatal("bad response to Tversion: " + nrm.text()); + } + +converting: + for(;;)alt{ + otm := <-oldtmsg => + if(DEBUG) + sys->fprint(sys->fildes(2), "-> %s\n", ostyx->tmsg2s(otm)); + if(otm == nil || tagof(otm) == tagof(OTmsg.Readerror)) + break converting; + oc2ns(otm, oldclient, newsrv); + nrm := <-newrmsg => + if(DEBUG) + sys->fprint(sys->fildes(2), " <- %s\n", nrm.text()); + if(nrm == nil || tagof(nrm) == tagof(Rmsg.Readerror)) + break converting; + t := looktag(nrm.tag); + if(t == nil){ + warning("reply by new-server to non-existent tag"); + break; + } + ns2oc(t, nrm, oldclient); + deletetag(nrm.tag); + } + + kill(<-killpids); + kill(<-killpids); +} + +# T messages: forward on or reply immediately +oc2ns(tm0: ref OTmsg, oldclient, newsrv: ref Sys->FD) +{ + ntm: ref Tmsg; + + t := ref Req(tm0.tag, -1, -1, -1, nil); + pick tm := tm0{ + Nop => + ORsend(oldclient, ref ORmsg.Nop(tm.tag)); + return; + Attach => + t.fid = tm.fid; + ntm = ref Tmsg.Attach(tm.tag, tm.fid, nstyx->NOFID, tm.uname, tm.aname); + Clone => + t.fid = tm.fid; + t.newfid = tm.newfid; + ntm = ref Tmsg.Walk(tm.tag, tm.fid, tm.newfid, nil); + Walk => + t.fid = tm.fid; + ntm = ref Tmsg.Walk(tm.tag, tm.fid, tm.fid, array[] of {tm.name}); + Flush => + t.oldtag = tm.oldtag; + ntm = ref Tmsg.Flush(tm.tag, tm.oldtag); + Open => + t.fid = tm.fid; + ntm = ref Tmsg.Open(tm.tag, tm.fid, tm.mode); + Create => + t.fid = tm.fid; + ntm = ref Tmsg.Create(tm.tag, tm.fid, tm.name, tm.perm, tm.mode); + Read => + t.fid = tm.fid; + fp := findfid(tm.fid); + count := tm.count; + offset := tm.offset; + if(fp.isdir){ + count = (count/OStyx->DIRLEN)*OStyx->DIRLEN; + # if we got some extra entries last time, + # then send 'em back this time. + extras := fp.extras; + if(len extras > 0){ + if(count > len extras) + count = len extras; + ORsend(oldclient, ref ORmsg.Read(tm.tag, t.fid, fp.extras[0:count])); + fp.extras = extras[count:]; + fp.coff += count; + return; + } + fp.n = count; + if(int offset != fp.coff){ + ORsend(oldclient, ref ORmsg.Error(tm.tag, "unexpected offset in dirread")); + return; + } + offset = big fp.soff; + } + ntm = ref Tmsg.Read(tm.tag, tm.fid, offset, count); + Write => + t.fid = tm.fid; + ntm = ref Tmsg.Write(tm.tag, tm.fid, tm.offset, tm.data); + Clunk => + t.fid = tm.fid; + ntm = ref Tmsg.Clunk(tm.tag, tm.fid); + Remove => + t.fid = tm.fid; + ntm = ref Tmsg.Remove(tm.tag, tm.fid); + Stat => + t.fid = tm.fid; + ntm = ref Tmsg.Stat(tm.tag, tm.fid); + Wstat => + t.fid = tm.fid; + ntm = ref Tmsg.Wstat(tm.tag, tm.fid, od2nd(tm.stat)); + * => + fatal("bad T message"); + } + storetag(t); + NTsend(newsrv, ntm); +} + +# R messages: new to old +ns2oc(t: ref Req, nrm0: ref Rmsg, oldclient: ref Sys->FD) +{ + rm: ref ORmsg; + pick nrm := nrm0{ + Error => + rm = ref ORmsg.Error(nrm.tag, nrm.ename); + Flush => + rm = ref ORmsg.Flush(nrm.tag); + deletetag(t.oldtag); + Walk => + if(len nrm.qids == 0){ + clonefid(t.fid, t.newfid); + rm = ref ORmsg.Clone(nrm.tag, t.fid); + }else{ + q := nrm.qids[0]; + setfid(t.fid, q); + rm = ref ORmsg.Walk(nrm.tag, t.fid, nq2oq(q)); + } + Open => + setfid(t.fid, nrm.qid); + rm = ref ORmsg.Open(nrm.tag, t.fid, nq2oq(nrm.qid)); + Create => + setfid(t.fid, nrm.qid); + rm = ref ORmsg.Create(nrm.tag, t.fid, nq2oq(nrm.qid)); + Read => + fp := findfid(t.fid); + data := nrm.data; + if(fp != nil && fp.isdir){ + data = nds2ods(data); + if(len data > fp.n){ + fp.extras = data[fp.n:]; + data = data[0:fp.n]; + } + fp.coff += len data; + fp.soff += len nrm.data; + } + rm = ref ORmsg.Read(nrm.tag, t.fid, data); + Write => + rm = ref ORmsg.Write(nrm.tag, t.fid, nrm.count); + Clunk => + deletefid(t.fid); + rm = ref ORmsg.Clunk(nrm.tag, t.fid); + Remove => + deletefid(t.fid); + rm = ref ORmsg.Remove(nrm.tag, t.fid); + Stat => + rm = ref ORmsg.Stat(nrm.tag, t.fid, nd2od(nrm.stat)); + Wstat => + rm = ref ORmsg.Wstat(nrm.tag, t.fid); + Attach => + newfid(t.fid, nrm.qid.qtype & NSys->QTDIR); + rm = ref ORmsg.Attach(nrm.tag, t.fid, nq2oq(nrm.qid)); + * => + fatal("bad R message"); + } + ORsend(oldclient, rm); +} + +storetag(t: ref Req) +{ + t.next = tags; + tags = t; +} + +looktag(tag: int): ref Req +{ + for(t := tags; t != nil; t = t.next) + if(t.tag == tag) + return t; + return nil; +} + +deletetag(tag: int) +{ + prev: ref Req; + t := tags; + while(t != nil){ + if(t.tag == tag){ + next := t.next; + t.next = nil; + if(prev != nil) + prev.next = next; + else + tags = next; + t = next; + }else{ + prev = t; + t = t.next; + } + } +} + +newfid(fid: int, isdir: int): ref Fid +{ + f := ref Fid; + f.fid = fid; + f.isdir = isdir; + f.n = f.soff = f.coff = 0; + f.next = fids; + fids = f; + return f; +} + +clonefid(ofid: int, fid: int): ref Fid +{ + if((f := findfid(ofid)) != nil) + return newfid(fid, f.isdir); + warning("clone of non-existent fid"); + return newfid(fid, 0); +} + +deletefid(fid: int) +{ + lf: ref Fid; + + for(f := fids; f != nil; f = f.next){ + if(f.fid == fid){ + if(lf == nil) + fids = f.next; + else + lf.next = f.next; + return; + } + lf = f; + } +} + +findfid(fid: int): ref Fid +{ + for(f := fids; f != nil && f.fid != fid; f = f.next) + ; + return f; +} + +setfid(fid: int, qid: NSys->Qid) +{ + if((f := findfid(fid)) != nil) + f.isdir = qid.qtype & NSys->QTDIR; +} + +om2nm(om: int): int +{ + # DMDIR == CHDIR + return om; +} + +nm2om(m: int): int +{ + # DMDIR == CHDIR + return m&~(NSys->DMAPPEND|NSys->DMEXCL|NSys->DMAUTH); +} + +oq2nq(oq: OSys->Qid): NSys->Qid +{ + q: NSys->Qid; + + isdir := oq.path&OSys->CHDIR; + q.path = big (oq.path&~OSys->CHDIR); + q.vers = oq.vers; + q.qtype = 0; + if(isdir) + q.qtype |= NSys->QTDIR; + return q; +} + +nq2oq(q: NSys->Qid): OSys->Qid +{ + oq: OSys->Qid; + + isdir := q.qtype&NSys->QTDIR; + oq.path = int q.path; + oq.vers = q.vers; + if(isdir) + oq.path |= OSys->CHDIR; + return oq; +} + +od2nd(od: OSys->Dir): NSys->Dir +{ + d: NSys->Dir; + + d.name = od.name; + d.uid = od.uid; + d.gid = od.gid; + d.muid = od.uid; + d.qid = oq2nq(od.qid); + d.mode = om2nm(od.mode); + d.atime = od.atime; + d.mtime = od.mtime; + d.length = big od.length; + d.dtype = od.dtype; + d.dev = od.dev; + return d; +} + +nd2od(d: NSys->Dir): OSys->Dir +{ + od: OSys->Dir; + + od.name = d.name; + od.uid = d.uid; + od.gid = d.gid; + od.qid = nq2oq(d.qid); + od.mode = nm2om(d.mode); + od.atime = d.atime; + od.mtime = d.mtime; + od.length = int d.length; + od.dtype = d.dtype; + od.dev = d.dev; + return od; +} + +nds2ods(ob: array of byte): array of byte +{ + i := 0; + n := 0; + ds: list of NSys->Dir; + while(i < len ob){ + (size, d) := nstyx->unpackdir(ob[i:]); + if(size == 0) + break; + ds = d :: ds; + i += size; + n++; + } + b := array[OStyx->DIRLEN * n] of byte; + for(i = (n - 1) * OStyx->DIRLEN; i >= 0; i -= OStyx->DIRLEN){ + ostyx->convD2M(b[i:], nd2od(hd ds)); + ds = tl ds; + } + return b; +} + +NTsend(fd: ref Sys->FD, ntm: ref Tmsg) +{ + if(DEBUG) + sys->fprint(sys->fildes(2), " -> %s\n", ntm.text()); + s := ntm.pack(); + sys->write(fd, s, len s); +} + +ORsend(fd: ref Sys->FD, orm: ref ORmsg) +{ + if(DEBUG) + sys->fprint(sys->fildes(2), "<- %s\n", ostyx->rmsg2s(orm)); + s := array[OStyx->MAXRPC] of byte; + n := ostyx->rmsg2d(orm, s); + if(n > 0) + sys->write(fd, s, n); +} + +readoldtmsgs(pidc: chan of int, oldclient: ref Sys->FD, oldtmsg: chan of ref OTmsg) +{ + pidc <-= sys->pctl(0, nil); + for(;;){ + oldtmsg <-= OTmsg.read(oldclient); + } +} + +readnewrmsgs(pidc: chan of int, newsrv: ref Sys->FD, newrmsg: chan of ref Rmsg) +{ + pidc <-= sys->pctl(0, nil); + for(;;){ + newrmsg <-= Rmsg.read(newsrv, Msize); + } +} + +warning(err: string) +{ + sys->fprint(sys->fildes(2), "warning: %s\n", err); +} + +fatal(err: string) +{ + sys->fprint(sys->fildes(2), "%s\n", err); + exit; +} + +nomod(mod: string, path: string) +{ + fatal(sys->sprint("can't load %s(%s): %r", mod, path)); +} + +kill(pid: int) +{ + sys->fprint(sys->open("#p/"+string pid+"/ctl", Sys->OWRITE), "kill"); +} diff --git a/appl/lib/styxconv/ostyx.b b/appl/lib/styxconv/ostyx.b index ce8e0d9e..b575a0cb 100644 --- a/appl/lib/styxconv/ostyx.b +++ b/appl/lib/styxconv/ostyx.b @@ -13,43 +13,81 @@ DEBUG: con 0; CHANHASHSIZE: con 32; +init() +{ + sys = load Sys Sys->PATH; + gsofar = 0; + gdata = array[MAXRPC] of {* => byte 0}; +} + +# note that this implementation fails if we're reading OTmsgs and ORmsgs +# concurrently. luckily we don't need to in styxconv. gsofar: int; gdata: array of byte; -ORmsg.read(fd: ref Sys->FD, msize: int): ref ORmsg +ORmsg.read(fd: ref Sys->FD): ref ORmsg { - if(sys == nil) - sys = load Sys Sys->PATH; - if(gdata == nil){ - gsofar = 0; - gdata = array[msize] of byte; - } + mlen := 0; + m: ref ORmsg; for (;;){ - n := sys->read(fd, gdata[gsofar:], len gdata - gsofar); - if(n <= 0){ - m: ref ORmsg = nil; - - if(n < 0) - m = ref ORmsg.Error(-1, sys->sprint("%r")); + if(gsofar > 0) + (mlen, m) = d2rmsg(gdata[0 : gsofar]); + if(mlen == 0){ + if(gsofar == len gdata){ + ndata := array[MAXRPC] of byte; + ndata[0:] = gdata; + gdata = ndata; + } + n := sys->read(fd, gdata[gsofar:], len gdata - gsofar); + if(n <= 0) + return nil; + gsofar += n; + }else if(mlen > 0){ + if(tagof(m) == tagof(OTmsg.Write)) { + ndata := array[MAXRPC] of byte; + ndata[0:] = gdata[mlen : gsofar]; + gdata = ndata; + }else + gdata[0:] = gdata[mlen : gsofar]; + gsofar -= mlen; return m; - } - gsofar += n; - (cn, m) := d2rmsg(gdata[0: gsofar]); - if(cn == -1) + }else gsofar = 0; - else if(cn > 0){ - if(tagof(m) == tagof(ORmsg.Read)) { - ndata := array[msize] of byte; - ndata[0: ] = gdata[cn: gsofar]; + } +} + +OTmsg.read(fd: ref Sys->FD): ref OTmsg +{ + mlen := 0; + m: ref OTmsg; + for (;;){ + if(gsofar > 0) + (mlen, m) = d2tmsg(gdata[0 : gsofar]); + if(mlen == 0){ + if(gsofar == len gdata){ + ndata := array[MAXRPC] of byte; + ndata[0:] = gdata; + gdata = ndata; + } + n := sys->read(fd, gdata[gsofar:], len gdata - gsofar); + if(n <= 0) + return nil; + gsofar += n; + }else if(mlen > 0){ + if(tagof(m) == tagof(OTmsg.Write)) { + ndata := array[MAXRPC] of byte; + ndata[0:] = gdata[mlen : gsofar]; gdata = ndata; }else - gdata[0: ] = gdata[cn: gsofar]; - gsofar -= cn; + gdata[0:] = gdata[mlen : gsofar]; + gsofar -= mlen; return m; - } + }else + gsofar = 0; } } + Styxserver.new(fd: ref Sys->FD): (chan of ref OTmsg, ref Styxserver) { if (sys == nil) @@ -572,7 +610,6 @@ pstring(a: array of byte, s: string, n: int): array of byte # convert from Dir to bytes convD2M(d: array of byte, f: OSys->Dir): array of byte { - n := len d; d = pstring(d, f.name, OSys->NAMELEN); d = pstring(d, f.uid, OSys->NAMELEN); d = pstring(d, f.gid, OSys->NAMELEN); diff --git a/appl/lib/styxconv/ostyx.m b/appl/lib/styxconv/ostyx.m index de99d65a..82d94d15 100644 --- a/appl/lib/styxconv/ostyx.m +++ b/appl/lib/styxconv/ostyx.m @@ -24,6 +24,7 @@ OStyx: module devclone: fn(srv: self ref Styxserver, m: ref OTmsg.Clone): ref Chan; }; + init: fn(); d2tmsg: fn(d: array of byte): (int, ref OTmsg); d2rmsg: fn(d: array of byte): (int, ref ORmsg); tmsg2d: fn(gm: ref OTmsg, d: array of byte): int; @@ -69,6 +70,7 @@ OStyx: module fid: int; uname, aname: string; } + read: fn(fd: ref Sys->FD): ref OTmsg; }; ORmsg: adt { @@ -99,7 +101,7 @@ OStyx: module stat: OSys->Dir; } - read: fn(fd: ref Sys->FD, msize: int): ref ORmsg; + read: fn(fd: ref Sys->FD): ref ORmsg; }; MAXRPC: con 128 + OSys->ATOMICIO; diff --git a/dis/charon.dis b/dis/charon.dis Binary files differindex f87c7aac..34054b67 100644 --- a/dis/charon.dis +++ b/dis/charon.dis diff --git a/dis/charon/build.dis b/dis/charon/build.dis Binary files differindex 658df708..43daa9f0 100644 --- a/dis/charon/build.dis +++ b/dis/charon/build.dis diff --git a/dis/charon/chutils.dis b/dis/charon/chutils.dis Binary files differindex c2c52e12..bd4c9cbb 100644 --- a/dis/charon/chutils.dis +++ b/dis/charon/chutils.dis diff --git a/dis/charon/date.dis b/dis/charon/date.dis Binary files differindex faa821df..3efd693e 100644 --- a/dis/charon/date.dis +++ b/dis/charon/date.dis diff --git a/dis/charon/file.dis b/dis/charon/file.dis Binary files differindex ae21e915..0f329d9a 100644 --- a/dis/charon/file.dis +++ b/dis/charon/file.dis diff --git a/dis/charon/ftp.dis b/dis/charon/ftp.dis Binary files differindex 1be3f503..1b2752d5 100644 --- a/dis/charon/ftp.dis +++ b/dis/charon/ftp.dis diff --git a/dis/charon/gui.dis b/dis/charon/gui.dis Binary files differindex ff44d1a0..503b19a1 100644 --- a/dis/charon/gui.dis +++ b/dis/charon/gui.dis diff --git a/dis/charon/http.dis b/dis/charon/http.dis Binary files differindex 28acaba0..0f09c160 100644 --- a/dis/charon/http.dis +++ b/dis/charon/http.dis diff --git a/dis/charon/img.dis b/dis/charon/img.dis Binary files differindex dfb65e7f..18e7f594 100644 --- a/dis/charon/img.dis +++ b/dis/charon/img.dis diff --git a/dis/charon/jscript.dis b/dis/charon/jscript.dis Binary files differindex 20f9696f..98a95c49 100644 --- a/dis/charon/jscript.dis +++ b/dis/charon/jscript.dis diff --git a/dis/charon/layout.dis b/dis/charon/layout.dis Binary files differindex 72b8fafa..cecb0fa7 100644 --- a/dis/charon/layout.dis +++ b/dis/charon/layout.dis diff --git a/dis/charon/lex.dis b/dis/charon/lex.dis Binary files differindex a7c38467..9c382756 100644 --- a/dis/charon/lex.dis +++ b/dis/charon/lex.dis diff --git a/dis/lib/styxconv/new2old.dis b/dis/lib/styxconv/new2old.dis Binary files differnew file mode 100644 index 00000000..35938c13 --- /dev/null +++ b/dis/lib/styxconv/new2old.dis diff --git a/dis/lib/styxconv/old2new.dis b/dis/lib/styxconv/old2new.dis Binary files differnew file mode 100644 index 00000000..c3cd1378 --- /dev/null +++ b/dis/lib/styxconv/old2new.dis diff --git a/dis/lib/styxconv/ostyx.dis b/dis/lib/styxconv/ostyx.dis Binary files differindex 61c961d9..c52aed56 100644 --- a/dis/lib/styxconv/ostyx.dis +++ b/dis/lib/styxconv/ostyx.dis diff --git a/dis/mount.dis b/dis/mount.dis Binary files differindex 21837f16..35463f5f 100644 --- a/dis/mount.dis +++ b/dis/mount.dis diff --git a/include/version.h b/include/version.h index ffe114f4..b83da283 100644 --- a/include/version.h +++ b/include/version.h @@ -1 +1 @@ -#define VERSION "Fourth Edition (20091119)" +#define VERSION "Fourth Edition (20091127)" diff --git a/man/2/styxconv b/man/2/styxconv index f18c48a6..9180ad96 100644 --- a/man/2/styxconv +++ b/man/2/styxconv @@ -4,10 +4,11 @@ styxconv \- convert between old and new Styx .SH SYNOPSIS .EX include "styxconv.m"; -styxconv := load Styxconv Styxconv->PATH; +styxconv := load Styxconv Styxconv->PATHNEW2OLD; +styxconv := load Styxconv Styxconv->PATHOLD2NEW; init: fn(); -styxconv: fn(to: ref Sys->FD, from: ref Sys->FD, pid: chan of int); +styxconv: fn(client: ref Sys->FD, server: ref Sys->FD); .EE .SH DESCRIPTION .B Styxconv @@ -22,49 +23,46 @@ must be called before any other function in the module. .PP The function .B styxconv -takes two file descriptors. -.I From -must be a connection to a file server that serves the original, older -version of Styx. -.I To -is a connection, perhaps a pipe, to something that requires the current protocol; -.B Sys->mount -for instance -(see -.IR sys-bind (2)). +takes two file descriptors: +.I client +should be a connection to a styx client requiring +one version of the protocol; +.I server +should be a connection to a styx server serving +the other version of the protocol. +There are two conversion modules: +.B PATHNEW2OLD +converts from a new client to an old server; +.B PATHOLD2NEW +converts from an old client to a new server. +.PP .B Styxconv -is spawned by the caller, to create a process that copies messages between -.I from +should be spawned by the caller, and copies messages between +.I client and -.IR to , -converting as required as it goes. -Its process ID is the only message sent on -channel -.IR pidc ; -it must be received by -.BR styxconv 's -caller. +.IR server , +converting as required. See the example below. .SH EXAMPLE Apply .B styxconv to file descriptor -.I fd -connected to an old Styx server: +.IR fd , +connected to an old Styx server, and return +a file descriptor suitable for mounting with +.IR mount (2). .IP .EX cvstyx(fd: ref Sys->FD): ref Sys->FD { - styxconv := load Styxconv Styxconv->PATH; + styxconv := load Styxconv Styxconv->NEW2OLDPATH; if(styxconv == nil) return nil; p := array[2] of ref Sys->FD; if(sys->pipe(p) < 0) return nil; styxconv->init(); - pidc := chan of int; - spawn styxconv->styxconv(p[1], fd, pidc); - <-pidc; + spawn styxconv->styxconv(p[1], fd); return p[0]; } .EE @@ -75,3 +73,5 @@ cvstyx(fd: ref Sys->FD): ref Sys->FD .IR sys-bind (2), .IR sys-pipe (2), .IR intro (5) +.SH BUGS +There is no provision for 9p2000 authentication. diff --git a/module/styxconv.m b/module/styxconv.m index 2752d3c6..81f1e210 100644 --- a/module/styxconv.m +++ b/module/styxconv.m @@ -1,9 +1,10 @@ Styxconv: module { - PATH: con "/dis/lib/styxconv/styxconv.dis"; - + PATHOLD2NEW: con "/dis/lib/styxconv/old2new.dis"; + PATHNEW2OLD: con "/dis/lib/styxconv/new2old.dis"; + # call first init: fn(); # spawn and synchronize - styxconv: fn(in: ref Sys->FD, out: ref Sys->FD, sync: chan of int); + styxconv: fn(client: ref Sys->FD, server: ref Sys->FD); }; diff --git a/os/pc/fns.h b/os/pc/fns.h index de8cfbe1..10a5f098 100644 --- a/os/pc/fns.h +++ b/os/pc/fns.h @@ -133,12 +133,12 @@ ulong rdtsc32(void); void screeninit(void); int screenprint(char*, ...); /* debugging */ void (*screenputs)(char*, int); -#define segflush(a,n) +int segflush(void*, ulong); void syncclock(void); uvlong tscticks(uvlong*); void trapenable(int, void (*)(Ureg*, void*), void*, char*); void trapinit(void); -ulong _tas(ulong*); +int _tas(int*); ulong umbmalloc(ulong, int, int); void umbfree(ulong, int); ulong umbrwmalloc(ulong, int, int); diff --git a/os/pc/mmu.c b/os/pc/mmu.c index 6a9e8089..da86517d 100644 --- a/os/pc/mmu.c +++ b/os/pc/mmu.c @@ -335,3 +335,9 @@ vunmap(void *va, int size) if(va != nil) upafree(PADDR(va), size); } + +int +segflush(void*, ulong) +{ + return 0; +} |
