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 _LIBCPP_BEGIN_NAMESPACE_STD 25 26 // class error_category 27 28 error_category::error_category() _NOEXCEPT 29 { 30 } 31 32 error_category::~error_category() _NOEXCEPT 33 { 34 } 35 36 error_condition 37 error_category::default_error_condition(int ev) const _NOEXCEPT 38 { 39 return error_condition(ev, *this); 40 } 41 42 bool 43 error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT 44 { 45 return default_error_condition(code) == condition; 46 } 47 48 bool 49 error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT 50 { 51 return *this == code.category() && code.value() == condition; 52 } 53 54 namespace { 55 56 // GLIBC also uses 1024 as the maximum buffer size internally. 57 constexpr size_t strerror_buff_size = 1024; 58 59 string do_strerror_r(int ev); 60 61 #if defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC) 62 // GNU Extended version 63 string do_strerror_r(int ev) { 64 char buffer[strerror_buff_size]; 65 char* ret = ::strerror_r(ev, buffer, strerror_buff_size); 66 return string(ret); 67 } 68 #else 69 // POSIX version 70 string do_strerror_r(int ev) { 71 char buffer[strerror_buff_size]; 72 const int old_errno = errno; 73 if (::strerror_r(ev, buffer, strerror_buff_size) == -1) { 74 const int new_errno = errno; 75 errno = old_errno; 76 if (new_errno == EINVAL) { 77 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev); 78 return string(buffer); 79 } else { 80 assert(new_errno == ERANGE); 81 // FIXME maybe? 'strerror_buff_size' is likely to exceed the 82 // maximum error size so ERANGE shouldn't be returned. 83 std::abort(); 84 } 85 } 86 return string(buffer); 87 } 88 #endif 89 90 } // end namespace 91 92 string 93 __do_message::message(int ev) const 94 { 95 #if defined(_LIBCPP_HAS_NO_THREADS) 96 return string(::strerror(ev)); 97 #else 98 return do_strerror_r(ev); 99 #endif 100 } 101 102 class _LIBCPP_HIDDEN __generic_error_category 103 : public __do_message 104 { 105 public: 106 virtual const char* name() const _NOEXCEPT; 107 virtual string message(int ev) const; 108 }; 109 110 const char* 111 __generic_error_category::name() const _NOEXCEPT 112 { 113 return "generic"; 114 } 115 116 string 117 __generic_error_category::message(int ev) const 118 { 119 #ifdef _LIBCPP_ELAST 120 if (ev > _LIBCPP_ELAST) 121 return string("unspecified generic_category error"); 122 #endif // _LIBCPP_ELAST 123 return __do_message::message(ev); 124 } 125 126 const error_category& 127 generic_category() _NOEXCEPT 128 { 129 static __generic_error_category s; 130 return s; 131 } 132 133 class _LIBCPP_HIDDEN __system_error_category 134 : public __do_message 135 { 136 public: 137 virtual const char* name() const _NOEXCEPT; 138 virtual string message(int ev) const; 139 virtual error_condition default_error_condition(int ev) const _NOEXCEPT; 140 }; 141 142 const char* 143 __system_error_category::name() const _NOEXCEPT 144 { 145 return "system"; 146 } 147 148 string 149 __system_error_category::message(int ev) const 150 { 151 #ifdef _LIBCPP_ELAST 152 if (ev > _LIBCPP_ELAST) 153 return string("unspecified system_category error"); 154 #endif // _LIBCPP_ELAST 155 return __do_message::message(ev); 156 } 157 158 error_condition 159 __system_error_category::default_error_condition(int ev) const _NOEXCEPT 160 { 161 #ifdef _LIBCPP_ELAST 162 if (ev > _LIBCPP_ELAST) 163 return error_condition(ev, system_category()); 164 #endif // _LIBCPP_ELAST 165 return error_condition(ev, generic_category()); 166 } 167 168 const error_category& 169 system_category() _NOEXCEPT 170 { 171 static __system_error_category s; 172 return s; 173 } 174 175 // error_condition 176 177 string 178 error_condition::message() const 179 { 180 return __cat_->message(__val_); 181 } 182 183 // error_code 184 185 string 186 error_code::message() const 187 { 188 return __cat_->message(__val_); 189 } 190 191 // system_error 192 193 string 194 system_error::__init(const error_code& ec, string what_arg) 195 { 196 if (ec) 197 { 198 if (!what_arg.empty()) 199 what_arg += ": "; 200 what_arg += ec.message(); 201 } 202 return what_arg; 203 } 204 205 system_error::system_error(error_code ec, const string& what_arg) 206 : runtime_error(__init(ec, what_arg)), 207 __ec_(ec) 208 { 209 } 210 211 system_error::system_error(error_code ec, const char* what_arg) 212 : runtime_error(__init(ec, what_arg)), 213 __ec_(ec) 214 { 215 } 216 217 system_error::system_error(error_code ec) 218 : runtime_error(__init(ec, "")), 219 __ec_(ec) 220 { 221 } 222 223 system_error::system_error(int ev, const error_category& ecat, const string& what_arg) 224 : runtime_error(__init(error_code(ev, ecat), what_arg)), 225 __ec_(error_code(ev, ecat)) 226 { 227 } 228 229 system_error::system_error(int ev, const error_category& ecat, const char* what_arg) 230 : runtime_error(__init(error_code(ev, ecat), what_arg)), 231 __ec_(error_code(ev, ecat)) 232 { 233 } 234 235 system_error::system_error(int ev, const error_category& ecat) 236 : runtime_error(__init(error_code(ev, ecat), "")), 237 __ec_(error_code(ev, ecat)) 238 { 239 } 240 241 system_error::~system_error() _NOEXCEPT 242 { 243 } 244 245 void 246 __throw_system_error(int ev, const char* what_arg) 247 { 248 #ifndef _LIBCPP_NO_EXCEPTIONS 249 throw system_error(error_code(ev, system_category()), what_arg); 250 #else 251 (void)ev; 252 (void)what_arg; 253 #endif 254 } 255 256 _LIBCPP_END_NAMESPACE_STD 257