Skip to main content

sysd_manager_proxy_lib/
interface.rs

1use base::{
2    RunMode,
3    consts::*,
4    proxy::{DisEnAbleUnitFiles, DisEnAbleUnitFilesResponse},
5};
6
7use std::{borrow::Cow, env, error::Error};
8use tokio::sync::OnceCell;
9use tracing::{debug, info, warn};
10use zbus::{
11    Connection, ObjectServer, connection, interface, message::Header, object_server::SignalEmitter,
12};
13
14use crate::{SysDManagerProxy, file, sysdcom};
15
16#[interface(name = "io.github.plrigaux.SysDManager", introspection_docs = true)]
17impl SysDManagerProxy {
18    pub async fn create_drop_in(
19        &mut self,
20        #[zbus(header)] header: Header<'_>,
21        runtime: bool,
22        unit_name: &str,
23        file_name: &str,
24        content: &str,
25    ) -> zbus::fdo::Result<()> {
26        //self.
27        self.check_autorisation(header).await?;
28
29        //   self.get_all(object_server, connection, header, emitter)
30        file::create_drop_in(runtime, unit_name, file_name, content).await
31    }
32
33    pub async fn save_file(
34        &mut self,
35        #[zbus(header)] header: Header<'_>,
36
37        file_path: &str,
38        content: &str,
39    ) -> zbus::fdo::Result<u64> {
40        self.check_autorisation(header).await?;
41        file::save(file_path, content).await
42    }
43
44    pub async fn my_user_id(
45        &mut self,
46        #[zbus(header)] header: Header<'_>,
47    ) -> zbus::fdo::Result<u32> {
48        self.check_autorisation(header).await?;
49
50        let id = unsafe { libc::getegid() };
51        info!("ids {}", id);
52
53        Ok(id)
54    }
55
56    // "Bye" signal (note: no implementation body).
57    #[zbus(signal)]
58    async fn bye(signal_emitter: &SignalEmitter<'_>, message: &str) -> zbus::Result<()>;
59
60    #[zbus(signal)]
61    async fn hello(signal_emitter: &SignalEmitter<'_>, message: &str) -> zbus::Result<()>;
62
63    // "Quit" method. A method may throw errors.
64    async fn quit(
65        &self,
66        #[zbus(header)] hdr: Header<'_>,
67        #[zbus(signal_emitter)] emitter: SignalEmitter<'_>,
68        #[zbus(object_server)] _server: &ObjectServer,
69    ) -> zbus::fdo::Result<()> {
70        let path = hdr.path().unwrap();
71        let msg = format!("You are leaving me on the {} path?", path);
72        emitter.bye(&msg).await?;
73
74        // Do some asynchronous tasks before quitting..
75
76        Ok(())
77    }
78
79    async fn even_ping(
80        &mut self,
81        #[zbus(header)] header: Header<'_>,
82        val: u32,
83    ) -> zbus::fdo::Result<u32> {
84        info!("even_ping {val}");
85        self.check_autorisation(header).await?;
86        if val.is_multiple_of(2) {
87            Ok(val)
88        } else {
89            Err(zbus::fdo::Error::Failed(format!("{val} not even!")))
90        }
91    }
92
93    async fn clean_unit(
94        &self,
95        #[zbus(header)] header: Header<'_>,
96
97        unit_name: &str,
98        what: Vec<&str>,
99    ) -> zbus::fdo::Result<()> {
100        info!("clean_unit {} {:?}", unit_name, what);
101
102        self.check_autorisation(header).await?;
103
104        let proxy = get_proxy().await?;
105        proxy
106            .clean_unit(unit_name, &what)
107            .await
108            .inspect_err(|e| warn!("Error while calling clean_unit on sysdbus proxy: {:?}", e))
109    }
110
111    async fn freeze_unit(
112        &self,
113        #[zbus(header)] header: Header<'_>,
114        unit_name: &str,
115    ) -> zbus::fdo::Result<()> {
116        info!("freeze_unit {}", unit_name);
117        self.check_autorisation(header).await?;
118
119        let proxy = get_proxy().await?;
120        proxy
121            .freeze_unit(unit_name)
122            .await
123            .inspect_err(|e| warn!("Error while calling freeze_unit on sysdbus proxy: {:?}", e))
124    }
125
126    async fn thaw_unit(
127        &self,
128        #[zbus(header)] header: Header<'_>,
129        unit_name: &str,
130    ) -> zbus::fdo::Result<()> {
131        info!("thaw_unit {}", unit_name);
132        self.check_autorisation(header).await?;
133
134        let proxy = get_proxy().await?;
135        proxy
136            .thaw_unit(unit_name)
137            .await
138            .inspect_err(|e| warn!("Error while calling thaw_unit on sysdbus proxy: {:?}", e))
139    }
140
141    async fn revert_unit_files(
142        &self,
143        #[zbus(header)] header: Header<'_>,
144        file_names: Vec<String>,
145    ) -> zbus::fdo::Result<Vec<DisEnAbleUnitFiles>> {
146        info!("Revert_unit_files  {:?}", file_names);
147
148        let proxy: &sysdcom::SysDManagerComLinkProxy<'_> = get_proxy().await?;
149
150        debug!("Proxy {:?}", proxy);
151        self.check_autorisation(header).await?;
152        debug!("Polkit autorized");
153        match proxy.revert_unit_files(&file_names).await {
154            Ok(vec) => {
155                info!("revert_unit_files {:?} --> {:?}", file_names, vec);
156                Ok(vec)
157            }
158            Err(err) => {
159                warn!(
160                    "Error while calling revert_unit_files on sysdbus proxy: {:?}",
161                    err
162                );
163                Err(err)
164            }
165        }
166    }
167
168    async fn reload(&self, #[zbus(header)] header: Header<'_>) -> zbus::fdo::Result<()> {
169        info!("Reload");
170        let proxy: &sysdcom::SysDManagerComLinkProxy<'_> = get_proxy().await?;
171        self.check_autorisation(header).await?;
172        debug!("Polkit autorized");
173        proxy
174            .reload()
175            .await
176            .inspect_err(|e| warn!("Error while calling reload on sysdbus proxy: {:?}", e))
177    }
178
179    async fn enable_unit_files_with_flags(
180        &self,
181        #[zbus(header)] header: Header<'_>,
182        unit_files: Vec<&str>,
183        flags: u64,
184    ) -> zbus::fdo::Result<DisEnAbleUnitFilesResponse> {
185        info!(
186            "enable_unit_files_with_flags {:?} flags {}",
187            unit_files, flags
188        );
189        self.check_autorisation(header).await?;
190
191        let proxy = get_proxy().await?;
192        proxy
193            .enable_unit_files_with_flags(&unit_files, flags)
194            .await
195            .inspect_err(|e| {
196                warn!(
197                    "Error while calling disable_unit_files_with_flags on sysdbus proxy: {:?}",
198                    e
199                )
200            })
201    }
202
203    async fn disable_unit_files_with_flags(
204        &self,
205        #[zbus(header)] header: Header<'_>,
206        unit_files: Vec<&str>,
207        flags: u64,
208    ) -> zbus::fdo::Result<DisEnAbleUnitFilesResponse> {
209        info!(
210            "disable_unit_files_with_flags {:?} flags {}",
211            unit_files, flags
212        );
213        self.check_autorisation(header).await?;
214
215        let proxy = get_proxy().await?;
216        proxy
217            .disable_unit_files_with_flags_and_install_info(&unit_files, flags)
218            .await
219            .inspect_err(|e| {
220                warn!(
221                    "Error while calling disable_unit_files_with_flags on sysdbus proxy: {:?}",
222                    e
223                )
224            })
225    }
226}
227
228pub async fn init_serve_connection(
229    run_mode: RunMode,
230) -> Result<(Connection, String), Box<dyn Error>> {
231    const VERSION: &str = env!("CARGO_PKG_VERSION");
232    info!("Init Proxy version {VERSION}");
233
234    let proxy = SysDManagerProxy::new()?;
235
236    let id = unsafe { libc::getegid() };
237    info!("User id {id}");
238
239    let default_name = if run_mode == RunMode::Development {
240        DBUS_NAME_DEV
241    } else {
242        DBUS_NAME
243    };
244
245    let dbus_name = get_env("DBUS_NAME", default_name);
246    let dbus_path = get_env("DBUS_PATH", DBUS_PATH);
247
248    info!("DBus name {dbus_name}");
249    info!("DBus path {dbus_path}");
250
251    let connection = connection::Builder::system()?
252        .name(dbus_name)?
253        .serve_at(dbus_path.clone(), proxy)?
254        .build()
255        .await?;
256
257    Ok((connection, dbus_path.to_string()))
258}
259
260fn get_env<'a>(key: &str, default: &'a str) -> Cow<'a, str> {
261    match env::var(key) {
262        Ok(val) => {
263            info!("Key {key}, Value {val}");
264            Cow::Owned(val)
265        }
266        Err(e) => {
267            debug!("Env error {e:?}");
268            info!("Key {key}, Use default value {default}");
269            Cow::Borrowed(default)
270        }
271    }
272}
273
274async fn get_proxy() -> Result<&'static sysdcom::SysDManagerComLinkProxy<'static>, zbus::Error> {
275    system_proxy().await //Only system cause the proxy runs at root so no session
276}
277
278static SYS_PROXY: OnceCell<sysdcom::SysDManagerComLinkProxy> = OnceCell::const_new();
279
280async fn system_proxy() -> Result<&'static sysdcom::SysDManagerComLinkProxy<'static>, zbus::Error> {
281    SYS_PROXY
282        .get_or_try_init(
283            async || -> Result<sysdcom::SysDManagerComLinkProxy, zbus::Error> {
284                let connection = Connection::system().await?;
285                let proxy = sysdcom::SysDManagerComLinkProxy::builder(&connection)
286                    .build()
287                    .await?;
288                Ok(proxy)
289            },
290        )
291        .await
292}