@@ -665,26 +665,62 @@ 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] ;
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 data
681+ . open_dirs
682+ . iter ( )
683+ . find ( |dir_info| dir_info. cluster == dir_entry. cluster )
684+ . is_some ( )
685+ {
686+ // Subdirectory is already open.
687+ return Err ( Error :: DirAlreadyOpen ) ;
688+ } else {
689+ // The subdirectory isn't yet open. Open it in order to be able to list it.
690+ let raw_directory = RawDirectory ( data. id_generator . generate ( ) ) ;
691+ DirectoryInfo {
692+ raw_directory,
693+ raw_volume : data. open_volumes [ volume_idx] . raw_volume ,
694+ cluster : dir_entry. cluster ,
695+ }
696+ } ;
697+ // Can only delete directories that are already empty.
698+ let mut count = 0 ;
699+ // Equivalent to `self.iterate_dir(raw_dir, |_| count += 1)?;`, without locking again.
700+ match & data. open_volumes [ volume_idx] . volume_type {
701+ VolumeType :: Fat ( fat) => {
702+ fat. iterate_dir ( & mut data. block_cache , & dir_info, |de| {
703+ // Hide all the LFN directory entries
704+ if !de. attributes . is_lfn ( )
705+ && de. name != ShortFileName :: this_dir ( )
706+ && de. name != ShortFileName :: parent_dir ( )
707+ {
708+ count += 1 ;
709+ }
710+ } ) ?;
711+ }
712+ }
713+ if count != 0 {
714+ return Err ( Error :: DeleteNonEmptyDir ) ;
715+ }
716+ } else if data. file_is_open ( parent_dir_info. raw_volume , & dir_entry) {
681717 return Err ( Error :: FileAlreadyOpen ) ;
682718 }
683719
684- let volume_idx = data. get_volume_by_id ( dir_info . raw_volume ) ?;
720+ let volume_idx = data. get_volume_by_id ( parent_dir_info . raw_volume ) ?;
685721 match & data. open_volumes [ volume_idx] . volume_type {
686722 VolumeType :: Fat ( fat) => {
687- fat. delete_directory_entry ( & mut data. block_cache , dir_info , & sfn) ?
723+ fat. delete_directory_entry ( & mut data. block_cache , parent_dir_info , & sfn) ?
688724 }
689725 }
690726
0 commit comments