X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;ds=sidebyside;f=src%2Forg%2Fibex%2Fnestedvm%2FUnixRuntime.java;h=5adcba04ff4b88c4eda148ec56a3d7fbf214d4b4;hb=refs%2Fheads%2Fmaster;hp=0ce093bf68aa7dd48910e6fd26e19492266c0986;hpb=beabe49c6d19528ab3d27081c7af4fd9fb74027b;p=nestedvm.git diff --git a/src/org/ibex/nestedvm/UnixRuntime.java b/src/org/ibex/nestedvm/UnixRuntime.java index 0ce093b..5adcba0 100644 --- a/src/org/ibex/nestedvm/UnixRuntime.java +++ b/src/org/ibex/nestedvm/UnixRuntime.java @@ -1,12 +1,10 @@ // Copyright 2000-2005 the Contributors, as shown in the revision logs. -// Licensed under the Apache Public Source License 2.0 ("the License"). +// Licensed under the Apache License 2.0 ("the License"). // You may not use this file except in compliance with the License. package org.ibex.nestedvm; import org.ibex.nestedvm.util.*; -// HACK: This is ugly, this stuff needs to be in org.ibex.util or something -import org.ibex.classgen.util.Sort; import java.io.*; import java.util.*; import java.net.*; @@ -46,28 +44,9 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { if(!exec) { gs = defaultGS; String userdir = Platform.getProperty("user.dir"); - String nvroot = Platform.getProperty("nestedvm.root"); - cwd = ""; - if(userdir != null && nvroot == null) { - if(userdir.startsWith("/") && File.separatorChar == '/') { - cwd = userdir.substring(1); - } else { - Vector vec = new Vector(); - File root = HostFS.hostRootDir(); - String s = new File(userdir).getAbsolutePath(); - File d = new File(s); - System.err.println(s); - System.err.println(d); - while(!d.equals(root)) { - System.err.println("Got " + d.getName()); - vec.addElement(d.getName()); - if((s = d.getParent()) == null) break; - d = new File(s); - } - if(s != null) - for(int i=vec.size()-1;i>=0;i--) cwd += (String) vec.elementAt(i) + (i==0?"":"/"); - } - } + cwd = userdir == null ? null : gs.mapHostPath(userdir); + if(cwd == null) cwd = "/"; + cwd = cwd.substring(1); } } @@ -93,13 +72,16 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { } String[] createEnv(String[] extra) { - String[] defaults = new String[6]; + String[] defaults = new String[7]; int n=0; if(extra == null) extra = new String[0]; + String tmp; if(!envHas("USER",extra) && Platform.getProperty("user.name") != null) defaults[n++] = "USER=" + Platform.getProperty("user.name"); - if(!envHas("HOME",extra) && Platform.getProperty("user.home") != null) - defaults[n++] = "HOME=" + Platform.getProperty("user.home"); + if(!envHas("HOME",extra) && (tmp=Platform.getProperty("user.home")) != null && (tmp=gs.mapHostPath(tmp)) != null) + defaults[n++] = "HOME=" + tmp; + if(!envHas("TMPDIR",extra) && (tmp=Platform.getProperty("java.io.tmpdir")) != null && (tmp=gs.mapHostPath(tmp)) != null) + defaults[n++] = "TMPDIR=" + tmp; if(!envHas("SHELL",extra)) defaults[n++] = "SHELL=/bin/sh"; if(!envHas("TERM",extra) && !win32Hacks) defaults[n++] = "TERM=vt100"; if(!envHas("TZ",extra)) defaults[n++] = "TZ=" + posixTZ(); @@ -137,7 +119,7 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { } } - int _syscall(int syscall, int a, int b, int c, int d, int e, int f) throws ErrnoException, FaultException { + protected int _syscall(int syscall, int a, int b, int c, int d, int e, int f) throws ErrnoException, FaultException { switch(syscall) { case SYS_kill: return sys_kill(a,b); case SYS_fork: return sys_fork(); @@ -169,23 +151,51 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { case SYS_select: return sys_select(a,b,c,d,e); case SYS_access: return sys_access(a,b); case SYS_realpath: return sys_realpath(a,b); - + case SYS_chown: return sys_chown(a,b,c); + case SYS_lchown: return sys_chown(a,b,c); + case SYS_fchown: return sys_fchown(a,b,c); + case SYS_chmod: return sys_chmod(a,b,c); + case SYS_fchmod: return sys_fchmod(a,b,c); + case SYS_fcntl: return sys_fcntl_lock(a,b,c); + case SYS_umask: return sys_umask(a); + default: return super._syscall(syscall,a,b,c,d,e,f); } } FD _open(String path, int flags, int mode) throws ErrnoException { - return gs.open(this,normalizePath(path),flags,mode); + path = normalizePath(path); + FD fd = gs.open(this,path,flags,mode); + if (fd != null && path != null) fd.setNormalizedPath(path); + return fd; } private int sys_getppid() { return parent == null ? 1 : parent.pid; } + private int sys_chown(int fileAddr, int uid, int gid) { + return 0; + } + private int sys_lchown(int fileAddr, int uid, int gid) { + return 0; + } + private int sys_fchown(int fd, int uid, int gid) { + return 0; + } + private int sys_chmod(int fileAddr, int uid, int gid) { + return 0; + } + private int sys_fchmod(int fd, int uid, int gid) { + return 0; + } + private int sys_umask(int mask) { + return 0; + } - private int sys_access(int cstring, int mode) { + private int sys_access(int cstring, int mode) throws ErrnoException, ReadFaultException { // FEATURE: sys_access - return 0; + return gs.stat(this,normalizePath(cstring(cstring))) == null ? -ENOENT : 0; } private int sys_realpath(int inAddr, int outAddr) throws FaultException { @@ -387,7 +397,7 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { static { Method m; try { - m = Class.forName("org.ibex.nestedvm.RuntimeCompiler").getMethod("compile",new Class[]{Seekable.class,String.class}); + m = Class.forName("org.ibex.nestedvm.RuntimeCompiler").getMethod("compile",new Class[]{Seekable.class,String.class,String.class}); } catch(NoSuchMethodException e) { m = null; } catch(ClassNotFoundException e) { @@ -396,14 +406,14 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { runtimeCompilerCompile = m; } - public Class runtimeCompile(Seekable s) throws IOException { + public Class runtimeCompile(Seekable s, String sourceName) throws IOException { if(runtimeCompilerCompile == null) { if(STDERR_DIAG) System.err.println("WARNING: Exec attempted but RuntimeCompiler not found!"); return null; } try { - return (Class) runtimeCompilerCompile.invoke(null,new Object[]{s,"unixruntime"}); + return (Class) runtimeCompilerCompile.invoke(null,new Object[]{s,"unixruntime,maxinsnpermethod=256,lessconstants",sourceName}); } catch(IllegalAccessException e) { e.printStackTrace(); return null; @@ -463,7 +473,9 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { if(n < 4) s.tryReadFully(buf,n,4-n); if(buf[1] != 'E' || buf[2] != 'L' || buf[3] != 'F') return -ENOEXEC; s.seek(0); - Class c = runtimeCompile(s); + 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); @@ -482,13 +494,16 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { if(p == buf.length) break OUTER; n = s.read(buf,p,buf.length-p); } - int arg; - for(arg=2;arg
= OPEN_MAX) return -EBADFD;
+ if(fds[fdn] == null) return -EBADFD;
+ FD fd = fds[fdn];
+
+ if (arg == 0) return -EINVAL;
+ int word = memRead(arg);
+ int l_start = memRead(arg+4);
+ int l_len = memRead(arg+8);
+ int l_type = word>>16;
+ int l_whence = word&0x00ff;
+
+ Seekable.Lock[] locks = gs.locks;
+ Seekable s = fd.seekable();
+ if (s == null) return -EINVAL;
+
+ try {
+
+ switch (l_whence) {
+ case SEEK_SET: break;
+ case SEEK_CUR: l_start += s.pos(); break;
+ case SEEK_END: l_start += s.length(); break;
+ default: return -1;
+ }
+
+ if (cmd == F_GETLK) {
+ // The simple Java file locking below will happily return
+ // a lock that overlaps one already held by the JVM. Thus
+ // we must check over all the locks held by other Runtimes
+ for (int i=0; i < locks.length; i++) {
+ if (locks[i] == null || !s.equals(locks[i].seekable()))
+ continue;
+ if (!locks[i].overlaps(l_start, l_len))
+ continue;
+ if (locks[i].getOwner() == this)
+ continue;
+ if (locks[i].isShared() && l_type == F_RDLCK)
+ continue;
+
+ // overlapping lock held by another process
+ return 0;
+ }
+
+ // check if an area is lockable by attempting to obtain a lock
+ Seekable.Lock lock = s.lock(l_start, l_len, l_type == F_RDLCK);
+
+ if (lock != null) { // no lock exists
+ memWrite(arg, SEEK_SET|(F_UNLCK<<16));
+ lock.release();
+ }
+
+ return 0;
+ }
+
+ // now processing F_SETLK
+ if (cmd != F_SETLK) return -EINVAL;
+
+ if (l_type == F_UNLCK) {
+ // release all locks that fall within the boundaries given
+ for (int i=0; i < locks.length; i++) {
+ if (locks[i] == null || !s.equals(locks[i].seekable()))
+ continue;
+ if (locks[i].getOwner() != this) continue;
+
+ int pos = (int)locks[i].position();
+ if (pos < l_start) continue;
+ if (l_start != 0 && l_len != 0) // start/len 0 means unlock all
+ if (pos + locks[i].size() > l_start + l_len)
+ continue;
+
+ locks[i].release();
+ locks[i] = null;
+ }
+ return 0;
+
+ } else if (l_type == F_RDLCK || l_type == F_WRLCK) {
+ // first see if a lock already exists
+ for (int i=0; i < locks.length; i++) {
+ if (locks[i] == null || !s.equals(locks[i].seekable()))
+ continue;
+
+ if (locks[i].getOwner() == this) {
+ // if this Runtime owns an overlapping lock work with it
+ if (locks[i].contained(l_start, l_len)) {
+ locks[i].release();
+ locks[i] = null;
+ } else if (locks[i].contains(l_start, l_len)) {
+ if (locks[i].isShared() == (l_type == F_RDLCK)) {
+ // return this more general lock
+ memWrite(arg+4, (int)locks[i].position());
+ memWrite(arg+8, (int)locks[i].size());
+ return 0;
+ } else {
+ locks[i].release();
+ locks[i] = null;
+ }
+ }
+ } else {
+ // if another Runtime has an lock and it is exclusive or
+ // we want an exclusive lock then fail
+ if (locks[i].overlaps(l_start, l_len)
+ && (!locks[i].isShared() || l_type == F_WRLCK))
+ return -EAGAIN;
+ }
+ }
+
+ // create the lock
+ Seekable.Lock lock = s.lock(l_start, l_len, l_type == F_RDLCK);
+ if (lock == null) return -EAGAIN;
+ lock.setOwner(this);
+
+ int i;
+ for (i=0; i < locks.length; i++)
+ if (locks[i] == null) break;
+ if (i == locks.length) return -ENOLCK;
+ locks[i] = lock;
+ return 0;
+
+ } else {
+ return -EINVAL;
+ }
+
+ } catch (IOException e) { throw new RuntimeException(e); }
+ }
+
static class SocketFD extends FD {
public static final int TYPE_STREAM = 0;
public static final int TYPE_DGRAM = 1;
@@ -1146,6 +1327,9 @@ public abstract class UnixRuntime extends Runtime implements Cloneable {
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;
@@ -1154,9 +1338,62 @@ public abstract class UnixRuntime extends Runtime implements Cloneable {
public GlobalState(int maxProcs, boolean defaultMounts) {
tasks = new UnixRuntime[maxProcs+1];
if(defaultMounts) {
- addMount("/",new HostFS());
+ 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