1*4d6fc14bSjoerg //===---------------------- system_error.cpp ------------------------------===//
2*4d6fc14bSjoerg //
3*4d6fc14bSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4d6fc14bSjoerg // See https://llvm.org/LICENSE.txt for license information.
5*4d6fc14bSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4d6fc14bSjoerg //
7*4d6fc14bSjoerg //===----------------------------------------------------------------------===//
8*4d6fc14bSjoerg
9*4d6fc14bSjoerg #include "__config"
10*4d6fc14bSjoerg
11*4d6fc14bSjoerg #include "system_error"
12*4d6fc14bSjoerg
13*4d6fc14bSjoerg #include "include/config_elast.h"
14*4d6fc14bSjoerg #include "cerrno"
15*4d6fc14bSjoerg #include "cstring"
16*4d6fc14bSjoerg #include "cstdio"
17*4d6fc14bSjoerg #include "cstdlib"
18*4d6fc14bSjoerg #include "string"
19*4d6fc14bSjoerg #include "string.h"
20*4d6fc14bSjoerg #include "__debug"
21*4d6fc14bSjoerg
22*4d6fc14bSjoerg #if defined(__ANDROID__)
23*4d6fc14bSjoerg #include <android/api-level.h>
24*4d6fc14bSjoerg #endif
25*4d6fc14bSjoerg
26*4d6fc14bSjoerg _LIBCPP_BEGIN_NAMESPACE_STD
27*4d6fc14bSjoerg
28*4d6fc14bSjoerg // class error_category
29*4d6fc14bSjoerg
30*4d6fc14bSjoerg #if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
error_category()31*4d6fc14bSjoerg error_category::error_category() noexcept
32*4d6fc14bSjoerg {
33*4d6fc14bSjoerg }
34*4d6fc14bSjoerg #endif
35*4d6fc14bSjoerg
~error_category()36*4d6fc14bSjoerg error_category::~error_category() noexcept
37*4d6fc14bSjoerg {
38*4d6fc14bSjoerg }
39*4d6fc14bSjoerg
40*4d6fc14bSjoerg error_condition
default_error_condition(int ev) const41*4d6fc14bSjoerg error_category::default_error_condition(int ev) const noexcept
42*4d6fc14bSjoerg {
43*4d6fc14bSjoerg return error_condition(ev, *this);
44*4d6fc14bSjoerg }
45*4d6fc14bSjoerg
46*4d6fc14bSjoerg bool
equivalent(int code,const error_condition & condition) const47*4d6fc14bSjoerg error_category::equivalent(int code, const error_condition& condition) const noexcept
48*4d6fc14bSjoerg {
49*4d6fc14bSjoerg return default_error_condition(code) == condition;
50*4d6fc14bSjoerg }
51*4d6fc14bSjoerg
52*4d6fc14bSjoerg bool
equivalent(const error_code & code,int condition) const53*4d6fc14bSjoerg error_category::equivalent(const error_code& code, int condition) const noexcept
54*4d6fc14bSjoerg {
55*4d6fc14bSjoerg return *this == code.category() && code.value() == condition;
56*4d6fc14bSjoerg }
57*4d6fc14bSjoerg
58*4d6fc14bSjoerg #if !defined(_LIBCPP_HAS_NO_THREADS)
59*4d6fc14bSjoerg namespace {
60*4d6fc14bSjoerg
61*4d6fc14bSjoerg // GLIBC also uses 1024 as the maximum buffer size internally.
62*4d6fc14bSjoerg constexpr size_t strerror_buff_size = 1024;
63*4d6fc14bSjoerg
64*4d6fc14bSjoerg string do_strerror_r(int ev);
65*4d6fc14bSjoerg
66*4d6fc14bSjoerg #if defined(_LIBCPP_MSVCRT_LIKE)
do_strerror_r(int ev)67*4d6fc14bSjoerg string do_strerror_r(int ev) {
68*4d6fc14bSjoerg char buffer[strerror_buff_size];
69*4d6fc14bSjoerg if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
70*4d6fc14bSjoerg return string(buffer);
71*4d6fc14bSjoerg std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
72*4d6fc14bSjoerg return string(buffer);
73*4d6fc14bSjoerg }
74*4d6fc14bSjoerg #else
75*4d6fc14bSjoerg
76*4d6fc14bSjoerg // Only one of the two following functions will be used, depending on
77*4d6fc14bSjoerg // the return type of strerror_r:
78*4d6fc14bSjoerg
79*4d6fc14bSjoerg // For the GNU variant, a char* return value:
80*4d6fc14bSjoerg __attribute__((unused)) const char *
handle_strerror_r_return(char * strerror_return,char * buffer)81*4d6fc14bSjoerg handle_strerror_r_return(char *strerror_return, char *buffer) {
82*4d6fc14bSjoerg // GNU always returns a string pointer in its return value. The
83*4d6fc14bSjoerg // string might point to either the input buffer, or a static
84*4d6fc14bSjoerg // buffer, but we don't care which.
85*4d6fc14bSjoerg return strerror_return;
86*4d6fc14bSjoerg }
87*4d6fc14bSjoerg
88*4d6fc14bSjoerg // For the POSIX variant: an int return value.
89*4d6fc14bSjoerg __attribute__((unused)) const char *
handle_strerror_r_return(int strerror_return,char * buffer)90*4d6fc14bSjoerg handle_strerror_r_return(int strerror_return, char *buffer) {
91*4d6fc14bSjoerg // The POSIX variant either:
92*4d6fc14bSjoerg // - fills in the provided buffer and returns 0
93*4d6fc14bSjoerg // - returns a positive error value, or
94*4d6fc14bSjoerg // - returns -1 and fills in errno with an error value.
95*4d6fc14bSjoerg if (strerror_return == 0)
96*4d6fc14bSjoerg return buffer;
97*4d6fc14bSjoerg
98*4d6fc14bSjoerg // Only handle EINVAL. Other errors abort.
99*4d6fc14bSjoerg int new_errno = strerror_return == -1 ? errno : strerror_return;
100*4d6fc14bSjoerg if (new_errno == EINVAL)
101*4d6fc14bSjoerg return "";
102*4d6fc14bSjoerg
103*4d6fc14bSjoerg _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
104*4d6fc14bSjoerg // FIXME maybe? 'strerror_buff_size' is likely to exceed the
105*4d6fc14bSjoerg // maximum error size so ERANGE shouldn't be returned.
106*4d6fc14bSjoerg std::abort();
107*4d6fc14bSjoerg }
108*4d6fc14bSjoerg
109*4d6fc14bSjoerg // This function handles both GNU and POSIX variants, dispatching to
110*4d6fc14bSjoerg // one of the two above functions.
do_strerror_r(int ev)111*4d6fc14bSjoerg string do_strerror_r(int ev) {
112*4d6fc14bSjoerg char buffer[strerror_buff_size];
113*4d6fc14bSjoerg // Preserve errno around the call. (The C++ standard requires that
114*4d6fc14bSjoerg // system_error functions not modify errno).
115*4d6fc14bSjoerg const int old_errno = errno;
116*4d6fc14bSjoerg const char *error_message = handle_strerror_r_return(
117*4d6fc14bSjoerg ::strerror_r(ev, buffer, strerror_buff_size), buffer);
118*4d6fc14bSjoerg // If we didn't get any message, print one now.
119*4d6fc14bSjoerg if (!error_message[0]) {
120*4d6fc14bSjoerg std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
121*4d6fc14bSjoerg error_message = buffer;
122*4d6fc14bSjoerg }
123*4d6fc14bSjoerg errno = old_errno;
124*4d6fc14bSjoerg return string(error_message);
125*4d6fc14bSjoerg }
126*4d6fc14bSjoerg #endif
127*4d6fc14bSjoerg } // end namespace
128*4d6fc14bSjoerg #endif
129*4d6fc14bSjoerg
130*4d6fc14bSjoerg string
message(int ev) const131*4d6fc14bSjoerg __do_message::message(int ev) const
132*4d6fc14bSjoerg {
133*4d6fc14bSjoerg #if defined(_LIBCPP_HAS_NO_THREADS)
134*4d6fc14bSjoerg return string(::strerror(ev));
135*4d6fc14bSjoerg #else
136*4d6fc14bSjoerg return do_strerror_r(ev);
137*4d6fc14bSjoerg #endif
138*4d6fc14bSjoerg }
139*4d6fc14bSjoerg
140*4d6fc14bSjoerg class _LIBCPP_HIDDEN __generic_error_category
141*4d6fc14bSjoerg : public __do_message
142*4d6fc14bSjoerg {
143*4d6fc14bSjoerg public:
144*4d6fc14bSjoerg virtual const char* name() const noexcept;
145*4d6fc14bSjoerg virtual string message(int ev) const;
146*4d6fc14bSjoerg };
147*4d6fc14bSjoerg
148*4d6fc14bSjoerg const char*
name() const149*4d6fc14bSjoerg __generic_error_category::name() const noexcept
150*4d6fc14bSjoerg {
151*4d6fc14bSjoerg return "generic";
152*4d6fc14bSjoerg }
153*4d6fc14bSjoerg
154*4d6fc14bSjoerg string
message(int ev) const155*4d6fc14bSjoerg __generic_error_category::message(int ev) const
156*4d6fc14bSjoerg {
157*4d6fc14bSjoerg #ifdef _LIBCPP_ELAST
158*4d6fc14bSjoerg if (ev > _LIBCPP_ELAST)
159*4d6fc14bSjoerg return string("unspecified generic_category error");
160*4d6fc14bSjoerg #endif // _LIBCPP_ELAST
161*4d6fc14bSjoerg return __do_message::message(ev);
162*4d6fc14bSjoerg }
163*4d6fc14bSjoerg
164*4d6fc14bSjoerg const error_category&
generic_category()165*4d6fc14bSjoerg generic_category() noexcept
166*4d6fc14bSjoerg {
167*4d6fc14bSjoerg static __generic_error_category s;
168*4d6fc14bSjoerg return s;
169*4d6fc14bSjoerg }
170*4d6fc14bSjoerg
171*4d6fc14bSjoerg class _LIBCPP_HIDDEN __system_error_category
172*4d6fc14bSjoerg : public __do_message
173*4d6fc14bSjoerg {
174*4d6fc14bSjoerg public:
175*4d6fc14bSjoerg virtual const char* name() const noexcept;
176*4d6fc14bSjoerg virtual string message(int ev) const;
177*4d6fc14bSjoerg virtual error_condition default_error_condition(int ev) const noexcept;
178*4d6fc14bSjoerg };
179*4d6fc14bSjoerg
180*4d6fc14bSjoerg const char*
name() const181*4d6fc14bSjoerg __system_error_category::name() const noexcept
182*4d6fc14bSjoerg {
183*4d6fc14bSjoerg return "system";
184*4d6fc14bSjoerg }
185*4d6fc14bSjoerg
186*4d6fc14bSjoerg string
message(int ev) const187*4d6fc14bSjoerg __system_error_category::message(int ev) const
188*4d6fc14bSjoerg {
189*4d6fc14bSjoerg #ifdef _LIBCPP_ELAST
190*4d6fc14bSjoerg if (ev > _LIBCPP_ELAST)
191*4d6fc14bSjoerg return string("unspecified system_category error");
192*4d6fc14bSjoerg #endif // _LIBCPP_ELAST
193*4d6fc14bSjoerg return __do_message::message(ev);
194*4d6fc14bSjoerg }
195*4d6fc14bSjoerg
196*4d6fc14bSjoerg error_condition
default_error_condition(int ev) const197*4d6fc14bSjoerg __system_error_category::default_error_condition(int ev) const noexcept
198*4d6fc14bSjoerg {
199*4d6fc14bSjoerg #ifdef _LIBCPP_ELAST
200*4d6fc14bSjoerg if (ev > _LIBCPP_ELAST)
201*4d6fc14bSjoerg return error_condition(ev, system_category());
202*4d6fc14bSjoerg #endif // _LIBCPP_ELAST
203*4d6fc14bSjoerg return error_condition(ev, generic_category());
204*4d6fc14bSjoerg }
205*4d6fc14bSjoerg
206*4d6fc14bSjoerg const error_category&
system_category()207*4d6fc14bSjoerg system_category() noexcept
208*4d6fc14bSjoerg {
209*4d6fc14bSjoerg static __system_error_category s;
210*4d6fc14bSjoerg return s;
211*4d6fc14bSjoerg }
212*4d6fc14bSjoerg
213*4d6fc14bSjoerg // error_condition
214*4d6fc14bSjoerg
215*4d6fc14bSjoerg string
message() const216*4d6fc14bSjoerg error_condition::message() const
217*4d6fc14bSjoerg {
218*4d6fc14bSjoerg return __cat_->message(__val_);
219*4d6fc14bSjoerg }
220*4d6fc14bSjoerg
221*4d6fc14bSjoerg // error_code
222*4d6fc14bSjoerg
223*4d6fc14bSjoerg string
message() const224*4d6fc14bSjoerg error_code::message() const
225*4d6fc14bSjoerg {
226*4d6fc14bSjoerg return __cat_->message(__val_);
227*4d6fc14bSjoerg }
228*4d6fc14bSjoerg
229*4d6fc14bSjoerg // system_error
230*4d6fc14bSjoerg
231*4d6fc14bSjoerg string
__init(const error_code & ec,string what_arg)232*4d6fc14bSjoerg system_error::__init(const error_code& ec, string what_arg)
233*4d6fc14bSjoerg {
234*4d6fc14bSjoerg if (ec)
235*4d6fc14bSjoerg {
236*4d6fc14bSjoerg if (!what_arg.empty())
237*4d6fc14bSjoerg what_arg += ": ";
238*4d6fc14bSjoerg what_arg += ec.message();
239*4d6fc14bSjoerg }
240*4d6fc14bSjoerg return what_arg;
241*4d6fc14bSjoerg }
242*4d6fc14bSjoerg
system_error(error_code ec,const string & what_arg)243*4d6fc14bSjoerg system_error::system_error(error_code ec, const string& what_arg)
244*4d6fc14bSjoerg : runtime_error(__init(ec, what_arg)),
245*4d6fc14bSjoerg __ec_(ec)
246*4d6fc14bSjoerg {
247*4d6fc14bSjoerg }
248*4d6fc14bSjoerg
system_error(error_code ec,const char * what_arg)249*4d6fc14bSjoerg system_error::system_error(error_code ec, const char* what_arg)
250*4d6fc14bSjoerg : runtime_error(__init(ec, what_arg)),
251*4d6fc14bSjoerg __ec_(ec)
252*4d6fc14bSjoerg {
253*4d6fc14bSjoerg }
254*4d6fc14bSjoerg
system_error(error_code ec)255*4d6fc14bSjoerg system_error::system_error(error_code ec)
256*4d6fc14bSjoerg : runtime_error(__init(ec, "")),
257*4d6fc14bSjoerg __ec_(ec)
258*4d6fc14bSjoerg {
259*4d6fc14bSjoerg }
260*4d6fc14bSjoerg
system_error(int ev,const error_category & ecat,const string & what_arg)261*4d6fc14bSjoerg system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
262*4d6fc14bSjoerg : runtime_error(__init(error_code(ev, ecat), what_arg)),
263*4d6fc14bSjoerg __ec_(error_code(ev, ecat))
264*4d6fc14bSjoerg {
265*4d6fc14bSjoerg }
266*4d6fc14bSjoerg
system_error(int ev,const error_category & ecat,const char * what_arg)267*4d6fc14bSjoerg system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
268*4d6fc14bSjoerg : runtime_error(__init(error_code(ev, ecat), what_arg)),
269*4d6fc14bSjoerg __ec_(error_code(ev, ecat))
270*4d6fc14bSjoerg {
271*4d6fc14bSjoerg }
272*4d6fc14bSjoerg
system_error(int ev,const error_category & ecat)273*4d6fc14bSjoerg system_error::system_error(int ev, const error_category& ecat)
274*4d6fc14bSjoerg : runtime_error(__init(error_code(ev, ecat), "")),
275*4d6fc14bSjoerg __ec_(error_code(ev, ecat))
276*4d6fc14bSjoerg {
277*4d6fc14bSjoerg }
278*4d6fc14bSjoerg
~system_error()279*4d6fc14bSjoerg system_error::~system_error() noexcept
280*4d6fc14bSjoerg {
281*4d6fc14bSjoerg }
282*4d6fc14bSjoerg
283*4d6fc14bSjoerg void
__throw_system_error(int ev,const char * what_arg)284*4d6fc14bSjoerg __throw_system_error(int ev, const char* what_arg)
285*4d6fc14bSjoerg {
286*4d6fc14bSjoerg #ifndef _LIBCPP_NO_EXCEPTIONS
287*4d6fc14bSjoerg throw system_error(error_code(ev, system_category()), what_arg);
288*4d6fc14bSjoerg #else
289*4d6fc14bSjoerg (void)ev;
290*4d6fc14bSjoerg (void)what_arg;
291*4d6fc14bSjoerg _VSTD::abort();
292*4d6fc14bSjoerg #endif
293*4d6fc14bSjoerg }
294*4d6fc14bSjoerg
295*4d6fc14bSjoerg _LIBCPP_END_NAMESPACE_STD
296