virtual_file_system/
file_system.rs

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
35/// Instance of the virtual file system.
36///
37/// # Safety
38/// I know, it is not safe to use mutable static variables.
39/// It is thread safe (after initialization) because it is only read after initialization.
40/// It is a pragmatic choice for efficiency in embedded systems contexts (avoid using Arc).
41static 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
64/// The virtual file system.
65///
66/// It is a singleton.
67pub struct VirtualFileSystem<'a> {
68    /// Mounted file systems.
69    file_systems:
70        RwLock<CriticalSectionRawMutex, BTreeMap<FileSystemIdentifier, InternalFileSystem>>,
71    /// Devices.
72    device_file_system: device::FileSystem<'a>,
73    /// Pipes.
74    pipe_file_system: pipe::FileSystem,
75    /// Network sockets.
76    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    /// Mount a file system at a given mount point.
155    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; // Get the file systems
172
173        // Create a directory in the underlying file system
174        let (_, parent_file_system, relative_path) =
175            Self::get_file_system_from_path(&file_systems, &path)?; // Get the file system identifier and the relative path
176
177        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        // Create a directory at the mount point
189        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; // Get the file systems
215
216        let file_system_identifier = {
217            let (file_system_identifier, _, relative_path) =
218                Self::get_file_system_from_path(&file_systems, &path)?; // Get the file system identifier and the relative path
219
220            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; // Get the file systems
289
290        let (file_system_identifier, file_system, relative_path) =
291            Self::get_file_system_from_path(&file_systems, path)?; // Get the file system identifier and the relative path
292
293        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        // - If there is an underlying file (some pipe and devices), close it too.
381        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; // Get the file systems
475
476                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; // Get the file systems
628
629        let (_, file_system, relative_path) =
630            Self::get_file_system_from_path(&file_systems, &path)?; // Get the file system identifier and the relative path
631
632        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; // Get the file systems
651
652        let (_, file_system, relative_path) =
653            Self::get_file_system_from_path(&file_systems, &path)?; // Get the file system identifier and the relative path
654
655        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; // Get the file systems
664
665        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; // Get the file systems
683
684        let (_, file_system, relative_path) =
685            Self::get_file_system_from_path(&file_systems, &path)?; // Get the file system identifier and the relative path
686
687        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; // Get the file systems
737
738        // Create a special file in the underlying file system.
739        let (_, file_system, relative_path) =
740            Self::get_file_system_from_path(&file_systems, &path)?; // Get the file system identifier and the relative path
741
742        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        // Create the actual device.
769        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        // Set the metadata of the special file.
784        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; // Get the file systems
800
801        let (_, file_system, relative_path) = Self::get_file_system_from_path(&file_systems, path)?; // Get the file system identifier and the relative path
802
803        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; // Get the file systems
862
863        // - Check metadata on the underlying file system
864        let (_, file_system, relative_path) =
865            Self::get_file_system_from_path(&file_systems, &path)?; // Get the file system identifier and the relative path
866
867        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; // Get the file systems
1041
1042        let (file_system_identifier, file_system, relative_path) =
1043            Self::get_file_system_from_path(&file_systems, path)?; // Get the file system identifier and the relative path
1044
1045        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; // Get the file systems
1164
1165        let (_, file_system, relative_path) = Self::get_file_system_from_path(&file_systems, path)?; // Get the file system identifier and the relative path
1166
1167        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; // Get the file systems
1335
1336        let (old_file_system_identifier, old_file_system, old_relative_path) =
1337            Self::get_file_system_from_path(&file_systems, old_path)?; // Get the file system identifier and the relative path
1338
1339        let (new_file_system_identifier, _, new_relative_path) =
1340            Self::get_file_system_from_path(&file_systems, new_path)?; // Get the file system identifier and the relative path
1341
1342        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) // TODO : Add support for moving between file systems
1350        }
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)?; // Get the file system identifier and the relative path
1357
1358        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)?; // Get the file system identifier and the relative path
1376
1377        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)?; // Get the file system identifier and the relative path
1388
1389        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; // Yield to allow other tasks to run, especially in a blocking operation
1686            continue; // Retry reading if no data was read
1687        }
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}