Skip to content

Commit

Permalink
完善pipe系统调用以及openat系统调用 (#441)
Browse files Browse the repository at this point in the history
  • Loading branch information
fslongjin authored Nov 15, 2023
1 parent bf4a489 commit 0fb515b
Show file tree
Hide file tree
Showing 7 changed files with 302 additions and 125 deletions.
1 change: 1 addition & 0 deletions kernel/src/arch/x86_64/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub const SYS_FCHMOD: usize = 91;
pub const SYS_UMASK: usize = 95;
pub const SYS_SYSINFO: usize = 99;
pub const SYS_CLOCK_GETTIME: usize = 228;
pub const SYS_OPENAT: usize = 257;
pub const SYS_FCHMODAT: usize = 268;
pub const SYS_FACCESSAT: usize = 269;
pub const SYS_PRLIMIT64: usize = 302;
Expand Down
4 changes: 2 additions & 2 deletions kernel/src/filesystem/vfs/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ pub fn do_remove_dir(dirfd: i32, path: &str) -> Result<u64, SystemError> {
}

let pcb = ProcessManager::current_pcb();
let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path.to_string())?;
let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path)?;

let inode: Result<Arc<dyn IndexNode>, SystemError> =
inode_begin.lookup_follow_symlink(remain_path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES);
Expand Down Expand Up @@ -258,7 +258,7 @@ pub fn do_unlink_at(dirfd: i32, path: &str) -> Result<u64, SystemError> {
return Err(SystemError::ENAMETOOLONG);
}
let pcb = ProcessManager::current_pcb();
let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path.to_string())?;
let (inode_begin, remain_path) = user_path_at(&pcb, dirfd, path)?;

let inode: Result<Arc<dyn IndexNode>, SystemError> =
inode_begin.lookup_follow_symlink(&remain_path, VFS_MAX_FOLLOW_SYMLINK_TIMES);
Expand Down
82 changes: 43 additions & 39 deletions kernel/src/filesystem/vfs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,45 +46,49 @@ bitflags! {
/// 与Linux 5.19.10的uapi/asm-generic/fcntl.h相同
/// https://opengrok.ringotek.cn/xref/linux-5.19.10/tools/include/uapi/asm-generic/fcntl.h#19
pub struct FileMode: u32{
/* File access modes for `open' and `fcntl'. */
/// Open Read-only
const O_RDONLY = 0o0;
/// Open Write-only
const O_WRONLY = 0o1;
/// Open read/write
const O_RDWR = 0o2;
/// Mask for file access modes
const O_ACCMODE = 0o00000003;

/* Bits OR'd into the second argument to open. */
/// Create file if it does not exist
const O_CREAT = 0o00000100;
/// Fail if file already exists
const O_EXCL = 0o00000200;
/// Do not assign controlling terminal
const O_NOCTTY = 0o00000400;
/// 文件存在且是普通文件,并以O_RDWR或O_WRONLY打开,则它会被清空
const O_TRUNC = 0o00001000;
/// 文件指针会被移动到文件末尾
const O_APPEND = 0o00002000;
/// 非阻塞式IO模式
const O_NONBLOCK = 0o00004000;
/// 每次write都等待物理I/O完成,但是如果写操作不影响读取刚写入的数据,则不等待文件属性更新
const O_DSYNC = 0o00010000;
/// fcntl, for BSD compatibility
const FASYNC = 0o00020000;
/* direct disk access hint */
const O_DIRECT = 0o00040000;
const O_LARGEFILE = 0o00100000;
/// 打开的必须是一个目录
const O_DIRECTORY = 0o00200000;
/// Do not follow symbolic links
const O_NOFOLLOW = 0o00400000;
const O_NOATIME = 0o01000000;
/// set close_on_exec
const O_CLOEXEC = 0o02000000;
/// 每次write都等到物理I/O完成,包括write引起的文件属性的更新
const O_SYNC = 0o04000000;
/* File access modes for `open' and `fcntl'. */
/// Open Read-only
const O_RDONLY = 0o0;
/// Open Write-only
const O_WRONLY = 0o1;
/// Open read/write
const O_RDWR = 0o2;
/// Mask for file access modes
const O_ACCMODE = 0o00000003;

/* Bits OR'd into the second argument to open. */
/// Create file if it does not exist
const O_CREAT = 0o00000100;
/// Fail if file already exists
const O_EXCL = 0o00000200;
/// Do not assign controlling terminal
const O_NOCTTY = 0o00000400;
/// 文件存在且是普通文件,并以O_RDWR或O_WRONLY打开,则它会被清空
const O_TRUNC = 0o00001000;
/// 文件指针会被移动到文件末尾
const O_APPEND = 0o00002000;
/// 非阻塞式IO模式
const O_NONBLOCK = 0o00004000;
/// 每次write都等待物理I/O完成,但是如果写操作不影响读取刚写入的数据,则不等待文件属性更新
const O_DSYNC = 0o00010000;
/// fcntl, for BSD compatibility
const FASYNC = 0o00020000;
/* direct disk access hint */
const O_DIRECT = 0o00040000;
const O_LARGEFILE = 0o00100000;
/// 打开的必须是一个目录
const O_DIRECTORY = 0o00200000;
/// Do not follow symbolic links
const O_NOFOLLOW = 0o00400000;
const O_NOATIME = 0o01000000;
/// set close_on_exec
const O_CLOEXEC = 0o02000000;
/// 每次write都等到物理I/O完成,包括write引起的文件属性的更新
const O_SYNC = 0o04000000;

const O_PATH = 0o10000000;

const O_PATH_FLAGS = Self::O_DIRECTORY.bits|Self::O_NOFOLLOW.bits|Self::O_CLOEXEC.bits|Self::O_PATH.bits;
}
}

Expand Down
104 changes: 100 additions & 4 deletions kernel/src/filesystem/vfs/open.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use alloc::sync::Arc;

use crate::{
driver::base::block::SeekFrom,
process::ProcessManager,
syscall::{user_access::check_and_clone_cstr, SystemError},
};

use super::{
fcntl::AtFlags, syscall::ModeType, utils::user_path_at, MAX_PATHLEN,
VFS_MAX_FOLLOW_SYMLINK_TIMES,
fcntl::AtFlags,
file::{File, FileMode},
syscall::{ModeType, OpenHow, OpenHowResolve},
utils::{rsplit_path, user_path_at},
FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES,
};

pub(super) fn do_faccessat(
Expand Down Expand Up @@ -34,7 +40,7 @@ pub(super) fn do_faccessat(
return Err(SystemError::EINVAL);
}

let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?;

// 如果找不到文件,则返回错误码ENOENT
let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
Expand All @@ -50,7 +56,7 @@ pub fn do_fchmodat(dirfd: i32, path: *const u8, _mode: ModeType) -> Result<usize
return Err(SystemError::EINVAL);
}

let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?;

// 如果找不到文件,则返回错误码ENOENT
let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
Expand All @@ -60,3 +66,93 @@ pub fn do_fchmodat(dirfd: i32, path: *const u8, _mode: ModeType) -> Result<usize

return Ok(0);
}

pub(super) fn do_sys_open(
dfd: i32,
path: &str,
o_flags: FileMode,
mode: ModeType,
follow_symlink: bool,
) -> Result<usize, SystemError> {
let how = OpenHow::new(o_flags, mode, OpenHowResolve::empty());
return do_sys_openat2(dfd, path, how, follow_symlink);
}

fn do_sys_openat2(
dirfd: i32,
path: &str,
how: OpenHow,
follow_symlink: bool,
) -> Result<usize, SystemError> {
// kdebug!("open: path: {}, mode: {:?}", path, mode);
// 文件名过长
if path.len() > MAX_PATHLEN as usize {
return Err(SystemError::ENAMETOOLONG);
}
let (inode_begin, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
let inode: Result<Arc<dyn IndexNode>, SystemError> = inode_begin.lookup_follow_symlink(
&path,
if follow_symlink {
VFS_MAX_FOLLOW_SYMLINK_TIMES
} else {
0
},
);

let inode: Arc<dyn IndexNode> = if inode.is_err() {
let errno = inode.unwrap_err();
// 文件不存在,且需要创建
if how.o_flags.contains(FileMode::O_CREAT)
&& !how.o_flags.contains(FileMode::O_DIRECTORY)
&& errno == SystemError::ENOENT
{
let (filename, parent_path) = rsplit_path(&path);
// 查找父目录
let parent_inode: Arc<dyn IndexNode> =
ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
// 创建文件
let inode: Arc<dyn IndexNode> = parent_inode.create(
filename,
FileType::File,
ModeType::from_bits_truncate(0o755),
)?;
inode
} else {
// 不需要创建文件,因此返回错误码
return Err(errno);
}
} else {
inode.unwrap()
};

let file_type: FileType = inode.metadata()?.file_type;
// 如果要打开的是文件夹,而目标不是文件夹
if how.o_flags.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir {
return Err(SystemError::ENOTDIR);
}

// 创建文件对象

let mut file: File = File::new(inode, how.o_flags)?;

// 打开模式为“追加”
if how.o_flags.contains(FileMode::O_APPEND) {
file.lseek(SeekFrom::SeekEnd(0))?;
}

// 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件
if how.o_flags.contains(FileMode::O_TRUNC)
&& (how.o_flags.contains(FileMode::O_RDWR) || how.o_flags.contains(FileMode::O_WRONLY))
&& file_type == FileType::File
{
file.ftruncate(0)?;
}
// 把文件对象存入pcb
let r = ProcessManager::current_pcb()
.fd_table()
.write()
.alloc_fd(file, None)
.map(|fd| fd as usize);

return r;
}
Loading

0 comments on commit 0fb515b

Please sign in to comment.