implement Dossrv; include "sys.m"; sys: Sys; include "draw.m"; include "arg.m"; include "daytime.m"; daytime: Daytime; include "styx.m"; styx: Styx; Tmsg, Rmsg: import styx; Dossrv: module{ init: fn(ctxt: ref Draw->Context, args: list of string); system: fn(ctxt: ref Draw->Context, args: list of string): string;}; arg0 := "dossrv"; deffile: string;pflag := 0;debug := 0; usage(iscmd: int): string{ sys->fprint(sys->fildes(2), "usage: %s [-v] [-s] [-F] [-c] [-S secpertrack] [-f devicefile] [-m mountpoint]\n", arg0); if(iscmd) raise "fail:usage"; return "usage";} init(nil: ref Draw->Context, args: list of string){ e := init2(nil, args, 1); if(e != nil){ sys->fprint(sys->fildes(2), "%s: %s\n", arg0, e); raise "fail:error"; }} system(nil: ref Draw->Context, args: list of string): string{ e := init2(nil, args, 0); if(e != nil) sys->fprint(sys->fildes(2), "%s: %s\n", arg0, e); return e;} nomod(s: string): string{ return sys->sprint("can't load %s: %r", s);} init2(nil: ref Draw->Context, args: list of string, iscmd: int): string{ sys = load Sys Sys->PATH; pipefd := array[2] of ref Sys->FD; srvfile := "/n/dos"; deffile = ""; # no default, for safety sectors := 0; stdin := 0; arg := load Arg Arg->PATH; if(arg == nil) return nomod(Arg->PATH); arg->init(args); arg0 = arg->progname(); while((o := arg->opt()) != 0) { case o { 'v' => if(debug & STYX_MESS) debug |= VERBOSE; debug |= STYX_MESS; 'F' => debug |= FAT_INFO; 'c' => debug |= CLUSTER_INFO; iodebug = 1; 'S' => s := arg->arg(); if(s != nil && s[0]>='0' && s[0]<='9') sectors = int s; else return usage(iscmd); 's' => stdin = 1; 'f' => deffile = arg->arg(); if(deffile == nil) return usage(iscmd); 'm' => srvfile = arg->arg(); if(srvfile == nil) return usage(iscmd); 'p' => pflag++; * => return usage(iscmd); } } args = arg->argv(); arg = nil; if(deffile == "" || !stdin && srvfile == "") return usage(iscmd); styx = load Styx Styx->PATH; if(styx == nil) return nomod(Styx->PATH); styx->init(); daytime = load Daytime Daytime->PATH; if(daytime == nil) return nomod(Daytime->PATH); iotrackinit(sectors); if(!stdin) { if(sys->pipe(pipefd) < 0) return sys->sprint("can't create pipe: %r"); }else{ pipefd[0] = nil; pipefd[1] = sys->fildes(1); } dossetup(); spawn dossrv(pipefd[1]); if(!stdin) { if(sys->mount(pipefd[0], nil, srvfile, sys->MREPL|sys->MCREATE, deffile) < 0) return sys->sprint("mount %s: %r", srvfile); } return nil;} ## Styx server# Enevermind, Eformat, Eio, Enomem, Enonexist, Enotdir, Enofid, Efidopen, Efidinuse, Eexist, Eperm, Enofilsys, Eauth, Econtig, Efull, Eopen, Ephase: con iota; errmsg := array[] of { Enevermind => "never mind", Eformat => "unknown format", Eio => "I/O error", Enomem => "server out of memory", Enonexist => "file does not exist", Enotdir => "not a directory", Enofid => "no such fid", Efidopen => "fid already open", Efidinuse => "fid in use", Eexist => "file exists", Eperm => "permission denied", Enofilsys => "no file system device specified", Eauth => "authentication failed", Econtig => "out of contiguous disk space", Efull => "file system full", Eopen => "invalid open mode", Ephase => "phase error -- directory entry not found",}; e(n: int): ref Rmsg.Error{ if(n < 0 || n >= len errmsg) return ref Rmsg.Error(0, "it's thermal problems"); return ref Rmsg.Error(0, errmsg[n]);} dossrv(rfd: ref Sys->FD){ sys->pctl(Sys->NEWFD, rfd.fd :: 2 :: nil); rfd = sys->fildes(rfd.fd); data := array[Styx->MAXRPC] of byte; while((t := Tmsg.read(rfd, 0)) != nil){ if(debug & STYX_MESS) chat(sys->sprint("%s...", t.text())); r: ref Rmsg; pick m := t { Readerror => panic(sys->sprint("mount read error: %s", m.error)); Version => r = rversion(m); Auth => r = rauth(m); Flush => r = rflush(m); Attach => r = rattach(m); Walk => r = rwalk(m); Open => r = ropen(m); Create => r = rcreate(m); Read => r = rread(m); Write => r = rwrite(m); Clunk => r = rclunk(m); Remove => r = rremove(m); Stat => r = rstat(m); Wstat => r = rwstat(m); * => panic("Styx mtype"); } pick m := r { Error => r.tag = t.tag; } rbuf := r.pack(); if(rbuf == nil) panic("Rmsg.pack"); if(debug & STYX_MESS) chat(sys->sprint("%s\n", r.text())); if(styx->write(rfd, rbuf, len rbuf) != len rbuf) panic("mount write"); } if(debug & STYX_MESS) chat("server EOF\n");} rversion(t: ref Tmsg.Version): ref Rmsg{ (msize, version) := styx->compatible(t, Styx->MAXRPC, Styx->VERSION); return ref Rmsg.Version(t.tag, msize, version);} rauth(t: ref Tmsg.Auth): ref Rmsg{ return ref Rmsg.Error(t.tag, "authentication not required");} rflush(t: ref Tmsg.Flush): ref Rmsg{ return ref Rmsg.Flush(t.tag);} rattach(t: ref Tmsg.Attach): ref Rmsg{ root := xfile(t.fid, Clean); if(root == nil) return e(Eio); if(t.aname == nil) t.aname = deffile; (xf, ec) := getxfs(t.aname); root.xf = xf; if(xf == nil) { if(root!=nil) xfile(t.fid, Clunk); return ref Rmsg.Error(t.tag, ec); } if(xf.fmt == 0 && dosfs(xf) < 0){ if(root!=nil) xfile(t.fid, Clunk); return e(Eformat); } root.qid = Sys->Qid(big 0, 0, Sys->QTDIR); root.xf.rootqid = root.qid; return ref Rmsg.Attach(t.tag, root.qid);} clone(ofl: ref Xfile, newfid: int): ref Xfile{ nfl := xfile(newfid, Clean); next := nfl.next; *nfl = *ofl; nfl.ptr = nil; nfl.next = next; nfl.fid = newfid; refxfs(nfl.xf, 1); if(ofl.ptr != nil){ dp := ref *ofl.ptr; dp.p = nil; dp.d = nil; nfl.ptr = dp; } return nfl;} walk1(f: ref Xfile, name: string): ref Rmsg.Error{ if((f.qid.qtype & Sys->QTDIR) == 0){ if(debug) chat(sys->sprint("qid.path=0x%bx...", f.qid.path)); return e(Enotdir); } if(name == ".") # can't happen return nil; if(name== "..") { if(f.qid.path == f.xf.rootqid.path) { if (debug) chat("walkup from root..."); return nil; } (r,dp) := walkup(f); if(r < 0) return e(Enonexist); f.ptr = dp; if(dp.addr == 0) { f.qid.path = f.xf.rootqid.path; f.qid.qtype = Sys->QTFILE; } else { f.qid.path = QIDPATH(dp); f.qid.qtype = Sys->QTDIR; } } else { if(getfile(f) < 0) return e(Enonexist); (r,dp) := searchdir(f, name, 0,1); putfile(f); if(r < 0) return e(Enonexist); f.ptr = dp; f.qid.path = QIDPATH(dp); f.qid.qtype = Sys->QTFILE; if(dp.addr == 0) f.qid.path = f.xf.rootqid.path; else { d := Dosdir.arr2Dd(dp.p.iobuf[dp.offset:dp.offset+DOSDIRSIZE]); if((int d.attr & DDIR) != 0) f.qid.qtype = Sys->QTDIR; } putfile(f); } return nil;} rwalk(t: ref Tmsg.Walk): ref Rmsg{ f := xfile(t.fid, Asis); if(f==nil) { if(debug) chat("no xfile..."); return e(Enofid); } nf: ref Xfile; if(t.newfid != t.fid) f = nf = clone(f, t.newfid); qids: array of Sys->Qid; if(len t.names > 0){ savedqid := f.qid; savedptr := f.ptr; qids = array[len t.names] of Sys->Qid; for(i := 0; i < len t.names; i++){ e := walk1(f, t.names[i]); if(e != nil){ f.qid = savedqid; f.ptr = savedptr; if(nf != nil) xfile(t.newfid, Clunk); if(i == 0) return e; return ref Rmsg.Walk(t.tag, qids[0:i]); } qids[i] = f.qid; } } return ref Rmsg.Walk(t.tag, qids);} ropen(t: ref Tmsg.Open): ref Rmsg{ attr: int; omode := 0; f := xfile(t.fid, Asis); if(f == nil) return e(Enofid); if((f.flags&Omodes) != 0) return e(Efidopen); dp := f.ptr; if(dp.paddr && (t.mode & Styx->ORCLOSE) != 0) { # check on parent directory of file to be deleted p := getsect(f.xf, dp.paddr); if(p == nil) return e(Eio); # 11 is the attr byte offset in a FAT directory entry attr = int p.iobuf[dp.poffset+11]; putsect(p); if((attr & int DRONLY) != 0) return e(Eperm); omode |= Orclose; } else if(t.mode & Styx->ORCLOSE) omode |= Orclose; if(getfile(f) < 0) return e(Enonexist); if(dp.addr != 0) { d := Dosdir.arr2Dd(dp.p.iobuf[dp.offset:dp.offset+DOSDIRSIZE]); attr = int d.attr; } else attr = int DDIR; case t.mode & 7 { Styx->OREAD or Styx->OEXEC => omode |= Oread; Styx->ORDWR => omode |= Oread; omode |= Owrite; if(attr & int (DRONLY|DDIR)) { putfile(f); return e(Eperm); } Styx->OWRITE => omode |= Owrite; if(attr & int (DRONLY|DDIR)) { putfile(f); return e(Eperm); } * => putfile(f); return e(Eopen); } if(t.mode & Styx->OTRUNC) { if((attr & int DDIR)!=0 || (attr & int DRONLY) != 0) { putfile(f); return e(Eperm); } if(truncfile(f) < 0) { putfile(f); return e(Eio); } } f.flags |= omode; putfile(f); return ref Rmsg.Open(t.tag, f.qid, Styx->MAXFDATA);} mkdentry(xf: ref Xfs, ndp: ref Dosptr, name: string, sname: string, islong: int, nattr: byte, start: array of byte, length: array of byte): int{ ndp.p = getsect(xf, ndp.addr); if(ndp.p == nil) return Eio; if(islong && (r := putlongname(xf, ndp, name, sname)) < 0){ putsect(ndp.p); if(r == -2) return Efull; return Eio; } nd := ref Dosdir(". "," ",byte 0,array[10] of { * => byte 0}, array[2] of { * => byte 0}, array[2] of { * => byte 0}, array[2] of { * => byte 0},array[4] of { * => byte 0}); nd.attr = nattr; puttime(nd); nd.start[0: ] = start[0: 2]; nd.length[0: ] = length[0: 4]; if(islong) putname(sname[0:8]+"."+sname[8:11], nd); else putname(name, nd); ndp.p.iobuf[ndp.offset: ] = Dosdir.Dd2arr(nd); ndp.p.flags |= BMOD; return 0;} Lines 1–500 of 3432. Load more
implement Dossrv; include "sys.m"; sys: Sys; include "draw.m"; include "arg.m"; include "daytime.m"; daytime: Daytime; include "styx.m"; styx: Styx; Tmsg, Rmsg: import styx; Dossrv: module { init: fn(ctxt: ref Draw->Context, args: list of string); system: fn(ctxt: ref Draw->Context, args: list of string): string; }; arg0 := "dossrv"; deffile: string; pflag := 0; debug := 0; usage(iscmd: int): string { sys->fprint(sys->fildes(2), "usage: %s [-v] [-s] [-F] [-c] [-S secpertrack] [-f devicefile] [-m mountpoint]\n", arg0); if(iscmd) raise "fail:usage"; return "usage"; } init(nil: ref Draw->Context, args: list of string) { e := init2(nil, args, 1); if(e != nil){ sys->fprint(sys->fildes(2), "%s: %s\n", arg0, e); raise "fail:error"; } } system(nil: ref Draw->Context, args: list of string): string { e := init2(nil, args, 0); if(e != nil) sys->fprint(sys->fildes(2), "%s: %s\n", arg0, e); return e; } nomod(s: string): string { return sys->sprint("can't load %s: %r", s); } init2(nil: ref Draw->Context, args: list of string, iscmd: int): string { sys = load Sys Sys->PATH; pipefd := array[2] of ref Sys->FD; srvfile := "/n/dos"; deffile = ""; # no default, for safety sectors := 0; stdin := 0; arg := load Arg Arg->PATH; if(arg == nil) return nomod(Arg->PATH); arg->init(args); arg0 = arg->progname(); while((o := arg->opt()) != 0) { case o { 'v' => if(debug & STYX_MESS) debug |= VERBOSE; debug |= STYX_MESS; 'F' => debug |= FAT_INFO; 'c' => debug |= CLUSTER_INFO; iodebug = 1; 'S' => s := arg->arg(); if(s != nil && s[0]>='0' && s[0]<='9') sectors = int s; else return usage(iscmd); 's' => stdin = 1; 'f' => deffile = arg->arg(); if(deffile == nil) return usage(iscmd); 'm' => srvfile = arg->arg(); if(srvfile == nil) return usage(iscmd); 'p' => pflag++; * => return usage(iscmd); } } args = arg->argv(); arg = nil; if(deffile == "" || !stdin && srvfile == "") return usage(iscmd); styx = load Styx Styx->PATH; if(styx == nil) return nomod(Styx->PATH); styx->init(); daytime = load Daytime Daytime->PATH; if(daytime == nil) return nomod(Daytime->PATH); iotrackinit(sectors); if(!stdin) { if(sys->pipe(pipefd) < 0) return sys->sprint("can't create pipe: %r"); }else{ pipefd[0] = nil; pipefd[1] = sys->fildes(1); } dossetup(); spawn dossrv(pipefd[1]); if(!stdin) { if(sys->mount(pipefd[0], nil, srvfile, sys->MREPL|sys->MCREATE, deffile) < 0) return sys->sprint("mount %s: %r", srvfile); } return nil; } # # Styx server # Enevermind, Eformat, Eio, Enomem, Enonexist, Enotdir, Enofid, Efidopen, Efidinuse, Eexist, Eperm, Enofilsys, Eauth, Econtig, Efull, Eopen, Ephase: con iota; errmsg := array[] of { Enevermind => "never mind", Eformat => "unknown format", Eio => "I/O error", Enomem => "server out of memory", Enonexist => "file does not exist", Enotdir => "not a directory", Enofid => "no such fid", Efidopen => "fid already open", Efidinuse => "fid in use", Eexist => "file exists", Eperm => "permission denied", Enofilsys => "no file system device specified", Eauth => "authentication failed", Econtig => "out of contiguous disk space", Efull => "file system full", Eopen => "invalid open mode", Ephase => "phase error -- directory entry not found", }; e(n: int): ref Rmsg.Error { if(n < 0 || n >= len errmsg) return ref Rmsg.Error(0, "it's thermal problems"); return ref Rmsg.Error(0, errmsg[n]); } dossrv(rfd: ref Sys->FD) { sys->pctl(Sys->NEWFD, rfd.fd :: 2 :: nil); rfd = sys->fildes(rfd.fd); data := array[Styx->MAXRPC] of byte; while((t := Tmsg.read(rfd, 0)) != nil){ if(debug & STYX_MESS) chat(sys->sprint("%s...", t.text())); r: ref Rmsg; pick m := t { Readerror => panic(sys->sprint("mount read error: %s", m.error)); Version => r = rversion(m); Auth => r = rauth(m); Flush => r = rflush(m); Attach => r = rattach(m); Walk => r = rwalk(m); Open => r = ropen(m); Create => r = rcreate(m); Read => r = rread(m); Write => r = rwrite(m); Clunk => r = rclunk(m); Remove => r = rremove(m); Stat => r = rstat(m); Wstat => r = rwstat(m); * => panic("Styx mtype"); } pick m := r { Error => r.tag = t.tag; } rbuf := r.pack(); if(rbuf == nil) panic("Rmsg.pack"); if(debug & STYX_MESS) chat(sys->sprint("%s\n", r.text())); if(styx->write(rfd, rbuf, len rbuf) != len rbuf) panic("mount write"); } if(debug & STYX_MESS) chat("server EOF\n"); } rversion(t: ref Tmsg.Version): ref Rmsg { (msize, version) := styx->compatible(t, Styx->MAXRPC, Styx->VERSION); return ref Rmsg.Version(t.tag, msize, version); } rauth(t: ref Tmsg.Auth): ref Rmsg { return ref Rmsg.Error(t.tag, "authentication not required"); } rflush(t: ref Tmsg.Flush): ref Rmsg { return ref Rmsg.Flush(t.tag); } rattach(t: ref Tmsg.Attach): ref Rmsg { root := xfile(t.fid, Clean); if(root == nil) return e(Eio); if(t.aname == nil) t.aname = deffile; (xf, ec) := getxfs(t.aname); root.xf = xf; if(xf == nil) { if(root!=nil) xfile(t.fid, Clunk); return ref Rmsg.Error(t.tag, ec); } if(xf.fmt == 0 && dosfs(xf) < 0){ if(root!=nil) xfile(t.fid, Clunk); return e(Eformat); } root.qid = Sys->Qid(big 0, 0, Sys->QTDIR); root.xf.rootqid = root.qid; return ref Rmsg.Attach(t.tag, root.qid); } clone(ofl: ref Xfile, newfid: int): ref Xfile { nfl := xfile(newfid, Clean); next := nfl.next; *nfl = *ofl; nfl.ptr = nil; nfl.next = next; nfl.fid = newfid; refxfs(nfl.xf, 1); if(ofl.ptr != nil){ dp := ref *ofl.ptr; dp.p = nil; dp.d = nil; nfl.ptr = dp; } return nfl; } walk1(f: ref Xfile, name: string): ref Rmsg.Error { if((f.qid.qtype & Sys->QTDIR) == 0){ if(debug) chat(sys->sprint("qid.path=0x%bx...", f.qid.path)); return e(Enotdir); } if(name == ".") # can't happen return nil; if(name== "..") { if(f.qid.path == f.xf.rootqid.path) { if (debug) chat("walkup from root..."); return nil; } (r,dp) := walkup(f); if(r < 0) return e(Enonexist); f.ptr = dp; if(dp.addr == 0) { f.qid.path = f.xf.rootqid.path; f.qid.qtype = Sys->QTFILE; } else { f.qid.path = QIDPATH(dp); f.qid.qtype = Sys->QTDIR; } } else { if(getfile(f) < 0) return e(Enonexist); (r,dp) := searchdir(f, name, 0,1); putfile(f); if(r < 0) return e(Enonexist); f.ptr = dp; f.qid.path = QIDPATH(dp); f.qid.qtype = Sys->QTFILE; if(dp.addr == 0) f.qid.path = f.xf.rootqid.path; else { d := Dosdir.arr2Dd(dp.p.iobuf[dp.offset:dp.offset+DOSDIRSIZE]); if((int d.attr & DDIR) != 0) f.qid.qtype = Sys->QTDIR; } putfile(f); } return nil; } rwalk(t: ref Tmsg.Walk): ref Rmsg { f := xfile(t.fid, Asis); if(f==nil) { if(debug) chat("no xfile..."); return e(Enofid); } nf: ref Xfile; if(t.newfid != t.fid) f = nf = clone(f, t.newfid); qids: array of Sys->Qid; if(len t.names > 0){ savedqid := f.qid; savedptr := f.ptr; qids = array[len t.names] of Sys->Qid; for(i := 0; i < len t.names; i++){ e := walk1(f, t.names[i]); if(e != nil){ f.qid = savedqid; f.ptr = savedptr; if(nf != nil) xfile(t.newfid, Clunk); if(i == 0) return e; return ref Rmsg.Walk(t.tag, qids[0:i]); } qids[i] = f.qid; } } return ref Rmsg.Walk(t.tag, qids); } ropen(t: ref Tmsg.Open): ref Rmsg { attr: int; omode := 0; f := xfile(t.fid, Asis); if(f == nil) return e(Enofid); if((f.flags&Omodes) != 0) return e(Efidopen); dp := f.ptr; if(dp.paddr && (t.mode & Styx->ORCLOSE) != 0) { # check on parent directory of file to be deleted p := getsect(f.xf, dp.paddr); if(p == nil) return e(Eio); # 11 is the attr byte offset in a FAT directory entry attr = int p.iobuf[dp.poffset+11]; putsect(p); if((attr & int DRONLY) != 0) return e(Eperm); omode |= Orclose; } else if(t.mode & Styx->ORCLOSE) omode |= Orclose; if(getfile(f) < 0) return e(Enonexist); if(dp.addr != 0) { d := Dosdir.arr2Dd(dp.p.iobuf[dp.offset:dp.offset+DOSDIRSIZE]); attr = int d.attr; } else attr = int DDIR; case t.mode & 7 { Styx->OREAD or Styx->OEXEC => omode |= Oread; Styx->ORDWR => omode |= Oread; omode |= Owrite; if(attr & int (DRONLY|DDIR)) { putfile(f); return e(Eperm); } Styx->OWRITE => omode |= Owrite; if(attr & int (DRONLY|DDIR)) { putfile(f); return e(Eperm); } * => putfile(f); return e(Eopen); } if(t.mode & Styx->OTRUNC) { if((attr & int DDIR)!=0 || (attr & int DRONLY) != 0) { putfile(f); return e(Eperm); } if(truncfile(f) < 0) { putfile(f); return e(Eio); } } f.flags |= omode; putfile(f); return ref Rmsg.Open(t.tag, f.qid, Styx->MAXFDATA); } mkdentry(xf: ref Xfs, ndp: ref Dosptr, name: string, sname: string, islong: int, nattr: byte, start: array of byte, length: array of byte): int { ndp.p = getsect(xf, ndp.addr); if(ndp.p == nil) return Eio; if(islong && (r := putlongname(xf, ndp, name, sname)) < 0){ putsect(ndp.p); if(r == -2) return Efull; return Eio; } nd := ref Dosdir(". "," ",byte 0,array[10] of { * => byte 0}, array[2] of { * => byte 0}, array[2] of { * => byte 0}, array[2] of { * => byte 0},array[4] of { * => byte 0}); nd.attr = nattr; puttime(nd); nd.start[0: ] = start[0: 2]; nd.length[0: ] = length[0: 4]; if(islong) putname(sname[0:8]+"."+sname[8:11], nd); else putname(name, nd); ndp.p.iobuf[ndp.offset: ] = Dosdir.Dd2arr(nd); ndp.p.flags |= BMOD; return 0; }