From c9879f770245813ae8c4ea81d49ebb306379fe80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 4 Mar 2025 19:07:42 +0100 Subject: [PATCH] feat(fd): implement `fcntl(F_GETFL)` --- src/fd/mod.rs | 5 +++++ src/fd/socket/tcp.rs | 14 ++++++++++++++ src/fd/socket/udp.rs | 14 ++++++++++++++ src/fd/socket/vsock.rs | 14 ++++++++++++++ src/syscalls/mod.rs | 12 ++++++++++++ 5 files changed, 59 insertions(+) diff --git a/src/fd/mod.rs b/src/fd/mod.rs index e366f66a88..f44e232c68 100644 --- a/src/fd/mod.rs +++ b/src/fd/mod.rs @@ -253,6 +253,11 @@ pub(crate) trait ObjectInterface: Sync + Send + core::fmt::Debug { Err(io::Error::ENOSYS) } + /// Returns the file status flags. + async fn status_flags(&self) -> io::Result { + Err(io::Error::ENOSYS) + } + /// Sets the file status flags. async fn set_status_flags(&self, _status_flags: StatusFlags) -> io::Result<()> { Err(io::Error::ENOSYS) diff --git a/src/fd/socket/tcp.rs b/src/fd/socket/tcp.rs index 401a8f0006..86a9983fb8 100644 --- a/src/fd/socket/tcp.rs +++ b/src/fd/socket/tcp.rs @@ -434,6 +434,16 @@ impl Socket { } } + async fn status_flags(&self) -> io::Result { + let status_flags = if self.is_nonblocking { + fd::StatusFlags::O_NONBLOCK + } else { + fd::StatusFlags::empty() + }; + + Ok(status_flags) + } + async fn set_status_flags(&mut self, status_flags: fd::StatusFlags) -> io::Result<()> { self.is_nonblocking = status_flags.contains(fd::StatusFlags::O_NONBLOCK); Ok(()) @@ -502,6 +512,10 @@ impl ObjectInterface for async_lock::RwLock { self.read().await.shutdown(how).await } + async fn status_flags(&self) -> io::Result { + self.read().await.status_flags().await + } + async fn set_status_flags(&self, status_flags: fd::StatusFlags) -> io::Result<()> { self.write().await.set_status_flags(status_flags).await } diff --git a/src/fd/socket/udp.rs b/src/fd/socket/udp.rs index 836d763f16..b770cc3fb2 100644 --- a/src/fd/socket/udp.rs +++ b/src/fd/socket/udp.rs @@ -215,6 +215,16 @@ impl Socket { } } + async fn status_flags(&self) -> io::Result { + let status_flags = if self.nonblocking { + fd::StatusFlags::O_NONBLOCK + } else { + fd::StatusFlags::empty() + }; + + Ok(status_flags) + } + async fn set_status_flags(&mut self, status_flags: fd::StatusFlags) -> io::Result<()> { self.nonblocking = status_flags.contains(fd::StatusFlags::O_NONBLOCK); Ok(()) @@ -258,6 +268,10 @@ impl ObjectInterface for async_lock::RwLock { self.read().await.write(buf).await } + async fn status_flags(&self) -> io::Result { + self.read().await.status_flags().await + } + async fn set_status_flags(&self, status_flags: fd::StatusFlags) -> io::Result<()> { self.write().await.set_status_flags(status_flags).await } diff --git a/src/fd/socket/vsock.rs b/src/fd/socket/vsock.rs index e2f68a3430..bb7cd5e85d 100644 --- a/src/fd/socket/vsock.rs +++ b/src/fd/socket/vsock.rs @@ -296,6 +296,16 @@ impl Socket { Ok(()) } + async fn status_flags(&self) -> io::Result { + let status_flags = if self.is_nonblocking { + fd::StatusFlags::O_NONBLOCK + } else { + fd::StatusFlags::empty() + }; + + Ok(status_flags) + } + async fn set_status_flags(&mut self, status_flags: fd::StatusFlags) -> io::Result<()> { self.is_nonblocking = status_flags.contains(fd::StatusFlags::O_NONBLOCK); Ok(()) @@ -450,6 +460,10 @@ impl ObjectInterface for async_lock::RwLock { self.read().await.shutdown(how).await } + async fn status_flags(&self) -> io::Result { + self.read().await.status_flags().await + } + async fn set_status_flags(&self, status_flags: fd::StatusFlags) -> io::Result<()> { self.write().await.set_status_flags(status_flags).await } diff --git a/src/syscalls/mod.rs b/src/syscalls/mod.rs index 4c58609534..b2154c809c 100644 --- a/src/syscalls/mod.rs +++ b/src/syscalls/mod.rs @@ -537,11 +537,23 @@ pub unsafe extern "C" fn sys_ioctl( #[unsafe(no_mangle)] pub extern "C" fn sys_fcntl(fd: i32, cmd: i32, arg: i32) -> i32 { const F_SETFD: i32 = 2; + const F_GETFL: i32 = 3; const F_SETFL: i32 = 4; const FD_CLOEXEC: i32 = 1; if cmd == F_SETFD && arg == FD_CLOEXEC { 0 + } else if cmd == F_GETFL { + let obj = get_object(fd); + obj.map_or_else( + |e| -num::ToPrimitive::to_i32(&e).unwrap(), + |v| { + block_on((*v).status_flags(), None).map_or_else( + |e| -num::ToPrimitive::to_i32(&e).unwrap(), + |status_flags| status_flags.bits(), + ) + }, + ) } else if cmd == F_SETFL { let obj = get_object(fd); obj.map_or_else(