starnix_core/vfs/
fs_registry.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::security;
6use crate::task::CurrentTask;
7use crate::vfs::{FileSystemHandle, FileSystemOptions, FsStr, FsString};
8use starnix_sync::{Locked, Mutex, Unlocked};
9use starnix_uapi::errors::Errno;
10use std::collections::BTreeMap;
11use std::sync::Arc;
12
13type CreateFs = Arc<
14    dyn Fn(
15            &mut Locked<Unlocked>,
16            &CurrentTask,
17            FileSystemOptions,
18        ) -> Result<FileSystemHandle, Errno>
19        + Send
20        + Sync
21        + 'static,
22>;
23
24#[derive(Default)]
25pub struct FsRegistry {
26    registry: Mutex<BTreeMap<FsString, CreateFs>>,
27}
28
29impl FsRegistry {
30    pub fn register<F>(&self, fs_type: &FsStr, create_fs: F)
31    where
32        F: Fn(
33                &mut Locked<Unlocked>,
34                &CurrentTask,
35                FileSystemOptions,
36            ) -> Result<FileSystemHandle, Errno>
37            + Send
38            + Sync
39            + 'static,
40    {
41        let existing = self.registry.lock().insert(fs_type.into(), Arc::new(create_fs));
42        assert!(existing.is_none());
43    }
44
45    pub fn create(
46        &self,
47        locked: &mut Locked<Unlocked>,
48        current_task: &CurrentTask,
49        fs_type: &FsStr,
50        options: FileSystemOptions,
51    ) -> Option<Result<FileSystemHandle, Errno>> {
52        let create_fs = self.registry.lock().get(fs_type).map(Arc::clone)?;
53        Some(create_fs(locked, current_task, options).and_then(|fs| {
54            assert_eq!(fs_type, fs.name(), "FileSystem::name() must match the registered name.");
55            security::file_system_resolve_security(locked, &current_task, &fs)?;
56            Ok(fs)
57        }))
58    }
59
60    pub fn list_all(&self) -> Vec<FsString> {
61        self.registry.lock().keys().cloned().collect()
62    }
63}