Skip to content

Commit b769e7a

Browse files
committed
fs: implement remove_dir_all
With this PR, the fs module is feature-complete and ready to be shipped.
1 parent c91e290 commit b769e7a

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

uefi-test-runner/src/fs/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ pub fn test(sfs: ScopedProtocol<SimpleFileSystem>) -> Result<(), fs::Error> {
6060
assert_eq!(boxinfo.file_size(), data_to_write.len() as u64);
6161

6262
// test remove dir all
63-
// TODO
63+
fs.remove_dir_all(cstr16!("foo_dir\\1"))?;
64+
// file should not be available after remove all
65+
let err = fs.try_exists(cstr16!("foo_dir\\1"));
66+
assert!(err.is_err());
6467

6568
Ok(())
6669
}

uefi/src/fs/dir_entry_iter.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ use alloc::boxed::Box;
66

77
/// Iterates over the entries of an UEFI directory. It returns boxed values of
88
/// type [`UefiFileInfo`].
9+
///
10+
/// Note that on UEFI/FAT-style file systems, the root dir usually doesn't
11+
/// return the entries `.` and `..`, whereas sub directories do.
912
#[derive(Debug)]
1013
pub struct UefiDirectoryIter(UefiDirectoryHandle);
1114

uefi/src/fs/file_system/fs.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use core::fmt;
1111
use core::fmt::{Debug, Formatter};
1212
use core::ops::Deref;
1313
use log::debug;
14+
use uefi::CStr16;
15+
use uefi_macros::cstr16;
1416

1517
/// Return type for public [`FileSystem`] operations.
1618
pub type FileSystemResult<T> = Result<T, Error>;
@@ -181,11 +183,35 @@ impl<'a> FileSystem<'a> {
181183
}
182184
}
183185

184-
/*/// Removes a directory at this path, after removing all its contents. Use
186+
/// Removes a directory at this path, after removing all its contents. Use
185187
/// carefully!
186188
pub fn remove_dir_all(&mut self, path: impl AsRef<Path>) -> FileSystemResult<()> {
189+
const SKIP_DIRS: [&CStr16; 2] = [cstr16!("."), cstr16!("..")];
187190
let path = path.as_ref();
188-
}*/
191+
for file_info in self
192+
.read_dir(path)?
193+
.filter_map(|file_info_result| file_info_result.ok())
194+
{
195+
if SKIP_DIRS.contains(&file_info.file_name()) {
196+
continue;
197+
}
198+
199+
let mut abs_entry_path = PathBuf::new();
200+
abs_entry_path.push(path);
201+
abs_entry_path.push(file_info.file_name());
202+
if file_info.is_directory() {
203+
// delete all inner files
204+
// This recursion is fine as there are no links in UEFI/FAT file
205+
// systems. No cycles possible.
206+
self.remove_dir_all(&abs_entry_path)?;
207+
} else {
208+
self.remove_file(abs_entry_path)?;
209+
}
210+
}
211+
// Now that the dir is empty, we delete it as final step.
212+
self.remove_dir(path)?;
213+
Ok(())
214+
}
189215

190216
/// Removes a file from the filesystem.
191217
pub fn remove_file(&mut self, path: impl AsRef<Path>) -> FileSystemResult<()> {
@@ -282,17 +308,17 @@ impl<'a> FileSystem<'a> {
282308
/// absolute path.
283309
///
284310
/// May create a file if [`UefiFileMode::CreateReadWrite`] is set. May
285-
/// create a directory if [`UefiFileMode::CreateReadWrite`] and `is_dir`
286-
/// is set.
311+
/// create a directory if [`UefiFileMode::CreateReadWrite`] and `create_dir`
312+
/// is set. The parameter `create_dir` is ignored otherwise.
287313
fn open(
288314
&mut self,
289315
path: &Path,
290316
mode: UefiFileMode,
291-
is_dir: bool,
317+
create_dir: bool,
292318
) -> FileSystemResult<UefiFileHandle> {
293319
validate_path(path)?;
294320

295-
let attr = if mode == UefiFileMode::CreateReadWrite && is_dir {
321+
let attr = if mode == UefiFileMode::CreateReadWrite && create_dir {
296322
UefiFileAttribute::DIRECTORY
297323
} else {
298324
UefiFileAttribute::empty()

0 commit comments

Comments
 (0)