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