From c8d5566473d2d0b98139cb586c62833eb76dbd01 Mon Sep 17 00:00:00 2001 From: MingyuChen Date: Fri, 10 May 2024 11:49:57 +0800 Subject: [PATCH] =?UTF-8?q?TCP=E5=A2=9E=E5=8A=A0fchown=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: MingyuChen --- ylong_runtime/src/macros.rs | 12 +++++++ ylong_runtime/src/net/async_source.rs | 8 +++++ ylong_runtime/src/net/sys/tcp/listener.rs | 32 ++++++++++++++++++ ylong_runtime/src/net/sys/tcp/stream.rs | 34 ++++++++++++++++++++ ylong_runtime/src/process/pty_process/sys.rs | 11 ------- 5 files changed, 86 insertions(+), 11 deletions(-) diff --git a/ylong_runtime/src/macros.rs b/ylong_runtime/src/macros.rs index edcff4a..28a7fac 100644 --- a/ylong_runtime/src/macros.rs +++ b/ylong_runtime/src/macros.rs @@ -119,3 +119,15 @@ macro_rules! cfg_metrics { )* } } + +#[cfg(target_os = "linux")] +macro_rules! syscall { + ($fn: ident ( $($arg: expr),* $(,)* ) ) => {{ + let res = unsafe { libc::$fn($($arg, )*) }; + if res == -1 { + Err(std::io::Error::last_os_error()) + } else { + Ok(res) + } + }}; +} diff --git a/ylong_runtime/src/net/async_source.rs b/ylong_runtime/src/net/async_source.rs index 202d486..d82278f 100644 --- a/ylong_runtime/src/net/async_source.rs +++ b/ylong_runtime/src/net/async_source.rs @@ -16,6 +16,8 @@ use std::io; use std::ops::Deref; use std::sync::Arc; +#[cfg(target_os = "linux")] +use libc::{gid_t, uid_t}; use ylong_io::{Interest, Source}; use crate::executor::Handle; @@ -46,6 +48,12 @@ pub(crate) struct AsyncSource { } impl AsyncSource { + #[cfg(target_os = "linux")] + pub fn fchown(&self, uid: uid_t, gid: gid_t) -> io::Result<()> { + syscall!(fchown(self.get_fd(), uid, gid))?; + Ok(()) + } + /// Wraps a `Source` object into an `AsyncSource`. When the `AsyncSource` /// object is created, it's fd will be registered into runtime's /// reactor. diff --git a/ylong_runtime/src/net/sys/tcp/listener.rs b/ylong_runtime/src/net/sys/tcp/listener.rs index a067b1a..297c71d 100644 --- a/ylong_runtime/src/net/sys/tcp/listener.rs +++ b/ylong_runtime/src/net/sys/tcp/listener.rs @@ -195,6 +195,35 @@ impl TcpListener { let source = AsyncSource::new(listener, None)?; Ok(TcpListener { source }) } + + /// Sets the owner for this source's fd + /// + /// # Error + /// This method calls libc::fchown, libc::fchown returns the following + /// errors [`libc::EBADF`]: The fd argument is not an open file descriptor. + /// [`libc::EPERM`]: The effective user ID does not match the owner of the file or the process does not have appropriate privilege and _POSIX_CHOWN_RESTRICTED indicates that such privilege is required. + /// [`libc::EROFS`]:The file referred to by fildes resides on a read-only file system. + /// [`libc::EINVAL`]: The owner or group ID is not a value supported by the implementation. + /// [`libc::EIO`]: A physical I/O error has occurred. + /// [`libc::EINTR`]: The fchown() function was interrupted by a signal which was caught. + /// + /// # Example + /// ```no_run + /// use std::io; + /// + /// use ylong_runtime::net::TcpListener; + /// + /// async fn io_func() -> io::Result<()> { + /// let addr = "127.0.0.1:1234"; + /// let mut server = TcpListener::bind(addr).await?; + /// server.fchown(0, 0)?; + /// Ok(()) + /// } + /// ``` + #[cfg(target_os = "linux")] + pub fn fchown(&self, uid: uid_t, gid: gid_t) -> io::Result<()> { + self.source.fchown(uid, gid) + } } #[cfg(windows)] @@ -210,6 +239,9 @@ impl AsRawSocket for TcpListener { #[cfg(unix)] use std::os::fd::{AsRawFd, RawFd}; +#[cfg(target_os = "linux")] +use libc::{gid_t, uid_t}; + #[cfg(unix)] use ylong_io::Source; diff --git a/ylong_runtime/src/net/sys/tcp/stream.rs b/ylong_runtime/src/net/sys/tcp/stream.rs index 2fe808e..b3a4cad 100644 --- a/ylong_runtime/src/net/sys/tcp/stream.rs +++ b/ylong_runtime/src/net/sys/tcp/stream.rs @@ -562,6 +562,37 @@ impl TcpStream { pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.source.shutdown(how) } + + /// Sets the owner for this source's fd + /// + /// # Error + /// This method calls libc::fchown, libc::fchown returns the following + /// errors [`libc::EBADF`]: The fd argument is not an open file descriptor. + /// [`libc::EPERM`]: The effective user ID does not match the owner of the file or the process does not have appropriate privilege and _POSIX_CHOWN_RESTRICTED indicates that such privilege is required. + /// [`libc::EROFS`]:The file referred to by fildes resides on a read-only file system. + /// [`libc::EINVAL`]: The owner or group ID is not a value supported by the implementation. + /// [`libc::EIO`]: A physical I/O error has occurred. + /// [`libc::EINTR`]: The fchown() function was interrupted by a signal which was caught. + /// + /// # Example + /// ```no_run + /// use std::io; + /// + /// use ylong_runtime::net::TcpStream; + /// + /// async fn io_func() -> io::Result<()> { + /// let addr = "127.0.0.1:1234"; + /// let stream = TcpStream::connect(addr) + /// .await + /// .expect("Couldn't connect to the server..."); + /// stream.fchown(0, 0)?; + /// Ok(()) + /// } + /// ``` + #[cfg(target_os = "linux")] + pub fn fchown(&self, uid: uid_t, gid: gid_t) -> io::Result<()> { + self.source.fchown(uid, gid) + } } impl AsyncRead for TcpStream { @@ -618,6 +649,9 @@ impl AsRawSocket for TcpStream { #[cfg(unix)] use std::os::fd::{AsRawFd, RawFd}; +#[cfg(target_os = "linux")] +use libc::{gid_t, uid_t}; + #[cfg(unix)] use ylong_io::Source; diff --git a/ylong_runtime/src/process/pty_process/sys.rs b/ylong_runtime/src/process/pty_process/sys.rs index c673c8d..b726f1f 100644 --- a/ylong_runtime/src/process/pty_process/sys.rs +++ b/ylong_runtime/src/process/pty_process/sys.rs @@ -22,17 +22,6 @@ use std::process::Stdio; use ylong_io::sys::SourceFd; use ylong_io::{Interest, Selector, Source, Token}; -macro_rules! syscall { - ($fn: ident ( $($arg: expr),* $(,)* ) ) => {{ - let res = unsafe { libc::$fn($($arg, )*) }; - if res == -1 { - Err(std::io::Error::last_os_error()) - } else { - Ok(res) - } - }}; -} - #[derive(Debug)] pub(crate) struct PtyInner(OwnedFd); -- Gitee