Skip to main content

sysd_manager_comcontroler/
errors.rs

1use base::file::SysdBaseError;
2use gettextrs::pgettext;
3use std::{
4    ffi::OsString,
5    fmt::{self, Display, Formatter},
6    string::FromUtf8Error,
7    time::Duration,
8};
9
10#[derive(Debug)]
11#[allow(unused)]
12pub enum SystemdErrors {
13    Command(
14        OsString,
15        Vec<OsString>,
16        Vec<(OsString, Option<OsString>)>,
17        std::io::Error,
18    ),
19    Custom(String),
20    IoError(std::io::Error),
21    Utf8Error(FromUtf8Error),
22    Fmt(std::fmt::Error),
23    ZMethodError(String, String, String),
24    CmdNoFlatpakSpawn,
25    CmdNoFreedesktopFlatpakPermission(Option<String>, Option<String>),
26    JournalError(String),
27    NoFilePathforUnit(String),
28    Malformed(String, String),
29    NotAuthorized,
30    NotAuthorizedAuthentificationDismissed,
31    NoUnit,
32    SystemCtlError(String),
33    Tokio,
34    ZBusError(zbus::Error),
35    ZAccessDenied(String, String),
36    ZNoSuchUnit(String, String),
37    ZNoSuchUnitProxy(String, String),
38    ZJobTypeNotApplicable(String, String),
39    ZUnitMasked(String, String),
40    ZVariantError(zvariant::Error),
41    ZBusFdoError(zbus::fdo::Error),
42    ZFdoServiceUnknowm(String),
43    ZFdoZError(String),
44    ZXml(zbus_xml::Error),
45    Unreachable,
46    InvalidPath(String),
47    Timeout(Duration),
48    JobRemoved(String),
49}
50
51impl SystemdErrors {
52    pub fn gui_description(&self) -> Option<String> {
53        match self {
54            SystemdErrors::CmdNoFlatpakSpawn => {
55                //error message flatpak permission
56                Some(pgettext(
57                    "error",
58                    "The program <b>flatpack-spawn</b> is needed if you use the application from Flatpack.\nPlease install it to enable all features.",
59                ))
60            }
61            SystemdErrors::CmdNoFreedesktopFlatpakPermission(_cmdl, _file_path) => {
62                //error message flatpak permission
63                Some(pgettext(
64                    "error",
65                    "It requires permission to talk to <b>org.freedesktop.Flatpak</b> D-Bus interface when the program is a Flatpak.",
66                ))
67            }
68            _ => None,
69        }
70    }
71
72    pub fn human_error_type(&self) -> String {
73        match self {
74            SystemdErrors::ZAccessDenied(_, detail) => detail.clone(),
75            SystemdErrors::ZJobTypeNotApplicable(_, detail) => detail.clone(),
76            SystemdErrors::ZNoSuchUnit(_, detail) => detail.clone(),
77            SystemdErrors::ZNoSuchUnitProxy(_, detail) => detail.clone(),
78            SystemdErrors::ZUnitMasked(_, detail) => detail.clone(),
79            SystemdErrors::JobRemoved(reason) => uppercase_first_letter(reason),
80            _ => self.to_string(),
81        }
82    }
83
84    pub fn file_not_found(&self) -> bool {
85        if let SystemdErrors::IoError(io_error) = self
86            && io_error.kind() == std::io::ErrorKind::NotFound
87        {
88            true
89        } else {
90            false
91        }
92    }
93}
94
95fn uppercase_first_letter(s: &str) -> String {
96    let mut c = s.chars();
97    match c.next() {
98        None => String::new(),
99        Some(f) => f.to_uppercase().chain(c).collect(),
100    }
101}
102
103impl Display for SystemdErrors {
104    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
105        write!(f, "{self:?}")
106    }
107}
108
109impl From<std::io::Error> for SystemdErrors {
110    fn from(error: std::io::Error) -> Self {
111        SystemdErrors::IoError(error)
112    }
113}
114
115impl From<FromUtf8Error> for SystemdErrors {
116    fn from(error: FromUtf8Error) -> Self {
117        SystemdErrors::Utf8Error(error)
118    }
119}
120
121impl From<(zbus::Error, &str)> for SystemdErrors {
122    fn from(value: (zbus::Error, &str)) -> Self {
123        let (zb_error, method) = value;
124
125        match zb_error {
126            zbus::Error::MethodError(owned_error_name, ref msg, _message) => {
127                let err_code = zvariant::Str::from(owned_error_name);
128
129                let err_code = err_code.as_str();
130                let message = msg.clone().unwrap_or_default();
131
132                match err_code {
133                    "org.freedesktop.DBus.Error.AccessDenied" => {
134                        let method = if method.is_empty() {
135                            "AccessDenied"
136                        } else {
137                            method
138                        };
139                        SystemdErrors::ZAccessDenied(method.to_owned(), message)
140                    }
141                    "org.freedesktop.systemd1.NoSuchUnit" => {
142                        let method = if method.is_empty() {
143                            "NoSuchUnit"
144                        } else {
145                            method
146                        };
147                        SystemdErrors::ZNoSuchUnit(method.to_owned(), message)
148                    }
149                    "org.freedesktop.DBus.Error.InvalidArgs" => {
150                        let method = if method.is_empty() {
151                            "InvalidArgs"
152                        } else {
153                            method
154                        };
155                        SystemdErrors::ZNoSuchUnitProxy(method.to_owned(), message)
156                    }
157                    "org.freedesktop.systemd1.JobTypeNotApplicable" => {
158                        let method = if method.is_empty() {
159                            "JobTypeNotApplicable"
160                        } else {
161                            method
162                        };
163                        SystemdErrors::ZJobTypeNotApplicable(method.to_owned(), message)
164                    }
165                    "org.freedesktop.systemd1.UnitMasked" => {
166                        let method = if method.is_empty() {
167                            "UnitMasked"
168                        } else {
169                            method
170                        };
171                        SystemdErrors::ZUnitMasked(method.to_owned(), message)
172                    }
173                    "org.freedesktop.zbus.Error" => {
174                        SystemdErrors::ZUnitMasked(method.to_owned(), message)
175                    }
176                    _ => {
177                        SystemdErrors::ZMethodError(method.to_owned(), err_code.to_owned(), message)
178                    }
179                }
180            }
181
182            _ => SystemdErrors::ZBusError(zb_error),
183        }
184    }
185}
186
187impl From<zbus::Error> for SystemdErrors {
188    fn from(error: zbus::Error) -> Self {
189        //log::info!("TS {:?}", error);
190        SystemdErrors::from((error, ""))
191    }
192}
193
194impl From<zbus::fdo::Error> for SystemdErrors {
195    fn from(error: zbus::fdo::Error) -> Self {
196        match error {
197            zbus::fdo::Error::ServiceUnknown(s) => SystemdErrors::ZFdoServiceUnknowm(s),
198            zbus::fdo::Error::ZBus(err) => err.into(),
199            _ => SystemdErrors::ZBusFdoError(error),
200        }
201    }
202}
203
204impl From<Box<dyn std::error::Error>> for SystemdErrors {
205    fn from(error: Box<dyn std::error::Error>) -> Self {
206        let msg = format!("{error}");
207        SystemdErrors::JournalError(msg)
208    }
209}
210
211impl From<zvariant::Error> for SystemdErrors {
212    fn from(value: zvariant::Error) -> Self {
213        SystemdErrors::ZVariantError(value)
214    }
215}
216
217impl From<tokio::task::JoinError> for SystemdErrors {
218    fn from(_value: tokio::task::JoinError) -> Self {
219        SystemdErrors::Tokio
220    }
221}
222
223impl From<zbus_xml::Error> for SystemdErrors {
224    fn from(value: zbus_xml::Error) -> Self {
225        SystemdErrors::ZXml(value)
226    }
227}
228
229impl From<std::fmt::Error> for SystemdErrors {
230    fn from(value: std::fmt::Error) -> Self {
231        SystemdErrors::Fmt(value)
232    }
233}
234
235impl From<String> for SystemdErrors {
236    fn from(value: String) -> Self {
237        SystemdErrors::Custom(value)
238    }
239}
240
241impl From<&str> for SystemdErrors {
242    fn from(value: &str) -> Self {
243        value.to_owned().into()
244    }
245}
246
247impl From<SysdBaseError> for SystemdErrors {
248    fn from(value: SysdBaseError) -> Self {
249        match value {
250            SysdBaseError::CmdNoFreedesktopFlatpakPermission => {
251                SystemdErrors::CmdNoFreedesktopFlatpakPermission(None, None)
252            }
253            SysdBaseError::CommandCallError(os_string, os_strings, items, error) => {
254                SystemdErrors::Command(os_string, os_strings, items, error)
255            }
256            SysdBaseError::Custom(s) => SystemdErrors::Custom(s),
257            SysdBaseError::IoError(error) => SystemdErrors::IoError(error),
258            SysdBaseError::NotAuthorizedAuthentificationDismissed => {
259                SystemdErrors::NotAuthorizedAuthentificationDismissed
260            }
261            SysdBaseError::NotAuthorized => SystemdErrors::NotAuthorized,
262            SysdBaseError::Tokio(_join_error) => SystemdErrors::Tokio,
263            SysdBaseError::InvalidPath(msg) => SystemdErrors::InvalidPath(msg),
264        }
265    }
266}