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