@@ -12,9 +12,9 @@ use crate::filesystem::{
12
12
SearchIdGenerator , TimeSource , ToShortFileName , MAX_FILE_SIZE ,
13
13
} ;
14
14
use 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 ,
18
18
} ;
19
19
use heapless:: Vec ;
20
20
@@ -206,11 +206,7 @@ where
206
206
/// You can then read the directory entries with `iterate_dir`, or you can
207
207
/// use `open_file_in_dir`.
208
208
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
214
210
215
211
let directory_id = RawDirectory ( self . id_generator . get ( ) ) ;
216
212
let dir_info = DirectoryInfo {
@@ -229,6 +225,8 @@ where
229
225
/// Open a directory.
230
226
///
231
227
/// 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.
232
230
pub fn open_dir < N > (
233
231
& mut self ,
234
232
parent_dir : RawDirectory ,
@@ -245,9 +243,25 @@ where
245
243
let parent_dir_idx = self . get_dir_by_id ( parent_dir) ?;
246
244
let volume_idx = self . get_volume_by_id ( self . open_dirs [ parent_dir_idx] . volume_id ) ?;
247
245
let short_file_name = name. to_short_filename ( ) . map_err ( Error :: FilenameError ) ?;
246
+ let parent_dir_info = & self . open_dirs [ parent_dir_idx] ;
248
247
249
248
// 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
+
251
265
let dir_entry = match & self . open_volumes [ volume_idx] . volume_type {
252
266
VolumeType :: Fat ( fat) => {
253
267
fat. find_directory_entry ( & self . block_device , parent_dir_info, & short_file_name) ?
@@ -260,14 +274,8 @@ where
260
274
return Err ( Error :: OpenedFileAsDir ) ;
261
275
}
262
276
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.
271
279
272
280
// Remember this open directory.
273
281
let directory_id = RawDirectory ( self . id_generator . get ( ) ) ;
0 commit comments