xref: /openbmc/sdbusplus/src/exception.cpp (revision a4bfefde)
1 #include <sdbusplus/exception.hpp>
2 
3 #include <cerrno>
4 #include <stdexcept>
5 #include <utility>
6 
7 #ifdef __clang__
8 #pragma clang diagnostic push
9 #pragma clang diagnostic ignored "-Wc99-extensions"
10 #endif
11 
12 namespace sdbusplus
13 {
14 namespace exception
15 {
16 
17 void exception::unused() const noexcept {}
18 
19 int exception::set_error(sd_bus_error* e) const
20 {
21     return sd_bus_error_set(e, name(), description());
22 }
23 
24 int exception::set_error(SdBusInterface* i, sd_bus_error* e) const
25 {
26     return i->sd_bus_error_set(e, name(), description());
27 }
28 
29 int generated_exception::get_errno() const noexcept
30 {
31     return EIO;
32 }
33 
34 SdBusError::SdBusError(int error_in, const char* prefix,
35                        SdBusInterface* intf_in) :
36     SdBusError(error_in, std::string(prefix), intf_in)
37 {}
38 
39 SdBusError::SdBusError(int error_in, std::string&& prefix,
40                        SdBusInterface* intf_in) :
41     error(SD_BUS_ERROR_NULL), intf(intf_in)
42 {
43     // We can't check the output of intf->sd_bus_error_set_errno() because
44     // it returns the input errorcode. We don't want to try and guess
45     // possible error statuses. Instead, check to see if the error was
46     // constructed to determine success.
47     intf->sd_bus_error_set_errno(&this->error, error_in);
48     if (!intf->sd_bus_error_is_set(&this->error))
49     {
50         throw std::runtime_error("Failed to create SdBusError");
51     }
52 
53     populateMessage(std::move(prefix));
54 }
55 
56 SdBusError::SdBusError(sd_bus_error* error_in, const char* prefix,
57                        SdBusInterface* intf_in) :
58     error(*error_in), intf(intf_in)
59 {
60     // We own the error so remove the caller's reference
61     *error_in = SD_BUS_ERROR_NULL;
62 
63     populateMessage(std::string(prefix));
64 }
65 
66 SdBusError::SdBusError(SdBusError&& other) : error(SD_BUS_ERROR_NULL)
67 {
68     move(std::move(other));
69 }
70 
71 SdBusError& SdBusError::operator=(SdBusError&& other)
72 {
73     if (this != &other)
74     {
75         move(std::move(other));
76     }
77     return *this;
78 }
79 
80 SdBusError::~SdBusError()
81 {
82     intf->sd_bus_error_free(&error);
83 }
84 
85 const char* SdBusError::name() const noexcept
86 {
87     return error.name;
88 }
89 
90 const char* SdBusError::description() const noexcept
91 {
92     return error.message;
93 }
94 
95 const char* SdBusError::what() const noexcept
96 {
97     return full_message.c_str();
98 }
99 
100 int SdBusError::get_errno() const noexcept
101 {
102     return intf->sd_bus_error_get_errno(&this->error);
103 }
104 
105 const sd_bus_error* SdBusError::get_error() const noexcept
106 {
107     return &error;
108 }
109 
110 void SdBusError::populateMessage(std::string&& prefix)
111 {
112     full_message = std::move(prefix);
113     if (error.name)
114     {
115         full_message += ": ";
116         full_message += error.name;
117     }
118     if (error.message)
119     {
120         full_message += ": ";
121         full_message += error.message;
122     }
123 }
124 
125 void SdBusError::move(SdBusError&& other)
126 {
127     intf = std::move(other.intf);
128 
129     intf->sd_bus_error_free(&error);
130     error = other.error;
131     other.error = SD_BUS_ERROR_NULL;
132 
133     full_message = std::move(other.full_message);
134 }
135 
136 const char* InvalidEnumString::name() const noexcept
137 {
138     return errName;
139 }
140 
141 const char* InvalidEnumString::description() const noexcept
142 {
143     return errDesc;
144 }
145 
146 const char* InvalidEnumString::what() const noexcept
147 {
148     return errWhat;
149 }
150 
151 int InvalidEnumString::get_errno() const noexcept
152 {
153     return EINVAL;
154 }
155 
156 static std::string unpackErrorReasonToString(const UnpackErrorReason reason)
157 {
158     switch (reason)
159     {
160         case UnpackErrorReason::missingProperty:
161             return "Missing property";
162         case UnpackErrorReason::wrongType:
163             return "Type not matched";
164     }
165     return "Unknown";
166 }
167 
168 UnpackPropertyError::UnpackPropertyError(std::string_view propertyNameIn,
169                                          const UnpackErrorReason reasonIn) :
170     propertyName(propertyNameIn), reason(reasonIn),
171     errWhatDetailed(std::string(errWhat) + " PropertyName: '" + propertyName +
172                     "', Reason: '" + unpackErrorReasonToString(reason) + "'.")
173 {}
174 
175 const char* UnpackPropertyError::name() const noexcept
176 {
177     return errName;
178 }
179 
180 const char* UnpackPropertyError::description() const noexcept
181 {
182     return errDesc;
183 }
184 
185 const char* UnpackPropertyError::what() const noexcept
186 {
187     return errWhatDetailed.c_str();
188 }
189 
190 int UnpackPropertyError::get_errno() const noexcept
191 {
192     return EINVAL;
193 }
194 
195 const char* UnhandledStop::name() const noexcept
196 {
197     return errName;
198 }
199 
200 const char* UnhandledStop::description() const noexcept
201 {
202     return errDesc;
203 }
204 
205 const char* UnhandledStop::what() const noexcept
206 {
207     return errWhat;
208 }
209 
210 int UnhandledStop::get_errno() const noexcept
211 {
212     return ECANCELED;
213 }
214 
215 } // namespace exception
216 } // namespace sdbusplus
217 
218 #ifdef __clang__
219 #pragma clang diagnostic pop
220 #endif
221