1
1
//! Module for [`FileSystem`].
2
2
3
3
use super :: * ;
4
- use crate :: fs;
5
4
use crate :: fs:: path:: validation:: { validate_path, PathError } ;
6
5
use crate :: proto:: media:: file:: { FileAttribute , FileInfo , FileType } ;
7
6
use crate :: table:: boot:: ScopedProtocol ;
8
7
use alloc:: boxed:: Box ;
9
8
use alloc:: string:: { FromUtf8Error , String , ToString } ;
9
+ use alloc:: vec;
10
10
use alloc:: vec:: Vec ;
11
- use alloc:: { format, vec} ;
12
11
use core:: fmt;
13
12
use core:: fmt:: { Debug , Formatter } ;
14
13
use core:: ops:: Deref ;
15
14
use derive_more:: Display ;
16
- use log:: info;
17
- use uefi:: Char16 ;
15
+ use log:: debug;
18
16
19
17
/// All errors that can happen when working with the [`FileSystem`].
20
18
#[ derive( Debug , Clone , Display , PartialEq , Eq ) ]
21
19
pub enum FileSystemError {
22
20
/// Can't open the root directory of the underlying volume.
23
21
CantOpenVolume ,
24
22
/// The path is invalid because of the underlying [`PathError`].
23
+ ///
24
+ /// [`PathError`]: path::validation::PathError
25
25
IllegalPath ( PathError ) ,
26
26
/// The file or directory was not found in the underlying volume.
27
27
FileNotFound ( String ) ,
@@ -47,8 +47,10 @@ pub enum FileSystemError {
47
47
/// and the underlying UEFI error.
48
48
#[ display( fmt = "{path:?}" ) ]
49
49
OpenError {
50
+ /// Path that caused the failure.
50
51
path : String ,
51
- error : crate :: Error < >
52
+ /// More detailed failure description.
53
+ error : crate :: Error ,
52
54
} ,
53
55
}
54
56
@@ -112,37 +114,39 @@ impl<'a> FileSystem<'a> {
112
114
/// Recursively create a directory and all of its parent components if they
113
115
/// are missing.
114
116
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 ( ( ) )
133
138
}
134
139
135
140
/// Given a path, query the file system to get information about a file,
136
141
/// directory, etc. Returns [`UefiFileInfo`].
137
142
pub fn metadata ( & mut self , path : impl AsRef < Path > ) -> FileSystemResult < Box < UefiFileInfo > > {
138
143
let path = path. as_ref ( ) ;
139
- let file = self . open ( path, UefiFileMode :: Read , false ) ?;
140
144
let mut file = self . open ( path, UefiFileMode :: Read , false ) ?;
141
145
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:#?}" ) ;
143
147
FileSystemError :: OpenError {
144
148
path : path. to_cstr16 ( ) . to_string ( ) ,
145
- error : err
149
+ error : err,
146
150
}
147
151
} )
148
152
}
@@ -155,12 +159,12 @@ impl<'a> FileSystem<'a> {
155
159
. open ( path, UefiFileMode :: Read , false ) ?
156
160
. into_regular_file ( )
157
161
. 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 {
160
165
path : path. to_cstr16 ( ) . to_string ( ) ,
161
- error : err
162
- }
163
- } ) ?;
166
+ error : err,
167
+ } ) ?;
164
168
165
169
let mut vec = vec ! [ 0 ; info. file_size( ) as usize ] ;
166
170
let read_bytes = file. read ( vec. as_mut_slice ( ) ) . map_err ( |e| {
@@ -205,14 +209,16 @@ impl<'a> FileSystem<'a> {
205
209
log:: error!( "error removing dir: {e:?}" ) ;
206
210
FileSystemError :: CantDeleteDirectory ( path. to_cstr16 ( ) . to_string ( ) )
207
211
} ) ,
208
- FileType :: Regular ( _) => Err ( FileSystemError :: NotADirectory ( path. to_cstr16 ( ) . to_string ( ) ) ) ,
212
+ FileType :: Regular ( _) => {
213
+ Err ( FileSystemError :: NotADirectory ( path. to_cstr16 ( ) . to_string ( ) ) )
214
+ }
209
215
}
210
216
}
211
217
212
218
/*/// Removes a directory at this path, after removing all its contents. Use
213
219
/// 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();
216
222
}*/
217
223
218
224
/// Removes a file from the filesystem.
@@ -311,7 +317,7 @@ impl<'a> FileSystem<'a> {
311
317
log:: trace!( "Can't open file {path}: {err:?}" ) ;
312
318
FileSystemError :: OpenError {
313
319
path : path. to_cstr16 ( ) . to_string ( ) ,
314
- error : err
320
+ error : err,
315
321
}
316
322
} )
317
323
}
0 commit comments