sysd_manager_comcontroler/
data.rs

1use std::{cmp::Ordering, fmt::Debug};
2
3use super::{SystemdUnitFile, UpdatedUnitInfo};
4
5use base::{enums::UnitDBusLevel, proxy::DisEnAbleUnitFiles};
6use glib::{self, subclass::types::ObjectSubclassIsExt};
7
8use serde::Deserialize;
9use zvariant::{OwnedObjectPath, Type, Value};
10
11glib::wrapper! {
12    pub struct UnitInfo(ObjectSubclass<imp::UnitInfoImpl>);
13}
14
15impl Default for UnitInfo {
16    fn default() -> Self {
17        UnitInfo::new()
18    }
19}
20
21impl UnitInfo {
22    fn new() -> Self {
23        let this_object: Self = glib::Object::new();
24        this_object
25    }
26
27    pub fn from_listed_unit(listed_unit: LUnit, level: UnitDBusLevel) -> Self {
28        let this_object: Self = glib::Object::new();
29        let imp = this_object.imp();
30        imp.init_from_listed_unit(listed_unit, level);
31        this_object
32    }
33
34    pub fn from_unit_file(unit_file: SystemdUnitFile) -> Self {
35        let this_object: Self = glib::Object::new();
36        this_object.imp().init_from_unit_file(unit_file);
37        this_object
38    }
39
40    pub fn update_from_unit_info(&self, update: UpdatedUnitInfo) {
41        self.imp().update_from_unit_info(update);
42    }
43
44    pub fn update_from_unit_file(&self, unit_file: SystemdUnitFile) {
45        self.imp().update_from_unit_file(unit_file);
46    }
47
48    pub fn debug(&self) -> String {
49        format!("{:#?}", *self.imp())
50    }
51}
52
53mod imp {
54    use std::cell::RefCell;
55
56    use base::enums::UnitDBusLevel;
57    use glib::{
58        self,
59        object::ObjectExt,
60        subclass::{object::*, types::ObjectSubclass},
61    };
62
63    use crate::{
64        SystemdUnitFile, UpdatedUnitInfo,
65        enums::{ActiveState, EnablementStatus, LoadState, Preset, UnitType},
66    };
67
68    #[derive(Debug, glib::Properties, Default)]
69    #[properties(wrapper_type = super::UnitInfo)]
70    pub struct UnitInfoImpl {
71        #[property(get, set = Self::set_primary )]
72        pub(super) primary: RefCell<String>,
73        #[property(get)]
74        display_name: RefCell<String>,
75        #[property(get, default)]
76        unit_type: RefCell<UnitType>,
77        #[property(get, set)]
78        pub(super) description: RefCell<Option<String>>,
79
80        #[property(get, set, default)]
81        pub(super) load_state: RefCell<LoadState>,
82
83        #[property(get, set, builder(ActiveState::Unknown))]
84        pub(super) active_state: RefCell<ActiveState>,
85
86        #[property(get, set)]
87        pub(super) sub_state: RefCell<String>,
88        #[property(get)]
89        pub(super) followed_unit: RefCell<String>,
90
91        //#[property(get = Self::has_object_path, name = "pathexists", type = bool)]
92        #[property(get=Self::get_unit_path, type = String)]
93        pub(super) object_path: RefCell<Option<String>>,
94        #[property(get, set, nullable, default = None)]
95        pub(super) file_path: RefCell<Option<String>>,
96        #[property(get, set, default)]
97        pub(super) enable_status: RefCell<EnablementStatus>,
98
99        #[property(get, set, default)]
100        pub(super) dbus_level: RefCell<UnitDBusLevel>,
101
102        #[property(get, set, default)]
103        pub(super) preset: RefCell<Preset>,
104    }
105
106    #[glib::object_subclass]
107    impl ObjectSubclass for UnitInfoImpl {
108        const NAME: &'static str = "UnitInfo";
109        type Type = super::UnitInfo;
110
111        fn new() -> Self {
112            Default::default()
113        }
114    }
115
116    #[glib::derived_properties]
117    impl ObjectImpl for UnitInfoImpl {}
118
119    impl UnitInfoImpl {
120        pub(super) fn init_from_listed_unit(
121            &self,
122            listed_unit: super::LUnit,
123            dbus_level: UnitDBusLevel,
124        ) {
125            let active_state: ActiveState = listed_unit.active_state.as_str().into();
126
127            self.set_primary(listed_unit.primary_unit_name);
128            self.active_state.replace(active_state);
129
130            let description = if listed_unit.description.is_empty() {
131                Some(listed_unit.description)
132            } else {
133                None
134            };
135
136            self.description.replace(description);
137            let load_state: LoadState = listed_unit.load_state.as_str().into();
138            self.load_state.replace(load_state);
139            self.sub_state.replace(listed_unit.sub_state);
140            self.followed_unit.replace(listed_unit.followed_unit);
141            let unit_object_path = Some(listed_unit.unit_object_path.to_string());
142            self.object_path.replace(unit_object_path);
143            self.dbus_level.replace(dbus_level);
144        }
145
146        pub(super) fn init_from_unit_file(&self, unit_file: SystemdUnitFile) {
147            self.set_primary(unit_file.full_name);
148            //self.set_active_state(ActiveState::Unknown);
149            self.dbus_level.replace(unit_file.level);
150            self.file_path.replace(Some(unit_file.path));
151            self.enable_status.replace(unit_file.status_code);
152        }
153
154        pub(super) fn update_from_unit_file(&self, unit_file: SystemdUnitFile) {
155            self.file_path.replace(Some(unit_file.path));
156            self.enable_status.replace(unit_file.status_code);
157        }
158
159        pub fn set_primary(&self, primary: String) {
160            let mut split_char_index = primary.len();
161            for (i, c) in primary.chars().rev().enumerate() {
162                if c == '.' {
163                    split_char_index -= i;
164                    break;
165                }
166            }
167
168            let display_name = primary[..split_char_index - 1].to_owned();
169            self.display_name.replace(display_name);
170
171            let unit_type = UnitType::new(&primary[(split_char_index)..]);
172            self.unit_type.replace(unit_type);
173
174            self.primary.replace(primary);
175        }
176
177        pub fn update_from_unit_info(&self, update: UpdatedUnitInfo) {
178            self.object_path.replace(Some(update.object_path));
179
180            self.description.replace(update.description);
181
182            if let Some(sub_state) = update.sub_state {
183                self.sub_state.replace(sub_state);
184            }
185
186            if let Some(active_state) = update.active_state {
187                self.active_state.replace(active_state);
188            }
189
190            if let Some(unit_file_preset) = update.unit_file_preset {
191                let preset: Preset = unit_file_preset.into();
192                self.preset.replace(preset);
193            }
194
195            if let Some(load_state) = update.load_state {
196                self.load_state.replace(load_state);
197            }
198
199            if let Some(fragment_path) = update.fragment_path {
200                self.file_path.replace(Some(fragment_path));
201            }
202
203            if let Some(enablement_status) = update.enablement_status {
204                self.enable_status.replace(enablement_status);
205            }
206        }
207
208        fn get_unit_path(&self) -> String {
209            if let Some(a) = &*self.object_path.borrow() {
210                a.clone()
211            } else {
212                let primary = &*self.primary.borrow();
213                let object_path = crate::sysdbus::unit_dbus_path_from_name(primary);
214                self.object_path.replace(Some(object_path.clone()));
215                object_path
216            }
217        }
218    }
219}
220
221#[derive(Debug, Eq, PartialEq)]
222pub struct UnitProcess {
223    pub path: String,
224    pub pid: u32,
225    pub name: String,
226    pub(crate) unit_name: usize,
227}
228
229impl UnitProcess {
230    pub fn unit_name(&self) -> &str {
231        &self.path[self.unit_name..]
232    }
233}
234
235impl Ord for UnitProcess {
236    fn cmp(&self, other: &Self) -> Ordering {
237        let cmp: Ordering = self.unit_name().cmp(other.unit_name());
238        if self.unit_name().cmp(other.unit_name()) == Ordering::Equal {
239            self.pid.cmp(&other.pid)
240        } else {
241            cmp
242        }
243    }
244}
245
246impl PartialOrd for UnitProcess {
247    fn partial_cmp(&self, other: &UnitProcess) -> Option<Ordering> {
248        Some(self.cmp(other))
249    }
250}
251
252#[derive(Debug, Type, Deserialize)]
253#[allow(unused)]
254pub struct EnableUnitFilesReturn {
255    pub carries_install_info: bool,
256    pub vec: Vec<DisEnAbleUnitFiles>,
257}
258
259#[derive(Deserialize, zvariant::Type, PartialEq, Debug)]
260pub struct LUnit {
261    pub primary_unit_name: String,
262    pub description: String,
263    pub load_state: String,
264    pub active_state: String,
265    pub sub_state: String,
266    pub followed_unit: String,
267
268    pub unit_object_path: OwnedObjectPath,
269    ///If there is a job queued for the job unit the numeric job id, 0 otherwise
270    pub numeric_job_id: u32,
271    pub job_type: String,
272    pub job_object_path: OwnedObjectPath,
273}
274
275pub fn convert_to_string(value: &Value) -> Option<String> {
276    match value {
277        Value::Bool(b) => Some(b.to_string()),
278        Value::U8(i) => Some(i.to_string()),
279        Value::I16(i) => Some(i.to_string()),
280        Value::U16(i) => Some(i.to_string()),
281        Value::I32(i) => Some(i.to_string()),
282        Value::U32(i) => Some(i.to_string()),
283        Value::I64(i) => Some(i.to_string()),
284        Value::U64(i) => Some(i.to_string()),
285        Value::F64(i) => Some(i.to_string()),
286        Value::Str(s) => Some(s.to_string()),
287        Value::Signature(s) => Some(s.to_string()),
288        Value::ObjectPath(op) => Some(op.to_string()),
289        Value::Value(v) => Some(v.to_string()),
290        Value::Array(a) => {
291            if a.is_empty() {
292                None
293            } else {
294                let mut d_str = String::from("");
295
296                let mut it = a.iter().peekable();
297                while let Some(mi) = it.next() {
298                    if let Some(v) = convert_to_string(mi) {
299                        d_str.push_str(&v);
300                    }
301                    if it.peek().is_some() {
302                        d_str.push_str(", ");
303                    }
304                }
305
306                Some(d_str)
307            }
308        }
309        Value::Dict(d) => {
310            let mut it = d.iter().peekable();
311            if it.peek().is_none() {
312                None
313            } else {
314                let mut d_str = String::from("{ ");
315
316                for (mik, miv) in it {
317                    if let Some(k) = convert_to_string(mik) {
318                        d_str.push_str(&k);
319                    }
320                    d_str.push_str(" : ");
321
322                    if let Some(v) = convert_to_string(miv) {
323                        d_str.push_str(&v);
324                    }
325                }
326                d_str.push_str(" }");
327                Some(d_str)
328            }
329        }
330        Value::Structure(stc) => {
331            let mut it = stc.fields().iter().peekable();
332
333            if it.peek().is_none() {
334                None
335            } else {
336                let mut d_str = String::from("");
337
338                while let Some(mi) = it.next() {
339                    if let Some(v) = convert_to_string(mi) {
340                        d_str.push_str(&v);
341                    }
342
343                    if it.peek().is_some() {
344                        d_str.push_str(", ");
345                    }
346                }
347
348                Some(d_str)
349            }
350        }
351        Value::Fd(fd) => Some(fd.to_string()),
352        //Value::Maybe(maybe) => (maybe.to_string(), false),
353    }
354}