137da2899SCharles.Forsythimplement Styxservers; 237da2899SCharles.Forsyth 337da2899SCharles.Forsyth# 437da2899SCharles.Forsyth# Copyright © 1999 Vita Nuova Limited. All rights reserved. 537da2899SCharles.Forsyth# Revisions copyright © 2000-2003 Vita Nuova Holdings Limited. All rights reserved. 637da2899SCharles.Forsyth# 737da2899SCharles.Forsyth# Derived from Roger Peppe's Styxlib by Martin C. Atkins, 2001/2002 by 837da2899SCharles.Forsyth# adding new helper functions, and then removing Dirgenmod and its helpers 937da2899SCharles.Forsyth# 1037da2899SCharles.Forsyth# Further modified by Roger Peppe to simplify the interface by 1137da2899SCharles.Forsyth# adding the Navigator/Navop channel interface and making other changes, 1237da2899SCharles.Forsyth# including using the Styx module 1337da2899SCharles.Forsyth# 1437da2899SCharles.Forsyth# converted to revised Styx at Vita Nuova 1537da2899SCharles.Forsyth# further revised August/September 2002 1637da2899SCharles.Forsyth# 1737da2899SCharles.Forsyth# TO DO: 1837da2899SCharles.Forsyth# - directory reading interface revision? 1937da2899SCharles.Forsyth# 2037da2899SCharles.Forsyth 2137da2899SCharles.Forsythinclude "sys.m"; 2237da2899SCharles.Forsyth sys: Sys; 2337da2899SCharles.Forsyth 2437da2899SCharles.Forsythinclude "styx.m"; 2537da2899SCharles.Forsyth styx: Styx; 2637da2899SCharles.Forsyth Tmsg, Rmsg: import styx; 2737da2899SCharles.Forsyth 2837da2899SCharles.Forsythinclude "styxservers.m"; 2937da2899SCharles.Forsyth 3037da2899SCharles.ForsythCHANHASHSIZE: con 32; 3137da2899SCharles.ForsythDIRREADSIZE: con Styx->STATFIXLEN+4*20; # ``reasonable'' chunk for reading directories 3237da2899SCharles.Forsyth 3337da2899SCharles.Forsythdebug := 0; 3437da2899SCharles.Forsyth 3537da2899SCharles.Forsythinit(styxmod: Styx) 3637da2899SCharles.Forsyth{ 3737da2899SCharles.Forsyth sys = load Sys Sys->PATH; 3837da2899SCharles.Forsyth styx = styxmod; 3937da2899SCharles.Forsyth} 4037da2899SCharles.Forsyth 4137da2899SCharles.Forsythtraceset(d: int) 4237da2899SCharles.Forsyth{ 4337da2899SCharles.Forsyth debug = d; 4437da2899SCharles.Forsyth} 4537da2899SCharles.Forsyth 4637da2899SCharles.ForsythStyxserver.new(fd: ref Sys->FD, t: ref Navigator, rootpath: big): (chan of ref Tmsg, ref Styxserver) 4737da2899SCharles.Forsyth{ 4837da2899SCharles.Forsyth tchan := chan of ref Tmsg; 4937da2899SCharles.Forsyth srv := ref Styxserver(fd, array[CHANHASHSIZE] of list of ref Fid, chan[1] of int, t, rootpath, 0, nil); 5037da2899SCharles.Forsyth 5137da2899SCharles.Forsyth sync := chan of int; 5237da2899SCharles.Forsyth spawn tmsgreader(fd, srv, tchan, sync); 5337da2899SCharles.Forsyth <-sync; 5437da2899SCharles.Forsyth return (tchan, srv); 5537da2899SCharles.Forsyth} 5637da2899SCharles.Forsyth 5737da2899SCharles.Forsythtmsgreader(fd: ref Sys->FD, srv: ref Styxserver, tchan: chan of ref Tmsg, sync: chan of int) 5837da2899SCharles.Forsyth{ 5937da2899SCharles.Forsyth if(debug) 6037da2899SCharles.Forsyth sys->pctl(Sys->NEWFD|Sys->NEWNS, fd.fd :: 2 :: nil); 6137da2899SCharles.Forsyth else 6237da2899SCharles.Forsyth sys->pctl(Sys->NEWFD|Sys->NEWNS, fd.fd :: nil); 6337da2899SCharles.Forsyth sync <-= 1; 6437da2899SCharles.Forsyth fd = sys->fildes(fd.fd); 6537da2899SCharles.Forsyth m: ref Tmsg; 6637da2899SCharles.Forsyth do { 6737da2899SCharles.Forsyth m = Tmsg.read(fd, srv.msize); 6837da2899SCharles.Forsyth if(debug && m != nil) 6937da2899SCharles.Forsyth sys->fprint(sys->fildes(2), "<- %s\n", m.text()); 7037da2899SCharles.Forsyth tchan <-= m; 7137da2899SCharles.Forsyth } while(m != nil && tagof(m) != tagof(Tmsg.Readerror)); 7237da2899SCharles.Forsyth} 7337da2899SCharles.Forsyth 7437da2899SCharles.ForsythFid.clone(oc: self ref Fid, c: ref Fid): ref Fid 7537da2899SCharles.Forsyth{ 7637da2899SCharles.Forsyth # c.fid not touched, other values copied from c 7737da2899SCharles.Forsyth c.path = oc.path; 7837da2899SCharles.Forsyth c.qtype = oc.qtype; 7937da2899SCharles.Forsyth c.isopen = oc.isopen; 8037da2899SCharles.Forsyth c.mode = oc.mode; 8137da2899SCharles.Forsyth c.doffset = oc.doffset; 8237da2899SCharles.Forsyth c.uname = oc.uname; 8337da2899SCharles.Forsyth c.param = oc.param; 8437da2899SCharles.Forsyth c.data = oc.data; 8537da2899SCharles.Forsyth return c; 8637da2899SCharles.Forsyth} 8737da2899SCharles.Forsyth 8837da2899SCharles.ForsythFid.walk(c: self ref Fid, qid: Sys->Qid) 8937da2899SCharles.Forsyth{ 9037da2899SCharles.Forsyth c.path = qid.path; 9137da2899SCharles.Forsyth c.qtype = qid.qtype; 9237da2899SCharles.Forsyth} 9337da2899SCharles.Forsyth 9437da2899SCharles.ForsythFid.open(c: self ref Fid, mode: int, qid: Sys->Qid) 9537da2899SCharles.Forsyth{ 9637da2899SCharles.Forsyth c.isopen = 1; 9737da2899SCharles.Forsyth c.mode = mode; 9837da2899SCharles.Forsyth c.doffset = (0, 0); 9937da2899SCharles.Forsyth c.path = qid.path; 10037da2899SCharles.Forsyth c.qtype = qid.qtype; 10137da2899SCharles.Forsyth} 10237da2899SCharles.Forsyth 103*ad4c862fSforsythStyxserver.error(srv: self ref Styxserver, m: ref Tmsg, msg: string) 104*ad4c862fSforsyth{ 105*ad4c862fSforsyth srv.reply(ref Rmsg.Error(m.tag, msg)); 106*ad4c862fSforsyth} 107*ad4c862fSforsyth 10837da2899SCharles.ForsythStyxserver.reply(srv: self ref Styxserver, m: ref Rmsg): int 10937da2899SCharles.Forsyth{ 11037da2899SCharles.Forsyth if(debug) 11137da2899SCharles.Forsyth sys->fprint(sys->fildes(2), "-> %s\n", m.text()); 11237da2899SCharles.Forsyth if(srv.replychan != nil){ 11337da2899SCharles.Forsyth srv.replychan <-= m; 11437da2899SCharles.Forsyth return 0; 11537da2899SCharles.Forsyth } 11637da2899SCharles.Forsyth return srv.replydirect(m); 11737da2899SCharles.Forsyth} 11837da2899SCharles.Forsyth 11937da2899SCharles.ForsythStyxserver.replydirect(srv: self ref Styxserver, m: ref Rmsg): int 12037da2899SCharles.Forsyth{ 12137da2899SCharles.Forsyth if(srv.msize == 0) 12237da2899SCharles.Forsyth m = ref Rmsg.Error(m.tag, "Tversion not seen"); 12337da2899SCharles.Forsyth d := m.pack(); 12437da2899SCharles.Forsyth if(srv.msize != 0 && len d > srv.msize){ 12537da2899SCharles.Forsyth m = ref Rmsg.Error(m.tag, "Styx reply didn't fit"); 12637da2899SCharles.Forsyth d = m.pack(); 12737da2899SCharles.Forsyth } 12837da2899SCharles.Forsyth return sys->write(srv.fd, d, len d); 12937da2899SCharles.Forsyth} 13037da2899SCharles.Forsyth 13137da2899SCharles.ForsythStyxserver.attach(srv: self ref Styxserver, m: ref Tmsg.Attach): ref Fid 13237da2899SCharles.Forsyth{ 13337da2899SCharles.Forsyth (d, err) := srv.t.stat(srv.rootpath); 13437da2899SCharles.Forsyth if(d == nil) { 13537da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, err)); 13637da2899SCharles.Forsyth return nil; 13737da2899SCharles.Forsyth } 13837da2899SCharles.Forsyth if((d.qid.qtype & Sys->QTDIR) == 0) { 13937da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Enotdir)); 14037da2899SCharles.Forsyth return nil; 14137da2899SCharles.Forsyth } 14237da2899SCharles.Forsyth c := srv.newfid(m.fid); 14337da2899SCharles.Forsyth if(c == nil) { 14437da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Einuse)); 14537da2899SCharles.Forsyth return nil; 14637da2899SCharles.Forsyth } 14737da2899SCharles.Forsyth c.uname = m.uname; 14837da2899SCharles.Forsyth c.param = m.aname; 14937da2899SCharles.Forsyth c.path = d.qid.path; 15037da2899SCharles.Forsyth c.qtype = d.qid.qtype; 15137da2899SCharles.Forsyth srv.reply(ref Rmsg.Attach(m.tag, d.qid)); 15237da2899SCharles.Forsyth return c; 15337da2899SCharles.Forsyth} 15437da2899SCharles.Forsyth 15537da2899SCharles.Forsythwalk1(n: ref Navigator, c: ref Fid, name: string): (ref Sys->Dir, string) 15637da2899SCharles.Forsyth{ 15737da2899SCharles.Forsyth (d, err) := n.stat(c.path); 15837da2899SCharles.Forsyth if(d == nil) 15937da2899SCharles.Forsyth return (nil, err); 16037da2899SCharles.Forsyth if((d.qid.qtype & Sys->QTDIR) == 0) 16137da2899SCharles.Forsyth return (nil, Enotdir); 16237da2899SCharles.Forsyth if(!openok(c.uname, Styx->OEXEC, d.mode, d.uid, d.gid)) 16337da2899SCharles.Forsyth return (nil, Eperm); 16437da2899SCharles.Forsyth (d, err) = n.walk(d.qid.path, name); 16537da2899SCharles.Forsyth if(d == nil) 16637da2899SCharles.Forsyth return (nil, err); 16737da2899SCharles.Forsyth return (d, nil); 16837da2899SCharles.Forsyth} 16937da2899SCharles.Forsyth 17037da2899SCharles.ForsythStyxserver.walk(srv: self ref Styxserver, m: ref Tmsg.Walk): ref Fid 17137da2899SCharles.Forsyth{ 17237da2899SCharles.Forsyth c := srv.getfid(m.fid); 17337da2899SCharles.Forsyth if(c == nil) { 17437da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Ebadfid)); 17537da2899SCharles.Forsyth return nil; 17637da2899SCharles.Forsyth } 17737da2899SCharles.Forsyth if(c.isopen) { 17837da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Eopen)); 17937da2899SCharles.Forsyth return nil; 18037da2899SCharles.Forsyth } 18137da2899SCharles.Forsyth if(m.newfid != m.fid){ 18237da2899SCharles.Forsyth nc := srv.newfid(m.newfid); 18337da2899SCharles.Forsyth if(nc == nil){ 18437da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Einuse)); 18537da2899SCharles.Forsyth return nil; 18637da2899SCharles.Forsyth } 18737da2899SCharles.Forsyth c = c.clone(nc); 18837da2899SCharles.Forsyth } 18937da2899SCharles.Forsyth qids := array[len m.names] of Sys->Qid; 19037da2899SCharles.Forsyth oldpath := c.path; 19137da2899SCharles.Forsyth oldqtype := c.qtype; 19237da2899SCharles.Forsyth for(i := 0; i < len m.names; i++){ 19337da2899SCharles.Forsyth (d, err) := walk1(srv.t, c, m.names[i]); 19437da2899SCharles.Forsyth if(d == nil){ 19537da2899SCharles.Forsyth c.path = oldpath; # restore c 19637da2899SCharles.Forsyth c.qtype = oldqtype; 19737da2899SCharles.Forsyth if(m.newfid != m.fid) 19837da2899SCharles.Forsyth srv.delfid(c); 19937da2899SCharles.Forsyth if(i == 0) 20037da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, err)); 20137da2899SCharles.Forsyth else 20237da2899SCharles.Forsyth srv.reply(ref Rmsg.Walk(m.tag, qids[0:i])); 20337da2899SCharles.Forsyth return nil; 20437da2899SCharles.Forsyth } 20537da2899SCharles.Forsyth c.walk(d.qid); 20637da2899SCharles.Forsyth qids[i] = d.qid; 20737da2899SCharles.Forsyth } 20837da2899SCharles.Forsyth srv.reply(ref Rmsg.Walk(m.tag, qids)); 20937da2899SCharles.Forsyth return c; 21037da2899SCharles.Forsyth} 21137da2899SCharles.Forsyth 21237da2899SCharles.ForsythStyxserver.canopen(srv: self ref Styxserver, m: ref Tmsg.Open): (ref Fid, int, ref Sys->Dir, string) 21337da2899SCharles.Forsyth{ 21437da2899SCharles.Forsyth c := srv.getfid(m.fid); 21537da2899SCharles.Forsyth if(c == nil) 21637da2899SCharles.Forsyth return (nil, 0, nil, Ebadfid); 21737da2899SCharles.Forsyth if(c.isopen) 21837da2899SCharles.Forsyth return (nil, 0, nil, Eopen); 21937da2899SCharles.Forsyth (f, err) := srv.t.stat(c.path); 22037da2899SCharles.Forsyth if(f == nil) 22137da2899SCharles.Forsyth return (nil, 0, nil, err); 22237da2899SCharles.Forsyth mode := openmode(m.mode); 22337da2899SCharles.Forsyth if(mode == -1) 22437da2899SCharles.Forsyth return (nil, 0, nil, Ebadarg); 22537da2899SCharles.Forsyth if(mode != Sys->OREAD && f.qid.qtype & Sys->QTDIR) 22637da2899SCharles.Forsyth return (nil, 0, nil, Eperm); 22737da2899SCharles.Forsyth if(!openok(c.uname, m.mode, f.mode, f.uid, f.gid)) 22837da2899SCharles.Forsyth return (nil, 0, nil, Eperm); 22937da2899SCharles.Forsyth if(m.mode & Sys->ORCLOSE) { 23037da2899SCharles.Forsyth (dir, nil) := srv.t.walk(c.path, ".."); 23137da2899SCharles.Forsyth if(dir == nil || dir.qid.path == f.qid.path && dir.qid.qtype == f.qid.qtype || # can't remove root directory 23237da2899SCharles.Forsyth !openok(c.uname, Sys->OWRITE, dir.mode, dir.uid, dir.gid)) 23337da2899SCharles.Forsyth return (nil, 0, nil, Eperm); 23437da2899SCharles.Forsyth mode |= Sys->ORCLOSE; 23537da2899SCharles.Forsyth } 23637da2899SCharles.Forsyth return (c, mode, f, err); 23737da2899SCharles.Forsyth} 23837da2899SCharles.Forsyth 23937da2899SCharles.ForsythStyxserver.open(srv: self ref Styxserver, m: ref Tmsg.Open): ref Fid 24037da2899SCharles.Forsyth{ 24137da2899SCharles.Forsyth (c, mode, f, err) := srv.canopen(m); 24237da2899SCharles.Forsyth if(c == nil){ 24337da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, err)); 24437da2899SCharles.Forsyth return nil; 24537da2899SCharles.Forsyth } 24637da2899SCharles.Forsyth c.open(mode, f.qid); 24737da2899SCharles.Forsyth srv.reply(ref Rmsg.Open(m.tag, f.qid, srv.iounit())); 24837da2899SCharles.Forsyth return c; 24937da2899SCharles.Forsyth} 25037da2899SCharles.Forsyth 25137da2899SCharles.ForsythStyxserver.cancreate(srv: self ref Styxserver, m: ref Tmsg.Create): (ref Fid, int, ref Sys->Dir, string) 25237da2899SCharles.Forsyth{ 25337da2899SCharles.Forsyth c := srv.getfid(m.fid); 25437da2899SCharles.Forsyth if(c == nil) 25537da2899SCharles.Forsyth return (nil, 0, nil, Ebadfid); 25637da2899SCharles.Forsyth if(c.isopen) 25737da2899SCharles.Forsyth return (nil, 0, nil, Eopen); 25837da2899SCharles.Forsyth (d, err) := srv.t.stat(c.path); 25937da2899SCharles.Forsyth if(d == nil) 26037da2899SCharles.Forsyth return (nil, 0, nil, err); 26137da2899SCharles.Forsyth if((d.mode & Sys->DMDIR) == 0) 26237da2899SCharles.Forsyth return (nil, 0, nil, Enotdir); 26337da2899SCharles.Forsyth if(m.name == "") 26437da2899SCharles.Forsyth return (nil, 0, nil, Ename); 26537da2899SCharles.Forsyth if(m.name == "." || m.name == "..") 26637da2899SCharles.Forsyth return (nil, 0, nil, Edot); 26737da2899SCharles.Forsyth if(!openok(c.uname, Sys->OWRITE, d.mode, d.uid, d.gid)) 26837da2899SCharles.Forsyth return (nil, 0, nil, Eperm); 26937da2899SCharles.Forsyth if(srv.t.walk(d.qid.path, m.name).t0 != nil) 27037da2899SCharles.Forsyth return (nil, 0, nil, Eexists); 27137da2899SCharles.Forsyth if((mode := openmode(m.mode)) == -1) 27237da2899SCharles.Forsyth return (nil, 0, nil, Ebadarg); 27337da2899SCharles.Forsyth mode |= m.mode & Sys->ORCLOSE; # can create, so directory known to be writable 27437da2899SCharles.Forsyth f := ref Sys->zerodir; 27537da2899SCharles.Forsyth if(m.perm & Sys->DMDIR){ 27637da2899SCharles.Forsyth f.mode = m.perm & (~8r777 | (d.mode & 8r777)); 27737da2899SCharles.Forsyth f.qid.qtype = Sys->QTDIR; 27837da2899SCharles.Forsyth }else{ 27937da2899SCharles.Forsyth f.mode = m.perm & (~8r666 | (d.mode & 8r666)); 28037da2899SCharles.Forsyth f.qid.qtype = Sys->QTFILE; 28137da2899SCharles.Forsyth } 28237da2899SCharles.Forsyth f.name = m.name; 28337da2899SCharles.Forsyth f.uid = c.uname; 28437da2899SCharles.Forsyth f.muid = c.uname; 28537da2899SCharles.Forsyth f.gid = d.gid; 28637da2899SCharles.Forsyth f.dtype = d.dtype; 28737da2899SCharles.Forsyth f.dev = d.dev; 28837da2899SCharles.Forsyth # caller must supply atime, mtime, qid.path 28937da2899SCharles.Forsyth return (c, mode, f, nil); 29037da2899SCharles.Forsyth} 29137da2899SCharles.Forsyth 29237da2899SCharles.ForsythStyxserver.canread(srv: self ref Styxserver, m: ref Tmsg.Read): (ref Fid, string) 29337da2899SCharles.Forsyth{ 29437da2899SCharles.Forsyth c := srv.getfid(m.fid); 29537da2899SCharles.Forsyth if(c == nil) 29637da2899SCharles.Forsyth return (nil, Ebadfid); 29737da2899SCharles.Forsyth if(!c.isopen) 29837da2899SCharles.Forsyth return (nil, Enotopen); 29937da2899SCharles.Forsyth mode := c.mode & 3; 30037da2899SCharles.Forsyth if(mode != Sys->OREAD && mode != Sys->ORDWR) # readable modes 30137da2899SCharles.Forsyth return (nil, Eaccess); 30237da2899SCharles.Forsyth if(m.count < 0 || m.count > srv.msize-Styx->IOHDRSZ) 30337da2899SCharles.Forsyth return (nil, Ecount); 30437da2899SCharles.Forsyth if(m.offset < big 0) 30537da2899SCharles.Forsyth return (nil, Eoffset); 30637da2899SCharles.Forsyth return (c, nil); 30737da2899SCharles.Forsyth} 30837da2899SCharles.Forsyth 30937da2899SCharles.ForsythStyxserver.read(srv: self ref Styxserver, m: ref Tmsg.Read): ref Fid 31037da2899SCharles.Forsyth{ 31137da2899SCharles.Forsyth (c, err) := srv.canread(m); 31237da2899SCharles.Forsyth if(c == nil){ 31337da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, err)); 31437da2899SCharles.Forsyth return nil; 31537da2899SCharles.Forsyth } 31637da2899SCharles.Forsyth if((c.qtype & Sys->QTDIR) == 0) { 31737da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Eperm)); 31837da2899SCharles.Forsyth return nil; 31937da2899SCharles.Forsyth } 32037da2899SCharles.Forsyth if(m.count <= 0){ 32137da2899SCharles.Forsyth srv.reply(ref Rmsg.Read(m.tag, nil)); 32237da2899SCharles.Forsyth return c; 32337da2899SCharles.Forsyth } 32437da2899SCharles.Forsyth a := array[m.count] of byte; 32537da2899SCharles.Forsyth (offset, index) := c.doffset; 32637da2899SCharles.Forsyth if(int m.offset != offset){ # rescan from the beginning 32737da2899SCharles.Forsyth offset = 0; 32837da2899SCharles.Forsyth index = 0; 32937da2899SCharles.Forsyth } 33037da2899SCharles.Forsyth p := 0; 33137da2899SCharles.ForsythDread: 33237da2899SCharles.Forsyth while((d := srv.t.readdir(c.path, index, (m.count+DIRREADSIZE-1)/DIRREADSIZE)) != nil && (nd := len d) > 0){ 33337da2899SCharles.Forsyth for(i := 0; i < nd; i++) { 33437da2899SCharles.Forsyth size := styx->packdirsize(*d[i]); 33537da2899SCharles.Forsyth offset += size; 33637da2899SCharles.Forsyth index++; 33737da2899SCharles.Forsyth if(offset < int m.offset) 33837da2899SCharles.Forsyth continue; 33937da2899SCharles.Forsyth if((m.count -= size) < 0){ # won't fit, save state for next time 34037da2899SCharles.Forsyth offset -= size; 34137da2899SCharles.Forsyth index--; 34237da2899SCharles.Forsyth break Dread; 34337da2899SCharles.Forsyth } 34437da2899SCharles.Forsyth de := styx->packdir(*d[i]); 34537da2899SCharles.Forsyth a[p:] = de; 34637da2899SCharles.Forsyth p += size; 34737da2899SCharles.Forsyth } 34837da2899SCharles.Forsyth } 34937da2899SCharles.Forsyth c.doffset = (offset, index); 35037da2899SCharles.Forsyth srv.reply(ref Rmsg.Read(m.tag, a[0:p])); 35137da2899SCharles.Forsyth return c; 35237da2899SCharles.Forsyth} 35337da2899SCharles.Forsyth 35437da2899SCharles.ForsythStyxserver.canwrite(srv: self ref Styxserver, m: ref Tmsg.Write): (ref Fid, string) 35537da2899SCharles.Forsyth{ 35637da2899SCharles.Forsyth c := srv.getfid(m.fid); 35737da2899SCharles.Forsyth if(c == nil) 35837da2899SCharles.Forsyth return (nil, Ebadfid); 35937da2899SCharles.Forsyth if(!c.isopen) 36037da2899SCharles.Forsyth return (nil, Enotopen); 36137da2899SCharles.Forsyth if(c.qtype & Sys->QTDIR) 36237da2899SCharles.Forsyth return (nil, Eperm); 36337da2899SCharles.Forsyth mode := c.mode & 3; 36437da2899SCharles.Forsyth if(mode != Sys->OWRITE && mode != Sys->ORDWR) # writable modes 36537da2899SCharles.Forsyth return (nil, Eaccess); 36637da2899SCharles.Forsyth if(m.offset < big 0) 36737da2899SCharles.Forsyth return (nil, Eoffset); 36837da2899SCharles.Forsyth # could check len m.data > iounit, but since we've got it now, it doesn't matter 36937da2899SCharles.Forsyth return (c, nil); 37037da2899SCharles.Forsyth} 37137da2899SCharles.Forsyth 37237da2899SCharles.ForsythStyxserver.stat(srv: self ref Styxserver, m: ref Tmsg.Stat) 37337da2899SCharles.Forsyth{ 37437da2899SCharles.Forsyth c := srv.getfid(m.fid); 37537da2899SCharles.Forsyth if(c == nil) { 37637da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Ebadfid)); 37737da2899SCharles.Forsyth return; 37837da2899SCharles.Forsyth } 37937da2899SCharles.Forsyth (d, err) := srv.t.stat(c.path); 38037da2899SCharles.Forsyth if(d == nil) { 38137da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, err)); 38237da2899SCharles.Forsyth return; 38337da2899SCharles.Forsyth } 38437da2899SCharles.Forsyth srv.reply(ref Rmsg.Stat(m.tag, *d)); 38537da2899SCharles.Forsyth} 38637da2899SCharles.Forsyth 38737da2899SCharles.ForsythStyxserver.canremove(srv: self ref Styxserver, m: ref Tmsg.Remove): (ref Fid, big, string) 38837da2899SCharles.Forsyth{ 38937da2899SCharles.Forsyth c := srv.getfid(m.fid); 39037da2899SCharles.Forsyth if(c == nil) 39137da2899SCharles.Forsyth return (nil, big 0, Ebadfid); 39237da2899SCharles.Forsyth (dir, nil) := srv.t.walk(c.path, ".."); # this relies on .. working for non-directories 39337da2899SCharles.Forsyth if(dir == nil) 39437da2899SCharles.Forsyth return (nil, big 0, "can't find parent directory"); 39537da2899SCharles.Forsyth if(dir.qid.path == c.path && dir.qid.qtype == c.qtype || # can't remove root directory 39637da2899SCharles.Forsyth !openok(c.uname, Sys->OWRITE, dir.mode, dir.uid, dir.gid)) 39737da2899SCharles.Forsyth return (nil, big 0, Eperm); 39837da2899SCharles.Forsyth return (c, dir.qid.path, nil); 39937da2899SCharles.Forsyth} 40037da2899SCharles.Forsyth 40137da2899SCharles.ForsythStyxserver.remove(srv: self ref Styxserver, m: ref Tmsg.Remove): ref Fid 40237da2899SCharles.Forsyth{ 40337da2899SCharles.Forsyth c := srv.getfid(m.fid); 40437da2899SCharles.Forsyth if(c == nil) { 40537da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Ebadfid)); 40637da2899SCharles.Forsyth return nil; 40737da2899SCharles.Forsyth } 40837da2899SCharles.Forsyth srv.delfid(c); # Remove always clunks the fid 40937da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Eperm)); 41037da2899SCharles.Forsyth return c; 41137da2899SCharles.Forsyth} 41237da2899SCharles.Forsyth 41337da2899SCharles.ForsythStyxserver.clunk(srv: self ref Styxserver, m: ref Tmsg.Clunk): ref Fid 41437da2899SCharles.Forsyth{ 41537da2899SCharles.Forsyth c := srv.getfid(m.fid); 41637da2899SCharles.Forsyth if(c == nil) { 41737da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Ebadfid)); 41837da2899SCharles.Forsyth return nil; 41937da2899SCharles.Forsyth } 42037da2899SCharles.Forsyth srv.delfid(c); 42137da2899SCharles.Forsyth srv.reply(ref Rmsg.Clunk(m.tag)); 42237da2899SCharles.Forsyth return c; 42337da2899SCharles.Forsyth} 42437da2899SCharles.Forsyth 42537da2899SCharles.ForsythStyxserver.default(srv: self ref Styxserver, gm: ref Tmsg) 42637da2899SCharles.Forsyth{ 42737da2899SCharles.Forsyth if(gm == nil) { 42837da2899SCharles.Forsyth srv.t.c <-= nil; 42937da2899SCharles.Forsyth exit; 43037da2899SCharles.Forsyth } 43137da2899SCharles.Forsyth pick m := gm { 43237da2899SCharles.Forsyth Readerror => 43337da2899SCharles.Forsyth srv.t.c <-= nil; 43437da2899SCharles.Forsyth exit; 43537da2899SCharles.Forsyth Version => 43637da2899SCharles.Forsyth if(srv.msize <= 0) 43737da2899SCharles.Forsyth srv.msize = Styx->MAXRPC; 43837da2899SCharles.Forsyth (msize, version) := styx->compatible(m, srv.msize, Styx->VERSION); 43937da2899SCharles.Forsyth if(msize < 256){ 44037da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, "message size too small")); 44137da2899SCharles.Forsyth break; 44237da2899SCharles.Forsyth } 44337da2899SCharles.Forsyth srv.msize = msize; 44437da2899SCharles.Forsyth srv.reply(ref Rmsg.Version(m.tag, msize, version)); 44537da2899SCharles.Forsyth Auth => 44637da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, "authentication not required")); 44737da2899SCharles.Forsyth Flush => 44837da2899SCharles.Forsyth srv.reply(ref Rmsg.Flush(m.tag)); 44937da2899SCharles.Forsyth Walk => 45037da2899SCharles.Forsyth srv.walk(m); 45137da2899SCharles.Forsyth Open => 45237da2899SCharles.Forsyth srv.open(m); 45337da2899SCharles.Forsyth Create => 45437da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Eperm)); 45537da2899SCharles.Forsyth Read => 45637da2899SCharles.Forsyth srv.read(m); 45737da2899SCharles.Forsyth Write => 45837da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Eperm)); 45937da2899SCharles.Forsyth Clunk => 46037da2899SCharles.Forsyth srv.clunk(m); 46137da2899SCharles.Forsyth # to delete on ORCLOSE: 46237da2899SCharles.Forsyth # c := srv.clunk(m); 46337da2899SCharles.Forsyth # if(c != nil && c.mode & Sys->ORCLOSE) 46437da2899SCharles.Forsyth # srv.doremove(c); 46537da2899SCharles.Forsyth Stat => 46637da2899SCharles.Forsyth srv.stat(m); 46737da2899SCharles.Forsyth Remove => 46837da2899SCharles.Forsyth srv.remove(m); 46937da2899SCharles.Forsyth Wstat => 47037da2899SCharles.Forsyth srv.reply(ref Rmsg.Error(m.tag, Eperm)); 47137da2899SCharles.Forsyth Attach => 47237da2899SCharles.Forsyth srv.attach(m); 47337da2899SCharles.Forsyth * => 47437da2899SCharles.Forsyth sys->fprint(sys->fildes(2), "styxservers: unhandled Tmsg tag %d - should not happen\n", tagof gm); 47537da2899SCharles.Forsyth raise "fail: unhandled case"; 47637da2899SCharles.Forsyth } 47737da2899SCharles.Forsyth} 47837da2899SCharles.Forsyth 47937da2899SCharles.ForsythStyxserver.iounit(srv: self ref Styxserver): int 48037da2899SCharles.Forsyth{ 48137da2899SCharles.Forsyth n := srv.msize - Styx->IOHDRSZ; 48237da2899SCharles.Forsyth if(n <= 0) 48337da2899SCharles.Forsyth return 0; # unknown 48437da2899SCharles.Forsyth return n; 48537da2899SCharles.Forsyth} 48637da2899SCharles.Forsyth 48737da2899SCharles.ForsythStyxserver.getfid(srv: self ref Styxserver, fid: int): ref Fid 48837da2899SCharles.Forsyth{ 48937da2899SCharles.Forsyth # the list is safe to use without locking 49037da2899SCharles.Forsyth for(l := srv.fids[fid & (CHANHASHSIZE-1)]; l != nil; l = tl l) 49137da2899SCharles.Forsyth if((hd l).fid == fid) 49237da2899SCharles.Forsyth return hd l; 49337da2899SCharles.Forsyth return nil; 49437da2899SCharles.Forsyth} 49537da2899SCharles.Forsyth 49637da2899SCharles.ForsythStyxserver.delfid(srv: self ref Styxserver, c: ref Fid) 49737da2899SCharles.Forsyth{ 49837da2899SCharles.Forsyth slot := c.fid & (CHANHASHSIZE-1); 49937da2899SCharles.Forsyth nl: list of ref Fid; 50037da2899SCharles.Forsyth srv.fidlock <-= 1; 50137da2899SCharles.Forsyth for(l := srv.fids[slot]; l != nil; l = tl l) 50237da2899SCharles.Forsyth if((hd l).fid != c.fid) 50337da2899SCharles.Forsyth nl = (hd l) :: nl; 50437da2899SCharles.Forsyth srv.fids[slot] = nl; 50537da2899SCharles.Forsyth <-srv.fidlock; 50637da2899SCharles.Forsyth} 50737da2899SCharles.Forsyth 50837da2899SCharles.ForsythStyxserver.allfids(srv: self ref Styxserver): list of ref Fid 50937da2899SCharles.Forsyth{ 51037da2899SCharles.Forsyth cl: list of ref Fid; 51137da2899SCharles.Forsyth srv.fidlock <-= 1; 51237da2899SCharles.Forsyth for(i := 0; i < len srv.fids; i++) 51337da2899SCharles.Forsyth for(l := srv.fids[i]; l != nil; l = tl l) 51437da2899SCharles.Forsyth cl = hd l :: cl; 51537da2899SCharles.Forsyth <-srv.fidlock; 51637da2899SCharles.Forsyth return cl; 51737da2899SCharles.Forsyth} 51837da2899SCharles.Forsyth 51937da2899SCharles.ForsythStyxserver.newfid(srv: self ref Styxserver, fid: int): ref Fid 52037da2899SCharles.Forsyth{ 52137da2899SCharles.Forsyth srv.fidlock <-= 1; 52237da2899SCharles.Forsyth if((c := srv.getfid(fid)) != nil){ 52337da2899SCharles.Forsyth <-srv.fidlock; 52437da2899SCharles.Forsyth return nil; # illegal: fid in use 52537da2899SCharles.Forsyth } 52637da2899SCharles.Forsyth c = ref Fid; 52737da2899SCharles.Forsyth c.path = big -1; 52837da2899SCharles.Forsyth c.qtype = 0; 52937da2899SCharles.Forsyth c.isopen = 0; 53037da2899SCharles.Forsyth c.mode = 0; 53137da2899SCharles.Forsyth c.fid = fid; 53237da2899SCharles.Forsyth c.doffset = (0, 0); 53337da2899SCharles.Forsyth slot := fid & (CHANHASHSIZE-1); 53437da2899SCharles.Forsyth srv.fids[slot] = c :: srv.fids[slot]; 53537da2899SCharles.Forsyth <-srv.fidlock; 53637da2899SCharles.Forsyth return c; 53737da2899SCharles.Forsyth} 53837da2899SCharles.Forsyth 53937da2899SCharles.Forsythreadstr(m: ref Tmsg.Read, d: string): ref Rmsg.Read 54037da2899SCharles.Forsyth{ 54137da2899SCharles.Forsyth return readbytes(m, array of byte d); 54237da2899SCharles.Forsyth} 54337da2899SCharles.Forsyth 54437da2899SCharles.Forsythreadbytes(m: ref Tmsg.Read, d: array of byte): ref Rmsg.Read 54537da2899SCharles.Forsyth{ 54637da2899SCharles.Forsyth r := ref Rmsg.Read(m.tag, nil); 54737da2899SCharles.Forsyth if(m.offset >= big len d || m.offset < big 0) 54837da2899SCharles.Forsyth return r; 54937da2899SCharles.Forsyth offset := int m.offset; 55037da2899SCharles.Forsyth e := offset + m.count; 55137da2899SCharles.Forsyth if(e > len d) 55237da2899SCharles.Forsyth e = len d; 55337da2899SCharles.Forsyth r.data = d[offset:e]; 55437da2899SCharles.Forsyth return r; 55537da2899SCharles.Forsyth} 55637da2899SCharles.Forsyth 55737da2899SCharles.ForsythNavigator.new(c: chan of ref Navop): ref Navigator 55837da2899SCharles.Forsyth{ 55937da2899SCharles.Forsyth return ref Navigator(c, chan of (ref Sys->Dir, string)); 56037da2899SCharles.Forsyth} 56137da2899SCharles.Forsyth 56237da2899SCharles.ForsythNavigator.stat(t: self ref Navigator, q: big): (ref Sys->Dir, string) 56337da2899SCharles.Forsyth{ 56437da2899SCharles.Forsyth t.c <-= ref Navop.Stat(t.reply, q); 56537da2899SCharles.Forsyth return <-t.reply; 56637da2899SCharles.Forsyth} 56737da2899SCharles.Forsyth 56837da2899SCharles.ForsythNavigator.walk(t: self ref Navigator, q: big, name: string): (ref Sys->Dir, string) 56937da2899SCharles.Forsyth{ 57037da2899SCharles.Forsyth t.c <-= ref Navop.Walk(t.reply, q, name); 57137da2899SCharles.Forsyth return <-t.reply; 57237da2899SCharles.Forsyth} 57337da2899SCharles.Forsyth 57437da2899SCharles.ForsythNavigator.readdir(t: self ref Navigator, q: big, offset, count: int): array of ref Sys->Dir 57537da2899SCharles.Forsyth{ 57637da2899SCharles.Forsyth a := array[count] of ref Sys->Dir; 57737da2899SCharles.Forsyth t.c <-= ref Navop.Readdir(t.reply, q, offset, count); 57837da2899SCharles.Forsyth i := 0; 57937da2899SCharles.Forsyth while((d := (<-t.reply).t0) != nil) 58037da2899SCharles.Forsyth if(i < count) 58137da2899SCharles.Forsyth a[i++] = d; 58237da2899SCharles.Forsyth if(i == 0) 58337da2899SCharles.Forsyth return nil; 58437da2899SCharles.Forsyth return a[0:i]; 58537da2899SCharles.Forsyth} 58637da2899SCharles.Forsyth 58737da2899SCharles.Forsythopenmode(o: int): int 58837da2899SCharles.Forsyth{ 58937da2899SCharles.Forsyth OTRUNC, ORCLOSE, OREAD, ORDWR: import Sys; 59037da2899SCharles.Forsyth o &= ~(OTRUNC|ORCLOSE); 59137da2899SCharles.Forsyth if(o > ORDWR) 59237da2899SCharles.Forsyth return -1; 59337da2899SCharles.Forsyth return o; 59437da2899SCharles.Forsyth} 59537da2899SCharles.Forsyth 59637da2899SCharles.Forsythaccess := array[] of {8r400, 8r200, 8r600, 8r100}; 59737da2899SCharles.Forsythopenok(uname: string, omode: int, perm: int, fuid: string, fgid: string): int 59837da2899SCharles.Forsyth{ 59937da2899SCharles.Forsyth t := access[omode & 3]; 60037da2899SCharles.Forsyth if(omode & Sys->OTRUNC){ 60137da2899SCharles.Forsyth if(perm & Sys->DMDIR) 60237da2899SCharles.Forsyth return 0; 60337da2899SCharles.Forsyth t |= 8r200; 60437da2899SCharles.Forsyth } 60537da2899SCharles.Forsyth if(uname == fuid && (t&perm) == t) 60637da2899SCharles.Forsyth return 1; 60737da2899SCharles.Forsyth if(uname == fgid && (t&(perm<<3)) == t) 60837da2899SCharles.Forsyth return 1; 60937da2899SCharles.Forsyth return (t&(perm<<6)) == t; 61037da2899SCharles.Forsyth} 611