zbus/address/transport/
unix.rs

1#[cfg(target_os = "linux")]
2use std::ffi::OsString;
3use std::{
4    ffi::OsStr,
5    fmt::{Display, Formatter},
6    path::PathBuf,
7};
8
9#[cfg(unix)]
10use super::encode_percents;
11
12/// A Unix domain socket transport in a D-Bus address.
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct Unix {
15    path: UnixSocket,
16}
17
18impl Unix {
19    /// Create a new Unix transport with the given path.
20    pub fn new(path: UnixSocket) -> Self {
21        Self { path }
22    }
23
24    /// The path.
25    pub fn path(&self) -> &UnixSocket {
26        &self.path
27    }
28
29    /// Take the path, consuming `self`.
30    pub fn take_path(self) -> UnixSocket {
31        self.path
32    }
33
34    pub(super) fn from_options(opts: std::collections::HashMap<&str, &str>) -> crate::Result<Self> {
35        let path = opts.get("path");
36        let abs = opts.get("abstract");
37        let dir = opts.get("dir");
38        let tmpdir = opts.get("tmpdir");
39        let path = match (path, abs, dir, tmpdir) {
40            (Some(p), None, None, None) => UnixSocket::File(PathBuf::from(p)),
41            #[cfg(target_os = "linux")]
42            (None, Some(p), None, None) => UnixSocket::Abstract(OsString::from(p)),
43            #[cfg(not(target_os = "linux"))]
44            (None, Some(_), None, None) => {
45                return Err(crate::Error::Address(
46                    "abstract sockets currently Linux-only".to_owned(),
47                ));
48            }
49            (None, None, Some(p), None) => UnixSocket::Dir(PathBuf::from(p)),
50            (None, None, None, Some(p)) => UnixSocket::TmpDir(PathBuf::from(p)),
51            _ => {
52                return Err(crate::Error::Address("unix: address is invalid".to_owned()));
53            }
54        };
55
56        Ok(Self::new(path))
57    }
58}
59
60impl Display for Unix {
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        write!(f, "unix:{}", self.path)
63    }
64}
65
66/// A Unix domain socket path in a D-Bus address.
67#[derive(Clone, Debug, PartialEq, Eq)]
68#[non_exhaustive]
69pub enum UnixSocket {
70    /// A path to a unix domain socket on the filesystem.
71    File(PathBuf),
72    /// A abstract unix domain socket name.
73    #[cfg(target_os = "linux")]
74    Abstract(OsString),
75    /// A listenable address using the specified path, in which a socket file with a random file
76    /// name starting with 'dbus-' will be created by the server. See [UNIX domain socket address]
77    /// reference documentation.
78    ///
79    /// This address is mostly relevant to server (typically bus broker) implementations.
80    ///
81    /// [UNIX domain socket address]: https://dbus.freedesktop.org/doc/dbus-specification.html#transports-unix-domain-sockets-addresses
82    Dir(PathBuf),
83    /// The same as UnixDir, except that on platforms with abstract sockets, the server may attempt
84    /// to create an abstract socket whose name starts with this directory instead of a path-based
85    /// socket.
86    ///
87    /// This address is mostly relevant to server (typically bus broker) implementations.
88    TmpDir(PathBuf),
89}
90
91impl Display for UnixSocket {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        fn fmt_unix_path(f: &mut Formatter<'_>, path: &OsStr) -> std::fmt::Result {
94            #[cfg(unix)]
95            {
96                use std::os::unix::ffi::OsStrExt;
97
98                encode_percents(f, path.as_bytes())?;
99            }
100
101            #[cfg(windows)]
102            write!(f, "{}", path.to_str().ok_or(std::fmt::Error)?)?;
103
104            Ok(())
105        }
106
107        match self {
108            UnixSocket::File(path) => {
109                f.write_str("path=")?;
110                fmt_unix_path(f, path.as_os_str())?;
111            }
112            #[cfg(target_os = "linux")]
113            UnixSocket::Abstract(name) => {
114                f.write_str("abstract=")?;
115                fmt_unix_path(f, name)?;
116            }
117            UnixSocket::Dir(path) => {
118                f.write_str("dir=")?;
119                fmt_unix_path(f, path.as_os_str())?;
120            }
121            UnixSocket::TmpDir(path) => {
122                f.write_str("tmpdir=")?;
123                fmt_unix_path(f, path.as_os_str())?;
124            }
125        }
126
127        Ok(())
128    }
129}