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