@@ -12,9 +12,9 @@ use crate::filesystem::{
1212 SearchIdGenerator , TimeSource , ToShortFileName , MAX_FILE_SIZE ,
1313} ;
1414use crate :: {
15- debug, Block , BlockCount , BlockDevice , BlockIdx , Error , RawVolume , Volume , VolumeIdx ,
16- VolumeInfo , VolumeType , PARTITION_ID_FAT16 , PARTITION_ID_FAT16_LBA , PARTITION_ID_FAT32_CHS_LBA ,
17- PARTITION_ID_FAT32_LBA ,
15+ debug, Block , BlockCount , BlockDevice , BlockIdx , Error , RawVolume , ShortFileName , Volume ,
16+ VolumeIdx , VolumeInfo , VolumeType , PARTITION_ID_FAT16 , PARTITION_ID_FAT16_LBA ,
17+ PARTITION_ID_FAT32_CHS_LBA , PARTITION_ID_FAT32_LBA ,
1818} ;
1919use heapless:: Vec ;
2020
@@ -206,11 +206,7 @@ where
206206 /// You can then read the directory entries with `iterate_dir`, or you can
207207 /// use `open_file_in_dir`.
208208 pub fn open_root_dir ( & mut self , volume : RawVolume ) -> Result < RawDirectory , Error < D :: Error > > {
209- for dir in self . open_dirs . iter ( ) {
210- if dir. cluster == ClusterId :: ROOT_DIR && dir. volume_id == volume {
211- return Err ( Error :: DirAlreadyOpen ) ;
212- }
213- }
209+ // Opening a root directory twice is OK
214210
215211 let directory_id = RawDirectory ( self . id_generator . get ( ) ) ;
216212 let dir_info = DirectoryInfo {
@@ -229,6 +225,8 @@ where
229225 /// Open a directory.
230226 ///
231227 /// You can then read the directory entries with `iterate_dir` and `open_file_in_dir`.
228+ ///
229+ /// Passing "." as the name results in opening the `parent_dir` a second time.
232230 pub fn open_dir < N > (
233231 & mut self ,
234232 parent_dir : RawDirectory ,
@@ -245,9 +243,25 @@ where
245243 let parent_dir_idx = self . get_dir_by_id ( parent_dir) ?;
246244 let volume_idx = self . get_volume_by_id ( self . open_dirs [ parent_dir_idx] . volume_id ) ?;
247245 let short_file_name = name. to_short_filename ( ) . map_err ( Error :: FilenameError ) ?;
246+ let parent_dir_info = & self . open_dirs [ parent_dir_idx] ;
248247
249248 // Open the directory
250- let parent_dir_info = & self . open_dirs [ parent_dir_idx] ;
249+ if short_file_name == ShortFileName :: this_dir ( ) {
250+ // short-cut (root dir doesn't have ".")
251+ let directory_id = RawDirectory ( self . id_generator . get ( ) ) ;
252+ let dir_info = DirectoryInfo {
253+ directory_id,
254+ volume_id : self . open_volumes [ volume_idx] . volume_id ,
255+ cluster : parent_dir_info. cluster ,
256+ } ;
257+
258+ self . open_dirs
259+ . push ( dir_info)
260+ . map_err ( |_| Error :: TooManyOpenDirs ) ?;
261+
262+ return Ok ( directory_id) ;
263+ }
264+
251265 let dir_entry = match & self . open_volumes [ volume_idx] . volume_type {
252266 VolumeType :: Fat ( fat) => {
253267 fat. find_directory_entry ( & self . block_device , parent_dir_info, & short_file_name) ?
@@ -260,14 +274,8 @@ where
260274 return Err ( Error :: OpenedFileAsDir ) ;
261275 }
262276
263- // Check it's not already open
264- for d in self . open_dirs . iter ( ) {
265- if d. volume_id == self . open_volumes [ volume_idx] . volume_id
266- && d. cluster == dir_entry. cluster
267- {
268- return Err ( Error :: DirAlreadyOpen ) ;
269- }
270- }
277+ // We don't check if the directory is already open - directories hold
278+ // no cached state and so opening a directory twice is allowable.
271279
272280 // Remember this open directory.
273281 let directory_id = RawDirectory ( self . id_generator . get ( ) ) ;
0 commit comments