1 | // error_handling.hpp --------------------------------------------------------------------// |
2 | |
3 | // Copyright 2002-2009, 2014 Beman Dawes |
4 | // Copyright 2019 Andrey Semashev |
5 | |
6 | // Distributed under the Boost Software License, Version 1.0. |
7 | // See 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 | #ifndef BOOST_FILESYSTEM_SRC_ERROR_HANDLING_HPP_ |
14 | #define BOOST_FILESYSTEM_SRC_ERROR_HANDLING_HPP_ |
15 | |
16 | #include <cerrno> |
17 | #include <boost/system/error_code.hpp> |
18 | #include <boost/filesystem/config.hpp> |
19 | #include <boost/filesystem/exception.hpp> |
20 | |
21 | #if defined(BOOST_WINDOWS_API) |
22 | #include <boost/winapi/basic_types.hpp> |
23 | #include <boost/winapi/get_last_error.hpp> |
24 | #include <boost/winapi/error_codes.hpp> |
25 | #endif |
26 | |
27 | #include <boost/filesystem/detail/header.hpp> // must be the last #include |
28 | |
29 | namespace boost { |
30 | namespace filesystem { |
31 | |
32 | #if defined(BOOST_POSIX_API) |
33 | |
34 | typedef int err_t; |
35 | |
36 | // POSIX uses a 0 return to indicate success |
37 | #define BOOST_ERRNO errno |
38 | |
39 | #define BOOST_ERROR_FILE_NOT_FOUND ENOENT |
40 | #define BOOST_ERROR_ALREADY_EXISTS EEXIST |
41 | #define BOOST_ERROR_NOT_SUPPORTED ENOSYS |
42 | |
43 | #else |
44 | |
45 | typedef boost::winapi::DWORD_ err_t; |
46 | |
47 | // Windows uses a non-0 return to indicate success |
48 | #define BOOST_ERRNO boost::winapi::GetLastError() |
49 | |
50 | #define BOOST_ERROR_FILE_NOT_FOUND boost::winapi::ERROR_FILE_NOT_FOUND_ |
51 | #define BOOST_ERROR_ALREADY_EXISTS boost::winapi::ERROR_ALREADY_EXISTS_ |
52 | #define BOOST_ERROR_NOT_SUPPORTED boost::winapi::ERROR_NOT_SUPPORTED_ |
53 | |
54 | // Note: Legacy MinGW doesn't have ntstatus.h and doesn't define NTSTATUS error codes other than STATUS_SUCCESS. |
55 | #if !defined(NT_SUCCESS) |
56 | #define NT_SUCCESS(Status) (((boost::winapi::NTSTATUS_)(Status)) >= 0) |
57 | #endif |
58 | #if !defined(STATUS_SUCCESS) |
59 | #define STATUS_SUCCESS ((boost::winapi::NTSTATUS_)0x00000000l) |
60 | #endif |
61 | #if !defined(STATUS_NOT_IMPLEMENTED) |
62 | #define STATUS_NOT_IMPLEMENTED ((boost::winapi::NTSTATUS_)0xC0000002l) |
63 | #endif |
64 | #if !defined(STATUS_INVALID_INFO_CLASS) |
65 | #define STATUS_INVALID_INFO_CLASS ((boost::winapi::NTSTATUS_)0xC0000003l) |
66 | #endif |
67 | #if !defined(STATUS_INVALID_HANDLE) |
68 | #define STATUS_INVALID_HANDLE ((boost::winapi::NTSTATUS_)0xC0000008l) |
69 | #endif |
70 | #if !defined(STATUS_INVALID_PARAMETER) |
71 | #define STATUS_INVALID_PARAMETER ((boost::winapi::NTSTATUS_)0xC000000Dl) |
72 | #endif |
73 | #if !defined(STATUS_NO_SUCH_DEVICE) |
74 | #define STATUS_NO_SUCH_DEVICE ((boost::winapi::NTSTATUS_)0xC000000El) |
75 | #endif |
76 | #if !defined(STATUS_NO_SUCH_FILE) |
77 | #define STATUS_NO_SUCH_FILE ((boost::winapi::NTSTATUS_)0xC000000Fl) |
78 | #endif |
79 | #if !defined(STATUS_NO_MORE_FILES) |
80 | #define STATUS_NO_MORE_FILES ((boost::winapi::NTSTATUS_)0x80000006l) |
81 | #endif |
82 | #if !defined(STATUS_BUFFER_OVERFLOW) |
83 | #define STATUS_BUFFER_OVERFLOW ((boost::winapi::NTSTATUS_)0x80000005l) |
84 | #endif |
85 | #if !defined(STATUS_NO_MEMORY) |
86 | #define STATUS_NO_MEMORY ((boost::winapi::NTSTATUS_)0xC0000017l) |
87 | #endif |
88 | #if !defined(STATUS_ACCESS_DENIED) |
89 | #define STATUS_ACCESS_DENIED ((boost::winapi::NTSTATUS_)0xC0000022l) |
90 | #endif |
91 | #if !defined(STATUS_OBJECT_NAME_NOT_FOUND) |
92 | #define STATUS_OBJECT_NAME_NOT_FOUND ((boost::winapi::NTSTATUS_)0xC0000034l) |
93 | #endif |
94 | #if !defined(STATUS_OBJECT_PATH_NOT_FOUND) |
95 | #define STATUS_OBJECT_PATH_NOT_FOUND ((boost::winapi::NTSTATUS_)0xC000003Al) |
96 | #endif |
97 | #if !defined(STATUS_SHARING_VIOLATION) |
98 | #define STATUS_SHARING_VIOLATION ((boost::winapi::NTSTATUS_)0xC0000043l) |
99 | #endif |
100 | #if !defined(STATUS_EAS_NOT_SUPPORTED) |
101 | #define STATUS_EAS_NOT_SUPPORTED ((boost::winapi::NTSTATUS_)0xC000004Fl) |
102 | #endif |
103 | #if !defined(STATUS_NOT_SUPPORTED) |
104 | #define STATUS_NOT_SUPPORTED ((boost::winapi::NTSTATUS_)0xC00000BBl) |
105 | #endif |
106 | #if !defined(STATUS_BAD_NETWORK_PATH) |
107 | #define STATUS_BAD_NETWORK_PATH ((boost::winapi::NTSTATUS_)0xC00000BEl) |
108 | #endif |
109 | #if !defined(STATUS_DEVICE_DOES_NOT_EXIST) |
110 | #define STATUS_DEVICE_DOES_NOT_EXIST ((boost::winapi::NTSTATUS_)0xC00000C0l) |
111 | #endif |
112 | #if !defined(STATUS_BAD_NETWORK_NAME) |
113 | #define STATUS_BAD_NETWORK_NAME ((boost::winapi::NTSTATUS_)0xC00000CCl) |
114 | #endif |
115 | #if !defined(STATUS_DIRECTORY_NOT_EMPTY) |
116 | #define STATUS_DIRECTORY_NOT_EMPTY ((boost::winapi::NTSTATUS_)0xC0000101l) |
117 | #endif |
118 | #if !defined(STATUS_NOT_A_DIRECTORY) |
119 | #define STATUS_NOT_A_DIRECTORY ((boost::winapi::NTSTATUS_)0xC0000103l) |
120 | #endif |
121 | #if !defined(STATUS_NOT_FOUND) |
122 | #define STATUS_NOT_FOUND ((boost::winapi::NTSTATUS_)0xC0000225l) |
123 | #endif |
124 | |
125 | //! Converts NTSTATUS error codes to Win32 error codes for reporting |
126 | inline boost::winapi::DWORD_ translate_ntstatus(boost::winapi::NTSTATUS_ status) noexcept |
127 | { |
128 | // We have to cast to unsigned integral type to avoid signed overflow and narrowing conversion in the constants. |
129 | switch (static_cast< boost::winapi::ULONG_ >(status)) |
130 | { |
131 | case static_cast< boost::winapi::ULONG_ >(STATUS_NO_MEMORY): |
132 | return boost::winapi::ERROR_OUTOFMEMORY_; |
133 | case static_cast< boost::winapi::ULONG_ >(STATUS_BUFFER_OVERFLOW): |
134 | return boost::winapi::ERROR_BUFFER_OVERFLOW_; |
135 | case static_cast< boost::winapi::ULONG_ >(STATUS_INVALID_HANDLE): |
136 | return boost::winapi::ERROR_INVALID_HANDLE_; |
137 | case static_cast< boost::winapi::ULONG_ >(STATUS_INVALID_PARAMETER): |
138 | return boost::winapi::ERROR_INVALID_PARAMETER_; |
139 | case static_cast< boost::winapi::ULONG_ >(STATUS_NO_MORE_FILES): |
140 | return boost::winapi::ERROR_NO_MORE_FILES_; |
141 | case static_cast< boost::winapi::ULONG_ >(STATUS_NO_SUCH_DEVICE): |
142 | case static_cast< boost::winapi::ULONG_ >(STATUS_DEVICE_DOES_NOT_EXIST): |
143 | return boost::winapi::ERROR_DEV_NOT_EXIST_; |
144 | case static_cast< boost::winapi::ULONG_ >(STATUS_NO_SUCH_FILE): |
145 | case static_cast< boost::winapi::ULONG_ >(STATUS_OBJECT_NAME_NOT_FOUND): |
146 | case static_cast< boost::winapi::ULONG_ >(STATUS_OBJECT_PATH_NOT_FOUND): |
147 | return boost::winapi::ERROR_FILE_NOT_FOUND_; |
148 | case static_cast< boost::winapi::ULONG_ >(STATUS_SHARING_VIOLATION): |
149 | return boost::winapi::ERROR_SHARING_VIOLATION_; |
150 | case static_cast< boost::winapi::ULONG_ >(STATUS_EAS_NOT_SUPPORTED): |
151 | return boost::winapi::ERROR_EAS_NOT_SUPPORTED_; |
152 | case static_cast< boost::winapi::ULONG_ >(STATUS_ACCESS_DENIED): |
153 | return boost::winapi::ERROR_ACCESS_DENIED_; |
154 | case static_cast< boost::winapi::ULONG_ >(STATUS_BAD_NETWORK_PATH): |
155 | return boost::winapi::ERROR_BAD_NETPATH_; |
156 | case static_cast< boost::winapi::ULONG_ >(STATUS_BAD_NETWORK_NAME): |
157 | return boost::winapi::ERROR_BAD_NET_NAME_; |
158 | case static_cast< boost::winapi::ULONG_ >(STATUS_DIRECTORY_NOT_EMPTY): |
159 | return boost::winapi::ERROR_DIR_NOT_EMPTY_; |
160 | case static_cast< boost::winapi::ULONG_ >(STATUS_NOT_A_DIRECTORY): |
161 | return boost::winapi::ERROR_DIRECTORY_; // The directory name is invalid |
162 | case static_cast< boost::winapi::ULONG_ >(STATUS_NOT_FOUND): |
163 | return boost::winapi::ERROR_NOT_FOUND_; |
164 | // map "invalid info class" to "not supported" as this error likely indicates that the kernel does not support what we request |
165 | case static_cast< boost::winapi::ULONG_ >(STATUS_INVALID_INFO_CLASS): |
166 | default: |
167 | return boost::winapi::ERROR_NOT_SUPPORTED_; |
168 | } |
169 | } |
170 | |
171 | //! Tests if the NTSTATUS indicates that the file is not found |
172 | inline bool not_found_ntstatus(boost::winapi::NTSTATUS_ status) noexcept |
173 | { |
174 | return status == STATUS_NO_SUCH_FILE || status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND || |
175 | status == STATUS_BAD_NETWORK_PATH || status == STATUS_BAD_NETWORK_NAME; |
176 | } |
177 | |
178 | #endif |
179 | |
180 | // error handling helpers ----------------------------------------------------------// |
181 | |
182 | // Implemented in exception.cpp |
183 | void emit_error(err_t error_num, system::error_code* ec, const char* message); |
184 | void emit_error(err_t error_num, path const& p, system::error_code* ec, const char* message); |
185 | void emit_error(err_t error_num, path const& p1, path const& p2, system::error_code* ec, const char* message); |
186 | |
187 | inline bool error(err_t error_num, system::error_code* ec, const char* message) |
188 | { |
189 | if (BOOST_LIKELY(!error_num)) |
190 | { |
191 | if (ec) |
192 | ec->clear(); |
193 | return false; |
194 | } |
195 | else |
196 | { // error |
197 | filesystem::emit_error(error_num, ec, message); |
198 | return true; |
199 | } |
200 | } |
201 | |
202 | inline bool error(err_t error_num, path const& p, system::error_code* ec, const char* message) |
203 | { |
204 | if (BOOST_LIKELY(!error_num)) |
205 | { |
206 | if (ec) |
207 | ec->clear(); |
208 | return false; |
209 | } |
210 | else |
211 | { // error |
212 | filesystem::emit_error(error_num, p, ec, message); |
213 | return true; |
214 | } |
215 | } |
216 | |
217 | inline bool error(err_t error_num, path const& p1, path const& p2, system::error_code* ec, const char* message) |
218 | { |
219 | if (BOOST_LIKELY(!error_num)) |
220 | { |
221 | if (ec) |
222 | ec->clear(); |
223 | return false; |
224 | } |
225 | else |
226 | { // error |
227 | filesystem::emit_error(error_num, p1, p2, ec, message); |
228 | return true; |
229 | } |
230 | } |
231 | |
232 | } // namespace filesystem |
233 | } // namespace boost |
234 | |
235 | #include <boost/filesystem/detail/footer.hpp> |
236 | |
237 | #endif // BOOST_FILESYSTEM_SRC_ERROR_HANDLING_HPP_ |
238 | |