1 //===---------------------- system_error.cpp ------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "__config"
11 
12 #define _LIBCPP_BUILDING_SYSTEM_ERROR
13 #include "system_error"
14 
15 #include "include/config_elast.h"
16 #include "cerrno"
17 #include "cstring"
18 #include "cstdio"
19 #include "cstdlib"
20 #include "cassert"
21 #include "string"
22 #include "string.h"
23 
24 #if defined(__ANDROID__)
25 #include <android/api-level.h>
26 #endif
27 
28 _LIBCPP_BEGIN_NAMESPACE_STD
29 
30 // class error_category
31 
32 #if defined(_LIBCPP_DEPRECATED_ABI_EXTERNAL_ERROR_CATEGORY_CONSTRUCTOR)
33 error_category::error_category() _NOEXCEPT
34 {
35 }
36 #endif
37 
38 error_category::~error_category() _NOEXCEPT
39 {
40 }
41 
42 error_condition
43 error_category::default_error_condition(int ev) const _NOEXCEPT
44 {
45     return error_condition(ev, *this);
46 }
47 
48 bool
49 error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
50 {
51     return default_error_condition(code) == condition;
52 }
53 
54 bool
55 error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
56 {
57     return *this == code.category() && code.value() == condition;
58 }
59 
60 #if !defined(_LIBCPP_HAS_NO_THREADS)
61 namespace {
62 
63 //  GLIBC also uses 1024 as the maximum buffer size internally.
64 constexpr size_t strerror_buff_size = 1024;
65 
66 string do_strerror_r(int ev);
67 
68 #if defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC)                      \
69     && (!defined(__ANDROID__) || __ANDROID_API__ >= 23)
70 // GNU Extended version
71 string do_strerror_r(int ev) {
72     char buffer[strerror_buff_size];
73     char* ret = ::strerror_r(ev, buffer, strerror_buff_size);
74     return string(ret);
75 }
76 #else
77 // POSIX version
78 string do_strerror_r(int ev) {
79     char buffer[strerror_buff_size];
80     const int old_errno = errno;
81     int ret;
82     if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
83         // If `ret == -1` then the error is specified using `errno`, otherwise
84         // `ret` represents the error.
85         const int new_errno = ret == -1 ? errno : ret;
86         errno = old_errno;
87         if (new_errno == EINVAL) {
88             std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
89             return string(buffer);
90         } else {
91             assert(new_errno == ERANGE);
92             // FIXME maybe? 'strerror_buff_size' is likely to exceed the
93             // maximum error size so ERANGE shouldn't be returned.
94             std::abort();
95         }
96     }
97     return string(buffer);
98 }
99 #endif
100 
101 } // end namespace
102 #endif
103 
104 string
105 __do_message::message(int ev) const
106 {
107 #if defined(_LIBCPP_HAS_NO_THREADS)
108     return string(::strerror(ev));
109 #else
110     return do_strerror_r(ev);
111 #endif
112 }
113 
114 class _LIBCPP_HIDDEN __generic_error_category
115     : public __do_message
116 {
117 public:
118     virtual const char* name() const _NOEXCEPT;
119     virtual string message(int ev) const;
120 };
121 
122 const char*
123 __generic_error_category::name() const _NOEXCEPT
124 {
125     return "generic";
126 }
127 
128 string
129 __generic_error_category::message(int ev) const
130 {
131 #ifdef _LIBCPP_ELAST
132     if (ev > _LIBCPP_ELAST)
133       return string("unspecified generic_category error");
134 #endif  // _LIBCPP_ELAST
135     return __do_message::message(ev);
136 }
137 
138 const error_category&
139 generic_category() _NOEXCEPT
140 {
141     static __generic_error_category s;
142     return s;
143 }
144 
145 class _LIBCPP_HIDDEN __system_error_category
146     : public __do_message
147 {
148 public:
149     virtual const char* name() const _NOEXCEPT;
150     virtual string message(int ev) const;
151     virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
152 };
153 
154 const char*
155 __system_error_category::name() const _NOEXCEPT
156 {
157     return "system";
158 }
159 
160 string
161 __system_error_category::message(int ev) const
162 {
163 #ifdef _LIBCPP_ELAST
164     if (ev > _LIBCPP_ELAST)
165       return string("unspecified system_category error");
166 #endif  // _LIBCPP_ELAST
167     return __do_message::message(ev);
168 }
169 
170 error_condition
171 __system_error_category::default_error_condition(int ev) const _NOEXCEPT
172 {
173 #ifdef _LIBCPP_ELAST
174     if (ev > _LIBCPP_ELAST)
175       return error_condition(ev, system_category());
176 #endif  // _LIBCPP_ELAST
177     return error_condition(ev, generic_category());
178 }
179 
180 const error_category&
181 system_category() _NOEXCEPT
182 {
183     static __system_error_category s;
184     return s;
185 }
186 
187 // error_condition
188 
189 string
190 error_condition::message() const
191 {
192     return __cat_->message(__val_);
193 }
194 
195 // error_code
196 
197 string
198 error_code::message() const
199 {
200     return __cat_->message(__val_);
201 }
202 
203 // system_error
204 
205 string
206 system_error::__init(const error_code& ec, string what_arg)
207 {
208     if (ec)
209     {
210         if (!what_arg.empty())
211             what_arg += ": ";
212         what_arg += ec.message();
213     }
214     return what_arg;
215 }
216 
217 system_error::system_error(error_code ec, const string& what_arg)
218     : runtime_error(__init(ec, what_arg)),
219       __ec_(ec)
220 {
221 }
222 
223 system_error::system_error(error_code ec, const char* what_arg)
224     : runtime_error(__init(ec, what_arg)),
225       __ec_(ec)
226 {
227 }
228 
229 system_error::system_error(error_code ec)
230     : runtime_error(__init(ec, "")),
231       __ec_(ec)
232 {
233 }
234 
235 system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
236     : runtime_error(__init(error_code(ev, ecat), what_arg)),
237       __ec_(error_code(ev, ecat))
238 {
239 }
240 
241 system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
242     : runtime_error(__init(error_code(ev, ecat), what_arg)),
243       __ec_(error_code(ev, ecat))
244 {
245 }
246 
247 system_error::system_error(int ev, const error_category& ecat)
248     : runtime_error(__init(error_code(ev, ecat), "")),
249       __ec_(error_code(ev, ecat))
250 {
251 }
252 
253 system_error::~system_error() _NOEXCEPT
254 {
255 }
256 
257 void
258 __throw_system_error(int ev, const char* what_arg)
259 {
260 #ifndef _LIBCPP_NO_EXCEPTIONS
261     throw system_error(error_code(ev, system_category()), what_arg);
262 #else
263     (void)ev;
264     (void)what_arg;
265     _VSTD::abort();
266 #endif
267 }
268 
269 _LIBCPP_END_NAMESPACE_STD
270