105 lines
3.1 KiB
Rust
105 lines
3.1 KiB
Rust
//! System call handler for sys_umount.
|
|
|
|
use crate::{
|
|
arch::{interrupt::TrapFrame, syscall::nr::SYS_UMOUNT2},
|
|
filesystem::vfs::{
|
|
fcntl::AtFlags, mount::MOUNT_LIST, utils::user_path_at, MountFS, MAX_PATHLEN,
|
|
},
|
|
process::ProcessManager,
|
|
syscall::{
|
|
table::{FormattedSyscallParam, Syscall},
|
|
user_access,
|
|
},
|
|
};
|
|
use alloc::{sync::Arc, vec::Vec};
|
|
use system_error::SystemError;
|
|
|
|
/// src/linux/mount.c `umount` & `umount2`
|
|
///
|
|
/// [umount(2) — Linux manual page](https://www.man7.org/linux/man-pages/man2/umount.2.html)
|
|
pub struct SysUmount2Handle;
|
|
|
|
impl Syscall for SysUmount2Handle {
|
|
fn num_args(&self) -> usize {
|
|
2
|
|
}
|
|
|
|
fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result<usize, SystemError> {
|
|
let target = Self::target(args);
|
|
let flags = Self::flags(args);
|
|
|
|
let target = user_access::check_and_clone_cstr(target, Some(MAX_PATHLEN))?
|
|
.into_string()
|
|
.map_err(|_| SystemError::EINVAL)?;
|
|
do_umount2(
|
|
AtFlags::AT_FDCWD.bits(),
|
|
&target,
|
|
UmountFlag::from_bits(flags).ok_or(SystemError::EINVAL)?,
|
|
)?;
|
|
return Ok(0);
|
|
}
|
|
|
|
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
|
vec![
|
|
FormattedSyscallParam::new("target", format!("{:#x}", Self::target(args) as usize)),
|
|
FormattedSyscallParam::new("flags", format!("{:#x}", Self::flags(args))),
|
|
]
|
|
}
|
|
}
|
|
|
|
impl SysUmount2Handle {
|
|
fn target(args: &[usize]) -> *const u8 {
|
|
args[0] as *const u8
|
|
}
|
|
|
|
fn flags(args: &[usize]) -> i32 {
|
|
args[1] as i32
|
|
}
|
|
}
|
|
|
|
syscall_table_macros::declare_syscall!(SYS_UMOUNT2, SysUmount2Handle);
|
|
|
|
/// # do_umount2 - 执行卸载文件系统的函数
|
|
///
|
|
/// 这个函数用于卸载指定的文件系统。
|
|
///
|
|
/// ## 参数
|
|
///
|
|
/// - dirfd: i32 - 目录文件描述符,用于指定要卸载的文件系统的根目录。
|
|
/// - target: &str - 要卸载的文件系统的目标路径。
|
|
/// - _flag: UmountFlag - 卸载标志,目前未使用。
|
|
///
|
|
/// ## 返回值
|
|
///
|
|
/// - Ok(Arc<MountFS>): 成功时返回文件系统的 Arc 引用。
|
|
/// - Err(SystemError): 出错时返回系统错误。
|
|
///
|
|
/// ## 错误处理
|
|
///
|
|
/// 如果指定的路径没有对应的文件系统,或者在尝试卸载时发生错误,将返回错误。
|
|
pub fn do_umount2(
|
|
dirfd: i32,
|
|
target: &str,
|
|
_flag: UmountFlag,
|
|
) -> Result<Arc<MountFS>, SystemError> {
|
|
let (work, rest) = user_path_at(&ProcessManager::current_pcb(), dirfd, target)?;
|
|
let path = work.absolute_path()? + &rest;
|
|
|
|
if let Some(fs) = MOUNT_LIST().remove(path) {
|
|
// Todo: 占用检测
|
|
fs.umount()?;
|
|
return Ok(fs);
|
|
}
|
|
return Err(SystemError::EINVAL);
|
|
}
|
|
|
|
bitflags! {
|
|
pub struct UmountFlag: i32 {
|
|
const DEFAULT = 0; /* Default call to umount. */
|
|
const MNT_FORCE = 1; /* Force unmounting. */
|
|
const MNT_DETACH = 2; /* Just detach from the tree. */
|
|
const MNT_EXPIRE = 4; /* Mark for expiry. */
|
|
const UMOUNT_NOFOLLOW = 8; /* Don't follow symlink on umount. */
|
|
}
|
|
}
|