xref: /freebsd/contrib/llvm-project/libcxx/src/filesystem/operations.cpp (revision d56accc7c3dcc897489b6a07834763a03b9f3d68)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "filesystem"
10 #include "array"
11 #include "iterator"
12 #include "string_view"
13 #include "type_traits"
14 #include "vector"
15 #include "cstdlib"
16 #include "climits"
17 
18 #include "filesystem_common.h"
19 
20 #include "posix_compat.h"
21 
22 #if defined(_LIBCPP_WIN32API)
23 # define WIN32_LEAN_AND_MEAN
24 # define NOMINMAX
25 # include <windows.h>
26 #else
27 # include <dirent.h>
28 # include <sys/stat.h>
29 # include <sys/statvfs.h>
30 # include <unistd.h>
31 #endif
32 #include <time.h>
33 #include <fcntl.h> /* values for fchmodat */
34 
35 #if __has_include(<sys/sendfile.h>)
36 # include <sys/sendfile.h>
37 # define _LIBCPP_FILESYSTEM_USE_SENDFILE
38 #elif defined(__APPLE__) || __has_include(<copyfile.h>)
39 # include <copyfile.h>
40 # define _LIBCPP_FILESYSTEM_USE_COPYFILE
41 #else
42 # include "fstream"
43 # define _LIBCPP_FILESYSTEM_USE_FSTREAM
44 #endif
45 
46 #if !defined(CLOCK_REALTIME) && !defined(_LIBCPP_WIN32API)
47 # include <sys/time.h> // for gettimeofday and timeval
48 #endif
49 
50 #if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB)
51 # pragma comment(lib, "rt")
52 #endif
53 
54 _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
55 
56 namespace {
57 
58 bool isSeparator(path::value_type C) {
59   if (C == '/')
60     return true;
61 #if defined(_LIBCPP_WIN32API)
62   if (C == '\\')
63     return true;
64 #endif
65   return false;
66 }
67 
68 bool isDriveLetter(path::value_type C) {
69   return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z');
70 }
71 
72 namespace parser {
73 
74 using string_view_t = path::__string_view;
75 using string_view_pair = pair<string_view_t, string_view_t>;
76 using PosPtr = path::value_type const*;
77 
78 struct PathParser {
79   enum ParserState : unsigned char {
80     // Zero is a special sentinel value used by default constructed iterators.
81     PS_BeforeBegin = path::iterator::_BeforeBegin,
82     PS_InRootName = path::iterator::_InRootName,
83     PS_InRootDir = path::iterator::_InRootDir,
84     PS_InFilenames = path::iterator::_InFilenames,
85     PS_InTrailingSep = path::iterator::_InTrailingSep,
86     PS_AtEnd = path::iterator::_AtEnd
87   };
88 
89   const string_view_t Path;
90   string_view_t RawEntry;
91   ParserState State;
92 
93 private:
94   PathParser(string_view_t P, ParserState State) noexcept : Path(P),
95                                                             State(State) {}
96 
97 public:
98   PathParser(string_view_t P, string_view_t E, unsigned char S)
99       : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) {
100     // S cannot be '0' or PS_BeforeBegin.
101   }
102 
103   static PathParser CreateBegin(string_view_t P) noexcept {
104     PathParser PP(P, PS_BeforeBegin);
105     PP.increment();
106     return PP;
107   }
108 
109   static PathParser CreateEnd(string_view_t P) noexcept {
110     PathParser PP(P, PS_AtEnd);
111     return PP;
112   }
113 
114   PosPtr peek() const noexcept {
115     auto TkEnd = getNextTokenStartPos();
116     auto End = getAfterBack();
117     return TkEnd == End ? nullptr : TkEnd;
118   }
119 
120   void increment() noexcept {
121     const PosPtr End = getAfterBack();
122     const PosPtr Start = getNextTokenStartPos();
123     if (Start == End)
124       return makeState(PS_AtEnd);
125 
126     switch (State) {
127     case PS_BeforeBegin: {
128       PosPtr TkEnd = consumeRootName(Start, End);
129       if (TkEnd)
130         return makeState(PS_InRootName, Start, TkEnd);
131     }
132       _LIBCPP_FALLTHROUGH();
133     case PS_InRootName: {
134       PosPtr TkEnd = consumeAllSeparators(Start, End);
135       if (TkEnd)
136         return makeState(PS_InRootDir, Start, TkEnd);
137       else
138         return makeState(PS_InFilenames, Start, consumeName(Start, End));
139     }
140     case PS_InRootDir:
141       return makeState(PS_InFilenames, Start, consumeName(Start, End));
142 
143     case PS_InFilenames: {
144       PosPtr SepEnd = consumeAllSeparators(Start, End);
145       if (SepEnd != End) {
146         PosPtr TkEnd = consumeName(SepEnd, End);
147         if (TkEnd)
148           return makeState(PS_InFilenames, SepEnd, TkEnd);
149       }
150       return makeState(PS_InTrailingSep, Start, SepEnd);
151     }
152 
153     case PS_InTrailingSep:
154       return makeState(PS_AtEnd);
155 
156     case PS_AtEnd:
157       _LIBCPP_UNREACHABLE();
158     }
159   }
160 
161   void decrement() noexcept {
162     const PosPtr REnd = getBeforeFront();
163     const PosPtr RStart = getCurrentTokenStartPos() - 1;
164     if (RStart == REnd) // we're decrementing the begin
165       return makeState(PS_BeforeBegin);
166 
167     switch (State) {
168     case PS_AtEnd: {
169       // Try to consume a trailing separator or root directory first.
170       if (PosPtr SepEnd = consumeAllSeparators(RStart, REnd)) {
171         if (SepEnd == REnd)
172           return makeState(PS_InRootDir, Path.data(), RStart + 1);
173         PosPtr TkStart = consumeRootName(SepEnd, REnd);
174         if (TkStart == REnd)
175           return makeState(PS_InRootDir, RStart, RStart + 1);
176         return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1);
177       } else {
178         PosPtr TkStart = consumeRootName(RStart, REnd);
179         if (TkStart == REnd)
180           return makeState(PS_InRootName, TkStart + 1, RStart + 1);
181         TkStart = consumeName(RStart, REnd);
182         return makeState(PS_InFilenames, TkStart + 1, RStart + 1);
183       }
184     }
185     case PS_InTrailingSep:
186       return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1,
187                        RStart + 1);
188     case PS_InFilenames: {
189       PosPtr SepEnd = consumeAllSeparators(RStart, REnd);
190       if (SepEnd == REnd)
191         return makeState(PS_InRootDir, Path.data(), RStart + 1);
192       PosPtr TkStart = consumeRootName(SepEnd ? SepEnd : RStart, REnd);
193       if (TkStart == REnd) {
194         if (SepEnd)
195           return makeState(PS_InRootDir, SepEnd + 1, RStart + 1);
196         return makeState(PS_InRootName, TkStart + 1, RStart + 1);
197       }
198       TkStart = consumeName(SepEnd, REnd);
199       return makeState(PS_InFilenames, TkStart + 1, SepEnd + 1);
200     }
201     case PS_InRootDir:
202       return makeState(PS_InRootName, Path.data(), RStart + 1);
203     case PS_InRootName:
204     case PS_BeforeBegin:
205       _LIBCPP_UNREACHABLE();
206     }
207   }
208 
209   /// \brief Return a view with the "preferred representation" of the current
210   ///   element. For example trailing separators are represented as a '.'
211   string_view_t operator*() const noexcept {
212     switch (State) {
213     case PS_BeforeBegin:
214     case PS_AtEnd:
215       return PS("");
216     case PS_InRootDir:
217       if (RawEntry[0] == '\\')
218         return PS("\\");
219       else
220         return PS("/");
221     case PS_InTrailingSep:
222       return PS("");
223     case PS_InRootName:
224     case PS_InFilenames:
225       return RawEntry;
226     }
227     _LIBCPP_UNREACHABLE();
228   }
229 
230   explicit operator bool() const noexcept {
231     return State != PS_BeforeBegin && State != PS_AtEnd;
232   }
233 
234   PathParser& operator++() noexcept {
235     increment();
236     return *this;
237   }
238 
239   PathParser& operator--() noexcept {
240     decrement();
241     return *this;
242   }
243 
244   bool atEnd() const noexcept {
245     return State == PS_AtEnd;
246   }
247 
248   bool inRootDir() const noexcept {
249     return State == PS_InRootDir;
250   }
251 
252   bool inRootName() const noexcept {
253     return State == PS_InRootName;
254   }
255 
256   bool inRootPath() const noexcept {
257     return inRootName() || inRootDir();
258   }
259 
260 private:
261   void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept {
262     State = NewState;
263     RawEntry = string_view_t(Start, End - Start);
264   }
265   void makeState(ParserState NewState) noexcept {
266     State = NewState;
267     RawEntry = {};
268   }
269 
270   PosPtr getAfterBack() const noexcept { return Path.data() + Path.size(); }
271 
272   PosPtr getBeforeFront() const noexcept { return Path.data() - 1; }
273 
274   /// \brief Return a pointer to the first character after the currently
275   ///   lexed element.
276   PosPtr getNextTokenStartPos() const noexcept {
277     switch (State) {
278     case PS_BeforeBegin:
279       return Path.data();
280     case PS_InRootName:
281     case PS_InRootDir:
282     case PS_InFilenames:
283       return &RawEntry.back() + 1;
284     case PS_InTrailingSep:
285     case PS_AtEnd:
286       return getAfterBack();
287     }
288     _LIBCPP_UNREACHABLE();
289   }
290 
291   /// \brief Return a pointer to the first character in the currently lexed
292   ///   element.
293   PosPtr getCurrentTokenStartPos() const noexcept {
294     switch (State) {
295     case PS_BeforeBegin:
296     case PS_InRootName:
297       return &Path.front();
298     case PS_InRootDir:
299     case PS_InFilenames:
300     case PS_InTrailingSep:
301       return &RawEntry.front();
302     case PS_AtEnd:
303       return &Path.back() + 1;
304     }
305     _LIBCPP_UNREACHABLE();
306   }
307 
308   // Consume all consecutive separators.
309   PosPtr consumeAllSeparators(PosPtr P, PosPtr End) const noexcept {
310     if (P == nullptr || P == End || !isSeparator(*P))
311       return nullptr;
312     const int Inc = P < End ? 1 : -1;
313     P += Inc;
314     while (P != End && isSeparator(*P))
315       P += Inc;
316     return P;
317   }
318 
319   // Consume exactly N separators, or return nullptr.
320   PosPtr consumeNSeparators(PosPtr P, PosPtr End, int N) const noexcept {
321     PosPtr Ret = consumeAllSeparators(P, End);
322     if (Ret == nullptr)
323       return nullptr;
324     if (P < End) {
325       if (Ret == P + N)
326         return Ret;
327     } else {
328       if (Ret == P - N)
329         return Ret;
330     }
331     return nullptr;
332   }
333 
334   PosPtr consumeName(PosPtr P, PosPtr End) const noexcept {
335     PosPtr Start = P;
336     if (P == nullptr || P == End || isSeparator(*P))
337       return nullptr;
338     const int Inc = P < End ? 1 : -1;
339     P += Inc;
340     while (P != End && !isSeparator(*P))
341       P += Inc;
342     if (P == End && Inc < 0) {
343       // Iterating backwards and consumed all the rest of the input.
344       // Check if the start of the string would have been considered
345       // a root name.
346       PosPtr RootEnd = consumeRootName(End + 1, Start);
347       if (RootEnd)
348         return RootEnd - 1;
349     }
350     return P;
351   }
352 
353   PosPtr consumeDriveLetter(PosPtr P, PosPtr End) const noexcept {
354     if (P == End)
355       return nullptr;
356     if (P < End) {
357       if (P + 1 == End || !isDriveLetter(P[0]) || P[1] != ':')
358         return nullptr;
359       return P + 2;
360     } else {
361       if (P - 1 == End || !isDriveLetter(P[-1]) || P[0] != ':')
362         return nullptr;
363       return P - 2;
364     }
365   }
366 
367   PosPtr consumeNetworkRoot(PosPtr P, PosPtr End) const noexcept {
368     if (P == End)
369       return nullptr;
370     if (P < End)
371       return consumeName(consumeNSeparators(P, End, 2), End);
372     else
373       return consumeNSeparators(consumeName(P, End), End, 2);
374   }
375 
376   PosPtr consumeRootName(PosPtr P, PosPtr End) const noexcept {
377 #if defined(_LIBCPP_WIN32API)
378     if (PosPtr Ret = consumeDriveLetter(P, End))
379       return Ret;
380     if (PosPtr Ret = consumeNetworkRoot(P, End))
381       return Ret;
382 #endif
383     return nullptr;
384   }
385 };
386 
387 string_view_pair separate_filename(string_view_t const& s) {
388   if (s == PS(".") || s == PS("..") || s.empty())
389     return string_view_pair{s, PS("")};
390   auto pos = s.find_last_of('.');
391   if (pos == string_view_t::npos || pos == 0)
392     return string_view_pair{s, string_view_t{}};
393   return string_view_pair{s.substr(0, pos), s.substr(pos)};
394 }
395 
396 string_view_t createView(PosPtr S, PosPtr E) noexcept {
397   return {S, static_cast<size_t>(E - S) + 1};
398 }
399 
400 } // namespace parser
401 } // namespace
402 
403 //                       POSIX HELPERS
404 
405 #if defined(_LIBCPP_WIN32API)
406 namespace detail {
407 
408 errc __win_err_to_errc(int err) {
409   constexpr struct {
410     DWORD win;
411     errc errc;
412   } win_error_mapping[] = {
413       {ERROR_ACCESS_DENIED, errc::permission_denied},
414       {ERROR_ALREADY_EXISTS, errc::file_exists},
415       {ERROR_BAD_NETPATH, errc::no_such_file_or_directory},
416       {ERROR_BAD_PATHNAME, errc::no_such_file_or_directory},
417       {ERROR_BAD_UNIT, errc::no_such_device},
418       {ERROR_BROKEN_PIPE, errc::broken_pipe},
419       {ERROR_BUFFER_OVERFLOW, errc::filename_too_long},
420       {ERROR_BUSY, errc::device_or_resource_busy},
421       {ERROR_BUSY_DRIVE, errc::device_or_resource_busy},
422       {ERROR_CANNOT_MAKE, errc::permission_denied},
423       {ERROR_CANTOPEN, errc::io_error},
424       {ERROR_CANTREAD, errc::io_error},
425       {ERROR_CANTWRITE, errc::io_error},
426       {ERROR_CURRENT_DIRECTORY, errc::permission_denied},
427       {ERROR_DEV_NOT_EXIST, errc::no_such_device},
428       {ERROR_DEVICE_IN_USE, errc::device_or_resource_busy},
429       {ERROR_DIR_NOT_EMPTY, errc::directory_not_empty},
430       {ERROR_DIRECTORY, errc::invalid_argument},
431       {ERROR_DISK_FULL, errc::no_space_on_device},
432       {ERROR_FILE_EXISTS, errc::file_exists},
433       {ERROR_FILE_NOT_FOUND, errc::no_such_file_or_directory},
434       {ERROR_HANDLE_DISK_FULL, errc::no_space_on_device},
435       {ERROR_INVALID_ACCESS, errc::permission_denied},
436       {ERROR_INVALID_DRIVE, errc::no_such_device},
437       {ERROR_INVALID_FUNCTION, errc::function_not_supported},
438       {ERROR_INVALID_HANDLE, errc::invalid_argument},
439       {ERROR_INVALID_NAME, errc::no_such_file_or_directory},
440       {ERROR_INVALID_PARAMETER, errc::invalid_argument},
441       {ERROR_LOCK_VIOLATION, errc::no_lock_available},
442       {ERROR_LOCKED, errc::no_lock_available},
443       {ERROR_NEGATIVE_SEEK, errc::invalid_argument},
444       {ERROR_NOACCESS, errc::permission_denied},
445       {ERROR_NOT_ENOUGH_MEMORY, errc::not_enough_memory},
446       {ERROR_NOT_READY, errc::resource_unavailable_try_again},
447       {ERROR_NOT_SAME_DEVICE, errc::cross_device_link},
448       {ERROR_NOT_SUPPORTED, errc::not_supported},
449       {ERROR_OPEN_FAILED, errc::io_error},
450       {ERROR_OPEN_FILES, errc::device_or_resource_busy},
451       {ERROR_OPERATION_ABORTED, errc::operation_canceled},
452       {ERROR_OUTOFMEMORY, errc::not_enough_memory},
453       {ERROR_PATH_NOT_FOUND, errc::no_such_file_or_directory},
454       {ERROR_READ_FAULT, errc::io_error},
455       {ERROR_REPARSE_TAG_INVALID, errc::invalid_argument},
456       {ERROR_RETRY, errc::resource_unavailable_try_again},
457       {ERROR_SEEK, errc::io_error},
458       {ERROR_SHARING_VIOLATION, errc::permission_denied},
459       {ERROR_TOO_MANY_OPEN_FILES, errc::too_many_files_open},
460       {ERROR_WRITE_FAULT, errc::io_error},
461       {ERROR_WRITE_PROTECT, errc::permission_denied},
462   };
463 
464   for (const auto &pair : win_error_mapping)
465     if (pair.win == static_cast<DWORD>(err))
466       return pair.errc;
467   return errc::invalid_argument;
468 }
469 
470 } // namespace detail
471 #endif
472 
473 namespace detail {
474 namespace {
475 
476 using value_type = path::value_type;
477 using string_type = path::string_type;
478 
479 struct FileDescriptor {
480   const path& name;
481   int fd = -1;
482   StatT m_stat;
483   file_status m_status;
484 
485   template <class... Args>
486   static FileDescriptor create(const path* p, error_code& ec, Args... args) {
487     ec.clear();
488     int fd;
489     if ((fd = detail::open(p->c_str(), args...)) == -1) {
490       ec = capture_errno();
491       return FileDescriptor{p};
492     }
493     return FileDescriptor(p, fd);
494   }
495 
496   template <class... Args>
497   static FileDescriptor create_with_status(const path* p, error_code& ec,
498                                            Args... args) {
499     FileDescriptor fd = create(p, ec, args...);
500     if (!ec)
501       fd.refresh_status(ec);
502 
503     return fd;
504   }
505 
506   file_status get_status() const { return m_status; }
507   StatT const& get_stat() const { return m_stat; }
508 
509   bool status_known() const { return _VSTD_FS::status_known(m_status); }
510 
511   file_status refresh_status(error_code& ec);
512 
513   void close() noexcept {
514     if (fd != -1)
515       detail::close(fd);
516     fd = -1;
517   }
518 
519   FileDescriptor(FileDescriptor&& other)
520       : name(other.name), fd(other.fd), m_stat(other.m_stat),
521         m_status(other.m_status) {
522     other.fd = -1;
523     other.m_status = file_status{};
524   }
525 
526   ~FileDescriptor() { close(); }
527 
528   FileDescriptor(FileDescriptor const&) = delete;
529   FileDescriptor& operator=(FileDescriptor const&) = delete;
530 
531 private:
532   explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {}
533 };
534 
535 perms posix_get_perms(const StatT& st) noexcept {
536   return static_cast<perms>(st.st_mode) & perms::mask;
537 }
538 
539 file_status create_file_status(error_code& m_ec, path const& p,
540                                const StatT& path_stat, error_code* ec) {
541   if (ec)
542     *ec = m_ec;
543   if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) {
544     return file_status(file_type::not_found);
545   } else if (m_ec) {
546     ErrorHandler<void> err("posix_stat", ec, &p);
547     err.report(m_ec, "failed to determine attributes for the specified path");
548     return file_status(file_type::none);
549   }
550   // else
551 
552   file_status fs_tmp;
553   auto const mode = path_stat.st_mode;
554   if (S_ISLNK(mode))
555     fs_tmp.type(file_type::symlink);
556   else if (S_ISREG(mode))
557     fs_tmp.type(file_type::regular);
558   else if (S_ISDIR(mode))
559     fs_tmp.type(file_type::directory);
560   else if (S_ISBLK(mode))
561     fs_tmp.type(file_type::block);
562   else if (S_ISCHR(mode))
563     fs_tmp.type(file_type::character);
564   else if (S_ISFIFO(mode))
565     fs_tmp.type(file_type::fifo);
566   else if (S_ISSOCK(mode))
567     fs_tmp.type(file_type::socket);
568   else
569     fs_tmp.type(file_type::unknown);
570 
571   fs_tmp.permissions(detail::posix_get_perms(path_stat));
572   return fs_tmp;
573 }
574 
575 file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) {
576   error_code m_ec;
577   if (detail::stat(p.c_str(), &path_stat) == -1)
578     m_ec = detail::capture_errno();
579   return create_file_status(m_ec, p, path_stat, ec);
580 }
581 
582 file_status posix_stat(path const& p, error_code* ec) {
583   StatT path_stat;
584   return posix_stat(p, path_stat, ec);
585 }
586 
587 file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) {
588   error_code m_ec;
589   if (detail::lstat(p.c_str(), &path_stat) == -1)
590     m_ec = detail::capture_errno();
591   return create_file_status(m_ec, p, path_stat, ec);
592 }
593 
594 file_status posix_lstat(path const& p, error_code* ec) {
595   StatT path_stat;
596   return posix_lstat(p, path_stat, ec);
597 }
598 
599 // http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
600 bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) {
601   if (detail::ftruncate(fd.fd, to_size) == -1) {
602     ec = capture_errno();
603     return true;
604   }
605   ec.clear();
606   return false;
607 }
608 
609 bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) {
610   if (detail::fchmod(fd.fd, st.st_mode) == -1) {
611     ec = capture_errno();
612     return true;
613   }
614   ec.clear();
615   return false;
616 }
617 
618 bool stat_equivalent(const StatT& st1, const StatT& st2) {
619   return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
620 }
621 
622 file_status FileDescriptor::refresh_status(error_code& ec) {
623   // FD must be open and good.
624   m_status = file_status{};
625   m_stat = {};
626   error_code m_ec;
627   if (detail::fstat(fd, &m_stat) == -1)
628     m_ec = capture_errno();
629   m_status = create_file_status(m_ec, name, m_stat, &ec);
630   return m_status;
631 }
632 } // namespace
633 } // end namespace detail
634 
635 using detail::capture_errno;
636 using detail::ErrorHandler;
637 using detail::StatT;
638 using detail::TimeSpec;
639 using parser::createView;
640 using parser::PathParser;
641 using parser::string_view_t;
642 
643 const bool _FilesystemClock::is_steady;
644 
645 _FilesystemClock::time_point _FilesystemClock::now() noexcept {
646   typedef chrono::duration<rep> __secs;
647 #if defined(_LIBCPP_WIN32API)
648   typedef chrono::duration<rep, nano> __nsecs;
649   FILETIME time;
650   GetSystemTimeAsFileTime(&time);
651   TimeSpec tp = detail::filetime_to_timespec(time);
652   return time_point(__secs(tp.tv_sec) +
653                     chrono::duration_cast<duration>(__nsecs(tp.tv_nsec)));
654 #elif defined(CLOCK_REALTIME)
655   typedef chrono::duration<rep, nano> __nsecs;
656   struct timespec tp;
657   if (0 != clock_gettime(CLOCK_REALTIME, &tp))
658     __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
659   return time_point(__secs(tp.tv_sec) +
660                     chrono::duration_cast<duration>(__nsecs(tp.tv_nsec)));
661 #else
662   typedef chrono::duration<rep, micro> __microsecs;
663   timeval tv;
664   gettimeofday(&tv, 0);
665   return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec));
666 #endif // CLOCK_REALTIME
667 }
668 
669 filesystem_error::~filesystem_error() {}
670 
671 void filesystem_error::__create_what(int __num_paths) {
672   const char* derived_what = system_error::what();
673   __storage_->__what_ = [&]() -> string {
674     switch (__num_paths) {
675     case 0:
676       return detail::format_string("filesystem error: %s", derived_what);
677     case 1:
678       return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "]",
679                                    derived_what, path1().c_str());
680     case 2:
681       return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "] [" PATH_CSTR_FMT "]",
682                                    derived_what, path1().c_str(), path2().c_str());
683     }
684     _LIBCPP_UNREACHABLE();
685   }();
686 }
687 
688 static path __do_absolute(const path& p, path* cwd, error_code* ec) {
689   if (ec)
690     ec->clear();
691   if (p.is_absolute())
692     return p;
693   *cwd = __current_path(ec);
694   if (ec && *ec)
695     return {};
696   return (*cwd) / p;
697 }
698 
699 path __absolute(const path& p, error_code* ec) {
700   path cwd;
701   return __do_absolute(p, &cwd, ec);
702 }
703 
704 path __canonical(path const& orig_p, error_code* ec) {
705   path cwd;
706   ErrorHandler<path> err("canonical", ec, &orig_p, &cwd);
707 
708   path p = __do_absolute(orig_p, &cwd, ec);
709 #if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || defined(_LIBCPP_WIN32API)
710   std::unique_ptr<path::value_type, decltype(&::free)>
711     hold(detail::realpath(p.c_str(), nullptr), &::free);
712   if (hold.get() == nullptr)
713     return err.report(capture_errno());
714   return {hold.get()};
715 #else
716   #if defined(__MVS__) && !defined(PATH_MAX)
717     path::value_type buff[ _XOPEN_PATH_MAX + 1 ];
718   #else
719     path::value_type buff[PATH_MAX + 1];
720   #endif
721   path::value_type* ret;
722   if ((ret = detail::realpath(p.c_str(), buff)) == nullptr)
723     return err.report(capture_errno());
724   return {ret};
725 #endif
726 }
727 
728 void __copy(const path& from, const path& to, copy_options options,
729             error_code* ec) {
730   ErrorHandler<void> err("copy", ec, &from, &to);
731 
732   const bool sym_status = bool(
733       options & (copy_options::create_symlinks | copy_options::skip_symlinks));
734 
735   const bool sym_status2 = bool(options & copy_options::copy_symlinks);
736 
737   error_code m_ec1;
738   StatT f_st = {};
739   const file_status f = sym_status || sym_status2
740                             ? detail::posix_lstat(from, f_st, &m_ec1)
741                             : detail::posix_stat(from, f_st, &m_ec1);
742   if (m_ec1)
743     return err.report(m_ec1);
744 
745   StatT t_st = {};
746   const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1)
747                                    : detail::posix_stat(to, t_st, &m_ec1);
748 
749   if (not status_known(t))
750     return err.report(m_ec1);
751 
752   if (!exists(f) || is_other(f) || is_other(t) ||
753       (is_directory(f) && is_regular_file(t)) ||
754       detail::stat_equivalent(f_st, t_st)) {
755     return err.report(errc::function_not_supported);
756   }
757 
758   if (ec)
759     ec->clear();
760 
761   if (is_symlink(f)) {
762     if (bool(copy_options::skip_symlinks & options)) {
763       // do nothing
764     } else if (not exists(t)) {
765       __copy_symlink(from, to, ec);
766     } else {
767       return err.report(errc::file_exists);
768     }
769     return;
770   } else if (is_regular_file(f)) {
771     if (bool(copy_options::directories_only & options)) {
772       // do nothing
773     } else if (bool(copy_options::create_symlinks & options)) {
774       __create_symlink(from, to, ec);
775     } else if (bool(copy_options::create_hard_links & options)) {
776       __create_hard_link(from, to, ec);
777     } else if (is_directory(t)) {
778       __copy_file(from, to / from.filename(), options, ec);
779     } else {
780       __copy_file(from, to, options, ec);
781     }
782     return;
783   } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) {
784     return err.report(errc::is_a_directory);
785   } else if (is_directory(f) && (bool(copy_options::recursive & options) ||
786                                  copy_options::none == options)) {
787 
788     if (!exists(t)) {
789       // create directory to with attributes from 'from'.
790       __create_directory(to, from, ec);
791       if (ec && *ec) {
792         return;
793       }
794     }
795     directory_iterator it =
796         ec ? directory_iterator(from, *ec) : directory_iterator(from);
797     if (ec && *ec) {
798       return;
799     }
800     error_code m_ec2;
801     for (; it != directory_iterator(); it.increment(m_ec2)) {
802       if (m_ec2) {
803         return err.report(m_ec2);
804       }
805       __copy(it->path(), to / it->path().filename(),
806              options | copy_options::__in_recursive_copy, ec);
807       if (ec && *ec) {
808         return;
809       }
810     }
811   }
812 }
813 
814 namespace detail {
815 namespace {
816 
817 #if defined(_LIBCPP_FILESYSTEM_USE_SENDFILE)
818   bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) {
819     size_t count = read_fd.get_stat().st_size;
820     do {
821       ssize_t res;
822       if ((res = ::sendfile(write_fd.fd, read_fd.fd, nullptr, count)) == -1) {
823         ec = capture_errno();
824         return false;
825       }
826       count -= res;
827     } while (count > 0);
828 
829     ec.clear();
830 
831     return true;
832   }
833 #elif defined(_LIBCPP_FILESYSTEM_USE_COPYFILE)
834   bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) {
835     struct CopyFileState {
836       copyfile_state_t state;
837       CopyFileState() { state = copyfile_state_alloc(); }
838       ~CopyFileState() { copyfile_state_free(state); }
839 
840     private:
841       CopyFileState(CopyFileState const&) = delete;
842       CopyFileState& operator=(CopyFileState const&) = delete;
843     };
844 
845     CopyFileState cfs;
846     if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) {
847       ec = capture_errno();
848       return false;
849     }
850 
851     ec.clear();
852     return true;
853   }
854 #elif defined(_LIBCPP_FILESYSTEM_USE_FSTREAM)
855   bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) {
856     ifstream in;
857     in.__open(read_fd.fd, ios::binary);
858     if (!in.is_open()) {
859       // This assumes that __open didn't reset the error code.
860       ec = capture_errno();
861       return false;
862     }
863     read_fd.fd = -1;
864     ofstream out;
865     out.__open(write_fd.fd, ios::binary);
866     if (!out.is_open()) {
867       ec = capture_errno();
868       return false;
869     }
870     write_fd.fd = -1;
871 
872     if (in.good() && out.good()) {
873       using InIt = istreambuf_iterator<char>;
874       using OutIt = ostreambuf_iterator<char>;
875       InIt bin(in);
876       InIt ein;
877       OutIt bout(out);
878       copy(bin, ein, bout);
879     }
880     if (out.fail() || in.fail()) {
881       ec = make_error_code(errc::io_error);
882       return false;
883     }
884 
885     ec.clear();
886     return true;
887   }
888 #else
889 # error "Unknown implementation for copy_file_impl"
890 #endif // copy_file_impl implementation
891 
892 } // end anonymous namespace
893 } // end namespace detail
894 
895 bool __copy_file(const path& from, const path& to, copy_options options,
896                  error_code* ec) {
897   using detail::FileDescriptor;
898   ErrorHandler<bool> err("copy_file", ec, &to, &from);
899 
900   error_code m_ec;
901   FileDescriptor from_fd = FileDescriptor::create_with_status(
902       &from, m_ec, O_RDONLY | O_NONBLOCK | O_BINARY);
903   if (m_ec)
904     return err.report(m_ec);
905 
906   auto from_st = from_fd.get_status();
907   StatT const& from_stat = from_fd.get_stat();
908   if (!is_regular_file(from_st)) {
909     if (not m_ec)
910       m_ec = make_error_code(errc::not_supported);
911     return err.report(m_ec);
912   }
913 
914   const bool skip_existing = bool(copy_options::skip_existing & options);
915   const bool update_existing = bool(copy_options::update_existing & options);
916   const bool overwrite_existing =
917       bool(copy_options::overwrite_existing & options);
918 
919   StatT to_stat_path;
920   file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec);
921   if (!status_known(to_st))
922     return err.report(m_ec);
923 
924   const bool to_exists = exists(to_st);
925   if (to_exists && !is_regular_file(to_st))
926     return err.report(errc::not_supported);
927 
928   if (to_exists && detail::stat_equivalent(from_stat, to_stat_path))
929     return err.report(errc::file_exists);
930 
931   if (to_exists && skip_existing)
932     return false;
933 
934   bool ShouldCopy = [&]() {
935     if (to_exists && update_existing) {
936       auto from_time = detail::extract_mtime(from_stat);
937       auto to_time = detail::extract_mtime(to_stat_path);
938       if (from_time.tv_sec < to_time.tv_sec)
939         return false;
940       if (from_time.tv_sec == to_time.tv_sec &&
941           from_time.tv_nsec <= to_time.tv_nsec)
942         return false;
943       return true;
944     }
945     if (!to_exists || overwrite_existing)
946       return true;
947     return err.report(errc::file_exists);
948   }();
949   if (!ShouldCopy)
950     return false;
951 
952   // Don't truncate right away. We may not be opening the file we originally
953   // looked at; we'll check this later.
954   int to_open_flags = O_WRONLY | O_BINARY;
955   if (!to_exists)
956     to_open_flags |= O_CREAT;
957   FileDescriptor to_fd = FileDescriptor::create_with_status(
958       &to, m_ec, to_open_flags, from_stat.st_mode);
959   if (m_ec)
960     return err.report(m_ec);
961 
962   if (to_exists) {
963     // Check that the file we initially stat'ed is equivalent to the one
964     // we opened.
965     // FIXME: report this better.
966     if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat()))
967       return err.report(errc::bad_file_descriptor);
968 
969     // Set the permissions and truncate the file we opened.
970     if (detail::posix_fchmod(to_fd, from_stat, m_ec))
971       return err.report(m_ec);
972     if (detail::posix_ftruncate(to_fd, 0, m_ec))
973       return err.report(m_ec);
974   }
975 
976   if (!copy_file_impl(from_fd, to_fd, m_ec)) {
977     // FIXME: Remove the dest file if we failed, and it didn't exist previously.
978     return err.report(m_ec);
979   }
980 
981   return true;
982 }
983 
984 void __copy_symlink(const path& existing_symlink, const path& new_symlink,
985                     error_code* ec) {
986   const path real_path(__read_symlink(existing_symlink, ec));
987   if (ec && *ec) {
988     return;
989   }
990 #if defined(_LIBCPP_WIN32API)
991   error_code local_ec;
992   if (is_directory(real_path, local_ec))
993     __create_directory_symlink(real_path, new_symlink, ec);
994   else
995 #endif
996     __create_symlink(real_path, new_symlink, ec);
997 }
998 
999 bool __create_directories(const path& p, error_code* ec) {
1000   ErrorHandler<bool> err("create_directories", ec, &p);
1001 
1002   error_code m_ec;
1003   auto const st = detail::posix_stat(p, &m_ec);
1004   if (!status_known(st))
1005     return err.report(m_ec);
1006   else if (is_directory(st))
1007     return false;
1008   else if (exists(st))
1009     return err.report(errc::file_exists);
1010 
1011   const path parent = p.parent_path();
1012   if (!parent.empty()) {
1013     const file_status parent_st = status(parent, m_ec);
1014     if (not status_known(parent_st))
1015       return err.report(m_ec);
1016     if (not exists(parent_st)) {
1017       if (parent == p)
1018         return err.report(errc::invalid_argument);
1019       __create_directories(parent, ec);
1020       if (ec && *ec) {
1021         return false;
1022       }
1023     } else if (not is_directory(parent_st))
1024       return err.report(errc::not_a_directory);
1025   }
1026   bool ret = __create_directory(p, &m_ec);
1027   if (m_ec)
1028     return err.report(m_ec);
1029   return ret;
1030 }
1031 
1032 bool __create_directory(const path& p, error_code* ec) {
1033   ErrorHandler<bool> err("create_directory", ec, &p);
1034 
1035   if (detail::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0)
1036     return true;
1037 
1038   if (errno != EEXIST)
1039     return err.report(capture_errno());
1040   error_code mec = capture_errno();
1041   error_code ignored_ec;
1042   const file_status st = status(p, ignored_ec);
1043   if (!is_directory(st))
1044     return err.report(mec);
1045   return false;
1046 }
1047 
1048 bool __create_directory(path const& p, path const& attributes, error_code* ec) {
1049   ErrorHandler<bool> err("create_directory", ec, &p, &attributes);
1050 
1051   StatT attr_stat;
1052   error_code mec;
1053   file_status st = detail::posix_stat(attributes, attr_stat, &mec);
1054   if (!status_known(st))
1055     return err.report(mec);
1056   if (!is_directory(st))
1057     return err.report(errc::not_a_directory,
1058                       "the specified attribute path is invalid");
1059 
1060   if (detail::mkdir(p.c_str(), attr_stat.st_mode) == 0)
1061     return true;
1062 
1063   if (errno != EEXIST)
1064     return err.report(capture_errno());
1065 
1066   mec = capture_errno();
1067   error_code ignored_ec;
1068   st = status(p, ignored_ec);
1069   if (!is_directory(st))
1070     return err.report(mec);
1071   return false;
1072 }
1073 
1074 void __create_directory_symlink(path const& from, path const& to,
1075                                 error_code* ec) {
1076   ErrorHandler<void> err("create_directory_symlink", ec, &from, &to);
1077   if (detail::symlink_dir(from.c_str(), to.c_str()) == -1)
1078     return err.report(capture_errno());
1079 }
1080 
1081 void __create_hard_link(const path& from, const path& to, error_code* ec) {
1082   ErrorHandler<void> err("create_hard_link", ec, &from, &to);
1083   if (detail::link(from.c_str(), to.c_str()) == -1)
1084     return err.report(capture_errno());
1085 }
1086 
1087 void __create_symlink(path const& from, path const& to, error_code* ec) {
1088   ErrorHandler<void> err("create_symlink", ec, &from, &to);
1089   if (detail::symlink_file(from.c_str(), to.c_str()) == -1)
1090     return err.report(capture_errno());
1091 }
1092 
1093 path __current_path(error_code* ec) {
1094   ErrorHandler<path> err("current_path", ec);
1095 
1096 #if defined(_LIBCPP_WIN32API) || defined(__GLIBC__) || defined(__APPLE__)
1097   // Common extension outside of POSIX getcwd() spec, without needing to
1098   // preallocate a buffer. Also supported by a number of other POSIX libcs.
1099   int size = 0;
1100   path::value_type* ptr = nullptr;
1101   typedef decltype(&::free) Deleter;
1102   Deleter deleter = &::free;
1103 #else
1104   auto size = ::pathconf(".", _PC_PATH_MAX);
1105   _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size");
1106 
1107   auto buff = unique_ptr<path::value_type[]>(new path::value_type[size + 1]);
1108   path::value_type* ptr = buff.get();
1109 
1110   // Preallocated buffer, don't free the buffer in the second unique_ptr
1111   // below.
1112   struct Deleter { void operator()(void*) const {} };
1113   Deleter deleter;
1114 #endif
1115 
1116   unique_ptr<path::value_type, Deleter> hold(detail::getcwd(ptr, size),
1117                                              deleter);
1118   if (hold.get() == nullptr)
1119     return err.report(capture_errno(), "call to getcwd failed");
1120 
1121   return {hold.get()};
1122 }
1123 
1124 void __current_path(const path& p, error_code* ec) {
1125   ErrorHandler<void> err("current_path", ec, &p);
1126   if (detail::chdir(p.c_str()) == -1)
1127     err.report(capture_errno());
1128 }
1129 
1130 bool __equivalent(const path& p1, const path& p2, error_code* ec) {
1131   ErrorHandler<bool> err("equivalent", ec, &p1, &p2);
1132 
1133   error_code ec1, ec2;
1134   StatT st1 = {}, st2 = {};
1135   auto s1 = detail::posix_stat(p1.native(), st1, &ec1);
1136   if (!exists(s1))
1137     return err.report(errc::not_supported);
1138   auto s2 = detail::posix_stat(p2.native(), st2, &ec2);
1139   if (!exists(s2))
1140     return err.report(errc::not_supported);
1141 
1142   return detail::stat_equivalent(st1, st2);
1143 }
1144 
1145 uintmax_t __file_size(const path& p, error_code* ec) {
1146   ErrorHandler<uintmax_t> err("file_size", ec, &p);
1147 
1148   error_code m_ec;
1149   StatT st;
1150   file_status fst = detail::posix_stat(p, st, &m_ec);
1151   if (!exists(fst) || !is_regular_file(fst)) {
1152     errc error_kind =
1153         is_directory(fst) ? errc::is_a_directory : errc::not_supported;
1154     if (!m_ec)
1155       m_ec = make_error_code(error_kind);
1156     return err.report(m_ec);
1157   }
1158   // is_regular_file(p) == true
1159   return static_cast<uintmax_t>(st.st_size);
1160 }
1161 
1162 uintmax_t __hard_link_count(const path& p, error_code* ec) {
1163   ErrorHandler<uintmax_t> err("hard_link_count", ec, &p);
1164 
1165   error_code m_ec;
1166   StatT st;
1167   detail::posix_stat(p, st, &m_ec);
1168   if (m_ec)
1169     return err.report(m_ec);
1170   return static_cast<uintmax_t>(st.st_nlink);
1171 }
1172 
1173 bool __fs_is_empty(const path& p, error_code* ec) {
1174   ErrorHandler<bool> err("is_empty", ec, &p);
1175 
1176   error_code m_ec;
1177   StatT pst;
1178   auto st = detail::posix_stat(p, pst, &m_ec);
1179   if (m_ec)
1180     return err.report(m_ec);
1181   else if (!is_directory(st) && !is_regular_file(st))
1182     return err.report(errc::not_supported);
1183   else if (is_directory(st)) {
1184     auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p);
1185     if (ec && *ec)
1186       return false;
1187     return it == directory_iterator{};
1188   } else if (is_regular_file(st))
1189     return static_cast<uintmax_t>(pst.st_size) == 0;
1190 
1191   _LIBCPP_UNREACHABLE();
1192 }
1193 
1194 static file_time_type __extract_last_write_time(const path& p, const StatT& st,
1195                                                 error_code* ec) {
1196   using detail::fs_time;
1197   ErrorHandler<file_time_type> err("last_write_time", ec, &p);
1198 
1199   auto ts = detail::extract_mtime(st);
1200   if (!fs_time::is_representable(ts))
1201     return err.report(errc::value_too_large);
1202 
1203   return fs_time::convert_from_timespec(ts);
1204 }
1205 
1206 file_time_type __last_write_time(const path& p, error_code* ec) {
1207   using namespace chrono;
1208   ErrorHandler<file_time_type> err("last_write_time", ec, &p);
1209 
1210   error_code m_ec;
1211   StatT st;
1212   detail::posix_stat(p, st, &m_ec);
1213   if (m_ec)
1214     return err.report(m_ec);
1215   return __extract_last_write_time(p, st, ec);
1216 }
1217 
1218 void __last_write_time(const path& p, file_time_type new_time, error_code* ec) {
1219   using detail::fs_time;
1220   ErrorHandler<void> err("last_write_time", ec, &p);
1221 
1222 #if defined(_LIBCPP_WIN32API)
1223   TimeSpec ts;
1224   if (!fs_time::convert_to_timespec(ts, new_time))
1225     return err.report(errc::value_too_large);
1226   detail::WinHandle h(p.c_str(), FILE_WRITE_ATTRIBUTES, 0);
1227   if (!h)
1228     return err.report(detail::make_windows_error(GetLastError()));
1229   FILETIME last_write = timespec_to_filetime(ts);
1230   if (!SetFileTime(h, nullptr, nullptr, &last_write))
1231     return err.report(detail::make_windows_error(GetLastError()));
1232 #else
1233   error_code m_ec;
1234   array<TimeSpec, 2> tbuf;
1235 #if !defined(_LIBCPP_USE_UTIMENSAT)
1236   // This implementation has a race condition between determining the
1237   // last access time and attempting to set it to the same value using
1238   // ::utimes
1239   StatT st;
1240   file_status fst = detail::posix_stat(p, st, &m_ec);
1241   if (m_ec)
1242     return err.report(m_ec);
1243   tbuf[0] = detail::extract_atime(st);
1244 #else
1245   tbuf[0].tv_sec = 0;
1246   tbuf[0].tv_nsec = UTIME_OMIT;
1247 #endif
1248   if (!fs_time::convert_to_timespec(tbuf[1], new_time))
1249     return err.report(errc::value_too_large);
1250 
1251   detail::set_file_times(p, tbuf, m_ec);
1252   if (m_ec)
1253     return err.report(m_ec);
1254 #endif
1255 }
1256 
1257 void __permissions(const path& p, perms prms, perm_options opts,
1258                    error_code* ec) {
1259   ErrorHandler<void> err("permissions", ec, &p);
1260 
1261   auto has_opt = [&](perm_options o) { return bool(o & opts); };
1262   const bool resolve_symlinks = !has_opt(perm_options::nofollow);
1263   const bool add_perms = has_opt(perm_options::add);
1264   const bool remove_perms = has_opt(perm_options::remove);
1265   _LIBCPP_ASSERT(
1266       (add_perms + remove_perms + has_opt(perm_options::replace)) == 1,
1267       "One and only one of the perm_options constants replace, add, or remove "
1268       "is present in opts");
1269 
1270   bool set_sym_perms = false;
1271   prms &= perms::mask;
1272   if (!resolve_symlinks || (add_perms || remove_perms)) {
1273     error_code m_ec;
1274     file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec)
1275                                       : detail::posix_lstat(p, &m_ec);
1276     set_sym_perms = is_symlink(st);
1277     if (m_ec)
1278       return err.report(m_ec);
1279     _LIBCPP_ASSERT(st.permissions() != perms::unknown,
1280                    "Permissions unexpectedly unknown");
1281     if (add_perms)
1282       prms |= st.permissions();
1283     else if (remove_perms)
1284       prms = st.permissions() & ~prms;
1285   }
1286   const auto real_perms = static_cast<detail::ModeT>(prms & perms::mask);
1287 
1288 #if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
1289   const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0;
1290   if (detail::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) {
1291     return err.report(capture_errno());
1292   }
1293 #else
1294   if (set_sym_perms)
1295     return err.report(errc::operation_not_supported);
1296   if (::chmod(p.c_str(), real_perms) == -1) {
1297     return err.report(capture_errno());
1298   }
1299 #endif
1300 }
1301 
1302 path __read_symlink(const path& p, error_code* ec) {
1303   ErrorHandler<path> err("read_symlink", ec, &p);
1304 
1305 #if defined(PATH_MAX) || defined(MAX_SYMLINK_SIZE)
1306   struct NullDeleter { void operator()(void*) const {} };
1307 #ifdef MAX_SYMLINK_SIZE
1308   const size_t size = MAX_SYMLINK_SIZE + 1;
1309 #else
1310   const size_t size = PATH_MAX + 1;
1311 #endif
1312   path::value_type stack_buff[size];
1313   auto buff = std::unique_ptr<path::value_type[], NullDeleter>(stack_buff);
1314 #else
1315   StatT sb;
1316   if (detail::lstat(p.c_str(), &sb) == -1) {
1317     return err.report(capture_errno());
1318   }
1319   const size_t size = sb.st_size + 1;
1320   auto buff = unique_ptr<path::value_type[]>(new path::value_type[size]);
1321 #endif
1322   detail::SSizeT ret;
1323   if ((ret = detail::readlink(p.c_str(), buff.get(), size)) == -1)
1324     return err.report(capture_errno());
1325   _LIBCPP_ASSERT(ret > 0, "TODO");
1326   if (static_cast<size_t>(ret) >= size)
1327     return err.report(errc::value_too_large);
1328   buff[ret] = 0;
1329   return {buff.get()};
1330 }
1331 
1332 bool __remove(const path& p, error_code* ec) {
1333   ErrorHandler<bool> err("remove", ec, &p);
1334   if (detail::remove(p.c_str()) == -1) {
1335     if (errno != ENOENT)
1336       err.report(capture_errno());
1337     return false;
1338   }
1339   return true;
1340 }
1341 
1342 // We currently have two implementations of `__remove_all`. The first one is general and
1343 // used on platforms where we don't have access to the `openat()` family of POSIX functions.
1344 // That implementation uses `directory_iterator`, however it is vulnerable to some race
1345 // conditions, see https://reviews.llvm.org/D118134 for details.
1346 //
1347 // The second implementation is used on platforms where `openat()` & friends are available,
1348 // and it threads file descriptors through recursive calls to avoid such race conditions.
1349 #if defined(_LIBCPP_WIN32API)
1350 # define REMOVE_ALL_USE_DIRECTORY_ITERATOR
1351 #endif
1352 
1353 #if defined(REMOVE_ALL_USE_DIRECTORY_ITERATOR)
1354 
1355 namespace {
1356 
1357 uintmax_t remove_all_impl(path const& p, error_code& ec) {
1358   const auto npos = static_cast<uintmax_t>(-1);
1359   const file_status st = __symlink_status(p, &ec);
1360   if (ec)
1361     return npos;
1362   uintmax_t count = 1;
1363   if (is_directory(st)) {
1364     for (directory_iterator it(p, ec); !ec && it != directory_iterator();
1365          it.increment(ec)) {
1366       auto other_count = remove_all_impl(it->path(), ec);
1367       if (ec)
1368         return npos;
1369       count += other_count;
1370     }
1371     if (ec)
1372       return npos;
1373   }
1374   if (!__remove(p, &ec))
1375     return npos;
1376   return count;
1377 }
1378 
1379 } // end namespace
1380 
1381 uintmax_t __remove_all(const path& p, error_code* ec) {
1382   ErrorHandler<uintmax_t> err("remove_all", ec, &p);
1383 
1384   error_code mec;
1385   auto count = remove_all_impl(p, mec);
1386   if (mec) {
1387     if (mec == errc::no_such_file_or_directory)
1388       return 0;
1389     return err.report(mec);
1390   }
1391   return count;
1392 }
1393 
1394 #else // !REMOVE_ALL_USE_DIRECTORY_ITERATOR
1395 
1396 namespace {
1397 
1398 template <class Cleanup>
1399 struct scope_exit {
1400   explicit scope_exit(Cleanup const& cleanup)
1401     : cleanup_(cleanup)
1402   { }
1403 
1404   ~scope_exit() { cleanup_(); }
1405 
1406 private:
1407   Cleanup cleanup_;
1408 };
1409 
1410 uintmax_t remove_all_impl(int parent_directory, const path& p, error_code& ec) {
1411   // First, try to open the path as a directory.
1412   const int options = O_CLOEXEC | O_RDONLY | O_DIRECTORY | O_NOFOLLOW;
1413   int fd = ::openat(parent_directory, p.c_str(), options);
1414   if (fd != -1) {
1415     // If that worked, iterate over the contents of the directory and
1416     // remove everything in it, recursively.
1417     scope_exit close_fd([=] { ::close(fd); });
1418     DIR* stream = ::fdopendir(fd);
1419     if (stream == nullptr) {
1420       ec = detail::capture_errno();
1421       return 0;
1422     }
1423     scope_exit close_stream([=] { ::closedir(stream); });
1424 
1425     uintmax_t count = 0;
1426     while (true) {
1427       auto [str, type] = detail::posix_readdir(stream, ec);
1428       static_assert(std::is_same_v<decltype(str), std::string_view>);
1429       if (str == "." || str == "..") {
1430         continue;
1431       } else if (ec || str.empty()) {
1432         break; // we're done iterating through the directory
1433       } else {
1434         count += remove_all_impl(fd, str, ec);
1435       }
1436     }
1437 
1438     // Then, remove the now-empty directory itself.
1439     if (::unlinkat(parent_directory, p.c_str(), AT_REMOVEDIR) == -1) {
1440       ec = detail::capture_errno();
1441       return count;
1442     }
1443 
1444     return count + 1; // the contents of the directory + the directory itself
1445   }
1446 
1447   ec = detail::capture_errno();
1448 
1449   // If we failed to open `p` because it didn't exist, it's not an
1450   // error -- it might have moved or have been deleted already.
1451   if (ec == errc::no_such_file_or_directory) {
1452     ec.clear();
1453     return 0;
1454   }
1455 
1456   // If opening `p` failed because it wasn't a directory, remove it as
1457   // a normal file instead. Note that `openat()` can return either ENOTDIR
1458   // or ELOOP depending on the exact reason of the failure.
1459   if (ec == errc::not_a_directory || ec == errc::too_many_symbolic_link_levels) {
1460     ec.clear();
1461     if (::unlinkat(parent_directory, p.c_str(), /* flags = */0) == -1) {
1462       ec = detail::capture_errno();
1463       return 0;
1464     }
1465     return 1;
1466   }
1467 
1468   // Otherwise, it's a real error -- we don't remove anything.
1469   return 0;
1470 }
1471 
1472 } // end namespace
1473 
1474 uintmax_t __remove_all(const path& p, error_code* ec) {
1475   ErrorHandler<uintmax_t> err("remove_all", ec, &p);
1476   error_code mec;
1477   uintmax_t count = remove_all_impl(AT_FDCWD, p, mec);
1478   if (mec)
1479     return err.report(mec);
1480   return count;
1481 }
1482 
1483 #endif // REMOVE_ALL_USE_DIRECTORY_ITERATOR
1484 
1485 void __rename(const path& from, const path& to, error_code* ec) {
1486   ErrorHandler<void> err("rename", ec, &from, &to);
1487   if (detail::rename(from.c_str(), to.c_str()) == -1)
1488     err.report(capture_errno());
1489 }
1490 
1491 void __resize_file(const path& p, uintmax_t size, error_code* ec) {
1492   ErrorHandler<void> err("resize_file", ec, &p);
1493   if (detail::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1)
1494     return err.report(capture_errno());
1495 }
1496 
1497 space_info __space(const path& p, error_code* ec) {
1498   ErrorHandler<void> err("space", ec, &p);
1499   space_info si;
1500   detail::StatVFS m_svfs = {};
1501   if (detail::statvfs(p.c_str(), &m_svfs) == -1) {
1502     err.report(capture_errno());
1503     si.capacity = si.free = si.available = static_cast<uintmax_t>(-1);
1504     return si;
1505   }
1506   // Multiply with overflow checking.
1507   auto do_mult = [&](uintmax_t& out, uintmax_t other) {
1508     out = other * m_svfs.f_frsize;
1509     if (other == 0 || out / other != m_svfs.f_frsize)
1510       out = static_cast<uintmax_t>(-1);
1511   };
1512   do_mult(si.capacity, m_svfs.f_blocks);
1513   do_mult(si.free, m_svfs.f_bfree);
1514   do_mult(si.available, m_svfs.f_bavail);
1515   return si;
1516 }
1517 
1518 file_status __status(const path& p, error_code* ec) {
1519   return detail::posix_stat(p, ec);
1520 }
1521 
1522 file_status __symlink_status(const path& p, error_code* ec) {
1523   return detail::posix_lstat(p, ec);
1524 }
1525 
1526 path __temp_directory_path(error_code* ec) {
1527   ErrorHandler<path> err("temp_directory_path", ec);
1528 
1529 #if defined(_LIBCPP_WIN32API)
1530   wchar_t buf[MAX_PATH];
1531   DWORD retval = GetTempPathW(MAX_PATH, buf);
1532   if (!retval)
1533     return err.report(detail::make_windows_error(GetLastError()));
1534   if (retval > MAX_PATH)
1535     return err.report(errc::filename_too_long);
1536   // GetTempPathW returns a path with a trailing slash, which we
1537   // shouldn't include for consistency.
1538   if (buf[retval-1] == L'\\')
1539     buf[retval-1] = L'\0';
1540   path p(buf);
1541 #else
1542   const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
1543   const char* ret = nullptr;
1544 
1545   for (auto& ep : env_paths)
1546     if ((ret = getenv(ep)))
1547       break;
1548   if (ret == nullptr)
1549     ret = "/tmp";
1550 
1551   path p(ret);
1552 #endif
1553   error_code m_ec;
1554   file_status st = detail::posix_stat(p, &m_ec);
1555   if (!status_known(st))
1556     return err.report(m_ec, "cannot access path " PATH_CSTR_FMT, p.c_str());
1557 
1558   if (!exists(st) || !is_directory(st))
1559     return err.report(errc::not_a_directory,
1560                       "path " PATH_CSTR_FMT " is not a directory", p.c_str());
1561 
1562   return p;
1563 }
1564 
1565 path __weakly_canonical(const path& p, error_code* ec) {
1566   ErrorHandler<path> err("weakly_canonical", ec, &p);
1567 
1568   if (p.empty())
1569     return __canonical("", ec);
1570 
1571   path result;
1572   path tmp;
1573   tmp.__reserve(p.native().size());
1574   auto PP = PathParser::CreateEnd(p.native());
1575   --PP;
1576   vector<string_view_t> DNEParts;
1577 
1578   while (PP.State != PathParser::PS_BeforeBegin) {
1579     tmp.assign(createView(p.native().data(), &PP.RawEntry.back()));
1580     error_code m_ec;
1581     file_status st = __status(tmp, &m_ec);
1582     if (!status_known(st)) {
1583       return err.report(m_ec);
1584     } else if (exists(st)) {
1585       result = __canonical(tmp, ec);
1586       break;
1587     }
1588     DNEParts.push_back(*PP);
1589     --PP;
1590   }
1591   if (PP.State == PathParser::PS_BeforeBegin)
1592     result = __canonical("", ec);
1593   if (ec)
1594     ec->clear();
1595   if (DNEParts.empty())
1596     return result;
1597   for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It)
1598     result /= *It;
1599   return result.lexically_normal();
1600 }
1601 
1602 ///////////////////////////////////////////////////////////////////////////////
1603 //                            path definitions
1604 ///////////////////////////////////////////////////////////////////////////////
1605 
1606 constexpr path::value_type path::preferred_separator;
1607 
1608 path& path::replace_extension(path const& replacement) {
1609   path p = extension();
1610   if (not p.empty()) {
1611     __pn_.erase(__pn_.size() - p.native().size());
1612   }
1613   if (!replacement.empty()) {
1614     if (replacement.native()[0] != '.') {
1615       __pn_ += PS(".");
1616     }
1617     __pn_.append(replacement.__pn_);
1618   }
1619   return *this;
1620 }
1621 
1622 ///////////////////////////////////////////////////////////////////////////////
1623 // path.decompose
1624 
1625 string_view_t path::__root_name() const {
1626   auto PP = PathParser::CreateBegin(__pn_);
1627   if (PP.State == PathParser::PS_InRootName)
1628     return *PP;
1629   return {};
1630 }
1631 
1632 string_view_t path::__root_directory() const {
1633   auto PP = PathParser::CreateBegin(__pn_);
1634   if (PP.State == PathParser::PS_InRootName)
1635     ++PP;
1636   if (PP.State == PathParser::PS_InRootDir)
1637     return *PP;
1638   return {};
1639 }
1640 
1641 string_view_t path::__root_path_raw() const {
1642   auto PP = PathParser::CreateBegin(__pn_);
1643   if (PP.State == PathParser::PS_InRootName) {
1644     auto NextCh = PP.peek();
1645     if (NextCh && isSeparator(*NextCh)) {
1646       ++PP;
1647       return createView(__pn_.data(), &PP.RawEntry.back());
1648     }
1649     return PP.RawEntry;
1650   }
1651   if (PP.State == PathParser::PS_InRootDir)
1652     return *PP;
1653   return {};
1654 }
1655 
1656 static bool ConsumeRootName(PathParser *PP) {
1657   static_assert(PathParser::PS_BeforeBegin == 1 &&
1658       PathParser::PS_InRootName == 2,
1659       "Values for enums are incorrect");
1660   while (PP->State <= PathParser::PS_InRootName)
1661     ++(*PP);
1662   return PP->State == PathParser::PS_AtEnd;
1663 }
1664 
1665 static bool ConsumeRootDir(PathParser* PP) {
1666   static_assert(PathParser::PS_BeforeBegin == 1 &&
1667                 PathParser::PS_InRootName == 2 &&
1668                 PathParser::PS_InRootDir == 3, "Values for enums are incorrect");
1669   while (PP->State <= PathParser::PS_InRootDir)
1670     ++(*PP);
1671   return PP->State == PathParser::PS_AtEnd;
1672 }
1673 
1674 string_view_t path::__relative_path() const {
1675   auto PP = PathParser::CreateBegin(__pn_);
1676   if (ConsumeRootDir(&PP))
1677     return {};
1678   return createView(PP.RawEntry.data(), &__pn_.back());
1679 }
1680 
1681 string_view_t path::__parent_path() const {
1682   if (empty())
1683     return {};
1684   // Determine if we have a root path but not a relative path. In that case
1685   // return *this.
1686   {
1687     auto PP = PathParser::CreateBegin(__pn_);
1688     if (ConsumeRootDir(&PP))
1689       return __pn_;
1690   }
1691   // Otherwise remove a single element from the end of the path, and return
1692   // a string representing that path
1693   {
1694     auto PP = PathParser::CreateEnd(__pn_);
1695     --PP;
1696     if (PP.RawEntry.data() == __pn_.data())
1697       return {};
1698     --PP;
1699     return createView(__pn_.data(), &PP.RawEntry.back());
1700   }
1701 }
1702 
1703 string_view_t path::__filename() const {
1704   if (empty())
1705     return {};
1706   {
1707     PathParser PP = PathParser::CreateBegin(__pn_);
1708     if (ConsumeRootDir(&PP))
1709       return {};
1710   }
1711   return *(--PathParser::CreateEnd(__pn_));
1712 }
1713 
1714 string_view_t path::__stem() const {
1715   return parser::separate_filename(__filename()).first;
1716 }
1717 
1718 string_view_t path::__extension() const {
1719   return parser::separate_filename(__filename()).second;
1720 }
1721 
1722 ////////////////////////////////////////////////////////////////////////////
1723 // path.gen
1724 
1725 enum PathPartKind : unsigned char {
1726   PK_None,
1727   PK_RootSep,
1728   PK_Filename,
1729   PK_Dot,
1730   PK_DotDot,
1731   PK_TrailingSep
1732 };
1733 
1734 static PathPartKind ClassifyPathPart(string_view_t Part) {
1735   if (Part.empty())
1736     return PK_TrailingSep;
1737   if (Part == PS("."))
1738     return PK_Dot;
1739   if (Part == PS(".."))
1740     return PK_DotDot;
1741   if (Part == PS("/"))
1742     return PK_RootSep;
1743 #if defined(_LIBCPP_WIN32API)
1744   if (Part == PS("\\"))
1745     return PK_RootSep;
1746 #endif
1747   return PK_Filename;
1748 }
1749 
1750 path path::lexically_normal() const {
1751   if (__pn_.empty())
1752     return *this;
1753 
1754   using PartKindPair = pair<string_view_t, PathPartKind>;
1755   vector<PartKindPair> Parts;
1756   // Guess as to how many elements the path has to avoid reallocating.
1757   Parts.reserve(32);
1758 
1759   // Track the total size of the parts as we collect them. This allows the
1760   // resulting path to reserve the correct amount of memory.
1761   size_t NewPathSize = 0;
1762   auto AddPart = [&](PathPartKind K, string_view_t P) {
1763     NewPathSize += P.size();
1764     Parts.emplace_back(P, K);
1765   };
1766   auto LastPartKind = [&]() {
1767     if (Parts.empty())
1768       return PK_None;
1769     return Parts.back().second;
1770   };
1771 
1772   bool MaybeNeedTrailingSep = false;
1773   // Build a stack containing the remaining elements of the path, popping off
1774   // elements which occur before a '..' entry.
1775   for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) {
1776     auto Part = *PP;
1777     PathPartKind Kind = ClassifyPathPart(Part);
1778     switch (Kind) {
1779     case PK_Filename:
1780     case PK_RootSep: {
1781       // Add all non-dot and non-dot-dot elements to the stack of elements.
1782       AddPart(Kind, Part);
1783       MaybeNeedTrailingSep = false;
1784       break;
1785     }
1786     case PK_DotDot: {
1787       // Only push a ".." element if there are no elements preceding the "..",
1788       // or if the preceding element is itself "..".
1789       auto LastKind = LastPartKind();
1790       if (LastKind == PK_Filename) {
1791         NewPathSize -= Parts.back().first.size();
1792         Parts.pop_back();
1793       } else if (LastKind != PK_RootSep)
1794         AddPart(PK_DotDot, PS(".."));
1795       MaybeNeedTrailingSep = LastKind == PK_Filename;
1796       break;
1797     }
1798     case PK_Dot:
1799     case PK_TrailingSep: {
1800       MaybeNeedTrailingSep = true;
1801       break;
1802     }
1803     case PK_None:
1804       _LIBCPP_UNREACHABLE();
1805     }
1806   }
1807   // [fs.path.generic]p6.8: If the path is empty, add a dot.
1808   if (Parts.empty())
1809     return PS(".");
1810 
1811   // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any
1812   // trailing directory-separator.
1813   bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename;
1814 
1815   path Result;
1816   Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep);
1817   for (auto& PK : Parts)
1818     Result /= PK.first;
1819 
1820   if (NeedTrailingSep)
1821     Result /= PS("");
1822 
1823   Result.make_preferred();
1824   return Result;
1825 }
1826 
1827 static int DetermineLexicalElementCount(PathParser PP) {
1828   int Count = 0;
1829   for (; PP; ++PP) {
1830     auto Elem = *PP;
1831     if (Elem == PS(".."))
1832       --Count;
1833     else if (Elem != PS(".") && Elem != PS(""))
1834       ++Count;
1835   }
1836   return Count;
1837 }
1838 
1839 path path::lexically_relative(const path& base) const {
1840   { // perform root-name/root-directory mismatch checks
1841     auto PP = PathParser::CreateBegin(__pn_);
1842     auto PPBase = PathParser::CreateBegin(base.__pn_);
1843     auto CheckIterMismatchAtBase = [&]() {
1844       return PP.State != PPBase.State &&
1845              (PP.inRootPath() || PPBase.inRootPath());
1846     };
1847     if (PP.inRootName() && PPBase.inRootName()) {
1848       if (*PP != *PPBase)
1849         return {};
1850     } else if (CheckIterMismatchAtBase())
1851       return {};
1852 
1853     if (PP.inRootPath())
1854       ++PP;
1855     if (PPBase.inRootPath())
1856       ++PPBase;
1857     if (CheckIterMismatchAtBase())
1858       return {};
1859   }
1860 
1861   // Find the first mismatching element
1862   auto PP = PathParser::CreateBegin(__pn_);
1863   auto PPBase = PathParser::CreateBegin(base.__pn_);
1864   while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) {
1865     ++PP;
1866     ++PPBase;
1867   }
1868 
1869   // If there is no mismatch, return ".".
1870   if (!PP && !PPBase)
1871     return ".";
1872 
1873   // Otherwise, determine the number of elements, 'n', which are not dot or
1874   // dot-dot minus the number of dot-dot elements.
1875   int ElemCount = DetermineLexicalElementCount(PPBase);
1876   if (ElemCount < 0)
1877     return {};
1878 
1879   // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise
1880   if (ElemCount == 0 && (PP.atEnd() || *PP == PS("")))
1881     return PS(".");
1882 
1883   // return a path constructed with 'n' dot-dot elements, followed by the the
1884   // elements of '*this' after the mismatch.
1885   path Result;
1886   // FIXME: Reserve enough room in Result that it won't have to re-allocate.
1887   while (ElemCount--)
1888     Result /= PS("..");
1889   for (; PP; ++PP)
1890     Result /= *PP;
1891   return Result;
1892 }
1893 
1894 ////////////////////////////////////////////////////////////////////////////
1895 // path.comparisons
1896 static int CompareRootName(PathParser *LHS, PathParser *RHS) {
1897   if (!LHS->inRootName() && !RHS->inRootName())
1898     return 0;
1899 
1900   auto GetRootName = [](PathParser *Parser) -> string_view_t {
1901     return Parser->inRootName() ? **Parser : PS("");
1902   };
1903   int res = GetRootName(LHS).compare(GetRootName(RHS));
1904   ConsumeRootName(LHS);
1905   ConsumeRootName(RHS);
1906   return res;
1907 }
1908 
1909 static int CompareRootDir(PathParser *LHS, PathParser *RHS) {
1910   if (!LHS->inRootDir() && RHS->inRootDir())
1911     return -1;
1912   else if (LHS->inRootDir() && !RHS->inRootDir())
1913     return 1;
1914   else {
1915     ConsumeRootDir(LHS);
1916     ConsumeRootDir(RHS);
1917     return 0;
1918   }
1919 }
1920 
1921 static int CompareRelative(PathParser *LHSPtr, PathParser *RHSPtr) {
1922   auto &LHS = *LHSPtr;
1923   auto &RHS = *RHSPtr;
1924 
1925   int res;
1926   while (LHS && RHS) {
1927     if ((res = (*LHS).compare(*RHS)) != 0)
1928       return res;
1929     ++LHS;
1930     ++RHS;
1931   }
1932   return 0;
1933 }
1934 
1935 static int CompareEndState(PathParser *LHS, PathParser *RHS) {
1936   if (LHS->atEnd() && !RHS->atEnd())
1937     return -1;
1938   else if (!LHS->atEnd() && RHS->atEnd())
1939     return 1;
1940   return 0;
1941 }
1942 
1943 int path::__compare(string_view_t __s) const {
1944   auto LHS = PathParser::CreateBegin(__pn_);
1945   auto RHS = PathParser::CreateBegin(__s);
1946   int res;
1947 
1948   if ((res = CompareRootName(&LHS, &RHS)) != 0)
1949     return res;
1950 
1951   if ((res = CompareRootDir(&LHS, &RHS)) != 0)
1952     return res;
1953 
1954   if ((res = CompareRelative(&LHS, &RHS)) != 0)
1955     return res;
1956 
1957   return CompareEndState(&LHS, &RHS);
1958 }
1959 
1960 ////////////////////////////////////////////////////////////////////////////
1961 // path.nonmembers
1962 size_t hash_value(const path& __p) noexcept {
1963   auto PP = PathParser::CreateBegin(__p.native());
1964   size_t hash_value = 0;
1965   hash<string_view_t> hasher;
1966   while (PP) {
1967     hash_value = __hash_combine(hash_value, hasher(*PP));
1968     ++PP;
1969   }
1970   return hash_value;
1971 }
1972 
1973 ////////////////////////////////////////////////////////////////////////////
1974 // path.itr
1975 path::iterator path::begin() const {
1976   auto PP = PathParser::CreateBegin(__pn_);
1977   iterator it;
1978   it.__path_ptr_ = this;
1979   it.__state_ = static_cast<path::iterator::_ParserState>(PP.State);
1980   it.__entry_ = PP.RawEntry;
1981   it.__stashed_elem_.__assign_view(*PP);
1982   return it;
1983 }
1984 
1985 path::iterator path::end() const {
1986   iterator it{};
1987   it.__state_ = path::iterator::_AtEnd;
1988   it.__path_ptr_ = this;
1989   return it;
1990 }
1991 
1992 path::iterator& path::iterator::__increment() {
1993   PathParser PP(__path_ptr_->native(), __entry_, __state_);
1994   ++PP;
1995   __state_ = static_cast<_ParserState>(PP.State);
1996   __entry_ = PP.RawEntry;
1997   __stashed_elem_.__assign_view(*PP);
1998   return *this;
1999 }
2000 
2001 path::iterator& path::iterator::__decrement() {
2002   PathParser PP(__path_ptr_->native(), __entry_, __state_);
2003   --PP;
2004   __state_ = static_cast<_ParserState>(PP.State);
2005   __entry_ = PP.RawEntry;
2006   __stashed_elem_.__assign_view(*PP);
2007   return *this;
2008 }
2009 
2010 #if defined(_LIBCPP_WIN32API)
2011 ////////////////////////////////////////////////////////////////////////////
2012 // Windows path conversions
2013 size_t __wide_to_char(const wstring &str, char *out, size_t outlen) {
2014   if (str.empty())
2015     return 0;
2016   ErrorHandler<size_t> err("__wide_to_char", nullptr);
2017   UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
2018   BOOL used_default = FALSE;
2019   int ret = WideCharToMultiByte(codepage, 0, str.data(), str.size(), out,
2020                                 outlen, nullptr, &used_default);
2021   if (ret <= 0 || used_default)
2022     return err.report(errc::illegal_byte_sequence);
2023   return ret;
2024 }
2025 
2026 size_t __char_to_wide(const string &str, wchar_t *out, size_t outlen) {
2027   if (str.empty())
2028     return 0;
2029   ErrorHandler<size_t> err("__char_to_wide", nullptr);
2030   UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
2031   int ret = MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, str.data(),
2032                                 str.size(), out, outlen);
2033   if (ret <= 0)
2034     return err.report(errc::illegal_byte_sequence);
2035   return ret;
2036 }
2037 #endif
2038 
2039 
2040 ///////////////////////////////////////////////////////////////////////////////
2041 //                           directory entry definitions
2042 ///////////////////////////////////////////////////////////////////////////////
2043 
2044 error_code directory_entry::__do_refresh() noexcept {
2045   __data_.__reset();
2046   error_code failure_ec;
2047 
2048   StatT full_st;
2049   file_status st = detail::posix_lstat(__p_, full_st, &failure_ec);
2050   if (!status_known(st)) {
2051     __data_.__reset();
2052     return failure_ec;
2053   }
2054 
2055   if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
2056     __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
2057     __data_.__type_ = st.type();
2058     __data_.__non_sym_perms_ = st.permissions();
2059   } else { // we have a symlink
2060     __data_.__sym_perms_ = st.permissions();
2061     // Get the information about the linked entity.
2062     // Ignore errors from stat, since we don't want errors regarding symlink
2063     // resolution to be reported to the user.
2064     error_code ignored_ec;
2065     st = detail::posix_stat(__p_, full_st, &ignored_ec);
2066 
2067     __data_.__type_ = st.type();
2068     __data_.__non_sym_perms_ = st.permissions();
2069 
2070     // If we failed to resolve the link, then only partially populate the
2071     // cache.
2072     if (!status_known(st)) {
2073       __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
2074       return error_code{};
2075     }
2076     // Otherwise, we resolved the link, potentially as not existing.
2077     // That's OK.
2078     __data_.__cache_type_ = directory_entry::_RefreshSymlink;
2079   }
2080 
2081   if (_VSTD_FS::is_regular_file(st))
2082     __data_.__size_ = static_cast<uintmax_t>(full_st.st_size);
2083 
2084   if (_VSTD_FS::exists(st)) {
2085     __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink);
2086 
2087     // Attempt to extract the mtime, and fail if it's not representable using
2088     // file_time_type. For now we ignore the error, as we'll report it when
2089     // the value is actually used.
2090     error_code ignored_ec;
2091     __data_.__write_time_ =
2092         __extract_last_write_time(__p_, full_st, &ignored_ec);
2093   }
2094 
2095   return failure_ec;
2096 }
2097 
2098 _LIBCPP_END_NAMESPACE_FILESYSTEM
2099