48#ifndef GHC_FILESYSTEM_H
49#define GHC_FILESYSTEM_H
51#ifndef GHC_OS_DETECTED
52#if defined(__APPLE__) && defined(__MACH__)
54#elif defined(__linux__)
56#if defined(__ANDROID__)
66#error "Operating system currently not supported!"
68#define GHC_OS_DETECTED
71#if defined(GHC_FILESYSTEM_IMPLEMENTATION)
72#define GHC_EXPAND_IMPL
76#define GHC_FS_API_CLASS
78#define GHC_FS_API __attribute__((visibility("default")))
79#define GHC_FS_API_CLASS __attribute__((visibility("default")))
81#elif defined(GHC_FILESYSTEM_FWD)
84#define GHC_FS_API extern
85#define GHC_FS_API_CLASS
87#define GHC_FS_API extern
88#define GHC_FS_API_CLASS
91#define GHC_EXPAND_IMPL
92#define GHC_INLINE inline
94#define GHC_FS_API_CLASS
104#include <sys/types.h>
111#include <sys/param.h>
113#include <sys/statvfs.h>
115#include <sys/types.h>
118#include <android/api-level.h>
122#include <Availability.h>
137#include <system_error>
138#include <type_traits>
149#include <system_error>
160#define LWG_2682_BEHAVIOUR
167#define LWG_2937_BEHAVIOUR
180#define GHC_FILESYSTEM_VERSION 10207L
183namespace filesystem {
190 : std::logic_error(
"function not implemented yet.")
195template<
typename char_type>
199 using value_type = char_type;
201 static constexpr value_type preferred_separator =
'\\';
203 static constexpr value_type preferred_separator =
'/';
207#if __cplusplus < 201703L
208template <
typename char_type>
214#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_WSTRING_STRING_TYPE)
215#define GHC_USE_WCHAR_T
226 using string_type = std::basic_string<value_type>;
243 template <
class CharT,
class Traits,
class Alloc>
247#ifdef __cpp_lib_string_view
248 template <
class CharT>
254 template <
typename T1,
typename T2 =
void>
255 using path_type =
typename std::enable_if<!std::is_same<path, T1>::value,
path>::type;
256#ifdef GHC_USE_WCHAR_T
257 template <
typename T>
258 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 ||
259 std::is_same<wchar_t const*, typename std::decay<T>::type>::value || std::is_same<wchar_t*, typename std::decay<T>::type>::value,
261 template <
typename T>
262 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,
path>::type;
264 template <
typename T>
265 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,
path>::type;
266 template <
typename T>
267 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;
273 path(string_type&& source, format fmt = auto_format);
274 template <class Source, typename = path_from_string<Source>>
275 path(const Source& source, format fmt = auto_format);
276 template <class InputIterator>
277 path(InputIterator first, InputIterator last, format fmt = auto_format);
278 template <class Source, typename = path_from_string<Source>>
279 path(const Source& source, const std::locale& loc, format fmt = auto_format);
280 template <class InputIterator>
281 path(InputIterator first, InputIterator last, const std::locale& loc, format fmt = auto_format);
287 path& operator=(string_type&& source);
288 path& assign(string_type&& source);
289 template <class Source>
290 path& operator=(const Source& source);
291 template <class Source>
292 path& assign(const Source& source);
293 template <class InputIterator>
294 path& assign(InputIterator first, InputIterator last);
298 template <class Source>
299 path& operator/=(const Source& source);
300 template <class Source>
301 path& append(const Source& source);
302 template <class InputIterator>
303 path& append(InputIterator first, InputIterator last);
307 path& operator+=(const string_type& x);
308#ifdef __cpp_lib_string_view
309 path& operator+=(std::basic_string_view<value_type> x);
311 path& operator+=(
const value_type* x);
312 path& operator+=(value_type x);
313 template <
class Source>
314 path_from_string<Source>& operator+=(
const Source& x);
315 template <
class E
charT>
316 path_type_EcharT<EcharT>& operator+=(EcharT x);
317 template <
class Source>
318 path& concat(
const Source& x);
319 template <
class InputIterator>
320 path& concat(InputIterator first, InputIterator last);
323 void clear() noexcept;
324 path& make_preferred();
325 path& remove_filename();
326 path& replace_filename(const
path& replacement);
327 path& replace_extension(const
path& replacement =
path());
328 void swap(
path& rhs) noexcept;
331 const string_type& native() const;
332 const value_type* c_str() const;
333 operator string_type() const;
334 template <class EcharT, class traits = std::char_traits<EcharT>, class Allocator = std::allocator<EcharT>>
335 std::basic_string<EcharT, traits, Allocator>
string(const Allocator& a = Allocator()) const;
336 std::
string string() const;
337 std::wstring wstring() const;
338 std::
string u8string() const;
339 std::u16string u16string() const;
340 std::u32string u32string() const;
343 template <class EcharT, class traits = std::char_traits<EcharT>, class Allocator = std::allocator<EcharT>>
344 std::basic_string<EcharT, traits, Allocator> generic_string(const Allocator& a = Allocator()) const;
345 const std::
string& generic_string() const;
346 std::wstring generic_wstring() const;
347 std::
string generic_u8string() const;
348 std::u16string generic_u16string() const;
349 std::u32string generic_u32string() const;
352 int compare(const
path& p) const noexcept;
353 int compare(const string_type& s) const;
354#ifdef __cpp_lib_string_view
355 int compare(std::basic_string_view<value_type> s)
const;
357 int compare(
const value_type* s)
const;
360 path root_name()
const;
361 path root_directory()
const;
362 path root_path()
const;
363 path relative_path()
const;
364 path parent_path()
const;
365 path filename()
const;
367 path extension()
const;
370 bool empty() const noexcept;
371 bool has_root_name() const;
372 bool has_root_directory() const;
373 bool has_root_path() const;
374 bool has_relative_path() const;
375 bool has_parent_path() const;
376 bool has_filename() const;
377 bool has_stem() const;
378 bool has_extension() const;
379 bool is_absolute() const;
380 bool is_relative() const;
383 path lexically_normal() const;
384 path lexically_relative(const
path& base) const;
385 path lexically_proximate(const
path& base) const;
389 using const_iterator = iterator;
390 iterator begin() const;
391 iterator end() const;
394 using impl_value_type = std::
string::value_type;
395 using impl_string_type = std::basic_string<impl_value_type>;
397 void append_name(const
char* name);
398 static constexpr impl_value_type generic_separator = '/';
399 template <typename InputIterator>
400 class input_iterator_range
403 typedef InputIterator iterator;
404 typedef InputIterator const_iterator;
405 typedef typename InputIterator::difference_type difference_type;
407 input_iterator_range(
const InputIterator& first,
const InputIterator& last)
413 InputIterator begin()
const {
return _first; }
414 InputIterator end()
const {
return _last; }
417 InputIterator _first;
420 friend void swap(path& lhs, path& rhs)
noexcept;
421 friend size_t hash_value(
const path& p)
noexcept;
422 static void postprocess_path_with_format(impl_string_type& p, format fmt);
423 impl_string_type _path;
425 impl_string_type native_impl()
const;
426 mutable string_type _native_cache;
428 const impl_string_type& native_impl()
const;
433GHC_FS_API
void swap(path& lhs, path& rhs)
noexcept;
434GHC_FS_API
size_t hash_value(
const path& p)
noexcept;
435GHC_FS_API
bool operator==(
const path& lhs,
const path& rhs)
noexcept;
436GHC_FS_API
bool operator!=(
const path& lhs,
const path& rhs)
noexcept;
437GHC_FS_API
bool operator<(
const path& lhs,
const path& rhs)
noexcept;
438GHC_FS_API
bool operator<=(
const path& lhs,
const path& rhs)
noexcept;
439GHC_FS_API
bool operator>(
const path& lhs,
const path& rhs)
noexcept;
440GHC_FS_API
bool operator>=(
const path& lhs,
const path& rhs)
noexcept;
442GHC_FS_API path operator/(
const path& lhs,
const path& rhs);
445template <
class charT,
class traits>
446std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os,
const path& p);
447template <
class charT,
class traits>
448std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, path& p);
451template <
class Source,
typename = path::path_from_
string<Source>>
452path u8path(
const Source& source);
453template <
class InputIterator>
454path u8path(InputIterator first, InputIterator last);
463 const path& path1()
const noexcept;
464 const path& path2()
const noexcept;
465 const char* what()
const noexcept override;
468 std::string _what_arg;
473class GHC_FS_API_CLASS
path::iterator
476 using value_type =
const path;
477 using difference_type = std::ptrdiff_t;
478 using pointer =
const path*;
479 using reference =
const path&;
480 using iterator_category = std::bidirectional_iterator_tag;
483 iterator(
const impl_string_type::const_iterator& first,
const impl_string_type::const_iterator& last,
const impl_string_type::const_iterator& pos);
484 iterator& operator++();
485 iterator operator++(
int);
486 iterator& operator--();
487 iterator operator--(
int);
488 bool operator==(
const iterator& other)
const;
489 bool operator!=(
const iterator& other)
const;
490 reference operator*()
const;
491 pointer operator->()
const;
494 impl_string_type::const_iterator increment(
const std::string::const_iterator& pos)
const;
495 impl_string_type::const_iterator decrement(
const std::string::const_iterator& pos)
const;
496 void updateCurrent();
497 impl_string_type::const_iterator _first;
498 impl_string_type::const_iterator _last;
499 impl_string_type::const_iterator _root;
500 impl_string_type::const_iterator _iter;
512enum class file_type {
525enum class perms : uint16_t {
552enum class perm_options : uint16_t {
559enum class copy_options : uint16_t {
563 overwrite_existing = 2,
568 copy_symlinks = 0x10,
569 skip_symlinks = 0x20,
571 directories_only = 0x40,
572 create_symlinks = 0x80,
573 create_hard_links = 0x100
576enum class directory_options : uint16_t {
578 follow_directory_symlink = 1,
579 skip_permission_denied = 2,
588 explicit file_status(file_type ft, perms prms = perms::unknown)
noexcept;
596 void type(file_type ft)
noexcept;
597 void permissions(perms prms)
noexcept;
599 file_type type()
const noexcept;
600 perms permissions()
const noexcept;
607using file_time_type = std::chrono::time_point<std::chrono::system_clock>;
626 void assign(
const path& p);
627 void assign(
const path& p, std::error_code& ec);
628 void replace_filename(
const path& p);
629 void replace_filename(
const path& p, std::error_code& ec);
631 void refresh(std::error_code& ec)
noexcept;
637 bool exists(std::error_code& ec)
const noexcept;
638 bool is_block_file()
const;
639 bool is_block_file(std::error_code& ec)
const noexcept;
640 bool is_character_file()
const;
641 bool is_character_file(std::error_code& ec)
const noexcept;
642 bool is_directory()
const;
643 bool is_directory(std::error_code& ec)
const noexcept;
644 bool is_fifo()
const;
645 bool is_fifo(std::error_code& ec)
const noexcept;
646 bool is_other()
const;
647 bool is_other(std::error_code& ec)
const noexcept;
648 bool is_regular_file()
const;
649 bool is_regular_file(std::error_code& ec)
const noexcept;
650 bool is_socket()
const;
651 bool is_socket(std::error_code& ec)
const noexcept;
652 bool is_symlink()
const;
653 bool is_symlink(std::error_code& ec)
const noexcept;
654 uintmax_t file_size()
const;
655 uintmax_t file_size(std::error_code& ec)
const noexcept;
656 uintmax_t hard_link_count()
const;
657 uintmax_t hard_link_count(std::error_code& ec)
const noexcept;
658 file_time_type last_write_time()
const;
659 file_time_type last_write_time(std::error_code& ec)
const noexcept;
662 file_status status(std::error_code& ec)
const noexcept;
665 file_status symlink_status(std::error_code& ec)
const noexcept;
678 uintmax_t _file_size = 0;
679#ifndef GHC_OS_WINDOWS
680 uintmax_t _hard_link_count;
682 time_t _last_write_time = 0;
692 const directory_entry& operator*()
const&
noexcept {
return _dir_entry; }
693 directory_entry operator*() &&
noexcept {
return std::move(_dir_entry); }
697 : _dir_entry(dir_entry)
704 using iterator_category = std::input_iterator_tag;
706 using difference_type = std::ptrdiff_t;
727 proxy operator++(
int)
733 bool operator==(
const directory_iterator& rhs)
const;
734 bool operator!=(
const directory_iterator& rhs)
const;
737 friend class recursive_directory_iterator;
739 std::shared_ptr<impl> _impl;
743GHC_FS_API directory_iterator begin(directory_iterator iter)
noexcept;
744GHC_FS_API directory_iterator end(
const directory_iterator&)
noexcept;
750 using iterator_category = std::input_iterator_tag;
752 using difference_type = std::ptrdiff_t;
767 directory_options options()
const;
769 bool recursion_pending()
const;
781 void pop(std::error_code& ec);
782 void disable_recursion_pending();
795 struct recursive_directory_iterator_impl
797 directory_options _options;
798 bool _recursion_pending;
799 std::stack<directory_iterator> _dir_iter_stack;
800 recursive_directory_iterator_impl(directory_options options,
bool recursion_pending)
802 , _recursion_pending(recursion_pending)
806 std::shared_ptr<recursive_directory_iterator_impl> _impl;
814GHC_FS_API
path absolute(
const path& p);
815GHC_FS_API
path absolute(
const path& p, std::error_code& ec);
817GHC_FS_API
path canonical(
const path& p);
818GHC_FS_API
path canonical(
const path& p, std::error_code& ec);
820GHC_FS_API
void copy(
const path& from,
const path& to);
821GHC_FS_API
void copy(
const path& from,
const path& to, std::error_code& ec)
noexcept;
822GHC_FS_API
void copy(
const path& from,
const path& to, copy_options options);
823GHC_FS_API
void copy(
const path& from,
const path& to, copy_options options, std::error_code& ec)
noexcept;
825GHC_FS_API
bool copy_file(
const path& from,
const path& to);
826GHC_FS_API
bool copy_file(
const path& from,
const path& to, std::error_code& ec)
noexcept;
827GHC_FS_API
bool copy_file(
const path& from,
const path& to, copy_options option);
828GHC_FS_API
bool copy_file(
const path& from,
const path& to, copy_options option, std::error_code& ec)
noexcept;
830GHC_FS_API
void copy_symlink(
const path& existing_symlink,
const path& new_symlink);
831GHC_FS_API
void copy_symlink(
const path& existing_symlink,
const path& new_symlink, std::error_code& ec)
noexcept;
833GHC_FS_API
bool create_directories(
const path& p);
834GHC_FS_API
bool create_directories(
const path& p, std::error_code& ec)
noexcept;
836GHC_FS_API
bool create_directory(
const path& p);
837GHC_FS_API
bool create_directory(
const path& p, std::error_code& ec)
noexcept;
839GHC_FS_API
bool create_directory(
const path& p,
const path& attributes);
840GHC_FS_API
bool create_directory(
const path& p,
const path& attributes, std::error_code& ec)
noexcept;
842GHC_FS_API
void create_directory_symlink(
const path& to,
const path& new_symlink);
843GHC_FS_API
void create_directory_symlink(
const path& to,
const path& new_symlink, std::error_code& ec)
noexcept;
845GHC_FS_API
void create_hard_link(
const path& to,
const path& new_hard_link);
846GHC_FS_API
void create_hard_link(
const path& to,
const path& new_hard_link, std::error_code& ec)
noexcept;
848GHC_FS_API
void create_symlink(
const path& to,
const path& new_symlink);
849GHC_FS_API
void create_symlink(
const path& to,
const path& new_symlink, std::error_code& ec)
noexcept;
851GHC_FS_API
path current_path();
852GHC_FS_API
path current_path(std::error_code& ec);
853GHC_FS_API
void current_path(
const path& p);
854GHC_FS_API
void current_path(
const path& p, std::error_code& ec)
noexcept;
857GHC_FS_API
bool exists(
const path& p);
858GHC_FS_API
bool exists(
const path& p, std::error_code& ec)
noexcept;
860GHC_FS_API
bool equivalent(
const path& p1,
const path& p2);
861GHC_FS_API
bool equivalent(
const path& p1,
const path& p2, std::error_code& ec)
noexcept;
863GHC_FS_API uintmax_t file_size(
const path& p);
864GHC_FS_API uintmax_t file_size(
const path& p, std::error_code& ec)
noexcept;
866GHC_FS_API uintmax_t hard_link_count(
const path& p);
867GHC_FS_API uintmax_t hard_link_count(
const path& p, std::error_code& ec)
noexcept;
869GHC_FS_API
bool is_block_file(
file_status s)
noexcept;
870GHC_FS_API
bool is_block_file(
const path& p);
871GHC_FS_API
bool is_block_file(
const path& p, std::error_code& ec)
noexcept;
872GHC_FS_API
bool is_character_file(
file_status s)
noexcept;
873GHC_FS_API
bool is_character_file(
const path& p);
874GHC_FS_API
bool is_character_file(
const path& p, std::error_code& ec)
noexcept;
875GHC_FS_API
bool is_directory(
file_status s)
noexcept;
876GHC_FS_API
bool is_directory(
const path& p);
877GHC_FS_API
bool is_directory(
const path& p, std::error_code& ec)
noexcept;
878GHC_FS_API
bool is_empty(
const path& p);
879GHC_FS_API
bool is_empty(
const path& p, std::error_code& ec)
noexcept;
881GHC_FS_API
bool is_fifo(
const path& p);
882GHC_FS_API
bool is_fifo(
const path& p, std::error_code& ec)
noexcept;
884GHC_FS_API
bool is_other(
const path& p);
885GHC_FS_API
bool is_other(
const path& p, std::error_code& ec)
noexcept;
886GHC_FS_API
bool is_regular_file(
file_status s)
noexcept;
887GHC_FS_API
bool is_regular_file(
const path& p);
888GHC_FS_API
bool is_regular_file(
const path& p, std::error_code& ec)
noexcept;
890GHC_FS_API
bool is_socket(
const path& p);
891GHC_FS_API
bool is_socket(
const path& p, std::error_code& ec)
noexcept;
893GHC_FS_API
bool is_symlink(
const path& p);
894GHC_FS_API
bool is_symlink(
const path& p, std::error_code& ec)
noexcept;
896GHC_FS_API file_time_type last_write_time(
const path& p);
897GHC_FS_API file_time_type last_write_time(
const path& p, std::error_code& ec)
noexcept;
898GHC_FS_API
void last_write_time(
const path& p, file_time_type new_time);
899GHC_FS_API
void last_write_time(
const path& p, file_time_type new_time, std::error_code& ec)
noexcept;
901GHC_FS_API
void permissions(
const path& p, perms prms, perm_options opts = perm_options::replace);
902GHC_FS_API
void permissions(
const path& p, perms prms, std::error_code& ec)
noexcept;
903GHC_FS_API
void permissions(
const path& p, perms prms, perm_options opts, std::error_code& ec);
905GHC_FS_API
path proximate(
const path& p, std::error_code& ec);
906GHC_FS_API
path proximate(
const path& p,
const path& base = current_path());
907GHC_FS_API
path proximate(
const path& p,
const path& base, std::error_code& ec);
909GHC_FS_API
path read_symlink(
const path& p);
910GHC_FS_API
path read_symlink(
const path& p, std::error_code& ec);
912GHC_FS_API
path relative(
const path& p, std::error_code& ec);
913GHC_FS_API
path relative(
const path& p,
const path& base = current_path());
914GHC_FS_API
path relative(
const path& p,
const path& base, std::error_code& ec);
916GHC_FS_API
bool remove(
const path& p);
917GHC_FS_API
bool remove(
const path& p, std::error_code& ec)
noexcept;
919GHC_FS_API uintmax_t remove_all(
const path& p);
920GHC_FS_API uintmax_t remove_all(
const path& p, std::error_code& ec)
noexcept;
922GHC_FS_API
void rename(
const path& from,
const path& to);
923GHC_FS_API
void rename(
const path& from,
const path& to, std::error_code& ec)
noexcept;
925GHC_FS_API
void resize_file(
const path& p, uintmax_t size);
926GHC_FS_API
void resize_file(
const path& p, uintmax_t size, std::error_code& ec)
noexcept;
929GHC_FS_API
space_info space(
const path& p, std::error_code& ec)
noexcept;
932GHC_FS_API
file_status status(
const path& p, std::error_code& ec)
noexcept;
934GHC_FS_API
bool status_known(
file_status s)
noexcept;
937GHC_FS_API
file_status symlink_status(
const path& p, std::error_code& ec)
noexcept;
939GHC_FS_API
path temp_directory_path();
940GHC_FS_API
path temp_directory_path(std::error_code& ec)
noexcept;
942GHC_FS_API
path weakly_canonical(
const path& p);
943GHC_FS_API
path weakly_canonical(
const path& p, std::error_code& ec)
noexcept;
946template <
class charT,
class traits = std::
char_traits<
charT>>
956#if defined(GHC_OS_WINDOWS) && !defined(__GNUC__)
957 return std::basic_filebuf<charT, traits>::open(p.wstring().c_str(), mode) ? this : 0;
959 return std::basic_filebuf<charT, traits>::open(p.string().c_str(), mode) ? this : 0;
964template <
class charT,
class traits = std::
char_traits<
charT>>
969#if defined(GHC_OS_WINDOWS) && !defined(__GNUC__)
970 explicit basic_ifstream(
const path& p, std::ios_base::openmode mode = std::ios_base::in)
971 : std::basic_ifstream<charT, traits>(p.wstring().c_str(), mode)
974 void open(
const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream<charT, traits>::open(p.wstring().c_str(), mode); }
976 explicit basic_ifstream(
const path& p, std::ios_base::openmode mode = std::ios_base::in)
977 : std::basic_ifstream<charT, traits>(p.string().c_str(), mode)
980 void open(
const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream<charT, traits>::open(p.string().c_str(), mode); }
987template <
class charT,
class traits = std::
char_traits<
charT>>
992#if defined(GHC_OS_WINDOWS) && !defined(__GNUC__)
993 explicit basic_ofstream(
const path& p, std::ios_base::openmode mode = std::ios_base::out)
994 : std::basic_ofstream<charT, traits>(p.wstring().c_str(), mode)
997 void open(
const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream<charT, traits>::open(p.wstring().c_str(), mode); }
999 explicit basic_ofstream(
const path& p, std::ios_base::openmode mode = std::ios_base::out)
1000 : std::basic_ofstream<charT, traits>(p.string().c_str(), mode)
1003 void open(
const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream<charT, traits>::open(p.string().c_str(), mode); }
1010template <
class charT,
class traits = std::
char_traits<
charT>>
1015#if defined(GHC_OS_WINDOWS) && !defined(__GNUC__)
1016 explicit basic_fstream(
const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
1017 : std::basic_fstream<charT, traits>(p.wstring().c_str(), mode)
1020 void open(
const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream<charT, traits>::open(p.wstring().c_str(), mode); }
1022 explicit basic_fstream(
const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
1023 : std::basic_fstream<charT, traits>(p.string().c_str(), mode)
1026 void open(
const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream<charT, traits>::open(p.string().c_str(), mode); }
1052 bool valid()
const {
return _isvalid; }
1060#ifdef GHC_OS_WINDOWS
1061 std::vector<std::string> _args;
1062 std::vector<char*> _argp;
1072enum utf8_states_t { S_STRT = 0, S_RJCT = 8 };
1073GHC_FS_API
void appendUTF8(std::string& str, uint32_t unicode);
1074GHC_FS_API
bool is_surrogate(uint32_t c);
1075GHC_FS_API
bool is_high_surrogate(uint32_t c);
1076GHC_FS_API
bool is_low_surrogate(uint32_t c);
1077GHC_FS_API
unsigned consumeUtf8Fragment(
const unsigned state,
const uint8_t fragment, uint32_t& codepoint);
1078enum class portable_error {
1087GHC_FS_API std::error_code make_error_code(portable_error err);
1088#ifdef GHC_OS_WINDOWS
1089GHC_FS_API std::error_code make_system_error(DWORD err = 0);
1091GHC_FS_API std::error_code make_system_error(
int err = 0);
1097#ifdef GHC_EXPAND_IMPL
1099GHC_INLINE std::error_code make_error_code(portable_error err)
1101#ifdef GHC_OS_WINDOWS
1103 case portable_error::none:
1104 return std::error_code();
1105 case portable_error::exists:
1106 return std::error_code(ERROR_ALREADY_EXISTS, std::system_category());
1107 case portable_error::not_found:
1108 return std::error_code(ERROR_PATH_NOT_FOUND, std::system_category());
1109 case portable_error::not_supported:
1110 return std::error_code(ERROR_NOT_SUPPORTED, std::system_category());
1111 case portable_error::not_implemented:
1112 return std::error_code(ERROR_CALL_NOT_IMPLEMENTED, std::system_category());
1113 case portable_error::invalid_argument:
1114 return std::error_code(ERROR_INVALID_PARAMETER, std::system_category());
1115 case portable_error::is_a_directory:
1116#ifdef ERROR_DIRECTORY_NOT_SUPPORTED
1117 return std::error_code(ERROR_DIRECTORY_NOT_SUPPORTED, std::system_category());
1119 return std::error_code(ERROR_NOT_SUPPORTED, std::system_category());
1124 case portable_error::none:
1125 return std::error_code();
1126 case portable_error::exists:
1127 return std::error_code(EEXIST, std::system_category());
1128 case portable_error::not_found:
1129 return std::error_code(ENOENT, std::system_category());
1130 case portable_error::not_supported:
1131 return std::error_code(ENOTSUP, std::system_category());
1132 case portable_error::not_implemented:
1133 return std::error_code(ENOSYS, std::system_category());
1134 case portable_error::invalid_argument:
1135 return std::error_code(EINVAL, std::system_category());
1136 case portable_error::is_a_directory:
1137 return std::error_code(EISDIR, std::system_category());
1140 return std::error_code();
1143#ifdef GHC_OS_WINDOWS
1144GHC_INLINE std::error_code make_system_error(DWORD err)
1146 return std::error_code(err ?
static_cast<int>(err) : static_cast<int>(::GetLastError()), std::system_category());
1149GHC_INLINE std::error_code make_system_error(
int err)
1151 return std::error_code(err ? err : errno, std::system_category());
1157template <
typename Enum>
1158using EnableBitmask =
typename std::enable_if<std::is_same<Enum, perms>::value || std::is_same<Enum, perm_options>::value || std::is_same<Enum, copy_options>::value || std::is_same<Enum, directory_options>::value, Enum>::type;
1161template <
typename Enum>
1162detail::EnableBitmask<Enum> operator&(Enum X, Enum Y)
1164 using underlying =
typename std::underlying_type<Enum>::type;
1165 return static_cast<Enum
>(
static_cast<underlying
>(X) &
static_cast<underlying
>(Y));
1168template <
typename Enum>
1169detail::EnableBitmask<Enum> operator|(Enum X, Enum Y)
1171 using underlying =
typename std::underlying_type<Enum>::type;
1172 return static_cast<Enum
>(
static_cast<underlying
>(X) |
static_cast<underlying
>(Y));
1175template <
typename Enum>
1176detail::EnableBitmask<Enum> operator^(Enum X, Enum Y)
1178 using underlying =
typename std::underlying_type<Enum>::type;
1179 return static_cast<Enum
>(
static_cast<underlying
>(X) ^
static_cast<underlying
>(Y));
1182template <
typename Enum>
1183detail::EnableBitmask<Enum> operator~(Enum X)
1185 using underlying =
typename std::underlying_type<Enum>::type;
1186 return static_cast<Enum
>(~static_cast<underlying>(X));
1189template <
typename Enum>
1190detail::EnableBitmask<Enum>& operator&=(Enum& X, Enum Y)
1196template <
typename Enum>
1197detail::EnableBitmask<Enum>& operator|=(Enum& X, Enum Y)
1203template <
typename Enum>
1204detail::EnableBitmask<Enum>& operator^=(Enum& X, Enum Y)
1210#ifdef GHC_EXPAND_IMPL
1214GHC_INLINE
bool in_range(uint32_t c, uint32_t lo, uint32_t hi)
1216 return (
static_cast<uint32_t
>(c - lo) < (hi - lo + 1));
1219GHC_INLINE
bool is_surrogate(uint32_t c)
1221 return in_range(c, 0xd800, 0xdfff);
1224GHC_INLINE
bool is_high_surrogate(uint32_t c)
1226 return (c & 0xfffffc00) == 0xd800;
1229GHC_INLINE
bool is_low_surrogate(uint32_t c)
1231 return (c & 0xfffffc00) == 0xdc00;
1234GHC_INLINE
void appendUTF8(std::string& str, uint32_t unicode)
1236 if (unicode <= 0x7f) {
1237 str.push_back(
static_cast<char>(unicode));
1239 else if (unicode >= 0x80 && unicode <= 0x7ff) {
1240 str.push_back(
static_cast<char>((unicode >> 6) + 192));
1241 str.push_back(
static_cast<char>((unicode & 0x3f) + 128));
1243 else if ((unicode >= 0x800 && unicode <= 0xd7ff) || (unicode >= 0xe000 && unicode <= 0xffff)) {
1244 str.push_back(
static_cast<char>((unicode >> 12) + 224));
1245 str.push_back(
static_cast<char>(((unicode & 0xfff) >> 6) + 128));
1246 str.push_back(
static_cast<char>((unicode & 0x3f) + 128));
1248 else if (unicode >= 0x10000 && unicode <= 0x10ffff) {
1249 str.push_back(
static_cast<char>((unicode >> 18) + 240));
1250 str.push_back(
static_cast<char>(((unicode & 0x3ffff) >> 12) + 128));
1251 str.push_back(
static_cast<char>(((unicode & 0xfff) >> 6) + 128));
1252 str.push_back(
static_cast<char>((unicode & 0x3f) + 128));
1255#ifdef GHC_RAISE_UNICODE_ERRORS
1256 throw filesystem_error(
"Illegal code point for unicode character.", str, std::make_error_code(std::errc::illegal_byte_sequence));
1258 appendUTF8(str, 0xfffd);
1266GHC_INLINE
unsigned consumeUtf8Fragment(
const unsigned state,
const uint8_t fragment, uint32_t& codepoint)
1268 static const uint32_t utf8_state_info[] = {
1270 0x11111111u, 0x11111111u, 0x77777777u, 0x77777777u, 0x88888888u, 0x88888888u, 0x88888888u, 0x88888888u, 0x22222299u, 0x22222222u, 0x22222222u, 0x22222222u, 0x3333333au, 0x33433333u, 0x9995666bu, 0x99999999u,
1271 0x88888880u, 0x22818108u, 0x88888881u, 0x88888882u, 0x88888884u, 0x88888887u, 0x88888886u, 0x82218108u, 0x82281108u, 0x88888888u, 0x88888883u, 0x88888885u, 0u, 0u, 0u, 0u,
1273 uint8_t category = fragment < 128 ? 0 : (utf8_state_info[(fragment >> 3) & 0xf] >> ((fragment & 7) << 2)) & 0xf;
1274 codepoint = (state ? (codepoint << 6) | (fragment & 0x3fu) : (0xffu >> category) & fragment);
1275 return state == S_RJCT ?
static_cast<unsigned>(S_RJCT) : static_cast<unsigned>((utf8_state_info[category + 16] >> (state << 2)) & 0xf);
1278GHC_INLINE
bool validUtf8(
const std::string& utf8String)
1280 std::string::const_iterator iter = utf8String.begin();
1281 unsigned utf8_state = S_STRT;
1282 std::uint32_t codepoint = 0;
1283 while (iter < utf8String.end()) {
1284 if ((utf8_state = consumeUtf8Fragment(utf8_state,
static_cast<uint8_t
>(*iter++), codepoint)) == S_RJCT) {
1300template <
class StringType,
typename std::enable_if<(sizeof(
typename StringType::value_type) == 1)>::type* =
nullptr>
1301inline StringType fromUtf8(
const std::string& utf8String,
const typename StringType::allocator_type& alloc =
typename StringType::allocator_type())
1303 return StringType(utf8String.begin(), utf8String.end(), alloc);
1306template <
class StringType,
typename std::enable_if<(sizeof(
typename StringType::value_type) == 2)>::type* =
nullptr>
1307inline StringType fromUtf8(
const std::string& utf8String,
const typename StringType::allocator_type& alloc =
typename StringType::allocator_type())
1309 StringType result(alloc);
1310 result.reserve(utf8String.length());
1311 std::string::const_iterator iter = utf8String.begin();
1312 unsigned utf8_state = S_STRT;
1313 std::uint32_t codepoint = 0;
1314 while (iter < utf8String.end()) {
1315 if ((utf8_state = consumeUtf8Fragment(utf8_state,
static_cast<uint8_t
>(*iter++), codepoint)) == S_STRT) {
1316 if (codepoint <= 0xffff) {
1317 result +=
static_cast<typename StringType::value_type
>(codepoint);
1320 codepoint -= 0x10000;
1321 result +=
static_cast<typename StringType::value_type
>((codepoint >> 10) + 0xd800);
1322 result +=
static_cast<typename StringType::value_type
>((codepoint & 0x3ff) + 0xdc00);
1326 else if (utf8_state == S_RJCT) {
1327#ifdef GHC_RAISE_UNICODE_ERRORS
1328 throw filesystem_error(
"Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1330 result +=
static_cast<typename StringType::value_type
>(0xfffd);
1331 utf8_state = S_STRT;
1337#ifdef GHC_RAISE_UNICODE_ERRORS
1338 throw filesystem_error(
"Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1340 result +=
static_cast<typename StringType::value_type
>(0xfffd);
1346template <
class StringType,
typename std::enable_if<(sizeof(
typename StringType::value_type) == 4)>::type* =
nullptr>
1347inline StringType fromUtf8(
const std::string& utf8String,
const typename StringType::allocator_type& alloc =
typename StringType::allocator_type())
1349 StringType result(alloc);
1350 result.reserve(utf8String.length());
1351 std::string::const_iterator iter = utf8String.begin();
1352 unsigned utf8_state = S_STRT;
1353 std::uint32_t codepoint = 0;
1354 while (iter < utf8String.end()) {
1355 if ((utf8_state = consumeUtf8Fragment(utf8_state,
static_cast<uint8_t
>(*iter++), codepoint)) == S_STRT) {
1356 result +=
static_cast<typename StringType::value_type
>(codepoint);
1359 else if (utf8_state == S_RJCT) {
1360#ifdef GHC_RAISE_UNICODE_ERRORS
1361 throw filesystem_error(
"Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1363 result +=
static_cast<typename StringType::value_type
>(0xfffd);
1364 utf8_state = S_STRT;
1370#ifdef GHC_RAISE_UNICODE_ERRORS
1371 throw filesystem_error(
"Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence));
1373 result +=
static_cast<typename StringType::value_type
>(0xfffd);
1379template <
typename charT,
typename traits,
typename Alloc,
typename std::enable_if<(sizeof(
charT) == 1),
int>::type size = 1>
1380inline std::string toUtf8(
const std::basic_string<charT, traits, Alloc>& unicodeString)
1382 return std::string(unicodeString.begin(), unicodeString.end());
1385template <
typename charT,
typename traits,
typename Alloc,
typename std::enable_if<(sizeof(
charT) == 2),
int>::type size = 2>
1386inline std::string toUtf8(
const std::basic_string<charT, traits, Alloc>& unicodeString)
1389 for (
auto iter = unicodeString.begin(); iter != unicodeString.end(); ++iter) {
1391 if (is_surrogate(c)) {
1393 if (iter != unicodeString.end() && is_high_surrogate(c) && is_low_surrogate(*iter)) {
1394 appendUTF8(result, (
char32_t(c) << 10) + *iter - 0x35fdc00);
1397#ifdef GHC_RAISE_UNICODE_ERRORS
1398 throw filesystem_error(
"Illegal code point for unicode character.", result, std::make_error_code(std::errc::illegal_byte_sequence));
1400 appendUTF8(result, 0xfffd);
1401 if(iter == unicodeString.end()) {
1408 appendUTF8(result, c);
1414template <
typename charT,
typename traits,
typename Alloc,
typename std::enable_if<(sizeof(
charT) == 4),
int>::type size = 4>
1415inline std::string toUtf8(
const std::basic_string<charT, traits, Alloc>& unicodeString)
1418 for (
auto c : unicodeString) {
1419 appendUTF8(result,
static_cast<uint32_t
>(c));
1424template <
typename charT>
1425inline std::string toUtf8(
const charT* unicodeString)
1427 return toUtf8(std::basic_string<charT, std::char_traits<charT>>(unicodeString));
1432#ifdef GHC_EXPAND_IMPL
1436GHC_INLINE
bool startsWith(
const std::string& what,
const std::string& with)
1438 return with.length() <= what.length() && equal(with.begin(), with.end(), what.begin());
1443GHC_INLINE
void path::postprocess_path_with_format(path::impl_string_type& p,
path::format fmt)
1445#ifdef GHC_RAISE_UNICODE_ERRORS
1446 if(!detail::validUtf8(p)) {
1449 throw filesystem_error(
"Illegal byte sequence for unicode character.", t, std::make_error_code(std::errc::illegal_byte_sequence));
1453#ifndef GHC_OS_WINDOWS
1460#ifdef GHC_OS_WINDOWS
1463 if (detail::startsWith(p, std::string(
"\\\\?\\"))) {
1466 if (detail::startsWith(p, std::string(
"UNC\\"))) {
1479 if (p.length() > 2 && p[0] ==
'/' && p[1] ==
'/' && p[2] !=
'/') {
1480 std::string::iterator new_end = std::unique(p.begin() + 2, p.end(), [](path::value_type lhs, path::value_type rhs) { return lhs == rhs && lhs ==
'/'; });
1481 p.erase(new_end, p.end());
1484 std::string::iterator new_end = std::unique(p.begin(), p.end(), [](path::value_type lhs, path::value_type rhs) { return lhs == rhs && lhs ==
'/'; });
1485 p.erase(new_end, p.end());
1491template <
class Source,
typename>
1492inline path::path(
const Source& source, format fmt)
1493 : _path(detail::toUtf8(source))
1495 postprocess_path_with_format(_path, fmt);
1498inline path::path(
const std::wstring& source, format fmt)
1500 _path = detail::toUtf8(source);
1501 postprocess_path_with_format(_path, fmt);
1504inline path::path(
const std::u16string& source, format fmt)
1506 _path = detail::toUtf8(source);
1507 postprocess_path_with_format(_path, fmt);
1510inline path::path(
const std::u32string& source, format fmt)
1512 _path = detail::toUtf8(source);
1513 postprocess_path_with_format(_path, fmt);
1516#ifdef __cpp_lib_string_view
1518inline path::path(
const std::string_view& source, format fmt)
1520 _path = detail::toUtf8(std::string(source));
1521 postprocess_path_with_format(_path, fmt);
1525template <
class Source,
typename>
1526inline path u8path(
const Source& source)
1528 return path(source);
1530template <
class InputIterator>
1531inline path u8path(InputIterator first, InputIterator last)
1533 return path(first, last);
1536template <
class InputIterator>
1537inline path::path(InputIterator first, InputIterator last, format fmt)
1538 : path(std::basic_string<typename std::iterator_traits<InputIterator>::value_type>(first, last), fmt)
1543#ifdef GHC_EXPAND_IMPL
1547GHC_INLINE
bool equals_simple_insensitive(
const char* str1,
const char* str2)
1549#ifdef GHC_OS_WINDOWS
1551 while (::tolower((
unsigned char)*str1) == ::tolower((
unsigned char)*str2++)) {
1557 return 0 == ::_stricmp(str1, str2);
1560 return 0 == ::strcasecmp(str1, str2);
1564GHC_INLINE
const char* strerror_adapter(
char* gnu,
char*)
1569GHC_INLINE
const char* strerror_adapter(
int posix,
char* buffer)
1572 return "Error in strerror_r!";
1577template <
typename ErrorNumber>
1578GHC_INLINE std::string systemErrorText(ErrorNumber code = 0)
1580#if defined(GHC_OS_WINDOWS)
1582 DWORD dw = code ?
static_cast<DWORD
>(code) : ::GetLastError();
1583 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&msgBuf, 0, NULL);
1584 std::string msg = toUtf8(std::wstring((LPWSTR)msgBuf));
1589 return strerror_adapter(strerror_r(code ? code : errno, buffer, sizeof(buffer)), buffer);
1593#ifdef GHC_OS_WINDOWS
1594using CreateSymbolicLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR, DWORD);
1595using CreateHardLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
1597GHC_INLINE
void create_symlink(
const path& target_name,
const path& new_symlink,
bool to_directory, std::error_code& ec)
1599 std::error_code tec;
1600 auto fs = status(target_name, tec);
1601 if ((fs.type() == file_type::directory && !to_directory) || (fs.type() == file_type::regular && to_directory)) {
1602 ec = detail::make_error_code(detail::portable_error::not_supported);
1605 static CreateSymbolicLinkW_fp api_call =
reinterpret_cast<CreateSymbolicLinkW_fp
>(GetProcAddress(GetModuleHandleW(L
"kernel32.dll"),
"CreateSymbolicLinkW"));
1607 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) {
1608 auto result = ::GetLastError();
1609 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) {
1612 ec = detail::make_system_error(result);
1616 ec = detail::make_system_error(ERROR_NOT_SUPPORTED);
1620GHC_INLINE
void create_hardlink(
const path& target_name,
const path& new_hardlink, std::error_code& ec)
1622 static CreateHardLinkW_fp api_call =
reinterpret_cast<CreateHardLinkW_fp
>(GetProcAddress(GetModuleHandleW(L
"kernel32.dll"),
"CreateHardLinkW"));
1624 if (api_call(detail::fromUtf8<std::wstring>(new_hardlink.u8string()).c_str(), detail::fromUtf8<std::wstring>(target_name.u8string()).c_str(), NULL) == 0) {
1625 ec = detail::make_system_error();
1629 ec = detail::make_system_error(ERROR_NOT_SUPPORTED);
1633GHC_INLINE
void create_symlink(
const path& target_name,
const path& new_symlink,
bool, std::error_code& ec)
1635 if (::symlink(target_name.c_str(), new_symlink.c_str()) != 0) {
1636 ec = detail::make_system_error();
1640GHC_INLINE
void create_hardlink(
const path& target_name,
const path& new_hardlink, std::error_code& ec)
1642 if (::link(target_name.c_str(), new_hardlink.c_str()) != 0) {
1643 ec = detail::make_system_error();
1648template <
typename T>
1649GHC_INLINE file_status file_status_from_st_mode(T mode)
1651#ifdef GHC_OS_WINDOWS
1652 file_type ft = file_type::unknown;
1653 if ((mode & _S_IFDIR) == _S_IFDIR) {
1654 ft = file_type::directory;
1656 else if ((mode & _S_IFREG) == _S_IFREG) {
1657 ft = file_type::regular;
1659 else if ((mode & _S_IFCHR) == _S_IFCHR) {
1660 ft = file_type::character;
1662 perms prms =
static_cast<perms
>(mode & 0xfff);
1663 return file_status(ft, prms);
1665 file_type ft = file_type::unknown;
1666 if (S_ISDIR(mode)) {
1667 ft = file_type::directory;
1669 else if (S_ISREG(mode)) {
1670 ft = file_type::regular;
1672 else if (S_ISCHR(mode)) {
1673 ft = file_type::character;
1675 else if (S_ISBLK(mode)) {
1676 ft = file_type::block;
1678 else if (S_ISFIFO(mode)) {
1679 ft = file_type::fifo;
1681 else if (S_ISLNK(mode)) {
1682 ft = file_type::symlink;
1684 else if (S_ISSOCK(mode)) {
1685 ft = file_type::socket;
1687 perms prms =
static_cast<perms
>(mode & 0xfff);
1688 return file_status(ft, prms);
1692GHC_INLINE path resolveSymlink(
const path& p, std::error_code& ec)
1694#ifdef GHC_OS_WINDOWS
1695#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE
1696 typedef struct _REPARSE_DATA_BUFFER
1699 USHORT ReparseDataLength;
1705 USHORT SubstituteNameOffset;
1706 USHORT SubstituteNameLength;
1707 USHORT PrintNameOffset;
1708 USHORT PrintNameLength;
1710 WCHAR PathBuffer[1];
1711 } SymbolicLinkReparseBuffer;
1714 USHORT SubstituteNameOffset;
1715 USHORT SubstituteNameLength;
1716 USHORT PrintNameOffset;
1717 USHORT PrintNameLength;
1718 WCHAR PathBuffer[1];
1719 } MountPointReparseBuffer;
1722 UCHAR DataBuffer[1];
1723 } GenericReparseBuffer;
1725 } REPARSE_DATA_BUFFER;
1726#ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
1727#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024)
1731 std::shared_ptr<void> file(CreateFileW(p.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
1732 if (file.get() == INVALID_HANDLE_VALUE) {
1733 ec = detail::make_system_error();
1737 std::shared_ptr<REPARSE_DATA_BUFFER> reparseData((REPARSE_DATA_BUFFER*)std::calloc(1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE), std::free);
1740 if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0, reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bufferUsed, 0)) {
1741 if (IsReparseTagMicrosoft(reparseData->ReparseTag)) {
1742 switch (reparseData->ReparseTag) {
1743 case IO_REPARSE_TAG_SYMLINK:
1744 result = std::wstring(&reparseData->SymbolicLinkReparseBuffer.PathBuffer[reparseData->SymbolicLinkReparseBuffer.PrintNameOffset /
sizeof(WCHAR)], reparseData->SymbolicLinkReparseBuffer.PrintNameLength /
sizeof(WCHAR));
1746 case IO_REPARSE_TAG_MOUNT_POINT:
1747 result = std::wstring(&reparseData->MountPointReparseBuffer.PathBuffer[reparseData->MountPointReparseBuffer.PrintNameOffset /
sizeof(WCHAR)], reparseData->MountPointReparseBuffer.PrintNameLength /
sizeof(WCHAR));
1755 ec = detail::make_system_error();
1759 size_t bufferSize = 256;
1761 std::vector<char> buffer(bufferSize,
static_cast<char>(0));
1762 auto rc = ::readlink(p.c_str(), buffer.data(), buffer.size());
1764 ec = detail::make_system_error();
1767 else if (rc <
static_cast<int>(bufferSize)) {
1768 return path(std::string(buffer.data(),
static_cast<std::string::size_type
>(rc)));
1776#ifdef GHC_OS_WINDOWS
1777GHC_INLINE time_t timeFromFILETIME(
const FILETIME& ft)
1780 ull.LowPart = ft.dwLowDateTime;
1781 ull.HighPart = ft.dwHighDateTime;
1782 return static_cast<time_t
>(ull.QuadPart / 10000000ULL - 11644473600ULL);
1785GHC_INLINE
void timeToFILETIME(time_t t, FILETIME& ft)
1788 ll = Int32x32To64(t, 10000000) + 116444736000000000;
1789 ft.dwLowDateTime =
static_cast<DWORD
>(ll);
1790 ft.dwHighDateTime =
static_cast<DWORD
>(ll >> 32);
1793template <
typename INFO>
1794GHC_INLINE uintmax_t hard_links_from_INFO(
const INFO* info)
1796 return static_cast<uintmax_t
>(-1);
1800GHC_INLINE uintmax_t hard_links_from_INFO<BY_HANDLE_FILE_INFORMATION>(
const BY_HANDLE_FILE_INFORMATION* info)
1802 return info->nNumberOfLinks;
1805template <
typename INFO>
1806GHC_INLINE file_status status_from_INFO(
const path& p,
const INFO* info, std::error_code&, uintmax_t* sz =
nullptr, time_t* lwt =
nullptr) noexcept
1808 file_type ft = file_type::unknown;
1809 if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
1810 ft = file_type::symlink;
1813 if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
1814 ft = file_type::directory;
1817 ft = file_type::regular;
1820 perms prms = perms::owner_read | perms::group_read | perms::others_read;
1821 if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
1822 prms = prms | perms::owner_write | perms::group_write | perms::others_write;
1824 std::string ext = p.extension().generic_string();
1825 if (equals_simple_insensitive(ext.c_str(),
".exe") || equals_simple_insensitive(ext.c_str(),
".cmd") || equals_simple_insensitive(ext.c_str(),
".bat") || equals_simple_insensitive(ext.c_str(),
".com")) {
1826 prms = prms | perms::owner_exec | perms::group_exec | perms::others_exec;
1829 *sz =
static_cast<uintmax_t
>(info->nFileSizeHigh) << (
sizeof(info->nFileSizeHigh) * 8) | info->nFileSizeLow;
1832 *lwt = detail::timeFromFILETIME(info->ftLastWriteTime);
1834 return file_status(ft, prms);
1839GHC_INLINE
bool is_not_found_error(std::error_code& ec)
1841#ifdef GHC_OS_WINDOWS
1842 return ec.value() == ERROR_FILE_NOT_FOUND || ec.value() == ERROR_PATH_NOT_FOUND || ec.value() == ERROR_INVALID_NAME;
1844 return ec.value() == ENOENT || ec.value() == ENOTDIR;
1848GHC_INLINE file_status symlink_status_ex(
const path& p, std::error_code& ec, uintmax_t* sz =
nullptr, uintmax_t* nhl =
nullptr, time_t* lwt =
nullptr) noexcept
1850#ifdef GHC_OS_WINDOWS
1852 WIN32_FILE_ATTRIBUTE_DATA attr;
1853 if (!GetFileAttributesExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GetFileExInfoStandard, &attr)) {
1854 ec = detail::make_system_error();
1858 fs = detail::status_from_INFO(p, &attr, ec, sz, lwt);
1862 if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1863 fs.type(file_type::symlink);
1866 if (detail::is_not_found_error(ec)) {
1867 return file_status(file_type::not_found);
1869 return ec ? file_status(file_type::none) : fs;
1875 auto result = ::lstat(p.c_str(), &fs);
1878 file_status f_s = detail::file_status_from_st_mode(fs.st_mode);
1881 ec = detail::make_system_error();
1882 if (detail::is_not_found_error(ec)) {
1883 return file_status(file_type::not_found, perms::unknown);
1885 return file_status(file_type::none);
1889GHC_INLINE file_status status_ex(
const path& p, std::error_code& ec, file_status* sls =
nullptr, uintmax_t* sz =
nullptr, uintmax_t* nhl =
nullptr, time_t* lwt =
nullptr,
int recurse_count = 0) noexcept
1892#ifdef GHC_OS_WINDOWS
1893 if (recurse_count > 16) {
1894 ec = detail::make_system_error(0x2A9 );
1895 return file_status(file_type::unknown);
1897 WIN32_FILE_ATTRIBUTE_DATA attr;
1898 if (!::GetFileAttributesExW(p.wstring().c_str(), GetFileExInfoStandard, &attr)) {
1899 ec = detail::make_system_error();
1901 else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1902 path target = resolveSymlink(p, ec);
1904 if (!ec && !target.empty()) {
1906 *sls = status_from_INFO(p, &attr, ec);
1908 return detail::status_ex(target, ec,
nullptr, sz, nhl, lwt, recurse_count + 1);
1910 return file_status(file_type::unknown);
1913 if (detail::is_not_found_error(ec)) {
1914 return file_status(file_type::not_found);
1916 return file_status(file_type::none);
1921 return detail::status_from_INFO(p, &attr, ec, sz, lwt);
1923 (void)recurse_count;
1925 auto result = ::lstat(p.c_str(), &st);
1928 file_status fs = detail::file_status_from_st_mode(st.st_mode);
1929 if (fs.type() == file_type::symlink) {
1930 result = ::stat(p.c_str(), &st);
1935 fs = detail::file_status_from_st_mode(st.st_mode);
1939 *sz =
static_cast<uintmax_t
>(st.st_size);
1950 ec = detail::make_system_error();
1951 if (detail::is_not_found_error(ec)) {
1952 return file_status(file_type::not_found, perms::unknown);
1954 return file_status(file_type::none);
1961GHC_INLINE u8arguments::u8arguments(
int& argc,
char**& argv)
1968#ifdef GHC_OS_WINDOWS
1970 p = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
1971 _args.reserve(
static_cast<size_t>(argc));
1972 _argp.reserve(
static_cast<size_t>(argc));
1973 for (
size_t i = 0; i < static_cast<size_t>(argc); ++i) {
1974 _args.push_back(detail::toUtf8(std::wstring(p[i])));
1975 _argp.push_back((
char*)_args[i].data());
1977 argv = _argp.data();
1981 std::setlocale(LC_ALL,
"");
1982#if defined(__ANDROID__) && __ANDROID_API__ < 26
1985 if (detail::equals_simple_insensitive(::nl_langinfo(CODESET),
"UTF-8")) {
1995GHC_INLINE path::path() noexcept {}
1997GHC_INLINE path::path(
const path& p)
2002GHC_INLINE path::path(path&& p) noexcept
2003 : _path(std::move(p._path))
2007GHC_INLINE path::path(string_type&& source, format fmt)
2008#ifdef GHC_USE_WCHAR_T
2009 : _path(detail::toUtf8(source))
2011 : _path(std::move(source))
2014 postprocess_path_with_format(_path, fmt);
2019template <
class Source,
typename>
2020inline path::path(
const Source& source,
const std::locale& loc, format fmt)
2023 std::string locName = loc.name();
2024 if (!(locName.length() >= 5 && (locName.substr(locName.length() - 5) ==
"UTF-8" || locName.substr(locName.length() - 5) ==
"utf-8"))) {
2025 throw filesystem_error(
"This implementation only supports UTF-8 locales!", path(_path), detail::make_error_code(detail::portable_error::not_supported));
2029template <
class InputIterator>
2030inline path::path(InputIterator first, InputIterator last,
const std::locale& loc, format fmt)
2031 : path(std::basic_string<typename std::iterator_traits<InputIterator>::value_type>(first, last), fmt)
2033 std::string locName = loc.name();
2034 if (!(locName.length() >= 5 && (locName.substr(locName.length() - 5) ==
"UTF-8" || locName.substr(locName.length() - 5) ==
"utf-8"))) {
2035 throw filesystem_error(
"This implementation only supports UTF-8 locales!", path(_path), detail::make_error_code(detail::portable_error::not_supported));
2039#ifdef GHC_EXPAND_IMPL
2041GHC_INLINE path::~path() {}
2046GHC_INLINE path& path::operator=(
const path& p)
2052GHC_INLINE path& path::operator=(path&& p)
noexcept
2054 _path = std::move(p._path);
2058GHC_INLINE path& path::operator=(path::string_type&& source)
2060 return assign(source);
2063GHC_INLINE path& path::assign(path::string_type&& source)
2065#ifdef GHC_USE_WCHAR_T
2066 _path = detail::toUtf8(source);
2068 _path = std::move(source);
2076template <
class Source>
2077inline path& path::operator=(
const Source& source)
2079 return assign(source);
2082template <
class Source>
2083inline path& path::assign(
const Source& source)
2085 _path.assign(detail::toUtf8(source));
2091inline path& path::assign<path>(
const path& source)
2093 _path = source._path;
2097template <
class InputIterator>
2098inline path& path::assign(InputIterator first, InputIterator last)
2100 _path.assign(first, last);
2105#ifdef GHC_EXPAND_IMPL
2110GHC_INLINE path& path::operator/=(
const path& p)
2114 if (!_path.empty() && _path[_path.length() - 1] !=
'/' && _path[_path.length() - 1] !=
':') {
2119 if ((p.is_absolute() && (_path != root_name() || p._path !=
"/")) || (p.has_root_name() && p.root_name() != root_name())) {
2123 if (p.has_root_directory()) {
2124 assign(root_name());
2126 else if ((!has_root_directory() && is_absolute()) || has_filename()) {
2129 auto iter = p.begin();
2131 if (p.has_root_name()) {
2134 while (iter != p.end()) {
2135 if (!first && !(!_path.empty() && _path[_path.length() - 1] ==
'/')) {
2139 _path += (*iter++).generic_string();
2144GHC_INLINE
void path::append_name(
const char* name)
2146 if (_path.empty()) {
2147 this->operator/=(path(name));
2150 if (_path.back() != path::generic_separator) {
2151 _path.push_back(path::generic_separator);
2159template <
class Source>
2160inline path& path::operator/=(
const Source& source)
2162 return append(source);
2165template <
class Source>
2166inline path& path::append(
const Source& source)
2168 return this->operator/=(path(detail::toUtf8(source)));
2172inline path& path::append<path>(
const path& p)
2174 return this->operator/=(p);
2177template <
class InputIterator>
2178inline path& path::append(InputIterator first, InputIterator last)
2180 std::basic_string<typename std::iterator_traits<InputIterator>::value_type> part(first, last);
2181 return append(part);
2184#ifdef GHC_EXPAND_IMPL
2189GHC_INLINE path& path::operator+=(
const path& x)
2191 return concat(x._path);
2194GHC_INLINE path& path::operator+=(
const string_type& x)
2199#ifdef __cpp_lib_string_view
2200GHC_INLINE path& path::operator+=(std::basic_string_view<value_type> x)
2206GHC_INLINE path& path::operator+=(
const value_type* x)
2208 return concat(string_type(x));
2211GHC_INLINE path& path::operator+=(value_type x)
2213#ifdef GHC_OS_WINDOWS
2215 x = generic_separator;
2218 if (_path.empty() || _path.back() != generic_separator) {
2219#ifdef GHC_USE_WCHAR_T
2220 _path += detail::toUtf8(string_type(1, x));
2230template <
class Source>
2231inline path::path_from_string<Source>& path::operator+=(
const Source& x)
2236template <
class E
charT>
2237inline path::path_type_EcharT<EcharT>& path::operator+=(EcharT x)
2239 std::basic_string<EcharT> part(1, x);
2240 concat(detail::toUtf8(part));
2244template <
class Source>
2245inline path& path::concat(
const Source& x)
2252template <
class InputIterator>
2253inline path& path::concat(InputIterator first, InputIterator last)
2255 _path.append(first, last);
2260#ifdef GHC_EXPAND_IMPL
2264GHC_INLINE
void path::clear() noexcept
2269GHC_INLINE path& path::make_preferred()
2276GHC_INLINE path& path::remove_filename()
2278 if (has_filename()) {
2279 _path.erase(_path.size() - filename()._path.size());
2284GHC_INLINE path& path::replace_filename(
const path& replacement)
2287 return append(replacement);
2290GHC_INLINE path& path::replace_extension(
const path& replacement)
2292 if (has_extension()) {
2293 _path.erase(_path.size() - extension()._path.size());
2295 if (!replacement.empty() && replacement._path[0] !=
'.') {
2298 return concat(replacement);
2301GHC_INLINE
void path::swap(path& rhs)
noexcept
2303 _path.swap(rhs._path);
2308#ifdef GHC_OS_WINDOWS
2309GHC_INLINE path::impl_string_type path::native_impl()
const
2311 impl_string_type result;
2312 if (is_absolute() && _path.length() > MAX_PATH - 10) {
2314 if (has_root_name() && _path[0] ==
'/') {
2315 result =
"\\\\?\\UNC" + _path.substr(1);
2318 result =
"\\\\?\\" + _path;
2327 for (
auto& c : result) {
2335GHC_INLINE
const path::impl_string_type& path::native_impl()
const
2341GHC_INLINE
const path::string_type& path::native()
const
2343#ifdef GHC_OS_WINDOWS
2344#ifdef GHC_USE_WCHAR_T
2345 _native_cache = detail::fromUtf8<string_type>(native_impl());
2347 _native_cache = native_impl();
2349 return _native_cache;
2355GHC_INLINE
const path::value_type* path::c_str()
const
2357 return native().c_str();
2360GHC_INLINE path::operator path::string_type()
const
2367template <
class E
charT,
class traits,
class Allocator>
2368inline std::basic_string<EcharT, traits, Allocator> path::string(
const Allocator& a)
const
2370 return detail::fromUtf8<std::basic_string<EcharT, traits, Allocator>>(native_impl(), a);
2373#ifdef GHC_EXPAND_IMPL
2375GHC_INLINE std::string path::string()
const
2377 return native_impl();
2380GHC_INLINE std::wstring path::wstring()
const
2382#ifdef GHC_USE_WCHAR_T
2385 return detail::fromUtf8<std::wstring>(native());
2389GHC_INLINE std::string path::u8string()
const
2391 return native_impl();
2394GHC_INLINE std::u16string path::u16string()
const
2396 return detail::fromUtf8<std::u16string>(native_impl());
2399GHC_INLINE std::u32string path::u32string()
const
2401 return detail::fromUtf8<std::u32string>(native_impl());
2408template <
class E
charT,
class traits,
class Allocator>
2409inline std::basic_string<EcharT, traits, Allocator> path::generic_string(
const Allocator& a)
const
2411 return detail::fromUtf8<std::basic_string<EcharT, traits, Allocator>>(_path, a);
2414#ifdef GHC_EXPAND_IMPL
2416GHC_INLINE
const std::string& path::generic_string()
const
2421GHC_INLINE std::wstring path::generic_wstring()
const
2423 return detail::fromUtf8<std::wstring>(_path);
2426GHC_INLINE std::string path::generic_u8string()
const
2431GHC_INLINE std::u16string path::generic_u16string()
const
2433 return detail::fromUtf8<std::u16string>(_path);
2436GHC_INLINE std::u32string path::generic_u32string()
const
2438 return detail::fromUtf8<std::u32string>(_path);
2443GHC_INLINE
int path::compare(
const path& p)
const noexcept
2445 return native().compare(p.native());
2448GHC_INLINE
int path::compare(
const string_type& s)
const
2450 return native().compare(path(s).native());
2453#ifdef __cpp_lib_string_view
2454GHC_INLINE
int path::compare(std::basic_string_view<value_type> s)
const
2456 return native().compare(path(s).native());
2460GHC_INLINE
int path::compare(
const value_type* s)
const
2462 return native().compare(path(s).native());
2467GHC_INLINE path path::root_name()
const
2469#ifdef GHC_OS_WINDOWS
2470 if (_path.length() >= 2 && std::toupper(
static_cast<unsigned char>(_path[0])) >=
'A' && std::toupper(
static_cast<unsigned char>(_path[0])) <=
'Z' && _path[1] ==
':') {
2471 return path(_path.substr(0, 2));
2474 if (_path.length() > 2 && _path[0] ==
'/' && _path[1] ==
'/' && _path[2] !=
'/' && std::isprint(_path[2])) {
2475 impl_string_type::size_type pos = _path.find_first_of(
"/\\", 3);
2476 if (pos == impl_string_type::npos) {
2480 return path(_path.substr(0, pos));
2486GHC_INLINE path path::root_directory()
const
2488 path root = root_name();
2489 if (_path.length() > root._path.length() && _path[root._path.length()] ==
'/') {
2495GHC_INLINE path path::root_path()
const
2497 return root_name().generic_string() + root_directory().generic_string();
2500GHC_INLINE path path::relative_path()
const
2502 std::string root = root_path()._path;
2503 return path(_path.substr((std::min)(root.length(), _path.length())),
generic_format);
2506GHC_INLINE path path::parent_path()
const
2508 if (has_relative_path()) {
2509 if (empty() || begin() == --end()) {
2514 for (string_type s : input_iterator_range<iterator>(begin(), --end())) {
2531GHC_INLINE path path::filename()
const
2533 return relative_path().empty() ? path() : path(*--end());
2536GHC_INLINE path path::stem()
const
2538 impl_string_type fn = filename().string();
2539 if (fn !=
"." && fn !=
"..") {
2540 impl_string_type::size_type n = fn.rfind(
".");
2541 if (n != impl_string_type::npos && n != 0) {
2542 return fn.substr(0, n);
2548GHC_INLINE path path::extension()
const
2550 impl_string_type fn = filename().string();
2551 impl_string_type::size_type pos = fn.find_last_of(
'.');
2552 if (pos == std::string::npos || pos == 0) {
2555 return fn.substr(pos);
2560GHC_INLINE
bool path::empty() const noexcept
2562 return _path.empty();
2565GHC_INLINE
bool path::has_root_name()
const
2567 return !root_name().empty();
2570GHC_INLINE
bool path::has_root_directory()
const
2572 return !root_directory().empty();
2575GHC_INLINE
bool path::has_root_path()
const
2577 return !root_path().empty();
2580GHC_INLINE
bool path::has_relative_path()
const
2582 return !relative_path().empty();
2585GHC_INLINE
bool path::has_parent_path()
const
2587 return !parent_path().empty();
2590GHC_INLINE
bool path::has_filename()
const
2592 return !filename().empty();
2595GHC_INLINE
bool path::has_stem()
const
2597 return !stem().empty();
2600GHC_INLINE
bool path::has_extension()
const
2602 return !extension().empty();
2605GHC_INLINE
bool path::is_absolute()
const
2607#ifdef GHC_OS_WINDOWS
2608 return has_root_name() && has_root_directory();
2610 return has_root_directory();
2614GHC_INLINE
bool path::is_relative()
const
2616 return !is_absolute();
2621GHC_INLINE path path::lexically_normal()
const
2624 bool lastDotDot =
false;
2625 for (string_type s : *this) {
2630 else if (s ==
".." && !dest.empty()) {
2631 auto root = root_path();
2635 else if (*(--dest.end()) !=
"..") {
2636 if (dest._path.back() == generic_separator) {
2637 dest._path.pop_back();
2639 dest.remove_filename();
2643 if (!(s.empty() && lastDotDot)) {
2646 lastDotDot = s ==
"..";
2654GHC_INLINE path path::lexically_relative(
const path& base)
const
2656 if (root_name() != base.root_name() || is_absolute() != base.is_absolute() || (!has_root_directory() && base.has_root_directory())) {
2659 const_iterator a = begin(), b = base.begin();
2660 while (a != end() && b != base.end() && *a == *b) {
2664 if (a == end() && b == base.end()) {
2668 for (
const auto& element : input_iterator_range<const_iterator>(b, base.end())) {
2669 if (element !=
"." && element !=
"..") {
2672 else if (element ==
"..") {
2680 for (
int i = 0; i < count; ++i) {
2683 for (
const auto& element : input_iterator_range<const_iterator>(a, end())) {
2689GHC_INLINE path path::lexically_proximate(
const path& base)
const
2691 path result = lexically_relative(base);
2692 return result.empty() ? *this : result;
2697GHC_INLINE path::iterator::iterator() {}
2699GHC_INLINE path::iterator::iterator(
const path::impl_string_type::const_iterator& first,
const path::impl_string_type::const_iterator& last,
const path::impl_string_type::const_iterator& pos)
2706#ifdef GHC_OS_WINDOWS
2707 if (_last - _first >= 3 && std::toupper(
static_cast<unsigned char>(*first)) >=
'A' && std::toupper(
static_cast<unsigned char>(*first)) <=
'Z' && *(first + 1) ==
':' && *(first + 2) ==
'/') {
2713 if (_first != _last && *_first ==
'/') {
2714 if (_last - _first >= 2 && *(_first + 1) ==
'/' && !(_last - _first >= 3 && *(_first + 2) ==
'/')) {
2715 _root = increment(_first);
2727GHC_INLINE path::impl_string_type::const_iterator path::iterator::increment(
const path::impl_string_type::const_iterator& pos)
const
2729 path::impl_string_type::const_iterator i = pos;
2730 bool fromStart = i == _first;
2734 if (i != _last && *i ==
'/') {
2735 if (fromStart && !(i + 1 != _last && *(i + 1) ==
'/')) {
2738 i = std::find(++i, _last,
'/');
2742 while (i != _last && *i ==
'/') {
2749 if (fromStart && i != _last && *i ==
':') {
2753 i = std::find(i, _last,
'/');
2760GHC_INLINE path::impl_string_type::const_iterator path::iterator::decrement(
const path::impl_string_type::const_iterator& pos)
const
2762 path::impl_string_type::const_iterator i = pos;
2767 if (i != _root && (pos != _last || *i !=
'/')) {
2768#ifdef GHC_OS_WINDOWS
2769 static const std::string seps =
"/:";
2770 i = std::find_first_of(std::reverse_iterator<path::impl_string_type::const_iterator>(i), std::reverse_iterator<path::impl_string_type::const_iterator>(_first), seps.begin(), seps.end()).base();
2771 if (i > _first && *i ==
':') {
2775 i = std::find(std::reverse_iterator<path::impl_string_type::const_iterator>(i), std::reverse_iterator<path::impl_string_type::const_iterator>(_first),
'/').base();
2778 if (i - _first == 2 && *_first ==
'/' && *(_first + 1) ==
'/') {
2786GHC_INLINE
void path::iterator::updateCurrent()
2788 if (_iter != _first && _iter != _last && (*_iter ==
'/' && _iter != _root) && (_iter + 1 == _last)) {
2792 _current.assign(_iter, increment(_iter));
2793 if (_current.generic_string().size() > 1 && _current.generic_string()[0] ==
'/' && _current.generic_string()[_current.generic_string().size() - 1] ==
'/') {
2800GHC_INLINE path::iterator& path::iterator::operator++()
2802 _iter = increment(_iter);
2803 while (_iter != _last &&
2806 (_iter + 1) != _last
2814GHC_INLINE path::iterator path::iterator::operator++(
int)
2816 path::iterator i{*
this};
2821GHC_INLINE path::iterator& path::iterator::operator--()
2823 _iter = decrement(_iter);
2828GHC_INLINE path::iterator path::iterator::operator--(
int)
2835GHC_INLINE
bool path::iterator::operator==(
const path::iterator& other)
const
2837 return _iter == other._iter;
2840GHC_INLINE
bool path::iterator::operator!=(
const path::iterator& other)
const
2842 return _iter != other._iter;
2845GHC_INLINE path::iterator::reference path::iterator::operator*()
const
2850GHC_INLINE path::iterator::pointer path::iterator::operator->()
const
2855GHC_INLINE path::iterator path::begin()
const
2857 return iterator(_path.begin(), _path.end(), _path.begin());
2860GHC_INLINE path::iterator path::end()
const
2862 return iterator(_path.begin(), _path.end(), _path.end());
2867GHC_INLINE
void swap(path& lhs, path& rhs)
noexcept
2869 swap(lhs._path, rhs._path);
2872GHC_INLINE
size_t hash_value(
const path& p)
noexcept
2874 return std::hash<std::string>()(p.generic_string());
2877GHC_INLINE
bool operator==(
const path& lhs,
const path& rhs)
noexcept
2879 return lhs.generic_string() == rhs.generic_string();
2882GHC_INLINE
bool operator!=(
const path& lhs,
const path& rhs)
noexcept
2884 return lhs.generic_string() != rhs.generic_string();
2887GHC_INLINE
bool operator<(
const path& lhs,
const path& rhs)
noexcept
2889 return lhs.generic_string() < rhs.generic_string();
2892GHC_INLINE
bool operator<=(
const path& lhs,
const path& rhs)
noexcept
2894 return lhs.generic_string() <= rhs.generic_string();
2897GHC_INLINE
bool operator>(
const path& lhs,
const path& rhs)
noexcept
2899 return lhs.generic_string() > rhs.generic_string();
2902GHC_INLINE
bool operator>=(
const path& lhs,
const path& rhs)
noexcept
2904 return lhs.generic_string() >= rhs.generic_string();
2907GHC_INLINE path operator/(
const path& lhs,
const path& rhs)
2918template <
class charT,
class traits>
2919inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os,
const path& p)
2922 auto ps = p.string<charT, traits>();
2924 if (c ==
'"' || c ==
'\\') {
2933template <
class charT,
class traits>
2934inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, path& p)
2936 std::basic_string<charT, traits> tmp;
2939 auto sf = is.flags();
2940 is >> std::noskipws;
2947 tmp +=
static_cast<charT
>(c);
2950 else if (c ==
'"') {
2954 tmp +=
static_cast<charT
>(c);
2958 if ((sf & std::ios_base::skipws) == std::ios_base::skipws) {
2965 p = path(
static_cast<charT
>(c) + tmp);
2970#ifdef GHC_EXPAND_IMPL
2974GHC_INLINE filesystem_error::filesystem_error(
const std::string& what_arg, std::error_code ec)
2975 : std::system_error(ec, what_arg)
2976 , _what_arg(what_arg)
2981GHC_INLINE filesystem_error::filesystem_error(
const std::string& what_arg,
const path& p1, std::error_code ec)
2982 : std::system_error(ec, what_arg)
2983 , _what_arg(what_arg)
2988 _what_arg +=
": '" + _p1.u8string() +
"'";
2992GHC_INLINE filesystem_error::filesystem_error(
const std::string& what_arg,
const path& p1,
const path& p2, std::error_code ec)
2993 : std::system_error(ec, what_arg)
2994 , _what_arg(what_arg)
3000 _what_arg +=
": '" + _p1.u8string() +
"'";
3003 _what_arg +=
", '" + _p2.u8string() +
"'";
3007GHC_INLINE
const path& filesystem_error::path1() const noexcept
3012GHC_INLINE
const path& filesystem_error::path2() const noexcept
3017GHC_INLINE
const char* filesystem_error::what() const noexcept
3019 return _what_arg.c_str();
3024GHC_INLINE path absolute(
const path& p)
3027 path result = absolute(p, ec);
3029 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3034GHC_INLINE path absolute(
const path& p, std::error_code& ec)
3037#ifdef GHC_OS_WINDOWS
3039 return absolute(current_path(ec), ec) /
"";
3041 ULONG size = ::GetFullPathNameW(p.wstring().c_str(), 0, 0, 0);
3043 std::vector<wchar_t> buf(size, 0);
3044 ULONG s2 = GetFullPathNameW(p.wstring().c_str(), size, buf.data(),
nullptr);
3045 if (s2 && s2 < size) {
3046 path result = path(std::wstring(buf.data(), s2));
3047 if (p.filename() ==
".") {
3053 ec = detail::make_system_error();
3056 path base = current_path(ec);
3061 if (p.has_root_name()) {
3062 if (p.has_root_directory()) {
3066 return p.root_name() / base.root_directory() / base.relative_path() / p.relative_path();
3070 if (p.has_root_directory()) {
3071 return base.root_name() / p;
3078 ec = detail::make_system_error();
3083GHC_INLINE path canonical(
const path& p)
3086 auto result = canonical(p, ec);
3088 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3093GHC_INLINE path canonical(
const path& p, std::error_code& ec)
3096 ec = detail::make_error_code(detail::portable_error::not_found);
3099 path work = p.is_absolute() ? p : absolute(p, ec);
3100 path root = work.root_path();
3103 auto fs = status(work, ec);
3107 if (fs.type() == file_type::not_found) {
3108 ec = detail::make_error_code(detail::portable_error::not_found);
3115 for (
auto pe : work) {
3116 if (pe.empty() || pe ==
".") {
3119 else if (pe ==
"..") {
3120 result = result.parent_path();
3123 else if ((result / pe).
string().length() <= root.string().length()) {
3127 auto sls = symlink_status(result / pe, ec);
3131 if (is_symlink(sls)) {
3133 auto target = read_symlink(result / pe, ec);
3137 if (target.is_absolute()) {
3156GHC_INLINE
void copy(
const path& from,
const path& to)
3158 copy(from, to, copy_options::none);
3161GHC_INLINE
void copy(
const path& from,
const path& to, std::error_code& ec)
noexcept
3163 copy(from, to, copy_options::none, ec);
3166GHC_INLINE
void copy(
const path& from,
const path& to, copy_options options)
3169 copy(from, to, options, ec);
3171 throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec);
3175GHC_INLINE
void copy(
const path& from,
const path& to, copy_options options, std::error_code& ec)
noexcept
3177 std::error_code tec;
3178 file_status fs_from, fs_to;
3180 if ((options & (copy_options::skip_symlinks | copy_options::copy_symlinks | copy_options::create_symlinks)) != copy_options::none) {
3181 fs_from = symlink_status(from, ec);
3184 fs_from = status(from, ec);
3186 if (!exists(fs_from)) {
3188 ec = detail::make_error_code(detail::portable_error::not_found);
3192 if ((options & (copy_options::skip_symlinks | copy_options::create_symlinks)) != copy_options::none) {
3193 fs_to = symlink_status(to, tec);
3196 fs_to = status(to, tec);
3198 if (is_other(fs_from) || is_other(fs_to) || (is_directory(fs_from) && is_regular_file(fs_to)) || (exists(fs_to) && equivalent(from, to, ec))) {
3199 ec = detail::make_error_code(detail::portable_error::invalid_argument);
3201 else if (is_symlink(fs_from)) {
3202 if ((options & copy_options::skip_symlinks) == copy_options::none) {
3203 if (!exists(fs_to) && (options & copy_options::copy_symlinks) != copy_options::none) {
3204 copy_symlink(from, to, ec);
3207 ec = detail::make_error_code(detail::portable_error::invalid_argument);
3211 else if (is_regular_file(fs_from)) {
3212 if ((options & copy_options::directories_only) == copy_options::none) {
3213 if ((options & copy_options::create_symlinks) != copy_options::none) {
3214 create_symlink(from.is_absolute() ? from : canonical(from, ec), to, ec);
3216 else if ((options & copy_options::create_hard_links) != copy_options::none) {
3217 create_hard_link(from, to, ec);
3219 else if (is_directory(fs_to)) {
3220 copy_file(from, to / from.filename(), options, ec);
3223 copy_file(from, to, options, ec);
3227#ifdef LWG_2682_BEHAVIOUR
3228 else if (is_directory(fs_from) && (options & copy_options::create_symlinks) != copy_options::none) {
3229 ec = detail::make_error_code(detail::portable_error::is_a_directory);
3232 else if (is_directory(fs_from) && (options == copy_options::none || (options & copy_options::recursive) != copy_options::none)) {
3233 if (!exists(fs_to)) {
3234 create_directory(to, from, ec);
3239 for (
auto iter = directory_iterator(from, ec); iter != directory_iterator(); iter.increment(ec)) {
3241 copy(iter->path(), to / iter->path().filename(), options |
static_cast<copy_options
>(0x8000), ec);
3251GHC_INLINE
bool copy_file(
const path& from,
const path& to)
3253 return copy_file(from, to, copy_options::none);
3256GHC_INLINE
bool copy_file(
const path& from,
const path& to, std::error_code& ec)
noexcept
3258 return copy_file(from, to, copy_options::none, ec);
3261GHC_INLINE
bool copy_file(
const path& from,
const path& to, copy_options option)
3264 auto result = copy_file(from, to, option, ec);
3266 throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec);
3271GHC_INLINE
bool copy_file(
const path& from,
const path& to, copy_options options, std::error_code& ec)
noexcept
3273 std::error_code tecf, tect;
3274 auto sf = status(from, tecf);
3275 auto st = status(to, tect);
3276 bool overwrite =
false;
3278 if (!is_regular_file(sf)) {
3282 if (exists(st) && (!is_regular_file(st) || equivalent(from, to, ec) || (options & (copy_options::skip_existing | copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none)) {
3283 ec = tect ? tect : detail::make_error_code(detail::portable_error::exists);
3287 if ((options & copy_options::update_existing) == copy_options::update_existing) {
3288 auto from_time = last_write_time(from, ec);
3290 ec = detail::make_system_error();
3293 auto to_time = last_write_time(to, ec);
3295 ec = detail::make_system_error();
3298 if (from_time <= to_time) {
3304#ifdef GHC_OS_WINDOWS
3305 if (!::CopyFileW(detail::fromUtf8<std::wstring>(from.u8string()).c_str(), detail::fromUtf8<std::wstring>(to.u8string()).c_str(), !overwrite)) {
3306 ec = detail::make_system_error();
3311 std::vector<char> buffer(16384,
'\0');
3312 int in = -1, out = -1;
3313 if ((in = ::open(from.c_str(), O_RDONLY)) < 0) {
3314 ec = detail::make_system_error();
3317 std::shared_ptr<void> guard_in(
nullptr, [in](
void*) { ::close(in); });
3318 int mode = O_CREAT | O_WRONLY | O_TRUNC;
3322 if ((out = ::open(to.c_str(), mode,
static_cast<int>(sf.permissions() & perms::all))) < 0) {
3323 ec = detail::make_system_error();
3326 std::shared_ptr<void> guard_out(
nullptr, [out](
void*) { ::close(out); });
3328 while ((br = ::read(in, buffer.data(), buffer.size())) > 0) {
3331 if ((bw = ::write(out, buffer.data() + offset,
static_cast<size_t>(br))) > 0) {
3336 ec = detail::make_system_error();
3345GHC_INLINE
void copy_symlink(
const path& existing_symlink,
const path& new_symlink)
3348 copy_symlink(existing_symlink, new_symlink, ec);
3350 throw filesystem_error(detail::systemErrorText(ec.value()), existing_symlink, new_symlink, ec);
3354GHC_INLINE
void copy_symlink(
const path& existing_symlink,
const path& new_symlink, std::error_code& ec)
noexcept
3357 auto to = read_symlink(existing_symlink, ec);
3359 if (exists(to, ec) && is_directory(to, ec)) {
3360 create_directory_symlink(to, new_symlink, ec);
3363 create_symlink(to, new_symlink, ec);
3368GHC_INLINE
bool create_directories(
const path& p)
3371 auto result = create_directories(p, ec);
3373 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3378GHC_INLINE
bool create_directories(
const path& p, std::error_code& ec)
noexcept
3382 for (path::string_type part : p) {
3384 if (current != p.root_name() && current != p.root_path()) {
3385 std::error_code tec;
3386 auto fs = status(current, tec);
3387 if (tec && fs.type() != file_type::not_found) {
3392 create_directory(current, ec);
3394 std::error_code tmp_ec;
3395 if (is_directory(current, tmp_ec)) {
3402#ifndef LWG_2935_BEHAVIOUR
3403 else if (!is_directory(fs)) {
3404 ec = detail::make_error_code(detail::portable_error::exists);
3413GHC_INLINE
bool create_directory(
const path& p)
3416 auto result = create_directory(p, path(), ec);
3418 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3423GHC_INLINE
bool create_directory(
const path& p, std::error_code& ec)
noexcept
3425 return create_directory(p, path(), ec);
3428GHC_INLINE
bool create_directory(
const path& p,
const path& attributes)
3431 auto result = create_directory(p, attributes, ec);
3433 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3438GHC_INLINE
bool create_directory(
const path& p,
const path& attributes, std::error_code& ec)
noexcept
3440 std::error_code tec;
3442 auto fs = status(p, tec);
3443#ifdef LWG_2935_BEHAVIOUR
3444 if (status_known(fs) && exists(fs)) {
3448 if (status_known(fs) && exists(fs) && is_directory(fs)) {
3452#ifdef GHC_OS_WINDOWS
3453 if (!attributes.empty()) {
3454 if (!::CreateDirectoryExW(detail::fromUtf8<std::wstring>(attributes.u8string()).c_str(), detail::fromUtf8<std::wstring>(p.u8string()).c_str(), NULL)) {
3455 ec = detail::make_system_error();
3459 else if (!::CreateDirectoryW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), NULL)) {
3460 ec = detail::make_system_error();
3464 ::mode_t attribs =
static_cast<mode_t
>(perms::all);
3465 if (!attributes.empty()) {
3466 struct ::stat fileStat;
3467 if (::stat(attributes.c_str(), &fileStat) != 0) {
3468 ec = detail::make_system_error();
3471 attribs = fileStat.st_mode;
3473 if (::mkdir(p.c_str(), attribs) != 0) {
3474 ec = detail::make_system_error();
3481GHC_INLINE
void create_directory_symlink(
const path& to,
const path& new_symlink)
3484 create_directory_symlink(to, new_symlink, ec);
3486 throw filesystem_error(detail::systemErrorText(ec.value()), to, new_symlink, ec);
3490GHC_INLINE
void create_directory_symlink(
const path& to,
const path& new_symlink, std::error_code& ec)
noexcept
3492 detail::create_symlink(to, new_symlink,
true, ec);
3495GHC_INLINE
void create_hard_link(
const path& to,
const path& new_hard_link)
3498 create_hard_link(to, new_hard_link, ec);
3500 throw filesystem_error(detail::systemErrorText(ec.value()), to, new_hard_link, ec);
3504GHC_INLINE
void create_hard_link(
const path& to,
const path& new_hard_link, std::error_code& ec)
noexcept
3506 detail::create_hardlink(to, new_hard_link, ec);
3509GHC_INLINE
void create_symlink(
const path& to,
const path& new_symlink)
3512 create_symlink(to, new_symlink, ec);
3514 throw filesystem_error(detail::systemErrorText(ec.value()), to, new_symlink, ec);
3518GHC_INLINE
void create_symlink(
const path& to,
const path& new_symlink, std::error_code& ec)
noexcept
3520 detail::create_symlink(to, new_symlink,
false, ec);
3523GHC_INLINE path current_path()
3526 auto result = current_path(ec);
3528 throw filesystem_error(detail::systemErrorText(ec.value()), ec);
3533GHC_INLINE path current_path(std::error_code& ec)
3536#ifdef GHC_OS_WINDOWS
3537 DWORD pathlen = ::GetCurrentDirectoryW(0, 0);
3538 std::unique_ptr<wchar_t[]> buffer(
new wchar_t[
size_t(pathlen) + 1]);
3539 if (::GetCurrentDirectoryW(pathlen, buffer.get()) == 0) {
3540 ec = detail::make_system_error();
3545 size_t pathlen =
static_cast<size_t>(std::max(
int(::pathconf(
".", _PC_PATH_MAX)),
int(PATH_MAX)));
3546 std::unique_ptr<char[]> buffer(
new char[pathlen + 1]);
3547 if (::getcwd(buffer.get(), pathlen) == NULL) {
3548 ec = detail::make_system_error();
3551 return path(buffer.get());
3555GHC_INLINE
void current_path(
const path& p)
3558 current_path(p, ec);
3560 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3564GHC_INLINE
void current_path(
const path& p, std::error_code& ec)
noexcept
3567#ifdef GHC_OS_WINDOWS
3568 if (!::SetCurrentDirectoryW(detail::fromUtf8<std::wstring>(p.u8string()).c_str())) {
3569 ec = detail::make_system_error();
3572 if (::chdir(p.string().c_str()) == -1) {
3573 ec = detail::make_system_error();
3578GHC_INLINE
bool exists(file_status s)
noexcept
3580 return status_known(s) && s.type() != file_type::not_found;
3583GHC_INLINE
bool exists(
const path& p)
3585 return exists(status(p));
3588GHC_INLINE
bool exists(
const path& p, std::error_code& ec)
noexcept
3590 file_status s = status(p, ec);
3591 if (status_known(s)) {
3597GHC_INLINE
bool equivalent(
const path& p1,
const path& p2)
3600 bool result = equivalent(p1, p2, ec);
3602 throw filesystem_error(detail::systemErrorText(ec.value()), p1, p2, ec);
3607GHC_INLINE
bool equivalent(
const path& p1,
const path& p2, std::error_code& ec)
noexcept
3610#ifdef GHC_OS_WINDOWS
3611 std::shared_ptr<void> file1(::CreateFileW(p1.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
3612 auto e1 = ::GetLastError();
3613 std::shared_ptr<void> file2(::CreateFileW(p2.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
3614 if (file1.get() == INVALID_HANDLE_VALUE || file2.get() == INVALID_HANDLE_VALUE) {
3615#ifdef LWG_2937_BEHAVIOUR
3616 ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
3618 if (file1 == file2) {
3619 ec = detail::make_system_error(e1 ? e1 : ::GetLastError());
3624 BY_HANDLE_FILE_INFORMATION inf1, inf2;
3625 if (!::GetFileInformationByHandle(file1.get(), &inf1)) {
3626 ec = detail::make_system_error();
3629 if (!::GetFileInformationByHandle(file2.get(), &inf2)) {
3630 ec = detail::make_system_error();
3633 return inf1.ftLastWriteTime.dwLowDateTime == inf2.ftLastWriteTime.dwLowDateTime && inf1.ftLastWriteTime.dwHighDateTime == inf2.ftLastWriteTime.dwHighDateTime && inf1.nFileIndexHigh == inf2.nFileIndexHigh && inf1.nFileIndexLow == inf2.nFileIndexLow &&
3634 inf1.nFileSizeHigh == inf2.nFileSizeHigh && inf1.nFileSizeLow == inf2.nFileSizeLow && inf1.dwVolumeSerialNumber == inf2.dwVolumeSerialNumber;
3636 struct ::stat s1, s2;
3637 auto rc1 = ::stat(p1.c_str(), &s1);
3639 auto rc2 = ::stat(p2.c_str(), &s2);
3641#ifdef LWG_2937_BEHAVIOUR
3642 ec = detail::make_system_error(e1 ? e1 : errno);
3645 ec = detail::make_system_error(e1 ? e1 : errno);
3650 return s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino && s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime;
3654GHC_INLINE uintmax_t file_size(
const path& p)
3657 auto result = file_size(p, ec);
3659 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3664GHC_INLINE uintmax_t file_size(
const path& p, std::error_code& ec)
noexcept
3667#ifdef GHC_OS_WINDOWS
3668 WIN32_FILE_ATTRIBUTE_DATA attr;
3669 if (!GetFileAttributesExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GetFileExInfoStandard, &attr)) {
3670 ec = detail::make_system_error();
3671 return static_cast<uintmax_t
>(-1);
3673 return static_cast<uintmax_t
>(attr.nFileSizeHigh) << (
sizeof(attr.nFileSizeHigh) * 8) | attr.nFileSizeLow;
3675 struct ::stat fileStat;
3676 if (::stat(p.c_str(), &fileStat) == -1) {
3677 ec = detail::make_system_error();
3678 return static_cast<uintmax_t
>(-1);
3680 return static_cast<uintmax_t
>(fileStat.st_size);
3684GHC_INLINE uintmax_t hard_link_count(
const path& p)
3687 auto result = hard_link_count(p, ec);
3689 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3694GHC_INLINE uintmax_t hard_link_count(
const path& p, std::error_code& ec)
noexcept
3697#ifdef GHC_OS_WINDOWS
3698 uintmax_t result =
static_cast<uintmax_t
>(-1);
3699 std::shared_ptr<void> file(::CreateFileW(p.wstring().c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0), CloseHandle);
3700 BY_HANDLE_FILE_INFORMATION inf;
3701 if (file.get() == INVALID_HANDLE_VALUE) {
3702 ec = detail::make_system_error();
3705 if (!::GetFileInformationByHandle(file.get(), &inf)) {
3706 ec = detail::make_system_error();
3709 result = inf.nNumberOfLinks;
3714 uintmax_t result = 0;
3715 file_status fs = detail::status_ex(p, ec,
nullptr,
nullptr, &result,
nullptr);
3716 if (fs.type() == file_type::not_found) {
3717 ec = detail::make_error_code(detail::portable_error::not_found);
3719 return ec ?
static_cast<uintmax_t
>(-1) : result;
3723GHC_INLINE
bool is_block_file(file_status s)
noexcept
3725 return s.type() == file_type::block;
3728GHC_INLINE
bool is_block_file(
const path& p)
3730 return is_block_file(status(p));
3733GHC_INLINE
bool is_block_file(
const path& p, std::error_code& ec)
noexcept
3735 return is_block_file(status(p, ec));
3738GHC_INLINE
bool is_character_file(file_status s)
noexcept
3740 return s.type() == file_type::character;
3743GHC_INLINE
bool is_character_file(
const path& p)
3745 return is_character_file(status(p));
3748GHC_INLINE
bool is_character_file(
const path& p, std::error_code& ec)
noexcept
3750 return is_character_file(status(p, ec));
3753GHC_INLINE
bool is_directory(file_status s)
noexcept
3755 return s.type() == file_type::directory;
3758GHC_INLINE
bool is_directory(
const path& p)
3760 return is_directory(status(p));
3763GHC_INLINE
bool is_directory(
const path& p, std::error_code& ec)
noexcept
3765 return is_directory(status(p, ec));
3768GHC_INLINE
bool is_empty(
const path& p)
3770 if (is_directory(p)) {
3771 return directory_iterator(p) == directory_iterator();
3774 return file_size(p) == 0;
3778GHC_INLINE
bool is_empty(
const path& p, std::error_code& ec)
noexcept
3780 auto fs = status(p, ec);
3784 if (is_directory(fs)) {
3785 directory_iterator iter(p, ec);
3789 return iter == directory_iterator();
3792 auto sz = file_size(p, ec);
3800GHC_INLINE
bool is_fifo(file_status s)
noexcept
3802 return s.type() == file_type::fifo;
3805GHC_INLINE
bool is_fifo(
const path& p)
3807 return is_fifo(status(p));
3810GHC_INLINE
bool is_fifo(
const path& p, std::error_code& ec)
noexcept
3812 return is_fifo(status(p, ec));
3815GHC_INLINE
bool is_other(file_status s)
noexcept
3817 return exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s);
3820GHC_INLINE
bool is_other(
const path& p)
3822 return is_other(status(p));
3825GHC_INLINE
bool is_other(
const path& p, std::error_code& ec)
noexcept
3827 return is_other(status(p, ec));
3830GHC_INLINE
bool is_regular_file(file_status s)
noexcept
3832 return s.type() == file_type::regular;
3835GHC_INLINE
bool is_regular_file(
const path& p)
3837 return is_regular_file(status(p));
3840GHC_INLINE
bool is_regular_file(
const path& p, std::error_code& ec)
noexcept
3842 return is_regular_file(status(p, ec));
3845GHC_INLINE
bool is_socket(file_status s)
noexcept
3847 return s.type() == file_type::socket;
3850GHC_INLINE
bool is_socket(
const path& p)
3852 return is_socket(status(p));
3855GHC_INLINE
bool is_socket(
const path& p, std::error_code& ec)
noexcept
3857 return is_socket(status(p, ec));
3860GHC_INLINE
bool is_symlink(file_status s)
noexcept
3862 return s.type() == file_type::symlink;
3865GHC_INLINE
bool is_symlink(
const path& p)
3867 return is_symlink(symlink_status(p));
3870GHC_INLINE
bool is_symlink(
const path& p, std::error_code& ec)
noexcept
3872 return is_symlink(symlink_status(p, ec));
3875GHC_INLINE file_time_type last_write_time(
const path& p)
3878 auto result = last_write_time(p, ec);
3880 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3885GHC_INLINE file_time_type last_write_time(
const path& p, std::error_code& ec)
noexcept
3889 file_status fs = detail::status_ex(p, ec,
nullptr,
nullptr,
nullptr, &result);
3890 return ec ? (file_time_type::min)() : std::chrono::system_clock::from_time_t(result);
3893GHC_INLINE
void last_write_time(
const path& p, file_time_type new_time)
3896 last_write_time(p, new_time, ec);
3898 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3902GHC_INLINE
void last_write_time(
const path& p, file_time_type new_time, std::error_code& ec)
noexcept
3905 auto d = new_time.time_since_epoch();
3906#ifdef GHC_OS_WINDOWS
3907 std::shared_ptr<void> file(::CreateFileW(p.wstring().c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL), ::CloseHandle);
3909 auto tt = std::chrono::duration_cast<std::chrono::microseconds>(d).count() * 10 + 116444736000000000;
3910 ft.dwLowDateTime =
static_cast<DWORD
>(tt);
3911 ft.dwHighDateTime =
static_cast<DWORD
>(tt >> 32);
3912 if (!::SetFileTime(file.get(), 0, 0, &ft)) {
3913 ec = detail::make_system_error();
3915#elif defined(GHC_OS_MACOS)
3916#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
3917#if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
3919 if (::stat(p.c_str(), &fs) == 0) {
3920 struct ::timeval tv[2];
3921 tv[0].tv_sec = fs.st_atimespec.tv_sec;
3922 tv[0].tv_usec =
static_cast<int>(fs.st_atimespec.tv_nsec / 1000);
3923 tv[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
3924 tv[1].tv_usec =
static_cast<int>(std::chrono::duration_cast<std::chrono::microseconds>(d).count() % 1000000);
3925 if (::utimes(p.c_str(), tv) == 0) {
3929 ec = detail::make_system_error();
3932 struct ::timespec times[2];
3933 times[0].tv_sec = 0;
3934 times[0].tv_nsec = UTIME_OMIT;
3935 times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
3936 times[1].tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
3937 if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
3938 ec = detail::make_system_error();
3944 struct ::timespec times[2];
3945 times[0].tv_sec = 0;
3946 times[0].tv_nsec = UTIME_OMIT;
3947 times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
3948 times[1].tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
3949 if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
3950 ec = detail::make_system_error();
3956GHC_INLINE
void permissions(
const path& p, perms prms, perm_options opts)
3959 permissions(p, prms, opts, ec);
3961 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
3965GHC_INLINE
void permissions(
const path& p, perms prms, std::error_code& ec)
noexcept
3967 permissions(p, prms, perm_options::replace, ec);
3970GHC_INLINE
void permissions(
const path& p, perms prms, perm_options opts, std::error_code& ec)
3972 if (
static_cast<int>(opts & (perm_options::replace | perm_options::add | perm_options::remove)) == 0) {
3973 ec = detail::make_error_code(detail::portable_error::invalid_argument);
3976 auto fs = symlink_status(p, ec);
3977 if ((opts & perm_options::replace) != perm_options::replace) {
3978 if ((opts & perm_options::add) == perm_options::add) {
3979 prms = fs.permissions() | prms;
3982 prms = fs.permissions() & ~prms;
3985#ifdef GHC_OS_WINDOWS
3987 auto oldAttr = GetFileAttributesW(p.wstring().c_str());
3988 if (oldAttr != INVALID_FILE_ATTRIBUTES) {
3989 DWORD newAttr = ((prms & perms::owner_write) == perms::owner_write) ? oldAttr & ~(
static_cast<DWORD
>(FILE_ATTRIBUTE_READONLY)) : oldAttr | FILE_ATTRIBUTE_READONLY;
3990 if (oldAttr == newAttr || SetFileAttributesW(p.wstring().c_str(), newAttr)) {
3994 ec = detail::make_system_error();
3997 if ((prms & perms::owner_read) == perms::owner_read) {
4000 if ((prms & perms::owner_write) == perms::owner_write) {
4003 if (::_wchmod(p.wstring().c_str(), mode) != 0) {
4004 ec = detail::make_system_error();
4008 if ((opts & perm_options::nofollow) != perm_options::nofollow) {
4009 if (::chmod(p.c_str(),
static_cast<mode_t
>(prms)) != 0) {
4010 ec = detail::make_system_error();
4016GHC_INLINE path proximate(
const path& p, std::error_code& ec)
4018 return proximate(p, current_path(), ec);
4021GHC_INLINE path proximate(
const path& p,
const path& base)
4023 return weakly_canonical(p).lexically_proximate(weakly_canonical(base));
4026GHC_INLINE path proximate(
const path& p,
const path& base, std::error_code& ec)
4028 return weakly_canonical(p, ec).lexically_proximate(weakly_canonical(base, ec));
4031GHC_INLINE path read_symlink(
const path& p)
4034 auto result = read_symlink(p, ec);
4036 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4041GHC_INLINE path read_symlink(
const path& p, std::error_code& ec)
4043 file_status fs = symlink_status(p, ec);
4044 if (fs.type() != file_type::symlink) {
4045 ec = detail::make_error_code(detail::portable_error::invalid_argument);
4048 auto result = detail::resolveSymlink(p, ec);
4049 return ec ? path() : result;
4052GHC_INLINE path relative(
const path& p, std::error_code& ec)
4054 return relative(p, current_path(ec), ec);
4057GHC_INLINE path relative(
const path& p,
const path& base)
4059 return weakly_canonical(p).lexically_relative(weakly_canonical(base));
4062GHC_INLINE path relative(
const path& p,
const path& base, std::error_code& ec)
4064 return weakly_canonical(p, ec).lexically_relative(weakly_canonical(base, ec));
4067GHC_INLINE
bool remove(
const path& p)
4070 auto result = remove(p, ec);
4072 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4077GHC_INLINE
bool remove(
const path& p, std::error_code& ec)
noexcept
4080#ifdef GHC_OS_WINDOWS
4081 std::wstring np = detail::fromUtf8<std::wstring>(p.u8string());
4082 DWORD attr = GetFileAttributesW(np.c_str());
4083 if (attr == INVALID_FILE_ATTRIBUTES) {
4084 auto error = ::GetLastError();
4085 if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) {
4088 ec = detail::make_system_error(error);
4091 if (attr & FILE_ATTRIBUTE_DIRECTORY) {
4092 if (!RemoveDirectoryW(np.c_str())) {
4093 ec = detail::make_system_error();
4097 if (!DeleteFileW(np.c_str())) {
4098 ec = detail::make_system_error();
4103 if (::remove(p.c_str()) == -1) {
4105 if (error == ENOENT) {
4108 ec = detail::make_system_error();
4111 return ec ? false :
true;
4114GHC_INLINE uintmax_t remove_all(
const path& p)
4117 auto result = remove_all(p, ec);
4119 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4124GHC_INLINE uintmax_t remove_all(
const path& p, std::error_code& ec)
noexcept
4127 uintmax_t count = 0;
4129 ec = detail::make_error_code(detail::portable_error::not_supported);
4130 return static_cast<uintmax_t
>(-1);
4132 std::error_code tec;
4133 auto fs = status(p, tec);
4134 if (exists(fs) && is_directory(fs)) {
4135 for (
auto iter = directory_iterator(p, ec); iter != directory_iterator(); iter.increment(ec)) {
4139 if (!iter->is_symlink() && iter->is_directory()) {
4140 count += remove_all(iter->path(), ec);
4142 return static_cast<uintmax_t
>(-1);
4146 remove(iter->path(), ec);
4148 return static_cast<uintmax_t
>(-1);
4155 if (remove(p, ec)) {
4160 return static_cast<uintmax_t
>(-1);
4165GHC_INLINE
void rename(
const path& from,
const path& to)
4168 rename(from, to, ec);
4170 throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec);
4174GHC_INLINE
void rename(
const path& from,
const path& to, std::error_code& ec)
noexcept
4177#ifdef GHC_OS_WINDOWS
4179 if (!MoveFileW(detail::fromUtf8<std::wstring>(from.u8string()).c_str(), detail::fromUtf8<std::wstring>(to.u8string()).c_str())) {
4180 ec = detail::make_system_error();
4185 if (::rename(from.c_str(), to.c_str()) != 0) {
4186 ec = detail::make_system_error();
4192GHC_INLINE
void resize_file(
const path& p, uintmax_t size)
4195 resize_file(p, size, ec);
4197 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4201GHC_INLINE
void resize_file(
const path& p, uintmax_t size, std::error_code& ec)
noexcept
4204#ifdef GHC_OS_WINDOWS
4205 LARGE_INTEGER lisize;
4206 lisize.QuadPart =
static_cast<LONGLONG
>(size);
4207 if(lisize.QuadPart < 0) {
4208 ec = detail::make_system_error(ERROR_FILE_TOO_LARGE);
4211 std::shared_ptr<void> file(CreateFileW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL), CloseHandle);
4212 if (file.get() == INVALID_HANDLE_VALUE) {
4213 ec = detail::make_system_error();
4215 else if (SetFilePointerEx(file.get(), lisize, NULL, FILE_BEGIN) == 0 || SetEndOfFile(file.get()) == 0) {
4216 ec = detail::make_system_error();
4219 if (::truncate(p.c_str(),
static_cast<off_t
>(size)) != 0) {
4220 ec = detail::make_system_error();
4225GHC_INLINE space_info space(
const path& p)
4228 auto result = space(p, ec);
4230 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4235GHC_INLINE space_info space(
const path& p, std::error_code& ec)
noexcept
4238#ifdef GHC_OS_WINDOWS
4239 ULARGE_INTEGER freeBytesAvailableToCaller = {0, 0};
4240 ULARGE_INTEGER totalNumberOfBytes = {0, 0};
4241 ULARGE_INTEGER totalNumberOfFreeBytes = {0, 0};
4242 if (!GetDiskFreeSpaceExW(detail::fromUtf8<std::wstring>(p.u8string()).c_str(), &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes)) {
4243 ec = detail::make_system_error();
4244 return {
static_cast<uintmax_t
>(-1),
static_cast<uintmax_t
>(-1),
static_cast<uintmax_t
>(-1)};
4246 return {
static_cast<uintmax_t
>(totalNumberOfBytes.QuadPart),
static_cast<uintmax_t
>(totalNumberOfFreeBytes.QuadPart),
static_cast<uintmax_t
>(freeBytesAvailableToCaller.QuadPart)};
4247#elif !defined(__ANDROID__) || __ANDROID_API__ >= 19
4248 struct ::statvfs sfs;
4249 if (::statvfs(p.c_str(), &sfs) != 0) {
4250 ec = detail::make_system_error();
4251 return {
static_cast<uintmax_t
>(-1),
static_cast<uintmax_t
>(-1),
static_cast<uintmax_t
>(-1)};
4253 return {
static_cast<uintmax_t
>(sfs.f_blocks * sfs.f_frsize),
static_cast<uintmax_t
>(sfs.f_bfree * sfs.f_frsize),
static_cast<uintmax_t
>(sfs.f_bavail * sfs.f_frsize)};
4255 ec = detail::make_error_code(detail::portable_error::not_supported);
4256 return {
static_cast<uintmax_t
>(-1),
static_cast<uintmax_t
>(-1),
static_cast<uintmax_t
>(-1)};
4260GHC_INLINE file_status status(
const path& p)
4263 auto result = status(p, ec);
4264 if (result.type() == file_type::none) {
4265 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4270GHC_INLINE file_status status(
const path& p, std::error_code& ec)
noexcept
4272 return detail::status_ex(p, ec);
4275GHC_INLINE
bool status_known(file_status s)
noexcept
4277 return s.type() != file_type::none;
4280GHC_INLINE file_status symlink_status(
const path& p)
4283 auto result = symlink_status(p, ec);
4284 if (result.type() == file_type::none) {
4285 throw filesystem_error(detail::systemErrorText(ec.value()), ec);
4290GHC_INLINE file_status symlink_status(
const path& p, std::error_code& ec)
noexcept
4292 return detail::symlink_status_ex(p, ec);
4295GHC_INLINE path temp_directory_path()
4298 path result = temp_directory_path(ec);
4300 throw filesystem_error(detail::systemErrorText(ec.value()), ec);
4305GHC_INLINE path temp_directory_path(std::error_code& ec)
noexcept
4308#ifdef GHC_OS_WINDOWS
4309 wchar_t buffer[512];
4310 auto rc = GetTempPathW(511, buffer);
4311 if (!rc || rc > 511) {
4312 ec = detail::make_system_error();
4315 return path(std::wstring(buffer));
4317 static const char* temp_vars[] = {
"TMPDIR",
"TMP",
"TEMP",
"TEMPDIR",
nullptr};
4318 const char* temp_path =
nullptr;
4319 for (
auto temp_name = temp_vars; *temp_name !=
nullptr; ++temp_name) {
4320 temp_path = std::getenv(*temp_name);
4322 return path(temp_path);
4325 return path(
"/tmp");
4329GHC_INLINE path weakly_canonical(
const path& p)
4332 auto result = weakly_canonical(p, ec);
4334 throw filesystem_error(detail::systemErrorText(ec.value()), p, ec);
4339GHC_INLINE path weakly_canonical(
const path& p, std::error_code& ec)
noexcept
4346 std::error_code tec;
4347 if (exists(result / pe, tec)) {
4355 if (!result.empty()) {
4356 result = canonical(result, ec) / pe;
4371 if (!result.empty()) {
4372 result = canonical(result, ec);
4375 return ec ? path() : result.lexically_normal();
4381GHC_INLINE file_status::file_status() noexcept
4382 : file_status(file_type::none)
4386GHC_INLINE file_status::file_status(file_type ft, perms prms) noexcept
4392GHC_INLINE file_status::file_status(
const file_status& other) noexcept
4393 : _type(other._type)
4394 , _perms(other._perms)
4398GHC_INLINE file_status::file_status(file_status&& other) noexcept
4399 : _type(other._type)
4400 , _perms(other._perms)
4404GHC_INLINE file_status::~file_status() {}
4407GHC_INLINE file_status& file_status::operator=(
const file_status& rhs)
noexcept
4410 _perms = rhs._perms;
4414GHC_INLINE file_status& file_status::operator=(file_status&& rhs)
noexcept
4417 _perms = rhs._perms;
4422GHC_INLINE
void file_status::type(file_type ft)
noexcept
4427GHC_INLINE
void file_status::permissions(perms prms)
noexcept
4433GHC_INLINE file_type file_status::type() const noexcept
4438GHC_INLINE perms file_status::permissions() const noexcept
4449GHC_INLINE directory_entry::directory_entry(
const filesystem::path& p)
4452#ifndef GHC_OS_WINDOWS
4453 , _hard_link_count(0)
4455 , _last_write_time(0)
4460GHC_INLINE directory_entry::directory_entry(
const filesystem::path& p, std::error_code& ec)
4463#ifndef GHC_OS_WINDOWS
4464 , _hard_link_count(0)
4466 , _last_write_time(0)
4471GHC_INLINE directory_entry::~directory_entry() {}
4478GHC_INLINE
void directory_entry::assign(
const filesystem::path& p)
4484GHC_INLINE
void directory_entry::assign(
const filesystem::path& p, std::error_code& ec)
4490GHC_INLINE
void directory_entry::replace_filename(
const filesystem::path& p)
4492 _path.replace_filename(p);
4496GHC_INLINE
void directory_entry::replace_filename(
const filesystem::path& p, std::error_code& ec)
4498 _path.replace_filename(p);
4502GHC_INLINE
void directory_entry::refresh()
4507 throw filesystem_error(detail::systemErrorText(ec.value()), _path, ec);
4511GHC_INLINE
void directory_entry::refresh(std::error_code& ec)
noexcept
4513#ifdef GHC_OS_WINDOWS
4514 _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size,
nullptr, &_last_write_time);
4516 _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size, &_hard_link_count, &_last_write_time);
4521GHC_INLINE
const filesystem::path& directory_entry::path() const noexcept
4526GHC_INLINE directory_entry::operator
const filesystem::path&()
const noexcept
4531GHC_INLINE
bool directory_entry::exists()
const
4533 return filesystem::exists(status());
4536GHC_INLINE
bool directory_entry::exists(std::error_code& ec)
const noexcept
4538 return filesystem::exists(status(ec));
4541GHC_INLINE
bool directory_entry::is_block_file()
const
4543 return filesystem::is_block_file(status());
4545GHC_INLINE
bool directory_entry::is_block_file(std::error_code& ec)
const noexcept
4547 return filesystem::is_block_file(status(ec));
4550GHC_INLINE
bool directory_entry::is_character_file()
const
4552 return filesystem::is_character_file(status());
4555GHC_INLINE
bool directory_entry::is_character_file(std::error_code& ec)
const noexcept
4557 return filesystem::is_character_file(status(ec));
4560GHC_INLINE
bool directory_entry::is_directory()
const
4562 return filesystem::is_directory(status());
4565GHC_INLINE
bool directory_entry::is_directory(std::error_code& ec)
const noexcept
4567 return filesystem::is_directory(status(ec));
4570GHC_INLINE
bool directory_entry::is_fifo()
const
4572 return filesystem::is_fifo(status());
4575GHC_INLINE
bool directory_entry::is_fifo(std::error_code& ec)
const noexcept
4577 return filesystem::is_fifo(status(ec));
4580GHC_INLINE
bool directory_entry::is_other()
const
4582 return filesystem::is_other(status());
4585GHC_INLINE
bool directory_entry::is_other(std::error_code& ec)
const noexcept
4587 return filesystem::is_other(status(ec));
4590GHC_INLINE
bool directory_entry::is_regular_file()
const
4592 return filesystem::is_regular_file(status());
4595GHC_INLINE
bool directory_entry::is_regular_file(std::error_code& ec)
const noexcept
4597 return filesystem::is_regular_file(status(ec));
4600GHC_INLINE
bool directory_entry::is_socket()
const
4602 return filesystem::is_socket(status());
4605GHC_INLINE
bool directory_entry::is_socket(std::error_code& ec)
const noexcept
4607 return filesystem::is_socket(status(ec));
4610GHC_INLINE
bool directory_entry::is_symlink()
const
4612 return filesystem::is_symlink(symlink_status());
4615GHC_INLINE
bool directory_entry::is_symlink(std::error_code& ec)
const noexcept
4617 return filesystem::is_symlink(symlink_status(ec));
4620GHC_INLINE uintmax_t directory_entry::file_size()
const
4622 if (_status.type() != file_type::none) {
4625 return filesystem::file_size(path());
4628GHC_INLINE uintmax_t directory_entry::file_size(std::error_code& ec)
const noexcept
4630 if (_status.type() != file_type::none) {
4633 return filesystem::file_size(path(), ec);
4636GHC_INLINE uintmax_t directory_entry::hard_link_count()
const
4638#ifndef GHC_OS_WINDOWS
4639 if (_status.type() != file_type::none) {
4640 return _hard_link_count;
4643 return filesystem::hard_link_count(path());
4646GHC_INLINE uintmax_t directory_entry::hard_link_count(std::error_code& ec)
const noexcept
4648#ifndef GHC_OS_WINDOWS
4649 if (_status.type() != file_type::none) {
4650 return _hard_link_count;
4653 return filesystem::hard_link_count(path(), ec);
4656GHC_INLINE file_time_type directory_entry::last_write_time()
const
4658 if (_status.type() != file_type::none) {
4659 return std::chrono::system_clock::from_time_t(_last_write_time);
4661 return filesystem::last_write_time(path());
4664GHC_INLINE file_time_type directory_entry::last_write_time(std::error_code& ec)
const noexcept
4666 if (_status.type() != file_type::none) {
4667 return std::chrono::system_clock::from_time_t(_last_write_time);
4669 return filesystem::last_write_time(path(), ec);
4672GHC_INLINE file_status directory_entry::status()
const
4674 if (_status.type() != file_type::none) {
4677 return filesystem::status(path());
4680GHC_INLINE file_status directory_entry::status(std::error_code& ec)
const noexcept
4682 if (_status.type() != file_type::none) {
4685 return filesystem::status(path(), ec);
4688GHC_INLINE file_status directory_entry::symlink_status()
const
4690 if (_symlink_status.type() != file_type::none) {
4691 return _symlink_status;
4693 return filesystem::symlink_status(path());
4696GHC_INLINE file_status directory_entry::symlink_status(std::error_code& ec)
const noexcept
4698 if (_symlink_status.type() != file_type::none) {
4699 return _symlink_status;
4701 return filesystem::symlink_status(path(), ec);
4704GHC_INLINE
bool directory_entry::operator<(
const directory_entry& rhs)
const noexcept
4706 return _path < rhs._path;
4709GHC_INLINE
bool directory_entry::operator==(
const directory_entry& rhs)
const noexcept
4711 return _path == rhs._path;
4714GHC_INLINE
bool directory_entry::operator!=(
const directory_entry& rhs)
const noexcept
4716 return _path != rhs._path;
4719GHC_INLINE
bool directory_entry::operator<=(
const directory_entry& rhs)
const noexcept
4721 return _path <= rhs._path;
4724GHC_INLINE
bool directory_entry::operator>(
const directory_entry& rhs)
const noexcept
4726 return _path > rhs._path;
4729GHC_INLINE
bool directory_entry::operator>=(
const directory_entry& rhs)
const noexcept
4731 return _path >= rhs._path;
4737#ifdef GHC_OS_WINDOWS
4738class directory_iterator::impl
4741 impl(
const path& p, directory_options options)
4744 , _dirHandle(INVALID_HANDLE_VALUE)
4746 if (!_base.empty()) {
4747 ZeroMemory(&_findData,
sizeof(WIN32_FIND_DATAW));
4748 if ((_dirHandle = FindFirstFileW(detail::fromUtf8<std::wstring>((_base /
"*").u8string()).c_str(), &_findData)) != INVALID_HANDLE_VALUE) {
4749 if (std::wstring(_findData.cFileName) == L
"." || std::wstring(_findData.cFileName) == L
"..") {
4753 _current = _base / std::wstring(_findData.cFileName);
4754 copyToDirEntry(_ec);
4758 auto error = ::GetLastError();
4759 _base = filesystem::path();
4760 if (error != ERROR_ACCESS_DENIED || (options & directory_options::skip_permission_denied) == directory_options::none) {
4761 _ec = detail::make_system_error();
4766 impl(
const impl& other) =
delete;
4769 if (_dirHandle != INVALID_HANDLE_VALUE) {
4770 FindClose(_dirHandle);
4771 _dirHandle = INVALID_HANDLE_VALUE;
4774 void increment(std::error_code& ec)
4776 if (_dirHandle != INVALID_HANDLE_VALUE) {
4778 if (FindNextFileW(_dirHandle, &_findData)) {
4781 _current.append_name(detail::toUtf8(_findData.cFileName).c_str());
4783 catch(filesystem_error& fe) {
4790 auto err = ::GetLastError();
4791 if(err != ERROR_NO_MORE_FILES) {
4792 _ec = ec = detail::make_system_error(err);
4794 FindClose(_dirHandle);
4795 _dirHandle = INVALID_HANDLE_VALUE;
4796 _current = filesystem::path();
4799 }
while (std::wstring(_findData.cFileName) == L
"." || std::wstring(_findData.cFileName) == L
"..");
4805 void copyToDirEntry(std::error_code& ec)
4807 _dir_entry._path = _current;
4808 if (_findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4809 _dir_entry._status = detail::status_ex(_current, ec, &_dir_entry._symlink_status, &_dir_entry._file_size,
nullptr, &_dir_entry._last_write_time);
4812 _dir_entry._status = detail::status_from_INFO(_current, &_findData, ec, &_dir_entry._file_size, &_dir_entry._last_write_time);
4813 _dir_entry._symlink_status = _dir_entry._status;
4816 if (_dir_entry._status.type() != file_type::none && _dir_entry._symlink_status.type() != file_type::none) {
4820 _dir_entry._file_size =
static_cast<uintmax_t
>(-1);
4821 _dir_entry._last_write_time = 0;
4826 directory_options _options;
4827 WIN32_FIND_DATAW _findData;
4830 directory_entry _dir_entry;
4831 std::error_code _ec;
4844 if (!
path.empty()) {
4845 _dir = ::opendir(
path.native().c_str());
4847 if (!
path.empty()) {
4851 if (error != EACCES || (options & directory_options::skip_permission_denied) == directory_options::none) {
4852 _ec = detail::make_system_error();
4867 void increment(std::error_code& ec)
4872 _entry = readdir(_dir);
4875 _current.append_name(_entry->d_name);
4883 ec = detail::make_system_error();
4887 }
while (std::strcmp(_entry->d_name,
".") == 0 || std::strcmp(_entry->d_name,
"..") == 0);
4891 directory_options _options;
4894 struct ::dirent* _entry;
4896 std::error_code _ec;
4901GHC_INLINE directory_iterator::directory_iterator() noexcept
4902 : _impl(new
impl(
path(), directory_options::none))
4906GHC_INLINE directory_iterator::directory_iterator(
const path& p)
4907 : _impl(new impl(p, directory_options::none))
4910 throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p, _impl->_ec);
4915GHC_INLINE directory_iterator::directory_iterator(
const path& p, directory_options options)
4916 : _impl(new impl(p, options))
4919 throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p, _impl->_ec);
4923GHC_INLINE directory_iterator::directory_iterator(
const path& p, std::error_code& ec) noexcept
4924 : _impl(
new impl(p, directory_options::none))
4931GHC_INLINE directory_iterator::directory_iterator(
const path& p, directory_options options, std::error_code& ec) noexcept
4932 : _impl(
new impl(p, options))
4939GHC_INLINE directory_iterator::directory_iterator(
const directory_iterator& rhs)
4944GHC_INLINE directory_iterator::directory_iterator(directory_iterator&& rhs) noexcept
4945 : _impl(std::move(rhs._impl))
4949GHC_INLINE directory_iterator::~directory_iterator() {}
4951GHC_INLINE directory_iterator& directory_iterator::operator=(
const directory_iterator& rhs)
4957GHC_INLINE directory_iterator& directory_iterator::operator=(directory_iterator&& rhs)
noexcept
4959 _impl = std::move(rhs._impl);
4963GHC_INLINE
const directory_entry& directory_iterator::operator*()
const
4965 return _impl->_dir_entry;
4968GHC_INLINE
const directory_entry* directory_iterator::operator->()
const
4970 return &_impl->_dir_entry;
4973GHC_INLINE directory_iterator& directory_iterator::operator++()
4976 _impl->increment(ec);
4978 throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_current, ec);
4983GHC_INLINE directory_iterator& directory_iterator::increment(std::error_code& ec)
noexcept
4985 _impl->increment(ec);
4989GHC_INLINE
bool directory_iterator::operator==(
const directory_iterator& rhs)
const
4991 return _impl->_current == rhs._impl->_current;
4994GHC_INLINE
bool directory_iterator::operator!=(
const directory_iterator& rhs)
const
4996 return _impl->_current != rhs._impl->_current;
5001GHC_INLINE directory_iterator begin(directory_iterator iter)
noexcept
5006GHC_INLINE directory_iterator end(
const directory_iterator&)
noexcept
5008 return directory_iterator();
5014GHC_INLINE recursive_directory_iterator::recursive_directory_iterator() noexcept
5015 : _impl(new recursive_directory_iterator_impl(directory_options::none, true))
5017 _impl->_dir_iter_stack.push(directory_iterator());
5020GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(
const path& p)
5021 : _impl(new recursive_directory_iterator_impl(directory_options::none, true))
5023 _impl->_dir_iter_stack.push(directory_iterator(p));
5026GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(
const path& p, directory_options options)
5027 : _impl(new recursive_directory_iterator_impl(options, true))
5029 _impl->_dir_iter_stack.push(directory_iterator(p, options));
5032GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(
const path& p, directory_options options, std::error_code& ec) noexcept
5033 : _impl(
new recursive_directory_iterator_impl(options,
true))
5035 _impl->_dir_iter_stack.push(directory_iterator(p, options, ec));
5038GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(
const path& p, std::error_code& ec) noexcept
5039 : _impl(
new recursive_directory_iterator_impl(directory_options::none,
true))
5041 _impl->_dir_iter_stack.push(directory_iterator(p, ec));
5044GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(
const recursive_directory_iterator& rhs)
5049GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept
5050 : _impl(std::move(rhs._impl))
5054GHC_INLINE recursive_directory_iterator::~recursive_directory_iterator() {}
5057GHC_INLINE directory_options recursive_directory_iterator::options()
const
5059 return _impl->_options;
5062GHC_INLINE
int recursive_directory_iterator::depth()
const
5064 return static_cast<int>(_impl->_dir_iter_stack.size() - 1);
5067GHC_INLINE
bool recursive_directory_iterator::recursion_pending()
const
5069 return _impl->_recursion_pending;
5072GHC_INLINE
const directory_entry& recursive_directory_iterator::operator*()
const
5074 return *(_impl->_dir_iter_stack.top());
5077GHC_INLINE
const directory_entry* recursive_directory_iterator::operator->()
const
5079 return &(*(_impl->_dir_iter_stack.top()));
5083GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator=(
const recursive_directory_iterator& rhs)
5089GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator=(recursive_directory_iterator&& rhs)
noexcept
5091 _impl = std::move(rhs._impl);
5095GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator++()
5100 throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_iter_stack.empty() ? path() : _impl->_dir_iter_stack.top()->path(), ec);
5105GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::increment(std::error_code& ec)
noexcept
5107 if (recursion_pending() && is_directory((*this)->status()) && (!is_symlink((*this)->symlink_status()) || (options() & directory_options::follow_directory_symlink) != directory_options::none)) {
5108 _impl->_dir_iter_stack.push(directory_iterator((*this)->path(), _impl->_options, ec));
5111 _impl->_dir_iter_stack.top().increment(ec);
5114 while (depth() && _impl->_dir_iter_stack.top() == directory_iterator()) {
5115 _impl->_dir_iter_stack.pop();
5116 _impl->_dir_iter_stack.top().increment(ec);
5119 else if (!_impl->_dir_iter_stack.empty()) {
5120 _impl->_dir_iter_stack.pop();
5122 _impl->_recursion_pending =
true;
5126GHC_INLINE
void recursive_directory_iterator::pop()
5131 throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_iter_stack.empty() ? path() : _impl->_dir_iter_stack.top()->path(), ec);
5135GHC_INLINE
void recursive_directory_iterator::pop(std::error_code& ec)
5138 *
this = recursive_directory_iterator();
5142 _impl->_dir_iter_stack.pop();
5143 _impl->_dir_iter_stack.top().increment(ec);
5144 }
while (depth() && _impl->_dir_iter_stack.top() == directory_iterator());
5148GHC_INLINE
void recursive_directory_iterator::disable_recursion_pending()
5150 _impl->_recursion_pending =
false;
5154GHC_INLINE
bool recursive_directory_iterator::operator==(
const recursive_directory_iterator& rhs)
const
5156 return _impl->_dir_iter_stack.top() == rhs._impl->_dir_iter_stack.top();
5159GHC_INLINE
bool recursive_directory_iterator::operator!=(
const recursive_directory_iterator& rhs)
const
5161 return _impl->_dir_iter_stack.top() != rhs._impl->_dir_iter_stack.top();
5165GHC_INLINE recursive_directory_iterator begin(recursive_directory_iterator iter)
noexcept
5170GHC_INLINE recursive_directory_iterator end(
const recursive_directory_iterator&)
noexcept
5172 return recursive_directory_iterator();
5182#undef GHC_EXPAND_IMPL
Definition filesystem.hpp:948
Definition filesystem.hpp:1012
Definition filesystem.hpp:966
Definition filesystem.hpp:989
Definition filesystem.hpp:611
Definition filesystem.hpp:4836
Definition filesystem.hpp:690
Definition filesystem.hpp:687
Definition filesystem.hpp:584
Definition filesystem.hpp:458
Definition filesystem.hpp:187
Definition filesystem.hpp:197
Definition filesystem.hpp:222
format
The path format in wich the constructor argument is given.
Definition filesystem.hpp:231
@ native_format
Definition filesystem.hpp:234
@ auto_format
Try to auto-detect the format, fallback to native.
Definition filesystem.hpp:236
@ generic_format
Definition filesystem.hpp:232
Definition filesystem.hpp:748
Definition filesystem.hpp:1043
Definition filesystem.hpp:241
Definition filesystem.hpp:505