diff --git a/src/filesys/filesys.rs b/src/filesys/filesys.rs index 866cc74..350ac13 100644 --- a/src/filesys/filesys.rs +++ b/src/filesys/filesys.rs @@ -1,11 +1,11 @@ -use crate::simulator::disk; - +use crate::{simulator::disk, utility::bitmap, kernel::mgerror::ErrorCode}; +const ERROR : i32 = -1; const FREE_MAP_SECTOR : i32 = 0; const DIRECTORY_SECTOR : i32 = 1; pub struct Filesys { - pub free_map_file : Open_File, //Bit map of free disk blocks, represented as a file + pub free_map_file : Open_file, //Bit map of free disk blocks, represented as a file pub directory_file : Open_file //"Root" directory -- list of file names, represented as a file } @@ -56,17 +56,17 @@ impl Filesys { } } - /// create a file in the Nachos file system (similar to UNIX create). + /// Create a file in the BurritOS file system (similar to UNIX create). /// Since we can't increase the size of files dynamically, we have /// to give Create the initial size of the file. // /// The steps to create a file are: - /// Make sure the file doesn't already exist - /// Allocate a sector for the file header - /// Allocate space on disk for the data blocks for the file - /// Add the name to the directory - /// Store the new file header on disk - /// Flush the changes to the bitmap and the directory back to disk + /// Make sure the file doesn't already exist + /// Allocate a sector for the file header + /// Allocate space on disk for the data blocks for the file + /// Add the name to the directory + /// Store the new file header on disk + /// Flush the changes to the bitmap and the directory back to disk /// /// Create fails if: /// file is already in directory @@ -81,9 +81,97 @@ impl Filesys { /// /// -**name** is the name of file to be created (NOT MODIFIED) /// -**initialSize** is the size of file to be created - /// \return NO_ERROR if everything goes ok, otherwise, return an error - // code as define in msgerror.h - pub fn create(name : String, initial_size : i32) -> i32 { + pub fn create(&mut self, name : String, initial_size : i32) -> Result<(), ErrorCode> { + + lock.acquire(); + let dir_sector = find_dir(name); + if dir_sector == ERROR { + lock.release(); + return Err(ErrorCode::InexistFileError); + } + + let dir_file = openfile::init_open_file(dir_sector); + let directory = directory::init_directory(num_dir_entries); + directory.fetch_from(&dir_file); + + if directory.find(name) != ERROR { + lock.release(); + return Err(ErrorCode::AlreadyInDirectory); + } + + // Get the freemap from the disk + let free_map = bitmap::init_bitmap(disk::NUM_SECTORS); + free_map.fetch_from(self.free_map_file); + + // Find a sector to hold the file header + let sector = free_map.find(); + if sector == ERROR { + lock.release(); + return Err(ErrorCode::OutOfDisk); + } + + // Add the file in the directory + let add_result = directory.add(name, sector); + match add_result { + Err(e) => { + lock.release(); + return Err(e); + } + _ => {} + } + + // Indicate that this is a file, not a directory + let hdr = file_header::init_file_header(); + hdr.set_file(); + + if !hdr.allocate(&free_map, initial_size) { + lock.release(); + return Err(ErrorCode::OutOfDisk); + } + + // everthing worked, flush all changes back to disk + hdr.write_back(sector); + directory.write_back(&dir_file); + free_map.write_back(self.free_map_file); + + lock.release(); + + Ok(()) } + + /// Open a file for reading and writing. + /// To open a file: + /// Find the location of the file's header, using the directory + /// Bring the header into memory + /// + /// ### parameters + /// + /// -**name** the text name of the file to be opened (NOT MODIFIED) + pub fn open(name : String) -> Option { + let open_file : Open_file; + // Find the directory containing the file + let dir_sector = find_dir(name); + if dir_sector == ERROR { + return None; + } + + // Read the directory from disk + let dir_file = open_file::init_open_file(dir_sector); + let directory = directory::init_directory(num_dir_entries); + directory.fetch_from(&directory); + + // Find the file in the directory + let sector = directory.find(name); + if sector >= 0 { + open_file = openfile::init_open_file(sector); + open_file.set_name(name); + if open_file.is_dir() { + return None; + } + } + + Some(open_file) + } + } \ No newline at end of file