sysd_manager_proxy_lib/
interface.rs1use base::{RunMode, consts::*, enums::UnitDBusLevel, proxy::DisEnAbleUnitFiles};
2
3use log::{debug, info, warn};
4use std::{borrow::Cow, env, error::Error, sync::OnceLock};
5use tokio::sync::OnceCell;
6use zbus::{
7 Connection, ObjectServer, connection, interface, message::Header, object_server::SignalEmitter,
8};
9
10use crate::{SysDManagerProxy, file, sysdcom};
11
12#[interface(name = "io.github.plrigaux.SysDManager", introspection_docs = true)]
13impl SysDManagerProxy {
14 pub async fn create_drop_in(
15 &mut self,
16 #[zbus(header)] header: Header<'_>,
17 runtime: bool,
18 unit_name: &str,
19 file_name: &str,
20 content: &str,
21 ) -> zbus::fdo::Result<()> {
22 self.check_autorisation(header).await?;
24
25 file::create_drop_in(runtime, unit_name, file_name, content).await
27 }
28
29 pub async fn save_file(
30 &mut self,
31 #[zbus(header)] header: Header<'_>,
32
33 file_path: &str,
34 content: &str,
35 ) -> zbus::fdo::Result<u64> {
36 self.check_autorisation(header).await?;
37 file::save(file_path, content).await
38 }
39
40 pub async fn my_user_id(
41 &mut self,
42 #[zbus(header)] header: Header<'_>,
43 ) -> zbus::fdo::Result<u32> {
44 self.check_autorisation(header).await?;
45
46 let id = unsafe { libc::getegid() };
47 info!("ids {}", id);
48
49 Ok(id)
50 }
51 #[zbus(signal)]
53 async fn bye(signal_emitter: &SignalEmitter<'_>, message: &str) -> zbus::Result<()>;
54
55 async fn quit(
57 &self,
58 #[zbus(header)] hdr: Header<'_>,
59 #[zbus(signal_emitter)] emitter: SignalEmitter<'_>,
60 #[zbus(object_server)] _server: &ObjectServer,
61 ) -> zbus::fdo::Result<()> {
62 let path = hdr.path().unwrap();
63 let msg = format!("You are leaving me on the {} path?", path);
64 emitter.bye(&msg).await?;
65
66 Ok(())
69 }
70
71 async fn even_ping(
72 &mut self,
73 #[zbus(header)] header: Header<'_>,
74 val: u32,
75 ) -> zbus::fdo::Result<u32> {
76 info!("even_ping {val}");
77 self.check_autorisation(header).await?;
78 if val.is_multiple_of(2) {
79 Ok(val)
80 } else {
81 Err(zbus::fdo::Error::Failed(format!("{val} not even!")))
82 }
83 }
84
85 async fn clean_unit(
86 &self,
87 #[zbus(header)] header: Header<'_>,
88
89 unit_name: &str,
90 what: Vec<&str>,
91 ) -> zbus::fdo::Result<()> {
92 self.check_autorisation(header).await?;
93 let proxy = get_proxy(UnitDBusLevel::System).await?;
94
95 info!("clean_unit {} {:?}", unit_name, what);
96 proxy
97 .clean_unit(unit_name, &what)
98 .await
99 .inspect_err(|e| warn!("Error while calling clean_unit on sysdbus proxy: {:?}", e))
100 }
101
102 async fn freeze_unit(
103 &self,
104 #[zbus(header)] header: Header<'_>,
105 unit_name: &str,
106 ) -> zbus::fdo::Result<()> {
107 let proxy = get_proxy(UnitDBusLevel::System).await?;
108 self.check_autorisation(header).await?;
109 info!("freeze_unit {}", unit_name);
110 proxy
111 .freeze_unit(unit_name)
112 .await
113 .inspect_err(|e| warn!("Error while calling freeze_unit on sysdbus proxy: {:?}", e))
114 }
115
116 async fn thaw_unit(
117 &self,
118 #[zbus(header)] header: Header<'_>,
119 unit_name: &str,
120 ) -> zbus::fdo::Result<()> {
121 let proxy = get_proxy(UnitDBusLevel::System).await?;
122 self.check_autorisation(header).await?;
123 info!("thaw_unit {}", unit_name);
124 proxy
125 .thaw_unit(unit_name)
126 .await
127 .inspect_err(|e| warn!("Error while calling thaw_unit on sysdbus proxy: {:?}", e))
128 }
129
130 async fn revert_unit_files(
131 &self,
132 #[zbus(header)] header: Header<'_>,
133 file_names: Vec<String>,
134 ) -> zbus::fdo::Result<Vec<DisEnAbleUnitFiles>> {
135 info!("Revert_unit_files {:?}", file_names);
136
137 let proxy: &sysdcom::SysDManagerComLinkProxy<'_> = get_proxy(UnitDBusLevel::System).await?;
138
139 debug!("Proxy {:?}", proxy);
140 self.check_autorisation(header).await?;
141 debug!("Polkit autorized");
142 match proxy.revert_unit_files(&file_names).await {
143 Ok(vec) => {
144 info!("revert_unit_files {:?} --> {:?}", file_names, vec);
145 Ok(vec)
146 }
147 Err(err) => {
148 warn!(
149 "Error while calling revert_unit_files on sysdbus proxy: {:?}",
150 err
151 );
152 Err(err)
153 }
154 }
155 }
156
157 async fn reload(&self, #[zbus(header)] header: Header<'_>) -> zbus::fdo::Result<()> {
158 info!("Reload");
159 let proxy: &sysdcom::SysDManagerComLinkProxy<'_> = get_proxy(UnitDBusLevel::System).await?;
160 self.check_autorisation(header).await?;
161 debug!("Polkit autorized");
162 proxy
163 .reload()
164 .await
165 .inspect_err(|e| warn!("Error while calling reload on sysdbus proxy: {:?}", e))
166 }
167}
168
169static CONNECTION: OnceLock<Connection> = OnceLock::new();
170
171pub async fn init_serve_connection(run_mode: RunMode) -> Result<(), Box<dyn Error>> {
172 info!("Init Proxy");
173
174 let proxy = SysDManagerProxy::new()?;
175
176 let id = unsafe { libc::getegid() };
177 info!("User id {id}");
178
179 let default_name = if run_mode == RunMode::Development {
180 DBUS_NAME_DEV
181 } else {
182 DBUS_NAME
183 };
184
185 let dbus_name = get_env("DBUS_NAME", default_name);
186 let dbus_path = get_env("DBUS_PATH", DBUS_PATH);
187
188 info!("DBus name {dbus_name}");
189 info!("DBus path {dbus_path}");
190
191 let connection = connection::Builder::system()?
192 .name(dbus_name)?
193 .serve_at(dbus_path, proxy)?
194 .build()
195 .await?;
196
197 CONNECTION.get_or_init(|| connection);
198 Ok(())
199}
200
201fn get_env<'a>(key: &str, default: &'a str) -> Cow<'a, str> {
202 match env::var(key) {
203 Ok(val) => {
204 info!("Key {key}, Value {val}");
205 Cow::Owned(val)
206 }
207 Err(e) => {
208 debug!("Env error {e:?}");
209 info!("Key {key}, Use default value {default}");
210 Cow::Borrowed(default)
211 }
212 }
213}
214
215async fn get_proxy(
216 _dbus_level: UnitDBusLevel,
217) -> Result<&'static sysdcom::SysDManagerComLinkProxy<'static>, zbus::Error> {
218 system_proxy().await }
220
221static SYS_PROXY: OnceCell<sysdcom::SysDManagerComLinkProxy> = OnceCell::const_new();
222
223async fn system_proxy() -> Result<&'static sysdcom::SysDManagerComLinkProxy<'static>, zbus::Error> {
224 SYS_PROXY
225 .get_or_try_init(
226 async || -> Result<sysdcom::SysDManagerComLinkProxy, zbus::Error> {
227 let connection = Connection::system().await?;
228 let proxy = sysdcom::SysDManagerComLinkProxy::builder(&connection)
229 .build()
230 .await?;
231 Ok(proxy)
232 },
233 )
234 .await
235}