+ return (Class) runtimeCompilerCompile.invoke(null,new Object[]{s,"unixruntime,maxinsnpermethod=256,lessconstants",sourceName});
+ } catch(IllegalAccessException e) {
+ e.printStackTrace();
+ return null;
+ } catch(InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ if(t instanceof IOException) throw (IOException) t;
+ if(t instanceof RuntimeException) throw (RuntimeException) t;
+ if(t instanceof Error) throw (Error) t;
+ if(STDERR_DIAG) t.printStackTrace();
+ return null;
+ }
+ }
+
+ private int exec(String path, String[] argv, String[] envp) throws ErrnoException {
+ if(argv.length == 0) argv = new String[]{""};
+ // HACK: Hideous hack to make a standalone busybox possible
+ if(path.equals("bin/busybox") && getClass().getName().endsWith("BusyBox"))
+ return execClass(getClass(),argv,envp);
+
+ // NOTE: For this little hack to work nestedvm.root MUST be "."
+ /*try {
+ System.err.println("Execing normalized path: " + normalizedPath);
+ if(true) return exec(new Interpreter(normalizedPath),argv,envp);
+ } catch(IOException e) { throw new Error(e); }*/
+
+ FStat fstat = gs.stat(this,path);
+ if(fstat == null) return -ENOENT;
+ GlobalState.CacheEnt ent = (GlobalState.CacheEnt) gs.execCache.get(path);
+ long mtime = fstat.mtime();
+ long size = fstat.size();
+ if(ent != null) {
+ //System.err.println("Found cached entry for " + path);
+ if(ent.time ==mtime && ent.size == size) {
+ if(ent.o instanceof Class)
+ return execClass((Class) ent.o,argv,envp);
+ if(ent.o instanceof String[])
+ return execScript(path,(String[]) ent.o,argv,envp);
+ throw new Error("should never happen");
+ }
+ //System.err.println("Cache was out of date");
+ gs.execCache.remove(path);
+ }
+
+ FD fd = gs.open(this,path,RD_ONLY,0);
+ if(fd == null) throw new ErrnoException(ENOENT);
+ Seekable s = fd.seekable();
+ if(s == null) throw new ErrnoException(EACCES);
+
+ byte[] buf = new byte[4096];
+
+ try {
+ int n = s.read(buf,0,buf.length);
+ if(n == -1) throw new ErrnoException(ENOEXEC);
+
+ switch(buf[0]) {
+ case '\177': // possible ELF
+ if(n < 4) s.tryReadFully(buf,n,4-n);
+ if(buf[1] != 'E' || buf[2] != 'L' || buf[3] != 'F') return -ENOEXEC;
+ s.seek(0);
+ if(STDERR_DIAG) System.err.println("Running RuntimeCompiler for " + path);
+ Class c = runtimeCompile(s,path);
+ if(STDERR_DIAG) System.err.println("RuntimeCompiler finished for " + path);
+ if(c == null) throw new ErrnoException(ENOEXEC);
+ gs.execCache.put(path,new GlobalState.CacheEnt(mtime,size,c));
+ return execClass(c,argv,envp);
+ case '#':
+ if(n == 1) {
+ int n2 = s.read(buf,1,buf.length-1);
+ if(n2 == -1) return -ENOEXEC;
+ n += n2;
+ }
+ if(buf[1] != '!') return -ENOEXEC;
+ int p = 2;
+ n -= 2;
+ OUTER: for(;;) {
+ for(int i=p;i<p+n;i++) if(buf[i] == '\n') { p = i; break OUTER; }
+ p += n;
+ if(p == buf.length) break OUTER;
+ n = s.read(buf,p,buf.length-p);
+ }
+ int arg;
+ for(arg=2;arg<p;arg++) if(buf[arg] == ' ') break;
+ int cmdEnd = arg;
+ while(arg < p && buf[arg] == ' ') arg++;
+ String[] command = new String[] {
+ new String(buf,2,cmdEnd),
+ arg < p ? new String(buf,arg,p-arg) : null
+ };
+ gs.execCache.put(path,new GlobalState.CacheEnt(mtime,size,command));
+ return execScript(path,command,argv,envp);
+ default:
+ return -ENOEXEC;
+ }