Rework libcxx strerror_r handling.
[lldb.git] / libcxx / src / system_error.cpp
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 "string"
21 #include "string.h"
22 #include "__debug"
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_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
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(_LIBCPP_MSVCRT_LIKE)
69 string do_strerror_r(int ev) {
70   char buffer[strerror_buff_size];
71   if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
72     return string(buffer);
73   std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
74   return string(buffer);
75 }
76 #else
77
78 // Only one of the two following functions will be used, depending on
79 // the return type of strerror_r:
80
81 // For the GNU variant, a char* return value:
82 __attribute__((unused)) const char *
83 handle_strerror_r_return(char *strerror_return, char *buffer) {
84   // GNU always returns a string pointer in its return value. The
85   // string might point to either the input buffer, or a static
86   // buffer, but we don't care which.
87   return strerror_return;
88 }
89
90 // For the POSIX variant: an int return value.
91 __attribute__((unused)) const char *
92 handle_strerror_r_return(int strerror_return, char *buffer) {
93   // The POSIX variant either:
94   // - fills in the provided buffer and returns 0
95   // - returns a positive error value, or
96   // - returns -1 and fills in errno with an error value.
97   if (strerror_return == 0)
98     return buffer;
99
100   // Only handle EINVAL. Other errors abort.
101   int new_errno = strerror_return == -1 ? errno : strerror_return;
102   if (new_errno == EINVAL)
103     return "";
104
105   _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
106   // FIXME maybe? 'strerror_buff_size' is likely to exceed the
107   // maximum error size so ERANGE shouldn't be returned.
108   std::abort();
109 }
110
111 // This function handles both GNU and POSIX variants, dispatching to
112 // one of the two above functions.
113 string do_strerror_r(int ev) {
114     char buffer[strerror_buff_size];
115     // Preserve errno around the call. (The C++ standard requires that
116     // system_error functions not modify errno).
117     const int old_errno = errno;
118     const char *error_message = handle_strerror_r_return(
119         ::strerror_r(ev, buffer, strerror_buff_size), buffer);
120     // If we didn't get any message, print one now.
121     if (!error_message[0]) {
122       std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
123       error_message = buffer;
124     }
125     errno = old_errno;
126     return string(error_message);
127 }
128 #endif
129 } // end namespace
130 #endif
131
132 string
133 __do_message::message(int ev) const
134 {
135 #if defined(_LIBCPP_HAS_NO_THREADS)
136     return string(::strerror(ev));
137 #else
138     return do_strerror_r(ev);
139 #endif
140 }
141
142 class _LIBCPP_HIDDEN __generic_error_category
143     : public __do_message
144 {
145 public:
146     virtual const char* name() const _NOEXCEPT;
147     virtual string message(int ev) const;
148 };
149
150 const char*
151 __generic_error_category::name() const _NOEXCEPT
152 {
153     return "generic";
154 }
155
156 string
157 __generic_error_category::message(int ev) const
158 {
159 #ifdef _LIBCPP_ELAST
160     if (ev > _LIBCPP_ELAST)
161       return string("unspecified generic_category error");
162 #endif  // _LIBCPP_ELAST
163     return __do_message::message(ev);
164 }
165
166 const error_category&
167 generic_category() _NOEXCEPT
168 {
169     static __generic_error_category s;
170     return s;
171 }
172
173 class _LIBCPP_HIDDEN __system_error_category
174     : public __do_message
175 {
176 public:
177     virtual const char* name() const _NOEXCEPT;
178     virtual string message(int ev) const;
179     virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
180 };
181
182 const char*
183 __system_error_category::name() const _NOEXCEPT
184 {
185     return "system";
186 }
187
188 string
189 __system_error_category::message(int ev) const
190 {
191 #ifdef _LIBCPP_ELAST
192     if (ev > _LIBCPP_ELAST)
193       return string("unspecified system_category error");
194 #endif  // _LIBCPP_ELAST
195     return __do_message::message(ev);
196 }
197
198 error_condition
199 __system_error_category::default_error_condition(int ev) const _NOEXCEPT
200 {
201 #ifdef _LIBCPP_ELAST
202     if (ev > _LIBCPP_ELAST)
203       return error_condition(ev, system_category());
204 #endif  // _LIBCPP_ELAST
205     return error_condition(ev, generic_category());
206 }
207
208 const error_category&
209 system_category() _NOEXCEPT
210 {
211     static __system_error_category s;
212     return s;
213 }
214
215 // error_condition
216
217 string
218 error_condition::message() const
219 {
220     return __cat_->message(__val_);
221 }
222
223 // error_code
224
225 string
226 error_code::message() const
227 {
228     return __cat_->message(__val_);
229 }
230
231 // system_error
232
233 string
234 system_error::__init(const error_code& ec, string what_arg)
235 {
236     if (ec)
237     {
238         if (!what_arg.empty())
239             what_arg += ": ";
240         what_arg += ec.message();
241     }
242     return what_arg;
243 }
244
245 system_error::system_error(error_code ec, const string& what_arg)
246     : runtime_error(__init(ec, what_arg)),
247       __ec_(ec)
248 {
249 }
250
251 system_error::system_error(error_code ec, const char* what_arg)
252     : runtime_error(__init(ec, what_arg)),
253       __ec_(ec)
254 {
255 }
256
257 system_error::system_error(error_code ec)
258     : runtime_error(__init(ec, "")),
259       __ec_(ec)
260 {
261 }
262
263 system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
264     : runtime_error(__init(error_code(ev, ecat), what_arg)),
265       __ec_(error_code(ev, ecat))
266 {
267 }
268
269 system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
270     : runtime_error(__init(error_code(ev, ecat), what_arg)),
271       __ec_(error_code(ev, ecat))
272 {
273 }
274
275 system_error::system_error(int ev, const error_category& ecat)
276     : runtime_error(__init(error_code(ev, ecat), "")),
277       __ec_(error_code(ev, ecat))
278 {
279 }
280
281 system_error::~system_error() _NOEXCEPT
282 {
283 }
284
285 void
286 __throw_system_error(int ev, const char* what_arg)
287 {
288 #ifndef _LIBCPP_NO_EXCEPTIONS
289     throw system_error(error_code(ev, system_category()), what_arg);
290 #else
291     (void)ev;
292     (void)what_arg;
293     _VSTD::abort();
294 #endif
295 }
296
297 _LIBCPP_END_NAMESPACE_STD