WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
matrix:
# Always run MSRV too!
rust: ["stable", "1.86"]
rust: ["stable", "1.87"]
features: ['log', 'defmt-log', '""']
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repository = "https://github.com/rust-embedded-community/embedded-sdmmc-rs"
version = "0.9.0"

# Make sure to update the CI too!
rust-version = "1.86"
rust-version = "1.87"

[dependencies]
byteorder = {version = "1", default-features = false}
Expand Down
6 changes: 5 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,10 @@ where
OpenedDirAsFile,
/// You can't open a file as a directory
OpenedFileAsDir,
/// You can't delete a directory as a file
/// You can't delete a directory as a file [no longer being emitted]
DeleteDirAsFile,
/// You can't delete a non-empty directory
DeleteNonEmptyDir,
/// You can't close a volume with open files or directories
VolumeStillInUse,
/// You can't open a volume twice
Expand Down Expand Up @@ -255,6 +257,7 @@ impl<E: Debug> embedded_io::Error for Error<E> {
Error::OpenedDirAsFile
| Error::OpenedFileAsDir
| Error::DeleteDirAsFile
| Error::DeleteNonEmptyDir
| Error::BadCluster
| Error::ConversionError
| Error::UnterminatedFatChain => ErrorKind::InvalidData,
Expand Down Expand Up @@ -294,6 +297,7 @@ where
Error::OpenedDirAsFile => write!(f, "cannot open directory as file"),
Error::OpenedFileAsDir => write!(f, "cannot open file as directory"),
Error::DeleteDirAsFile => write!(f, "cannot delete directory as file"),
Error::DeleteNonEmptyDir => write!(f, "cannot delete a non-empty directory"),
Error::VolumeStillInUse => write!(f, "volume is still in use"),
Error::VolumeAlreadyOpen => write!(f, "cannot open volume twice"),
Error::Unsupported => write!(f, "unsupported operation"),
Expand Down
54 changes: 45 additions & 9 deletions src/volume_mgr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -665,26 +665,62 @@ where
let data = data.deref_mut();

let dir_idx = data.get_dir_by_id(directory)?;
let dir_info = &data.open_dirs[dir_idx];
let volume_idx = data.get_volume_by_id(dir_info.raw_volume)?;
let parent_dir_info = &data.open_dirs[dir_idx];
let volume_idx = data.get_volume_by_id(parent_dir_info.raw_volume)?;
let sfn = name.to_short_filename().map_err(Error::FilenameError)?;

let dir_entry = match &data.open_volumes[volume_idx].volume_type {
VolumeType::Fat(fat) => fat.find_directory_entry(&mut data.block_cache, dir_info, &sfn),
VolumeType::Fat(fat) => {
fat.find_directory_entry(&mut data.block_cache, parent_dir_info, &sfn)
}
}?;

if dir_entry.attributes.is_directory() {
return Err(Error::DeleteDirAsFile);
}

if data.file_is_open(dir_info.raw_volume, &dir_entry) {
// Find the directory to be deleted, so that we can check its contents.
let dir_info = if data
.open_dirs
.iter()
.find(|dir_info| dir_info.cluster == dir_entry.cluster)
.is_some()
{
// Subdirectory is already open.
return Err(Error::DirAlreadyOpen);
} else {
// The subdirectory isn't yet open. Open it in order to be able to list it.
let raw_directory = RawDirectory(data.id_generator.generate());
DirectoryInfo {
raw_directory,
raw_volume: data.open_volumes[volume_idx].raw_volume,
cluster: dir_entry.cluster,
}
};
// Can only delete directories that are already empty.
let mut count = 0;
// Equivalent to `self.iterate_dir(raw_dir, |_| count += 1)?;`, without locking again.
match &data.open_volumes[volume_idx].volume_type {
VolumeType::Fat(fat) => {
fat.iterate_dir(&mut data.block_cache, &dir_info, |de| {
// Hide all the LFN directory entries
if !de.attributes.is_lfn()
&& de.name != ShortFileName::this_dir()
&& de.name != ShortFileName::parent_dir()
{
count += 1;
}
})?;
}
}
if count != 0 {
return Err(Error::DeleteNonEmptyDir);
}
} else if data.file_is_open(parent_dir_info.raw_volume, &dir_entry) {
return Err(Error::FileAlreadyOpen);
}

let volume_idx = data.get_volume_by_id(dir_info.raw_volume)?;
let volume_idx = data.get_volume_by_id(parent_dir_info.raw_volume)?;
match &data.open_volumes[volume_idx].volume_type {
VolumeType::Fat(fat) => {
fat.delete_directory_entry(&mut data.block_cache, dir_info, &sfn)?
fat.delete_directory_entry(&mut data.block_cache, parent_dir_info, &sfn)?
}
}

Expand Down
43 changes: 43 additions & 0 deletions tests/directories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,49 @@ fn make_directory() {
volume_mgr.close_file(new_file).expect("close file");
}

#[test]
fn delete_directory() {
let time_source = utils::make_time_source();
let disk = utils::make_block_device(utils::DISK_SOURCE).unwrap();
let volume_mgr = embedded_sdmmc::VolumeManager::new(disk, time_source);

let fat32_volume = volume_mgr
.open_raw_volume(embedded_sdmmc::VolumeIdx(1))
.expect("open volume 1");

let root_dir = volume_mgr
.open_root_dir(fat32_volume)
.expect("open root dir");

volume_mgr.make_dir_in_dir(root_dir, "FOOBAR").unwrap();

let dir = volume_mgr.open_dir(root_dir, "FOOBAR").unwrap();

assert!(matches!(
volume_mgr.delete_file_in_dir(root_dir, "FOOBAR"),
Err(embedded_sdmmc::Error::DirAlreadyOpen)
));

assert!(matches!(
volume_mgr.delete_file_in_dir(root_dir, "FOO"),
Err(embedded_sdmmc::Error::NotFound)
));

volume_mgr.close_dir(dir).unwrap();

volume_mgr.delete_file_in_dir(root_dir, "FOOBAR").unwrap();

assert!(matches!(
volume_mgr.delete_file_in_dir(root_dir, "FOOBAR"),
Err(embedded_sdmmc::Error::NotFound)
));

assert!(matches!(
volume_mgr.open_dir(root_dir, "FOOBAR"),
Err(embedded_sdmmc::Error::NotFound)
));
}

// ****************************************************************************
//
// End Of File
Expand Down