mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-14 07:56:47 +00:00
添加access、faccessat、faccessat2 (#439)
This commit is contained in:
parent
0d9b7d9240
commit
9b0abe6da7
@ -13,7 +13,10 @@ use alloc::string::String;
|
|||||||
|
|
||||||
use super::{interrupt::TrapFrame, mm::barrier::mfence};
|
use super::{interrupt::TrapFrame, mm::barrier::mfence};
|
||||||
|
|
||||||
|
pub const SYS_ACCESS: usize = 21;
|
||||||
pub const SYS_PRLIMIT64: usize = 302;
|
pub const SYS_PRLIMIT64: usize = 302;
|
||||||
|
pub const SYS_FACCESSAT: usize = 269;
|
||||||
|
pub const SYS_FACCESSAT2: usize = 439;
|
||||||
|
|
||||||
/// ### 存储PCB系统调用栈以及在syscall过程中暂存用户态rsp的结构体
|
/// ### 存储PCB系统调用栈以及在syscall过程中暂存用户态rsp的结构体
|
||||||
///
|
///
|
||||||
|
@ -58,55 +58,48 @@ pub enum FcntlCommand {
|
|||||||
SetFileRwHint = F_LINUX_SPECIFIC_BASE + 14,
|
SetFileRwHint = F_LINUX_SPECIFIC_BASE + 14,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The constants AT_REMOVEDIR and AT_EACCESS have the same value. AT_EACCESS is
|
bitflags! {
|
||||||
/// meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
|
|
||||||
/// unlinkat. The two functions do completely different things and therefore,
|
|
||||||
/// the flags can be allowed to overlap. For example, passing AT_REMOVEDIR to
|
|
||||||
/// faccessat would be undefined behavior and thus treating it equivalent to
|
|
||||||
/// AT_EACCESS is valid undefined behavior.
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, FromPrimitive, ToPrimitive)]
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
pub enum AtFlags {
|
|
||||||
/// 特殊值,用于指示openat应使用当前工作目录。
|
|
||||||
AtFdCwd = -100,
|
|
||||||
/// 不要跟随符号链接。
|
|
||||||
/// AT_SYMLINK_NOFOLLOW: 0x100
|
|
||||||
AtSymlinkNoFollow = 0x100,
|
|
||||||
/// AtEAccess: 使用有效ID进行访问测试,而不是实际ID。
|
|
||||||
/// AtRemoveDir: 删除目录而不是取消链接文件。
|
|
||||||
/// AT_EACCESS: 0x200
|
|
||||||
/// AT_REMOVEDIR: 0x200
|
|
||||||
AtEAccess_OR_AtRemoveDir = 0x200,
|
|
||||||
|
|
||||||
/// 跟随符号链接。
|
/// The constants AT_REMOVEDIR and AT_EACCESS have the same value. AT_EACCESS is
|
||||||
/// AT_SYMLINK_FOLLOW: 0x400
|
/// meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
|
||||||
AtSymlinkFollow = 0x400,
|
/// unlinkat. The two functions do completely different things and therefore,
|
||||||
/// 禁止终端自动挂载遍历。
|
/// the flags can be allowed to overlap. For example, passing AT_REMOVEDIR to
|
||||||
/// AT_NO_AUTOMOUNT: 0x800
|
/// faccessat would be undefined behavior and thus treating it equivalent to
|
||||||
AtNoAutomount = 0x800,
|
/// AT_EACCESS is valid undefined behavior.
|
||||||
/// 允许空的相对路径名。
|
pub struct AtFlags: i32 {
|
||||||
/// AT_EMPTY_PATH: 0x1000
|
/// 特殊值,用于指示openat应使用当前工作目录。
|
||||||
AtEmptyPath = 0x1000,
|
const AT_FDCWD = -100;
|
||||||
/// statx()所需的同步类型。
|
/// 不要跟随符号链接。
|
||||||
/// AT_STATX_SYNC_TYPE: 0x6000
|
const AT_SYMLINK_NOFOLLOW = 0x100;
|
||||||
AtStatxSyncType = 0x6000,
|
/// AtEAccess: 使用有效ID进行访问测试,而不是实际ID。
|
||||||
/// 执行与stat()相同的操作。
|
const AT_EACCESS = 0x200;
|
||||||
/// AT_STATX_SYNC_AS_STAT: 0x0000
|
/// AtRemoveDir: 删除目录而不是取消链接文件。
|
||||||
AtStatxSyncAsStat = 0x0000,
|
const AT_REMOVEDIR = 0x200;
|
||||||
/// 强制将属性与服务器同步。
|
|
||||||
/// AT_STATX_FORCE_SYNC: 0x2000
|
|
||||||
AtStatxForceSync = 0x2000,
|
|
||||||
/// 不要将属性与服务器同步。
|
|
||||||
/// AT_STATX_DONT_SYNC: 0x4000
|
|
||||||
AtStatxDontSync = 0x4000,
|
|
||||||
/// 应用于整个子树。
|
|
||||||
/// AT_RECURSIVE: 0x8000
|
|
||||||
AtRecursive = 0x8000,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<i32> for AtFlags {
|
/// 跟随符号链接。
|
||||||
fn into(self) -> i32 {
|
/// AT_SYMLINK_FOLLOW: 0x400
|
||||||
self as i32
|
const AT_SYMLINK_FOLLOW = 0x400;
|
||||||
|
/// 禁止终端自动挂载遍历。
|
||||||
|
/// AT_NO_AUTOMOUNT: 0x800
|
||||||
|
const AT_NO_AUTOMOUNT = 0x800;
|
||||||
|
/// 允许空的相对路径名。
|
||||||
|
/// AT_EMPTY_PATH: 0x1000
|
||||||
|
const AT_EMPTY_PATH = 0x1000;
|
||||||
|
/// statx()所需的同步类型。
|
||||||
|
/// AT_STATX_SYNC_TYPE: 0x6000
|
||||||
|
const AT_STATX_SYNC_TYPE = 0x6000;
|
||||||
|
/// 执行与stat()相同的操作。
|
||||||
|
/// AT_STATX_SYNC_AS_STAT: 0x0000
|
||||||
|
const AT_STATX_SYNC_AS_STAT = 0x0000;
|
||||||
|
/// 强制将属性与服务器同步。
|
||||||
|
/// AT_STATX_FORCE_SYNC: 0x2000
|
||||||
|
const AT_STATX_FORCE_SYNC = 0x2000;
|
||||||
|
/// 不要将属性与服务器同步。
|
||||||
|
/// AT_STATX_DONT_SYNC: 0x4000
|
||||||
|
const AT_STATX_DONT_SYNC = 0x4000;
|
||||||
|
/// 应用于整个子树。
|
||||||
|
/// AT_RECURSIVE: 0x8000
|
||||||
|
const AT_RECURSIVE = 0x8000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ pub mod core;
|
|||||||
pub mod fcntl;
|
pub mod fcntl;
|
||||||
pub mod file;
|
pub mod file;
|
||||||
pub mod mount;
|
pub mod mount;
|
||||||
|
pub mod open;
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
|
27
kernel/src/filesystem/vfs/open.rs
Normal file
27
kernel/src/filesystem/vfs/open.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use crate::syscall::SystemError;
|
||||||
|
|
||||||
|
use super::{fcntl::AtFlags, syscall::ModeType};
|
||||||
|
|
||||||
|
pub(super) fn do_faccessat(
|
||||||
|
_dirfd: i32,
|
||||||
|
_pathname: *const u8,
|
||||||
|
mode: ModeType,
|
||||||
|
flags: u32,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
if (mode.bits() & (!ModeType::S_IXUGO.bits())) != 0 {
|
||||||
|
return Err(SystemError::EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags
|
||||||
|
& (!((AtFlags::AT_EACCESS | AtFlags::AT_SYMLINK_NOFOLLOW | AtFlags::AT_EMPTY_PATH).bits()
|
||||||
|
as u32)))
|
||||||
|
!= 0
|
||||||
|
{
|
||||||
|
return Err(SystemError::EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// let follow_symlink = flags & AtFlags::AT_SYMLINK_NOFOLLOW.bits() as u32 == 0;
|
||||||
|
|
||||||
|
// todo: 接着完善(可以借鉴linux 6.1.9的do_faccessat)
|
||||||
|
return Ok(0);
|
||||||
|
}
|
@ -25,7 +25,8 @@ use super::{
|
|||||||
core::{do_mkdir, do_remove_dir, do_unlink_at},
|
core::{do_mkdir, do_remove_dir, do_unlink_at},
|
||||||
fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC},
|
fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC},
|
||||||
file::{File, FileMode},
|
file::{File, FileMode},
|
||||||
utils::rsplit_path,
|
open::do_faccessat,
|
||||||
|
utils::{rsplit_path, user_path_at},
|
||||||
Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES,
|
Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES,
|
||||||
};
|
};
|
||||||
// use crate::kdebug;
|
// use crate::kdebug;
|
||||||
@ -804,41 +805,14 @@ impl Syscall {
|
|||||||
user_buf: *mut u8,
|
user_buf: *mut u8,
|
||||||
buf_size: usize,
|
buf_size: usize,
|
||||||
) -> Result<usize, SystemError> {
|
) -> Result<usize, SystemError> {
|
||||||
let mut path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
|
let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
|
||||||
let mut user_buf = UserBufferWriter::new(user_buf, buf_size, true)?;
|
let mut user_buf = UserBufferWriter::new(user_buf, buf_size, true)?;
|
||||||
|
|
||||||
if path.len() == 0 {
|
if path.len() == 0 {
|
||||||
return Err(SystemError::EINVAL);
|
return Err(SystemError::EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut inode = ROOT_INODE();
|
let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
|
||||||
// 如果path不是绝对路径,则需要拼接
|
|
||||||
if path.as_bytes()[0] != b'/' {
|
|
||||||
// 如果dirfd不是AT_FDCWD,则需要检查dirfd是否是目录
|
|
||||||
if dirfd != AtFlags::AtFdCwd.into() {
|
|
||||||
let binding = ProcessManager::current_pcb().fd_table();
|
|
||||||
let fd_table_guard = binding.read();
|
|
||||||
let file = fd_table_guard
|
|
||||||
.get_file_by_fd(dirfd)
|
|
||||||
.ok_or(SystemError::EBADF)?;
|
|
||||||
|
|
||||||
// drop guard 以避免无法调度的问题
|
|
||||||
drop(fd_table_guard);
|
|
||||||
|
|
||||||
let file_guard = file.lock();
|
|
||||||
// 如果dirfd不是目录,则返回错误码ENOTDIR
|
|
||||||
if file_guard.file_type() != FileType::Dir {
|
|
||||||
return Err(SystemError::ENOTDIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
inode = file_guard.inode();
|
|
||||||
} else {
|
|
||||||
let mut cwd = ProcessManager::current_pcb().basic().cwd();
|
|
||||||
cwd.push('/');
|
|
||||||
cwd.push_str(path.as_str());
|
|
||||||
path = cwd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let inode = inode.lookup(path.as_str())?;
|
let inode = inode.lookup(path.as_str())?;
|
||||||
if inode.metadata()?.file_type != FileType::SymLink {
|
if inode.metadata()?.file_type != FileType::SymLink {
|
||||||
@ -859,7 +833,25 @@ impl Syscall {
|
|||||||
user_buf: *mut u8,
|
user_buf: *mut u8,
|
||||||
buf_size: usize,
|
buf_size: usize,
|
||||||
) -> Result<usize, SystemError> {
|
) -> Result<usize, SystemError> {
|
||||||
return Self::readlink_at(AtFlags::AtFdCwd.into(), path, user_buf, buf_size);
|
return Self::readlink_at(AtFlags::AT_FDCWD.bits(), path, user_buf, buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn access(pathname: *const u8, mode: u32) -> Result<usize, SystemError> {
|
||||||
|
return do_faccessat(
|
||||||
|
AtFlags::AT_FDCWD.bits(),
|
||||||
|
pathname,
|
||||||
|
ModeType::from_bits_truncate(mode),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn faccessat2(
|
||||||
|
dirfd: i32,
|
||||||
|
pathname: *const u8,
|
||||||
|
mode: u32,
|
||||||
|
flags: u32,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
return do_faccessat(dirfd, pathname, ModeType::from_bits_truncate(mode), flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
use alloc::{string::String, sync::Arc};
|
||||||
|
|
||||||
|
use crate::{process::ProcessControlBlock, syscall::SystemError};
|
||||||
|
|
||||||
|
use super::{fcntl::AtFlags, FileType, IndexNode, ROOT_INODE};
|
||||||
|
|
||||||
/// @brief 切分路径字符串,返回最左侧那一级的目录名和剩余的部分。
|
/// @brief 切分路径字符串,返回最左侧那一级的目录名和剩余的部分。
|
||||||
///
|
///
|
||||||
/// 举例:对于 /123/456/789/ 本函数返回的第一个值为123, 第二个值为456/789
|
/// 举例:对于 /123/456/789/ 本函数返回的第一个值为123, 第二个值为456/789
|
||||||
@ -19,3 +25,45 @@ pub fn rsplit_path(path: &str) -> (&str, Option<&str>) {
|
|||||||
|
|
||||||
return (comp, rest_opt);
|
return (comp, rest_opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 根据dirfd和path,计算接下来开始lookup的inode和剩余的path
|
||||||
|
///
|
||||||
|
/// ## 返回值
|
||||||
|
///
|
||||||
|
/// 返回值为(需要lookup的inode, 剩余的path)
|
||||||
|
pub fn user_path_at(
|
||||||
|
pcb: &Arc<ProcessControlBlock>,
|
||||||
|
dirfd: i32,
|
||||||
|
mut path: String,
|
||||||
|
) -> Result<(Arc<dyn IndexNode>, String), SystemError> {
|
||||||
|
let mut inode = ROOT_INODE();
|
||||||
|
// 如果path不是绝对路径,则需要拼接
|
||||||
|
if path.as_bytes()[0] != b'/' {
|
||||||
|
// 如果dirfd不是AT_FDCWD,则需要检查dirfd是否是目录
|
||||||
|
if dirfd != AtFlags::AT_FDCWD.bits() {
|
||||||
|
let binding = pcb.fd_table();
|
||||||
|
let fd_table_guard = binding.read();
|
||||||
|
let file = fd_table_guard
|
||||||
|
.get_file_by_fd(dirfd)
|
||||||
|
.ok_or(SystemError::EBADF)?;
|
||||||
|
|
||||||
|
// drop guard 以避免无法调度的问题
|
||||||
|
drop(fd_table_guard);
|
||||||
|
|
||||||
|
let file_guard = file.lock();
|
||||||
|
// 如果dirfd不是目录,则返回错误码ENOTDIR
|
||||||
|
if file_guard.file_type() != FileType::Dir {
|
||||||
|
return Err(SystemError::ENOTDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
inode = file_guard.inode();
|
||||||
|
} else {
|
||||||
|
let mut cwd = pcb.basic().cwd();
|
||||||
|
cwd.push('/');
|
||||||
|
cwd.push_str(path.as_str());
|
||||||
|
path = cwd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok((inode, path));
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@ use core::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::syscall::SYS_PRLIMIT64,
|
arch::syscall::{SYS_ACCESS, SYS_FACCESSAT, SYS_FACCESSAT2, SYS_PRLIMIT64},
|
||||||
libs::{futex::constant::FutexFlag, rand::GRandFlags},
|
libs::{futex::constant::FutexFlag, rand::GRandFlags},
|
||||||
process::{
|
process::{
|
||||||
fork::KernelCloneArgs,
|
fork::KernelCloneArgs,
|
||||||
@ -1204,6 +1204,27 @@ impl Syscall {
|
|||||||
Self::prlimit64(pid, resource, new_limit, old_limit)
|
Self::prlimit64(pid, resource, new_limit, old_limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SYS_ACCESS => {
|
||||||
|
let pathname = args[0] as *const u8;
|
||||||
|
let mode = args[1] as u32;
|
||||||
|
Self::access(pathname, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_FACCESSAT => {
|
||||||
|
let dirfd = args[0] as i32;
|
||||||
|
let pathname = args[1] as *const u8;
|
||||||
|
let mode = args[2] as u32;
|
||||||
|
Self::faccessat2(dirfd, pathname, mode, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_FACCESSAT2 => {
|
||||||
|
let dirfd = args[0] as i32;
|
||||||
|
let pathname = args[1] as *const u8;
|
||||||
|
let mode = args[2] as u32;
|
||||||
|
let flags = args[3] as u32;
|
||||||
|
Self::faccessat2(dirfd, pathname, mode, flags)
|
||||||
|
}
|
||||||
|
|
||||||
_ => panic!("Unsupported syscall ID: {}", syscall_num),
|
_ => panic!("Unsupported syscall ID: {}", syscall_num),
|
||||||
};
|
};
|
||||||
return r;
|
return r;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user