Skip to content

Commit c8b9d55

Browse files
committed
finish
1 parent 378bcfa commit c8b9d55

File tree

5 files changed

+141
-10
lines changed

5 files changed

+141
-10
lines changed

os/src/fs/inode.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ use alloc::vec::Vec;
1313
use bitflags::*;
1414
use easy_fs::{EasyFileSystem, Inode};
1515
use lazy_static::*;
16-
16+
use crate::fs::Stat;
17+
use crate::fs::StatMode;
18+
use core::any::Any;
1719
/// inode in memory
1820
/// A wrapper around a filesystem inode
1921
/// to implement File trait atop
@@ -53,9 +55,31 @@ impl OSInode {
5355
}
5456
v
5557
}
58+
/// get stat information of this inode
59+
pub fn get_stat(&self) -> Stat {
60+
let inner = self.inner.exclusive_access();
61+
let inode = &inner.inode;
62+
63+
let is_dir = inode.is_dir();
64+
let nlink = inode.get_nlink();
65+
let inode_id = inode.get_inode_id();
66+
67+
Stat {
68+
dev: 0,
69+
ino: inode_id as u64,
70+
mode: if is_dir {
71+
StatMode::DIR
72+
} else {
73+
StatMode::FILE
74+
},
75+
nlink,
76+
pad: [0; 7],
77+
}
78+
}
5679
}
5780

5881
lazy_static! {
82+
/// The root inode of the file system
5983
pub static ref ROOT_INODE: Arc<Inode> = {
6084
let efs = EasyFileSystem::open(BLOCK_DEVICE.clone());
6185
Arc::new(EasyFileSystem::root_inode(&efs))
@@ -156,4 +180,8 @@ impl File for OSInode {
156180
}
157181
total_write_size
158182
}
183+
184+
fn as_any(&self) -> &dyn Any {
185+
self
186+
}
159187
}

os/src/fs/mod.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
//! File trait & inode(dir, file, pipe, stdin, stdout)
22
3-
mod inode;
3+
pub mod inode;
44
mod stdio;
55

66
use crate::mm::UserBuffer;
7+
use core::any::Any;
78

89
/// trait File for all file types
910
pub trait File: Send + Sync {
@@ -15,6 +16,9 @@ pub trait File: Send + Sync {
1516
fn read(&self, buf: UserBuffer) -> usize;
1617
/// write to the file from buf, return the number of bytes written
1718
fn write(&self, buf: UserBuffer) -> usize;
19+
20+
/// 添加 as_any 方法用于向下转换
21+
fn as_any(&self) -> &dyn Any;
1822
}
1923

2024
/// The stat of a inode
@@ -33,6 +37,29 @@ pub struct Stat {
3337
pad: [u64; 7],
3438
}
3539

40+
impl Stat {
41+
/// 为特殊文件类型创建默认的 Stat 信息
42+
pub fn for_special_file() -> Self {
43+
Self {
44+
dev: 0,
45+
ino: 0,
46+
mode: StatMode::FILE,
47+
nlink: 1,
48+
pad: [0; 7],
49+
}
50+
}
51+
52+
/// 判断是否是目录
53+
pub fn is_dir(&self) -> bool {
54+
self.mode.contains(StatMode::DIR)
55+
}
56+
57+
/// 判断是否是文件
58+
pub fn is_file(&self) -> bool {
59+
self.mode.contains(StatMode::FILE)
60+
}
61+
}
62+
3663
bitflags! {
3764
/// The mode of a inode
3865
/// whether a directory or a file

os/src/fs/stdio.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::task::suspend_current_and_run_next;
66

77
/// stdin file for getting chars from console
88
pub struct Stdin;
9-
9+
use core::any::Any;
1010
/// stdout file for putting chars to console
1111
pub struct Stdout;
1212

@@ -39,6 +39,9 @@ impl File for Stdin {
3939
fn write(&self, _user_buf: UserBuffer) -> usize {
4040
panic!("Cannot write to stdin!");
4141
}
42+
fn as_any(&self) -> &dyn Any {
43+
self
44+
}
4245
}
4346

4447
impl File for Stdout {
@@ -57,4 +60,8 @@ impl File for Stdout {
5760
}
5861
user_buf.len()
5962
}
63+
64+
fn as_any(&self) -> &dyn Any {
65+
self
66+
}
6067
}

os/src/syscall/fs.rs

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
//! File and filesystem-related syscalls
22
use crate::fs::{open_file, OpenFlags, Stat};
3-
use crate::mm::{translated_byte_buffer, translated_str, UserBuffer};
3+
use crate::mm::{translated_byte_buffer, translated_str, UserBuffer, translated_refmut};
44
use crate::task::{current_task, current_user_token};
5-
5+
use crate::fs::inode::ROOT_INODE;
6+
use crate::fs::OSInode;
67

78
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
89
trace!("kernel:pid[{}] sys_write", current_task().unwrap().pid.0);
@@ -51,6 +52,7 @@ pub fn sys_open(path: *const u8, flags: u32) -> isize {
5152
trace!("kernel:pid[{}] sys_open", current_task().unwrap().pid.0);
5253
let task = current_task().unwrap();
5354
let token = current_user_token();
55+
// 通过页表将另一个地址空间中的C风格字符串(以\0结尾的字节数组)转换为Rust的String
5456
let path = translated_str(token, path);
5557
if let Some(inode) = open_file(path.as_str(), OpenFlags::from_bits(flags).unwrap()) {
5658
let mut inner = task.inner_exclusive_access();
@@ -77,28 +79,85 @@ pub fn sys_close(fd: usize) -> isize {
7779
}
7880

7981
/// YOUR JOB: Implement fstat.
80-
pub fn sys_fstat(_fd: usize, _st: *mut Stat) -> isize {
82+
pub fn sys_fstat(fd: usize, st: *mut Stat) -> isize {
8183
trace!(
8284
"kernel:pid[{}] sys_fstat NOT IMPLEMENTED",
8385
current_task().unwrap().pid.0
8486
);
87+
let task = current_task().unwrap();
88+
let token = current_user_token();
89+
90+
if let Some(file) = task.get_file(fd) {
91+
// 只处理 OSInode(普通文件)
92+
if let Some(os_inode) = file.as_any().downcast_ref::<OSInode>() {
93+
let stat = os_inode.get_stat();
94+
let st_buf = translated_refmut(token, st);
95+
*st_buf = stat;
96+
return 0;
97+
}
98+
// 对于其他类型的文件(Stdin/Stdout),暂时返回错误
99+
// 等普通文件工作后再扩展
100+
else {
101+
return -1;
102+
}
103+
}
104+
85105
-1
86106
}
87107

88108
/// YOUR JOB: Implement linkat.
89-
pub fn sys_linkat(_old_name: *const u8, _new_name: *const u8) -> isize {
109+
pub fn sys_linkat(old_name: *const u8, new_name: *const u8) -> isize {
90110
trace!(
91111
"kernel:pid[{}] sys_linkat NOT IMPLEMENTED",
92112
current_task().unwrap().pid.0
93113
);
94-
-1
114+
115+
let token = current_user_token();
116+
let old_path = translated_str(token, old_name);
117+
let new_path = translated_str(token, new_name);
118+
119+
// 检查路径是否相同
120+
if old_path == new_path {
121+
return -1;
122+
}
123+
124+
// 查找原文件
125+
let old_inode = match ROOT_INODE.find(&old_path) {
126+
Some(inode) => inode,
127+
None => return -1, // 原文件不存在
128+
};
129+
130+
// 检查新文件是否已存在
131+
if ROOT_INODE.find(&new_path).is_some() {
132+
return -1; // 新文件已存在
133+
}
134+
// 创建硬链接
135+
match ROOT_INODE.create_hardlink(&new_path, &old_inode) {
136+
Some(_) => {
137+
0
138+
},
139+
None => {
140+
-1
141+
}
142+
}
95143
}
96144

97145
/// YOUR JOB: Implement unlinkat.
98-
pub fn sys_unlinkat(_name: *const u8) -> isize {
146+
pub fn sys_unlinkat(name: *const u8) -> isize {
99147
trace!(
100148
"kernel:pid[{}] sys_unlinkat NOT IMPLEMENTED",
101149
current_task().unwrap().pid.0
102150
);
103-
-1
151+
152+
153+
let token = current_user_token();
154+
let path = translated_str(token, name);
155+
156+
// 检查路径是否为空
157+
if path.is_empty() {
158+
return -1;
159+
}
160+
161+
// 直接调用 ROOT_INODE 的 unlink 方法
162+
ROOT_INODE.unlink(&path)
104163
}

os/src/task/task.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,16 @@ impl TaskControlBlock {
397397
// 返回新任务
398398
new_task
399399
}
400+
401+
/// Get file by file descriptor
402+
pub fn get_file(&self, fd: usize) -> Option<Arc<dyn File + Send + Sync>> {
403+
let inner = self.inner_exclusive_access();
404+
if fd < inner.fd_table.len() {
405+
inner.fd_table[fd].clone()
406+
} else {
407+
None
408+
}
409+
}
400410
}
401411

402412
#[derive(Copy, Clone, PartialEq)]

0 commit comments

Comments
 (0)