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