1*37da2899SCharles.Forsythimplement Styxlib; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsyth# 4*37da2899SCharles.Forsyth# Copyright © 1999 Vita Nuova Limited. All rights reserved. 5*37da2899SCharles.Forsyth# Revisions copyright © 2002 Vita Nuova Holdings Limited. All rights reserved. 6*37da2899SCharles.Forsyth# 7*37da2899SCharles.Forsyth 8*37da2899SCharles.Forsythinclude "sys.m"; 9*37da2899SCharles.Forsyth sys: Sys; 10*37da2899SCharles.Forsythinclude "styx.m"; 11*37da2899SCharles.Forsyth styx: Styx; 12*37da2899SCharles.Forsyth Tmsg, Rmsg: import styx; 13*37da2899SCharles.Forsyth 14*37da2899SCharles.Forsythinclude "styxlib.m"; 15*37da2899SCharles.Forsyth 16*37da2899SCharles.ForsythCHANHASHSIZE: con 32; 17*37da2899SCharles.Forsythstarttime: int; 18*37da2899SCharles.Forsythtimefd: ref Sys->FD; 19*37da2899SCharles.Forsyth 20*37da2899SCharles.ForsythDEBUG: con 0; 21*37da2899SCharles.Forsyth 22*37da2899SCharles.Forsythinit(s: Styx): string 23*37da2899SCharles.Forsyth{ 24*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 25*37da2899SCharles.Forsyth styx = s; # our caller inits 26*37da2899SCharles.Forsyth return nil; 27*37da2899SCharles.Forsyth} 28*37da2899SCharles.Forsyth 29*37da2899SCharles.ForsythStyxserver.new(fd: ref Sys->FD): (chan of ref Tmsg, ref Styxserver) 30*37da2899SCharles.Forsyth{ 31*37da2899SCharles.Forsyth starttime = now(); 32*37da2899SCharles.Forsyth srv := ref Styxserver(fd, array[CHANHASHSIZE] of list of ref Chan, getuname(), 0); 33*37da2899SCharles.Forsyth if(fd == nil) 34*37da2899SCharles.Forsyth return (nil, srv); 35*37da2899SCharles.Forsyth tchan := chan of ref Tmsg; 36*37da2899SCharles.Forsyth sync := chan of int; 37*37da2899SCharles.Forsyth spawn tmsgreader(fd, srv, tchan, sync); 38*37da2899SCharles.Forsyth <-sync; 39*37da2899SCharles.Forsyth return (tchan, srv); 40*37da2899SCharles.Forsyth} 41*37da2899SCharles.Forsyth 42*37da2899SCharles.Forsythnow(): int 43*37da2899SCharles.Forsyth{ 44*37da2899SCharles.Forsyth if(timefd == nil){ 45*37da2899SCharles.Forsyth timefd = sys->open("/dev/time", sys->OREAD); 46*37da2899SCharles.Forsyth if(timefd == nil) 47*37da2899SCharles.Forsyth return 0; 48*37da2899SCharles.Forsyth } 49*37da2899SCharles.Forsyth buf := array[64] of byte; 50*37da2899SCharles.Forsyth sys->seek(timefd, big 0, 0); 51*37da2899SCharles.Forsyth n := sys->read(timefd, buf, len buf); 52*37da2899SCharles.Forsyth if(n < 0) 53*37da2899SCharles.Forsyth return 0; 54*37da2899SCharles.Forsyth 55*37da2899SCharles.Forsyth t := (big string buf[0:n]) / big 1000000; 56*37da2899SCharles.Forsyth return int t; 57*37da2899SCharles.Forsyth} 58*37da2899SCharles.Forsyth 59*37da2899SCharles.Forsyth 60*37da2899SCharles.Forsythgetuname(): string 61*37da2899SCharles.Forsyth{ 62*37da2899SCharles.Forsyth if ((fd := sys->open("/dev/user", Sys->OREAD)) == nil) 63*37da2899SCharles.Forsyth return "unknown"; 64*37da2899SCharles.Forsyth buf := array[Sys->NAMEMAX] of byte; 65*37da2899SCharles.Forsyth n := sys->read(fd, buf, len buf); 66*37da2899SCharles.Forsyth if (n <= 0) 67*37da2899SCharles.Forsyth return "unknown"; 68*37da2899SCharles.Forsyth return string buf[0:n]; 69*37da2899SCharles.Forsyth} 70*37da2899SCharles.Forsyth 71*37da2899SCharles.Forsythtmsgreader(fd: ref Sys->FD, srv: ref Styxserver, tchan: chan of ref Tmsg, sync: chan of int) 72*37da2899SCharles.Forsyth{ 73*37da2899SCharles.Forsyth sys->pctl(Sys->NEWFD|Sys->NEWNS, fd.fd :: nil); 74*37da2899SCharles.Forsyth sync <-= 1; 75*37da2899SCharles.Forsyth fd = sys->fildes(fd.fd); 76*37da2899SCharles.Forsyth while((m := Tmsg.read(fd, srv.msize)) != nil && tagof m != tagof Tmsg.Readerror){ 77*37da2899SCharles.Forsyth tchan <-= m; 78*37da2899SCharles.Forsyth m = nil; 79*37da2899SCharles.Forsyth } 80*37da2899SCharles.Forsyth tchan <-= m; 81*37da2899SCharles.Forsyth} 82*37da2899SCharles.Forsyth 83*37da2899SCharles.ForsythStyxserver.reply(srv: self ref Styxserver, m: ref Rmsg): int 84*37da2899SCharles.Forsyth{ 85*37da2899SCharles.Forsyth if (DEBUG) 86*37da2899SCharles.Forsyth sys->fprint(sys->fildes(2), "%s\n", m.text()); 87*37da2899SCharles.Forsyth a := m.pack(); 88*37da2899SCharles.Forsyth if(a == nil) 89*37da2899SCharles.Forsyth return -1; 90*37da2899SCharles.Forsyth return sys->write(srv.fd, a, len a); 91*37da2899SCharles.Forsyth} 92*37da2899SCharles.Forsyth 93*37da2899SCharles.ForsythStyxserver.devversion(srv: self ref Styxserver, m: ref Tmsg.Version): int 94*37da2899SCharles.Forsyth{ 95*37da2899SCharles.Forsyth if(srv.msize <= 0) 96*37da2899SCharles.Forsyth srv.msize = Styx->MAXRPC; 97*37da2899SCharles.Forsyth (msize, version) := styx->compatible(m, srv.msize, Styx->VERSION); 98*37da2899SCharles.Forsyth if(msize < 128){ 99*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, "unusable message size")); 100*37da2899SCharles.Forsyth return -1; 101*37da2899SCharles.Forsyth } 102*37da2899SCharles.Forsyth srv.msize = msize; 103*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Version(m.tag, msize, version)); 104*37da2899SCharles.Forsyth return 0; 105*37da2899SCharles.Forsyth} 106*37da2899SCharles.Forsyth 107*37da2899SCharles.ForsythStyxserver.devauth(srv: self ref Styxserver, m: ref Tmsg.Auth) 108*37da2899SCharles.Forsyth{ 109*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, "authentication not required")); 110*37da2899SCharles.Forsyth} 111*37da2899SCharles.Forsyth 112*37da2899SCharles.ForsythStyxserver.devattach(srv: self ref Styxserver, m: ref Tmsg.Attach): ref Chan 113*37da2899SCharles.Forsyth{ 114*37da2899SCharles.Forsyth c := srv.newchan(m.fid); 115*37da2899SCharles.Forsyth if (c == nil) { 116*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Einuse)); 117*37da2899SCharles.Forsyth return nil; 118*37da2899SCharles.Forsyth } 119*37da2899SCharles.Forsyth c.uname = m.uname; 120*37da2899SCharles.Forsyth c.qid.qtype = Sys->QTDIR; 121*37da2899SCharles.Forsyth c.qid.path = big 0; 122*37da2899SCharles.Forsyth c.path = "dev"; 123*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Attach(m.tag, c.qid)); 124*37da2899SCharles.Forsyth return c; 125*37da2899SCharles.Forsyth} 126*37da2899SCharles.Forsyth 127*37da2899SCharles.ForsythStyxserver.clone(srv: self ref Styxserver, oc: ref Chan, newfid: int): ref Chan 128*37da2899SCharles.Forsyth{ 129*37da2899SCharles.Forsyth c := srv.newchan(newfid); 130*37da2899SCharles.Forsyth if (c == nil) 131*37da2899SCharles.Forsyth return nil; 132*37da2899SCharles.Forsyth c.qid = oc.qid; 133*37da2899SCharles.Forsyth c.uname = oc.uname; 134*37da2899SCharles.Forsyth c.open = oc.open; 135*37da2899SCharles.Forsyth c.mode = oc.mode; 136*37da2899SCharles.Forsyth c.path = oc.path; 137*37da2899SCharles.Forsyth c.data = oc.data; 138*37da2899SCharles.Forsyth return c; 139*37da2899SCharles.Forsyth} 140*37da2899SCharles.Forsyth 141*37da2899SCharles.ForsythStyxserver.devflush(srv: self ref Styxserver, m: ref Tmsg.Flush) 142*37da2899SCharles.Forsyth{ 143*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Flush(m.tag)); 144*37da2899SCharles.Forsyth} 145*37da2899SCharles.Forsyth 146*37da2899SCharles.ForsythStyxserver.devwalk(srv: self ref Styxserver, m: ref Tmsg.Walk, 147*37da2899SCharles.Forsyth gen: Dirgenmod, tab: array of Dirtab): ref Chan 148*37da2899SCharles.Forsyth{ 149*37da2899SCharles.Forsyth c := srv.fidtochan(m.fid); 150*37da2899SCharles.Forsyth if (c == nil) { 151*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Ebadfid)); 152*37da2899SCharles.Forsyth return nil; 153*37da2899SCharles.Forsyth } 154*37da2899SCharles.Forsyth if (c.open) { 155*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Eopen)); 156*37da2899SCharles.Forsyth return nil; 157*37da2899SCharles.Forsyth } 158*37da2899SCharles.Forsyth if (!c.isdir()) { 159*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Enotdir)); 160*37da2899SCharles.Forsyth return nil; 161*37da2899SCharles.Forsyth } 162*37da2899SCharles.Forsyth # should check permissions here? 163*37da2899SCharles.Forsyth qids: array of Sys->Qid; 164*37da2899SCharles.Forsyth cc := ref *c; # walk a temporary copy 165*37da2899SCharles.Forsyth if(len m.names > 0){ 166*37da2899SCharles.Forsyth qids = array[len m.names] of Sys->Qid; 167*37da2899SCharles.Forsyth for(i := 0; i < len m.names; i++){ 168*37da2899SCharles.Forsyth for(k := 0;; k++){ 169*37da2899SCharles.Forsyth (ok, d) := gen->dirgen(srv, cc, tab, k); 170*37da2899SCharles.Forsyth if(ok < 0){ 171*37da2899SCharles.Forsyth if(i == 0) 172*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Enotfound)); 173*37da2899SCharles.Forsyth else 174*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Walk(m.tag, qids[0:i])); 175*37da2899SCharles.Forsyth return nil; 176*37da2899SCharles.Forsyth } 177*37da2899SCharles.Forsyth if (d.name == m.names[i]) { 178*37da2899SCharles.Forsyth cc.qid = d.qid; 179*37da2899SCharles.Forsyth cc.path = d.name; 180*37da2899SCharles.Forsyth qids[i] = cc.qid; 181*37da2899SCharles.Forsyth break; 182*37da2899SCharles.Forsyth } 183*37da2899SCharles.Forsyth } 184*37da2899SCharles.Forsyth } 185*37da2899SCharles.Forsyth } 186*37da2899SCharles.Forsyth # successful walk 187*37da2899SCharles.Forsyth if(m.newfid != m.fid){ 188*37da2899SCharles.Forsyth # clone/walk 189*37da2899SCharles.Forsyth nc := srv.clone(cc, m.newfid); 190*37da2899SCharles.Forsyth if(nc == nil){ 191*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Einuse)); 192*37da2899SCharles.Forsyth return nil; 193*37da2899SCharles.Forsyth } 194*37da2899SCharles.Forsyth c = nc; 195*37da2899SCharles.Forsyth }else{ 196*37da2899SCharles.Forsyth # walk c itself 197*37da2899SCharles.Forsyth c.qid = cc.qid; 198*37da2899SCharles.Forsyth c.path = cc.path; 199*37da2899SCharles.Forsyth } 200*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Walk(m.tag, qids)); 201*37da2899SCharles.Forsyth return c; 202*37da2899SCharles.Forsyth} 203*37da2899SCharles.Forsyth 204*37da2899SCharles.ForsythStyxserver.devclunk(srv: self ref Styxserver, m: ref Tmsg.Clunk): ref Chan 205*37da2899SCharles.Forsyth{ 206*37da2899SCharles.Forsyth c := srv.fidtochan(m.fid); 207*37da2899SCharles.Forsyth if (c == nil) { 208*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Ebadfid)); 209*37da2899SCharles.Forsyth return nil; 210*37da2899SCharles.Forsyth } 211*37da2899SCharles.Forsyth srv.chanfree(c); 212*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Clunk(m.tag)); 213*37da2899SCharles.Forsyth return c; 214*37da2899SCharles.Forsyth} 215*37da2899SCharles.Forsyth 216*37da2899SCharles.ForsythStyxserver.devstat(srv: self ref Styxserver, m: ref Tmsg.Stat, 217*37da2899SCharles.Forsyth gen: Dirgenmod, tab: array of Dirtab) 218*37da2899SCharles.Forsyth{ 219*37da2899SCharles.Forsyth c := srv.fidtochan(m.fid); 220*37da2899SCharles.Forsyth if (c == nil) { 221*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Ebadfid)); 222*37da2899SCharles.Forsyth return; 223*37da2899SCharles.Forsyth } 224*37da2899SCharles.Forsyth i := 0; 225*37da2899SCharles.Forsyth (ok, d) := gen->dirgen(srv, c, tab, i++); 226*37da2899SCharles.Forsyth while (ok >= 0) { 227*37da2899SCharles.Forsyth if (ok > 0 && c.qid.path == d.qid.path) { 228*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Stat(m.tag, d)); 229*37da2899SCharles.Forsyth return; 230*37da2899SCharles.Forsyth } 231*37da2899SCharles.Forsyth (ok, d) = gen->dirgen(srv, c, tab, i++); 232*37da2899SCharles.Forsyth } 233*37da2899SCharles.Forsyth # auto-generate entry for directory if not found. 234*37da2899SCharles.Forsyth # XXX this is asking for trouble, as the permissions given 235*37da2899SCharles.Forsyth # on stat() of a directory can be different from those given 236*37da2899SCharles.Forsyth # when reading the directory's entry in its parent dir. 237*37da2899SCharles.Forsyth if (c.qid.qtype & Sys->QTDIR) 238*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Stat(m.tag, devdir(c, c.qid, c.path, big 0, srv.uname, Sys->DMDIR|8r555))); 239*37da2899SCharles.Forsyth else 240*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Enotfound)); 241*37da2899SCharles.Forsyth} 242*37da2899SCharles.Forsyth 243*37da2899SCharles.ForsythStyxserver.devdirread(srv: self ref Styxserver, m: ref Tmsg.Read, 244*37da2899SCharles.Forsyth gen: Dirgenmod, tab: array of Dirtab) 245*37da2899SCharles.Forsyth{ 246*37da2899SCharles.Forsyth c := srv.fidtochan(m.fid); 247*37da2899SCharles.Forsyth if (c == nil) { 248*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Ebadfid)); 249*37da2899SCharles.Forsyth return; 250*37da2899SCharles.Forsyth } 251*37da2899SCharles.Forsyth offset := int m.offset; 252*37da2899SCharles.Forsyth data := array[m.count] of byte; 253*37da2899SCharles.Forsyth start := 0; 254*37da2899SCharles.Forsyth n := 0; 255*37da2899SCharles.Forsyth for (k := 0;; k++) { 256*37da2899SCharles.Forsyth (ok, d) := gen->dirgen(srv, c, tab, k); 257*37da2899SCharles.Forsyth if(ok < 0){ 258*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Read(m.tag, data[0:n])); 259*37da2899SCharles.Forsyth return; 260*37da2899SCharles.Forsyth } 261*37da2899SCharles.Forsyth size := styx->packdirsize(d); 262*37da2899SCharles.Forsyth if(start < offset){ 263*37da2899SCharles.Forsyth start += size; 264*37da2899SCharles.Forsyth continue; 265*37da2899SCharles.Forsyth } 266*37da2899SCharles.Forsyth if(n+size > m.count) 267*37da2899SCharles.Forsyth break; 268*37da2899SCharles.Forsyth data[n:] = styx->packdir(d); 269*37da2899SCharles.Forsyth n += size; 270*37da2899SCharles.Forsyth } 271*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Read(m.tag, data[0:n])); 272*37da2899SCharles.Forsyth} 273*37da2899SCharles.Forsyth 274*37da2899SCharles.ForsythStyxserver.devopen(srv: self ref Styxserver, m: ref Tmsg.Open, 275*37da2899SCharles.Forsyth gen: Dirgenmod, tab: array of Dirtab): ref Chan 276*37da2899SCharles.Forsyth{ 277*37da2899SCharles.Forsyth c := srv.fidtochan(m.fid); 278*37da2899SCharles.Forsyth if (c == nil) { 279*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Ebadfid)); 280*37da2899SCharles.Forsyth return nil; 281*37da2899SCharles.Forsyth } 282*37da2899SCharles.Forsyth omode := m.mode; 283*37da2899SCharles.Forsyth i := 0; 284*37da2899SCharles.Forsyth (ok, d) := gen->dirgen(srv, c, tab, i++); 285*37da2899SCharles.Forsyth while (ok >= 0) { 286*37da2899SCharles.Forsyth # XXX dev.c checks vers as well... is that desirable? 287*37da2899SCharles.Forsyth if (ok > 0 && c.qid.path == d.qid.path) { 288*37da2899SCharles.Forsyth if (openok(omode, d.mode, c.uname, d.uid, d.gid)) { 289*37da2899SCharles.Forsyth c.qid.vers = d.qid.vers; 290*37da2899SCharles.Forsyth break; 291*37da2899SCharles.Forsyth } 292*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Eperm)); 293*37da2899SCharles.Forsyth return nil; 294*37da2899SCharles.Forsyth } 295*37da2899SCharles.Forsyth (ok, d) = gen->dirgen(srv, c, tab, i++); 296*37da2899SCharles.Forsyth } 297*37da2899SCharles.Forsyth if ((c.qid.qtype & Sys->QTDIR) && omode != Sys->OREAD) { 298*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Eperm)); 299*37da2899SCharles.Forsyth return nil; 300*37da2899SCharles.Forsyth } 301*37da2899SCharles.Forsyth if ((c.mode = openmode(omode)) == -1) { 302*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Ebadarg)); 303*37da2899SCharles.Forsyth return nil; 304*37da2899SCharles.Forsyth } 305*37da2899SCharles.Forsyth c.open = 1; 306*37da2899SCharles.Forsyth c.mode = omode; 307*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Open(m.tag, c.qid, Styx->MAXFDATA)); 308*37da2899SCharles.Forsyth return c; 309*37da2899SCharles.Forsyth} 310*37da2899SCharles.Forsyth 311*37da2899SCharles.ForsythStyxserver.devremove(srv: self ref Styxserver, m: ref Tmsg.Remove): ref Chan 312*37da2899SCharles.Forsyth{ 313*37da2899SCharles.Forsyth c := srv.fidtochan(m.fid); 314*37da2899SCharles.Forsyth if (c == nil) { 315*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Ebadfid)); 316*37da2899SCharles.Forsyth return nil; 317*37da2899SCharles.Forsyth } 318*37da2899SCharles.Forsyth srv.chanfree(c); 319*37da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Eperm)); 320*37da2899SCharles.Forsyth return c; 321*37da2899SCharles.Forsyth} 322*37da2899SCharles.Forsyth 323*37da2899SCharles.ForsythStyxserver.fidtochan(srv: self ref Styxserver, fid: int): ref Chan 324*37da2899SCharles.Forsyth{ 325*37da2899SCharles.Forsyth for (l := srv.chans[fid & (CHANHASHSIZE-1)]; l != nil; l = tl l) 326*37da2899SCharles.Forsyth if ((hd l).fid == fid) 327*37da2899SCharles.Forsyth return hd l; 328*37da2899SCharles.Forsyth return nil; 329*37da2899SCharles.Forsyth} 330*37da2899SCharles.Forsyth 331*37da2899SCharles.ForsythStyxserver.chanfree(srv: self ref Styxserver, c: ref Chan) 332*37da2899SCharles.Forsyth{ 333*37da2899SCharles.Forsyth slot := c.fid & (CHANHASHSIZE-1); 334*37da2899SCharles.Forsyth nl: list of ref Chan; 335*37da2899SCharles.Forsyth for (l := srv.chans[slot]; l != nil; l = tl l) 336*37da2899SCharles.Forsyth if ((hd l).fid != c.fid) 337*37da2899SCharles.Forsyth nl = (hd l) :: nl; 338*37da2899SCharles.Forsyth srv.chans[slot] = nl; 339*37da2899SCharles.Forsyth} 340*37da2899SCharles.Forsyth 341*37da2899SCharles.ForsythStyxserver.chanlist(srv: self ref Styxserver): list of ref Chan 342*37da2899SCharles.Forsyth{ 343*37da2899SCharles.Forsyth cl: list of ref Chan; 344*37da2899SCharles.Forsyth for (i := 0; i < len srv.chans; i++) 345*37da2899SCharles.Forsyth for (l := srv.chans[i]; l != nil; l = tl l) 346*37da2899SCharles.Forsyth cl = hd l :: cl; 347*37da2899SCharles.Forsyth return cl; 348*37da2899SCharles.Forsyth} 349*37da2899SCharles.Forsyth 350*37da2899SCharles.ForsythStyxserver.newchan(srv: self ref Styxserver, fid: int): ref Chan 351*37da2899SCharles.Forsyth{ 352*37da2899SCharles.Forsyth # fid already in use 353*37da2899SCharles.Forsyth if ((c := srv.fidtochan(fid)) != nil) 354*37da2899SCharles.Forsyth return nil; 355*37da2899SCharles.Forsyth c = ref Chan; 356*37da2899SCharles.Forsyth c.qid = Sys->Qid(big 0, 0, Sys->QTFILE); 357*37da2899SCharles.Forsyth c.open = 0; 358*37da2899SCharles.Forsyth c.mode = 0; 359*37da2899SCharles.Forsyth c.fid = fid; 360*37da2899SCharles.Forsyth slot := fid & (CHANHASHSIZE-1); 361*37da2899SCharles.Forsyth srv.chans[slot] = c :: srv.chans[slot]; 362*37da2899SCharles.Forsyth return c; 363*37da2899SCharles.Forsyth} 364*37da2899SCharles.Forsyth 365*37da2899SCharles.Forsythdevdir(nil: ref Chan, qid: Sys->Qid, name: string, length: big, 366*37da2899SCharles.Forsyth user: string, perm: int): Sys->Dir 367*37da2899SCharles.Forsyth{ 368*37da2899SCharles.Forsyth d: Sys->Dir; 369*37da2899SCharles.Forsyth d.name = name; 370*37da2899SCharles.Forsyth d.qid = qid; 371*37da2899SCharles.Forsyth d.dtype = 'X'; 372*37da2899SCharles.Forsyth d.dev = 0; # XXX what should this be? 373*37da2899SCharles.Forsyth d.mode = perm; 374*37da2899SCharles.Forsyth if (qid.qtype & Sys->QTDIR) 375*37da2899SCharles.Forsyth d.mode |= Sys->DMDIR; 376*37da2899SCharles.Forsyth d.atime = starttime; # XXX should be better than this. 377*37da2899SCharles.Forsyth d.mtime = starttime; 378*37da2899SCharles.Forsyth d.length = length; 379*37da2899SCharles.Forsyth d.uid = user; 380*37da2899SCharles.Forsyth d.gid = user; 381*37da2899SCharles.Forsyth return d; 382*37da2899SCharles.Forsyth} 383*37da2899SCharles.Forsyth 384*37da2899SCharles.Forsythreadbytes(m: ref Tmsg.Read, d: array of byte): ref Rmsg.Read 385*37da2899SCharles.Forsyth{ 386*37da2899SCharles.Forsyth r := ref Rmsg.Read(m.tag, nil); 387*37da2899SCharles.Forsyth offset := int m.offset; 388*37da2899SCharles.Forsyth if (offset >= len d) 389*37da2899SCharles.Forsyth return r; 390*37da2899SCharles.Forsyth e := offset + m.count; 391*37da2899SCharles.Forsyth if (e > len d) 392*37da2899SCharles.Forsyth e = len d; 393*37da2899SCharles.Forsyth r.data = d[offset:e]; 394*37da2899SCharles.Forsyth return r; 395*37da2899SCharles.Forsyth} 396*37da2899SCharles.Forsyth 397*37da2899SCharles.Forsythreadnum(m: ref Tmsg.Read, val, size: int): ref Rmsg.Read 398*37da2899SCharles.Forsyth{ 399*37da2899SCharles.Forsyth return readbytes(m, sys->aprint("%-*d", size, val)); 400*37da2899SCharles.Forsyth} 401*37da2899SCharles.Forsyth 402*37da2899SCharles.Forsythreadstr(m: ref Tmsg.Read, d: string): ref Rmsg.Read 403*37da2899SCharles.Forsyth{ 404*37da2899SCharles.Forsyth return readbytes(m, array of byte d); 405*37da2899SCharles.Forsyth} 406*37da2899SCharles.Forsyth 407*37da2899SCharles.Forsythdirgenmodule(): Dirgenmod 408*37da2899SCharles.Forsyth{ 409*37da2899SCharles.Forsyth return load Dirgenmod "$self"; 410*37da2899SCharles.Forsyth} 411*37da2899SCharles.Forsyth 412*37da2899SCharles.Forsythdirgen(srv: ref Styxserver, c: ref Styxlib->Chan, 413*37da2899SCharles.Forsyth tab: array of Dirtab, i: int): (int, Sys->Dir) 414*37da2899SCharles.Forsyth{ 415*37da2899SCharles.Forsyth d: Sys->Dir; 416*37da2899SCharles.Forsyth if (tab == nil || i >= len tab) 417*37da2899SCharles.Forsyth return (-1, d); 418*37da2899SCharles.Forsyth return (1, devdir(c, tab[i].qid, tab[i].name, tab[i].length, srv.uname, tab[i].perm)); 419*37da2899SCharles.Forsyth} 420*37da2899SCharles.Forsyth 421*37da2899SCharles.Forsythopenmode(o: int): int 422*37da2899SCharles.Forsyth{ 423*37da2899SCharles.Forsyth OTRUNC, ORCLOSE, OREAD, ORDWR: import Sys; 424*37da2899SCharles.Forsyth if(o >= (OTRUNC|ORCLOSE|ORDWR)) 425*37da2899SCharles.Forsyth return -1; 426*37da2899SCharles.Forsyth o &= ~(OTRUNC|ORCLOSE); 427*37da2899SCharles.Forsyth if(o > ORDWR) 428*37da2899SCharles.Forsyth return -1; 429*37da2899SCharles.Forsyth return o; 430*37da2899SCharles.Forsyth} 431*37da2899SCharles.Forsyth 432*37da2899SCharles.Forsythaccess := array[] of {8r400, 8r200, 8r600, 8r100}; 433*37da2899SCharles.Forsythopenok(omode, perm: int, uname, funame, nil: string): int 434*37da2899SCharles.Forsyth{ 435*37da2899SCharles.Forsyth # XXX what should we do about groups? 436*37da2899SCharles.Forsyth # this is inadequate anyway: 437*37da2899SCharles.Forsyth # OTRUNC 438*37da2899SCharles.Forsyth # user should be allowed to open it if permission 439*37da2899SCharles.Forsyth # is allowed to others. 440*37da2899SCharles.Forsyth mode: int; 441*37da2899SCharles.Forsyth if (uname == funame) 442*37da2899SCharles.Forsyth mode = perm; 443*37da2899SCharles.Forsyth else 444*37da2899SCharles.Forsyth mode = perm << 6; 445*37da2899SCharles.Forsyth 446*37da2899SCharles.Forsyth t := access[omode & 3]; 447*37da2899SCharles.Forsyth return ((t & mode) == t); 448*37da2899SCharles.Forsyth} 449*37da2899SCharles.Forsyth 450*37da2899SCharles.ForsythChan.isdir(c: self ref Chan): int 451*37da2899SCharles.Forsyth{ 452*37da2899SCharles.Forsyth return (c.qid.qtype & Sys->QTDIR) != 0; 453*37da2899SCharles.Forsyth} 454