diff --git a/libcxx/src/filesystem/directory_iterator.cpp b/libcxx/src/filesystem/directory_iterator.cpp --- a/libcxx/src/filesystem/directory_iterator.cpp +++ b/libcxx/src/filesystem/directory_iterator.cpp @@ -12,6 +12,7 @@ #include #include +#include "error.h" #include "filesystem_common.h" _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM diff --git a/libcxx/src/filesystem/error.h b/libcxx/src/filesystem/error.h new file mode 100644 --- /dev/null +++ b/libcxx/src/filesystem/error.h @@ -0,0 +1,240 @@ +//===----------------------------------------------------------------------===//// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===//// + +#ifndef FILESYSTEM_ERROR_H +#define FILESYSTEM_ERROR_H + +#include <__assert> +#include <__utility/unreachable.h> +#include +#include +#include +#include +#include +#include + +#include "format_string.h" + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include // ERROR_* macros +#endif + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +namespace detail { + +#if defined(_LIBCPP_WIN32API) + +inline _LIBCPP_HIDE_FROM_ABI +errc __win_err_to_errc(int err) { + constexpr struct { + DWORD win; + errc errc; + } win_error_mapping[] = { + {ERROR_ACCESS_DENIED, errc::permission_denied}, + {ERROR_ALREADY_EXISTS, errc::file_exists}, + {ERROR_BAD_NETPATH, errc::no_such_file_or_directory}, + {ERROR_BAD_PATHNAME, errc::no_such_file_or_directory}, + {ERROR_BAD_UNIT, errc::no_such_device}, + {ERROR_BROKEN_PIPE, errc::broken_pipe}, + {ERROR_BUFFER_OVERFLOW, errc::filename_too_long}, + {ERROR_BUSY, errc::device_or_resource_busy}, + {ERROR_BUSY_DRIVE, errc::device_or_resource_busy}, + {ERROR_CANNOT_MAKE, errc::permission_denied}, + {ERROR_CANTOPEN, errc::io_error}, + {ERROR_CANTREAD, errc::io_error}, + {ERROR_CANTWRITE, errc::io_error}, + {ERROR_CURRENT_DIRECTORY, errc::permission_denied}, + {ERROR_DEV_NOT_EXIST, errc::no_such_device}, + {ERROR_DEVICE_IN_USE, errc::device_or_resource_busy}, + {ERROR_DIR_NOT_EMPTY, errc::directory_not_empty}, + {ERROR_DIRECTORY, errc::invalid_argument}, + {ERROR_DISK_FULL, errc::no_space_on_device}, + {ERROR_FILE_EXISTS, errc::file_exists}, + {ERROR_FILE_NOT_FOUND, errc::no_such_file_or_directory}, + {ERROR_HANDLE_DISK_FULL, errc::no_space_on_device}, + {ERROR_INVALID_ACCESS, errc::permission_denied}, + {ERROR_INVALID_DRIVE, errc::no_such_device}, + {ERROR_INVALID_FUNCTION, errc::function_not_supported}, + {ERROR_INVALID_HANDLE, errc::invalid_argument}, + {ERROR_INVALID_NAME, errc::no_such_file_or_directory}, + {ERROR_INVALID_PARAMETER, errc::invalid_argument}, + {ERROR_LOCK_VIOLATION, errc::no_lock_available}, + {ERROR_LOCKED, errc::no_lock_available}, + {ERROR_NEGATIVE_SEEK, errc::invalid_argument}, + {ERROR_NOACCESS, errc::permission_denied}, + {ERROR_NOT_ENOUGH_MEMORY, errc::not_enough_memory}, + {ERROR_NOT_READY, errc::resource_unavailable_try_again}, + {ERROR_NOT_SAME_DEVICE, errc::cross_device_link}, + {ERROR_NOT_SUPPORTED, errc::not_supported}, + {ERROR_OPEN_FAILED, errc::io_error}, + {ERROR_OPEN_FILES, errc::device_or_resource_busy}, + {ERROR_OPERATION_ABORTED, errc::operation_canceled}, + {ERROR_OUTOFMEMORY, errc::not_enough_memory}, + {ERROR_PATH_NOT_FOUND, errc::no_such_file_or_directory}, + {ERROR_READ_FAULT, errc::io_error}, + {ERROR_REPARSE_TAG_INVALID, errc::invalid_argument}, + {ERROR_RETRY, errc::resource_unavailable_try_again}, + {ERROR_SEEK, errc::io_error}, + {ERROR_SHARING_VIOLATION, errc::permission_denied}, + {ERROR_TOO_MANY_OPEN_FILES, errc::too_many_files_open}, + {ERROR_WRITE_FAULT, errc::io_error}, + {ERROR_WRITE_PROTECT, errc::permission_denied}, + }; + + for (const auto &pair : win_error_mapping) + if (pair.win == static_cast(err)) + return pair.errc; + return errc::invalid_argument; +} + +#endif // _LIBCPP_WIN32API + +inline _LIBCPP_HIDE_FROM_ABI error_code capture_errno() { + _LIBCPP_ASSERT(errno != 0, "Expected errno to be non-zero"); + return error_code(errno, generic_category()); +} + +#if defined(_LIBCPP_WIN32API) +inline _LIBCPP_HIDE_FROM_ABI error_code make_windows_error(int err) { + return make_error_code(__win_err_to_errc(err)); +} +#endif + +template +_LIBCPP_HIDE_FROM_ABI T error_value(); +template <> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void error_value() {} +template <> +inline _LIBCPP_HIDE_FROM_ABI bool error_value() { + return false; +} +#if __SIZEOF_SIZE_T__ != __SIZEOF_LONG_LONG__ +template <> +inline _LIBCPP_HIDE_FROM_ABI size_t error_value() { + return size_t(-1); +} +#endif +template <> +inline _LIBCPP_HIDE_FROM_ABI uintmax_t error_value() { + return uintmax_t(-1); +} +template <> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 file_time_type error_value() { + return file_time_type::min(); +} +template <> +inline _LIBCPP_HIDE_FROM_ABI path error_value() { + return {}; +} + +template +struct ErrorHandler { + const char* func_name_; + error_code* ec_ = nullptr; + const path* p1_ = nullptr; + const path* p2_ = nullptr; + + _LIBCPP_HIDE_FROM_ABI + ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr, + const path* p2 = nullptr) + : func_name_(fname), ec_(ec), p1_(p1), p2_(p2) { + if (ec_) + ec_->clear(); + } + + _LIBCPP_HIDE_FROM_ABI + T report(const error_code& ec) const { + if (ec_) { + *ec_ = ec; + return error_value(); + } + string what = string("in ") + func_name_; + switch (bool(p1_) + bool(p2_)) { + case 0: + __throw_filesystem_error(what, ec); + case 1: + __throw_filesystem_error(what, *p1_, ec); + case 2: + __throw_filesystem_error(what, *p1_, *p2_, ec); + } + __libcpp_unreachable(); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 0) + void report_impl(const error_code& ec, const char* msg, va_list ap) const { + if (ec_) { + *ec_ = ec; + return; + } + string what = + string("in ") + func_name_ + ": " + detail::vformat_string(msg, ap); + switch (bool(p1_) + bool(p2_)) { + case 0: + __throw_filesystem_error(what, ec); + case 1: + __throw_filesystem_error(what, *p1_, ec); + case 2: + __throw_filesystem_error(what, *p1_, *p2_, ec); + } + __libcpp_unreachable(); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) + T report(const error_code& ec, const char* msg, ...) const { + va_list ap; + va_start(ap, msg); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + report_impl(ec, msg, ap); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + va_end(ap); + throw; + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + va_end(ap); + return error_value(); + } + + _LIBCPP_HIDE_FROM_ABI + T report(errc const& err) const { + return report(make_error_code(err)); + } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) + T report(errc const& err, const char* msg, ...) const { + va_list ap; + va_start(ap, msg); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + report_impl(make_error_code(err), msg, ap); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + va_end(ap); + throw; + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + va_end(ap); + return error_value(); + } + +private: + ErrorHandler(ErrorHandler const&) = delete; + ErrorHandler& operator=(ErrorHandler const&) = delete; +}; + +} // end namespace detail + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // FILESYSTEM_ERROR_H diff --git a/libcxx/src/filesystem/filesystem_common.h b/libcxx/src/filesystem/filesystem_common.h --- a/libcxx/src/filesystem/filesystem_common.h +++ b/libcxx/src/filesystem/filesystem_common.h @@ -22,6 +22,7 @@ #include #include +#include "error.h" #include "format_string.h" #include "posix_compat.h" @@ -47,147 +48,6 @@ namespace detail { -#if defined(_LIBCPP_WIN32API) -// Non anonymous, to allow access from two translation units. -_LIBCPP_HIDE_FROM_ABI errc __win_err_to_errc(int err); -#endif - -inline _LIBCPP_HIDE_FROM_ABI error_code capture_errno() { - _LIBCPP_ASSERT(errno != 0, "Expected errno to be non-zero"); - return error_code(errno, generic_category()); -} - -#if defined(_LIBCPP_WIN32API) -inline _LIBCPP_HIDE_FROM_ABI error_code make_windows_error(int err) { - return make_error_code(__win_err_to_errc(err)); -} -#endif - -template -_LIBCPP_HIDE_FROM_ABI T error_value(); -template <> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void error_value() {} -template <> -inline _LIBCPP_HIDE_FROM_ABI bool error_value() { - return false; -} -#if __SIZEOF_SIZE_T__ != __SIZEOF_LONG_LONG__ -template <> -inline _LIBCPP_HIDE_FROM_ABI size_t error_value() { - return size_t(-1); -} -#endif -template <> -inline _LIBCPP_HIDE_FROM_ABI uintmax_t error_value() { - return uintmax_t(-1); -} -template <> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 file_time_type error_value() { - return file_time_type::min(); -} -template <> -inline _LIBCPP_HIDE_FROM_ABI path error_value() { - return {}; -} - -template -struct ErrorHandler { - const char* func_name_; - error_code* ec_ = nullptr; - const path* p1_ = nullptr; - const path* p2_ = nullptr; - - _LIBCPP_HIDE_FROM_ABI - ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr, - const path* p2 = nullptr) - : func_name_(fname), ec_(ec), p1_(p1), p2_(p2) { - if (ec_) - ec_->clear(); - } - - _LIBCPP_HIDE_FROM_ABI - T report(const error_code& ec) const { - if (ec_) { - *ec_ = ec; - return error_value(); - } - string what = string("in ") + func_name_; - switch (bool(p1_) + bool(p2_)) { - case 0: - __throw_filesystem_error(what, ec); - case 1: - __throw_filesystem_error(what, *p1_, ec); - case 2: - __throw_filesystem_error(what, *p1_, *p2_, ec); - } - __libcpp_unreachable(); - } - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 0) - void report_impl(const error_code& ec, const char* msg, va_list ap) const { - if (ec_) { - *ec_ = ec; - return; - } - string what = - string("in ") + func_name_ + ": " + detail::vformat_string(msg, ap); - switch (bool(p1_) + bool(p2_)) { - case 0: - __throw_filesystem_error(what, ec); - case 1: - __throw_filesystem_error(what, *p1_, ec); - case 2: - __throw_filesystem_error(what, *p1_, *p2_, ec); - } - __libcpp_unreachable(); - } - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) - T report(const error_code& ec, const char* msg, ...) const { - va_list ap; - va_start(ap, msg); -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - try { -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - report_impl(ec, msg, ap); -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - } catch (...) { - va_end(ap); - throw; - } -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - va_end(ap); - return error_value(); - } - - _LIBCPP_HIDE_FROM_ABI - T report(errc const& err) const { - return report(make_error_code(err)); - } - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4) - T report(errc const& err, const char* msg, ...) const { - va_list ap; - va_start(ap, msg); -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - try { -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - report_impl(make_error_code(err), msg, ap); -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS - } catch (...) { - va_end(ap); - throw; - } -#endif // _LIBCPP_HAS_NO_EXCEPTIONS - va_end(ap); - return error_value(); - } - -private: - ErrorHandler(ErrorHandler const&) = delete; - ErrorHandler& operator=(ErrorHandler const&) = delete; -}; - using chrono::duration; using chrono::duration_cast; @@ -574,73 +434,6 @@ // POSIX HELPERS -#if defined(_LIBCPP_WIN32API) - -inline _LIBCPP_HIDE_FROM_ABI -errc __win_err_to_errc(int err) { - constexpr struct { - DWORD win; - errc errc; - } win_error_mapping[] = { - {ERROR_ACCESS_DENIED, errc::permission_denied}, - {ERROR_ALREADY_EXISTS, errc::file_exists}, - {ERROR_BAD_NETPATH, errc::no_such_file_or_directory}, - {ERROR_BAD_PATHNAME, errc::no_such_file_or_directory}, - {ERROR_BAD_UNIT, errc::no_such_device}, - {ERROR_BROKEN_PIPE, errc::broken_pipe}, - {ERROR_BUFFER_OVERFLOW, errc::filename_too_long}, - {ERROR_BUSY, errc::device_or_resource_busy}, - {ERROR_BUSY_DRIVE, errc::device_or_resource_busy}, - {ERROR_CANNOT_MAKE, errc::permission_denied}, - {ERROR_CANTOPEN, errc::io_error}, - {ERROR_CANTREAD, errc::io_error}, - {ERROR_CANTWRITE, errc::io_error}, - {ERROR_CURRENT_DIRECTORY, errc::permission_denied}, - {ERROR_DEV_NOT_EXIST, errc::no_such_device}, - {ERROR_DEVICE_IN_USE, errc::device_or_resource_busy}, - {ERROR_DIR_NOT_EMPTY, errc::directory_not_empty}, - {ERROR_DIRECTORY, errc::invalid_argument}, - {ERROR_DISK_FULL, errc::no_space_on_device}, - {ERROR_FILE_EXISTS, errc::file_exists}, - {ERROR_FILE_NOT_FOUND, errc::no_such_file_or_directory}, - {ERROR_HANDLE_DISK_FULL, errc::no_space_on_device}, - {ERROR_INVALID_ACCESS, errc::permission_denied}, - {ERROR_INVALID_DRIVE, errc::no_such_device}, - {ERROR_INVALID_FUNCTION, errc::function_not_supported}, - {ERROR_INVALID_HANDLE, errc::invalid_argument}, - {ERROR_INVALID_NAME, errc::no_such_file_or_directory}, - {ERROR_INVALID_PARAMETER, errc::invalid_argument}, - {ERROR_LOCK_VIOLATION, errc::no_lock_available}, - {ERROR_LOCKED, errc::no_lock_available}, - {ERROR_NEGATIVE_SEEK, errc::invalid_argument}, - {ERROR_NOACCESS, errc::permission_denied}, - {ERROR_NOT_ENOUGH_MEMORY, errc::not_enough_memory}, - {ERROR_NOT_READY, errc::resource_unavailable_try_again}, - {ERROR_NOT_SAME_DEVICE, errc::cross_device_link}, - {ERROR_NOT_SUPPORTED, errc::not_supported}, - {ERROR_OPEN_FAILED, errc::io_error}, - {ERROR_OPEN_FILES, errc::device_or_resource_busy}, - {ERROR_OPERATION_ABORTED, errc::operation_canceled}, - {ERROR_OUTOFMEMORY, errc::not_enough_memory}, - {ERROR_PATH_NOT_FOUND, errc::no_such_file_or_directory}, - {ERROR_READ_FAULT, errc::io_error}, - {ERROR_REPARSE_TAG_INVALID, errc::invalid_argument}, - {ERROR_RETRY, errc::resource_unavailable_try_again}, - {ERROR_SEEK, errc::io_error}, - {ERROR_SHARING_VIOLATION, errc::permission_denied}, - {ERROR_TOO_MANY_OPEN_FILES, errc::too_many_files_open}, - {ERROR_WRITE_FAULT, errc::io_error}, - {ERROR_WRITE_PROTECT, errc::permission_denied}, - }; - - for (const auto &pair : win_error_mapping) - if (pair.win == static_cast(err)) - return pair.errc; - return errc::invalid_argument; -} - -#endif - using value_type = path::value_type; using string_type = path::string_type; diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp --- a/libcxx/src/filesystem/operations.cpp +++ b/libcxx/src/filesystem/operations.cpp @@ -17,6 +17,7 @@ #include #include +#include "error.h" #include "filesystem_common.h" #include "path_parser.h" #include "posix_compat.h" diff --git a/libcxx/src/filesystem/path.cpp b/libcxx/src/filesystem/path.cpp --- a/libcxx/src/filesystem/path.cpp +++ b/libcxx/src/filesystem/path.cpp @@ -9,9 +9,8 @@ #include #include -#include "filesystem_common.h" +#include "error.h" #include "path_parser.h" -#include "posix_compat.h" _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM