Skip to content

Commit

Permalink
added permissions and owner to UnixListener (#668)
Browse files Browse the repository at this point in the history
  • Loading branch information
yasamoka authored Nov 18, 2023
1 parent 0a1dc1e commit 7542061
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 4 deletions.
3 changes: 3 additions & 0 deletions poem/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ tokio-stream = { workspace = true, optional = true }
anyhow = { version = "1.0.0", optional = true }
eyre06 = { package = "eyre", version = "0.6", optional = true }

[target.'cfg(unix)'.dependencies]
nix = { version = "0.27.1", features = ["fs", "user"] }

[dev-dependencies]
async-stream = "0.3.2"
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
Expand Down
56 changes: 52 additions & 4 deletions poem/src/listener/unix.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
use std::{io::Result, path::Path};
use std::{
fs::{set_permissions, Permissions},
io::Result,
path::Path,
};

use http::uri::Scheme;
use nix::unistd::chown;
use nix::unistd::{Gid, Uid};
use tokio::{
io::Result as IoResult,
net::{UnixListener as TokioUnixListener, UnixStream},
Expand All @@ -15,21 +21,63 @@ use crate::{
#[cfg_attr(docsrs, doc(cfg(unix)))]
pub struct UnixListener<T> {
path: T,
permissions: Option<Permissions>,
owner: Option<(Option<Uid>, Option<Gid>)>,
}

impl<T> UnixListener<T> {
/// Binds to the provided address, and returns a [`UnixListener<T>`].
pub fn bind(path: T) -> Self {
Self { path }
Self {
path,
permissions: None,
owner: None,
}
}

/// Provides permissions to be set on actual bind
pub fn with_permissions(self, permissions: Permissions) -> Self {
Self {
permissions: Some(permissions),
..self
}
}

#[cfg(unix)]
/// Provides owner to be set on actual bind
pub fn with_owner(self, uid: Option<u32>, gid: Option<u32>) -> Self {
Self {
owner: Some((uid.map(|v| Uid::from_raw(v)), gid.map(|v| Gid::from_raw(v)))),
..self
}
}
}

#[async_trait::async_trait]
impl<T: AsRef<Path> + Send> Listener for UnixListener<T> {
impl<T: AsRef<Path> + Send + Clone> Listener for UnixListener<T> {
type Acceptor = UnixAcceptor;

async fn into_acceptor(self) -> IoResult<Self::Acceptor> {
let listener = TokioUnixListener::bind(self.path)?;
let listener = match (self.permissions, self.owner) {
(Some(permissions), Some((uid, gid))) => {
let listener = TokioUnixListener::bind(self.path.clone())?;
set_permissions(self.path.clone(), permissions)?;
chown(self.path.as_ref().as_os_str().into(), uid, gid)?;
listener
}
(Some(permissions), None) => {
let listener = TokioUnixListener::bind(self.path.clone())?;
set_permissions(self.path.clone(), permissions)?;
listener
}
(None, Some((uid, gid))) => {
let listener = TokioUnixListener::bind(self.path.clone())?;
chown(self.path.as_ref().as_os_str().into(), uid, gid)?;
listener
}
(None, None) => TokioUnixListener::bind(self.path)?,
};

let local_addr = listener.local_addr().map(|addr| LocalAddr(addr.into()))?;
Ok(UnixAcceptor {
local_addr,
Expand Down

0 comments on commit 7542061

Please sign in to comment.