strat9_kernel/vfs/
mount.rs1use super::scheme::DynScheme;
6use crate::syscall::error::SyscallError;
7use alloc::{string::String, vec::Vec};
8use spin::{Lazy, RwLock};
9
10#[derive(Clone)]
12struct Mount {
13 prefix: String,
15 scheme: DynScheme,
17}
18
19pub struct MountTable {
21 mounts: Vec<Mount>,
22}
23
24impl MountTable {
25 pub fn new() -> Self {
27 MountTable { mounts: Vec::new() }
28 }
29
30 pub fn mount(&mut self, prefix: &str, scheme: DynScheme) -> Result<(), SyscallError> {
34 if prefix.is_empty() || !prefix.starts_with('/') {
35 return Err(SyscallError::InvalidArgument);
36 }
37
38 let prefix = if prefix.len() > 1 && prefix.ends_with('/') {
40 &prefix[..prefix.len() - 1]
41 } else {
42 prefix
43 };
44
45 if self.mounts.iter().any(|m| m.prefix == prefix) {
47 return Err(SyscallError::AlreadyExists);
48 }
49
50 self.mounts.push(Mount {
51 prefix: String::from(prefix),
52 scheme,
53 });
54
55 self.mounts
57 .sort_by(|a, b| b.prefix.len().cmp(&a.prefix.len()));
58
59 Ok(())
60 }
61
62 pub fn unmount(&mut self, prefix: &str) -> Result<(), SyscallError> {
64 let pos = self
65 .mounts
66 .iter()
67 .position(|m| m.prefix == prefix)
68 .ok_or(SyscallError::BadHandle)?;
69 self.mounts.remove(pos);
70 Ok(())
71 }
72
73 pub fn resolve(&self, path: &str) -> Result<(DynScheme, String), SyscallError> {
77 if !path.starts_with('/') {
78 return Err(SyscallError::InvalidArgument);
79 }
80
81 for mount in &self.mounts {
82 if path == mount.prefix {
83 return Ok((mount.scheme.clone(), String::new()));
84 } else if path.starts_with(&mount.prefix) {
85 let is_root = mount.prefix == "/";
86 let next_byte = path.as_bytes().get(mount.prefix.len());
87 if is_root || next_byte == Some(&b'/') {
88 let relative = if is_root {
89 &path[1..]
90 } else {
91 &path[mount.prefix.len() + 1..]
92 };
93 return Ok((mount.scheme.clone(), String::from(relative)));
94 }
95 }
96 }
97
98 Err(SyscallError::NotFound)
99 }
100
101 pub fn list(&self) -> Vec<String> {
103 self.mounts.iter().map(|m| m.prefix.clone()).collect()
104 }
105}
106
107static GLOBAL_MOUNTS: Lazy<RwLock<MountTable>> = Lazy::new(|| RwLock::new(MountTable::new()));
108
109pub fn mount(prefix: &str, scheme: DynScheme) -> Result<(), SyscallError> {
111 GLOBAL_MOUNTS.write().mount(prefix, scheme)
112}
113
114pub fn unmount(prefix: &str) -> Result<(), SyscallError> {
116 GLOBAL_MOUNTS.write().unmount(prefix)
117}
118
119pub fn resolve(path: &str) -> Result<(DynScheme, String), SyscallError> {
121 GLOBAL_MOUNTS.read().resolve(path)
122}
123
124pub fn list_mounts() -> Vec<String> {
126 GLOBAL_MOUNTS.read().list()
127}
128
129pub struct Namespace {
137 mounts: MountTable,
138}
139
140impl Namespace {
141 pub fn new() -> Self {
143 Namespace {
144 mounts: MountTable::new(),
145 }
146 }
147
148 pub fn from_global() -> Self {
150 let global = GLOBAL_MOUNTS.read();
151 Namespace {
152 mounts: MountTable {
153 mounts: global.mounts.clone(),
154 },
155 }
156 }
157
158 pub fn mount(&mut self, prefix: &str, scheme: DynScheme) -> Result<(), SyscallError> {
160 self.mounts.mount(prefix, scheme)
161 }
162
163 pub fn unmount(&mut self, prefix: &str) -> Result<(), SyscallError> {
165 self.mounts.unmount(prefix)
166 }
167
168 pub fn resolve(&self, path: &str) -> Result<(DynScheme, String), SyscallError> {
170 self.mounts.resolve(path)
171 }
172}
173
174impl Default for Namespace {
175 fn default() -> Self {
177 Self::new()
178 }
179}