History

20091204

forsyth committed 16 years ago

Commit cf8bba71 parent a77a84337 files · +1294 −77Browse files

Unified · Split

37 files
  1. CHANGES +6 −0
  2. appl/charon/build.b +1 −1
  3. appl/charon/chutils.b +4 −9
  4. appl/charon/chutils.m +0 −1
  5. appl/charon/date.b +1 −1
  6. appl/charon/gui.b +3 −3
  7. appl/charon/img.b +3 −3
  8. appl/charon/jscript.b +1 −1
  9. appl/charon/layout.b +7 −7
  10. appl/cmd/mount.b +3 −5
  11. appl/lib/styxconv/mkfile +4 −2
  12. appl/lib/styxconv/new2old.b +640 −0
  13. appl/lib/styxconv/nsys.m +51 −0
  14. appl/lib/styxconv/old2new.b +480 −0
  15. appl/lib/styxconv/ostyx.b +62 −25
  16. appl/lib/styxconv/ostyx.m +3 −1
  17. dis/charon.dis +0 −0
  18. dis/charon/build.dis +0 −0
  19. dis/charon/chutils.dis +0 −0
  20. dis/charon/date.dis +0 −0
  21. dis/charon/file.dis +0 −0
  22. dis/charon/ftp.dis +0 −0
  23. dis/charon/gui.dis +0 −0
  24. dis/charon/http.dis +0 −0
  25. dis/charon/img.dis +0 −0
  26. dis/charon/jscript.dis +0 −0
  27. dis/charon/layout.dis +0 −0
  28. dis/charon/lex.dis +0 −0
  29. dis/lib/styxconv/new2old.dis +0 −0
  30. dis/lib/styxconv/old2new.dis +0 −0
  31. dis/lib/styxconv/ostyx.dis +0 −0
  32. dis/mount.dis +0 −0
  33. include/version.h +1 −1
  34. man/2/styxconv +28 −28
  35. module/styxconv.m +4 −3
  36. os/pc/fns.h +2 −2
  37. os/pc/mmu.c +6 −0
CHANGES+6−0
@@ -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
17 20091004
28 restore "keyring" to lib section of emu/Plan9/emu
39 20090930
appl/charon/build.b+1−1
@@ -1620,7 +1620,7 @@ lexstring(s: string) : array of ref Token · 1619 unmodified lines
16201620 lastps(psl: list of ref Pstate) : ref Pstate
16211621 {
16221622 if(psl == nil)
1623− CU->raisex("EXInternal: empty pstate stack");
1623+ raise "EXInternal: empty pstate stack";
16241624 while(tl psl != nil)
16251625 psl = tl psl;
16261626 return hd psl;
appl/charon/chutils.b+4−9
@@ -1227,14 +1227,14 @@ ResourceState.cur() : ResourceState · 1226 unmodified lines
12271227 if(mfd == nil)
12281228 mfd = sys->open("/dev/memory", sys->OREAD);
12291229 if (mfd == nil)
1230− raisex(sys->sprint("can't open /dev/memory: %r"));
1230+ raise sys->sprint("can't open /dev/memory: %r");
12311231
12321232 sys->seek(mfd, big 0, Sys->SEEKSTART);
12331233
12341234 buf := array[400] of byte;
12351235 n := sys->read(mfd, buf, len buf);
12361236 if (n <= 0)
1237− raisex(sys->sprint("can't read /dev/memory: %r"));
1237+ raise sys->sprint("can't read /dev/memory: %r");
12381238
12391239 (nil, l) := sys->tokenize(string buf[0:n], "\n");
12401240 # 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
17631763 ans[i].key = a[i];
17641764 ans[i].val = i;
17651765 if(i > 0 && a[i] < a[i-1])
1766− raisex("EXInternal: table out of alphabetical order");
1766+ raise "EXInternal: table out of alphabetical order";
17671767 }
17681768 return ans;
17691769 }
@@ -1866,15 +1866,10 @@ min(a,b: int) : int · 96 unmodified lines
18661866 return b;
18671867 }
18681868
1869−raisex(e: string)
1870−{
1871− raise e;
1872−}
1873−
18741869 assert(i: int)
18751870 {
18761871 if(!i) {
1877− raisex("EXInternal: assertion failed");
1872+ raise "EXInternal: assertion failed";
18781873 # sys->print("assertion failed\n");
18791874 # s := hmeth[-1];
18801875 }
appl/charon/chutils.m+0−1
@@ -360,7 +360,6 @@ CharonUtils: module · 359 unmodified lines
360360 color: fn(s: string, dflt: int) : int;
361361 max: fn(a, b : int) : int;
362362 min: fn(a, b : int) : int;
363− raisex: fn(e: string);
364363 assert: fn(i: int);
365364 stripscript: fn(s: string) : string; # strip HTML comments from Script
366365 getconv: fn(chset : string) : Btos;
appl/charon/date.b+1−1
@@ -23,7 +23,7 @@ init(cu: CharonUtils) · 22 unmodified lines
2323 CU = cu;
2424 daytime = load Daytime Daytime->PATH;
2525 if (daytime==nil)
26− CU->raisex(sys->sprint("EXInternal: can't load Daytime: %r"));
26+ raise sys->sprint("EXInternal: can't load Daytime: %r");
2727 }
2828
2929 # print dates in the format
appl/charon/gui.b+3−3
@@ -98,7 +98,7 @@ init(ctxt: ref Draw->Context, cu: CharonUtils): ref Draw->Context · 97 unmodified lines
9898 tk = load Tk Tk->PATH;
9999 tkclient = load Tkclient Tkclient->PATH;
100100 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");
102102 tkclient->init();
103103
104104 wmctl: chan of string;
@@ -386,11 +386,11 @@ makewins() · 281 unmodified lines
386386 realwin = screen.newwindow(r, D->Refnone, D->White);
387387 realwin.origin(ZP, r.min);
388388 if(realwin == nil)
389− CU->raisex(sys->sprint("EXFatal: can't initialize windows: %r"));
389+ raise sys->sprint("EXFatal: can't initialize windows: %r");
390390
391391 mainwin = display.newimage(realwin.r, realwin.chans, 0, D->White);
392392 if(mainwin == nil)
393− CU->raisex(sys->sprint("EXFatal: can't initialize windows: %r"));
393+ raise sys->sprint("EXFatal: can't initialize windows: %r");
394394 }
395395
396396 hidewins()
appl/charon/img.b+3−3
@@ -161,7 +161,7 @@ imgerror(is: ref ImageSource, msg: string) · 160 unmodified lines
161161 is.err = msg;
162162 if(dbg)
163163 sys->print("Image error: %s\n", msg);
164− CU->raisex("exImageerror:");
164+ raise "exImageerror:";
165165 }
166166
167167 # Get next char or raise exception if cannot
@@ -179,7 +179,7 @@ getc(is: ref ImageSource) : int · 11 unmodified lines
179179 ungetc(is: ref ImageSource)
180180 {
181181 if(is.i == 0)
182− CU->raisex("EXInternal: ungetc past beginning of buffer");
182+ raise "EXInternal: ungetc past beginning of buffer";
183183 is.i--;
184184 }
185185
@@ -190,7 +190,7 @@ ungetc2(is: ref ImageSource, nil: byte) · 4 unmodified lines
190190 {
191191 if(is.i < 2) {
192192 if(is.i != 1)
193− CU->raisex("EXInternal: ungetc2 past beginning of buffer");
193+ raise "EXInternal: ungetc2 past beginning of buffer";
194194 is.i = 0;
195195 }
196196 else
appl/charon/jscript.b+1−1
@@ -2107,7 +2107,7 @@ specindex(class: string) : int · 2106 unmodified lines
21072107 if(objspecs[i].name == class)
21082108 break;
21092109 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;
21112111 return i;
21122112 }
21132113
appl/charon/layout.b+7−7
@@ -516,7 +516,7 @@ createvscroll(f: ref Frame) · 515 unmodified lines
516516 f.vscr.r = f.vscr.r.addpt(Point(f.cr.max.x-breadth, f.cr.min.y));
517517 f.cr.max.x -= breadth;
518518 if(f.cr.dx() <= 2*f.marginw)
519− CU->raisex("EXInternal: frame too small for layout");
519+ raise "EXInternal: frame too small for layout";
520520 f.vscr.draw(1);
521521 }
522522
@@ -531,7 +531,7 @@ createhscroll(f: ref Frame) · 8 unmodified lines
531531 f.hscr.r = f.hscr.r.addpt(Point(x,f.cr.max.y-breadth));
532532 f.cr.max.y -= breadth;
533533 if(f.cr.dy() <= 2*f.marginh)
534− CU->raisex("EXInternal: frame too small for layout");
534+ raise "EXInternal: frame too small for layout";
535535 f.hscr.draw(1);
536536 }
537537
@@ -985,7 +985,7 @@ fixlinegeom(f: ref Frame, lay: ref Lay, l: ref Line) · 447 unmodified lines
985985 # line is complete, next line will start with it (or it is nil)
986986 rest := it;
987987 if(lastit == nil)
988− CU->raisex("EXInternal: no items on line");
988+ raise "EXInternal: no items on line";
989989 lastit.next = nil;
990990
991991 l.width = w;
@@ -1087,7 +1087,7 @@ getfont(num: int) : ref Font · 95 unmodified lines
10871087 f = Font.open(display, fonts[num].name);
10881088 if(f == nil) {
10891089 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);
10911091 else {
10921092 if(int (CU->config).dbg['w'])
10931093 sys->print("warning: substituting default for font %s\n",
@@ -2389,7 +2389,7 @@ markchanges(loc: ref Loc) · 1295 unmodified lines
23892389 }
23902390 LEtablecell =>
23912391 if(lastf == nil)
2392− CU->raisex("EXInternal: markchanges no lastf");
2392+ raise "EXInternal: markchanges no lastf";
23932393 c := loc.le[i].tcell;
23942394 clay := lastf.sublays[c.layid];
23952395 if(clay != nil)
@@ -2424,7 +2424,7 @@ colorimage(rgb: int) : ref Image · 28 unmodified lines
24242424 # im := display.color(pix);
24252425 im := display.rgb((rgb>>16)&255, (rgb>>8)&255, rgb&255);
24262426 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);
24282428 x = ref Colornode(rgb, im, xhd);
24292429 colorhashtab[hv] = x;
24302430 }
@@ -3309,7 +3309,7 @@ Control.scrollset(c: self ref Control, v1, v2, vmax, nsteps, draw: int) · 878 unmodified lines
33093309 if(l <= 0)
33103310 l = 1;
33113311 if(l < 0)
3312− CU->raisex("EXInternal: negative scrollbar trough");
3312+ raise "EXInternal: negative scrollbar trough";
33133313 sc.top = l*v1/vmax;
33143314 sc.bot = l*(vmax-v2)/vmax;
33153315 if (nsteps == 0)
appl/cmd/mount.b+3−5
@@ -215,17 +215,15 @@ runcmd(sh: Sh, ctxt: ref Draw->Context, argv: list of string, stdin: ref Sys->FD · 214 unmodified lines
215215
216216 cvstyx(fd: ref Sys->FD): (ref Sys->FD, string)
217217 {
218− styxconv := load Styxconv Styxconv->PATH;
218+ styxconv := load Styxconv Styxconv->PATHNEW2OLD;
219219 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));
221221 styxconv->init();
222222 p := array[2] of ref Sys->FD;
223223 if(sys->pipe(p) < 0)
224224 return (nil, sys->sprint("can't create pipe: %r"));
225− pidc := chan of int;
226− spawn styxconv->styxconv(p[1], fd, pidc);
225+ spawn styxconv->styxconv(p[1], fd);
227226 p[1] = nil;
228− <-pidc;
229227 return (p[0], nil);
230228 }
231229
appl/lib/styxconv/mkfile+4−2
@@ -2,11 +2,13 @@ · 1 unmodified line
22
33 TARG=\
44 ostyx.dis\
5− styxconv.dis\
6−
5+ new2old.dis\
6+ old2new.dis\
7+
78 MODULES=\
89 ostyx.m\
910 osys.m\
11+ nsys.m\
1012
1113 SYSMODULES=\
1214 bufio.m\
appl/lib/styxconv/new2old.b+640−0
@@ -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+}
appl/lib/styxconv/nsys.m+51−0
@@ -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+};
appl/lib/styxconv/old2new.b+480−0
@@ -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+}
appl/lib/styxconv/ostyx.b+62−25
@@ -13,43 +13,81 @@ DEBUG: con 0; · 12 unmodified lines
1313
1414 CHANHASHSIZE: con 32;
1515
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.
1625 gsofar: int;
1726 gdata: array of byte;
1827
19−ORmsg.read(fd: ref Sys->FD, msize: int): ref ORmsg
28+ORmsg.read(fd: ref Sys->FD): ref ORmsg
2029 {
21− if(sys == nil)
22− sys = load Sys Sys->PATH;
23− if(gdata == nil){
24− gsofar = 0;
25− gdata = array[msize] of byte;
26− }
30+ mlen := 0;
31+ m: ref ORmsg;
2732 for (;;){
28− n := sys->read(fd, gdata[gsofar:], len gdata - gsofar);
29− if(n <= 0){
30− m: ref ORmsg = nil;
31−
32− if(n < 0)
33− m = ref ORmsg.Error(-1, sys->sprint("%r"));
33+ if(gsofar > 0)
34+ (mlen, m) = d2rmsg(gdata[0 : gsofar]);
35+ if(mlen == 0){
36+ if(gsofar == len gdata){
37+ ndata := array[MAXRPC] of byte;
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;
3453 return m;
35− }
36− gsofar += n;
37− (cn, m) := d2rmsg(gdata[0: gsofar]);
38− if(cn == -1)
54+ }else
3955 gsofar = 0;
40− else if(cn > 0){
41− if(tagof(m) == tagof(ORmsg.Read)) {
42− ndata := array[msize] of byte;
43− ndata[0: ] = gdata[cn: gsofar];
56+ }
57+}
58+
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];
4480 gdata = ndata;
4581 }else
46− gdata[0: ] = gdata[cn: gsofar];
47− gsofar -= cn;
82+ gdata[0:] = gdata[mlen : gsofar];
83+ gsofar -= mlen;
4884 return m;
49− }
85+ }else
86+ gsofar = 0;
5087 }
5188 }
5289
90+
5391 Styxserver.new(fd: ref Sys->FD): (chan of ref OTmsg, ref Styxserver)
5492 {
5593 if (sys == nil)
@@ -572,7 +610,6 @@ pstring(a: array of byte, s: string, n: int): array of byte · 516 unmodified lines
572610 # convert from Dir to bytes
573611 convD2M(d: array of byte, f: OSys->Dir): array of byte
574612 {
575− n := len d;
576613 d = pstring(d, f.name, OSys->NAMELEN);
577614 d = pstring(d, f.uid, OSys->NAMELEN);
578615 d = pstring(d, f.gid, OSys->NAMELEN);
appl/lib/styxconv/ostyx.m+3−1
@@ -24,6 +24,7 @@ OStyx: module · 23 unmodified lines
2424 devclone: fn(srv: self ref Styxserver, m: ref OTmsg.Clone): ref Chan;
2525 };
2626
27+ init: fn();
2728 d2tmsg: fn(d: array of byte): (int, ref OTmsg);
2829 d2rmsg: fn(d: array of byte): (int, ref ORmsg);
2930 tmsg2d: fn(gm: ref OTmsg, d: array of byte): int;
@@ -69,6 +70,7 @@ OStyx: module · 39 unmodified lines
6970 fid: int;
7071 uname, aname: string;
7172 }
73+ read: fn(fd: ref Sys->FD): ref OTmsg;
7274 };
7375
7476 ORmsg: adt {
@@ -99,7 +101,7 @@ OStyx: module · 24 unmodified lines
99101 stat: OSys->Dir;
100102 }
101103
102− read: fn(fd: ref Sys->FD, msize: int): ref ORmsg;
104+ read: fn(fd: ref Sys->FD): ref ORmsg;
103105 };
104106
105107 MAXRPC: con 128 + OSys->ATOMICIO;
dis/charon.dis+0−0

Binary file not shown.

dis/charon/build.dis+0−0

Binary file not shown.

dis/charon/chutils.dis+0−0

Binary file not shown.

dis/charon/date.dis+0−0

Binary file not shown.

dis/charon/file.dis+0−0

Binary file not shown.

dis/charon/ftp.dis+0−0

Binary file not shown.

dis/charon/gui.dis+0−0

Binary file not shown.

dis/charon/http.dis+0−0

Binary file not shown.

dis/charon/img.dis+0−0

Binary file not shown.

dis/charon/jscript.dis+0−0

Binary file not shown.

dis/charon/layout.dis+0−0

Binary file not shown.

dis/charon/lex.dis+0−0

Binary file not shown.

dis/lib/styxconv/new2old.dis+0−0

Binary file not shown.

dis/lib/styxconv/old2new.dis+0−0

Binary file not shown.

dis/lib/styxconv/ostyx.dis+0−0

Binary file not shown.

dis/mount.dis+0−0

Binary file not shown.

include/version.h+1−1
@@ -1 +1 @@
1−#define VERSION "Fourth Edition (20091119)"
1+#define VERSION "Fourth Edition (20091127)"
man/2/styxconv+28−28
@@ -4,10 +4,11 @@ styxconv \- convert between old and new Styx · 3 unmodified lines
44 .SH SYNOPSIS
55 .EX
66 include "styxconv.m";
7−styxconv := load Styxconv Styxconv->PATH;
7+styxconv := load Styxconv Styxconv->PATHNEW2OLD;
8+styxconv := load Styxconv Styxconv->PATHOLD2NEW;
89
910 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);
1112 .EE
1213 .SH DESCRIPTION
1314 .B Styxconv
@@ -22,49 +23,46 @@ must be called before any other function in the module. · 8 unmodified lines
2223 .PP
2324 The function
2425 .B styxconv
25−takes two file descriptors.
26−.I From
27−must be a connection to a file server that serves the original, older
28−version of Styx.
29−.I To
30−is a connection, perhaps a pipe, to something that requires the current protocol;
31−.B Sys->mount
32−for instance
33−(see
34−.IR sys-bind (2)).
26+takes two file descriptors:
27+.I client
28+should be a connection to a styx client requiring
29+one version of the protocol;
30+.I server
31+should be a connection to a styx server serving
32+the other version of the protocol.
33+There are two conversion modules:
34+.B PATHNEW2OLD
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
3539 .B Styxconv
36−is spawned by the caller, to create a process that copies messages between
37−.I from
40+should be spawned by the caller, and copies messages between
41+.I client
3842 and
39−.IR to ,
40−converting as required as it goes.
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.
43+.IR server ,
44+converting as required.
4745 See the example below.
4846 .SH EXAMPLE
4947 Apply
5048 .B styxconv
5149 to file descriptor
52−.I fd
53−connected to an old Styx server:
50+.IR fd ,
51+connected to an old Styx server, and return
52+a file descriptor suitable for mounting with
53+.IR mount (2).
5454 .IP
5555 .EX
5656 cvstyx(fd: ref Sys->FD): ref Sys->FD
5757 {
58− styxconv := load Styxconv Styxconv->PATH;
58+ styxconv := load Styxconv Styxconv->NEW2OLDPATH;
5959 if(styxconv == nil)
6060 return nil;
6161 p := array[2] of ref Sys->FD;
6262 if(sys->pipe(p) < 0)
6363 return nil;
6464 styxconv->init();
65− pidc := chan of int;
66− spawn styxconv->styxconv(p[1], fd, pidc);
67− <-pidc;
65+ spawn styxconv->styxconv(p[1], fd);
6866 return p[0];
6967 }
7068 .EE
@@ -75,3 +73,5 @@ cvstyx(fd: ref Sys->FD): ref Sys->FD · 4 unmodified lines
7573 .IR sys-bind (2),
7674 .IR sys-pipe (2),
7775 .IR intro (5)
76+.SH BUGS
77+There is no provision for 9p2000 authentication.
module/styxconv.m+4−3
@@ -1,9 +1,10 @@
11 Styxconv: module
22 {
3− PATH: con "/dis/lib/styxconv/styxconv.dis";
4−
3+ PATHOLD2NEW: con "/dis/lib/styxconv/old2new.dis";
4+ PATHNEW2OLD: con "/dis/lib/styxconv/new2old.dis";
5+
56 # call first
67 init: fn();
78 # 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);
910 };
os/pc/fns.h+2−2
@@ -133,12 +133,12 @@ ulong rdtsc32(void); · 132 unmodified lines
133133 void screeninit(void);
134134 int screenprint(char*, ...); /* debugging */
135135 void (*screenputs)(char*, int);
136−#define segflush(a,n)
136+int segflush(void*, ulong);
137137 void syncclock(void);
138138 uvlong tscticks(uvlong*);
139139 void trapenable(int, void (*)(Ureg*, void*), void*, char*);
140140 void trapinit(void);
141−ulong _tas(ulong*);
141+int _tas(int*);
142142 ulong umbmalloc(ulong, int, int);
143143 void umbfree(ulong, int);
144144 ulong umbrwmalloc(ulong, int, int);
os/pc/mmu.c+6−0
@@ -335,3 +335,9 @@ vunmap(void *va, int size) · 334 unmodified lines
335335 if(va != nil)
336336 upafree(PADDR(va), size);
337337 }
338+
339+int
340+segflush(void*, ulong)
341+{
342+ return 0;
343+}