Skip to content

Commit 3018cfb

Browse files
committed
"is_regular_file" for file trait + integration test
1 parent f93f089 commit 3018cfb

File tree

6 files changed

+85
-16
lines changed

6 files changed

+85
-16
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
- Implemented `core::fmt::Write` for the `Serial` protocol.
1212
- Added the `MemoryProtection` protocol.
1313
- Added `BootServices::get_handle_for_protocol`.
14+
- the `File` trait now knows the methods `is_regular_file()` and `is_directory`.
15+
Developers profit from this on the struct `FileHandle`, for example.
1416

1517
### Changed
1618

@@ -27,7 +29,7 @@
2729
version to make sure it's 2.0 or higher before calling the associated
2830
function pointers. This prevents potential invalid pointer access.
2931
- The table `Header` struct's `Debug` impl now prints the correct signature.
30-
32+
3133
### Removed
3234

3335
- Removed the `exts::allocate_buffer` function. This function could

src/proto/media/file/dir.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,12 @@ impl File for Directory {
6767
fn handle(&mut self) -> &mut FileHandle {
6868
self.0.handle()
6969
}
70+
71+
fn is_regular_file(&self) -> bool {
72+
false
73+
}
74+
75+
fn is_directory(&self) -> bool {
76+
true
77+
}
7078
}

src/proto/media/file/mod.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,16 @@ pub trait File: Sized {
214214
// global allocator.
215215
unsafe { Ok(Box::from_raw(info)) }
216216
}
217+
218+
/// Returns true if the file is a regular file.
219+
///
220+
/// UEFI file system protocol only knows "regular files" and "directories".
221+
fn is_regular_file(&self) -> bool;
222+
223+
/// Returns if the file is a directory.
224+
///
225+
/// UEFI file system protocol only knows "regular files" and "directories".
226+
fn is_directory(&self) -> bool;
217227
}
218228

219229
// Internal File helper methods to access the funciton pointer table.
@@ -242,15 +252,13 @@ impl FileHandle {
242252

243253
/// Converts `File` into a more specific subtype based on if it is a
244254
/// directory or not. It does this via a call to `get_position`.
245-
pub fn into_type(mut self) -> Result<FileType> {
255+
pub fn into_type(self) -> Result<FileType> {
246256
use FileType::*;
247257

248-
// get_position fails with EFI_UNSUPPORTED on directories
249-
let mut pos = 0;
250-
match (self.imp().get_position)(self.imp(), &mut pos) {
251-
Status::SUCCESS => unsafe { Ok(Regular(RegularFile::new(self))) },
252-
Status::UNSUPPORTED => unsafe { Ok(Dir(Directory::new(self))) },
253-
s => Err(s.into()),
258+
if self.is_regular_file() {
259+
unsafe { Ok(Regular(RegularFile::new(self))) }
260+
} else {
261+
unsafe { Ok(Dir(Directory::new(self))) }
254262
}
255263
}
256264

@@ -280,6 +288,22 @@ impl File for FileHandle {
280288
fn handle(&mut self) -> &mut FileHandle {
281289
self
282290
}
291+
292+
fn is_regular_file(&self) -> bool {
293+
let this = unsafe { self.0.as_mut().unwrap() };
294+
295+
// get_position fails with EFI_UNSUPPORTED on directories
296+
let mut pos = 0;
297+
match (this.get_position)(this, &mut pos) {
298+
Status::SUCCESS => true,
299+
Status::UNSUPPORTED => false,
300+
_ => panic!("unexpected response"),
301+
}
302+
}
303+
304+
fn is_directory(&self) -> bool {
305+
!self.is_regular_file()
306+
}
283307
}
284308

285309
impl Drop for FileHandle {

src/proto/media/file/regular.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,12 @@ impl File for RegularFile {
104104
fn handle(&mut self) -> &mut FileHandle {
105105
&mut self.0
106106
}
107+
108+
fn is_regular_file(&self) -> bool {
109+
true
110+
}
111+
112+
fn is_directory(&self) -> bool {
113+
false
114+
}
107115
}

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

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
mod known_disk;
22

33
use uefi::prelude::*;
4-
use uefi::proto::media::file::{Directory, File, FileSystemInfo, FileSystemVolumeLabel};
4+
use uefi::proto::media::file::{
5+
Directory, File, FileAttribute, FileMode, FileSystemInfo, FileSystemVolumeLabel, FileType,
6+
};
57
use uefi::proto::media::fs::SimpleFileSystem;
68
use uefi::proto::media::partition::PartitionInfo;
79
use uefi::table::boot::{OpenProtocolAttributes, OpenProtocolParams};
10+
use uefi::CString16;
811

912
/// Test `FileSystemInfo` and `FileSystemVolumeLabel`.
1013
fn test_file_system_info(directory: &mut Directory) {
@@ -24,8 +27,8 @@ fn test_file_system_info(directory: &mut Directory) {
2427
assert_eq!(fs_info.volume_label(), fs_vol.volume_label());
2528
}
2629

27-
pub fn test(image: Handle, bt: &BootServices) {
28-
info!("Testing Media Access protocols");
30+
pub fn test_simple_file_system_protocol(image: Handle, bt: &BootServices) {
31+
info!("Testing Simple File System Protocol");
2932

3033
if let Ok(handle) = bt.get_handle_for_protocol::<SimpleFileSystem>() {
3134
let mut sfs = bt
@@ -39,10 +42,10 @@ pub fn test(image: Handle, bt: &BootServices) {
3942
)
4043
.expect("failed to open SimpleFileSystem protocol");
4144

42-
let mut directory = sfs.open_volume().unwrap();
45+
let mut root_directory = sfs.open_volume().unwrap();
4346
let mut buffer = vec![0; 128];
4447
loop {
45-
let file_info = match directory.read_entry(&mut buffer) {
48+
let file_info = match root_directory.read_entry(&mut buffer) {
4649
Ok(info) => {
4750
if let Some(info) = info {
4851
info
@@ -60,12 +63,35 @@ pub fn test(image: Handle, bt: &BootServices) {
6063
};
6164
info!("Root directory entry: {:?}", file_info);
6265
}
63-
directory.reset_entry_readout().unwrap();
66+
root_directory.reset_entry_readout().unwrap();
6467

65-
test_file_system_info(&mut directory);
68+
test_file_system_info(&mut root_directory);
69+
70+
assert!(root_directory.is_directory());
71+
assert!(!root_directory.is_regular_file());
72+
73+
info!("creating file in root volume");
74+
let created_file = root_directory
75+
.open(
76+
CString16::try_from("foo").unwrap().as_ref(),
77+
FileMode::CreateReadWrite,
78+
FileAttribute::empty(),
79+
)
80+
.unwrap();
81+
assert!(created_file.is_regular_file());
82+
let created_file = match created_file.into_type().unwrap() {
83+
FileType::Regular(file) => file,
84+
_ => panic!("unsupported value"),
85+
};
86+
assert!(created_file.is_regular_file());
87+
assert!(!created_file.is_directory());
6688
} else {
6789
warn!("`SimpleFileSystem` protocol is not available");
6890
}
91+
}
92+
93+
pub fn test_partition_info_protocol(image: Handle, bt: &BootServices) {
94+
info!("Testing Partition Info protocols");
6995

7096
let handles = bt
7197
.find_handles::<PartitionInfo>()

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ pub fn test(image: Handle, st: &mut SystemTable<Boot>) {
1515
debug::test(image, bt);
1616
device_path::test(image, bt);
1717
loaded_image::test(image, bt);
18-
media::test(image, bt);
18+
media::test_simple_file_system_protocol(image, bt);
19+
media::test_partition_info_protocol(image, bt);
1920
network::test(image, bt);
2021
pi::test(image, bt);
2122
rng::test(image, bt);

0 commit comments

Comments
 (0)