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