1use core::{
3 cmp::min,
4 ffi::{CStr, c_char},
5 num::NonZeroU32,
6 ptr::copy_nonoverlapping,
7};
8
9use futures::block_on;
10
11use file_system::{Error, FileIdentifier, Flags, Mode, Open, Status};
12use virtual_file_system::get_instance as get_file_system_instance;
13
14use crate::{XilaTime, context, into_position};
15
16use super::{
17 XilaFileSystemMode, XilaFileSystemOpen, XilaFileSystemResult, XilaFileSystemSize,
18 XilaFileSystemStatistics, XilaFileSystemStatus, XilaFileSystemWhence, XilaUniqueFileIdentifier,
19};
20
21pub fn into_u32<F>(function: F) -> XilaFileSystemResult
23where
24 F: FnOnce() -> Result<(), NonZeroU32>,
25{
26 match function() {
27 Ok(()) => 0,
28 Err(error) => error.get(),
29 }
30}
31
32#[unsafe(no_mangle)]
42pub unsafe extern "C" fn xila_file_system_get_statistics(
43 file: XilaUniqueFileIdentifier,
44 statistics: *mut XilaFileSystemStatistics,
45) -> XilaFileSystemResult {
46 unsafe {
47 into_u32(move || {
48 let task_identifier = context::get_instance().get_current_task_identifier();
49
50 let statistics = XilaFileSystemStatistics::from_mutable_pointer(statistics)
51 .ok_or(Error::InvalidParameter)?;
52
53 let file = file_system::UniqueFileIdentifier::from_raw(file);
54
55 *statistics = XilaFileSystemStatistics::from_statistics(
56 block_on(get_file_system_instance().get_statistics(file, task_identifier))
57 .expect("Failed to get file statistics."),
58 );
59
60 Ok(())
61 })
62 }
63}
64
65#[unsafe(no_mangle)]
71pub unsafe extern "C" fn xila_file_system_get_statistics_from_path(
72 path: *const c_char,
73 statistics: *mut XilaFileSystemStatistics,
74 _: bool,
75) -> XilaFileSystemResult {
76 unsafe {
77 into_u32(move || {
78 let path = CStr::from_ptr(path)
79 .to_str()
80 .map_err(|_| Error::InvalidParameter)?;
81
82 let statistics = XilaFileSystemStatistics::from_mutable_pointer(statistics)
83 .ok_or(Error::InvalidParameter)?;
84
85 *statistics = XilaFileSystemStatistics::from_statistics(block_on(
86 get_file_system_instance().get_statistics_from_path(&path),
87 )?);
88
89 Ok(())
90 })
91 }
92}
93
94#[unsafe(no_mangle)]
104pub unsafe extern "C" fn xila_file_system_get_access_mode(
105 file: XilaUniqueFileIdentifier,
106 mode: *mut XilaFileSystemMode,
107) -> XilaFileSystemResult {
108 unsafe {
109 into_u32(move || {
112 let task_identifier = context::get_instance().get_current_task_identifier();
113
114 if mode.is_null() {
115 Err(Error::InvalidParameter)?;
116 }
117
118 let file = file_system::UniqueFileIdentifier::from_raw(file);
119
120 mode.write(
121 block_on(get_file_system_instance().get_mode(file, task_identifier))?.as_u8(),
122 );
123
124 Ok(())
125 })
126 }
127}
128
129#[unsafe(no_mangle)]
136pub extern "C" fn xila_file_system_close(file: XilaUniqueFileIdentifier) -> XilaFileSystemResult {
137 into_u32(move || {
138 let task_identifier = context::get_instance().get_current_task_identifier();
139
140 let file = file_system::UniqueFileIdentifier::from_raw(file);
141
142 block_on(get_file_system_instance().close(file, task_identifier))?;
143
144 Ok(())
145 })
146}
147
148#[unsafe(no_mangle)]
160pub unsafe extern "C" fn xila_file_system_write_vectored(
161 file: XilaUniqueFileIdentifier,
162 buffers: *const *const u8,
163 buffers_length: *const usize,
164 buffer_count: usize,
165 written: *mut usize,
166) -> XilaFileSystemResult {
167 unsafe {
168 into_u32(move || {
169 let task_identifier = context::get_instance().get_current_task_identifier();
170
171 let buffers = core::slice::from_raw_parts(buffers, buffer_count);
172 let buffers_length = core::slice::from_raw_parts(buffers_length, buffer_count);
173
174 let mut current_written = 0;
175
176 let file = file_system::UniqueFileIdentifier::from_raw(file);
177
178 for (buffer, length) in buffers.iter().zip(buffers_length.iter()) {
179 let buffer_slice = core::slice::from_raw_parts(*buffer, *length);
180
181 current_written += usize::from(block_on(get_file_system_instance().write(
182 file,
183 buffer_slice,
184 task_identifier,
185 ))?);
186 }
187
188 if !written.is_null() {
189 *written = current_written;
190 }
191
192 Ok(())
193 })
194 }
195}
196
197#[unsafe(no_mangle)]
207pub unsafe extern "C" fn xila_file_system_read_vectored(
208 file: XilaUniqueFileIdentifier,
209 buffers: *mut *mut u8,
210 buffers_length: *mut usize,
211 buffer_count: usize,
212 read: *mut usize,
213) -> XilaFileSystemResult {
214 unsafe {
215 into_u32(move || {
216 let task_identifier = context::get_instance().get_current_task_identifier();
217
218 let buffers = core::slice::from_raw_parts_mut(buffers, buffer_count);
219 let buffers_length = core::slice::from_raw_parts_mut(buffers_length, buffer_count);
220
221 let mut current_read = 0;
222
223 let file = file_system::UniqueFileIdentifier::from_raw(file);
224
225 for (buffer_pointer, buffer_length) in buffers.iter_mut().zip(buffers_length.iter_mut())
226 {
227 let buffer = core::slice::from_raw_parts_mut(*buffer_pointer, *buffer_length);
228
229 let read =
230 block_on(get_file_system_instance().read(file, buffer, task_identifier))?;
231
232 current_read += usize::from(read);
233 }
234
235 if !read.is_null() {
236 *read = current_read;
237 }
238
239 Ok(())
240 })
241 }
242}
243
244#[unsafe(no_mangle)]
250pub unsafe extern "C" fn xila_file_system_read_at_position_vectored(
251 file: XilaUniqueFileIdentifier,
252 buffers: *mut *mut u8,
253 buffers_length: *mut usize,
254 buffer_count: usize,
255 position: u64,
256 read: *mut usize,
257) -> XilaFileSystemResult {
258 unsafe {
259 into_u32(move || {
260 let task_identifier = context::get_instance().get_current_task_identifier();
261
262 let buffers = core::slice::from_raw_parts_mut(buffers, buffer_count);
263 let buffers_length = core::slice::from_raw_parts_mut(buffers_length, buffer_count);
264
265 let mut current_read = 0;
266
267 let file: file_system::UniqueFileIdentifier =
268 file_system::UniqueFileIdentifier::from_raw(file);
269
270 block_on(get_file_system_instance().set_position(
271 file,
272 &file_system::Position::Start(position),
273 task_identifier,
274 ))?;
275
276 for (buffer_pointer, buffer_length) in buffers.iter_mut().zip(buffers_length.iter_mut())
277 {
278 let buffer = core::slice::from_raw_parts_mut(*buffer_pointer, *buffer_length);
279
280 let read =
281 block_on(get_file_system_instance().read(file, buffer, task_identifier))?;
282
283 current_read += usize::from(read);
284 }
285
286 if !read.is_null() {
287 *read = current_read;
288 }
289
290 Ok(())
291 })
292 }
293}
294
295#[unsafe(no_mangle)]
301pub unsafe extern "C" fn xila_file_system_write_at_position_vectored(
302 file: XilaUniqueFileIdentifier,
303 buffers: *const *const u8,
304 buffers_length: *const usize,
305 buffer_count: usize,
306 position: u64,
307 written: *mut usize,
308) -> XilaFileSystemResult {
309 unsafe {
310 into_u32(move || {
311 let task_identifier = context::get_instance().get_current_task_identifier();
312
313 let buffers = core::slice::from_raw_parts(buffers, buffer_count);
314 let buffers_length = core::slice::from_raw_parts(buffers_length, buffer_count);
315
316 let mut current_written = 0;
317
318 let file: file_system::UniqueFileIdentifier =
319 file_system::UniqueFileIdentifier::from_raw(file);
320
321 block_on(get_file_system_instance().set_position(
322 file,
323 &file_system::Position::Start(position),
324 task_identifier,
325 ))?;
326
327 for (buffer, length) in buffers.iter().zip(buffers_length.iter()) {
328 let buffer_slice = core::slice::from_raw_parts(*buffer, *length);
329
330 current_written += usize::from(block_on(get_file_system_instance().write(
331 file,
332 buffer_slice,
333 task_identifier,
334 ))?);
335 }
336
337 if !written.is_null() {
338 *written = current_written;
339 }
340
341 Ok(())
342 })
343 }
344}
345
346#[unsafe(no_mangle)]
356pub unsafe extern "C" fn xila_file_system_is_a_terminal(
357 file: XilaUniqueFileIdentifier,
358 is_a_terminal: *mut bool,
359) -> XilaFileSystemResult {
360 unsafe {
361 into_u32(move || {
362 let task_identifier = context::get_instance().get_current_task_identifier();
363
364 if is_a_terminal.is_null() {
365 Err(Error::InvalidParameter)?;
366 }
367
368 let file = file_system::UniqueFileIdentifier::from_raw(file);
369
370 *is_a_terminal =
371 block_on(get_file_system_instance().is_a_terminal(file, task_identifier))?;
372
373 Ok(())
374 })
375 }
376}
377
378#[unsafe(no_mangle)]
379pub extern "C" fn xila_file_system_is_stdin(file: XilaUniqueFileIdentifier) -> bool {
380 let file = file_system::UniqueFileIdentifier::from_raw(file);
381
382 let (_, file) = file.split();
383
384 file == FileIdentifier::STANDARD_IN
387}
388
389#[unsafe(no_mangle)]
390pub extern "C" fn xila_file_system_is_stderr(file: XilaUniqueFileIdentifier) -> bool {
391 let file = file_system::UniqueFileIdentifier::from_raw(file);
392
393 let (_, file) = file.split();
394
395 file == FileIdentifier::STANDARD_ERROR
398}
399
400#[unsafe(no_mangle)]
401pub extern "C" fn xila_file_system_is_stdout(file: XilaUniqueFileIdentifier) -> bool {
402 let file = file_system::UniqueFileIdentifier::from_raw(file);
403
404 let (_, file) = file.split();
405
406 file == FileIdentifier::STANDARD_OUT
409}
410
411#[unsafe(no_mangle)]
417pub unsafe extern "C" fn xila_file_system_open(
418 path: *const c_char,
419 mode: XilaFileSystemMode,
420 open: XilaFileSystemOpen,
421 status: XilaFileSystemStatus,
422 file: *mut XilaUniqueFileIdentifier,
423) -> XilaFileSystemResult {
424 unsafe {
425 into_u32(move || {
426 let path = core::ffi::CStr::from_ptr(path)
427 .to_str()
428 .map_err(|_| Error::InvalidParameter)?;
429
430 let mode = Mode::from_u8(mode);
431 let open = Open::from_u8(open);
432 let status = Status::from_u8(status);
433
434 let flags = Flags::new(mode, Some(open), Some(status));
435
436 let task = context::get_instance().get_current_task_identifier();
439
440 *file = block_on(get_file_system_instance().open(&path, flags, task))
441 .expect("Failed to open file")
442 .into_inner();
443
444 Ok(())
445 })
446 }
447}
448
449#[unsafe(no_mangle)]
450pub extern "C" fn xila_file_system_set_flags(
451 _file: XilaUniqueFileIdentifier,
452 _status: XilaFileSystemStatus,
453) -> XilaFileSystemResult {
454 todo!()
455}
456
457#[unsafe(no_mangle)]
463pub unsafe extern "C" fn xila_file_system_get_flags(
464 _file: XilaUniqueFileIdentifier,
465 _status: *mut XilaFileSystemStatus,
466) -> XilaFileSystemResult {
467 todo!()
468}
469
470#[unsafe(no_mangle)]
476pub unsafe extern "C" fn xila_file_system_resolve_path(
477 path: *const i8,
478 resolved_path: *mut u8,
479 resolved_path_size: usize,
480) -> XilaFileSystemResult {
481 unsafe {
482 into_u32(move || {
483 let path = core::ffi::CStr::from_ptr(path)
484 .to_str()
485 .map_err(|_| Error::InvalidParameter)?;
486
487 copy_nonoverlapping(
491 path.as_ptr(),
492 resolved_path,
493 min(resolved_path_size, path.len()),
494 );
495
496 Ok(())
497 })
498 }
499}
500
501#[unsafe(no_mangle)]
502pub extern "C" fn xila_file_system_flush(
503 file: XilaUniqueFileIdentifier,
504 _: bool,
505) -> XilaFileSystemResult {
506 into_u32(move || {
507 let task = context::get_instance().get_current_task_identifier();
508
509 let file = file_system::UniqueFileIdentifier::from_raw(file);
510
511 block_on(get_file_system_instance().flush(file, task))?;
512
513 Ok(())
514 })
515}
516
517#[unsafe(no_mangle)]
518pub extern "C" fn xila_file_system_create_symbolic_link_at(
519 _: XilaUniqueFileIdentifier,
520 _: *const c_char,
521 _: *const c_char,
522) -> XilaFileSystemResult {
523 todo!()
524}
525
526#[unsafe(no_mangle)]
527pub extern "C" fn xila_file_system_read_link_at(
528 _directory: XilaUniqueFileIdentifier,
529 _path: *mut i8,
530 _size: usize,
531 _used: *mut usize,
532) -> XilaFileSystemResult {
533 todo!()
534}
535
536#[unsafe(no_mangle)]
542pub unsafe extern "C" fn xila_file_system_set_position(
543 file: XilaUniqueFileIdentifier,
544 offset: i64,
545 whence: XilaFileSystemWhence,
546 position: *mut XilaFileSystemSize,
547) -> XilaFileSystemResult {
548 unsafe {
549 into_u32(move || {
550 let task = context::get_instance().get_current_task_identifier();
551 let current_position = into_position(whence, offset);
552
553 let file = file_system::UniqueFileIdentifier::from_raw(file);
556
557 *position =
558 block_on(get_file_system_instance().set_position(file, ¤t_position, task))?
559 .as_u64();
560
561 Ok(())
562 })
563 }
564}
565
566#[unsafe(no_mangle)]
572pub unsafe extern "C" fn xila_file_system_create_directory(
573 path: *const c_char,
574) -> XilaFileSystemResult {
575 unsafe {
576 into_u32(move || {
577 let path = CStr::from_ptr(path)
578 .to_str()
579 .map_err(|_| Error::InvalidParameter)?;
580
581 let task = context::get_instance().get_current_task_identifier();
584 block_on(get_file_system_instance().create_directory(&path, task))?;
585
586 Ok(())
587 })
588 }
589}
590
591#[unsafe(no_mangle)]
597pub unsafe extern "C" fn xila_file_system_rename(
598 old_path: *const c_char,
599 new_path: *const c_char,
600) -> XilaFileSystemResult {
601 unsafe {
602 into_u32(move || {
603 let old_path = CStr::from_ptr(old_path)
604 .to_str()
605 .map_err(|_| Error::InvalidParameter)?;
606
607 let new_path = CStr::from_ptr(new_path)
608 .to_str()
609 .map_err(|_| Error::InvalidParameter)?;
610
611 block_on(get_file_system_instance().rename(&old_path, &new_path))?;
614
615 Ok(())
616 })
617 }
618}
619
620#[unsafe(no_mangle)]
621pub extern "C" fn xila_file_system_set_times(
622 _: XilaUniqueFileIdentifier,
623 _: XilaTime,
624 _: XilaTime,
625 _: u8,
626) -> XilaFileSystemResult {
627 todo!()
628}
629
630#[unsafe(no_mangle)]
636pub unsafe extern "C" fn xila_file_system_set_times_from_path(
637 _path: *const c_char,
638 _access: XilaTime,
639 _modification: XilaTime,
640 _flags: u8,
641 _follow: bool,
642) -> XilaFileSystemResult {
643 todo!()
644}
645
646#[unsafe(no_mangle)]
652pub unsafe extern "C" fn xila_file_system_remove(_path: *const c_char) -> XilaFileSystemResult {
653 unsafe {
654 into_u32(|| {
655 let path = CStr::from_ptr(_path)
656 .to_str()
657 .map_err(|_| Error::InvalidParameter)?;
658
659 block_on(get_file_system_instance().remove(path))?;
660
661 Ok(())
662 })
663 }
664}
665
666#[unsafe(no_mangle)]
668pub extern "C" fn xila_file_system_truncate(
669 _file: XilaUniqueFileIdentifier,
670 _length: XilaFileSystemSize,
671) -> XilaFileSystemResult {
672 into_u32(move || {
673 let _task = context::get_instance().get_current_task_identifier();
674
675 let _file = file_system::UniqueFileIdentifier::from_raw(_file);
676
677 todo!();
678 })
679}
680
681#[unsafe(no_mangle)]
687pub unsafe extern "C" fn xila_file_system_link(
688 _path: *const c_char,
689 _link: *const c_char,
690) -> XilaFileSystemResult {
691 todo!()
692}
693
694#[unsafe(no_mangle)]
696pub extern "C" fn xila_file_system_advise(
697 _file: XilaUniqueFileIdentifier,
698 _offset: XilaFileSystemSize,
699 _length: XilaFileSystemSize,
700 _advice: u8,
701) -> XilaFileSystemResult {
702 todo!()
703}
704
705#[unsafe(no_mangle)]
706pub extern "C" fn xila_file_system_allocate(
707 _file: XilaUniqueFileIdentifier,
708 _offset: XilaFileSystemSize,
709 _length: XilaFileSystemSize,
710) -> XilaFileSystemResult {
711 todo!()
712}