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