+
+ public static final class GlobalState {
+ Hashtable execCache = new Hashtable();
+
+ final UnixRuntime[] tasks;
+ int nextPID = 1;
+
+ /** Table of all current file locks held by this process. */
+ Seekable.Lock[] locks = new Seekable.Lock[16];
+
+ private MP[] mps = new MP[0];
+ private FS root;
+
+ public GlobalState() { this(255); }
+ public GlobalState(int maxProcs) { this(maxProcs,true); }
+ public GlobalState(int maxProcs, boolean defaultMounts) {
+ tasks = new UnixRuntime[maxProcs+1];
+ if(defaultMounts) {
+ File root = null;
+ if(Platform.getProperty("nestedvm.root") != null) {
+ root = new File(Platform.getProperty("nestedvm.root"));
+ if(!root.isDirectory()) throw new IllegalArgumentException("nestedvm.root is not a directory");
+ } else {
+ String cwd = Platform.getProperty("user.dir");
+ root = Platform.getRoot(new File(cwd != null ? cwd : "."));
+ }
+
+ addMount("/",new HostFS(root));
+
+ if(Platform.getProperty("nestedvm.root") == null) {
+ File[] roots = Platform.listRoots();
+ for(int i=0;i<roots.length;i++) {
+ String name = roots[i].getPath();
+ if(name.endsWith(File.separator))
+ name = name.substring(0,name.length()-1);
+ if(name.length() == 0 || name.indexOf('/') != -1) continue;
+ addMount("/" + name.toLowerCase(),new HostFS(roots[i]));
+ }
+ }
+
+ addMount("/dev",new DevFS());
+ addMount("/resource",new ResourceFS());
+ addMount("/cygdrive",new CygdriveFS());
+ }
+ }
+
+ public String mapHostPath(String s) { return mapHostPath(new File(s)); }
+ public String mapHostPath(File f) {
+ MP[] list;
+ FS root;
+ synchronized(this) { mps = this.mps; root = this.root; }
+ if(!f.isAbsolute()) f = new File(f.getAbsolutePath());
+ for(int i=mps.length;i>=0;i--) {
+ FS fs = i == mps.length ? root : mps[i].fs;
+ String path = i == mps.length ? "" : mps[i].path;
+ if(!(fs instanceof HostFS)) continue;
+ File fsroot = ((HostFS)fs).getRoot();
+ if(!fsroot.isAbsolute()) fsroot = new File(fsroot.getAbsolutePath());
+ if(f.getPath().startsWith(fsroot.getPath())) {
+ char sep = File.separatorChar;
+ String child = f.getPath().substring(fsroot.getPath().length());
+ if(sep != '/') {
+ char[] child_ = child.toCharArray();
+ for(int j=0;j<child_.length;j++) {
+ if(child_[j] == '/') child_[j] = sep;
+ else if(child_[j] == sep) child_[j] = '/';
+ }
+ child = new String(child_);
+ }
+ String mapped = "/" + (path.length()==0?"":path+"/") + child;
+ return mapped;
+ }
+ }
+ return null;
+ }
+
+ static class MP implements Sort.Comparable {
+ 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);
+ }
+ }
+
+ 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);
+ for(int i=0;i<mps.length;i++)
+ if(mps[i].path.equals(path)) return mps[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(fs.owner != null) fs.owner.removeMount(fs);
+ fs.owner = this;
+
+ if(path.equals("/")) { root = fs; fs.devno = 1; return; }
+ path = path.substring(1);
+ int oldLength = mps.length;
+ MP[] newMPS = new MP[oldLength + 1];
+ if(oldLength != 0) System.arraycopy(mps,0,newMPS,0,oldLength);
+ newMPS[oldLength] = new MP(path,fs);
+ Sort.sort(newMPS);
+ mps = newMPS;
+ int highdevno = 0;
+ for(int i=0;i<mps.length;i++) highdevno = max(highdevno,mps[i].fs.devno);
+ fs.devno = highdevno + 2;
+ }
+
+ public synchronized void removeMount(FS fs) {
+ for(int i=0;i<mps.length;i++) if(mps[i].fs == fs) { removeMount(i); return; }
+ throw new IllegalArgumentException("mount point doesn't exist");
+ }
+
+ public synchronized void removeMount(String path) {
+ if(!path.startsWith("/")) throw new IllegalArgumentException("Mount point doesn't start with a /");
+ if(path.equals("/")) {
+ removeMount(-1);
+ } else {
+ path = path.substring(1);
+ int p;
+ for(p=0;p<mps.length;p++) if(mps[p].path.equals(path)) break;
+ if(p == mps.length) throw new IllegalArgumentException("mount point doesn't exist");
+ removeMount(p);
+ }
+ }
+
+ private void removeMount(int index) {
+ if(index == -1) { root.owner = null; root = null; return; }
+ MP[] newMPS = new MP[mps.length - 1];
+ System.arraycopy(mps,0,newMPS,0,index);
+ System.arraycopy(mps,0,newMPS,index,mps.length-index-1);
+ mps = newMPS;
+ }
+
+ private Object fsop(int op, UnixRuntime r, String normalizedPath, int arg1, int arg2) throws ErrnoException {
+ int pl = normalizedPath.length();
+ if(pl != 0) {
+ MP[] list;
+ synchronized(this) { list = mps; }
+ for(int i=0;i<list.length;i++) {
+ MP mp = list[i];
+ int mpl = mp.path.length();
+ if(normalizedPath.startsWith(mp.path) && (pl == mpl || normalizedPath.charAt(mpl) == '/'))
+ return mp.fs.dispatch(op,r,pl == mpl ? "" : normalizedPath.substring(mpl+1),arg1,arg2);
+ }
+ }
+ return root.dispatch(op,r,normalizedPath,arg1,arg2);
+ }