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