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