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