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