summaryrefslogtreecommitdiffstats
path: root/libcxx/src/experimental/filesystem/operations.cpp
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2018-07-25 20:51:49 +0000
committerEric Fiselier <eric@efcs.ca>2018-07-25 20:51:49 +0000
commitc55ac1055a419eeca16ec885ec2d18c3d4124726 (patch)
tree5d15b9f274079d9faabb11aa7862040109f67ce4 /libcxx/src/experimental/filesystem/operations.cpp
parent1d4a78ef042280319f95172a2d1e95558b0ce2ab (diff)
downloadbcm5719-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.cpp82
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();
OpenPOWER on IntegriCloud