1027 lines · 26.9 KB · Java
RawDownload
package plan9; /* * A renaming of styx-n-9p.google.com's Styx package for Java * * Ninep definitions and message formatting * * TO DO *	simplify *	NinepReader * * Copyright © 2005 Vita Nuova Holdings Limited [C H Forsyth, forsyth@vitanuova.com] * Subject to the terms of the MIT-template (google for a copy) */ import plan9.lib.Strings;import static plan9.lib.Strings.utflen; import java.nio.ByteBuffer;	// not ideal, but will do for nowimport java.nio.channels.ByteChannel; public class Ninep { 	/* fundamental constants; don't change */	public static final String VERSION = "9P2000";	public static final int	MAXWELEM = 16;	// limit to elements walked in one Twalk	public static final int	NOTAG = 0xFFFF;	// invalid tag	public static final int	NOFID = ~0;		// invalid fid 	public static final int	IOHDRSZ = 24;		// room for Twrite/Rread header	public static final int	MAXFDATA = 8192;	// `reasonable' iounit	public static final int MAXRPC = IOHDRSZ+MAXFDATA;	// usable default for fversion and iounit 	public static final int	ERRMAX = 128;		// protocol's arbitrary limit to error message strings 	/* open/create modes; don't change */	public static final int	OREAD = 0; 		// open for read	public static final int	OWRITE = 1; 		// write	public static final int	ORDWR = 2; 		// read and write	public static final int	OEXEC = 3; 		// execute, == read but check execute permission	public static final int	OTRUNC = 16; 		// or'ed in (except for exec), truncate file first	public static final int	ORCLOSE = 64; 	// or'ed in, remove on close	public static final int OEXCL = 0x1000;	// exclusive-create 	public static class FormatError extends Exception {		FormatError(String s){ super("Ninep: "+s); }	} 	/* message types; don't change */	static final int	MTversion = 100;	static final int	MRversion = MTversion+1;	static final int	MTauth = 102;	static final int	MRauth = MTauth+1;	static final int	MTattach = 104;	static final int	MRattach = MTattach+1;	static final int	MTerror = 106;	// illegal	static final int	MRerror = MTerror+1;	static final int	MTflush = 108;	static final int	MRflush = MTflush+1;	static final int	MTwalk = 110;	static final int	MRwalk = MTwalk+1;	static final int	MTopen = 112;	static final int	MRopen = MTopen+1;	static final int	MTcreate = 114;	static final int	MRcreate = MTcreate+1;	static final int	MTread = 116;	static final int	MRread = MTread+1;	static final int	MTwrite = 118;	static final int	MRwrite = MTwrite+1;	static final int	MTclunk = 120;	static final int	MRclunk = MTclunk+1;	static final int	MTremove = 122;	static final int	MRremove = MTremove+1;	static final int	MTstat = 124;	static final int	MRstat = MTstat+1;	static final int	MTwstat = 126;	static final int	MRwstat = MTwstat+1;	static final int	MTmax = MRwstat+1; 	/* size of protocol elements in bytes; don't change */	static final int	BIT8SZ = 1;	static final int	BIT16SZ = 2;	static final int	BIT32SZ = 4;	static final int	BIT64SZ = 8;	static final int	QIDSZ = BIT8SZ+BIT32SZ+BIT64SZ; 	static final int	STATFIXLEN = BIT16SZ+QIDSZ+5*BIT16SZ+4*BIT32SZ+BIT64SZ;	// amount of fixed length data in a stat buffer 	/* names  for use in a message size formula */	private static final int STR = BIT16SZ;	private static final int TAG = BIT16SZ;	private static final int FID = BIT32SZ;	private static final int QID = BIT8SZ + BIT32SZ + BIT64SZ;	private static final int LEN = BIT16SZ;	// stat and qid array lengths	private static final int COUNT = BIT32SZ;	private static final int OFFSET = BIT64SZ;	private static final int H = BIT32SZ + BIT8SZ + BIT16SZ;	// minimum header length: size[4] type tag[2] 	public static abstract class Smsg {		public abstract int mtype();		public abstract String mname();		abstract void  pack(ByteBuffer b);		public void packsize(ByteBuffer b, int n){			p32(b, n);		}		public abstract int packedsize();		public abstract boolean isTmsg();	} 	public static abstract class Tmsg extends Smsg {		public int	tag = NOTAG; 		Tmsg(){}		public final Tmsg read(ByteChannel fd, int msize) { return null; }		protected final void packtag(ByteBuffer b){ p16(b, tag); }		protected Tmsg(ByteBuffer b){ tag = g16(b); }		public final boolean isTmsg(){ return true; };	} 	public class Unpack {		public final Tmsg unpackT(ByteBuffer b) throws FormatError {			/* length has already been consumed */			switch(b.get()){			case MTversion:				return new Tversion(b);			case MTauth:				return new Tauth(b);			case MTattach:				return new Tattach(b);			case MTflush:				return new Tflush(b);			case MTwalk:				return new Twalk(b);			case MTopen:				return new Topen(b);			case MTcreate:				return new Tcreate(b);			case MTread:				return new Tread(b);			case MTwrite:				return new Twrite(b);			case MTclunk:				return new Tclunk(b);			case MTremove:				return new Tremove(b);			case MTstat:				return new Tstat(b);			case MTwstat:				return new Twstat(b);			default:				throw new FormatError("invalid Tmsg type");			}		}		public final Rmsg unpackR(ByteBuffer b) throws FormatError {			/* length has already been consumed */			switch(b.get()){			case MRversion:				return new Rversion(b);			case MRauth:				return new Rauth(b);			case MRattach:				return new Rattach(b);			case MRflush:				return new Rflush(b);			case MRwalk:				return new Rwalk(b);			case MRopen:				return new Ropen(b);			case MRcreate:				return new Rcreate(b);			case MRread:				return new Rread(b);			case MRwrite:				return new Rwrite(b);			case MRclunk:				return new Rclunk(b);			case MRremove:				return new Rremove(b);			case MRstat:				return new Rstat(b);			case MRwstat:				return new Rwstat(b);			case MRerror:				return new Rerror(b);			default:				throw new FormatError("invalid Rmsg type");			}		}	} 	public class Tversion extends Tmsg {		public int	msize;		public String	version; 		public Tversion(int msize, String version) {			this.msize = msize; this.version = version;		}		Tversion(ByteBuffer b){			super(b);			msize = g32(b);			version = gets(b);		}		final void pack(ByteBuffer b){			b.put((byte)MTversion);			packtag(b);			p32(b, msize);			puts(b, version);		}		public final int mtype(){ return MTversion; }		public final String mname(){ return "Tversion"; }		public final int packedsize(){ return H+COUNT+STR+utflen(version); }		public final String toString(){ return "Tversion("+tag+","+msize+",\""+version+"\")"; } 		public final Rversion compatible(int msize, String version){			if(version == null)				version = VERSION;			if(this.msize < msize)				msize = this.msize;			String v = this.version;			if(v.length() < 2 || !v.substring(0, 2).equals("9P"))				return new Rversion(this.tag, msize, "unknown");			for(int i=2; i<v.length(); i++){				char c = v.charAt(i);				if(c == '.'){					v = v.substring(0, i);					break;				}else if(!(c >= '0' && c <= '9'))					return new Rversion(this.tag, msize, "unknown");	// fussier than Plan 9			}			if(v.compareTo(VERSION) < 0)				return new Rversion(this.tag, msize, "unknown");			if(v.compareTo(version) < 0)				version = v;			return new Rversion(this.tag, msize, version);		}	}	public class Tauth extends Tmsg {		public int	afid;		public String	uname;		public String	aname; 		public Tauth(int afid, String uname, String aname){			this.afid = afid; this.uname = uname; this.aname = aname;		}		Tauth(ByteBuffer b){			super(b);			afid = g32(b);			uname = gets(b);			aname = gets(b);		}		final void pack(ByteBuffer b){			b.put((byte)MTauth);			packtag(b);			p32(b, afid);			puts(b, uname);			puts(b, aname);		}		public int mtype() { return MTauth; }		public String mname(){ return "Tauth"; }		public final int packedsize(){ return H+FID+STR+utflen(uname)+STR+utflen(aname); }		public final String toString(){ return "Tauth("+tag+","+afid+",\""+uname+"\",\""+aname+"\")"; }	}	public class Tattach extends Tmsg {		public int	fid;		public int	afid;		public String	uname;		public String	aname; 		public Tattach(int fid, int afid, String uname, String aname){			if(uname == null)				uname = "";			if(aname == null)				aname = "";			this.fid = fid; this.afid = afid; this.uname = uname; this.aname = aname;		}		Tattach(ByteBuffer b){			super(b);			fid = g32(b);			afid = g32(b);			uname = gets(b);			aname = gets(b);		}		final void pack(ByteBuffer b){			b.put((byte)MTattach);			packtag(b);			p32(b, fid);			p32(b, afid);			puts(b, uname);			puts(b, aname);		} 		public int mtype() { return MTattach; }		public String mname(){ return "Tattach"; }		public final int packedsize(){ return H+2*FID+STR+utflen(uname)+STR+utflen(aname); }		public String toString(){ return "Tattach("+tag+","+fid+","+afid+",\""+uname+"\",\""+aname+"\")"; }	}	public class Tflush extends Tmsg {		public int	oldtag; 		public Tflush(int oldtag){			this.oldtag = oldtag;		}		Tflush(ByteBuffer b){			super(b);			oldtag = g16(b);		}		final void pack(ByteBuffer b){			b.put((byte)MTflush);			packtag(b);			p16(b, oldtag);		}		public int mtype() { return MTflush; }		public String mname(){ return "Tflush"; }		public final int packedsize(){ return H+TAG; }		public String toString(){ return "Tflush("+tag+","+oldtag+")"; }	}	public class Twalk extends Tmsg {		public int	fid;		public int	newfid;		public String[]	names; 		public Twalk(int fid, int newfid, String[] names){			this.fid = fid; this.newfid = newfid; this.names = names;		}		Twalk(ByteBuffer b){			super(b);			fid = g32(b);			newfid = g32(b);			int n = g16(b);			names = new String[n];			for(int i = 0; i < n; i++)				names[i] = gets(b);		}		final void pack(ByteBuffer b){			b.put((byte)MTwalk);			packtag(b);			p32(b, fid);			p32(b, newfid);			int n = names.length;			p16(b, n);			for(int i = 0; i < n; i++)				puts(b, names[i]);		}		public int mtype() { return MTwalk; }		public String mname(){ return "Twalk"; }		public final int packedsize(){			int n = H+2*FID+LEN;			for(int i = 0; i < names.length; i++)				n += STR+utflen(names[i]);			return n;		}		public final String toString(){			StringBuilder bs = new StringBuilder(64);			bs.append(String.format("Twalk(%d,%d,%d,{", tag, fid, newfid));			for(int i = 0; i < names.length; i++){				bs.append('"');				bs.append(names[i]);				bs.append('"');				if(i+1 < names.length)					bs.append(',');			}			bs.append("})");			return bs.toString();		}	}	public class Topen extends Tmsg {		public int	fid;		public int	mode; 		public Topen(int fid, int mode){			this.fid = fid; this.mode = mode;		}		Topen(ByteBuffer b){			super(b);			fid = g32(b);			mode = g8(b);		}		final void pack(ByteBuffer b){			b.put((byte)MTopen);			packtag(b);			p32(b, fid);			b.put((byte)mode);		}		public int mtype() { return MTopen; }		public String mname(){ return "Topen"; }		public final int packedsize(){ return H+FID+BIT8SZ; }		public final String toString(){ return "Topen("+tag+","+fid+","+mode+")"; }	}	public class Tcreate extends Tmsg {		public int	fid;		public String name;		public int	perm;		public int	mode; 		public Tcreate(int fid, String name, int perm, int mode){			this.fid = fid; this.name = name; this.perm = perm; this.mode = mode;		}		Tcreate(ByteBuffer b){			super(b);			fid = g32(b);			name = gets(b);			perm = g32(b);			mode = g32(b);		}		final void pack(ByteBuffer b){			b.put((byte)MTcreate);			packtag(b);			p32(b, fid);			puts(b, name);			p32(b, perm);			b.put((byte)mode);		}		public int mtype() { return MTcreate; }		public String mname(){ return "Tcreate"; }		public final int packedsize(){ return H+FID+STR+BIT32SZ+BIT8SZ+utflen(name); }		public final String toString(){ return "Tcreate("+tag+","+fid+",\""+name+"\","+Integer.toHexString(perm)+","+mode+")"; }	}	public class Tread extends Tmsg {		public int	fid;		public long offset;		public int	count; 		public Tread(int fid, long offset, int count){			this.fid = fid; this.offset = offset; this.count = count;		}		Tread(ByteBuffer b){			super(b);			fid = g32(b);			offset = g64(b);			count = g32(b);		}		final void pack(ByteBuffer b){			b.put((byte)MTread);			packtag(b);			p32(b, fid);			p64(b, offset);			p32(b, count);		}		public int mtype() { return MTread; }		public String mname(){ return "Tread"; }		public final int packedsize(){ return H+FID+OFFSET+COUNT; }		public final String toString(){ return "Tread("+tag+","+fid+","+offset+","+count+")"; }	}	public class Twrite extends Tmsg {		public int	fid;		public long offset;		public ByteBuffer	data; 		public Twrite(int fid, long offset, ByteBuffer data){			this.fid = fid; this.offset = offset; this.data = data;		}		public Twrite(int fid, long offset, ByteBuffer data, int n){			data = data.duplicate();			data.limit(data.position()+n);			data = data.slice();			this.fid = fid; this.offset = offset; this.data = data;		}		Twrite(ByteBuffer b){			super(b);			fid = g32(b);			offset = g64(b);			int count = g32(b);			data = b.duplicate();			data.limit(b.position()+count);			data = data.slice();		}		final void pack(ByteBuffer b){			b.put((byte)MTwrite);			packtag(b);			p32(b, fid);			p64(b, offset);			p32(b, data.remaining());			b.put(data);		}		public int mtype() { return MTwrite; }		public String mname(){ return "Twrite"; }		public final int packedsize(){ return H+FID+OFFSET+COUNT+data.remaining(); }		public final String toString(){ return "Twrite("+tag+","+fid+","+offset+","+data.remaining()+")"; }	}	public class Tclunk extends Tmsg {		public int	fid; 		public Tclunk(int fid){			this.fid = fid;		}		Tclunk(ByteBuffer b){			super(b);			fid = g32(b);		}		final void pack(ByteBuffer b){			b.put((byte)MTclunk);			packtag(b);			p32(b, fid);		}		public int mtype() { return MTclunk; }		public String mname(){ return "Tclunk"; }		public final int packedsize(){ return H+FID; }		public final String toString(){ return "Tclunk("+tag+","+fid+")"; }	}	public class Tstat extends Tmsg {

Lines 1–500 of 1027.