@@ -665,26 +665,64 @@ where
665665 let data = data. deref_mut ( ) ;
666666
667667 let dir_idx = data. get_dir_by_id ( directory) ?;
668- let dir_info = & data. open_dirs [ dir_idx] ;
669- let volume_idx = data. get_volume_by_id ( dir_info . raw_volume ) ?;
668+ let parent_dir_info = data. open_dirs [ dir_idx] . clone ( ) ;
669+ let volume_idx = data. get_volume_by_id ( parent_dir_info . raw_volume ) ?;
670670 let sfn = name. to_short_filename ( ) . map_err ( Error :: FilenameError ) ?;
671671
672672 let dir_entry = match & data. open_volumes [ volume_idx] . volume_type {
673- VolumeType :: Fat ( fat) => fat. find_directory_entry ( & mut data. block_cache , dir_info, & sfn) ,
673+ VolumeType :: Fat ( fat) => {
674+ fat. find_directory_entry ( & mut data. block_cache , & parent_dir_info, & sfn)
675+ }
674676 } ?;
675677
676678 if dir_entry. attributes . is_directory ( ) {
677- return Err ( Error :: DeleteDirAsFile ) ;
678- }
679-
680- if data. file_is_open ( dir_info. raw_volume , & dir_entry) {
679+ // Find the directory to be deleted, so that we can check its contents.
680+ let dir_info = if let Some ( dir_info) = data
681+ . open_dirs
682+ . iter ( )
683+ . find ( |dir_info| {
684+ // Subdirectory is already open.
685+ dir_info. cluster == dir_entry. cluster
686+ } )
687+ . cloned ( )
688+ {
689+ dir_info
690+ } else {
691+ // The subdirectory isn't yet open. Open it in order to be able to list it.
692+ let raw_directory = RawDirectory ( data. id_generator . generate ( ) ) ;
693+ DirectoryInfo {
694+ raw_directory,
695+ raw_volume : data. open_volumes [ volume_idx] . raw_volume ,
696+ cluster : dir_entry. cluster ,
697+ }
698+ } ;
699+ // Can only delete directories that are already empty.
700+ let mut count = 0 ;
701+ // Equivalent to `self.iterate_dir(raw_dir, |_| count += 1)?;`, without locking again.
702+ match & data. open_volumes [ volume_idx] . volume_type {
703+ VolumeType :: Fat ( fat) => {
704+ fat. iterate_dir ( & mut data. block_cache , & dir_info, |de| {
705+ // Hide all the LFN directory entries
706+ if !de. attributes . is_lfn ( )
707+ && de. name != ShortFileName :: this_dir ( )
708+ && de. name != ShortFileName :: parent_dir ( )
709+ {
710+ count += 1 ;
711+ }
712+ } ) ?;
713+ }
714+ }
715+ if count != 0 {
716+ return Err ( Error :: DeleteNonEmptyDir ) ;
717+ }
718+ } else if data. file_is_open ( parent_dir_info. raw_volume , & dir_entry) {
681719 return Err ( Error :: FileAlreadyOpen ) ;
682720 }
683721
684- let volume_idx = data. get_volume_by_id ( dir_info . raw_volume ) ?;
722+ let volume_idx = data. get_volume_by_id ( parent_dir_info . raw_volume ) ?;
685723 match & data. open_volumes [ volume_idx] . volume_type {
686724 VolumeType :: Fat ( fat) => {
687- fat. delete_directory_entry ( & mut data. block_cache , dir_info , & sfn) ?
725+ fat. delete_directory_entry ( & mut data. block_cache , & parent_dir_info , & sfn) ?
688726 }
689727 }
690728
0 commit comments