How to port the libjava file handling code


The classes in ultimately require some connection to the underlying operating system's notion of files. This document attempts to describe how to port the native file-handling layer.

There are basically two parts to the porting. First, the FileDescriptor class is used to represent an open file. It has native methods to open, close, read, write, etc. Second, the File class can be used to manipulate the file system via methods such as mkdir, rename, etc.

Porting FileDescriptor

The current implementation of FileDescriptor assumes a POSIX-like system. For instance, the current representation of the native state is a single int, the POSIX file descriptor.

Here are the semantics of the various functions you must write to port this class:
boolean valid ()
Should return true if this object is valid, and false otherwise.
void sync ()
Synchronize the file descriptor. On error, throw a SyncFailedException.
int open (String path, int flags)
Open a file and return the native file descriptor. Should throw exception on error. flags is either READ, WRITE, READ | WRITE, or WRITE | APPEND and is used to specify the mode in which the file should be opened.
void write (int byte)
Write a single byte (low-order bits of byte) to the file. Throw exception on error.
void write (byte[] bytes, int offset, int length)
Write several bytes to the file. If bytes is null, throw NullPointerException. Should check offset and length as well, and throw ArrayIndexOutOfBoundsException on error. Also should throw exception if write fails.
void close ()
Close the file. Throw exception on error.
int seek (long pos, int whence)
Seek to a new position in the file. whence is either SET (set the new position absolutely) or CUR (set the new position relative to the current position. If the call would set the position past the end of the file, should throw EOFException Should throw exception on error. Return value is the new position.
long length ()
Returns the size of the file in bytes. Throws exception on error.
long getFilePointer ()
Returns current location in file of file pointer. Throws exception on error.
int read ()
Read a single byte from the file. On EOF, return -1. On error, throw exception.
int read (byte[] buffer, int offset, int count)
First, check buffer, offset, and count, just like write. Then read as many bytes are as available into buffer (at location offset), up to count bytes. If EOF hit before any bytes read, return -1. On error, throw exception. Otherwise, return number of bytes read. This method should never return 0; instead it should block until at least one byte is read.
int available ()
Return number of bytes that could be read without blocking. On error, throw exception.

Porting File

The File class represents a file name, and also provides the interface to manipulating the file system. It is this latter functionality we are primarily concerned with. Here are the methods involved:
boolean access (String canonical, int query)
Determine if access to the file is permitted. canonical is the file name to use. query is READ to see if read access is permitted, WRITE to see if write access is permitted, and EXISTS to see if the file exists. canonical might be null, in which case the answer should be false.
boolean stat (String canonical, int query)
Like access, but used to query file type. In this case, query is either DIRECTORY to see if the name represents a directory, or ISFILE to see if the name represents a file (which is basically anything that is not a directory).
long attr (String canonical, int query)
Like stat, but returns non-boolean information about the file. If query is MODIFIED, return the last modified time (in milliseconds since the Epoch). If it is LENGTH, return the file's length. Return 0 on error.
String getCanonicalPath ()
Return the canonical form of this.path. Throw exception on error. See the JCL book for information on path canonicalization.
boolean isAbsolute ()
Return true if this.path represents an absolute path for the underlying filesystem. The current implementation knows about both POSIX and Windows filesystems, so probably should not need much porting.
String[] performList (jstring canon, FilenameFilter filter)
If the string is null, just return. Otherwise, if it names a directory, this should return an array of all the files in the directory. The directories ``.'' and ``..'' should be omitted. If the path is not a directory, this method should return null.
boolean performMkdir ()
This function should make a directory named by path. Returns true on success.
boolean performRenameTo (File dest)
This function should rename the current file to dest. Returns true on success.
boolean performDelete (String canonical)
Should try to delete the path specified by canonical. This might be either a file or a directory. Should return true on success.