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