1 //===----------------------------------------------------------------------===////
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===////
9 #ifndef FILESYSTEM_ERROR_H
10 #define FILESYSTEM_ERROR_H
20 #include <system_error>
21 #include <utility> // __libcpp_unreachable
23 #include "format_string.h"
25 #if defined(_LIBCPP_WIN32API)
26 # define WIN32_LEAN_AND_MEAN
28 # include <windows.h> // ERROR_* macros
31 _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
35 #if defined(_LIBCPP_WIN32API)
37 inline errc
__win_err_to_errc(int err
) {
41 } win_error_mapping
[] = {
42 {ERROR_ACCESS_DENIED
, errc::permission_denied
},
43 {ERROR_ALREADY_EXISTS
, errc::file_exists
},
44 {ERROR_BAD_NETPATH
, errc::no_such_file_or_directory
},
45 {ERROR_BAD_PATHNAME
, errc::no_such_file_or_directory
},
46 {ERROR_BAD_UNIT
, errc::no_such_device
},
47 {ERROR_BROKEN_PIPE
, errc::broken_pipe
},
48 {ERROR_BUFFER_OVERFLOW
, errc::filename_too_long
},
49 {ERROR_BUSY
, errc::device_or_resource_busy
},
50 {ERROR_BUSY_DRIVE
, errc::device_or_resource_busy
},
51 {ERROR_CANNOT_MAKE
, errc::permission_denied
},
52 {ERROR_CANTOPEN
, errc::io_error
},
53 {ERROR_CANTREAD
, errc::io_error
},
54 {ERROR_CANTWRITE
, errc::io_error
},
55 {ERROR_CURRENT_DIRECTORY
, errc::permission_denied
},
56 {ERROR_DEV_NOT_EXIST
, errc::no_such_device
},
57 {ERROR_DEVICE_IN_USE
, errc::device_or_resource_busy
},
58 {ERROR_DIR_NOT_EMPTY
, errc::directory_not_empty
},
59 {ERROR_DIRECTORY
, errc::invalid_argument
},
60 {ERROR_DISK_FULL
, errc::no_space_on_device
},
61 {ERROR_FILE_EXISTS
, errc::file_exists
},
62 {ERROR_FILE_NOT_FOUND
, errc::no_such_file_or_directory
},
63 {ERROR_HANDLE_DISK_FULL
, errc::no_space_on_device
},
64 {ERROR_INVALID_ACCESS
, errc::permission_denied
},
65 {ERROR_INVALID_DRIVE
, errc::no_such_device
},
66 {ERROR_INVALID_FUNCTION
, errc::function_not_supported
},
67 {ERROR_INVALID_HANDLE
, errc::invalid_argument
},
68 {ERROR_INVALID_NAME
, errc::no_such_file_or_directory
},
69 {ERROR_INVALID_PARAMETER
, errc::invalid_argument
},
70 {ERROR_LOCK_VIOLATION
, errc::no_lock_available
},
71 {ERROR_LOCKED
, errc::no_lock_available
},
72 {ERROR_NEGATIVE_SEEK
, errc::invalid_argument
},
73 {ERROR_NOACCESS
, errc::permission_denied
},
74 {ERROR_NOT_ENOUGH_MEMORY
, errc::not_enough_memory
},
75 {ERROR_NOT_READY
, errc::resource_unavailable_try_again
},
76 {ERROR_NOT_SAME_DEVICE
, errc::cross_device_link
},
77 {ERROR_NOT_SUPPORTED
, errc::not_supported
},
78 {ERROR_OPEN_FAILED
, errc::io_error
},
79 {ERROR_OPEN_FILES
, errc::device_or_resource_busy
},
80 {ERROR_OPERATION_ABORTED
, errc::operation_canceled
},
81 {ERROR_OUTOFMEMORY
, errc::not_enough_memory
},
82 {ERROR_PATH_NOT_FOUND
, errc::no_such_file_or_directory
},
83 {ERROR_READ_FAULT
, errc::io_error
},
84 {ERROR_REPARSE_TAG_INVALID
, errc::invalid_argument
},
85 {ERROR_RETRY
, errc::resource_unavailable_try_again
},
86 {ERROR_SEEK
, errc::io_error
},
87 {ERROR_SHARING_VIOLATION
, errc::permission_denied
},
88 {ERROR_TOO_MANY_OPEN_FILES
, errc::too_many_files_open
},
89 {ERROR_WRITE_FAULT
, errc::io_error
},
90 {ERROR_WRITE_PROTECT
, errc::permission_denied
},
93 for (const auto &pair
: win_error_mapping
)
94 if (pair
.win
== static_cast<DWORD
>(err
))
96 return errc::invalid_argument
;
99 #endif // _LIBCPP_WIN32API
101 inline error_code
capture_errno() {
102 _LIBCPP_ASSERT_UNCATEGORIZED(errno
!= 0, "Expected errno to be non-zero");
103 return error_code(errno
, generic_category());
106 #if defined(_LIBCPP_WIN32API)
107 inline error_code
make_windows_error(int err
) {
108 return make_error_code(__win_err_to_errc(err
));
115 inline constexpr void error_value
<void>() {}
117 inline bool error_value
<bool>() {
120 #if __SIZEOF_SIZE_T__ != __SIZEOF_LONG_LONG__
122 inline size_t error_value
<size_t>() {
127 inline uintmax_t error_value
<uintmax_t>() {
128 return uintmax_t(-1);
131 inline constexpr file_time_type error_value
<file_time_type
>() {
132 return file_time_type::min();
135 inline path error_value
<path
>() {
140 struct ErrorHandler
{
141 const char* func_name_
;
142 error_code
* ec_
= nullptr;
143 const path
* p1_
= nullptr;
144 const path
* p2_
= nullptr;
146 ErrorHandler(const char* fname
, error_code
* ec
, const path
* p1
= nullptr,
147 const path
* p2
= nullptr)
148 : func_name_(fname
), ec_(ec
), p1_(p1
), p2_(p2
) {
153 T
report(const error_code
& ec
) const {
156 return error_value
<T
>();
158 string what
= string("in ") + func_name_
;
159 switch (bool(p1_
) + bool(p2_
)) {
161 __throw_filesystem_error(what
, ec
);
163 __throw_filesystem_error(what
, *p1_
, ec
);
165 __throw_filesystem_error(what
, *p1_
, *p2_
, ec
);
167 __libcpp_unreachable();
170 _LIBCPP_ATTRIBUTE_FORMAT(__printf__
, 3, 0)
171 void report_impl(const error_code
& ec
, const char* msg
, va_list ap
) const {
177 string("in ") + func_name_
+ ": " + detail::vformat_string(msg
, ap
);
178 switch (bool(p1_
) + bool(p2_
)) {
180 __throw_filesystem_error(what
, ec
);
182 __throw_filesystem_error(what
, *p1_
, ec
);
184 __throw_filesystem_error(what
, *p1_
, *p2_
, ec
);
186 __libcpp_unreachable();
189 _LIBCPP_ATTRIBUTE_FORMAT(__printf__
, 3, 4)
190 T
report(const error_code
& ec
, const char* msg
, ...) const {
193 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
195 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
196 report_impl(ec
, msg
, ap
);
197 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
202 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
204 return error_value
<T
>();
207 T
report(errc
const& err
) const {
208 return report(make_error_code(err
));
211 _LIBCPP_ATTRIBUTE_FORMAT(__printf__
, 3, 4)
212 T
report(errc
const& err
, const char* msg
, ...) const {
215 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
217 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
218 report_impl(make_error_code(err
), msg
, ap
);
219 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
224 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
226 return error_value
<T
>();
230 ErrorHandler(ErrorHandler
const&) = delete;
231 ErrorHandler
& operator=(ErrorHandler
const&) = delete;
234 } // end namespace detail
236 _LIBCPP_END_NAMESPACE_FILESYSTEM
238 #endif // FILESYSTEM_ERROR_H