pub fn open_file_in_dir(
        &mut self,
        volume: &mut Volume,
        dir: &Directory,
        name: &str,
        mode: Mode,
    ) -> Result<File, Error<D::Error>> {
        // Find a free directory entry
        let mut open_files_row = None;
        for (i, d) in self.open_files.iter().enumerate() {
            if d.1 == Cluster::INVALID {
                open_files_row = Some(i);
            }
        }
        let open_files_row = open_files_row.ok_or(Error::TooManyOpenDirs)?;
        let dir_entry = match &volume.volume_type {
            VolumeType::Fat16(fat) => fat.find_directory_entry(self, dir, name),
            VolumeType::Fat32(fat) => fat.find_directory_entry(self, dir, name),
        };

        let dir_entry = match dir_entry {
            Ok(entry) => Some(entry),
            Err(_)
                if (mode == Mode::ReadWriteCreate)
                    | (mode == Mode::ReadWriteCreateOrTruncate)
                    | (mode == Mode::ReadWriteCreateOrAppend) =>
            {
                None
            }
            _ => return Err(Error::FileNotFound),
        };

        if let Some(entry) = &dir_entry {
            // Check it's not already open
            for dir_table_row in self.open_files.iter() {
                if *dir_table_row == (volume.idx, entry.cluster) {
                    return Err(Error::DirAlreadyOpen);
                }
            }
            if entry.attributes.is_directory() {
                return Err(Error::OpenedDirAsFile);
            }
            if entry.attributes.is_read_only() && mode != Mode::ReadOnly {
                return Err(Error::ReadOnly);
            }
        };

        let mut mode = mode;
        if mode == Mode::ReadWriteCreateOrAppend {
            if dir_entry.is_some() {
                mode = Mode::ReadWriteAppend;
            } else {
                mode = Mode::ReadWriteCreate;
            }
        } else if mode == Mode::ReadWriteCreateOrTruncate {
            if dir_entry.is_some() {
                mode = Mode::ReadWriteTruncate;
            } else {
                mode = Mode::ReadWriteCreate;
            }
        }

        let file = match mode {
            Mode::ReadOnly => {
                // Safe to unwrap, since we actually have an entry if we got here
                let dir_entry = dir_entry.unwrap();

                File {
                    starting_cluster: dir_entry.cluster,
                    current_cluster: (0, dir_entry.cluster),
                    current_offset: 0,
                    length: dir_entry.size,
                    mode,
                    entry: dir_entry,
                }
            }
            Mode::ReadWriteAppend => {
                // Safe to unwrap, since we actually have an entry if we got here
                let dir_entry = dir_entry.unwrap();

                let mut file = File {
                    starting_cluster: dir_entry.cluster,
                    current_cluster: (0, dir_entry.cluster),
                    current_offset: 0,
                    length: dir_entry.size,
                    mode,
                    entry: dir_entry,
                };
                // seek_from_end with 0 can't fail
                file.seek_from_end(0).ok();
                file
            }
            Mode::ReadWriteTruncate => {
                // Safe to unwrap, since we actually have an entry if we got here
                let dir_entry = dir_entry.unwrap();

                let mut file = File {
                    starting_cluster: dir_entry.cluster,
                    current_cluster: (0, dir_entry.cluster),
                    current_offset: 0,
                    length: dir_entry.size,
                    mode,
                    entry: dir_entry,
                };
                match &mut volume.volume_type {
                    VolumeType::Fat16(fat) => {
                        fat.truncate_cluster_chain(self, file.starting_cluster)?
                    }
                    VolumeType::Fat32(fat) => {
                        fat.truncate_cluster_chain(self, file.starting_cluster)?
                    }
                };
                file.update_length(0);
                // TODO update entry Timestamps
                let fat_type = match &volume.volume_type {
                    VolumeType::Fat16(_) => FatType::Fat16,
                    VolumeType::Fat32(_) => FatType::Fat32,
                };
                self.write_entry_to_disk(fat_type, &file.entry)?;

                file
            }
            Mode::ReadWriteCreate => {
                if dir_entry.is_some() {
                    return Err(Error::FileAlreadyExists);
                }
                let file_name =
                    ShortFileName::create_from_str(name).map_err(Error::FilenameError)?;
                let att = Attributes::create_from_fat(0);
                let entry = match &mut volume.volume_type {
                    VolumeType::Fat16(fat) => {
                        fat.write_new_directory_entry(self, dir, file_name, att)?
                    }
                    VolumeType::Fat32(fat) => {
                        fat.write_new_directory_entry(self, dir, file_name, att)?
                    }
                };

                File {
                    starting_cluster: entry.cluster,
                    current_cluster: (0, entry.cluster),
                    current_offset: 0,
                    length: entry.size,
                    mode,
                    entry,
                }
            }
            _ => return Err(Error::Unsupported),
        };
        // Remember this open file
        self.open_files[open_files_row] = (volume.idx, file.starting_cluster);
        Ok(file)
    }
/// Open a file with the given full path. A file can only be opened once.
Open a file with the given full path. A file can only be opened once.
Open a file with the given full path . A file can only be opened once .
pub fn open_file_in_dir(
        &mut self,
        volume: &mut Volume,
        dir: &Directory,
        name: &str,
        mode: Mode,
    ) -> Result<File, Error<D::Error>> {
        // Find a free directory entry
        let mut open_files_row = None;
        for (i, d) in self.open_files.iter().enumerate() {
            if d.1 == Cluster::INVALID {
                open_files_row = Some(i);
            }
        }
        let open_files_row = open_files_row.ok_or(Error::TooManyOpenDirs)?;
        let dir_entry = match &volume.volume_type {
            VolumeType::Fat16(fat) => fat.find_directory_entry(self, dir, name),
            VolumeType::Fat32(fat) => fat.find_directory_entry(self, dir, name),
        };
        let dir_entry = match dir_entry {
            Ok(entry) => Some(entry),
            Err(_)
                if (mode == Mode::ReadWriteCreate)
                    | (mode == Mode::ReadWriteCreateOrTruncate)
                    | (mode == Mode::ReadWriteCreateOrAppend) =>
            {
                None
            }
            _ => return Err(Error::FileNotFound),
        };
        if let Some(entry) = &dir_entry {
            // Check it's not already open
            for dir_table_row in self.open_files.iter() {
                if *dir_table_row == (volume.idx, entry.cluster) {
                    return Err(Error::DirAlreadyOpen);
                }
            }
            if entry.attributes.is_directory() {
                return Err(Error::OpenedDirAsFile);
            }
            if entry.attributes.is_read_only() && mode != Mode::ReadOnly {
                return Err(Error::ReadOnly);
            }
        };
        let mut mode = mode;
        if mode == Mode::ReadWriteCreateOrAppend {
            if dir_entry.is_some() {
                mode = Mode::ReadWriteAppend;
            } else {
                mode = Mode::ReadWriteCreate;
            }
        } else if mode == Mode::ReadWriteCreateOrTruncate {
            if dir_entry.is_some() {
                mode = Mode::ReadWriteTruncate;
            } else {
                mode = Mode::ReadWriteCreate;
            }
        }
        let file = match mode {
            Mode::ReadOnly => {
                // Safe to unwrap, since we actually have an entry if we got here
                let dir_entry = dir_entry.unwrap();
                File {
                    starting_cluster: dir_entry.cluster,
                    current_cluster: (0, dir_entry.cluster),
                    current_offset: 0,
                    length: dir_entry.size,
                    mode,
                    entry: dir_entry,
                }
            }
            Mode::ReadWriteAppend => {
                // Safe to unwrap, since we actually have an entry if we got here
                let dir_entry = dir_entry.unwrap();
                let mut file = File {
                    starting_cluster: dir_entry.cluster,
                    current_cluster: (0, dir_entry.cluster),
                    current_offset: 0,
                    length: dir_entry.size,
                    mode,
                    entry: dir_entry,
                };
                // seek_from_end with 0 can't fail
                file.seek_from_end(0).ok();
                file
            }
            Mode::ReadWriteTruncate => {
                // Safe to unwrap, since we actually have an entry if we got here
                let dir_entry = dir_entry.unwrap();
                let mut file = File {
                    starting_cluster: dir_entry.cluster,
                    current_cluster: (0, dir_entry.cluster),
                    current_offset: 0,
                    length: dir_entry.size,
                    mode,
                    entry: dir_entry,
                };
                match &mut volume.volume_type {
                    VolumeType::Fat16(fat) => {
                        fat.truncate_cluster_chain(self, file.starting_cluster)?
                    }
                    VolumeType::Fat32(fat) => {
                        fat.truncate_cluster_chain(self, file.starting_cluster)?
                    }
                };
                file.update_length(0);
                // TODO update entry Timestamps
                let fat_type = match &volume.volume_type {
                    VolumeType::Fat16(_) => FatType::Fat16,
                    VolumeType::Fat32(_) => FatType::Fat32,
                };
                self.write_entry_to_disk(fat_type, &file.entry)?;
                file
            }
            Mode::ReadWriteCreate => {
                if dir_entry.is_some() {
                    return Err(Error::FileAlreadyExists);
                }
                let file_name =
                    ShortFileName::create_from_str(name).map_err(Error::FilenameError)?;
                let att = Attributes::create_from_fat(0);
                let entry = match &mut volume.volume_type {
                    VolumeType::Fat16(fat) => {
                        fat.write_new_directory_entry(self, dir, file_name, att)?
                    }
                    VolumeType::Fat32(fat) => {
                        fat.write_new_directory_entry(self, dir, file_name, att)?
                    }
                };
                File {
                    starting_cluster: entry.cluster,
                    current_cluster: (0, entry.cluster),
                    current_offset: 0,
                    length: entry.size,
                    mode,
                    entry,
                }
            }
            _ => return Err(Error::Unsupported),
        };
        // Remember this open file
        self.open_files[open_files_row] = (volume.idx, file.starting_cluster);
        Ok(file)
    }
pub fn open_file_in_dir ( & mut self , volume : & mut Volume , dir : & Directory , name : & str , mode : Mode , ) -> Result < File , Error < D :: Error > > { // Find a free directory entry let mut open_files_row = None ; for ( i , d ) in self . open_files . iter ( ) . enumerate ( ) { if d . 1 == Cluster :: INVALID { open_files_row = Some ( i ) ; } } let open_files_row = open_files_row . ok_or ( Error :: TooManyOpenDirs ) ? ; let dir_entry = match & volume . volume_type { VolumeType :: Fat16 ( fat ) => fat . find_directory_entry ( self , dir , name ) , VolumeType :: Fat32 ( fat ) => fat . find_directory_entry ( self , dir , name ) , } ; let dir_entry = match dir_entry { Ok ( entry ) => Some ( entry ) , Err ( _ ) if ( mode == Mode :: ReadWriteCreate ) | ( mode == Mode :: ReadWriteCreateOrTruncate ) | ( mode == Mode :: ReadWriteCreateOrAppend ) => { None } _ => return Err ( Error :: FileNotFound ) , } ; if let Some ( entry ) = & dir_entry { // Check it's not already open for dir_table_row in self . open_files . iter ( ) { if * dir_table_row == ( volume . idx , entry . cluster ) { return Err ( Error :: DirAlreadyOpen ) ; } } if entry . attributes . is_directory ( ) { return Err ( Error :: OpenedDirAsFile ) ; } if entry . attributes . is_read_only ( ) && mode != Mode :: ReadOnly { return Err ( Error :: ReadOnly ) ; } } ; let mut mode = mode ; if mode == Mode :: ReadWriteCreateOrAppend { if dir_entry . is_some ( ) { mode = Mode :: ReadWriteAppend ; } else { mode = Mode :: ReadWriteCreate ; } } else if mode == Mode :: ReadWriteCreateOrTruncate { if dir_entry . is_some ( ) { mode = Mode :: ReadWriteTruncate ; } else { mode = Mode :: ReadWriteCreate ; } } let file = match mode { Mode :: ReadOnly => { // Safe to unwrap, since we actually have an entry if we got here let dir_entry = dir_entry . unwrap ( ) ; File { starting_cluster : dir_entry . cluster , current_cluster : ( 0 , dir_entry . cluster ) , current_offset : 0 , length : dir_entry . size , mode , entry : dir_entry , } } Mode :: ReadWriteAppend => { // Safe to unwrap, since we actually have an entry if we got here let dir_entry = dir_entry . unwrap ( ) ; let mut file = File { starting_cluster : dir_entry . cluster , current_cluster : ( 0 , dir_entry . cluster ) , current_offset : 0 , length : dir_entry . size , mode , entry : dir_entry , } ; // seek_from_end with 0 can't fail file . seek_from_end ( 0 ) . ok ( ) ; file } Mode :: ReadWriteTruncate => { // Safe to unwrap, since we actually have an entry if we got here let dir_entry = dir_entry . unwrap ( ) ; let mut file = File { starting_cluster : dir_entry . cluster , current_cluster : ( 0 , dir_entry . cluster ) , current_offset : 0 , length : dir_entry . size , mode , entry : dir_entry , } ; match & mut volume . volume_type { VolumeType :: Fat16 ( fat ) => { fat . truncate_cluster_chain ( self , file . starting_cluster ) ? } VolumeType :: Fat32 ( fat ) => { fat . truncate_cluster_chain ( self , file . starting_cluster ) ? } } ; file . update_length ( 0 ) ; // TODO update entry Timestamps let fat_type = match & volume . volume_type { VolumeType :: Fat16 ( _ ) => FatType :: Fat16 , VolumeType :: Fat32 ( _ ) => FatType :: Fat32 , } ; self . write_entry_to_disk ( fat_type , & file . entry ) ? ; file } Mode :: ReadWriteCreate => { if dir_entry . is_some ( ) { return Err ( Error :: FileAlreadyExists ) ; } let file_name = ShortFileName :: create_from_str ( name ) . map_err ( Error :: FilenameError ) ? ; let att = Attributes :: create_from_fat ( 0 ) ; let entry = match & mut volume . volume_type { VolumeType :: Fat16 ( fat ) => { fat . write_new_directory_entry ( self , dir , file_name , att ) ? } VolumeType :: Fat32 ( fat ) => { fat . write_new_directory_entry ( self , dir , file_name , att ) ? } } ; File { starting_cluster : entry . cluster , current_cluster : ( 0 , entry . cluster ) , current_offset : 0 , length : entry . size , mode , entry , } } _ => return Err ( Error :: Unsupported ) , } ; // Remember this open file self . open_files [ open_files_row ] = ( volume . idx , file . starting_cluster ) ; Ok ( file ) }
Open a file with the given full path.
Open a file with the given full path .
&mut self
volume
&mut Volume
dir
&Directory
name
&str
mode
Mode
&mut self
volume
&mut Volume
dir
&Directory
name
&str
mode
Mode