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