diff options
author | Eric Fiselier <eric@efcs.ca> | 2018-07-25 20:51:49 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2018-07-25 20:51:49 +0000 |
commit | c55ac1055a419eeca16ec885ec2d18c3d4124726 (patch) | |
tree | 5d15b9f274079d9faabb11aa7862040109f67ce4 /libcxx/src/experimental/filesystem/operations.cpp | |
parent | 1d4a78ef042280319f95172a2d1e95558b0ce2ab (diff) | |
download | bcm5719-llvm-c55ac1055a419eeca16ec885ec2d18c3d4124726.tar.gz bcm5719-llvm-c55ac1055a419eeca16ec885ec2d18c3d4124726.zip |
[libc++] Use __int128_t to represent file_time_type.
Summary:
The ``file_time_type`` time point is used to represent the write times for files.
Its job is to act as part of a C++ wrapper for less ideal system interfaces. The
underlying filesystem uses the ``timespec`` struct for the same purpose.
However, the initial implementation of ``file_time_type`` could not represent
either the range or resolution of ``timespec``, making it unsuitable. Fixing
this requires an implementation which uses more than 64 bits to store the
time point.
I primarily considered two solutions: Using ``__int128_t`` and using a
arithmetic emulation of ``timespec``. Each has its pros and cons, and both
come with more than one complication.
However, after a lot of consideration, I decided on using `__int128_t`. This patch implements that change.
Please see the [FileTimeType Design Document](http://libcxx.llvm.org/docs/DesignDocs/FileTimeType.html) for more information.
Reviewers: mclow.lists, ldionne, joerg, arthur.j.odwyer, EricWF
Reviewed By: EricWF
Subscribers: christof, K-ballo, cfe-commits, BillyONeal
Differential Revision: https://reviews.llvm.org/D49774
llvm-svn: 337960
Diffstat (limited to 'libcxx/src/experimental/filesystem/operations.cpp')
-rw-r--r-- | libcxx/src/experimental/filesystem/operations.cpp | 82 |
1 files changed, 52 insertions, 30 deletions
diff --git a/libcxx/src/experimental/filesystem/operations.cpp b/libcxx/src/experimental/filesystem/operations.cpp index dd8b4347774..d5706687560 100644 --- a/libcxx/src/experimental/filesystem/operations.cpp +++ b/libcxx/src/experimental/filesystem/operations.cpp @@ -23,6 +23,7 @@ #include <unistd.h> #include <sys/stat.h> #include <sys/statvfs.h> +#include <time.h> #include <fcntl.h> /* values for fchmodat */ #if defined(__linux__) @@ -36,6 +37,14 @@ # define _LIBCPP_USE_COPYFILE #endif +#if !defined(__APPLE__) +#define _LIBCPP_USE_CLOCK_GETTIME +#endif + +#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME) +#include <sys/time.h> // for gettimeofday and timeval +#endif // !defined(CLOCK_REALTIME) + #if defined(_LIBCPP_COMPILER_GCC) #if _GNUC_VER < 500 #pragma GCC diagnostic ignored "-Wmissing-field-initializers" @@ -44,9 +53,6 @@ _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM -filesystem_error::~filesystem_error() {} - - namespace { namespace parser { @@ -355,7 +361,7 @@ private: explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {} }; -perms posix_get_perms(const struct ::stat& st) noexcept { +perms posix_get_perms(const StatT& st) noexcept { return static_cast<perms>(st.st_mode) & perms::mask; } @@ -364,8 +370,7 @@ perms posix_get_perms(const struct ::stat& st) noexcept { } file_status create_file_status(error_code& m_ec, path const& p, - const struct ::stat& path_stat, - error_code* ec) { + const StatT& path_stat, error_code* ec) { if (ec) *ec = m_ec; if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { @@ -400,8 +405,7 @@ file_status create_file_status(error_code& m_ec, path const& p, return fs_tmp; } -file_status posix_stat(path const& p, struct ::stat& path_stat, - error_code* ec) { +file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) { error_code m_ec; if (::stat(p.c_str(), &path_stat) == -1) m_ec = detail::capture_errno(); @@ -409,12 +413,11 @@ file_status posix_stat(path const& p, struct ::stat& path_stat, } file_status posix_stat(path const& p, error_code* ec) { - struct ::stat path_stat; + StatT path_stat; return posix_stat(p, path_stat, ec); } -file_status posix_lstat(path const& p, struct ::stat& path_stat, - error_code* ec) { +file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) { error_code m_ec; if (::lstat(p.c_str(), &path_stat) == -1) m_ec = detail::capture_errno(); @@ -422,7 +425,7 @@ file_status posix_lstat(path const& p, struct ::stat& path_stat, } file_status posix_lstat(path const& p, error_code* ec) { - struct ::stat path_stat; + StatT path_stat; return posix_lstat(p, path_stat, ec); } @@ -464,10 +467,32 @@ file_status FileDescriptor::refresh_status(error_code& ec) { using detail::capture_errno; using detail::ErrorHandler; using detail::StatT; +using detail::TimeSpec; using parser::createView; using parser::PathParser; using parser::string_view_t; +const bool _FilesystemClock::is_steady; + +_FilesystemClock::time_point _FilesystemClock::now() noexcept { + typedef chrono::duration<rep> __secs; +#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) + typedef chrono::duration<rep, nano> __nsecs; + struct timespec tp; + if (0 != clock_gettime(CLOCK_REALTIME, &tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); + return time_point(__secs(tp.tv_sec) + + chrono::duration_cast<duration>(__nsecs(tp.tv_nsec))); +#else + typedef chrono::duration<rep, micro> __microsecs; + timeval tv; + gettimeofday(&tv, 0); + return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec)); +#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME +} + +filesystem_error::~filesystem_error() {} + void filesystem_error::__create_what(int __num_paths) { const char* derived_what = system_error::what(); __storage_->__what_ = [&]() -> string { @@ -525,14 +550,14 @@ void __copy(const path& from, const path& to, copy_options options, const bool sym_status2 = bool(options & copy_options::copy_symlinks); error_code m_ec1; - struct ::stat f_st = {}; + StatT f_st = {}; const file_status f = sym_status || sym_status2 ? detail::posix_lstat(from, f_st, &m_ec1) : detail::posix_stat(from, f_st, &m_ec1); if (m_ec1) return err.report(m_ec1); - struct ::stat t_st = {}; + StatT t_st = {}; const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1) : detail::posix_stat(to, t_st, &m_ec1); @@ -916,7 +941,7 @@ uintmax_t __file_size(const path& p, error_code *ec) ErrorHandler<uintmax_t> err("file_size", ec, &p); error_code m_ec; - struct ::stat st; + StatT st; file_status fst = detail::posix_stat(p, st, &m_ec); if (!exists(fst) || !is_regular_file(fst)) { errc error_kind = @@ -966,14 +991,14 @@ bool __fs_is_empty(const path& p, error_code *ec) static file_time_type __extract_last_write_time(const path& p, const StatT& st, error_code* ec) { - using detail::FSTime; + using detail::fs_time; ErrorHandler<file_time_type> err("last_write_time", ec, &p); auto ts = detail::extract_mtime(st); - if (!FSTime::is_representable(ts)) + if (!fs_time::is_representable(ts)) return err.report(errc::value_too_large); - return FSTime::convert_timespec(ts); + return fs_time::convert_from_timespec(ts); } file_time_type __last_write_time(const path& p, error_code *ec) @@ -992,30 +1017,27 @@ file_time_type __last_write_time(const path& p, error_code *ec) void __last_write_time(const path& p, file_time_type new_time, error_code *ec) { - using namespace chrono; - using namespace detail; - ErrorHandler<void> err("last_write_time", ec, &p); error_code m_ec; - TimeStructArray tbuf; -#if !defined(_LIBCXX_USE_UTIMENSAT) + array<TimeSpec, 2> tbuf; +#if !defined(_LIBCPP_USE_UTIMENSAT) // This implementation has a race condition between determining the // last access time and attempting to set it to the same value using // ::utimes - struct ::stat st; + StatT st; file_status fst = detail::posix_stat(p, st, &m_ec); - if (m_ec && !status_known(fst)) + if (m_ec) return err.report(m_ec); - SetTimeStructTo(tbuf[0], detail::extract_atime(st)); + tbuf[0] = detail::extract_atime(st); #else tbuf[0].tv_sec = 0; tbuf[0].tv_nsec = UTIME_OMIT; #endif - if (SetTimeStructTo(tbuf[1], new_time)) - return err.report(errc::invalid_argument); + if (detail::set_time_spec_to(tbuf[1], new_time)) + return err.report(errc::value_too_large); - SetFileTimes(p, tbuf, m_ec); + detail::set_file_times(p, tbuf, m_ec); if (m_ec) return err.report(m_ec); } @@ -1591,7 +1613,7 @@ error_code directory_entry::__do_refresh() noexcept { __data_.__reset(); error_code failure_ec; - struct ::stat full_st; + StatT full_st; file_status st = detail::posix_lstat(__p_, full_st, &failure_ec); if (!status_known(st)) { __data_.__reset(); |