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