diff --git a/services/libs/jinux-std/src/fs/file_handle.rs b/services/libs/jinux-std/src/fs/file_handle.rs index 01a2f3e79..b4aedaf3e 100644 --- a/services/libs/jinux-std/src/fs/file_handle.rs +++ b/services/libs/jinux-std/src/fs/file_handle.rs @@ -1,7 +1,7 @@ //! Opend File Handle use crate::events::Observer; -use crate::fs::utils::{IoEvents, IoctlCmd, Metadata, Poller, SeekFrom}; +use crate::fs::utils::{AccessMode, IoEvents, IoctlCmd, Metadata, Poller, SeekFrom, StatusFlags}; use crate::prelude::*; use crate::tty::get_n_tty; @@ -40,6 +40,18 @@ pub trait FileLike: Send + Sync + Any { panic!("metadata unsupported"); } + fn status_flags(&self) -> StatusFlags { + StatusFlags::empty() + } + + fn set_status_flags(&self, _new_flags: StatusFlags) -> Result<()> { + return_errno_with_message!(Errno::EINVAL, "set_status_flags is not supported"); + } + + fn access_mode(&self) -> AccessMode { + AccessMode::O_RDWR + } + fn seek(&self, seek_from: SeekFrom) -> Result { return_errno_with_message!(Errno::EINVAL, "seek is not supported"); } diff --git a/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs b/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs index 94afd08ef..9e6ca4c44 100644 --- a/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs +++ b/services/libs/jinux-std/src/fs/inode_handle/dyn_cap.rs @@ -23,7 +23,7 @@ impl InodeHandle { dentry, offset: Mutex::new(0), access_mode, - status_flags: Mutex::new(status_flags), + status_flags: AtomicU32::new(status_flags.bits()), }); Ok(Self(inner, Rights::from(access_mode))) } @@ -80,6 +80,19 @@ impl FileLike for InodeHandle { self.dentry().vnode().metadata() } + fn status_flags(&self) -> StatusFlags { + self.0.status_flags() + } + + fn set_status_flags(&self, new_status_flags: StatusFlags) -> Result<()> { + self.0.set_status_flags(new_status_flags); + Ok(()) + } + + fn access_mode(&self) -> AccessMode { + self.0.access_mode() + } + fn seek(&self, seek_from: SeekFrom) -> Result { self.0.seek(seek_from) } diff --git a/services/libs/jinux-std/src/fs/inode_handle/mod.rs b/services/libs/jinux-std/src/fs/inode_handle/mod.rs index 24500cf0f..41e272e4b 100644 --- a/services/libs/jinux-std/src/fs/inode_handle/mod.rs +++ b/services/libs/jinux-std/src/fs/inode_handle/mod.rs @@ -3,6 +3,8 @@ mod dyn_cap; mod static_cap; +use core::sync::atomic::{AtomicU32, Ordering}; + use crate::fs::file_handle::FileLike; use crate::fs::utils::{ AccessMode, Dentry, DirentVisitor, InodeType, IoEvents, Metadata, Poller, SeekFrom, StatusFlags, @@ -16,13 +18,13 @@ struct InodeHandle_ { dentry: Arc, offset: Mutex, access_mode: AccessMode, - status_flags: Mutex, + status_flags: AtomicU32, } impl InodeHandle_ { pub fn read(&self, buf: &mut [u8]) -> Result { let mut offset = self.offset.lock(); - let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) { + let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { self.dentry.vnode().read_direct_at(*offset, buf)? } else { self.dentry.vnode().read_at(*offset, buf)? @@ -34,10 +36,10 @@ impl InodeHandle_ { pub fn write(&self, buf: &[u8]) -> Result { let mut offset = self.offset.lock(); - if self.status_flags.lock().contains(StatusFlags::O_APPEND) { + if self.status_flags().contains(StatusFlags::O_APPEND) { *offset = self.dentry.vnode().len(); } - let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) { + let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { self.dentry.vnode().write_direct_at(*offset, buf)? } else { self.dentry.vnode().write_at(*offset, buf)? @@ -48,7 +50,7 @@ impl InodeHandle_ { } pub fn read_to_end(&self, buf: &mut Vec) -> Result { - let len = if self.status_flags.lock().contains(StatusFlags::O_DIRECT) { + let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { self.dentry.vnode().read_direct_to_end(buf)? } else { self.dentry.vnode().read_to_end(buf)? @@ -99,19 +101,13 @@ impl InodeHandle_ { } pub fn status_flags(&self) -> StatusFlags { - let status_flags = self.status_flags.lock(); - *status_flags + let bits = self.status_flags.load(Ordering::Relaxed); + StatusFlags::from_bits(bits).unwrap() } pub fn set_status_flags(&self, new_status_flags: StatusFlags) { - let mut status_flags = self.status_flags.lock(); - // Can change only the O_APPEND, O_ASYNC, O_NOATIME, and O_NONBLOCK flags - let valid_flags_mask = StatusFlags::O_APPEND - | StatusFlags::O_ASYNC - | StatusFlags::O_NOATIME - | StatusFlags::O_NONBLOCK; - status_flags.remove(valid_flags_mask); - status_flags.insert(new_status_flags & valid_flags_mask); + self.status_flags + .store(new_status_flags.bits(), Ordering::Relaxed); } pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result { @@ -124,30 +120,6 @@ impl InodeHandle_ { /// Methods for both dyn and static impl InodeHandle { - pub fn seek(&self, pos: SeekFrom) -> Result { - self.0.seek(pos) - } - - pub fn offset(&self) -> usize { - self.0.offset() - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn access_mode(&self) -> AccessMode { - self.0.access_mode() - } - - pub fn status_flags(&self) -> StatusFlags { - self.0.status_flags() - } - - pub fn set_status_flags(&self, new_status_flags: StatusFlags) { - self.0.set_status_flags(new_status_flags) - } - pub fn dentry(&self) -> &Arc { &self.0.dentry } diff --git a/services/libs/jinux-std/src/fs/pipe.rs b/services/libs/jinux-std/src/fs/pipe.rs index 2bbc1126e..d829aadbf 100644 --- a/services/libs/jinux-std/src/fs/pipe.rs +++ b/services/libs/jinux-std/src/fs/pipe.rs @@ -2,7 +2,7 @@ use crate::events::Observer; use crate::prelude::*; use super::file_handle::FileLike; -use super::utils::{Consumer, IoEvents, Poller, Producer}; +use super::utils::{AccessMode, Consumer, IoEvents, Poller, Producer, StatusFlags}; pub struct PipeReader { consumer: Consumer, @@ -43,6 +43,18 @@ impl FileLike for PipeReader { self.consumer.poll(mask, poller) } + fn status_flags(&self) -> StatusFlags { + self.consumer.status_flags() + } + + fn set_status_flags(&self, new_flags: StatusFlags) -> Result<()> { + self.consumer.set_status_flags(new_flags) + } + + fn access_mode(&self) -> AccessMode { + AccessMode::O_RDONLY + } + fn register_observer( &self, observer: Weak>, @@ -98,6 +110,18 @@ impl FileLike for PipeWriter { self.producer.poll(mask, poller) } + fn status_flags(&self) -> StatusFlags { + self.producer.status_flags() + } + + fn set_status_flags(&self, new_flags: StatusFlags) -> Result<()> { + self.producer.set_status_flags(new_flags) + } + + fn access_mode(&self) -> AccessMode { + AccessMode::O_WRONLY + } + fn register_observer( &self, observer: Weak>, diff --git a/services/libs/jinux-std/src/fs/utils/channel.rs b/services/libs/jinux-std/src/fs/utils/channel.rs index ed8448b0b..5c2dd9b0d 100644 --- a/services/libs/jinux-std/src/fs/utils/channel.rs +++ b/services/libs/jinux-std/src/fs/utils/channel.rs @@ -67,7 +67,7 @@ macro_rules! impl_common_methods_for_channel { self.this_end().status_flags() } - pub fn set_status_flags(&self, new_flags: StatusFlags) { + pub fn set_status_flags(&self, new_flags: StatusFlags) -> Result<()> { self.this_end().set_status_flags(new_flags) } @@ -330,8 +330,10 @@ impl EndPointInner { StatusFlags::from_bits(bits).unwrap() } - pub fn set_status_flags(&self, new_flags: StatusFlags) { + pub fn set_status_flags(&self, new_flags: StatusFlags) -> Result<()> { + check_status_flags(new_flags)?; self.status_flags.store(new_flags.bits(), Ordering::Relaxed); + Ok(()) } } diff --git a/services/libs/jinux-std/src/syscall/fcntl.rs b/services/libs/jinux-std/src/syscall/fcntl.rs index f1808c907..fefbdd2b5 100644 --- a/services/libs/jinux-std/src/syscall/fcntl.rs +++ b/services/libs/jinux-std/src/syscall/fcntl.rs @@ -1,6 +1,9 @@ use super::{SyscallReturn, SYS_FCNTL}; use crate::log_syscall_entry; -use crate::{fs::file_table::FileDescripter, prelude::*}; +use crate::{ + fs::{file_table::FileDescripter, utils::StatusFlags}, + prelude::*, +}; pub fn sys_fcntl(fd: FileDescripter, cmd: i32, arg: u64) -> Result { log_syscall_entry!(SYS_FCNTL); @@ -21,6 +24,40 @@ pub fn sys_fcntl(fd: FileDescripter, cmd: i32, arg: u64) -> Result { + let current = current!(); + let file = { + let file_table = current.file_table().lock(); + file_table.get_file(arg as FileDescripter)?.clone() + }; + let status_flags = file.status_flags(); + let access_mode = file.access_mode(); + return Ok(SyscallReturn::Return( + (status_flags.bits() | access_mode as u32) as _, + )); + } + FcntlCmd::F_SETFL => { + let current = current!(); + let file = { + let file_table = current.file_table().lock(); + file_table.get_file(arg as FileDescripter)?.clone() + }; + let new_status_flags = { + // This cmd can change(set or unset) only the O_APPEND, O_ASYNC, O_DIRECT, + // O_NOATIME and O_NONBLOCK flags. + let valid_flags_mask = StatusFlags::O_APPEND + | StatusFlags::O_ASYNC + | StatusFlags::O_DIRECT + | StatusFlags::O_NOATIME + | StatusFlags::O_NONBLOCK; + let mut status_flags = file.status_flags(); + status_flags.remove(valid_flags_mask); + status_flags.insert(StatusFlags::from_bits_truncate(arg as _) & valid_flags_mask); + status_flags + }; + file.set_status_flags(new_status_flags)?; + return Ok(SyscallReturn::Return(0)); + } _ => todo!(), } } @@ -32,5 +69,7 @@ enum FcntlCmd { F_DUPFD = 0, F_GETFD = 1, F_SETFD = 2, + F_GETFL = 3, + F_SETFL = 4, F_DUPFD_CLOEXEC = 1030, }