#[cfg(unix)]
use crate::OwnedFd;
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
#[cfg(feature = "proxy")]
use std::collections::HashMap;
use std::fmt;
use super::Result;
use crate::{
Basic, DeserializeDict, OwnedVariant, SerializeDict, Type, Variant, utils::fmt_bitflags,
};
#[cfg(feature = "proxy")]
use crate::{
Optional, OwnedGuid,
names::{
BusName, OwnedBusName, OwnedInterfaceName, OwnedUniqueName, UniqueName, WellKnownName,
},
proxy,
};
#[cfg_attr(
feature = "proxy",
doc = "The flags used by the [`DBusProxy::request_name`] method."
)]
#[cfg_attr(
not(feature = "proxy"),
doc = "The flags used by `DBusProxy::request_name` (requires the `proxy` feature)."
)]
#[derive(
Copy,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Serialize,
Deserialize,
Type,
Variant,
OwnedVariant,
)]
pub struct RequestNameFlags(u32);
bitflags::bitflags! {
impl RequestNameFlags: u32 {
#[cfg_attr(
feature = "proxy",
doc = "and another application B later calls [`DBusProxy::request_name`] with the"
)]
#[cfg_attr(
not(feature = "proxy"),
doc = "and another application B later calls `DBusProxy::request_name` with the"
)]
const ALLOW_REPLACEMENT = 0x01;
const REPLACE_EXISTING = 0x02;
const DO_NOT_QUEUE = 0x04;
}
}
impl Default for RequestNameFlags {
fn default() -> Self {
Self::ALLOW_REPLACEMENT | Self::REPLACE_EXISTING | Self::DO_NOT_QUEUE
}
}
impl fmt::Debug for RequestNameFlags {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_bitflags("RequestNameFlags", self, f)
}
}
impl Basic for RequestNameFlags {
const SIGNATURE_CHAR: char = u32::SIGNATURE_CHAR;
const SIGNATURE_STR: &'static str = u32::SIGNATURE_STR;
}
#[cfg_attr(
feature = "proxy",
doc = "The return code of the [`DBusProxy::request_name`] method."
)]
#[cfg_attr(
not(feature = "proxy"),
doc = "The return code of `DBusProxy::request_name` (requires the `proxy` feature)."
)]
#[repr(u32)]
#[derive(Deserialize_repr, Serialize_repr, Type, Debug, PartialEq, Eq)]
pub enum RequestNameReply {
PrimaryOwner = 0x01,
InQueue = 0x02,
Exists = 0x03,
AlreadyOwner = 0x04,
}
impl std::fmt::Display for RequestNameReply {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::PrimaryOwner => write!(f, "PrimaryOwner"),
Self::InQueue => write!(f, "InQueue"),
Self::Exists => write!(f, "Exists"),
Self::AlreadyOwner => write!(f, "AlreadyOwner"),
}
}
}
#[cfg_attr(
feature = "proxy",
doc = "The return code of the [`DBusProxy::release_name`] method."
)]
#[cfg_attr(
not(feature = "proxy"),
doc = "The return code of `DBusProxy::release_name` (requires the `proxy` feature)."
)]
#[repr(u32)]
#[derive(Deserialize_repr, Serialize_repr, Type, Debug, PartialEq, Eq)]
pub enum ReleaseNameReply {
Released = 0x01,
NonExistent = 0x02,
NotOwner = 0x03,
}
impl std::fmt::Display for ReleaseNameReply {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Released => write!(f, "Released"),
Self::NonExistent => write!(f, "NonExistent"),
Self::NotOwner => write!(f, "NotOwner"),
}
}
}
#[cfg_attr(
feature = "proxy",
doc = "The return code of the [`DBusProxy::start_service_by_name`] method."
)]
#[cfg_attr(
not(feature = "proxy"),
doc = "The return code of `DBusProxy::start_service_by_name` (requires the `proxy` feature)."
)]
#[repr(u32)]
#[derive(Deserialize_repr, Serialize_repr, Type, Debug, PartialEq, Eq)]
pub enum StartServiceReply {
Success = 0x01,
AlreadyRunning = 0x02,
}
impl std::fmt::Display for StartServiceReply {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Success => write!(f, "Success"),
Self::AlreadyRunning => write!(f, "AlreadyRunning"),
}
}
}
impl TryFrom<u32> for StartServiceReply {
type Error = super::Error;
fn try_from(value: u32) -> Result<Self> {
match value {
0x01 => Ok(StartServiceReply::Success),
0x02 => Ok(StartServiceReply::AlreadyRunning),
_ => Err(super::Error::ZBus(crate::Error::InvalidReply)),
}
}
}
#[derive(Debug, Default, DeserializeDict, PartialEq, Eq, SerializeDict, Type)]
#[zbus(signature = "a{sv}")]
pub struct ConnectionCredentials {
#[zbus(rename = "UnixUserID")]
pub(crate) unix_user_id: Option<u32>,
#[zbus(rename = "UnixGroupIDs")]
pub(crate) unix_group_ids: Option<Vec<u32>>,
#[cfg(unix)]
#[zbus(rename = "ProcessFD")]
pub(crate) process_fd: Option<OwnedFd>,
#[zbus(rename = "ProcessID")]
pub(crate) process_id: Option<u32>,
#[zbus(rename = "WindowsSID")]
pub(crate) windows_sid: Option<String>,
#[zbus(rename = "LinuxSecurityLabel")]
pub(crate) linux_security_label: Option<Vec<u8>>,
}
impl ConnectionCredentials {
pub fn unix_user_id(&self) -> Option<u32> {
self.unix_user_id
}
pub fn unix_group_ids(&self) -> Option<&Vec<u32>> {
self.unix_group_ids.as_ref()
}
pub fn into_unix_group_ids(self) -> Option<Vec<u32>> {
self.unix_group_ids
}
#[cfg(unix)]
pub fn process_fd(&self) -> Option<&OwnedFd> {
self.process_fd.as_ref()
}
#[cfg(unix)]
pub fn into_process_fd(self) -> Option<OwnedFd> {
self.process_fd
}
pub fn process_id(&self) -> Option<u32> {
self.process_id
}
pub fn windows_sid(&self) -> Option<&String> {
self.windows_sid.as_ref()
}
pub fn into_windows_sid(self) -> Option<String> {
self.windows_sid
}
pub fn linux_security_label(&self) -> Option<&Vec<u8>> {
self.linux_security_label.as_ref()
}
pub fn into_linux_security_label(self) -> Option<Vec<u8>> {
self.linux_security_label
}
pub fn set_unix_user_id(mut self, unix_user_id: u32) -> Self {
self.unix_user_id = Some(unix_user_id);
self
}
pub fn add_unix_group_id(mut self, unix_group_id: u32) -> Self {
self.unix_group_ids
.get_or_insert_with(Vec::new)
.push(unix_group_id);
self
}
#[cfg(unix)]
pub fn set_process_fd(mut self, process_fd: OwnedFd) -> Self {
self.process_fd = Some(process_fd);
self
}
pub fn set_process_id(mut self, process_id: u32) -> Self {
self.process_id = Some(process_id);
self
}
pub fn set_windows_sid(mut self, windows_sid: String) -> Self {
self.windows_sid = Some(windows_sid);
self
}
pub fn set_linux_security_label(mut self, linux_security_label: Vec<u8>) -> Self {
self.linux_security_label = Some(linux_security_label);
self
}
}
#[cfg(feature = "proxy")]
#[proxy(
default_service = "org.freedesktop.DBus",
default_path = "/org/freedesktop/DBus",
interface = "org.freedesktop.DBus"
)]
pub trait DBus {
#[zbus(name = "AddMatch")]
fn add_match_rule(&self, rule: crate::MatchRule<'_>) -> Result<()>;
fn get_adt_audit_session_data(&self, bus_name: BusName<'_>) -> Result<Vec<u8>>;
fn get_connection_credentials(&self, bus_name: BusName<'_>) -> Result<ConnectionCredentials>;
#[zbus(name = "GetConnectionSELinuxSecurityContext")]
fn get_connection_selinux_security_context(&self, bus_name: BusName<'_>) -> Result<Vec<u8>>;
#[zbus(name = "GetConnectionUnixProcessID")]
fn get_connection_unix_process_id(&self, bus_name: BusName<'_>) -> Result<u32>;
fn get_connection_unix_user(&self, bus_name: BusName<'_>) -> Result<u32>;
fn get_id(&self) -> Result<OwnedGuid>;
fn get_name_owner(&self, name: BusName<'_>) -> Result<OwnedUniqueName>;
fn hello(&self) -> Result<OwnedUniqueName>;
fn list_activatable_names(&self) -> Result<Vec<OwnedBusName>>;
fn list_names(&self) -> Result<Vec<OwnedBusName>>;
fn list_queued_owners(&self, name: WellKnownName<'_>) -> Result<Vec<OwnedUniqueName>>;
fn name_has_owner(&self, name: BusName<'_>) -> Result<bool>;
fn release_name(&self, name: WellKnownName<'_>) -> Result<ReleaseNameReply>;
fn reload_config(&self) -> Result<()>;
#[zbus(name = "RemoveMatch")]
fn remove_match_rule(&self, rule: crate::MatchRule<'_>) -> Result<()>;
fn request_name(
&self,
name: WellKnownName<'_>,
flags: RequestNameFlags,
) -> Result<RequestNameReply>;
fn start_service_by_name(
&self,
name: WellKnownName<'_>,
flags: u32,
) -> Result<StartServiceReply>;
fn update_activation_environment(&self, environment: HashMap<&str, &str>) -> Result<()>;
#[zbus(signal)]
fn name_owner_changed(
&self,
name: BusName<'_>,
old_owner: Optional<UniqueName<'_>>,
new_owner: Optional<UniqueName<'_>>,
);
#[zbus(signal)]
fn name_lost(&self, name: BusName<'_>);
#[zbus(signal)]
fn name_acquired(&self, name: BusName<'_>);
#[zbus(property)]
fn features(&self) -> Result<Vec<String>>;
#[zbus(property)]
fn interfaces(&self) -> Result<Vec<OwnedInterfaceName>>;
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn request_name_flags_default() {
let flags = RequestNameFlags::default();
assert!(flags.contains(RequestNameFlags::ALLOW_REPLACEMENT));
assert!(flags.contains(RequestNameFlags::REPLACE_EXISTING));
assert!(flags.contains(RequestNameFlags::DO_NOT_QUEUE));
}
#[test]
fn request_name_flags_signature_and_debug() {
assert_eq!(RequestNameFlags::SIGNATURE, "u");
assert_eq!(
format!("{:?}", RequestNameFlags::default()),
"RequestNameFlags(ALLOW_REPLACEMENT | REPLACE_EXISTING | DO_NOT_QUEUE)"
);
}
#[test]
fn request_name_flags_convert_from_borrowed_value() {
use crate::wire::{LE, serialized::Context, to_bytes};
let flags = RequestNameFlags::REPLACE_EXISTING | RequestNameFlags::DO_NOT_QUEUE;
let encoded = to_bytes(Context::new(LE, 0), &Variant::from(flags)).unwrap();
let (value, _): (Variant<'_>, _) = encoded.deserialize().unwrap();
assert_eq!(RequestNameFlags::try_from(value).unwrap(), flags);
}
}