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