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