starry_api/imp/fs/
mount.rs1use core::ffi::{c_char, c_void};
2
3use alloc::vec::Vec;
4use axerrno::{LinuxError, LinuxResult};
5use axsync::Mutex;
6use linux_raw_sys::general::AT_FDCWD;
7
8use crate::{
9 path::{FilePath, handle_file_path},
10 ptr::UserConstPtr,
11};
12
13pub fn sys_mount(
14 source: UserConstPtr<c_char>,
15 target: UserConstPtr<c_char>,
16 fs_type: UserConstPtr<c_char>,
17 flags: i32,
18 _data: UserConstPtr<c_void>,
19) -> LinuxResult<isize> {
20 let source = source.get_as_str()?;
21 let target = target.get_as_str()?;
22 let fs_type = fs_type.get_as_str()?;
23 info!(
24 "sys_mount <= source: {}, target: {}, fs_type: {}, flags: {}",
25 source, target, fs_type, flags
26 );
27
28 let device_path = handle_file_path(AT_FDCWD, source)?;
29 let mount_path = handle_file_path(AT_FDCWD, target)?;
30 info!(
31 "mount {:?} to {:?} with fs_type={:?}",
32 device_path, mount_path, fs_type
33 );
34
35 if fs_type != "vfat" {
36 debug!("fs_type can only be vfat.");
37 return Err(LinuxError::EPERM);
38 }
39
40 if !mount_path.exists() {
41 debug!("mount path not exist");
42 return Err(LinuxError::EPERM);
43 }
44
45 if check_mounted(&mount_path) {
46 debug!("mount path includes mounted fs");
47 return Err(LinuxError::EPERM);
48 }
49
50 if !mount_fat_fs(&device_path, &mount_path) {
51 debug!("mount error");
52 return Err(LinuxError::EPERM);
53 }
54 Ok(0)
55}
56
57pub fn sys_umount2(target: UserConstPtr<c_char>, flags: i32) -> LinuxResult<isize> {
58 let target = target.get_as_str()?;
59 info!("sys_umount2 <= target: {}, flags: {}", target, flags);
60
61 let mount_path = handle_file_path(AT_FDCWD, target)?;
62 if flags != 0 {
63 debug!("flags unimplemented");
64 return Err(LinuxError::EPERM);
65 }
66
67 if !mount_path.exists() {
68 debug!("mount path not exist");
69 return Err(LinuxError::EPERM);
70 }
71
72 if !umount_fat_fs(&mount_path) {
73 debug!("umount error");
74 return Err(LinuxError::EPERM);
75 }
76 Ok(0)
77}
78
79struct MountedFs {
82 pub device: FilePath,
84 pub mnt_dir: FilePath,
85}
86
87impl MountedFs {
88 pub fn new(device: &FilePath, mnt_dir: &FilePath) -> Self {
89 Self {
90 device: device.clone(),
91 mnt_dir: mnt_dir.clone(),
92 }
93 }
94
95 #[allow(unused)]
96 pub fn device(&self) -> FilePath {
97 self.device.clone()
98 }
99
100 pub fn mnt_dir(&self) -> FilePath {
101 self.mnt_dir.clone()
102 }
103}
104
105static MOUNTED: Mutex<Vec<MountedFs>> = Mutex::new(Vec::new());
108
109pub fn mount_fat_fs(device_path: &FilePath, mount_path: &FilePath) -> bool {
111 if mount_path.exists() {
116 MOUNTED.lock().push(MountedFs::new(device_path, mount_path));
117 info!(
118 "mounted {} to {}",
119 device_path.as_str(),
120 mount_path.as_str()
121 );
122 return true;
123 }
124 info!(
125 "mount failed: {} to {}",
126 device_path.as_str(),
127 mount_path.as_str()
128 );
129 false
130}
131
132pub fn umount_fat_fs(mount_path: &FilePath) -> bool {
134 let mut mounted = MOUNTED.lock();
135 let length_before_deletion = mounted.len();
136 mounted.retain(|m| m.mnt_dir() != *mount_path);
137 length_before_deletion > mounted.len()
138}
139
140pub fn check_mounted(path: &FilePath) -> bool {
142 let mounted = MOUNTED.lock();
143 mounted.iter().any(|m| path.starts_with(&m.mnt_dir()))
144}