// File: FileSystemAbstract.java // // Author: Andrew H. Fagg // 11/15/2 // // To Do: // Implement: // list() // createDir() // deleteDir() // create() // delete() // read(String name) // read(String name, int offset, int length) // existsFile() // existsDirectory() // append() // move() // fileCopy() // fileAppend() // import java.util.*; import java.lang.*; import java.io.*; abstract class FileSystemAbstract { protected int f_index; // Set by getFileRef() protected DirectoryBlock db; // Set by getFileRef() protected String fname; // Set by getFileRef() public Disk disk; // Disk reference public FreeBlock free_block; // Cached copy of the free block // public FileSystemAbstract() // // Create the FileSystem structures // // Effects: // 1. Opens the simulated disk // 2. Caches the free block // public FileSystemAbstract() { // Create reference to a disk of a specific geometry disk = new Disk("Disk0", 1024, 256); // Cache the free block list free_block = new FreeBlock(disk); try { free_block.read(0); }catch(FileSystemException e) { System.out.println("FileSystem(): Init error"); System.exit(1); }; }; // public void format () throws FileSystemException // // Format the file system // // Return = nothing // // Effects: // 1. Block 0 is configured as the free_block representation // 2. Block 1 is configured as an empty root directory // 3. All but the first two blocks are marked as being free // // throws FileSystemException if: // 1. An I/O error occurs with the external file system. // final public void format () throws FileSystemException{ disk.format(); free_block.read(0); disk.debug("f:" + free_block.buffer[0]); }; // protected void checkDirectoryName(String name) throws FileSystemException // // Check the name of the directory. If valid, returns without doing // anything // // Return = nothing // // Effects: // 1. Nothing // // throws FileSystemException if: // 1. the directory name is not valid // final protected void checkDirectoryName(String name) throws FileSystemException { // Check for valid characters if(!name.matches("^[\\w\\._/]*$")) { throw new FileSystemException("Ill-formed file name (" + name + ")."); }; // Check for repeated "/" if(name.matches(".*//.*")) { throw new FileSystemException("Ill-formed file name (" + name + ")."); }; }; //////////////////////////////////////////////////////////////////////// // Technically not FileSystem functions, as they are built upon // file system functionality // // public void fileImport(String fname1, String fname2) // throws FileSystemException // // Import a file from the base file system into our file system // // Effects: // 1. Creates a new file in our file system // 2. If already exists, it is first removed // // Return = nothing // // throws FileSystemException if: // 1. is a directory // 2. The file system is too full to insert the file // 3. The parent directory of is full // 4. does not exist or is not a file // 5. there is a read error on // final public void fileImport(String fname1, String fname2) throws FileSystemException { int i; int len; byte[] buf = new byte[1000]; try { // Open the original file in the base file system FileInputStream f = new FileInputStream(fname1); // Create the new file in the local file system create(fname2); // While there are bytes to read from the base file system while((len=f.read(buf)) > 0) { // Append these bytes to the local file system append(fname2, buf, len); }; f.close(); }catch(IOException e) { // Catch any errors from the import file access throw new FileSystemException("Import file error: " + e); }; }; // public void fileExport(String fname1, String fname2) // throws FileSystemException // // Exports a file from our file system to the base file system // // Effects: // 1. Creates a new file in the base file system. // // Return = nothing // // throws FileSystemException if: // 1. is a directory // 2. There is an error in creating the file in the base file system // 3. does not exist // final public void fileExport(String fname1, String fname2) throws FileSystemException { int i; byte[] buf; try { if(existsFile(fname1)) { // The original file exists // Create the output file in the base system FileOutputStream f = new FileOutputStream(fname2); i = 0; // Read the first 1000 bytes buf = read(fname1, i, 1000); // While there are bytes in the buffer while(buf != null) { // Write the bytes to f.write(buf); // Increment the byte count i += 1000; // Read the next 1000 bytes from the local file system buf = read(fname1, i, 1000); }; f.close(); }else if(existsDirectory(fname1)) { // original was a directory throw new FileSystemException(fname1 + " is a directory."); }else{ // original does not exist throw new FileSystemException(fname1 + " does not exist."); }; }catch(IOException e) { // Catch any errors from the export file access throw new FileSystemException("Export file error: " + e); }; }; ///////////////////////////////////////////////////////////////////// // To be provided in class FileSystem // public void list(String name) throws FileSystemException // // List a named file or the contents of a named directory. // is an absolute name. // // Return = nothing // // Effects: // 1. No changes are made to the file system // 2. If does not exist, then a 'file not found' // error is printed // // throws FileSystemException if: // 1. is not a valid name // 2. there is a read error // abstract public void list(String name) throws FileSystemException; // public void createDir(String name) throws FileSystemException // // Create a named directory. // is an absolute directory name // // Return = nothing // // Effects: // 1. A new entry is added to the parent directory // 2. A new directory block is allocated // // throws FileSystemException if : // 1. is not a valid name // 2. the parent directory does not exist // 3. The file system is too full to allocate the necessary space // for the new directory // 4. The parent directory does not have enough space. abstract public void createDir(String name) throws FileSystemException; // public void deleteDir(String name) throws FileSystemException // // Delete a named diretory. // is an absolute directory name // // Return = nothing // // Effects: // 1. The specified directory block is deallocated // 2. The directory's entry is removed from its parent // // throws FileSystemException if: // 1. is not a valid name // 2. The directory does not exist // 3. The named directory is not empty // 4. The name corresponds to a file // abstract public void deleteDir(String name) throws FileSystemException; // public void create(String name) throws FileSystemException // // Create a named file // is an absolute file name // // Return = nothing // // Effects: // Inserts the file into the parent directory's file list. // The file is of size 0. // If the file already exists, then its contents are removed // (ie it is set back to a file of size 0). // // throws FileSystemException if: // 1. is not a valid name // 2. The directory does not exist // 3. The name corresponds to a directory // 4. The parent directory is full // abstract public void create(String name) throws FileSystemException; // public void delete(String name) throws FileSystemException // // Delete the named file // // Return = nothing // // Effects: // Removes the specified file from its parent directory's list // Releases the data blocks used by the file // // throws FileSystemException if: // 1. is not a valid name // 2. The file does not exist // 3. The name corresponds to a directory // abstract public void delete(String name) throws FileSystemException; // public byte[] read(String name) throws FileSystemException // // Read all of the bytes from a named file. // // Return = the array of bytes (normally). // = null if the file is empty. // // Effects: // None (no changes are made to the file system) // // throws FileSystemException if: // 1. is not a valid name // 2. The file does not exist // 3. The name corresponds to a directory // abstract public byte[] read(String name) throws FileSystemException; // public byte[] read(String name, int offset, int length) // throws FileSystemException // // Read bytes from a file starting at position // (where 0 is the first byte in the file). // // Return = the array of bytes (normally) // = the array of size-offset bytes (if smaller than length) // = null if offset is passed the end of the file. // // Effects: // None (no changes are made to the file system) // // throws FileSystemException if: // 1. is not a valid name // 2. The file does not exist // 3. The name corresponds to a directory // abstract public byte[] read(String name, int offset, int length) throws FileSystemException; // public boolean existsFile(String name) throws FileSystemException // // Return = true if exists and is a file // // Effects: none // // throws FileSystemException if: // 1. is not a valid file/directory name // abstract public boolean existsFile(String name) throws FileSystemException; // public boolean existsDirectory(String name) throws FileSystemException // // Return = true if exists and is a directory // // Effects: none // // throws FileSystemException if: // 1. is not a valid file/directory name // abstract public boolean existsDirectory(String name) throws FileSystemException; // public void append(String name, byte[] buf, int bufLen) // // Append the first bytes in to file // // Return = nothing // // Effects: // 1. buf[0 ... bufLen-1] are appended to the end of the file // 2. If these bytes would make the file longer than can be // represented by the inode, then only those bytes that would // fit are appended to the file // 3. If not enough data blocks can be allocated to fit these // bytes, then NO change is made to the file // // throws FileSystemException if: // 1. does not exist // 2. is a directory // 3. The file system is full (and not enough blocks can be // allocated // 4. The file is too long to be represented by the inode // abstract public void append(String name, byte[] buf, int bufLen) throws FileSystemException; // public void move(String name1, String name2) // throws FileSystemException // // Move absolute to absolute // // Notation: assume that = / // Where is the parent directory reference (and may be ""), // and is the local name of the file or directory // // Return = nothing // // Effects: // // If is a file: // If is a file, then the old is removed and // replaced with the contents of // // If does not exist: inherits the contents // of // // If is a directory, then / inherits the // contents of // // If is a directory: // If does not exist, then inherits the // contents of // // If is a directory, then / inherits the // contents of // // throws FileSystemException if: // does not exist // or are not valid names // and are the same object // is a directory, and is a file // is an ancestor of (ie, doing the move would // set up a cycle in the directory structure that would not // be reachable from the root directory). // // HINT: 1. This should behave just like the unix "mv" command // 2. Because there are so many different conditions, // implement this method last. // abstract public void move(String name1, String name2) throws FileSystemException; //////////////////////////////////////////////////////////////////////// // Technically not FileSystem functions, as they are built upon // file system functionality // // public void fileCopy(String fname1, String fname2) // throws FileSystemException // // Copy file to // // Effects: // 1. Creates file and copies the contents of // into the new file // 2. If is a directory, then a file is created within // with the same name as in // // throws FileSystemException if: // 1. Parent directory of is full // 2. File system is full // 3. or are not valid file names // 4. does not exist // 5. is a directory // abstract public void fileCopy(String fname1, String fname2) throws FileSystemException; // public void fileAppend(String fname1, String fname2) // throws FileSystemException // // Append file to // // Effects: // 1. Appends the bytes of onto // // throws FileSystemException if: // 1. or are not valid file names // 2. or do not exist // 3. or are directories // 4. File system is full // abstract public void fileAppend(String fname1, String fname2) throws FileSystemException; };