Skip to content

Commit

Permalink
[feat] Support for ext4 junior
Browse files Browse the repository at this point in the history
  • Loading branch information
Azure-stars committed Feb 22, 2025
1 parent 6bd518c commit cb34789
Show file tree
Hide file tree
Showing 25 changed files with 1,438 additions and 60 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion api/arceos_posix_api/ctypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <netinet/in.h>
#include <pthread.h>
#include <stddef.h>
#include <time.h>
#include <sys/epoll.h>
#include <sys/resource.h>
#include <sys/select.h>
Expand All @@ -12,4 +11,5 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <time.h>
#include <unistd.h>
18 changes: 17 additions & 1 deletion api/arceos_posix_api/src/imp/fd_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,23 @@ pub trait FileLike: Send + Sync {
}

def_resource! {
pub(crate) static FD_TABLE: ResArc<RwLock<FlattenObjects<Arc<dyn FileLike>, AX_FILE_LIMIT>>> = ResArc::new();
pub static FD_TABLE: ResArc<RwLock<FlattenObjects<Arc<dyn FileLike>, AX_FILE_LIMIT>>> = ResArc::new();
}

impl FD_TABLE {
/// Return a copy of the inner table.
pub fn copy_inner(&self) -> RwLock<FlattenObjects<Arc<dyn FileLike>, AX_FILE_LIMIT>> {
let table = self.read();
let mut new_table = FlattenObjects::new();
let count = table.count();
for i in 0..count {
let _ = new_table.add_at(i, table.get(i).unwrap().clone());
}
RwLock::new(new_table)
}
}

/// Get a file by `fd`.
pub fn get_file_like(fd: c_int) -> LinuxResult<Arc<dyn FileLike>> {
FD_TABLE
.read()
Expand All @@ -34,10 +48,12 @@ pub fn get_file_like(fd: c_int) -> LinuxResult<Arc<dyn FileLike>> {
.ok_or(LinuxError::EBADF)
}

/// Add a file to the file descriptor table.
pub fn add_file_like(f: Arc<dyn FileLike>) -> LinuxResult<c_int> {
Ok(FD_TABLE.write().add(f).map_err(|_| LinuxError::EMFILE)? as c_int)
}

/// Close a file by `fd`.
pub fn close_file_like(fd: c_int) -> LinuxResult {
let f = FD_TABLE
.write()
Expand Down
175 changes: 169 additions & 6 deletions api/arceos_posix_api/src/imp/fs.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::string::{String, ToString};
use alloc::sync::Arc;
use core::ffi::{c_char, c_int};

Expand All @@ -7,16 +8,20 @@ use axio::{PollState, SeekFrom};
use axsync::Mutex;

use super::fd_ops::{FileLike, get_file_like};
use crate::AT_FDCWD;
use crate::{ctypes, utils::char_ptr_to_str};

/// File wrapper for `axfs::fops::File`.
pub struct File {
inner: Mutex<axfs::fops::File>,
path: String,
}

impl File {
fn new(inner: axfs::fops::File) -> Self {
fn new(inner: axfs::fops::File, path: String) -> Self {
Self {
inner: Mutex::new(inner),
path,
}
}

Expand All @@ -30,6 +35,16 @@ impl File {
.downcast::<Self>()
.map_err(|_| LinuxError::EINVAL)
}

/// Get the path of the file.
pub fn path(&self) -> &str {
&self.path
}

/// Get the inner node of the file.
pub fn inner(&self) -> &Mutex<axfs::fops::File> {
&self.inner
}
}

impl FileLike for File {
Expand Down Expand Up @@ -97,7 +112,11 @@ fn flags_to_options(flags: c_int, _mode: ctypes::mode_t) -> OpenOptions {
options.create(true);
}
if flags & ctypes::O_EXEC != 0 {
options.create_new(true);
//options.create_new(true);
options.execute(true);
}
if flags & ctypes::O_DIRECTORY != 0 {
options.directory(true);
}
options
}
Expand All @@ -111,11 +130,89 @@ pub fn sys_open(filename: *const c_char, flags: c_int, mode: ctypes::mode_t) ->
debug!("sys_open <= {:?} {:#o} {:#o}", filename, flags, mode);
syscall_body!(sys_open, {
let options = flags_to_options(flags, mode);
let file = axfs::fops::File::open(filename?, &options)?;
File::new(file).add_to_fd_table()
if options.has_directory() {
return Directory::from_path(filename?.into(), &options)
.and_then(Directory::add_to_fd_table);
}
add_file_or_directory_fd(
axfs::fops::File::open,
axfs::fops::Directory::open_dir,
filename?,
&options,
)
})
}

/// Open or create a file.
/// fd: file descriptor
/// filename: file path to be opened or created
/// flags: open flags
/// mode: see man 7 inode
/// return new file descriptor if succeed, or return -1.
pub fn sys_openat(
dirfd: c_int,
filename: *const c_char,
flags: c_int,
mode: ctypes::mode_t,
) -> c_int {
let filename = match char_ptr_to_str(filename) {
Ok(s) => s,
Err(_) => return -1,
};

debug!(
"sys_openat <= {} {:?} {:#o} {:#o}",
dirfd, filename, flags, mode
);

let options = flags_to_options(flags, mode);

if filename.starts_with('/') || dirfd == AT_FDCWD as _ {
return sys_open(filename.as_ptr() as _, flags, mode);
}

match Directory::from_fd(dirfd).and_then(|dir| {
add_file_or_directory_fd(
|filename, options| dir.inner.lock().open_file_at(filename, options),
|filename, options| dir.inner.lock().open_dir_at(filename, options),
filename,
&options,
)
}) {
Ok(fd) => fd,
Err(e) => {
debug!("sys_openat => {}", e);
-1
}
}
}

/// Use the function to open file or directory, then add into file descriptor table.
/// First try opening files, if fails, try directory.
fn add_file_or_directory_fd<F, D, E>(
open_file: F,
open_dir: D,
filename: &str,
options: &OpenOptions,
) -> LinuxResult<c_int>
where
E: Into<LinuxError>,
F: FnOnce(&str, &OpenOptions) -> Result<axfs::fops::File, E>,
D: FnOnce(&str, &OpenOptions) -> Result<axfs::fops::Directory, E>,
{
open_file(filename, options)
.map_err(Into::into)
.map(|f| File::new(f, filename.into()))
.and_then(File::add_to_fd_table)
.or_else(|e| match e {
LinuxError::EISDIR => open_dir(filename, options)
.map_err(Into::into)
.map(|d| Directory::new(d, filename.into()))
.and_then(Directory::add_to_fd_table),
_ => Err(e),
})
}

/// Set the position of the file indicated by `fd`.
///
/// Return its position after seek.
Expand Down Expand Up @@ -146,7 +243,7 @@ pub unsafe fn sys_stat(path: *const c_char, buf: *mut ctypes::stat) -> c_int {
let mut options = OpenOptions::new();
options.read(true);
let file = axfs::fops::File::open(path?, &options)?;
let st = File::new(file).stat()?;
let st = File::new(file, path?.to_string()).stat()?;
unsafe { *buf = st };
Ok(0)
})
Expand Down Expand Up @@ -183,7 +280,6 @@ pub unsafe fn sys_lstat(path: *const c_char, buf: *mut ctypes::stat) -> ctypes::
}

/// Get the path of the current directory.
#[allow(clippy::unnecessary_cast)] // `c_char` is either `i8` or `u8`
pub fn sys_getcwd(buf: *mut c_char, size: usize) -> *mut c_char {
debug!("sys_getcwd <= {:#x} {}", buf as usize, size);
syscall_body!(sys_getcwd, {
Expand Down Expand Up @@ -216,3 +312,70 @@ pub fn sys_rename(old: *const c_char, new: *const c_char) -> c_int {
Ok(0)
})
}

/// Directory wrapper for `axfs::fops::Directory`.
pub struct Directory {
inner: Mutex<axfs::fops::Directory>,
path: String,
}

impl Directory {
fn new(inner: axfs::fops::Directory, path: String) -> Self {
Self {
inner: Mutex::new(inner),
path,
}
}

fn from_path(path: String, options: &OpenOptions) -> LinuxResult<Self> {
axfs::fops::Directory::open_dir(&path, options)
.map_err(Into::into)
.map(|d| Self::new(d, path))
}

fn add_to_fd_table(self) -> LinuxResult<c_int> {
super::fd_ops::add_file_like(Arc::new(self))
}

/// Open a directory by `fd`.
pub fn from_fd(fd: c_int) -> LinuxResult<Arc<Self>> {
let f = super::fd_ops::get_file_like(fd)?;
f.into_any()
.downcast::<Self>()
.map_err(|_| LinuxError::EINVAL)
}

/// Get the path of the directory.
pub fn path(&self) -> &str {
&self.path
}
}

impl FileLike for Directory {
fn read(&self, _buf: &mut [u8]) -> LinuxResult<usize> {
Err(LinuxError::EBADF)
}

fn write(&self, _buf: &[u8]) -> LinuxResult<usize> {
Err(LinuxError::EBADF)
}

fn stat(&self) -> LinuxResult<ctypes::stat> {
Err(LinuxError::EBADF)
}

fn into_any(self: Arc<Self>) -> Arc<dyn core::any::Any + Send + Sync> {
self
}

fn poll(&self) -> LinuxResult<PollState> {
Ok(PollState {
readable: true,
writable: false,
})
}

fn set_nonblocking(&self, _nonblocking: bool) -> LinuxResult {
Ok(())
}
}
2 changes: 2 additions & 0 deletions api/arceos_posix_api/src/imp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pub mod fs;
pub mod io_mpx;
#[cfg(feature = "net")]
pub mod net;
#[cfg(feature = "fs")]
pub mod path_link;
#[cfg(feature = "pipe")]
pub mod pipe;
#[cfg(feature = "multitask")]
Expand Down
Loading

0 comments on commit cb34789

Please sign in to comment.