1 // Exception implementation file -------------------------------------------//
3 // Copyright © 2002 Beman Dawes
4 // Copyright © 2001 Dietmar Kühl
5 // Use, modification, and distribution is subject to the Boost Software
6 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
7 // at http://www.boost.org/LICENSE_1_0.txt)
9 // See library home page at http://www.boost.org/libs/filesystem
11 //----------------------------------------------------------------------------//
13 // define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows
14 // the library is being built (possibly exporting rather than importing code)
15 #define BOOST_FILESYSTEM_SOURCE
17 #include <boost/filesystem/config.hpp>
18 #include <boost/filesystem/exception.hpp>
20 namespace fs = boost::filesystem;
22 #include <cstring> // SGI MIPSpro compilers need this
25 # ifdef BOOST_NO_STDC_NAMESPACE
26 namespace std { using ::strerror; }
29 // BOOST_POSIX or BOOST_WINDOWS specify which API to use.
30 # if !defined( BOOST_WINDOWS ) && !defined( BOOST_POSIX )
31 # if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)
32 # define BOOST_WINDOWS
38 # if defined( BOOST_WINDOWS )
41 # include <errno.h> // for POSIX error codes
44 #include <boost/config/abi_prefix.hpp> // must be the last header
46 //----------------------------------------------------------------------------//
51 std::string system_message( int sys_err_code )
56 FORMAT_MESSAGE_ALLOCATE_BUFFER |
57 FORMAT_MESSAGE_FROM_SYSTEM |
58 FORMAT_MESSAGE_IGNORE_INSERTS,
61 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
66 str += static_cast<LPCSTR>(lpMsgBuf);
67 ::LocalFree( lpMsgBuf ); // free the buffer
69 && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') )
70 str.erase( str.size()-1 );
74 std::string system_message( int )
77 str += std::strerror( errno );
82 struct ec_xlate { int sys_ec; fs::error_code ec; };
83 const ec_xlate ec_table[] =
86 { ERROR_ACCESS_DENIED, fs::security_error },
87 { ERROR_INVALID_ACCESS, fs::security_error },
88 { ERROR_SHARING_VIOLATION, fs::security_error },
89 { ERROR_LOCK_VIOLATION, fs::security_error },
90 { ERROR_LOCKED, fs::security_error },
91 { ERROR_NOACCESS, fs::security_error },
92 { ERROR_WRITE_PROTECT, fs::read_only_error },
93 { ERROR_NOT_READY, fs::io_error },
94 { ERROR_SEEK, fs::io_error },
95 { ERROR_READ_FAULT, fs::io_error },
96 { ERROR_WRITE_FAULT, fs::io_error },
97 { ERROR_CANTOPEN, fs::io_error },
98 { ERROR_CANTREAD, fs::io_error },
99 { ERROR_CANTWRITE, fs::io_error },
100 { ERROR_DIRECTORY, fs::path_error },
101 { ERROR_INVALID_NAME, fs::path_error },
102 { ERROR_FILE_NOT_FOUND, fs::not_found_error },
103 { ERROR_PATH_NOT_FOUND, fs::not_found_error },
104 { ERROR_DEV_NOT_EXIST, fs::not_found_error },
105 { ERROR_DEVICE_IN_USE, fs::busy_error },
106 { ERROR_OPEN_FILES, fs::busy_error },
107 { ERROR_BUSY_DRIVE, fs::busy_error },
108 { ERROR_BUSY, fs::busy_error },
109 { ERROR_FILE_EXISTS, fs::already_exists_error },
110 { ERROR_ALREADY_EXISTS, fs::already_exists_error },
111 { ERROR_DIR_NOT_EMPTY, fs::not_empty_error },
112 { ERROR_HANDLE_DISK_FULL, fs::out_of_space_error },
113 { ERROR_DISK_FULL, fs::out_of_space_error },
114 { ERROR_OUTOFMEMORY, fs::out_of_memory_error },
115 { ERROR_NOT_ENOUGH_MEMORY, fs::out_of_memory_error },
116 { ERROR_TOO_MANY_OPEN_FILES, fs::out_of_resource_error }
118 { EACCES, fs::security_error },
119 { EROFS, fs::read_only_error },
120 { EIO, fs::io_error },
121 { ENAMETOOLONG, fs::path_error },
122 { ENOENT, fs::not_found_error },
123 { ENOTDIR, fs::not_directory_error },
124 { EAGAIN, fs::busy_error },
125 { EBUSY, fs::busy_error },
126 { ETXTBSY, fs::busy_error },
127 { EEXIST, fs::already_exists_error },
128 { ENOTEMPTY, fs::not_empty_error },
129 { EISDIR, fs::is_directory_error },
130 { ENOSPC, fs::out_of_space_error },
131 { ENOMEM, fs::out_of_memory_error },
132 { EMFILE, fs::out_of_resource_error }
136 fs::error_code lookup_error( int sys_err_code )
138 for ( const ec_xlate * cur = &ec_table[0];
140 + sizeof(ec_table)/sizeof(ec_xlate); ++cur )
142 if ( sys_err_code == cur->sys_ec ) return cur->ec;
144 return fs::system_error; // general system error code
147 // These helper functions work for POSIX and Windows. For systems where
148 // path->native_file_string() != path->native_directory_string(), more
149 // care would be required to get the right form for the function involved.
151 std::string other_error_prep(
152 const std::string & who,
153 const std::string & message )
155 return who + ": " + message;
158 std::string other_error_prep(
159 const std::string & who,
160 const fs::path & path1,
161 const std::string & message )
163 return who + ": \"" + path1.native_file_string() + "\": " + message;
166 std::string system_error_prep(
167 const std::string & who,
168 const fs::path & path1,
171 return who + ": \"" + path1.native_file_string() + "\": "
172 + system_message( sys_err_code );
175 std::string system_error_prep(
176 const std::string & who,
177 const fs::path & path1,
178 const fs::path & path2,
181 return who + ": \"" + path1.native_file_string()
182 + "\", \"" + path2.native_file_string() + "\": "
183 + system_message( sys_err_code );
186 const fs::path empty_path;
187 const std::string empty_string;
188 } // unnamed namespace
194 // filesystem_error m_imp class --------------------------------------------//
195 // see www.boost.org/more/error_handling.html for implementation rationale
197 class filesystem_error::m_imp
207 // filesystem_error implementation -----------------------------------------//
209 filesystem_error::filesystem_error(
210 const std::string & who,
211 const std::string & message )
212 : m_sys_err(0), m_err(other_error)
216 m_imp_ptr.reset( new m_imp );
217 m_imp_ptr->m_who = who;
218 m_imp_ptr->m_what = other_error_prep( who, message );
220 catch (...) { m_imp_ptr.reset(); }
223 filesystem_error::filesystem_error(
224 const std::string & who,
226 const std::string & message,
228 : m_sys_err(0), m_err(ec)
232 m_imp_ptr.reset( new m_imp );
233 m_imp_ptr->m_who = who;
234 m_imp_ptr->m_what = other_error_prep( who, path1, message );
235 m_imp_ptr->m_path1 = path1;
237 catch (...) { m_imp_ptr.reset(); }
240 filesystem_error::filesystem_error(
241 const std::string & who,
244 : m_sys_err(sys_err_code), m_err(lookup_error(sys_err_code))
248 m_imp_ptr.reset( new m_imp );
249 m_imp_ptr->m_who = who;
250 m_imp_ptr->m_what = system_error_prep( who, path1, sys_err_code );
251 m_imp_ptr->m_path1 = path1;
253 catch (...) { m_imp_ptr.reset(); }
256 filesystem_error::filesystem_error(
257 const std::string & who,
261 : m_sys_err(sys_err_code), m_err(lookup_error(sys_err_code))
265 m_imp_ptr.reset( new m_imp );
266 m_imp_ptr->m_who = who;
267 m_imp_ptr->m_what = system_error_prep( who, path1, path2, sys_err_code );
268 m_imp_ptr->m_path1 = path1;
269 m_imp_ptr->m_path2 = path2;
271 catch (...) { m_imp_ptr.reset(); }
274 filesystem_error::~filesystem_error() throw()
278 const std::string & filesystem_error::who() const
280 return m_imp_ptr.get() == 0 ? empty_string : m_imp_ptr->m_who;
283 const path & filesystem_error::path1() const
285 return m_imp_ptr.get() == 0 ? empty_path : m_imp_ptr->m_path1;
288 const path & filesystem_error::path2() const
290 return m_imp_ptr.get() == 0 ? empty_path : m_imp_ptr->m_path2;
293 const char * filesystem_error::what() const throw()
295 return m_imp_ptr.get() == 0 ? empty_string.c_str()
296 : m_imp_ptr->m_what.c_str();
301 BOOST_FILESYSTEM_DECL int system_error_code() // artifact of POSIX and WINDOWS error reporting
303 # ifdef BOOST_WINDOWS
304 return ::GetLastError();
306 return errno; // GCC 3.1 won't accept ::errno
309 } // namespace detail
310 } // namespace filesystem