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