Charles.Forsyth20060303a828770d19 years agoHistory
3432 lines · 66.2 KB · Brainfuck
RawDownload
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.