1// error_code support implementation file ----------------------------------// 2 3// Copyright Beman Dawes 2002, 2006 4// Copyright (c) Microsoft Corporation 2014 5// Distributed under the Boost Software License, Version 1.0. (See accompanying 6// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 8// See library home page at http://www.boost.org/libs/system 9 10//----------------------------------------------------------------------------// 11 12#include <boost/config/warning_disable.hpp> 13 14#include <boost/system/config.hpp> 15#include <boost/system/error_code.hpp> 16#include <boost/cerrno.hpp> 17#include <vector> 18#include <cstdlib> 19#include <cassert> 20 21#include <cstring> // for strerror/strerror_r 22 23# if defined( BOOST_WINDOWS_API ) 24# include <windows.h> 25# if !BOOST_PLAT_WINDOWS_RUNTIME 26# include <boost/system/detail/local_free_on_destruction.hpp> 27# endif 28# ifndef ERROR_INCORRECT_SIZE 29# define ERROR_INCORRECT_SIZE ERROR_BAD_ARGUMENTS 30# endif 31# endif 32 33//----------------------------------------------------------------------------// 34namespace boost 35{ 36 namespace system 37 { 38 39namespace 40{ 41 42 // standard error categories ---------------------------------------------// 43 44 class generic_error_category : public error_category 45 { 46 public: 47 generic_error_category(){} 48 const char * name() const BOOST_SYSTEM_NOEXCEPT; 49 std::string message( int ev ) const; 50 }; 51 52 class system_error_category : public error_category 53 { 54 public: 55 system_error_category(){} 56 const char * name() const BOOST_SYSTEM_NOEXCEPT; 57 std::string message( int ev ) const; 58 error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT; 59 }; 60 61 // generic_error_category implementation ---------------------------------// 62 63 const char * generic_error_category::name() const BOOST_SYSTEM_NOEXCEPT 64 { 65 return "generic"; 66 } 67 68 std::string generic_error_category::message( int ev ) const 69 { 70 using namespace boost::system::errc; 71#if defined(__PGI) 72 using boost::system::errc::invalid_argument; 73#endif 74 75 static std::string unknown_err( "Unknown error" ); 76 // strerror_r is preferred because it is always thread safe, 77 // however, we fallback to strerror in certain cases because: 78 // -- Windows doesn't provide strerror_r. 79 // -- HP and Sun do provide strerror_r on newer systems, but there is 80 // no way to tell if is available at runtime and in any case their 81 // versions of strerror are thread safe anyhow. 82 // -- Linux only sometimes provides strerror_r. 83 // -- Tru64 provides strerror_r only when compiled -pthread. 84 // -- VMS doesn't provide strerror_r, but on this platform, strerror is 85 // thread safe. 86 # if defined(BOOST_WINDOWS_API) || defined(__hpux) || defined(__sun)\ 87 || (defined(__linux) && (!defined(__USE_XOPEN2K) || defined(BOOST_SYSTEM_USE_STRERROR)))\ 88 || (defined(__osf__) && !defined(_REENTRANT))\ 89 || (defined(__INTEGRITY))\ 90 || (defined(__vms))\ 91 || (defined(__QNXNTO__)) 92 const char * c_str = std::strerror( ev ); 93 return c_str 94 ? std::string( c_str ) 95 : unknown_err; 96 # else // use strerror_r 97 char buf[64]; 98 char * bp = buf; 99 std::size_t sz = sizeof(buf); 100 # if defined(__CYGWIN__) || defined(__USE_GNU) 101 // Oddball version of strerror_r 102 const char * c_str = strerror_r( ev, bp, sz ); 103 return c_str 104 ? std::string( c_str ) 105 : unknown_err; 106 # else 107 // POSIX version of strerror_r 108 int result; 109 for (;;) 110 { 111 // strerror_r returns 0 on success, otherwise ERANGE if buffer too small, 112 // invalid_argument if ev not a valid error number 113 # if defined (__sgi) 114 const char * c_str = strerror( ev ); 115 result = 0; 116 return c_str 117 ? std::string( c_str ) 118 : unknown_err; 119 # else 120 result = strerror_r( ev, bp, sz ); 121 # endif 122 if (result == 0 ) 123 break; 124 else 125 { 126 # if defined(__linux) 127 // Linux strerror_r returns -1 on error, with error number in errno 128 result = errno; 129 # endif 130 if ( result != ERANGE ) break; 131 if ( sz > sizeof(buf) ) std::free( bp ); 132 sz *= 2; 133 if ( (bp = static_cast<char*>(std::malloc( sz ))) == 0 ) 134 return std::string( "ENOMEM" ); 135 } 136 } 137 std::string msg; 138# ifndef BOOST_NO_EXCEPTIONS 139 try 140# endif 141 { 142 msg = ( ( result == invalid_argument ) ? "Unknown error" : bp ); 143 } 144 145# ifndef BOOST_NO_EXCEPTIONS 146 // See ticket #2098 147 catch(...) 148 { 149 // just eat the exception 150 } 151# endif 152 153 if ( sz > sizeof(buf) ) std::free( bp ); 154 sz = 0; 155 return msg; 156 # endif // else POSIX version of strerror_r 157 # endif // else use strerror_r 158 } 159 // system_error_category implementation --------------------------------// 160 161 const char * system_error_category::name() const BOOST_SYSTEM_NOEXCEPT 162 { 163 return "system"; 164 } 165 166 error_condition system_error_category::default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT 167 { 168 using namespace boost::system::errc; 169#if defined(__PGI) 170 using boost::system::errc::invalid_argument; 171#endif 172 173# if defined(BOOST_WINDOWS_API) 174# if defined(WINAPI_FAMILY) && ((WINAPI_FAMILY & WINAPI_PARTITION_APP) != 0) 175 // When using the Windows Runtime, most system errors are reported as HRESULTs. 176 // We want to map the common Win32 errors to their equivalent error condition, 177 // whether or not they are reported via an HRESULT. 178 if ( ev < 0 ) // Check for failed HRESULTs only. 179 if ( HRESULT_FACILITY( ev ) == FACILITY_WIN32 ) 180 ev = HRESULT_CODE( ev ); 181# endif 182# endif 183 184 switch ( ev ) 185 { 186 case 0: return make_error_condition( success ); 187# if defined(BOOST_POSIX_API) 188 // POSIX-like O/S -> posix_errno decode table ---------------------------// 189 case E2BIG: return make_error_condition( argument_list_too_long ); 190 case EACCES: return make_error_condition( permission_denied ); 191 case EADDRINUSE: return make_error_condition( address_in_use ); 192 case EADDRNOTAVAIL: return make_error_condition( address_not_available ); 193 case EAFNOSUPPORT: return make_error_condition( address_family_not_supported ); 194 case EAGAIN: return make_error_condition( resource_unavailable_try_again ); 195# if EALREADY != EBUSY // EALREADY and EBUSY are the same on QNX Neutrino 196 case EALREADY: return make_error_condition( connection_already_in_progress ); 197# endif 198 case EBADF: return make_error_condition( bad_file_descriptor ); 199 case EBADMSG: return make_error_condition( bad_message ); 200 case EBUSY: return make_error_condition( device_or_resource_busy ); 201 case ECANCELED: return make_error_condition( operation_canceled ); 202 case ECHILD: return make_error_condition( no_child_process ); 203 case ECONNABORTED: return make_error_condition( connection_aborted ); 204 case ECONNREFUSED: return make_error_condition( connection_refused ); 205 case ECONNRESET: return make_error_condition( connection_reset ); 206 case EDEADLK: return make_error_condition( resource_deadlock_would_occur ); 207 case EDESTADDRREQ: return make_error_condition( destination_address_required ); 208 case EDOM: return make_error_condition( argument_out_of_domain ); 209 case EEXIST: return make_error_condition( file_exists ); 210 case EFAULT: return make_error_condition( bad_address ); 211 case EFBIG: return make_error_condition( file_too_large ); 212 case EHOSTUNREACH: return make_error_condition( host_unreachable ); 213 case EIDRM: return make_error_condition( identifier_removed ); 214 case EILSEQ: return make_error_condition( illegal_byte_sequence ); 215 case EINPROGRESS: return make_error_condition( operation_in_progress ); 216 case EINTR: return make_error_condition( interrupted ); 217 case EINVAL: return make_error_condition( invalid_argument ); 218 case EIO: return make_error_condition( io_error ); 219 case EISCONN: return make_error_condition( already_connected ); 220 case EISDIR: return make_error_condition( is_a_directory ); 221 case ELOOP: return make_error_condition( too_many_symbolic_link_levels ); 222 case EMFILE: return make_error_condition( too_many_files_open ); 223 case EMLINK: return make_error_condition( too_many_links ); 224 case EMSGSIZE: return make_error_condition( message_size ); 225 case ENAMETOOLONG: return make_error_condition( filename_too_long ); 226 case ENETDOWN: return make_error_condition( network_down ); 227 case ENETRESET: return make_error_condition( network_reset ); 228 case ENETUNREACH: return make_error_condition( network_unreachable ); 229 case ENFILE: return make_error_condition( too_many_files_open_in_system ); 230 case ENOBUFS: return make_error_condition( no_buffer_space ); 231 case ENODATA: return make_error_condition( no_message_available ); 232 case ENODEV: return make_error_condition( no_such_device ); 233 case ENOENT: return make_error_condition( no_such_file_or_directory ); 234 case ENOEXEC: return make_error_condition( executable_format_error ); 235 case ENOLCK: return make_error_condition( no_lock_available ); 236 case ENOLINK: return make_error_condition( no_link ); 237 case ENOMEM: return make_error_condition( not_enough_memory ); 238 case ENOMSG: return make_error_condition( no_message ); 239 case ENOPROTOOPT: return make_error_condition( no_protocol_option ); 240 case ENOSPC: return make_error_condition( no_space_on_device ); 241 case ENOSR: return make_error_condition( no_stream_resources ); 242 case ENOSTR: return make_error_condition( not_a_stream ); 243 case ENOSYS: return make_error_condition( function_not_supported ); 244 case ENOTCONN: return make_error_condition( not_connected ); 245 case ENOTDIR: return make_error_condition( not_a_directory ); 246 # if ENOTEMPTY != EEXIST // AIX treats ENOTEMPTY and EEXIST as the same value 247 case ENOTEMPTY: return make_error_condition( directory_not_empty ); 248 # endif // ENOTEMPTY != EEXIST 249 # if ENOTRECOVERABLE != ECONNRESET // the same on some Broadcom chips 250 case ENOTRECOVERABLE: return make_error_condition( state_not_recoverable ); 251 # endif // ENOTRECOVERABLE != ECONNRESET 252 case ENOTSOCK: return make_error_condition( not_a_socket ); 253 case ENOTSUP: return make_error_condition( not_supported ); 254 case ENOTTY: return make_error_condition( inappropriate_io_control_operation ); 255 case ENXIO: return make_error_condition( no_such_device_or_address ); 256 # if EOPNOTSUPP != ENOTSUP 257 case EOPNOTSUPP: return make_error_condition( operation_not_supported ); 258 # endif // EOPNOTSUPP != ENOTSUP 259 case EOVERFLOW: return make_error_condition( value_too_large ); 260 # if EOWNERDEAD != ECONNABORTED // the same on some Broadcom chips 261 case EOWNERDEAD: return make_error_condition( owner_dead ); 262 # endif // EOWNERDEAD != ECONNABORTED 263 case EPERM: return make_error_condition( operation_not_permitted ); 264 case EPIPE: return make_error_condition( broken_pipe ); 265 case EPROTO: return make_error_condition( protocol_error ); 266 case EPROTONOSUPPORT: return make_error_condition( protocol_not_supported ); 267 case EPROTOTYPE: return make_error_condition( wrong_protocol_type ); 268 case ERANGE: return make_error_condition( result_out_of_range ); 269 case EROFS: return make_error_condition( read_only_file_system ); 270 case ESPIPE: return make_error_condition( invalid_seek ); 271 case ESRCH: return make_error_condition( no_such_process ); 272 case ETIME: return make_error_condition( stream_timeout ); 273 case ETIMEDOUT: return make_error_condition( timed_out ); 274 case ETXTBSY: return make_error_condition( text_file_busy ); 275 # if EAGAIN != EWOULDBLOCK 276 case EWOULDBLOCK: return make_error_condition( operation_would_block ); 277 # endif // EAGAIN != EWOULDBLOCK 278 case EXDEV: return make_error_condition( cross_device_link ); 279 #else 280 // Windows system -> posix_errno decode table ---------------------------// 281 // see WinError.h comments for descriptions of errors 282 case ERROR_ACCESS_DENIED: return make_error_condition( permission_denied ); 283 case ERROR_ALREADY_EXISTS: return make_error_condition( file_exists ); 284 case ERROR_BAD_UNIT: return make_error_condition( no_such_device ); 285 case ERROR_BUFFER_OVERFLOW: return make_error_condition( filename_too_long ); 286 case ERROR_BUSY: return make_error_condition( device_or_resource_busy ); 287 case ERROR_BUSY_DRIVE: return make_error_condition( device_or_resource_busy ); 288 case ERROR_CANNOT_MAKE: return make_error_condition( permission_denied ); 289 case ERROR_CANTOPEN: return make_error_condition( io_error ); 290 case ERROR_CANTREAD: return make_error_condition( io_error ); 291 case ERROR_CANTWRITE: return make_error_condition( io_error ); 292 case ERROR_CURRENT_DIRECTORY: return make_error_condition( permission_denied ); 293 case ERROR_DEV_NOT_EXIST: return make_error_condition( no_such_device ); 294 case ERROR_DEVICE_IN_USE: return make_error_condition( device_or_resource_busy ); 295 case ERROR_DIR_NOT_EMPTY: return make_error_condition( directory_not_empty ); 296 case ERROR_DIRECTORY: return make_error_condition( invalid_argument ); // WinError.h: "The directory name is invalid" 297 case ERROR_DISK_FULL: return make_error_condition( no_space_on_device ); 298 case ERROR_FILE_EXISTS: return make_error_condition( file_exists ); 299 case ERROR_FILE_NOT_FOUND: return make_error_condition( no_such_file_or_directory ); 300 case ERROR_HANDLE_DISK_FULL: return make_error_condition( no_space_on_device ); 301 case ERROR_INVALID_ACCESS: return make_error_condition( permission_denied ); 302 case ERROR_INVALID_DRIVE: return make_error_condition( no_such_device ); 303 case ERROR_INVALID_FUNCTION: return make_error_condition( function_not_supported ); 304 case ERROR_INVALID_HANDLE: return make_error_condition( invalid_argument ); 305 case ERROR_INVALID_NAME: return make_error_condition( invalid_argument ); 306 case ERROR_LOCK_VIOLATION: return make_error_condition( no_lock_available ); 307 case ERROR_LOCKED: return make_error_condition( no_lock_available ); 308 case ERROR_NEGATIVE_SEEK: return make_error_condition( invalid_argument ); 309 case ERROR_NOACCESS: return make_error_condition( permission_denied ); 310 case ERROR_NOT_ENOUGH_MEMORY: return make_error_condition( not_enough_memory ); 311 case ERROR_NOT_READY: return make_error_condition( resource_unavailable_try_again ); 312 case ERROR_NOT_SAME_DEVICE: return make_error_condition( cross_device_link ); 313 case ERROR_OPEN_FAILED: return make_error_condition( io_error ); 314 case ERROR_OPEN_FILES: return make_error_condition( device_or_resource_busy ); 315 case ERROR_OPERATION_ABORTED: return make_error_condition( operation_canceled ); 316 case ERROR_OUTOFMEMORY: return make_error_condition( not_enough_memory ); 317 case ERROR_PATH_NOT_FOUND: return make_error_condition( no_such_file_or_directory ); 318 case ERROR_READ_FAULT: return make_error_condition( io_error ); 319 case ERROR_RETRY: return make_error_condition( resource_unavailable_try_again ); 320 case ERROR_SEEK: return make_error_condition( io_error ); 321 case ERROR_SHARING_VIOLATION: return make_error_condition( permission_denied ); 322 case ERROR_TOO_MANY_OPEN_FILES: return make_error_condition( too_many_files_open ); 323 case ERROR_WRITE_FAULT: return make_error_condition( io_error ); 324 case ERROR_WRITE_PROTECT: return make_error_condition( permission_denied ); 325 case WSAEACCES: return make_error_condition( permission_denied ); 326 case WSAEADDRINUSE: return make_error_condition( address_in_use ); 327 case WSAEADDRNOTAVAIL: return make_error_condition( address_not_available ); 328 case WSAEAFNOSUPPORT: return make_error_condition( address_family_not_supported ); 329 case WSAEALREADY: return make_error_condition( connection_already_in_progress ); 330 case WSAEBADF: return make_error_condition( bad_file_descriptor ); 331 case WSAECONNABORTED: return make_error_condition( connection_aborted ); 332 case WSAECONNREFUSED: return make_error_condition( connection_refused ); 333 case WSAECONNRESET: return make_error_condition( connection_reset ); 334 case WSAEDESTADDRREQ: return make_error_condition( destination_address_required ); 335 case WSAEFAULT: return make_error_condition( bad_address ); 336 case WSAEHOSTUNREACH: return make_error_condition( host_unreachable ); 337 case WSAEINPROGRESS: return make_error_condition( operation_in_progress ); 338 case WSAEINTR: return make_error_condition( interrupted ); 339 case WSAEINVAL: return make_error_condition( invalid_argument ); 340 case WSAEISCONN: return make_error_condition( already_connected ); 341 case WSAEMFILE: return make_error_condition( too_many_files_open ); 342 case WSAEMSGSIZE: return make_error_condition( message_size ); 343 case WSAENAMETOOLONG: return make_error_condition( filename_too_long ); 344 case WSAENETDOWN: return make_error_condition( network_down ); 345 case WSAENETRESET: return make_error_condition( network_reset ); 346 case WSAENETUNREACH: return make_error_condition( network_unreachable ); 347 case WSAENOBUFS: return make_error_condition( no_buffer_space ); 348 case WSAENOPROTOOPT: return make_error_condition( no_protocol_option ); 349 case WSAENOTCONN: return make_error_condition( not_connected ); 350 case WSAENOTSOCK: return make_error_condition( not_a_socket ); 351 case WSAEOPNOTSUPP: return make_error_condition( operation_not_supported ); 352 case WSAEPROTONOSUPPORT: return make_error_condition( protocol_not_supported ); 353 case WSAEPROTOTYPE: return make_error_condition( wrong_protocol_type ); 354 case WSAETIMEDOUT: return make_error_condition( timed_out ); 355 case WSAEWOULDBLOCK: return make_error_condition( operation_would_block ); 356 #endif 357 default: return error_condition( ev, system_category() ); 358 } 359 } 360 361# if !defined( BOOST_WINDOWS_API ) 362 363 std::string system_error_category::message( int ev ) const 364 { 365 return generic_category().message( ev ); 366 } 367# else 368 369 std::string system_error_category::message( int ev ) const 370 { 371#if defined(UNDER_CE) || BOOST_PLAT_WINDOWS_RUNTIME || defined(BOOST_NO_ANSI_APIS) 372 std::wstring buf(128, wchar_t()); 373 for (;;) 374 { 375 DWORD retval = ::FormatMessageW( 376 FORMAT_MESSAGE_FROM_SYSTEM | 377 FORMAT_MESSAGE_IGNORE_INSERTS, 378 NULL, 379 ev, 380 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 381 &buf[0], 382 buf.size(), 383 NULL 384 ); 385 386 if (retval > 0) 387 { 388 buf.resize(retval); 389 break; 390 } 391 else if ( ::GetLastError() != ERROR_INSUFFICIENT_BUFFER ) 392 { 393 return std::string("Unknown error"); 394 } 395 else 396 { 397 buf.resize(buf.size() + buf.size() / 2); 398 } 399 } 400 401 int num_chars = (buf.size() + 1) * 2; 402 LPSTR narrow_buffer = (LPSTR)_alloca( num_chars ); 403 if (::WideCharToMultiByte(CP_ACP, 0, buf.c_str(), -1, narrow_buffer, num_chars, NULL, NULL) == 0) 404 { 405 return std::string("Unknown error"); 406 } 407 408 std::string str( narrow_buffer ); 409#else 410 LPVOID lpMsgBuf = 0; 411 DWORD retval = ::FormatMessageA( 412 FORMAT_MESSAGE_ALLOCATE_BUFFER | 413 FORMAT_MESSAGE_FROM_SYSTEM | 414 FORMAT_MESSAGE_IGNORE_INSERTS, 415 NULL, 416 ev, 417 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 418 (LPSTR) &lpMsgBuf, 419 0, 420 NULL 421 ); 422 detail::local_free_on_destruction lfod(lpMsgBuf); 423 if (retval == 0) 424 return std::string("Unknown error"); 425 426 std::string str( static_cast<LPCSTR>(lpMsgBuf) ); 427# endif 428 while ( str.size() 429 && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') ) 430 str.erase( str.size()-1 ); 431 if ( str.size() && str[str.size()-1] == '.' ) 432 { str.erase( str.size()-1 ); } 433 return str; 434 } 435# endif 436 437} // unnamed namespace 438 439 440# ifndef BOOST_SYSTEM_NO_DEPRECATED 441 BOOST_SYSTEM_DECL error_code throws; // "throw on error" special error_code; 442 // note that it doesn't matter if this 443 // isn't initialized before use since 444 // the only use is to take its 445 // address for comparison purposes 446# endif 447 448# ifdef BOOST_ERROR_CODE_HEADER_ONLY 449# define BOOST_SYSTEM_LINKAGE inline 450# else 451# define BOOST_SYSTEM_LINKAGE BOOST_SYSTEM_DECL 452# endif 453 454 BOOST_SYSTEM_LINKAGE const error_category & system_category() BOOST_SYSTEM_NOEXCEPT 455 { 456 static const system_error_category system_category_const; 457 return system_category_const; 458 } 459 460 BOOST_SYSTEM_LINKAGE const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT 461 { 462 static const generic_error_category generic_category_const; 463 return generic_category_const; 464 } 465 466 } // namespace system 467} // namespace boost 468