From: brian Date: Tue, 4 May 2004 08:04:13 +0000 (-0700) Subject: even more fixmes/features X-Git-Tag: merge~25 X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=commitdiff_plain;h=98f786ce8ee1fcd9568d1c367160851d32e1c786 even more fixmes/features darcs-hash:20040504080413-24bed-cbd5cee5602aac4be9c3a666d2af6a748f6de006.gz --- diff --git a/src/org/ibex/nestedvm/ClassFileCompiler.java b/src/org/ibex/nestedvm/ClassFileCompiler.java index 0f0b418..931f1b9 100644 --- a/src/org/ibex/nestedvm/ClassFileCompiler.java +++ b/src/org/ibex/nestedvm/ClassFileCompiler.java @@ -1073,23 +1073,10 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if(pc == -1) throw new Exn("pc modifying insn in delay slot"); int target = (pc&0xf0000000)|(jumpTarget << 2); emitInstruction(-1,nextInsn,-1); - // FIXME: Have a memcpy syscall and just override memcpy in libnestedvm - if(optimizedMemcpy && (target == memcpy || target == memset)) { - a(InstructionConstants.ALOAD_0); - pushRegZ(R+4); - pushRegZ(R+5); - pushRegZ(R+6); - a(fac.createInvoke(fullClassName,target==memcpy ? "memcpy" : "memset", Type.VOID, new Type[]{Type.INT,Type.INT,Type.INT},INVOKEVIRTUAL)); - preSetReg(R+2); - pushReg(R+4); - setReg(); - branch(pc,pc+8); - } else { - preSetReg(R+RA); - pushConst(pc+8); - setReg(); - branch(pc, target); - } + preSetReg(R+RA); + pushConst(pc+8); + setReg(); + branch(pc, target); unreachable = true; break; } diff --git a/src/org/ibex/nestedvm/Compiler.java b/src/org/ibex/nestedvm/Compiler.java index 68d2dee..ebdf29d 100644 --- a/src/org/ibex/nestedvm/Compiler.java +++ b/src/org/ibex/nestedvm/Compiler.java @@ -50,8 +50,6 @@ public abstract class Compiler implements Registers { protected boolean assumeTailCalls = true; - protected boolean optimizedMemcpy = true; - // True to insert some code in the output to help diagnore compiler problems protected boolean debugCompiler = false; @@ -84,12 +82,6 @@ public abstract class Compiler implements Registers { while(pageSize>>>pageShift != 1) pageShift++; } - /** The address of the memcpy function in the binary (used for optimizedMemcpy) */ - protected int memcpy; - - /** The address of the memset function in the binary (used for optimizedMemcpy) */ - protected int memset; - /** A set of all addresses that can be jumped too (only available if pruneCases == true) */ protected Set jumpableAddresses; @@ -213,13 +205,6 @@ public abstract class Compiler implements Registers { if(symtab == null) throw new Exn("Binary has no symtab (did you strip it?)"); ELF.Symbol sym; - // Check for some functions we can override - sym = symtab.getGlobalSymbol("memcpy"); - memcpy = sym == null ? -1 : sym.addr; - - sym = symtab.getGlobalSymbol("memset"); - memset = sym == null ? -1 : sym.addr; - userInfo = symtab.getGlobalSymbol("user_info"); gp = symtab.getGlobalSymbol("_gp"); if(gp == null) throw new Exn("no _gp symbol (did you strip the binary?)"); diff --git a/src/org/ibex/nestedvm/JavaSourceCompiler.java b/src/org/ibex/nestedvm/JavaSourceCompiler.java index 887e232..a983b58 100644 --- a/src/org/ibex/nestedvm/JavaSourceCompiler.java +++ b/src/org/ibex/nestedvm/JavaSourceCompiler.java @@ -549,17 +549,8 @@ public class JavaSourceCompiler extends Compiler { if(pc == -1) throw new Error("pc modifying insn in delay slot"); int target = (pc&0xf0000000)|(jumpTarget << 2); emitInstruction(-1,nextInsn,-1); - if(optimizedMemcpy && (target == memcpy || target == memset)) { - if(target == memcpy) - p("memcpy(r4,r5,r6);"); - else if(target == memset) - p("memset(r4,r5,r6);"); - p("r2 = r4;"); - branch(pc,pc+8); - } else { - p("r" + RA + "=" + constant(pc+8 /*skip this insn and delay slot*/) + ";"); - branch(pc, target); - } + p("r" + RA + "=" + constant(pc+8 /*skip this insn and delay slot*/) + ";"); + branch(pc, target); unreachable = true; break; } diff --git a/src/org/ibex/nestedvm/Runtime.java b/src/org/ibex/nestedvm/Runtime.java index 80fcadd..fc97e71 100644 --- a/src/org/ibex/nestedvm/Runtime.java +++ b/src/org/ibex/nestedvm/Runtime.java @@ -81,7 +81,7 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { private byte[] _byteBuf; /** Max size of temporary buffer @see Runtime#_byteBuf */ - private final static int MAX_CHUNK = 16*1024*1024 - 1024; + final static int MAX_CHUNK = 16*1024*1024 - 1024; /** Subclasses should actually execute program in this method. They should continue executing until state != RUNNING. Only syscall() can modify state. It is safe @@ -292,7 +292,6 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public final void memcpy(int dst, int src, int count) throws FaultException { int pageWords = (1<>>2; int pageWordMask = pageWords - 1; - if((dst&3) == 0 && (src&3)==0) { if((count&~3) != 0) { int c = count>>2; @@ -693,12 +692,12 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public static final int O_TRUNC = 0x0400; public static final int O_NONBLOCK = 0x4000; - FD hostFSOpen(final File f, int flags, int mode) throws ErrnoException { + FD hostFSOpen(final File f, int flags, int mode, final Object data) throws ErrnoException { if((flags & ~(3|O_CREAT|O_EXCL|O_APPEND|O_TRUNC)) != 0) { System.err.println("WARNING: Unsupported flags passed to open(): " + toHex(flags & ~(3|O_CREAT|O_EXCL|O_APPEND|O_TRUNC))); throw new ErrnoException(ENOTSUP); } - boolean write = mode!=RD_ONLY; + boolean write = (flags&3) != RD_ONLY; if(sm != null && !(write ? sm.allowWrite(f) : sm.allowRead(f))) throw new ErrnoException(EACCES); @@ -712,7 +711,7 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { } else if(!f.exists()) { if((flags&O_CREAT)==0) return null; } else if(f.isDirectory()) { - return hostFSDirFD(f); + return hostFSDirFD(f,data); } final Seekable.File sf; @@ -723,14 +722,15 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { return null; } catch(IOException e) { throw new ErrnoException(EIO); } - return new SeekableFD(sf,flags) { protected FStat _fstat() { return hostFStat(f); } }; + return new SeekableFD(sf,flags) { protected FStat _fstat() { return hostFStat(f,data); } }; } - FStat hostFStat(File f) { return new HostFStat(f); } - FD hostFSDirFD(File f) { return null; } + FStat hostFStat(File f, Object data) { return new HostFStat(f); } + + FD hostFSDirFD(File f, Object data) { return null; } FD _open(String path, int flags, int mode) throws ErrnoException { - return hostFSOpen(new File(path),flags,mode); + return hostFSOpen(new File(path),flags,mode,null); } /** The open syscall */ @@ -743,34 +743,26 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { } /** The write syscall */ - private int sys_write(int fdn, int addr, int count) throws FaultException { + + // FIXME: Handle pipe closed exception + private int sys_write(int fdn, int addr, int count) throws FaultException, ErrnoException { count = Math.min(count,MAX_CHUNK); if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; - if(fds[fdn] == null || !fds[fdn].writable()) return -EBADFD; - try { - byte[] buf = byteBuf(count); - copyin(addr,buf,count); - return fds[fdn].write(buf,0,count); - } catch(IOException e) { - // NOTE: This should really send a SIGPIPE - if(e.getMessage().equals("Pipe closed")) return sys_exit(128+13); - return -EIO; - } + if(fds[fdn] == null) return -EBADFD; + byte[] buf = byteBuf(count); + copyin(addr,buf,count); + return fds[fdn].write(buf,0,count); } /** The read syscall */ - private int sys_read(int fdn, int addr, int count) throws FaultException { + private int sys_read(int fdn, int addr, int count) throws FaultException, ErrnoException { count = Math.min(count,MAX_CHUNK); if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; - if(fds[fdn] == null || !fds[fdn].readable()) return -EBADFD; - try { - byte[] buf = byteBuf(count); - int n = fds[fdn].read(buf,0,count); - copyout(buf,addr,n); - return n; - } catch(IOException e) { - return -EIO; - } + if(fds[fdn] == null) return -EBADFD; + byte[] buf = byteBuf(count); + int n = fds[fdn].read(buf,0,count); + copyout(buf,addr,n); + return n; } /** The close syscall */ @@ -780,16 +772,12 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { /** The seek syscall */ - private int sys_lseek(int fdn, int offset, int whence) { + private int sys_lseek(int fdn, int offset, int whence) throws ErrnoException { if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; if(fds[fdn] == null) return -EBADFD; if(whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) return -EINVAL; - try { - int n = fds[fdn].seek(offset,whence); - return n < 0 ? -ESPIPE : n; - } catch(IOException e) { - return -ESPIPE; - } + int n = fds[fdn].seek(offset,whence); + return n < 0 ? -ESPIPE : n; } /** The stat/fstat syscall helper */ @@ -940,13 +928,6 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { private int sys_getpagesize() { return writePages.length == 1 ? 4096 : (1<= OPEN_MAX) return -EBADFD; - if(fds[fdn] == null) return -EBADFD; - return fds[fdn].isatty() ? 1 : 0; - } - - /** Hook for subclasses to do something when the process exits */ void _exited() { } @@ -973,10 +954,7 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { fds[i] = fd.dup(); return 0; case F_GETFL: - int flags = 0; - if(fd.writable() && fd.readable()) flags = 2; - else if(fd.writable()) flags = 1; - return flags; + return fd.flags(); case F_SETFD: closeOnExec[fdn] = arg != 0; return 0; @@ -1025,9 +1003,11 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { case SYS_sleep: return sys_sleep(a); case SYS_times: return sys_times(a); case SYS_getpagesize: return sys_getpagesize(); - case SYS_isatty: return sys_isatty(a); case SYS_fcntl: return sys_fcntl(a,b,c); case SYS_sysconf: return sys_sysconf(a); + + case SYS_memcpy: memcpy(a,b,c); return a; + case SYS_memset: memset(a,b,c); return a; case SYS_kill: case SYS_fork: @@ -1087,28 +1067,23 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { /** File Descriptor class */ public static abstract class FD { private int refCount = 1; - - /** returns true if the fd is readable */ - public boolean readable() { return false; } - /** returns true if the fd is writable */ - public boolean writable() { return false; } /** Read some bytes. Should return the number of bytes read, 0 on EOF, or throw an IOException on error */ - public int read(byte[] a, int off, int length) throws IOException { throw new IOException("no definition"); } + public int read(byte[] a, int off, int length) throws ErrnoException { throw new ErrnoException(EBADFD); } /** Write. Should return the number of bytes written or throw an IOException on error */ - public int write(byte[] a, int off, int length) throws IOException { throw new IOException("no definition"); } + public int write(byte[] a, int off, int length) throws ErrnoException { throw new ErrnoException(EBADFD); } /** Seek in the filedescriptor. Whence is SEEK_SET, SEEK_CUR, or SEEK_END. Should return -1 on error or the new position. */ - public int seek(int n, int whence) throws IOException { return -1; } + public int seek(int n, int whence) throws ErrnoException { return -1; } + + public int getdents(byte[] a, int off, int length) throws ErrnoException { throw new ErrnoException(EBADFD); } + + public int flags() { return O_RDONLY; } /** Return a Seekable object representing this file descriptor (can be read only) This is required for exec() */ Seekable seekable() { return null; } - /** Should return true if this is a tty */ - // FIXME: get rid of the isatty syscall and just do with newlib's dumb isatty.c - public boolean isatty() { return false; } - private FStat cachedFStat = null; public final FStat fstat() { if(cachedFStat == null) cachedFStat = _fstat(); @@ -1128,35 +1103,48 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public abstract static class SeekableFD extends FD { private final int flags; private final Seekable data; - public boolean readable() { return (flags&3) != WR_ONLY; } - public boolean writable() { return (flags&3) != RD_ONLY; } SeekableFD(Seekable data, int flags) { this.data = data; this.flags = flags; } protected abstract FStat _fstat(); + public int flags() { return flags; } Seekable seekable() { return data; } - public int seek(int n, int whence) throws IOException { - switch(whence) { - case SEEK_SET: break; - case SEEK_CUR: n += data.pos(); break; - case SEEK_END: n += data.length(); break; - default: return -1; + public int seek(int n, int whence) throws ErrnoException { + try { + switch(whence) { + case SEEK_SET: break; + case SEEK_CUR: n += data.pos(); break; + case SEEK_END: n += data.length(); break; + default: return -1; + } + data.seek(n); + return n; + } catch(IOException e) { + throw new ErrnoException(ESPIPE); } - data.seek(n); - return n; } - public int write(byte[] a, int off, int length) throws IOException { + public int write(byte[] a, int off, int length) throws ErrnoException { + if((flags&3) == RD_ONLY) throw new ErrnoException(EBADFD); // NOTE: There is race condition here but we can't fix it in pure java if((flags&O_APPEND) != 0) seek(0,SEEK_END); - return data.write(a,off,length); + try { + return data.write(a,off,length); + } catch(IOException e) { + throw new ErrnoException(EIO); + } } - public int read(byte[] a, int off, int length) throws IOException { - int n = data.read(a,off,length); - return n < 0 ? 0 : n; + public int read(byte[] a, int off, int length) throws ErrnoException { + if((flags&3) == WR_ONLY) throw new ErrnoException(EBADFD); + try { + int n = data.read(a,off,length); + return n < 0 ? 0 : n; + } catch(IOException e) { + throw new ErrnoException(EIO); + } } protected void _close() { try { data.close(); } catch(IOException e) { /*ignore*/ } } @@ -1164,18 +1152,32 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public static class OutputStreamFD extends FD { private OutputStream os; - public boolean writable() { return true; } + public int flags() { return O_WRONLY; } public OutputStreamFD(OutputStream os) { this.os = os; } - public int write(byte[] a, int off, int length) throws IOException { os.write(a,off,length); return length; } + public int write(byte[] a, int off, int length) throws ErrnoException { + try { + os.write(a,off,length); + return length; + } catch(IOException e) { + throw new ErrnoException(EIO); + } + } public void _close() { try { os.close(); } catch(IOException e) { /*ignore*/ } } public FStat _fstat() { return new FStat(); } } public static class InputStreamFD extends FD { private InputStream is; - public boolean readable() { return true; } + public int flags() { return O_RDONLY; } public InputStreamFD(InputStream is) { this.is = is; } - public int read(byte[] a, int off, int length) throws IOException { int n = is.read(a,off,length); return n < 0 ? 0 : n; } + public int read(byte[] a, int off, int length) throws ErrnoException { + try { + int n = is.read(a,off,length); + return n < 0 ? 0 : n; + } catch(IOException e) { + throw new ErrnoException(EIO); + } + } public void _close() { try { is.close(); } catch(IOException e) { /*ignore*/ } } public FStat _fstat() { return new FStat(); } } @@ -1184,14 +1186,12 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public StdinFD(InputStream is) { super(is); } public void _close() { /* noop */ } public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; } - public boolean isatty() { return true; } } static class StdoutFD extends OutputStreamFD { public StdoutFD(OutputStream os) { super(os); } public void _close() { /* noop */ } public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; } - public boolean isatty() { return true; } } public static class FStat { @@ -1200,9 +1200,8 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public static final int S_IFDIR = 0040000; public static final int S_IFREG = 0100000; - public int dev() { return -1; } - // FIXME: inode numbers are calculated inconsistently throught the runtime - public int inode() { return hashCode() & 0xfffff; } + public int dev() { return 1; } + public int inode() { return hashCode() & 0x7fff; } public int mode() { return 0; } public int type() { return S_IFIFO; } public int nlink() { return 0; } @@ -1308,7 +1307,7 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { } // Utility functions - private byte[] byteBuf(int size) { + byte[] byteBuf(int size) { if(_byteBuf==null) _byteBuf = new byte[size]; else if(_byteBuf.length < size) _byteBuf = new byte[min(max(_byteBuf.length*2,size),MAX_CHUNK)]; diff --git a/src/org/ibex/nestedvm/RuntimeCompiler.java b/src/org/ibex/nestedvm/RuntimeCompiler.java index 2aa4305..80f56ac 100644 --- a/src/org/ibex/nestedvm/RuntimeCompiler.java +++ b/src/org/ibex/nestedvm/RuntimeCompiler.java @@ -5,8 +5,9 @@ import java.io.*; import org.ibex.nestedvm.util.*; // FEATURE: This need a lot of work to support binaries spanned across many classes -public class RuntimeCompiler { - private static final SingleClassLoader singleClassLoader = new SingleClassLoader(); +public class RuntimeCompiler { + // FEATURE: Do we need to periodicly create a new classloader to allow old clases to be GCed? + private static SingleClassLoader singleClassLoader = new SingleClassLoader(); // FEATURE: Is it ok if this overflows? private static long nextID = 1; private static synchronized String uniqueID() { return Long.toString(nextID++); } diff --git a/src/org/ibex/nestedvm/UnixRuntime.java b/src/org/ibex/nestedvm/UnixRuntime.java index 8aa5dc7..5eb9178 100644 --- a/src/org/ibex/nestedvm/UnixRuntime.java +++ b/src/org/ibex/nestedvm/UnixRuntime.java @@ -4,14 +4,10 @@ import org.ibex.nestedvm.util.*; import java.io.*; import java.util.*; -// FIXME: Fix readdir in support_aux.c // FIXME: Make plain old "mips-unknown-elf-gcc -o foo foo.c" work (modify spec file or whatever) // FEATURE: Remove System.{out,err}.printlns and throw Errors where applicable -// FIXME: 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 implements Cloneable { /** The pid of this "process" */ private int pid; @@ -112,6 +108,7 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { case SYS_getcwd: return sys_getcwd(a,b); case SYS_chdir: return sys_chdir(a); case SYS_exec: return sys_exec(a,b,c); + case SYS_getdents: return sys_getdents(a,b,c,d); default: return super._syscall(syscall,a,b,c,d); } @@ -407,7 +404,6 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { return 0; } - private int sys_getcwd(int addr, int size) throws FaultException, ErrnoException { byte[] b = getBytes(cwd); if(size == 0) return -EINVAL; @@ -427,6 +423,16 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { return 0; } + private int sys_getdents(int fdn, int addr, int count, int seekptr) throws FaultException, ErrnoException { + count = Math.min(count,MAX_CHUNK); + if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; + if(fds[fdn] == null) return -EBADFD; + byte[] buf = byteBuf(count); + int n = fds[fdn].getdents(buf,0,count); + copyout(buf,addr,n); + return n; + } + // FEATURE: Run through the fork/wait stuff one more time public static class GlobalState { protected static final int OPEN = 1; @@ -437,7 +443,7 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { final UnixRuntime[] tasks; int nextPID = 1; - private final MP[][] mps = new MP[128][]; + private MP[] mps = new MP[0]; private FS root; public GlobalState() { this(255); } @@ -445,7 +451,7 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { public GlobalState(int maxProcs, boolean defaultMounts) { tasks = new UnixRuntime[maxProcs+1]; if(defaultMounts) { - root = new HostFS(); + addMount("/",new HostFS()); addMount("/dev",new DevFS()); } } @@ -464,56 +470,70 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { if(!path.startsWith("/")) throw new IllegalArgumentException("Mount point doesn't start with a /"); if(path.equals("/")) return root; path = path.substring(1); - 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; + for(int i=0;i>>24)&0xff); + buf[off+1] = (byte)((n>>>16)&0xff); + buf[off+2] = (byte)((n>>> 8)&0xff); + buf[off+3] = (byte)((n>>> 0)&0xff); + } + + public static abstract class DirFD extends FD { + private int pos = -2; + + protected abstract int size(); + protected abstract String name(int n); + protected abstract int inode(int n); + protected abstract int myDev(); + protected int parentInode() { return -1; } + protected int myInode() { return -1; } + + public int getdents(byte[] buf, int off, int len) { + int ooff = off; + int ino; + int reclen; + OUTER: for(;len > 0 && pos < size();pos++){ + switch(pos) { + case -2: + case -1: + ino = pos == -1 ? parentInode() : myInode(); + if(ino == -1) continue; + reclen = 9 + (pos == -1 ? 2 : 1); + if(reclen > len) break OUTER; + buf[off+8] = '.'; + if(pos == -1) buf[off+9] = '.'; + break; + default: { + String f = name(pos); + byte[] fb = getBytes(f); + reclen = fb.length + 9; + if(reclen > len) break OUTER; + ino = inode(pos); + System.arraycopy(fb,0,buf,off+8,fb.length); + } + } + buf[off+reclen-1] = 0; // null terminate + reclen = (reclen + 3) & ~3; // add padding + putInt(buf,off,reclen); + putInt(buf,off+4,ino); + off += reclen; + len -= reclen; + } + return off-ooff; + } + + protected FStat _fstat() { + return new FStat() { + public int type() { return S_IFDIR; } + public int inode() { return myInode(); } + public int dev() { return myDev(); } + }; + } } public static class DevFS extends FS { - private static class DevFStat extends FStat { - public int dev() { return 1; } + private static final int ROOT_INODE = 1; + private static final int NULL_INODE = 2; + private static final int ZERO_INODE = 3; + private static final int FD_INODE = 4; + private static final int FD_INODES = 32; + + private class DevFStat extends FStat { + public int dev() { return devno; } public int mode() { return 0666; } public int type() { return S_IFCHR; } public int nlink() { return 1; } } - private static FD devZeroFD = new FD() { + + private abstract class DevDirFD extends DirFD { + public int myDev() { return devno; } + } + + private FD devZeroFD = new FD() { public boolean readable() { return true; } public boolean writable() { return true; } public int read(byte[] a, int off, int length) { Arrays.fill(a,off,off+length,(byte)0); return length; } public int write(byte[] a, int off, int length) { return length; } public int seek(int n, int whence) { return 0; } - public FStat _fstat() { return new DevFStat(); } + public FStat _fstat() { return new DevFStat(){ public int inode() { return ZERO_INODE; } }; } }; - private static FD devNullFD = new FD() { + private FD devNullFD = new FD() { public boolean readable() { return true; } public boolean writable() { return true; } public int read(byte[] a, int off, int length) { return 0; } public int write(byte[] a, int off, int length) { return length; } public int seek(int n, int whence) { return 0; } - public FStat _fstat() { return new DevFStat(); } + public FStat _fstat() { return new DevFStat(){ public int inode() { return NULL_INODE; } }; } }; public FD open(UnixRuntime r, String path, int mode, int flags) throws ErrnoException { @@ -816,15 +910,42 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { } if(path.equals("fd")) { int count=0; - for(int i=0;i_errno != ERANGE) return NULL; } - return 0; } DIR *opendir(const char *path) { @@ -105,40 +118,35 @@ DIR *opendir(const char *path) { return NULL; } dir->dd_fd = fd; - //dir->dd_pos = 0; + dir->dd_buf = malloc(sizeof(struct dirent)); + dir->dd_size = sizeof(struct dirent); + if(dir->dd_buf == NULL) { + close(fd); + free(dir); + return NULL; + } + dir->dd_loc = 0; + dir->dd_len = 0; return dir; } -int readdir_r(DIR *dir,struct dirent *entry, struct dirent **result) { - struct { - int inode; - int name_len; - } h; - if(dir->dd_fd < 0) return -1; -again: - if(read_fully(dir->dd_fd,&h,sizeof(h)) < 0) goto fail; - if(h.name_len < 0 || h.name_len >= sizeof(entry->d_name)-1) goto fail; - - entry->d_ino = h.inode; - if(read_fully(dir->dd_fd,entry->d_name,h.name_len) < 0) goto fail; - - entry->d_name[h.name_len] = '\0'; - //dir->dd_pos += h.name_len + 8; - - if(result) *result = entry; - return 0; -fail: - if(result) *result = NULL; - return -1; +struct dirent *readdir(DIR *dir) { + struct dirent *dp; + errno = 0; + if(dir->dd_loc == 0 || dir->dd_loc == dir->dd_len) { + dir->dd_len = getdents(dir->dd_fd,dir->dd_buf,dir->dd_size,NULL); + dir->dd_loc = 0; + if(dir->dd_len <= 0) { dir->dd_len = 0; return NULL; } + } + dp = (struct dirent*) (dir->dd_buf + dir->dd_loc); + if(dp->d_reclen == 0 || dp->d_reclen > dir->dd_len - dir->dd_loc) return NULL; + dir->dd_loc += dp->d_reclen; + return dp; } -// FIXME: Rewrite all this dirent stuff in terms of a getdirentries syscall -static struct dirent static_dir_ent; - -struct dirent *readdir(DIR *dir) { return readdir_r(dir,&static_dir_ent,NULL) == 0 ? &static_dir_ent : NULL; } - int closedir(DIR *dir) { - close(dir->dd_fd); + int fd = dir->dd_fd; + free(dir->dd_buf); free(dir); - return 0; + return close(fd); } diff --git a/src/org/ibex/nestedvm/syscalls.h b/src/org/ibex/nestedvm/syscalls.h index b4a36ed..be74766 100644 --- a/src/org/ibex/nestedvm/syscalls.h +++ b/src/org/ibex/nestedvm/syscalls.h @@ -7,7 +7,6 @@ #define SYS_write 6 #define SYS_sbrk 7 #define SYS_fstat 8 -#define SYS_isatty 9 #define SYS_lseek 10 #define SYS_kill 11 #define SYS_getpid 12 @@ -34,3 +33,6 @@ #define SYS_lstat 33 #define SYS_symlink 34 #define SYS_link 35 +#define SYS_getdents 36 +#define SYS_memcpy 37 +#define SYS_memset 38 diff --git a/src/tests/Test.c b/src/tests/Test.c index d133ede..0e49b45 100644 --- a/src/tests/Test.c +++ b/src/tests/Test.c @@ -137,8 +137,13 @@ int main(int argc, char **argv) { printf("Trying to opendir .\n"); dir = opendir("."); if(dir) { - while((dent=readdir(dir))!=NULL) - printf("\t[%s] %lu\n",dent->d_name,dent->d_ino); + printf("Success!\n"); + while((dent=readdir(dir))!=NULL) { + struct stat statbuf; + stat(dent->d_name,&statbuf); + printf("\t[%s] %lu %i %i\n",dent->d_name,dent->d_ino,statbuf.st_ino,statbuf.st_dev); + } + if(errno != 0) { fprintf(stderr,"readdir errno: %d\n",errno); perror("readdir"); } closedir(dir); } else { perror("opendir"); @@ -178,6 +183,13 @@ int main(int argc, char **argv) { } } + { + char buf[1024]; + memcpy(buf,"Hello, World",sizeof("Hello, World")); + printf("%s\n",buf); + } + printf("cwd: %s\n",getcwd(NULL,0)); + printf("isatty(0): %d\n",isatty(0)); printf("exiting\n"); return 0; }