Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d5d2322

Browse files
committed
fs/path: finalize implementation + integration test
Now, only remove_dir_all is missing. The reason for this is not technical. Someone just needs to put a little more effort into it.
1 parent f6caee4 commit d5d2322

File tree

7 files changed

+230
-131
lines changed

7 files changed

+230
-131
lines changed

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

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
33
use alloc::string::{String, ToString};
44
use alloc::vec::Vec;
5-
use uefi::fs::{FileSystem, FileSystemError};
5+
use uefi::cstr16;
6+
use uefi::fs::{FileSystem, FileSystemError, PathBuf};
67
use uefi::proto::media::fs::SimpleFileSystem;
78
use uefi::table::boot::ScopedProtocol;
89

@@ -11,47 +12,50 @@ use uefi::table::boot::ScopedProtocol;
1112
pub fn test(sfs: ScopedProtocol<SimpleFileSystem>) -> Result<(), FileSystemError> {
1213
let mut fs = FileSystem::new(sfs);
1314

14-
fs.create_dir("test_file_system_abs")?;
15+
// test create dir
16+
fs.create_dir(cstr16!("foo_dir"))?;
1517

16-
// slash is transparently transformed to backslash
17-
fs.write("test_file_system_abs/foo", "hello")?;
18-
// absolute or relative paths are supported; ./ is ignored
19-
fs.copy("\\test_file_system_abs/foo", "\\test_file_system_abs/./bar")?;
20-
let read = fs.read("\\test_file_system_abs\\bar")?;
18+
// test write, copy, and read
19+
let data_to_write = "hello world";
20+
fs.write(cstr16!("foo_dir\\foo"), data_to_write)?;
21+
// Here, we additionally check that absolute paths work.
22+
fs.copy(cstr16!("\\foo_dir\\foo"), cstr16!("\\foo_dir\\foo_cpy"))?;
23+
let read = fs.read(cstr16!("foo_dir\\foo_cpy"))?;
2124
let read = String::from_utf8(read).expect("Should be valid utf8");
22-
assert_eq!(read, "hello");
23-
24-
assert_eq!(
25-
fs.try_exists("test_file_system_abs\\barfoo"),
26-
Err(FileSystemError::OpenError(
27-
"\\test_file_system_abs\\barfoo".to_string()
28-
))
29-
);
30-
fs.rename("test_file_system_abs\\bar", "test_file_system_abs\\barfoo")?;
31-
assert!(fs.try_exists("test_file_system_abs\\barfoo").is_ok());
32-
25+
assert_eq!(read.as_str(), data_to_write);
26+
27+
// test copy from non-existent file
28+
let err = fs.copy(cstr16!("not_found"), cstr16!("abc"));
29+
assert!(matches!(err, Err(FileSystemError::OpenError { .. })));
30+
31+
// test rename file + path buf replaces / with \
32+
fs.rename(
33+
PathBuf::from(cstr16!("/foo_dir/foo_cpy")),
34+
cstr16!("foo_dir\\foo_cpy2"),
35+
)?;
36+
// file should not be available after rename
37+
let err = fs.read(cstr16!("foo_dir\\foo_cpy"));
38+
assert!(matches!(err, Err(FileSystemError::OpenError { .. })));
39+
40+
// test read dir on a sub dir
3341
let entries = fs
34-
.read_dir("test_file_system_abs")?
35-
.map(|e| {
36-
e.expect("Should return boxed file info")
37-
.file_name()
38-
.to_string()
39-
})
42+
.read_dir(cstr16!("foo_dir"))?
43+
.map(|entry| entry.expect("Should be valid").file_name().to_string())
4044
.collect::<Vec<_>>();
41-
assert_eq!(&[".", "..", "foo", "barfoo"], entries.as_slice());
42-
43-
fs.create_dir("/deeply_nested_test")?;
44-
fs.create_dir("/deeply_nested_test/1")?;
45-
fs.create_dir("/deeply_nested_test/1/2")?;
46-
fs.create_dir("/deeply_nested_test/1/2/3")?;
47-
fs.create_dir("/deeply_nested_test/1/2/3/4")?;
48-
fs.create_dir_all("/deeply_nested_test/1/2/3/4/5/6/7")?;
49-
fs.try_exists("/deeply_nested_test/1/2/3/4/5/6/7")?;
45+
assert_eq!(&[".", "..", "foo", "foo_cpy2"], entries.as_slice());
46+
47+
// test create dir recursively
48+
fs.create_dir_all(cstr16!("foo_dir\\1\\2\\3\\4\\5\\6\\7"))?;
49+
fs.create_dir_all(cstr16!("foo_dir\\1\\2\\3\\4\\5\\6\\7\\8"))?;
50+
fs.write(
51+
cstr16!("foo_dir\\1\\2\\3\\4\\5\\6\\7\\8\\foobar"),
52+
data_to_write,
53+
)?;
54+
let boxinfo = fs.metadata(cstr16!("foo_dir\\1\\2\\3\\4\\5\\6\\7\\8\\foobar"))?;
55+
assert_eq!(boxinfo.file_size(), data_to_write.len() as u64);
56+
57+
// test remove dir all
5058
// TODO
51-
// fs.remove_dir_all("/deeply_nested_test/1/2/3/4/5/6/7")?;
52-
fs.remove_dir("/deeply_nested_test/1/2/3/4/5/6/7")?;
53-
let exists = matches!(fs.try_exists("/deeply_nested_test/1/2/3/4/5/6/7"), Ok(_));
54-
assert!(!exists);
5559

5660
Ok(())
5761
}

‎uefi/src/fs/file_system.rs

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
//! Module for [`FileSystem`].
22
33
use super::*;
4-
use crate::fs;
54
use crate::fs::path::validation::{validate_path, PathError};
65
use crate::proto::media::file::{FileAttribute, FileInfo, FileType};
76
use crate::table::boot::ScopedProtocol;
87
use alloc::boxed::Box;
98
use alloc::string::{FromUtf8Error, String, ToString};
9+
use alloc::vec;
1010
use alloc::vec::Vec;
11-
use alloc::{format, vec};
1211
use core::fmt;
1312
use core::fmt::{Debug, Formatter};
1413
use core::ops::Deref;
1514
use derive_more::Display;
16-
use log::info;
17-
use uefi::Char16;
15+
use log::debug;
1816

1917
/// All errors that can happen when working with the [`FileSystem`].
2018
#[derive(Debug, Clone, Display, PartialEq, Eq)]
2119
pub enum FileSystemError {
2220
/// Can't open the root directory of the underlying volume.
2321
CantOpenVolume,
2422
/// The path is invalid because of the underlying [`PathError`].
23+
///
24+
/// [`PathError`]: path::validation::PathError
2525
IllegalPath(PathError),
2626
/// The file or directory was not found in the underlying volume.
2727
FileNotFound(String),
@@ -47,8 +47,10 @@ pub enum FileSystemError {
4747
/// and the underlying UEFI error.
4848
#[display(fmt = "{path:?}")]
4949
OpenError {
50+
/// Path that caused the failure.
5051
path: String,
51-
error: crate::Error<>
52+
/// More detailed failure description.
53+
error: crate::Error,
5254
},
5355
}
5456

@@ -112,37 +114,39 @@ impl<'a> FileSystem<'a> {
112114
/// Recursively create a directory and all of its parent components if they
113115
/// are missing.
114116
pub fn create_dir_all(&mut self, path: impl AsRef<Path>) -> FileSystemResult<()> {
115-
todo!()
116-
/*let path = path.as_ref();
117-
118-
let normalized_path = NormalizedPath::new("\\", path)?;
119-
let normalized_path_string = normalized_path.to_string();
120-
let normalized_path_pathref = Path::new(&normalized_path_string);
121-
122-
let iter = || normalized_path_pathref.components(SEPARATOR);
123-
iter()
124-
.scan(String::new(), |path_acc, component| {
125-
if component != Component::RootDir {
126-
*path_acc += SEPARATOR_STR;
127-
*path_acc += format!("{component}").as_str();
128-
}
129-
info!("path_acc: {path_acc}, component: {component}");
130-
Some((component, path_acc.clone()))
131-
})
132-
.try_for_each(|(_component, full_path)| self.create_dir(full_path.to_cstr16()))*/
117+
let path = path.as_ref();
118+
119+
// Collect all relevant sub paths in a vector.
120+
let mut dirs_to_create = vec![path.to_path_buf()];
121+
while let Some(parent) = dirs_to_create.last().unwrap().parent() {
122+
debug!("parent={parent}");
123+
dirs_to_create.push(parent)
124+
}
125+
// Now reverse, so that we have something like this:
126+
// - a
127+
// - a\\b
128+
// - a\\b\\c
129+
dirs_to_create.reverse();
130+
131+
for parent in dirs_to_create {
132+
if self.try_exists(&parent).is_err() {
133+
self.create_dir(parent)?;
134+
}
135+
}
136+
137+
Ok(())
133138
}
134139

135140
/// Given a path, query the file system to get information about a file,
136141
/// directory, etc. Returns [`UefiFileInfo`].
137142
pub fn metadata(&mut self, path: impl AsRef<Path>) -> FileSystemResult<Box<UefiFileInfo>> {
138143
let path = path.as_ref();
139-
let file = self.open(path, UefiFileMode::Read, false)?;
140144
let mut file = self.open(path, UefiFileMode::Read, false)?;
141145
file.get_boxed_info().map_err(|err| {
142-
log::debug!("failed to fetch file info: {err:#?}");
146+
log::trace!("failed to fetch file info: {err:#?}");
143147
FileSystemError::OpenError {
144148
path: path.to_cstr16().to_string(),
145-
error: err
149+
error: err,
146150
}
147151
})
148152
}
@@ -155,12 +159,12 @@ impl<'a> FileSystem<'a> {
155159
.open(path, UefiFileMode::Read, false)?
156160
.into_regular_file()
157161
.ok_or(FileSystemError::NotAFile(path.to_cstr16().to_string()))?;
158-
let info = file.get_boxed_info::<FileInfo>().map_err(|err| {
159-
FileSystemError::OpenError {
162+
let info = file
163+
.get_boxed_info::<FileInfo>()
164+
.map_err(|err| FileSystemError::OpenError {
160165
path: path.to_cstr16().to_string(),
161-
error: err
162-
}
163-
})?;
166+
error: err,
167+
})?;
164168

165169
let mut vec = vec![0; info.file_size() as usize];
166170
let read_bytes = file.read(vec.as_mut_slice()).map_err(|e| {
@@ -205,14 +209,16 @@ impl<'a> FileSystem<'a> {
205209
log::error!("error removing dir: {e:?}");
206210
FileSystemError::CantDeleteDirectory(path.to_cstr16().to_string())
207211
}),
208-
FileType::Regular(_) => Err(FileSystemError::NotADirectory(path.to_cstr16().to_string())),
212+
FileType::Regular(_) => {
213+
Err(FileSystemError::NotADirectory(path.to_cstr16().to_string()))
214+
}
209215
}
210216
}
211217

212218
/*/// Removes a directory at this path, after removing all its contents. Use
213219
/// carefully!
214-
pub fn remove_dir_all(&mut self, _path: impl AsRef<Path>) -> FileSystemResult<()> {
215-
todo!()
220+
pub fn remove_dir_all(&mut self, path: impl AsRef<Path>) -> FileSystemResult<()> {
221+
let path = path.as_ref();
216222
}*/
217223

218224
/// Removes a file from the filesystem.
@@ -311,7 +317,7 @@ impl<'a> FileSystem<'a> {
311317
log::trace!("Can't open file {path}: {err:?}");
312318
FileSystemError::OpenError {
313319
path: path.to_cstr16().to_string(),
314-
error: err
320+
error: err,
315321
}
316322
})
317323
}

‎uefi/src/fs/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
3232
mod dir_entry_iter;
3333
mod file_system;
34-
mod uefi_types;
3534
mod path;
35+
mod uefi_types;
3636

3737
pub use file_system::{FileSystem, FileSystemError, FileSystemResult};
3838
pub use path::*;

‎uefi/src/fs/path/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,22 @@
1515
1616
mod path;
1717
mod pathbuf;
18-
pub(super) mod validation;
18+
pub mod validation;
1919

2020
pub use path::Path;
2121
pub use pathbuf::PathBuf;
2222

23-
use uefi::{Char16,CStr16};
23+
use uefi::{CStr16,Char16};
2424

2525
/// The default separator for paths.
2626
pub const SEPARATOR: char = '\\';
27+
/// [`SEPARATOR`] but as useful UEFI type.
2728
pub const SEPARATOR_C16: Char16 = unsafe { Char16::from_u16_unchecked('\\' as u16) };
2829

2930
/// Stringified version of [`SEPARATOR`].
3031
pub const SEPARATOR_STR: &str = "\\";
32+
/// [`SEPARATOR_STR`] but as useful UEFI type.
3133
pub const SEPARATOR_CSTR16: &CStr16 = uefi_macros::cstr16!("\\");
3234

3335
/// Denied characters in a path component.
34-
pub const CHARACTER_DENY_LIST: [char; 10] =
35-
['0円', '"', '*', '/', ':', '<', '>', '?', '\\', '|'];
36+
pub const CHARACTER_DENY_LIST: [char; 10] = ['0円', '"', '*', '/', ':', '<', '>', '?', '\\', '|'];

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /