From: <mic...@us...> - 2007-05-15 21:59:10
|
Revision: 115 http://svn.sourceforge.net/pearcolator/?rev=115&view=rev Author: michael_baer Date: 2007-05-15 14:58:53 -0700 (Tue, 15 May 2007) Log Message: ----------- Added more flexible support for file system emulation Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java Added Paths: ----------- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java src/org/binarytranslator/generic/os/abi/linux/filesystem/ src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java Modified: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-05-14 22:14:10 UTC (rev 114) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-05-15 21:58:53 UTC (rev 115) @@ -3,6 +3,7 @@ import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; +import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider; public class ARM_LinuxSystemCalls extends LinuxSystemCalls { @@ -32,12 +33,10 @@ systemCallTable[202] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[221] = new LinuxSystemCalls.SysFcntl64(); systemCallTable[252] = new LinuxSystemCalls.SysExitGroup(); - } @Override public void doSysCall() { - super.doSysCall(); } @@ -46,6 +45,12 @@ //TODO: Grab this from a real machine return "ARM"; } + + @Override + protected FileProvider buildFileSystem() { + ARM_ProcFileSystem fs = new ARM_ProcFileSystem(super.buildFileSystem()); + return fs; + } @Override public String sysCallToString(int syscall) { Added: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,29 @@ +package org.binarytranslator.arch.arm.os.abi.linux; + +import org.binarytranslator.generic.os.abi.linux.files.FixedContentFile; +import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; +import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider; +import org.binarytranslator.generic.os.abi.linux.filesystem.ProcFileSystem; + +public class ARM_ProcFileSystem extends ProcFileSystem { + + public ARM_ProcFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected ReadableFile openCpuInfo() { + + String output = ""; + output += "Processor : XScale-IOP80321 rev 2 (v5l)\n"; + output += "BogoMIPS : 599.65\n"; + output += "Features : swp half thumb fastmult edsp\n"; + output += "\n"; + output += "Hardware : Iyonix\n"; + output += "Revision : 0000\n"; + output += "Serial : 0000000000000000\n"; + + return new FixedContentFile(output); + } + +} Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-14 22:14:10 UTC (rev 114) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-15 21:58:53 UTC (rev 115) @@ -8,6 +8,7 @@ */ package org.binarytranslator.generic.os.abi.linux; +import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.memory.MemoryMapException; @@ -19,6 +20,11 @@ import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; import org.binarytranslator.generic.os.abi.linux.files.WriteableFile; import org.binarytranslator.generic.os.abi.linux.files.OpenFileList.InvalidFileDescriptor; +import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider; +import org.binarytranslator.generic.os.abi.linux.filesystem.HostFileSystem; +import org.binarytranslator.generic.os.abi.linux.filesystem.ReadonlyFilesystem; +import org.binarytranslator.generic.os.abi.linux.filesystem.TempFileSystem; +import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider.FileMode; import org.binarytranslator.generic.os.abi.linux.LinuxConstants.*; import java.io.File; @@ -46,6 +52,9 @@ /** List of currently opened files. */ protected OpenFileList openFiles; + /** List of currently opened files. */ + protected FileProvider filesystem; + /** The top of the bss segment */ protected int brk; @@ -144,16 +153,32 @@ openFiles = new OpenFileList(); - if (openFiles.open(new ConsoleIn(), 0) != 0 - || openFiles.open(new ConsoleOut(System.out), 1) != 1 - || openFiles.open(new ConsoleOut(System.err), 2) != 2) { + if (openFiles.add(new ConsoleIn(), 0) != 0 + || openFiles.add(new ConsoleOut(System.out), 1) != 1 + || openFiles.add(new ConsoleOut(System.err), 2) != 2) { throw new RuntimeException( "File descriptors for standard streams could not be assigned correctly."); } structures = new LinuxStructureFactory(); + filesystem = buildFileSystem(); } + + /** + * This method creates a virtual file system for this linux host. Override it, to create a specific file systems + * for an architecture. + * + * The standard implementation mounts the host's file system readonly but enables writes to the host's temp directory. + * @return + * A {@link FileProvider} that will be used to access the file system for this host. + */ + protected FileProvider buildFileSystem() { + FileProvider fs = new HostFileSystem(null); + fs = new ReadonlyFilesystem(fs); + fs = new TempFileSystem(fs); + return fs; + } /** * Handle a system call @@ -318,42 +343,51 @@ // Examine the flags argument and open read or read-write // accordingly. args[0] points to the file name. String fileName = memoryReadString(pathname); + + FileMode mode; - // Create a File object so we can test for the existance and - // properties of the file. - File testFile = new File(fileName); - - if (((flags & fcntl.O_CREAT) != 0) && ((flags & fcntl.O_EXCL) != 0) - && testFile.exists()) { - // O_CREAT specified. If O_EXCL also specified, we require - // that the file does not already exist - src.setSysCallError(errno.EEXIST); - return; - } else if (((flags & fcntl.O_CREAT) != 0) && !testFile.exists()) { - // O_CREAT not specified. We require that the file exists. - src.setSysCallError(errno.ENOENT); - return; + //shall we create the target file? + if ((flags & fcntl.O_CREAT) != 0) { + //We want to create a file. This also implies that we're gonna write to it + mode = FileMode.WriteCreate; + if (DBT.VerifyAssertions) DBT._assert((flags & 0x3) != fcntl.O_RDONLY); + + //Yes, we want to create that file. Do we demand that it does not yet exist? + if ((flags & fcntl.O_EXCL) != 0) { + //check if it does not exist by trying to open it + OpenFile testfile = filesystem.openFile(fileName, FileMode.Read); + + if (testfile != null) { + //the file we're trying to create already exists. With O_EXCL, this is an error condition. + src.setSysCallError(errno.EEXIST); + try { + testfile.close(); + } catch (IOException e) {} + + return; + } + } } - - // we have not found an error, so we go ahead and try to open the file - try { - RandomAccessFile raFile; - int fd; - - if ((flags & 0x3) == fcntl.O_RDONLY) { - raFile = new RandomAccessFile(fileName, "r"); - fd = openFiles.open(HostFile.forReading(raFile)); - } else { - // NB Java RandomAccessFile has no write only - raFile = new RandomAccessFile(fileName, "rw"); - fd = openFiles.open(HostFile.forWriting(raFile)); - } - src.setSysCallReturn(fd); - } catch (FileNotFoundException e) { - System.err.println("Open tried to open non-existent file: " + fileName); + else { + //we shall not create the file. Check if we're supposed to open it for reading, though + if ((flags & 0x3) == fcntl.O_RDONLY) + mode = FileMode.Read; + else + mode = FileMode.Write; + } + + OpenFile file = filesystem.openFile(fileName, mode); + + //did we successfully open the file? + if (file == null) { + //if not, return with an error src.setSysCallError(errno.ENOENT); return; } + + //otherwise add it to the list of open files and return a handle to the file + int fd = openFiles.add(file); + src.setSysCallReturn(fd); // NOT YET HANDLING ALL THE flags OPTIONS (IW have included // TRUNC & APPEND but not properly!) Added: src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,51 @@ +package org.binarytranslator.generic.os.abi.linux.files; + +import java.io.IOException; + +/** + * This is a file, for which the content is given by a constant string or byte array. + */ +public class FixedContentFile implements ReadableFile { + + /** The data that is actually returned to a reader. */ + protected final byte[] data; + + /** An integer offset into the {@link #data} array, that points at the next byte that is to be read. */ + protected int readPtr; + + public FixedContentFile(byte[] data) { + readPtr = 0; + this.data = data; + } + + public FixedContentFile(String asciiData) { + readPtr = 0; + data = new byte[asciiData.length()]; + + for (int i = 0; i < asciiData.length(); i++) + data[i] = (byte)asciiData.charAt(i); + } + + public int read(byte[] buffer) throws IOException { + + if (readPtr == data.length) { + return -1; + } + + for (int i = 0; i < buffer.length; i++) { + + if (readPtr == data.length) { + return i; + } + + buffer[i] = data[readPtr++]; + } + + return buffer.length; + } + + public void close() throws IOException { + //no-op + } + +} Modified: src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java 2007-05-14 22:14:10 UTC (rev 114) +++ src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java 2007-05-15 21:58:53 UTC (rev 115) @@ -27,7 +27,7 @@ * @return * The file descriptor that identifies this file. */ - public int open(OpenFile file) { + public int add(OpenFile file) { int handle = nextFileHandle++; files.put(nextFileHandle, file); @@ -47,7 +47,7 @@ * @return * The file descriptor that identifies this file. */ - public int open(OpenFile file, int preferredFd) { + public int add(OpenFile file, int preferredFd) { if (files.get(preferredFd) != null) { preferredFd = nextFileHandle++; } Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,34 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * This is a base class for file system that follow the chain of responsibility pattern. + * In this pattern, all file systems are chained and if one file system cannot handle the request to + * open a specific file, the request is forwarded to the next file system until either one system + * can provide the file or the end of the chain is reached. + * + */ +public abstract class ChainedFileProvider implements FileProvider { + + protected final FileProvider nextProvider; + + public ChainedFileProvider(FileProvider nextProvider) { + + if (nextProvider == null) + nextProvider = new NullFileSystem(); + + this.nextProvider = nextProvider; + } + + public OpenFile openFile(String file, FileMode mode) { + OpenFile result = tryOpen(file, mode); + + if (result == null) + result = nextProvider.openFile(file, mode); + + return result; + } + + protected abstract OpenFile tryOpen(String file, FileMode mode); +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,26 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * The FileProvider interface defines the methods that any class shall implement, that serves as (part) + * of the virtual file system that is simulated for the linux guest OS. */ +public interface FileProvider { + + public enum FileMode { + Read, + Write, + WriteCreate + } + + /** + * Opens the given file on the host. + * @param file + * The path of the file that is to be opened. + * @param mode + * The mode with which the file shall be opened. + * @return + * A file object representing the file on success or null otherwise. + */ + public OpenFile openFile(String file, FileMode mode); +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,50 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.RandomAccessFile; + +import org.binarytranslator.generic.os.abi.linux.files.HostFile; +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +public class HostFileSystem extends ChainedFileProvider { + + + public HostFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected OpenFile tryOpen(String file, FileMode mode) { + + try { + File f = new File(file); + + if (!f.isFile()) + return null; + + switch (mode) { + case Read: + if (!f.exists()) + return null; + + return HostFile.forReading(new RandomAccessFile(f, "r")); + + case Write: + if (!f.exists()) + return null; + + return HostFile.forWriting(new RandomAccessFile(f, "rw")); + + case WriteCreate: + return HostFile.forWriting(new RandomAccessFile(f, "rw")); + + default: + throw new RuntimeException("Invalid file open mode: " + mode); + } + + } catch (FileNotFoundException e) { + return null; + } + } +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,15 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * A NULL filesystem object. + * + */ +public class NullFileSystem implements FileProvider { + + public OpenFile openFile(String file, FileMode mode) { + //no-nop + return null; + } +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,32 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; +import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; + +/** Represents the Unix /proc/ file system. */ +public abstract class ProcFileSystem extends ChainedFileProvider { + + /** A string that defines the path of the virtual proc file system on the guest. */ + protected final static String PROC_DIRECTORY_PATH = "/proc/"; + + public ProcFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected OpenFile tryOpen(String file, FileMode mode) { + if (!file.startsWith(PROC_DIRECTORY_PATH)) + return null; + + if (file.equals(PROC_DIRECTORY_PATH + "cpuinfo") && mode == FileMode.Read) + return openCpuInfo(); + + return null; + } + + /** + * Called when the application tries to open /proc/cpuinfo. + * Implement it by returning a {@link ReadableFile} that contains the information usually returned by /proc/cpuinfo. + */ + protected abstract ReadableFile openCpuInfo(); +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,22 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * A file system decorator, that prevents all write-accesses to this file system. + */ +public final class ReadonlyFilesystem implements FileProvider { + + private final FileProvider filesystem; + + public ReadonlyFilesystem(FileProvider filesystem) { + this.filesystem = filesystem; + } + + public OpenFile openFile(String file, FileMode mode) { + if (mode != FileMode.Read) + return null; + + return filesystem.openFile(file, mode); + } +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,22 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** This class allows write-access to the /tmp file system from the guest. */ +public class TempFileSystem extends HostFileSystem { + + /** A string that defines the location of the tmp file system on the guest. */ + protected final static String TMP_FILE_PATH = "/tmp/"; + + public TempFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected OpenFile tryOpen(String file, FileMode mode) { + if (!file.startsWith(TMP_FILE_PATH)) + return null; + + return super.tryOpen(file, mode); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |