Last updated: [98/05/14 Chip]
This page was written by Chip, based on Arturo's excellent
template.
The file wrapper subsystem provides an alternative API for Java
file I/O. It provides essentially the same functionality as the
standard java.io classes (if fact,
it is built on top of them), but does so in a way that is capability
secure and Vat-safe. The idea is to treat file and directory accessors
as the objects from which file access is derived, rather than
allowing file name strings to designate access.
The principal requirement of the file wrapper subsystem was to
provide a Vat-safe means for objects running in the Vat to access
files. The standard Java file access classes are not suitable
because they grant access via static methods and variables (thus
preventing control over which objects can access what) and because
they cannot be made to behave appropriately in a quake (either
by surviving or by letting themselves be cleanly smashed).
The ec.e.file package provides capability-secure file access to guest objects in the Vat. This overview describes the basic architecture of the package: what the classes are and how they relate to each other. For the specific details of the interfaces of these classes, consult the appropriate javadoc pages.
Files and directories are represented as objects. There is a set of objects for files and a set of objects for directories. Within each set, different classes of object encapsulate different sorts of access to the files or directories which their instances describe.
There are three varieties of directory object:
EReadableDirectory - read-only access to contained files and directories
EAccessibleDirectory - read-only access to contained directories, edit access to contained files
EEditableDirectory - edit access to contained files and directories
And three varieties of file object:
EReadableFile - read-only access to a file, optionally random access
EAppendableFile - append-only write access to a file
EEditableFile - read/write access to a file, optionally random access
All of the objects of classes EXxxxDirectory or EXxxxFile are instances of EDirectoryEntry and support a common interface that allows you to determine if the described entity in fact exists, find out if it is a file or directory, and find out if it is contained by a particular directory.
All the EXxxxDirectory objects can provide a list of their contents, in the form of a ReadOnlyHashtable which maps from Strings to EDirectoryEntry objects (org.erights.e.elib.util.ReadOnlyHashtable works like a regular Java hashtable, except that you can't modify it).
From an EReadableDirectory object you can obtain EReadableDirectory and EReadableFile objects for the directories and files within that directory.
From an EAccessibleDirectory object you can obtain EAccessibleDirectory and EEditableFile objects for the directories and files within that directory. In addition, from an EAccessibleDirectory object you can obtain an EReadableDirectory object for the same directory.
From an EEditableDirectory object you can obtain EEditableDirectory and EEditableFile objects for the directories and files within that directory. In addition, from an EEditableDirectory object you can obtain an EReadableDirectory or EAccessibleDirectory object for the same directory. Furthermore, an EEditableDirectory object allows you to modify the directory it represents by adding, deleting, renaming and relocating the files and directories within it.
From an EReadableFile or an EEditable file object you can obtain an input stream for sequential read access or an EFileReader object for random access reading of the corresponding file.
From an EEditableFile object or an EAppendableFile object you can obtain an output stream for sequential write access (to the end of) the corresponding file.
From an EEditableFile object you can obtain an EFileEditor object for random access reading and writing of the corresponding file. In addition, from an EEditableFile object you can obtain an EReadableFile or EAppendableFile object for the same file.
Note that the file and directory access provided by the above described objects are circular in nature: the only way to get a file or directory object is from another file or directory object. This raises the question of how you get a file or directory object to begin with. The answer is that there is an EDirectoryRootMaker object (of which only one instance exists) which has the power to produce an EEditableDirectory object given only a string representing the pathname of the directory in question. The EDirectoryRootMaker object is generated at startup time and should be closely held.
The EFileReader and EFileEditor objects, as well as the input and output stream objects obtainable from EXxxxFile objects, are fragile. That is, they get smashed in a quake. Attempts to perform I/O after a quake will result in a SmashedException (which is a type of IOExcpetion). However, the EXxxxDirectory and EXxxxFile objects are sturdy. They survive a quake just fine, though do not guarantee that the state of the file system will be the same after the quake as before (they will, however, always present a correct view of the current state of the file system).
The input and output streams provided by the file classes are implemented by EInputStream and EOutputStream, which are streams that behave appropriately (i.e., the get smashed) in a quake. There is also an alternative version of EOutputStream called QuakeProofAppendFile whose behavior on return from a quake is to seek to the end of the file and resume writing.
The EStdio class provides access in the Vat to the standard I/O streams that the class System provides outside the Vat. The methods EStdio.out(), EStdio.in() and EStdio.err() correspond to the same input or output streams as System.out, System.in and System.err, respectively. The difference is that the streams provided by EStdio are sturdy whereas those provided by System are not. And yes, these are static methods; talk to MarkM or me about why we decided that these were OK even though they break one of the cardinal rules.
The obvious alternative to using this package is simply to use
the regular Java I/O classes, if Vat safety and/or capability
security are not concerns.
All the classes in this subsystem are in the package ec.e.file, which are in the single directory ec4/javasrc/ec/e/file.
The file wrapper package is completely JavaDoc'd, except for a mysterious class of unknown provenenance called URLStreamMaker.
In the older ec3 tree, in ec3/E/runtime/e/file,
are a couple of test programs, FileTest.e
and QuakeFileTest.e. These have not
been converted for ec4 or later environments. The file wrapper
package itself is fairly small and simple and has not required
much further maintenance since it was first released. Thes test
programs were fairly ad hoc and informal; they are probably not
worth converting.
The future need for this package is debatable. In a future product which allows user-submitted Java code to run in our environment, the capability-secure aspects of this file access paradigm will be essential. However, the Vat-safety aspects are less critical now that we have switched to state-bundle persistence rather than orthogonal persistence. The paradigm is also somewhat awkward to use for programmers used to simply naming a file with a string. And there is a further question as to whether user-submitted Java code should be accessing files at all. On the other hand, the implementation has proven reasonably reliable and trouble free and we have a fair quantity of code in our source base which depends on it. Maintaining a capability-safe source base is probably a wise thing to do, all other cost factors being equal.