// COM3336 Operating Systems // Homework 2 part 1 // John Sung // Started: 10/22/1999 // import java.util.*; import java.io.*; import File; import SymbolicLink; import SimpleFile; // The simple file to signify a simple file. It really doesn't // add much to the abstract File class. public class ComplexFile extends File { ////////////////////////////////////////////////////////////// // Private Data Members // linked list of File. LinkedList DirEntries; // link to the parent File ParentDir; // the default constructor public ComplexFile(String fileName, File parentDir) { super(fileName); ParentDir = parentDir; DirEntries = new LinkedList(); } // returns true if the file already exists. boolean doesFileExist(String fileName) { // get the list iterator ListIterator listIter = DirEntries.listIterator(0); // loop through the list of dir entries // and see if we find an entry with the same name while(listIter.hasNext()) { File aFile = (File)listIter.next(); if (aFile.getFileName().compareTo(fileName)==0) { return true; } } return false; } // the method removes a file from the DirEntries list public boolean removeFileFromDir(String fileName, PrintStream err) { // get the list iterator ListIterator listIter = DirEntries.listIterator(0); // loop through the list of dir entries // and see if we find an entry with the same name while(listIter.hasNext()) { File aFile = (File)listIter.next(); if (aFile.removeFile(fileName, err)) { DirEntries.remove(aFile); return true; } } return false; } // the method removes a file from the DirEntries list public boolean removeDirFromDir(String fileName, PrintStream err) { // get the list iterator ListIterator listIter = DirEntries.listIterator(0); // loop through the list of dir entries // and see if we find an entry with the same name while(listIter.hasNext()) { File aFile = (File)listIter.next(); if (aFile.removeDir(fileName, err)) { DirEntries.remove(aFile); return true; } } return false; } ////////////////////////////////////////////////////////////// // methods specific to the ComplexFile class. // this method recursively copies the directory entries. private void recursiveCopyDirEntries(LinkedList srcDirEntries) { // get the list iterator ListIterator listIter = srcDirEntries.listIterator(0); // loop through and call the recursive copy on each of // the files in the linked list while(listIter.hasNext()) { // get the file File srcFile = (File) listIter.next(); if (doesFileExist(srcFile.getFileName())) { System.out.println("File " + srcFile.getFileName() + " already exists and not copied"); } else { // create a copy of the file. File newFile = srcFile.recursiveCopy(this); // System.out.println("Adding file " + newFile.getFileName()); // add the new file to the dir entries DirEntries.add(newFile); } } } // this method recursively copies the entries from the // source complex file to this complex file's entries. public void recursiveCopyDirEntries(ComplexFile srcFile) { // if srcFile t is null then output a error // message if (srcFile == null) { System.out.println("recursive copy on / not allowed"); return; } // now recursively copy the dir entries from // the source. recursiveCopyDirEntries(srcFile.DirEntries); } // a method to add a file to the dir entry. public void addFile(File newFile) { DirEntries.add(newFile); } // attemt to find the subDirectory public ComplexFile findSubDir(String subDirName, PrintStream err) { // get the list iterator ListIterator listIter = DirEntries.listIterator(0); // loop through the list of dir entries // and see if we find an entry with the same name while(listIter.hasNext()) { File aFile = (File)listIter.next(); if (aFile.getFileName().compareTo(subDirName)==0) { return (ComplexFile)aFile.changeDirectory(subDirName,err); } } // output an error message. err.println("Subdirectory with name " + subDirName + " not found."); // we didn't find it, return null return null; } ////////////////////////////////////////////////////////////// // Abstract methods from the abstract File class // a function to recursively copy a File, with a file // as the parent of the copy. Just returns the // copy of itself. public File recursiveCopy(File Parent) { // check to make sure we don't have name collision if (doesFileExist(getFileName())) { // output some error and return null System.out.println("Some file with name " + getFileName() + " already exists."); return null; } // create a new file ComplexFile newFile = new ComplexFile(getFileName(), this); // copy each of the dir entries. newFile.recursiveCopyDirEntries(DirEntries); // return the new file return newFile; } // function to find a particular file and print it to an // ostream public void recursiveFindAndPrint(String prefix, String fileName, PrintStream out) { // call the File's version of this method first super.recursiveFindAndPrint(prefix, fileName, out); recursiveFindAndPrintDirList(prefix + "/" + getFileName(), fileName, out); } // function to find a particular file and print it to an // ostream public void recursiveFindAndPrintDirList(String prefix, String fileName, PrintStream out) { // get the list iterator ListIterator listIter = DirEntries.listIterator(0); // loop through the list of dir entries // and see if we find an entry with the same name while(listIter.hasNext()) { File aFile = (File)listIter.next(); aFile.recursiveFindAndPrint(prefix, fileName, out); } } // function to implement the "du ." command. The object that // implements this function sould print itself if it's // a directory to the ostream. public void recursivePrintDirectory(String prefix, PrintStream out) { // print myself out.println(prefix + "/"+ getFileName()); // print all of the entries in the DirEntries list recursivePrintDirectoryList(prefix + "/" + getFileName(), out); } // recursively print all directories public void recursivePrintDirectoryList(String prefix, PrintStream out) { // get the list iterator ListIterator listIter = DirEntries.listIterator(0); // call recursive print on all of the dir entries. while(listIter.hasNext()) { File aFile = (File) listIter.next(); aFile.recursivePrintDirectory(prefix, out); } } public void recursivePrintAll(String prefix, PrintStream out) { // print myself out.println(prefix + "/" + getFileName()); recursivePrintAllList(prefix+ "/" + getFileName(), out); } public void recursivePrintAllList(String prefix, PrintStream out) { // get the list iterator ListIterator listIter = DirEntries.listIterator(0); // call recursive print on all of the dir entries. while(listIter.hasNext()) { File aFile = (File) listIter.next(); aFile.recursivePrintAll(prefix, out); } } // function to implement the directory down command, // returns null if something goes wrong. public File changeDirectory(String subDirName, PrintStream err) { // if the file name mathes the subDirName // then return this if (subDirName.compareTo(getFileName())==0) return this; // return null to signify failure. return null; } // function returns the parent, unless it doesn't have a // parent. Used to implement cd .. public File getParent() { return ParentDir; } // function used to implement the touch command. // it attempts to create a file. Outputs any errors // to err. public void createFile(String newFileName, PrintStream err) { // check to make sure we don't have name collision if (doesFileExist(newFileName)) { // output some error and return null System.out.println("Some file with name " + newFileName + " already exists."); return; } // create a new ComplexFile SimpleFile newFile = new SimpleFile(newFileName); // add it to the dir entries addFile(newFile); } // function used to implement the mkdir command. // it attempts to create a directory. Outputs any errors // to err. public void createDir(String newDirName, PrintStream err) { // check to make sure we don't have name collision if (doesFileExist(newDirName)) { // output some error and return null System.out.println("Some file with name " + newDirName + " already exists."); return; } // create a new ComplexFile ComplexFile newDir = new ComplexFile(newDirName, this); // add it to the dir entries addFile(newDir); } // function to implement the ln -s command. public void createSymbolicLink(String destName, String linkName) { // check to make sure we don't have name collision if (doesFileExist(linkName)) { // output some error and return null System.out.println("Some file with name " + linkName + " already exists."); return; } // create a new symbolic link object SymbolicLink newLink = new SymbolicLink(destName,linkName, this); // add the file to the DirEntry addFile(newLink); } // function used to implement rmdir. Outputs error to // the err PrintStream if something goes wrong. public boolean removeDir(String dirName, PrintStream err) { // if the name matches then remove myself from the parent. if (dirName.compareTo(getFileName())==0) { return true; } return false; } // function used to implement rm. Outputs error to // the err PrintStream if something goes wrong. public boolean removeFile(String fileName, PrintStream err) { // if the name matches then remove myself from the parent. if (fileName.compareTo(getFileName())==0) { err.println("removeFile: " + fileName + " is a directory. Not removed."); return false; } return false; } }