From: brian Date: Wed, 21 Apr 2004 03:52:19 +0000 (-0700) Subject: new fs stuff X-Git-Tag: merge~32 X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=commitdiff_plain;h=9a641039c47c2619982213501f49e1168fcdbda2 new fs stuff darcs-hash:20040421035219-24bed-5a0c1aee6c56334a83fd5bdbfdb6572d3a3e74af.gz --- diff --git a/src/org/ibex/nestedvm/ClassLoader.java b/src/org/ibex/nestedvm/ClassLoader.java index f51cd51..c1023b0 100644 --- a/src/org/ibex/nestedvm/ClassLoader.java +++ b/src/org/ibex/nestedvm/ClassLoader.java @@ -4,6 +4,11 @@ import java.io.*; // FEATURE: This is just a quick hack, it is really ugly and broken +// FEATURE: Cache based on org.ibex.util.Cache +// FEATURE: Base64 encode some id to form package name +// FEATURE: Timestamped cache entries, requests carry minimum timestamp +// NOTE: Need to handle binaries spanned accross many classfiles + public class ClassLoader extends java.lang.ClassLoader { public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Class c; diff --git a/src/org/ibex/nestedvm/Compiler.java b/src/org/ibex/nestedvm/Compiler.java index de5a048..c68e5cf 100644 --- a/src/org/ibex/nestedvm/Compiler.java +++ b/src/org/ibex/nestedvm/Compiler.java @@ -7,6 +7,8 @@ import java.io.*; import org.ibex.nestedvm.util.*; +// FEATURE: -d option for classfilecompiler (just like javac's -d) + public abstract class Compiler implements Registers { /** The ELF binary being read */ protected ELF elf; diff --git a/src/org/ibex/nestedvm/Runtime.java b/src/org/ibex/nestedvm/Runtime.java index 902e377..bcbadd4 100644 --- a/src/org/ibex/nestedvm/Runtime.java +++ b/src/org/ibex/nestedvm/Runtime.java @@ -194,6 +194,7 @@ public abstract class Runtime implements UsermodeConstants,Registers { addr INTO a java byte array a */ public final void copyin(int addr, byte[] buf, int count) throws ReadFaultException { int x=0; + if(count == 0) return; if((addr&3)!=0) { int word = memRead(addr&~3); switch(addr&3) { @@ -236,6 +237,7 @@ public abstract class Runtime implements UsermodeConstants,Registers { space at addr */ public final void copyout(byte[] buf, int addr, int count) throws FaultException { int x=0; + if(count == 0) return; if((addr&3)!=0) { int word = memRead(addr&~3); switch(addr&3) { @@ -1161,9 +1163,17 @@ public abstract class Runtime implements UsermodeConstants,Registers { private final boolean executable; public HostFStat(File f) { this.f = f; - String name = f.getName(); - // FEATURE: This is ugly.. maybe we should do a file(1) type check - executable = name.endsWith(".mips") || name.endsWith(".sh"); + boolean _executable = false; + // FEATURE: This might be too expensive + try { + FileInputStream fis = new FileInputStream(f); + switch(fis.read()) { + case '\177': _executable = fis.read() == 'E' && fis.read() == 'L' && fis.read() == 'F'; break; + case '#': _executable = fis.read() == '!'; + } + fis.close(); + } catch(IOException e) { /* ignore */ } + executable = _executable; } public int dev() { return 1; } public int inode() { return f.getName().hashCode() & 0xffff; } diff --git a/src/org/ibex/nestedvm/UnixRuntime.java b/src/org/ibex/nestedvm/UnixRuntime.java index 3befb91..bcac59b 100644 --- a/src/org/ibex/nestedvm/UnixRuntime.java +++ b/src/org/ibex/nestedvm/UnixRuntime.java @@ -4,6 +4,9 @@ import org.ibex.nestedvm.util.*; import java.io.*; import java.util.*; +// FEATURE: BusyBox's ASH doesn't like \r\n at the end of lines +// is ash just broken or are many apps like this? if so workaround in nestedvm + public abstract class UnixRuntime extends Runtime { /** The pid of this "process" */ private int pid; @@ -18,7 +21,8 @@ public abstract class UnixRuntime extends Runtime { this.fs = fs; } - /** proceses current working directory */ + /** proceses' current working directory - absolute path WITHOUT leading slash + "" = root, "bin" = /bin "usr/bin" = /usr/bin */ private String cwd; /* Static stuff */ @@ -48,16 +52,15 @@ public abstract class UnixRuntime extends Runtime { public UnixRuntime(int pageSize, int totalPages, boolean allowEmptyPages) { super(pageSize,totalPages,allowEmptyPages); - HostFS root = new HostFS(); - fs = new UnixOverlayFS(root); + FS root = new HostFS(); + FS dev = new DevFS(); + MountPointFS mounts = new MountPointFS(root); + mounts.add("/dev",dev); + fs = mounts; - String dir = root.hostCWD(); - try { - chdir(dir == null ? "/" : dir); - } catch(FileNotFoundException e) { - e.printStackTrace(); - cwd = "/"; - } + // FEATURE: Do the proper mangling for non-unix hosts + String userdir = getSystemProperty("user.dir"); + cwd = userdir != null && userdir.startsWith("/") && File.separatorChar == '/' ? userdir.substring(1) : ""; } // NOTE: getDisplayName() is a Java2 function @@ -128,12 +131,15 @@ public abstract class UnixRuntime extends Runtime { case SYS_mkdir: return sys_mkdir(a,b); case SYS_getcwd: return sys_getcwd(a,b); case SYS_chdir: return sys_chdir(a); + case SYS_execve: return sys_execve(a,b.c); default: return super.syscall(syscall,a,b,c,d); } } - protected FD open(String path, int flags, int mode) throws IOException { return fs.open(cleanupPath(path),flags,mode); } + protected FD open(String path, int flags, int mode) throws IOException { + return fs.open(normalizePath(path),flags,mode); + } // FEATURE: Allow simple, broken signal delivery to other processes // (check if a signal was delivered before and after syscalls) @@ -214,6 +220,7 @@ public abstract class UnixRuntime extends Runtime { } } + // FEATURE: Make this cleaner // Great ugliness lies within..... private int sys_fork() { CPUState state = getCPUState(); @@ -264,6 +271,20 @@ public abstract class UnixRuntime extends Runtime { return child_pid; } + + private int sys_execve(int cstring, int argv, int envp) { + /* + try { + String path = cstring(cstring); + FStat stat = fs.stat(path); + + + } + catch(FaultException e) { return -EFAULT; } + catch(FileNotFoundException e) { return -ENOENT; } + catch(IOException e) { return -EIO; }*/ + throw new Error("FIXME - exec() isn't finished"); + } private int sys_pipe(int addr) { PipedOutputStream writerStream = new PipedOutputStream(); @@ -302,7 +323,7 @@ public abstract class UnixRuntime extends Runtime { private int sys_stat(int cstring, int addr) { try { - String path = cleanupPath(cstring(cstring)); + String path = normalizePath(cstring(cstring)); return stat(fs.stat(path),addr); } catch(ErrnoException e) { return -e.errno; } @@ -317,7 +338,7 @@ public abstract class UnixRuntime extends Runtime { private int sys_mkdir(int cstring, int mode) { try { - fs.mkdir(cleanupPath(cstring(cstring))); + fs.mkdir(normalizePath(cstring(cstring))); return 0; } catch(ErrnoException e) { return -e.errno; } @@ -330,10 +351,10 @@ public abstract class UnixRuntime extends Runtime { private int sys_getcwd(int addr, int size) { byte[] b = getBytes(cwd); if(size == 0) return -EINVAL; - if(size < b.length+1) return -ERANGE; - if(!new File(cwd).exists()) return -ENOENT; + if(size < b.length+2) return -ERANGE; try { - copyout(b,addr,b.length); + memset(addr,'/',1); + copyout(b,addr+1,b.length); memset(addr+b.length+1,0,1); return addr; } catch(FaultException e) { @@ -343,11 +364,11 @@ public abstract class UnixRuntime extends Runtime { private int sys_chdir(int addr) { try { - String path = cleanupPath(cstring(addr)); + String path = normalizePath(cstring(addr)); System.err.println("Chdir: " + cstring(addr) + " -> " + path + " pwd: " + cwd); if(fs.stat(path).type() != FStat.S_IFDIR) return -ENOTDIR; cwd = path; - System.err.println("Now: " + cwd); + System.err.println("Now: [" + cwd + "]"); return 0; } catch(ErrnoException e) { return -e.errno; } @@ -359,7 +380,7 @@ public abstract class UnixRuntime extends Runtime { public void chdir(String dir) throws FileNotFoundException { if(state >= RUNNING) throw new IllegalStateException("Can't chdir while process is running"); try { - dir = cleanupPath(dir); + dir = normalizePath(dir); if(fs.stat(dir).type() != FStat.S_IFDIR) throw new FileNotFoundException(); } catch(IOException e) { throw new FileNotFoundException(); @@ -368,11 +389,29 @@ public abstract class UnixRuntime extends Runtime { } public abstract static class FS { - public FD open(String path, int flags, int mode) throws IOException { throw new FileNotFoundException(); } - public FStat stat(String path) throws IOException { throw new FileNotFoundException(); } - public void mkdir(String path) throws IOException { throw new ErrnoException(ENOTDIR); } + protected FD _open(String path, int flags, int mode) throws IOException { return null; } + protected FStat _stat(String path) throws IOException { return null; } + protected void _mkdir(String path) throws IOException { throw new ErrnoException(EROFS); } + + protected static final int OPEN = 1; + protected static final int STAT = 2; + protected static final int MKDIR = 3; - public static FD directoryFD(String[] files, int hashCode) throws IOException { + protected Object op(int op, String path, int arg1, int arg2) throws IOException { + switch(op) { + case OPEN: return _open(path,arg1,arg2); + case STAT: return _stat(path); + case MKDIR: _mkdir(path); return null; + default: throw new IllegalArgumentException("Unknown FS OP"); + } + } + + public final FD open(String path, int flags, int mode) throws IOException { return (FD) op(OPEN,path,flags,mode); } + public final FStat stat(String path) throws IOException { return (FStat) op(STAT,path,0,0); } + public final void mkdir(String path) throws IOException { op(MKDIR,path,0,0); } + + // FIXME: inode stuff + protected static FD directoryFD(String[] files, int hashCode) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); for(int i=0;i 0) outp--; + while(outp > 0 && out[outp] != '/') outp--; + System.err.println("After ..: " + new String(out,0,outp)); + continue; + } + inp++; + out[outp++] = '.'; + } + if(outp > 0 && out[outp-1] == '/') outp--; + //System.err.println("normalize: " + path + " -> " + new String(out,0,outp) + " (cwd: " + cwd + ")"); + return new String(out,0,outp); } // FIXME: This is probably still buggy // FEATURE: Remove some of the "should never happen checks" - protected String cleanupPath(String p) throws ErrnoException { + /*protected static String cleanupPath(String p) throws ErrnoException { if(p.length() == 0) throw new ErrnoException(ENOENT); if(needsCleanup(p)) { char[] in = p.toCharArray(); @@ -453,10 +523,79 @@ public abstract class UnixRuntime extends Runtime { if(!cwd.equals("/")) sb.append('/'); return sb.append(p).toString(); } + }*/ + + 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