1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
pub mod dispatch_conn;
pub mod ll_conn;
pub mod rpc_conn;
use crate::wire::unmarshal;
use std::path::PathBuf;
use std::time;
#[derive(Clone, Copy)]
pub enum Timeout {
Infinite,
Nonblock,
Duration(time::Duration),
}
use nix::sys::socket::UnixAddr;
#[derive(Debug)]
pub enum Error {
IoError(std::io::Error),
NixError(nix::Error),
UnmarshalError(unmarshal::Error),
MarshalError(crate::Error),
AuthFailed,
UnixFdNegotiationFailed,
NameTaken,
AddressTypeNotSupported(String),
PathDoesNotExist(String),
NoAddressFound,
UnexpectedTypeReceived,
TimedOut,
}
impl std::convert::From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Error {
Error::IoError(e)
}
}
impl std::convert::From<unmarshal::Error> for Error {
fn from(e: unmarshal::Error) -> Error {
Error::UnmarshalError(e)
}
}
impl std::convert::From<nix::Error> for Error {
fn from(e: nix::Error) -> Error {
Error::NixError(e)
}
}
impl std::convert::From<crate::Error> for Error {
fn from(e: crate::Error) -> Error {
Error::MarshalError(e)
}
}
type Result<T> = std::result::Result<T, Error>;
fn parse_dbus_addr_str(addr: &str) -> Result<UnixAddr> {
if addr.starts_with("unix:path=") {
let ps = addr.trim_start_matches("unix:path=");
let p = PathBuf::from(&ps);
if p.exists() {
Ok(UnixAddr::new(&p)?)
} else {
Err(Error::PathDoesNotExist(ps.to_owned()))
}
} else if addr.starts_with("unix:abstract=") {
#[cfg(not(target_os = "linux"))]
{
Err(Error::AddressTypeNotSupported(addr.to_owned()))
}
#[cfg(target_os = "linux")]
{
let mut ps = addr.trim_start_matches("unix:abstract=").to_string();
let end_path_offset = ps.find(',').unwrap_or_else(|| ps.len());
let ps: String = ps.drain(..end_path_offset).collect();
let path_buf = ps.as_bytes();
Ok(UnixAddr::new_abstract(&path_buf)?)
}
} else {
Err(Error::AddressTypeNotSupported(addr.to_owned()))
}
}
pub fn get_session_bus_path() -> Result<UnixAddr> {
if let Ok(envvar) = std::env::var("DBUS_SESSION_BUS_ADDRESS") {
parse_dbus_addr_str(&envvar)
} else {
Err(Error::NoAddressFound)
}
}
pub fn get_system_bus_path() -> Result<UnixAddr> {
let ps = "/run/dbus/system_bus_socket";
let p = PathBuf::from(&ps);
if p.exists() {
Ok(UnixAddr::new(&p)?)
} else {
Err(Error::PathDoesNotExist(ps.to_owned()))
}
}
pub(crate) fn calc_timeout_left(start_time: &time::Instant, timeout: Timeout) -> Result<Timeout> {
match timeout {
Timeout::Duration(timeout) => {
let elapsed = start_time.elapsed();
if elapsed >= timeout {
return Err(Error::TimedOut);
}
let time_left = timeout - elapsed;
Ok(Timeout::Duration(time_left))
}
other => Ok(other),
}
}
#[cfg(test)]
mod tests {
use super::*;
use nix::sys::socket::UnixAddr;
#[cfg(target_os = "linux")]
#[test]
fn test_get_session_bus_path() {
let path = "unix:path=/tmp/dbus-test-not-exist";
let abstract_path = "unix:abstract=/tmp/dbus-test";
let abstract_path_with_keys = "unix:abstract=/tmp/dbus-test,guid=aaaaaaaa,test=bbbbbbbb";
let addr = parse_dbus_addr_str(path);
assert!(addr.is_err());
let addr = parse_dbus_addr_str(abstract_path).unwrap();
assert_eq!(addr, UnixAddr::new_abstract(b"/tmp/dbus-test").unwrap());
let addr = parse_dbus_addr_str(abstract_path_with_keys).unwrap();
assert_eq!(addr, UnixAddr::new_abstract(b"/tmp/dbus-test").unwrap());
}
#[cfg(not(target_os = "linux"))]
#[test]
fn test_get_session_bus_path() {
let path = "unix:path=/tmp/dbus-test-not-exist";
let addr = parse_dbus_addr_str(path);
assert!(addr.is_err());
}
}