]> git.lyx.org Git - lyx.git/blob - boost/libs/filesystem/src/exception.cpp
update to boost 1.32.0
[lyx.git] / boost / libs / filesystem / src / exception.cpp
1 //  Exception implementation file  -------------------------------------------//
2
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)
8
9 //  See library home page at http://www.boost.org/libs/filesystem
10
11 //----------------------------------------------------------------------------//
12
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 
16
17 #include <boost/filesystem/config.hpp>
18 #include <boost/filesystem/exception.hpp>
19
20 namespace fs = boost::filesystem;
21
22 #include <cstring> // SGI MIPSpro compilers need this
23 #include <string>
24
25 # ifdef BOOST_NO_STDC_NAMESPACE
26     namespace std { using ::strerror; }
27 # endif
28
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
33 #   else
34 #     define BOOST_POSIX
35 #   endif
36 # endif
37
38 # if defined( BOOST_WINDOWS )
39 #   include "windows.h"
40 # else
41 #   include <errno.h> // for POSIX error codes
42 # endif
43
44 #include <boost/config/abi_prefix.hpp> // must be the last header
45
46 //----------------------------------------------------------------------------//
47
48 namespace
49 {
50 # ifdef BOOST_WINDOWS
51   std::string system_message( int sys_err_code )
52   {
53     std::string str;
54     LPVOID lpMsgBuf;
55     ::FormatMessageA( 
56         FORMAT_MESSAGE_ALLOCATE_BUFFER | 
57         FORMAT_MESSAGE_FROM_SYSTEM | 
58         FORMAT_MESSAGE_IGNORE_INSERTS,
59         NULL,
60         sys_err_code,
61         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
62         (LPSTR) &lpMsgBuf,
63         0,
64         NULL 
65     );
66     str += static_cast<LPCSTR>(lpMsgBuf);
67     ::LocalFree( lpMsgBuf ); // free the buffer
68     while ( str.size()
69       && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') )
70         str.erase( str.size()-1 );
71     return str;
72   }
73 # else
74   std::string system_message( int )
75   {
76     std::string str;
77     str += std::strerror( errno );
78     return str;
79   }
80 # endif
81
82   struct ec_xlate { int sys_ec; fs::error_code ec; };
83   const ec_xlate ec_table[] =
84   {
85 #     ifdef BOOST_WINDOWS
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 }
117 #     else
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 }
133 #     endif
134   };
135
136   fs::error_code lookup_error( int sys_err_code )
137   {
138     for ( const ec_xlate * cur = &ec_table[0];
139       cur != ec_table
140         + sizeof(ec_table)/sizeof(ec_xlate); ++cur )
141     {
142       if ( sys_err_code == cur->sys_ec ) return cur->ec;
143     }
144     return fs::system_error; // general system error code
145   }
146
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.
150
151   std::string other_error_prep(
152     const std::string & who,
153     const std::string & message )
154   {
155     return who + ": " + message;
156   }
157
158   std::string other_error_prep(
159     const std::string & who,
160     const fs::path & path1,
161     const std::string & message )
162   {
163     return who + ": \"" + path1.native_file_string() + "\": " + message;
164   }
165
166   std::string system_error_prep(
167     const std::string & who,
168     const fs::path & path1,
169     int sys_err_code )
170   {
171     return who + ": \"" + path1.native_file_string() + "\": "
172       + system_message( sys_err_code );
173   }
174
175   std::string system_error_prep(
176     const std::string & who,
177     const fs::path & path1,
178     const fs::path & path2,
179     int sys_err_code )
180   {
181     return who + ": \"" + path1.native_file_string()
182       + "\", \"" + path2.native_file_string() + "\": "
183       + system_message( sys_err_code );
184   }
185
186   const fs::path empty_path;
187   const std::string empty_string;
188 } // unnamed namespace
189
190 namespace boost
191 {
192   namespace filesystem
193   {
194 //  filesystem_error m_imp class  --------------------------------------------//
195 //  see www.boost.org/more/error_handling.html for implementation rationale
196
197     class filesystem_error::m_imp
198     {
199     public:
200       std::string     m_who;
201       path            m_path1;
202       path            m_path2;
203       std::string     m_what;
204     };
205
206
207 //  filesystem_error implementation  -----------------------------------------//
208
209     filesystem_error::filesystem_error(
210       const std::string & who,
211       const std::string & message )
212       : m_sys_err(0), m_err(other_error)
213     {
214       try
215       {
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 );
219       }
220       catch (...) { m_imp_ptr.reset(); }
221     }
222  
223     filesystem_error::filesystem_error(
224       const std::string & who,
225       const path & path1,
226       const std::string & message,
227       error_code ec )
228       : m_sys_err(0), m_err(ec)
229     {
230       try
231       {
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;
236       }
237       catch (...) { m_imp_ptr.reset(); }
238     }
239  
240     filesystem_error::filesystem_error(
241       const std::string & who,
242       const path & path1,
243       int sys_err_code )
244       : m_sys_err(sys_err_code), m_err(lookup_error(sys_err_code))
245     {
246       try
247       {
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;
252       }
253       catch (...) { m_imp_ptr.reset(); }
254     }
255
256     filesystem_error::filesystem_error(
257       const std::string & who,
258       const path & path1,
259       const path & path2,
260       int sys_err_code )
261       : m_sys_err(sys_err_code), m_err(lookup_error(sys_err_code))
262     {
263       try
264       {
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;
270       }
271       catch (...) { m_imp_ptr.reset(); }
272     }
273
274     filesystem_error::~filesystem_error() throw()
275     {
276     }
277
278     const std::string & filesystem_error::who() const
279     {
280       return m_imp_ptr.get() == 0 ? empty_string : m_imp_ptr->m_who;
281     }
282
283     const path & filesystem_error::path1() const
284     {
285       return m_imp_ptr.get() == 0 ? empty_path : m_imp_ptr->m_path1;
286     }
287
288     const path & filesystem_error::path2() const
289     {
290       return m_imp_ptr.get() == 0 ? empty_path : m_imp_ptr->m_path2;
291     }
292
293     const char * filesystem_error::what() const throw()
294     {
295       return m_imp_ptr.get() == 0 ? empty_string.c_str()
296                                   : m_imp_ptr->m_what.c_str();
297     }
298
299     namespace detail
300     {
301       BOOST_FILESYSTEM_DECL int system_error_code() // artifact of POSIX and WINDOWS error reporting
302       {
303   #   ifdef BOOST_WINDOWS
304         return ::GetLastError();
305   #   else
306         return errno; // GCC 3.1 won't accept ::errno
307   #   endif
308       }
309     } // namespace detail
310   } // namespace filesystem
311 } // namespace boost
312