mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 18:03:25 +00:00
Add F_GETFL and F_SETFL for fcntl
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
b34dc85e7e
commit
41a1cfd169
@ -1,7 +1,7 @@
|
|||||||
//! Opend File Handle
|
//! Opend File Handle
|
||||||
|
|
||||||
use crate::events::Observer;
|
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::prelude::*;
|
||||||
use crate::tty::get_n_tty;
|
use crate::tty::get_n_tty;
|
||||||
|
|
||||||
@ -40,6 +40,18 @@ pub trait FileLike: Send + Sync + Any {
|
|||||||
panic!("metadata unsupported");
|
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<usize> {
|
fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
|
||||||
return_errno_with_message!(Errno::EINVAL, "seek is not supported");
|
return_errno_with_message!(Errno::EINVAL, "seek is not supported");
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ impl InodeHandle<Rights> {
|
|||||||
dentry,
|
dentry,
|
||||||
offset: Mutex::new(0),
|
offset: Mutex::new(0),
|
||||||
access_mode,
|
access_mode,
|
||||||
status_flags: Mutex::new(status_flags),
|
status_flags: AtomicU32::new(status_flags.bits()),
|
||||||
});
|
});
|
||||||
Ok(Self(inner, Rights::from(access_mode)))
|
Ok(Self(inner, Rights::from(access_mode)))
|
||||||
}
|
}
|
||||||
@ -80,6 +80,19 @@ impl FileLike for InodeHandle<Rights> {
|
|||||||
self.dentry().vnode().metadata()
|
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<usize> {
|
fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
|
||||||
self.0.seek(seek_from)
|
self.0.seek(seek_from)
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
mod dyn_cap;
|
mod dyn_cap;
|
||||||
mod static_cap;
|
mod static_cap;
|
||||||
|
|
||||||
|
use core::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
|
||||||
use crate::fs::file_handle::FileLike;
|
use crate::fs::file_handle::FileLike;
|
||||||
use crate::fs::utils::{
|
use crate::fs::utils::{
|
||||||
AccessMode, Dentry, DirentVisitor, InodeType, IoEvents, Metadata, Poller, SeekFrom, StatusFlags,
|
AccessMode, Dentry, DirentVisitor, InodeType, IoEvents, Metadata, Poller, SeekFrom, StatusFlags,
|
||||||
@ -16,13 +18,13 @@ struct InodeHandle_ {
|
|||||||
dentry: Arc<Dentry>,
|
dentry: Arc<Dentry>,
|
||||||
offset: Mutex<usize>,
|
offset: Mutex<usize>,
|
||||||
access_mode: AccessMode,
|
access_mode: AccessMode,
|
||||||
status_flags: Mutex<StatusFlags>,
|
status_flags: AtomicU32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InodeHandle_ {
|
impl InodeHandle_ {
|
||||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
let mut offset = self.offset.lock();
|
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)?
|
self.dentry.vnode().read_direct_at(*offset, buf)?
|
||||||
} else {
|
} else {
|
||||||
self.dentry.vnode().read_at(*offset, buf)?
|
self.dentry.vnode().read_at(*offset, buf)?
|
||||||
@ -34,10 +36,10 @@ impl InodeHandle_ {
|
|||||||
|
|
||||||
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
pub fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
let mut offset = self.offset.lock();
|
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();
|
*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)?
|
self.dentry.vnode().write_direct_at(*offset, buf)?
|
||||||
} else {
|
} else {
|
||||||
self.dentry.vnode().write_at(*offset, buf)?
|
self.dentry.vnode().write_at(*offset, buf)?
|
||||||
@ -48,7 +50,7 @@ impl InodeHandle_ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> Result<usize> {
|
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> Result<usize> {
|
||||||
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)?
|
self.dentry.vnode().read_direct_to_end(buf)?
|
||||||
} else {
|
} else {
|
||||||
self.dentry.vnode().read_to_end(buf)?
|
self.dentry.vnode().read_to_end(buf)?
|
||||||
@ -99,19 +101,13 @@ impl InodeHandle_ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn status_flags(&self) -> StatusFlags {
|
pub fn status_flags(&self) -> StatusFlags {
|
||||||
let status_flags = self.status_flags.lock();
|
let bits = self.status_flags.load(Ordering::Relaxed);
|
||||||
*status_flags
|
StatusFlags::from_bits(bits).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_status_flags(&self, new_status_flags: StatusFlags) {
|
pub fn set_status_flags(&self, new_status_flags: StatusFlags) {
|
||||||
let mut status_flags = self.status_flags.lock();
|
self.status_flags
|
||||||
// Can change only the O_APPEND, O_ASYNC, O_NOATIME, and O_NONBLOCK flags
|
.store(new_status_flags.bits(), Ordering::Relaxed);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
pub fn readdir(&self, visitor: &mut dyn DirentVisitor) -> Result<usize> {
|
||||||
@ -124,30 +120,6 @@ impl InodeHandle_ {
|
|||||||
|
|
||||||
/// Methods for both dyn and static
|
/// Methods for both dyn and static
|
||||||
impl<R> InodeHandle<R> {
|
impl<R> InodeHandle<R> {
|
||||||
pub fn seek(&self, pos: SeekFrom) -> Result<usize> {
|
|
||||||
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<Dentry> {
|
pub fn dentry(&self) -> &Arc<Dentry> {
|
||||||
&self.0.dentry
|
&self.0.dentry
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::events::Observer;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use super::file_handle::FileLike;
|
use super::file_handle::FileLike;
|
||||||
use super::utils::{Consumer, IoEvents, Poller, Producer};
|
use super::utils::{AccessMode, Consumer, IoEvents, Poller, Producer, StatusFlags};
|
||||||
|
|
||||||
pub struct PipeReader {
|
pub struct PipeReader {
|
||||||
consumer: Consumer<u8>,
|
consumer: Consumer<u8>,
|
||||||
@ -43,6 +43,18 @@ impl FileLike for PipeReader {
|
|||||||
self.consumer.poll(mask, poller)
|
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(
|
fn register_observer(
|
||||||
&self,
|
&self,
|
||||||
observer: Weak<dyn Observer<IoEvents>>,
|
observer: Weak<dyn Observer<IoEvents>>,
|
||||||
@ -98,6 +110,18 @@ impl FileLike for PipeWriter {
|
|||||||
self.producer.poll(mask, poller)
|
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(
|
fn register_observer(
|
||||||
&self,
|
&self,
|
||||||
observer: Weak<dyn Observer<IoEvents>>,
|
observer: Weak<dyn Observer<IoEvents>>,
|
||||||
|
@ -67,7 +67,7 @@ macro_rules! impl_common_methods_for_channel {
|
|||||||
self.this_end().status_flags()
|
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)
|
self.this_end().set_status_flags(new_flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,8 +330,10 @@ impl<T> EndPointInner<T> {
|
|||||||
StatusFlags::from_bits(bits).unwrap()
|
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);
|
self.status_flags.store(new_flags.bits(), Ordering::Relaxed);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use super::{SyscallReturn, SYS_FCNTL};
|
use super::{SyscallReturn, SYS_FCNTL};
|
||||||
use crate::log_syscall_entry;
|
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<SyscallReturn> {
|
pub fn sys_fcntl(fd: FileDescripter, cmd: i32, arg: u64) -> Result<SyscallReturn> {
|
||||||
log_syscall_entry!(SYS_FCNTL);
|
log_syscall_entry!(SYS_FCNTL);
|
||||||
@ -21,6 +24,40 @@ pub fn sys_fcntl(fd: FileDescripter, cmd: i32, arg: u64) -> Result<SyscallReturn
|
|||||||
// TODO: Set cloexec
|
// TODO: Set cloexec
|
||||||
return Ok(SyscallReturn::Return(0));
|
return Ok(SyscallReturn::Return(0));
|
||||||
}
|
}
|
||||||
|
FcntlCmd::F_GETFL => {
|
||||||
|
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!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -32,5 +69,7 @@ enum FcntlCmd {
|
|||||||
F_DUPFD = 0,
|
F_DUPFD = 0,
|
||||||
F_GETFD = 1,
|
F_GETFD = 1,
|
||||||
F_SETFD = 2,
|
F_SETFD = 2,
|
||||||
|
F_GETFL = 3,
|
||||||
|
F_SETFL = 4,
|
||||||
F_DUPFD_CLOEXEC = 1030,
|
F_DUPFD_CLOEXEC = 1030,
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user