16e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier//===--------------------- filesystem/ops.cpp -----------------------------===//
26e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier//
36e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier//                     The LLVM Compiler Infrastructure
46e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier//
56e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier// This file is dual licensed under the MIT and the University of Illinois Open
66e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier// Source Licenses. See LICENSE.TXT for details.
76e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier//
86e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier//===----------------------------------------------------------------------===//
96e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
106e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include "experimental/filesystem"
116e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include "iterator"
126e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include "fstream"
136e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include "type_traits"
146e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include "random"  /* for unique_path */
156e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include "cstdlib"
166e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include "climits"
176e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
18b2e9337b06425b4af554651d5f2fa65615eb009fEric Fiselier#include "filesystem_time_helper.h"
19b2e9337b06425b4af554651d5f2fa65615eb009fEric Fiselier
206e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include <unistd.h>
216e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include <sys/stat.h>
226e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include <sys/statvfs.h>
236e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include <fcntl.h>  /* values for fchmodat */
2468b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber
2568b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#if (__APPLE__)
2668b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
2768b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101300
2868b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#define _LIBCXX_USE_UTIMENSAT
2968b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#endif
3068b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__)
3168b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 110000
3268b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#define _LIBCXX_USE_UTIMENSAT
3368b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#endif
3468b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__)
3568b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 110000
3668b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#define _LIBCXX_USE_UTIMENSAT
3768b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#endif
3868b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__)
3968b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 40000
4068b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#define _LIBCXX_USE_UTIMENSAT
4168b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#endif
4268b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__
4368b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#else
4468b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber// We can use the presence of UTIME_OMIT to detect platforms that provide
4568b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber// utimensat.
4668b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#if defined(UTIME_OMIT)
4768b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#define _LIBCXX_USE_UTIMENSAT
4868b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#endif
4968b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#endif // __APPLE__
5068b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber
5168b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#if !defined(_LIBCXX_USE_UTIMENSAT)
526e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#include <sys/time.h> // for ::utimes as used in __last_write_time
536e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#endif
546e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
556e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM
566e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
576e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierfilesystem_error::~filesystem_error() {}
586e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
596e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
606e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier//                       POSIX HELPERS
616e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
626e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliernamespace detail { namespace  {
636e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
646e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierusing value_type = path::value_type;
656e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierusing string_type = path::string_type;
666e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
676e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierinline std::error_code capture_errno() {
68166d27ed3133af1deb0c1b73ab142847e1942644Saleem Abdulrasool  _LIBCPP_ASSERT(errno, "Expected errno to be non-zero");
69166d27ed3133af1deb0c1b73ab142847e1942644Saleem Abdulrasool  return std::error_code(errno, std::generic_category());
706e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
716e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
726e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid set_or_throw(std::error_code const& m_ec, std::error_code* ec,
736e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                  const char* msg, path const& p = {}, path const& p2 = {})
746e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
756e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) {
766e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        *ec = m_ec;
776e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    } else {
786e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        string msg_s("std::experimental::filesystem::");
796e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        msg_s += msg;
80e7acb0e5be91c8e6ded934184f4053757c5f5360Marshall Clow        __throw_filesystem_error(msg_s, p, p2, m_ec);
816e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
826e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
836e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
846e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid set_or_throw(std::error_code* ec, const char* msg,
856e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                  path const& p = {}, path const& p2 = {})
866e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
876e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return set_or_throw(capture_errno(), ec, msg, p, p2);
886e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
896e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
906e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierperms posix_get_perms(const struct ::stat & st) noexcept {
916e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return static_cast<perms>(st.st_mode) & perms::mask;
926e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
936e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
946e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier::mode_t posix_convert_perms(perms prms) {
956e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return static_cast< ::mode_t>(prms & perms::mask);
966e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
976e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
986e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierfile_status create_file_status(std::error_code& m_ec, path const& p,
996e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                               struct ::stat& path_stat,
1006e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                               std::error_code* ec)
1016e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
1026e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) *ec = m_ec;
1036e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) {
1046e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return file_status(file_type::not_found);
1056e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
1066e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (m_ec) {
1076e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(m_ec, ec, "posix_stat", p);
1086e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return file_status(file_type::none);
1096e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
1106e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    // else
1116e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1126e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    file_status fs_tmp;
1136e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto const mode = path_stat.st_mode;
1146e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if      (S_ISLNK(mode))  fs_tmp.type(file_type::symlink);
1156e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (S_ISREG(mode))  fs_tmp.type(file_type::regular);
1166e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (S_ISDIR(mode))  fs_tmp.type(file_type::directory);
1176e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (S_ISBLK(mode))  fs_tmp.type(file_type::block);
1186e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (S_ISCHR(mode))  fs_tmp.type(file_type::character);
1196e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (S_ISFIFO(mode)) fs_tmp.type(file_type::fifo);
1206e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (S_ISSOCK(mode)) fs_tmp.type(file_type::socket);
1216e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else                     fs_tmp.type(file_type::unknown);
1226e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1236e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    fs_tmp.permissions(detail::posix_get_perms(path_stat));
1246e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return fs_tmp;
1256e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
1266e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1276e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierfile_status posix_stat(path const & p, struct ::stat& path_stat,
1286e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                       std::error_code* ec)
1296e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
1306e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code m_ec;
1316e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::stat(p.c_str(), &path_stat) == -1)
1326e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        m_ec = detail::capture_errno();
1336e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return create_file_status(m_ec, p, path_stat, ec);
1346e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
1356e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1366e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierfile_status posix_stat(path const & p, std::error_code* ec) {
1376e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat path_stat;
1386e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return posix_stat(p, path_stat, ec);
1396e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
1406e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1416e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierfile_status posix_lstat(path const & p, struct ::stat & path_stat,
1426e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                        std::error_code* ec)
1436e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
1446e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code m_ec;
1456e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::lstat(p.c_str(), &path_stat) == -1)
1466e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        m_ec = detail::capture_errno();
1476e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return create_file_status(m_ec, p, path_stat, ec);
1486e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
1496e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1506e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierfile_status posix_lstat(path const & p, std::error_code* ec) {
1516e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat path_stat;
1526e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return posix_lstat(p, path_stat, ec);
1536e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
1546e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1556e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierbool stat_equivalent(struct ::stat& st1, struct ::stat& st2) {
1566e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
1576e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
1586e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1596e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier//                           DETAIL::MISC
1606e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1616e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1626e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierbool copy_file_impl(const path& from, const path& to, perms from_perms,
1636e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                    std::error_code *ec)
1646e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
1656e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::ifstream in(from.c_str(), std::ios::binary);
1666e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::ofstream out(to.c_str(),  std::ios::binary);
1676e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1686e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (in.good() && out.good()) {
1696e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        using InIt = std::istreambuf_iterator<char>;
1706e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        using OutIt = std::ostreambuf_iterator<char>;
1716e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        InIt bin(in);
1726e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        InIt ein;
1736e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        OutIt bout(out);
1746e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        std::copy(bin, ein, bout);
1756e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
1766e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (out.fail() || in.fail()) {
1776e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(make_error_code(errc::operation_not_permitted),
1786e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                     ec, "copy_file", from, to);
1796e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return false;
1806e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
1816e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    __permissions(to, from_perms, ec);
1826e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    // TODO what if permissions fails?
1836e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return true;
1846e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
1856e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1866e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}} // end namespace detail
1876e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1886e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierusing detail::set_or_throw;
1896e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
1906e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierpath __canonical(path const & orig_p, const path& base, std::error_code *ec)
1916e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
1926e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    path p = absolute(orig_p, base);
1936e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    char buff[PATH_MAX + 1];
1946e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    char *ret;
1956e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if ((ret = ::realpath(p.c_str(), buff)) == nullptr) {
1966e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "canonical", orig_p, base);
1976e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return {};
1986e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
1996e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
2006e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return {ret};
2016e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
2026e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2036e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid __copy(const path& from, const path& to, copy_options options,
2046e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            std::error_code *ec)
2056e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
2066e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    const bool sym_status = bool(options &
2076e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        (copy_options::create_symlinks | copy_options::skip_symlinks));
2086e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2096e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    const bool sym_status2 = bool(options &
2106e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        copy_options::copy_symlinks);
2116e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2124aee06b818ed7ee73a7be11997fc8b9afb442bbeMarshall Clow    std::error_code m_ec1;
2136e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat f_st = {};
2146e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    const file_status f = sym_status || sym_status2
2154aee06b818ed7ee73a7be11997fc8b9afb442bbeMarshall Clow                                     ? detail::posix_lstat(from, f_st, &m_ec1)
2164aee06b818ed7ee73a7be11997fc8b9afb442bbeMarshall Clow                                     : detail::posix_stat(from,  f_st, &m_ec1);
2174aee06b818ed7ee73a7be11997fc8b9afb442bbeMarshall Clow    if (m_ec1)
2184aee06b818ed7ee73a7be11997fc8b9afb442bbeMarshall Clow        return set_or_throw(m_ec1, ec, "copy", from, to);
2196e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2206e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat t_st = {};
2214aee06b818ed7ee73a7be11997fc8b9afb442bbeMarshall Clow    const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1)
2224aee06b818ed7ee73a7be11997fc8b9afb442bbeMarshall Clow                                     : detail::posix_stat(to, t_st, &m_ec1);
2236e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2246e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (not status_known(t))
2254aee06b818ed7ee73a7be11997fc8b9afb442bbeMarshall Clow        return set_or_throw(m_ec1, ec, "copy", from, to);
2266e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2276e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (!exists(f) || is_other(f) || is_other(t)
2286e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        || (is_directory(f) && is_regular_file(t))
2296e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        || detail::stat_equivalent(f_st, t_st))
2306e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    {
2316e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return set_or_throw(make_error_code(errc::function_not_supported),
2326e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                            ec, "copy", from, to);
2336e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
2346e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2356e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
2366e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2376e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (is_symlink(f)) {
2386e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (bool(copy_options::skip_symlinks & options)) {
2396e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            // do nothing
2406e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        } else if (not exists(t)) {
2416e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            __copy_symlink(from, to, ec);
2426e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        } else {
2436e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            set_or_throw(make_error_code(errc::file_exists),
2446e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                         ec, "copy", from, to);
2456e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        }
2466e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return;
2476e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
2486e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (is_regular_file(f)) {
2496e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (bool(copy_options::directories_only & options)) {
2506e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            // do nothing
2516e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        }
2526e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        else if (bool(copy_options::create_symlinks & options)) {
2536e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            __create_symlink(from, to, ec);
2546e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        }
2556e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        else if (bool(copy_options::create_hard_links & options)) {
2566e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            __create_hard_link(from, to, ec);
2576e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        }
2586e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        else if (is_directory(t)) {
2596e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            __copy_file(from, to / from.filename(), options, ec);
2606e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        } else {
2616e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            __copy_file(from, to, options, ec);
2626e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        }
2636e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return;
2646e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
265451f34db162fddec235736bc0ee0c670ad452e2aEric Fiselier    else if (is_directory(f) && bool(copy_options::create_symlinks & options)) {
266451f34db162fddec235736bc0ee0c670ad452e2aEric Fiselier        return set_or_throw(make_error_code(errc::is_a_directory), ec, "copy");
267451f34db162fddec235736bc0ee0c670ad452e2aEric Fiselier    }
268508f208ae9fe8afa4cccea0763ffc99662433886Eric Fiselier    else if (is_directory(f) && (bool(copy_options::recursive & options) ||
269508f208ae9fe8afa4cccea0763ffc99662433886Eric Fiselier             copy_options::none == options)) {
2706e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2716e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (!exists(t)) {
2726e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            // create directory to with attributes from 'from'.
2736e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            __create_directory(to, from, ec);
2746e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            if (ec && *ec) { return; }
2756e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        }
2766e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        directory_iterator it = ec ? directory_iterator(from, *ec)
2776e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                                   : directory_iterator(from);
2786e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (ec && *ec) { return; }
2794aee06b818ed7ee73a7be11997fc8b9afb442bbeMarshall Clow        std::error_code m_ec2;
2804aee06b818ed7ee73a7be11997fc8b9afb442bbeMarshall Clow        for (; it != directory_iterator(); it.increment(m_ec2)) {
2814aee06b818ed7ee73a7be11997fc8b9afb442bbeMarshall Clow            if (m_ec2) return set_or_throw(m_ec2, ec, "copy", from, to);
2826e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            __copy(it->path(), to / it->path().filename(),
2836e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                   options | copy_options::__in_recursive_copy, ec);
2846e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            if (ec && *ec) { return; }
2856e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        }
2866e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
2876e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
2886e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2896e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2906e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierbool __copy_file(const path& from, const path& to, copy_options options,
2916e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                 std::error_code *ec)
2926e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
293af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier    using StatT = struct ::stat;
294af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier    if (ec)
295af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier      ec->clear();
2966e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
2976e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code m_ec;
298af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier    StatT from_stat;
299af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier    auto from_st = detail::posix_stat(from, from_stat, &m_ec);
3006e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (not is_regular_file(from_st)) {
301af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier      if (not m_ec)
302af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier        m_ec = make_error_code(errc::not_supported);
303af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier      set_or_throw(m_ec, ec, "copy_file", from, to);
304af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier      return false;
3056e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
3066e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
307af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier    StatT to_stat;
308af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier    auto to_st = detail::posix_stat(to, to_stat, &m_ec);
3096e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (!status_known(to_st)) {
3106e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(m_ec, ec, "copy_file", from, to);
3116e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return false;
3126e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
3136e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
3146e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    const bool to_exists = exists(to_st);
3151e1bbc7437f4679ce8b6ed5984f2cc72a96f3349Eric Fiselier    if (to_exists && !is_regular_file(to_st)) {
3161e1bbc7437f4679ce8b6ed5984f2cc72a96f3349Eric Fiselier        set_or_throw(make_error_code(errc::not_supported), ec, "copy_file", from, to);
3171e1bbc7437f4679ce8b6ed5984f2cc72a96f3349Eric Fiselier        return false;
3181e1bbc7437f4679ce8b6ed5984f2cc72a96f3349Eric Fiselier    }
319af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier    if (to_exists && detail::stat_equivalent(from_stat, to_stat)) {
320af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier      set_or_throw(make_error_code(errc::file_exists), ec, "copy_file", from,
321af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier                   to);
322af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier      return false;
323af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier    }
3246e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (to_exists && bool(copy_options::skip_existing & options)) {
3256e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return false;
3266e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
3276e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (to_exists && bool(copy_options::update_existing & options)) {
3286e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        auto from_time = __last_write_time(from, ec);
3296e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (ec && *ec) { return false; }
3306e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        auto to_time = __last_write_time(to, ec);
3316e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (ec && *ec) { return false; }
3326e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (from_time <= to_time) {
3336e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            return false;
3346e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        }
3356e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return detail::copy_file_impl(from, to, from_st.permissions(), ec);
3366e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
3376e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (!to_exists || bool(copy_options::overwrite_existing & options)) {
3386e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return detail::copy_file_impl(from, to, from_st.permissions(), ec);
3396e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
3406e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else {
341af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier      set_or_throw(make_error_code(errc::file_exists), ec, "copy_file", from,
342af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier                   to);
343af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier      return false;
3446e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
3451e1bbc7437f4679ce8b6ed5984f2cc72a96f3349Eric Fiselier
3461e1bbc7437f4679ce8b6ed5984f2cc72a96f3349Eric Fiselier    _LIBCPP_UNREACHABLE();
3476e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
3486e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
3496e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid __copy_symlink(const path& existing_symlink, const path& new_symlink,
3506e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                    std::error_code *ec)
3516e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
3526e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    const path real_path(__read_symlink(existing_symlink, ec));
3536e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec && *ec) { return; }
3546e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    // NOTE: proposal says you should detect if you should call
3556e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    // create_symlink or create_directory_symlink. I don't think this
3566e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    // is needed with POSIX
3576e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    __create_symlink(real_path, new_symlink, ec);
3586e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
3596e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
3606e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
3616e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierbool __create_directories(const path& p, std::error_code *ec)
3626e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
3636e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code m_ec;
3646e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto const st = detail::posix_stat(p, &m_ec);
3656e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (!status_known(st)) {
3666e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(m_ec, ec, "create_directories", p);
3676e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return false;
3686e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
3696e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (is_directory(st)) {
3706e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (ec) ec->clear();
3716e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return false;
3726e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
3736e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (exists(st)) {
3746e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(make_error_code(errc::file_exists),
3756e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                     ec, "create_directories", p);
3766e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return false;
3776e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
3786e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
3796e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    const path parent = p.parent_path();
3806e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (!parent.empty()) {
3816e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        const file_status parent_st = status(parent, m_ec);
3826e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (not status_known(parent_st)) {
3836e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            set_or_throw(m_ec, ec, "create_directories", p);
3846e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            return false;
3856e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        }
3866e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (not exists(parent_st)) {
3876e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            __create_directories(parent, ec);
3886e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            if (ec && *ec) { return false; }
3896e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        }
3906e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
3916e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return __create_directory(p, ec);
3926e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
3936e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
3946e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierbool __create_directory(const path& p, std::error_code *ec)
3956e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
3966e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
3976e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0)
3986e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return true;
3996e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (errno != EEXIST || !is_directory(p))
4006e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "create_directory", p);
4016e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return false;
4026e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
4036e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
4046e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierbool __create_directory(path const & p, path const & attributes,
4056e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                        std::error_code *ec)
4066e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
4076e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat attr_stat;
4086e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code mec;
4096e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto st = detail::posix_stat(attributes, attr_stat, &mec);
4106e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (!status_known(st)) {
4116e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(mec, ec, "create_directory", p, attributes);
4126e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return false;
4136e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
4146e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
4156e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::mkdir(p.c_str(), attr_stat.st_mode) == 0)
4166e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return true;
4176e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (errno != EEXIST || !is_directory(p))
4186e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "create_directory", p, attributes);
4196e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return false;
4206e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
4216e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
4226e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid __create_directory_symlink(path const & from, path const & to,
4236e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                                std::error_code *ec){
4246e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::symlink(from.c_str(), to.c_str()) != 0)
4256e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "create_directory_symlink", from, to);
4266e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (ec)
4276e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        ec->clear();
4286e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
4296e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
4306e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid __create_hard_link(const path& from, const path& to, std::error_code *ec){
4316e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::link(from.c_str(), to.c_str()) == -1)
4326e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "create_hard_link", from, to);
4336e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (ec)
4346e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        ec->clear();
4356e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
4366e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
4376e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid __create_symlink(path const & from, path const & to, std::error_code *ec) {
4386e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
4396e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::symlink(from.c_str(), to.c_str()) == -1)
4406e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "create_symlink", from, to);
4416e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (ec)
4426e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        ec->clear();
4436e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
4446e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
4456e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierpath __current_path(std::error_code *ec) {
4466e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto size = ::pathconf(".", _PC_PATH_MAX);
4476e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size");
4486e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
4496e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto buff = std::unique_ptr<char[]>(new char[size + 1]);
4506e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    char* ret;
4516e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if ((ret = ::getcwd(buff.get(), static_cast<size_t>(size))) == nullptr) {
4526e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "current_path");
4536e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return {};
4546e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
4556e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
4566e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return {buff.get()};
4576e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
4586e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
4596e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid __current_path(const path& p, std::error_code *ec) {
4606e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::chdir(p.c_str()) == -1)
4616e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "current_path", p);
4626e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (ec)
4636e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        ec->clear();
4646e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
4656e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
4666e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierbool __equivalent(const path& p1, const path& p2, std::error_code *ec)
4676e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
4683288eac67369acd35e37ee70d140af2836957f0bEric Fiselier    auto make_unsupported_error = [&]() {
4693288eac67369acd35e37ee70d140af2836957f0bEric Fiselier      set_or_throw(make_error_code(errc::not_supported), ec,
4703288eac67369acd35e37ee70d140af2836957f0bEric Fiselier                     "equivalent", p1, p2);
4713288eac67369acd35e37ee70d140af2836957f0bEric Fiselier      return false;
4723288eac67369acd35e37ee70d140af2836957f0bEric Fiselier    };
4736e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code ec1, ec2;
4746e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat st1 = {};
4756e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat st2 = {};
4766e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto s1 = detail::posix_stat(p1.native(), st1, &ec1);
4773288eac67369acd35e37ee70d140af2836957f0bEric Fiselier    if (!exists(s1))
4783288eac67369acd35e37ee70d140af2836957f0bEric Fiselier      return make_unsupported_error();
4796e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto s2 = detail::posix_stat(p2.native(), st2, &ec2);
4803288eac67369acd35e37ee70d140af2836957f0bEric Fiselier    if (!exists(s2))
4813288eac67369acd35e37ee70d140af2836957f0bEric Fiselier      return make_unsupported_error();
4826e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
483af1fd7c75f5cb2a19c11339d60b4fa2da31fd901Eric Fiselier    return detail::stat_equivalent(st1, st2);
4846e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
4856e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
4866e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
4876e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierstd::uintmax_t __file_size(const path& p, std::error_code *ec)
4886e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
4896e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code m_ec;
4906e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat st;
4916e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    file_status fst = detail::posix_stat(p, st, &m_ec);
4926e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (!exists(fst) || !is_regular_file(fst)) {
4936e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (!m_ec)
4946e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            m_ec = make_error_code(errc::not_supported);
4956e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(m_ec, ec, "file_size", p);
4966e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return static_cast<uintmax_t>(-1);
4976e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
4986e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    // is_regular_file(p) == true
4996e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
5006e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return static_cast<std::uintmax_t>(st.st_size);
5016e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
5026e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
5036e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierstd::uintmax_t __hard_link_count(const path& p, std::error_code *ec)
5046e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
5056e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code m_ec;
5066e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat st;
5076e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    detail::posix_stat(p, st, &m_ec);
5086e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (m_ec) {
5096e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(m_ec, ec, "hard_link_count", p);
5106e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return static_cast<std::uintmax_t>(-1);
5116e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
5126e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
5136e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return static_cast<std::uintmax_t>(st.st_nlink);
5146e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
5156e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
5166e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
5176e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierbool __fs_is_empty(const path& p, std::error_code *ec)
5186e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
5196e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
5206e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code m_ec;
5216e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat pst;
5226e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto st = detail::posix_stat(p, pst, &m_ec);
52325dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier    if (m_ec) {
52425dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier        set_or_throw(m_ec, ec, "is_empty", p);
52525dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier        return false;
52625dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier    }
52725dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier    else if (!is_directory(st) && !is_regular_file(st)) {
52825dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier        m_ec = make_error_code(errc::not_supported);
52925dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier        set_or_throw(m_ec, ec, "is_empty");
53025dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier        return false;
53125dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier    }
53225dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier    else if (is_directory(st)) {
53325dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier        auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p);
53425dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier        if (ec && *ec)
53525dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier            return false;
53625dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier        return it == directory_iterator{};
53725dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier    }
5386e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (is_regular_file(st))
5396e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return static_cast<std::uintmax_t>(pst.st_size) == 0;
54025dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier
54125dc5bdb887e80a232f86e5b54b298427392e1c7Eric Fiselier    _LIBCPP_UNREACHABLE();
5426e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
5436e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
5446e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
54570f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiseliernamespace detail { namespace {
54670f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier
54750ca6f720fca3ef95813d1366bea47cd081814b6Eric Fiselierusing TimeSpec = struct timespec;
54850ca6f720fca3ef95813d1366bea47cd081814b6Eric Fiselierusing StatT =  struct stat;
549fd0e7614738ac855b28f24631cff8e4d8986d100Eric Fiselier
550fd0e7614738ac855b28f24631cff8e4d8986d100Eric Fiselier#if defined(__APPLE__)
551fd0e7614738ac855b28f24631cff8e4d8986d100Eric FiselierTimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
55214d7b698bfd65044583ae34ab136bd84016cc16eDon Hinton__attribute__((unused)) // Suppress warning
553fd0e7614738ac855b28f24631cff8e4d8986d100Eric FiselierTimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
554fd0e7614738ac855b28f24631cff8e4d8986d100Eric Fiselier#else
555fd0e7614738ac855b28f24631cff8e4d8986d100Eric FiselierTimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
556fd0e7614738ac855b28f24631cff8e4d8986d100Eric Fiselier__attribute__((unused)) // Suppress warning
557fd0e7614738ac855b28f24631cff8e4d8986d100Eric FiselierTimeSpec extract_atime(StatT const& st) { return st.st_atim; }
558fd0e7614738ac855b28f24631cff8e4d8986d100Eric Fiselier#endif
559fd0e7614738ac855b28f24631cff8e4d8986d100Eric Fiselier
56070f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier}} // end namespace detail
56170f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier
562b2e9337b06425b4af554651d5f2fa65615eb009fEric Fiselierusing FSTime = fs_time_util<file_time_type, time_t, struct timespec>;
563b2e9337b06425b4af554651d5f2fa65615eb009fEric Fiselier
5646e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierfile_time_type __last_write_time(const path& p, std::error_code *ec)
5656e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
566d5fc5ca37f673f47938d3a36f6f762eee58a3a7aEric Fiselier    using namespace ::std::chrono;
5676e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code m_ec;
5686e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat st;
5696e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    detail::posix_stat(p, st, &m_ec);
5706e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (m_ec) {
5716e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(m_ec, ec, "last_write_time", p);
5726e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return file_time_type::min();
5736e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
574c0f860c9460cf084f9fbd3bd3635c06e839bcabbEric Fiselier    if (ec) ec->clear();
575c0f860c9460cf084f9fbd3bd3635c06e839bcabbEric Fiselier    auto ts = detail::extract_mtime(st);
576b2e9337b06425b4af554651d5f2fa65615eb009fEric Fiselier    if (!FSTime::is_representable(ts)) {
577d5fc5ca37f673f47938d3a36f6f762eee58a3a7aEric Fiselier        set_or_throw(error_code(EOVERFLOW, generic_category()), ec,
578d5fc5ca37f673f47938d3a36f6f762eee58a3a7aEric Fiselier                     "last_write_time", p);
579d5fc5ca37f673f47938d3a36f6f762eee58a3a7aEric Fiselier        return file_time_type::min();
580d5fc5ca37f673f47938d3a36f6f762eee58a3a7aEric Fiselier    }
581b2e9337b06425b4af554651d5f2fa65615eb009fEric Fiselier    return FSTime::convert_timespec(ts);
5826e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
5836e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
5846e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid __last_write_time(const path& p, file_time_type new_time,
5856e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                       std::error_code *ec)
5866e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
5876e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    using namespace std::chrono;
5886e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code m_ec;
5896e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
59068b20ca4d9c4bee2c2ad5a9240599b3e4b78d0baNico Weber#if !defined(_LIBCXX_USE_UTIMENSAT)
5916e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    // This implementation has a race condition between determining the
5926e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    // last access time and attempting to set it to the same value using
5936e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    // ::utimes
5946e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::stat st;
5956e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    file_status fst = detail::posix_stat(p, st, &m_ec);
5966e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (m_ec && !status_known(fst)) {
5976e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(m_ec, ec, "last_write_time", p);
5986e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return;
5996e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
600d5fc5ca37f673f47938d3a36f6f762eee58a3a7aEric Fiselier    auto atime = detail::extract_atime(st);
6016e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::timeval tbuf[2];
602d5fc5ca37f673f47938d3a36f6f762eee58a3a7aEric Fiselier    tbuf[0].tv_sec = atime.tv_sec;
603d5fc5ca37f673f47938d3a36f6f762eee58a3a7aEric Fiselier    tbuf[0].tv_usec = duration_cast<microseconds>(nanoseconds(atime.tv_nsec)).count();
604b2e9337b06425b4af554651d5f2fa65615eb009fEric Fiselier    const bool overflowed = !FSTime::set_times_checked<microseconds>(
60570f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier        &tbuf[1].tv_sec, &tbuf[1].tv_usec, new_time);
60670f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier
60770f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier    if (overflowed) {
60870f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier        set_or_throw(make_error_code(errc::invalid_argument), ec,
60970f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier                     "last_write_time", p);
61070f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier        return;
61170f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier    }
6126e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::utimes(p.c_str(), tbuf) == -1) {
6136e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        m_ec = detail::capture_errno();
6146e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
6156e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#else
6166e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    struct ::timespec tbuf[2];
6176e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    tbuf[0].tv_sec = 0;
6186e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    tbuf[0].tv_nsec = UTIME_OMIT;
61970f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier
620b2e9337b06425b4af554651d5f2fa65615eb009fEric Fiselier    const bool overflowed = !FSTime::set_times_checked<nanoseconds>(
62170f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier        &tbuf[1].tv_sec, &tbuf[1].tv_nsec, new_time);
62270f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier    if (overflowed) {
62370f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier        set_or_throw(make_error_code(errc::invalid_argument),
62470f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier            ec, "last_write_time", p);
62570f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier        return;
62670f7afec38f9b2064d9aa22440fde30234a58af2Eric Fiselier    }
6276e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::utimensat(AT_FDCWD, p.c_str(), tbuf, 0) == -1) {
6286e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        m_ec = detail::capture_errno();
6296e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
6306e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier#endif
6316e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (m_ec)
6326e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(m_ec, ec, "last_write_time", p);
6336e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (ec)
6346e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        ec->clear();
6356e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
6366e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
6376e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
6386e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid __permissions(const path& p, perms prms, std::error_code *ec)
6396e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
6406e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
6417c96ddb5639078164a3fe8bcfbf7a11d7f502afbEric Fiselier    const bool resolve_symlinks = !bool(perms::symlink_nofollow & prms);
6426e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    const bool add_perms = bool(perms::add_perms & prms);
6436e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    const bool remove_perms = bool(perms::remove_perms & prms);
6446e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    _LIBCPP_ASSERT(!(add_perms && remove_perms),
6456e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                   "Both add_perms and remove_perms are set");
6466e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
64755e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier    bool set_sym_perms = false;
64855e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier    prms &= perms::mask;
64955e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier    if (!resolve_symlinks || (add_perms || remove_perms)) {
65055e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier        std::error_code m_ec;
65155e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier        file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec)
65255e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier                                          : detail::posix_lstat(p, &m_ec);
65355e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier        set_sym_perms = is_symlink(st);
6546e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (m_ec) return set_or_throw(m_ec, ec, "permissions", p);
65555e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier        _LIBCPP_ASSERT(st.permissions() != perms::unknown,
65655e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier                       "Permissions unexpectedly unknown");
65755e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier        if (add_perms)
65855e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier            prms |= st.permissions();
65955e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier        else if (remove_perms)
66055e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier           prms = st.permissions() & ~prms;
66155e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier    }
66255e084dd4de60d5a80c1295653f1e41d45ce1c1bEric Fiselier    const auto real_perms = detail::posix_convert_perms(prms);
6636e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
6646e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier# if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
6656e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0;
6666e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) {
6677c96ddb5639078164a3fe8bcfbf7a11d7f502afbEric Fiselier        return set_or_throw(ec, "permissions", p);
6687c96ddb5639078164a3fe8bcfbf7a11d7f502afbEric Fiselier    }
6696e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier# else
6706e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (set_sym_perms)
6716e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return set_or_throw(make_error_code(errc::operation_not_supported),
6726e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier                            ec, "permissions", p);
6736e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::chmod(p.c_str(), real_perms) == -1) {
6746e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return set_or_throw(ec, "permissions", p);
6756e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
6767c96ddb5639078164a3fe8bcfbf7a11d7f502afbEric Fiselier# endif
6776e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
6786e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
6796e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
6806e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
6816e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierpath __read_symlink(const path& p, std::error_code *ec) {
6826e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    char buff[PATH_MAX + 1];
6836e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code m_ec;
6846e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    ::ssize_t ret;
6856e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) {
6866e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "read_symlink", p);
6876e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return {};
6886e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
6896e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO");
6906e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    _LIBCPP_ASSERT(ret > 0, "TODO");
6916e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
6926e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    buff[ret] = 0;
6936e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return {buff};
6946e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
6956e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
6966e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
6976e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierbool __remove(const path& p, std::error_code *ec) {
6986e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
69945d5893943f0099a4ef827d699708cda005a37f5Ekaterina Vaartis
7006e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::remove(p.c_str()) == -1) {
70145d5893943f0099a4ef827d699708cda005a37f5Ekaterina Vaartis        if (errno != ENOENT)
70245d5893943f0099a4ef827d699708cda005a37f5Ekaterina Vaartis            set_or_throw(ec, "remove", p);
7036e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return false;
7046e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
7056e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return true;
7066e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
7076e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
7086e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliernamespace {
7096e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
7106e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierstd::uintmax_t remove_all_impl(path const & p, std::error_code& ec)
7116e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier{
7126e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    const auto npos = static_cast<std::uintmax_t>(-1);
7136e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    const file_status st = __symlink_status(p, &ec);
7146e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) return npos;
7156e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier     std::uintmax_t count = 1;
7166e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (is_directory(st)) {
7176e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        for (directory_iterator it(p, ec); !ec && it != directory_iterator();
7186e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier             it.increment(ec)) {
7196e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            auto other_count = remove_all_impl(it->path(), ec);
7206e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            if (ec) return npos;
7216e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            count += other_count;
7226e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        }
7236e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        if (ec) return npos;
7246e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
7256e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (!__remove(p, &ec)) return npos;
7266e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return count;
7276e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
7286e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
7296e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier} // end namespace
7306e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
7316e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierstd::uintmax_t __remove_all(const path& p, std::error_code *ec) {
73245d5893943f0099a4ef827d699708cda005a37f5Ekaterina Vaartis    if (ec) ec->clear();
73345d5893943f0099a4ef827d699708cda005a37f5Ekaterina Vaartis
7346e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    std::error_code mec;
7356e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto count = remove_all_impl(p, mec);
7366e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (mec) {
73745d5893943f0099a4ef827d699708cda005a37f5Ekaterina Vaartis        if (mec == errc::no_such_file_or_directory) {
73845d5893943f0099a4ef827d699708cda005a37f5Ekaterina Vaartis            return 0;
73945d5893943f0099a4ef827d699708cda005a37f5Ekaterina Vaartis        } else {
74045d5893943f0099a4ef827d699708cda005a37f5Ekaterina Vaartis            set_or_throw(mec, ec, "remove_all", p);
74145d5893943f0099a4ef827d699708cda005a37f5Ekaterina Vaartis            return static_cast<std::uintmax_t>(-1);
74245d5893943f0099a4ef827d699708cda005a37f5Ekaterina Vaartis        }
7436e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
7446e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return count;
7456e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
7466e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
7476e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid __rename(const path& from, const path& to, std::error_code *ec) {
7486e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::rename(from.c_str(), to.c_str()) == -1)
7496e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "rename", from, to);
7506e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (ec)
7516e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        ec->clear();
7526e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
7536e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
7546e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiseliervoid __resize_file(const path& p, std::uintmax_t size, std::error_code *ec) {
7554b1c560ca313f8fdd268d93586b175b60124b738Eric Fiselier    if (::truncate(p.c_str(), static_cast<::off_t>(size)) == -1)
7566e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "resize_file", p);
7576e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (ec)
7586e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        ec->clear();
7596e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
7606e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
7616e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierspace_info __space(const path& p, std::error_code *ec) {
7626e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    space_info si;
763591e18f6aaa7f8a8ae1ed0e239708b5e752173bdEric Fiselier    struct statvfs m_svfs = {};
7646e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (::statvfs(p.c_str(), &m_svfs) == -1)  {
7656e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        set_or_throw(ec, "space", p);
7666e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        si.capacity = si.free = si.available =
7676e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier            static_cast<std::uintmax_t>(-1);
7686e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return si;
7696e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
7706e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
7716e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    // Multiply with overflow checking.
772591e18f6aaa7f8a8ae1ed0e239708b5e752173bdEric Fiselier    auto do_mult = [&](std::uintmax_t& out, std::uintmax_t other) {
7736e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier      out = other * m_svfs.f_frsize;
774fbdbb36015dc4695e07d00da213705f57b87f78dEric Fiselier      if (other == 0 || out / other != m_svfs.f_frsize)
7756e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier          out = static_cast<std::uintmax_t>(-1);
7766e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    };
7776e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    do_mult(si.capacity, m_svfs.f_blocks);
7786e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    do_mult(si.free, m_svfs.f_bfree);
7796e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    do_mult(si.available, m_svfs.f_bavail);
7806e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return si;
7816e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
7826e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
7836e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierfile_status __status(const path& p, std::error_code *ec) {
7846e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return detail::posix_stat(p, ec);
7856e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
7866e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
7876e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierfile_status __symlink_status(const path& p, std::error_code *ec) {
7886e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return detail::posix_lstat(p, ec);
7896e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
7906e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
7916e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierpath __system_complete(const path& p, std::error_code *ec) {
7926e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (ec) ec->clear();
7936e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return absolute(p, current_path());
7946e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
7956e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
7967566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasoolpath __temp_directory_path(std::error_code* ec) {
7977566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool  const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
7987566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool  const char* ret = nullptr;
7997566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool
8007566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool  for (auto& ep : env_paths)
8017566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool    if ((ret = std::getenv(ep)))
8027566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool      break;
8037566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool  if (ret == nullptr)
8047566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool    ret = "/tmp";
8057566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool
8067566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool  path p(ret);
8077566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool  std::error_code m_ec;
8087566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool  if (!exists(p, m_ec) || !is_directory(p, m_ec)) {
8096e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (!m_ec || m_ec == make_error_code(errc::no_such_file_or_directory))
8107566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool      m_ec = make_error_code(errc::not_a_directory);
8116e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    set_or_throw(m_ec, ec, "temp_directory_path");
8126e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return {};
8137566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool  }
8147566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool
8157566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool  if (ec)
8167566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool    ec->clear();
8177566869dabd82699f26c8c95f18de331ec3950ceSaleem Abdulrasool  return p;
8186e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
8196e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
8206e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier// An absolute path is composed according to the table in [fs.op.absolute].
8216e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselierpath absolute(const path& p, const path& base) {
8226e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto root_name = p.root_name();
8236e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto root_dir = p.root_directory();
8246e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
8256e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (!root_name.empty() && !root_dir.empty())
8266e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier      return p;
8276e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
8286e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    auto abs_base = base.is_absolute() ? base : absolute(base);
8296e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
8306e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    /* !has_root_name && !has_root_dir */
8316e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    if (root_name.empty() && root_dir.empty())
8326e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    {
8336e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier      return abs_base / p;
8346e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
8356e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else if (!root_name.empty()) /* has_root_name && !has_root_dir */
8366e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    {
8376e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier      return  root_name / abs_base.root_directory()
8386e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier              /
8396e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier              abs_base.relative_path() / p.relative_path();
8406e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
8416e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    else /* !has_root_name && has_root_dir */
8426e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    {
8436e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier      if (abs_base.has_root_name())
8446e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier        return abs_base.root_name() / p;
8456e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier      // else p is absolute,  return outside of block
8466e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    }
8476e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier    return p;
8486e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier}
8496e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier
8506e9a694dce70319e60dbdfb09cf055bacb4c948eEric Fiselier_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM
851