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