abi_definitions/file_system/
file.rs1use core::ffi::c_char;
3use file_system::{
4 AccessFlags, CreateFlags, Flags, Kind, Permissions, StateFlags, Statistics, Time,
5 character_device,
6};
7use shared::generate_shadow_type;
8use users::{GroupIdentifier, UserIdentifier};
9use virtual_file_system::{Error, SynchronousFile, get_instance as get_file_system_instance};
10
11use crate::{
12 XilaFileSystemPollEvent, XilaFileSystemState, XilaTaskIdentifier, XilaTime,
13 abi_unsafe_function, file_system::into_position, parse_c_str,
14};
15
16use super::{
17 XilaFileSystemAccess, XilaFileSystemOpen, XilaFileSystemSize, XilaFileSystemStatistics,
18 XilaFileSystemWhence,
19};
20
21generate_shadow_type!(XilaFileSystemFile, SynchronousFile);
22
23abi_unsafe_function! {
24 fn xila_file_system_file_get_statistics(
32 file: *mut XilaFileSystemFile,
33 statistics: *mut XilaFileSystemStatistics,
34 ) -> XilaFileSystemResult {
35 log::debug!("Getting statistics for file {file:?}");
36
37 let result = match (*file).get_statistics() {
38 Ok(statistics) => statistics,
39 Err(Error::UnsupportedOperation)
43 | Err(Error::FileSystem(file_system::Error::UnsupportedOperation)) => {
44 log::warning!(
45 "File system does not support getting statistics for file {file:?}, returning synthetic character device metadata"
46 );
47 Statistics::new(
48 0,
49 1,
50 0,
51 Time::new(0),
52 Time::new(0),
53 Time::new(0),
54 Time::new(0),
55 Kind::CharacterDevice,
56 Permissions::DEVICE_DEFAULT,
57 UserIdentifier::ROOT,
58 GroupIdentifier::ROOT,
59 )
60 }
61 Err(error) => return Err(error),
62 };
63
64 *statistics = XilaFileSystemStatistics::from_statistics(result);
65 Ok(())
66 }
67}
68
69abi_unsafe_function! {
70 fn xila_file_system_file_get_access_flags(
80 file: *mut XilaFileSystemFile,
81 mode: *mut XilaFileSystemAccess,
82 ) -> XilaFileSystemResult {
83 let m = (*file).get_access()?;
84 mode.write(m.bits());
85 Ok(())
86 }
87}
88
89abi_unsafe_function! {
90 fn xila_file_system_file_close(
99 file: *mut XilaFileSystemFile,
100 ) -> XilaFileSystemResult {
101 log::information!("Closing file {file:?}");
102 (*file).close_internal(get_file_system_instance())
103 }
104}
105
106abi_unsafe_function! {
107 fn xila_file_system_file_write(
117 file: *mut XilaFileSystemFile,
118 buffers: *const *const u8,
119 buffers_length: *const usize,
120 buffer_count: usize,
121 written: *mut usize,
122 ) -> XilaFileSystemResult {
123 let buffers = core::slice::from_raw_parts(buffers, buffer_count);
124 let buffers_length = core::slice::from_raw_parts(buffers_length, buffer_count);
125
126 let mut current_written = 0;
127
128 for (buffer, length) in buffers.iter().zip(buffers_length.iter()) {
129 let buffer_slice = core::slice::from_raw_parts(*buffer, *length);
130 current_written += (*file).write(buffer_slice)?;
131 }
132
133 if !written.is_null() {
134 *written = current_written;
135 }
136 Ok(())
137 }
138}
139
140abi_unsafe_function! {
141 fn xila_file_system_file_read(
151 file: *mut XilaFileSystemFile,
152 buffers: *const *mut u8,
153 buffers_length: *const usize,
154 buffer_count: usize,
155 read: *mut usize,
156 ) -> XilaFileSystemResult {
157 let buffers = core::slice::from_raw_parts(buffers, buffer_count);
158 let buffers_length = core::slice::from_raw_parts(buffers_length, buffer_count);
159
160 let mut current_read = 0;
161
162 for (buffer_pointer, buffer_length) in buffers.iter().zip(buffers_length.iter()) {
163 let buffer = core::slice::from_raw_parts_mut(*buffer_pointer, *buffer_length);
164 let read_count = (*file).read(buffer)?;
165 current_read += read_count;
166 }
167
168 if !read.is_null() {
169 *read = current_read;
170 }
171 Ok(())
172 }
173}
174
175abi_unsafe_function! {
176 fn xila_file_system_file_read_at(
182 file: *mut XilaFileSystemFile,
183 position: u64,
184 buffers: *const *mut u8,
185 buffers_length: *const usize,
186 buffer_count: usize,
187 read: *mut usize,
188 ) -> XilaFileSystemResult {
189 let buffers = core::slice::from_raw_parts(buffers, buffer_count);
190 let buffers_length = core::slice::from_raw_parts(buffers_length, buffer_count);
191
192 (*file).set_position(&file_system::Position::Start(position))?;
193
194 let mut current_read = 0;
195
196 for (buffer_pointer, buffer_length) in buffers.iter().zip(buffers_length.iter()) {
197 let buffer = core::slice::from_raw_parts_mut(*buffer_pointer, *buffer_length);
198 let read_count = (*file).read(buffer)?;
199 current_read += read_count;
200 }
201
202 if !read.is_null() {
203 *read = current_read;
204 }
205 Ok(())
206 }
207}
208
209abi_unsafe_function! {
210 fn xila_file_system_file_write_at(
216 file: *mut XilaFileSystemFile,
217 position: u64,
218 buffers: *const *const u8,
219 buffers_length: *const usize,
220 buffer_count: usize,
221 written: *mut usize,
222 ) -> XilaFileSystemResult {
223 let buffers = core::slice::from_raw_parts(buffers, buffer_count);
224 let buffers_length = core::slice::from_raw_parts(buffers_length, buffer_count);
225
226 (*file).set_position(&file_system::Position::Start(position))?;
227
228 let mut current_written = 0;
229
230 for (buffer, length) in buffers.iter().zip(buffers_length.iter()) {
231 let buffer_slice = core::slice::from_raw_parts(*buffer, *length);
232 current_written += (*file).write(buffer_slice)?;
233 }
234
235 if !written.is_null() {
236 *written = current_written;
237 }
238 Ok(())
239 }
240}
241
242abi_unsafe_function! {
243 fn xila_file_system_file_is_a_terminal(
253 file: *mut XilaFileSystemFile,
254 is_a_terminal: *mut bool,
255 ) -> XilaFileSystemResult {
256 *is_a_terminal = match (*file).control(character_device::IS_A_TERMINAL, &()) {
257 Ok(result) => result,
258 Err(Error::UnsupportedOperation) => false,
259 Err(_) => false,
260 };
261 Ok(())
262 }
263}
264
265abi_unsafe_function! {
266 fn xila_file_system_file_open(
272 task: XilaTaskIdentifier,
273 path: *const c_char,
274 mode: XilaFileSystemAccess,
275 open: XilaFileSystemOpen,
276 status: XilaFileSystemState,
277 file: *mut XilaFileSystemFile,
278 ) -> XilaFileSystemResult {
279 log::information!("Opening file at path {:?} with mode {:?}, open {:?} and status {:?}",
280 unsafe { parse_c_str(path) },
281 mode,
282 open,
283 status
284 );
285
286 let path = parse_c_str(path)?;
287
288 let mode = AccessFlags::from_bits_truncate(mode);
289 let open = CreateFlags::from_bits_truncate(open);
290 let status = StateFlags::from_bits_truncate(status);
291
292 let flags = Flags::new(mode, Some(open), Some(status));
293
294 log::information!("Resolved flags: {:?}", flags);
295
296 let f = SynchronousFile::open(get_file_system_instance(), task.into(), path, flags)?;
297
298 log::information!("Successfully opened file at path {:?} with mode {:?}, open {:?} and status {:?}",
299 path,
300 mode,
301 open,
302 status
303 );
304
305 unsafe {
306 let target_slot = file as *mut SynchronousFile;
307 ::core::ptr::write(target_slot, f);
308 }
309
310 Ok(())
311 }
312}
313
314abi_unsafe_function! {
315 fn xila_file_system_file_set_flags(
320 _file: *mut XilaFileSystemFile,
321 _state: XilaFileSystemState,
322 ) -> XilaFileSystemResult {
323 todo!()
324 }
325}
326
327abi_unsafe_function! {
328 fn xila_file_system_file_get_state(
334 file: *mut XilaFileSystemFile,
335 state: *mut XilaFileSystemState,
336 ) -> XilaFileSystemResult {
337 let s = (*file).get_state()?;
338 state.write(s.bits());
339 Ok(())
340 }
341}
342
343abi_unsafe_function! {
344 fn xila_file_system_file_flush(
349 file: *mut XilaFileSystemFile,
350 _t: bool,
351 ) -> XilaFileSystemResult {
352 (*file).flush()
353 }
354}
355
356abi_unsafe_function! {
357 fn xila_file_system_file_set_position(
363 file: *mut XilaFileSystemFile,
364 offset: i64,
365 whence: XilaFileSystemWhence,
366 position: *mut XilaFileSystemSize,
367 ) -> XilaFileSystemResult {
368 let current_position = into_position(whence, offset);
369
370 let result = (*file).set_position(¤t_position)?;
372 *position = result;
373 Ok(())
374 }
375}
376
377abi_unsafe_function! {
378 fn xila_file_system_set_times(
383 _file: *mut XilaFileSystemFile,
384 _access: XilaTime,
385 _modification: XilaTime,
386 _flags: u8,
387 ) -> XilaFileSystemResult {
388 todo!()
389 }
390}
391
392abi_unsafe_function! {
393 fn xila_file_system_set_times_from_path(
399 _path: *const c_char,
400 _access: XilaTime,
401 _modification: XilaTime,
402 _flags: u8,
403 _follow: bool,
404 ) -> XilaFileSystemResult {
405 todo!()
406 }
407}
408
409abi_unsafe_function! {
410 fn xila_file_system_truncate(
415 _file: *mut XilaFileSystemFile,
416 _length: XilaFileSystemSize,
417 ) -> XilaFileSystemResult {
418 todo!()
419 }
420}
421
422abi_unsafe_function! {
423 fn xila_file_system_link(
429 _path: *const c_char,
430 _link: *const c_char,
431 ) -> XilaFileSystemResult {
432 todo!()
433 }
434}
435
436abi_unsafe_function! {
437 fn xila_file_system_file_advise(
442 _file: *mut XilaFileSystemFile,
443 _offset: XilaFileSystemSize,
444 _length: XilaFileSystemSize,
445 _advice: u8,
446 ) -> XilaFileSystemResult {
447 todo!()
448 }
449}
450
451abi_unsafe_function! {
452 fn xila_file_system_file_allocate(
457 _file: *mut XilaFileSystemFile,
458 _offset: XilaFileSystemSize,
459 _length: XilaFileSystemSize,
460 ) -> XilaFileSystemResult {
461 todo!()
462 }
463}
464
465abi_unsafe_function! {
466 fn xila_file_system_file_truncate(
471 _file: *mut XilaFileSystemFile,
472 _length: XilaFileSystemSize,
473 ) -> XilaFileSystemResult {
474 todo!()
475 }
476}
477
478abi_unsafe_function! {
479 fn xila_file_system_dummy(_event: XilaFileSystemPollEvent) -> XilaFileSystemResult {
484 Ok(())
485 }
486}