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