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