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