3rdparty: Update GHC 1.5.4 to 1.5.8

Make ghc act more like std::fs + consistency with C++17 and other fixes.
This commit is contained in:
RedDevilus 2021-07-19 05:05:14 +02:00 committed by Kojin
parent 69ba5b447f
commit 02a60acbcc
1 changed files with 230 additions and 154 deletions

View File

@ -74,6 +74,9 @@
#elif defined(__EMSCRIPTEN__) #elif defined(__EMSCRIPTEN__)
#define GHC_OS_WEB #define GHC_OS_WEB
#include <wasi/api.h> #include <wasi/api.h>
#elif defined(__QNX__)
#define GHC_OS_QNX
#define GHC_NO_DIRENT_D_TYPE
#else #else
#error "Operating system currently not supported!" #error "Operating system currently not supported!"
#endif #endif
@ -240,6 +243,9 @@
#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW #define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW
#elif defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)) && (__cplusplus >= 201402) #elif defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)) && (__cplusplus >= 201402)
#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW #define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW
#elif defined(__GLIBCXX__) && defined(_GLIBCXX_USE_DUAL_ABI) && (__cplusplus >= 201402)
// macro _GLIBCXX_USE_DUAL_ABI is always defined in libstdc++ from gcc-5 and newer
#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW
#endif #endif
#if defined(GHC_HAS_STD_STRING_VIEW) #if defined(GHC_HAS_STD_STRING_VIEW)
@ -295,7 +301,7 @@
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch) // ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch)
#define GHC_FILESYSTEM_VERSION 10504L #define GHC_FILESYSTEM_VERSION 10508L
#if !defined(GHC_WITH_EXCEPTIONS) && (defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)) #if !defined(GHC_WITH_EXCEPTIONS) && (defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND))
#define GHC_WITH_EXCEPTIONS #define GHC_WITH_EXCEPTIONS
@ -351,7 +357,7 @@ bool has_executable_extension(const path& p);
} }
#endif #endif
// 30.10.8 class path // [fs.class.path] class path
class GHC_FS_API_CLASS path class GHC_FS_API_CLASS path
#if defined(GHC_OS_WINDOWS) && !defined(GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE) #if defined(GHC_OS_WINDOWS) && !defined(GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE)
#define GHC_USE_WCHAR_T #define GHC_USE_WCHAR_T
@ -372,7 +378,7 @@ public:
using string_type = std::basic_string<value_type>; using string_type = std::basic_string<value_type>;
using path_helper_base<value_type>::preferred_separator; using path_helper_base<value_type>::preferred_separator;
// 30.10.10.1 enumeration format // [fs.enum.path.format] enumeration format
/// The path format in which the constructor argument is given. /// The path format in which the constructor argument is given.
enum format { enum format {
generic_format, ///< The generic format, internally used by generic_format, ///< The generic format, internally used by
@ -408,12 +414,24 @@ public:
template <typename T1, typename T2 = void> template <typename T1, typename T2 = void>
using path_type = typename std::enable_if<!std::is_same<path, T1>::value, path>::type; using path_type = typename std::enable_if<!std::is_same<path, T1>::value, path>::type;
template <typename T> template <typename T>
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
using path_from_string =
typename std::enable_if<_is_basic_string<T>::value || std::is_same<char const*, typename std::decay<T>::type>::value || std::is_same<char*, typename std::decay<T>::type>::value || std::is_same<char8_t const*, typename std::decay<T>::type>::value ||
std::is_same<char8_t*, typename std::decay<T>::type>::value || std::is_same<char16_t const*, typename std::decay<T>::type>::value || std::is_same<char16_t*, typename std::decay<T>::type>::value ||
std::is_same<char32_t const*, typename std::decay<T>::type>::value || std::is_same<char32_t*, typename std::decay<T>::type>::value || std::is_same<wchar_t const*, typename std::decay<T>::type>::value ||
std::is_same<wchar_t*, typename std::decay<T>::type>::value,
path>::type;
template <typename T>
using path_type_EcharT = typename std::enable_if<std::is_same<T, char>::value || std::is_same<T, char8_t>::value || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value || std::is_same<T, wchar_t>::value, path>::type;
#else
using path_from_string = typename std::enable_if<_is_basic_string<T>::value || std::is_same<char const*, typename std::decay<T>::type>::value || std::is_same<char*, typename std::decay<T>::type>::value || using path_from_string = typename std::enable_if<_is_basic_string<T>::value || std::is_same<char const*, typename std::decay<T>::type>::value || std::is_same<char*, typename std::decay<T>::type>::value ||
std::is_same<wchar_t const*, typename std::decay<T>::type>::value || std::is_same<wchar_t*, typename std::decay<T>::type>::value, std::is_same<char16_t const*, typename std::decay<T>::type>::value || std::is_same<char16_t*, typename std::decay<T>::type>::value || std::is_same<char32_t const*, typename std::decay<T>::type>::value ||
path>::type; std::is_same<char32_t*, typename std::decay<T>::type>::value || std::is_same<wchar_t const*, typename std::decay<T>::type>::value || std::is_same<wchar_t*, typename std::decay<T>::type>::value,
path>::type;
template <typename T> template <typename T>
using path_type_EcharT = typename std::enable_if<std::is_same<T, char>::value || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value || std::is_same<T, wchar_t>::value, path>::type; using path_type_EcharT = typename std::enable_if<std::is_same<T, char>::value || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value || std::is_same<T, wchar_t>::value, path>::type;
// 30.10.8.4.1 constructors and destructor #endif
// [fs.path.construct] constructors and destructor
path() noexcept; path() noexcept;
path(const path& p); path(const path& p);
path(path&& p) noexcept; path(path&& p) noexcept;
@ -430,7 +448,7 @@ public:
#endif #endif
~path(); ~path();
// 30.10.8.4.2 assignments // [fs.path.assign] assignments
path& operator=(const path& p); path& operator=(const path& p);
path& operator=(path&& p) noexcept; path& operator=(path&& p) noexcept;
path& operator=(string_type&& source); path& operator=(string_type&& source);
@ -442,7 +460,7 @@ public:
template <class InputIterator> template <class InputIterator>
path& assign(InputIterator first, InputIterator last); path& assign(InputIterator first, InputIterator last);
// 30.10.8.4.3 appends // [fs.path.append] appends
path& operator/=(const path& p); path& operator/=(const path& p);
template <class Source> template <class Source>
path& operator/=(const Source& source); path& operator/=(const Source& source);
@ -451,7 +469,7 @@ public:
template <class InputIterator> template <class InputIterator>
path& append(InputIterator first, InputIterator last); path& append(InputIterator first, InputIterator last);
// 30.10.8.4.4 concatenation // [fs.path.concat] concatenation
path& operator+=(const path& x); path& operator+=(const path& x);
path& operator+=(const string_type& x); path& operator+=(const string_type& x);
#ifdef GHC_WITH_STRING_VIEW #ifdef GHC_WITH_STRING_VIEW
@ -468,7 +486,7 @@ public:
template <class InputIterator> template <class InputIterator>
path& concat(InputIterator first, InputIterator last); path& concat(InputIterator first, InputIterator last);
// 30.10.8.4.5 modifiers // [fs.path.modifiers] modifiers
void clear() noexcept; void clear() noexcept;
path& make_preferred(); path& make_preferred();
path& remove_filename(); path& remove_filename();
@ -476,7 +494,7 @@ public:
path& replace_extension(const path& replacement = path()); path& replace_extension(const path& replacement = path());
void swap(path& rhs) noexcept; void swap(path& rhs) noexcept;
// 30.10.8.4.6 native format observers // [fs.path.native.obs] native format observers
const string_type& native() const noexcept; const string_type& native() const noexcept;
const value_type* c_str() const noexcept; const value_type* c_str() const noexcept;
operator string_type() const; operator string_type() const;
@ -492,7 +510,7 @@ public:
std::u16string u16string() const; std::u16string u16string() const;
std::u32string u32string() const; std::u32string u32string() const;
// 30.10.8.4.7 generic format observers // [fs.path.generic.obs] generic format observers
template <class EcharT, class traits = std::char_traits<EcharT>, class Allocator = std::allocator<EcharT>> template <class EcharT, class traits = std::char_traits<EcharT>, class Allocator = std::allocator<EcharT>>
std::basic_string<EcharT, traits, Allocator> generic_string(const Allocator& a = Allocator()) const; std::basic_string<EcharT, traits, Allocator> generic_string(const Allocator& a = Allocator()) const;
std::string generic_string() const; std::string generic_string() const;
@ -505,7 +523,7 @@ public:
std::u16string generic_u16string() const; std::u16string generic_u16string() const;
std::u32string generic_u32string() const; std::u32string generic_u32string() const;
// 30.10.8.4.8 compare // [fs.path.compare] compare
int compare(const path& p) const noexcept; int compare(const path& p) const noexcept;
int compare(const string_type& s) const; int compare(const string_type& s) const;
#ifdef GHC_WITH_STRING_VIEW #ifdef GHC_WITH_STRING_VIEW
@ -513,7 +531,7 @@ public:
#endif #endif
int compare(const value_type* s) const; int compare(const value_type* s) const;
// 30.10.8.4.9 decomposition // [fs.path.decompose] decomposition
path root_name() const; path root_name() const;
path root_directory() const; path root_directory() const;
path root_path() const; path root_path() const;
@ -523,7 +541,7 @@ public:
path stem() const; path stem() const;
path extension() const; path extension() const;
// 30.10.8.4.10 query // [fs.path.query] query
bool empty() const noexcept; bool empty() const noexcept;
bool has_root_name() const; bool has_root_name() const;
bool has_root_directory() const; bool has_root_directory() const;
@ -536,12 +554,12 @@ public:
bool is_absolute() const; bool is_absolute() const;
bool is_relative() const; bool is_relative() const;
// 30.10.8.4.11 generation // [fs.path.gen] generation
path lexically_normal() const; path lexically_normal() const;
path lexically_relative(const path& base) const; path lexically_relative(const path& base) const;
path lexically_proximate(const path& base) const; path lexically_proximate(const path& base) const;
// 30.10.8.5 iterators // [fs.path.itr] iterators
class iterator; class iterator;
using const_iterator = iterator; using const_iterator = iterator;
iterator begin() const; iterator begin() const;
@ -577,6 +595,7 @@ private:
friend void swap(path& lhs, path& rhs) noexcept; friend void swap(path& lhs, path& rhs) noexcept;
friend size_t hash_value(const path& p) noexcept; friend size_t hash_value(const path& p) noexcept;
friend path canonical(const path& p, std::error_code& ec); friend path canonical(const path& p, std::error_code& ec);
friend bool create_directories(const path& p, std::error_code& ec) noexcept;
string_type::size_type root_name_length() const noexcept; string_type::size_type root_name_length() const noexcept;
void postprocess_path_with_format(format fmt); void postprocess_path_with_format(format fmt);
void check_long_path(); void check_long_path();
@ -594,7 +613,7 @@ private:
#endif #endif
}; };
// 30.10.8.6 path non-member functions // [fs.path.nonmember] path non-member functions
GHC_FS_API void swap(path& lhs, path& rhs) noexcept; GHC_FS_API void swap(path& lhs, path& rhs) noexcept;
GHC_FS_API size_t hash_value(const path& p) noexcept; GHC_FS_API size_t hash_value(const path& p) noexcept;
#ifdef GHC_HAS_THREEWAY_COMP #ifdef GHC_HAS_THREEWAY_COMP
@ -608,13 +627,13 @@ GHC_FS_API bool operator>(const path& lhs, const path& rhs) noexcept;
GHC_FS_API bool operator>=(const path& lhs, const path& rhs) noexcept; GHC_FS_API bool operator>=(const path& lhs, const path& rhs) noexcept;
GHC_FS_API path operator/(const path& lhs, const path& rhs); GHC_FS_API path operator/(const path& lhs, const path& rhs);
// 30.10.8.6.1 path inserter and extractor // [fs.path.io] path inserter and extractor
template <class charT, class traits> template <class charT, class traits>
std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const path& p); std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const path& p);
template <class charT, class traits> template <class charT, class traits>
std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, path& p); std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, path& p);
// 30.10.8.6.2 path factory functions // [pfs.path.factory] path factory functions
template <class Source, typename = path::path_from_string<Source>> template <class Source, typename = path::path_from_string<Source>>
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) #if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
[[deprecated("use ghc::filesystem::path::path() with std::u8string instead")]] [[deprecated("use ghc::filesystem::path::path() with std::u8string instead")]]
@ -626,7 +645,7 @@ template <class InputIterator>
#endif #endif
path u8path(InputIterator first, InputIterator last); path u8path(InputIterator first, InputIterator last);
// 30.10.9 class filesystem_error // [fs.class.filesystem_error] class filesystem_error
class GHC_FS_API_CLASS filesystem_error : public std::system_error class GHC_FS_API_CLASS filesystem_error : public std::system_error
{ {
public: public:
@ -683,7 +702,8 @@ struct space_info
uintmax_t available; uintmax_t available;
}; };
// 30.10.10, enumerations // [fs.enum] enumerations
// [fs.enum.file_type]
enum class file_type { enum class file_type {
none, none,
not_found, not_found,
@ -697,6 +717,7 @@ enum class file_type {
unknown, unknown,
}; };
// [fs.enum.perms]
enum class perms : uint16_t { enum class perms : uint16_t {
none = 0, none = 0,
@ -724,6 +745,7 @@ enum class perms : uint16_t {
unknown = 0xffff unknown = 0xffff
}; };
// [fs.enum.perm.opts]
enum class perm_options : uint16_t { enum class perm_options : uint16_t {
replace = 3, replace = 3,
add = 1, add = 1,
@ -731,6 +753,7 @@ enum class perm_options : uint16_t {
nofollow = 4, nofollow = 4,
}; };
// [fs.enum.copy.opts]
enum class copy_options : uint16_t { enum class copy_options : uint16_t {
none = 0, none = 0,
@ -750,17 +773,18 @@ enum class copy_options : uint16_t {
#endif #endif
}; };
// [fs.enum.dir.opts]
enum class directory_options : uint16_t { enum class directory_options : uint16_t {
none = 0, none = 0,
follow_directory_symlink = 1, follow_directory_symlink = 1,
skip_permission_denied = 2, skip_permission_denied = 2,
}; };
// 30.10.11 class file_status // [fs.class.file_status] class file_status
class GHC_FS_API_CLASS file_status class GHC_FS_API_CLASS file_status
{ {
public: public:
// 30.10.11.1 constructors and destructor // [fs.file_status.cons] constructors and destructor
file_status() noexcept; file_status() noexcept;
explicit file_status(file_type ft, perms prms = perms::unknown) noexcept; explicit file_status(file_type ft, perms prms = perms::unknown) noexcept;
file_status(const file_status&) noexcept; file_status(const file_status&) noexcept;
@ -769,10 +793,10 @@ public:
// assignments: // assignments:
file_status& operator=(const file_status&) noexcept; file_status& operator=(const file_status&) noexcept;
file_status& operator=(file_status&&) noexcept; file_status& operator=(file_status&&) noexcept;
// 30.10.11.3 modifiers // [fs.file_status.mods] modifiers
void type(file_type ft) noexcept; void type(file_type ft) noexcept;
void permissions(perms prms) noexcept; void permissions(perms prms) noexcept;
// 30.10.11.2 observers // [fs.file_status.obs] observers
file_type type() const noexcept; file_type type() const noexcept;
perms permissions() const noexcept; perms permissions() const noexcept;
friend bool operator==(const file_status& lhs, const file_status& rhs) noexcept { return lhs.type() == rhs.type() && lhs.permissions() == rhs.permissions(); } friend bool operator==(const file_status& lhs, const file_status& rhs) noexcept { return lhs.type() == rhs.type() && lhs.permissions() == rhs.permissions(); }
@ -783,11 +807,11 @@ private:
using file_time_type = std::chrono::time_point<std::chrono::system_clock>; using file_time_type = std::chrono::time_point<std::chrono::system_clock>;
// 30.10.12 Class directory_entry // [fs.class.directory_entry] Class directory_entry
class GHC_FS_API_CLASS directory_entry class GHC_FS_API_CLASS directory_entry
{ {
public: public:
// 30.10.12.1 constructors and destructor // [fs.dir.entry.cons] constructors and destructor
directory_entry() noexcept = default; directory_entry() noexcept = default;
directory_entry(const directory_entry&) = default; directory_entry(const directory_entry&) = default;
directory_entry(directory_entry&&) noexcept = default; directory_entry(directory_entry&&) noexcept = default;
@ -801,7 +825,7 @@ public:
directory_entry& operator=(const directory_entry&) = default; directory_entry& operator=(const directory_entry&) = default;
directory_entry& operator=(directory_entry&&) noexcept = default; directory_entry& operator=(directory_entry&&) noexcept = default;
// 30.10.12.2 modifiers // [fs.dir.entry.mods] modifiers
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
void assign(const path& p); void assign(const path& p);
void replace_filename(const path& p); void replace_filename(const path& p);
@ -811,7 +835,7 @@ public:
void replace_filename(const path& p, std::error_code& ec); void replace_filename(const path& p, std::error_code& ec);
void refresh(std::error_code& ec) noexcept; void refresh(std::error_code& ec) noexcept;
// 30.10.12.3 observers // [fs.dir.entry.obs] observers
const filesystem::path& path() const noexcept; const filesystem::path& path() const noexcept;
operator const filesystem::path&() const noexcept; operator const filesystem::path&() const noexcept;
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
@ -876,7 +900,7 @@ private:
time_t _last_write_time = 0; time_t _last_write_time = 0;
}; };
// 30.10.13 Class directory_iterator // [fs.class.directory.iterator] Class directory_iterator
class GHC_FS_API_CLASS directory_iterator class GHC_FS_API_CLASS directory_iterator
{ {
public: public:
@ -901,7 +925,7 @@ public:
using pointer = const directory_entry*; using pointer = const directory_entry*;
using reference = const directory_entry&; using reference = const directory_entry&;
// 30.10.13.1 member functions // [fs.dir.itr.members] member functions
directory_iterator() noexcept; directory_iterator() noexcept;
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
explicit directory_iterator(const path& p); explicit directory_iterator(const path& p);
@ -921,7 +945,7 @@ public:
#endif #endif
directory_iterator& increment(std::error_code& ec) noexcept; directory_iterator& increment(std::error_code& ec) noexcept;
// other members as required by 27.2.3, input iterators // other members as required by [input.iterators]
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
proxy operator++(int) proxy operator++(int)
{ {
@ -939,11 +963,11 @@ private:
std::shared_ptr<impl> _impl; std::shared_ptr<impl> _impl;
}; };
// 30.10.13.2 directory_iterator non-member functions // [fs.dir.itr.nonmembers] directory_iterator non-member functions
GHC_FS_API directory_iterator begin(directory_iterator iter) noexcept; GHC_FS_API directory_iterator begin(directory_iterator iter) noexcept;
GHC_FS_API directory_iterator end(const directory_iterator&) noexcept; GHC_FS_API directory_iterator end(const directory_iterator&) noexcept;
// 30.10.14 class recursive_directory_iterator // [fs.class.re.dir.itr] class recursive_directory_iterator
class GHC_FS_API_CLASS recursive_directory_iterator class GHC_FS_API_CLASS recursive_directory_iterator
{ {
public: public:
@ -953,7 +977,7 @@ public:
using pointer = const directory_entry*; using pointer = const directory_entry*;
using reference = const directory_entry&; using reference = const directory_entry&;
// 30.10.14.1 constructors and destructor // [fs.rec.dir.itr.members] constructors and destructor
recursive_directory_iterator() noexcept; recursive_directory_iterator() noexcept;
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
explicit recursive_directory_iterator(const path& p); explicit recursive_directory_iterator(const path& p);
@ -965,7 +989,7 @@ public:
recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept; recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept;
~recursive_directory_iterator(); ~recursive_directory_iterator();
// 30.10.14.1 observers // [fs.rec.dir.itr.members] observers
directory_options options() const; directory_options options() const;
int depth() const; int depth() const;
bool recursion_pending() const; bool recursion_pending() const;
@ -973,7 +997,7 @@ public:
const directory_entry& operator*() const; const directory_entry& operator*() const;
const directory_entry* operator->() const; const directory_entry* operator->() const;
// 30.10.14.1 modifiers recursive_directory_iterator& // [fs.rec.dir.itr.members] modifiers recursive_directory_iterator&
recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs); recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs);
recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept; recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept;
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
@ -987,7 +1011,7 @@ public:
void pop(std::error_code& ec); void pop(std::error_code& ec);
void disable_recursion_pending(); void disable_recursion_pending();
// other members as required by 27.2.3, input iterators // other members as required by [input.iterators]
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
directory_iterator::proxy operator++(int) directory_iterator::proxy operator++(int)
{ {
@ -1014,11 +1038,11 @@ private:
std::shared_ptr<recursive_directory_iterator_impl> _impl; std::shared_ptr<recursive_directory_iterator_impl> _impl;
}; };
// 30.10.14.2 directory_iterator non-member functions // [fs.rec.dir.itr.nonmembers] directory_iterator non-member functions
GHC_FS_API recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept; GHC_FS_API recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
GHC_FS_API recursive_directory_iterator end(const recursive_directory_iterator&) noexcept; GHC_FS_API recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
// 30.10.15 filesystem operations // [fs.op.funcs] filesystem operations
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_FS_API path absolute(const path& p); GHC_FS_API path absolute(const path& p);
GHC_FS_API path canonical(const path& p); GHC_FS_API path canonical(const path& p);
@ -1871,9 +1895,9 @@ GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink,
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
if (api_call) { if (api_call) {
if (api_call(detail::fromUtf8<std::wstring>(new_symlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), to_directory ? 1 : 0) == 0) { if (api_call(GHC_NATIVEWP(new_symlink), GHC_NATIVEWP(target_name), to_directory ? 1 : 0) == 0) {
auto result = ::GetLastError(); auto result = ::GetLastError();
if (result == ERROR_PRIVILEGE_NOT_HELD && api_call(detail::fromUtf8<std::wstring>(new_symlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), to_directory ? 3 : 2) != 0) { if (result == ERROR_PRIVILEGE_NOT_HELD && api_call(GHC_NATIVEWP(new_symlink), GHC_NATIVEWP(target_name), to_directory ? 3 : 2) != 0) {
return; return;
} }
ec = detail::make_system_error(result); ec = detail::make_system_error(result);
@ -1980,56 +2004,70 @@ GHC_INLINE file_status file_status_from_st_mode(T mode)
#endif #endif
} }
GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec)
{
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE #ifndef REPARSE_DATA_BUFFER_HEADER_SIZE
typedef struct _REPARSE_DATA_BUFFER typedef struct _REPARSE_DATA_BUFFER
{
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union
{ {
ULONG ReparseTag; struct
USHORT ReparseDataLength;
USHORT Reserved;
union
{ {
struct USHORT SubstituteNameOffset;
{ USHORT SubstituteNameLength;
USHORT SubstituteNameOffset; USHORT PrintNameOffset;
USHORT SubstituteNameLength; USHORT PrintNameLength;
USHORT PrintNameOffset; ULONG Flags;
USHORT PrintNameLength; WCHAR PathBuffer[1];
ULONG Flags; } SymbolicLinkReparseBuffer;
WCHAR PathBuffer[1]; struct
} SymbolicLinkReparseBuffer; {
struct USHORT SubstituteNameOffset;
{ USHORT SubstituteNameLength;
USHORT SubstituteNameOffset; USHORT PrintNameOffset;
USHORT SubstituteNameLength; USHORT PrintNameLength;
USHORT PrintNameOffset; WCHAR PathBuffer[1];
USHORT PrintNameLength; } MountPointReparseBuffer;
WCHAR PathBuffer[1]; struct
} MountPointReparseBuffer; {
struct UCHAR DataBuffer[1];
{ } GenericReparseBuffer;
UCHAR DataBuffer[1]; } DUMMYUNIONNAME;
} GenericReparseBuffer; } REPARSE_DATA_BUFFER;
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER;
#ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE #ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024) #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024)
#endif #endif
#endif #endif
GHC_INLINE std::shared_ptr<REPARSE_DATA_BUFFER> getReparseData(const path& p, std::error_code& ec)
{
std::shared_ptr<void> file(CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle); std::shared_ptr<void> file(CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
if (file.get() == INVALID_HANDLE_VALUE) { if (file.get() == INVALID_HANDLE_VALUE) {
ec = detail::make_system_error(); ec = detail::make_system_error();
return path(); return nullptr;
} }
std::shared_ptr<REPARSE_DATA_BUFFER> reparseData((REPARSE_DATA_BUFFER*)std::calloc(1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE), std::free); std::shared_ptr<REPARSE_DATA_BUFFER> reparseData((REPARSE_DATA_BUFFER*)std::calloc(1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE), std::free);
ULONG bufferUsed; ULONG bufferUsed;
path result;
if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0, reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bufferUsed, 0)) { if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0, reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bufferUsed, 0)) {
if (IsReparseTagMicrosoft(reparseData->ReparseTag)) { return reparseData;
}
else {
ec = detail::make_system_error();
}
return nullptr;
}
#endif
GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec)
{
#ifdef GHC_OS_WINDOWS
path result;
auto reparseData = detail::getReparseData(p, ec);
if (!ec) {
if (reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag)) {
switch (reparseData->ReparseTag) { switch (reparseData->ReparseTag) {
case IO_REPARSE_TAG_SYMLINK: { case IO_REPARSE_TAG_SYMLINK: {
auto printName = std::wstring(&reparseData->SymbolicLinkReparseBuffer.PathBuffer[reparseData->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)], reparseData->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(WCHAR)); auto printName = std::wstring(&reparseData->SymbolicLinkReparseBuffer.PathBuffer[reparseData->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)], reparseData->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(WCHAR));
@ -2047,16 +2085,14 @@ GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec)
break; break;
} }
case IO_REPARSE_TAG_MOUNT_POINT: case IO_REPARSE_TAG_MOUNT_POINT:
result = std::wstring(&reparseData->MountPointReparseBuffer.PathBuffer[reparseData->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], reparseData->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR)); result = detail::getFullPathName(GHC_NATIVEWP(p), ec);
//result = std::wstring(&reparseData->MountPointReparseBuffer.PathBuffer[reparseData->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], reparseData->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR));
break; break;
default: default:
break; break;
} }
} }
} }
else {
ec = detail::make_system_error();
}
return result; return result;
#else #else
size_t bufferSize = 256; size_t bufferSize = 256;
@ -2106,13 +2142,35 @@ GHC_INLINE uintmax_t hard_links_from_INFO<BY_HANDLE_FILE_INFORMATION>(const BY_H
} }
template <typename INFO> template <typename INFO>
GHC_INLINE file_status status_from_INFO(const path& p, const INFO* info, std::error_code&, uintmax_t* sz = nullptr, time_t* lwt = nullptr) GHC_INLINE DWORD reparse_tag_from_INFO(const INFO*)
{
return 0;
}
template <>
GHC_INLINE DWORD reparse_tag_from_INFO(const WIN32_FIND_DATAW* info)
{
return info->dwReserved0;
}
template <typename INFO>
GHC_INLINE file_status status_from_INFO(const path& p, const INFO* info, std::error_code& ec, uintmax_t* sz = nullptr, time_t* lwt = nullptr)
{ {
file_type ft = file_type::unknown; file_type ft = file_type::unknown;
if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { if (sizeof(INFO) == sizeof(WIN32_FIND_DATAW)) {
ft = file_type::symlink; if (detail::reparse_tag_from_INFO(info) == IO_REPARSE_TAG_SYMLINK) {
ft = file_type::symlink;
}
} }
else { else {
if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
auto reparseData = detail::getReparseData(p, ec);
if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
ft = file_type::symlink;
}
}
}
if (ft == file_type::unknown) {
if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
ft = file_type::directory; ft = file_type::directory;
} }
@ -2161,9 +2219,6 @@ GHC_INLINE file_status symlink_status_ex(const path& p, std::error_code& ec, uin
if (nhl) { if (nhl) {
*nhl = 0; *nhl = 0;
} }
if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
fs.type(file_type::symlink);
}
} }
if (detail::is_not_found_error(ec)) { if (detail::is_not_found_error(ec)) {
return file_status(file_type::not_found); return file_status(file_type::not_found);
@ -2201,15 +2256,18 @@ GHC_INLINE file_status status_ex(const path& p, std::error_code& ec, file_status
ec = detail::make_system_error(); ec = detail::make_system_error();
} }
else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
path target = resolveSymlink(p, ec); auto reparseData = detail::getReparseData(p, ec);
file_status result; if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
if (!ec && !target.empty()) { path target = resolveSymlink(p, ec);
if (sls) { file_status result;
*sls = status_from_INFO(p, &attr, ec); if (!ec && !target.empty()) {
if (sls) {
*sls = status_from_INFO(p, &attr, ec);
}
return detail::status_ex(target, ec, nullptr, sz, nhl, lwt, recurse_count + 1);
} }
return detail::status_ex(target, ec, nullptr, sz, nhl, lwt, recurse_count + 1); return file_status(file_type::unknown);
} }
return file_status(file_type::unknown);
} }
if (ec) { if (ec) {
if (detail::is_not_found_error(ec)) { if (detail::is_not_found_error(ec)) {
@ -2299,7 +2357,7 @@ GHC_INLINE u8arguments::u8arguments(int& argc, char**& argv)
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.4.1 constructors and destructor // [fs.path.construct] constructors and destructor
GHC_INLINE path::path() noexcept {} GHC_INLINE path::path() noexcept {}
@ -2354,7 +2412,7 @@ inline path::path(InputIterator first, InputIterator last, const std::locale& lo
GHC_INLINE path::~path() {} GHC_INLINE path::~path() {}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.4.2 assignments // [fs.path.assign] assignments
GHC_INLINE path& path::operator=(const path& p) GHC_INLINE path& path::operator=(const path& p)
{ {
@ -2427,7 +2485,7 @@ inline path& path::assign(InputIterator first, InputIterator last)
#ifdef GHC_EXPAND_IMPL #ifdef GHC_EXPAND_IMPL
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.4.3 appends // [fs.path.append] appends
GHC_INLINE path& path::operator/=(const path& p) GHC_INLINE path& path::operator/=(const path& p)
{ {
@ -2508,7 +2566,7 @@ inline path& path::append(InputIterator first, InputIterator last)
#ifdef GHC_EXPAND_IMPL #ifdef GHC_EXPAND_IMPL
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.4.4 concatenation // [fs.path.concat] concatenation
GHC_INLINE path& path::operator+=(const path& x) GHC_INLINE path& path::operator+=(const path& x)
{ {
@ -2590,7 +2648,7 @@ inline path& path::concat(InputIterator first, InputIterator last)
#ifdef GHC_EXPAND_IMPL #ifdef GHC_EXPAND_IMPL
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.4.5 modifiers // [fs.path.modifiers] modifiers
GHC_INLINE void path::clear() noexcept GHC_INLINE void path::clear() noexcept
{ {
_path.clear(); _path.clear();
@ -2640,7 +2698,7 @@ GHC_INLINE void path::swap(path& rhs) noexcept
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.4.6, native format observers // [fs.path.native.obs] native format observers
GHC_INLINE const path::string_type& path::native() const noexcept GHC_INLINE const path::string_type& path::native() const noexcept
{ {
return _path; return _path;
@ -2723,7 +2781,7 @@ GHC_INLINE std::u32string path::u32string() const
#endif // GHC_EXPAND_IMPL #endif // GHC_EXPAND_IMPL
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.4.7, generic format observers // [fs.path.generic.obs] generic format observers
template <class EcharT, class traits, class Allocator> template <class EcharT, class traits, class Allocator>
inline std::basic_string<EcharT, traits, Allocator> path::generic_string(const Allocator& a) const inline std::basic_string<EcharT, traits, Allocator> path::generic_string(const Allocator& a) const
{ {
@ -2803,7 +2861,7 @@ GHC_INLINE std::u32string path::generic_u32string() const
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.4.8, compare // [fs.path.compare] compare
GHC_INLINE int path::compare(const path& p) const noexcept GHC_INLINE int path::compare(const path& p) const noexcept
{ {
#ifdef LWG_2936_BEHAVIOUR #ifdef LWG_2936_BEHAVIOUR
@ -2877,7 +2935,7 @@ GHC_INLINE int path::compare(const value_type* s) const
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.4.9, decomposition // [fs.path.decompose] decomposition
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
GHC_INLINE void path::handle_prefixes() GHC_INLINE void path::handle_prefixes()
{ {
@ -3009,7 +3067,7 @@ GHC_INLINE bool has_executable_extension(const path& p)
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.4.10, query // [fs.path.query] query
GHC_INLINE bool path::empty() const noexcept GHC_INLINE bool path::empty() const noexcept
{ {
return _path.empty(); return _path.empty();
@ -3072,7 +3130,7 @@ GHC_INLINE bool path::is_relative() const
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.4.11, generation // [fs.path.gen] generation
GHC_INLINE path path::lexically_normal() const GHC_INLINE path path::lexically_normal() const
{ {
path dest; path dest;
@ -3148,7 +3206,7 @@ GHC_INLINE path path::lexically_proximate(const path& base) const
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.5, iterators // [fs.path.itr] iterators
GHC_INLINE path::iterator::iterator() {} GHC_INLINE path::iterator::iterator() {}
GHC_INLINE path::iterator::iterator(const path& p, const impl_string_type::const_iterator& pos) GHC_INLINE path::iterator::iterator(const path& p, const impl_string_type::const_iterator& pos)
@ -3301,7 +3359,7 @@ GHC_INLINE path::iterator path::end() const
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.6, path non-member functions // [fs.path.nonmember] path non-member functions
GHC_INLINE void swap(path& lhs, path& rhs) noexcept GHC_INLINE void swap(path& lhs, path& rhs) noexcept
{ {
swap(lhs._path, rhs._path); swap(lhs._path, rhs._path);
@ -3359,7 +3417,7 @@ GHC_INLINE path operator/(const path& lhs, const path& rhs)
#endif // GHC_EXPAND_IMPL #endif // GHC_EXPAND_IMPL
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.8.6.1 path inserter and extractor // [fs.path.io] path inserter and extractor
template <class charT, class traits> template <class charT, class traits>
inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const path& p) inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const path& p)
{ {
@ -3416,7 +3474,7 @@ inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, t
#ifdef GHC_EXPAND_IMPL #ifdef GHC_EXPAND_IMPL
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.9 Class filesystem_error // [fs.class.filesystem_error] Class filesystem_error
GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, std::error_code ec) GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, std::error_code ec)
: std::system_error(ec, what_arg) : std::system_error(ec, what_arg)
, _what_arg(what_arg) , _what_arg(what_arg)
@ -3466,7 +3524,7 @@ GHC_INLINE const char* filesystem_error::what() const noexcept
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.15, filesystem operations // [fs.op.funcs] filesystem operations
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE path absolute(const path& p) GHC_INLINE path absolute(const path& p)
{ {
@ -3843,35 +3901,36 @@ GHC_INLINE bool create_directories(const path& p, std::error_code& ec) noexcept
path current; path current;
ec.clear(); ec.clear();
bool didCreate = false; bool didCreate = false;
for (path::string_type part : p) { auto rootPathLen = p._prefixLength + p.root_name_length() + (p.has_root_directory() ? 1 : 0);
current = p.native().substr(0, rootPathLen);
path folders(p._path.substr(rootPathLen));
for (path::string_type part : folders) {
current /= part; current /= part;
if (current != p.root_name() && current != p.root_path()) { std::error_code tec;
std::error_code tec; auto fs = status(current, tec);
auto fs = status(current, tec); if (tec && fs.type() != file_type::not_found) {
if (tec && fs.type() != file_type::not_found) { ec = tec;
ec = tec; return false;
return false;
}
if (!exists(fs)) {
create_directory(current, ec);
if (ec) {
std::error_code tmp_ec;
if (is_directory(current, tmp_ec)) {
ec.clear();
}
else {
return false;
}
}
didCreate = true;
}
#ifndef LWG_2935_BEHAVIOUR
else if (!is_directory(fs)) {
ec = detail::make_error_code(detail::portable_error::exists);
return false;
}
#endif
} }
if (!exists(fs)) {
create_directory(current, ec);
if (ec) {
std::error_code tmp_ec;
if (is_directory(current, tmp_ec)) {
ec.clear();
}
else {
return false;
}
}
didCreate = true;
}
#ifndef LWG_2935_BEHAVIOUR
else if (!is_directory(fs)) {
ec = detail::make_error_code(detail::portable_error::exists);
return false;
}
#endif
} }
return didCreate; return didCreate;
} }
@ -4629,6 +4688,13 @@ GHC_INLINE bool remove(const path& p, std::error_code& ec) noexcept
} }
ec = detail::make_system_error(error); ec = detail::make_system_error(error);
} }
else if(attr & FILE_ATTRIBUTE_READONLY) {
auto new_attr = attr & ~static_cast<DWORD>(FILE_ATTRIBUTE_READONLY);
if(!SetFileAttributesW(cstr, new_attr)) {
auto error = ::GetLastError();
ec = detail::make_system_error(error);
}
}
if (!ec) { if (!ec) {
if (attr & FILE_ATTRIBUTE_DIRECTORY) { if (attr & FILE_ATTRIBUTE_DIRECTORY) {
if (!RemoveDirectoryW(cstr)) { if (!RemoveDirectoryW(cstr)) {
@ -4940,8 +5006,8 @@ GHC_INLINE path weakly_canonical(const path& p, std::error_code& ec) noexcept
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.11 class file_status // [fs.class.file_status] class file_status
// 30.10.11.1 constructors and destructor // [fs.file_status.cons] constructors and destructor
GHC_INLINE file_status::file_status() noexcept GHC_INLINE file_status::file_status() noexcept
: file_status(file_type::none) : file_status(file_type::none)
{ {
@ -4982,7 +5048,7 @@ GHC_INLINE file_status& file_status::operator=(file_status&& rhs) noexcept
return *this; return *this;
} }
// 30.10.11.3 modifiers // [fs.file_status.mods] modifiers
GHC_INLINE void file_status::type(file_type ft) noexcept GHC_INLINE void file_status::type(file_type ft) noexcept
{ {
_type = ft; _type = ft;
@ -4993,7 +5059,7 @@ GHC_INLINE void file_status::permissions(perms prms) noexcept
_perms = prms; _perms = prms;
} }
// 30.10.11.2 observers // [fs.file_status.obs] observers
GHC_INLINE file_type file_status::type() const noexcept GHC_INLINE file_type file_status::type() const noexcept
{ {
return _type; return _type;
@ -5005,8 +5071,8 @@ GHC_INLINE perms file_status::permissions() const noexcept
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.12 class directory_entry // [fs.class.directory_entry] class directory_entry
// 30.10.12.1 constructors and destructor // [fs.dir.entry.cons] constructors and destructor
// directory_entry::directory_entry() noexcept = default; // directory_entry::directory_entry() noexcept = default;
// directory_entry::directory_entry(const directory_entry&) = default; // directory_entry::directory_entry(const directory_entry&) = default;
// directory_entry::directory_entry(directory_entry&&) noexcept = default; // directory_entry::directory_entry(directory_entry&&) noexcept = default;
@ -5040,7 +5106,7 @@ GHC_INLINE directory_entry::~directory_entry() {}
// directory_entry& directory_entry::operator=(const directory_entry&) = default; // directory_entry& directory_entry::operator=(const directory_entry&) = default;
// directory_entry& directory_entry::operator=(directory_entry&&) noexcept = default; // directory_entry& directory_entry::operator=(directory_entry&&) noexcept = default;
// 30.10.12.2 directory_entry modifiers // [fs.dir.entry.mods] directory_entry modifiers
#ifdef GHC_WITH_EXCEPTIONS #ifdef GHC_WITH_EXCEPTIONS
GHC_INLINE void directory_entry::assign(const filesystem::path& p) GHC_INLINE void directory_entry::assign(const filesystem::path& p)
{ {
@ -5089,7 +5155,7 @@ GHC_INLINE void directory_entry::refresh(std::error_code& ec) noexcept
#endif #endif
} }
// 30.10.12.3 directory_entry observers // [fs.dir.entry.obs] directory_entry observers
GHC_INLINE const filesystem::path& directory_entry::path() const noexcept GHC_INLINE const filesystem::path& directory_entry::path() const noexcept
{ {
return _path; return _path;
@ -5369,7 +5435,7 @@ GHC_INLINE bool directory_entry::operator>=(const directory_entry& rhs) const no
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.13 class directory_iterator // [fs.class.directory_iterator] class directory_iterator
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
class directory_iterator::impl class directory_iterator::impl
@ -5534,8 +5600,13 @@ public:
} while (skip || std::strcmp(_entry->d_name, ".") == 0 || std::strcmp(_entry->d_name, "..") == 0); } while (skip || std::strcmp(_entry->d_name, ".") == 0 || std::strcmp(_entry->d_name, "..") == 0);
} }
} }
void copyToDirEntry() void copyToDirEntry()
{ {
#ifdef GHC_NO_DIRENT_D_TYPE
_dir_entry._symlink_status = file_status();
_dir_entry._status = file_status();
#else
_dir_entry._symlink_status.permissions(perms::unknown); _dir_entry._symlink_status.permissions(perms::unknown);
switch(_entry->d_type) { switch(_entry->d_type) {
case DT_BLK: _dir_entry._symlink_status.type(file_type::block); break; case DT_BLK: _dir_entry._symlink_status.type(file_type::block); break;
@ -5545,6 +5616,7 @@ public:
case DT_LNK: _dir_entry._symlink_status.type(file_type::symlink); break; case DT_LNK: _dir_entry._symlink_status.type(file_type::symlink); break;
case DT_REG: _dir_entry._symlink_status.type(file_type::regular); break; case DT_REG: _dir_entry._symlink_status.type(file_type::regular); break;
case DT_SOCK: _dir_entry._symlink_status.type(file_type::socket); break; case DT_SOCK: _dir_entry._symlink_status.type(file_type::socket); break;
case DT_UNKNOWN: _dir_entry._symlink_status.type(file_type::none); break;
default: _dir_entry._symlink_status.type(file_type::unknown); break; default: _dir_entry._symlink_status.type(file_type::unknown); break;
} }
if (_entry->d_type != DT_LNK) { if (_entry->d_type != DT_LNK) {
@ -5554,6 +5626,7 @@ public:
_dir_entry._status.type(file_type::none); _dir_entry._status.type(file_type::none);
_dir_entry._status.permissions(perms::unknown); _dir_entry._status.permissions(perms::unknown);
} }
#endif
_dir_entry._file_size = static_cast<uintmax_t>(-1); _dir_entry._file_size = static_cast<uintmax_t>(-1);
_dir_entry._hard_link_count = static_cast<uintmax_t>(-1); _dir_entry._hard_link_count = static_cast<uintmax_t>(-1);
_dir_entry._last_write_time = 0; _dir_entry._last_write_time = 0;
@ -5567,7 +5640,7 @@ public:
}; };
#endif #endif
// 30.10.13.1 member functions // [fs.dir.itr.members] member functions
GHC_INLINE directory_iterator::directory_iterator() noexcept GHC_INLINE directory_iterator::directory_iterator() noexcept
: _impl(new impl(path(), directory_options::none)) : _impl(new impl(path(), directory_options::none))
{ {
@ -5670,7 +5743,7 @@ GHC_INLINE bool directory_iterator::operator!=(const directory_iterator& rhs) co
return _impl->_dir_entry._path != rhs._impl->_dir_entry._path; return _impl->_dir_entry._path != rhs._impl->_dir_entry._path;
} }
// 30.10.13.2 directory_iterator non-member functions // [fs.dir.itr.nonmembers] directory_iterator non-member functions
GHC_INLINE directory_iterator begin(directory_iterator iter) noexcept GHC_INLINE directory_iterator begin(directory_iterator iter) noexcept
{ {
@ -5683,7 +5756,7 @@ GHC_INLINE directory_iterator end(const directory_iterator&) noexcept
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// 30.10.14 class recursive_directory_iterator // [fs.class.rec.dir.itr] class recursive_directory_iterator
GHC_INLINE recursive_directory_iterator::recursive_directory_iterator() noexcept GHC_INLINE recursive_directory_iterator::recursive_directory_iterator() noexcept
: _impl(new recursive_directory_iterator_impl(directory_options::none, true)) : _impl(new recursive_directory_iterator_impl(directory_options::none, true))
@ -5729,7 +5802,7 @@ GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(recursive_
GHC_INLINE recursive_directory_iterator::~recursive_directory_iterator() {} GHC_INLINE recursive_directory_iterator::~recursive_directory_iterator() {}
// 30.10.14.1 observers // [fs.rec.dir.itr.members] observers
GHC_INLINE directory_options recursive_directory_iterator::options() const GHC_INLINE directory_options recursive_directory_iterator::options() const
{ {
return _impl->_options; return _impl->_options;
@ -5755,7 +5828,7 @@ GHC_INLINE const directory_entry* recursive_directory_iterator::operator->() con
return &(*(_impl->_dir_iter_stack.top())); return &(*(_impl->_dir_iter_stack.top()));
} }
// 30.10.14.1 modifiers recursive_directory_iterator& // [fs.rec.dir.itr.members] modifiers recursive_directory_iterator&
GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator=(const recursive_directory_iterator& rhs) GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator=(const recursive_directory_iterator& rhs)
{ {
_impl = rhs._impl; _impl = rhs._impl;
@ -5782,8 +5855,11 @@ GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator+
GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::increment(std::error_code& ec) noexcept GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::increment(std::error_code& ec) noexcept
{ {
bool isDir = (*this)->is_directory(ec); bool isSymLink = (*this)->is_symlink(ec);
bool isSymLink = !ec && (*this)->is_symlink(ec); bool isDir = !ec && (*this)->is_directory(ec);
if(isSymLink && detail::is_not_found_error(ec)) {
ec.clear();
}
if(!ec) { if(!ec) {
if (recursion_pending() && isDir && (!isSymLink || (options() & directory_options::follow_directory_symlink) != directory_options::none)) { if (recursion_pending() && isDir && (!isSymLink || (options() & directory_options::follow_directory_symlink) != directory_options::none)) {
_impl->_dir_iter_stack.push(directory_iterator((*this)->path(), _impl->_options, ec)); _impl->_dir_iter_stack.push(directory_iterator((*this)->path(), _impl->_options, ec));
@ -5834,7 +5910,7 @@ GHC_INLINE void recursive_directory_iterator::disable_recursion_pending()
_impl->_recursion_pending = false; _impl->_recursion_pending = false;
} }
// other members as required by 27.2.3, input iterators // other members as required by [input.iterators]
GHC_INLINE bool recursive_directory_iterator::operator==(const recursive_directory_iterator& rhs) const GHC_INLINE bool recursive_directory_iterator::operator==(const recursive_directory_iterator& rhs) const
{ {
return _impl->_dir_iter_stack.top() == rhs._impl->_dir_iter_stack.top(); return _impl->_dir_iter_stack.top() == rhs._impl->_dir_iter_stack.top();
@ -5845,7 +5921,7 @@ GHC_INLINE bool recursive_directory_iterator::operator!=(const recursive_directo
return _impl->_dir_iter_stack.top() != rhs._impl->_dir_iter_stack.top(); return _impl->_dir_iter_stack.top() != rhs._impl->_dir_iter_stack.top();
} }
// 30.10.14.2 directory_iterator non-member functions // [fs.rec.dir.itr.nonmembers] directory_iterator non-member functions
GHC_INLINE recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept GHC_INLINE recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept
{ {
return iter; return iter;