1use alloc::borrow::ToOwned;
2use alloc::string::{String, ToString};
3use alloc::vec;
4use alloc::vec::Vec;
5use futures::yield_now;
6use synchronization::{
7 blocking_mutex::raw::CriticalSectionRawMutex, once_lock::OnceLock, rwlock::RwLock,
8};
9
10use alloc::{boxed::Box, collections::BTreeMap};
11
12use network::{IP, Port, Protocol, SocketDriver};
13use task::TaskIdentifier;
14use time::Duration;
15use users::{GroupIdentifier, UserIdentifier};
16
17use file_system::{
18 Device, Entry, FileIdentifier, Inode, Kind, LocalFileIdentifier, Metadata, Mode, Open,
19 Statistics_type, Time,
20};
21
22use file_system::{
23 Error, FileSystemIdentifier, FileSystemTraits, Flags, Path, PathOwned, Permissions, Position,
24 Result, Size, Status, UniqueFileIdentifier,
25};
26
27use crate::device::InternalPath;
28use crate::{SockerAddress, device, pipe};
29
30struct InternalFileSystem {
31 pub mount_point: PathOwned,
32 pub inner: Box<dyn FileSystemTraits>,
33}
34
35static VIRTUAL_FILE_SYSTEM_INSTANCE: OnceLock<VirtualFileSystem> = OnceLock::new();
42
43pub fn initialize(
44 root_file_system: Box<dyn FileSystemTraits>,
45 network_socket_driver: Option<&'static dyn SocketDriver>,
46) -> Result<&'static VirtualFileSystem<'static>> {
47 let virtual_file_system = VirtualFileSystem::new(
48 task::get_instance(),
49 users::get_instance(),
50 time::get_instance(),
51 root_file_system,
52 network_socket_driver,
53 )?;
54
55 Ok(VIRTUAL_FILE_SYSTEM_INSTANCE.get_or_init(|| virtual_file_system))
56}
57
58pub fn get_instance() -> &'static VirtualFileSystem<'static> {
59 VIRTUAL_FILE_SYSTEM_INSTANCE
60 .try_get()
61 .expect("Virtual file system not initialized")
62}
63
64pub struct VirtualFileSystem<'a> {
68 file_systems:
70 RwLock<CriticalSectionRawMutex, BTreeMap<FileSystemIdentifier, InternalFileSystem>>,
71 device_file_system: device::FileSystem<'a>,
73 pipe_file_system: pipe::FileSystem,
75 network_socket_driver: Option<&'a dyn SocketDriver>,
77}
78
79impl<'a> VirtualFileSystem<'a> {
80 pub const STANDARD_INPUT_FILE_IDENTIFIER: FileIdentifier = FileIdentifier::new(0);
81 pub const STANDARD_OUTPUT_FILE_IDENTIFIER: FileIdentifier = FileIdentifier::new(1);
82 pub const STANDARD_ERROR_FILE_IDENTIFIER: FileIdentifier = FileIdentifier::new(2);
83
84 pub fn new(
85 _: &'static task::Manager,
86 _: &'static users::Manager,
87 _: &'static time::Manager,
88 root_file_system: Box<dyn FileSystemTraits>,
89 network_socket_driver: Option<&'a dyn SocketDriver>,
90 ) -> Result<Self> {
91 let mut file_systems = BTreeMap::new();
92
93 let identifier = Self::get_new_file_system_identifier(&file_systems)
94 .ok_or(Error::TooManyMountedFileSystems)?;
95
96 file_systems.insert(
97 identifier,
98 InternalFileSystem {
99 mount_point: PathOwned::new("/".to_string()).unwrap(),
100 inner: root_file_system,
101 },
102 );
103
104 Ok(Self {
105 file_systems: RwLock::new(file_systems),
106 device_file_system: device::FileSystem::new(),
107 pipe_file_system: pipe::FileSystem::new(),
108 network_socket_driver,
109 })
110 }
111
112 pub async fn uninitialize(&self) {
113 if let Ok(inodes) = self
114 .device_file_system
115 .get_devices_from_path(Path::ROOT)
116 .await
117 {
118 for inode in inodes {
119 if let Ok(path) = self.device_file_system.get_path_from_inode(inode).await {
120 match path {
121 InternalPath::Owned(path) => {
122 let _ = self.remove(path).await;
123 }
124 InternalPath::Borrowed(path) => {
125 let _ = self.remove(path).await;
126 }
127 }
128 }
129 }
130 }
131 }
132
133 fn get_new_file_system_identifier(
134 file_systems: &BTreeMap<FileSystemIdentifier, InternalFileSystem>,
135 ) -> Option<FileSystemIdentifier> {
136 let mut file_system_identifier = FileSystemIdentifier::MINIMUM;
137
138 while file_systems.contains_key(&file_system_identifier) {
139 file_system_identifier += 1;
140 }
141
142 Some(file_system_identifier)
143 }
144
145 fn get_file_system_from_identifier(
146 file_systems: &BTreeMap<FileSystemIdentifier, InternalFileSystem>,
147 file_system_identifier: FileSystemIdentifier,
148 ) -> Result<&InternalFileSystem> {
149 file_systems
150 .get(&file_system_identifier)
151 .ok_or(Error::InvalidIdentifier)
152 }
153
154 pub async fn mount_file_system(
156 &self,
157 file_system: Box<dyn FileSystemTraits>,
158 path: impl AsRef<Path>,
159 task: TaskIdentifier,
160 ) -> Result<FileSystemIdentifier> {
161 if !path.as_ref().is_valid() {
162 return Err(Error::InvalidPath);
163 }
164
165 let path = path.as_ref();
166
167 if !path.is_absolute() {
168 return Err(Error::InvalidPath);
169 }
170
171 let mut file_systems = self.file_systems.write().await; let (_, parent_file_system, relative_path) =
175 Self::get_file_system_from_path(&file_systems, &path)?; let time = time::get_instance()
178 .get_current_time()
179 .map_err(|_| Error::TimeError)?
180 .into();
181
182 let user = task::get_instance().get_user(task).await?;
183
184 let group = users::get_instance().get_user_primary_group(user).await?;
185
186 parent_file_system.create_directory(relative_path, time, user, group)?;
187
188 let file_system_identifier = Self::get_new_file_system_identifier(&file_systems)
190 .ok_or(Error::TooManyMountedFileSystems)?;
191
192 file_systems.insert(
193 file_system_identifier,
194 InternalFileSystem {
195 mount_point: path.to_owned(),
196 inner: file_system,
197 },
198 );
199
200 Ok(file_system_identifier)
201 }
202
203 pub async fn unmount_file_system(
204 &self,
205 path: impl AsRef<Path>,
206 task: TaskIdentifier,
207 ) -> Result<()> {
208 let path = path.as_ref();
209
210 if !path.is_valid() || !path.is_absolute() {
211 return Err(Error::InvalidPath);
212 }
213
214 let mut file_systems = self.file_systems.write().await; let file_system_identifier = {
217 let (file_system_identifier, _, relative_path) =
218 Self::get_file_system_from_path(&file_systems, &path)?; if !relative_path.is_root() {
221 return Err(Error::InvalidPath);
222 }
223
224 file_system_identifier
225 };
226
227 let file_system = file_systems
228 .remove(&file_system_identifier)
229 .ok_or(Error::InvalidIdentifier)?;
230
231 file_system.inner.close_all(task)?;
232
233 let (_, parent_file_system, relative_path) =
234 Self::get_file_system_from_path(&file_systems, &file_system.mount_point)?;
235
236 parent_file_system.remove(relative_path)?;
237
238 Ok(())
239 }
240
241 fn get_file_system_from_path<'b>(
242 file_systems: &'b BTreeMap<FileSystemIdentifier, InternalFileSystem>,
243 path: &'b impl AsRef<Path>,
244 ) -> Result<(FileSystemIdentifier, &'b dyn FileSystemTraits, &'b Path)> {
245 let mut result_score = 0;
246 let mut result: Option<FileSystemIdentifier> = None;
247
248 let path = path.as_ref();
249 let path_components = path.get_components();
250
251 for (file_system_identifier, file_system) in file_systems.iter() {
252 let mount_point: &Path = file_system.mount_point.as_ref();
253 let mount_point_components = mount_point.get_components();
254
255 let score = path_components
256 .clone()
257 .get_common_components(mount_point_components);
258
259 if result_score < score {
260 result_score = score;
261 result = Some(*file_system_identifier);
262 }
263 }
264
265 let file_system_identifier = result.ok_or(Error::InvalidPath)?;
266
267 let file_system = file_systems
268 .get(&file_system_identifier)
269 .ok_or(Error::InvalidPath)?;
270
271 let relative_path = path
272 .strip_prefix_absolute(file_system.mount_point.as_ref())
273 .ok_or(Error::InvalidPath)?;
274
275 Ok((
276 file_system_identifier,
277 file_system.inner.as_ref(),
278 relative_path,
279 ))
280 }
281
282 pub async fn open(
283 &self,
284 path: &impl AsRef<Path>,
285 flags: Flags,
286 task: TaskIdentifier,
287 ) -> Result<UniqueFileIdentifier> {
288 let file_systems = self.file_systems.read().await; let (file_system_identifier, file_system, relative_path) =
291 Self::get_file_system_from_path(&file_systems, path)?; let time: Time = time::get_instance()
294 .get_current_time()
295 .map_err(|_| Error::TimeError)?
296 .into();
297
298 let user = task::get_instance().get_user(task).await?;
299
300 let group = users::get_instance().get_user_primary_group(user).await?;
301
302 let local_file = file_system.open(task, relative_path, flags, time, user, group)?;
303
304 let metadata = file_system.get_metadata(local_file)?;
305
306 let (_, unique_file) = local_file.into_unique_file_identifier(file_system_identifier);
307
308 let unique_file = match metadata.get_type() {
309 Kind::CharacterDevice | Kind::BlockDevice => {
310 if let Some(inode) = metadata.get_inode() {
311 let local_file = self
312 .device_file_system
313 .open(inode, task, flags, unique_file)
314 .await?;
315
316 local_file
317 .into_unique_file_identifier(FileSystemIdentifier::DEVICE_FILE_SYSTEM)
318 .1
319 } else {
320 return Err(Error::Corrupted)?;
321 }
322 }
323 Kind::Pipe => {
324 if let Some(inode) = metadata.get_inode() {
325 let local_file = self
326 .pipe_file_system
327 .open(inode, task, flags, unique_file)
328 .await?;
329
330 local_file
331 .into_unique_file_identifier(FileSystemIdentifier::PIPE_FILE_SYSTEM)
332 .1
333 } else {
334 return Err(Error::Corrupted)?;
335 }
336 }
337 _ => unique_file,
338 };
339
340 Ok(unique_file)
341 }
342
343 pub async fn close(
344 &self,
345 file: UniqueFileIdentifier,
346 task: TaskIdentifier,
347 ) -> crate::Result<()> {
348 let (file_system, local_file) = file.into_local_file_identifier(task);
349
350 let underlying_file = match file_system {
351 FileSystemIdentifier::PIPE_FILE_SYSTEM => {
352 match self.pipe_file_system.close(local_file).await? {
353 Some(underlying_file) => underlying_file,
354 None => return Ok(()),
355 }
356 }
357 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
358 self.device_file_system.close(local_file).await?
359 }
360 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => {
361 self.network_socket_driver
362 .ok_or(Error::UnsupportedOperation)?
363 .close(local_file)?;
364
365 return Ok(());
366 }
367 _ => {
368 self.file_systems
369 .read()
370 .await
371 .get(&file_system)
372 .ok_or(Error::InvalidIdentifier)?
373 .inner
374 .close(local_file)?;
375
376 return Ok(());
377 }
378 };
379
380 let (file_system, local_file) = underlying_file.into_local_file_identifier(task);
382
383 self.file_systems
384 .read()
385 .await
386 .get(&file_system)
387 .ok_or(Error::InvalidIdentifier)?
388 .inner
389 .close(local_file)?;
390
391 Ok(())
392 }
393
394 pub async fn read(
395 &self,
396 file: UniqueFileIdentifier,
397 buffer: &mut [u8],
398 task: TaskIdentifier,
399 ) -> Result<Size> {
400 let (file_system, local_file_identifier) = file.into_local_file_identifier(task);
401
402 let time = time::get_instance()
403 .get_current_time()
404 .map_err(|_| Error::TimeError)?
405 .into();
406
407 let (size, underlying_file) = match file_system {
408 FileSystemIdentifier::PIPE_FILE_SYSTEM => {
409 self.pipe_file_system
410 .read(local_file_identifier, buffer)
411 .await?
412 }
413 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
414 let result = self
415 .device_file_system
416 .read(local_file_identifier, buffer)
417 .await?;
418 (result.0, Some(result.1))
419 }
420 _ => {
421 return self
422 .file_systems
423 .read()
424 .await
425 .get(&file_system)
426 .ok_or(Error::InvalidIdentifier)?
427 .inner
428 .read(local_file_identifier, buffer, time);
429 }
430 };
431
432 if let Some(underlying_file) = underlying_file {
433 let (file_system, local_file_identifier) =
434 underlying_file.into_local_file_identifier(task);
435
436 self.file_systems
437 .read()
438 .await
439 .get(&file_system)
440 .ok_or(Error::InvalidIdentifier)?
441 .inner
442 .read(local_file_identifier, &mut [0; 0], time)?;
443 }
444 Ok(size)
445 }
446
447 pub async fn read_line(
448 &self,
449 file: UniqueFileIdentifier,
450 task: TaskIdentifier,
451 buffer: &mut String,
452 ) -> Result<Size> {
453 let (file_system, local_file_identifier) = file.into_local_file_identifier(task);
454
455 let time = time::get_instance()
456 .get_current_time()
457 .map_err(|_| Error::TimeError)?
458 .into();
459
460 let (size, underlying_file) = match file_system {
461 FileSystemIdentifier::PIPE_FILE_SYSTEM => {
462 self.pipe_file_system
463 .read_line(local_file_identifier, buffer)
464 .await?
465 }
466 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
467 let result = self
468 .device_file_system
469 .read_line(local_file_identifier, buffer)
470 .await?;
471 (result.0, Some(result.1))
472 }
473 _ => {
474 let file_systems = self.file_systems.read().await; let file_system = &file_systems
477 .get(&file_system)
478 .ok_or(Error::InvalidIdentifier)?
479 .inner;
480
481 return read_line(&**file_system, buffer, local_file_identifier, time).await;
482 }
483 };
484
485 if let Some(underlying_file) = underlying_file {
486 let (file_system, local_file_identifier) =
487 underlying_file.into_local_file_identifier(task);
488
489 self.file_systems
490 .read()
491 .await
492 .get(&file_system)
493 .ok_or(Error::InvalidIdentifier)?
494 .inner
495 .read(local_file_identifier, &mut [0; 0], time)?;
496 }
497
498 Ok(size)
499 }
500
501 pub async fn read_to_end(
502 &self,
503 file: UniqueFileIdentifier,
504 task: TaskIdentifier,
505 buffer: &mut Vec<u8>,
506 ) -> Result<Size> {
507 const CHUNK_SIZE: usize = 512;
508
509 let mut read_size = 0;
510
511 loop {
512 let mut chunk = vec![0; CHUNK_SIZE];
513
514 let size: usize = self.read(file, &mut chunk, task).await?.into();
515
516 if size == 0 {
517 break;
518 }
519
520 buffer.extend_from_slice(&chunk[..size]);
521
522 read_size += size;
523 }
524
525 Ok(read_size.into())
526 }
527
528 pub async fn write(
529 &self,
530 file: UniqueFileIdentifier,
531 buffer: &[u8],
532 task: TaskIdentifier,
533 ) -> Result<Size> {
534 let (file_system, local_file_identifier) = file.into_local_file_identifier(task);
535
536 let time = time::get_instance()
537 .get_current_time()
538 .map_err(|_| Error::TimeError)?
539 .into();
540
541 let (size, underlying_file) = match file_system {
542 FileSystemIdentifier::PIPE_FILE_SYSTEM => {
543 self.pipe_file_system
544 .write(local_file_identifier, buffer)
545 .await?
546 }
547 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
548 let result = self
549 .device_file_system
550 .write(local_file_identifier, buffer)
551 .await?;
552 (result.0, Some(result.1))
553 }
554 _ => {
555 return self
556 .file_systems
557 .read()
558 .await
559 .get(&file_system)
560 .ok_or(Error::InvalidIdentifier)?
561 .inner
562 .write(local_file_identifier, buffer, time);
563 }
564 };
565
566 if let Some(underlying_file) = underlying_file {
567 let (file_system, local_file_identifier) =
568 underlying_file.into_local_file_identifier(task);
569
570 self.file_systems
571 .read()
572 .await
573 .get(&file_system)
574 .ok_or(Error::InvalidIdentifier)?
575 .inner
576 .write(local_file_identifier, &[0; 0], time)?;
577 }
578
579 Ok(size)
580 }
581
582 pub async fn set_position(
583 &self,
584 file: UniqueFileIdentifier,
585 position: &Position,
586 task: TaskIdentifier,
587 ) -> Result<Size> {
588 let (file_system, local_file) = file.into_local_file_identifier(task);
589
590 match file_system {
591 FileSystemIdentifier::PIPE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
592 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
593 let (size, underlying_file) = self
594 .device_file_system
595 .set_position(local_file, position)
596 .await?;
597
598 let (file_system, local_file) = underlying_file.into_local_file_identifier(task);
599
600 self.file_systems
601 .read()
602 .await
603 .get(&file_system)
604 .ok_or(Error::InvalidIdentifier)?
605 .inner
606 .set_position(local_file, position)?;
607
608 Ok(size)
609 }
610 _ => self
611 .file_systems
612 .read()
613 .await
614 .get(&file_system)
615 .ok_or(Error::InvalidIdentifier)?
616 .inner
617 .set_position(local_file, position),
618 }
619 }
620
621 pub async fn set_owner(
622 &self,
623 path: impl AsRef<Path>,
624 user: Option<UserIdentifier>,
625 group: Option<GroupIdentifier>,
626 ) -> Result<()> {
627 let file_systems = self.file_systems.read().await; let (_, file_system, relative_path) =
630 Self::get_file_system_from_path(&file_systems, &path)?; let mut metadata = file_system.get_metadata_from_path(relative_path)?;
633
634 if let Some(user) = user {
635 metadata.set_owner(user);
636 }
637
638 if let Some(group) = group {
639 metadata.set_group(group);
640 }
641
642 file_system.set_metadata_from_path(relative_path, &metadata)
643 }
644
645 pub async fn set_permissions(
646 &self,
647 path: impl AsRef<Path>,
648 permissions: Permissions,
649 ) -> Result<()> {
650 let file_systems = self.file_systems.read().await; let (_, file_system, relative_path) =
653 Self::get_file_system_from_path(&file_systems, &path)?; let mut metadata = file_system.get_metadata_from_path(relative_path)?;
656
657 metadata.set_permissions(permissions);
658
659 file_system.set_metadata_from_path(relative_path, &metadata)
660 }
661
662 pub async fn close_all(&self, task_identifier: TaskIdentifier) -> Result<()> {
663 let file_systems = self.file_systems.read().await; for file_system in file_systems.values() {
666 file_system.inner.close_all(task_identifier)?;
667 }
668
669 self.device_file_system.close_all(task_identifier).await?;
670
671 self.pipe_file_system.close_all(task_identifier).await?;
672
673 Ok(())
674 }
675
676 pub async fn mount_device(
677 &self,
678 task: TaskIdentifier,
679 path: &impl AsRef<Path>,
680 device: Device,
681 ) -> Result<()> {
682 let file_systems = self.file_systems.read().await; let (_, file_system, relative_path) =
685 Self::get_file_system_from_path(&file_systems, &path)?; let time = time::get_instance()
688 .get_current_time()
689 .map_err(|_| Error::TimeError)?
690 .into();
691
692 let user = task::get_instance().get_user(task).await?;
693
694 let group = users::get_instance().get_user_primary_group(user).await?;
695
696 let file = file_system.open(
697 task,
698 relative_path,
699 Flags::new(Mode::READ_WRITE, Some(Open::CREATE_ONLY), None),
700 time,
701 user,
702 group,
703 )?;
704
705 file_system.close(file)?;
706
707 let inode = self
708 .device_file_system
709 .mount_device(relative_path.to_owned(), device)
710 .await?;
711
712 let time: Time = time::get_instance()
713 .get_current_time()
714 .map_err(|_| Error::TimeError)?
715 .into();
716
717 let user = task::get_instance().get_user(task).await?;
718
719 let group = users::get_instance().get_user_primary_group(user).await?;
720
721 let mut metadata = Metadata::get_default(Kind::BlockDevice, time, user, group)
722 .ok_or(Error::InvalidParameter)?;
723 metadata.set_inode(inode);
724
725 file_system.set_metadata_from_path(relative_path, &metadata)?;
726
727 Ok(())
728 }
729
730 pub async fn mount_static_device(
731 &self,
732 task: TaskIdentifier,
733 path: &'a impl AsRef<Path>,
734 device: Device,
735 ) -> Result<()> {
736 let file_systems = self.file_systems.read().await; let (_, file_system, relative_path) =
740 Self::get_file_system_from_path(&file_systems, &path)?; let time = time::get_instance()
743 .get_current_time()
744 .map_err(|_| Error::TimeError)?
745 .into();
746
747 let user = task::get_instance().get_user(task).await?;
748
749 let group = users::get_instance().get_user_primary_group(user).await?;
750
751 let file = file_system.open(
752 task,
753 relative_path,
754 Flags::new(Mode::WRITE_ONLY, Some(Open::CREATE_ONLY), None),
755 time,
756 user,
757 group,
758 )?;
759
760 file_system.close(file)?;
761
762 let r#type = if device.is_a_block_device() {
763 Kind::BlockDevice
764 } else {
765 Kind::CharacterDevice
766 };
767
768 let inode = self
770 .device_file_system
771 .mount_static_device(path, device)
772 .await?;
773
774 let time: Time = time::get_instance()
775 .get_current_time()
776 .map_err(|_| Error::TimeError)?
777 .into();
778
779 let user = task::get_instance().get_user(task).await?;
780
781 let group = users::get_instance().get_user_primary_group(user).await?;
782
783 let mut metadata =
785 Metadata::get_default(r#type, time, user, group).ok_or(Error::InvalidParameter)?;
786 metadata.set_inode(inode);
787
788 file_system.set_metadata_from_path(relative_path, &metadata)?;
789
790 Ok(())
791 }
792
793 pub async fn create_named_pipe(
794 &self,
795 path: &impl AsRef<Path>,
796 size: usize,
797 task: TaskIdentifier,
798 ) -> Result<()> {
799 let file_systems = self.file_systems.read().await; let (_, file_system, relative_path) = Self::get_file_system_from_path(&file_systems, path)?; let time = time::get_instance()
804 .get_current_time()
805 .map_err(|_| Error::TimeError)?
806 .into();
807
808 let user = task::get_instance().get_user(task).await?;
809
810 let group = users::get_instance().get_user_primary_group(user).await?;
811
812 let file = file_system.open(
813 task,
814 relative_path,
815 Flags::new(Mode::READ_WRITE, Some(Open::CREATE_ONLY), None),
816 time,
817 user,
818 group,
819 )?;
820
821 file_system.close(file)?;
822
823 let inode = self.pipe_file_system.create_named_pipe(size).await?;
824
825 let time: Time = time::get_instance()
826 .get_current_time()
827 .map_err(|_| Error::TimeError)?
828 .into();
829
830 let user = task::get_instance().get_user(task).await?;
831
832 let group = users::get_instance().get_user_primary_group(user).await?;
833
834 let mut metadata =
835 Metadata::get_default(Kind::Pipe, time, user, group).ok_or(Error::InvalidParameter)?;
836 metadata.set_inode(inode);
837
838 file_system.set_metadata_from_path(relative_path, &metadata)?;
839
840 Ok(())
841 }
842
843 pub async fn create_unnamed_pipe(
844 &self,
845 task: TaskIdentifier,
846 status: Status,
847 size: usize,
848 ) -> Result<(UniqueFileIdentifier, UniqueFileIdentifier)> {
849 let (read, write) = self
850 .pipe_file_system
851 .create_unnamed_pipe(task, status, size)
852 .await?;
853
854 let (_, read) = read.into_unique_file_identifier(FileSystemIdentifier::PIPE_FILE_SYSTEM);
855 let (_, write) = write.into_unique_file_identifier(FileSystemIdentifier::PIPE_FILE_SYSTEM);
856
857 Ok((read, write))
858 }
859
860 pub async fn remove(&self, path: impl AsRef<Path>) -> Result<()> {
861 let file_systems = self.file_systems.read().await; let (_, file_system, relative_path) =
865 Self::get_file_system_from_path(&file_systems, &path)?; let metadata = file_system.get_metadata_from_path(relative_path)?;
868
869 file_system.remove(relative_path)?;
870
871 match metadata.get_type() {
872 Kind::Pipe => {
873 if let Some(inode) = metadata.get_inode() {
874 match self.pipe_file_system.remove(inode).await {
875 Ok(_) | Err(Error::InvalidInode) => (),
876 Err(error) => {
877 return Err(error);
878 }
879 }
880 }
881 }
882 Kind::BlockDevice => {
883 if let Some(inode) = metadata.get_inode() {
884 match self.device_file_system.remove(inode).await {
885 Ok(_) | Err(Error::InvalidInode) => (),
886 Err(error) => {
887 return Err(error);
888 }
889 }
890 }
891 }
892 Kind::CharacterDevice => {
893 if let Some(inode) = metadata.get_inode() {
894 match self.device_file_system.remove(inode).await {
895 Ok(_) | Err(Error::InvalidInode) => (),
896 Err(error) => {
897 return Err(error);
898 }
899 }
900 }
901 }
902
903 _ => (),
904 };
905
906 Ok(())
907 }
908
909 pub async fn transfert(
910 &self,
911 file: UniqueFileIdentifier,
912 current_task: TaskIdentifier,
913 new_task: TaskIdentifier,
914 new_file: Option<FileIdentifier>,
915 ) -> Result<UniqueFileIdentifier> {
916 let (file_system, file) = file.into_local_file_identifier(current_task);
917
918 let underlying_file = match file_system {
919 FileSystemIdentifier::PIPE_FILE_SYSTEM => {
920 self.pipe_file_system.get_underlying_file(file).await?
921 }
922 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
923 Some(self.device_file_system.get_underlying_file(file).await?)
924 }
925 _ => None,
926 };
927
928 let file_systems = self.file_systems.read().await;
929
930 let underlying_file = if let Some(underlying_file) = underlying_file {
931 let (file_system, local_file) =
932 underlying_file.into_local_file_identifier(current_task);
933
934 Some(
935 file_systems
936 .get(&file_system)
937 .ok_or(Error::InvalidIdentifier)?
938 .inner
939 .transfert(new_task, local_file, new_file)?
940 .into_unique_file_identifier(file_system)
941 .1,
942 )
943 } else {
944 None
945 };
946
947 let new_file = match file_system {
948 FileSystemIdentifier::PIPE_FILE_SYSTEM => {
949 self.pipe_file_system
950 .transfert(new_task, file, new_file)
951 .await?
952 }
953 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
954 let underlying_file = underlying_file.ok_or(Error::InternalError)?;
955
956 self.device_file_system
957 .transfert(new_task, file, underlying_file, new_file)
958 .await?
959 }
960 _ => Self::get_file_system_from_identifier(&file_systems, file_system)?
961 .inner
962 .transfert(new_task, file, new_file)?,
963 };
964
965 let (_, new_file) = new_file.into_unique_file_identifier(file_system);
966
967 Ok(new_file)
968 }
969
970 pub async fn flush(
971 &self,
972 file: UniqueFileIdentifier,
973 task_identifier: TaskIdentifier,
974 ) -> Result<()> {
975 let (file_system, file_identifier) = file.into_local_file_identifier(task_identifier);
976
977 if file_system == FileSystemIdentifier::PIPE_FILE_SYSTEM {
978 Ok(())
979 } else if file_system == FileSystemIdentifier::DEVICE_FILE_SYSTEM {
980 let underlying_file = self.device_file_system.flush(file_identifier).await?;
981
982 let (file_system, local_file) =
983 underlying_file.into_local_file_identifier(task_identifier);
984
985 self.file_systems
986 .read()
987 .await
988 .get(&file_system)
989 .ok_or(Error::InvalidIdentifier)?
990 .inner
991 .flush(local_file)?;
992
993 Ok(())
994 } else {
995 self.file_systems
996 .read()
997 .await
998 .get(&file_system)
999 .ok_or(Error::InvalidIdentifier)?
1000 .inner
1001 .flush(file_identifier)
1002 }
1003 }
1004
1005 pub async fn get_statistics(
1006 &self,
1007 file: UniqueFileIdentifier,
1008 task_identifier: TaskIdentifier,
1009 ) -> Result<Statistics_type> {
1010 let (file_system, local_file) = file.into_local_file_identifier(task_identifier);
1011
1012 let file_systems = self.file_systems.read().await;
1013
1014 let file = match file_system {
1015 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
1016 self.device_file_system
1017 .get_underlying_file(local_file)
1018 .await?
1019 }
1020 FileSystemIdentifier::PIPE_FILE_SYSTEM => self
1021 .pipe_file_system
1022 .get_underlying_file(local_file)
1023 .await?
1024 .ok_or(Error::UnsupportedOperation)?,
1025 _ => file,
1026 };
1027
1028 let (file_system, local_file) = file.into_local_file_identifier(task_identifier);
1029
1030 Self::get_file_system_from_identifier(&file_systems, file_system)?
1031 .inner
1032 .get_statistics(local_file)
1033 }
1034
1035 pub async fn open_directory(
1036 &self,
1037 path: &impl AsRef<Path>,
1038 task: TaskIdentifier,
1039 ) -> Result<UniqueFileIdentifier> {
1040 let file_systems = self.file_systems.read().await; let (file_system_identifier, file_system, relative_path) =
1043 Self::get_file_system_from_path(&file_systems, path)?; let (_, file) = file_system
1046 .open_directory(relative_path, task)?
1047 .into_unique_file_identifier(file_system_identifier);
1048
1049 Ok(file)
1050 }
1051
1052 pub async fn read_directory(
1053 &self,
1054 file: UniqueFileIdentifier,
1055 task: TaskIdentifier,
1056 ) -> Result<Option<Entry>> {
1057 let (file_system, file) = file.into_local_file_identifier(task);
1058
1059 match file_system {
1060 FileSystemIdentifier::PIPE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
1061 FileSystemIdentifier::DEVICE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
1062 _ => self
1063 .file_systems
1064 .read()
1065 .await
1066 .get(&file_system)
1067 .ok_or(Error::InvalidIdentifier)?
1068 .inner
1069 .read_directory(file),
1070 }
1071 }
1072
1073 pub async fn set_position_directory(
1074 &self,
1075 file: UniqueFileIdentifier,
1076 position: Size,
1077 task: TaskIdentifier,
1078 ) -> Result<()> {
1079 let (file_system, file) = file.into_local_file_identifier(task);
1080
1081 match file_system {
1082 FileSystemIdentifier::PIPE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
1083 FileSystemIdentifier::DEVICE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
1084 _ => self
1085 .file_systems
1086 .read()
1087 .await
1088 .get(&file_system)
1089 .ok_or(Error::InvalidIdentifier)?
1090 .inner
1091 .set_position_directory(file, position),
1092 }
1093 }
1094
1095 pub async fn get_position_directory(
1096 &self,
1097 file: UniqueFileIdentifier,
1098 task: TaskIdentifier,
1099 ) -> Result<Size> {
1100 let (file_system, file) = file.into_local_file_identifier(task);
1101
1102 match file_system {
1103 FileSystemIdentifier::PIPE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
1104 FileSystemIdentifier::DEVICE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
1105 _ => self
1106 .file_systems
1107 .read()
1108 .await
1109 .get(&file_system)
1110 .ok_or(Error::InvalidIdentifier)?
1111 .inner
1112 .get_position_directory(file),
1113 }
1114 }
1115
1116 pub async fn rewind_directory(
1117 &self,
1118 file: UniqueFileIdentifier,
1119 task: TaskIdentifier,
1120 ) -> Result<()> {
1121 let (file_system, file) = file.into_local_file_identifier(task);
1122
1123 match file_system {
1124 FileSystemIdentifier::PIPE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
1125 FileSystemIdentifier::DEVICE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
1126 _ => self
1127 .file_systems
1128 .read()
1129 .await
1130 .get(&file_system)
1131 .ok_or(Error::InvalidIdentifier)?
1132 .inner
1133 .rewind_directory(file),
1134 }
1135 }
1136
1137 pub async fn close_directory(
1138 &self,
1139 file: UniqueFileIdentifier,
1140 task: TaskIdentifier,
1141 ) -> Result<()> {
1142 let (file_system, file) = file.into_local_file_identifier(task);
1143
1144 match file_system {
1145 FileSystemIdentifier::PIPE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
1146 FileSystemIdentifier::DEVICE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
1147 _ => self
1148 .file_systems
1149 .read()
1150 .await
1151 .get(&file_system)
1152 .ok_or(Error::InvalidIdentifier)?
1153 .inner
1154 .close_directory(file),
1155 }
1156 }
1157
1158 pub async fn create_directory(
1159 &self,
1160 path: &impl AsRef<Path>,
1161 task: TaskIdentifier,
1162 ) -> Result<()> {
1163 let file_systems = self.file_systems.read().await; let (_, file_system, relative_path) = Self::get_file_system_from_path(&file_systems, path)?; let time = time::get_instance()
1168 .get_current_time()
1169 .map_err(|_| Error::TimeError)?
1170 .into();
1171
1172 let user = task::get_instance().get_user(task).await?;
1173
1174 let group = users::get_instance().get_user_primary_group(user).await?;
1175
1176 file_system.create_directory(relative_path, time, user, group)
1177 }
1178
1179 pub async fn get_mode(&self, file: UniqueFileIdentifier, task: TaskIdentifier) -> Result<Mode> {
1180 let (file_system, file) = file.into_local_file_identifier(task);
1181
1182 match file_system {
1183 FileSystemIdentifier::PIPE_FILE_SYSTEM => self.pipe_file_system.get_mode(file).await,
1184 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
1185 self.device_file_system.get_mode(file).await
1186 }
1187 _ => self
1188 .file_systems
1189 .read()
1190 .await
1191 .get(&file_system)
1192 .ok_or(Error::InvalidIdentifier)?
1193 .inner
1194 .get_mode(file),
1195 }
1196 }
1197
1198 pub async fn duplicate_file_identifier(
1199 &self,
1200 file: UniqueFileIdentifier,
1201 task: TaskIdentifier,
1202 ) -> Result<UniqueFileIdentifier> {
1203 let (file_system, file) = file.into_local_file_identifier(task);
1204
1205 let underlying_file = match file_system {
1206 FileSystemIdentifier::PIPE_FILE_SYSTEM => {
1207 self.pipe_file_system.get_underlying_file(file).await?
1208 }
1209 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
1210 Some(self.device_file_system.get_underlying_file(file).await?)
1211 }
1212 _ => None,
1213 };
1214
1215 let file_systems = self.file_systems.read().await;
1216
1217 let underlying_file = if let Some(underlying_file) = underlying_file {
1218 let (file_system, local_file) = underlying_file.into_local_file_identifier(task);
1219
1220 Some(
1221 file_systems
1222 .get(&file_system)
1223 .ok_or(Error::InvalidIdentifier)?
1224 .inner
1225 .duplicate(local_file)?
1226 .into_unique_file_identifier(file_system)
1227 .1,
1228 )
1229 } else {
1230 None
1231 };
1232
1233 let new_file = match file_system {
1234 FileSystemIdentifier::PIPE_FILE_SYSTEM => {
1235 self.pipe_file_system
1236 .duplicate(file, underlying_file)
1237 .await?
1238 }
1239 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
1240 let underlying_file = underlying_file.ok_or(Error::InternalError)?;
1241
1242 self.device_file_system
1243 .duplicate(file, underlying_file)
1244 .await?
1245 }
1246 _ => Self::get_file_system_from_identifier(&file_systems, file_system)?
1247 .inner
1248 .duplicate(file)?,
1249 };
1250
1251 let (_, new_file) = new_file.into_unique_file_identifier(file_system);
1252
1253 Ok(new_file)
1254 }
1255
1256 pub async fn create_new_task_standard_io(
1257 &self,
1258 standard_in: UniqueFileIdentifier,
1259 standard_error: UniqueFileIdentifier,
1260 standard_out: UniqueFileIdentifier,
1261 current_task: TaskIdentifier,
1262 new_task: TaskIdentifier,
1263 duplicate: bool,
1264 ) -> Result<(
1265 UniqueFileIdentifier,
1266 UniqueFileIdentifier,
1267 UniqueFileIdentifier,
1268 )> {
1269 let (standard_in, standard_error, standard_out) = if duplicate {
1270 let standard_in = self
1271 .duplicate_file_identifier(standard_in, current_task)
1272 .await?;
1273 let standard_error = self
1274 .duplicate_file_identifier(standard_error, current_task)
1275 .await?;
1276 let standard_out = self
1277 .duplicate_file_identifier(standard_out, current_task)
1278 .await?;
1279
1280 (standard_in, standard_error, standard_out)
1281 } else {
1282 (standard_in, standard_error, standard_out)
1283 };
1284
1285 let standard_in = self
1286 .transfert(
1287 standard_in,
1288 current_task,
1289 new_task,
1290 Some(FileIdentifier::STANDARD_IN),
1291 )
1292 .await?;
1293 let standard_error = self
1294 .transfert(
1295 standard_error,
1296 current_task,
1297 new_task,
1298 Some(FileIdentifier::STANDARD_ERROR),
1299 )
1300 .await?;
1301 let standard_out = self
1302 .transfert(
1303 standard_out,
1304 current_task,
1305 new_task,
1306 Some(FileIdentifier::STANDARD_OUT),
1307 )
1308 .await?;
1309
1310 Ok((standard_in, standard_error, standard_out))
1311 }
1312
1313 pub async fn is_a_terminal(
1314 &self,
1315 file: UniqueFileIdentifier,
1316 task: TaskIdentifier,
1317 ) -> Result<bool> {
1318 let (file_system, file) = file.into_local_file_identifier(task);
1319
1320 match file_system {
1321 FileSystemIdentifier::PIPE_FILE_SYSTEM => Err(Error::UnsupportedOperation),
1322 FileSystemIdentifier::DEVICE_FILE_SYSTEM => {
1323 self.device_file_system.is_a_terminal(file).await
1324 }
1325 _ => Err(Error::UnsupportedOperation),
1326 }
1327 }
1328
1329 pub async fn rename(
1330 &self,
1331 old_path: &impl AsRef<Path>,
1332 new_path: &impl AsRef<Path>,
1333 ) -> Result<()> {
1334 let file_systems = self.file_systems.read().await; let (old_file_system_identifier, old_file_system, old_relative_path) =
1337 Self::get_file_system_from_path(&file_systems, old_path)?; let (new_file_system_identifier, _, new_relative_path) =
1340 Self::get_file_system_from_path(&file_systems, new_path)?; if old_file_system_identifier != new_file_system_identifier {
1343 return Err(Error::InvalidPath);
1344 }
1345
1346 if old_file_system_identifier == new_file_system_identifier {
1347 old_file_system.rename(old_relative_path, new_relative_path)
1348 } else {
1349 Err(Error::UnsupportedOperation) }
1351 }
1352
1353 pub async fn get_raw_device(&self, path: &impl AsRef<Path>) -> Result<Device> {
1354 let file_systems = self.file_systems.read().await;
1355
1356 let (_, file_system, relative_path) = Self::get_file_system_from_path(&file_systems, path)?; let metadata = file_system.get_metadata_from_path(relative_path)?;
1359
1360 if metadata.get_type() != Kind::BlockDevice && metadata.get_type() != Kind::CharacterDevice
1361 {
1362 return Err(Error::UnsupportedOperation);
1363 }
1364
1365 if let Some(inode) = metadata.get_inode() {
1366 self.device_file_system.get_raw_device(inode).await
1367 } else {
1368 Err(Error::Corrupted)
1369 }
1370 }
1371
1372 pub async fn get_metadata_from_path(&self, path: &impl AsRef<Path>) -> Result<Metadata> {
1373 let file_systems = self.file_systems.read().await;
1374
1375 let (_, file_system, relative_path) = Self::get_file_system_from_path(&file_systems, path)?; file_system.get_metadata_from_path(relative_path)
1378 }
1379
1380 pub async fn get_statistics_from_path(
1381 &self,
1382 path: &impl AsRef<Path>,
1383 ) -> Result<Statistics_type> {
1384 let file_systems = self.file_systems.read().await;
1385
1386 let (file_system_identifier, file_system, relative_path) =
1387 Self::get_file_system_from_path(&file_systems, path)?; let metadata = file_system.get_metadata_from_path(relative_path)?;
1390
1391 Ok(Statistics_type::new(
1392 file_system_identifier,
1393 metadata.get_inode().unwrap_or(Inode::new(0)),
1394 0,
1395 Size::new(0),
1396 metadata.get_access_time(),
1397 metadata.get_modification_time(),
1398 metadata.get_creation_time(),
1399 metadata.get_type(),
1400 metadata.get_permissions(),
1401 metadata.get_user(),
1402 metadata.get_group(),
1403 ))
1404 }
1405
1406 pub async fn send(
1407 &self,
1408 task: TaskIdentifier,
1409 socket: UniqueFileIdentifier,
1410 data: &[u8],
1411 ) -> crate::Result<()> {
1412 let (file_system, socket) = socket.into_local_file_identifier(task);
1413
1414 match file_system {
1415 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => self
1416 .network_socket_driver
1417 .ok_or(crate::Error::UnavailableDriver)?
1418 .send(socket, data)?,
1419 _ => Err(crate::Error::InvalidFileSystem)?,
1420 }
1421
1422 Ok(())
1423 }
1424
1425 pub async fn receive(
1426 &self,
1427 task: TaskIdentifier,
1428 socket: UniqueFileIdentifier,
1429 data: &mut [u8],
1430 ) -> crate::Result<usize> {
1431 let (file_system, socket) = socket.into_local_file_identifier(task);
1432
1433 match file_system {
1434 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => Ok(self
1435 .network_socket_driver
1436 .ok_or(crate::Error::UnavailableDriver)?
1437 .receive(socket, data)?),
1438 _ => Err(crate::Error::InvalidFileSystem)?,
1439 }
1440 }
1441
1442 pub async fn send_to(
1443 &self,
1444 task: TaskIdentifier,
1445 socket: UniqueFileIdentifier,
1446 data: &[u8],
1447 address: SockerAddress,
1448 ) -> crate::Result<()> {
1449 let (file_system, socket) = socket.into_local_file_identifier(task);
1450
1451 match file_system {
1452 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => {
1453 let (ip, port) = address
1454 .into_ip_and_port()
1455 .ok_or(crate::Error::InvalidParameter)?;
1456
1457 self.network_socket_driver
1458 .ok_or(crate::Error::UnavailableDriver)?
1459 .send_to(socket, data, ip, port)?
1460 }
1461 _ => Err(crate::Error::InvalidFileSystem)?,
1462 }
1463
1464 Ok(())
1465 }
1466
1467 pub async fn receive_from(
1468 &self,
1469 task: TaskIdentifier,
1470 socket: UniqueFileIdentifier,
1471 data: &mut [u8],
1472 ) -> crate::Result<(usize, SockerAddress)> {
1473 let (file_system, socket) = socket.into_local_file_identifier(task);
1474
1475 match file_system {
1476 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => {
1477 let (size, ip, port) = self
1478 .network_socket_driver
1479 .ok_or(crate::Error::UnavailableDriver)?
1480 .receive_from(socket, data)?;
1481
1482 Ok((size, SockerAddress::from_ip_and_port(ip, port)))
1483 }
1484 _ => Err(crate::Error::InvalidFileSystem)?,
1485 }
1486 }
1487
1488 fn new_file_identifier(
1489 &self,
1490 file_system: FileSystemIdentifier,
1491 task: TaskIdentifier,
1492 ) -> crate::Result<LocalFileIdentifier> {
1493 let iterator = LocalFileIdentifier::get_minimum(task).into_iter();
1494
1495 match file_system {
1496 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => Ok(self
1497 .network_socket_driver
1498 .ok_or(crate::Error::UnavailableDriver)?
1499 .get_new_socket_identifier(iterator)?
1500 .ok_or(crate::Error::TooManyOpenFiles)?),
1501 _ => Err(crate::Error::InvalidFileSystem)?,
1502 }
1503 }
1504
1505 pub async fn bind(
1506 &self,
1507 task: TaskIdentifier,
1508 address: SockerAddress,
1509 protocol: Protocol,
1510 ) -> crate::Result<UniqueFileIdentifier> {
1511 let file_system = match address {
1512 SockerAddress::IPv4(_, _) | SockerAddress::IPv6(_, _) => {
1513 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM
1514 }
1515 SockerAddress::Local(_) => {
1516 todo!()
1517 }
1518 };
1519
1520 let new_socket = self.new_file_identifier(file_system, task)?;
1521
1522 match file_system {
1523 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => {
1524 let (ip, port) = if let Some((ip_type, port)) = address.into_ip_and_port() {
1525 (ip_type, port)
1526 } else {
1527 unreachable!()
1528 };
1529
1530 self.network_socket_driver
1531 .ok_or(crate::Error::UnavailableDriver)?
1532 .bind(ip, port, protocol, new_socket)?
1533 }
1534 _ => return Err(crate::Error::InvalidFileSystem),
1535 }
1536
1537 let (_, new_socket) = new_socket.into_unique_file_identifier(file_system);
1538
1539 Ok(new_socket)
1540 }
1541
1542 pub async fn connect(
1543 &self,
1544 task: TaskIdentifier,
1545 address: SockerAddress,
1546 ) -> crate::Result<UniqueFileIdentifier> {
1547 let file_system = match address {
1548 SockerAddress::IPv4(_, _) | SockerAddress::IPv6(_, _) => {
1549 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM
1550 }
1551 SockerAddress::Local(_) => {
1552 todo!()
1553 }
1554 };
1555
1556 let new_socket = self.new_file_identifier(file_system, task)?;
1557
1558 match file_system {
1559 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => {
1560 let (ip, port) = if let Some((ip_type, port)) = address.into_ip_and_port() {
1561 (ip_type, port)
1562 } else {
1563 unreachable!()
1564 };
1565
1566 self.network_socket_driver
1567 .ok_or(crate::Error::UnavailableDriver)?
1568 .connect(ip, port, new_socket)?
1569 }
1570 _ => return Err(crate::Error::InvalidFileSystem),
1571 }
1572
1573 let (_, new_socket) = new_socket.into_unique_file_identifier(file_system);
1574
1575 Ok(new_socket)
1576 }
1577
1578 pub async fn accept(
1579 &self,
1580 task: TaskIdentifier,
1581 socket: UniqueFileIdentifier,
1582 ) -> crate::Result<(UniqueFileIdentifier, Option<(IP, Port)>)> {
1583 let (file_system, socket) = socket.into_local_file_identifier(task);
1584
1585 match file_system {
1586 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => {
1587 let new_socket = self.new_file_identifier(file_system, task)?;
1588
1589 let (ip, port) = self
1590 .network_socket_driver
1591 .ok_or(crate::Error::UnavailableDriver)?
1592 .accept(socket, new_socket)?;
1593
1594 let (_, new_socket) = new_socket.into_unique_file_identifier(file_system);
1595
1596 Ok((new_socket, Some((ip, port))))
1597 }
1598 _ => Err(crate::Error::InvalidFileSystem),
1599 }
1600 }
1601
1602 pub async fn set_send_timeout(
1603 &self,
1604 task: TaskIdentifier,
1605 socket: UniqueFileIdentifier,
1606 timeout: Duration,
1607 ) -> crate::Result<()> {
1608 let (file_system, socket) = socket.into_local_file_identifier(task);
1609
1610 match file_system {
1611 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => self
1612 .network_socket_driver
1613 .ok_or(crate::Error::UnavailableDriver)?
1614 .set_send_timeout(socket, timeout)?,
1615 _ => return Err(crate::Error::InvalidFileSystem),
1616 }
1617
1618 Ok(())
1619 }
1620
1621 pub async fn set_receive_timeout(
1622 &self,
1623 task: TaskIdentifier,
1624 socket: UniqueFileIdentifier,
1625 timeout: Duration,
1626 ) -> crate::Result<()> {
1627 let (file_system, socket) = socket.into_local_file_identifier(task);
1628
1629 match file_system {
1630 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => self
1631 .network_socket_driver
1632 .ok_or(crate::Error::UnavailableDriver)?
1633 .set_receive_timeout(socket, timeout)?,
1634 _ => return Err(crate::Error::InvalidFileSystem),
1635 }
1636
1637 Ok(())
1638 }
1639
1640 pub async fn get_send_timeout(
1641 &self,
1642 task: TaskIdentifier,
1643 socket: UniqueFileIdentifier,
1644 ) -> crate::Result<Option<Duration>> {
1645 let (file_system, socket) = socket.into_local_file_identifier(task);
1646
1647 match file_system {
1648 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => Ok(self
1649 .network_socket_driver
1650 .ok_or(crate::Error::UnavailableDriver)?
1651 .get_send_timeout(socket)?),
1652 _ => Err(crate::Error::InvalidFileSystem),
1653 }
1654 }
1655
1656 pub async fn get_receive_timeout(
1657 &self,
1658 task: TaskIdentifier,
1659 socket: UniqueFileIdentifier,
1660 ) -> crate::Result<Option<Duration>> {
1661 let (file_system, socket) = socket.into_local_file_identifier(task);
1662
1663 match file_system {
1664 FileSystemIdentifier::NETWORK_SOCKET_FILE_SYSTEM => Ok(self
1665 .network_socket_driver
1666 .ok_or(crate::Error::UnavailableDriver)?
1667 .get_receive_timeout(socket)?),
1668 _ => Err(crate::Error::InvalidFileSystem),
1669 }
1670 }
1671}
1672
1673async fn read_line(
1674 file_system: &dyn FileSystemTraits,
1675 buffer: &mut String,
1676 file: LocalFileIdentifier,
1677 time: Time,
1678) -> Result<Size> {
1679 loop {
1680 let current_buffer = &mut [0; 1];
1681
1682 let size = file_system.read(file, current_buffer, time)?;
1683
1684 if size == 0 {
1685 yield_now().await; continue; }
1688
1689 let byte = current_buffer[0];
1690
1691 if byte == b'\n' || byte == b'\r' {
1692 break;
1693 }
1694
1695 buffer.push(byte as char);
1696 }
1697
1698 Ok(buffer.len().into())
1699}
1700
1701#[cfg(test)]
1702mod tests {
1703 use file_system::LocalFileIdentifier;
1704
1705 use super::*;
1706
1707 struct DummyFileSystem;
1708
1709 impl FileSystemTraits for DummyFileSystem {
1710 fn open(
1711 &self,
1712 _: TaskIdentifier,
1713 _: &Path,
1714 _: Flags,
1715 _: Time,
1716 _: UserIdentifier,
1717 _: GroupIdentifier,
1718 ) -> Result<LocalFileIdentifier> {
1719 todo!()
1720 }
1721
1722 fn close(&self, _: LocalFileIdentifier) -> Result<()> {
1723 todo!()
1724 }
1725
1726 fn close_all(&self, _: TaskIdentifier) -> Result<()> {
1727 todo!()
1728 }
1729
1730 fn duplicate(&self, _: LocalFileIdentifier) -> Result<LocalFileIdentifier> {
1731 todo!()
1732 }
1733
1734 fn transfert(
1735 &self,
1736 _: TaskIdentifier,
1737 _: LocalFileIdentifier,
1738 _: Option<FileIdentifier>,
1739 ) -> Result<LocalFileIdentifier> {
1740 todo!()
1741 }
1742
1743 fn remove(&self, _: &Path) -> Result<()> {
1744 todo!()
1745 }
1746
1747 fn read(&self, _: LocalFileIdentifier, _: &mut [u8], _: Time) -> Result<Size> {
1748 todo!()
1749 }
1750
1751 fn write(&self, _: LocalFileIdentifier, _: &[u8], _: Time) -> Result<Size> {
1752 todo!()
1753 }
1754
1755 fn rename(&self, _: &Path, _: &Path) -> Result<()> {
1756 todo!()
1757 }
1758
1759 fn set_position(&self, _: LocalFileIdentifier, _: &Position) -> Result<Size> {
1760 todo!()
1761 }
1762
1763 fn flush(&self, _: LocalFileIdentifier) -> Result<()> {
1764 todo!()
1765 }
1766
1767 fn create_directory(
1768 &self,
1769 _: &Path,
1770 _: Time,
1771 _: UserIdentifier,
1772 _: GroupIdentifier,
1773 ) -> Result<()> {
1774 todo!()
1775 }
1776
1777 fn open_directory(&self, _: &Path, _: TaskIdentifier) -> Result<LocalFileIdentifier> {
1778 todo!()
1779 }
1780
1781 fn read_directory(&self, _: LocalFileIdentifier) -> Result<Option<Entry>> {
1782 todo!()
1783 }
1784
1785 fn set_position_directory(&self, _: LocalFileIdentifier, _: Size) -> Result<()> {
1786 todo!()
1787 }
1788
1789 fn get_position_directory(&self, _: LocalFileIdentifier) -> Result<Size> {
1790 todo!()
1791 }
1792
1793 fn rewind_directory(&self, _: LocalFileIdentifier) -> Result<()> {
1794 todo!()
1795 }
1796
1797 fn close_directory(&self, _: LocalFileIdentifier) -> Result<()> {
1798 todo!()
1799 }
1800
1801 fn set_metadata_from_path(&self, _: &Path, _: &Metadata) -> Result<()> {
1802 todo!()
1803 }
1804
1805 fn get_metadata_from_path(&self, _: &Path) -> Result<Metadata> {
1806 todo!()
1807 }
1808
1809 fn get_statistics(&self, _: LocalFileIdentifier) -> Result<Statistics_type> {
1810 todo!()
1811 }
1812
1813 fn get_mode(&self, _: LocalFileIdentifier) -> Result<Mode> {
1814 todo!()
1815 }
1816
1817 fn get_metadata(&self, _: LocalFileIdentifier) -> Result<Metadata> {
1818 todo!()
1819 }
1820 }
1821
1822 #[test]
1823 fn test_get_file_system_from_path() {
1824 let mut file_systems: BTreeMap<FileSystemIdentifier, InternalFileSystem> = BTreeMap::new();
1825
1826 file_systems.insert(
1827 1.into(),
1828 InternalFileSystem {
1829 mount_point: PathOwned::new("/".to_string()).unwrap(),
1830 inner: Box::new(DummyFileSystem),
1831 },
1832 );
1833
1834 file_systems.insert(
1835 2.into(),
1836 InternalFileSystem {
1837 mount_point: PathOwned::new("/Foo".to_string()).unwrap(),
1838 inner: Box::new(DummyFileSystem),
1839 },
1840 );
1841
1842 file_systems.insert(
1843 3.into(),
1844 InternalFileSystem {
1845 mount_point: PathOwned::new("/Foo/Bar".to_string()).unwrap(),
1846 inner: Box::new(DummyFileSystem),
1847 },
1848 );
1849
1850 let (file_system, _, relative_path) =
1851 VirtualFileSystem::get_file_system_from_path(&file_systems, &"/").unwrap();
1852
1853 assert_eq!(file_system, 1.into());
1854 assert_eq!(relative_path, Path::ROOT);
1855
1856 let (file_system, _, relative_path) =
1857 VirtualFileSystem::get_file_system_from_path(&file_systems, &"/Foo/Bar").unwrap();
1858
1859 assert_eq!(file_system, 3.into());
1860 assert_eq!(relative_path, Path::ROOT);
1861
1862 let (file_system, _, relative_path) =
1863 VirtualFileSystem::get_file_system_from_path(&file_systems, &"/Foo/Bar/Baz").unwrap();
1864
1865 assert_eq!(file_system, 3.into());
1866 assert_eq!(relative_path, "/Baz".as_ref());
1867
1868 let (file_system, _, relative_path) =
1869 VirtualFileSystem::get_file_system_from_path(&file_systems, &"/Foo").unwrap();
1870
1871 assert_eq!(file_system, 2.into());
1872 assert_eq!(relative_path, Path::ROOT);
1873 }
1874}