sysd_manager_comcontroler/
errors.rs1use 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 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 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 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}