xref: /freebsd/contrib/llvm-project/libcxx/src/filesystem/operations.cpp (revision 924226fba12cc9a228c73b956e1b7fa24c60b055)
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     DIR* stream = ::fdopendir(fd);
1418     if (stream == nullptr) {
1419       ::close(fd);
1420       ec = detail::capture_errno();
1421       return 0;
1422     }
1423     // Note: `::closedir` will also close the associated file descriptor, so
1424     // there should be no call to `close(fd)`.
1425     scope_exit close_stream([=] { ::closedir(stream); });
1426 
1427     uintmax_t count = 0;
1428     while (true) {
1429       auto [str, type] = detail::posix_readdir(stream, ec);
1430       static_assert(std::is_same_v<decltype(str), std::string_view>);
1431       if (str == "." || str == "..") {
1432         continue;
1433       } else if (ec || str.empty()) {
1434         break; // we're done iterating through the directory
1435       } else {
1436         count += remove_all_impl(fd, str, ec);
1437       }
1438     }
1439 
1440     // Then, remove the now-empty directory itself.
1441     if (::unlinkat(parent_directory, p.c_str(), AT_REMOVEDIR) == -1) {
1442       ec = detail::capture_errno();
1443       return count;
1444     }
1445 
1446     return count + 1; // the contents of the directory + the directory itself
1447   }
1448 
1449   ec = detail::capture_errno();
1450 
1451   // If we failed to open `p` because it didn't exist, it's not an
1452   // error -- it might have moved or have been deleted already.
1453   if (ec == errc::no_such_file_or_directory) {
1454     ec.clear();
1455     return 0;
1456   }
1457 
1458   // If opening `p` failed because it wasn't a directory, remove it as
1459   // a normal file instead. Note that `openat()` can return either ENOTDIR
1460   // or ELOOP depending on the exact reason of the failure.
1461   if (ec == errc::not_a_directory || ec == errc::too_many_symbolic_link_levels) {
1462     ec.clear();
1463     if (::unlinkat(parent_directory, p.c_str(), /* flags = */0) == -1) {
1464       ec = detail::capture_errno();
1465       return 0;
1466     }
1467     return 1;
1468   }
1469 
1470   // Otherwise, it's a real error -- we don't remove anything.
1471   return 0;
1472 }
1473 
1474 } // end namespace
1475 
1476 uintmax_t __remove_all(const path& p, error_code* ec) {
1477   ErrorHandler<uintmax_t> err("remove_all", ec, &p);
1478   error_code mec;
1479   uintmax_t count = remove_all_impl(AT_FDCWD, p, mec);
1480   if (mec)
1481     return err.report(mec);
1482   return count;
1483 }
1484 
1485 #endif // REMOVE_ALL_USE_DIRECTORY_ITERATOR
1486 
1487 void __rename(const path& from, const path& to, error_code* ec) {
1488   ErrorHandler<void> err("rename", ec, &from, &to);
1489   if (detail::rename(from.c_str(), to.c_str()) == -1)
1490     err.report(capture_errno());
1491 }
1492 
1493 void __resize_file(const path& p, uintmax_t size, error_code* ec) {
1494   ErrorHandler<void> err("resize_file", ec, &p);
1495   if (detail::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1)
1496     return err.report(capture_errno());
1497 }
1498 
1499 space_info __space(const path& p, error_code* ec) {
1500   ErrorHandler<void> err("space", ec, &p);
1501   space_info si;
1502   detail::StatVFS m_svfs = {};
1503   if (detail::statvfs(p.c_str(), &m_svfs) == -1) {
1504     err.report(capture_errno());
1505     si.capacity = si.free = si.available = static_cast<uintmax_t>(-1);
1506     return si;
1507   }
1508   // Multiply with overflow checking.
1509   auto do_mult = [&](uintmax_t& out, uintmax_t other) {
1510     out = other * m_svfs.f_frsize;
1511     if (other == 0 || out / other != m_svfs.f_frsize)
1512       out = static_cast<uintmax_t>(-1);
1513   };
1514   do_mult(si.capacity, m_svfs.f_blocks);
1515   do_mult(si.free, m_svfs.f_bfree);
1516   do_mult(si.available, m_svfs.f_bavail);
1517   return si;
1518 }
1519 
1520 file_status __status(const path& p, error_code* ec) {
1521   return detail::posix_stat(p, ec);
1522 }
1523 
1524 file_status __symlink_status(const path& p, error_code* ec) {
1525   return detail::posix_lstat(p, ec);
1526 }
1527 
1528 path __temp_directory_path(error_code* ec) {
1529   ErrorHandler<path> err("temp_directory_path", ec);
1530 
1531 #if defined(_LIBCPP_WIN32API)
1532   wchar_t buf[MAX_PATH];
1533   DWORD retval = GetTempPathW(MAX_PATH, buf);
1534   if (!retval)
1535     return err.report(detail::make_windows_error(GetLastError()));
1536   if (retval > MAX_PATH)
1537     return err.report(errc::filename_too_long);
1538   // GetTempPathW returns a path with a trailing slash, which we
1539   // shouldn't include for consistency.
1540   if (buf[retval-1] == L'\\')
1541     buf[retval-1] = L'\0';
1542   path p(buf);
1543 #else
1544   const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
1545   const char* ret = nullptr;
1546 
1547   for (auto& ep : env_paths)
1548     if ((ret = getenv(ep)))
1549       break;
1550   if (ret == nullptr)
1551     ret = "/tmp";
1552 
1553   path p(ret);
1554 #endif
1555   error_code m_ec;
1556   file_status st = detail::posix_stat(p, &m_ec);
1557   if (!status_known(st))
1558     return err.report(m_ec, "cannot access path " PATH_CSTR_FMT, p.c_str());
1559 
1560   if (!exists(st) || !is_directory(st))
1561     return err.report(errc::not_a_directory,
1562                       "path " PATH_CSTR_FMT " is not a directory", p.c_str());
1563 
1564   return p;
1565 }
1566 
1567 path __weakly_canonical(const path& p, error_code* ec) {
1568   ErrorHandler<path> err("weakly_canonical", ec, &p);
1569 
1570   if (p.empty())
1571     return __canonical("", ec);
1572 
1573   path result;
1574   path tmp;
1575   tmp.__reserve(p.native().size());
1576   auto PP = PathParser::CreateEnd(p.native());
1577   --PP;
1578   vector<string_view_t> DNEParts;
1579 
1580   while (PP.State != PathParser::PS_BeforeBegin) {
1581     tmp.assign(createView(p.native().data(), &PP.RawEntry.back()));
1582     error_code m_ec;
1583     file_status st = __status(tmp, &m_ec);
1584     if (!status_known(st)) {
1585       return err.report(m_ec);
1586     } else if (exists(st)) {
1587       result = __canonical(tmp, ec);
1588       break;
1589     }
1590     DNEParts.push_back(*PP);
1591     --PP;
1592   }
1593   if (PP.State == PathParser::PS_BeforeBegin)
1594     result = __canonical("", ec);
1595   if (ec)
1596     ec->clear();
1597   if (DNEParts.empty())
1598     return result;
1599   for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It)
1600     result /= *It;
1601   return result.lexically_normal();
1602 }
1603 
1604 ///////////////////////////////////////////////////////////////////////////////
1605 //                            path definitions
1606 ///////////////////////////////////////////////////////////////////////////////
1607 
1608 constexpr path::value_type path::preferred_separator;
1609 
1610 path& path::replace_extension(path const& replacement) {
1611   path p = extension();
1612   if (not p.empty()) {
1613     __pn_.erase(__pn_.size() - p.native().size());
1614   }
1615   if (!replacement.empty()) {
1616     if (replacement.native()[0] != '.') {
1617       __pn_ += PS(".");
1618     }
1619     __pn_.append(replacement.__pn_);
1620   }
1621   return *this;
1622 }
1623 
1624 ///////////////////////////////////////////////////////////////////////////////
1625 // path.decompose
1626 
1627 string_view_t path::__root_name() const {
1628   auto PP = PathParser::CreateBegin(__pn_);
1629   if (PP.State == PathParser::PS_InRootName)
1630     return *PP;
1631   return {};
1632 }
1633 
1634 string_view_t path::__root_directory() const {
1635   auto PP = PathParser::CreateBegin(__pn_);
1636   if (PP.State == PathParser::PS_InRootName)
1637     ++PP;
1638   if (PP.State == PathParser::PS_InRootDir)
1639     return *PP;
1640   return {};
1641 }
1642 
1643 string_view_t path::__root_path_raw() const {
1644   auto PP = PathParser::CreateBegin(__pn_);
1645   if (PP.State == PathParser::PS_InRootName) {
1646     auto NextCh = PP.peek();
1647     if (NextCh && isSeparator(*NextCh)) {
1648       ++PP;
1649       return createView(__pn_.data(), &PP.RawEntry.back());
1650     }
1651     return PP.RawEntry;
1652   }
1653   if (PP.State == PathParser::PS_InRootDir)
1654     return *PP;
1655   return {};
1656 }
1657 
1658 static bool ConsumeRootName(PathParser *PP) {
1659   static_assert(PathParser::PS_BeforeBegin == 1 &&
1660       PathParser::PS_InRootName == 2,
1661       "Values for enums are incorrect");
1662   while (PP->State <= PathParser::PS_InRootName)
1663     ++(*PP);
1664   return PP->State == PathParser::PS_AtEnd;
1665 }
1666 
1667 static bool ConsumeRootDir(PathParser* PP) {
1668   static_assert(PathParser::PS_BeforeBegin == 1 &&
1669                 PathParser::PS_InRootName == 2 &&
1670                 PathParser::PS_InRootDir == 3, "Values for enums are incorrect");
1671   while (PP->State <= PathParser::PS_InRootDir)
1672     ++(*PP);
1673   return PP->State == PathParser::PS_AtEnd;
1674 }
1675 
1676 string_view_t path::__relative_path() const {
1677   auto PP = PathParser::CreateBegin(__pn_);
1678   if (ConsumeRootDir(&PP))
1679     return {};
1680   return createView(PP.RawEntry.data(), &__pn_.back());
1681 }
1682 
1683 string_view_t path::__parent_path() const {
1684   if (empty())
1685     return {};
1686   // Determine if we have a root path but not a relative path. In that case
1687   // return *this.
1688   {
1689     auto PP = PathParser::CreateBegin(__pn_);
1690     if (ConsumeRootDir(&PP))
1691       return __pn_;
1692   }
1693   // Otherwise remove a single element from the end of the path, and return
1694   // a string representing that path
1695   {
1696     auto PP = PathParser::CreateEnd(__pn_);
1697     --PP;
1698     if (PP.RawEntry.data() == __pn_.data())
1699       return {};
1700     --PP;
1701     return createView(__pn_.data(), &PP.RawEntry.back());
1702   }
1703 }
1704 
1705 string_view_t path::__filename() const {
1706   if (empty())
1707     return {};
1708   {
1709     PathParser PP = PathParser::CreateBegin(__pn_);
1710     if (ConsumeRootDir(&PP))
1711       return {};
1712   }
1713   return *(--PathParser::CreateEnd(__pn_));
1714 }
1715 
1716 string_view_t path::__stem() const {
1717   return parser::separate_filename(__filename()).first;
1718 }
1719 
1720 string_view_t path::__extension() const {
1721   return parser::separate_filename(__filename()).second;
1722 }
1723 
1724 ////////////////////////////////////////////////////////////////////////////
1725 // path.gen
1726 
1727 enum PathPartKind : unsigned char {
1728   PK_None,
1729   PK_RootSep,
1730   PK_Filename,
1731   PK_Dot,
1732   PK_DotDot,
1733   PK_TrailingSep
1734 };
1735 
1736 static PathPartKind ClassifyPathPart(string_view_t Part) {
1737   if (Part.empty())
1738     return PK_TrailingSep;
1739   if (Part == PS("."))
1740     return PK_Dot;
1741   if (Part == PS(".."))
1742     return PK_DotDot;
1743   if (Part == PS("/"))
1744     return PK_RootSep;
1745 #if defined(_LIBCPP_WIN32API)
1746   if (Part == PS("\\"))
1747     return PK_RootSep;
1748 #endif
1749   return PK_Filename;
1750 }
1751 
1752 path path::lexically_normal() const {
1753   if (__pn_.empty())
1754     return *this;
1755 
1756   using PartKindPair = pair<string_view_t, PathPartKind>;
1757   vector<PartKindPair> Parts;
1758   // Guess as to how many elements the path has to avoid reallocating.
1759   Parts.reserve(32);
1760 
1761   // Track the total size of the parts as we collect them. This allows the
1762   // resulting path to reserve the correct amount of memory.
1763   size_t NewPathSize = 0;
1764   auto AddPart = [&](PathPartKind K, string_view_t P) {
1765     NewPathSize += P.size();
1766     Parts.emplace_back(P, K);
1767   };
1768   auto LastPartKind = [&]() {
1769     if (Parts.empty())
1770       return PK_None;
1771     return Parts.back().second;
1772   };
1773 
1774   bool MaybeNeedTrailingSep = false;
1775   // Build a stack containing the remaining elements of the path, popping off
1776   // elements which occur before a '..' entry.
1777   for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) {
1778     auto Part = *PP;
1779     PathPartKind Kind = ClassifyPathPart(Part);
1780     switch (Kind) {
1781     case PK_Filename:
1782     case PK_RootSep: {
1783       // Add all non-dot and non-dot-dot elements to the stack of elements.
1784       AddPart(Kind, Part);
1785       MaybeNeedTrailingSep = false;
1786       break;
1787     }
1788     case PK_DotDot: {
1789       // Only push a ".." element if there are no elements preceding the "..",
1790       // or if the preceding element is itself "..".
1791       auto LastKind = LastPartKind();
1792       if (LastKind == PK_Filename) {
1793         NewPathSize -= Parts.back().first.size();
1794         Parts.pop_back();
1795       } else if (LastKind != PK_RootSep)
1796         AddPart(PK_DotDot, PS(".."));
1797       MaybeNeedTrailingSep = LastKind == PK_Filename;
1798       break;
1799     }
1800     case PK_Dot:
1801     case PK_TrailingSep: {
1802       MaybeNeedTrailingSep = true;
1803       break;
1804     }
1805     case PK_None:
1806       _LIBCPP_UNREACHABLE();
1807     }
1808   }
1809   // [fs.path.generic]p6.8: If the path is empty, add a dot.
1810   if (Parts.empty())
1811     return PS(".");
1812 
1813   // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any
1814   // trailing directory-separator.
1815   bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename;
1816 
1817   path Result;
1818   Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep);
1819   for (auto& PK : Parts)
1820     Result /= PK.first;
1821 
1822   if (NeedTrailingSep)
1823     Result /= PS("");
1824 
1825   Result.make_preferred();
1826   return Result;
1827 }
1828 
1829 static int DetermineLexicalElementCount(PathParser PP) {
1830   int Count = 0;
1831   for (; PP; ++PP) {
1832     auto Elem = *PP;
1833     if (Elem == PS(".."))
1834       --Count;
1835     else if (Elem != PS(".") && Elem != PS(""))
1836       ++Count;
1837   }
1838   return Count;
1839 }
1840 
1841 path path::lexically_relative(const path& base) const {
1842   { // perform root-name/root-directory mismatch checks
1843     auto PP = PathParser::CreateBegin(__pn_);
1844     auto PPBase = PathParser::CreateBegin(base.__pn_);
1845     auto CheckIterMismatchAtBase = [&]() {
1846       return PP.State != PPBase.State &&
1847              (PP.inRootPath() || PPBase.inRootPath());
1848     };
1849     if (PP.inRootName() && PPBase.inRootName()) {
1850       if (*PP != *PPBase)
1851         return {};
1852     } else if (CheckIterMismatchAtBase())
1853       return {};
1854 
1855     if (PP.inRootPath())
1856       ++PP;
1857     if (PPBase.inRootPath())
1858       ++PPBase;
1859     if (CheckIterMismatchAtBase())
1860       return {};
1861   }
1862 
1863   // Find the first mismatching element
1864   auto PP = PathParser::CreateBegin(__pn_);
1865   auto PPBase = PathParser::CreateBegin(base.__pn_);
1866   while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) {
1867     ++PP;
1868     ++PPBase;
1869   }
1870 
1871   // If there is no mismatch, return ".".
1872   if (!PP && !PPBase)
1873     return ".";
1874 
1875   // Otherwise, determine the number of elements, 'n', which are not dot or
1876   // dot-dot minus the number of dot-dot elements.
1877   int ElemCount = DetermineLexicalElementCount(PPBase);
1878   if (ElemCount < 0)
1879     return {};
1880 
1881   // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise
1882   if (ElemCount == 0 && (PP.atEnd() || *PP == PS("")))
1883     return PS(".");
1884 
1885   // return a path constructed with 'n' dot-dot elements, followed by the the
1886   // elements of '*this' after the mismatch.
1887   path Result;
1888   // FIXME: Reserve enough room in Result that it won't have to re-allocate.
1889   while (ElemCount--)
1890     Result /= PS("..");
1891   for (; PP; ++PP)
1892     Result /= *PP;
1893   return Result;
1894 }
1895 
1896 ////////////////////////////////////////////////////////////////////////////
1897 // path.comparisons
1898 static int CompareRootName(PathParser *LHS, PathParser *RHS) {
1899   if (!LHS->inRootName() && !RHS->inRootName())
1900     return 0;
1901 
1902   auto GetRootName = [](PathParser *Parser) -> string_view_t {
1903     return Parser->inRootName() ? **Parser : PS("");
1904   };
1905   int res = GetRootName(LHS).compare(GetRootName(RHS));
1906   ConsumeRootName(LHS);
1907   ConsumeRootName(RHS);
1908   return res;
1909 }
1910 
1911 static int CompareRootDir(PathParser *LHS, PathParser *RHS) {
1912   if (!LHS->inRootDir() && RHS->inRootDir())
1913     return -1;
1914   else if (LHS->inRootDir() && !RHS->inRootDir())
1915     return 1;
1916   else {
1917     ConsumeRootDir(LHS);
1918     ConsumeRootDir(RHS);
1919     return 0;
1920   }
1921 }
1922 
1923 static int CompareRelative(PathParser *LHSPtr, PathParser *RHSPtr) {
1924   auto &LHS = *LHSPtr;
1925   auto &RHS = *RHSPtr;
1926 
1927   int res;
1928   while (LHS && RHS) {
1929     if ((res = (*LHS).compare(*RHS)) != 0)
1930       return res;
1931     ++LHS;
1932     ++RHS;
1933   }
1934   return 0;
1935 }
1936 
1937 static int CompareEndState(PathParser *LHS, PathParser *RHS) {
1938   if (LHS->atEnd() && !RHS->atEnd())
1939     return -1;
1940   else if (!LHS->atEnd() && RHS->atEnd())
1941     return 1;
1942   return 0;
1943 }
1944 
1945 int path::__compare(string_view_t __s) const {
1946   auto LHS = PathParser::CreateBegin(__pn_);
1947   auto RHS = PathParser::CreateBegin(__s);
1948   int res;
1949 
1950   if ((res = CompareRootName(&LHS, &RHS)) != 0)
1951     return res;
1952 
1953   if ((res = CompareRootDir(&LHS, &RHS)) != 0)
1954     return res;
1955 
1956   if ((res = CompareRelative(&LHS, &RHS)) != 0)
1957     return res;
1958 
1959   return CompareEndState(&LHS, &RHS);
1960 }
1961 
1962 ////////////////////////////////////////////////////////////////////////////
1963 // path.nonmembers
1964 size_t hash_value(const path& __p) noexcept {
1965   auto PP = PathParser::CreateBegin(__p.native());
1966   size_t hash_value = 0;
1967   hash<string_view_t> hasher;
1968   while (PP) {
1969     hash_value = __hash_combine(hash_value, hasher(*PP));
1970     ++PP;
1971   }
1972   return hash_value;
1973 }
1974 
1975 ////////////////////////////////////////////////////////////////////////////
1976 // path.itr
1977 path::iterator path::begin() const {
1978   auto PP = PathParser::CreateBegin(__pn_);
1979   iterator it;
1980   it.__path_ptr_ = this;
1981   it.__state_ = static_cast<path::iterator::_ParserState>(PP.State);
1982   it.__entry_ = PP.RawEntry;
1983   it.__stashed_elem_.__assign_view(*PP);
1984   return it;
1985 }
1986 
1987 path::iterator path::end() const {
1988   iterator it{};
1989   it.__state_ = path::iterator::_AtEnd;
1990   it.__path_ptr_ = this;
1991   return it;
1992 }
1993 
1994 path::iterator& path::iterator::__increment() {
1995   PathParser PP(__path_ptr_->native(), __entry_, __state_);
1996   ++PP;
1997   __state_ = static_cast<_ParserState>(PP.State);
1998   __entry_ = PP.RawEntry;
1999   __stashed_elem_.__assign_view(*PP);
2000   return *this;
2001 }
2002 
2003 path::iterator& path::iterator::__decrement() {
2004   PathParser PP(__path_ptr_->native(), __entry_, __state_);
2005   --PP;
2006   __state_ = static_cast<_ParserState>(PP.State);
2007   __entry_ = PP.RawEntry;
2008   __stashed_elem_.__assign_view(*PP);
2009   return *this;
2010 }
2011 
2012 #if defined(_LIBCPP_WIN32API)
2013 ////////////////////////////////////////////////////////////////////////////
2014 // Windows path conversions
2015 size_t __wide_to_char(const wstring &str, char *out, size_t outlen) {
2016   if (str.empty())
2017     return 0;
2018   ErrorHandler<size_t> err("__wide_to_char", nullptr);
2019   UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
2020   BOOL used_default = FALSE;
2021   int ret = WideCharToMultiByte(codepage, 0, str.data(), str.size(), out,
2022                                 outlen, nullptr, &used_default);
2023   if (ret <= 0 || used_default)
2024     return err.report(errc::illegal_byte_sequence);
2025   return ret;
2026 }
2027 
2028 size_t __char_to_wide(const string &str, wchar_t *out, size_t outlen) {
2029   if (str.empty())
2030     return 0;
2031   ErrorHandler<size_t> err("__char_to_wide", nullptr);
2032   UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
2033   int ret = MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, str.data(),
2034                                 str.size(), out, outlen);
2035   if (ret <= 0)
2036     return err.report(errc::illegal_byte_sequence);
2037   return ret;
2038 }
2039 #endif
2040 
2041 
2042 ///////////////////////////////////////////////////////////////////////////////
2043 //                           directory entry definitions
2044 ///////////////////////////////////////////////////////////////////////////////
2045 
2046 error_code directory_entry::__do_refresh() noexcept {
2047   __data_.__reset();
2048   error_code failure_ec;
2049 
2050   StatT full_st;
2051   file_status st = detail::posix_lstat(__p_, full_st, &failure_ec);
2052   if (!status_known(st)) {
2053     __data_.__reset();
2054     return failure_ec;
2055   }
2056 
2057   if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
2058     __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
2059     __data_.__type_ = st.type();
2060     __data_.__non_sym_perms_ = st.permissions();
2061   } else { // we have a symlink
2062     __data_.__sym_perms_ = st.permissions();
2063     // Get the information about the linked entity.
2064     // Ignore errors from stat, since we don't want errors regarding symlink
2065     // resolution to be reported to the user.
2066     error_code ignored_ec;
2067     st = detail::posix_stat(__p_, full_st, &ignored_ec);
2068 
2069     __data_.__type_ = st.type();
2070     __data_.__non_sym_perms_ = st.permissions();
2071 
2072     // If we failed to resolve the link, then only partially populate the
2073     // cache.
2074     if (!status_known(st)) {
2075       __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
2076       return error_code{};
2077     }
2078     // Otherwise, we resolved the link, potentially as not existing.
2079     // That's OK.
2080     __data_.__cache_type_ = directory_entry::_RefreshSymlink;
2081   }
2082 
2083   if (_VSTD_FS::is_regular_file(st))
2084     __data_.__size_ = static_cast<uintmax_t>(full_st.st_size);
2085 
2086   if (_VSTD_FS::exists(st)) {
2087     __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink);
2088 
2089     // Attempt to extract the mtime, and fail if it's not representable using
2090     // file_time_type. For now we ignore the error, as we'll report it when
2091     // the value is actually used.
2092     error_code ignored_ec;
2093     __data_.__write_time_ =
2094         __extract_last_write_time(__p_, full_st, &ignored_ec);
2095   }
2096 
2097   return failure_ec;
2098 }
2099 
2100 _LIBCPP_END_NAMESPACE_FILESYSTEM
2101