内存缓存和ext4完整支持

This commit is contained in:
wcjbr
2026-07-29 12:35:25 +08:00
parent 86dbf7482f
commit a9f3f71063
27 changed files with 1813 additions and 175 deletions
+106 -19
View File
@@ -15,7 +15,6 @@ const EINVAL: isize = 22;
const ENOENT: isize = 2;
const ENOTDIR: isize = 20;
const EMFILE: isize = 24;
const EIO: isize = 5;
#[derive(Clone, Copy, PartialEq, Eq)]
enum Color {
@@ -226,12 +225,25 @@ impl Vfs {
return -EINVAL;
}
let offset = self.fds[fd].offset.min(node.len);
let available = node.len - offset;
if node.data.is_null() {
let count =
match crate::fs::lwext4::read_path_at(&node.path, self.fds[fd].offset, buffer, len)
{
Ok(count) => count,
Err(error) => return error,
};
self.fds[fd].offset = self.fds[fd].offset.saturating_add(count);
return count as isize;
}
let node_len = self.node_len(node_index);
let offset = self.fds[fd].offset.min(node_len);
let available = node_len - offset;
let count = len.min(available);
if count > 0 {
unsafe {
core::ptr::copy_nonoverlapping(node.data.add(offset), buffer, count);
let source = node.data.add(offset);
core::ptr::copy_nonoverlapping(source, buffer, count);
}
}
self.fds[fd].offset = offset + count;
@@ -245,6 +257,9 @@ impl Vfs {
let Some(node_index) = self.fds[fd].node else {
return -EBADF;
};
if self.nodes[node_index].kind == NodeKind::Regular {
return self.write_regular_fd(fd, node_index, buffer, len);
}
if self.nodes[node_index].kind != NodeKind::CharDevice {
return -EINVAL;
}
@@ -253,6 +268,31 @@ impl Vfs {
crate::console::write(buffer) as isize
}
fn write_regular_fd(
&mut self,
fd: usize,
node_index: usize,
buffer: *const u8,
len: usize,
) -> isize {
let offset = self.fds[fd].offset;
let count = match crate::fs::lwext4::write_path_at(
&self.nodes[node_index].path,
offset,
buffer,
len,
) {
Ok(count) => count,
Err(error) => return error,
};
let end = offset.saturating_add(count);
self.fds[fd].offset = end;
if end > self.nodes[node_index].len {
self.nodes[node_index].len = end;
}
count as isize
}
fn close_fd(&mut self, fd: usize) -> isize {
if fd < 3 || fd >= MAX_FDS || self.fds[fd].node.is_none() {
return -EBADF;
@@ -298,7 +338,7 @@ impl Vfs {
let Some(node_index) = self.fds[fd].node else {
return -EBADF;
};
let len = self.nodes[node_index].len as isize;
let len = self.node_len(node_index) as isize;
let current = self.fds[fd].offset as isize;
let next = match whence {
0 => offset,
@@ -323,6 +363,24 @@ impl Vfs {
write_stat(stat, self.nodes[node_index])
}
fn ftruncate_fd(&mut self, fd: usize, size: usize) -> isize {
if fd >= MAX_FDS {
return -EBADF;
}
let Some(node_index) = self.fds[fd].node else {
return -EBADF;
};
if self.nodes[node_index].kind != NodeKind::Regular {
return -EINVAL;
}
match crate::fs::lwext4::truncate_path(&self.nodes[node_index].path, size) {
Ok(()) => {}
Err(error) => return error,
}
self.nodes[node_index].len = size;
0
}
fn is_tty_fd(&self, fd: usize) -> bool {
if fd >= MAX_FDS {
return false;
@@ -387,6 +445,22 @@ impl Vfs {
write_stat(stat, self.nodes[node_index])
}
fn truncate_path(&mut self, path: &[u8], size: usize) -> isize {
let Some(node_index) = self.find(path) else {
return -ENOENT;
};
if self.nodes[node_index].kind != NodeKind::Regular {
return -EINVAL;
}
match crate::fs::lwext4::truncate_path(&self.nodes[node_index].path, size) {
Ok(()) => {
self.nodes[node_index].len = size;
0
}
Err(error) => error,
}
}
fn chdir_path(&mut self, path: &[u8]) -> isize {
let Some(node_index) = self.find(path) else {
return -ENOENT;
@@ -414,6 +488,15 @@ impl Vfs {
}
}
fn node_len(&self, node_index: usize) -> usize {
let node = self.nodes[node_index];
if node.kind == NodeKind::Regular && node.data.is_null() {
crate::fs::lwext4::size_path(&node.path).unwrap_or(node.len)
} else {
node.len
}
}
fn getcwd(&self, buffer: *mut u8, len: usize) -> isize {
if buffer.is_null() {
return -EFAULT;
@@ -576,10 +659,7 @@ pub unsafe fn init() {
}
}
pub unsafe fn mount_static_file(path: &'static [u8], data: *const u8, len: usize) -> Option<()> {
unsafe { vfs_mut().insert(path, NodeKind::Regular, data, len) }
}
#[allow(dead_code)]
pub fn mount_ext4_node(path: &[u8], kind: NodeKind) -> Option<()> {
unsafe { vfs_mut().insert(path, kind, core::ptr::null(), 0) }
}
@@ -655,6 +735,10 @@ pub fn fstat(fd: usize, stat: *mut u8) -> isize {
unsafe { vfs_ref().stat_fd(fd, stat) }
}
pub fn ftruncate(fd: usize, size: usize) -> isize {
unsafe { vfs_mut().ftruncate_fd(fd, size) }
}
pub fn is_tty(fd: usize) -> bool {
unsafe { vfs_ref().is_tty_fd(fd) }
}
@@ -684,6 +768,13 @@ pub fn stat_user_path(path: *const u8, stat: *mut u8) -> isize {
unsafe { vfs_ref().stat_path(&path, stat) }
}
pub fn truncate_user_path(path: *const u8, size: usize) -> isize {
let Some(path) = (unsafe { read_user_path(path) }) else {
return -EFAULT;
};
unsafe { vfs_mut().truncate_path(&path, size) }
}
pub fn statat_user_path(dirfd: isize, path: *const u8, stat: *mut u8) -> isize {
if unsafe { path_starts_with_slash(path) } || dirfd == AT_FDCWD {
return stat_user_path(path, stat);
@@ -761,9 +852,9 @@ fn create_directory_path(path: &[u8]) -> isize {
if unsafe { vfs_ref().find(path).is_some() } {
return 0;
}
match crate::fs::ext4::create_dir(path) {
match crate::fs::lwext4::create_dir(path) {
Ok(()) => unsafe { vfs_mut().create_path(path, NodeKind::Directory) },
Err(_) => -EIO,
Err(error) => error,
}
}
@@ -771,9 +862,9 @@ fn create_regular_path(path: &[u8]) -> isize {
if unsafe { vfs_ref().find(path).is_some() } {
return 0;
}
match crate::fs::ext4::create_file(path) {
match crate::fs::lwext4::create_file(path) {
Ok(()) => unsafe { vfs_mut().create_path(path, NodeKind::Regular) },
Err(_) => -EIO,
Err(error) => error,
}
}
@@ -781,15 +872,11 @@ pub fn getcwd(buffer: *mut u8, len: usize) -> isize {
unsafe { vfs_ref().getcwd(buffer, len) }
}
pub fn file_data_user_path(path: *const u8) -> Option<(*const u8, usize)> {
pub fn exec_path_user(path: *const u8) -> Option<[u8; MAX_PATH]> {
let path = unsafe { read_user_path(path) }?;
unsafe {
let index = vfs_ref().resolve_executable_path(&path)?;
let node = &vfs_ref().nodes[index];
if node.kind != NodeKind::Regular {
return None;
}
Some((node.data, node.len))
Some(vfs_ref().nodes[index].path)
}
}