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