sysd_manager_comcontroler/
data.rs1use 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::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.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 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 }
354}