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) 31error_category::error_category() _NOEXCEPT 32{ 33} 34#endif 35 36error_category::~error_category() _NOEXCEPT 37{ 38} 39 40error_condition 41error_category::default_error_condition(int ev) const _NOEXCEPT 42{ 43 return error_condition(ev, *this); 44} 45 46bool 47error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT 48{ 49 return default_error_condition(code) == condition; 50} 51 52bool 53error_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) 59namespace { 60 61// GLIBC also uses 1024 as the maximum buffer size internally. 62constexpr size_t strerror_buff_size = 1024; 63 64string do_strerror_r(int ev); 65 66#if defined(_LIBCPP_MSVCRT_LIKE) 67string 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 * 81handle_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 * 90handle_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. 111string 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 130string 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 140class _LIBCPP_HIDDEN __generic_error_category 141 : public __do_message 142{ 143public: 144 virtual const char* name() const _NOEXCEPT; 145 virtual string message(int ev) const; 146}; 147 148const char* 149__generic_error_category::name() const _NOEXCEPT 150{ 151 return "generic"; 152} 153 154string 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 164const error_category& 165generic_category() _NOEXCEPT 166{ 167 static __generic_error_category s; 168 return s; 169} 170 171class _LIBCPP_HIDDEN __system_error_category 172 : public __do_message 173{ 174public: 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 180const char* 181__system_error_category::name() const _NOEXCEPT 182{ 183 return "system"; 184} 185 186string 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 196error_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 206const error_category& 207system_category() _NOEXCEPT 208{ 209 static __system_error_category s; 210 return s; 211} 212 213// error_condition 214 215string 216error_condition::message() const 217{ 218 return __cat_->message(__val_); 219} 220 221// error_code 222 223string 224error_code::message() const 225{ 226 return __cat_->message(__val_); 227} 228 229// system_error 230 231string 232system_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 243system_error::system_error(error_code ec, const string& what_arg) 244 : runtime_error(__init(ec, what_arg)), 245 __ec_(ec) 246{ 247} 248 249system_error::system_error(error_code ec, const char* what_arg) 250 : runtime_error(__init(ec, what_arg)), 251 __ec_(ec) 252{ 253} 254 255system_error::system_error(error_code ec) 256 : runtime_error(__init(ec, "")), 257 __ec_(ec) 258{ 259} 260 261system_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 267system_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 273system_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 279system_error::~system_error() _NOEXCEPT 280{ 281} 282 283void 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