+ public synchronized FS getMount(String path) {
+ if(!path.startsWith("/")) throw new IllegalArgumentException("Mount point doesn't start with a /");
+ if(path.equals("/")) return root;
+ path = path.substring(1);
+ int f = path.charAt(0) & 0x7f;
+ for(int i=0;mps[f] != null && i < mps[f].length;i++)
+ if(mps[f][i].path.equals(path)) return mps[f][i].fs;
+ return null;
+ }
+
+ public synchronized void addMount(String path, FS fs) {
+ if(getMount(path) != null) throw new IllegalArgumentException("mount point already exists");
+ if(!path.startsWith("/")) throw new IllegalArgumentException("Mount point doesn't start with a /");
+ if(path.equals("/")) { root = fs; return; }
+ path = path.substring(1);
+ int f = path.charAt(0) & 0x7f;
+ int oldLength = mps[f] == null ? 0 : mps[f].length;
+ MP[] newList = new MP[oldLength + 1];
+ if(oldLength != 0) System.arraycopy(mps[f],0,newList,0,oldLength);
+ newList[oldLength] = new MP(path,fs);
+ Arrays.sort(newList);
+ mps[f] = newList;
+ }
+
+ public synchronized void removeMount(String path) {
+ if(getMount(path) == null) throw new IllegalArgumentException("mount point doesn't exist");
+ if(!path.startsWith("/")) throw new IllegalArgumentException("Mount point doesn't start with a /");
+ if(path.equals("/")) { root = null; return; }
+ path = path.substring(1);
+ int f = path.charAt(0) & 0x7f;
+ MP[] oldList = mps[f];
+ MP[] newList = new MP[oldList.length - 1];
+ int p = 0;
+ for(p=0;p<oldList.length;p++) if(oldList[p].path.equals(path)) break;
+ if(p == oldList.length) throw new Error("should never happen");
+ System.arraycopy(oldList,0,newList,0,p);
+ System.arraycopy(oldList,0,newList,p,oldList.length-p-1);
+ mps[f] = newList;
+ }
+
+ private Object fsop(int op, UnixRuntime r, String path, int arg1, int arg2) throws ErrnoException {
+ int pl = path.length();
+ if(pl != 0) {
+ MP[] list = mps[path.charAt(0) & 0x7f];
+ if(list != null) {
+ for(int i=0;i<list.length;i++) {
+ MP mp = list[i];
+ int mpl = mp.path.length();
+ if(path.startsWith(mp.path) && (pl == mpl || (pl < mpl && path.charAt(mpl) == '/')))
+ return dispatch(mp.fs,op,r,pl == mpl ? "" : path.substring(mpl+1),arg1,arg2);
+ }
+ }
+ }
+ return dispatch(root,op,r,path,arg1,arg2);
+ }
+
+ private static Object dispatch(FS fs, int op, UnixRuntime r, String path, int arg1, int arg2) throws ErrnoException {
+ switch(op) {
+ case OPEN: return fs.open(r,path,arg1,arg2);
+ case STAT: return fs.stat(r,path);
+ case LSTAT: return fs.lstat(r,path);
+ case MKDIR: fs.mkdir(r,path,arg1); return null;
+ default: throw new Error("should never happen");
+ }
+ }
+
+ public final FD open(UnixRuntime r, String path, int flags, int mode) throws ErrnoException { return (FD) fsop(OPEN,r,path,flags,mode); }
+ public final FStat stat(UnixRuntime r, String path) throws ErrnoException { return (FStat) fsop(STAT,r,path,0,0); }
+ public final FStat lstat(UnixRuntime r, String path) throws ErrnoException { return (FStat) fsop(LSTAT,r,path,0,0); }
+ public final void mkdir(UnixRuntime r, String path, int mode) throws ErrnoException { fsop(MKDIR,r,path,mode,0); }