blob: cd09c0c85f7dbafaf958ee36cefcef1c6f148f0e [file] [log] [blame]
Patrick Williams93b0e702017-04-18 11:19:45 -05001#include <sdbusplus/exception.hpp>
Patrick Williamsb08d14d2024-11-05 21:35:55 -05002#include <sdbusplus/sdbuspp_support/event.hpp>
Patrick Williams127b8ab2020-05-21 15:24:19 -05003
Patrick Williamsb6f729d2021-09-02 15:02:19 -05004#include <cerrno>
William A. Kennington III2726c172018-06-22 19:39:04 -07005#include <stdexcept>
William A. Kennington III2726c172018-06-22 19:39:04 -07006#include <utility>
William A. Kennington III37657502018-06-22 19:00:05 -07007
Patrick Williams0c8136a2021-08-28 14:42:31 -05008#ifdef __clang__
9#pragma clang diagnostic push
10#pragma clang diagnostic ignored "-Wc99-extensions"
11#endif
12
Patrick Williamsb08d14d2024-11-05 21:35:55 -050013namespace sdbusplus::exception
Patrick Williams93b0e702017-04-18 11:19:45 -050014{
15
Patrick Williamsf289c652022-08-26 10:43:10 -050016void exception::unused() const noexcept {}
Patrick Williamsa8e35022021-09-28 06:16:52 -050017
Patrick Williamsa4bfefd2024-09-24 21:07:25 -040018int exception::set_error(sd_bus_error* e) const
19{
20 return sd_bus_error_set(e, name(), description());
21}
22
23int exception::set_error(SdBusInterface* i, sd_bus_error* e) const
24{
25 return i->sd_bus_error_set(e, name(), description());
26}
27
Patrick Williams15228662021-09-03 06:04:25 -050028int generated_exception::get_errno() const noexcept
29{
30 return EIO;
31}
32
Ed Tanoused4a5a62023-01-05 09:38:50 -080033SdBusError::SdBusError(int error_in, const char* prefix,
34 SdBusInterface* intf_in) :
Patrick Williams70bcf142023-07-26 16:19:48 -050035 SdBusError(error_in, std::string(prefix), intf_in)
36{}
37
38SdBusError::SdBusError(int error_in, std::string&& prefix,
39 SdBusInterface* intf_in) :
Patrick Williams06f265f2024-08-16 15:19:49 -040040 error(SD_BUS_ERROR_NULL), intf(intf_in)
William A. Kennington III20db3bf2018-05-14 16:18:37 -070041{
William A. Kennington III2726c172018-06-22 19:39:04 -070042 // We can't check the output of intf->sd_bus_error_set_errno() because
43 // it returns the input errorcode. We don't want to try and guess
44 // possible error statuses. Instead, check to see if the error was
45 // constructed to determine success.
Ed Tanoused4a5a62023-01-05 09:38:50 -080046 intf->sd_bus_error_set_errno(&this->error, error_in);
William A. Kennington III2726c172018-06-22 19:39:04 -070047 if (!intf->sd_bus_error_is_set(&this->error))
William A. Kennington III20db3bf2018-05-14 16:18:37 -070048 {
William A. Kennington III2726c172018-06-22 19:39:04 -070049 throw std::runtime_error("Failed to create SdBusError");
William A. Kennington III20db3bf2018-05-14 16:18:37 -070050 }
51
Patrick Williams70bcf142023-07-26 16:19:48 -050052 populateMessage(std::move(prefix));
William A. Kennington III20db3bf2018-05-14 16:18:37 -070053}
54
Ed Tanoused4a5a62023-01-05 09:38:50 -080055SdBusError::SdBusError(sd_bus_error* error_in, const char* prefix,
56 SdBusInterface* intf_in) :
Patrick Williams06f265f2024-08-16 15:19:49 -040057 error(*error_in), intf(intf_in)
William A. Kennington III20db3bf2018-05-14 16:18:37 -070058{
William A. Kennington III68cb1702018-06-22 19:35:48 -070059 // We own the error so remove the caller's reference
Ed Tanoused4a5a62023-01-05 09:38:50 -080060 *error_in = SD_BUS_ERROR_NULL;
William A. Kennington III68cb1702018-06-22 19:35:48 -070061
Patrick Williams70bcf142023-07-26 16:19:48 -050062 populateMessage(std::string(prefix));
William A. Kennington III20db3bf2018-05-14 16:18:37 -070063}
64
Vernon Maueryfac43a62018-08-01 12:29:23 -070065SdBusError::SdBusError(SdBusError&& other) : error(SD_BUS_ERROR_NULL)
William A. Kennington III20db3bf2018-05-14 16:18:37 -070066{
67 move(std::move(other));
68}
69
70SdBusError& SdBusError::operator=(SdBusError&& other)
71{
72 if (this != &other)
73 {
74 move(std::move(other));
75 }
76 return *this;
77}
78
79SdBusError::~SdBusError()
80{
William A. Kennington III37657502018-06-22 19:00:05 -070081 intf->sd_bus_error_free(&error);
William A. Kennington III20db3bf2018-05-14 16:18:37 -070082}
83
84const char* SdBusError::name() const noexcept
85{
86 return error.name;
87}
88
89const char* SdBusError::description() const noexcept
90{
91 return error.message;
92}
93
94const char* SdBusError::what() const noexcept
95{
96 return full_message.c_str();
97}
98
Adriana Kobylak33335b32018-09-21 11:50:42 -050099int SdBusError::get_errno() const noexcept
100{
101 return intf->sd_bus_error_get_errno(&this->error);
102}
103
Adrian Ambrożewicza66f6b42020-01-09 17:21:58 +0100104const sd_bus_error* SdBusError::get_error() const noexcept
105{
106 return &error;
107}
108
Patrick Williams70bcf142023-07-26 16:19:48 -0500109void SdBusError::populateMessage(std::string&& prefix)
William A. Kennington III20db3bf2018-05-14 16:18:37 -0700110{
Patrick Williams70bcf142023-07-26 16:19:48 -0500111 full_message = std::move(prefix);
William A. Kennington III20db3bf2018-05-14 16:18:37 -0700112 if (error.name)
113 {
114 full_message += ": ";
115 full_message += error.name;
116 }
117 if (error.message)
118 {
119 full_message += ": ";
120 full_message += error.message;
121 }
122}
123
124void SdBusError::move(SdBusError&& other)
125{
William A. Kennington III37657502018-06-22 19:00:05 -0700126 intf = std::move(other.intf);
127
128 intf->sd_bus_error_free(&error);
William A. Kennington III20db3bf2018-05-14 16:18:37 -0700129 error = other.error;
130 other.error = SD_BUS_ERROR_NULL;
131
132 full_message = std::move(other.full_message);
133}
134
Patrick Williams93b0e702017-04-18 11:19:45 -0500135const char* InvalidEnumString::name() const noexcept
136{
137 return errName;
138}
139
140const char* InvalidEnumString::description() const noexcept
141{
142 return errDesc;
143}
144
145const char* InvalidEnumString::what() const noexcept
146{
147 return errWhat;
148}
149
Patrick Williamsbd372ec2021-09-02 15:15:24 -0500150int InvalidEnumString::get_errno() const noexcept
151{
152 return EINVAL;
153}
154
Ed Tanousc3484732023-01-04 15:59:18 -0800155static std::string unpackErrorReasonToString(const UnpackErrorReason reason)
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100156{
157 switch (reason)
158 {
159 case UnpackErrorReason::missingProperty:
160 return "Missing property";
161 case UnpackErrorReason::wrongType:
162 return "Type not matched";
163 }
164 return "Unknown";
165}
166
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200167UnpackPropertyError::UnpackPropertyError(std::string_view propertyNameIn,
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100168 const UnpackErrorReason reasonIn) :
Patrick Williams06f265f2024-08-16 15:19:49 -0400169 propertyName(propertyNameIn), reason(reasonIn),
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200170 errWhatDetailed(std::string(errWhat) + " PropertyName: '" + propertyName +
Krzysztof Grobelnyc8447d52022-01-05 13:21:37 +0100171 "', Reason: '" + unpackErrorReasonToString(reason) + "'.")
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200172{}
173
174const char* UnpackPropertyError::name() const noexcept
175{
176 return errName;
177}
178
179const char* UnpackPropertyError::description() const noexcept
180{
181 return errDesc;
182}
183
184const char* UnpackPropertyError::what() const noexcept
185{
Szymon Dompke6d83cf52021-10-19 16:31:29 +0200186 return errWhatDetailed.c_str();
Krzysztof Grobelny09b88f22020-09-02 14:49:01 +0200187}
188
Patrick Williamsbd372ec2021-09-02 15:15:24 -0500189int UnpackPropertyError::get_errno() const noexcept
190{
191 return EINVAL;
192}
193
Patrick Williams4cfc2842022-09-22 09:53:33 -0500194const char* UnhandledStop::name() const noexcept
195{
196 return errName;
197}
198
199const char* UnhandledStop::description() const noexcept
200{
201 return errDesc;
202}
203
204const char* UnhandledStop::what() const noexcept
205{
206 return errWhat;
207}
208
209int UnhandledStop::get_errno() const noexcept
210{
211 return ECANCELED;
212}
213
Patrick Williamsb08d14d2024-11-05 21:35:55 -0500214static std::unordered_map<std::string, sdbusplus::sdbuspp::register_hook>
215 event_hooks = {};
216
217void throw_via_json(const nlohmann::json& j, const std::source_location& source)
218{
219 for (const auto& i : j.items())
220 {
221 if (auto it = event_hooks.find(i.key()); it != event_hooks.end())
222 {
223 it->second(j, source);
224 }
225 }
226}
227
228auto known_events() -> std::vector<std::string>
229{
230 std::vector<std::string> result{};
231
232 for (const auto& [key, _] : event_hooks)
233 {
234 result.emplace_back(key);
235 }
236
237 std::ranges::sort(result);
238
239 return result;
240}
241
242} // namespace sdbusplus::exception
243
244namespace sdbusplus::sdbuspp
245{
246
247void register_event(const std::string& event, register_hook throw_hook)
248{
249 sdbusplus::exception::event_hooks.emplace(event, throw_hook);
250}
251
252} // namespace sdbusplus::sdbuspp
Patrick Williams0c8136a2021-08-28 14:42:31 -0500253
254#ifdef __clang__
255#pragma clang diagnostic pop
256#endif