mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 19:36:47 +00:00
实现SYS_LINK和SYS_LINKAT (#611)
* 实现do_linkat及SYS_LINK和SYS_LINKAT * 未在riscv上测试,添加target_arch * 将c字符串检查移动到vfs/syscall.rs,修改do_linkat()逻辑 * 修改部分注释
This commit is contained in:
parent
70f159a398
commit
4695947e1b
@ -737,6 +737,112 @@ impl Syscall {
|
|||||||
return do_mkdir(&path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize);
|
return do_mkdir(&path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// **创建硬连接的系统调用**
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - 'oldfd': 用于解析源文件路径的文件描述符
|
||||||
|
/// - 'old': 源文件路径
|
||||||
|
/// - 'newfd': 用于解析新文件路径的文件描述符
|
||||||
|
/// - 'new': 新文件将创建的路径
|
||||||
|
/// - 'flags': 标志位,仅以位或方式包含AT_EMPTY_PATH和AT_SYMLINK_FOLLOW
|
||||||
|
///
|
||||||
|
///
|
||||||
|
pub fn do_linkat(
|
||||||
|
oldfd: i32,
|
||||||
|
old: &str,
|
||||||
|
newfd: i32,
|
||||||
|
new: &str,
|
||||||
|
flags: AtFlags,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
// flag包含其他未规定值时返回EINVAL
|
||||||
|
if !(AtFlags::AT_EMPTY_PATH | AtFlags::AT_SYMLINK_FOLLOW).contains(flags) {
|
||||||
|
return Err(SystemError::EINVAL);
|
||||||
|
}
|
||||||
|
// TODO AT_EMPTY_PATH标志启用时,进行调用者CAP_DAC_READ_SEARCH或相似的检查
|
||||||
|
let symlink_times = if flags.contains(AtFlags::AT_SYMLINK_FOLLOW) {
|
||||||
|
0 as usize
|
||||||
|
} else {
|
||||||
|
VFS_MAX_FOLLOW_SYMLINK_TIMES
|
||||||
|
};
|
||||||
|
let pcb = ProcessManager::current_pcb();
|
||||||
|
|
||||||
|
// 得到源路径的inode
|
||||||
|
let old_inode: Arc<dyn IndexNode> = if old.is_empty() {
|
||||||
|
if flags.contains(AtFlags::AT_EMPTY_PATH) {
|
||||||
|
// 在AT_EMPTY_PATH启用时,old可以为空,old_inode实际为oldfd所指文件,但该文件不能为目录。
|
||||||
|
let binding = pcb.fd_table();
|
||||||
|
let fd_table_guard = binding.read();
|
||||||
|
let file = fd_table_guard
|
||||||
|
.get_file_by_fd(oldfd)
|
||||||
|
.ok_or(SystemError::EBADF)?;
|
||||||
|
let old_inode = file.lock().inode();
|
||||||
|
old_inode
|
||||||
|
} else {
|
||||||
|
return Err(SystemError::ENONET);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let (old_begin_inode, old_remain_path) = user_path_at(&pcb, oldfd, old)?;
|
||||||
|
old_begin_inode.lookup_follow_symlink(&old_remain_path, symlink_times)?
|
||||||
|
};
|
||||||
|
|
||||||
|
// old_inode为目录时返回EPERM
|
||||||
|
if old_inode.metadata().unwrap().file_type == FileType::Dir {
|
||||||
|
return Err(SystemError::EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 得到新创建节点的父节点
|
||||||
|
let (new_begin_inode, new_remain_path) = user_path_at(&pcb, newfd, new)?;
|
||||||
|
let (new_name, new_parent_path) = rsplit_path(&new_remain_path);
|
||||||
|
let new_parent = new_begin_inode
|
||||||
|
.lookup_follow_symlink(&new_parent_path.unwrap_or("/"), symlink_times)?;
|
||||||
|
|
||||||
|
// 被调用者利用downcast_ref判断两inode是否为同一文件系统
|
||||||
|
return new_parent.link(&new_name, &old_inode).map(|_| 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn link(old: *const u8, new: *const u8) -> Result<usize, SystemError> {
|
||||||
|
let get_path = |cstr: *const u8| -> Result<String, SystemError> {
|
||||||
|
let res = check_and_clone_cstr(cstr, Some(MAX_PATHLEN))?;
|
||||||
|
if res.len() >= MAX_PATHLEN {
|
||||||
|
return Err(SystemError::ENAMETOOLONG);
|
||||||
|
}
|
||||||
|
if res.is_empty() {
|
||||||
|
return Err(SystemError::ENOENT);
|
||||||
|
}
|
||||||
|
Ok(res)
|
||||||
|
};
|
||||||
|
let old = get_path(old)?;
|
||||||
|
let new = get_path(new)?;
|
||||||
|
return Self::do_linkat(
|
||||||
|
AtFlags::AT_FDCWD.bits() as i32,
|
||||||
|
&old,
|
||||||
|
AtFlags::AT_FDCWD.bits() as i32,
|
||||||
|
&new,
|
||||||
|
AtFlags::empty(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linkat(
|
||||||
|
oldfd: i32,
|
||||||
|
old: *const u8,
|
||||||
|
newfd: i32,
|
||||||
|
new: *const u8,
|
||||||
|
flags: i32,
|
||||||
|
) -> Result<usize, SystemError> {
|
||||||
|
let old = check_and_clone_cstr(old, Some(MAX_PATHLEN))?;
|
||||||
|
let new = check_and_clone_cstr(new, Some(MAX_PATHLEN))?;
|
||||||
|
if old.len() >= MAX_PATHLEN || new.len() >= MAX_PATHLEN {
|
||||||
|
return Err(SystemError::ENAMETOOLONG);
|
||||||
|
}
|
||||||
|
// old 根据flags & AtFlags::AT_EMPTY_PATH判空
|
||||||
|
if new.is_empty() {
|
||||||
|
return Err(SystemError::ENOENT);
|
||||||
|
}
|
||||||
|
let flags = AtFlags::from_bits(flags).ok_or(SystemError::EINVAL)?;
|
||||||
|
Self::do_linkat(oldfd, &old, newfd, &new, flags)
|
||||||
|
}
|
||||||
|
|
||||||
/// **删除文件夹、取消文件的链接、删除文件的系统调用**
|
/// **删除文件夹、取消文件的链接、删除文件的系统调用**
|
||||||
///
|
///
|
||||||
/// ## 参数
|
/// ## 参数
|
||||||
|
@ -345,6 +345,21 @@ impl Syscall {
|
|||||||
Self::rmdir(path)
|
Self::rmdir(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SYS_LINK => {
|
||||||
|
let old = args[0] as *const u8;
|
||||||
|
let new = args[1] as *const u8;
|
||||||
|
return Self::link(old, new);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_LINKAT => {
|
||||||
|
let oldfd = args[0] as i32;
|
||||||
|
let old = args[1] as *const u8;
|
||||||
|
let newfd = args[2] as i32;
|
||||||
|
let new = args[3] as *const u8;
|
||||||
|
let flags = args[4] as i32;
|
||||||
|
return Self::linkat(oldfd, old, newfd, new, flags);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
SYS_UNLINK => {
|
SYS_UNLINK => {
|
||||||
let path = args[0] as *const u8;
|
let path = args[0] as *const u8;
|
||||||
|
@ -65,9 +65,10 @@
|
|||||||
#define SYS_CHDIR 80
|
#define SYS_CHDIR 80
|
||||||
|
|
||||||
#define SYS_MKDIR 83
|
#define SYS_MKDIR 83
|
||||||
|
|
||||||
#define SYS_RMDIR 84
|
#define SYS_RMDIR 84
|
||||||
|
|
||||||
|
#define SYS_LINK 86
|
||||||
|
|
||||||
#define SYS_GETTIMEOFDAY 96
|
#define SYS_GETTIMEOFDAY 96
|
||||||
|
|
||||||
#define SYS_ARCH_PRCTL 158
|
#define SYS_ARCH_PRCTL 158
|
||||||
@ -86,6 +87,8 @@
|
|||||||
|
|
||||||
#define SYS_UNLINK_AT 263
|
#define SYS_UNLINK_AT 263
|
||||||
|
|
||||||
|
#define SYS_LINKAT 265
|
||||||
|
|
||||||
#define SYS_PIPE 293
|
#define SYS_PIPE 293
|
||||||
|
|
||||||
#define SYS_WRITEV 20
|
#define SYS_WRITEV 20
|
||||||
|
Loading…
x
Reference in New Issue
Block a user