1
1
//! Module for [`FileSystem`].
2
2
3
3
use super :: * ;
4
+ use crate :: fs;
5
+ use crate :: fs:: path:: validation:: { validate_path, PathError } ;
4
6
use crate :: proto:: media:: file:: { FileAttribute , FileInfo , FileType } ;
5
7
use crate :: table:: boot:: ScopedProtocol ;
6
8
use alloc:: boxed:: Box ;
@@ -12,6 +14,7 @@ use core::fmt::{Debug, Formatter};
12
14
use core:: ops:: Deref ;
13
15
use derive_more:: Display ;
14
16
use log:: info;
17
+ use uefi:: Char16 ;
15
18
16
19
/// All errors that can happen when working with the [`FileSystem`].
17
20
#[ derive( Debug , Clone , Display , PartialEq , Eq ) ]
@@ -40,12 +43,26 @@ pub enum FileSystemError {
40
43
ReadFailure ,
41
44
/// Can't parse file content as UTF-8.
42
45
Utf8Error ( FromUtf8Error ) ,
43
- /// Could not open the given path.
44
- OpenError ( String ) ,
46
+ /// Could not open the given path. Carries the path that could not be opened
47
+ /// and the underlying UEFI error.
48
+ #[ display( fmt = "{path:?}" ) ]
49
+ OpenError {
50
+ path : String ,
51
+ error : crate :: Error < >
52
+ } ,
45
53
}
46
54
47
55
#[ cfg( feature = "unstable" ) ]
48
- impl core:: error:: Error for FileSystemError { }
56
+ impl core:: error:: Error for FileSystemError {
57
+ fn source ( & self ) -> Option < & ( dyn Error + ' static ) > {
58
+ match self {
59
+ FileSystemError :: IllegalPath ( e) => Some ( e) ,
60
+ FileSystemError :: Utf8Error ( e) => Some ( e) ,
61
+ FileSystemError :: OpenError ( _path, e) => Some ( e) ,
62
+ _ => None ,
63
+ }
64
+ }
65
+ }
49
66
50
67
impl From < PathError > for FileSystemError {
51
68
fn from ( err : PathError ) -> Self {
@@ -90,16 +107,13 @@ impl<'a> FileSystem<'a> {
90
107
let path = path. as_ref ( ) ;
91
108
self . open ( path, UefiFileMode :: CreateReadWrite , true )
92
109
. map ( |_| ( ) )
93
- . map_err ( |err| {
94
- log:: debug!( "failed to fetch file info: {err:#?}" ) ;
95
- FileSystemError :: OpenError ( path. to_string ( ) )
96
- } )
97
110
}
98
111
99
112
/// Recursively create a directory and all of its parent components if they
100
113
/// are missing.
101
114
pub fn create_dir_all ( & mut self , path : impl AsRef < Path > ) -> FileSystemResult < ( ) > {
102
- let path = path. as_ref ( ) ;
115
+ todo ! ( )
116
+ /*let path = path.as_ref();
103
117
104
118
let normalized_path = NormalizedPath::new("\\", path)?;
105
119
let normalized_path_string = normalized_path.to_string();
@@ -115,19 +129,21 @@ impl<'a> FileSystem<'a> {
115
129
info!("path_acc: {path_acc}, component: {component}");
116
130
Some((component, path_acc.clone()))
117
131
})
118
- . try_for_each ( |( _component, full_path) | self . create_dir ( full_path. as_str ( ) ) )
132
+ .try_for_each(|(_component, full_path)| self.create_dir(full_path.to_cstr16 ()))*/
119
133
}
120
134
121
135
/// Given a path, query the file system to get information about a file,
122
136
/// directory, etc. Returns [`UefiFileInfo`].
123
137
pub fn metadata ( & mut self , path : impl AsRef < Path > ) -> FileSystemResult < Box < UefiFileInfo > > {
124
138
let path = path. as_ref ( ) ;
125
139
let file = self . open ( path, UefiFileMode :: Read , false ) ?;
126
- log:: debug!( "{:#?}" , & file. into_type( ) . unwrap( ) ) ;
127
140
let mut file = self . open ( path, UefiFileMode :: Read , false ) ?;
128
141
file. get_boxed_info ( ) . map_err ( |err| {
129
142
log:: debug!( "failed to fetch file info: {err:#?}" ) ;
130
- FileSystemError :: OpenError ( path. to_string ( ) )
143
+ FileSystemError :: OpenError {
144
+ path : path. to_cstr16 ( ) . to_string ( ) ,
145
+ error : err
146
+ }
131
147
} )
132
148
}
133
149
@@ -138,10 +154,12 @@ impl<'a> FileSystem<'a> {
138
154
let mut file = self
139
155
. open ( path, UefiFileMode :: Read , false ) ?
140
156
. into_regular_file ( )
141
- . ok_or ( FileSystemError :: NotAFile ( path. as_str ( ) . to_string ( ) ) ) ?;
142
- let info = file. get_boxed_info :: < FileInfo > ( ) . map_err ( |e| {
143
- log:: error!( "get info failed: {e:?}" ) ;
144
- FileSystemError :: OpenError ( path. as_str ( ) . to_string ( ) )
157
+ . ok_or ( FileSystemError :: NotAFile ( path. to_cstr16 ( ) . to_string ( ) ) ) ?;
158
+ let info = file. get_boxed_info :: < FileInfo > ( ) . map_err ( |err| {
159
+ FileSystemError :: OpenError {
160
+ path : path. to_cstr16 ( ) . to_string ( ) ,
161
+ error : err
162
+ }
145
163
} ) ?;
146
164
147
165
let mut vec = vec ! [ 0 ; info. file_size( ) as usize ] ;
@@ -164,7 +182,7 @@ impl<'a> FileSystem<'a> {
164
182
let dir = self
165
183
. open ( path, UefiFileMode :: Read , false ) ?
166
184
. into_directory ( )
167
- . ok_or ( FileSystemError :: NotADirectory ( path. as_str ( ) . to_string ( ) ) ) ?;
185
+ . ok_or ( FileSystemError :: NotADirectory ( path. to_cstr16 ( ) . to_string ( ) ) ) ?;
168
186
Ok ( UefiDirectoryIter :: new ( dir) )
169
187
}
170
188
@@ -185,9 +203,9 @@ impl<'a> FileSystem<'a> {
185
203
match file {
186
204
FileType :: Dir ( dir) => dir. delete ( ) . map_err ( |e| {
187
205
log:: error!( "error removing dir: {e:?}" ) ;
188
- FileSystemError :: CantDeleteDirectory ( path. as_str ( ) . to_string ( ) )
206
+ FileSystemError :: CantDeleteDirectory ( path. to_cstr16 ( ) . to_string ( ) )
189
207
} ) ,
190
- FileType :: Regular ( _) => Err ( FileSystemError :: NotADirectory ( path. as_str ( ) . to_string ( ) ) ) ,
208
+ FileType :: Regular ( _) => Err ( FileSystemError :: NotADirectory ( path. to_cstr16 ( ) . to_string ( ) ) ) ,
191
209
}
192
210
}
193
211
@@ -209,9 +227,9 @@ impl<'a> FileSystem<'a> {
209
227
match file {
210
228
FileType :: Regular ( file) => file. delete ( ) . map_err ( |e| {
211
229
log:: error!( "error removing file: {e:?}" ) ;
212
- FileSystemError :: CantDeleteFile ( path. as_str ( ) . to_string ( ) )
230
+ FileSystemError :: CantDeleteFile ( path. to_cstr16 ( ) . to_string ( ) )
213
231
} ) ,
214
- FileType :: Dir ( _) => Err ( FileSystemError :: NotAFile ( path. as_str ( ) . to_string ( ) ) ) ,
232
+ FileType :: Dir ( _) => Err ( FileSystemError :: NotAFile ( path. to_cstr16 ( ) . to_string ( ) ) ) ,
215
233
}
216
234
}
217
235
@@ -278,19 +296,24 @@ impl<'a> FileSystem<'a> {
278
296
mode : UefiFileMode ,
279
297
is_dir : bool ,
280
298
) -> FileSystemResult < UefiFileHandle > {
281
- let path = NormalizedPath :: new ( " \\ " , path) ?;
282
- log:: debug !( "normalized path: {path}" ) ;
299
+ validate_path ( path) ?;
300
+ log:: trace !( "open validated path: {path}" ) ;
283
301
284
302
let attr = if mode == UefiFileMode :: CreateReadWrite && is_dir {
285
303
FileAttribute :: DIRECTORY
286
304
} else {
287
305
FileAttribute :: empty ( )
288
306
} ;
289
307
290
- self . open_root ( ) ?. open ( & path, mode, attr) . map_err ( |x| {
291
- log:: trace!( "Can't open file {path}: {x:?}" ) ;
292
- FileSystemError :: OpenError ( path. to_string ( ) )
293
- } )
308
+ self . open_root ( ) ?
309
+ . open ( path. to_cstr16 ( ) , mode, attr)
310
+ . map_err ( |err| {
311
+ log:: trace!( "Can't open file {path}: {err:?}" ) ;
312
+ FileSystemError :: OpenError {
313
+ path : path. to_cstr16 ( ) . to_string ( ) ,
314
+ error : err
315
+ }
316
+ } )
294
317
}
295
318
}
296
319
0 commit comments