Skip to content

Commit 62ee08a

Browse files
committed
fs: add high-level file system abstraction
1 parent d060364 commit 62ee08a

File tree

11 files changed

+836
-2
lines changed

11 files changed

+836
-2
lines changed

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//! Tests functionality from the `uefi::fs` module. See function [`test`].
2+
3+
use alloc::string::{String, ToString};
4+
use alloc::vec::Vec;
5+
use uefi::proto::media::fs::SimpleFileSystem;
6+
use uefi::table::boot::ScopedProtocol;
7+
use uefi::fs::{FileSystem, FileSystemError};
8+
9+
/// Tests functionality from the `uefi::fs` module. This test relies on a
10+
/// working File System Protocol, which is tested at a dedicated place.
11+
pub fn test(sfs: ScopedProtocol<SimpleFileSystem>) {
12+
let mut fs = FileSystem::new(sfs);
13+
14+
fs.create_dir("test_file_system_abs").unwrap();
15+
16+
// slash is transparently transformed to backslash
17+
fs.write("test_file_system_abs/foo", "hello").unwrap();
18+
// absolute or relative paths are supported; ./ is ignored
19+
fs.copy("\\test_file_system_abs/foo", "\\test_file_system_abs/./bar")
20+
.unwrap();
21+
let read = fs.read("\\test_file_system_abs\\bar").unwrap();
22+
let read = String::from_utf8(read).unwrap();
23+
assert_eq!(read, "hello");
24+
25+
assert_eq!(
26+
fs.try_exists("test_file_system_abs\\barfoo"),
27+
Err(FileSystemError::OpenError(
28+
"\\test_file_system_abs\\barfoo".to_string()
29+
))
30+
);
31+
fs.rename("test_file_system_abs\\bar", "test_file_system_abs\\barfoo")
32+
.unwrap();
33+
assert!(fs.try_exists("test_file_system_abs\\barfoo").is_ok());
34+
35+
let entries = fs
36+
.read_dir("test_file_system_abs")
37+
.unwrap()
38+
.map(|e| e.unwrap().file_name().to_string())
39+
.collect::<Vec<_>>();
40+
assert_eq!(&[".", "..", "foo", "barfoo"], entries.as_slice());
41+
42+
fs.create_dir_all("/test_file_system_abs/1/2/3/4/5/6/7").unwrap();
43+
fs.try_exists("/test_file_system_abs/1/2/3/4/5/6/7").unwrap();
44+
fs.remove_dir_all("/test_file_system_abs/1/2/3/4/5/6/7").unwrap();
45+
let x = fs.try_exists("/test_file_system_abs/1/2/3/4/5/6/7");
46+
assert!(x.is_err());
47+
}
48+

uefi-test-runner/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use uefi::Result;
1515
use uefi_services::{print, println};
1616

1717
mod boot;
18+
mod fs;
1819
mod proto;
1920
mod runtime;
2021

uefi-test-runner/src/proto/media.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,12 @@ pub fn test(bt: &BootServices) {
433433
test_partition_info(bt, handle);
434434
}
435435

436-
// Close the `SimpleFileSystem` protocol so that the raw disk tests work.
437-
drop(sfs);
436+
// Invoke the fs test after the basic low-level file system protocol
437+
// tests succeeded.
438+
439+
// This will also drop the `SimpleFileSystem` protocol so that the raw disk
440+
// tests work.
441+
crate::fs::test(sfs);
438442

439443
test_raw_disk_io(handle, bt);
440444
test_raw_disk_io2(handle, bt);

uefi/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ unstable = []
2424

2525
[dependencies]
2626
bitflags = "1.3.1"
27+
derive_more = { version = "0.99.17", features = ["display"] }
2728
log = { version = "0.4.5", default-features = false }
2829
ptr_meta = { version = "0.2.0", default-features = false }
2930
ucs2 = "0.3.2"

uefi/src/fs/dir_entry_iter.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use super::*;
2+
use alloc::boxed::Box;
3+
use uefi::Result;
4+
5+
/// Iterates over the entries of an UEFI directory. It returns boxed values of
6+
/// type [`UefiFileInfo`].
7+
pub struct UefiDirectoryIter(UefiDirectoryHandle);
8+
9+
impl UefiDirectoryIter {
10+
/// Constructor.
11+
pub(crate) fn new(handle: UefiDirectoryHandle) -> Self {
12+
Self(handle)
13+
}
14+
}
15+
16+
impl Iterator for UefiDirectoryIter {
17+
type Item = Result<Box<UefiFileInfo>, ()>;
18+
19+
fn next(&mut self) -> Option<Self::Item> {
20+
let e = self.0.read_entry_boxed();
21+
match e {
22+
// no more entries
23+
Ok(None) => None,
24+
Ok(Some(e)) => Some(Ok(e)),
25+
Err(e) => Some(Err(e)),
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)