1
1
//! Module for [`FileSystem`].
2
2
3
- use super :: super :: * ;
4
- use crate :: fs:: path:: { validate_path, PathError } ;
5
- use crate :: proto:: media:: file:: { FileAttribute , FileInfo , FileType } ;
3
+ use crate :: fs:: * ;
4
+ use crate :: fs:: { Path , PathBuf , UefiDirectoryIter , SEPARATOR_STR } ;
6
5
use crate :: table:: boot:: ScopedProtocol ;
7
6
use alloc:: boxed:: Box ;
8
- use alloc:: string:: { FromUtf8Error , String , ToString } ;
7
+ use alloc:: string:: String ;
9
8
use alloc:: vec;
10
9
use alloc:: vec:: Vec ;
11
10
use core:: fmt;
12
11
use core:: fmt:: { Debug , Formatter } ;
13
12
use core:: ops:: Deref ;
14
- use derive_more:: Display ;
15
13
use log:: debug;
16
14
17
- /// All errors that can happen when working with the [`FileSystem`].
18
- #[ derive( Debug , Clone , Display , PartialEq , Eq ) ]
19
- pub enum FileSystemError {
20
- /// Can't open the root directory of the underlying volume.
21
- CantOpenVolume ,
22
- /// The path is invalid because of the underlying [`PathError`].
23
- ///
24
- /// [`PathError`]: path::PathError
25
- IllegalPath ( PathError ) ,
26
- /// The file or directory was not found in the underlying volume.
27
- FileNotFound ( String ) ,
28
- /// The path is existent but does not correspond to a directory when a
29
- /// directory was expected.
30
- NotADirectory ( String ) ,
31
- /// The path is existent but does not correspond to a file when a file was
32
- /// expected.
33
- NotAFile ( String ) ,
34
- /// Can't delete the file.
35
- CantDeleteFile ( String ) ,
36
- /// Can't delete the directory.
37
- CantDeleteDirectory ( String ) ,
38
- /// Error writing bytes.
39
- WriteFailure ,
40
- /// Error flushing file.
41
- FlushFailure ,
42
- /// Error reading file.
43
- ReadFailure ,
44
- /// Can't parse file content as UTF-8.
45
- Utf8Error ( FromUtf8Error ) ,
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 that caused the failure.
51
- path : String ,
52
- /// More detailed failure description.
53
- error : crate :: Error ,
54
- } ,
55
- }
56
-
57
- #[ cfg( feature = "unstable" ) ]
58
- impl core:: error:: Error for FileSystemError {
59
- fn source ( & self ) -> Option < & ( dyn core:: error:: Error + ' static ) > {
60
- match self {
61
- FileSystemError :: IllegalPath ( e) => Some ( e) ,
62
- FileSystemError :: Utf8Error ( e) => Some ( e) ,
63
- FileSystemError :: OpenError { path : _path, error } => Some ( error) ,
64
- _ => None ,
65
- }
66
- }
67
- }
68
-
69
- impl From < PathError > for FileSystemError {
70
- fn from ( err : PathError ) -> Self {
71
- Self :: IllegalPath ( err)
72
- }
73
- }
74
-
75
15
/// Return type for public [`FileSystem`] operations.
76
16
pub type FileSystemResult < T > = Result < T , FileSystemError > ;
77
17
@@ -143,11 +83,11 @@ impl<'a> FileSystem<'a> {
143
83
let path = path. as_ref ( ) ;
144
84
let mut file = self . open ( path, UefiFileMode :: Read , false ) ?;
145
85
file. get_boxed_info ( ) . map_err ( |err| {
146
- log :: trace! ( "failed to fetch file info: {err:#?}" ) ;
147
- FileSystemError :: OpenError {
148
- path : path . to_cstr16 ( ) . to_string ( ) ,
149
- error : err,
150
- }
86
+ FileSystemError :: IO ( FileSystemIOError {
87
+ path : path . to_path_buf ( ) ,
88
+ context : FileSystemIOErrorContext :: Metadata ,
89
+ uefi_error : err,
90
+ } )
151
91
} )
152
92
}
153
93
@@ -158,18 +98,24 @@ impl<'a> FileSystem<'a> {
158
98
let mut file = self
159
99
. open ( path, UefiFileMode :: Read , false ) ?
160
100
. into_regular_file ( )
161
- . ok_or ( FileSystemError :: NotAFile ( path. to_cstr16 ( ) . to_string ( ) ) ) ?;
162
- let info = file
163
- . get_boxed_info :: < FileInfo > ( )
164
- . map_err ( |err| FileSystemError :: OpenError {
165
- path : path. to_cstr16 ( ) . to_string ( ) ,
166
- error : err,
167
- } ) ?;
101
+ . ok_or ( FileSystemError :: Logic ( LogicError :: NotAFile (
102
+ path. to_path_buf ( ) ,
103
+ ) ) ) ?;
104
+ let info = file. get_boxed_info :: < UefiFileInfo > ( ) . map_err ( |err| {
105
+ FileSystemError :: IO ( FileSystemIOError {
106
+ path : path. to_path_buf ( ) ,
107
+ context : FileSystemIOErrorContext :: Metadata ,
108
+ uefi_error : err,
109
+ } )
110
+ } ) ?;
168
111
169
112
let mut vec = vec ! [ 0 ; info. file_size( ) as usize ] ;
170
- let read_bytes = file. read ( vec. as_mut_slice ( ) ) . map_err ( |e| {
171
- log:: error!( "reading failed: {e:?}" ) ;
172
- FileSystemError :: ReadFailure
113
+ let read_bytes = file. read ( vec. as_mut_slice ( ) ) . map_err ( |err| {
114
+ FileSystemError :: IO ( FileSystemIOError {
115
+ path : path. to_path_buf ( ) ,
116
+ context : FileSystemIOErrorContext :: ReadFailure ,
117
+ uefi_error : err. to_err_without_payload ( ) ,
118
+ } )
173
119
} ) ?;
174
120
175
121
// we read the whole file at once!
@@ -186,13 +132,15 @@ impl<'a> FileSystem<'a> {
186
132
let dir = self
187
133
. open ( path, UefiFileMode :: Read , false ) ?
188
134
. into_directory ( )
189
- . ok_or ( FileSystemError :: NotADirectory ( path. to_cstr16 ( ) . to_string ( ) ) ) ?;
135
+ . ok_or ( FileSystemError :: Logic ( LogicError :: NotADirectory (
136
+ path. to_path_buf ( ) ,
137
+ ) ) ) ?;
190
138
Ok ( UefiDirectoryIter :: new ( dir) )
191
139
}
192
140
193
- /// Read the entire contents of a file into a string.
141
+ /// Read the entire contents of a file into a Rust string.
194
142
pub fn read_to_string ( & mut self , path : impl AsRef < Path > ) -> FileSystemResult < String > {
195
- String :: from_utf8 ( self . read ( path) ?) . map_err ( FileSystemError :: Utf8Error )
143
+ String :: from_utf8 ( self . read ( path) ?) . map_err ( FileSystemError :: Utf8Encoding )
196
144
}
197
145
198
146
/// Removes an empty directory.
@@ -205,13 +153,16 @@ impl<'a> FileSystem<'a> {
205
153
. unwrap ( ) ;
206
154
207
155
match file {
208
- FileType :: Dir ( dir) => dir. delete ( ) . map_err ( |e| {
209
- log:: error!( "error removing dir: {e:?}" ) ;
210
- FileSystemError :: CantDeleteDirectory ( path. to_cstr16 ( ) . to_string ( ) )
156
+ UefiFileType :: Dir ( dir) => dir. delete ( ) . map_err ( |err| {
157
+ FileSystemError :: IO ( FileSystemIOError {
158
+ path : path. to_path_buf ( ) ,
159
+ context : FileSystemIOErrorContext :: CantDeleteDirectory ,
160
+ uefi_error : err,
161
+ } )
211
162
} ) ,
212
- FileType :: Regular ( _) => {
213
- Err ( FileSystemError :: NotADirectory ( path. to_cstr16 ( ) . to_string ( ) ) )
214
- }
163
+ UefiFileType :: Regular ( _) => Err ( FileSystemError :: Logic ( LogicError :: NotADirectory (
164
+ path. to_path_buf ( ) ,
165
+ ) ) ) ,
215
166
}
216
167
}
217
168
@@ -231,11 +182,16 @@ impl<'a> FileSystem<'a> {
231
182
. unwrap ( ) ;
232
183
233
184
match file {
234
- FileType :: Regular ( file) => file. delete ( ) . map_err ( |e| {
235
- log:: error!( "error removing file: {e:?}" ) ;
236
- FileSystemError :: CantDeleteFile ( path. to_cstr16 ( ) . to_string ( ) )
185
+ UefiFileType :: Regular ( file) => file. delete ( ) . map_err ( |err| {
186
+ FileSystemError :: IO ( FileSystemIOError {
187
+ path : path. to_path_buf ( ) ,
188
+ context : FileSystemIOErrorContext :: CantDeleteFile ,
189
+ uefi_error : err,
190
+ } )
237
191
} ) ,
238
- FileType :: Dir ( _) => Err ( FileSystemError :: NotAFile ( path. to_cstr16 ( ) . to_string ( ) ) ) ,
192
+ UefiFileType :: Dir ( _) => Err ( FileSystemError :: Logic ( LogicError :: NotAFile (
193
+ path. to_path_buf ( ) ,
194
+ ) ) ) ,
239
195
}
240
196
}
241
197
@@ -271,22 +227,35 @@ impl<'a> FileSystem<'a> {
271
227
. into_regular_file ( )
272
228
. unwrap ( ) ;
273
229
274
- handle. write ( content. as_ref ( ) ) . map_err ( |e| {
275
- log:: error!( "only wrote {e:?} bytes" ) ;
276
- FileSystemError :: WriteFailure
230
+ handle. write ( content. as_ref ( ) ) . map_err ( |err| {
231
+ FileSystemError :: IO ( FileSystemIOError {
232
+ path : path. to_path_buf ( ) ,
233
+ context : FileSystemIOErrorContext :: WriteFailure ,
234
+ uefi_error : err. to_err_without_payload ( ) ,
235
+ } )
277
236
} ) ?;
278
- handle. flush ( ) . map_err ( |e| {
279
- log:: error!( "flush failure: {e:?}" ) ;
280
- FileSystemError :: FlushFailure
237
+ handle. flush ( ) . map_err ( |err| {
238
+ FileSystemError :: IO ( FileSystemIOError {
239
+ path : path. to_path_buf ( ) ,
240
+ context : FileSystemIOErrorContext :: FlushFailure ,
241
+ uefi_error : err,
242
+ } )
281
243
} ) ?;
282
244
Ok ( ( ) )
283
245
}
284
246
285
247
/// Opens a fresh handle to the root directory of the volume.
286
248
fn open_root ( & mut self ) -> FileSystemResult < UefiDirectoryHandle > {
287
- self . 0 . open_volume ( ) . map_err ( |e| {
288
- log:: error!( "Can't open root volume: {e:?}" ) ;
289
- FileSystemError :: CantOpenVolume
249
+ self . 0 . open_volume ( ) . map_err ( |err| {
250
+ FileSystemError :: IO ( FileSystemIOError {
251
+ path : {
252
+ let mut path = PathBuf :: new ( ) ;
253
+ path. push ( SEPARATOR_STR ) ;
254
+ path
255
+ } ,
256
+ context : FileSystemIOErrorContext :: CantOpenVolume ,
257
+ uefi_error : err,
258
+ } )
290
259
} )
291
260
}
292
261
@@ -303,22 +272,22 @@ impl<'a> FileSystem<'a> {
303
272
is_dir : bool ,
304
273
) -> FileSystemResult < UefiFileHandle > {
305
274
validate_path ( path) ?;
306
- log:: trace!( "open validated path: {path}" ) ;
307
275
308
276
let attr = if mode == UefiFileMode :: CreateReadWrite && is_dir {
309
- FileAttribute :: DIRECTORY
277
+ UefiFileAttribute :: DIRECTORY
310
278
} else {
311
- FileAttribute :: empty ( )
279
+ UefiFileAttribute :: empty ( )
312
280
} ;
313
281
314
282
self . open_root ( ) ?
315
283
. open ( path. to_cstr16 ( ) , mode, attr)
316
284
. map_err ( |err| {
317
285
log:: trace!( "Can't open file {path}: {err:?}" ) ;
318
- FileSystemError :: OpenError {
319
- path : path. to_cstr16 ( ) . to_string ( ) ,
320
- error : err,
321
- }
286
+ FileSystemError :: IO ( FileSystemIOError {
287
+ path : path. to_path_buf ( ) ,
288
+ context : FileSystemIOErrorContext :: OpenError ,
289
+ uefi_error : err,
290
+ } )
322
291
} )
323
292
}
324
293
}
0 commit comments