+ }*/
+
+ public static class MountPointFS extends FS {
+ private static class MP {
+ public MP(String path, FS fs) { this.path = path; this.fs = fs; }
+ public String path;
+ public FS fs;
+ public int compareTo(Object o) {
+ if(!(o instanceof MP)) return 1;
+ return -path.compareTo(((MP)o).path);
+ }
+ }
+ private final MP[][] mps = new MP[128][];
+ private final FS root;
+ public MountPointFS(FS root) { this.root = root; }
+
+ private static String fixup(String path) {
+ if(!path.startsWith("/")) throw new IllegalArgumentException("Mount point doesn't start with a /");
+ path = path.substring(1);
+ if(path.length() == 0) throw new IllegalArgumentException("Zero length mount point path");
+ return path;
+ }
+ public FS get(String path) {
+ path = fixup(path);
+ 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 void add(String path, FS fs) {
+ if(get(path) != null) throw new IllegalArgumentException("mount point already exists");
+ path = fixup(path);
+ 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 void remove(String path) {
+ path = fixup(path);
+ if(get(path) == null) throw new IllegalArgumentException("mount point doesn't exist");
+ 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;
+ }
+
+ protected Object op(int op, String path, int arg1, int arg2) throws IOException {
+ 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(pl == mpl || (pl < mpl && path.charAt(mpl) == '/'))
+ return mp.fs.op(op,pl == mpl ? "" : path.substring(mpl+1),arg1,arg2);
+ }
+ }
+ return root.op(op,path,arg1,arg2);
+ }