Unified · Split
| @@ -1,3 +1,9 @@ | |||
| 1 | 20091127 | ||
| 2 | problems fixed in styxconv(2), which can now convert both ways [rog] | ||
| 3 | 20091119 | ||
| 4 | emu/port/devfs-posix.c missing waserror in dirread (obscure but possible failure) | ||
| 5 | 20091007 | ||
| 6 | remove intermediate exception-raising function from charon implementation | ||
| 1 | 20091004 | 7 | 20091004 |
| 2 | restore "keyring" to lib section of emu/Plan9/emu | 8 | restore "keyring" to lib section of emu/Plan9/emu |
| 3 | 20090930 | 9 | 20090930 |
| @@ -1620,7 +1620,7 @@ lexstring(s: string) : array of ref Token · 1619 unmodified lines | |||
| 1620 | lastps(psl: list of ref Pstate) : ref Pstate | 1620 | lastps(psl: list of ref Pstate) : ref Pstate |
| 1621 | { | 1621 | { |
| 1622 | if(psl == nil) | 1622 | if(psl == nil) |
| 1623 | CU->raisex("EXInternal: empty pstate stack"); | 1623 | raise "EXInternal: empty pstate stack"; |
| 1624 | while(tl psl != nil) | 1624 | while(tl psl != nil) |
| 1625 | psl = tl psl; | 1625 | psl = tl psl; |
| 1626 | return hd psl; | 1626 | return hd psl; |
| @@ -1227,14 +1227,14 @@ ResourceState.cur() : ResourceState · 1226 unmodified lines | |||
| 1227 | if(mfd == nil) | 1227 | if(mfd == nil) |
| 1228 | mfd = sys->open("/dev/memory", sys->OREAD); | 1228 | mfd = sys->open("/dev/memory", sys->OREAD); |
| 1229 | if (mfd == nil) | 1229 | if (mfd == nil) |
| 1230 | raisex(sys->sprint("can't open /dev/memory: %r")); | 1230 | raise sys->sprint("can't open /dev/memory: %r"); |
| 1231 | 1231 | ||
| 1232 | sys->seek(mfd, big 0, Sys->SEEKSTART); | 1232 | sys->seek(mfd, big 0, Sys->SEEKSTART); |
| 1233 | 1233 | ||
| 1234 | buf := array[400] of byte; | 1234 | buf := array[400] of byte; |
| 1235 | n := sys->read(mfd, buf, len buf); | 1235 | n := sys->read(mfd, buf, len buf); |
| 1236 | if (n <= 0) | 1236 | if (n <= 0) |
| 1237 | raisex(sys->sprint("can't read /dev/memory: %r")); | 1237 | raise sys->sprint("can't read /dev/memory: %r"); |
| 1238 | 1238 | ||
| 1239 | (nil, l) := sys->tokenize(string buf[0:n], "\n"); | 1239 | (nil, l) := sys->tokenize(string buf[0:n], "\n"); |
| 1240 | # p->cursize, p->maxsize, p->hw, p->nalloc, p->nfree, p->nbrk, poolmax(p), p->name) | 1240 | # 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 · 522 unmodified lines | |||
| 1763 | ans[i].key = a[i]; | 1763 | ans[i].key = a[i]; |
| 1764 | ans[i].val = i; | 1764 | ans[i].val = i; |
| 1765 | if(i > 0 && a[i] < a[i-1]) | 1765 | if(i > 0 && a[i] < a[i-1]) |
| 1766 | raisex("EXInternal: table out of alphabetical order"); | 1766 | raise "EXInternal: table out of alphabetical order"; |
| 1767 | } | 1767 | } |
| 1768 | return ans; | 1768 | return ans; |
| 1769 | } | 1769 | } |
| @@ -1866,15 +1866,10 @@ min(a,b: int) : int · 96 unmodified lines | |||
| 1866 | return b; | 1866 | return b; |
| 1867 | } | 1867 | } |
| 1868 | 1868 | ||
| 1869 | raisex(e: string) | ||
| 1870 | { | ||
| 1871 | raise e; | ||
| 1872 | } | ||
| 1873 | |||
| 1874 | assert(i: int) | 1869 | assert(i: int) |
| 1875 | { | 1870 | { |
| 1876 | if(!i) { | 1871 | if(!i) { |
| 1877 | raisex("EXInternal: assertion failed"); | 1872 | raise "EXInternal: assertion failed"; |
| 1878 | # sys->print("assertion failed\n"); | 1873 | # sys->print("assertion failed\n"); |
| 1879 | # s := hmeth[-1]; | 1874 | # s := hmeth[-1]; |
| 1880 | } | 1875 | } |
| @@ -360,7 +360,6 @@ CharonUtils: module · 359 unmodified lines | |||
| 360 | color: fn(s: string, dflt: int) : int; | 360 | color: fn(s: string, dflt: int) : int; |
| 361 | max: fn(a, b : int) : int; | 361 | max: fn(a, b : int) : int; |
| 362 | min: fn(a, b : int) : int; | 362 | min: fn(a, b : int) : int; |
| 363 | raisex: fn(e: string); | ||
| 364 | assert: fn(i: int); | 363 | assert: fn(i: int); |
| 365 | stripscript: fn(s: string) : string; # strip HTML comments from Script | 364 | stripscript: fn(s: string) : string; # strip HTML comments from Script |
| 366 | getconv: fn(chset : string) : Btos; | 365 | getconv: fn(chset : string) : Btos; |
| @@ -23,7 +23,7 @@ init(cu: CharonUtils) · 22 unmodified lines | |||
| 23 | CU = cu; | 23 | CU = cu; |
| 24 | daytime = load Daytime Daytime->PATH; | 24 | daytime = load Daytime Daytime->PATH; |
| 25 | if (daytime==nil) | 25 | if (daytime==nil) |
| 26 | CU->raisex(sys->sprint("EXInternal: can't load Daytime: %r")); | 26 | raise sys->sprint("EXInternal: can't load Daytime: %r"); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | # print dates in the format | 29 | # print dates in the format |
| @@ -98,7 +98,7 @@ init(ctxt: ref Draw->Context, cu: CharonUtils): ref Draw->Context · 97 unmodified lines | |||
| 98 | tk = load Tk Tk->PATH; | 98 | tk = load Tk Tk->PATH; |
| 99 | tkclient = load Tkclient Tkclient->PATH; | 99 | tkclient = load Tkclient Tkclient->PATH; |
| 100 | if(tkclient == nil) | 100 | if(tkclient == nil) |
| 101 | CU->raisex(sys->sprint("EXInternal: can't load module Tkclient: %r")); | 101 | raise sys->sprint("EXInternal: can't load module Tkclient: %r"); |
| 102 | tkclient->init(); | 102 | tkclient->init(); |
| 103 | 103 | ||
| 104 | wmctl: chan of string; | 104 | wmctl: chan of string; |
| @@ -386,11 +386,11 @@ makewins() · 281 unmodified lines | |||
| 386 | realwin = screen.newwindow(r, D->Refnone, D->White); | 386 | realwin = screen.newwindow(r, D->Refnone, D->White); |
| 387 | realwin.origin(ZP, r.min); | 387 | realwin.origin(ZP, r.min); |
| 388 | if(realwin == nil) | 388 | if(realwin == nil) |
| 389 | CU->raisex(sys->sprint("EXFatal: can't initialize windows: %r")); | 389 | raise sys->sprint("EXFatal: can't initialize windows: %r"); |
| 390 | 390 | ||
| 391 | mainwin = display.newimage(realwin.r, realwin.chans, 0, D->White); | 391 | mainwin = display.newimage(realwin.r, realwin.chans, 0, D->White); |
| 392 | if(mainwin == nil) | 392 | if(mainwin == nil) |
| 393 | CU->raisex(sys->sprint("EXFatal: can't initialize windows: %r")); | 393 | raise sys->sprint("EXFatal: can't initialize windows: %r"); |
| 394 | } | 394 | } |
| 395 | 395 | ||
| 396 | hidewins() | 396 | hidewins() |
| @@ -161,7 +161,7 @@ imgerror(is: ref ImageSource, msg: string) · 160 unmodified lines | |||
| 161 | is.err = msg; | 161 | is.err = msg; |
| 162 | if(dbg) | 162 | if(dbg) |
| 163 | sys->print("Image error: %s\n", msg); | 163 | sys->print("Image error: %s\n", msg); |
| 164 | CU->raisex("exImageerror:"); | 164 | raise "exImageerror:"; |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | # Get next char or raise exception if cannot | 167 | # Get next char or raise exception if cannot |
| @@ -179,7 +179,7 @@ getc(is: ref ImageSource) : int · 11 unmodified lines | |||
| 179 | ungetc(is: ref ImageSource) | 179 | ungetc(is: ref ImageSource) |
| 180 | { | 180 | { |
| 181 | if(is.i == 0) | 181 | if(is.i == 0) |
| 182 | CU->raisex("EXInternal: ungetc past beginning of buffer"); | 182 | raise "EXInternal: ungetc past beginning of buffer"; |
| 183 | is.i--; | 183 | is.i--; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| @@ -190,7 +190,7 @@ ungetc2(is: ref ImageSource, nil: byte) · 4 unmodified lines | |||
| 190 | { | 190 | { |
| 191 | if(is.i < 2) { | 191 | if(is.i < 2) { |
| 192 | if(is.i != 1) | 192 | if(is.i != 1) |
| 193 | CU->raisex("EXInternal: ungetc2 past beginning of buffer"); | 193 | raise "EXInternal: ungetc2 past beginning of buffer"; |
| 194 | is.i = 0; | 194 | is.i = 0; |
| 195 | } | 195 | } |
| 196 | else | 196 | else |
| @@ -2107,7 +2107,7 @@ specindex(class: string) : int · 2106 unmodified lines | |||
| 2107 | if(objspecs[i].name == class) | 2107 | if(objspecs[i].name == class) |
| 2108 | break; | 2108 | break; |
| 2109 | if(i == len objspecs) | 2109 | if(i == len objspecs) |
| 2110 | CU->raisex("EXInternal: couldn't find host object class " + class); | 2110 | raise "EXInternal: couldn't find host object class " + class; |
| 2111 | return i; | 2111 | return i; |
| 2112 | } | 2112 | } |
| 2113 | 2113 | ||
| @@ -516,7 +516,7 @@ createvscroll(f: ref Frame) · 515 unmodified lines | |||
| 516 | f.vscr.r = f.vscr.r.addpt(Point(f.cr.max.x-breadth, f.cr.min.y)); | 516 | f.vscr.r = f.vscr.r.addpt(Point(f.cr.max.x-breadth, f.cr.min.y)); |
| 517 | f.cr.max.x -= breadth; | 517 | f.cr.max.x -= breadth; |
| 518 | if(f.cr.dx() <= 2*f.marginw) | 518 | if(f.cr.dx() <= 2*f.marginw) |
| 519 | CU->raisex("EXInternal: frame too small for layout"); | 519 | raise "EXInternal: frame too small for layout"; |
| 520 | f.vscr.draw(1); | 520 | f.vscr.draw(1); |
| 521 | } | 521 | } |
| 522 | 522 | ||
| @@ -531,7 +531,7 @@ createhscroll(f: ref Frame) · 8 unmodified lines | |||
| 531 | f.hscr.r = f.hscr.r.addpt(Point(x,f.cr.max.y-breadth)); | 531 | f.hscr.r = f.hscr.r.addpt(Point(x,f.cr.max.y-breadth)); |
| 532 | f.cr.max.y -= breadth; | 532 | f.cr.max.y -= breadth; |
| 533 | if(f.cr.dy() <= 2*f.marginh) | 533 | if(f.cr.dy() <= 2*f.marginh) |
| 534 | CU->raisex("EXInternal: frame too small for layout"); | 534 | raise "EXInternal: frame too small for layout"; |
| 535 | f.hscr.draw(1); | 535 | f.hscr.draw(1); |
| 536 | } | 536 | } |
| 537 | 537 | ||
| @@ -985,7 +985,7 @@ fixlinegeom(f: ref Frame, lay: ref Lay, l: ref Line) · 447 unmodified lines | |||
| 985 | # line is complete, next line will start with it (or it is nil) | 985 | # line is complete, next line will start with it (or it is nil) |
| 986 | rest := it; | 986 | rest := it; |
| 987 | if(lastit == nil) | 987 | if(lastit == nil) |
| 988 | CU->raisex("EXInternal: no items on line"); | 988 | raise "EXInternal: no items on line"; |
| 989 | lastit.next = nil; | 989 | lastit.next = nil; |
| 990 | 990 | ||
| 991 | l.width = w; | 991 | l.width = w; |
| @@ -1087,7 +1087,7 @@ getfont(num: int) : ref Font · 95 unmodified lines | |||
| 1087 | f = Font.open(display, fonts[num].name); | 1087 | f = Font.open(display, fonts[num].name); |
| 1088 | if(f == nil) { | 1088 | if(f == nil) { |
| 1089 | if(num == DefFnt) | 1089 | if(num == DefFnt) |
| 1090 | CU->raisex(sys->sprint("exLayout: can't open default font %s: %r", fonts[num].name)); | 1090 | raise sys->sprint("exLayout: can't open default font %s: %r", fonts[num].name); |
| 1091 | else { | 1091 | else { |
| 1092 | if(int (CU->config).dbg['w']) | 1092 | if(int (CU->config).dbg['w']) |
| 1093 | sys->print("warning: substituting default for font %s\n", | 1093 | sys->print("warning: substituting default for font %s\n", |
| @@ -2389,7 +2389,7 @@ markchanges(loc: ref Loc) · 1295 unmodified lines | |||
| 2389 | } | 2389 | } |
| 2390 | LEtablecell => | 2390 | LEtablecell => |
| 2391 | if(lastf == nil) | 2391 | if(lastf == nil) |
| 2392 | CU->raisex("EXInternal: markchanges no lastf"); | 2392 | raise "EXInternal: markchanges no lastf"; |
| 2393 | c := loc.le[i].tcell; | 2393 | c := loc.le[i].tcell; |
| 2394 | clay := lastf.sublays[c.layid]; | 2394 | clay := lastf.sublays[c.layid]; |
| 2395 | if(clay != nil) | 2395 | if(clay != nil) |
| @@ -2424,7 +2424,7 @@ colorimage(rgb: int) : ref Image · 28 unmodified lines | |||
| 2424 | # im := display.color(pix); | 2424 | # im := display.color(pix); |
| 2425 | im := display.rgb((rgb>>16)&255, (rgb>>8)&255, rgb&255); | 2425 | im := display.rgb((rgb>>16)&255, (rgb>>8)&255, rgb&255); |
| 2426 | if(im == nil) | 2426 | if(im == nil) |
| 2427 | CU->raisex(sys->sprint("exLayout: can't allocate color #%8.8ux: %r", rgb)); | 2427 | raise sys->sprint("exLayout: can't allocate color #%8.8ux: %r", rgb); |
| 2428 | x = ref Colornode(rgb, im, xhd); | 2428 | x = ref Colornode(rgb, im, xhd); |
| 2429 | colorhashtab[hv] = x; | 2429 | colorhashtab[hv] = x; |
| 2430 | } | 2430 | } |
| @@ -3309,7 +3309,7 @@ Control.scrollset(c: self ref Control, v1, v2, vmax, nsteps, draw: int) · 878 unmodified lines | |||
| 3309 | if(l <= 0) | 3309 | if(l <= 0) |
| 3310 | l = 1; | 3310 | l = 1; |
| 3311 | if(l < 0) | 3311 | if(l < 0) |
| 3312 | CU->raisex("EXInternal: negative scrollbar trough"); | 3312 | raise "EXInternal: negative scrollbar trough"; |
| 3313 | sc.top = l*v1/vmax; | 3313 | sc.top = l*v1/vmax; |
| 3314 | sc.bot = l*(vmax-v2)/vmax; | 3314 | sc.bot = l*(vmax-v2)/vmax; |
| 3315 | if (nsteps == 0) | 3315 | if (nsteps == 0) |
| @@ -215,17 +215,15 @@ runcmd(sh: Sh, ctxt: ref Draw->Context, argv: list of string, stdin: ref Sys->FD · 214 unmodified lines | |||
| 215 | 215 | ||
| 216 | cvstyx(fd: ref Sys->FD): (ref Sys->FD, string) | 216 | cvstyx(fd: ref Sys->FD): (ref Sys->FD, string) |
| 217 | { | 217 | { |
| 218 | styxconv := load Styxconv Styxconv->PATH; | 218 | styxconv := load Styxconv Styxconv->PATHNEW2OLD; |
| 219 | if(styxconv == nil) | 219 | if(styxconv == nil) |
| 220 | return (nil, sys->sprint("cannot load %s: %r", Styxconv->PATH)); | 220 | return (nil, sys->sprint("cannot load %s: %r", Styxconv->PATHNEW2OLD)); |
| 221 | styxconv->init(); | 221 | styxconv->init(); |
| 222 | p := array[2] of ref Sys->FD; | 222 | p := array[2] of ref Sys->FD; |
| 223 | if(sys->pipe(p) < 0) | 223 | if(sys->pipe(p) < 0) |
| 224 | return (nil, sys->sprint("can't create pipe: %r")); | 224 | return (nil, sys->sprint("can't create pipe: %r")); |
| 225 | pidc := chan of int; | 225 | spawn styxconv->styxconv(p[1], fd); |
| 226 | spawn styxconv->styxconv(p[1], fd, pidc); | ||
| 227 | p[1] = nil; | 226 | p[1] = nil; |
| 228 | <-pidc; | ||
| 229 | return (p[0], nil); | 227 | return (p[0], nil); |
| 230 | } | 228 | } |
| 231 | 229 | ||
| @@ -2,11 +2,13 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | TARG=\ | 3 | TARG=\ |
| 4 | ostyx.dis\ | 4 | ostyx.dis\ |
| 5 | styxconv.dis\ | 5 | new2old.dis\ |
| 6 | 6 | old2new.dis\ | |
| 7 | |||
| 7 | MODULES=\ | 8 | MODULES=\ |
| 8 | ostyx.m\ | 9 | ostyx.m\ |
| 9 | osys.m\ | 10 | osys.m\ |
| 11 | nsys.m\ | ||
| 10 | 12 | ||
| 11 | SYSMODULES=\ | 13 | SYSMODULES=\ |
| 12 | bufio.m\ | 14 | bufio.m\ |
| @@ -0,0 +1,640 @@ | |||
| 1 | implement Styxconv; | ||
| 2 | |||
| 3 | include "sys.m"; | ||
| 4 | sys: Sys; | ||
| 5 | include "osys.m"; | ||
| 6 | include "nsys.m"; | ||
| 7 | include "draw.m"; | ||
| 8 | include "styx.m"; | ||
| 9 | nstyx: Styx; | ||
| 10 | Tmsg, Rmsg: import nstyx; | ||
| 11 | include "ostyx.m"; | ||
| 12 | ostyx: OStyx; | ||
| 13 | OTmsg, ORmsg: import ostyx; | ||
| 14 | include "styxconv.m"; | ||
| 15 | |||
| 16 | # todo: map fids > ffff into 16 bits | ||
| 17 | |||
| 18 | DEBUG: con 1; | ||
| 19 | |||
| 20 | Fid: adt | ||
| 21 | { | ||
| 22 | fid: int; | ||
| 23 | isdir: int; | ||
| 24 | n: int; # size of last new client dirread request. | ||
| 25 | soff: int; # dir offset on old server. | ||
| 26 | coff: int; # dir offset on new client. | ||
| 27 | next: cyclic ref Fid; | ||
| 28 | }; | ||
| 29 | |||
| 30 | Req: adt { | ||
| 31 | tag: int; | ||
| 32 | oldtag: int; # if it's a flush. | ||
| 33 | rp: ref Reqproc; | ||
| 34 | next: cyclic ref Req; | ||
| 35 | flushes: list of ref Rmsg.Flush; # flushes awaiting req finish. | ||
| 36 | }; | ||
| 37 | |||
| 38 | Reqproc: adt { | ||
| 39 | newtmsg: chan of ref Tmsg; # convproc -> reqproc, once per req. | ||
| 40 | newrmsg: chan of ref Rmsg; # reqproc -> convproc, once per req | ||
| 41 | |||
| 42 | oldtmsg: chan of ref OTmsg; # reqproc -> convproc | ||
| 43 | oldrmsg: chan of ref ORmsg; # convproc -> reqproc | ||
| 44 | |||
| 45 | flushable: int; | ||
| 46 | |||
| 47 | new: fn(): ref Reqproc; | ||
| 48 | rpc: fn(rp: self ref Reqproc, otm: ref OTmsg): ref ORmsg; | ||
| 49 | }; | ||
| 50 | |||
| 51 | tags: ref Req; | ||
| 52 | avail: chan of ref Reqproc; | ||
| 53 | fids: ref Fid; | ||
| 54 | nprocs := 0; | ||
| 55 | |||
| 56 | init() | ||
| 57 | { | ||
| 58 | sys = load Sys Sys->PATH; | ||
| 59 | if(sys == nil) | ||
| 60 | nomod("Sys", Sys->PATH); | ||
| 61 | nstyx = load Styx Styx->PATH; | ||
| 62 | if(nstyx == nil) | ||
| 63 | nomod("Styx", Styx->PATH); | ||
| 64 | ostyx = load OStyx OStyx->PATH; | ||
| 65 | if(ostyx == nil) | ||
| 66 | nomod("OStyx", OStyx->PATH); | ||
| 67 | |||
| 68 | ostyx->init(); | ||
| 69 | nstyx->init(); | ||
| 70 | avail = chan of ref Reqproc; | ||
| 71 | } | ||
| 72 | |||
| 73 | styxconv(newclient: ref Sys->FD, oldsrv: ref Sys->FD) | ||
| 74 | { | ||
| 75 | newtmsg := chan of ref Tmsg; | ||
| 76 | oldrmsg := chan of ref ORmsg; | ||
| 77 | |||
| 78 | killpids := chan[2] of int; | ||
| 79 | spawn readnewtmsgs(killpids, newclient, newtmsg); | ||
| 80 | spawn readoldrmsgs(killpids, oldsrv, oldrmsg); | ||
| 81 | |||
| 82 | converting: | ||
| 83 | for(;;)alt{ | ||
| 84 | ntm := <-newtmsg => | ||
| 85 | if(DEBUG) | ||
| 86 | sys->fprint(sys->fildes(2), "-> %s\n", ntm.text()); | ||
| 87 | if(ntm == nil) | ||
| 88 | break converting; | ||
| 89 | ns2os(ntm, newclient, oldsrv); | ||
| 90 | orm := <-oldrmsg => | ||
| 91 | if(DEBUG) | ||
| 92 | sys->fprint(sys->fildes(2), " <- %s\n", ostyx->rmsg2s(orm)); | ||
| 93 | if(orm == nil) | ||
| 94 | break converting; | ||
| 95 | t := looktag(orm.tag); | ||
| 96 | if(t == nil){ | ||
| 97 | warning("reply by old-server to non-existent tag"); | ||
| 98 | break; | ||
| 99 | } | ||
| 100 | pick rm := orm { | ||
| 101 | Flush => | ||
| 102 | ot := looktag(t.oldtag); | ||
| 103 | # if it's an Rflush of a request-in-progress, | ||
| 104 | # we send it to the reqproc, which | ||
| 105 | # can then clean up as it likes. | ||
| 106 | if(ot != nil){ | ||
| 107 | if(ot.rp != nil){ | ||
| 108 | if(ot.rp.flushable){ | ||
| 109 | ot.rp.oldrmsg <-= rm; | ||
| 110 | # reqproc is bound to finish after a flush | ||
| 111 | reqreply(ot, newclient, oldsrv); | ||
| 112 | }else { | ||
| 113 | # hold flush reply for later | ||
| 114 | ot.flushes = ref Rmsg.Flush(rm.tag) :: ot.flushes; | ||
| 115 | } | ||
| 116 | break; | ||
| 117 | } | ||
| 118 | deletetag(t.oldtag); | ||
| 119 | } | ||
| 120 | NRsend(newclient, ref Rmsg.Flush(rm.tag)); | ||
| 121 | deletetag(rm.tag); | ||
| 122 | * => | ||
| 123 | if(t.rp != nil){ | ||
| 124 | t.rp.oldrmsg <-= orm; | ||
| 125 | reqreply(t, newclient, oldsrv); | ||
| 126 | }else{ | ||
| 127 | os2ns(orm, newclient); | ||
| 128 | deletetag(orm.tag); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | } | ||
| 132 | # kill off active reqprocs | ||
| 133 | for(; tags != nil; tags = tags.next){ | ||
| 134 | if(tags.rp != nil){ | ||
| 135 | tags.rp.oldrmsg <-= nil; | ||
| 136 | nprocs--; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | # kill off idle reqprocs | ||
| 140 | while(nprocs > 0){ | ||
| 141 | rp := <-avail; | ||
| 142 | rp.newtmsg <-= nil; | ||
| 143 | nprocs--; | ||
| 144 | } | ||
| 145 | # kill off message readers | ||
| 146 | kill(<-killpids); | ||
| 147 | kill(<-killpids); | ||
| 148 | } | ||
| 149 | |||
| 150 | # process one response from the request proc. | ||
| 151 | # request proc can respond by sending a new tmsg to the old server | ||
| 152 | # or by sending an rmsg to the new client, in which case | ||
| 153 | # it implicitly signals that it has finished processing the request. | ||
| 154 | # the actual reply might be an Rflush, signifying that | ||
| 155 | # the request has been aborted. | ||
| 156 | reqreply(t: ref Req, newclient: ref Sys->FD, oldsrv: ref Sys->FD) | ||
| 157 | { | ||
| 158 | rp := t.rp; | ||
| 159 | alt{ | ||
| 160 | nrm := <-rp.newrmsg => | ||
| 161 | # request is done when process sends rmsg | ||
| 162 | pick rm := nrm { | ||
| 163 | Flush => | ||
| 164 | deletetag(t.tag); | ||
| 165 | } | ||
| 166 | deletetag(nrm.tag); | ||
| 167 | NRsend(newclient, nrm); | ||
| 168 | for(; t.flushes != nil; t.flushes = tl t.flushes) | ||
| 169 | NRsend(newclient, hd t.flushes); | ||
| 170 | |||
| 171 | otm := <-rp.oldtmsg => | ||
| 172 | OTsend(oldsrv, otm); | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | |||
| 177 | # T messages: forward on, reply immediately, or start processing. | ||
| 178 | ns2os(tm0: ref Tmsg, newclient, oldsrv: ref Sys->FD) | ||
| 179 | { | ||
| 180 | otm: ref OTmsg; | ||
| 181 | |||
| 182 | t := ref Req(tm0.tag, -1, nil, nil, nil); | ||
| 183 | pick tm := tm0{ | ||
| 184 | Readerror => | ||
| 185 | exit; | ||
| 186 | Version => | ||
| 187 | (s, v) := nstyx->compatible(tm, nstyx->MAXRPC, nil); | ||
| 188 | NRsend(newclient, ref Rmsg.Version(tm.tag, s, v)); | ||
| 189 | return; | ||
| 190 | Auth => | ||
| 191 | NRsend(newclient, ref Rmsg.Error(tm.tag, "authorization not required")); | ||
| 192 | return; | ||
| 193 | Walk => | ||
| 194 | storetag(t); | ||
| 195 | t.rp = Reqproc.new(); | ||
| 196 | t.rp.newtmsg <-= tm; | ||
| 197 | reqreply(t, newclient, oldsrv); | ||
| 198 | return; | ||
| 199 | Attach => | ||
| 200 | otm = ref OTmsg.Attach(tm.tag, tm.fid, tm.uname, tm.aname); | ||
| 201 | Flush => | ||
| 202 | t.oldtag = tm.oldtag; | ||
| 203 | otm = ref OTmsg.Flush(tm.tag, tm.oldtag); | ||
| 204 | Open => | ||
| 205 | otm = ref OTmsg.Open(tm.tag, tm.fid, tm.mode); | ||
| 206 | Create => | ||
| 207 | otm = ref OTmsg.Create(tm.tag, tm.fid, tm.perm, tm.mode, tm.name); | ||
| 208 | Read => | ||
| 209 | fp := findfid(tm.fid); | ||
| 210 | count := tm.count; | ||
| 211 | offset := tm.offset; | ||
| 212 | if(fp != nil && fp.isdir){ | ||
| 213 | fp.n = count; | ||
| 214 | count = (count/OStyx->DIRLEN)*OStyx->DIRLEN; | ||
| 215 | if(int offset != fp.coff){ | ||
| 216 | NRsend(newclient, ref Rmsg.Error(tm.tag, "unexpected offset in dirread")); | ||
| 217 | return; | ||
| 218 | } | ||
| 219 | offset = big fp.soff; | ||
| 220 | } | ||
| 221 | otm = ref OTmsg.Read(tm.tag, tm.fid, count, offset); | ||
| 222 | Write => | ||
| 223 | otm = ref OTmsg.Write(tm.tag, tm.fid, tm.offset, tm.data); | ||
| 224 | Clunk => | ||
| 225 | otm = ref OTmsg.Clunk(tm.tag, tm.fid); | ||
| 226 | Remove => | ||
| 227 | otm = ref OTmsg.Remove(tm.tag, tm.fid); | ||
| 228 | Stat => | ||
| 229 | otm = ref OTmsg.Stat(tm.tag, tm.fid); | ||
| 230 | Wstat => | ||
| 231 | otm = ref OTmsg.Wstat(tm.tag, tm.fid, nd2od(tm.stat)); | ||
| 232 | * => | ||
| 233 | fatal("bad T message"); | ||
| 234 | } | ||
| 235 | storetag(t); | ||
| 236 | OTsend(oldsrv, otm); | ||
| 237 | } | ||
| 238 | |||
| 239 | # R messages: old to new | ||
| 240 | os2ns(orm0: ref ORmsg, newclient: ref Sys->FD) | ||
| 241 | { | ||
| 242 | rm: ref Rmsg; | ||
| 243 | |||
| 244 | rm = nil; | ||
| 245 | pick orm := orm0 { | ||
| 246 | Error => | ||
| 247 | rm = ref Rmsg.Error(orm.tag, orm.err); | ||
| 248 | Flush => | ||
| 249 | rm = ref Rmsg.Flush(orm.tag); | ||
| 250 | Clone => | ||
| 251 | rm = ref Rmsg.Walk(orm.tag, nil); | ||
| 252 | Walk => | ||
| 253 | fatal("walk rmsgs should be dealt with be walkreqproc"); | ||
| 254 | Open => | ||
| 255 | setfid(orm.fid, orm.qid); | ||
| 256 | rm = ref Rmsg.Open(orm.tag, oq2nq(orm.qid), 0); | ||
| 257 | Create => | ||
| 258 | setfid(orm.fid, orm.qid); | ||
| 259 | rm = ref Rmsg.Create(orm.tag, oq2nq(orm.qid), 0); | ||
| 260 | Read => | ||
| 261 | fp := findfid(orm.fid); | ||
| 262 | data := orm.data; | ||
| 263 | if(fp != nil && fp.isdir) | ||
| 264 | data = ods2nds(data, fp.n); | ||
| 265 | fp.coff += len data; | ||
| 266 | fp.soff += len orm.data; | ||
| 267 | rm = ref Rmsg.Read(orm.tag, data); | ||
| 268 | Write => | ||
| 269 | rm = ref Rmsg.Write(orm.tag, orm.count); | ||
| 270 | Clunk => | ||
| 271 | rm = ref Rmsg.Clunk(orm.tag); | ||
| 272 | deletefid(orm.fid); | ||
| 273 | Remove => | ||
| 274 | rm = ref Rmsg.Remove(orm.tag); | ||
| 275 | deletefid(orm.fid); | ||
| 276 | Stat => | ||
| 277 | rm = ref Rmsg.Stat(orm.tag, od2nd(orm.stat)); | ||
| 278 | Wstat => | ||
| 279 | rm = ref Rmsg.Wstat(orm.tag); | ||
| 280 | Attach => | ||
| 281 | newfid(orm.fid, orm.qid.path & OSys->CHDIR); | ||
| 282 | rm = ref Rmsg.Attach(orm.tag, oq2nq(orm.qid)); | ||
| 283 | * => | ||
| 284 | fatal("bad R message"); | ||
| 285 | } | ||
| 286 | NRsend(newclient, rm); | ||
| 287 | } | ||
| 288 | |||
| 289 | Reqproc.rpc(rp: self ref Reqproc, otm: ref OTmsg): ref ORmsg | ||
| 290 | { | ||
| 291 | rp.oldtmsg <-= otm; | ||
| 292 | m := <-rp.oldrmsg; | ||
| 293 | if(m == nil) | ||
| 294 | exit; | ||
| 295 | return m; | ||
| 296 | } | ||
| 297 | |||
| 298 | Reqproc.new(): ref Reqproc | ||
| 299 | { | ||
| 300 | alt{ | ||
| 301 | rp := <-avail => | ||
| 302 | return rp; | ||
| 303 | * => | ||
| 304 | rp := ref Reqproc( | ||
| 305 | chan of ref Tmsg, | ||
| 306 | chan of ref Rmsg, | ||
| 307 | chan of ref OTmsg, | ||
| 308 | chan of ref ORmsg, | ||
| 309 | 1); | ||
| 310 | spawn reqproc(rp); | ||
| 311 | nprocs++; | ||
| 312 | return rp; | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | reqproc(rp: ref Reqproc) | ||
| 317 | { | ||
| 318 | for(;;){ | ||
| 319 | tm := <-rp.newtmsg; | ||
| 320 | if(tm == nil) | ||
| 321 | return; | ||
| 322 | rm: ref Rmsg; | ||
| 323 | pick m := tm { | ||
| 324 | Walk => | ||
| 325 | rm = walkreq(m, rp); | ||
| 326 | * => | ||
| 327 | fatal("non-walk req passed to reqproc"); | ||
| 328 | } | ||
| 329 | rp.flushable = 1; | ||
| 330 | rp.newrmsg <-= rm; | ||
| 331 | avail <-= rp; | ||
| 332 | } | ||
| 333 | } | ||
| 334 | |||
| 335 | # note that although this is in a separate process, | ||
| 336 | # whenever it's not in Reqproc.rpc, the styxconv | ||
| 337 | # process is blocked, so although state is shared, | ||
| 338 | # there are no race conditions. | ||
| 339 | walkreq(tm: ref Tmsg.Walk, rp: ref Reqproc): ref Rmsg | ||
| 340 | { | ||
| 341 | cloned := 0; | ||
| 342 | n := len tm.names; | ||
| 343 | if(tm.newfid != tm.fid){ | ||
| 344 | cloned = 1; | ||
| 345 | pick rm := rp.rpc(ref OTmsg.Clone(tm.tag, tm.fid, tm.newfid)) { | ||
| 346 | Clone => | ||
| 347 | ; | ||
| 348 | Error => | ||
| 349 | return ref Rmsg.Error(tm.tag, rm.err); | ||
| 350 | Flush => | ||
| 351 | return ref Rmsg.Flush(rm.tag); | ||
| 352 | * => | ||
| 353 | fatal("unexpected reply to OTmsg.Clone"); | ||
| 354 | } | ||
| 355 | cloned = 1; | ||
| 356 | } | ||
| 357 | qids := array[n] of NSys->Qid; | ||
| 358 | finalqid: OSys->Qid; | ||
| 359 | |||
| 360 | # make sure we don't get flushed in an unwindable state. | ||
| 361 | rp.flushable = n == 1 || cloned; | ||
| 362 | for(i := 0; i < n; i++){ | ||
| 363 | pick rm := rp.rpc(ref OTmsg.Walk(tm.tag, tm.newfid, tm.names[i])) { | ||
| 364 | Walk => | ||
| 365 | qids[i] = oq2nq(rm.qid); | ||
| 366 | finalqid = rm.qid; | ||
| 367 | Flush => | ||
| 368 | if(cloned){ | ||
| 369 | rp.flushable = 0; | ||
| 370 | rp.rpc(ref OTmsg.Clunk(tm.tag, tm.newfid)); | ||
| 371 | } | ||
| 372 | return ref Rmsg.Flush(rm.tag); | ||
| 373 | Error => | ||
| 374 | if(cloned){ | ||
| 375 | rp.flushable = 0; | ||
| 376 | rp.rpc(ref OTmsg.Clunk(tm.tag, tm.newfid)); | ||
| 377 | } | ||
| 378 | if(i == 0) | ||
| 379 | return ref Rmsg.Error(tm.tag, rm.err); | ||
| 380 | return ref Rmsg.Walk(tm.tag, qids[0:i]); | ||
| 381 | } | ||
| 382 | } | ||
| 383 | if(cloned) | ||
| 384 | clonefid(tm.fid, tm.newfid); | ||
| 385 | if(n > 0) | ||
| 386 | setfid(tm.newfid, finalqid); | ||
| 387 | return ref Rmsg.Walk(tm.tag, qids); | ||
| 388 | } | ||
| 389 | |||
| 390 | storetag(t: ref Req) | ||
| 391 | { | ||
| 392 | t.next = tags; | ||
| 393 | tags = t; | ||
| 394 | } | ||
| 395 | |||
| 396 | looktag(tag: int): ref Req | ||
| 397 | { | ||
| 398 | for(t := tags; t != nil; t = t.next) | ||
| 399 | if(t.tag == tag) | ||
| 400 | return t; | ||
| 401 | return nil; | ||
| 402 | } | ||
| 403 | |||
| 404 | deletetag(tag: int) | ||
| 405 | { | ||
| 406 | prev: ref Req; | ||
| 407 | t := tags; | ||
| 408 | while(t != nil){ | ||
| 409 | if(t.tag == tag){ | ||
| 410 | next := t.next; | ||
| 411 | t.next = nil; | ||
| 412 | if(prev != nil) | ||
| 413 | prev.next = next; | ||
| 414 | else | ||
| 415 | tags = next; | ||
| 416 | t = next; | ||
| 417 | }else{ | ||
| 418 | prev = t; | ||
| 419 | t = t.next; | ||
| 420 | } | ||
| 421 | } | ||
| 422 | } | ||
| 423 | |||
| 424 | newfid(fid: int, isdir: int): ref Fid | ||
| 425 | { | ||
| 426 | f := ref Fid; | ||
| 427 | f.fid = fid; | ||
| 428 | f.isdir = isdir; | ||
| 429 | f.n = f.soff = f.coff = 0; | ||
| 430 | f.next = fids; | ||
| 431 | fids = f; | ||
| 432 | return f; | ||
| 433 | } | ||
| 434 | |||
| 435 | clonefid(ofid: int, fid: int): ref Fid | ||
| 436 | { | ||
| 437 | if((f := findfid(ofid)) != nil){ | ||
| 438 | nf := newfid(fid, f.isdir); | ||
| 439 | return nf; | ||
| 440 | } | ||
| 441 | warning("clone of non-existent fid"); | ||
| 442 | return newfid(fid, 0); | ||
| 443 | } | ||
| 444 | |||
| 445 | deletefid(fid: int) | ||
| 446 | { | ||
| 447 | lf: ref Fid; | ||
| 448 | |||
| 449 | for(f := fids; f != nil; f = f.next){ | ||
| 450 | if(f.fid == fid){ | ||
| 451 | if(lf == nil) | ||
| 452 | fids = f.next; | ||
| 453 | else | ||
| 454 | lf.next = f.next; | ||
| 455 | return; | ||
| 456 | } | ||
| 457 | lf = f; | ||
| 458 | } | ||
| 459 | } | ||
| 460 | |||
| 461 | findfid(fid: int): ref Fid | ||
| 462 | { | ||
| 463 | for(f := fids; f != nil; f = f.next) | ||
| 464 | if(f.fid == fid) | ||
| 465 | return f; | ||
| 466 | return nil; | ||
| 467 | } | ||
| 468 | |||
| 469 | setfid(fid: int, qid: OSys->Qid) | ||
| 470 | { | ||
| 471 | f := findfid(fid); | ||
| 472 | if(f == nil){ | ||
| 473 | warning(sys->sprint("cannot find fid %d", fid)); | ||
| 474 | }else{ | ||
| 475 | f.isdir = qid.path & OSys->CHDIR; | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 479 | om2nm(om: int): int | ||
| 480 | { | ||
| 481 | # DMDIR == CHDIR | ||
| 482 | return om; | ||
| 483 | } | ||
| 484 | |||
| 485 | nm2om(m: int): int | ||
| 486 | { | ||
| 487 | # DMDIR == CHDIR | ||
| 488 | return m&~(NSys->DMAPPEND|NSys->DMEXCL|NSys->DMAUTH); | ||
| 489 | } | ||
| 490 | |||
| 491 | oq2nq(oq: OSys->Qid): NSys->Qid | ||
| 492 | { | ||
| 493 | q: NSys->Qid; | ||
| 494 | |||
| 495 | isdir := oq.path&OSys->CHDIR; | ||
| 496 | q.path = big (oq.path&~OSys->CHDIR); | ||
| 497 | q.vers = oq.vers; | ||
| 498 | q.qtype = 0; | ||
| 499 | if(isdir) | ||
| 500 | q.qtype |= NSys->QTDIR; | ||
| 501 | return q; | ||
| 502 | } | ||
| 503 | |||
| 504 | nq2oq(q: NSys->Qid): OSys->Qid | ||
| 505 | { | ||
| 506 | oq: OSys->Qid; | ||
| 507 | |||
| 508 | isdir := q.qtype&NSys->QTDIR; | ||
| 509 | oq.path = int q.path; | ||
| 510 | oq.vers = q.vers; | ||
| 511 | if(isdir) | ||
| 512 | oq.path |= OSys->CHDIR; | ||
| 513 | return oq; | ||
| 514 | } | ||
| 515 | |||
| 516 | od2nd(od: OSys->Dir): NSys->Dir | ||
| 517 | { | ||
| 518 | d: NSys->Dir; | ||
| 519 | |||
| 520 | d.name = od.name; | ||
| 521 | d.uid = od.uid; | ||
| 522 | d.gid = od.gid; | ||
| 523 | d.muid = od.uid; | ||
| 524 | d.qid = oq2nq(od.qid); | ||
| 525 | d.mode = om2nm(od.mode); | ||
| 526 | d.atime = od.atime; | ||
| 527 | d.mtime = od.mtime; | ||
| 528 | d.length = big od.length; | ||
| 529 | d.dtype = od.dtype; | ||
| 530 | d.dev = od.dev; | ||
| 531 | return d; | ||
| 532 | } | ||
| 533 | |||
| 534 | nd2od(d: NSys->Dir): OSys->Dir | ||
| 535 | { | ||
| 536 | od: OSys->Dir; | ||
| 537 | |||
| 538 | od.name = d.name; | ||
| 539 | od.uid = d.uid; | ||
| 540 | od.gid = d.gid; | ||
| 541 | od.qid = nq2oq(d.qid); | ||
| 542 | od.mode = nm2om(d.mode); | ||
| 543 | od.atime = d.atime; | ||
| 544 | od.mtime = d.mtime; | ||
| 545 | od.length = int d.length; | ||
| 546 | od.dtype = d.dtype; | ||
| 547 | od.dev = d.dev; | ||
| 548 | return od; | ||
| 549 | } | ||
| 550 | |||
| 551 | ods2nds(ob: array of byte, max: int): array of byte | ||
| 552 | { | ||
| 553 | od: OSys->Dir; | ||
| 554 | |||
| 555 | m := len ob; | ||
| 556 | if(m % OStyx->DIRLEN != 0) | ||
| 557 | fatal(sys->sprint("bad dir len %d", m)); | ||
| 558 | m /= OStyx->DIRLEN; | ||
| 559 | n := 0; | ||
| 560 | p := ob; | ||
| 561 | for(i := 0; i < m; i++){ | ||
| 562 | (p, od) = ostyx->convM2D(p); | ||
| 563 | d := od2nd(od); | ||
| 564 | nn := nstyx->packdirsize(d); | ||
| 565 | if(n+nn > max) # might just happen with long file names | ||
| 566 | break; | ||
| 567 | n += nn; | ||
| 568 | } | ||
| 569 | m = i; | ||
| 570 | b := array[n] of byte; | ||
| 571 | n = 0; | ||
| 572 | p = ob; | ||
| 573 | for(i = 0; i < m; i++){ | ||
| 574 | (p, od) = ostyx->convM2D(p); | ||
| 575 | d := od2nd(od); | ||
| 576 | q := nstyx->packdir(d); | ||
| 577 | nn := len q; | ||
| 578 | b[n: ] = q[0: nn]; | ||
| 579 | n += nn; | ||
| 580 | } | ||
| 581 | return b; | ||
| 582 | } | ||
| 583 | |||
| 584 | OTsend(fd: ref Sys->FD, otm: ref OTmsg): int | ||
| 585 | { | ||
| 586 | if(DEBUG) | ||
| 587 | sys->fprint(sys->fildes(2), " -> %s\n", ostyx->tmsg2s(otm)); | ||
| 588 | s := array[OStyx->MAXRPC] of byte; | ||
| 589 | n := ostyx->tmsg2d(otm, s); | ||
| 590 | if(n < 0) | ||
| 591 | return -1; | ||
| 592 | return sys->write(fd, s, n); | ||
| 593 | } | ||
| 594 | |||
| 595 | NRsend(fd: ref Sys->FD, rm: ref Rmsg): int | ||
| 596 | { | ||
| 597 | if(DEBUG) | ||
| 598 | sys->fprint(sys->fildes(2), "<- %s\n", rm.text()); | ||
| 599 | s := rm.pack(); | ||
| 600 | if(s == nil) | ||
| 601 | return -1; | ||
| 602 | return sys->write(fd, s, len s); | ||
| 603 | } | ||
| 604 | |||
| 605 | readnewtmsgs(pidc: chan of int, newclient: ref Sys->FD, newtmsg: chan of ref Tmsg) | ||
| 606 | { | ||
| 607 | pidc <-= sys->pctl(0, nil); | ||
| 608 | for(;;){ | ||
| 609 | newtmsg <-= Tmsg.read(newclient, nstyx->MAXRPC); | ||
| 610 | } | ||
| 611 | } | ||
| 612 | |||
| 613 | readoldrmsgs(pidc: chan of int, oldsrv: ref Sys->FD, oldrmsg: chan of ref ORmsg) | ||
| 614 | { | ||
| 615 | pidc <-= sys->pctl(0, nil); | ||
| 616 | for(;;){ | ||
| 617 | oldrmsg <-= ORmsg.read(oldsrv); | ||
| 618 | } | ||
| 619 | } | ||
| 620 | |||
| 621 | warning(err: string) | ||
| 622 | { | ||
| 623 | sys->fprint(sys->fildes(2), "warning: %s\n", err); | ||
| 624 | } | ||
| 625 | |||
| 626 | fatal(err: string) | ||
| 627 | { | ||
| 628 | sys->fprint(sys->fildes(2), "%s\n", err); | ||
| 629 | exit; | ||
| 630 | } | ||
| 631 | |||
| 632 | nomod(mod: string, path: string) | ||
| 633 | { | ||
| 634 | fatal(sys->sprint("can't load %s(%s): %r", mod, path)); | ||
| 635 | } | ||
| 636 | |||
| 637 | kill(pid: int) | ||
| 638 | { | ||
| 639 | sys->fprint(sys->open("#p/"+string pid+"/ctl", Sys->OWRITE), "kill"); | ||
| 640 | } | ||
| @@ -0,0 +1,51 @@ | |||
| 1 | NSys: module | ||
| 2 | { | ||
| 3 | # Unique file identifier for file objects | ||
| 4 | Qid: adt | ||
| 5 | { | ||
| 6 | path: big; | ||
| 7 | vers: int; | ||
| 8 | qtype: int; | ||
| 9 | }; | ||
| 10 | |||
| 11 | QTDIR: con 16r80; | ||
| 12 | QTAPPEND: con 16r40; | ||
| 13 | QTEXCL: con 16r20; | ||
| 14 | QTAUTH: con 16r08; | ||
| 15 | QTTMP: con 16r04; | ||
| 16 | QTFILE: con 0; | ||
| 17 | |||
| 18 | # Return from stat and directory read | ||
| 19 | Dir: adt | ||
| 20 | { | ||
| 21 | name: string; | ||
| 22 | uid: string; | ||
| 23 | gid: string; | ||
| 24 | muid: string; | ||
| 25 | qid: Qid; | ||
| 26 | mode: int; | ||
| 27 | atime: int; | ||
| 28 | mtime: int; | ||
| 29 | length: big; | ||
| 30 | dtype: int; | ||
| 31 | dev: int; | ||
| 32 | }; | ||
| 33 | |||
| 34 | # Maximum read which will be completed atomically; | ||
| 35 | # also the optimum block size | ||
| 36 | # | ||
| 37 | ATOMICIO: con 8192; | ||
| 38 | |||
| 39 | OREAD: con 0; | ||
| 40 | OWRITE: con 1; | ||
| 41 | ORDWR: con 2; | ||
| 42 | OTRUNC: con 16; | ||
| 43 | ORCLOSE: con 64; | ||
| 44 | OEXCL: con 16r1000; | ||
| 45 | |||
| 46 | DMDIR: con int 1<<31; | ||
| 47 | DMAPPEND: con int 1<<30; | ||
| 48 | DMEXCL: con int 1<<29; | ||
| 49 | DMAUTH: con int 1<<27; | ||
| 50 | DMTMP: con int 1<<26; | ||
| 51 | }; | ||
| @@ -0,0 +1,480 @@ | |||
| 1 | implement Styxconv; | ||
| 2 | |||
| 3 | include "sys.m"; | ||
| 4 | sys: Sys; | ||
| 5 | include "osys.m"; | ||
| 6 | include "nsys.m"; | ||
| 7 | include "draw.m"; | ||
| 8 | include "styx.m"; | ||
| 9 | nstyx: Styx; | ||
| 10 | Tmsg, Rmsg: import nstyx; | ||
| 11 | include "ostyx.m"; | ||
| 12 | ostyx: OStyx; | ||
| 13 | OTmsg, ORmsg: import ostyx; | ||
| 14 | include "styxconv.m"; | ||
| 15 | |||
| 16 | DEBUG: con 0; | ||
| 17 | |||
| 18 | # convert from old styx client to new styx server. | ||
| 19 | # more straightforward than the other way around | ||
| 20 | # because there's an almost exactly 1-1 mapping | ||
| 21 | # between message types. (the exception is Tversion, | ||
| 22 | # but we do that synchronously anyway). | ||
| 23 | |||
| 24 | # todo: map qids > ffffffff into 32 bits. | ||
| 25 | |||
| 26 | Msize: con nstyx->IOHDRSZ + OSys->ATOMICIO; | ||
| 27 | Fid: adt | ||
| 28 | { | ||
| 29 | fid: int; | ||
| 30 | isdir: int; | ||
| 31 | n: int; # size of last new client dirread request. | ||
| 32 | soff: int; # dir offset on new server. | ||
| 33 | coff: int; # dir offset on old client. | ||
| 34 | next: cyclic ref Fid; | ||
| 35 | extras: array of byte; # packed old styx dir structures | ||
| 36 | }; | ||
| 37 | |||
| 38 | Req: adt { | ||
| 39 | tag: int; | ||
| 40 | fid: int; | ||
| 41 | oldtag: int; # if it's a flush. | ||
| 42 | newfid: int; # if it's a clone | ||
| 43 | next: cyclic ref Req; | ||
| 44 | }; | ||
| 45 | |||
| 46 | tags: ref Req; | ||
| 47 | fids: ref Fid; | ||
| 48 | |||
| 49 | init() | ||
| 50 | { | ||
| 51 | sys = load Sys Sys->PATH; | ||
| 52 | if(sys == nil) | ||
| 53 | nomod("Sys", Sys->PATH); | ||
| 54 | nstyx = load Styx Styx->PATH; | ||
| 55 | if(nstyx == nil) | ||
| 56 | nomod("Styx", Styx->PATH); | ||
| 57 | ostyx = load OStyx OStyx->PATH; | ||
| 58 | if(ostyx == nil) | ||
| 59 | nomod("OStyx", OStyx->PATH); | ||
| 60 | |||
| 61 | ostyx->init(); | ||
| 62 | nstyx->init(); | ||
| 63 | } | ||
| 64 | |||
| 65 | styxconv(oldclient, newsrv: ref Sys->FD) | ||
| 66 | { | ||
| 67 | oldtmsg := chan of ref OTmsg; | ||
| 68 | newrmsg := chan of ref Rmsg; | ||
| 69 | |||
| 70 | killpids := chan[2] of int; | ||
| 71 | spawn readoldtmsgs(killpids, oldclient, oldtmsg); | ||
| 72 | spawn readnewrmsgs(killpids, newsrv, newrmsg); | ||
| 73 | # XXX difficulty: what happens if the server isn't responding | ||
| 74 | # and the client hangs up? we won't know about it. | ||
| 75 | # but we don't want to know about normal t-messages | ||
| 76 | # piling up either, so we don't want to alt on oldtmsg too. | ||
| 77 | NTsend(newsrv, ref Tmsg.Version(nstyx->NOTAG, Msize, "9P2000")); | ||
| 78 | pick nrm := <-newrmsg { | ||
| 79 | Version => | ||
| 80 | if(DEBUG) | ||
| 81 | sys->fprint(sys->fildes(2), " <- %s\n", nrm.text()); | ||
| 82 | if(nrm.msize < Msize) | ||
| 83 | fatal("message size too small"); | ||
| 84 | Error => | ||
| 85 | fatal("versioning failed: " + nrm.ename); | ||
| 86 | * => | ||
| 87 | fatal("bad response to Tversion: " + nrm.text()); | ||
| 88 | } | ||
| 89 | |||
| 90 | converting: | ||
| 91 | for(;;)alt{ | ||
| 92 | otm := <-oldtmsg => | ||
| 93 | if(DEBUG) | ||
| 94 | sys->fprint(sys->fildes(2), "-> %s\n", ostyx->tmsg2s(otm)); | ||
| 95 | if(otm == nil || tagof(otm) == tagof(OTmsg.Readerror)) | ||
| 96 | break converting; | ||
| 97 | oc2ns(otm, oldclient, newsrv); | ||
| 98 | nrm := <-newrmsg => | ||
| 99 | if(DEBUG) | ||
| 100 | sys->fprint(sys->fildes(2), " <- %s\n", nrm.text()); | ||
| 101 | if(nrm == nil || tagof(nrm) == tagof(Rmsg.Readerror)) | ||
| 102 | break converting; | ||
| 103 | t := looktag(nrm.tag); | ||
| 104 | if(t == nil){ | ||
| 105 | warning("reply by new-server to non-existent tag"); | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | ns2oc(t, nrm, oldclient); | ||
| 109 | deletetag(nrm.tag); | ||
| 110 | } | ||
| 111 | |||
| 112 | kill(<-killpids); | ||
| 113 | kill(<-killpids); | ||
| 114 | } | ||
| 115 | |||
| 116 | # T messages: forward on or reply immediately | ||
| 117 | oc2ns(tm0: ref OTmsg, oldclient, newsrv: ref Sys->FD) | ||
| 118 | { | ||
| 119 | ntm: ref Tmsg; | ||
| 120 | |||
| 121 | t := ref Req(tm0.tag, -1, -1, -1, nil); | ||
| 122 | pick tm := tm0{ | ||
| 123 | Nop => | ||
| 124 | ORsend(oldclient, ref ORmsg.Nop(tm.tag)); | ||
| 125 | return; | ||
| 126 | Attach => | ||
| 127 | t.fid = tm.fid; | ||
| 128 | ntm = ref Tmsg.Attach(tm.tag, tm.fid, nstyx->NOFID, tm.uname, tm.aname); | ||
| 129 | Clone => | ||
| 130 | t.fid = tm.fid; | ||
| 131 | t.newfid = tm.newfid; | ||
| 132 | ntm = ref Tmsg.Walk(tm.tag, tm.fid, tm.newfid, nil); | ||
| 133 | Walk => | ||
| 134 | t.fid = tm.fid; | ||
| 135 | ntm = ref Tmsg.Walk(tm.tag, tm.fid, tm.fid, array[] of {tm.name}); | ||
| 136 | Flush => | ||
| 137 | t.oldtag = tm.oldtag; | ||
| 138 | ntm = ref Tmsg.Flush(tm.tag, tm.oldtag); | ||
| 139 | Open => | ||
| 140 | t.fid = tm.fid; | ||
| 141 | ntm = ref Tmsg.Open(tm.tag, tm.fid, tm.mode); | ||
| 142 | Create => | ||
| 143 | t.fid = tm.fid; | ||
| 144 | ntm = ref Tmsg.Create(tm.tag, tm.fid, tm.name, tm.perm, tm.mode); | ||
| 145 | Read => | ||
| 146 | t.fid = tm.fid; | ||
| 147 | fp := findfid(tm.fid); | ||
| 148 | count := tm.count; | ||
| 149 | offset := tm.offset; | ||
| 150 | if(fp.isdir){ | ||
| 151 | count = (count/OStyx->DIRLEN)*OStyx->DIRLEN; | ||
| 152 | # if we got some extra entries last time, | ||
| 153 | # then send 'em back this time. | ||
| 154 | extras := fp.extras; | ||
| 155 | if(len extras > 0){ | ||
| 156 | if(count > len extras) | ||
| 157 | count = len extras; | ||
| 158 | ORsend(oldclient, ref ORmsg.Read(tm.tag, t.fid, fp.extras[0:count])); | ||
| 159 | fp.extras = extras[count:]; | ||
| 160 | fp.coff += count; | ||
| 161 | return; | ||
| 162 | } | ||
| 163 | fp.n = count; | ||
| 164 | if(int offset != fp.coff){ | ||
| 165 | ORsend(oldclient, ref ORmsg.Error(tm.tag, "unexpected offset in dirread")); | ||
| 166 | return; | ||
| 167 | } | ||
| 168 | offset = big fp.soff; | ||
| 169 | } | ||
| 170 | ntm = ref Tmsg.Read(tm.tag, tm.fid, offset, count); | ||
| 171 | Write => | ||
| 172 | t.fid = tm.fid; | ||
| 173 | ntm = ref Tmsg.Write(tm.tag, tm.fid, tm.offset, tm.data); | ||
| 174 | Clunk => | ||
| 175 | t.fid = tm.fid; | ||
| 176 | ntm = ref Tmsg.Clunk(tm.tag, tm.fid); | ||
| 177 | Remove => | ||
| 178 | t.fid = tm.fid; | ||
| 179 | ntm = ref Tmsg.Remove(tm.tag, tm.fid); | ||
| 180 | Stat => | ||
| 181 | t.fid = tm.fid; | ||
| 182 | ntm = ref Tmsg.Stat(tm.tag, tm.fid); | ||
| 183 | Wstat => | ||
| 184 | t.fid = tm.fid; | ||
| 185 | ntm = ref Tmsg.Wstat(tm.tag, tm.fid, od2nd(tm.stat)); | ||
| 186 | * => | ||
| 187 | fatal("bad T message"); | ||
| 188 | } | ||
| 189 | storetag(t); | ||
| 190 | NTsend(newsrv, ntm); | ||
| 191 | } | ||
| 192 | |||
| 193 | # R messages: new to old | ||
| 194 | ns2oc(t: ref Req, nrm0: ref Rmsg, oldclient: ref Sys->FD) | ||
| 195 | { | ||
| 196 | rm: ref ORmsg; | ||
| 197 | pick nrm := nrm0{ | ||
| 198 | Error => | ||
| 199 | rm = ref ORmsg.Error(nrm.tag, nrm.ename); | ||
| 200 | Flush => | ||
| 201 | rm = ref ORmsg.Flush(nrm.tag); | ||
| 202 | deletetag(t.oldtag); | ||
| 203 | Walk => | ||
| 204 | if(len nrm.qids == 0){ | ||
| 205 | clonefid(t.fid, t.newfid); | ||
| 206 | rm = ref ORmsg.Clone(nrm.tag, t.fid); | ||
| 207 | }else{ | ||
| 208 | q := nrm.qids[0]; | ||
| 209 | setfid(t.fid, q); | ||
| 210 | rm = ref ORmsg.Walk(nrm.tag, t.fid, nq2oq(q)); | ||
| 211 | } | ||
| 212 | Open => | ||
| 213 | setfid(t.fid, nrm.qid); | ||
| 214 | rm = ref ORmsg.Open(nrm.tag, t.fid, nq2oq(nrm.qid)); | ||
| 215 | Create => | ||
| 216 | setfid(t.fid, nrm.qid); | ||
| 217 | rm = ref ORmsg.Create(nrm.tag, t.fid, nq2oq(nrm.qid)); | ||
| 218 | Read => | ||
| 219 | fp := findfid(t.fid); | ||
| 220 | data := nrm.data; | ||
| 221 | if(fp != nil && fp.isdir){ | ||
| 222 | data = nds2ods(data); | ||
| 223 | if(len data > fp.n){ | ||
| 224 | fp.extras = data[fp.n:]; | ||
| 225 | data = data[0:fp.n]; | ||
| 226 | } | ||
| 227 | fp.coff += len data; | ||
| 228 | fp.soff += len nrm.data; | ||
| 229 | } | ||
| 230 | rm = ref ORmsg.Read(nrm.tag, t.fid, data); | ||
| 231 | Write => | ||
| 232 | rm = ref ORmsg.Write(nrm.tag, t.fid, nrm.count); | ||
| 233 | Clunk => | ||
| 234 | deletefid(t.fid); | ||
| 235 | rm = ref ORmsg.Clunk(nrm.tag, t.fid); | ||
| 236 | Remove => | ||
| 237 | deletefid(t.fid); | ||
| 238 | rm = ref ORmsg.Remove(nrm.tag, t.fid); | ||
| 239 | Stat => | ||
| 240 | rm = ref ORmsg.Stat(nrm.tag, t.fid, nd2od(nrm.stat)); | ||
| 241 | Wstat => | ||
| 242 | rm = ref ORmsg.Wstat(nrm.tag, t.fid); | ||
| 243 | Attach => | ||
| 244 | newfid(t.fid, nrm.qid.qtype & NSys->QTDIR); | ||
| 245 | rm = ref ORmsg.Attach(nrm.tag, t.fid, nq2oq(nrm.qid)); | ||
| 246 | * => | ||
| 247 | fatal("bad R message"); | ||
| 248 | } | ||
| 249 | ORsend(oldclient, rm); | ||
| 250 | } | ||
| 251 | |||
| 252 | storetag(t: ref Req) | ||
| 253 | { | ||
| 254 | t.next = tags; | ||
| 255 | tags = t; | ||
| 256 | } | ||
| 257 | |||
| 258 | looktag(tag: int): ref Req | ||
| 259 | { | ||
| 260 | for(t := tags; t != nil; t = t.next) | ||
| 261 | if(t.tag == tag) | ||
| 262 | return t; | ||
| 263 | return nil; | ||
| 264 | } | ||
| 265 | |||
| 266 | deletetag(tag: int) | ||
| 267 | { | ||
| 268 | prev: ref Req; | ||
| 269 | t := tags; | ||
| 270 | while(t != nil){ | ||
| 271 | if(t.tag == tag){ | ||
| 272 | next := t.next; | ||
| 273 | t.next = nil; | ||
| 274 | if(prev != nil) | ||
| 275 | prev.next = next; | ||
| 276 | else | ||
| 277 | tags = next; | ||
| 278 | t = next; | ||
| 279 | }else{ | ||
| 280 | prev = t; | ||
| 281 | t = t.next; | ||
| 282 | } | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | newfid(fid: int, isdir: int): ref Fid | ||
| 287 | { | ||
| 288 | f := ref Fid; | ||
| 289 | f.fid = fid; | ||
| 290 | f.isdir = isdir; | ||
| 291 | f.n = f.soff = f.coff = 0; | ||
| 292 | f.next = fids; | ||
| 293 | fids = f; | ||
| 294 | return f; | ||
| 295 | } | ||
| 296 | |||
| 297 | clonefid(ofid: int, fid: int): ref Fid | ||
| 298 | { | ||
| 299 | if((f := findfid(ofid)) != nil) | ||
| 300 | return newfid(fid, f.isdir); | ||
| 301 | warning("clone of non-existent fid"); | ||
| 302 | return newfid(fid, 0); | ||
| 303 | } | ||
| 304 | |||
| 305 | deletefid(fid: int) | ||
| 306 | { | ||
| 307 | lf: ref Fid; | ||
| 308 | |||
| 309 | for(f := fids; f != nil; f = f.next){ | ||
| 310 | if(f.fid == fid){ | ||
| 311 | if(lf == nil) | ||
| 312 | fids = f.next; | ||
| 313 | else | ||
| 314 | lf.next = f.next; | ||
| 315 | return; | ||
| 316 | } | ||
| 317 | lf = f; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | findfid(fid: int): ref Fid | ||
| 322 | { | ||
| 323 | for(f := fids; f != nil && f.fid != fid; f = f.next) | ||
| 324 | ; | ||
| 325 | return f; | ||
| 326 | } | ||
| 327 | |||
| 328 | setfid(fid: int, qid: NSys->Qid) | ||
| 329 | { | ||
| 330 | if((f := findfid(fid)) != nil) | ||
| 331 | f.isdir = qid.qtype & NSys->QTDIR; | ||
| 332 | } | ||
| 333 | |||
| 334 | om2nm(om: int): int | ||
| 335 | { | ||
| 336 | # DMDIR == CHDIR | ||
| 337 | return om; | ||
| 338 | } | ||
| 339 | |||
| 340 | nm2om(m: int): int | ||
| 341 | { | ||
| 342 | # DMDIR == CHDIR | ||
| 343 | return m&~(NSys->DMAPPEND|NSys->DMEXCL|NSys->DMAUTH); | ||
| 344 | } | ||
| 345 | |||
| 346 | oq2nq(oq: OSys->Qid): NSys->Qid | ||
| 347 | { | ||
| 348 | q: NSys->Qid; | ||
| 349 | |||
| 350 | isdir := oq.path&OSys->CHDIR; | ||
| 351 | q.path = big (oq.path&~OSys->CHDIR); | ||
| 352 | q.vers = oq.vers; | ||
| 353 | q.qtype = 0; | ||
| 354 | if(isdir) | ||
| 355 | q.qtype |= NSys->QTDIR; | ||
| 356 | return q; | ||
| 357 | } | ||
| 358 | |||
| 359 | nq2oq(q: NSys->Qid): OSys->Qid | ||
| 360 | { | ||
| 361 | oq: OSys->Qid; | ||
| 362 | |||
| 363 | isdir := q.qtype&NSys->QTDIR; | ||
| 364 | oq.path = int q.path; | ||
| 365 | oq.vers = q.vers; | ||
| 366 | if(isdir) | ||
| 367 | oq.path |= OSys->CHDIR; | ||
| 368 | return oq; | ||
| 369 | } | ||
| 370 | |||
| 371 | od2nd(od: OSys->Dir): NSys->Dir | ||
| 372 | { | ||
| 373 | d: NSys->Dir; | ||
| 374 | |||
| 375 | d.name = od.name; | ||
| 376 | d.uid = od.uid; | ||
| 377 | d.gid = od.gid; | ||
| 378 | d.muid = od.uid; | ||
| 379 | d.qid = oq2nq(od.qid); | ||
| 380 | d.mode = om2nm(od.mode); | ||
| 381 | d.atime = od.atime; | ||
| 382 | d.mtime = od.mtime; | ||
| 383 | d.length = big od.length; | ||
| 384 | d.dtype = od.dtype; | ||
| 385 | d.dev = od.dev; | ||
| 386 | return d; | ||
| 387 | } | ||
| 388 | |||
| 389 | nd2od(d: NSys->Dir): OSys->Dir | ||
| 390 | { | ||
| 391 | od: OSys->Dir; | ||
| 392 | |||
| 393 | od.name = d.name; | ||
| 394 | od.uid = d.uid; | ||
| 395 | od.gid = d.gid; | ||
| 396 | od.qid = nq2oq(d.qid); | ||
| 397 | od.mode = nm2om(d.mode); | ||
| 398 | od.atime = d.atime; | ||
| 399 | od.mtime = d.mtime; | ||
| 400 | od.length = int d.length; | ||
| 401 | od.dtype = d.dtype; | ||
| 402 | od.dev = d.dev; | ||
| 403 | return od; | ||
| 404 | } | ||
| 405 | |||
| 406 | nds2ods(ob: array of byte): array of byte | ||
| 407 | { | ||
| 408 | i := 0; | ||
| 409 | n := 0; | ||
| 410 | ds: list of NSys->Dir; | ||
| 411 | while(i < len ob){ | ||
| 412 | (size, d) := nstyx->unpackdir(ob[i:]); | ||
| 413 | if(size == 0) | ||
| 414 | break; | ||
| 415 | ds = d :: ds; | ||
| 416 | i += size; | ||
| 417 | n++; | ||
| 418 | } | ||
| 419 | b := array[OStyx->DIRLEN * n] of byte; | ||
| 420 | for(i = (n - 1) * OStyx->DIRLEN; i >= 0; i -= OStyx->DIRLEN){ | ||
| 421 | ostyx->convD2M(b[i:], nd2od(hd ds)); | ||
| 422 | ds = tl ds; | ||
| 423 | } | ||
| 424 | return b; | ||
| 425 | } | ||
| 426 | |||
| 427 | NTsend(fd: ref Sys->FD, ntm: ref Tmsg) | ||
| 428 | { | ||
| 429 | if(DEBUG) | ||
| 430 | sys->fprint(sys->fildes(2), " -> %s\n", ntm.text()); | ||
| 431 | s := ntm.pack(); | ||
| 432 | sys->write(fd, s, len s); | ||
| 433 | } | ||
| 434 | |||
| 435 | ORsend(fd: ref Sys->FD, orm: ref ORmsg) | ||
| 436 | { | ||
| 437 | if(DEBUG) | ||
| 438 | sys->fprint(sys->fildes(2), "<- %s\n", ostyx->rmsg2s(orm)); | ||
| 439 | s := array[OStyx->MAXRPC] of byte; | ||
| 440 | n := ostyx->rmsg2d(orm, s); | ||
| 441 | if(n > 0) | ||
| 442 | sys->write(fd, s, n); | ||
| 443 | } | ||
| 444 | |||
| 445 | readoldtmsgs(pidc: chan of int, oldclient: ref Sys->FD, oldtmsg: chan of ref OTmsg) | ||
| 446 | { | ||
| 447 | pidc <-= sys->pctl(0, nil); | ||
| 448 | for(;;){ | ||
| 449 | oldtmsg <-= OTmsg.read(oldclient); | ||
| 450 | } | ||
| 451 | } | ||
| 452 | |||
| 453 | readnewrmsgs(pidc: chan of int, newsrv: ref Sys->FD, newrmsg: chan of ref Rmsg) | ||
| 454 | { | ||
| 455 | pidc <-= sys->pctl(0, nil); | ||
| 456 | for(;;){ | ||
| 457 | newrmsg <-= Rmsg.read(newsrv, Msize); | ||
| 458 | } | ||
| 459 | } | ||
| 460 | |||
| 461 | warning(err: string) | ||
| 462 | { | ||
| 463 | sys->fprint(sys->fildes(2), "warning: %s\n", err); | ||
| 464 | } | ||
| 465 | |||
| 466 | fatal(err: string) | ||
| 467 | { | ||
| 468 | sys->fprint(sys->fildes(2), "%s\n", err); | ||
| 469 | exit; | ||
| 470 | } | ||
| 471 | |||
| 472 | nomod(mod: string, path: string) | ||
| 473 | { | ||
| 474 | fatal(sys->sprint("can't load %s(%s): %r", mod, path)); | ||
| 475 | } | ||
| 476 | |||
| 477 | kill(pid: int) | ||
| 478 | { | ||
| 479 | sys->fprint(sys->open("#p/"+string pid+"/ctl", Sys->OWRITE), "kill"); | ||
| 480 | } | ||
| @@ -13,43 +13,81 @@ DEBUG: con 0; · 12 unmodified lines | |||
| 13 | 13 | ||
| 14 | CHANHASHSIZE: con 32; | 14 | CHANHASHSIZE: con 32; |
| 15 | 15 | ||
| 16 | init() | ||
| 17 | { | ||
| 18 | sys = load Sys Sys->PATH; | ||
| 19 | gsofar = 0; | ||
| 20 | gdata = array[MAXRPC] of {* => byte 0}; | ||
| 21 | } | ||
| 22 | |||
| 23 | # note that this implementation fails if we're reading OTmsgs and ORmsgs | ||
| 24 | # concurrently. luckily we don't need to in styxconv. | ||
| 16 | gsofar: int; | 25 | gsofar: int; |
| 17 | gdata: array of byte; | 26 | gdata: array of byte; |
| 18 | 27 | ||
| 19 | ORmsg.read(fd: ref Sys->FD, msize: int): ref ORmsg | 28 | ORmsg.read(fd: ref Sys->FD): ref ORmsg |
| 20 | { | 29 | { |
| 21 | if(sys == nil) | 30 | mlen := 0; |
| 22 | sys = load Sys Sys->PATH; | 31 | m: ref ORmsg; |
| 23 | if(gdata == nil){ | ||
| 24 | gsofar = 0; | ||
| 25 | gdata = array[msize] of byte; | ||
| 26 | } | ||
| 27 | for (;;){ | 32 | for (;;){ |
| 28 | n := sys->read(fd, gdata[gsofar:], len gdata - gsofar); | 33 | if(gsofar > 0) |
| 29 | if(n <= 0){ | 34 | (mlen, m) = d2rmsg(gdata[0 : gsofar]); |
| 30 | m: ref ORmsg = nil; | 35 | if(mlen == 0){ |
| 31 | 36 | if(gsofar == len gdata){ | |
| 32 | if(n < 0) | 37 | ndata := array[MAXRPC] of byte; |
| 33 | m = ref ORmsg.Error(-1, sys->sprint("%r")); | 38 | ndata[0:] = gdata; |
| 39 | gdata = ndata; | ||
| 40 | } | ||
| 41 | n := sys->read(fd, gdata[gsofar:], len gdata - gsofar); | ||
| 42 | if(n <= 0) | ||
| 43 | return nil; | ||
| 44 | gsofar += n; | ||
| 45 | }else if(mlen > 0){ | ||
| 46 | if(tagof(m) == tagof(OTmsg.Write)) { | ||
| 47 | ndata := array[MAXRPC] of byte; | ||
| 48 | ndata[0:] = gdata[mlen : gsofar]; | ||
| 49 | gdata = ndata; | ||
| 50 | }else | ||
| 51 | gdata[0:] = gdata[mlen : gsofar]; | ||
| 52 | gsofar -= mlen; | ||
| 34 | return m; | 53 | return m; |
| 35 | } | 54 | }else |
| 36 | gsofar += n; | ||
| 37 | (cn, m) := d2rmsg(gdata[0: gsofar]); | ||
| 38 | if(cn == -1) | ||
| 39 | gsofar = 0; | 55 | gsofar = 0; |
| 40 | else if(cn > 0){ | 56 | } |
| 41 | if(tagof(m) == tagof(ORmsg.Read)) { | 57 | } |
| 42 | ndata := array[msize] of byte; | 58 | |
| 43 | ndata[0: ] = gdata[cn: gsofar]; | 59 | OTmsg.read(fd: ref Sys->FD): ref OTmsg |
| 60 | { | ||
| 61 | mlen := 0; | ||
| 62 | m: ref OTmsg; | ||
| 63 | for (;;){ | ||
| 64 | if(gsofar > 0) | ||
| 65 | (mlen, m) = d2tmsg(gdata[0 : gsofar]); | ||
| 66 | if(mlen == 0){ | ||
| 67 | if(gsofar == len gdata){ | ||
| 68 | ndata := array[MAXRPC] of byte; | ||
| 69 | ndata[0:] = gdata; | ||
| 70 | gdata = ndata; | ||
| 71 | } | ||
| 72 | n := sys->read(fd, gdata[gsofar:], len gdata - gsofar); | ||
| 73 | if(n <= 0) | ||
| 74 | return nil; | ||
| 75 | gsofar += n; | ||
| 76 | }else if(mlen > 0){ | ||
| 77 | if(tagof(m) == tagof(OTmsg.Write)) { | ||
| 78 | ndata := array[MAXRPC] of byte; | ||
| 79 | ndata[0:] = gdata[mlen : gsofar]; | ||
| 44 | gdata = ndata; | 80 | gdata = ndata; |
| 45 | }else | 81 | }else |
| 46 | gdata[0: ] = gdata[cn: gsofar]; | 82 | gdata[0:] = gdata[mlen : gsofar]; |
| 47 | gsofar -= cn; | 83 | gsofar -= mlen; |
| 48 | return m; | 84 | return m; |
| 49 | } | 85 | }else |
| 86 | gsofar = 0; | ||
| 50 | } | 87 | } |
| 51 | } | 88 | } |
| 52 | 89 | ||
| 90 | |||
| 53 | Styxserver.new(fd: ref Sys->FD): (chan of ref OTmsg, ref Styxserver) | 91 | Styxserver.new(fd: ref Sys->FD): (chan of ref OTmsg, ref Styxserver) |
| 54 | { | 92 | { |
| 55 | if (sys == nil) | 93 | if (sys == nil) |
| @@ -572,7 +610,6 @@ pstring(a: array of byte, s: string, n: int): array of byte · 516 unmodified lines | |||
| 572 | # convert from Dir to bytes | 610 | # convert from Dir to bytes |
| 573 | convD2M(d: array of byte, f: OSys->Dir): array of byte | 611 | convD2M(d: array of byte, f: OSys->Dir): array of byte |
| 574 | { | 612 | { |
| 575 | n := len d; | ||
| 576 | d = pstring(d, f.name, OSys->NAMELEN); | 613 | d = pstring(d, f.name, OSys->NAMELEN); |
| 577 | d = pstring(d, f.uid, OSys->NAMELEN); | 614 | d = pstring(d, f.uid, OSys->NAMELEN); |
| 578 | d = pstring(d, f.gid, OSys->NAMELEN); | 615 | d = pstring(d, f.gid, OSys->NAMELEN); |
| @@ -24,6 +24,7 @@ OStyx: module · 23 unmodified lines | |||
| 24 | devclone: fn(srv: self ref Styxserver, m: ref OTmsg.Clone): ref Chan; | 24 | devclone: fn(srv: self ref Styxserver, m: ref OTmsg.Clone): ref Chan; |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | init: fn(); | ||
| 27 | d2tmsg: fn(d: array of byte): (int, ref OTmsg); | 28 | d2tmsg: fn(d: array of byte): (int, ref OTmsg); |
| 28 | d2rmsg: fn(d: array of byte): (int, ref ORmsg); | 29 | d2rmsg: fn(d: array of byte): (int, ref ORmsg); |
| 29 | tmsg2d: fn(gm: ref OTmsg, d: array of byte): int; | 30 | tmsg2d: fn(gm: ref OTmsg, d: array of byte): int; |
| @@ -69,6 +70,7 @@ OStyx: module · 39 unmodified lines | |||
| 69 | fid: int; | 70 | fid: int; |
| 70 | uname, aname: string; | 71 | uname, aname: string; |
| 71 | } | 72 | } |
| 73 | read: fn(fd: ref Sys->FD): ref OTmsg; | ||
| 72 | }; | 74 | }; |
| 73 | 75 | ||
| 74 | ORmsg: adt { | 76 | ORmsg: adt { |
| @@ -99,7 +101,7 @@ OStyx: module · 24 unmodified lines | |||
| 99 | stat: OSys->Dir; | 101 | stat: OSys->Dir; |
| 100 | } | 102 | } |
| 101 | 103 | ||
| 102 | read: fn(fd: ref Sys->FD, msize: int): ref ORmsg; | 104 | read: fn(fd: ref Sys->FD): ref ORmsg; |
| 103 | }; | 105 | }; |
| 104 | 106 | ||
| 105 | MAXRPC: con 128 + OSys->ATOMICIO; | 107 | MAXRPC: con 128 + OSys->ATOMICIO; |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -1 +1 @@ | |||
| 1 | #define VERSION "Fourth Edition (20091119)" | 1 | #define VERSION "Fourth Edition (20091127)" |
| @@ -4,10 +4,11 @@ styxconv \- convert between old and new Styx · 3 unmodified lines | |||
| 4 | .SH SYNOPSIS | 4 | .SH SYNOPSIS |
| 5 | .EX | 5 | .EX |
| 6 | include "styxconv.m"; | 6 | include "styxconv.m"; |
| 7 | styxconv := load Styxconv Styxconv->PATH; | 7 | styxconv := load Styxconv Styxconv->PATHNEW2OLD; |
| 8 | styxconv := load Styxconv Styxconv->PATHOLD2NEW; | ||
| 8 | 9 | ||
| 9 | init: fn(); | 10 | init: fn(); |
| 10 | styxconv: fn(to: ref Sys->FD, from: ref Sys->FD, pid: chan of int); | 11 | styxconv: fn(client: ref Sys->FD, server: ref Sys->FD); |
| 11 | .EE | 12 | .EE |
| 12 | .SH DESCRIPTION | 13 | .SH DESCRIPTION |
| 13 | .B Styxconv | 14 | .B Styxconv |
| @@ -22,49 +23,46 @@ must be called before any other function in the module. · 8 unmodified lines | |||
| 22 | .PP | 23 | .PP |
| 23 | The function | 24 | The function |
| 24 | .B styxconv | 25 | .B styxconv |
| 25 | takes two file descriptors. | 26 | takes two file descriptors: |
| 26 | .I From | 27 | .I client |
| 27 | must be a connection to a file server that serves the original, older | 28 | should be a connection to a styx client requiring |
| 28 | version of Styx. | 29 | one version of the protocol; |
| 29 | .I To | 30 | .I server |
| 30 | is a connection, perhaps a pipe, to something that requires the current protocol; | 31 | should be a connection to a styx server serving |
| 31 | .B Sys->mount | 32 | the other version of the protocol. |
| 32 | for instance | 33 | There are two conversion modules: |
| 33 | (see | 34 | .B PATHNEW2OLD |
| 34 | .IR sys-bind (2)). | 35 | converts from a new client to an old server; |
| 36 | .B PATHOLD2NEW | ||
| 37 | converts from an old client to a new server. | ||
| 38 | .PP | ||
| 35 | .B Styxconv | 39 | .B Styxconv |
| 36 | is spawned by the caller, to create a process that copies messages between | 40 | should be spawned by the caller, and copies messages between |
| 37 | .I from | 41 | .I client |
| 38 | and | 42 | and |
| 39 | .IR to , | 43 | .IR server , |
| 40 | converting as required as it goes. | 44 | converting as required. |
| 41 | Its process ID is the only message sent on | ||
| 42 | channel | ||
| 43 | .IR pidc ; | ||
| 44 | it must be received by | ||
| 45 | .BR styxconv 's | ||
| 46 | caller. | ||
| 47 | See the example below. | 45 | See the example below. |
| 48 | .SH EXAMPLE | 46 | .SH EXAMPLE |
| 49 | Apply | 47 | Apply |
| 50 | .B styxconv | 48 | .B styxconv |
| 51 | to file descriptor | 49 | to file descriptor |
| 52 | .I fd | 50 | .IR fd , |
| 53 | connected to an old Styx server: | 51 | connected to an old Styx server, and return |
| 52 | a file descriptor suitable for mounting with | ||
| 53 | .IR mount (2). | ||
| 54 | .IP | 54 | .IP |
| 55 | .EX | 55 | .EX |
| 56 | cvstyx(fd: ref Sys->FD): ref Sys->FD | 56 | cvstyx(fd: ref Sys->FD): ref Sys->FD |
| 57 | { | 57 | { |
| 58 | styxconv := load Styxconv Styxconv->PATH; | 58 | styxconv := load Styxconv Styxconv->NEW2OLDPATH; |
| 59 | if(styxconv == nil) | 59 | if(styxconv == nil) |
| 60 | return nil; | 60 | return nil; |
| 61 | p := array[2] of ref Sys->FD; | 61 | p := array[2] of ref Sys->FD; |
| 62 | if(sys->pipe(p) < 0) | 62 | if(sys->pipe(p) < 0) |
| 63 | return nil; | 63 | return nil; |
| 64 | styxconv->init(); | 64 | styxconv->init(); |
| 65 | pidc := chan of int; | 65 | spawn styxconv->styxconv(p[1], fd); |
| 66 | spawn styxconv->styxconv(p[1], fd, pidc); | ||
| 67 | <-pidc; | ||
| 68 | return p[0]; | 66 | return p[0]; |
| 69 | } | 67 | } |
| 70 | .EE | 68 | .EE |
| @@ -75,3 +73,5 @@ cvstyx(fd: ref Sys->FD): ref Sys->FD · 4 unmodified lines | |||
| 75 | .IR sys-bind (2), | 73 | .IR sys-bind (2), |
| 76 | .IR sys-pipe (2), | 74 | .IR sys-pipe (2), |
| 77 | .IR intro (5) | 75 | .IR intro (5) |
| 76 | .SH BUGS | ||
| 77 | There is no provision for 9p2000 authentication. | ||
| @@ -1,9 +1,10 @@ | |||
| 1 | Styxconv: module | 1 | Styxconv: module |
| 2 | { | 2 | { |
| 3 | PATH: con "/dis/lib/styxconv/styxconv.dis"; | 3 | PATHOLD2NEW: con "/dis/lib/styxconv/old2new.dis"; |
| 4 | 4 | PATHNEW2OLD: con "/dis/lib/styxconv/new2old.dis"; | |
| 5 | |||
| 5 | # call first | 6 | # call first |
| 6 | init: fn(); | 7 | init: fn(); |
| 7 | # spawn and synchronize | 8 | # spawn and synchronize |
| 8 | styxconv: fn(in: ref Sys->FD, out: ref Sys->FD, sync: chan of int); | 9 | styxconv: fn(client: ref Sys->FD, server: ref Sys->FD); |
| 9 | }; | 10 | }; |
| @@ -133,12 +133,12 @@ ulong rdtsc32(void); · 132 unmodified lines | |||
| 133 | void screeninit(void); | 133 | void screeninit(void); |
| 134 | int screenprint(char*, ...); /* debugging */ | 134 | int screenprint(char*, ...); /* debugging */ |
| 135 | void (*screenputs)(char*, int); | 135 | void (*screenputs)(char*, int); |
| 136 | #define segflush(a,n) | 136 | int segflush(void*, ulong); |
| 137 | void syncclock(void); | 137 | void syncclock(void); |
| 138 | uvlong tscticks(uvlong*); | 138 | uvlong tscticks(uvlong*); |
| 139 | void trapenable(int, void (*)(Ureg*, void*), void*, char*); | 139 | void trapenable(int, void (*)(Ureg*, void*), void*, char*); |
| 140 | void trapinit(void); | 140 | void trapinit(void); |
| 141 | ulong _tas(ulong*); | 141 | int _tas(int*); |
| 142 | ulong umbmalloc(ulong, int, int); | 142 | ulong umbmalloc(ulong, int, int); |
| 143 | void umbfree(ulong, int); | 143 | void umbfree(ulong, int); |
| 144 | ulong umbrwmalloc(ulong, int, int); | 144 | ulong umbrwmalloc(ulong, int, int); |
| @@ -335,3 +335,9 @@ vunmap(void *va, int size) · 334 unmodified lines | |||
| 335 | if(va != nil) | 335 | if(va != nil) |
| 336 | upafree(PADDR(va), size); | 336 | upafree(PADDR(va), size); |
| 337 | } | 337 | } |
| 338 | |||
| 339 | int | ||
| 340 | segflush(void*, ulong) | ||
| 341 | { | ||
| 342 | return 0; | ||
| 343 | } | ||